]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge remote-tracking branch 'signal/for-next'
authorStephen Rothwell <sfr@canb.auug.org.au>
Thu, 25 Oct 2012 02:50:12 +0000 (13:50 +1100)
committerStephen Rothwell <sfr@canb.auug.org.au>
Thu, 25 Oct 2012 02:50:12 +0000 (13:50 +1100)
Conflicts:
arch/alpha/kernel/osf_sys.c

2761 files changed:
.gitignore
CREDITS
Documentation/00-INDEX
Documentation/ABI/testing/ima_policy
Documentation/ABI/testing/sysfs-class-devfreq
Documentation/ABI/testing/sysfs-devices-power
Documentation/ABI/testing/sysfs-driver-hid-roccat-koneplus
Documentation/ABI/testing/sysfs-driver-hid-roccat-lua [new file with mode: 0644]
Documentation/DMA-API-HOWTO.txt
Documentation/DMA-API.txt
Documentation/DocBook/uio-howto.tmpl
Documentation/RCU/RTFP.txt
Documentation/RCU/checklist.txt
Documentation/RCU/listRCU.txt
Documentation/RCU/whatisRCU.txt
Documentation/acpi/initrd_table_override.txt [new file with mode: 0644]
Documentation/arm64/memory.txt
Documentation/devicetree/bindings/gpio/gpio_atmel.txt
Documentation/devicetree/bindings/i2c/fsl-imx-i2c.txt
Documentation/devicetree/bindings/input/touchscreen/mms114.txt [new file with mode: 0644]
Documentation/devicetree/bindings/media/s5p-mfc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mtd/denali-nand.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mtd/fsmc-nand.txt
Documentation/devicetree/bindings/mtd/m25p80.txt [new file with mode: 0644]
Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt [new file with mode: 0644]
Documentation/devicetree/bindings/pinctrl/nvidia,tegra20-pinmux.txt
Documentation/devicetree/bindings/pinctrl/nvidia,tegra30-pinmux.txt
Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt
Documentation/devicetree/bindings/regulator/gpio-regulator.txt [new file with mode: 0644]
Documentation/devicetree/bindings/regulator/vexpress.txt [new file with mode: 0644]
Documentation/devicetree/bindings/rtc/nvidia,tegra20-rtc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/ak4104.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/cs4271.txt
Documentation/devicetree/bindings/spi/omap-spi.txt
Documentation/devicetree/bindings/timer/nvidia,tegra20-timer.txt [new file with mode: 0644]
Documentation/devicetree/bindings/timer/nvidia,tegra30-timer.txt [new file with mode: 0644]
Documentation/hwmon/ads7828
Documentation/hwmon/coretemp
Documentation/hwmon/da9055 [new file with mode: 0644]
Documentation/hwmon/submitting-patches
Documentation/memory-barriers.txt
Documentation/pinctrl.txt
Documentation/power/pm_qos_interface.txt
Documentation/prctl/seccomp_filter.txt
Documentation/scheduler/numa-problem.txt [new file with mode: 0644]
Documentation/security/keys.txt
Documentation/thermal/sysfs-api.txt
Documentation/usb/error-codes.txt
Documentation/virtual/kvm/api.txt
MAINTAINERS
Makefile
arch/alpha/kernel/osf_sys.c
arch/arm/Kconfig
arch/arm/Kconfig.debug
arch/arm/Makefile
arch/arm/arm-soc-for-next-contents.txt [new file with mode: 0644]
arch/arm/boot/Makefile
arch/arm/boot/compressed/Makefile
arch/arm/boot/compressed/head-vt8500.S [deleted file]
arch/arm/boot/dts/Makefile
arch/arm/boot/dts/at91sam9260.dtsi
arch/arm/boot/dts/at91sam9263.dtsi
arch/arm/boot/dts/at91sam9263ek.dts
arch/arm/boot/dts/at91sam9g15.dtsi [new file with mode: 0644]
arch/arm/boot/dts/at91sam9g15ek.dts [new file with mode: 0644]
arch/arm/boot/dts/at91sam9g20ek_common.dtsi
arch/arm/boot/dts/at91sam9g25.dtsi [new file with mode: 0644]
arch/arm/boot/dts/at91sam9g25ek.dts
arch/arm/boot/dts/at91sam9g35.dtsi [new file with mode: 0644]
arch/arm/boot/dts/at91sam9g35ek.dts [new file with mode: 0644]
arch/arm/boot/dts/at91sam9g45.dtsi
arch/arm/boot/dts/at91sam9m10g45ek.dts
arch/arm/boot/dts/at91sam9n12.dtsi
arch/arm/boot/dts/at91sam9x25.dtsi [new file with mode: 0644]
arch/arm/boot/dts/at91sam9x25ek.dts [new file with mode: 0644]
arch/arm/boot/dts/at91sam9x35.dtsi [new file with mode: 0644]
arch/arm/boot/dts/at91sam9x35ek.dts [new file with mode: 0644]
arch/arm/boot/dts/at91sam9x5.dtsi
arch/arm/boot/dts/at91sam9x5ek.dtsi [new file with mode: 0644]
arch/arm/boot/dts/dove.dtsi
arch/arm/boot/dts/exynos4210-origen.dts
arch/arm/boot/dts/exynos4210-pinctrl.dtsi
arch/arm/boot/dts/exynos4210-smdkv310.dts
arch/arm/boot/dts/exynos4210-trats.dts
arch/arm/boot/dts/exynos4210.dtsi
arch/arm/boot/dts/exynos5250-smdk5250.dts
arch/arm/boot/dts/exynos5250.dtsi
arch/arm/boot/dts/imx27.dtsi
arch/arm/boot/dts/imx51.dtsi
arch/arm/boot/dts/imx53.dtsi
arch/arm/boot/dts/imx6q-arm2.dts
arch/arm/boot/dts/imx6q.dtsi
arch/arm/boot/dts/kirkwood-lsxl.dtsi
arch/arm/boot/dts/sh7372-mackerel.dts [new file with mode: 0644]
arch/arm/boot/dts/spear13xx.dtsi
arch/arm/boot/dts/spear300.dtsi
arch/arm/boot/dts/spear310.dtsi
arch/arm/boot/dts/spear320.dtsi
arch/arm/boot/dts/spear600.dtsi
arch/arm/boot/dts/tegra20-harmony.dts
arch/arm/boot/dts/tegra20-paz00.dts
arch/arm/boot/dts/tegra20-seaboard.dts
arch/arm/boot/dts/tegra20-tamonten.dtsi
arch/arm/boot/dts/tegra20-ventana.dts
arch/arm/boot/dts/tegra20-whistler.dts
arch/arm/boot/dts/tegra20.dtsi
arch/arm/boot/dts/tegra30-cardhu-a02.dts
arch/arm/boot/dts/tegra30-cardhu-a04.dts
arch/arm/boot/dts/tegra30-cardhu.dtsi
arch/arm/boot/dts/tegra30.dtsi
arch/arm/boot/dts/wm8505.dtsi
arch/arm/common/vic.c
arch/arm/configs/armadillo800eva_defconfig
arch/arm/configs/at91_dt_defconfig
arch/arm/configs/imx_v4_v5_defconfig
arch/arm/configs/imx_v6_v7_defconfig
arch/arm/configs/kzm9g_defconfig
arch/arm/configs/mackerel_defconfig
arch/arm/configs/marzen_defconfig
arch/arm/configs/nhk8815_defconfig
arch/arm/configs/tegra_defconfig
arch/arm/include/asm/assembler.h
arch/arm/include/asm/cp15.h
arch/arm/include/asm/cputype.h
arch/arm/include/asm/dma-mapping.h
arch/arm/include/asm/flat.h
arch/arm/include/asm/glue-cache.h
arch/arm/include/asm/glue-df.h
arch/arm/include/asm/glue-proc.h
arch/arm/include/asm/hardware/cache-l2x0.h
arch/arm/include/asm/hardware/vic.h
arch/arm/include/asm/hw_breakpoint.h
arch/arm/include/asm/io.h
arch/arm/include/asm/irqflags.h
arch/arm/include/asm/mmu.h
arch/arm/include/asm/mmu_context.h
arch/arm/include/asm/perf_event.h
arch/arm/include/asm/pmu.h
arch/arm/include/asm/processor.h
arch/arm/include/asm/ptrace.h
arch/arm/include/asm/system_info.h
arch/arm/include/asm/uaccess.h
arch/arm/include/asm/xen/interface.h
arch/arm/include/asm/xen/page.h
arch/arm/include/debug/imx.S [moved from arch/arm/plat-mxc/include/mach/debug-macro.S with 59% similarity]
arch/arm/include/uapi/asm/ptrace.h
arch/arm/include/uapi/asm/unistd.h
arch/arm/kernel/asm-offsets.c
arch/arm/kernel/calls.S
arch/arm/kernel/entry-common.S
arch/arm/kernel/entry-header.S
arch/arm/kernel/entry-v7m.S [new file with mode: 0644]
arch/arm/kernel/head-common.S
arch/arm/kernel/head-nommu.S
arch/arm/kernel/hw_breakpoint.c
arch/arm/kernel/irq.c
arch/arm/kernel/kprobes-test-arm.c
arch/arm/kernel/machine_kexec.c
arch/arm/kernel/perf_event.c
arch/arm/kernel/perf_event_cpu.c
arch/arm/kernel/perf_event_v6.c
arch/arm/kernel/perf_event_v7.c
arch/arm/kernel/perf_event_xscale.c
arch/arm/kernel/process.c
arch/arm/kernel/ptrace.c
arch/arm/kernel/setup.c
arch/arm/kernel/smp.c
arch/arm/kernel/smp_twd.c
arch/arm/kernel/traps.c
arch/arm/lib/delay.c
arch/arm/mach-at91/Kconfig
arch/arm/mach-at91/at91rm9200.c
arch/arm/mach-at91/at91sam9260.c
arch/arm/mach-at91/at91sam9260_devices.c
arch/arm/mach-at91/at91sam9261.c
arch/arm/mach-at91/at91sam9263.c
arch/arm/mach-at91/at91sam9g45.c
arch/arm/mach-at91/at91sam9n12.c
arch/arm/mach-at91/at91sam9rl.c
arch/arm/mach-at91/at91sam9x5.c
arch/arm/mach-at91/board-csb337.c
arch/arm/mach-at91/board-dt.c
arch/arm/mach-at91/board-sam9g20ek.c
arch/arm/mach-at91/gpio.c
arch/arm/mach-at91/include/mach/at91rm9200_emac.h [deleted file]
arch/arm/mach-at91/setup.c
arch/arm/mach-at91/soc.h
arch/arm/mach-cns3xxx/cns3420vb.c
arch/arm/mach-davinci/board-da850-evm.c
arch/arm/mach-dove/common.c
arch/arm/mach-dove/pcie.c
arch/arm/mach-exynos/Kconfig
arch/arm/mach-exynos/clock-exynos4.c
arch/arm/mach-exynos/clock-exynos5.c
arch/arm/mach-exynos/common.c
arch/arm/mach-exynos/mach-exynos4-dt.c
arch/arm/mach-exynos/mach-exynos5-dt.c
arch/arm/mach-exynos/mach-nuri.c
arch/arm/mach-exynos/mach-universal_c210.c
arch/arm/mach-imx/3ds_debugboard.c [moved from arch/arm/plat-mxc/3ds_debugboard.c with 99% similarity]
arch/arm/mach-imx/3ds_debugboard.h [moved from arch/arm/plat-mxc/include/mach/3ds_debugboard.h with 100% similarity]
arch/arm/mach-imx/Kconfig
arch/arm/mach-imx/Makefile
arch/arm/mach-imx/avic.c [moved from arch/arm/plat-mxc/avic.c with 98% similarity]
arch/arm/mach-imx/board-mx31lilly.h [moved from arch/arm/plat-mxc/include/mach/board-mx31lilly.h with 100% similarity]
arch/arm/mach-imx/board-mx31lite.h [moved from arch/arm/plat-mxc/include/mach/board-mx31lite.h with 100% similarity]
arch/arm/mach-imx/board-mx31moboard.h [moved from arch/arm/plat-mxc/include/mach/board-mx31moboard.h with 100% similarity]
arch/arm/mach-imx/board-pcm038.h [moved from arch/arm/plat-mxc/include/mach/board-pcm038.h with 100% similarity]
arch/arm/mach-imx/clk-imx1.c
arch/arm/mach-imx/clk-imx21.c
arch/arm/mach-imx/clk-imx25.c
arch/arm/mach-imx/clk-imx27.c
arch/arm/mach-imx/clk-imx31.c
arch/arm/mach-imx/clk-imx35.c
arch/arm/mach-imx/clk-imx51-imx53.c
arch/arm/mach-imx/clk-imx6q.c
arch/arm/mach-imx/clk-pllv1.c
arch/arm/mach-imx/common.h [moved from arch/arm/plat-mxc/include/mach/common.h with 99% similarity]
arch/arm/mach-imx/cpu-imx25.c
arch/arm/mach-imx/cpu-imx27.c
arch/arm/mach-imx/cpu-imx31.c
arch/arm/mach-imx/cpu-imx35.c
arch/arm/mach-imx/cpu-imx5.c
arch/arm/mach-imx/cpu.c [moved from arch/arm/plat-mxc/cpu.c with 97% similarity]
arch/arm/mach-imx/cpu_op-mx51.c
arch/arm/mach-imx/cpufreq.c [moved from arch/arm/plat-mxc/cpufreq.c with 99% similarity]
arch/arm/mach-imx/cpuidle.c [moved from arch/arm/plat-mxc/cpuidle.c with 100% similarity]
arch/arm/mach-imx/cpuidle.h [moved from arch/arm/plat-mxc/include/mach/cpuidle.h with 100% similarity]
arch/arm/mach-imx/devices-imx1.h
arch/arm/mach-imx/devices-imx21.h
arch/arm/mach-imx/devices-imx25.h
arch/arm/mach-imx/devices-imx27.h
arch/arm/mach-imx/devices-imx31.h
arch/arm/mach-imx/devices-imx35.h
arch/arm/mach-imx/devices-imx50.h
arch/arm/mach-imx/devices-imx51.h
arch/arm/mach-imx/devices/Kconfig [moved from arch/arm/plat-mxc/devices/Kconfig with 100% similarity]
arch/arm/mach-imx/devices/Makefile [moved from arch/arm/plat-mxc/devices/Makefile with 98% similarity]
arch/arm/mach-imx/devices/devices-common.h [moved from arch/arm/plat-mxc/include/mach/devices-common.h with 97% similarity]
arch/arm/mach-imx/devices/devices.c [moved from arch/arm/plat-mxc/devices.c with 92% similarity]
arch/arm/mach-imx/devices/platform-ahci-imx.c [moved from arch/arm/plat-mxc/devices/platform-ahci-imx.c with 98% similarity]
arch/arm/mach-imx/devices/platform-fec.c [moved from arch/arm/plat-mxc/devices/platform-fec.c with 97% similarity]
arch/arm/mach-imx/devices/platform-flexcan.c [moved from arch/arm/plat-mxc/devices/platform-flexcan.c with 96% similarity]
arch/arm/mach-imx/devices/platform-fsl-usb2-udc.c [moved from arch/arm/plat-mxc/devices/platform-fsl-usb2-udc.c with 96% similarity]
arch/arm/mach-imx/devices/platform-gpio-mxc.c [moved from arch/arm/plat-mxc/devices/platform-gpio-mxc.c with 96% similarity]
arch/arm/mach-imx/devices/platform-gpio_keys.c [moved from arch/arm/plat-mxc/devices/platform-gpio_keys.c with 94% similarity]
arch/arm/mach-imx/devices/platform-imx-dma.c [moved from arch/arm/plat-mxc/devices/platform-imx-dma.c with 63% similarity]
arch/arm/mach-imx/devices/platform-imx-fb.c [moved from arch/arm/plat-mxc/devices/platform-imx-fb.c with 79% similarity]
arch/arm/mach-imx/devices/platform-imx-i2c.c [moved from arch/arm/plat-mxc/devices/platform-imx-i2c.c with 76% similarity]
arch/arm/mach-imx/devices/platform-imx-keypad.c [moved from arch/arm/plat-mxc/devices/platform-imx-keypad.c with 97% similarity]
arch/arm/mach-imx/devices/platform-imx-ssi.c [moved from arch/arm/plat-mxc/devices/platform-imx-ssi.c with 98% similarity]
arch/arm/mach-imx/devices/platform-imx-uart.c [moved from arch/arm/plat-mxc/devices/platform-imx-uart.c with 98% similarity]
arch/arm/mach-imx/devices/platform-imx2-wdt.c [moved from arch/arm/plat-mxc/devices/platform-imx2-wdt.c with 97% similarity]
arch/arm/mach-imx/devices/platform-imx21-hcd.c [moved from arch/arm/plat-mxc/devices/platform-imx21-hcd.c with 94% similarity]
arch/arm/mach-imx/devices/platform-imx27-coda.c [moved from arch/arm/plat-mxc/devices/platform-imx27-coda.c with 93% similarity]
arch/arm/mach-imx/devices/platform-imx_udc.c [moved from arch/arm/plat-mxc/devices/platform-imx_udc.c with 96% similarity]
arch/arm/mach-imx/devices/platform-imxdi_rtc.c [moved from arch/arm/plat-mxc/devices/platform-imxdi_rtc.c with 94% similarity]
arch/arm/mach-imx/devices/platform-ipu-core.c [moved from arch/arm/plat-mxc/devices/platform-ipu-core.c with 98% similarity]
arch/arm/mach-imx/devices/platform-mx1-camera.c [moved from arch/arm/plat-mxc/devices/platform-mx1-camera.c with 94% similarity]
arch/arm/mach-imx/devices/platform-mx2-camera.c [moved from arch/arm/plat-mxc/devices/platform-mx2-camera.c with 83% similarity]
arch/arm/mach-imx/devices/platform-mxc-ehci.c [moved from arch/arm/plat-mxc/devices/platform-mxc-ehci.c with 97% similarity]
arch/arm/mach-imx/devices/platform-mxc-mmc.c [moved from arch/arm/plat-mxc/devices/platform-mxc-mmc.c with 76% similarity]
arch/arm/mach-imx/devices/platform-mxc_nand.c [moved from arch/arm/plat-mxc/devices/platform-mxc_nand.c with 74% similarity]
arch/arm/mach-imx/devices/platform-mxc_pwm.c [moved from arch/arm/plat-mxc/devices/platform-mxc_pwm.c with 97% similarity]
arch/arm/mach-imx/devices/platform-mxc_rnga.c [moved from arch/arm/plat-mxc/devices/platform-mxc_rnga.c with 95% similarity]
arch/arm/mach-imx/devices/platform-mxc_rtc.c [moved from arch/arm/plat-mxc/devices/platform-mxc_rtc.c with 77% similarity]
arch/arm/mach-imx/devices/platform-mxc_w1.c [moved from arch/arm/plat-mxc/devices/platform-mxc_w1.c with 95% similarity]
arch/arm/mach-imx/devices/platform-pata_imx.c [moved from arch/arm/plat-mxc/devices/platform-pata_imx.c with 96% similarity]
arch/arm/mach-imx/devices/platform-sdhci-esdhc-imx.c [moved from arch/arm/plat-mxc/devices/platform-sdhci-esdhc-imx.c with 98% similarity]
arch/arm/mach-imx/devices/platform-spi_imx.c [moved from arch/arm/plat-mxc/devices/platform-spi_imx.c with 98% similarity]
arch/arm/mach-imx/ehci-imx25.c
arch/arm/mach-imx/ehci-imx27.c
arch/arm/mach-imx/ehci-imx31.c
arch/arm/mach-imx/ehci-imx35.c
arch/arm/mach-imx/ehci-imx5.c
arch/arm/mach-imx/epit.c [moved from arch/arm/plat-mxc/epit.c with 99% similarity]
arch/arm/mach-imx/eukrea-baseboards.h [moved from arch/arm/plat-mxc/include/mach/eukrea-baseboards.h with 100% similarity]
arch/arm/mach-imx/eukrea_mbimx27-baseboard.c
arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c
arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c
arch/arm/mach-imx/eukrea_mbimxsd51-baseboard.c
arch/arm/mach-imx/hardware.h [moved from arch/arm/plat-mxc/include/mach/hardware.h with 94% similarity]
arch/arm/mach-imx/hotplug.c
arch/arm/mach-imx/iim.h [moved from arch/arm/plat-mxc/include/mach/iim.h with 100% similarity]
arch/arm/mach-imx/imx27-dt.c
arch/arm/mach-imx/imx31-dt.c
arch/arm/mach-imx/imx51-dt.c
arch/arm/mach-imx/include/mach/dma-mx1-mx2.h [deleted file]
arch/arm/mach-imx/iomux-imx31.c
arch/arm/mach-imx/iomux-mx1.h [moved from arch/arm/plat-mxc/include/mach/iomux-mx1.h with 99% similarity]
arch/arm/mach-imx/iomux-mx21.h [moved from arch/arm/plat-mxc/include/mach/iomux-mx21.h with 99% similarity]
arch/arm/mach-imx/iomux-mx25.h [moved from arch/arm/plat-mxc/include/mach/iomux-mx25.h with 99% similarity]
arch/arm/mach-imx/iomux-mx27.h [moved from arch/arm/plat-mxc/include/mach/iomux-mx27.h with 99% similarity]
arch/arm/mach-imx/iomux-mx2x.h [moved from arch/arm/plat-mxc/include/mach/iomux-mx2x.h with 100% similarity]
arch/arm/mach-imx/iomux-mx3.h [moved from arch/arm/plat-mxc/include/mach/iomux-mx3.h with 100% similarity]
arch/arm/mach-imx/iomux-mx35.h [moved from arch/arm/plat-mxc/include/mach/iomux-mx35.h with 99% similarity]
arch/arm/mach-imx/iomux-mx50.h [moved from arch/arm/plat-mxc/include/mach/iomux-mx50.h with 99% similarity]
arch/arm/mach-imx/iomux-mx51.h [moved from arch/arm/plat-mxc/include/mach/iomux-mx51.h with 99% similarity]
arch/arm/mach-imx/iomux-v1.c [moved from arch/arm/plat-mxc/iomux-v1.c with 98% similarity]
arch/arm/mach-imx/iomux-v1.h [moved from arch/arm/plat-mxc/include/mach/iomux-v1.h with 100% similarity]
arch/arm/mach-imx/iomux-v3.c [moved from arch/arm/plat-mxc/iomux-v3.c with 97% similarity]
arch/arm/mach-imx/iomux-v3.h [moved from arch/arm/plat-mxc/include/mach/iomux-v3.h with 100% similarity]
arch/arm/mach-imx/iram.h [moved from arch/arm/plat-mxc/include/mach/iram.h with 100% similarity]
arch/arm/mach-imx/iram_alloc.c [moved from arch/arm/plat-mxc/iram_alloc.c with 98% similarity]
arch/arm/mach-imx/irq-common.c [moved from arch/arm/plat-mxc/irq-common.c with 100% similarity]
arch/arm/mach-imx/irq-common.h [moved from arch/arm/plat-mxc/irq-common.h with 94% similarity]
arch/arm/mach-imx/lluart.c
arch/arm/mach-imx/mach-apf9328.c
arch/arm/mach-imx/mach-armadillo5x0.c
arch/arm/mach-imx/mach-bug.c
arch/arm/mach-imx/mach-cpuimx27.c
arch/arm/mach-imx/mach-cpuimx35.c
arch/arm/mach-imx/mach-cpuimx51sd.c
arch/arm/mach-imx/mach-eukrea_cpuimx25.c
arch/arm/mach-imx/mach-imx27_visstrim_m10.c
arch/arm/mach-imx/mach-imx27ipcam.c
arch/arm/mach-imx/mach-imx27lite.c
arch/arm/mach-imx/mach-imx53.c
arch/arm/mach-imx/mach-imx6q.c
arch/arm/mach-imx/mach-kzm_arm11_01.c
arch/arm/mach-imx/mach-mx1ads.c
arch/arm/mach-imx/mach-mx21ads.c
arch/arm/mach-imx/mach-mx25_3ds.c
arch/arm/mach-imx/mach-mx27_3ds.c
arch/arm/mach-imx/mach-mx27ads.c
arch/arm/mach-imx/mach-mx31_3ds.c
arch/arm/mach-imx/mach-mx31ads.c
arch/arm/mach-imx/mach-mx31lilly.c
arch/arm/mach-imx/mach-mx31lite.c
arch/arm/mach-imx/mach-mx31moboard.c
arch/arm/mach-imx/mach-mx35_3ds.c
arch/arm/mach-imx/mach-mx50_rdp.c
arch/arm/mach-imx/mach-mx51_3ds.c
arch/arm/mach-imx/mach-mx51_babbage.c
arch/arm/mach-imx/mach-mxt_td60.c
arch/arm/mach-imx/mach-pca100.c
arch/arm/mach-imx/mach-pcm037.c
arch/arm/mach-imx/mach-pcm037_eet.c
arch/arm/mach-imx/mach-pcm038.c
arch/arm/mach-imx/mach-pcm043.c
arch/arm/mach-imx/mach-qong.c
arch/arm/mach-imx/mach-scb9328.c
arch/arm/mach-imx/mach-vpr200.c
arch/arm/mach-imx/mm-imx1.c
arch/arm/mach-imx/mm-imx21.c
arch/arm/mach-imx/mm-imx25.c
arch/arm/mach-imx/mm-imx27.c
arch/arm/mach-imx/mm-imx3.c
arch/arm/mach-imx/mm-imx5.c
arch/arm/mach-imx/mx1.h [moved from arch/arm/plat-mxc/include/mach/mx1.h with 100% similarity]
arch/arm/mach-imx/mx21.h [moved from arch/arm/plat-mxc/include/mach/mx21.h with 100% similarity]
arch/arm/mach-imx/mx25.h [moved from arch/arm/plat-mxc/include/mach/mx25.h with 100% similarity]
arch/arm/mach-imx/mx27.h [moved from arch/arm/plat-mxc/include/mach/mx27.h with 100% similarity]
arch/arm/mach-imx/mx2x.h [moved from arch/arm/plat-mxc/include/mach/mx2x.h with 100% similarity]
arch/arm/mach-imx/mx31.h [moved from arch/arm/plat-mxc/include/mach/mx31.h with 100% similarity]
arch/arm/mach-imx/mx31lilly-db.c
arch/arm/mach-imx/mx31lite-db.c
arch/arm/mach-imx/mx31moboard-devboard.c
arch/arm/mach-imx/mx31moboard-marxbot.c
arch/arm/mach-imx/mx31moboard-smartbot.c
arch/arm/mach-imx/mx35.h [moved from arch/arm/plat-mxc/include/mach/mx35.h with 100% similarity]
arch/arm/mach-imx/mx3x.h [moved from arch/arm/plat-mxc/include/mach/mx3x.h with 100% similarity]
arch/arm/mach-imx/mx50.h [moved from arch/arm/plat-mxc/include/mach/mx50.h with 100% similarity]
arch/arm/mach-imx/mx51.h [moved from arch/arm/plat-mxc/include/mach/mx51.h with 100% similarity]
arch/arm/mach-imx/mx53.h [moved from arch/arm/plat-mxc/include/mach/mx53.h with 100% similarity]
arch/arm/mach-imx/mx6q.h [moved from arch/arm/plat-mxc/include/mach/mx6q.h with 100% similarity]
arch/arm/mach-imx/mxc.h [moved from arch/arm/plat-mxc/include/mach/mxc.h with 100% similarity]
arch/arm/mach-imx/pcm970-baseboard.c
arch/arm/mach-imx/platsmp.c
arch/arm/mach-imx/pm-imx27.c
arch/arm/mach-imx/pm-imx3.c
arch/arm/mach-imx/pm-imx5.c
arch/arm/mach-imx/pm-imx6q.c
arch/arm/mach-imx/ssi-fiq-ksym.c [moved from arch/arm/plat-mxc/ssi-fiq-ksym.c with 100% similarity]
arch/arm/mach-imx/ssi-fiq.S [moved from arch/arm/plat-mxc/ssi-fiq.S with 100% similarity]
arch/arm/mach-imx/system.c [moved from arch/arm/plat-mxc/system.c with 97% similarity]
arch/arm/mach-imx/time.c [moved from arch/arm/plat-mxc/time.c with 99% similarity]
arch/arm/mach-imx/tzic.c [moved from arch/arm/plat-mxc/tzic.c with 98% similarity]
arch/arm/mach-imx/ulpi.c [moved from arch/arm/plat-mxc/ulpi.c with 99% similarity]
arch/arm/mach-imx/ulpi.h [moved from arch/arm/plat-mxc/include/mach/ulpi.h with 100% similarity]
arch/arm/mach-ixp4xx/common-pci.c
arch/arm/mach-ixp4xx/common.c
arch/arm/mach-ixp4xx/goramo_mlr.c
arch/arm/mach-ixp4xx/include/mach/debug-macro.S
arch/arm/mach-ixp4xx/include/mach/ixp4xx-regs.h
arch/arm/mach-ixp4xx/include/mach/qmgr.h
arch/arm/mach-ixp4xx/ixp4xx_npe.c
arch/arm/mach-ixp4xx/ixp4xx_qmgr.c
arch/arm/mach-kirkwood/board-dt.c
arch/arm/mach-kirkwood/common.c
arch/arm/mach-nomadik/board-nhk8815.c
arch/arm/mach-nomadik/cpu-8815.c
arch/arm/mach-nomadik/i2c-8815nhk.c
arch/arm/mach-nomadik/include/mach/fsmc.h [deleted file]
arch/arm/mach-omap2/clock44xx_data.c
arch/arm/mach-omap2/clockdomain.c
arch/arm/mach-omap2/devices.c
arch/arm/mach-omap2/gpmc.c
arch/arm/mach-omap2/timer.c
arch/arm/mach-s3c24xx/clock-s3c2440.c
arch/arm/mach-s3c24xx/s3c2416.c
arch/arm/mach-s3c24xx/s3c2443.c
arch/arm/mach-s3c64xx/mach-crag6410-module.c
arch/arm/mach-s3c64xx/mach-crag6410.c
arch/arm/mach-s5p64x0/common.c
arch/arm/mach-s5pc100/common.c
arch/arm/mach-s5pv210/common.c
arch/arm/mach-s5pv210/mach-goni.c
arch/arm/mach-shmobile/Kconfig
arch/arm/mach-shmobile/board-armadillo800eva.c
arch/arm/mach-shmobile/board-kzm9g.c
arch/arm/mach-shmobile/board-mackerel.c
arch/arm/mach-shmobile/board-marzen.c
arch/arm/mach-shmobile/clock-r8a7779.c
arch/arm/mach-shmobile/include/mach/sh7372.h
arch/arm/mach-shmobile/setup-r8a7740.c
arch/arm/mach-shmobile/setup-r8a7779.c
arch/arm/mach-shmobile/setup-sh7372.c
arch/arm/mach-tegra/apbio.c
arch/arm/mach-tegra/board-dt-tegra20.c
arch/arm/mach-tegra/board-dt-tegra30.c
arch/arm/mach-tegra/board.h
arch/arm/mach-tegra/clock.c
arch/arm/mach-tegra/cpu-tegra.c
arch/arm/mach-tegra/cpuidle.c
arch/arm/mach-tegra/include/mach/dma.h [deleted file]
arch/arm/mach-tegra/include/mach/irqs.h [deleted file]
arch/arm/mach-tegra/include/mach/powergate.h
arch/arm/mach-tegra/pcie.c
arch/arm/mach-tegra/platsmp.c
arch/arm/mach-tegra/sleep-t20.S
arch/arm/mach-tegra/sleep-t30.S
arch/arm/mach-tegra/tegra20_clocks_data.c
arch/arm/mach-tegra/tegra2_emc.c
arch/arm/mach-tegra/tegra30_clocks.c
arch/arm/mach-tegra/tegra30_clocks_data.c
arch/arm/mach-tegra/timer.c
arch/arm/mach-u300/core.c
arch/arm/mach-u300/include/mach/irqs.h
arch/arm/mach-ux500/board-mop500-audio.c
arch/arm/mach-ux500/board-mop500-pins.c
arch/arm/mach-ux500/board-mop500.c
arch/arm/mach-ux500/cpu-db8500.c
arch/arm/mach-ux500/devices-common.c
arch/arm/mach-vt8500/include/mach/hardware.h [deleted file]
arch/arm/mach-vt8500/include/mach/i8042.h [deleted file]
arch/arm/mach-vt8500/include/mach/restart.h [deleted file]
arch/arm/mach-vt8500/timer.c
arch/arm/mach-vt8500/vt8500.c
arch/arm/mm/alignment.c
arch/arm/mm/cache-aurora-l2.h [new file with mode: 0644]
arch/arm/mm/cache-l2x0.c
arch/arm/mm/context.c
arch/arm/mm/dma-mapping.c
arch/arm/mm/mmap.c
arch/arm/mm/mmu.c
arch/arm/mm/nommu.c
arch/arm/mm/proc-v7.S
arch/arm/mm/proc-v7m.S [new file with mode: 0644]
arch/arm/mm/vmregion.h
arch/arm/plat-mxc/Kconfig [deleted file]
arch/arm/plat-mxc/Makefile [deleted file]
arch/arm/plat-mxc/include/mach/irqs.h [deleted file]
arch/arm/plat-mxc/include/mach/timex.h [deleted file]
arch/arm/plat-mxc/include/mach/uncompress.h [deleted file]
arch/arm/plat-nomadik/include/plat/gpio-nomadik.h [deleted file]
arch/arm/plat-omap/debug-devices.c
arch/arm/plat-omap/include/plat/omap-serial.h
arch/arm/plat-omap/include/plat/serial.h
arch/arm/plat-samsung/clock.c
arch/arm/plat-samsung/devs.c
arch/arm/plat-samsung/include/plat/gpio-core.h
arch/arm/plat-samsung/include/plat/mfc.h
arch/arm/plat-samsung/include/plat/spi-core.h [new file with mode: 0644]
arch/arm/plat-samsung/s5p-dev-mfc.c
arch/arm/plat-samsung/s5p-irq-gpioint.c
arch/arm/tools/Makefile
arch/arm/xen/grant-table.c
arch/arm64/Kconfig
arch/arm64/include/asm/Kbuild
arch/arm64/include/asm/io.h
arch/arm64/include/asm/linkage.h [new file with mode: 0644]
arch/arm64/include/asm/processor.h
arch/arm64/include/uapi/asm/ptrace.h
arch/arm64/kernel/ptrace.c
arch/arm64/kernel/setup.c
arch/arm64/kernel/smp.c
arch/arm64/kernel/vdso.c
arch/arm64/mm/fault.c
arch/avr32/Kconfig
arch/blackfin/include/asm/Kbuild
arch/blackfin/include/asm/bfin_sport.h
arch/blackfin/include/asm/bfin_twi.h
arch/blackfin/include/asm/fixed_code.h
arch/blackfin/include/asm/ptrace.h
arch/blackfin/include/asm/uaccess.h
arch/blackfin/include/asm/unistd.h
arch/blackfin/include/uapi/asm/Kbuild
arch/blackfin/include/uapi/asm/bfin_sport.h [new file with mode: 0644]
arch/blackfin/include/uapi/asm/byteorder.h [moved from arch/blackfin/include/asm/byteorder.h with 100% similarity]
arch/blackfin/include/uapi/asm/cachectl.h [moved from arch/blackfin/include/asm/cachectl.h with 100% similarity]
arch/blackfin/include/uapi/asm/fcntl.h [moved from arch/blackfin/include/asm/fcntl.h with 100% similarity]
arch/blackfin/include/uapi/asm/fixed_code.h [new file with mode: 0644]
arch/blackfin/include/uapi/asm/ioctls.h [moved from arch/blackfin/include/asm/ioctls.h with 100% similarity]
arch/blackfin/include/uapi/asm/poll.h [moved from arch/blackfin/include/asm/poll.h with 100% similarity]
arch/blackfin/include/uapi/asm/posix_types.h [moved from arch/blackfin/include/asm/posix_types.h with 100% similarity]
arch/blackfin/include/uapi/asm/ptrace.h [new file with mode: 0644]
arch/blackfin/include/uapi/asm/sigcontext.h [moved from arch/blackfin/include/asm/sigcontext.h with 100% similarity]
arch/blackfin/include/uapi/asm/siginfo.h [moved from arch/blackfin/include/asm/siginfo.h with 100% similarity]
arch/blackfin/include/uapi/asm/signal.h [moved from arch/blackfin/include/asm/signal.h with 100% similarity]
arch/blackfin/include/uapi/asm/stat.h [moved from arch/blackfin/include/asm/stat.h with 100% similarity]
arch/blackfin/include/uapi/asm/swab.h [moved from arch/blackfin/include/asm/swab.h with 100% similarity]
arch/blackfin/include/uapi/asm/unistd.h [new file with mode: 0644]
arch/cris/include/arch-v10/arch/Kbuild
arch/cris/include/arch-v32/arch/Kbuild
arch/cris/include/arch-v32/arch/cryptocop.h
arch/cris/include/arch-v32/arch/spinlock.h
arch/cris/include/asm/Kbuild
arch/cris/include/asm/ptrace.h
arch/cris/include/asm/signal.h
arch/cris/include/asm/swab.h
arch/cris/include/asm/termios.h
arch/cris/include/asm/types.h
arch/cris/include/asm/unistd.h
arch/cris/include/uapi/arch-v10/arch/Kbuild
arch/cris/include/uapi/arch-v10/arch/sv_addr.agh [moved from arch/cris/include/arch-v10/arch/sv_addr.agh with 100% similarity]
arch/cris/include/uapi/arch-v10/arch/sv_addr_ag.h [moved from arch/cris/include/arch-v10/arch/sv_addr_ag.h with 100% similarity]
arch/cris/include/uapi/arch-v10/arch/svinto.h [moved from arch/cris/include/arch-v10/arch/svinto.h with 100% similarity]
arch/cris/include/uapi/arch-v10/arch/user.h [moved from arch/cris/include/arch-v10/arch/user.h with 100% similarity]
arch/cris/include/uapi/arch-v32/arch/Kbuild
arch/cris/include/uapi/arch-v32/arch/cryptocop.h [new file with mode: 0644]
arch/cris/include/uapi/arch-v32/arch/user.h [moved from arch/cris/include/arch-v32/arch/user.h with 100% similarity]
arch/cris/include/uapi/asm/Kbuild
arch/cris/include/uapi/asm/auxvec.h [moved from arch/cris/include/asm/auxvec.h with 100% similarity]
arch/cris/include/uapi/asm/bitsperlong.h [moved from arch/cris/include/asm/bitsperlong.h with 100% similarity]
arch/cris/include/uapi/asm/byteorder.h [moved from arch/cris/include/asm/byteorder.h with 100% similarity]
arch/cris/include/uapi/asm/errno.h [moved from arch/cris/include/asm/errno.h with 100% similarity]
arch/cris/include/uapi/asm/ethernet.h [moved from arch/cris/include/asm/ethernet.h with 100% similarity]
arch/cris/include/uapi/asm/etraxgpio.h [moved from arch/cris/include/asm/etraxgpio.h with 100% similarity]
arch/cris/include/uapi/asm/fcntl.h [moved from arch/cris/include/asm/fcntl.h with 100% similarity]
arch/cris/include/uapi/asm/ioctl.h [moved from arch/cris/include/asm/ioctl.h with 100% similarity]
arch/cris/include/uapi/asm/ioctls.h [moved from arch/cris/include/asm/ioctls.h with 100% similarity]
arch/cris/include/uapi/asm/ipcbuf.h [moved from arch/cris/include/asm/ipcbuf.h with 100% similarity]
arch/cris/include/uapi/asm/mman.h [moved from arch/cris/include/asm/mman.h with 100% similarity]
arch/cris/include/uapi/asm/msgbuf.h [moved from arch/cris/include/asm/msgbuf.h with 100% similarity]
arch/cris/include/uapi/asm/param.h [moved from arch/cris/include/asm/param.h with 100% similarity]
arch/cris/include/uapi/asm/poll.h [moved from arch/cris/include/asm/poll.h with 100% similarity]
arch/cris/include/uapi/asm/posix_types.h [moved from arch/cris/include/asm/posix_types.h with 100% similarity]
arch/cris/include/uapi/asm/ptrace.h [new file with mode: 0644]
arch/cris/include/uapi/asm/resource.h [moved from arch/cris/include/asm/resource.h with 100% similarity]
arch/cris/include/uapi/asm/rs485.h [moved from arch/cris/include/asm/rs485.h with 100% similarity]
arch/cris/include/uapi/asm/sembuf.h [moved from arch/cris/include/asm/sembuf.h with 100% similarity]
arch/cris/include/uapi/asm/setup.h [moved from arch/cris/include/asm/setup.h with 100% similarity]
arch/cris/include/uapi/asm/shmbuf.h [moved from arch/cris/include/asm/shmbuf.h with 100% similarity]
arch/cris/include/uapi/asm/sigcontext.h [moved from arch/cris/include/asm/sigcontext.h with 100% similarity]
arch/cris/include/uapi/asm/siginfo.h [moved from arch/cris/include/asm/siginfo.h with 100% similarity]
arch/cris/include/uapi/asm/signal.h [new file with mode: 0644]
arch/cris/include/uapi/asm/socket.h [moved from arch/cris/include/asm/socket.h with 100% similarity]
arch/cris/include/uapi/asm/sockios.h [moved from arch/cris/include/asm/sockios.h with 100% similarity]
arch/cris/include/uapi/asm/stat.h [moved from arch/cris/include/asm/stat.h with 100% similarity]
arch/cris/include/uapi/asm/statfs.h [moved from arch/cris/include/asm/statfs.h with 100% similarity]
arch/cris/include/uapi/asm/swab.h [new file with mode: 0644]
arch/cris/include/uapi/asm/sync_serial.h [moved from arch/cris/include/asm/sync_serial.h with 100% similarity]
arch/cris/include/uapi/asm/termbits.h [moved from arch/cris/include/asm/termbits.h with 100% similarity]
arch/cris/include/uapi/asm/termios.h [new file with mode: 0644]
arch/cris/include/uapi/asm/types.h [new file with mode: 0644]
arch/cris/include/uapi/asm/unistd.h [new file with mode: 0644]
arch/cris/kernel/asm-offsets.c
arch/hexagon/include/asm/Kbuild
arch/hexagon/include/asm/atomic.h
arch/hexagon/include/asm/barrier.h
arch/hexagon/include/asm/bitops.h
arch/hexagon/include/asm/cache.h
arch/hexagon/include/asm/cacheflush.h
arch/hexagon/include/asm/checksum.h
arch/hexagon/include/asm/cmpxchg.h
arch/hexagon/include/asm/delay.h
arch/hexagon/include/asm/dma-mapping.h
arch/hexagon/include/asm/dma.h
arch/hexagon/include/asm/elf.h
arch/hexagon/include/asm/exec.h
arch/hexagon/include/asm/fixmap.h
arch/hexagon/include/asm/hexagon_vm.h
arch/hexagon/include/asm/intrinsics.h
arch/hexagon/include/asm/io.h
arch/hexagon/include/asm/irq.h
arch/hexagon/include/asm/irqflags.h
arch/hexagon/include/asm/kgdb.h
arch/hexagon/include/asm/linkage.h
arch/hexagon/include/asm/mem-layout.h
arch/hexagon/include/asm/mmu.h
arch/hexagon/include/asm/mmu_context.h
arch/hexagon/include/asm/module.h
arch/hexagon/include/asm/page.h
arch/hexagon/include/asm/perf_event.h
arch/hexagon/include/asm/pgalloc.h
arch/hexagon/include/asm/pgtable.h
arch/hexagon/include/asm/processor.h
arch/hexagon/include/asm/smp.h
arch/hexagon/include/asm/spinlock.h
arch/hexagon/include/asm/spinlock_types.h
arch/hexagon/include/asm/string.h
arch/hexagon/include/asm/suspend.h
arch/hexagon/include/asm/switch_to.h
arch/hexagon/include/asm/syscall.h
arch/hexagon/include/asm/thread_info.h
arch/hexagon/include/asm/time.h
arch/hexagon/include/asm/timer-regs.h
arch/hexagon/include/asm/timex.h
arch/hexagon/include/asm/tlb.h
arch/hexagon/include/asm/tlbflush.h
arch/hexagon/include/asm/traps.h
arch/hexagon/include/asm/uaccess.h
arch/hexagon/include/asm/vdso.h
arch/hexagon/include/asm/vm_fault.h
arch/hexagon/include/asm/vm_mmu.h
arch/hexagon/include/uapi/asm/Kbuild
arch/hexagon/include/uapi/asm/bitsperlong.h [moved from arch/hexagon/include/asm/bitsperlong.h with 92% similarity]
arch/hexagon/include/uapi/asm/byteorder.h [moved from arch/hexagon/include/asm/byteorder.h with 92% similarity]
arch/hexagon/include/uapi/asm/kvm_para.h [moved from arch/blackfin/include/asm/kvm_para.h with 100% similarity]
arch/hexagon/include/uapi/asm/param.h [moved from arch/hexagon/include/asm/param.h with 91% similarity]
arch/hexagon/include/uapi/asm/ptrace.h [moved from arch/hexagon/include/asm/ptrace.h with 94% similarity]
arch/hexagon/include/uapi/asm/registers.h [moved from arch/hexagon/include/asm/registers.h with 85% similarity]
arch/hexagon/include/uapi/asm/setup.h [moved from arch/hexagon/include/asm/setup.h with 92% similarity]
arch/hexagon/include/uapi/asm/sigcontext.h [moved from arch/hexagon/include/asm/sigcontext.h with 93% similarity]
arch/hexagon/include/uapi/asm/signal.h [moved from arch/hexagon/include/asm/signal.h with 92% similarity]
arch/hexagon/include/uapi/asm/swab.h [moved from arch/hexagon/include/asm/swab.h with 91% similarity]
arch/hexagon/include/uapi/asm/unistd.h [moved from arch/hexagon/include/asm/unistd.h with 93% similarity]
arch/hexagon/include/uapi/asm/user.h [moved from arch/hexagon/include/asm/user.h with 63% similarity]
arch/hexagon/kernel/asm-offsets.c
arch/hexagon/kernel/dma.c
arch/hexagon/kernel/head.S
arch/hexagon/kernel/hexagon_ksyms.c
arch/hexagon/kernel/irq_cpu.c
arch/hexagon/kernel/kgdb.c
arch/hexagon/kernel/module.c
arch/hexagon/kernel/process.c
arch/hexagon/kernel/ptrace.c
arch/hexagon/kernel/reset.c
arch/hexagon/kernel/setup.c
arch/hexagon/kernel/signal.c
arch/hexagon/kernel/smp.c
arch/hexagon/kernel/stacktrace.c
arch/hexagon/kernel/syscall.c
arch/hexagon/kernel/syscalltab.c
arch/hexagon/kernel/time.c
arch/hexagon/kernel/topology.c
arch/hexagon/kernel/trampoline.S
arch/hexagon/kernel/traps.c
arch/hexagon/kernel/vdso.c
arch/hexagon/kernel/vm_entry.S
arch/hexagon/kernel/vm_events.c
arch/hexagon/kernel/vm_init_segtable.S
arch/hexagon/kernel/vm_ops.S
arch/hexagon/kernel/vm_switch.S
arch/hexagon/kernel/vm_vectors.S
arch/hexagon/kernel/vmlinux.lds.S
arch/hexagon/lib/checksum.c
arch/hexagon/lib/io.c
arch/hexagon/lib/memcpy.S
arch/hexagon/lib/memset.S
arch/hexagon/mm/cache.c
arch/hexagon/mm/copy_from_user.S
arch/hexagon/mm/copy_to_user.S
arch/hexagon/mm/copy_user_template.S
arch/hexagon/mm/init.c
arch/hexagon/mm/ioremap.c
arch/hexagon/mm/pgalloc.c
arch/hexagon/mm/strnlen_user.S
arch/hexagon/mm/uaccess.c
arch/hexagon/mm/vm_fault.c
arch/hexagon/mm/vm_tlb.c
arch/ia64/include/asm/Kbuild
arch/ia64/include/asm/io.h
arch/ia64/include/asm/kvm_para.h [deleted file]
arch/ia64/kernel/efi.c
arch/m68k/Kconfig.cpu
arch/m68k/Makefile
arch/m68k/include/asm/Kbuild
arch/m68k/include/asm/auxvec.h [deleted file]
arch/m68k/include/asm/hw_irq.h [deleted file]
arch/m68k/include/asm/msgbuf.h [deleted file]
arch/m68k/include/asm/ptrace.h
arch/m68k/include/asm/sembuf.h [deleted file]
arch/m68k/include/asm/setup.h
arch/m68k/include/asm/shmbuf.h [deleted file]
arch/m68k/include/asm/shmparam.h [deleted file]
arch/m68k/include/asm/signal.h
arch/m68k/include/asm/socket.h [deleted file]
arch/m68k/include/asm/sockios.h [deleted file]
arch/m68k/include/asm/spinlock.h [deleted file]
arch/m68k/include/asm/termbits.h [deleted file]
arch/m68k/include/asm/termios.h [deleted file]
arch/m68k/include/asm/unistd.h
arch/m68k/include/uapi/asm/Kbuild
arch/m68k/include/uapi/asm/a.out.h [moved from arch/m68k/include/asm/a.out.h with 100% similarity]
arch/m68k/include/uapi/asm/byteorder.h [moved from arch/m68k/include/asm/byteorder.h with 100% similarity]
arch/m68k/include/uapi/asm/cachectl.h [moved from arch/m68k/include/asm/cachectl.h with 100% similarity]
arch/m68k/include/uapi/asm/fcntl.h [moved from arch/m68k/include/asm/fcntl.h with 100% similarity]
arch/m68k/include/uapi/asm/ioctls.h [moved from arch/m68k/include/asm/ioctls.h with 100% similarity]
arch/m68k/include/uapi/asm/param.h [moved from arch/m68k/include/asm/param.h with 100% similarity]
arch/m68k/include/uapi/asm/poll.h [moved from arch/m68k/include/asm/poll.h with 100% similarity]
arch/m68k/include/uapi/asm/posix_types.h [moved from arch/m68k/include/asm/posix_types.h with 100% similarity]
arch/m68k/include/uapi/asm/ptrace.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/setup.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/sigcontext.h [moved from arch/m68k/include/asm/sigcontext.h with 100% similarity]
arch/m68k/include/uapi/asm/signal.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/stat.h [moved from arch/m68k/include/asm/stat.h with 100% similarity]
arch/m68k/include/uapi/asm/swab.h [moved from arch/m68k/include/asm/swab.h with 100% similarity]
arch/m68k/include/uapi/asm/termios.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/unistd.h [new file with mode: 0644]
arch/m68k/kernel/syscalltable.S
arch/m68k/platform/68000/Makefile [new file with mode: 0644]
arch/m68k/platform/68000/bootlogo-vz.h [moved from arch/m68k/platform/68VZ328/bootlogo.h with 100% similarity]
arch/m68k/platform/68000/bootlogo.h [moved from arch/m68k/platform/68328/bootlogo.h with 100% similarity]
arch/m68k/platform/68000/entry.S [moved from arch/m68k/platform/68328/entry.S with 100% similarity]
arch/m68k/platform/68000/head.S [new file with mode: 0644]
arch/m68k/platform/68000/ints.c [moved from arch/m68k/platform/68328/ints.c with 98% similarity]
arch/m68k/platform/68000/m68328.c [moved from arch/m68k/platform/68328/config.c with 97% similarity]
arch/m68k/platform/68000/m68EZ328.c [moved from arch/m68k/platform/68EZ328/config.c with 97% similarity]
arch/m68k/platform/68000/m68VZ328.c [moved from arch/m68k/platform/68VZ328/config.c with 98% similarity]
arch/m68k/platform/68000/romvec.S [moved from arch/m68k/platform/68328/romvec.S with 94% similarity]
arch/m68k/platform/68000/timers.c [moved from arch/m68k/platform/68328/timers.c with 98% similarity]
arch/m68k/platform/68328/Makefile [deleted file]
arch/m68k/platform/68328/head-de2.S [deleted file]
arch/m68k/platform/68328/head-pilot.S [deleted file]
arch/m68k/platform/68328/head-ram.S [deleted file]
arch/m68k/platform/68328/head-rom.S [deleted file]
arch/m68k/platform/68EZ328/Makefile [deleted file]
arch/m68k/platform/68VZ328/Makefile [deleted file]
arch/microblaze/include/asm/Kbuild
arch/microblaze/include/asm/elf.h
arch/microblaze/include/asm/kvm_para.h [deleted file]
arch/microblaze/include/asm/ptrace.h
arch/microblaze/include/asm/setup.h
arch/microblaze/include/asm/unistd.h
arch/microblaze/include/uapi/asm/Kbuild
arch/microblaze/include/uapi/asm/auxvec.h [moved from arch/microblaze/include/asm/auxvec.h with 100% similarity]
arch/microblaze/include/uapi/asm/bitsperlong.h [moved from arch/microblaze/include/asm/bitsperlong.h with 100% similarity]
arch/microblaze/include/uapi/asm/byteorder.h [moved from arch/microblaze/include/asm/byteorder.h with 100% similarity]
arch/microblaze/include/uapi/asm/elf.h [new file with mode: 0644]
arch/microblaze/include/uapi/asm/errno.h [moved from arch/microblaze/include/asm/errno.h with 100% similarity]
arch/microblaze/include/uapi/asm/fcntl.h [moved from arch/microblaze/include/asm/fcntl.h with 100% similarity]
arch/microblaze/include/uapi/asm/ioctl.h [moved from arch/microblaze/include/asm/ioctl.h with 100% similarity]
arch/microblaze/include/uapi/asm/ioctls.h [moved from arch/microblaze/include/asm/ioctls.h with 100% similarity]
arch/microblaze/include/uapi/asm/ipcbuf.h [moved from arch/microblaze/include/asm/ipcbuf.h with 100% similarity]
arch/microblaze/include/uapi/asm/kvm_para.h [moved from arch/hexagon/include/asm/kvm_para.h with 100% similarity]
arch/microblaze/include/uapi/asm/mman.h [moved from arch/microblaze/include/asm/mman.h with 100% similarity]
arch/microblaze/include/uapi/asm/msgbuf.h [moved from arch/microblaze/include/asm/msgbuf.h with 100% similarity]
arch/microblaze/include/uapi/asm/param.h [moved from arch/microblaze/include/asm/param.h with 100% similarity]
arch/microblaze/include/uapi/asm/poll.h [moved from arch/microblaze/include/asm/poll.h with 100% similarity]
arch/microblaze/include/uapi/asm/posix_types.h [moved from arch/microblaze/include/asm/posix_types.h with 100% similarity]
arch/microblaze/include/uapi/asm/ptrace.h [new file with mode: 0644]
arch/microblaze/include/uapi/asm/resource.h [moved from arch/microblaze/include/asm/resource.h with 100% similarity]
arch/microblaze/include/uapi/asm/sembuf.h [moved from arch/microblaze/include/asm/sembuf.h with 100% similarity]
arch/microblaze/include/uapi/asm/setup.h [new file with mode: 0644]
arch/microblaze/include/uapi/asm/shmbuf.h [moved from arch/microblaze/include/asm/shmbuf.h with 100% similarity]
arch/microblaze/include/uapi/asm/sigcontext.h [moved from arch/microblaze/include/asm/sigcontext.h with 100% similarity]
arch/microblaze/include/uapi/asm/siginfo.h [moved from arch/microblaze/include/asm/siginfo.h with 100% similarity]
arch/microblaze/include/uapi/asm/signal.h [moved from arch/microblaze/include/asm/signal.h with 100% similarity]
arch/microblaze/include/uapi/asm/socket.h [moved from arch/microblaze/include/asm/socket.h with 100% similarity]
arch/microblaze/include/uapi/asm/sockios.h [moved from arch/microblaze/include/asm/sockios.h with 100% similarity]
arch/microblaze/include/uapi/asm/stat.h [moved from arch/microblaze/include/asm/stat.h with 100% similarity]
arch/microblaze/include/uapi/asm/statfs.h [moved from arch/microblaze/include/asm/statfs.h with 100% similarity]
arch/microblaze/include/uapi/asm/swab.h [moved from arch/microblaze/include/asm/swab.h with 100% similarity]
arch/microblaze/include/uapi/asm/termbits.h [moved from arch/microblaze/include/asm/termbits.h with 100% similarity]
arch/microblaze/include/uapi/asm/termios.h [moved from arch/microblaze/include/asm/termios.h with 100% similarity]
arch/microblaze/include/uapi/asm/types.h [moved from arch/microblaze/include/asm/types.h with 100% similarity]
arch/microblaze/include/uapi/asm/unistd.h [new file with mode: 0644]
arch/mips/Kconfig
arch/mips/alchemy/common/Makefile
arch/mips/alchemy/common/platform.c
arch/mips/alchemy/common/usb.c [moved from drivers/usb/host/alchemy-common.c with 100% similarity]
arch/mips/bcm47xx/nvram.c
arch/mips/bcm47xx/wgt634u.c
arch/mips/cavium-octeon/setup.c
arch/mips/configs/cavium_octeon_defconfig
arch/mips/configs/db1000_defconfig
arch/mips/configs/db1235_defconfig
arch/mips/configs/gpr_defconfig
arch/mips/configs/ls1b_defconfig
arch/mips/configs/mtx1_defconfig
arch/mips/include/asm/cpu.h
arch/mips/include/asm/mipsregs.h
arch/mips/include/asm/page.h
arch/mips/include/asm/pgtable-64.h
arch/mips/include/asm/pgtable-bits.h
arch/mips/include/asm/pgtable.h
arch/mips/include/asm/sparsemem.h
arch/mips/include/asm/tlbdebug.h
arch/mips/kernel/mips_ksyms.c
arch/mips/kernel/scall64-n32.S
arch/mips/lib/dump_tlb.c
arch/mips/loongson1/common/platform.c
arch/mips/mm/c-octeon.c
arch/mips/mm/pgtable-64.c
arch/mips/mm/tlb-r4k.c
arch/mips/mm/tlbex.c
arch/mips/netlogic/xlr/platform.c
arch/mips/pci/pci-octeon.c
arch/mips/pnx8550/common/platform.c
arch/parisc/include/asm/Kbuild
arch/parisc/include/asm/auxvec.h [deleted file]
arch/parisc/include/asm/compat_signal.h [deleted file]
arch/parisc/include/asm/cputime.h [deleted file]
arch/parisc/include/asm/device.h [deleted file]
arch/parisc/include/asm/div64.h [deleted file]
arch/parisc/include/asm/emergency-restart.h [deleted file]
arch/parisc/include/asm/hw_irq.h [deleted file]
arch/parisc/include/asm/irq_regs.h [deleted file]
arch/parisc/include/asm/kdebug.h [deleted file]
arch/parisc/include/asm/kvm_para.h [deleted file]
arch/parisc/include/asm/local.h [deleted file]
arch/parisc/include/asm/local64.h [deleted file]
arch/parisc/include/asm/mutex.h [deleted file]
arch/parisc/include/asm/param.h [deleted file]
arch/parisc/include/asm/pdc.h
arch/parisc/include/asm/percpu.h [deleted file]
arch/parisc/include/asm/poll.h [deleted file]
arch/parisc/include/asm/ptrace.h
arch/parisc/include/asm/real.h [deleted file]
arch/parisc/include/asm/segment.h [deleted file]
arch/parisc/include/asm/signal.h
arch/parisc/include/asm/termios.h
arch/parisc/include/asm/topology.h [deleted file]
arch/parisc/include/asm/unistd.h
arch/parisc/include/asm/user.h [deleted file]
arch/parisc/include/asm/vga.h [deleted file]
arch/parisc/include/asm/xor.h [deleted file]
arch/parisc/include/uapi/asm/Kbuild
arch/parisc/include/uapi/asm/bitsperlong.h [moved from arch/parisc/include/asm/bitsperlong.h with 100% similarity]
arch/parisc/include/uapi/asm/byteorder.h [moved from arch/parisc/include/asm/byteorder.h with 100% similarity]
arch/parisc/include/uapi/asm/errno.h [moved from arch/parisc/include/asm/errno.h with 100% similarity]
arch/parisc/include/uapi/asm/fcntl.h [moved from arch/parisc/include/asm/fcntl.h with 100% similarity]
arch/parisc/include/uapi/asm/ioctl.h [moved from arch/parisc/include/asm/ioctl.h with 100% similarity]
arch/parisc/include/uapi/asm/ioctls.h [moved from arch/parisc/include/asm/ioctls.h with 100% similarity]
arch/parisc/include/uapi/asm/ipcbuf.h [moved from arch/parisc/include/asm/ipcbuf.h with 100% similarity]
arch/parisc/include/uapi/asm/mman.h [moved from arch/parisc/include/asm/mman.h with 100% similarity]
arch/parisc/include/uapi/asm/msgbuf.h [moved from arch/parisc/include/asm/msgbuf.h with 100% similarity]
arch/parisc/include/uapi/asm/pdc.h [new file with mode: 0644]
arch/parisc/include/uapi/asm/posix_types.h [moved from arch/parisc/include/asm/posix_types.h with 100% similarity]
arch/parisc/include/uapi/asm/ptrace.h [new file with mode: 0644]
arch/parisc/include/uapi/asm/resource.h [moved from arch/parisc/include/asm/resource.h with 100% similarity]
arch/parisc/include/uapi/asm/sembuf.h [moved from arch/parisc/include/asm/sembuf.h with 100% similarity]
arch/parisc/include/uapi/asm/setup.h [moved from arch/parisc/include/asm/setup.h with 100% similarity]
arch/parisc/include/uapi/asm/shmbuf.h [moved from arch/parisc/include/asm/shmbuf.h with 100% similarity]
arch/parisc/include/uapi/asm/sigcontext.h [moved from arch/parisc/include/asm/sigcontext.h with 100% similarity]
arch/parisc/include/uapi/asm/siginfo.h [moved from arch/parisc/include/asm/siginfo.h with 100% similarity]
arch/parisc/include/uapi/asm/signal.h [new file with mode: 0644]
arch/parisc/include/uapi/asm/socket.h [moved from arch/parisc/include/asm/socket.h with 100% similarity]
arch/parisc/include/uapi/asm/sockios.h [moved from arch/parisc/include/asm/sockios.h with 100% similarity]
arch/parisc/include/uapi/asm/stat.h [moved from arch/parisc/include/asm/stat.h with 100% similarity]
arch/parisc/include/uapi/asm/statfs.h [moved from arch/parisc/include/asm/statfs.h with 100% similarity]
arch/parisc/include/uapi/asm/swab.h [moved from arch/parisc/include/asm/swab.h with 100% similarity]
arch/parisc/include/uapi/asm/termbits.h [moved from arch/parisc/include/asm/termbits.h with 100% similarity]
arch/parisc/include/uapi/asm/termios.h [new file with mode: 0644]
arch/parisc/include/uapi/asm/types.h [moved from arch/parisc/include/asm/types.h with 100% similarity]
arch/parisc/include/uapi/asm/unistd.h [new file with mode: 0644]
arch/powerpc/boot/dts/mpc5200b.dtsi
arch/powerpc/boot/dts/o2d.dtsi
arch/powerpc/boot/dts/pcm030.dts
arch/powerpc/include/asm/fsl_hcalls.h
arch/powerpc/include/asm/kvm_book3s.h
arch/powerpc/include/asm/kvm_booke_hv_asm.h
arch/powerpc/include/asm/kvm_host.h
arch/powerpc/include/asm/kvm_para.h
arch/powerpc/include/asm/kvm_ppc.h
arch/powerpc/include/asm/reg_booke.h
arch/powerpc/include/asm/systbl.h
arch/powerpc/include/asm/unistd.h
arch/powerpc/include/uapi/asm/Kbuild
arch/powerpc/include/uapi/asm/epapr_hcalls.h [moved from arch/powerpc/include/asm/epapr_hcalls.h with 96% similarity]
arch/powerpc/include/uapi/asm/kvm.h
arch/powerpc/include/uapi/asm/kvm_para.h
arch/powerpc/include/uapi/asm/unistd.h
arch/powerpc/kernel/epapr_hcalls.S
arch/powerpc/kernel/epapr_paravirt.c
arch/powerpc/kernel/kvm.c
arch/powerpc/kernel/ppc_ksyms.c
arch/powerpc/kvm/44x.c
arch/powerpc/kvm/44x_emulate.c
arch/powerpc/kvm/Kconfig
arch/powerpc/kvm/book3s.c
arch/powerpc/kvm/book3s_32_mmu_host.c
arch/powerpc/kvm/book3s_64_mmu_host.c
arch/powerpc/kvm/book3s_64_mmu_hv.c
arch/powerpc/kvm/book3s_hv.c
arch/powerpc/kvm/book3s_hv_builtin.c
arch/powerpc/kvm/book3s_hv_rm_mmu.c
arch/powerpc/kvm/book3s_mmu_hpte.c
arch/powerpc/kvm/book3s_pr.c
arch/powerpc/kvm/book3s_rmhandlers.S
arch/powerpc/kvm/booke.c
arch/powerpc/kvm/booke_emulate.c
arch/powerpc/kvm/e500.h
arch/powerpc/kvm/e500_tlb.c
arch/powerpc/kvm/emulate.c
arch/powerpc/kvm/powerpc.c
arch/powerpc/kvm/trace.h
arch/powerpc/platforms/52xx/mpc52xx_pic.c
arch/powerpc/platforms/Kconfig
arch/powerpc/sysdev/fsl_msi.c
arch/powerpc/sysdev/fsl_soc.c
arch/s390/Kconfig
arch/s390/boot/compressed/vmlinux.lds.S
arch/s390/include/asm/perf_event.h
arch/s390/include/asm/pgtable.h
arch/s390/include/uapi/asm/Kbuild
arch/s390/include/uapi/asm/chpid.h
arch/s390/include/uapi/asm/kvm_para.h [new file with mode: 0644]
arch/s390/kernel/Makefile
arch/s390/kernel/cache.c
arch/s390/kernel/entry.h
arch/s390/kernel/entry64.S
arch/s390/kernel/head_kdump.S
arch/s390/kernel/perf_cpum_cf.c
arch/s390/kernel/pgm_check.S [new file with mode: 0644]
arch/s390/kernel/traps.c
arch/s390/kernel/vmlinux.lds.S
arch/s390/kvm/interrupt.c
arch/s390/kvm/kvm-s390.c
arch/s390/mm/dump_pagetables.c
arch/s390/mm/pageattr.c
arch/s390/mm/vmem.c
arch/sh/include/asm/io.h
arch/sh/kernel/cpu/sh3/setup-sh7720.c
arch/sh/kernel/cpu/sh4a/setup-sh7757.c
arch/sh/kernel/cpu/sh4a/setup-sh7763.c
arch/sh/kernel/cpu/sh4a/setup-sh7786.c
arch/sh/mm/Kconfig
arch/sh/mm/mmap.c
arch/tile/Makefile
arch/tile/kernel/module.c
arch/um/drivers/mconsole_kern.c
arch/x86/Kconfig
arch/x86/crypto/Makefile
arch/x86/crypto/camellia_glue.c
arch/x86/crypto/cast5-avx-x86_64-asm_64.S
arch/x86/crypto/cast5_avx_glue.c
arch/x86/crypto/cast6-avx-x86_64-asm_64.S
arch/x86/crypto/cast6_avx_glue.c
arch/x86/crypto/crc32c-intel_glue.c [moved from arch/x86/crypto/crc32c-intel.c with 69% similarity]
arch/x86/crypto/crc32c-pcl-intel-asm_64.S [new file with mode: 0644]
arch/x86/crypto/glue_helper-asm-avx.S [new file with mode: 0644]
arch/x86/crypto/glue_helper.c
arch/x86/crypto/serpent-avx-x86_64-asm_64.S
arch/x86/crypto/serpent_avx_glue.c
arch/x86/crypto/serpent_sse2_glue.c
arch/x86/crypto/twofish-avx-x86_64-asm_64.S
arch/x86/crypto/twofish_avx_glue.c
arch/x86/crypto/twofish_glue_3way.c
arch/x86/include/asm/crypto/glue_helper.h
arch/x86/include/asm/crypto/serpent-avx.h
arch/x86/include/asm/crypto/twofish.h
arch/x86/include/asm/dma-mapping.h
arch/x86/include/asm/efi.h
arch/x86/include/asm/pgtable.h
arch/x86/include/asm/xen/interface.h
arch/x86/include/asm/xen/page.h
arch/x86/kernel/Makefile
arch/x86/kernel/acpi/boot.c
arch/x86/kernel/acpi/sleep.c
arch/x86/kernel/apic/io_apic.c
arch/x86/kernel/cpu/intel_cacheinfo.c
arch/x86/kernel/cpu/mcheck/mce.c
arch/x86/kernel/cpu/mcheck/mce_amd.c
arch/x86/kernel/cpu/perf_event.c
arch/x86/kernel/cpu/perf_event.h
arch/x86/kernel/cpu/perf_event_amd.c
arch/x86/kernel/cpu/perf_event_intel.c
arch/x86/kernel/cpu/perf_event_intel_uncore.c
arch/x86/kernel/cpu/perf_event_knc.c
arch/x86/kernel/cpu/perf_event_p6.c
arch/x86/kernel/entry_32.S
arch/x86/kernel/entry_64.S
arch/x86/kernel/kvm.c
arch/x86/kernel/reboot.c
arch/x86/kernel/rtc.c
arch/x86/kernel/setup.c
arch/x86/kernel/signal.c
arch/x86/kernel/tsc.c
arch/x86/kernel/uprobes.c
arch/x86/kernel/vsyscall_64.c
arch/x86/kvm/lapic.c
arch/x86/kvm/mmu.c
arch/x86/kvm/x86.c
arch/x86/lib/copy_page_64.S
arch/x86/mm/gup.c
arch/x86/mm/init.c
arch/x86/mm/init_64.c
arch/x86/mm/pgtable.c
arch/x86/oprofile/nmi_int.c
arch/x86/pci/acpi.c
arch/x86/platform/ce4100/ce4100.c
arch/x86/platform/efi/efi.c
arch/x86/platform/efi/efi_64.c
arch/x86/realmode/rm/wakeup_asm.S
arch/x86/syscalls/syscall_32.tbl
arch/x86/syscalls/syscall_64.tbl
arch/x86/xen/enlighten.c
arch/x86/xen/setup.c
arch/x86/xen/smp.c
arch/xtensa/boot/boot-redboot/bootstrap.S
arch/xtensa/include/asm/Kbuild
arch/xtensa/include/asm/atomic.h
arch/xtensa/include/asm/bitsperlong.h [deleted file]
arch/xtensa/include/asm/bug.h [deleted file]
arch/xtensa/include/asm/cacheflush.h
arch/xtensa/include/asm/cmpxchg.h
arch/xtensa/include/asm/coprocessor.h
arch/xtensa/include/asm/cputime.h [deleted file]
arch/xtensa/include/asm/delay.h
arch/xtensa/include/asm/device.h [deleted file]
arch/xtensa/include/asm/div64.h [deleted file]
arch/xtensa/include/asm/emergency-restart.h [deleted file]
arch/xtensa/include/asm/errno.h [deleted file]
arch/xtensa/include/asm/fcntl.h [deleted file]
arch/xtensa/include/asm/futex.h [deleted file]
arch/xtensa/include/asm/hardirq.h [deleted file]
arch/xtensa/include/asm/ioctl.h [deleted file]
arch/xtensa/include/asm/irq_regs.h [deleted file]
arch/xtensa/include/asm/irqflags.h
arch/xtensa/include/asm/kdebug.h [deleted file]
arch/xtensa/include/asm/kmap_types.h [deleted file]
arch/xtensa/include/asm/kvm_para.h [deleted file]
arch/xtensa/include/asm/local.h [deleted file]
arch/xtensa/include/asm/local64.h [deleted file]
arch/xtensa/include/asm/mmu_context.h
arch/xtensa/include/asm/param.h
arch/xtensa/include/asm/percpu.h [deleted file]
arch/xtensa/include/asm/ptrace.h
arch/xtensa/include/asm/regs.h
arch/xtensa/include/asm/resource.h [deleted file]
arch/xtensa/include/asm/scatterlist.h [deleted file]
arch/xtensa/include/asm/sections.h [deleted file]
arch/xtensa/include/asm/siginfo.h [deleted file]
arch/xtensa/include/asm/signal.h
arch/xtensa/include/asm/statfs.h [deleted file]
arch/xtensa/include/asm/termios.h [deleted file]
arch/xtensa/include/asm/timex.h
arch/xtensa/include/asm/tlbflush.h
arch/xtensa/include/asm/topology.h [deleted file]
arch/xtensa/include/asm/types.h
arch/xtensa/include/asm/unistd.h
arch/xtensa/include/asm/xor.h [deleted file]
arch/xtensa/include/uapi/asm/Kbuild
arch/xtensa/include/uapi/asm/auxvec.h [moved from arch/xtensa/include/asm/auxvec.h with 100% similarity]
arch/xtensa/include/uapi/asm/byteorder.h [moved from arch/xtensa/include/asm/byteorder.h with 100% similarity]
arch/xtensa/include/uapi/asm/ioctls.h [moved from arch/xtensa/include/asm/ioctls.h with 100% similarity]
arch/xtensa/include/uapi/asm/ipcbuf.h [moved from arch/xtensa/include/asm/ipcbuf.h with 100% similarity]
arch/xtensa/include/uapi/asm/mman.h [moved from arch/xtensa/include/asm/mman.h with 100% similarity]
arch/xtensa/include/uapi/asm/msgbuf.h [moved from arch/xtensa/include/asm/msgbuf.h with 100% similarity]
arch/xtensa/include/uapi/asm/param.h [new file with mode: 0644]
arch/xtensa/include/uapi/asm/poll.h [moved from arch/xtensa/include/asm/poll.h with 100% similarity]
arch/xtensa/include/uapi/asm/posix_types.h [moved from arch/xtensa/include/asm/posix_types.h with 100% similarity]
arch/xtensa/include/uapi/asm/ptrace.h [new file with mode: 0644]
arch/xtensa/include/uapi/asm/sembuf.h [moved from arch/xtensa/include/asm/sembuf.h with 100% similarity]
arch/xtensa/include/uapi/asm/setup.h [moved from arch/xtensa/include/asm/setup.h with 100% similarity]
arch/xtensa/include/uapi/asm/shmbuf.h [moved from arch/xtensa/include/asm/shmbuf.h with 100% similarity]
arch/xtensa/include/uapi/asm/sigcontext.h [moved from arch/xtensa/include/asm/sigcontext.h with 100% similarity]
arch/xtensa/include/uapi/asm/signal.h [new file with mode: 0644]
arch/xtensa/include/uapi/asm/socket.h [moved from arch/xtensa/include/asm/socket.h with 100% similarity]
arch/xtensa/include/uapi/asm/sockios.h [moved from arch/xtensa/include/asm/sockios.h with 100% similarity]
arch/xtensa/include/uapi/asm/stat.h [moved from arch/xtensa/include/asm/stat.h with 100% similarity]
arch/xtensa/include/uapi/asm/swab.h [moved from arch/xtensa/include/asm/swab.h with 100% similarity]
arch/xtensa/include/uapi/asm/termbits.h [moved from arch/xtensa/include/asm/termbits.h with 100% similarity]
arch/xtensa/include/uapi/asm/types.h [new file with mode: 0644]
arch/xtensa/include/uapi/asm/unistd.h [new file with mode: 0644]
arch/xtensa/kernel/align.S
arch/xtensa/kernel/coprocessor.S
arch/xtensa/kernel/entry.S
arch/xtensa/kernel/head.S
arch/xtensa/kernel/irq.c
arch/xtensa/kernel/process.c
arch/xtensa/kernel/setup.c
arch/xtensa/kernel/syscall.c
arch/xtensa/kernel/traps.c
arch/xtensa/kernel/vectors.S
arch/xtensa/lib/memcopy.S
arch/xtensa/mm/fault.c
arch/xtensa/platforms/iss/console.c
arch/xtensa/platforms/iss/include/platform/simcall.h
arch/xtensa/platforms/iss/setup.c
arch/xtensa/platforms/xt2000/setup.c
block/blk-core.c
block/genhd.c
crypto/Kconfig
crypto/cryptd.c
crypto/tcrypt.c
crypto/testmgr.c
crypto/testmgr.h
crypto/vmac.c
drivers/acpi/Kconfig
drivers/acpi/acpi_pad.c
drivers/acpi/container.c
drivers/acpi/dock.c
drivers/acpi/ec.c
drivers/acpi/glue.c
drivers/acpi/internal.h
drivers/acpi/osl.c
drivers/acpi/processor_driver.c
drivers/acpi/scan.c
drivers/acpi/sleep.c
drivers/acpi/thermal.c
drivers/acpi/video.c
drivers/amba/tegra-ahb.c
drivers/base/Kconfig
drivers/base/core.c
drivers/base/dma-buf.c
drivers/base/dma-coherent.c
drivers/base/dma-contiguous.c
drivers/base/firmware_class.c
drivers/base/node.c
drivers/base/power/clock_ops.c
drivers/base/power/domain.c
drivers/base/power/opp.c
drivers/base/power/power.h
drivers/base/power/qos.c
drivers/base/power/sysfs.c
drivers/base/regmap/Kconfig
drivers/base/regmap/internal.h
drivers/base/regmap/regmap-debugfs.c
drivers/base/regmap/regmap-irq.c
drivers/base/regmap/regmap.c
drivers/bcma/driver_chipcommon.c
drivers/bcma/driver_chipcommon_nflash.c
drivers/bcma/driver_chipcommon_pmu.c
drivers/bcma/driver_chipcommon_sflash.c
drivers/bcma/driver_mips.c
drivers/bcma/driver_pci_host.c
drivers/bcma/main.c
drivers/bcma/sprom.c
drivers/block/Kconfig
drivers/block/cciss.c
drivers/block/floppy.c
drivers/block/loop.c
drivers/block/mtip32xx/mtip32xx.c
drivers/block/mtip32xx/mtip32xx.h
drivers/block/rbd.c
drivers/block/xen-blkback/common.h
drivers/block/xen-blkback/xenbus.c
drivers/bluetooth/btmrvl_sdio.c
drivers/bluetooth/hci_ldisc.c
drivers/char/hw_random/Kconfig
drivers/char/hw_random/ixp4xx-rng.c
drivers/char/mem.c
drivers/char/ppdev.c
drivers/char/virtio_console.c
drivers/clk/clk-nomadik.c
drivers/cpufreq/Makefile
drivers/cpufreq/cpufreq.c
drivers/cpufreq/cpufreq_conservative.c
drivers/cpufreq/cpufreq_governor.c [new file with mode: 0644]
drivers/cpufreq/cpufreq_ondemand.c
drivers/cpufreq/cpufreq_performance.c
drivers/cpufreq/cpufreq_powersave.c
drivers/cpufreq/cpufreq_stats.c
drivers/cpufreq/cpufreq_userspace.c
drivers/cpufreq/freq_table.c
drivers/cpufreq/powernow-k8.c
drivers/cpuidle/cpuidle.c
drivers/cpuidle/cpuidle.h
drivers/cpuidle/governors/menu.c
drivers/cpuidle/sysfs.c
drivers/crypto/Kconfig
drivers/crypto/ixp4xx_crypto.c
drivers/crypto/talitos.c
drivers/crypto/tegra-aes.c
drivers/devfreq/devfreq.c
drivers/devfreq/governor.h
drivers/devfreq/governor_performance.c
drivers/devfreq/governor_powersave.c
drivers/devfreq/governor_simpleondemand.c
drivers/devfreq/governor_userspace.c
drivers/dma/Kconfig
drivers/dma/imx-dma.c
drivers/dma/imx-sdma.c
drivers/dma/ipu/ipu_idmac.c
drivers/dma/ipu/ipu_irq.c
drivers/edac/Kconfig
drivers/edac/Makefile
drivers/edac/amd64_edac.c
drivers/edac/amd64_edac.h
drivers/edac/amd64_edac_inj.c
drivers/edac/edac_mc.c
drivers/edac/edac_mc_sysfs.c
drivers/edac/edac_module.c
drivers/edac/edac_pci.c
drivers/edac/highbank_mc_edac.c
drivers/edac/mce_amd.c
drivers/edac/mce_amd.h
drivers/edac/octeon_edac-l2c.c [new file with mode: 0644]
drivers/edac/octeon_edac-lmc.c [new file with mode: 0644]
drivers/edac/octeon_edac-lmc.h [new file with mode: 0644]
drivers/edac/octeon_edac-pc.c [new file with mode: 0644]
drivers/edac/octeon_edac-pci.c [new file with mode: 0644]
drivers/extcon/extcon-adc-jack.c
drivers/extcon/extcon-class.c
drivers/extcon/extcon-gpio.c
drivers/extcon/extcon-max77693.c
drivers/extcon/extcon-max8997.c
drivers/firmware/memmap.c
drivers/gpio/Kconfig
drivers/gpio/Makefile
drivers/gpio/gpio-74x164.c
drivers/gpio/gpio-clps711x.c [new file with mode: 0644]
drivers/gpio/gpio-da9055.c [new file with mode: 0644]
drivers/gpio/gpio-mvebu.c
drivers/gpio/gpio-omap.c
drivers/gpio/gpio-pl061.c
drivers/gpio/gpio-samsung.c
drivers/gpio/gpio-timberdale.c
drivers/gpio/gpio-vt8500.c
drivers/gpio/gpiolib.c
drivers/gpu/drm/drm_fb_cma_helper.c
drivers/gpu/drm/drm_info.c
drivers/gpu/drm/drm_platform.c
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/intel_crt.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_lvds.c
drivers/gpu/drm/i915/intel_sdvo.c
drivers/gpu/drm/nouveau/core/core/gpuobj.c
drivers/gpu/drm/nouveau/core/core/mm.c
drivers/gpu/drm/nouveau/core/subdev/bios/base.c
drivers/gpu/drm/nouveau/core/subdev/bios/pll.c
drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c
drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c
drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c
drivers/gpu/drm/nouveau/nouveau_display.c
drivers/gpu/drm/shmobile/shmob_drm_drv.c
drivers/gpu/drm/ttm/ttm_bo.c
drivers/hid/Makefile
drivers/hid/hid-core.c
drivers/hid/hid-ids.h
drivers/hid/hid-roccat-koneplus.c
drivers/hid/hid-roccat-lua.c [new file with mode: 0644]
drivers/hid/hid-roccat-lua.h [new file with mode: 0644]
drivers/hv/channel.c
drivers/hv/channel_mgmt.c
drivers/hwmon/Kconfig
drivers/hwmon/Makefile
drivers/hwmon/ads7828.c
drivers/hwmon/asb100.c
drivers/hwmon/coretemp.c
drivers/hwmon/da9052-hwmon.c
drivers/hwmon/da9055-hwmon.c [new file with mode: 0644]
drivers/hwmon/ina2xx.c
drivers/hwmon/pmbus/Kconfig
drivers/hwmon/w83627ehf.c
drivers/hwmon/w83627hf.c
drivers/hwmon/w83781d.c
drivers/hwmon/w83791d.c
drivers/hwmon/w83792d.c
drivers/hwmon/w83l786ng.c
drivers/i2c/Makefile
drivers/i2c/busses/Kconfig
drivers/i2c/busses/Makefile
drivers/i2c/busses/i2c-i801.c
drivers/i2c/busses/i2c-imx.c
drivers/i2c/i2c-stub.c [moved from drivers/i2c/busses/i2c-stub.c with 75% similarity]
drivers/iio/Kconfig
drivers/iio/Makefile
drivers/iio/accel/Kconfig
drivers/iio/adc/at91_adc.c
drivers/iio/dac/Kconfig
drivers/iio/dac/Makefile
drivers/iio/dac/ad5449.c [new file with mode: 0644]
drivers/iio/dac/ad5686.c
drivers/iio/industrialio-buffer.c
drivers/iio/industrialio-core.c
drivers/iio/industrialio-event.c
drivers/iio/inkern.c
drivers/infiniband/hw/cxgb4/mem.c
drivers/infiniband/hw/mlx4/alias_GUID.c
drivers/infiniband/hw/mlx4/mad.c
drivers/infiniband/hw/mlx4/mcg.c
drivers/input/evdev.c
drivers/input/joydev.c
drivers/input/joystick/as5011.c
drivers/input/misc/wm831x-on.c
drivers/input/mousedev.c
drivers/input/serio/Kconfig
drivers/input/serio/Makefile
drivers/input/serio/arc_ps2.c [new file with mode: 0644]
drivers/input/serio/i8042-io.h
drivers/input/touchscreen/cy8ctmg110_ts.c
drivers/input/touchscreen/edt-ft5x06.c
drivers/input/touchscreen/mms114.c
drivers/input/touchscreen/wm831x-ts.c
drivers/iommu/amd_iommu.c
drivers/iommu/amd_iommu_init.c
drivers/iommu/amd_iommu_types.h
drivers/iommu/tegra-smmu.c
drivers/lguest/core.c
drivers/md/dm-raid1.c
drivers/md/dm-snap.c
drivers/md/faulty.c
drivers/md/md.c
drivers/md/md.h
drivers/md/persistent-data/dm-btree-internal.h
drivers/md/persistent-data/dm-btree-remove.c
drivers/md/persistent-data/dm-btree-spine.c
drivers/md/persistent-data/dm-btree.c
drivers/md/raid5.c
drivers/md/raid5.h
drivers/media/platform/soc_camera/mx2_camera.c
drivers/media/platform/soc_camera/mx3_camera.c
drivers/memstick/core/Kconfig
drivers/memstick/core/Makefile
drivers/memstick/core/ms_block.c [new file with mode: 0644]
drivers/memstick/core/ms_block.h [new file with mode: 0644]
drivers/misc/atmel-ssc.c
drivers/misc/mei/init.c
drivers/misc/mei/interrupt.c
drivers/misc/mei/iorw.c
drivers/misc/mei/main.c
drivers/misc/mei/mei_dev.h
drivers/mmc/card/queue.c
drivers/mmc/host/Kconfig
drivers/mmc/host/Makefile
drivers/mmc/host/dw_mmc-pci.c
drivers/mmc/host/dw_mmc-pltfm.c
drivers/mmc/host/dw_mmc.c
drivers/mmc/host/mmci.c
drivers/mmc/host/mxcmmc.c
drivers/mmc/host/rtsx_pci_sdmmc.c [new file with mode: 0644]
drivers/mmc/host/sdhci-s3c.c
drivers/mtd/cmdlinepart.c
drivers/mtd/devices/m25p80.c
drivers/mtd/devices/slram.c
drivers/mtd/devices/spear_smi.c
drivers/mtd/nand/Kconfig
drivers/mtd/nand/Makefile
drivers/mtd/nand/atmel_nand.c
drivers/mtd/nand/denali.c
drivers/mtd/nand/denali.h
drivers/mtd/nand/denali_dt.c [new file with mode: 0644]
drivers/mtd/nand/denali_pci.c [new file with mode: 0644]
drivers/mtd/nand/fsl_elbc_nand.c
drivers/mtd/nand/fsmc_nand.c
drivers/mtd/nand/gpmi-nand/gpmi-nand.c
drivers/mtd/nand/mxc_nand.c
drivers/mtd/nand/nand_base.c
drivers/mtd/nand/nomadik_nand.c [deleted file]
drivers/mtd/nand/sh_flctl.c
drivers/mtd/ofpart.c
drivers/mtd/onenand/onenand_base.c
drivers/mtd/tests/mtd_nandbiterrs.c
drivers/mtd/tests/mtd_nandecctest.c
drivers/mtd/tests/mtd_oobtest.c
drivers/mtd/tests/mtd_pagetest.c
drivers/mtd/tests/mtd_readtest.c
drivers/mtd/tests/mtd_speedtest.c
drivers/mtd/tests/mtd_stresstest.c
drivers/mtd/tests/mtd_subpagetest.c
drivers/mtd/tests/mtd_torturetest.c
drivers/net/ethernet/cadence/Kconfig
drivers/net/ethernet/cadence/at91_ether.c
drivers/net/ethernet/cadence/at91_ether.h [deleted file]
drivers/net/ethernet/cadence/macb.c
drivers/net/ethernet/cadence/macb.h
drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
drivers/net/ethernet/emulex/benet/be.h
drivers/net/ethernet/emulex/benet/be_cmds.c
drivers/net/ethernet/emulex/benet/be_cmds.h
drivers/net/ethernet/emulex/benet/be_ethtool.c
drivers/net/ethernet/emulex/benet/be_hw.h
drivers/net/ethernet/emulex/benet/be_main.c
drivers/net/ethernet/intel/e1000e/netdev.c
drivers/net/ethernet/intel/igb/e1000_82575.h
drivers/net/ethernet/intel/igb/e1000_phy.c
drivers/net/ethernet/intel/igb/igb.h
drivers/net/ethernet/intel/igb/igb_ethtool.c
drivers/net/ethernet/intel/igb/igb_main.c
drivers/net/ethernet/intel/igb/igb_ptp.c
drivers/net/ethernet/intel/ixgbe/ixgbe.h
drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c
drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h
drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c
drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
drivers/net/ethernet/intel/ixgbevf/defines.h
drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
drivers/net/ethernet/intel/ixgbevf/mbx.h
drivers/net/ethernet/intel/ixgbevf/vf.c
drivers/net/ethernet/intel/ixgbevf/vf.h
drivers/net/ethernet/mellanox/mlx4/eq.c
drivers/net/ethernet/mellanox/mlx4/main.c
drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
drivers/net/ethernet/qlogic/qla3xxx.c
drivers/net/ethernet/toshiba/ps3_gelic_wireless.c
drivers/net/hyperv/rndis_filter.c
drivers/net/phy/Kconfig
drivers/net/phy/Makefile
drivers/net/phy/at803x.c [new file with mode: 0644]
drivers/net/usb/Kconfig
drivers/net/usb/Makefile
drivers/net/usb/cdc_mbim.c [new file with mode: 0644]
drivers/net/usb/cdc_ncm.c
drivers/net/usb/ipheth.c
drivers/net/usb/qmi_wwan.c
drivers/net/virtio_net.c
drivers/net/wan/ixp4xx_hss.c
drivers/net/wireless/airo.c
drivers/net/wireless/ath/ath6kl/cfg80211.c
drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h
drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
drivers/net/wireless/ath/ath9k/ath9k.h
drivers/net/wireless/ath/ath9k/gpio.c
drivers/net/wireless/ath/ath9k/hif_usb.c
drivers/net/wireless/ath/ath9k/hw.h
drivers/net/wireless/ath/ath9k/link.c
drivers/net/wireless/ath/ath9k/main.c
drivers/net/wireless/ath/carl9170/rx.c
drivers/net/wireless/ath/carl9170/usb.c
drivers/net/wireless/ath/hw.c
drivers/net/wireless/b43/main.c
drivers/net/wireless/brcm80211/brcmfmac/dhd.h
drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c
drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
drivers/net/wireless/brcm80211/brcmfmac/usb.c
drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
drivers/net/wireless/brcm80211/brcmsmac/aiutils.c
drivers/net/wireless/brcm80211/brcmsmac/main.c
drivers/net/wireless/hostap/hostap_80211_rx.c
drivers/net/wireless/ipw2x00/ipw2200.c
drivers/net/wireless/ipw2x00/libipw_rx.c
drivers/net/wireless/iwlwifi/dvm/devices.c
drivers/net/wireless/iwlwifi/dvm/main.c
drivers/net/wireless/iwlwifi/iwl-devtrace.h
drivers/net/wireless/iwlwifi/iwl-io.c
drivers/net/wireless/iwlwifi/iwl-io.h
drivers/net/wireless/iwlwifi/iwl-prph.h
drivers/net/wireless/iwlwifi/iwl-trans.h
drivers/net/wireless/iwlwifi/pcie/rx.c
drivers/net/wireless/iwlwifi/pcie/trans.c
drivers/net/wireless/iwlwifi/pcie/tx.c
drivers/net/wireless/libertas/mesh.c
drivers/net/wireless/mwifiex/cfg80211.c
drivers/net/wireless/mwifiex/cmdevt.c
drivers/net/wireless/mwifiex/main.h
drivers/net/wireless/mwifiex/scan.c
drivers/net/wireless/mwifiex/sta_ioctl.c
drivers/net/wireless/orinoco/main.h
drivers/net/wireless/orinoco/orinoco_usb.c
drivers/net/wireless/rt2x00/rt2500usb.c
drivers/net/wireless/rt2x00/rt2800lib.c
drivers/net/wireless/rt2x00/rt2800usb.c
drivers/net/wireless/rt2x00/rt73usb.c
drivers/net/wireless/rtlwifi/cam.c
drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
drivers/net/wireless/rtlwifi/usb.c
drivers/net/xen-netback/netback.c
drivers/of/base.c
drivers/pci/pci-acpi.c
drivers/pcmcia/pxa2xx_sharpsl.c
drivers/pinctrl/Kconfig
drivers/pinctrl/Makefile
drivers/pinctrl/core.c
drivers/pinctrl/core.h
drivers/pinctrl/pinconf.c
drivers/pinctrl/pinctrl-at91.c [new file with mode: 0644]
drivers/pinctrl/pinctrl-coh901.c
drivers/pinctrl/pinctrl-exynos.c
drivers/pinctrl/pinctrl-exynos.h
drivers/pinctrl/pinctrl-nomadik-db8500.c
drivers/pinctrl/pinctrl-nomadik.c
drivers/pinctrl/pinctrl-nomadik.h
drivers/pinctrl/pinctrl-samsung.c
drivers/pinctrl/pinctrl-samsung.h
drivers/pinctrl/pinctrl-tegra.c
drivers/pinctrl/pinctrl-tegra30.c
drivers/pinctrl/pinctrl-u300.c
drivers/pinctrl/pinmux.c
drivers/platform/x86/acerhdf.c
drivers/platform/x86/asus-wmi.c
drivers/platform/x86/intel_mid_thermal.c
drivers/power/power_supply_core.c
drivers/regulator/Kconfig
drivers/regulator/Makefile
drivers/regulator/core.c
drivers/regulator/gpio-regulator.c
drivers/regulator/lp8788-ldo.c
drivers/regulator/max77686.c
drivers/regulator/tps51632-regulator.c [new file with mode: 0644]
drivers/regulator/tps65090-regulator.c
drivers/regulator/vexpress.c [new file with mode: 0644]
drivers/rpmsg/virtio_rpmsg_bus.c
drivers/rtc/rtc-mxc.c
drivers/s390/cio/css.c
drivers/s390/cio/idset.c
drivers/s390/cio/idset.h
drivers/scsi/arm/fas216.c
drivers/scsi/arm/oak.c
drivers/scsi/osd/osd_uld.c
drivers/scsi/virtio_scsi.c
drivers/spi/spi-bcm63xx.c
drivers/spi/spi-mxs.c
drivers/spi/spi-omap2-mcspi.c
drivers/spi/spi-pl022.c
drivers/spi/spi-rspi.c
drivers/spi/spi-s3c64xx.c
drivers/spi/spi.c
drivers/ssb/driver_mipscore.c
drivers/staging/android/Makefile
drivers/staging/android/binder.c
drivers/staging/android/binder_trace.h [new file with mode: 0644]
drivers/staging/bcm/CmHost.c
drivers/staging/bcm/InterfaceIdleMode.h
drivers/staging/bcm/InterfaceMisc.c
drivers/staging/bcm/LeakyBucket.c
drivers/staging/bcm/Misc.c
drivers/staging/bcm/Prototypes.h
drivers/staging/ccg/ccg.c
drivers/staging/ced1401/ced_ioc.c
drivers/staging/ced1401/usb1401.c
drivers/staging/comedi/Kconfig
drivers/staging/comedi/comedi.h
drivers/staging/comedi/comedidev.h
drivers/staging/comedi/drivers.c
drivers/staging/comedi/drivers/8255_pci.c
drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c
drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c
drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c
drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c
drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c
drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c
drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c
drivers/staging/comedi/drivers/addi-data/addi_common.c
drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c
drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c
drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c
drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c
drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c
drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c
drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c
drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c
drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c
drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c
drivers/staging/comedi/drivers/adl_pci6208.c
drivers/staging/comedi/drivers/adl_pci7x3x.c
drivers/staging/comedi/drivers/adl_pci8164.c
drivers/staging/comedi/drivers/adl_pci9111.c
drivers/staging/comedi/drivers/adl_pci9118.c
drivers/staging/comedi/drivers/adq12b.c
drivers/staging/comedi/drivers/adv_pci1710.c
drivers/staging/comedi/drivers/adv_pci1723.c
drivers/staging/comedi/drivers/adv_pci_dio.c
drivers/staging/comedi/drivers/aio_aio12_8.c
drivers/staging/comedi/drivers/aio_iiro_16.c
drivers/staging/comedi/drivers/amplc_dio200.c
drivers/staging/comedi/drivers/amplc_pc236.c
drivers/staging/comedi/drivers/amplc_pc263.c
drivers/staging/comedi/drivers/amplc_pci224.c
drivers/staging/comedi/drivers/amplc_pci230.c
drivers/staging/comedi/drivers/cb_das16_cs.c
drivers/staging/comedi/drivers/cb_pcidas.c
drivers/staging/comedi/drivers/cb_pcidas64.c
drivers/staging/comedi/drivers/cb_pcidda.c
drivers/staging/comedi/drivers/cb_pcimdas.c
drivers/staging/comedi/drivers/cb_pcimdda.c
drivers/staging/comedi/drivers/comedi_bond.c
drivers/staging/comedi/drivers/comedi_parport.c
drivers/staging/comedi/drivers/comedi_test.c
drivers/staging/comedi/drivers/contec_pci_dio.c
drivers/staging/comedi/drivers/daqboard2000.c
drivers/staging/comedi/drivers/das08.c
drivers/staging/comedi/drivers/das08_cs.c
drivers/staging/comedi/drivers/das16.c
drivers/staging/comedi/drivers/das16m1.c
drivers/staging/comedi/drivers/das1800.c
drivers/staging/comedi/drivers/das6402.c
drivers/staging/comedi/drivers/das800.c
drivers/staging/comedi/drivers/dmm32at.c
drivers/staging/comedi/drivers/dt2801.c
drivers/staging/comedi/drivers/dt2811.c
drivers/staging/comedi/drivers/dt2814.c
drivers/staging/comedi/drivers/dt2815.c
drivers/staging/comedi/drivers/dt282x.c
drivers/staging/comedi/drivers/dt3000.c
drivers/staging/comedi/drivers/dt9812.c
drivers/staging/comedi/drivers/dyna_pci10xx.c
drivers/staging/comedi/drivers/fl512.c
drivers/staging/comedi/drivers/gsc_hpdi.c
drivers/staging/comedi/drivers/icp_multi.c
drivers/staging/comedi/drivers/ii_pci20kc.c
drivers/staging/comedi/drivers/jr3_pci.c
drivers/staging/comedi/drivers/jr3_pci.h
drivers/staging/comedi/drivers/ke_counter.c
drivers/staging/comedi/drivers/me4000.c
drivers/staging/comedi/drivers/me_daq.c
drivers/staging/comedi/drivers/mpc624.c
drivers/staging/comedi/drivers/mpc8260cpm.c [deleted file]
drivers/staging/comedi/drivers/multiq3.c
drivers/staging/comedi/drivers/ni_6527.c
drivers/staging/comedi/drivers/ni_65xx.c
drivers/staging/comedi/drivers/ni_660x.c
drivers/staging/comedi/drivers/ni_670x.c
drivers/staging/comedi/drivers/ni_at_a2150.c
drivers/staging/comedi/drivers/ni_at_ao.c
drivers/staging/comedi/drivers/ni_atmio.c
drivers/staging/comedi/drivers/ni_atmio16d.c
drivers/staging/comedi/drivers/ni_daq_700.c
drivers/staging/comedi/drivers/ni_daq_dio24.c
drivers/staging/comedi/drivers/ni_labpc.c
drivers/staging/comedi/drivers/ni_labpc_cs.c
drivers/staging/comedi/drivers/ni_mio_common.c
drivers/staging/comedi/drivers/ni_mio_cs.c
drivers/staging/comedi/drivers/ni_pcidio.c
drivers/staging/comedi/drivers/ni_pcimio.c
drivers/staging/comedi/drivers/pcl711.c
drivers/staging/comedi/drivers/pcl726.c
drivers/staging/comedi/drivers/pcl812.c
drivers/staging/comedi/drivers/pcl816.c
drivers/staging/comedi/drivers/pcl818.c
drivers/staging/comedi/drivers/pcm3724.c
drivers/staging/comedi/drivers/pcmad.c
drivers/staging/comedi/drivers/pcmda12.c
drivers/staging/comedi/drivers/pcmmio.c
drivers/staging/comedi/drivers/pcmuio.c
drivers/staging/comedi/drivers/poc.c
drivers/staging/comedi/drivers/quatech_daqp_cs.c
drivers/staging/comedi/drivers/rtd520.c
drivers/staging/comedi/drivers/rti800.c
drivers/staging/comedi/drivers/rti802.c
drivers/staging/comedi/drivers/s526.c
drivers/staging/comedi/drivers/s626.c
drivers/staging/comedi/drivers/serial2002.c
drivers/staging/comedi/drivers/skel.c
drivers/staging/comedi/drivers/ssv_dnp.c
drivers/staging/comedi/drivers/unioxx5.c
drivers/staging/comedi/drivers/usbdux.c
drivers/staging/comedi/drivers/usbduxfast.c
drivers/staging/comedi/drivers/vmk80xx.c
drivers/staging/comedi/kcomedilib/kcomedilib_main.c
drivers/staging/crystalhd/crystalhd_cmds.c
drivers/staging/csr/csr_framework_ext.c
drivers/staging/csr/csr_framework_ext.h
drivers/staging/csr/csr_framework_ext_types.h
drivers/staging/csr/csr_log.h
drivers/staging/csr/csr_log_configure.h
drivers/staging/csr/csr_sched.h
drivers/staging/csr/csr_time.c
drivers/staging/csr/csr_time.h
drivers/staging/csr/csr_wifi_hip_dump.c
drivers/staging/csr/csr_wifi_hip_signals.h
drivers/staging/csr/csr_wifi_hip_unifi.h
drivers/staging/csr/csr_wifi_router_ctrl_sef.c
drivers/staging/csr/csr_wifi_router_free_upstream_contents.c
drivers/staging/csr/csr_wifi_sme_sef.h
drivers/staging/csr/csr_wifi_sme_serialize.h
drivers/staging/csr/csr_wifi_sme_task.h
drivers/staging/csr/data_tx.c
drivers/staging/csr/io.c
drivers/staging/csr/monitor.c
drivers/staging/csr/netdev.c
drivers/staging/csr/sdio_mmc.c
drivers/staging/csr/sme_native.c
drivers/staging/csr/sme_sys.c
drivers/staging/csr/sme_userspace.h
drivers/staging/csr/ul_int.c
drivers/staging/csr/unifi_pdu_processing.c
drivers/staging/csr/unifi_priv.h
drivers/staging/csr/unifi_wext.h
drivers/staging/dgrp/Kconfig
drivers/staging/dgrp/dgrp_dpa_ops.c
drivers/staging/dgrp/dgrp_mon_ops.c
drivers/staging/dgrp/dgrp_net_ops.c
drivers/staging/dgrp/dgrp_specproc.c
drivers/staging/dgrp/dgrp_sysfs.c
drivers/staging/dgrp/dgrp_tty.c
drivers/staging/et131x/et131x.c
drivers/staging/gdm72xx/gdm_wimax.c
drivers/staging/gdm72xx/sdio_boot.c
drivers/staging/iio/accel/adis16201_core.c
drivers/staging/iio/accel/adis16203_core.c
drivers/staging/iio/accel/adis16204_core.c
drivers/staging/iio/accel/adis16209_core.c
drivers/staging/iio/accel/adis16209_trigger.c
drivers/staging/iio/accel/adis16220_core.c
drivers/staging/iio/accel/adis16240_core.c
drivers/staging/iio/accel/adis16240_trigger.c
drivers/staging/iio/accel/kxsd9.c
drivers/staging/iio/accel/lis3l02dq.h
drivers/staging/iio/accel/lis3l02dq_core.c
drivers/staging/iio/accel/lis3l02dq_ring.c
drivers/staging/iio/adc/lpc32xx_adc.c
drivers/staging/iio/adc/mxs-lradc.c
drivers/staging/iio/cdc/ad7150.c
drivers/staging/iio/cdc/ad7152.c
drivers/staging/iio/cdc/ad7746.c
drivers/staging/iio/gyro/adis16260_core.c
drivers/staging/iio/iio_dummy_evgen.c
drivers/staging/iio/imu/adis16400.h
drivers/staging/iio/imu/adis16400_core.c
drivers/staging/iio/magnetometer/hmc5843.c
drivers/staging/iio/meter/ade7753.h
drivers/staging/iio/meter/ade7754.h
drivers/staging/iio/meter/ade7758.h
drivers/staging/iio/meter/ade7759.h
drivers/staging/iio/meter/ade7854.h
drivers/staging/ipack/Kconfig
drivers/staging/ipack/Makefile
drivers/staging/ipack/bridges/Kconfig [deleted file]
drivers/staging/ipack/carriers/Kconfig [new file with mode: 0644]
drivers/staging/ipack/carriers/Makefile [moved from drivers/staging/ipack/bridges/Makefile with 100% similarity]
drivers/staging/ipack/carriers/tpci200.c [moved from drivers/staging/ipack/bridges/tpci200.c with 68% similarity]
drivers/staging/ipack/carriers/tpci200.h [moved from drivers/staging/ipack/bridges/tpci200.h with 89% similarity]
drivers/staging/ipack/devices/Kconfig
drivers/staging/ipack/devices/ipoctal.c
drivers/staging/ipack/ipack.c
drivers/staging/ipack/ipack.h
drivers/staging/line6/audio.c
drivers/staging/line6/driver.c
drivers/staging/line6/driver.h
drivers/staging/nvec/nvec.c
drivers/staging/olpc_dcon/olpc_dcon.c
drivers/staging/olpc_dcon/olpc_dcon.h
drivers/staging/olpc_dcon/olpc_dcon_xo_1_5.c
drivers/staging/omap-thermal/omap-thermal-common.c
drivers/staging/omapdrm/omap_crtc.c
drivers/staging/omapdrm/omap_dmm_priv.h
drivers/staging/omapdrm/omap_dmm_tiler.c
drivers/staging/omapdrm/omap_dmm_tiler.h
drivers/staging/omapdrm/omap_fb.c
drivers/staging/omapdrm/omap_gem.c
drivers/staging/ramster/Kconfig
drivers/staging/rtl8192u/ieee80211/ieee80211.h
drivers/staging/rtl8712/rtl871x_ioctl_linux.c
drivers/staging/rts5139/Makefile
drivers/staging/rts5139/ms.c
drivers/staging/rts5139/ms.h
drivers/staging/rts5139/ms_mg.c
drivers/staging/rts5139/ms_mg.h
drivers/staging/rts5139/rts51x.c
drivers/staging/rts5139/rts51x_card.c
drivers/staging/rts5139/rts51x_card.h
drivers/staging/rts5139/rts51x_chip.c
drivers/staging/rts5139/rts51x_chip.h
drivers/staging/rts5139/rts51x_fop.c
drivers/staging/rts5139/rts51x_scsi.c
drivers/staging/rts5139/rts51x_scsi.h
drivers/staging/rts5139/sd.c
drivers/staging/rts5139/sd.h
drivers/staging/rts5139/sd_cprm.c
drivers/staging/rts5139/sd_cprm.h
drivers/staging/rts5139/xd.c
drivers/staging/rts5139/xd.h
drivers/staging/sbe-2t3e3/cpld.c
drivers/staging/sbe-2t3e3/main.c
drivers/staging/sbe-2t3e3/module.c
drivers/staging/sbe-2t3e3/netdev.c
drivers/staging/silicom/bp_mod.c
drivers/staging/silicom/bp_proc.c
drivers/staging/silicom/bypasslib/bplibk.h
drivers/staging/silicom/bypasslib/bypass.c
drivers/staging/slicoss/slicoss.c
drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c
drivers/staging/usbip/stub_dev.c
drivers/staging/usbip/stub_rx.c
drivers/staging/usbip/stub_tx.c
drivers/staging/usbip/usbip_common.c
drivers/staging/usbip/usbip_common.h
drivers/staging/usbip/vhci.h
drivers/staging/usbip/vhci_hcd.c
drivers/staging/usbip/vhci_rx.c
drivers/staging/usbip/vhci_sysfs.c
drivers/staging/usbip/vhci_tx.c
drivers/staging/vt6655/hostap.c
drivers/staging/vt6655/rxtx.c
drivers/staging/vt6655/wcmd.c
drivers/staging/vt6656/device.h
drivers/staging/vt6656/firmware.c
drivers/staging/vt6656/hostap.c
drivers/staging/vt6656/main_usb.c
drivers/staging/vt6656/rf.c
drivers/staging/vt6656/rxtx.c
drivers/staging/vt6656/usbpipe.c
drivers/staging/winbond/mds.c
drivers/staging/winbond/wbhal.h
drivers/staging/wlags49_h2/man/wlags49.4
drivers/staging/xgifb/TODO
drivers/staging/xgifb/vb_setmode.c
drivers/staging/zram/zram_drv.c
drivers/staging/zram/zram_drv.h
drivers/target/iscsi/iscsi_target_parameters.c
drivers/thermal/Kconfig
drivers/thermal/Makefile
drivers/thermal/exynos_thermal.c
drivers/thermal/fair_share.c [new file with mode: 0644]
drivers/thermal/rcar_thermal.c
drivers/thermal/spear_thermal.c
drivers/thermal/step_wise.c [new file with mode: 0644]
drivers/thermal/thermal_core.h [new file with mode: 0644]
drivers/thermal/thermal_sys.c
drivers/thermal/user_space.c [new file with mode: 0644]
drivers/tty/Kconfig
drivers/tty/hvc/hvcs.c
drivers/tty/n_tty.c
drivers/tty/pty.c
drivers/tty/serial/8250/8250.c
drivers/tty/serial/8250/8250.h
drivers/tty/serial/8250/8250_dw.c
drivers/tty/serial/8250/8250_early.c
drivers/tty/serial/8250/8250_hp300.c
drivers/tty/serial/8250/8250_pci.c
drivers/tty/serial/Kconfig
drivers/tty/serial/atmel_serial.c
drivers/tty/serial/clps711x.c
drivers/tty/serial/omap-serial.c
drivers/tty/serial/pxa.c
drivers/tty/serial/samsung.c
drivers/tty/serial/sccnxp.c
drivers/tty/serial/vt8500_serial.c
drivers/tty/tty_audit.c
drivers/tty/tty_buffer.c
drivers/tty/tty_io.c
drivers/tty/tty_ldisc.c
drivers/tty/tty_mutex.c
drivers/tty/tty_port.c
drivers/tty/vt/selection.c
drivers/uio/Kconfig
drivers/uio/Makefile
drivers/uio/uio_dmem_genirq.c [new file with mode: 0644]
drivers/usb/class/cdc-acm.c
drivers/usb/core/devices.c
drivers/usb/core/devio.c
drivers/usb/core/driver.c
drivers/usb/core/hcd.c
drivers/usb/core/hub.c
drivers/usb/core/urb.c
drivers/usb/core/usb.c
drivers/usb/dwc3/core.c
drivers/usb/dwc3/gadget.c
drivers/usb/gadget/Kconfig
drivers/usb/gadget/lpc32xx_udc.c
drivers/usb/gadget/net2272.c
drivers/usb/host/Kconfig
drivers/usb/host/Makefile
drivers/usb/host/ehci-au1xxx.c [deleted file]
drivers/usb/host/ehci-cns3xxx.c [deleted file]
drivers/usb/host/ehci-dbg.c
drivers/usb/host/ehci-fsl.c
drivers/usb/host/ehci-hcd.c
drivers/usb/host/ehci-hub.c
drivers/usb/host/ehci-ixp4xx.c [deleted file]
drivers/usb/host/ehci-lpm.c
drivers/usb/host/ehci-ls1x.c [deleted file]
drivers/usb/host/ehci-mxc.c
drivers/usb/host/ehci-orion.c
drivers/usb/host/ehci-pci.c
drivers/usb/host/ehci-platform.c
drivers/usb/host/ehci-s5p.c
drivers/usb/host/ehci-sched.c
drivers/usb/host/ehci-tegra.c
drivers/usb/host/ehci-vt8500.c
drivers/usb/host/ehci-w90x900.c
drivers/usb/host/ehci-xls.c [deleted file]
drivers/usb/host/ehci.h
drivers/usb/host/ohci-at91.c
drivers/usb/host/ohci-au1xxx.c [deleted file]
drivers/usb/host/ohci-cns3xxx.c [deleted file]
drivers/usb/host/ohci-ep93xx.c
drivers/usb/host/ohci-exynos.c
drivers/usb/host/ohci-hcd.c
drivers/usb/host/ohci-hub.c
drivers/usb/host/ohci-omap.c
drivers/usb/host/ohci-pci.c
drivers/usb/host/ohci-platform.c
drivers/usb/host/ohci-pnx8550.c [deleted file]
drivers/usb/host/ohci-ppc-soc.c [deleted file]
drivers/usb/host/ohci-pxa27x.c
drivers/usb/host/ohci-q.c
drivers/usb/host/ohci-s3c2410.c
drivers/usb/host/ohci-sh.c [deleted file]
drivers/usb/host/ohci-sm501.c
drivers/usb/host/ohci-spear.c
drivers/usb/host/ohci-tmio.c
drivers/usb/host/ohci-xls.c [deleted file]
drivers/usb/host/r8a66597-hcd.c
drivers/usb/host/uhci-platform.c
drivers/usb/host/uhci-q.c
drivers/usb/host/xhci-hub.c
drivers/usb/host/xhci.c
drivers/usb/misc/ezusb.c
drivers/usb/musb/am35x.c
drivers/usb/musb/musb_dsps.c
drivers/usb/phy/tegra_usb_phy.c
drivers/usb/renesas_usbhs/fifo.c
drivers/usb/renesas_usbhs/mod.c
drivers/usb/renesas_usbhs/mod_host.c
drivers/usb/renesas_usbhs/pipe.h
drivers/usb/serial/ark3116.c
drivers/usb/serial/belkin_sa.c
drivers/usb/serial/cp210x.c
drivers/usb/serial/cyberjack.c
drivers/usb/serial/cypress_m8.c
drivers/usb/serial/f81232.c
drivers/usb/serial/garmin_gps.c
drivers/usb/serial/io_edgeport.c
drivers/usb/serial/io_tables.h
drivers/usb/serial/io_ti.c
drivers/usb/serial/iuu_phoenix.c
drivers/usb/serial/keyspan_pda.c
drivers/usb/serial/kl5kusb105.c
drivers/usb/serial/kobil_sct.c
drivers/usb/serial/option.c
drivers/usb/serial/oti6858.c
drivers/usb/serial/pl2303.c
drivers/usb/serial/sierra.c
drivers/usb/serial/spcp8x5.c
drivers/usb/serial/ssu100.c
drivers/usb/serial/ti_usb_3410_5052.c
drivers/usb/storage/unusual_devs.h
drivers/usb/usb-skeleton.c
drivers/usb/wusbcore/devconnect.c
drivers/video/backlight/lm3639_bl.c
drivers/video/imxfb.c
drivers/video/mx3fb.c
drivers/virt/Kconfig
drivers/virtio/virtio_mmio.c
drivers/virtio/virtio_pci.c
drivers/virtio/virtio_ring.c
drivers/watchdog/davinci_wdt.c
drivers/watchdog/imx2_wdt.c
drivers/xen/Kconfig
drivers/xen/balloon.c
drivers/xen/cpu_hotplug.c
drivers/xen/dbgp.c
drivers/xen/events.c
drivers/xen/grant-table.c
drivers/xen/sys-hypervisor.c
drivers/xen/xen-pciback/vpci.c
drivers/xen/xenbus/xenbus_client.c
drivers/xen/xenbus/xenbus_xs.c
fs/Kconfig
fs/char_dev.c
fs/cifs/cifsacl.c
fs/cifs/cifsacl.h
fs/cifs/cifsfs.c
fs/cifs/cifsproto.h
fs/cifs/inode.c
fs/cifs/readdir.c
fs/devpts/inode.c
fs/ext4/balloc.c
fs/ext4/bitmap.c
fs/ext4/ext4.h
fs/ext4/ext4_jbd2.c
fs/ext4/extents.c
fs/ext4/ialloc.c
fs/ext4/mballoc.c
fs/ext4/resize.c
fs/ext4/super.c
fs/fuse/Kconfig
fs/fuse/dev.c
fs/fuse/dir.c
fs/fuse/fuse_i.h
fs/fuse/inode.c
fs/gfs2/file.c
fs/gfs2/glock.c
fs/gfs2/glock.h
fs/gfs2/glops.c
fs/gfs2/incore.h
fs/gfs2/lops.c
fs/gfs2/ops_fstype.c
fs/gfs2/quota.c
fs/gfs2/rgrp.c
fs/jffs2/file.c
fs/jfs/jfs_discard.c
fs/lockd/clnt4xdr.c
fs/lockd/clntproc.c
fs/lockd/clntxdr.c
fs/lockd/host.c
fs/lockd/mon.c
fs/lockd/svcproc.c
fs/logfs/dev_mtd.c
fs/nfs/cache_lib.c
fs/nfs/callback.c
fs/nfs/callback_proc.c
fs/nfs/client.c
fs/nfs/idmap.c
fs/nfs/inode.c
fs/nfs/mount_clnt.c
fs/nfs/nfs2xdr.c
fs/nfs/nfs3xdr.c
fs/nfs/nfs4_fs.h
fs/nfs/nfs4client.c
fs/nfs/nfs4file.c
fs/nfs/nfs4filelayout.c
fs/nfs/nfs4filelayout.h
fs/nfs/nfs4filelayoutdev.c
fs/nfs/nfs4getroot.c
fs/nfs/nfs4proc.c
fs/nfs/nfs4state.c
fs/nfs/nfs4xdr.c
fs/nfs/objlayout/objio_osd.c
fs/nfs/objlayout/objlayout.c
fs/nfs/pnfs.c
fs/nfs/pnfs.h
fs/nfs/write.c
fs/notify/dnotify/dnotify.c
fs/notify/fanotify/fanotify.c
fs/notify/fanotify/fanotify_user.c
fs/notify/group.c
fs/notify/inode_mark.c
fs/notify/inotify/inotify_fsnotify.c
fs/notify/inotify/inotify_user.c
fs/notify/mark.c
fs/notify/notification.c
fs/notify/vfsmount_mark.c
fs/ocfs2/cluster/heartbeat.c
fs/ocfs2/cluster/masklog.h
fs/ocfs2/dlm/dlmmaster.c
fs/ocfs2/dlm/dlmrecovery.c
fs/ocfs2/symlink.c
fs/proc/internal.h
fs/proc/stat.c
fs/proc/task_mmu.c
fs/ubifs/find.c
fs/ubifs/lprops.c
fs/ubifs/ubifs.h
fs/xfs/Makefile
fs/xfs/xfs_alloc.c
fs/xfs/xfs_alloc.h
fs/xfs/xfs_bmap.c
fs/xfs/xfs_bmap.h
fs/xfs/xfs_export.c
fs/xfs/xfs_file.c
fs/xfs/xfs_ialloc.c
fs/xfs/xfs_icache.c [moved from fs/xfs/xfs_sync.c with 64% similarity]
fs/xfs/xfs_icache.h [moved from fs/xfs/xfs_sync.h with 73% similarity]
fs/xfs/xfs_iget.c [deleted file]
fs/xfs/xfs_inode.c
fs/xfs/xfs_inode.h
fs/xfs/xfs_iomap.c
fs/xfs/xfs_itable.c
fs/xfs/xfs_log.c
fs/xfs/xfs_log.h
fs/xfs/xfs_log_priv.h
fs/xfs/xfs_log_recover.c
fs/xfs/xfs_mount.c
fs/xfs/xfs_mount.h
fs/xfs/xfs_qm.c
fs/xfs/xfs_qm_syscalls.c
fs/xfs/xfs_rtalloc.c
fs/xfs/xfs_super.c
fs/xfs/xfs_super.h
fs/xfs/xfs_vnodeops.c
include/acpi/acpi_bus.h
include/asm-generic/pgtable.h
include/crypto/vmac.h
include/linux/acpi.h
include/linux/asn1.h
include/linux/bcma/bcma.h
include/linux/bcma/bcma_driver_chipcommon.h
include/linux/bcma/bcma_driver_mips.h
include/linux/bcma/bcma_regs.h
include/linux/cgroup.h
include/linux/coredump.h
include/linux/cpufreq.h
include/linux/cred.h
include/linux/devfreq.h
include/linux/devpts_fs.h
include/linux/dma-debug.h
include/linux/dma/ipu-dma.h [moved from arch/arm/plat-mxc/include/mach/ipu.h with 97% similarity]
include/linux/earlycpio.h [new file with mode: 0644]
include/linux/edac.h
include/linux/extcon.h
include/linux/freezer.h
include/linux/fsnotify_backend.h
include/linux/hsi/Kbuild
include/linux/huge_mm.h
include/linux/ieee80211.h
include/linux/iio/iio.h
include/linux/iio/types.h
include/linux/ima.h
include/linux/init_task.h
include/linux/key.h
include/linux/kvm_host.h
include/linux/mempolicy.h
include/linux/mfd/max77693.h
include/linux/mfd/tps65090.h
include/linux/mfd/wm8994/pdata.h
include/linux/migrate.h
include/linux/migrate_mode.h
include/linux/mm.h
include/linux/mm_types.h
include/linux/mmc/dw_mmc.h
include/linux/mmzone.h
include/linux/mtd/fsmc.h
include/linux/mtd/mtd.h
include/linux/page-flags-layout.h [new file with mode: 0644]
include/linux/perf_event.h
include/linux/pid_namespace.h
include/linux/platform_data/ad5449.h [new file with mode: 0644]
include/linux/platform_data/ads7828.h [new file with mode: 0644]
include/linux/platform_data/asoc-imx-ssi.h
include/linux/platform_data/davinci_asp.h
include/linux/platform_data/dma-imx.h
include/linux/platform_data/macb.h
include/linux/platform_data/mtd-nomadik-nand.h [deleted file]
include/linux/platform_data/pinctrl-coh901.h
include/linux/platform_data/pinctrl-nomadik.h [moved from arch/arm/plat-nomadik/include/plat/pincfg.h with 66% similarity]
include/linux/platform_data/spi-omap2-mcspi.h
include/linux/platform_data/uio_dmem_genirq.h [new file with mode: 0644]
include/linux/pm.h
include/linux/pm_qos.h
include/linux/raid/Kbuild
include/linux/raid/md_u.h
include/linux/ratelimit.h
include/linux/rculist.h
include/linux/rcupdate.h
include/linux/regmap.h
include/linux/regulator/driver.h
include/linux/regulator/tps51632-regulator.h [new file with mode: 0644]
include/linux/regulator/tps65090-regulator.h [deleted file]
include/linux/sched.h
include/linux/security.h
include/linux/spi/tsc2005.h
include/linux/srcu.h
include/linux/ssb/ssb_driver_mips.h
include/linux/syscalls.h
include/linux/tcp.h
include/linux/tegra-ahb.h [moved from arch/arm/mach-tegra/include/mach/tegra-ahb.h with 86% similarity]
include/linux/thermal.h
include/linux/tick.h
include/linux/tty.h
include/linux/tty_flip.h
include/linux/uprobes.h
include/linux/usb.h
include/linux/usb/Kbuild
include/linux/usb/audio.h
include/linux/usb/cdc_ncm.h [new file with mode: 0644]
include/linux/usb/ch9.h
include/linux/usb/ehci_pdriver.h
include/linux/usb/ezusb.h
include/linux/usb/functionfs.h
include/linux/usb/ohci_pdriver.h
include/linux/virtio.h
include/linux/virtio_scsi.h
include/net/af_unix.h
include/net/bluetooth/a2mp.h
include/net/bluetooth/amp.h [new file with mode: 0644]
include/net/bluetooth/bluetooth.h
include/net/bluetooth/hci.h
include/net/bluetooth/hci_core.h
include/net/bluetooth/l2cap.h
include/net/cfg80211.h
include/net/ip6_fib.h
include/net/mac80211.h
include/sound/Kbuild
include/sound/asequencer.h
include/sound/asound.h
include/sound/cs4271.h
include/sound/emu10k1.h
include/sound/pcm.h
include/sound/sb16_csp.h
include/uapi/asm-generic/unistd.h
include/uapi/linux/fuse.h
include/uapi/linux/hsi/Kbuild
include/uapi/linux/hsi/hsi_char.h [moved from include/linux/hsi/hsi_char.h with 100% similarity]
include/uapi/linux/inet_diag.h
include/uapi/linux/kvm.h
include/uapi/linux/mempolicy.h
include/uapi/linux/nl80211.h
include/uapi/linux/raid/Kbuild
include/uapi/linux/raid/md_p.h [moved from include/linux/raid/md_p.h with 100% similarity]
include/uapi/linux/raid/md_u.h [new file with mode: 0644]
include/uapi/linux/tcp.h
include/uapi/linux/unix_diag.h
include/uapi/linux/usb/Kbuild
include/uapi/linux/usb/audio.h [new file with mode: 0644]
include/uapi/linux/usb/cdc.h [moved from include/linux/usb/cdc.h with 93% similarity]
include/uapi/linux/usb/ch11.h [moved from include/linux/usb/ch11.h with 100% similarity]
include/uapi/linux/usb/ch9.h [new file with mode: 0644]
include/uapi/linux/usb/functionfs.h [new file with mode: 0644]
include/uapi/linux/usb/g_printer.h [moved from include/linux/usb/g_printer.h with 100% similarity]
include/uapi/linux/usb/gadgetfs.h [moved from include/linux/usb/gadgetfs.h with 100% similarity]
include/uapi/linux/usb/midi.h [moved from include/linux/usb/midi.h with 100% similarity]
include/uapi/linux/usb/tmc.h [moved from include/linux/usb/tmc.h with 100% similarity]
include/uapi/linux/usb/video.h [moved from include/linux/usb/video.h with 100% similarity]
include/uapi/sound/Kbuild
include/uapi/sound/asequencer.h [new file with mode: 0644]
include/uapi/sound/asound.h [new file with mode: 0644]
include/uapi/sound/asound_fm.h [moved from include/sound/asound_fm.h with 100% similarity]
include/uapi/sound/compress_offload.h [moved from include/sound/compress_offload.h with 100% similarity]
include/uapi/sound/compress_params.h [moved from include/sound/compress_params.h with 100% similarity]
include/uapi/sound/emu10k1.h [new file with mode: 0644]
include/uapi/sound/hdsp.h [moved from include/sound/hdsp.h with 100% similarity]
include/uapi/sound/hdspm.h [moved from include/sound/hdspm.h with 100% similarity]
include/uapi/sound/sb16_csp.h [new file with mode: 0644]
include/uapi/sound/sfnt_info.h [moved from include/sound/sfnt_info.h with 100% similarity]
include/xen/grant_table.h
include/xen/interface/grant_table.h
include/xen/interface/memory.h
include/xen/interface/xen.h
include/xen/xen.h
init/Kconfig
kernel/audit_tree.c
kernel/audit_watch.c
kernel/auditsc.c
kernel/cgroup.c
kernel/cgroup_freezer.c
kernel/cpu.c
kernel/cred.c
kernel/events/uprobes.c
kernel/fork.c
kernel/ksysfs.c
kernel/lockdep_proc.c
kernel/module-internal.h
kernel/module.c
kernel/module_signing.c
kernel/pid_namespace.c
kernel/power/main.c
kernel/power/qos.c
kernel/power/swap.c
kernel/printk.c
kernel/rcu.h
kernel/rcupdate.c
kernel/rcutiny.c
kernel/rcutiny_plugin.h
kernel/rcutorture.c
kernel/rcutree.c
kernel/rcutree.h
kernel/rcutree_plugin.h
kernel/rcutree_trace.c
kernel/sched/core.c
kernel/sched/debug.c
kernel/sched/fair.c
kernel/sched/features.h
kernel/sched/sched.h
kernel/seccomp.c
kernel/srcu.c
kernel/sys.c
kernel/sys_ni.c
kernel/sysctl.c
kernel/time/tick-sched.c
kernel/trace/ring_buffer.c
kernel/workqueue.c
lib/Kconfig.debug
lib/Makefile
lib/asn1_decoder.c
lib/dma-debug.c
lib/earlycpio.c [new file with mode: 0644]
mm/compaction.c
mm/fremap.c
mm/highmem.c
mm/huge_memory.c
mm/memory.c
mm/mempolicy.c
mm/migrate.c
mm/mprotect.c
mm/page_alloc.c
mm/pgtable-generic.c
mm/slab.c
mm/slab.h
mm/slab_common.c
mm/slob.c
mm/slub.c
mm/util.c
mm/vmstat.c
net/8021q/vlan.c
net/9p/trans_virtio.c
net/batman-adv/bridge_loop_avoidance.c
net/batman-adv/routing.c
net/batman-adv/types.h
net/bluetooth/Kconfig
net/bluetooth/Makefile
net/bluetooth/a2mp.c
net/bluetooth/af_bluetooth.c
net/bluetooth/amp.c [new file with mode: 0644]
net/bluetooth/bnep/core.c
net/bluetooth/cmtp/capi.c
net/bluetooth/cmtp/core.c
net/bluetooth/cmtp/sock.c
net/bluetooth/hci_conn.c
net/bluetooth/hci_core.c
net/bluetooth/hci_event.c
net/bluetooth/hci_sysfs.c
net/bluetooth/hidp/core.c
net/bluetooth/l2cap_core.c
net/bluetooth/l2cap_sock.c
net/bluetooth/lib.c
net/bluetooth/mgmt.c
net/bluetooth/rfcomm/core.c
net/bluetooth/rfcomm/sock.c
net/bluetooth/rfcomm/tty.c
net/bluetooth/sco.c
net/bluetooth/smp.c
net/ceph/messenger.c
net/core/dev.c
net/core/pktgen.c
net/core/rtnetlink.c
net/core/skbuff.c
net/core/sock.c
net/dns_resolver/dns_key.c
net/ipv4/fib_semantics.c
net/ipv4/inet_diag.c
net/ipv4/route.c
net/ipv4/tcp.c
net/ipv4/tcp_input.c
net/ipv4/tcp_ipv4.c
net/ipv4/tcp_minisocks.c
net/ipv4/tcp_timer.c
net/ipv6/ip6_fib.c
net/ipv6/route.c
net/ipv6/tcp_ipv6.c
net/irda/ircomm/ircomm_tty.c
net/mac80211/Kconfig
net/mac80211/Makefile
net/mac80211/cfg.c
net/mac80211/chan.c
net/mac80211/debugfs.h
net/mac80211/debugfs_netdev.c
net/mac80211/driver-ops.h
net/mac80211/ibss.c
net/mac80211/ieee80211_i.h
net/mac80211/iface.c
net/mac80211/main.c
net/mac80211/mesh.c
net/mac80211/mesh.h
net/mac80211/mesh_plink.c
net/mac80211/mesh_sync.c
net/mac80211/mlme.c
net/mac80211/offchannel.c
net/mac80211/pm.c
net/mac80211/rate.h
net/mac80211/rx.c
net/mac80211/scan.c
net/mac80211/sta_info.c
net/mac80211/status.c
net/mac80211/trace.h
net/mac80211/tx.c
net/mac80211/util.c
net/mac80211/vht.c [new file with mode: 0644]
net/mac80211/wpa.c
net/netfilter/ipvs/ip_vs_ctl.c
net/netfilter/xt_CT.c
net/netfilter/xt_TEE.c
net/netfilter/xt_nat.c
net/netlink/af_netlink.c
net/sched/sch_api.c
net/sched/sch_cbq.c
net/sunrpc/cache.c
net/sunrpc/xprtsock.c
net/unix/diag.c
net/wireless/Makefile
net/wireless/ap.c
net/wireless/chan.c
net/wireless/core.c
net/wireless/core.h
net/wireless/ethtool.c
net/wireless/ibss.c
net/wireless/mesh.c
net/wireless/mlme.c
net/wireless/nl80211.c
net/wireless/rdev-ops.h [new file with mode: 0644]
net/wireless/scan.c
net/wireless/sme.c
net/wireless/sysfs.c
net/wireless/trace.c [new file with mode: 0644]
net/wireless/trace.h [new file with mode: 0644]
net/wireless/util.c
net/wireless/wext-compat.c
scripts/Makefile.modinst
scripts/Makefile.modpost
scripts/kconfig/Makefile
scripts/sign-file [changed mode: 0644->0755]
scripts/x509keyid [deleted file]
security/capability.c
security/integrity/ima/ima.h
security/integrity/ima/ima_api.c
security/integrity/ima/ima_main.c
security/integrity/ima/ima_policy.c
security/keys/key.c
security/keys/keyctl.c
security/keys/keyring.c
security/keys/process_keys.c
security/keys/request_key.c
security/security.c
sound/core/pcm_compat.c
sound/core/pcm_lib.c
sound/core/pcm_native.c
sound/drivers/Kconfig
sound/drivers/aloop.c
sound/drivers/dummy.c
sound/isa/Kconfig
sound/isa/opti9xx/miro.c
sound/pci/Kconfig
sound/pci/als300.c
sound/pci/hda/Kconfig
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_codec.h
sound/pci/hda/hda_intel.c
sound/pci/hda/hda_jack.c
sound/pci/hda/hda_jack.h
sound/pci/hda/hda_local.h
sound/pci/hda/patch_cirrus.c
sound/pci/hda/patch_conexant.c
sound/pci/hda/patch_hdmi.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_sigmatel.c
sound/pci/ice1712/Makefile
sound/pci/ice1712/amp.c
sound/pci/ice1712/aureon.c
sound/pci/ice1712/delta.c
sound/pci/ice1712/ews.c
sound/pci/ice1712/hoontech.c
sound/pci/ice1712/ice1712.c
sound/pci/ice1712/ice1712.h
sound/pci/ice1712/ice1724.c
sound/pci/ice1712/juli.c
sound/pci/ice1712/maya44.c
sound/pci/ice1712/phase.c
sound/pci/ice1712/pontis.c
sound/pci/ice1712/prodigy192.c
sound/pci/ice1712/prodigy_hifi.c
sound/pci/ice1712/psc724.c [new file with mode: 0644]
sound/pci/ice1712/psc724.h [new file with mode: 0644]
sound/pci/ice1712/quartet.c
sound/pci/ice1712/revo.c
sound/pci/ice1712/se.c
sound/pci/ice1712/vt1720_mobo.c
sound/pci/ice1712/wm8766.c [new file with mode: 0644]
sound/pci/ice1712/wm8766.h [new file with mode: 0644]
sound/pci/ice1712/wm8776.c [new file with mode: 0644]
sound/pci/ice1712/wm8776.h [new file with mode: 0644]
sound/pci/ice1712/wtm.c
sound/pci/rme9652/hdspm.c
sound/soc/atmel/sam9g20_wm8731.c
sound/soc/codecs/Kconfig
sound/soc/codecs/Makefile
sound/soc/codecs/ak4104.c
sound/soc/codecs/cs4271.c
sound/soc/codecs/da9055.c
sound/soc/codecs/si476x.c [new file with mode: 0644]
sound/soc/codecs/wm2200.c
sound/soc/codecs/wm8750.c
sound/soc/codecs/wm8770.c
sound/soc/codecs/wm8958-dsp2.c
sound/soc/codecs/wm8971.c
sound/soc/codecs/wm8994.c
sound/soc/codecs/wm8994.h
sound/soc/codecs/wmfw.h [new file with mode: 0644]
sound/soc/davinci/davinci-evm.c
sound/soc/davinci/davinci-mcasp.c
sound/soc/davinci/davinci-mcasp.h
sound/soc/davinci/davinci-pcm.c
sound/soc/davinci/davinci-pcm.h
sound/soc/fsl/Kconfig
sound/soc/fsl/Makefile
sound/soc/fsl/imx-pcm-fiq.c
sound/soc/fsl/imx-ssi.c
sound/soc/fsl/p1022_rdk.c [new file with mode: 0644]
sound/soc/fsl/pcm030-audio-fabric.c
sound/soc/samsung/ac97.c
sound/soc/samsung/bells.c
sound/soc/samsung/i2s.c
sound/soc/samsung/pcm.c
sound/soc/samsung/spdif.c
sound/soc/sh/fsi.c
sound/soc/soc-jack.c
sound/soc/tegra/tegra30_ahub.c
sound/soc/tegra/tegra_pcm.h
sound/soc/ux500/mop500.c
sound/soc/ux500/ux500_msp_i2s.c
sound/usb/Kconfig
sound/usb/pcm.c
sound/usb/quirks-table.h
tools/kvm/.gitignore [new file with mode: 0644]
tools/kvm/CREDITS-Git [new file with mode: 0644]
tools/kvm/Documentation/kernel-debugging.txt [new file with mode: 0644]
tools/kvm/Documentation/kvm-balloon.txt [new file with mode: 0644]
tools/kvm/Documentation/kvm-debug.txt [new file with mode: 0644]
tools/kvm/Documentation/kvm-list.txt [new file with mode: 0644]
tools/kvm/Documentation/kvm-pause.txt [new file with mode: 0644]
tools/kvm/Documentation/kvm-resume.txt [new file with mode: 0644]
tools/kvm/Documentation/kvm-run.txt [new file with mode: 0644]
tools/kvm/Documentation/kvm-sandbox.txt [new file with mode: 0644]
tools/kvm/Documentation/kvm-setup.txt [new file with mode: 0644]
tools/kvm/Documentation/kvm-stat.txt [new file with mode: 0644]
tools/kvm/Documentation/kvm-stop.txt [new file with mode: 0644]
tools/kvm/Documentation/kvm-version.txt [new file with mode: 0644]
tools/kvm/Documentation/virtio-console.txt [new file with mode: 0644]
tools/kvm/Makefile [new file with mode: 0644]
tools/kvm/README [new file with mode: 0644]
tools/kvm/builtin-balloon.c [new file with mode: 0644]
tools/kvm/builtin-debug.c [new file with mode: 0644]
tools/kvm/builtin-help.c [new file with mode: 0644]
tools/kvm/builtin-list.c [new file with mode: 0644]
tools/kvm/builtin-pause.c [new file with mode: 0644]
tools/kvm/builtin-resume.c [new file with mode: 0644]
tools/kvm/builtin-run.c [new file with mode: 0644]
tools/kvm/builtin-sandbox.c [new file with mode: 0644]
tools/kvm/builtin-setup.c [new file with mode: 0644]
tools/kvm/builtin-stat.c [new file with mode: 0644]
tools/kvm/builtin-stop.c [new file with mode: 0644]
tools/kvm/builtin-version.c [new file with mode: 0644]
tools/kvm/code16gcc.h [new file with mode: 0644]
tools/kvm/command-list.txt [new file with mode: 0644]
tools/kvm/config/feature-tests.mak [new file with mode: 0644]
tools/kvm/config/utilities.mak [new file with mode: 0644]
tools/kvm/disk/blk.c [new file with mode: 0644]
tools/kvm/disk/core.c [new file with mode: 0644]
tools/kvm/disk/qcow.c [new file with mode: 0644]
tools/kvm/disk/raw.c [new file with mode: 0644]
tools/kvm/framebuffer.c [new file with mode: 0644]
tools/kvm/guest/init.c [new file with mode: 0644]
tools/kvm/guest_compat.c [new file with mode: 0644]
tools/kvm/hw/i8042.c [new file with mode: 0644]
tools/kvm/hw/pci-shmem.c [new file with mode: 0644]
tools/kvm/hw/rtc.c [new file with mode: 0644]
tools/kvm/hw/serial.c [new file with mode: 0644]
tools/kvm/hw/vesa.c [new file with mode: 0644]
tools/kvm/include/asm/hweight.h [new file with mode: 0644]
tools/kvm/include/bios/memcpy.h [new file with mode: 0644]
tools/kvm/include/kvm/8250-serial.h [new file with mode: 0644]
tools/kvm/include/kvm/apic.h [new file with mode: 0644]
tools/kvm/include/kvm/brlock.h [new file with mode: 0644]
tools/kvm/include/kvm/builtin-balloon.h [new file with mode: 0644]
tools/kvm/include/kvm/builtin-debug.h [new file with mode: 0644]
tools/kvm/include/kvm/builtin-help.h [new file with mode: 0644]
tools/kvm/include/kvm/builtin-list.h [new file with mode: 0644]
tools/kvm/include/kvm/builtin-pause.h [new file with mode: 0644]
tools/kvm/include/kvm/builtin-resume.h [new file with mode: 0644]
tools/kvm/include/kvm/builtin-run.h [new file with mode: 0644]
tools/kvm/include/kvm/builtin-sandbox.h [new file with mode: 0644]
tools/kvm/include/kvm/builtin-setup.h [new file with mode: 0644]
tools/kvm/include/kvm/builtin-stat.h [new file with mode: 0644]
tools/kvm/include/kvm/builtin-stop.h [new file with mode: 0644]
tools/kvm/include/kvm/builtin-version.h [new file with mode: 0644]
tools/kvm/include/kvm/compiler.h [new file with mode: 0644]
tools/kvm/include/kvm/disk-image.h [new file with mode: 0644]
tools/kvm/include/kvm/e820.h [new file with mode: 0644]
tools/kvm/include/kvm/framebuffer.h [new file with mode: 0644]
tools/kvm/include/kvm/guest_compat.h [new file with mode: 0644]
tools/kvm/include/kvm/i8042.h [new file with mode: 0644]
tools/kvm/include/kvm/ioeventfd.h [new file with mode: 0644]
tools/kvm/include/kvm/ioport.h [new file with mode: 0644]
tools/kvm/include/kvm/irq.h [new file with mode: 0644]
tools/kvm/include/kvm/kvm-cmd.h [new file with mode: 0644]
tools/kvm/include/kvm/kvm-config.h [new file with mode: 0644]
tools/kvm/include/kvm/kvm-cpu.h [new file with mode: 0644]
tools/kvm/include/kvm/kvm-ipc.h [new file with mode: 0644]
tools/kvm/include/kvm/kvm.h [new file with mode: 0644]
tools/kvm/include/kvm/msi.h [new file with mode: 0644]
tools/kvm/include/kvm/mutex.h [new file with mode: 0644]
tools/kvm/include/kvm/parse-options.h [new file with mode: 0644]
tools/kvm/include/kvm/pci-shmem.h [new file with mode: 0644]
tools/kvm/include/kvm/pci.h [new file with mode: 0644]
tools/kvm/include/kvm/qcow.h [new file with mode: 0644]
tools/kvm/include/kvm/rbtree-interval.h [new file with mode: 0644]
tools/kvm/include/kvm/read-write.h [new file with mode: 0644]
tools/kvm/include/kvm/rtc.h [new file with mode: 0644]
tools/kvm/include/kvm/rwsem.h [new file with mode: 0644]
tools/kvm/include/kvm/sdl.h [new file with mode: 0644]
tools/kvm/include/kvm/segment.h [new file with mode: 0644]
tools/kvm/include/kvm/strbuf.h [new file with mode: 0644]
tools/kvm/include/kvm/symbol.h [new file with mode: 0644]
tools/kvm/include/kvm/term.h [new file with mode: 0644]
tools/kvm/include/kvm/threadpool.h [new file with mode: 0644]
tools/kvm/include/kvm/types.h [new file with mode: 0644]
tools/kvm/include/kvm/uip.h [new file with mode: 0644]
tools/kvm/include/kvm/util-init.h [new file with mode: 0644]
tools/kvm/include/kvm/util.h [new file with mode: 0644]
tools/kvm/include/kvm/vesa.h [new file with mode: 0644]
tools/kvm/include/kvm/virtio-9p.h [new file with mode: 0644]
tools/kvm/include/kvm/virtio-balloon.h [new file with mode: 0644]
tools/kvm/include/kvm/virtio-blk.h [new file with mode: 0644]
tools/kvm/include/kvm/virtio-console.h [new file with mode: 0644]
tools/kvm/include/kvm/virtio-mmio.h [new file with mode: 0644]
tools/kvm/include/kvm/virtio-net.h [new file with mode: 0644]
tools/kvm/include/kvm/virtio-pci-dev.h [new file with mode: 0644]
tools/kvm/include/kvm/virtio-pci.h [new file with mode: 0644]
tools/kvm/include/kvm/virtio-rng.h [new file with mode: 0644]
tools/kvm/include/kvm/virtio-scsi.h [new file with mode: 0644]
tools/kvm/include/kvm/virtio.h [new file with mode: 0644]
tools/kvm/include/kvm/vnc.h [new file with mode: 0644]
tools/kvm/include/linux/bitops.h [new file with mode: 0644]
tools/kvm/include/linux/byteorder.h [new file with mode: 0644]
tools/kvm/include/linux/compiler.h [new file with mode: 0644]
tools/kvm/include/linux/kernel.h [new file with mode: 0644]
tools/kvm/include/linux/module.h [new file with mode: 0644]
tools/kvm/include/linux/prefetch.h [new file with mode: 0644]
tools/kvm/include/linux/stddef.h [new file with mode: 0644]
tools/kvm/include/linux/types.h [new file with mode: 0644]
tools/kvm/ioeventfd.c [new file with mode: 0644]
tools/kvm/ioport.c [new file with mode: 0644]
tools/kvm/kvm-cmd.c [new file with mode: 0644]
tools/kvm/kvm-cpu.c [new file with mode: 0644]
tools/kvm/kvm-ipc.c [new file with mode: 0644]
tools/kvm/kvm.c [new file with mode: 0644]
tools/kvm/main.c [new file with mode: 0644]
tools/kvm/mmio.c [new file with mode: 0644]
tools/kvm/net/uip/arp.c [new file with mode: 0644]
tools/kvm/net/uip/buf.c [new file with mode: 0644]
tools/kvm/net/uip/core.c [new file with mode: 0644]
tools/kvm/net/uip/csum.c [new file with mode: 0644]
tools/kvm/net/uip/dhcp.c [new file with mode: 0644]
tools/kvm/net/uip/icmp.c [new file with mode: 0644]
tools/kvm/net/uip/ipv4.c [new file with mode: 0644]
tools/kvm/net/uip/tcp.c [new file with mode: 0644]
tools/kvm/net/uip/udp.c [new file with mode: 0644]
tools/kvm/pci.c [new file with mode: 0644]
tools/kvm/powerpc/boot.c [new file with mode: 0644]
tools/kvm/powerpc/cpu_info.c [new file with mode: 0644]
tools/kvm/powerpc/cpu_info.h [new file with mode: 0644]
tools/kvm/powerpc/include/kvm/barrier.h [new file with mode: 0644]
tools/kvm/powerpc/include/kvm/kvm-arch.h [new file with mode: 0644]
tools/kvm/powerpc/include/kvm/kvm-cpu-arch.h [new file with mode: 0644]
tools/kvm/powerpc/ioport.c [new file with mode: 0644]
tools/kvm/powerpc/irq.c [new file with mode: 0644]
tools/kvm/powerpc/kvm-cpu.c [new file with mode: 0644]
tools/kvm/powerpc/kvm.c [new file with mode: 0644]
tools/kvm/powerpc/spapr.h [new file with mode: 0644]
tools/kvm/powerpc/spapr_hcall.c [new file with mode: 0644]
tools/kvm/powerpc/spapr_hvcons.c [new file with mode: 0644]
tools/kvm/powerpc/spapr_hvcons.h [new file with mode: 0644]
tools/kvm/powerpc/spapr_pci.c [new file with mode: 0644]
tools/kvm/powerpc/spapr_pci.h [new file with mode: 0644]
tools/kvm/powerpc/spapr_rtas.c [new file with mode: 0644]
tools/kvm/powerpc/xics.c [new file with mode: 0644]
tools/kvm/powerpc/xics.h [new file with mode: 0644]
tools/kvm/symbol.c [new file with mode: 0644]
tools/kvm/term.c [new file with mode: 0644]
tools/kvm/tests/Makefile [new file with mode: 0644]
tools/kvm/tests/boot/Makefile [new file with mode: 0644]
tools/kvm/tests/boot/init.c [new file with mode: 0644]
tools/kvm/tests/kernel/.gitignore [new file with mode: 0644]
tools/kvm/tests/kernel/Makefile [new file with mode: 0644]
tools/kvm/tests/kernel/README [new file with mode: 0644]
tools/kvm/tests/kernel/kernel.S [new file with mode: 0644]
tools/kvm/tests/pit/.gitignore [new file with mode: 0644]
tools/kvm/tests/pit/Makefile [new file with mode: 0644]
tools/kvm/tests/pit/README [new file with mode: 0644]
tools/kvm/tests/pit/tick.S [new file with mode: 0644]
tools/kvm/ui/sdl.c [new file with mode: 0644]
tools/kvm/ui/vnc.c [new file with mode: 0644]
tools/kvm/util/KVMTOOLS-VERSION-GEN [new file with mode: 0755]
tools/kvm/util/generate-cmdlist.sh [new file with mode: 0755]
tools/kvm/util/init.c [new file with mode: 0644]
tools/kvm/util/kvm-ifup-vbr0 [new file with mode: 0755]
tools/kvm/util/parse-options.c [new file with mode: 0644]
tools/kvm/util/rbtree-interval.c [new file with mode: 0644]
tools/kvm/util/read-write.c [new file with mode: 0644]
tools/kvm/util/set_private_br.sh [new file with mode: 0755]
tools/kvm/util/strbuf.c [new file with mode: 0644]
tools/kvm/util/threadpool.c [new file with mode: 0644]
tools/kvm/util/util.c [new file with mode: 0644]
tools/kvm/virtio/9p-pdu.c [new file with mode: 0644]
tools/kvm/virtio/9p.c [new file with mode: 0644]
tools/kvm/virtio/balloon.c [new file with mode: 0644]
tools/kvm/virtio/blk.c [new file with mode: 0644]
tools/kvm/virtio/console.c [new file with mode: 0644]
tools/kvm/virtio/core.c [new file with mode: 0644]
tools/kvm/virtio/mmio.c [new file with mode: 0644]
tools/kvm/virtio/net.c [new file with mode: 0644]
tools/kvm/virtio/pci.c [new file with mode: 0644]
tools/kvm/virtio/rng.c [new file with mode: 0644]
tools/kvm/virtio/scsi.c [new file with mode: 0644]
tools/kvm/x86/bios.c [new file with mode: 0644]
tools/kvm/x86/bios/.gitignore [new file with mode: 0644]
tools/kvm/x86/bios/bios-rom.S [new file with mode: 0644]
tools/kvm/x86/bios/e820.c [new file with mode: 0644]
tools/kvm/x86/bios/entry.S [new file with mode: 0644]
tools/kvm/x86/bios/gen-offsets.sh [new file with mode: 0644]
tools/kvm/x86/bios/int10.c [new file with mode: 0644]
tools/kvm/x86/bios/int15.c [new file with mode: 0644]
tools/kvm/x86/bios/local.S [new file with mode: 0644]
tools/kvm/x86/bios/macro.S [new file with mode: 0644]
tools/kvm/x86/bios/memcpy.c [new file with mode: 0644]
tools/kvm/x86/bios/rom.ld.S [new file with mode: 0644]
tools/kvm/x86/boot.c [new file with mode: 0644]
tools/kvm/x86/cpuid.c [new file with mode: 0644]
tools/kvm/x86/include/kvm/assembly.h [new file with mode: 0644]
tools/kvm/x86/include/kvm/barrier.h [new file with mode: 0644]
tools/kvm/x86/include/kvm/bios-export.h [new file with mode: 0644]
tools/kvm/x86/include/kvm/bios.h [new file with mode: 0644]
tools/kvm/x86/include/kvm/boot-protocol.h [new file with mode: 0644]
tools/kvm/x86/include/kvm/cpufeature.h [new file with mode: 0644]
tools/kvm/x86/include/kvm/interrupt.h [new file with mode: 0644]
tools/kvm/x86/include/kvm/kvm-arch.h [new file with mode: 0644]
tools/kvm/x86/include/kvm/kvm-cpu-arch.h [new file with mode: 0644]
tools/kvm/x86/include/kvm/mptable.h [new file with mode: 0644]
tools/kvm/x86/interrupt.c [new file with mode: 0644]
tools/kvm/x86/ioport.c [new file with mode: 0644]
tools/kvm/x86/irq.c [new file with mode: 0644]
tools/kvm/x86/kvm-cpu.c [new file with mode: 0644]
tools/kvm/x86/kvm.c [new file with mode: 0644]
tools/kvm/x86/mptable.c [new file with mode: 0644]
tools/lguest/lguest.c
tools/lib/traceevent/event-parse.c
tools/lib/traceevent/parse-filter.c
tools/perf/Documentation/android.txt [new file with mode: 0644]
tools/perf/Documentation/perf-diff.txt
tools/perf/Makefile
tools/perf/builtin-annotate.c
tools/perf/builtin-diff.c
tools/perf/builtin-help.c
tools/perf/builtin-inject.c
tools/perf/builtin-kvm.c
tools/perf/builtin-record.c
tools/perf/builtin-report.c
tools/perf/builtin-sched.c
tools/perf/builtin-script.c
tools/perf/builtin-test.c
tools/perf/builtin-top.c
tools/perf/builtin-trace.c
tools/perf/config/feature-tests.mak
tools/perf/perf.c
tools/perf/perf.h
tools/perf/ui/browsers/hists.c
tools/perf/ui/hist.c
tools/perf/ui/stdio/hist.c
tools/perf/util/build-id.c
tools/perf/util/event.c
tools/perf/util/event.h
tools/perf/util/evlist.c
tools/perf/util/hist.h
tools/perf/util/machine.c [new file with mode: 0644]
tools/perf/util/machine.h [new file with mode: 0644]
tools/perf/util/parse-events-test.c
tools/perf/util/parse-events.c
tools/perf/util/parse-events.h
tools/perf/util/parse-events.y
tools/perf/util/pmu.c
tools/perf/util/scripting-engines/trace-event-python.c
tools/perf/util/session.c
tools/perf/util/setup.py
tools/perf/util/sort.c
tools/perf/util/sort.h
tools/perf/util/thread.c
tools/perf/util/thread.h
tools/perf/util/trace-event-read.c
tools/perf/util/util.c
tools/perf/util/util.h
tools/virtio/virtio_test.c
virt/kvm/iommu.c
virt/kvm/kvm_main.c

index 0f2f40f71915fcdbf1a10b1e975131d137cdf2fa..92bd0e45dfa165cfdaddb3de4f91e2db61a7a927 100644 (file)
 *.o.*
 *.a
 *.s
-*.ko.unsigned
-*.ko.stripped
-*.ko.stripped.dig
-*.ko.stripped.sig
 *.ko
 *.so
 *.so.dbg
@@ -95,6 +91,4 @@ GTAGS
 extra_certificates
 signing_key.priv
 signing_key.x509
-signing_key.x509.keyid
-signing_key.x509.signer
 x509.genkey
diff --git a/CREDITS b/CREDITS
index d8fe12a9421fa2a7145e7218cc7d664232d0d7ce..b4cdc8f2971abaea1d397199f23095fc7a98e754 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -125,6 +125,7 @@ D: Author of pscan that helps to fix lp/parport bugs
 D: Author of lil (Linux Interrupt Latency benchmark)
 D: Fixed the shm swap deallocation at swapoff time (try_to_unuse message)
 D: VM hacker
+D: NUMA task placement
 D: Various other kernel hacks
 S: Imola 40026
 S: Italy
index f54273e2ac979a386e27c0174e4a9524e60eae5e..ceb1ff735469995b560f0cdf07227407be682235 100644 (file)
@@ -210,6 +210,8 @@ local_ops.txt
        - semantics and behavior of local atomic operations.
 lockdep-design.txt
        - documentation on the runtime locking correctness validator.
+lockup-watchdogs.txt
+       - info on soft and hard lockup detectors (aka nmi_watchdog).
 logo.gif
        - full colour GIF image of Linux logo (penguin - Tux).
 logo.txt
@@ -240,8 +242,6 @@ netlabel/
        - directory with information on the NetLabel subsystem.
 networking/
        - directory with info on various aspects of networking with Linux.
-nmi_watchdog.txt
-       - info on NMI watchdog for SMP systems.
 nommu-mmap.txt
        - documentation about no-mmu memory mapping support.
 numastat.txt
index 986946613542b4bc1852aaf671e62059d3295cea..ec0a38ef3145e30a90ace37c391d0eba33c81bc7 100644 (file)
@@ -23,7 +23,7 @@ Description:
                        lsm:    [[subj_user=] [subj_role=] [subj_type=]
                                 [obj_user=] [obj_role=] [obj_type=]]
 
-               base:   func:= [BPRM_CHECK][FILE_MMAP][FILE_CHECK]
+               base:   func:= [BPRM_CHECK][FILE_MMAP][FILE_CHECK][MODULE_CHECK]
                        mask:= [MAY_READ] [MAY_WRITE] [MAY_APPEND] [MAY_EXEC]
                        fsmagic:= hex value
                        uid:= decimal value
@@ -53,6 +53,7 @@ Description:
                        measure func=BPRM_CHECK
                        measure func=FILE_MMAP mask=MAY_EXEC
                        measure func=FILE_CHECK mask=MAY_READ uid=0
+                       measure func=MODULE_CHECK uid=0
                        appraise fowner=0
 
                The default policy measures all executables in bprm_check,
index 23d78b5aab11d140f1f47e29c098d44051793ef8..e6cf08e6734d4b727055022077afd2c7ece03d84 100644 (file)
@@ -19,15 +19,16 @@ Date:               September 2011
 Contact:       MyungJoo Ham <myungjoo.ham@samsung.com>
 Description:
                The /sys/class/devfreq/.../cur_freq shows the current
-               frequency of the corresponding devfreq object.
+               frequency of the corresponding devfreq object. Same as
+               target_freq when get_cur_freq() is not implemented by
+               devfreq driver.
 
-What:          /sys/class/devfreq/.../central_polling
-Date:          September 2011
-Contact:       MyungJoo Ham <myungjoo.ham@samsung.com>
+What:          /sys/class/devfreq/.../target_freq
+Date:          September 2012
+Contact:       Rajagopal Venkat <rajagopal.venkat@linaro.org>
 Description:
-               The /sys/class/devfreq/.../central_polling shows whether
-               the devfreq ojbect is using devfreq-provided central
-               polling mechanism or not.
+               The /sys/class/devfreq/.../target_freq shows the next governor
+               predicted target frequency of the corresponding devfreq object.
 
 What:          /sys/class/devfreq/.../polling_interval
 Date:          September 2011
index 45000f0db4d4b4f7779ee9dbd44e727613a930cf..7fc2997b23a6e25e1690249b3161a29f6b950596 100644 (file)
@@ -204,3 +204,34 @@ Description:
 
                This attribute has no effect on system-wide suspend/resume and
                hibernation.
+
+What:          /sys/devices/.../power/pm_qos_no_power_off
+Date:          September 2012
+Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Description:
+               The /sys/devices/.../power/pm_qos_no_power_off attribute
+               is used for manipulating the PM QoS "no power off" flag.  If
+               set, this flag indicates to the kernel that power should not
+               be removed entirely from the device.
+
+               Not all drivers support this attribute.  If it isn't supported,
+               it is not present.
+
+               This attribute has no effect on system-wide suspend/resume and
+               hibernation.
+
+What:          /sys/devices/.../power/pm_qos_remote_wakeup
+Date:          September 2012
+Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Description:
+               The /sys/devices/.../power/pm_qos_remote_wakeup attribute
+               is used for manipulating the PM QoS "remote wakeup required"
+               flag.  If set, this flag indicates to the kernel that the
+               device is a source of user events that have to be signaled from
+               its low-power states.
+
+               Not all drivers support this attribute.  If it isn't supported,
+               it is not present.
+
+               This attribute has no effect on system-wide suspend/resume and
+               hibernation.
index 65e6e5dd67e83a04cc0f8e93feffda8eb5c7be38..f9e2a61900e506cc8fe77930462e96d19d7abdb0 100644 (file)
@@ -104,9 +104,9 @@ What:               /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-
 Date:          October 2010
 Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
 Description:   When written a calibration process for the tracking control unit
-               can be initiated/cancelled.
-               The data has to be 3 bytes long.
-               This file is writeonly.
+               can be initiated/cancelled. Also lets one read/write sensor
+               registers.
+               The data has to be 4 bytes long.
 Users:         http://roccat.sourceforge.net
 
 What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/tcu_image
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-roccat-lua b/Documentation/ABI/testing/sysfs-driver-hid-roccat-lua
new file mode 100644 (file)
index 0000000..31c6c4c
--- /dev/null
@@ -0,0 +1,7 @@
+What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/control
+Date:          October 2012
+Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:   When written, cpi, button and light settings can be configured.
+               When read, actual cpi setting and sensor data are returned.
+               The data has to be 8 bytes long.
+Users:         http://roccat.sourceforge.net
index a0b6250add79c9c144fd1185fa91314febaa4241..4a4fb295ceefb722e5bbbf46dbff37af0669d848 100644 (file)
@@ -468,11 +468,46 @@ To map a single region, you do:
        size_t size = buffer->len;
 
        dma_handle = dma_map_single(dev, addr, size, direction);
+       if (dma_mapping_error(dma_handle)) {
+               /*
+                * reduce current DMA mapping usage,
+                * delay and try again later or
+                * reset driver.
+                */
+               goto map_error_handling;
+       }
 
 and to unmap it:
 
        dma_unmap_single(dev, dma_handle, size, direction);
 
+You should call dma_mapping_error() as dma_map_single() could fail and return
+error. Not all dma implementations support dma_mapping_error() interface.
+However, it is a good practice to call dma_mapping_error() interface, which
+will invoke the generic mapping error check interface. Doing so will ensure
+that the mapping code will work correctly on all dma implementations without
+any dependency on the specifics of the underlying implementation. Using the
+returned address without checking for errors could result in failures ranging
+from panics to silent data corruption. Couple of example of incorrect ways to
+check for errors that make assumptions about the underlying dma implementation
+are as follows and these are applicable to dma_map_page() as well.
+
+Incorrect example 1:
+       dma_addr_t dma_handle;
+
+       dma_handle = dma_map_single(dev, addr, size, direction);
+       if ((dma_handle & 0xffff != 0) || (dma_handle >= 0x1000000)) {
+               goto map_error;
+       }
+
+Incorrect example 2:
+       dma_addr_t dma_handle;
+
+       dma_handle = dma_map_single(dev, addr, size, direction);
+       if (dma_handle == DMA_ERROR_CODE) {
+               goto map_error;
+       }
+
 You should call dma_unmap_single when the DMA activity is finished, e.g.
 from the interrupt which told you that the DMA transfer is done.
 
@@ -489,6 +524,14 @@ Specifically:
        size_t size = buffer->len;
 
        dma_handle = dma_map_page(dev, page, offset, size, direction);
+       if (dma_mapping_error(dma_handle)) {
+               /*
+                * reduce current DMA mapping usage,
+                * delay and try again later or
+                * reset driver.
+                */
+               goto map_error_handling;
+       }
 
        ...
 
@@ -496,6 +539,12 @@ Specifically:
 
 Here, "offset" means byte offset within the given page.
 
+You should call dma_mapping_error() as dma_map_page() could fail and return
+error as outlined under the dma_map_single() discussion.
+
+You should call dma_unmap_page when the DMA activity is finished, e.g.
+from the interrupt which told you that the DMA transfer is done.
+
 With scatterlists, you map a region gathered from several regions by:
 
        int i, count = dma_map_sg(dev, sglist, nents, direction);
@@ -578,6 +627,14 @@ to use the dma_sync_*() interfaces.
                dma_addr_t mapping;
 
                mapping = dma_map_single(cp->dev, buffer, len, DMA_FROM_DEVICE);
+               if (dma_mapping_error(dma_handle)) {
+                       /*
+                        * reduce current DMA mapping usage,
+                        * delay and try again later or
+                        * reset driver.
+                        */
+                       goto map_error_handling;
+               }
 
                cp->rx_buf = buffer;
                cp->rx_len = len;
@@ -658,6 +715,75 @@ failure can be determined by:
                 * delay and try again later or
                 * reset driver.
                 */
+               goto map_error_handling;
+       }
+
+- unmap pages that are already mapped, when mapping error occurs in the middle
+  of a multiple page mapping attempt. These example are applicable to
+  dma_map_page() as well.
+
+Example 1:
+       dma_addr_t dma_handle1;
+       dma_addr_t dma_handle2;
+
+       dma_handle1 = dma_map_single(dev, addr, size, direction);
+       if (dma_mapping_error(dev, dma_handle1)) {
+               /*
+                * reduce current DMA mapping usage,
+                * delay and try again later or
+                * reset driver.
+                */
+               goto map_error_handling1;
+       }
+       dma_handle2 = dma_map_single(dev, addr, size, direction);
+       if (dma_mapping_error(dev, dma_handle2)) {
+               /*
+                * reduce current DMA mapping usage,
+                * delay and try again later or
+                * reset driver.
+                */
+               goto map_error_handling2;
+       }
+
+       ...
+
+       map_error_handling2:
+               dma_unmap_single(dma_handle1);
+       map_error_handling1:
+
+Example 2: (if buffers are allocated a loop, unmap all mapped buffers when
+           mapping error is detected in the middle)
+
+       dma_addr_t dma_addr;
+       dma_addr_t array[DMA_BUFFERS];
+       int save_index = 0;
+
+       for (i = 0; i < DMA_BUFFERS; i++) {
+
+               ...
+
+               dma_addr = dma_map_single(dev, addr, size, direction);
+               if (dma_mapping_error(dev, dma_addr)) {
+                       /*
+                        * reduce current DMA mapping usage,
+                        * delay and try again later or
+                        * reset driver.
+                        */
+                       goto map_error_handling;
+               }
+               array[i].dma_addr = dma_addr;
+               save_index++;
+       }
+
+       ...
+
+       map_error_handling:
+
+       for (i = 0; i < save_index; i++) {
+
+               ...
+
+               dma_unmap_single(array[i].dma_addr);
        }
 
 Networking drivers must call dev_kfree_skb to free the socket buffer
index 66bd97a95f10e18fc9b2a4bff7acb691957cc6a3..78a6c569d204bc0073e33fe093d34a8137e5eaf4 100644 (file)
@@ -678,3 +678,15 @@ out of dma_debug_entries. These entries are preallocated at boot. The number
 of preallocated entries is defined per architecture. If it is too low for you
 boot with 'dma_debug_entries=<your_desired_number>' to overwrite the
 architectural default.
+
+void debug_dmap_mapping_error(struct device *dev, dma_addr_t dma_addr);
+
+dma-debug interface debug_dma_mapping_error() to debug drivers that fail
+to check dma mapping errors on addresses returned by dma_map_single() and
+dma_map_page() interfaces. This interface clears a flag set by
+debug_dma_map_page() to indicate that dma_mapping_error() has been called by
+the driver. When driver does unmap, debug_dma_unmap() checks the flag and if
+this flag is still set, prints warning message that includes call trace that
+leads up to the unmap. This interface can be called from dma_mapping_error()
+routines to enable dma mapping error check debugging.
+
index ac3d0018140cd34cd7dd242334de64713406c6b6..fdbf86fcfccd4525e3fbbd267106a7a0019b6e12 100644 (file)
@@ -719,6 +719,62 @@ framework to set up sysfs files for this region. Simply leave it alone.
        </para>
 </sect1>
 
+<sect1 id="using uio_dmem_genirq">
+<title>Using uio_dmem_genirq for platform devices</title>
+       <para>
+       In addition to statically allocated memory ranges, they may also be
+       a desire to use dynamically allocated regions in a user space driver.
+       In particular, being able to access memory made available through the
+       dma-mapping API, may be particularly useful.  The
+       <varname>uio_dmem_genirq</varname> driver provides a way to accomplish
+       this.
+       </para>
+       <para>
+       This driver is used in a similar manner to the
+       <varname>"uio_pdrv_genirq"</varname> driver with respect to interrupt
+       configuration and handling.
+       </para>
+       <para>
+       Set the <varname>.name</varname> element of
+       <varname>struct platform_device</varname> to
+       <varname>"uio_dmem_genirq"</varname> to use this driver.
+       </para>
+       <para>
+       When using this driver, fill in the <varname>.platform_data</varname>
+       element of <varname>struct platform_device</varname>, which is of type
+       <varname>struct uio_dmem_genirq_pdata</varname> and which contains the
+       following elements:
+       </para>
+       <itemizedlist>
+       <listitem><varname>struct uio_info uioinfo</varname>: The same
+       structure used as the  <varname>uio_pdrv_genirq</varname> platform
+       data</listitem>
+       <listitem><varname>unsigned int *dynamic_region_sizes</varname>:
+       Pointer to list of sizes of dynamic memory regions to be mapped into
+       user space.
+       </listitem>
+       <listitem><varname>unsigned int num_dynamic_regions</varname>:
+       Number of elements in <varname>dynamic_region_sizes</varname> array.
+       </listitem>
+       </itemizedlist>
+       <para>
+       The dynamic regions defined in the platform data will be appended to
+       the <varname> mem[] </varname> array after the platform device
+       resources, which implies that the total number of static and dynamic
+       memory regions cannot exceed <varname>MAX_UIO_MAPS</varname>.
+       </para>
+       <para>
+       The dynamic memory regions will be allocated when the UIO device file,
+       <varname>/dev/uioX</varname> is opened.
+       Simiar to static memory resources, the memory region information for
+       dynamic regions is then visible via sysfs at
+       <varname>/sys/class/uio/uioX/maps/mapY/*</varname>.
+       The dynmaic memory regions will be freed when the UIO device file is
+       closed. When no processes are holding the device file open, the address
+       returned to userspace is DMA_ERROR_CODE.
+       </para>
+</sect1>
+
 </chapter>
 
 <chapter id="userspace_driver" xreflabel="Writing a driver in user space">
index 7c1dfb19fc40a9074f2cc182f356f458df802d44..7f40c72a9c515078afe5fa2b0c7da2d09cebfedb 100644 (file)
@@ -186,7 +186,7 @@ Bibtex Entries
 
 @article{Kung80
 ,author="H. T. Kung and Q. Lehman"
-,title="Concurrent Maintenance of Binary Search Trees"
+,title="Concurrent Manipulation of Binary Search Trees"
 ,Year="1980"
 ,Month="September"
 ,journal="ACM Transactions on Database Systems"
index cdb20d41a44ad8992f2f7b6e13a01d0200c67a32..31ef8fe07f828026ad31f29e63bdd95143bf3e2a 100644 (file)
@@ -271,15 +271,14 @@ over a rather long period of time, but improvements are always welcome!
        The same cautions apply to call_rcu_bh() and call_rcu_sched().
 
 9.     All RCU list-traversal primitives, which include
-       rcu_dereference(), list_for_each_entry_rcu(),
-       list_for_each_continue_rcu(), and list_for_each_safe_rcu(),
-       must be either within an RCU read-side critical section or
-       must be protected by appropriate update-side locks.  RCU
-       read-side critical sections are delimited by rcu_read_lock()
-       and rcu_read_unlock(), or by similar primitives such as
-       rcu_read_lock_bh() and rcu_read_unlock_bh(), in which case
-       the matching rcu_dereference() primitive must be used in order
-       to keep lockdep happy, in this case, rcu_dereference_bh().
+       rcu_dereference(), list_for_each_entry_rcu(), and
+       list_for_each_safe_rcu(), must be either within an RCU read-side
+       critical section or must be protected by appropriate update-side
+       locks.  RCU read-side critical sections are delimited by
+       rcu_read_lock() and rcu_read_unlock(), or by similar primitives
+       such as rcu_read_lock_bh() and rcu_read_unlock_bh(), in which
+       case the matching rcu_dereference() primitive must be used in
+       order to keep lockdep happy, in this case, rcu_dereference_bh().
 
        The reason that it is permissible to use RCU list-traversal
        primitives when the update-side lock is held is that doing so
index 4349c1487e919ce0e49702313229027a18bc7245..adb5a37828467c1cc1393b03495fc11c4654e6e7 100644 (file)
@@ -205,7 +205,7 @@ RCU ("read-copy update") its name.  The RCU code is as follows:
                                audit_copy_rule(&ne->rule, &e->rule);
                                ne->rule.action = newaction;
                                ne->rule.file_count = newfield_count;
-                               list_replace_rcu(e, ne);
+                               list_replace_rcu(&e->list, &ne->list);
                                call_rcu(&e->rcu, audit_free_rule);
                                return 0;
                        }
index bf0f6de2aa00c8d6ee482890bc2bd05434b772c2..0cc7820967f4b54213918e6e21bb7e3cb952d141 100644 (file)
@@ -499,6 +499,8 @@ The foo_reclaim() function might appear as follows:
        {
                struct foo *fp = container_of(rp, struct foo, rcu);
 
+               foo_cleanup(fp->a);
+
                kfree(fp);
        }
 
@@ -521,6 +523,12 @@ o  Use call_rcu() -after- removing a data element from an
        read-side critical sections that might be referencing that
        data item.
 
+If the callback for call_rcu() is not doing anything more than calling
+kfree() on the structure, you can use kfree_rcu() instead of call_rcu()
+to avoid having to write your own callback:
+
+       kfree_rcu(old_fp, rcu);
+
 Again, see checklist.txt for additional rules governing the use of RCU.
 
 
@@ -773,8 +781,8 @@ a single atomic update, converting to RCU will require special care.
 
 Also, the presence of synchronize_rcu() means that the RCU version of
 delete() can now block.  If this is a problem, there is a callback-based
-mechanism that never blocks, namely call_rcu(), that can be used in
-place of synchronize_rcu().
+mechanism that never blocks, namely call_rcu() or kfree_rcu(), that can
+be used in place of synchronize_rcu().
 
 
 7.  FULL LIST OF RCU APIs
@@ -789,9 +797,7 @@ RCU list traversal:
        list_for_each_entry_rcu
        hlist_for_each_entry_rcu
        hlist_nulls_for_each_entry_rcu
-
-       list_for_each_continue_rcu      (to be deprecated in favor of new
-                                        list_for_each_entry_continue_rcu)
+       list_for_each_entry_continue_rcu
 
 RCU pointer/list update:
 
@@ -813,6 +819,7 @@ RCU:        Critical sections       Grace period            Barrier
        rcu_read_unlock         synchronize_rcu
        rcu_dereference         synchronize_rcu_expedited
                                call_rcu
+                               kfree_rcu
 
 
 bh:    Critical sections       Grace period            Barrier
diff --git a/Documentation/acpi/initrd_table_override.txt b/Documentation/acpi/initrd_table_override.txt
new file mode 100644 (file)
index 0000000..35c3f54
--- /dev/null
@@ -0,0 +1,94 @@
+Overriding ACPI tables via initrd
+=================================
+
+1) Introduction (What is this about)
+2) What is this for
+3) How does it work
+4) References (Where to retrieve userspace tools)
+
+1) What is this about
+---------------------
+
+If the ACPI_INITRD_TABLE_OVERRIDE compile option is true, it is possible to
+override nearly any ACPI table provided by the BIOS with an instrumented,
+modified one.
+
+For a full list of ACPI tables that can be overridden, take a look at
+the char *table_sigs[MAX_ACPI_SIGNATURE]; definition in drivers/acpi/osl.c
+All ACPI tables iasl (Intel's ACPI compiler and disassembler) knows should
+be overridable, except:
+   - ACPI_SIG_RSDP (has a signature of 6 bytes)
+   - ACPI_SIG_FACS (does not have an ordinary ACPI table header)
+Both could get implemented as well.
+
+
+2) What is this for
+-------------------
+
+Please keep in mind that this is a debug option.
+ACPI tables should not get overridden for productive use.
+If BIOS ACPI tables are overridden the kernel will get tainted with the
+TAINT_OVERRIDDEN_ACPI_TABLE flag.
+Complain to your platform/BIOS vendor if you find a bug which is so sever
+that a workaround is not accepted in the Linux kernel.
+
+Still, it can and should be enabled in any kernel, because:
+  - There is no functional change with not instrumented initrds
+  - It provides a powerful feature to easily debug and test ACPI BIOS table
+    compatibility with the Linux kernel.
+
+
+3) How does it work
+-------------------
+
+# Extract the machine's ACPI tables:
+cd /tmp
+acpidump >acpidump
+acpixtract -a acpidump
+# Disassemble, modify and recompile them:
+iasl -d *.dat
+# For example add this statement into a _PRT (PCI Routing Table) function
+# of the DSDT:
+Store("HELLO WORLD", debug)
+iasl -sa dsdt.dsl
+# Add the raw ACPI tables to an uncompressed cpio archive.
+# They must be put into a /kernel/firmware/acpi directory inside the
+# cpio archive.
+# The uncompressed cpio archive must be the first.
+# Other, typically compressed cpio archives, must be
+# concatenated on top of the uncompressed one.
+mkdir -p kernel/firmware/acpi
+cp dsdt.aml kernel/firmware/acpi
+# A maximum of: #define ACPI_OVERRIDE_TABLES 10
+# tables are  currently allowed (see osl.c):
+iasl -sa facp.dsl
+iasl -sa ssdt1.dsl
+cp facp.aml kernel/firmware/acpi
+cp ssdt1.aml kernel/firmware/acpi
+# Create the uncompressed cpio archive and concatenate the original initrd
+# on top:
+find kernel | cpio -H newc --create > /boot/instrumented_initrd
+cat /boot/initrd >>/boot/instrumented_initrd
+# reboot with increased acpi debug level, e.g. boot params:
+acpi.debug_level=0x2 acpi.debug_layer=0xFFFFFFFF
+# and check your syslog:
+[    1.268089] ACPI: PCI Interrupt Routing Table [\_SB_.PCI0._PRT]
+[    1.272091] [ACPI Debug]  String [0x0B] "HELLO WORLD"
+
+iasl is able to disassemble and recompile quite a lot different,
+also static ACPI tables.
+
+
+4) Where to retrieve userspace tools
+------------------------------------
+
+iasl and acpixtract are part of Intel's ACPICA project:
+http://acpica.org/
+and should be packaged by distributions (for example in the acpica package
+on SUSE).
+
+acpidump can be found in Len Browns pmtools:
+ftp://kernel.org/pub/linux/kernel/people/lenb/acpi/utils/pmtools/acpidump
+This tool is also part of the acpica package on SUSE.
+Alternatively, used ACPI tables can be retrieved via sysfs in latest kernels:
+/sys/firmware/acpi/tables
index dbbdcbba75a34005ced4edea51e7a9a308aec1e6..4110cca96bd608f1b9d246d31fd482f503c2c5b4 100644 (file)
@@ -27,17 +27,17 @@ Start                       End                     Size            Use
 -----------------------------------------------------------------------
 0000000000000000       0000007fffffffff         512GB          user
 
-ffffff8000000000       ffffffbbfffcffff        ~240GB          vmalloc
+ffffff8000000000       ffffffbbfffeffff        ~240GB          vmalloc
 
-ffffffbbfffd0000       ffffffbcfffdffff          64KB          [guard page]
+ffffffbbffff0000       ffffffbbffffffff          64KB          [guard page]
 
-ffffffbbfffe0000       ffffffbcfffeffff          64KB          PCI I/O space
+ffffffbc00000000       ffffffbdffffffff           8GB          vmemmap
 
-ffffffbbffff0000       ffffffbcffffffff          64KB          [guard page]
+ffffffbe00000000       ffffffbffbbfffff          ~8GB          [guard, future vmmemap]
 
-ffffffbc00000000       ffffffbdffffffff           8GB          vmemmap
+ffffffbffbe00000       ffffffbffbe0ffff          64KB          PCI I/O space
 
-ffffffbe00000000       ffffffbffbffffff          ~8GB          [guard, future vmmemap]
+ffffffbbffff0000       ffffffbcffffffff          ~2MB          [guard]
 
 ffffffbffc000000       ffffffbfffffffff          64MB          modules
 
index 66efc804806adf4124f36b359c09670dc006bd39..85f8c0d084fab7b0b4bf1ee862ef96eafbf046c2 100644 (file)
@@ -9,6 +9,10 @@ Required properties:
   unused).
 - gpio-controller: Marks the device node as a GPIO controller.
 
+optional properties:
+- #gpio-lines: Number of gpio if absent 32.
+
+
 Example:
        pioA: gpio@fffff200 {
                compatible = "atmel,at91rm9200-gpio";
@@ -16,5 +20,6 @@ Example:
                interrupts = <2 4>;
                #gpio-cells = <2>;
                gpio-controller;
+               #gpio-lines = <19>;
        };
 
index f3cf43b66f7e0e45da4402e6181a8487e0f26329..3614242e77321d376b9411c2f3a6168408315605 100644 (file)
@@ -12,13 +12,13 @@ Optional properties:
 Examples:
 
 i2c@83fc4000 { /* I2C2 on i.MX51 */
-       compatible = "fsl,imx51-i2c", "fsl,imx1-i2c";
+       compatible = "fsl,imx51-i2c", "fsl,imx21-i2c";
        reg = <0x83fc4000 0x4000>;
        interrupts = <63>;
 };
 
 i2c@70038000 { /* HS-I2C on i.MX51 */
-       compatible = "fsl,imx51-i2c", "fsl,imx1-i2c";
+       compatible = "fsl,imx51-i2c", "fsl,imx21-i2c";
        reg = <0x70038000 0x4000>;
        interrupts = <64>;
        clock-frequency = <400000>;
diff --git a/Documentation/devicetree/bindings/input/touchscreen/mms114.txt b/Documentation/devicetree/bindings/input/touchscreen/mms114.txt
new file mode 100644 (file)
index 0000000..89d4c56
--- /dev/null
@@ -0,0 +1,34 @@
+* MELFAS MMS114 touchscreen controller
+
+Required properties:
+- compatible: must be "melfas,mms114"
+- reg: I2C address of the chip
+- interrupts: interrupt to which the chip is connected
+- x-size: horizontal resolution of touchscreen
+- y-size: vertical resolution of touchscreen
+
+Optional properties:
+- contact-threshold:
+- moving-threshold:
+- x-invert: invert X axis
+- y-invert: invert Y axis
+
+Example:
+
+       i2c@00000000 {
+               /* ... */
+
+               touchscreen@48 {
+                       compatible = "melfas,mms114";
+                       reg = <0x48>;
+                       interrupts = <39 0>;
+                       x-size = <720>;
+                       y-size = <1280>;
+                       contact-threshold = <10>;
+                       moving-threshold = <10>;
+                       x-invert;
+                       y-invert;
+               };
+
+               /* ... */
+       };
diff --git a/Documentation/devicetree/bindings/media/s5p-mfc.txt b/Documentation/devicetree/bindings/media/s5p-mfc.txt
new file mode 100644 (file)
index 0000000..67ec3d4
--- /dev/null
@@ -0,0 +1,23 @@
+* Samsung Multi Format Codec (MFC)
+
+Multi Format Codec (MFC) is the IP present in Samsung SoCs which
+supports high resolution decoding and encoding functionalities.
+The MFC device driver is a v4l2 driver which can encode/decode
+video raw/elementary streams and has support for all popular
+video codecs.
+
+Required properties:
+  - compatible : value should be either one among the following
+       (a) "samsung,mfc-v5" for MFC v5 present in Exynos4 SoCs
+       (b) "samsung,mfc-v6" for MFC v6 present in Exynos5 SoCs
+
+  - reg : Physical base address of the IP registers and length of memory
+         mapped region.
+
+  - interrupts : MFC interrupt number to the CPU.
+
+  - samsung,mfc-r : Base address of the first memory bank used by MFC
+                   for DMA contiguous memory allocation and its size.
+
+  - samsung,mfc-l : Base address of the second memory bank used by MFC
+                   for DMA contiguous memory allocation and its size.
diff --git a/Documentation/devicetree/bindings/mtd/denali-nand.txt b/Documentation/devicetree/bindings/mtd/denali-nand.txt
new file mode 100644 (file)
index 0000000..b04d03a
--- /dev/null
@@ -0,0 +1,23 @@
+* Denali NAND controller
+
+Required properties:
+  - compatible : should be "denali,denali-nand-dt"
+  - reg : should contain registers location and length for data and reg.
+  - reg-names: Should contain the reg names "nand_data" and "denali_reg"
+  - interrupts : The interrupt number.
+  - dm-mask : DMA bit mask
+
+The device tree may optionally contain sub-nodes describing partitions of the
+address space. See partition.txt for more detail.
+
+Examples:
+
+nand: nand@ff900000 {
+       #address-cells = <1>;
+       #size-cells = <1>;
+       compatible = "denali,denali-nand-dt";
+       reg = <0xff900000 0x100000>, <0xffb80000 0x10000>;
+       reg-names = "nand_data", "denali_reg";
+       interrupts = <0 144 4>;
+       dma-mask = <0xffffffff>;
+};
index e2c663b354d2ae2f241e5739d9cf2b6e67b23e37..e3ea32e7de3e763bae2aa515375ee8ea8ccd5efd 100644 (file)
@@ -3,9 +3,7 @@
 Required properties:
 - compatible : "st,spear600-fsmc-nand"
 - reg : Address range of the mtd chip
-- reg-names: Should contain the reg names "fsmc_regs" and "nand_data"
-- st,ale-off : Chip specific offset to ALE
-- st,cle-off : Chip specific offset to CLE
+- reg-names: Should contain the reg names "fsmc_regs", "nand_data", "nand_addr" and "nand_cmd"
 
 Optional properties:
 - bank-width : Width (in bytes) of the device.  If not present, the width
@@ -19,10 +17,10 @@ Example:
                #address-cells = <1>;
                #size-cells = <1>;
                reg = <0xd1800000 0x1000        /* FSMC Register */
-                      0xd2000000 0x4000>;      /* NAND Base */
-               reg-names = "fsmc_regs", "nand_data";
-               st,ale-off = <0x20000>;
-               st,cle-off = <0x10000>;
+                      0xd2000000 0x0010        /* NAND Base DATA */
+                      0xd2020000 0x0010        /* NAND Base ADDR */
+                      0xd2010000 0x0010>;      /* NAND Base CMD */
+               reg-names = "fsmc_regs", "nand_data", "nand_addr", "nand_cmd";
 
                bank-width = <1>;
                nand-skip-bbtscan;
diff --git a/Documentation/devicetree/bindings/mtd/m25p80.txt b/Documentation/devicetree/bindings/mtd/m25p80.txt
new file mode 100644 (file)
index 0000000..6d3d576
--- /dev/null
@@ -0,0 +1,29 @@
+* MTD SPI driver for ST M25Pxx (and similar) serial flash chips
+
+Required properties:
+- #address-cells, #size-cells : Must be present if the device has sub-nodes
+  representing partitions.
+- compatible : Should be the manufacturer and the name of the chip. Bear in mind
+               the DT binding is not Linux-only, but in case of Linux, see the
+               "m25p_ids" table in drivers/mtd/devices/m25p80.c for the list of
+               supported chips.
+- reg : Chip-Select number
+- spi-max-frequency : Maximum frequency of the SPI bus the chip can operate at
+
+Optional properties:
+- m25p,fast-read : Use the "fast read" opcode to read data from the chip instead
+                   of the usual "read" opcode. This opcode is not supported by
+                   all chips and support for it can not be detected at runtime.
+                   Refer to your chips' datasheet to check if this is supported
+                   by your chip.
+
+Example:
+
+       flash: m25p80@0 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "spansion,m25p80";
+               reg = <0>;
+               spi-max-frequency = <40000000>;
+               m25p,fast-read;
+       };
diff --git a/Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt
new file mode 100644 (file)
index 0000000..20a987e
--- /dev/null
@@ -0,0 +1,136 @@
+* Atmel AT91 Pinmux Controller
+
+The AT91 Pinmux Controler, enables the IC
+to share one PAD to several functional blocks. The sharing is done by
+multiplexing the PAD input/output signals. For each PAD there are up to
+8 muxing options (called periph modes). Since different modules require
+different PAD settings (like pull up, keeper, etc) the contoller controls
+also the PAD settings parameters.
+
+Please refer to pinctrl-bindings.txt in this directory for details of the
+common pinctrl bindings used by client devices, including the meaning of the
+phrase "pin configuration node".
+
+Atmel AT91 pin configuration node is a node of a group of pins which can be
+used for a specific device or function. This node represents both mux and config
+of the pins in that group. The 'pins' selects the function mode(also named pin
+mode) this pin can work on and the 'config' configures various pad settings
+such as pull-up, multi drive, etc.
+
+Required properties for iomux controller:
+- compatible: "atmel,at91rm9200-pinctrl"
+- atmel,mux-mask: array of mask (periph per bank) to describe if a pin can be
+  configured in this periph mode. All the periph and bank need to be describe.
+
+How to create such array:
+
+Each column will represent the possible peripheral of the pinctrl
+Each line will represent a pio bank
+
+Take an example on the 9260
+Peripheral: 2 ( A and B)
+Bank: 3 (A, B and C)
+=>
+
+  /*    A         B     */
+  0xffffffff 0xffc00c3b  /* pioA */
+  0xffffffff 0x7fff3ccf  /* pioB */
+  0xffffffff 0x007fffff  /* pioC */
+
+For each peripheral/bank we will descibe in a u32 if a pin can can be
+configured in it by putting 1 to the pin bit (1 << pin)
+
+Let's take the pioA on peripheral B
+From the datasheet Table 10-2.
+Peripheral B
+PA0    MCDB0
+PA1    MCCDB
+PA2
+PA3    MCDB3
+PA4    MCDB2
+PA5    MCDB1
+PA6
+PA7
+PA8
+PA9
+PA10   ETX2
+PA11   ETX3
+PA12
+PA13
+PA14
+PA15
+PA16
+PA17
+PA18
+PA19
+PA20
+PA21
+PA22   ETXER
+PA23   ETX2
+PA24   ETX3
+PA25   ERX2
+PA26   ERX3
+PA27   ERXCK
+PA28   ECRS
+PA29   ECOL
+PA30   RXD4
+PA31   TXD4
+
+=> 0xffc00c3b
+
+Required properties for pin configuration node:
+- atmel,pins: 4 integers array, represents a group of pins mux and config
+  setting. The format is atmel,pins = <PIN_BANK PIN_BANK_NUM PERIPH CONFIG>.
+  The PERIPH 0 means gpio.
+
+Bits used for CONFIG:
+PULL_UP(1 << 0): indicate this pin need a pull up.
+MULTIDRIVE(1 << 1): indicate this pin need to be configured as multidrive.
+
+NOTE:
+Some requirements for using atmel,at91rm9200-pinctrl binding:
+1. We have pin function node defined under at91 controller node to represent
+   what pinmux functions this SoC supports.
+2. The driver can use the function node's name and pin configuration node's
+   name describe the pin function and group hierarchy.
+   For example, Linux at91 pinctrl driver takes the function node's name
+   as the function name and pin configuration node's name as group name to
+   create the map table.
+3. Each pin configuration node should have a phandle, devices can set pins
+   configurations by referring to the phandle of that pin configuration node.
+4. The gpio controller must be describe in the pinctrl simple-bus.
+
+Examples:
+
+pinctrl@fffff400 {
+       #address-cells = <1>;
+       #size-cells = <1>;
+       ranges;
+       compatible = "atmel,at91rm9200-pinctrl", "simple-bus";
+       reg = <0xfffff400 0x600>;
+
+       atmel,mux-mask = <
+             /*    A         B     */
+              0xffffffff 0xffc00c3b  /* pioA */
+              0xffffffff 0x7fff3ccf  /* pioB */
+              0xffffffff 0x007fffff  /* pioC */
+             >;
+
+       /* shared pinctrl settings */
+       dbgu {
+               pinctrl_dbgu: dbgu-0 {
+                       atmel,pins =
+                               <1 14 0x1 0x0   /* PB14 periph A */
+                                1 15 0x1 0x1>; /* PB15 periph with pullup */
+               };
+       };
+};
+
+dbgu: serial@fffff200 {
+       compatible = "atmel,at91sam9260-usart";
+       reg = <0xfffff200 0x200>;
+       interrupts = <1 4 7>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_dbgu>;
+       status = "disabled";
+};
index c8e578263ce2654251aacde50bc1a55fe514e264..683fde93c4fb1ab9dac7d9472f1ad808202d7cf4 100644 (file)
@@ -93,7 +93,7 @@ Valid values for pin and group names are:
 
     With some exceptions, these support nvidia,high-speed-mode,
     nvidia,schmitt, nvidia,low-power-mode, nvidia,pull-down-strength,
-    nvidia,pull-up-strength, nvidia,slew_rate-rising, nvidia,slew_rate-falling.
+    nvidia,pull-up-strength, nvidia,slew-rate-rising, nvidia,slew-rate-falling.
 
     drive_ao1, drive_ao2, drive_at1, drive_at2, drive_cdev1, drive_cdev2,
     drive_csus, drive_dap1, drive_dap2, drive_dap3, drive_dap4, drive_dbg,
index c275b70349c11aedb4e8db6a1982c57bfbfcb619..6f426ed7009e5e43461770787225b398fe68e67f 100644 (file)
@@ -83,7 +83,7 @@ Valid values for pin and group names are:
   drive groups:
 
     These all support nvidia,pull-down-strength, nvidia,pull-up-strength,
-    nvidia,slew_rate-rising, nvidia,slew_rate-falling. Most but not all
+    nvidia,slew-rate-rising, nvidia,slew-rate-falling. Most but not all
     support nvidia,high-speed-mode, nvidia,schmitt, nvidia,low-power-mode.
 
     ao1, ao2, at1, at2, at3, at4, at5, cdev1, cdev2, cec, crt, csus, dap1,
index 03dee50532f5c3d5f94f49fb2ee0bf44232d8fa3..63806e2d49c2e010a188290506093631782ee29a 100644 (file)
@@ -13,8 +13,14 @@ Required Properties:
 - reg: Base address of the pin controller hardware module and length of
   the address space it occupies.
 
-- interrupts: interrupt specifier for the controller. The format and value of
-  the interrupt specifier depends on the interrupt parent for the controller.
+- Pin banks as child nodes: Pin banks of the controller are represented by child
+  nodes of the controller node. Bank name is taken from name of the node. Each
+  bank node must contain following properties:
+
+  - gpio-controller: identifies the node as a gpio controller and pin bank.
+  - #gpio-cells: number of cells in GPIO specifier. Since the generic GPIO
+    binding is used, the amount of cells must be specified as 2. See generic
+    GPIO binding documentation for description of particular cells.
 
 - Pin mux/config groups as child nodes: The pin mux (selecting pin function
   mode) and pin config (pull up/down, driver strength) settings are represented
@@ -72,16 +78,24 @@ used as system wakeup events.
 A. External GPIO Interrupts: For supporting external gpio interrupts, the
    following properties should be specified in the pin-controller device node.
 
-- interrupt-controller: identifies the controller node as interrupt-parent.
-- #interrupt-cells: the value of this property should be 2.
-  - First Cell: represents the external gpio interrupt number local to the
-    external gpio interrupt space of the controller.
-  - Second Cell: flags to identify the type of the interrupt
-    - 1 = rising edge triggered
-    - 2 = falling edge triggered
-    - 3 = rising and falling edge triggered
-    - 4 = high level triggered
-    - 8 = low level triggered
+   - interrupt-parent: phandle of the interrupt parent to which the external
+     GPIO interrupts are forwarded to.
+   - interrupts: interrupt specifier for the controller. The format and value of
+     the interrupt specifier depends on the interrupt parent for the controller.
+
+   In addition, following properties must be present in node of every bank
+   of pins supporting GPIO interrupts:
+
+   - interrupt-controller: identifies the controller node as interrupt-parent.
+   - #interrupt-cells: the value of this property should be 2.
+     - First Cell: represents the external gpio interrupt number local to the
+       external gpio interrupt space of the controller.
+     - Second Cell: flags to identify the type of the interrupt
+       - 1 = rising edge triggered
+       - 2 = falling edge triggered
+       - 3 = rising and falling edge triggered
+       - 4 = high level triggered
+       - 8 = low level triggered
 
 B. External Wakeup Interrupts: For supporting external wakeup interrupts, a
    child node representing the external wakeup interrupt controller should be
@@ -94,6 +108,11 @@ B. External Wakeup Interrupts: For supporting external wakeup interrupts, a
        found on Samsung Exynos4210 SoC.
    - interrupt-parent: phandle of the interrupt parent to which the external
      wakeup interrupts are forwarded to.
+   - interrupts: interrupt used by multiplexed wakeup interrupts.
+
+   In addition, following properties must be present in node of every bank
+   of pins supporting wake-up interrupts:
+
    - interrupt-controller: identifies the node as interrupt-parent.
    - #interrupt-cells: the value of this property should be 2
      - First Cell: represents the external wakeup interrupt number local to
@@ -105,11 +124,63 @@ B. External Wakeup Interrupts: For supporting external wakeup interrupts, a
        - 4 = high level triggered
        - 8 = low level triggered
 
+   Node of every bank of pins supporting direct wake-up interrupts (without
+   multiplexing) must contain following properties:
+
+   - interrupt-parent: phandle of the interrupt parent to which the external
+     wakeup interrupts are forwarded to.
+   - interrupts: interrupts of the interrupt parent which are used for external
+     wakeup interrupts from pins of the bank, must contain interrupts for all
+     pins of the bank.
+
 Aliases:
 
 All the pin controller nodes should be represented in the aliases node using
 the following format 'pinctrl{n}' where n is a unique number for the alias.
 
+Example: A pin-controller node with pin banks:
+
+       pinctrl_0: pinctrl@11400000 {
+               compatible = "samsung,pinctrl-exynos4210";
+               reg = <0x11400000 0x1000>;
+               interrupts = <0 47 0>;
+
+               /* ... */
+
+               /* Pin bank without external interrupts */
+               gpy0: gpy0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               /* ... */
+
+               /* Pin bank with external GPIO or muxed wake-up interrupts */
+               gpj0: gpj0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               /* ... */
+
+               /* Pin bank with external direct wake-up interrupts */
+               gpx0: gpx0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       interrupt-parent = <&gic>;
+                       interrupts = <0 16 0>, <0 17 0>, <0 18 0>, <0 19 0>,
+                                    <0 20 0>, <0 21 0>, <0 22 0>, <0 23 0>;
+                       #interrupt-cells = <2>;
+               };
+
+               /* ... */
+       };
+
 Example 1: A pin-controller node with pin groups.
 
        pinctrl_0: pinctrl@11400000 {
@@ -117,6 +188,8 @@ Example 1: A pin-controller node with pin groups.
                reg = <0x11400000 0x1000>;
                interrupts = <0 47 0>;
 
+               /* ... */
+
                uart0_data: uart0-data {
                        samsung,pins = "gpa0-0", "gpa0-1";
                        samsung,pin-function = <2>;
@@ -158,20 +231,14 @@ Example 2: A pin-controller node with external wakeup interrupt controller node.
        pinctrl_1: pinctrl@11000000 {
                compatible = "samsung,pinctrl-exynos4210";
                reg = <0x11000000 0x1000>;
-               interrupts = <0 46 0>;
-               interrupt-controller;
-               #interrupt-cells = <2>;
+               interrupts = <0 46 0>
 
-               wakup_eint: wakeup-interrupt-controller {
+               /* ... */
+
+               wakeup-interrupt-controller {
                        compatible = "samsung,exynos4210-wakeup-eint";
                        interrupt-parent = <&gic>;
-                       interrupt-controller;
-                       #interrupt-cells = <2>;
-                       interrupts = <0 16 0>, <0 17 0>, <0 18 0>, <0 19 0>,
-                                       <0 20 0>, <0 21 0>, <0 22 0>, <0 23 0>,
-                                       <0 24 0>, <0 25 0>, <0 26 0>, <0 27 0>,
-                                       <0 28 0>, <0 29 0>, <0 30 0>, <0 31 0>,
-                                       <0 32 0>;
+                       interrupts = <0 32 0>;
                };
        };
 
@@ -190,7 +257,8 @@ Example 4: Set up the default pin state for uart controller.
 
        static int s3c24xx_serial_probe(struct platform_device *pdev) {
                struct pinctrl *pinctrl;
-               ...
-               ...
+
+               /* ... */
+
                pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
        }
diff --git a/Documentation/devicetree/bindings/regulator/gpio-regulator.txt b/Documentation/devicetree/bindings/regulator/gpio-regulator.txt
new file mode 100644 (file)
index 0000000..3703be2
--- /dev/null
@@ -0,0 +1,36 @@
+GPIO controlled regulators
+
+Required properties:
+- compatible           : Must be "regulator-gpio".
+
+Optional properties:
+- gpio-enable          : GPIO to use to enable/disable the regulator.
+- gpios                        : GPIO group used to control voltage.
+- states               : Selection of available voltages and GPIO configs.
+- startup-delay-us     : Startup time in microseconds.
+- enable-active-high   : Polarity of GPIO is active high (default is low).
+
+Any property defined as part of the core regulator binding defined in
+regulator.txt can also be used.
+
+Example:
+
+       mmciv: gpio-regulator {
+               compatible = "regulator-gpio";
+
+               regulator-name = "mmci-gpio-supply";
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <2600000>;
+               regulator-boot-on;
+
+               gpio-enable = <&gpio0 23 0x4>;
+               gpios = <&gpio0 24 0x4
+                        &gpio0 25 0x4>;
+               states = <1800000 0x3
+                         2200000 0x2
+                         2600000 0x1
+                         2900000 0x0>;
+
+               startup-delay-us = <100000>;
+               enable-active-high;
+       };
diff --git a/Documentation/devicetree/bindings/regulator/vexpress.txt b/Documentation/devicetree/bindings/regulator/vexpress.txt
new file mode 100644 (file)
index 0000000..d775f72
--- /dev/null
@@ -0,0 +1,32 @@
+Versatile Express voltage regulators
+------------------------------------
+
+Requires node properties:
+- "compatible" value: "arm,vexpress-volt"
+- "arm,vexpress-sysreg,func" when controlled via vexpress-sysreg
+  (see Documentation/devicetree/bindings/arm/vexpress-sysreg.txt
+  for more details)
+
+Required regulator properties:
+- "regulator-name"
+- "regulator-always-on"
+
+Optional regulator properties:
+- "regulator-min-microvolt"
+- "regulator-max-microvolt"
+
+See Documentation/devicetree/bindings/regulator/regulator.txt
+for more details about the regulator properties.
+
+When no "regulator-[min|max]-microvolt" properties are defined,
+the device is treated as fixed (or rather "read-only") regulator.
+
+Example:
+       volt@0 {
+               compatible = "arm,vexpress-volt";
+               arm,vexpress-sysreg,func = <2 0>;
+               regulator-name = "Cores";
+               regulator-min-microvolt = <800000>;
+               regulator-max-microvolt = <1050000>;
+               regulator-always-on;
+       };
diff --git a/Documentation/devicetree/bindings/rtc/nvidia,tegra20-rtc.txt b/Documentation/devicetree/bindings/rtc/nvidia,tegra20-rtc.txt
new file mode 100644 (file)
index 0000000..93f45e9
--- /dev/null
@@ -0,0 +1,19 @@
+NVIDIA Tegra20 real-time clock
+
+The Tegra RTC maintains seconds and milliseconds counters, and five alarm
+registers. The alarms and other interrupts may wake the system from low-power
+state.
+
+Required properties:
+
+- compatible : should be "nvidia,tegra20-rtc".
+- reg : Specifies base physical address and size of the registers.
+- interrupts : A single interrupt specifier.
+
+Example:
+
+timer {
+       compatible = "nvidia,tegra20-rtc";
+       reg = <0x7000e000 0x100>;
+       interrupts = <0 2 0x04>;
+};
diff --git a/Documentation/devicetree/bindings/sound/ak4104.txt b/Documentation/devicetree/bindings/sound/ak4104.txt
new file mode 100644 (file)
index 0000000..1f8e506
--- /dev/null
@@ -0,0 +1,17 @@
+AK4104 S/PDIF transmitter
+
+This device supports SPI mode only.
+
+Required properties:
+
+  - compatible : "asahi-kasei,ak4104"
+
+  - reg : The chip select number on the SPI bus
+
+Example:
+
+spdif: ak4104@0 {
+       compatible = "asahi-kasei,ak4104";
+       reg = <0>;
+       spi-max-frequency = <5000000>;
+};
index c81b5fd5a5bc80459a1b2d626c9f20b5a86bfbe9..a850fb9c88eab2156ec89f0c76d8ca59073540f8 100644 (file)
@@ -18,6 +18,8 @@ Optional properties:
 
  - reset-gpio:         a GPIO spec to define which pin is connected to the chip's
                !RESET pin
+ - cirrus,amuteb-eq-bmutec:    When given, the Codec's AMUTEB=BMUTEC flag
+                               is enabled.
 
 Examples:
 
index 81df374adbb97f53a8c7b8d56cb21e70e5d39cb3..2ef0a6b85653c4dc0ddbd18aac6c958c839f5004 100644 (file)
@@ -6,7 +6,9 @@ Required properties:
   - "ti,omap4-spi" for OMAP4+.
 - ti,spi-num-cs : Number of chipselect supported  by the instance.
 - ti,hwmods: Name of the hwmod associated to the McSPI
-
+- ti,pindir-d0-in-d1-out: Select the D0 pin as input and D1 as
+                         output. The default is D0 as output and
+                         D1 as input.
 
 Example:
 
diff --git a/Documentation/devicetree/bindings/timer/nvidia,tegra20-timer.txt b/Documentation/devicetree/bindings/timer/nvidia,tegra20-timer.txt
new file mode 100644 (file)
index 0000000..e019fdc
--- /dev/null
@@ -0,0 +1,21 @@
+NVIDIA Tegra20 timer
+
+The Tegra20 timer provides four 29-bit timer channels and a single 32-bit free
+running counter. The first two channels may also trigger a watchdog reset.
+
+Required properties:
+
+- compatible : should be "nvidia,tegra20-timer".
+- reg : Specifies base physical address and size of the registers.
+- interrupts : A list of 4 interrupts; one per timer channel.
+
+Example:
+
+timer {
+       compatible = "nvidia,tegra20-timer";
+       reg = <0x60005000 0x60>;
+       interrupts = <0 0 0x04
+                       0 1 0x04
+                       0 41 0x04
+                       0 42 0x04>;
+};
diff --git a/Documentation/devicetree/bindings/timer/nvidia,tegra30-timer.txt b/Documentation/devicetree/bindings/timer/nvidia,tegra30-timer.txt
new file mode 100644 (file)
index 0000000..906109d
--- /dev/null
@@ -0,0 +1,23 @@
+NVIDIA Tegra30 timer
+
+The Tegra30 timer provides ten 29-bit timer channels, a single 32-bit free
+running counter, and 5 watchdog modules. The first two channels may also
+trigger a legacy watchdog reset.
+
+Required properties:
+
+- compatible : should be "nvidia,tegra30-timer", "nvidia,tegra20-timer".
+- reg : Specifies base physical address and size of the registers.
+- interrupts : A list of 6 interrupts; one per each of timer channels 1
+    through 5, and one for the shared interrupt for the remaining channels.
+
+timer {
+       compatible = "nvidia,tegra30-timer", "nvidia,tegra20-timer";
+       reg = <0x60005000 0x400>;
+       interrupts = <0 0 0x04
+                     0 1 0x04
+                     0 41 0x04
+                     0 42 0x04
+                     0 121 0x04
+                     0 122 0x04>;
+};
index 2bbebe6f771fd418fbecf810ea4399dcc17d1057..f6e263e0f6070baf87fd2a46aa710a783c4b10ef 100644 (file)
@@ -4,29 +4,47 @@ Kernel driver ads7828
 Supported chips:
   * Texas Instruments/Burr-Brown ADS7828
     Prefix: 'ads7828'
-    Addresses scanned: I2C 0x48, 0x49, 0x4a, 0x4b
-    Datasheet: Publicly available at the Texas Instruments website :
+    Datasheet: Publicly available at the Texas Instruments website:
                http://focus.ti.com/lit/ds/symlink/ads7828.pdf
 
+  * Texas Instruments ADS7830
+    Prefix: 'ads7830'
+    Datasheet: Publicly available at the Texas Instruments website:
+               http://focus.ti.com/lit/ds/symlink/ads7830.pdf
+
 Authors:
         Steve Hardy <shardy@redhat.com>
+        Vivien Didelot <vivien.didelot@savoirfairelinux.com>
+        Guillaume Roguez <guillaume.roguez@savoirfairelinux.com>
+
+Platform data
+-------------
+
+The ads7828 driver accepts an optional ads7828_platform_data structure (defined
+in include/linux/platform_data/ads7828.h). The structure fields are:
 
-Module Parameters
------------------
+* diff_input: (bool) Differential operation
+  set to true for differential mode, false for default single ended mode.
 
-* se_input: bool (default Y)
-  Single ended operation - set to N for differential mode
-* int_vref: bool (default Y)
-  Operate with the internal 2.5V reference - set to N for external reference
-* vref_mv: int (default 2500)
-  If using an external reference, set this to the reference voltage in mV
+* ext_vref: (bool) External reference
+  set to true if it operates with an external reference, false for default
+  internal reference.
+
+* vref_mv: (unsigned int) Voltage reference
+  if using an external reference, set this to the reference voltage in mV,
+  otherwise it will default to the internal value (2500mV). This value will be
+  bounded with limits accepted by the chip, described in the datasheet.
+
+ If no structure is provided, the configuration defaults to single ended
+ operation and internal voltage reference (2.5V).
 
 Description
 -----------
 
-This driver implements support for the Texas Instruments ADS7828.
+This driver implements support for the Texas Instruments ADS7828 and ADS7830.
 
-This device is a 12-bit 8-channel A-D converter.
+The ADS7828 device is a 12-bit 8-channel A/D converter, while the ADS7830 does
+8-bit sampling.
 
 It can operate in single ended mode (8 +ve inputs) or in differential mode,
 where 4 differential pairs can be measured.
@@ -34,3 +52,7 @@ where 4 differential pairs can be measured.
 The chip also has the facility to use an external voltage reference.  This
 may be required if your hardware supplies the ADS7828 from a 5V supply, see
 the datasheet for more details.
+
+There is no reliable way to identify this chip, so the driver will not scan
+some addresses to try to auto-detect it. That means that you will have to
+statically declare the device in the platform support code.
index c86b50c03ea8f02276d2a35deb4a6f5822d78be9..3374c085678d694e450dbbab29c94d7c928ddde9 100644 (file)
@@ -98,13 +98,16 @@ Process             Processor                                       TjMax(C)
 
 45nm           Atom Processors
                D525/510/425/410                                100
+               Z670/650                                        90
                Z560/550/540/530P/530/520PT/520/515/510PT/510P  90
                Z510/500                                        90
+               N570/550                                        100
                N475/470/455/450                                100
                N280/270                                        90
                330/230                                         125
                E680/660/640/620                                90
                E680T/660T/640T/620T                            110
+               CE4170/4150/4110                                110
 
 45nm           Core2 Processors
                Solo ULV SU3500/3300                            100
diff --git a/Documentation/hwmon/da9055 b/Documentation/hwmon/da9055
new file mode 100644 (file)
index 0000000..855c3f5
--- /dev/null
@@ -0,0 +1,47 @@
+Supported chips:
+  * Dialog Semiconductors DA9055 PMIC
+    Prefix: 'da9055'
+    Datasheet: Datasheet is not publicly available.
+
+Authors: David Dajun Chen <dchen@diasemi.com>
+
+Description
+-----------
+
+The DA9055 provides an Analogue to Digital Converter (ADC) with 10 bits
+resolution and track and hold circuitry combined with an analogue input
+multiplexer. The analogue input multiplexer will allow conversion of up to 5
+different inputs. The track and hold circuit ensures stable input voltages at
+the input of the ADC during the conversion.
+
+The ADC is used to measure the following inputs:
+Channel 0: VDDOUT - measurement of the system voltage
+Channel 1: ADC_IN1 - high impedance input (0 - 2.5V)
+Channel 2: ADC_IN2 - high impedance input (0 - 2.5V)
+Channel 3: ADC_IN3 - high impedance input (0 - 2.5V)
+Channel 4: Internal Tjunc. - sense (internal temp. sensor)
+
+By using sysfs attributes we can measure the system voltage VDDOUT,
+chip junction temperature and auxiliary channels voltages.
+
+Voltage Monitoring
+------------------
+
+Voltages are sampled in a AUTO mode it can be manually sampled too and results
+are stored in a 10 bit ADC.
+
+The system voltage is calculated as:
+       Milli volt = ((ADC value * 1000) / 85) + 2500
+
+The voltages on ADC channels 1, 2 and 3 are calculated as:
+       Milli volt = (ADC value * 1000) / 102
+
+Temperature Monitoring
+----------------------
+
+Temperatures are sampled by a 10 bit ADC.  Junction temperatures
+are monitored by the ADC channels.
+
+The junction temperature is calculated:
+       Degrees celsius = -0.4084 * (ADC_RES - T_OFFSET) + 307.6332
+The junction temperature attribute is supported by the driver.
index 790f774a303247c0693ed6c24c8d9dfd6103d2f0..843751c41fea59d207497d991a67bba5af1ee617 100644 (file)
@@ -60,8 +60,7 @@ increase the chances of your change being accepted.
 
 * Add the driver to Kconfig and Makefile in alphabetical order.
 
-* Make sure that all dependencies are listed in Kconfig. For new drivers, it
-  is most likely prudent to add a dependency on EXPERIMENTAL.
+* Make sure that all dependencies are listed in Kconfig.
 
 * Avoid forward declarations if you can. Rearrange the code if necessary.
 
index 2759f7c188f0cd9232ce10122d3dd6595b4f0d30..3c4e1b3b80a1f8036a8b220ddcd0210d167c62b6 100644 (file)
@@ -251,12 +251,13 @@ And there are a number of things that _must_ or _must_not_ be assumed:
 
      And for:
 
-       *A = X; Y = *A;
+       *A = X; *(A + 4) = Y;
 
-     we may get either of:
+     we may get any of:
 
-       STORE *A = X; Y = LOAD *A;
-       STORE *A = Y = X;
+       STORE *A = X; STORE *(A + 4) = Y;
+       STORE *(A + 4) = Y; STORE *A = X;
+       STORE {*A, *(A + 4) } = {X, Y};
 
 
 =========================
index 3b4ee5328868cea31b024ad9631a286886826c60..a1cd2f9428d715d9afb14060f2cb61b1923362e4 100644 (file)
@@ -1193,4 +1193,6 @@ foo_switch()
        ...
 }
 
-The above has to be done from process context.
+The above has to be done from process context. The reservation of the pins
+will be done when the state is activated, so in effect one specific pin
+can be used by different functions at different times on a running system.
index 17e130a803470377ba898d069b84f8b0f51eda69..79a2a58425ee1c1df7df251bc12aa40fdbeb0ecb 100644 (file)
@@ -99,7 +99,7 @@ reading the aggregated value does not require any locking mechanism.
 
 From kernel mode the use of this interface is the following:
 
-int dev_pm_qos_add_request(device, handle, value):
+int dev_pm_qos_add_request(device, handle, type, value):
 Will insert an element into the list for that identified device with the
 target value.  Upon change to this list the new target is recomputed and any
 registered notifiers are called only if the target value is now different.
index 597c3c5813751ac54629cc690e1137b9f339dd66..1e469ef7577835ae690094ec47262912d899727a 100644 (file)
@@ -95,12 +95,15 @@ SECCOMP_RET_KILL:
 
 SECCOMP_RET_TRAP:
        Results in the kernel sending a SIGSYS signal to the triggering
-       task without executing the system call.  The kernel will
-       rollback the register state to just before the system call
-       entry such that a signal handler in the task will be able to
-       inspect the ucontext_t->uc_mcontext registers and emulate
-       system call success or failure upon return from the signal
-       handler.
+       task without executing the system call.  siginfo->si_call_addr
+       will show the address of the system call instruction, and
+       siginfo->si_syscall and siginfo->si_arch will indicate which
+       syscall was attempted.  The program counter will be as though
+       the syscall happened (i.e. it will not point to the syscall
+       instruction).  The return value register will contain an arch-
+       dependent value -- if resuming execution, set it to something
+       sensible.  (The architecture dependency is because replacing
+       it with -ENOSYS could overwrite some useful information.)
 
        The SECCOMP_RET_DATA portion of the return value will be passed
        as si_errno.
@@ -123,6 +126,18 @@ SECCOMP_RET_TRACE:
        the BPF program return value will be available to the tracer
        via PTRACE_GETEVENTMSG.
 
+       The tracer can skip the system call by changing the syscall number
+       to -1.  Alternatively, the tracer can change the system call
+       requested by changing the system call to a valid syscall number.  If
+       the tracer asks to skip the system call, then the system call will
+       appear to return the value that the tracer puts in the return value
+       register.
+
+       The seccomp check will not be run again after the tracer is
+       notified.  (This means that seccomp-based sandboxes MUST NOT
+       allow use of ptrace, even of other sandboxed processes, without
+       extreme care; ptracers can use this mechanism to escape.)
+
 SECCOMP_RET_ALLOW:
        Results in the system call being executed.
 
@@ -161,3 +176,50 @@ architecture supports both ptrace_event and seccomp, it will be able to
 support seccomp filter with minor fixup: SIGSYS support and seccomp return
 value checking.  Then it must just add CONFIG_HAVE_ARCH_SECCOMP_FILTER
 to its arch-specific Kconfig.
+
+
+
+Caveats
+-------
+
+The vDSO can cause some system calls to run entirely in userspace,
+leading to surprises when you run programs on different machines that
+fall back to real syscalls.  To minimize these surprises on x86, make
+sure you test with
+/sys/devices/system/clocksource/clocksource0/current_clocksource set to
+something like acpi_pm.
+
+On x86-64, vsyscall emulation is enabled by default.  (vsyscalls are
+legacy variants on vDSO calls.)  Currently, emulated vsyscalls will honor seccomp, with a few oddities:
+
+- A return value of SECCOMP_RET_TRAP will set a si_call_addr pointing to
+  the vsyscall entry for the given call and not the address after the
+  'syscall' instruction.  Any code which wants to restart the call
+  should be aware that (a) a ret instruction has been emulated and (b)
+  trying to resume the syscall will again trigger the standard vsyscall
+  emulation security checks, making resuming the syscall mostly
+  pointless.
+
+- A return value of SECCOMP_RET_TRACE will signal the tracer as usual,
+  but the syscall may not be changed to another system call using the
+  orig_rax register. It may only be changed to -1 order to skip the
+  currently emulated call. Any other change MAY terminate the process.
+  The rip value seen by the tracer will be the syscall entry address;
+  this is different from normal behavior.  The tracer MUST NOT modify
+  rip or rsp.  (Do not rely on other changes terminating the process.
+  They might work.  For example, on some kernels, choosing a syscall
+  that only exists in future kernels will be correctly emulated (by
+  returning -ENOSYS).
+
+To detect this quirky behavior, check for addr & ~0x0C00 ==
+0xFFFFFFFFFF600000.  (For SECCOMP_RET_TRACE, use rip.  For
+SECCOMP_RET_TRAP, use siginfo->si_call_addr.)  Do not check any other
+condition: future kernels may improve vsyscall emulation and current
+kernels in vsyscall=native mode will behave differently, but the
+instructions at 0xF...F600{0,4,8,C}00 will not be system calls in these
+cases.
+
+Note that modern systems are unlikely to use vsyscalls at all -- they
+are a legacy feature and they are considerably slower than standard
+syscalls.  New code will use the vDSO, and vDSO-issued system calls
+are indistinguishable from normal system calls.
diff --git a/Documentation/scheduler/numa-problem.txt b/Documentation/scheduler/numa-problem.txt
new file mode 100644 (file)
index 0000000..a5d2fee
--- /dev/null
@@ -0,0 +1,230 @@
+
+
+Effective NUMA scheduling problem statement, described formally:
+
+ * minimize interconnect traffic
+
+For each task 't_i' we have memory, this memory can be spread over multiple
+physical nodes, let us denote this as: 'p_i,k', the memory task 't_i' has on
+node 'k' in [pages].  
+
+If a task shares memory with another task let us denote this as:
+'s_i,k', the memory shared between tasks including 't_i' residing on node
+'k'.
+
+Let 'M' be the distribution that governs all 'p' and 's', ie. the page placement.
+
+Similarly, lets define 'fp_i,k' and 'fs_i,k' resp. as the (average) usage
+frequency over those memory regions [1/s] such that the product gives an
+(average) bandwidth 'bp' and 'bs' in [pages/s].
+
+(note: multiple tasks sharing memory naturally avoid duplicat accounting
+       because each task will have its own access frequency 'fs')
+
+(pjt: I think this frequency is more numerically consistent if you explicitly 
+      restrict p/s above to be the working-set. (It also makes explicit the 
+      requirement for <C0,M0> to change about a change in the working set.)
+
+      Doing this does have the nice property that it lets you use your frequency
+      measurement as a weak-ordering for the benefit a task would receive when
+      we can't fit everything.
+
+      e.g. task1 has working set 10mb, f=90%
+           task2 has working set 90mb, f=10%
+
+      Both are using 9mb/s of bandwidth, but we'd expect a much larger benefit
+      from task1 being on the right node than task2. )
+
+Let 'C' map every task 't_i' to a cpu 'c_i' and its corresponding node 'n_i':
+
+  C: t_i -> {c_i, n_i}
+
+This gives us the total interconnect traffic between nodes 'k' and 'l',
+'T_k,l', as:
+
+  T_k,l = \Sum_i bp_i,l + bs_i,l + \Sum bp_j,k + bs_j,k where n_i == k, n_j == l
+
+And our goal is to obtain C0 and M0 such that:
+
+  T_k,l(C0, M0) =< T_k,l(C, M) for all C, M where k != l
+
+(note: we could introduce 'nc(k,l)' as the cost function of accessing memory
+       on node 'l' from node 'k', this would be useful for bigger NUMA systems
+
+ pjt: I agree nice to have, but intuition suggests diminishing returns on more
+      usual systems given factors like things like Haswell's enormous 35mb l3
+      cache and QPI being able to do a direct fetch.)
+
+(note: do we need a limit on the total memory per node?)
+
+
+ * fairness
+
+For each task 't_i' we have a weight 'w_i' (related to nice), and each cpu
+'c_n' has a compute capacity 'P_n', again, using our map 'C' we can formulate a
+load 'L_n':
+
+  L_n = 1/P_n * \Sum_i w_i for all c_i = n
+
+using that we can formulate a load difference between CPUs
+
+  L_n,m = | L_n - L_m |
+
+Which allows us to state the fairness goal like:
+
+  L_n,m(C0) =< L_n,m(C) for all C, n != m
+
+(pjt: It can also be usefully stated that, having converged at C0:
+
+   | L_n(C0) - L_m(C0) | <= 4/3 * | G_n( U(t_i, t_j) ) - G_m( U(t_i, t_j) ) |
+
+      Where G_n,m is the greedy partition of tasks between L_n and L_m. This is
+      the "worst" partition we should accept; but having it gives us a useful 
+      bound on how much we can reasonably adjust L_n/L_m at a Pareto point to 
+      favor T_n,m. )
+
+Together they give us the complete multi-objective optimization problem:
+
+  min_C,M [ L_n,m(C), T_k,l(C,M) ]
+
+
+
+Notes:
+
+ - the memory bandwidth problem is very much an inter-process problem, in
+   particular there is no such concept as a process in the above problem.
+
+ - the naive solution would completely prefer fairness over interconnect
+   traffic, the more complicated solution could pick another Pareto point using
+   an aggregate objective function such that we balance the loss of work
+   efficiency against the gain of running, we'd want to more or less suggest
+   there to be a fixed bound on the error from the Pareto line for any
+   such solution.
+
+References:
+
+  http://en.wikipedia.org/wiki/Mathematical_optimization
+  http://en.wikipedia.org/wiki/Multi-objective_optimization
+
+
+* warning, significant hand-waving ahead, improvements welcome *
+
+
+Partial solutions / approximations:
+
+ 1) have task node placement be a pure preference from the 'fairness' pov.
+
+This means we always prefer fairness over interconnect bandwidth. This reduces
+the problem to:
+
+  min_C,M [ T_k,l(C,M) ]
+
+ 2a) migrate memory towards 'n_i' (the task's node).
+
+This creates memory movement such that 'p_i,k for k != n_i' becomes 0 -- 
+provided 'n_i' stays stable enough and there's sufficient memory (looks like
+we might need memory limits for this).
+
+This does however not provide us with any 's_i' (shared) information. It does
+however remove 'M' since it defines memory placement in terms of task
+placement.
+
+XXX properties of this M vs a potential optimal
+
+ 2b) migrate memory towards 'n_i' using 2 samples.
+
+This separates pages into those that will migrate and those that will not due
+to the two samples not matching. We could consider the first to be of 'p_i'
+(private) and the second to be of 's_i' (shared).
+
+This interpretation can be motivated by the previously observed property that
+'p_i,k for k != n_i' should become 0 under sufficient memory, leaving only
+'s_i' (shared). (here we loose the need for memory limits again, since it
+becomes indistinguishable from shared).
+
+XXX include the statistical babble on double sampling somewhere near
+
+This reduces the problem further; we loose 'M' as per 2a, it further reduces
+the 'T_k,l' (interconnect traffic) term to only include shared (since per the
+above all private will be local):
+
+  T_k,l = \Sum_i bs_i,l for every n_i = k, l != k
+
+[ more or less matches the state of sched/numa and describes its remaining
+  problems and assumptions. It should work well for tasks without significant
+  shared memory usage between tasks. ]
+
+Possible future directions:
+
+Motivated by the form of 'T_k,l', try and obtain each term of the sum, so we
+can evaluate it;
+
+ 3a) add per-task per node counters
+
+At fault time, count the number of pages the task faults on for each node.
+This should give an approximation of 'p_i' for the local node and 's_i,k' for
+all remote nodes.
+
+While these numbers provide pages per scan, and so have the unit [pages/s] they
+don't count repeat access and thus aren't actually representable for our
+bandwidth numberes.
+
+ 3b) additional frequency term
+
+Additionally (or instead if it turns out we don't need the raw 'p' and 's' 
+numbers) we can approximate the repeat accesses by using the time since marking
+the pages as indication of the access frequency.
+
+Let 'I' be the interval of marking pages and 'e' the elapsed time since the
+last marking, then we could estimate the number of accesses 'a' as 'a = I / e'.
+If we then increment the node counters using 'a' instead of 1 we might get
+a better estimate of bandwidth terms.
+
+ 3c) additional averaging; can be applied on top of either a/b.
+
+[ Rik argues that decaying averages on 3a might be sufficient for bandwidth since
+  the decaying avg includes the old accesses and therefore has a measure of repeat
+  accesses.
+
+  Rik also argued that the sample frequency is too low to get accurate access
+  frequency measurements, I'm not entirely convinced, event at low sample 
+  frequencies the avg elapsed time 'e' over multiple samples should still
+  give us a fair approximation of the avg access frequency 'a'.
+
+  So doing both b&c has a fair chance of working and allowing us to distinguish
+  between important and less important memory accesses.
+
+  Experimentation has shown no benefit from the added frequency term so far. ]
+
+This will give us 'bp_i' and 'bs_i,k' so that we can approximately compute
+'T_k,l' Our optimization problem now reads:
+
+  min_C [ \Sum_i bs_i,l for every n_i = k, l != k ]
+
+And includes only shared terms, this makes sense since all task private memory
+will become local as per 2.
+
+This suggests that if there is significant shared memory, we should try and
+move towards it.
+
+ 4) move towards where 'most' memory is
+
+The simplest significance test is comparing the biggest shared 's_i,k' against
+the private 'p_i'. If we have more shared than private, move towards it.
+
+This effectively makes us move towards where most our memory is and forms a
+feed-back loop with 2. We migrate memory towards us and we migrate towards
+where 'most' memory is.
+
+(Note: even if there were two tasks fully trashing the same shared memory, it
+       is very rare for there to be an 50/50 split in memory, lacking a perfect
+       split, the small will move towards the larger. In case of the perfect
+       split, we'll tie-break towards the lower node number.)
+
+ 5) 'throttle' 4's node placement
+
+Since per 2b our 's_i,k' and 'p_i' require at least two scans to 'stabilize'
+and show representative numbers, we should limit node-migration to not be
+faster than this.
+
+ n) poke holes in previous that require more stuff and describe it.
index 7d9ca92022d8c97b2f9db88c66713211c9c8cc2a..7b4145d00452f259fe79eff4f400ecfc949a6fd1 100644 (file)
@@ -994,6 +994,23 @@ payload contents" for more information.
     reference pointer if successful.
 
 
+(*) A keyring can be created by:
+
+       struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid,
+                                 const struct cred *cred,
+                                 key_perm_t perm,
+                                 unsigned long flags,
+                                 struct key *dest);
+
+    This creates a keyring with the given attributes and returns it.  If dest
+    is not NULL, the new keyring will be linked into the keyring to which it
+    points.  No permission checks are made upon the destination keyring.
+
+    Error EDQUOT can be returned if the keyring would overload the quota (pass
+    KEY_ALLOC_NOT_IN_QUOTA in flags if the keyring shouldn't be accounted
+    towards the user's quota).  Error ENOMEM can also be returned.
+
+
 (*) To check the validity of a key, this function can be called:
 
        int validate_key(struct key *key);
index ca1a1a34970eae5dc8ddcc8d1d383e2d42be66ae..88c02334e35681b005ac20a1ad0dfe4a894bc1f7 100644 (file)
@@ -112,6 +112,29 @@ temperature) and throttle appropriate devices.
     trip: indicates which trip point the cooling devices is associated with
          in this thermal zone.
 
+1.4 Thermal Zone Parameters
+1.4.1 struct thermal_bind_params
+    This structure defines the following parameters that are used to bind
+    a zone with a cooling device for a particular trip point.
+    .cdev: The cooling device pointer
+    .weight: The 'influence' of a particular cooling device on this zone.
+             This is on a percentage scale. The sum of all these weights
+             (for a particular zone) cannot exceed 100.
+    .trip_mask:This is a bit mask that gives the binding relation between
+               this thermal zone and cdev, for a particular trip point.
+               If nth bit is set, then the cdev and thermal zone are bound
+               for trip point n.
+    .match: This call back returns success(0) if the 'tz and cdev' need to
+           be bound, as per platform data.
+1.4.2 struct thermal_zone_params
+    This structure defines the platform level parameters for a thermal zone.
+    This data, for each thermal zone should come from the platform layer.
+    This is an optional feature where some platforms can choose not to
+    provide this data.
+    .governor_name: Name of the thermal governor used for this zone
+    .num_tbps: Number of thermal_bind_params entries for this zone
+    .tbp: thermal_bind_params entries
+
 2. sysfs attributes structure
 
 RO     read only value
@@ -126,6 +149,7 @@ Thermal zone device sys I/F, created once it's registered:
     |---type:                  Type of the thermal zone
     |---temp:                  Current temperature
     |---mode:                  Working mode of the thermal zone
+    |---policy:                        Thermal governor used for this zone
     |---trip_point_[0-*]_temp: Trip point temperature
     |---trip_point_[0-*]_type: Trip point type
     |---trip_point_[0-*]_hyst: Hysteresis value for this trip point
@@ -187,6 +211,10 @@ mode
                          charge of the thermal management.
        RW, Optional
 
+policy
+       One of the various thermal governors used for a particular zone.
+       RW, Required
+
 trip_point_[0-*]_temp
        The temperature above which trip point will be fired.
        Unit: millidegree Celsius
@@ -264,6 +292,7 @@ method, the sys I/F structure will be built like this:
     |---type:                  acpitz
     |---temp:                  37000
     |---mode:                  enabled
+    |---policy:                        step_wise
     |---trip_point_0_temp:     100000
     |---trip_point_0_type:     critical
     |---trip_point_1_temp:     80000
@@ -305,3 +334,38 @@ to a thermal_zone_device when it registers itself with the framework. The
 event will be one of:{THERMAL_AUX0, THERMAL_AUX1, THERMAL_CRITICAL,
 THERMAL_DEV_FAULT}. Notification can be sent when the current temperature
 crosses any of the configured thresholds.
+
+5. Export Symbol APIs:
+
+5.1: get_tz_trend:
+This function returns the trend of a thermal zone, i.e the rate of change
+of temperature of the thermal zone. Ideally, the thermal sensor drivers
+are supposed to implement the callback. If they don't, the thermal
+framework calculated the trend by comparing the previous and the current
+temperature values.
+
+5.2:get_thermal_instance:
+This function returns the thermal_instance corresponding to a given
+{thermal_zone, cooling_device, trip_point} combination. Returns NULL
+if such an instance does not exist.
+
+5.3:notify_thermal_framework:
+This function handles the trip events from sensor drivers. It starts
+throttling the cooling devices according to the policy configured.
+For CRITICAL and HOT trip points, this notifies the respective drivers,
+and does actual throttling for other trip points i.e ACTIVE and PASSIVE.
+The throttling policy is based on the configured platform data; if no
+platform data is provided, this uses the step_wise throttling policy.
+
+5.4:thermal_cdev_update:
+This function serves as an arbitrator to set the state of a cooling
+device. It sets the cooling device to the deepest cooling state if
+possible.
+
+5.5:thermal_register_governor:
+This function lets the various thermal governors to register themselves
+with the Thermal framework. At run time, depending on a zone's platform
+data, a particular governor is used for throttling.
+
+5.6:thermal_unregister_governor:
+This function unregisters a governor from the thermal framework.
index b3f606b81a03926e287a13afa443ed8cd44d47a7..8d1e2a9ebbba25a2736690877c524927eb96b0b1 100644 (file)
@@ -35,9 +35,8 @@ USB-specific:
                d) ISO: number_of_packets is < 0
                e) various other cases
 
--EAGAIN                a) specified ISO start frame too early
-               b) (using ISO-ASAP) too much scheduled for the future
-                  wait some time and try again.
+-EXDEV         ISO: URB_ISO_ASAP wasn't specified and all the frames
+               the URB would be scheduled in have already expired.
 
 -EFBIG         Host controller driver can't schedule that many ISO frames.
 
index f6ec3a92e62148087b8ac0764e8f916e175d8eb8..6671fdc0afb1171920976b841da0f968a90f70cb 100644 (file)
@@ -1194,12 +1194,15 @@ struct kvm_ppc_pvinfo {
 This ioctl fetches PV specific information that need to be passed to the guest
 using the device tree or other means from vm context.
 
-For now the only implemented piece of information distributed here is an array
-of 4 instructions that make up a hypercall.
+The hcall array defines 4 instructions that make up a hypercall.
 
 If any additional field gets added to this structure later on, a bit for that
 additional piece of information will be set in the flags bitmap.
 
+The flags bitmap is defined as:
+
+   /* the host supports the ePAPR idle hcall
+   #define KVM_PPC_PVINFO_FLAGS_EV_IDLE   (1<<0)
 
 4.48 KVM_ASSIGN_PCI_DEVICE
 
@@ -1731,7 +1734,45 @@ registers, find a list below:
   Arch  |       Register        | Width (bits)
         |                       |
   PPC   | KVM_REG_PPC_HIOR      | 64
-
+  PPC   | KVM_REG_PPC_IAC1      | 64
+  PPC   | KVM_REG_PPC_IAC2      | 64
+  PPC   | KVM_REG_PPC_IAC3      | 64
+  PPC   | KVM_REG_PPC_IAC4      | 64
+  PPC   | KVM_REG_PPC_DAC1      | 64
+  PPC   | KVM_REG_PPC_DAC2      | 64
+  PPC   | KVM_REG_PPC_DABR      | 64
+  PPC   | KVM_REG_PPC_DSCR      | 64
+  PPC   | KVM_REG_PPC_PURR      | 64
+  PPC   | KVM_REG_PPC_SPURR     | 64
+  PPC   | KVM_REG_PPC_DAR       | 64
+  PPC   | KVM_REG_PPC_DSISR     | 32
+  PPC   | KVM_REG_PPC_AMR       | 64
+  PPC   | KVM_REG_PPC_UAMOR     | 64
+  PPC   | KVM_REG_PPC_MMCR0     | 64
+  PPC   | KVM_REG_PPC_MMCR1     | 64
+  PPC   | KVM_REG_PPC_MMCRA     | 64
+  PPC   | KVM_REG_PPC_PMC1      | 32
+  PPC   | KVM_REG_PPC_PMC2      | 32
+  PPC   | KVM_REG_PPC_PMC3      | 32
+  PPC   | KVM_REG_PPC_PMC4      | 32
+  PPC   | KVM_REG_PPC_PMC5      | 32
+  PPC   | KVM_REG_PPC_PMC6      | 32
+  PPC   | KVM_REG_PPC_PMC7      | 32
+  PPC   | KVM_REG_PPC_PMC8      | 32
+  PPC   | KVM_REG_PPC_FPR0      | 64
+          ...
+  PPC   | KVM_REG_PPC_FPR31     | 64
+  PPC   | KVM_REG_PPC_VR0       | 128
+          ...
+  PPC   | KVM_REG_PPC_VR31      | 128
+  PPC   | KVM_REG_PPC_VSR0      | 128
+          ...
+  PPC   | KVM_REG_PPC_VSR31     | 128
+  PPC   | KVM_REG_PPC_FPSCR     | 64
+  PPC   | KVM_REG_PPC_VSCR      | 32
+  PPC   | KVM_REG_PPC_VPA_ADDR  | 64
+  PPC   | KVM_REG_PPC_VPA_SLB   | 128
+  PPC   | KVM_REG_PPC_VPA_DTL   | 128
 
 4.69 KVM_GET_ONE_REG
 
@@ -1747,7 +1788,7 @@ kvm_one_reg struct passed in. On success, the register value can be found
 at the memory location pointed to by "addr".
 
 The list of registers accessible using this interface is identical to the
-list in 4.64.
+list in 4.68.
 
 
 4.70 KVM_KVMCLOCK_CTRL
@@ -1997,6 +2038,39 @@ return the hash table order in the parameter.  (If the guest is using
 the virtualized real-mode area (VRMA) facility, the kernel will
 re-create the VMRA HPTEs on the next KVM_RUN of any vcpu.)
 
+4.77 KVM_S390_INTERRUPT
+
+Capability: basic
+Architectures: s390
+Type: vm ioctl, vcpu ioctl
+Parameters: struct kvm_s390_interrupt (in)
+Returns: 0 on success, -1 on error
+
+Allows to inject an interrupt to the guest. Interrupts can be floating
+(vm ioctl) or per cpu (vcpu ioctl), depending on the interrupt type.
+
+Interrupt parameters are passed via kvm_s390_interrupt:
+
+struct kvm_s390_interrupt {
+       __u32 type;
+       __u32 parm;
+       __u64 parm64;
+};
+
+type can be one of the following:
+
+KVM_S390_SIGP_STOP (vcpu) - sigp restart
+KVM_S390_PROGRAM_INT (vcpu) - program check; code in parm
+KVM_S390_SIGP_SET_PREFIX (vcpu) - sigp set prefix; prefix address in parm
+KVM_S390_RESTART (vcpu) - restart
+KVM_S390_INT_VIRTIO (vm) - virtio external interrupt; external interrupt
+                          parameters in parm and parm64
+KVM_S390_INT_SERVICE (vm) - sclp external interrupt; sclp parameter in parm
+KVM_S390_INT_EMERGENCY (vcpu) - sigp emergency; source cpu in parm
+KVM_S390_INT_EXTERNAL_CALL (vcpu) - sigp external call; source cpu in parm
+
+Note that the vcpu ioctl is asynchronous to vcpu execution.
+
 
 5. The kvm_run structure
 ------------------------
@@ -2109,7 +2183,8 @@ executed a memory-mapped I/O instruction which could not be satisfied
 by kvm.  The 'data' member contains the written data if 'is_write' is
 true, and should be filled by application code otherwise.
 
-NOTE: For KVM_EXIT_IO, KVM_EXIT_MMIO and KVM_EXIT_OSI, the corresponding
+NOTE: For KVM_EXIT_IO, KVM_EXIT_MMIO, KVM_EXIT_OSI, KVM_EXIT_DCR
+      and KVM_EXIT_PAPR the corresponding
 operations are complete (and guest state is consistent) only after userspace
 has re-entered the kernel with KVM_RUN.  The kernel side will first finish
 incomplete operations and then check for pending signals.  Userspace
index 41c53491db60fe9cbf199e8afbf2a876a82412d3..00af53baa0a2274b16523b8f6d2c2eff46041662 100644 (file)
@@ -235,6 +235,7 @@ F:  drivers/platform/x86/acer-wmi.c
 
 ACPI
 M:     Len Brown <lenb@kernel.org>
+M:     Rafael J. Wysocki <rjw@sisk.pl>
 L:     linux-acpi@vger.kernel.org
 W:     http://www.lesswatts.org/projects/acpi/
 Q:     http://patchwork.kernel.org/project/linux-acpi/list/
@@ -789,7 +790,6 @@ L:  linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
 T:     git git://git.pengutronix.de/git/imx/linux-2.6.git
 F:     arch/arm/mach-imx/
-F:     arch/arm/plat-mxc/
 F:     arch/arm/configs/imx*_defconfig
 
 ARM/FREESCALE IMX6
@@ -2705,6 +2705,15 @@ W:       bluesmoke.sourceforge.net
 S:     Supported
 F:     drivers/edac/amd64_edac*
 
+EDAC-CAVIUM
+M:     Ralf Baechle <ralf@linux-mips.org>
+M:     David Daney <david.daney@cavium.com>
+L:     linux-edac@vger.kernel.org
+L:     linux-mips@linux-mips.org
+W:     bluesmoke.sourceforge.net
+S:     Supported
+F:     drivers/edac/octeon_edac*
+
 EDAC-E752X
 M:     Mark Gross <mark.gross@intel.com>
 M:     Doug Thompson <dougthompson@xmission.com>
@@ -3869,7 +3878,9 @@ M:        Greg Rose <gregory.v.rose@intel.com>
 M:     Peter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com>
 M:     Alex Duyck <alexander.h.duyck@intel.com>
 M:     John Ronciak <john.ronciak@intel.com>
+M:     Tushar Dave <tushar.n.dave@intel.com>
 L:     e1000-devel@lists.sourceforge.net
+W:     http://www.intel.com/support/feedback.htm
 W:     http://e1000.sourceforge.net/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/net.git
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/net-next.git
@@ -4907,6 +4918,14 @@ L:       alsa-devel@alsa-project.org
 W:     http://www.native-instruments.com
 F:     sound/usb/caiaq/
 
+NATIVE LINUX KVM TOOL
+M:     Pekka Enberg <penberg@kernel.org>
+M:     Sasha Levin <levinsasha928@gmail.com>
+M:     Asias He <asias.hejun@gmail.com>
+L:     kvm@vger.kernel.org
+S:     Maintained
+F:     tools/kvm/
+
 NCP FILESYSTEM
 M:     Petr Vandrovec <petr@vandrovec.name>
 S:     Odd Fixes
@@ -5060,7 +5079,13 @@ T:       git git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git
 S:     Odd Fixes
 F:     drivers/net/
 F:     include/linux/if_*
-F:     include/linux/*device.h
+F:     include/linux/netdevice.h
+F:     include/linux/arcdevice.h
+F:     include/linux/etherdevice.h
+F:     include/linux/fcdevice.h
+F:     include/linux/fddidevice.h
+F:     include/linux/hippidevice.h
+F:     include/linux/inetdevice.h
 
 NETXEN (1/10) GbE SUPPORT
 M:     Sony Chacko <sony.chacko@qlogic.com>
@@ -5632,7 +5657,7 @@ S:        Maintained
 F:     drivers/pinctrl/spear/
 
 PKTCDVD DRIVER
-M:     Peter Osterlund <petero2@telia.com>
+M:     Jiri Kosina <jkosina@suse.cz>
 S:     Maintained
 F:     drivers/block/pktcdvd.c
 F:     include/linux/pktcdvd.h
@@ -6716,6 +6741,11 @@ W:       http://tifmxx.berlios.de/
 S:     Maintained
 F:     drivers/memstick/host/tifm_ms.c
 
+SONY MEMORYSTICK STANDARD SUPPORT
+M:     Maxim Levitsky <maximlevitsky@gmail.com>
+S:     Maintained
+F:     drivers/memstick/core/ms_block.*
+
 SOUND
 M:     Jaroslav Kysela <perex@perex.cz>
 M:     Takashi Iwai <tiwai@suse.de>
@@ -7745,6 +7775,13 @@ W:       http://www.ideasonboard.org/uvc/
 S:     Maintained
 F:     drivers/media/usb/uvc/
 
+USB WEBCAM GADGET
+M:     Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+L:     linux-usb@vger.kernel.org
+S:     Maintained
+F:     drivers/usb/gadget/*uvc*.c
+F:     drivers/usb/gadget/webcam.c
+
 USB WIRELESS RNDIS DRIVER (rndis_wlan)
 M:     Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
 L:     linux-wireless@vger.kernel.org
index 366d0ab0c5fe7f0f0c8e82f4d909aeb541a44e98..14c93b39b9291a45d07bd6c4afe8fe792ede241f 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 3
 PATCHLEVEL = 7
 SUBLEVEL = 0
-EXTRAVERSION = -rc1
+EXTRAVERSION = -rc2
 NAME = Terrified Chipmunk
 
 # *DOCUMENTATION*
@@ -719,6 +719,17 @@ endif # INSTALL_MOD_STRIP
 export mod_strip_cmd
 
 
+ifeq ($(CONFIG_MODULE_SIG),y)
+MODSECKEY = ./signing_key.priv
+MODPUBKEY = ./signing_key.x509
+export MODPUBKEY
+mod_sign_cmd = perl $(srctree)/scripts/sign-file $(MODSECKEY) $(MODPUBKEY)
+else
+mod_sign_cmd = true
+endif
+export mod_sign_cmd
+
+
 ifeq ($(KBUILD_EXTMOD),)
 core-y         += kernel/ mm/ fs/ ipc/ security/ crypto/ block/
 
index 5530911dd010725d90b0371b6bb2acc346a58be7..14db93e4c8a83662d459a6ff1a818318dbc61eeb 100644 (file)
@@ -445,7 +445,7 @@ struct procfs_args {
  * unhappy with OSF UFS. [CHECKME]
  */
 static int
-osf_ufs_mount(char *dirname, struct ufs_args __user *args, int flags)
+osf_ufs_mount(const char *dirname, struct ufs_args __user *args, int flags)
 {
        int retval;
        struct cdfs_args tmp;
@@ -465,7 +465,7 @@ osf_ufs_mount(char *dirname, struct ufs_args __user *args, int flags)
 }
 
 static int
-osf_cdfs_mount(char *dirname, struct cdfs_args __user *args, int flags)
+osf_cdfs_mount(const char *dirname, struct cdfs_args __user *args, int flags)
 {
        int retval;
        struct cdfs_args tmp;
@@ -485,7 +485,7 @@ osf_cdfs_mount(char *dirname, struct cdfs_args __user *args, int flags)
 }
 
 static int
-osf_procfs_mount(char *dirname, struct procfs_args __user *args, int flags)
+osf_procfs_mount(const char *dirname, struct procfs_args __user *args, int flags)
 {
        struct procfs_args tmp;
 
@@ -906,10 +906,10 @@ SYSCALL_DEFINE5(osf_setsysinfo, unsigned long, op, void __user *, buffer,
                unsigned __user *p = buffer;
                unsigned i;
                
-               for (i = 0, p = buffer; i < nbytes; ++i, p += 2) {
+               for (i = 0, p = buffer; i < nbytes; ++i, p += 2) {
                        unsigned v, w, status;
 
-                       if (get_user(v, p) || get_user(w, p + 1))
+                       if (get_user(v, p) || get_user(w, p + 1))
                                return -EFAULT;
                        switch (v) {
                        case SSIN_UACPROC:
index 73067efd484530d4021a220fecce329b4752b3c0..e2ffefcc0992d9239d5b4ddd39913004009e1b5f 100644 (file)
@@ -330,6 +330,8 @@ config ARCH_AT91
        select IRQ_DOMAIN
        select NEED_MACH_GPIO_H
        select NEED_MACH_IO_H if PCCARD
+       select PINCTRL
+       select PINCTRL_AT91 if USE_OF
        help
          This enables support for systems based on Atmel
          AT91RM9200 and AT91SAM9* processors.
@@ -364,6 +366,7 @@ config ARCH_CNS3XXX
 
 config ARCH_CLPS711X
        bool "Cirrus Logic CLPS711x/EP721x/EP731x-based"
+       select ARCH_REQUIRE_GPIOLIB
        select ARCH_USES_GETTIMEOFFSET
        select CLKDEV_LOOKUP
        select COMMON_CLK
@@ -433,19 +436,6 @@ config ARCH_FOOTBRIDGE
          Support for systems based on the DC21285 companion chip
          ("FootBridge"), such as the Simtec CATS and the Rebel NetWinder.
 
-config ARCH_MXC
-       bool "Freescale MXC/iMX-based"
-       select ARCH_REQUIRE_GPIOLIB
-       select CLKDEV_LOOKUP
-       select CLKSRC_MMIO
-       select GENERIC_CLOCKEVENTS
-       select GENERIC_IRQ_CHIP
-       select MULTI_IRQ_HANDLER
-       select SPARSE_IRQ
-       select USE_OF
-       help
-         Support for Freescale MXC/iMX-based family of processors
-
 config ARCH_MXS
        bool "Freescale MXS-based"
        select ARCH_REQUIRE_GPIOLIB
@@ -644,6 +634,7 @@ config ARCH_TEGRA
        select HAVE_CLK
        select HAVE_SMP
        select MIGHT_HAVE_CACHE_L2X0
+       select SPARSE_IRQ
        select USE_OF
        help
          This enables support for NVIDIA Tegra based systems (Tegra APX,
@@ -1058,7 +1049,7 @@ source "arch/arm/mach-msm/Kconfig"
 
 source "arch/arm/mach-mv78xx0/Kconfig"
 
-source "arch/arm/plat-mxc/Kconfig"
+source "arch/arm/mach-imx/Kconfig"
 
 source "arch/arm/mach-mxs/Kconfig"
 
@@ -1603,8 +1594,8 @@ config NR_CPUS
        default "4"
 
 config HOTPLUG_CPU
-       bool "Support for hot-pluggable CPUs (EXPERIMENTAL)"
-       depends on SMP && HOTPLUG && EXPERIMENTAL
+       bool "Support for hot-pluggable CPUs"
+       depends on SMP && HOTPLUG
        help
          Say Y here to experiment with turning CPUs off and on.  CPUs
          can be controlled through /sys/devices/system/cpu.
@@ -1645,8 +1636,8 @@ config HZ
        default 100
 
 config THUMB2_KERNEL
-       bool "Compile the kernel in Thumb-2 mode (EXPERIMENTAL)"
-       depends on CPU_V7 && !CPU_V6 && !CPU_V6K && EXPERIMENTAL
+       bool "Compile the kernel in Thumb-2 mode"
+       depends on CPU_V7 && !CPU_V6 && !CPU_V6K
        select AEABI
        select ARM_ASM_UNIFIED
        select ARM_UNWIND
@@ -1850,6 +1841,7 @@ config XEN_DOM0
 config XEN
        bool "Xen guest support on ARM (EXPERIMENTAL)"
        depends on EXPERIMENTAL && ARM && OF
+       depends on CPU_V7 && !CPU_V6
        help
          Say Y if you want to run Linux in a Virtual Machine on Xen on ARM.
 
index b0f3857b3a4c647714a4d748726524e20f01bd4c..5566520686a5a8bcad7d66f9b6bb0e56b494b6e0 100644 (file)
@@ -412,6 +412,14 @@ endchoice
 config DEBUG_LL_INCLUDE
        string
        default "debug/icedcc.S" if DEBUG_ICEDCC
+       default "debug/imx.S" if DEBUG_IMX1_UART || \
+                                DEBUG_IMX25_UART || \
+                                DEBUG_IMX21_IMX27_UART || \
+                                DEBUG_IMX31_IMX35_UART || \
+                                DEBUG_IMX51_UART || \
+                                DEBUG_IMX50_IMX53_UART ||\
+                                DEBUG_IMX6Q_UART2 || \
+                                DEBUG_IMX6Q_UART4
        default "debug/highbank.S" if DEBUG_HIGHBANK_UART
        default "debug/mvebu.S" if DEBUG_MVEBU_UART
        default "debug/picoxcell.S" if DEBUG_PICOXCELL_UART
index f023e3acdfbd8c7c17335cfa9518df05119f4ab7..3353b761320854fd1720bf50648ebc9684398627 100644 (file)
@@ -21,8 +21,6 @@ endif
 OBJCOPYFLAGS   :=-O binary -R .comment -S
 GZFLAGS                :=-9
 #KBUILD_CFLAGS +=-pipe
-# Explicitly specifiy 32-bit ARM ISA since toolchain default can be -mthumb:
-KBUILD_CFLAGS  +=$(call cc-option,-marm,)
 
 # Never generate .eh_frame
 KBUILD_CFLAGS  += $(call cc-option,-fno-dwarf2-cfi-asm)
@@ -105,17 +103,20 @@ endif
 ifeq ($(CONFIG_THUMB2_KERNEL),y)
 AFLAGS_AUTOIT  :=$(call as-option,-Wa$(comma)-mimplicit-it=always,-Wa$(comma)-mauto-it)
 AFLAGS_NOWARN  :=$(call as-option,-Wa$(comma)-mno-warn-deprecated,-Wa$(comma)-W)
-CFLAGS_THUMB2  :=-mthumb $(AFLAGS_AUTOIT) $(AFLAGS_NOWARN)
-AFLAGS_THUMB2  :=$(CFLAGS_THUMB2) -Wa$(comma)-mthumb
+CFLAGS_ISA     :=-mthumb $(AFLAGS_AUTOIT) $(AFLAGS_NOWARN)
+AFLAGS_ISA     :=$(CFLAGS_ISA) -Wa$(comma)-mthumb
 # Work around buggy relocation from gas if requested:
 ifeq ($(CONFIG_THUMB2_AVOID_R_ARM_THM_JUMP11),y)
 CFLAGS_MODULE  +=-fno-optimize-sibling-calls
 endif
+else
+CFLAGS_ISA     :=$(call cc-option,-marm,)
+AFLAGS_ISA     :=$(CFLAGS_ISA)
 endif
 
 # Need -Uarm for gcc < 3.x
-KBUILD_CFLAGS  +=$(CFLAGS_ABI) $(CFLAGS_THUMB2) $(arch-y) $(tune-y) $(call cc-option,-mshort-load-bytes,$(call cc-option,-malignment-traps,)) -msoft-float -Uarm
-KBUILD_AFLAGS  +=$(CFLAGS_ABI) $(AFLAGS_THUMB2) $(arch-y) $(tune-y) -include asm/unified.h -msoft-float
+KBUILD_CFLAGS  +=$(CFLAGS_ABI) $(CFLAGS_ISA) $(arch-y) $(tune-y) $(call cc-option,-mshort-load-bytes,$(call cc-option,-malignment-traps,)) -msoft-float -Uarm
+KBUILD_AFLAGS  +=$(CFLAGS_ABI) $(AFLAGS_ISA) $(arch-y) $(tune-y) -include asm/unified.h -msoft-float
 
 CHECKFLAGS     += -D__arm__
 
@@ -195,7 +196,6 @@ machine-$(CONFIG_ARCH_ZYNQ)         += zynq
 
 # Platform directory name.  This list is sorted alphanumerically
 # by CONFIG_* macro name.
-plat-$(CONFIG_ARCH_MXC)                += mxc
 plat-$(CONFIG_ARCH_OMAP)       += omap
 plat-$(CONFIG_ARCH_S3C64XX)    += samsung
 plat-$(CONFIG_ARCH_ZYNQ)       += versatile
diff --git a/arch/arm/arm-soc-for-next-contents.txt b/arch/arm/arm-soc-for-next-contents.txt
new file mode 100644 (file)
index 0000000..cb4e35a
--- /dev/null
@@ -0,0 +1,7 @@
+arm-soc for-next contents for 3.8:
+
+next/fixes-non-critical:
+
+next/cleanup:
+imx/multiplatform      git://git.linaro.org/people/shawnguo/linux-2.6.git imx/multi-platform
+vt8500/cleanup         git://server.prisktech.co.nz/git/linuxwmt.git/ tags/cleanup-for-3.8 
index 3fdab016aa5cfdc9132813f4c5be44348fb1c539..f2aa09eb658e632c7703203d97cd3469d7996259 100644 (file)
@@ -33,7 +33,7 @@ ifeq ($(CONFIG_XIP_KERNEL),y)
 
 $(obj)/xipImage: vmlinux FORCE
        $(call if_changed,objcopy)
-       @echo '  Kernel: $@ is ready (physical address: $(CONFIG_XIP_PHYS_ADDR))'
+       $(kecho) '  Kernel: $@ is ready (physical address: $(CONFIG_XIP_PHYS_ADDR))'
 
 $(obj)/Image $(obj)/zImage: FORCE
        @echo 'Kernel configured for XIP (CONFIG_XIP_KERNEL=y)'
@@ -48,14 +48,14 @@ $(obj)/xipImage: FORCE
 
 $(obj)/Image: vmlinux FORCE
        $(call if_changed,objcopy)
-       @echo '  Kernel: $@ is ready'
+       $(kecho) '  Kernel: $@ is ready'
 
 $(obj)/compressed/vmlinux: $(obj)/Image FORCE
        $(Q)$(MAKE) $(build)=$(obj)/compressed $@
 
 $(obj)/zImage: $(obj)/compressed/vmlinux FORCE
        $(call if_changed,objcopy)
-       @echo '  Kernel: $@ is ready'
+       $(kecho) '  Kernel: $@ is ready'
 
 endif
 
@@ -90,7 +90,7 @@ fi
 $(obj)/uImage: $(obj)/zImage FORCE
        @$(check_for_multiple_loadaddr)
        $(call if_changed,uimage)
-       @echo '  Image $@ is ready'
+       $(kecho) '  Image $@ is ready'
 
 $(obj)/bootp/bootp: $(obj)/zImage initrd FORCE
        $(Q)$(MAKE) $(build)=$(obj)/bootp $@
@@ -98,7 +98,7 @@ $(obj)/bootp/bootp: $(obj)/zImage initrd FORCE
 
 $(obj)/bootpImage: $(obj)/bootp/bootp FORCE
        $(call if_changed,objcopy)
-       @echo '  Kernel: $@ is ready'
+       $(kecho) '  Kernel: $@ is ready'
 
 PHONY += initrd FORCE
 initrd:
index a517153a13eabdad582b6b6f75080cf93f699595..537208f22e564db68de821ca2908b18d3ed281c6 100644 (file)
@@ -54,10 +54,6 @@ ifeq ($(CONFIG_ARCH_SA1100),y)
 OBJS           += head-sa1100.o
 endif
 
-ifeq ($(CONFIG_ARCH_VT8500),y)
-OBJS           += head-vt8500.o
-endif
-
 ifeq ($(CONFIG_CPU_XSCALE),y)
 OBJS           += head-xscale.o
 endif
diff --git a/arch/arm/boot/compressed/head-vt8500.S b/arch/arm/boot/compressed/head-vt8500.S
deleted file mode 100644 (file)
index 1dc1e21..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * linux/arch/arm/boot/compressed/head-vt8500.S
- *
- * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
- *
- * VIA VT8500 specific tweaks. This is merged into head.S by the linker.
- *
- */
-
-#include <linux/linkage.h>
-#include <asm/mach-types.h>
-
-               .section        ".start", "ax"
-
-__VT8500_start:
-       @ Compare the SCC ID register against a list of known values
-       ldr     r1, .SCCID
-       ldr     r3, [r1]
-
-       @ VT8500 override
-       ldr     r4, .VT8500SCC
-       cmp     r3, r4
-       ldreq   r7, .ID_BV07
-       beq     .Lendvt8500
-
-       @ WM8505 override
-       ldr     r4, .WM8505SCC
-       cmp     r3, r4
-       ldreq   r7, .ID_8505
-       beq     .Lendvt8500
-
-       @ Otherwise, leave the bootloader's machine id untouched
-
-.SCCID:
-       .word   0xd8120000
-.VT8500SCC:
-       .word   0x34000102
-.WM8505SCC:
-       .word   0x34260103
-
-.ID_BV07:
-       .word   MACH_TYPE_BV07
-.ID_8505:
-       .word   MACH_TYPE_WM8505_7IN_NETBOOK
-
-.Lendvt8500:
index c1ce813fcc4a1ea9094eb450ce4e50efd3d6048b..3bf4f53416ad9323cf3ddb3526f95ba81d843792 100644 (file)
@@ -1,21 +1,33 @@
 ifeq ($(CONFIG_OF),y)
 
-dtb-$(CONFIG_ARCH_AT91) += aks-cdu.dtb \
-       at91sam9263ek.dtb \
-       at91sam9g20ek_2mmc.dtb \
-       at91sam9g20ek.dtb \
-       at91sam9g25ek.dtb \
-       at91sam9m10g45ek.dtb \
-       at91sam9n12ek.dtb \
-       ethernut5.dtb \
-       evk-pro3.dtb \
-       kizbox.dtb \
-       tny_a9260.dtb \
-       tny_a9263.dtb \
-       tny_a9g20.dtb \
-       usb_a9260.dtb \
-       usb_a9263.dtb \
-       usb_a9g20.dtb
+# Keep at91 dtb files sorted alphabetically for each SoC
+# sam9260
+dtb-$(CONFIG_ARCH_AT91) += aks-cdu.dtb
+dtb-$(CONFIG_ARCH_AT91) += ethernut5.dtb
+dtb-$(CONFIG_ARCH_AT91) += evk-pro3.dtb
+dtb-$(CONFIG_ARCH_AT91) += tny_a9260.dtb
+dtb-$(CONFIG_ARCH_AT91) += usb_a9260.dtb
+# sam9263
+dtb-$(CONFIG_ARCH_AT91) += at91sam9263ek.dtb
+dtb-$(CONFIG_ARCH_AT91) += tny_a9263.dtb
+dtb-$(CONFIG_ARCH_AT91) += usb_a9263.dtb
+# sam9g20
+dtb-$(CONFIG_ARCH_AT91) += at91sam9g20ek.dtb
+dtb-$(CONFIG_ARCH_AT91) += at91sam9g20ek_2mmc.dtb
+dtb-$(CONFIG_ARCH_AT91) += kizbox.dtb
+dtb-$(CONFIG_ARCH_AT91) += tny_a9g20.dtb
+dtb-$(CONFIG_ARCH_AT91) += usb_a9g20.dtb
+# sam9g45
+dtb-$(CONFIG_ARCH_AT91) += at91sam9m10g45ek.dtb
+# sam9n12
+dtb-$(CONFIG_ARCH_AT91) += at91sam9n12ek.dtb
+# sam9x5
+dtb-$(CONFIG_ARCH_AT91) += at91sam9g15ek.dtb
+dtb-$(CONFIG_ARCH_AT91) += at91sam9g25ek.dtb
+dtb-$(CONFIG_ARCH_AT91) += at91sam9g35ek.dtb
+dtb-$(CONFIG_ARCH_AT91) += at91sam9x25ek.dtb
+dtb-$(CONFIG_ARCH_AT91) += at91sam9x35ek.dtb
+
 dtb-$(CONFIG_ARCH_BCM2835) += bcm2835-rpi-b.dtb
 dtb-$(CONFIG_ARCH_DOVE) += dove-cm-a510.dtb \
        dove-cubox.dtb \
@@ -25,6 +37,8 @@ dtb-$(CONFIG_ARCH_EXYNOS) += exynos4210-origen.dtb \
        exynos4210-trats.dtb \
        exynos5250-smdk5250.dtb
 dtb-$(CONFIG_ARCH_HIGHBANK) += highbank.dtb
+dtb-$(CONFIG_ARCH_INTEGRATOR) += integratorap.dtb \
+       integratorcp.dtb
 dtb-$(CONFIG_ARCH_LPC32XX) += ea3250.dtb phy3250.dtb
 dtb-$(CONFIG_ARCH_KIRKWOOD) += kirkwood-dns320.dtb \
        kirkwood-dns325.dtb \
@@ -75,7 +89,8 @@ dtb-$(CONFIG_ARCH_PRIMA2) += prima2-evb.dtb
 dtb-$(CONFIG_ARCH_U8500) += snowball.dtb
 dtb-$(CONFIG_ARCH_SHMOBILE) += emev2-kzm9d.dtb \
        r8a7740-armadillo800eva.dtb \
-       sh73a0-kzm9g.dtb
+       sh73a0-kzm9g.dtb \
+       sh7372-mackerel.dtb
 dtb-$(CONFIG_ARCH_SPEAR13XX) += spear1310-evb.dtb \
        spear1340-evb.dtb
 dtb-$(CONFIG_ARCH_SPEAR3XX)+= spear300-evb.dtb \
index d410581a5a859901b32a49a1f037356c9f22e294..9a24ffbb723103cc44a4f980781d081271078739 100644 (file)
                                interrupts = <26 4 0 27 4 0 28 4 0>;
                        };
 
-                       pioA: gpio@fffff400 {
-                               compatible = "atmel,at91rm9200-gpio";
-                               reg = <0xfffff400 0x100>;
-                               interrupts = <2 4 1>;
-                               #gpio-cells = <2>;
-                               gpio-controller;
-                               interrupt-controller;
-                               #interrupt-cells = <2>;
-                       };
+                       pinctrl@fffff400 {
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               compatible = "atmel,at91rm9200-pinctrl", "simple-bus";
+                               ranges = <0xfffff400 0xfffff400 0x600>;
+
+                               atmel,mux-mask = <
+                                     /*    A         B     */
+                                      0xffffffff 0xffc00c3b  /* pioA */
+                                      0xffffffff 0x7fff3ccf  /* pioB */
+                                      0xffffffff 0x007fffff  /* pioC */
+                                     >;
+
+                               /* shared pinctrl settings */
+                               dbgu {
+                                       pinctrl_dbgu: dbgu-0 {
+                                               atmel,pins =
+                                                       <1 14 0x1 0x0   /* PB14 periph A */
+                                                        1 15 0x1 0x1>; /* PB15 periph with pullup */
+                                       };
+                               };
 
-                       pioB: gpio@fffff600 {
-                               compatible = "atmel,at91rm9200-gpio";
-                               reg = <0xfffff600 0x100>;
-                               interrupts = <3 4 1>;
-                               #gpio-cells = <2>;
-                               gpio-controller;
-                               interrupt-controller;
-                               #interrupt-cells = <2>;
-                       };
+                               uart0 {
+                                       pinctrl_uart0: uart0-0 {
+                                               atmel,pins =
+                                                       <1 4 0x1 0x0    /* PB4 periph A */
+                                                        1 5 0x1 0x0>;  /* PB5 periph A */
+                                       };
+
+                                       pinctrl_uart0_rts_cts: uart0_rts_cts-0 {
+                                               atmel,pins =
+                                                       <1 26 0x1 0x0   /* PB26 periph A */
+                                                        1 27 0x1 0x0>; /* PB27 periph A */
+                                       };
+
+                                       pinctrl_uart0_dtr_dsr: uart0_dtr_dsr-0 {
+                                               atmel,pins =
+                                                       <1 24 0x1 0x0   /* PB24 periph A */
+                                                        1 22 0x1 0x0>; /* PB22 periph A */
+                                       };
+
+                                       pinctrl_uart0_dcd: uart0_dcd-0 {
+                                               atmel,pins =
+                                                       <1 23 0x1 0x0>; /* PB23 periph A */
+                                       };
+
+                                       pinctrl_uart0_ri: uart0_ri-0 {
+                                               atmel,pins =
+                                                       <1 25 0x1 0x0>; /* PB25 periph A */
+                                       };
+                               };
 
-                       pioC: gpio@fffff800 {
-                               compatible = "atmel,at91rm9200-gpio";
-                               reg = <0xfffff800 0x100>;
-                               interrupts = <4 4 1>;
-                               #gpio-cells = <2>;
-                               gpio-controller;
-                               interrupt-controller;
-                               #interrupt-cells = <2>;
+                               uart1 {
+                                       pinctrl_uart1: uart1-0 {
+                                               atmel,pins =
+                                                       <2 6 0x1 0x1    /* PB6 periph A with pullup */
+                                                        2 7 0x1 0x0>;  /* PB7 periph A */
+                                       };
+
+                                       pinctrl_uart1_rts_cts: uart1_rts_cts-0 {
+                                               atmel,pins =
+                                                       <1 28 0x1 0x0   /* PB28 periph A */
+                                                        1 29 0x1 0x0>; /* PB29 periph A */
+                                       };
+                               };
+
+                               uart2 {
+                                       pinctrl_uart2: uart2-0 {
+                                               atmel,pins =
+                                                       <1 8 0x1 0x1    /* PB8 periph A with pullup */
+                                                        1 9 0x1 0x0>;  /* PB9 periph A */
+                                       };
+
+                                       pinctrl_uart2_rts_cts: uart2_rts_cts-0 {
+                                               atmel,pins =
+                                                       <0 4 0x1 0x0    /* PA4 periph A */
+                                                        0 5 0x1 0x0>;  /* PA5 periph A */
+                                       };
+                               };
+
+                               uart3 {
+                                       pinctrl_uart3: uart3-0 {
+                                               atmel,pins =
+                                                       <2 10 0x1 0x1   /* PB10 periph A with pullup */
+                                                        2 11 0x1 0x0>; /* PB11 periph A */
+                                       };
+
+                                       pinctrl_uart3_rts_cts: uart3_rts_cts-0 {
+                                               atmel,pins =
+                                                       <3 8 0x2 0x0    /* PB8 periph B */
+                                                        3 10 0x2 0x0>; /* PB10 periph B */
+                                       };
+                               };
+
+                               uart4 {
+                                       pinctrl_uart4: uart4-0 {
+                                               atmel,pins =
+                                                       <0 31 0x2 0x1   /* PA31 periph B with pullup */
+                                                        0 30 0x2 0x0>; /* PA30 periph B */
+                                       };
+                               };
+
+                               uart5 {
+                                       pinctrl_uart5: uart5-0 {
+                                               atmel,pins =
+                                                       <2 12 0x1 0x1   /* PB12 periph A with pullup */
+                                                        2 13 0x1 0x0>; /* PB13 periph A */
+                                       };
+                               };
+
+                               nand {
+                                       pinctrl_nand: nand-0 {
+                                               atmel,pins =
+                                                       <2 13 0x0 0x1   /* PC13 gpio RDY pin pull_up */
+                                                        2 14 0x0 0x1>; /* PC14 gpio enable pin pull_up */
+                                       };
+                               };
+
+                               pioA: gpio@fffff400 {
+                                       compatible = "atmel,at91rm9200-gpio";
+                                       reg = <0xfffff400 0x200>;
+                                       interrupts = <2 4 1>;
+                                       #gpio-cells = <2>;
+                                       gpio-controller;
+                                       interrupt-controller;
+                                       #interrupt-cells = <2>;
+                               };
+
+                               pioB: gpio@fffff600 {
+                                       compatible = "atmel,at91rm9200-gpio";
+                                       reg = <0xfffff600 0x200>;
+                                       interrupts = <3 4 1>;
+                                       #gpio-cells = <2>;
+                                       gpio-controller;
+                                       interrupt-controller;
+                                       #interrupt-cells = <2>;
+                               };
+
+                               pioC: gpio@fffff800 {
+                                       compatible = "atmel,at91rm9200-gpio";
+                                       reg = <0xfffff800 0x200>;
+                                       interrupts = <4 4 1>;
+                                       #gpio-cells = <2>;
+                                       gpio-controller;
+                                       interrupt-controller;
+                                       #interrupt-cells = <2>;
+                               };
                        };
 
                        dbgu: serial@fffff200 {
                                compatible = "atmel,at91sam9260-usart";
                                reg = <0xfffff200 0x200>;
                                interrupts = <1 4 7>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_dbgu>;
                                status = "disabled";
                        };
 
                                interrupts = <6 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_uart0>;
                                status = "disabled";
                        };
 
                                interrupts = <7 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_uart1>;
                                status = "disabled";
                        };
 
                                interrupts = <8 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_uart2>;
                                status = "disabled";
                        };
 
                                interrupts = <23 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_uart3>;
                                status = "disabled";
                        };
 
                                interrupts = <24 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_uart4>;
                                status = "disabled";
                        };
 
                                interrupts = <25 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_uart5>;
                                status = "disabled";
                        };
 
                              >;
                        atmel,nand-addr-offset = <21>;
                        atmel,nand-cmd-offset = <22>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&pinctrl_nand>;
                        gpios = <&pioC 13 0
                                 &pioC 14 0
                                 0
index 3e6e5c1abbf37184a44237e464080a52f4312e9f..251ccec430a40be60be2212c65ce51d72f798800 100644 (file)
                                reg = <0xfffffd10 0x10>;
                        };
 
-                       pioA: gpio@fffff200 {
-                               compatible = "atmel,at91rm9200-gpio";
-                               reg = <0xfffff200 0x100>;
-                               interrupts = <2 4 1>;
-                               #gpio-cells = <2>;
-                               gpio-controller;
-                               interrupt-controller;
-                               #interrupt-cells = <2>;
-                       };
+                       pinctrl@fffff200 {
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               compatible = "atmel,at91rm9200-pinctrl", "simple-bus";
+                               ranges = <0xfffff200 0xfffff200 0xa00>;
 
-                       pioB: gpio@fffff400 {
-                               compatible = "atmel,at91rm9200-gpio";
-                               reg = <0xfffff400 0x100>;
-                               interrupts = <3 4 1>;
-                               #gpio-cells = <2>;
-                               gpio-controller;
-                               interrupt-controller;
-                               #interrupt-cells = <2>;
-                       };
+                               atmel,mux-mask = <
+                                     /*    A         B     */
+                                      0xfffffffb 0xffffe07f  /* pioA */
+                                      0x0007ffff 0x39072fff  /* pioB */
+                                      0xffffffff 0x3ffffff8  /* pioC */
+                                      0xfffffbff 0xffffffff  /* pioD */
+                                      0xffe00fff 0xfbfcff00  /* pioE */
+                                     >;
 
-                       pioC: gpio@fffff600 {
-                               compatible = "atmel,at91rm9200-gpio";
-                               reg = <0xfffff600 0x100>;
-                               interrupts = <4 4 1>;
-                               #gpio-cells = <2>;
-                               gpio-controller;
-                               interrupt-controller;
-                               #interrupt-cells = <2>;
-                       };
+                               /* shared pinctrl settings */
+                               dbgu {
+                                       pinctrl_dbgu: dbgu-0 {
+                                               atmel,pins =
+                                                       <2 30 0x1 0x0   /* PC30 periph A */
+                                                        2 31 0x1 0x1>; /* PC31 periph with pullup */
+                                       };
+                               };
 
-                       pioD: gpio@fffff800 {
-                               compatible = "atmel,at91rm9200-gpio";
-                               reg = <0xfffff800 0x100>;
-                               interrupts = <4 4 1>;
-                               #gpio-cells = <2>;
-                               gpio-controller;
-                               interrupt-controller;
-                               #interrupt-cells = <2>;
-                       };
+                               uart0 {
+                                       pinctrl_uart0: uart0-0 {
+                                               atmel,pins =
+                                                       <0 26 0x1 0x1   /* PA26 periph A with pullup */
+                                                        0 27 0x1 0x0>; /* PA27 periph A */
+                                       };
 
-                       pioE: gpio@fffffa00 {
-                               compatible = "atmel,at91rm9200-gpio";
-                               reg = <0xfffffa00 0x100>;
-                               interrupts = <4 4 1>;
-                               #gpio-cells = <2>;
-                               gpio-controller;
-                               interrupt-controller;
-                               #interrupt-cells = <2>;
+                                       pinctrl_uart0_rts_cts: uart0_rts_cts-0 {
+                                               atmel,pins =
+                                                       <0 28 0x1 0x0   /* PA28 periph A */
+                                                        0 29 0x1 0x0>; /* PA29 periph A */
+                                       };
+                               };
+
+                               uart1 {
+                                       pinctrl_uart1: uart1-0 {
+                                               atmel,pins =
+                                                       <3 0 0x1 0x1    /* PD0 periph A with pullup */
+                                                        3 1 0x1 0x0>;  /* PD1 periph A */
+                                       };
+
+                                       pinctrl_uart1_rts_cts: uart1_rts_cts-0 {
+                                               atmel,pins =
+                                                       <3 7 0x2 0x0    /* PD7 periph B */
+                                                        3 8 0x2 0x0>;  /* PD8 periph B */
+                                       };
+                               };
+
+                               uart2 {
+                                       pinctrl_uart2: uart2-0 {
+                                               atmel,pins =
+                                                       <3 2 0x1 0x1    /* PD2 periph A with pullup */
+                                                        3 3 0x1 0x0>;  /* PD3 periph A */
+                                       };
+
+                                       pinctrl_uart2_rts_cts: uart2_rts_cts-0 {
+                                               atmel,pins =
+                                                       <3 5 0x2 0x0    /* PD5 periph B */
+                                                        4 6 0x2 0x0>;  /* PD6 periph B */
+                                       };
+                               };
+
+                               nand {
+                                       pinctrl_nand: nand-0 {
+                                               atmel,pins =
+                                                       <0 22 0x0 0x1   /* PA22 gpio RDY pin pull_up*/
+                                                        3 15 0x0 0x1>; /* PD15 gpio enable pin pull_up */
+                                       };
+                               };
+
+                               pioA: gpio@fffff200 {
+                                       compatible = "atmel,at91rm9200-gpio";
+                                       reg = <0xfffff200 0x200>;
+                                       interrupts = <2 4 1>;
+                                       #gpio-cells = <2>;
+                                       gpio-controller;
+                                       interrupt-controller;
+                                       #interrupt-cells = <2>;
+                               };
+
+                               pioB: gpio@fffff400 {
+                                       compatible = "atmel,at91rm9200-gpio";
+                                       reg = <0xfffff400 0x200>;
+                                       interrupts = <3 4 1>;
+                                       #gpio-cells = <2>;
+                                       gpio-controller;
+                                       interrupt-controller;
+                                       #interrupt-cells = <2>;
+                               };
+
+                               pioC: gpio@fffff600 {
+                                       compatible = "atmel,at91rm9200-gpio";
+                                       reg = <0xfffff600 0x200>;
+                                       interrupts = <4 4 1>;
+                                       #gpio-cells = <2>;
+                                       gpio-controller;
+                                       interrupt-controller;
+                                       #interrupt-cells = <2>;
+                               };
+
+                               pioD: gpio@fffff800 {
+                                       compatible = "atmel,at91rm9200-gpio";
+                                       reg = <0xfffff800 0x200>;
+                                       interrupts = <4 4 1>;
+                                       #gpio-cells = <2>;
+                                       gpio-controller;
+                                       interrupt-controller;
+                                       #interrupt-cells = <2>;
+                               };
+
+                               pioE: gpio@fffffa00 {
+                                       compatible = "atmel,at91rm9200-gpio";
+                                       reg = <0xfffffa00 0x200>;
+                                       interrupts = <4 4 1>;
+                                       #gpio-cells = <2>;
+                                       gpio-controller;
+                                       interrupt-controller;
+                                       #interrupt-cells = <2>;
+                               };
                        };
 
                        dbgu: serial@ffffee00 {
                                compatible = "atmel,at91sam9260-usart";
                                reg = <0xffffee00 0x200>;
                                interrupts = <1 4 7>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_dbgu>;
                                status = "disabled";
                        };
 
                                interrupts = <7 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_uart0>;
                                status = "disabled";
                        };
 
                                interrupts = <8 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_uart1>;
                                status = "disabled";
                        };
 
                                interrupts = <9 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_uart2>;
                                status = "disabled";
                        };
 
                              >;
                        atmel,nand-addr-offset = <21>;
                        atmel,nand-cmd-offset = <22>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&pinctrl_nand>;
                        gpios = <&pioA 22 0
                                 &pioD 15 0
                                 0
index f86ac4b609fc108c0f1ad757c4a254dc6aec18d3..7cfe9d521f1262d8e7c6d13873e792c594f88858 100644 (file)
@@ -38,6 +38,7 @@
                        };
 
                        usart0: serial@fff8c000 {
+                               pinctrl-0 = <&pinctrl_uart0 &pinctrl_uart0_rts_cts>;
                                status = "okay";
                        };
 
diff --git a/arch/arm/boot/dts/at91sam9g15.dtsi b/arch/arm/boot/dts/at91sam9g15.dtsi
new file mode 100644 (file)
index 0000000..fbe7a70
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * at91sam9g15.dtsi - Device Tree Include file for AT91SAM9G15 SoC
+ *
+ * Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * Licensed under GPLv2.
+ */
+
+/include/ "at91sam9x5.dtsi"
+
+/ {
+       model = "Atmel AT91SAM9G15 SoC";
+       compatible = "atmel, at91sam9g15, atmel,at91sam9x5";
+
+       ahb {
+               apb {
+                       pinctrl@fffff400 {
+                               atmel,mux-mask = <
+                                     /*    A         B          C     */
+                                      0xffffffff 0xffe0399f 0x00000000  /* pioA */
+                                      0x00040000 0x00047e3f 0x00000000  /* pioB */
+                                      0xfdffffff 0x00000000 0xb83fffff  /* pioC */
+                                      0x003fffff 0x003f8000 0x00000000  /* pioD */
+                                     >;
+                       };
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/at91sam9g15ek.dts b/arch/arm/boot/dts/at91sam9g15ek.dts
new file mode 100644 (file)
index 0000000..86dd3f6
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * at91sam9g15ek.dts - Device Tree file for AT91SAM9G15-EK board
+ *
+ *  Copyright (C) 2012 Atmel,
+ *                2012 Nicolas Ferre <nicolas.ferre@atmel.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+/dts-v1/;
+/include/ "at91sam9g15.dtsi"
+/include/ "at91sam9x5ek.dtsi"
+
+/ {
+       model = "Atmel AT91SAM9G25-EK";
+       compatible = "atmel,at91sam9g15ek", "atmel,at91sam9x5ek", "atmel,at91sam9x5", "atmel,at91sam9";
+};
index b06c0db273b1fff820543d692b2a0470efe6b8f2..e33ab0a88d043abd9ef5a671eaa2ed56c37aac36 100644 (file)
                        };
 
                        usart0: serial@fffb0000 {
+                               pinctrl-0 =
+                                       <&pinctrl_uart0
+                                        &pinctrl_uart0_rts_cts
+                                        &pinctrl_uart0_dtr_dsr
+                                        &pinctrl_uart0_dcd
+                                        &pinctrl_uart0_ri>;
                                status = "okay";
                        };
 
diff --git a/arch/arm/boot/dts/at91sam9g25.dtsi b/arch/arm/boot/dts/at91sam9g25.dtsi
new file mode 100644 (file)
index 0000000..05a718f
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * at91sam9g25.dtsi - Device Tree Include file for AT91SAM9G25 SoC
+ *
+ * Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * Licensed under GPLv2.
+ */
+
+/include/ "at91sam9x5.dtsi"
+
+/ {
+       model = "Atmel AT91SAM9G25 SoC";
+       compatible = "atmel, at91sam9g25, atmel,at91sam9x5";
+
+       ahb {
+               apb {
+                       pinctrl@fffff400 {
+                               atmel,mux-mask = <
+                                     /*    A         B          C     */
+                                      0xffffffff 0xffe0399f 0xc000001c  /* pioA */
+                                      0x0007ffff 0x8000fe3f 0x00000000  /* pioB */
+                                      0x80000000 0x07c0ffff 0xb83fffff  /* pioC */
+                                      0x003fffff 0x003f8000 0x00000000  /* pioD */
+                                     >;
+                       };
+               };
+       };
+};
index 877c08f06763c643362eb41b8ebd058ac85abf7d..c5ab16fba059421730a212593a69ae6cd47acddc 100644 (file)
@@ -7,55 +7,10 @@
  * Licensed under GPLv2 or later.
  */
 /dts-v1/;
-/include/ "at91sam9x5.dtsi"
-/include/ "at91sam9x5cm.dtsi"
+/include/ "at91sam9g25.dtsi"
+/include/ "at91sam9x5ek.dtsi"
 
 / {
        model = "Atmel AT91SAM9G25-EK";
        compatible = "atmel,at91sam9g25ek", "atmel,at91sam9x5ek", "atmel,at91sam9x5", "atmel,at91sam9";
-
-       chosen {
-               bootargs = "console=ttyS0,115200 root=/dev/mtdblock1 rw rootfstype=ubifs ubi.mtd=1 root=ubi0:rootfs";
-       };
-
-       ahb {
-               apb {
-                       dbgu: serial@fffff200 {
-                               status = "okay";
-                       };
-
-                       usart0: serial@f801c000 {
-                               status = "okay";
-                       };
-
-                       macb0: ethernet@f802c000 {
-                               phy-mode = "rmii";
-                               status = "okay";
-                       };
-
-                       i2c0: i2c@f8010000 {
-                               status = "okay";
-                       };
-
-                       i2c1: i2c@f8014000 {
-                               status = "okay";
-                       };
-
-                       i2c2: i2c@f8018000 {
-                               status = "okay";
-                       };
-               };
-
-               usb0: ohci@00600000 {
-                       status = "okay";
-                       num-ports = <2>;
-                       atmel,vbus-gpio = <&pioD 19 1
-                                          &pioD 20 1
-                                         >;
-               };
-
-               usb1: ehci@00700000 {
-                       status = "okay";
-               };
-       };
 };
diff --git a/arch/arm/boot/dts/at91sam9g35.dtsi b/arch/arm/boot/dts/at91sam9g35.dtsi
new file mode 100644 (file)
index 0000000..f9d14a7
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * at91sam9g35.dtsi - Device Tree Include file for AT91SAM9G35 SoC
+ *
+ * Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * Licensed under GPLv2.
+ */
+
+/include/ "at91sam9x5.dtsi"
+
+/ {
+       model = "Atmel AT91SAM9G35 SoC";
+       compatible = "atmel, at91sam9g35, atmel,at91sam9x5";
+
+       ahb {
+               apb {
+                       pinctrl@fffff400 {
+                               atmel,mux-mask = <
+                                     /*    A         B          C     */
+                                      0xffffffff 0xffe0399f 0xc000000c  /* pioA */
+                                      0x000406ff 0x00047e3f 0x00000000  /* pioB */
+                                      0xfdffffff 0x00000000 0xb83fffff  /* pioC */
+                                      0x003fffff 0x003f8000 0x00000000  /* pioD */
+                                     >;
+                       };
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/at91sam9g35ek.dts b/arch/arm/boot/dts/at91sam9g35ek.dts
new file mode 100644 (file)
index 0000000..95944bd
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * at91sam9g35ek.dts - Device Tree file for AT91SAM9G35-EK board
+ *
+ *  Copyright (C) 2012 Atmel,
+ *                2012 Nicolas Ferre <nicolas.ferre@atmel.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+/dts-v1/;
+/include/ "at91sam9g35.dtsi"
+/include/ "at91sam9x5ek.dtsi"
+
+/ {
+       model = "Atmel AT91SAM9G35-EK";
+       compatible = "atmel,at91sam9g35ek", "atmel,at91sam9x5ek", "atmel,at91sam9x5", "atmel,at91sam9";
+};
index 3add030d61f8651fcf5a0476b11423897de71560..c340f6635d815bea339e196cd05c95195c6a2f63 100644 (file)
                                interrupts = <21 4 0>;
                        };
 
-                       pioA: gpio@fffff200 {
-                               compatible = "atmel,at91rm9200-gpio";
-                               reg = <0xfffff200 0x100>;
-                               interrupts = <2 4 1>;
-                               #gpio-cells = <2>;
-                               gpio-controller;
-                               interrupt-controller;
-                               #interrupt-cells = <2>;
-                       };
+                       pinctrl@fffff200 {
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               compatible = "atmel,at91rm9200-pinctrl", "simple-bus";
+                               ranges = <0xfffff200 0xfffff200 0xa00>;
+
+                               atmel,mux-mask = <
+                                     /*    A         B     */
+                                      0xffffffff 0xffc003ff  /* pioA */
+                                      0xffffffff 0x800f8f00  /* pioB */
+                                      0xffffffff 0x00000e00  /* pioC */
+                                      0xffffffff 0xff0c1381  /* pioD */
+                                      0xffffffff 0x81ffff81  /* pioE */
+                                     >;
+
+                               /* shared pinctrl settings */
+                               dbgu {
+                                       pinctrl_dbgu: dbgu-0 {
+                                               atmel,pins =
+                                                       <1 12 0x1 0x0   /* PB12 periph A */
+                                                        1 13 0x1 0x0>; /* PB13 periph A */
+                                       };
+                               };
 
-                       pioB: gpio@fffff400 {
-                               compatible = "atmel,at91rm9200-gpio";
-                               reg = <0xfffff400 0x100>;
-                               interrupts = <3 4 1>;
-                               #gpio-cells = <2>;
-                               gpio-controller;
-                               interrupt-controller;
-                               #interrupt-cells = <2>;
-                       };
+                               uart0 {
+                                       pinctrl_uart0: uart0-0 {
+                                               atmel,pins =
+                                                       <1 19 0x1 0x1   /* PB19 periph A with pullup */
+                                                        1 18 0x1 0x0>; /* PB18 periph A */
+                                       };
+
+                                       pinctrl_uart0_rts_cts: uart0_rts_cts-0 {
+                                               atmel,pins =
+                                                       <1 17 0x2 0x0   /* PB17 periph B */
+                                                        1 15 0x2 0x0>; /* PB15 periph B */
+                                       };
+                               };
 
-                       pioC: gpio@fffff600 {
-                               compatible = "atmel,at91rm9200-gpio";
-                               reg = <0xfffff600 0x100>;
-                               interrupts = <4 4 1>;
-                               #gpio-cells = <2>;
-                               gpio-controller;
-                               interrupt-controller;
-                               #interrupt-cells = <2>;
-                       };
+                               uart1 {
+                                       pinctrl_uart1: uart1-0 {
+                                               atmel,pins =
+                                                       <1 4 0x1 0x1    /* PB4 periph A with pullup */
+                                                        1 5 0x1 0x0>;  /* PB5 periph A */
+                                       };
+
+                                       pinctrl_uart1_rts_cts: uart1_rts_cts-0 {
+                                               atmel,pins =
+                                                       <3 16 0x1 0x0   /* PD16 periph A */
+                                                        3 17 0x1 0x0>; /* PD17 periph A */
+                                       };
+                               };
 
-                       pioD: gpio@fffff800 {
-                               compatible = "atmel,at91rm9200-gpio";
-                               reg = <0xfffff800 0x100>;
-                               interrupts = <5 4 1>;
-                               #gpio-cells = <2>;
-                               gpio-controller;
-                               interrupt-controller;
-                               #interrupt-cells = <2>;
-                       };
+                               uart2 {
+                                       pinctrl_uart2: uart2-0 {
+                                               atmel,pins =
+                                                       <1 6 0x1 0x1    /* PB6 periph A with pullup */
+                                                        1 7 0x1 0x0>;  /* PB7 periph A */
+                                       };
+
+                                       pinctrl_uart2_rts_cts: uart2_rts_cts-0 {
+                                               atmel,pins =
+                                                       <2 9 0x2 0x0    /* PC9 periph B */
+                                                        2 11 0x2 0x0>; /* PC11 periph B */
+                                       };
+                               };
 
-                       pioE: gpio@fffffa00 {
-                               compatible = "atmel,at91rm9200-gpio";
-                               reg = <0xfffffa00 0x100>;
-                               interrupts = <5 4 1>;
-                               #gpio-cells = <2>;
-                               gpio-controller;
-                               interrupt-controller;
-                               #interrupt-cells = <2>;
+                               uart3 {
+                                       pinctrl_uart3: uart3-0 {
+                                               atmel,pins =
+                                                       <1 8 0x1 0x1    /* PB9 periph A with pullup */
+                                                        1 9 0x1 0x0>;  /* PB8 periph A */
+                                       };
+
+                                       pinctrl_uart3_rts_cts: uart3_rts_cts-0 {
+                                               atmel,pins =
+                                                       <0 23 0x2 0x0   /* PA23 periph B */
+                                                        0 24 0x2 0x0>; /* PA24 periph B */
+                                       };
+                               };
+
+                               nand {
+                                       pinctrl_nand: nand-0 {
+                                               atmel,pins =
+                                                       <2 8 0x0 0x1    /* PC8 gpio RDY pin pull_up*/
+                                                        2 14 0x0 0x1>; /* PC14 gpio enable pin pull_up */
+                                       };
+                               };
+
+                               pioA: gpio@fffff200 {
+                                       compatible = "atmel,at91rm9200-gpio";
+                                       reg = <0xfffff200 0x200>;
+                                       interrupts = <2 4 1>;
+                                       #gpio-cells = <2>;
+                                       gpio-controller;
+                                       interrupt-controller;
+                                       #interrupt-cells = <2>;
+                               };
+
+                               pioB: gpio@fffff400 {
+                                       compatible = "atmel,at91rm9200-gpio";
+                                       reg = <0xfffff400 0x200>;
+                                       interrupts = <3 4 1>;
+                                       #gpio-cells = <2>;
+                                       gpio-controller;
+                                       interrupt-controller;
+                                       #interrupt-cells = <2>;
+                               };
+
+                               pioC: gpio@fffff600 {
+                                       compatible = "atmel,at91rm9200-gpio";
+                                       reg = <0xfffff600 0x200>;
+                                       interrupts = <4 4 1>;
+                                       #gpio-cells = <2>;
+                                       gpio-controller;
+                                       interrupt-controller;
+                                       #interrupt-cells = <2>;
+                               };
+
+                               pioD: gpio@fffff800 {
+                                       compatible = "atmel,at91rm9200-gpio";
+                                       reg = <0xfffff800 0x200>;
+                                       interrupts = <5 4 1>;
+                                       #gpio-cells = <2>;
+                                       gpio-controller;
+                                       interrupt-controller;
+                                       #interrupt-cells = <2>;
+                               };
+
+                               pioE: gpio@fffffa00 {
+                                       compatible = "atmel,at91rm9200-gpio";
+                                       reg = <0xfffffa00 0x200>;
+                                       interrupts = <5 4 1>;
+                                       #gpio-cells = <2>;
+                                       gpio-controller;
+                                       interrupt-controller;
+                                       #interrupt-cells = <2>;
+                               };
                        };
 
                        dbgu: serial@ffffee00 {
                                compatible = "atmel,at91sam9260-usart";
                                reg = <0xffffee00 0x200>;
                                interrupts = <1 4 7>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_dbgu>;
                                status = "disabled";
                        };
 
                                interrupts = <7 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_uart0>;
                                status = "disabled";
                        };
 
                                interrupts = <8 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_uart1>;
                                status = "disabled";
                        };
 
                                interrupts = <9 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_uart2>;
                                status = "disabled";
                        };
 
                                interrupts = <10 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_uart3>;
                                status = "disabled";
                        };
 
                              >;
                        atmel,nand-addr-offset = <21>;
                        atmel,nand-cmd-offset = <22>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&pinctrl_nand>;
                        gpios = <&pioC 8 0
                                 &pioC 14 0
                                 0
index 15e1dd43f625aee627438c302e9a4a13f7002031..6aa28b941907bc9b5185374111e6580eac579e25 100644 (file)
@@ -39,6 +39,7 @@
                        };
 
                        usart1: serial@fff90000 {
+                               pinctrl-0 = <&pinctrl_uart0 &pinctrl_uart1_rts_cts>;
                                status = "okay";
                        };
 
index 82508d68aa7edb0cdc98c5245d7872d47720dfd9..7b644c5b0bed7b2c65f0e71e4a373b11d52790f4 100644 (file)
                                interrupts = <20 4 0>;
                        };
 
-                       pioA: gpio@fffff400 {
-                               compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
-                               reg = <0xfffff400 0x100>;
-                               interrupts = <2 4 1>;
-                               #gpio-cells = <2>;
-                               gpio-controller;
-                               interrupt-controller;
-                               #interrupt-cells = <2>;
-                       };
+                       pinctrl@fffff400 {
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               compatible = "atmel,at91sam9x5-pinctrl", "atmel,at91rm9200-pinctrl", "simple-bus";
+                               ranges = <0xfffff400 0xfffff400 0x800>;
 
-                       pioB: gpio@fffff600 {
-                               compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
-                               reg = <0xfffff600 0x100>;
-                               interrupts = <2 4 1>;
-                               #gpio-cells = <2>;
-                               gpio-controller;
-                               interrupt-controller;
-                               #interrupt-cells = <2>;
-                       };
+                               atmel,mux-mask = <
+                                     /*    A         B          C     */
+                                      0xffffffff 0xffe07983 0x00000000  /* pioA */
+                                      0x00040000 0x00047e0f 0x00000000  /* pioB */
+                                      0xfdffffff 0x07c00000 0xb83fffff  /* pioC */
+                                      0x003fffff 0x003f8000 0x00000000  /* pioD */
+                                     >;
 
-                       pioC: gpio@fffff800 {
-                               compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
-                               reg = <0xfffff800 0x100>;
-                               interrupts = <3 4 1>;
-                               #gpio-cells = <2>;
-                               gpio-controller;
-                               interrupt-controller;
-                               #interrupt-cells = <2>;
-                       };
+                               /* shared pinctrl settings */
+                               dbgu {
+                                       pinctrl_dbgu: dbgu-0 {
+                                               atmel,pins =
+                                                       <0 9 0x1 0x0    /* PA9 periph A */
+                                                        0 10 0x1 0x1>; /* PA10 periph with pullup */
+                                       };
+                               };
 
-                       pioD: gpio@fffffa00 {
-                               compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
-                               reg = <0xfffffa00 0x100>;
-                               interrupts = <3 4 1>;
-                               #gpio-cells = <2>;
-                               gpio-controller;
-                               interrupt-controller;
-                               #interrupt-cells = <2>;
+                               uart0 {
+                                       pinctrl_uart0: uart0-0 {
+                                               atmel,pins =
+                                                       <0 1 0x1 0x1    /* PA1 periph A with pullup */
+                                                        0 0 0x1 0x0>;  /* PA0 periph A */
+                                       };
+
+                                       pinctrl_uart0_rts_cts: uart0_rts_cts-0 {
+                                               atmel,pins =
+                                                       <0 2 0x1 0x0    /* PA2 periph A */
+                                                        0 3 0x1 0x0>;  /* PA3 periph A */
+                                       };
+                               };
+
+                               uart1 {
+                                       pinctrl_uart1: uart1-0 {
+                                               atmel,pins =
+                                                       <0 6 0x1 0x1    /* PA6 periph A with pullup */
+                                                        0 5 0x1 0x0>;  /* PA5 periph A */
+                                       };
+                               };
+
+                               uart2 {
+                                       pinctrl_uart2: uart2-0 {
+                                               atmel,pins =
+                                                       <0 8 0x1 0x1    /* PA8 periph A with pullup */
+                                                        0 7 0x1 0x0>;  /* PA7 periph A */
+                                       };
+
+                                       pinctrl_uart2_rts_cts: uart2_rts_cts-0 {
+                                               atmel,pins =
+                                                       <1 0 0x2 0x0    /* PB0 periph B */
+                                                        1 1 0x2 0x0>;  /* PB1 periph B */
+                                       };
+                               };
+
+                               uart3 {
+                                       pinctrl_uart3: uart3-0 {
+                                               atmel,pins =
+                                                       <2 23 0x2 0x1   /* PC23 periph B with pullup */
+                                                        2 22 0x2 0x0>; /* PC22 periph B */
+                                       };
+
+                                       pinctrl_uart3_rts_cts: uart3_rts_cts-0 {
+                                               atmel,pins =
+                                                       <2 24 0x2 0x0   /* PC24 periph B */
+                                                        2 25 0x2 0x0>; /* PC25 periph B */
+                                       };
+                               };
+
+                               usart0 {
+                                       pinctrl_usart0: usart0-0 {
+                                               atmel,pins =
+                                                       <2 9 0x3 0x1    /* PC9 periph C with pullup */
+                                                        2 8 0x3 0x0>;  /* PC8 periph C */
+                                       };
+                               };
+
+                               usart1 {
+                                       pinctrl_usart1: usart1-0 {
+                                               atmel,pins =
+                                                       <2 16 0x3 0x1   /* PC17 periph C with pullup */
+                                                        2 17 0x3 0x0>; /* PC16 periph C */
+                                       };
+                               };
+
+                               nand {
+                                       pinctrl_nand: nand-0 {
+                                               atmel,pins =
+                                                       <3 5 0x0 0x1    /* PD5 gpio RDY pin pull_up*/
+                                                        3 4 0x0 0x1>;  /* PD4 gpio enable pin pull_up */
+                                       };
+                               };
+
+                               pioA: gpio@fffff400 {
+                                       compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
+                                       reg = <0xfffff400 0x200>;
+                                       interrupts = <2 4 1>;
+                                       #gpio-cells = <2>;
+                                       gpio-controller;
+                                       interrupt-controller;
+                                       #interrupt-cells = <2>;
+                               };
+
+                               pioB: gpio@fffff600 {
+                                       compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
+                                       reg = <0xfffff600 0x200>;
+                                       interrupts = <2 4 1>;
+                                       #gpio-cells = <2>;
+                                       gpio-controller;
+                                       interrupt-controller;
+                                       #interrupt-cells = <2>;
+                               };
+
+                               pioC: gpio@fffff800 {
+                                       compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
+                                       reg = <0xfffff800 0x200>;
+                                       interrupts = <3 4 1>;
+                                       #gpio-cells = <2>;
+                                       gpio-controller;
+                                       interrupt-controller;
+                                       #interrupt-cells = <2>;
+                               };
+
+                               pioD: gpio@fffffa00 {
+                                       compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
+                                       reg = <0xfffffa00 0x200>;
+                                       interrupts = <3 4 1>;
+                                       #gpio-cells = <2>;
+                                       gpio-controller;
+                                       interrupt-controller;
+                                       #interrupt-cells = <2>;
+                               };
                        };
 
                        dbgu: serial@fffff200 {
                                compatible = "atmel,at91sam9260-usart";
                                reg = <0xfffff200 0x200>;
                                interrupts = <1 4 7>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_dbgu>;
                                status = "disabled";
                        };
 
                                interrupts = <5 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_uart0>;
                                status = "disabled";
                        };
 
                                interrupts = <6 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_uart1>;
                                status = "disabled";
                        };
 
                                interrupts = <7 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_uart2>;
                                status = "disabled";
                        };
 
                                interrupts = <8 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_uart3>;
                                status = "disabled";
                        };
 
                               >;
                        atmel,nand-addr-offset = <21>;
                        atmel,nand-cmd-offset = <22>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&pinctrl_nand>;
                        gpios = <&pioD 5 0
                                 &pioD 4 0
                                 0
diff --git a/arch/arm/boot/dts/at91sam9x25.dtsi b/arch/arm/boot/dts/at91sam9x25.dtsi
new file mode 100644 (file)
index 0000000..956c65f
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * at91sam9x25.dtsi - Device Tree Include file for AT91SAM9X25 SoC
+ *
+ * Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * Licensed under GPLv2.
+ */
+
+/include/ "at91sam9x5.dtsi"
+
+/ {
+       model = "Atmel AT91SAM9X25 SoC";
+       compatible = "atmel, at91sam9x25, atmel,at91sam9x5";
+
+       ahb {
+               apb {
+                       pinctrl@fffff400 {
+                               atmel,mux-mask = <
+                                     /*    A         B          C     */
+                                      0xffffffff 0xffe03fff 0xc000001c  /* pioA */
+                                      0x0007ffff 0x00047e3f 0x00000000  /* pioB */
+                                      0x80000000 0xfffd0000 0xb83fffff  /* pioC */
+                                      0x003fffff 0x003f8000 0x00000000  /* pioD */
+                                     >;
+                       };
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/at91sam9x25ek.dts b/arch/arm/boot/dts/at91sam9x25ek.dts
new file mode 100644 (file)
index 0000000..af907ea
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * at91sam9x25ek.dts - Device Tree file for AT91SAM9X25-EK board
+ *
+ *  Copyright (C) 2012 Atmel,
+ *                2012 Nicolas Ferre <nicolas.ferre@atmel.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+/dts-v1/;
+/include/ "at91sam9x25.dtsi"
+/include/ "at91sam9x5ek.dtsi"
+
+/ {
+       model = "Atmel AT91SAM9G25-EK";
+       compatible = "atmel,at91sam9x25ek", "atmel,at91sam9x5ek", "atmel,at91sam9x5", "atmel,at91sam9";
+};
diff --git a/arch/arm/boot/dts/at91sam9x35.dtsi b/arch/arm/boot/dts/at91sam9x35.dtsi
new file mode 100644 (file)
index 0000000..fb102d6
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * at91sam9x35.dtsi - Device Tree Include file for AT91SAM9X35 SoC
+ *
+ * Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * Licensed under GPLv2.
+ */
+
+/include/ "at91sam9x5.dtsi"
+
+/ {
+       model = "Atmel AT91SAM9X35 SoC";
+       compatible = "atmel, at91sam9x35, atmel,at91sam9x5";
+
+       ahb {
+               apb {
+                       pinctrl@fffff400 {
+                               atmel,mux-mask = <
+                                     /*    A         B          C     */
+                                      0xffffffff 0xffe03fff 0xc000000c  /* pioA */
+                                      0x000406ff 0x00047e3f 0x00000000  /* pioB */
+                                      0xfdffffff 0x00000000 0xb83fffff  /* pioC */
+                                      0x003fffff 0x003f8000 0x00000000  /* pioD */
+                                     >;
+                       };
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/at91sam9x35ek.dts b/arch/arm/boot/dts/at91sam9x35ek.dts
new file mode 100644 (file)
index 0000000..5ccb607
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * at91sam9x35ek.dts - Device Tree file for AT91SAM9X35-EK board
+ *
+ *  Copyright (C) 2012 Atmel,
+ *                2012 Nicolas Ferre <nicolas.ferre@atmel.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+/dts-v1/;
+/include/ "at91sam9x35.dtsi"
+/include/ "at91sam9x5ek.dtsi"
+
+/ {
+       model = "Atmel AT91SAM9X35-EK";
+       compatible = "atmel,at91sam9x35ek", "atmel,at91sam9x5ek", "atmel,at91sam9x5", "atmel,at91sam9";
+};
index 03fc136421c5e31b01649c9caacdaf134bef4560..6a40b777ea4cd1761cf3816f0030c966faffaae4 100644 (file)
                                interrupts = <21 4 0>;
                        };
 
-                       pioA: gpio@fffff400 {
-                               compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
-                               reg = <0xfffff400 0x100>;
-                               interrupts = <2 4 1>;
-                               #gpio-cells = <2>;
-                               gpio-controller;
-                               interrupt-controller;
-                               #interrupt-cells = <2>;
-                       };
+                       pinctrl@fffff400 {
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               compatible = "atmel,at91sam9x5-pinctrl", "atmel,at91rm9200-pinctrl", "simple-bus";
+                               ranges = <0xfffff400 0xfffff400 0x800>;
+
+                               /* shared pinctrl settings */
+                               dbgu {
+                                       pinctrl_dbgu: dbgu-0 {
+                                               atmel,pins =
+                                                       <0 9 0x1 0x0    /* PA9 periph A */
+                                                        0 10 0x1 0x1>; /* PA10 periph A with pullup */
+                                       };
+                               };
 
-                       pioB: gpio@fffff600 {
-                               compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
-                               reg = <0xfffff600 0x100>;
-                               interrupts = <2 4 1>;
-                               #gpio-cells = <2>;
-                               gpio-controller;
-                               interrupt-controller;
-                               #interrupt-cells = <2>;
-                       };
+                               uart0 {
+                                       pinctrl_uart0: uart0-0 {
+                                               atmel,pins =
+                                                       <0 0 0x1 0x1    /* PA0 periph A with pullup */
+                                                        0 1 0x1 0x0>;  /* PA1 periph A */
+                                       };
+
+                                       pinctrl_uart0_rts_cts: uart0_rts_cts-0 {
+                                               atmel,pins =
+                                                       <0 2 0x1 0x0    /* PA2 periph A */
+                                                        0 3 0x1 0x0>;  /* PA3 periph A */
+                                       };
+                               };
 
-                       pioC: gpio@fffff800 {
-                               compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
-                               reg = <0xfffff800 0x100>;
-                               interrupts = <3 4 1>;
-                               #gpio-cells = <2>;
-                               gpio-controller;
-                               interrupt-controller;
-                               #interrupt-cells = <2>;
-                       };
+                               uart1 {
+                                       pinctrl_uart1: uart1-0 {
+                                               atmel,pins =
+                                                       <0 5 0x1 0x1    /* PA5 periph A with pullup */
+                                                        0 6 0x1 0x0>;  /* PA6 periph A */
+                                       };
+
+                                       pinctrl_uart1_rts_cts: uart1_rts_cts-0 {
+                                               atmel,pins =
+                                                       <3 27 0x3 0x0   /* PC27 periph C */
+                                                        3 28 0x3 0x0>; /* PC28 periph C */
+                                       };
+                               };
 
-                       pioD: gpio@fffffa00 {
-                               compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
-                               reg = <0xfffffa00 0x100>;
-                               interrupts = <3 4 1>;
-                               #gpio-cells = <2>;
-                               gpio-controller;
-                               interrupt-controller;
-                               #interrupt-cells = <2>;
+                               uart2 {
+                                       pinctrl_uart2: uart2-0 {
+                                               atmel,pins =
+                                                       <0 7 0x1 0x1    /* PA7 periph A with pullup */
+                                                        0 8 0x1 0x0>;  /* PA8 periph A */
+                                       };
+
+                                       pinctrl_uart2_rts_cts: uart2_rts_cts-0 {
+                                               atmel,pins =
+                                                       <0 0 0x2 0x0    /* PB0 periph B */
+                                                        0 1 0x2 0x0>;  /* PB1 periph B */
+                                       };
+                               };
+
+                               uart3 {
+                                       pinctrl_uart3: uart3-0 {
+                                               atmel,pins =
+                                                       <3 23 0x2 0x1   /* PC22 periph B with pullup */
+                                                        3 23 0x2 0x0>; /* PC23 periph B */
+                                       };
+
+                                       pinctrl_uart3_rts_cts: uart3_rts_cts-0 {
+                                               atmel,pins =
+                                                       <3 24 0x2 0x0   /* PC24 periph B */
+                                                        3 25 0x2 0x0>; /* PC25 periph B */
+                                       };
+                               };
+
+                               usart0 {
+                                       pinctrl_usart0: usart0-0 {
+                                               atmel,pins =
+                                                       <3 8 0x3 0x0    /* PC8 periph C */
+                                                        3 9 0x3 0x1>;  /* PC9 periph C with pullup */
+                                       };
+                               };
+
+                               usart1 {
+                                       pinctrl_usart1: usart1-0 {
+                                               atmel,pins =
+                                                       <3 16 0x3 0x0   /* PC16 periph C */
+                                                        3 17 0x3 0x1>; /* PC17 periph C with pullup */
+                                       };
+                               };
+
+                               nand {
+                                       pinctrl_nand: nand-0 {
+                                               atmel,pins =
+                                                       <3 4 0x0 0x1    /* PD5 gpio RDY pin pull_up */
+                                                        3 5 0x0 0x1>;  /* PD4 gpio enable pin pull_up */
+                                       };
+                               };
+
+                               pioA: gpio@fffff400 {
+                                       compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
+                                       reg = <0xfffff400 0x200>;
+                                       interrupts = <2 4 1>;
+                                       #gpio-cells = <2>;
+                                       gpio-controller;
+                                       interrupt-controller;
+                                       #interrupt-cells = <2>;
+                               };
+
+                               pioB: gpio@fffff600 {
+                                       compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
+                                       reg = <0xfffff600 0x200>;
+                                       interrupts = <2 4 1>;
+                                       #gpio-cells = <2>;
+                                       gpio-controller;
+                                       #gpio-lines = <19>;
+                                       interrupt-controller;
+                                       #interrupt-cells = <2>;
+                               };
+
+                               pioC: gpio@fffff800 {
+                                       compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
+                                       reg = <0xfffff800 0x200>;
+                                       interrupts = <3 4 1>;
+                                       #gpio-cells = <2>;
+                                       gpio-controller;
+                                       interrupt-controller;
+                                       #interrupt-cells = <2>;
+                               };
+
+                               pioD: gpio@fffffa00 {
+                                       compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
+                                       reg = <0xfffffa00 0x200>;
+                                       interrupts = <3 4 1>;
+                                       #gpio-cells = <2>;
+                                       gpio-controller;
+                                       #gpio-lines = <22>;
+                                       interrupt-controller;
+                                       #interrupt-cells = <2>;
+                               };
                        };
 
                        dbgu: serial@fffff200 {
                                compatible = "atmel,at91sam9260-usart";
                                reg = <0xfffff200 0x200>;
                                interrupts = <1 4 7>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_dbgu>;
                                status = "disabled";
                        };
 
                                interrupts = <5 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_uart0>;
                                status = "disabled";
                        };
 
                                interrupts = <6 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_uart1>;
                                status = "disabled";
                        };
 
                                interrupts = <7 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_uart2>;
                                status = "disabled";
                        };
 
                              >;
                        atmel,nand-addr-offset = <21>;
                        atmel,nand-cmd-offset = <22>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&pinctrl_nand>;
                        gpios = <&pioD 5 0
                                 &pioD 4 0
                                 0
diff --git a/arch/arm/boot/dts/at91sam9x5ek.dtsi b/arch/arm/boot/dts/at91sam9x5ek.dtsi
new file mode 100644 (file)
index 0000000..cc9730c
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * at91sam9x5ek.dtsi - Device Tree file for AT91SAM9x5CM Base board
+ *
+ *  Copyright (C) 2012 Atmel,
+ *                2012 Nicolas Ferre <nicolas.ferre@atmel.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+/include/ "at91sam9x5cm.dtsi"
+
+/ {
+       model = "Atmel AT91SAM9X5-EK";
+       compatible = "atmel,at91sam9x5ek", "atmel,at91sam9x5", "atmel,at91sam9";
+
+       chosen {
+               bootargs = "128M console=ttyS0,115200 root=/dev/mtdblock1 rw rootfstype=ubifs ubi.mtd=1 root=ubi0:rootfs";
+       };
+
+       ahb {
+               apb {
+                       dbgu: serial@fffff200 {
+                               status = "okay";
+                       };
+
+                       usart0: serial@f801c000 {
+                               status = "okay";
+                       };
+
+                       macb0: ethernet@f802c000 {
+                               phy-mode = "rmii";
+                               status = "okay";
+                       };
+
+                       i2c0: i2c@f8010000 {
+                               status = "okay";
+                       };
+
+                       i2c1: i2c@f8014000 {
+                               status = "okay";
+                       };
+
+                       i2c2: i2c@f8018000 {
+                               status = "okay";
+                       };
+               };
+
+               usb0: ohci@00600000 {
+                       status = "okay";
+                       num-ports = <2>;
+                       atmel,vbus-gpio = <&pioD 19 1
+                                          &pioD 20 1
+                                         >;
+               };
+
+               usb1: ehci@00700000 {
+                       status = "okay";
+               };
+       };
+};
index 96fb824b5e6ecb3dd26481dcdbd3d67bb691772d..5a00022383e74d7e457c34be0331eb3edf7c0521 100644 (file)
@@ -4,21 +4,32 @@
        compatible = "marvell,dove";
        model = "Marvell Armada 88AP510 SoC";
 
-       interrupt-parent = <&intc>;
-
-       intc: interrupt-controller {
-               compatible = "marvell,orion-intc";
-               interrupt-controller;
-               #interrupt-cells = <1>;
-               reg = <0xf1020204 0x04>,
-                     <0xf1020214 0x04>;
-       };
-
-       mbus@f1000000 {
+       soc@f1000000 {
                compatible = "simple-bus";
-               ranges = <0 0xf1000000 0x4000000>;
                #address-cells = <1>;
                #size-cells = <1>;
+               interrupt-parent = <&intc>;
+
+               ranges = <0xc8000000 0xc8000000 0x0100000   /* CESA SRAM   1M */
+                         0xe0000000 0xe0000000 0x8000000   /* PCIe0 Mem 128M */
+                         0xe8000000 0xe8000000 0x8000000   /* PCIe1 Mem 128M */
+                         0xf0000000 0xf0000000 0x0100000   /* ScratchPad  1M */
+                         0x00000000 0xf1000000 0x1000000   /* SB/NB regs 16M */
+                         0xf2000000 0xf2000000 0x0100000   /* PCIe0 I/O   1M */
+                         0xf2100000 0xf2100000 0x0100000   /* PCIe0 I/O   1M */
+                         0xf8000000 0xf8000000 0x8000000>; /* BootROM   128M */
+
+               l2: l2-cache {
+                       compatible = "marvell,tauros2-cache";
+                       marvell,tauros2-cache-features = <0>;
+               };
+
+               intc: interrupt-controller {
+                       compatible = "marvell,orion-intc";
+                       interrupt-controller;
+                       #interrupt-cells = <1>;
+                       reg = <0x20204 0x04>, <0x20214 0x04>;
+               };
 
                uart0: serial@12000 {
                        compatible = "ns16550a";
                        status = "disabled";
                };
 
-               wdt: wdt@20300 {
-                       compatible = "marvell,orion-wdt";
-                       reg = <0x20300 0x28>;
-               };
-
                gpio0: gpio@d0400 {
                        compatible = "marvell,orion-gpio";
                        #gpio-cells = <2>;
                        nr-ports = <1>;
                        status = "disabled";
                };
+
+               crypto: crypto@30000 {
+                       compatible = "marvell,orion-crypto";
+                       reg = <0x30000 0x10000>,
+                             <0xc8000000 0x800>;
+                       reg-names = "regs", "sram";
+                       interrupts = <31>;
+                       status = "okay";
+               };
        };
 };
index 3e68f52e8454431d90c5bd1d47de5b791ce56b2e..f16c99f2f0fc33232a81b724e845f1bad71f2968 100644 (file)
                status = "okay";
        };
 
+       serial@13800000 {
+               status = "okay";
+       };
+
+       serial@13810000 {
+               status = "okay";
+       };
+
+       serial@13820000 {
+               status = "okay";
+       };
+
+       serial@13830000 {
+               status = "okay";
+       };
+
        gpio_keys {
                compatible = "gpio-keys";
                #address-cells = <1>;
index b12cf272ad0deb82c0c856de71338dd8242944e9..6a4a1a04221c316b2b4ca9ab95f2179b17bbb7a4 100644 (file)
 
 / {
        pinctrl@11400000 {
+               gpa0: gpa0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpa1: gpa1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpb: gpb {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpc0: gpc0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpc1: gpc1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpd0: gpd0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpd1: gpd1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpe0: gpe0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpe1: gpe1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpe2: gpe2 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpe3: gpe3 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpe4: gpe4 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpf0: gpf0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpf1: gpf1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpf2: gpf2 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpf3: gpf3 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
                uart0_data: uart0-data {
                        samsung,pins = "gpa0-0", "gpa0-1";
                        samsung,pin-function = <0x2>;
        };
 
        pinctrl@11000000 {
+               gpj0: gpj0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpj1: gpj1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpk0: gpk0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpk1: gpk1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpk2: gpk2 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpk3: gpk3 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpl0: gpl0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpl1: gpl1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpl2: gpl2 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpy0: gpy0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpy1: gpy1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpy2: gpy2 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpy3: gpy3 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpy4: gpy4 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpy5: gpy5 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpy6: gpy6 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpx0: gpx0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       interrupt-parent = <&gic>;
+                       interrupts = <0 16 0>, <0 17 0>, <0 18 0>, <0 19 0>,
+                                    <0 20 0>, <0 21 0>, <0 22 0>, <0 23 0>;
+                       #interrupt-cells = <2>;
+               };
+
+               gpx1: gpx1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       interrupt-parent = <&gic>;
+                       interrupts = <0 24 0>, <0 25 0>, <0 26 0>, <0 27 0>,
+                                    <0 28 0>, <0 29 0>, <0 30 0>, <0 31 0>;
+                       #interrupt-cells = <2>;
+               };
+
+               gpx2: gpx2 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpx3: gpx3 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
                sd0_clk: sd0-clk {
                        samsung,pins = "gpk0-0";
                        samsung,pin-function = <2>;
        };
 
        pinctrl@03860000 {
+               gpz: gpz {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
                i2s0_bus: i2s0-bus {
                        samsung,pins = "gpz-0", "gpz-1", "gpz-2", "gpz-3",
                                        "gpz-4", "gpz-5", "gpz-6";
index 63610c3ba3afbeffbeee894d2ea75e3b8ed24709..9b23a8255e39a148eecdd18e04391f4a2f6529f0 100644 (file)
                status = "okay";
        };
 
+       serial@13800000 {
+               status = "okay";
+       };
+
+       serial@13810000 {
+               status = "okay";
+       };
+
+       serial@13820000 {
+               status = "okay";
+       };
+
+       serial@13830000 {
+               status = "okay";
+       };
+
        keypad@100A0000 {
                samsung,keypad-num-rows = <2>;
                samsung,keypad-num-columns = <8>;
index 73567b843e72ae28e9ba4e721c8607a6135bf288..a21511c140712e24c4759293ac66248bbb8ae309 100644 (file)
        compatible = "samsung,trats", "samsung,exynos4210";
 
        memory {
-               reg =  <0x40000000 0x20000000
-                       0x60000000 0x20000000>;
+               reg =  <0x40000000 0x10000000
+                       0x50000000 0x10000000
+                       0x60000000 0x10000000
+                       0x70000000 0x10000000>;
        };
 
        chosen {
index 214c557eda7f7119584df481bde074c43a3611d4..d877dbe7ac0e767c020e2b8bf63ebe7566a8aa65 100644 (file)
                compatible = "samsung,pinctrl-exynos4210";
                reg = <0x11400000 0x1000>;
                interrupts = <0 47 0>;
-               interrupt-controller;
-               #interrupt-cells = <2>;
        };
 
        pinctrl_1: pinctrl@11000000 {
                compatible = "samsung,pinctrl-exynos4210";
                reg = <0x11000000 0x1000>;
                interrupts = <0 46 0>;
-               interrupt-controller;
-               #interrupt-cells = <2>;
 
                wakup_eint: wakeup-interrupt-controller {
                        compatible = "samsung,exynos4210-wakeup-eint";
                        interrupt-parent = <&gic>;
-                       interrupt-controller;
-                       #interrupt-cells = <2>;
-                       interrupts = <0 16 0>, <0 17 0>, <0 18 0>, <0 19 0>,
-                                    <0 20 0>, <0 21 0>, <0 22 0>, <0 23 0>,
-                                    <0 24 0>, <0 25 0>, <0 26 0>, <0 27 0>,
-                                    <0 28 0>, <0 29 0>, <0 30 0>, <0 31 0>,
-                                    <0 32 0>;
+                       interrupts = <0 32 0>;
                };
        };
 
                compatible = "samsung,pinctrl-exynos4210";
                reg = <0x03860000 0x1000>;
        };
-
-       gpio-controllers {
-               #address-cells = <1>;
-               #size-cells = <1>;
-               gpio-controller;
-               ranges;
-
-               gpa0: gpio-controller@11400000 {
-                       compatible = "samsung,exynos4-gpio";
-                       reg = <0x11400000 0x20>;
-                       #gpio-cells = <4>;
-               };
-
-               gpa1: gpio-controller@11400020 {
-                       compatible = "samsung,exynos4-gpio";
-                       reg = <0x11400020 0x20>;
-                       #gpio-cells = <4>;
-               };
-
-               gpb: gpio-controller@11400040 {
-                       compatible = "samsung,exynos4-gpio";
-                       reg = <0x11400040 0x20>;
-                       #gpio-cells = <4>;
-               };
-
-               gpc0: gpio-controller@11400060 {
-                       compatible = "samsung,exynos4-gpio";
-                       reg = <0x11400060 0x20>;
-                       #gpio-cells = <4>;
-               };
-
-               gpc1: gpio-controller@11400080 {
-                       compatible = "samsung,exynos4-gpio";
-                       reg = <0x11400080 0x20>;
-                       #gpio-cells = <4>;
-               };
-
-               gpd0: gpio-controller@114000A0 {
-                       compatible = "samsung,exynos4-gpio";
-                       reg = <0x114000A0 0x20>;
-                       #gpio-cells = <4>;
-               };
-
-               gpd1: gpio-controller@114000C0 {
-                       compatible = "samsung,exynos4-gpio";
-                       reg = <0x114000C0 0x20>;
-                       #gpio-cells = <4>;
-               };
-
-               gpe0: gpio-controller@114000E0 {
-                       compatible = "samsung,exynos4-gpio";
-                       reg = <0x114000E0 0x20>;
-                       #gpio-cells = <4>;
-               };
-
-               gpe1: gpio-controller@11400100 {
-                       compatible = "samsung,exynos4-gpio";
-                       reg = <0x11400100 0x20>;
-                       #gpio-cells = <4>;
-               };
-
-               gpe2: gpio-controller@11400120 {
-                       compatible = "samsung,exynos4-gpio";
-                       reg = <0x11400120 0x20>;
-                       #gpio-cells = <4>;
-               };
-
-               gpe3: gpio-controller@11400140 {
-                       compatible = "samsung,exynos4-gpio";
-                       reg = <0x11400140 0x20>;
-                       #gpio-cells = <4>;
-               };
-
-               gpe4: gpio-controller@11400160 {
-                       compatible = "samsung,exynos4-gpio";
-                       reg = <0x11400160 0x20>;
-                       #gpio-cells = <4>;
-               };
-
-               gpf0: gpio-controller@11400180 {
-                       compatible = "samsung,exynos4-gpio";
-                       reg = <0x11400180 0x20>;
-                       #gpio-cells = <4>;
-               };
-
-               gpf1: gpio-controller@114001A0 {
-                       compatible = "samsung,exynos4-gpio";
-                       reg = <0x114001A0 0x20>;
-                       #gpio-cells = <4>;
-               };
-
-               gpf2: gpio-controller@114001C0 {
-                       compatible = "samsung,exynos4-gpio";
-                       reg = <0x114001C0 0x20>;
-                       #gpio-cells = <4>;
-               };
-
-               gpf3: gpio-controller@114001E0 {
-                       compatible = "samsung,exynos4-gpio";
-                       reg = <0x114001E0 0x20>;
-                       #gpio-cells = <4>;
-               };
-
-               gpj0: gpio-controller@11000000 {
-                       compatible = "samsung,exynos4-gpio";
-                       reg = <0x11000000 0x20>;
-                       #gpio-cells = <4>;
-               };
-
-               gpj1: gpio-controller@11000020 {
-                       compatible = "samsung,exynos4-gpio";
-                       reg = <0x11000020 0x20>;
-                       #gpio-cells = <4>;
-               };
-
-               gpk0: gpio-controller@11000040 {
-                       compatible = "samsung,exynos4-gpio";
-                       reg = <0x11000040 0x20>;
-                       #gpio-cells = <4>;
-               };
-
-               gpk1: gpio-controller@11000060 {
-                       compatible = "samsung,exynos4-gpio";
-                       reg = <0x11000060 0x20>;
-                       #gpio-cells = <4>;
-               };
-
-               gpk2: gpio-controller@11000080 {
-                       compatible = "samsung,exynos4-gpio";
-                       reg = <0x11000080 0x20>;
-                       #gpio-cells = <4>;
-               };
-
-               gpk3: gpio-controller@110000A0 {
-                       compatible = "samsung,exynos4-gpio";
-                       reg = <0x110000A0 0x20>;
-                       #gpio-cells = <4>;
-               };
-
-               gpl0: gpio-controller@110000C0 {
-                       compatible = "samsung,exynos4-gpio";
-                       reg = <0x110000C0 0x20>;
-                       #gpio-cells = <4>;
-               };
-
-               gpl1: gpio-controller@110000E0 {
-                       compatible = "samsung,exynos4-gpio";
-                       reg = <0x110000E0 0x20>;
-                       #gpio-cells = <4>;
-               };
-
-               gpl2: gpio-controller@11000100 {
-                       compatible = "samsung,exynos4-gpio";
-                       reg = <0x11000100 0x20>;
-                       #gpio-cells = <4>;
-               };
-
-               gpy0: gpio-controller@11000120 {
-                       compatible = "samsung,exynos4-gpio";
-                       reg = <0x11000120 0x20>;
-                       #gpio-cells = <4>;
-               };
-
-               gpy1: gpio-controller@11000140 {
-                       compatible = "samsung,exynos4-gpio";
-                       reg = <0x11000140 0x20>;
-                       #gpio-cells = <4>;
-               };
-
-               gpy2: gpio-controller@11000160 {
-                       compatible = "samsung,exynos4-gpio";
-                       reg = <0x11000160 0x20>;
-                       #gpio-cells = <4>;
-               };
-
-               gpy3: gpio-controller@11000180 {
-                       compatible = "samsung,exynos4-gpio";
-                       reg = <0x11000180 0x20>;
-                       #gpio-cells = <4>;
-               };
-
-               gpy4: gpio-controller@110001A0 {
-                       compatible = "samsung,exynos4-gpio";
-                       reg = <0x110001A0 0x20>;
-                       #gpio-cells = <4>;
-               };
-
-               gpy5: gpio-controller@110001C0 {
-                       compatible = "samsung,exynos4-gpio";
-                       reg = <0x110001C0 0x20>;
-                       #gpio-cells = <4>;
-               };
-
-               gpy6: gpio-controller@110001E0 {
-                       compatible = "samsung,exynos4-gpio";
-                       reg = <0x110001E0 0x20>;
-                       #gpio-cells = <4>;
-               };
-
-               gpx0: gpio-controller@11000C00 {
-                       compatible = "samsung,exynos4-gpio";
-                       reg = <0x11000C00 0x20>;
-                       #gpio-cells = <4>;
-               };
-
-               gpx1: gpio-controller@11000C20 {
-                       compatible = "samsung,exynos4-gpio";
-                       reg = <0x11000C20 0x20>;
-                       #gpio-cells = <4>;
-               };
-
-               gpx2: gpio-controller@11000C40 {
-                       compatible = "samsung,exynos4-gpio";
-                       reg = <0x11000C40 0x20>;
-                       #gpio-cells = <4>;
-               };
-
-               gpx3: gpio-controller@11000C60 {
-                       compatible = "samsung,exynos4-gpio";
-                       reg = <0x11000C60 0x20>;
-                       #gpio-cells = <4>;
-               };
-
-               gpz: gpio-controller@03860000 {
-                       compatible = "samsung,exynos4-gpio";
-                       reg = <0x03860000 0x20>;
-                       #gpio-cells = <4>;
-               };
-       };
 };
index a352df403b7a5586ad1b2a47cb51c9eca0e89b0e..21d4ccdb0a5aa9a5067cc110588ebe98ba10d29e 100644 (file)
        spi_2: spi@12d40000 {
                status = "disabled";
        };
+
+       codec@11000000 {
+               samsung,mfc-r = <0x43000000 0x800000>;
+               samsung,mfc-l = <0x51000000 0x800000>;
+       };
 };
index dddfd6e444dcb1edbcb1d6f94617e6d29f87e5c7..49546bc43ec02be987d5fec4d145097088091e30 100644 (file)
                interrupts = <0 42 0>;
        };
 
+       codec@11000000 {
+               compatible = "samsung,mfc-v6";
+               reg = <0x11000000 0x10000>;
+               interrupts = <0 96 0>;
+       };
+
        rtc {
                compatible = "samsung,s3c6410-rtc";
                reg = <0x101E0000 0x100>;
index 3e54f1498841ca7ff3da6636cabd7d9274e3bd65..67d672792b0ddd1c8ea48bf5df4a309d48aa04ae 100644 (file)
                        i2c1: i2c@10012000 {
                                #address-cells = <1>;
                                #size-cells = <0>;
-                               compatible = "fsl,imx27-i2c", "fsl,imx1-i2c";
+                               compatible = "fsl,imx27-i2c", "fsl,imx21-i2c";
                                reg = <0x10012000 0x1000>;
                                interrupts = <12>;
                                status = "disabled";
                        i2c2: i2c@1001d000 {
                                #address-cells = <1>;
                                #size-cells = <0>;
-                               compatible = "fsl,imx27-i2c", "fsl,imx1-i2c";
+                               compatible = "fsl,imx27-i2c", "fsl,imx21-i2c";
                                reg = <0x1001d000 0x1000>;
                                interrupts = <1>;
                                status = "disabled";
index 75d069fcf8979d9684d2c979badaacdb3d3a7876..54aea74769a161d6fc6482ae171cd3fa9b62fdb7 100644 (file)
                        i2c@83fc4000 { /* I2C2 */
                                #address-cells = <1>;
                                #size-cells = <0>;
-                               compatible = "fsl,imx51-i2c", "fsl,imx1-i2c";
+                               compatible = "fsl,imx51-i2c", "fsl,imx21-i2c";
                                reg = <0x83fc4000 0x4000>;
                                interrupts = <63>;
                                status = "disabled";
                        i2c@83fc8000 { /* I2C1 */
                                #address-cells = <1>;
                                #size-cells = <0>;
-                               compatible = "fsl,imx51-i2c", "fsl,imx1-i2c";
+                               compatible = "fsl,imx51-i2c", "fsl,imx21-i2c";
                                reg = <0x83fc8000 0x4000>;
                                interrupts = <62>;
                                status = "disabled";
index 76ebb1ad2675334d38674fda586c9dee87d0cef8..caf09ff73f1005f14b753b06e02fffffdef95bf9 100644 (file)
                        i2c@53fec000 { /* I2C3 */
                                #address-cells = <1>;
                                #size-cells = <0>;
-                               compatible = "fsl,imx53-i2c", "fsl,imx1-i2c";
+                               compatible = "fsl,imx53-i2c", "fsl,imx21-i2c";
                                reg = <0x53fec000 0x4000>;
                                interrupts = <64>;
                                status = "disabled";
                        i2c@63fc4000 { /* I2C2 */
                                #address-cells = <1>;
                                #size-cells = <0>;
-                               compatible = "fsl,imx53-i2c", "fsl,imx1-i2c";
+                               compatible = "fsl,imx53-i2c", "fsl,imx21-i2c";
                                reg = <0x63fc4000 0x4000>;
                                interrupts = <63>;
                                status = "disabled";
                        i2c@63fc8000 { /* I2C1 */
                                #address-cells = <1>;
                                #size-cells = <0>;
-                               compatible = "fsl,imx53-i2c", "fsl,imx1-i2c";
+                               compatible = "fsl,imx53-i2c", "fsl,imx21-i2c";
                                reg = <0x63fc8000 0x4000>;
                                interrupts = <62>;
                                status = "disabled";
index 15df4c105e89c3b0ac20c7c0800307f4aa644a62..5bfa02a3f85cdd027d25d488513272ec4082579c 100644 (file)
                                        pinctrl_hog: hoggrp {
                                                fsl,pins = <
                                                        176  0x80000000 /* MX6Q_PAD_EIM_D25__GPIO_3_25 */
+                                               >;
+                                       };
+                               };
+
+                               arm2 {
+                                       pinctrl_usdhc3_arm2: usdhc3grp-arm2 {
+                                               fsl,pins = <
                                                        1363 0x80000000 /* MX6Q_PAD_NANDF_CS0__GPIO_6_11 */
                                                        1369 0x80000000 /* MX6Q_PAD_NANDF_CS1__GPIO_6_14 */
                                                >;
@@ -58,7 +65,8 @@
                                wp-gpios = <&gpio6 14 0>;
                                vmmc-supply = <&reg_3p3v>;
                                pinctrl-names = "default";
-                               pinctrl-0 = <&pinctrl_usdhc3_1>;
+                               pinctrl-0 = <&pinctrl_usdhc3_1
+                                            &pinctrl_usdhc3_arm2>;
                                status = "okay";
                        };
 
index f3990b04fecf4661216c9cf321dc817c72e1a0b7..f604a44a5c66c7225333e7c8abe17dd6d1a7623a 100644 (file)
                        i2c@021a0000 { /* I2C1 */
                                #address-cells = <1>;
                                #size-cells = <0>;
-                               compatible = "fsl,imx6q-i2c", "fsl,imx1-i2c";
+                               compatible = "fsl,imx6q-i2c", "fsl,imx21-i2c";
                                reg = <0x021a0000 0x4000>;
                                interrupts = <0 36 0x04>;
                                clocks = <&clks 125>;
                        i2c@021a4000 { /* I2C2 */
                                #address-cells = <1>;
                                #size-cells = <0>;
-                               compatible = "fsl,imx6q-i2c", "fsl,imx1-i2c";
+                               compatible = "fsl,imx6q-i2c", "fsl,imx21-i2c";
                                reg = <0x021a4000 0x4000>;
                                interrupts = <0 37 0x04>;
                                clocks = <&clks 126>;
                        i2c@021a8000 { /* I2C3 */
                                #address-cells = <1>;
                                #size-cells = <0>;
-                               compatible = "fsl,imx6q-i2c", "fsl,imx1-i2c";
+                               compatible = "fsl,imx6q-i2c", "fsl,imx21-i2c";
                                reg = <0x021a8000 0x4000>;
                                interrupts = <0 38 0x04>;
                                clocks = <&clks 127>;
index 8ac51c08269d303b77cd0560133e475dc7bfa927..8fea375c734d75e99ad06adac9f65f5413989285 100644 (file)
                #size-cells = <0>;
                button@1 {
                        label = "Function Button";
-                       linux,code = <132>;
+                       linux,code = <357>;
                        gpios = <&gpio1 9 1>;
                };
                button@2 {
                        label = "Power-on Switch";
-                       linux,code = <116>;
+                       linux,code = <0>;
+                       linux,input-type = <5>;
                        gpios = <&gpio1 10 1>;
                };
                button@3 {
                        label = "Power-auto Switch";
-                       linux,code = <142>;
+                       linux,code = <1>;
+                       linux,input-type = <5>;
                        gpios = <&gpio1 11 1>;
                };
        };
                compatible = "gpio-leds";
 
                led@1 {
-                       label = "lschlv2:blue:func";
+                       label = "lsxl:blue:func";
                        gpios = <&gpio1 4 1>;
                };
 
                led@2 {
-                       label = "lschlv2:red:alarm";
+                       label = "lsxl:red:alarm";
                        gpios = <&gpio1 5 1>;
                };
 
                led@3 {
-                       label = "lschlv2:amber:info";
+                       label = "lsxl:amber:info";
                        gpios = <&gpio1 6 1>;
                };
 
                led@4 {
-                       label = "lschlv2:blue:power";
+                       label = "lsxl:blue:power";
                        gpios = <&gpio1 7 1>;
                        linux,default-trigger = "default-on";
                };
 
                led@5 {
-                       label = "lschlv2:red:func";
+                       label = "lsxl:red:func";
                        gpios = <&gpio1 16 1>;
                };
        };
diff --git a/arch/arm/boot/dts/sh7372-mackerel.dts b/arch/arm/boot/dts/sh7372-mackerel.dts
new file mode 100644 (file)
index 0000000..286f0ca
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Device Tree Source for the mackerel board
+ *
+ * Copyright (C) 2012 Renesas Solutions Corp.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+/dts-v1/;
+/include/ "skeleton.dtsi"
+
+/ {
+       model = "Mackerel (AP4 EVM 2nd)";
+       compatible = "renesas,mackerel";
+
+       memory {
+               device_type = "memory";
+               reg = <0x40000000 0x10000000>;
+       };
+};
index f7b84aced654ca643bc49ebe83b376425a6b893f..14a6d15c2a81e58220a8f9f142cf07d507909a26 100644 (file)
                        compatible = "st,spear600-fsmc-nand";
                        #address-cells = <1>;
                        #size-cells = <1>;
-                       reg = <0xb0000000 0x1000        /* FSMC Register */
-                              0xb0800000 0x0010>;      /* NAND Base */
-                       reg-names = "fsmc_regs", "nand_data";
+                       reg = <0xb0000000 0x1000        /* FSMC Register*/
+                              0xb0800000 0x0010        /* NAND Base DATA */
+                              0xb0820000 0x0010        /* NAND Base ADDR */
+                              0xb0810000 0x0010>;      /* NAND Base CMD */
+                       reg-names = "fsmc_regs", "nand_data", "nand_addr", "nand_cmd";
                        interrupts = <0 20 0x4
                                      0 21 0x4
                                      0 22 0x4
                                      0 23 0x4>;
-                       st,ale-off = <0x20000>;
-                       st,cle-off = <0x10000>;
                        status = "disabled";
                };
 
index ed3627c116ccbd7c5e8f90208fab4c37ef7a97d0..bc436387d7f9bb9b75c96ce7eaf312ea570ecac8 100644 (file)
                        #address-cells = <1>;
                        #size-cells = <1>;
                        reg = <0x94000000 0x1000        /* FSMC Register */
-                              0x80000000 0x0010>;      /* NAND Base */
-                       reg-names = "fsmc_regs", "nand_data";
-                       st,ale-off = <0x20000>;
-                       st,cle-off = <0x10000>;
+                              0x80000000 0x0010        /* NAND Base DATA */
+                              0x80020000 0x0010        /* NAND Base ADDR */
+                              0x80010000 0x0010>;      /* NAND Base CMD */
+                       reg-names = "fsmc_regs", "nand_data", "nand_addr", "nand_cmd";
                        status = "disabled";
                };
 
index 62fc4fb3e5f92f079cd3caaf0ccdf852e1ff01d1..7840e529aba28c820998391f16c1018534763a97 100644 (file)
                        #address-cells = <1>;
                        #size-cells = <1>;
                        reg = <0x44000000 0x1000        /* FSMC Register */
-                              0x40000000 0x0010>;      /* NAND Base */
-                       reg-names = "fsmc_regs", "nand_data";
-                       st,ale-off = <0x10000>;
-                       st,cle-off = <0x20000>;
+                              0x40000000 0x0010        /* NAND Base DATA */
+                              0x40020000 0x0010        /* NAND Base ADDR */
+                              0x40010000 0x0010>;      /* NAND Base CMD */
+                       reg-names = "fsmc_regs", "nand_data", "nand_addr", "nand_cmd";
                        status = "disabled";
                };
 
index 1f49d69595a06996b0c8b48d631ed116716f7abb..5ad820641ac05b68fb0552134f4a3d7886312bfb 100644 (file)
                        #address-cells = <1>;
                        #size-cells = <1>;
                        reg = <0x4c000000 0x1000        /* FSMC Register */
-                              0x50000000 0x0010>;      /* NAND Base */
-                       reg-names = "fsmc_regs", "nand_data";
-                       st,ale-off = <0x20000>;
-                       st,cle-off = <0x10000>;
+                              0x50000000 0x0010        /* NAND Base DATA */
+                              0x50020000 0x0010        /* NAND Base ADDR */
+                              0x50010000 0x0010>;      /* NAND Base CMD */
+                       reg-names = "fsmc_regs", "nand_data", "nand_addr", "nand_cmd";
                        status = "disabled";
                };
 
index a3c36e47d7efcafee29eb73865eb5dec5651d4a4..4ecc66f5ac88e5282f04cd930b6f3ae25b4a1025 100644 (file)
                        #address-cells = <1>;
                        #size-cells = <1>;
                        reg = <0xd1800000 0x1000        /* FSMC Register */
-                              0xd2000000 0x4000>;      /* NAND Base */
-                       reg-names = "fsmc_regs", "nand_data";
-                       st,ale-off = <0x20000>;
-                       st,cle-off = <0x10000>;
+                              0xd2000000 0x0010        /* NAND Base DATA */
+                              0xd2020000 0x0010        /* NAND Base ADDR */
+                              0xd2010000 0x0010>;      /* NAND Base CMD */
+                       reg-names = "fsmc_regs", "nand_data", "nand_addr", "nand_cmd";
                        status = "disabled";
                };
 
index c3ef1ad26b6a29b0f86124fc7fcb2276aa08a034..74b8a47adf91561494e0d7d884d8aed0c6cfc785 100644 (file)
                        vinldo9-supply = <&sm2_reg>;
 
                        regulators {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-
-                               sys_reg: regulator@0 {
-                                       reg = <0>;
-                                       regulator-compatible = "sys";
+                               sys_reg: sys {
                                        regulator-name = "vdd_sys";
                                        regulator-always-on;
                                };
 
-                               regulator@1 {
-                                       reg = <1>;
-                                       regulator-compatible = "sm0";
+                               sm0 {
                                        regulator-name = "vdd_sm0,vdd_core";
                                        regulator-min-microvolt = <1200000>;
                                        regulator-max-microvolt = <1200000>;
                                        regulator-always-on;
                                };
 
-                               regulator@2 {
-                                       reg = <2>;
-                                       regulator-compatible = "sm1";
+                               sm1 {
                                        regulator-name = "vdd_sm1,vdd_cpu";
                                        regulator-min-microvolt = <1000000>;
                                        regulator-max-microvolt = <1000000>;
                                        regulator-always-on;
                                };
 
-                               sm2_reg: regulator@3 {
-                                       reg = <3>;
-                                       regulator-compatible = "sm2";
+                               sm2_reg: sm2 {
                                        regulator-name = "vdd_sm2,vin_ldo*";
                                        regulator-min-microvolt = <3700000>;
                                        regulator-max-microvolt = <3700000>;
                                        regulator-always-on;
                                };
 
-                               regulator@4 {
-                                       reg = <4>;
-                                       regulator-compatible = "ldo0";
+                               ldo0 {
                                        regulator-name = "vdd_ldo0,vddio_pex_clk";
                                        regulator-min-microvolt = <3300000>;
                                        regulator-max-microvolt = <3300000>;
                                };
 
-                               regulator@5 {
-                                       reg = <5>;
-                                       regulator-compatible = "ldo1";
+                               ldo1 {
                                        regulator-name = "vdd_ldo1,avdd_pll*";
                                        regulator-min-microvolt = <1100000>;
                                        regulator-max-microvolt = <1100000>;
                                        regulator-always-on;
                                };
 
-                               regulator@6 {
-                                       reg = <6>;
-                                       regulator-compatible = "ldo2";
+                               ldo2 {
                                        regulator-name = "vdd_ldo2,vdd_rtc";
                                        regulator-min-microvolt = <1200000>;
                                        regulator-max-microvolt = <1200000>;
                                };
 
-                               regulator@7 {
-                                       reg = <7>;
-                                       regulator-compatible = "ldo3";
+                               ldo3 {
                                        regulator-name = "vdd_ldo3,avdd_usb*";
                                        regulator-min-microvolt = <3300000>;
                                        regulator-max-microvolt = <3300000>;
                                        regulator-always-on;
                                };
 
-                               regulator@8 {
-                                       reg = <8>;
-                                       regulator-compatible = "ldo4";
+                               ldo4 {
                                        regulator-name = "vdd_ldo4,avdd_osc,vddio_sys";
                                        regulator-min-microvolt = <1800000>;
                                        regulator-max-microvolt = <1800000>;
                                        regulator-always-on;
                                };
 
-                               regulator@9 {
-                                       reg = <9>;
-                                       regulator-compatible = "ldo5";
+                               ldo5 {
                                        regulator-name = "vdd_ldo5,vcore_mmc";
                                        regulator-min-microvolt = <2850000>;
                                        regulator-max-microvolt = <2850000>;
                                        regulator-always-on;
                                };
 
-                               regulator@10 {
-                                       reg = <10>;
-                                       regulator-compatible = "ldo6";
+                               ldo6 {
                                        regulator-name = "vdd_ldo6,avdd_vdac";
                                        regulator-min-microvolt = <1800000>;
                                        regulator-max-microvolt = <1800000>;
                                };
 
-                               regulator@11 {
-                                       reg = <11>;
-                                       regulator-compatible = "ldo7";
+                               ldo7 {
                                        regulator-name = "vdd_ldo7,avdd_hdmi";
                                        regulator-min-microvolt = <3300000>;
                                        regulator-max-microvolt = <3300000>;
                                };
 
-                               regulator@12 {
-                                       reg = <12>;
-                                       regulator-compatible = "ldo8";
+                               ldo8 {
                                        regulator-name = "vdd_ldo8,avdd_hdmi_pll";
                                        regulator-min-microvolt = <1800000>;
                                        regulator-max-microvolt = <1800000>;
                                };
 
-                               regulator@13 {
-                                       reg = <13>;
-                                       regulator-compatible = "ldo9";
+                               ldo9 {
                                        regulator-name = "vdd_ldo9,avdd_2v85,vdd_ddr_rx";
                                        regulator-min-microvolt = <2850000>;
                                        regulator-max-microvolt = <2850000>;
                                        regulator-always-on;
                                };
 
-                               regulator@14 {
-                                       reg = <14>;
-                                       regulator-compatible = "ldo_rtc";
+                               ldo_rtc {
                                        regulator-name = "vdd_rtc_out,vdd_cell";
                                        regulator-min-microvolt = <3300000>;
                                        regulator-max-microvolt = <3300000>;
index ddf287f52d498dd5bfe6d5451e019f64dda6f20c..6a93d1404c76d367577b82e10ff75648f1481f4e 100644 (file)
                        vinldo9-supply = <&sm2_reg>;
 
                        regulators {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-
-                               sys_reg: regulator@0 {
-                                       reg = <0>;
-                                       regulator-compatible = "sys";
+                               sys_reg: sys {
                                        regulator-name = "vdd_sys";
                                        regulator-always-on;
                                };
 
-                               regulator@1 {
-                                       reg = <1>;
-                                       regulator-compatible = "sm0";
+                               sm0 {
                                        regulator-name = "+1.2vs_sm0,vdd_core";
                                        regulator-min-microvolt = <1200000>;
                                        regulator-max-microvolt = <1200000>;
                                        regulator-always-on;
                                };
 
-                               regulator@2 {
-                                       reg = <2>;
-                                       regulator-compatible = "sm1";
+                               sm1 {
                                        regulator-name = "+1.0vs_sm1,vdd_cpu";
                                        regulator-min-microvolt = <1000000>;
                                        regulator-max-microvolt = <1000000>;
                                        regulator-always-on;
                                };
 
-                               sm2_reg: regulator@3 {
-                                       reg = <3>;
-                                       regulator-compatible = "sm2";
+                               sm2_reg: sm2 {
                                        regulator-name = "+3.7vs_sm2,vin_ldo*";
                                        regulator-min-microvolt = <3700000>;
                                        regulator-max-microvolt = <3700000>;
 
                                /* LDO0 is not connected to anything */
 
-                               regulator@5 {
-                                       reg = <5>;
-                                       regulator-compatible = "ldo1";
+                               ldo1 {
                                        regulator-name = "+1.1vs_ldo1,avdd_pll*";
                                        regulator-min-microvolt = <1100000>;
                                        regulator-max-microvolt = <1100000>;
                                        regulator-always-on;
                                };
 
-                               regulator@6 {
-                                       reg = <6>;
-                                       regulator-compatible = "ldo2";
+                               ldo2 {
                                        regulator-name = "+1.2vs_ldo2,vdd_rtc";
                                        regulator-min-microvolt = <1200000>;
                                        regulator-max-microvolt = <1200000>;
                                };
 
-                               regulator@7 {
-                                       reg = <7>;
-                                       regulator-compatible = "ldo3";
+                               ldo3 {
                                        regulator-name = "+3.3vs_ldo3,avdd_usb*";
                                        regulator-min-microvolt = <3300000>;
                                        regulator-max-microvolt = <3300000>;
                                        regulator-always-on;
                                };
 
-                               regulator@8 {
-                                       reg = <8>;
-                                       regulator-compatible = "ldo4";
+                               ldo4 {
                                        regulator-name = "+1.8vs_ldo4,avdd_osc,vddio_sys";
                                        regulator-min-microvolt = <1800000>;
                                        regulator-max-microvolt = <1800000>;
                                        regulator-always-on;
                                };
 
-                               regulator@9 {
-                                       reg = <9>;
-                                       regulator-compatible = "ldo5";
+                               ldo5 {
                                        regulator-name = "+2.85vs_ldo5,vcore_mmc";
                                        regulator-min-microvolt = <2850000>;
                                        regulator-max-microvolt = <2850000>;
                                        regulator-always-on;
                                };
 
-                               regulator@10 {
-                                       reg = <10>;
-                                       regulator-compatible = "ldo6";
+                               ldo6 {
                                        /*
                                         * Research indicates this should be
                                         * 1.8v; other boards that use this
                                        regulator-max-microvolt = <1800000>;
                                };
 
-                               regulator@11 {
-                                       reg = <11>;
-                                       regulator-compatible = "ldo7";
+                               ldo7 {
                                        regulator-name = "+3.3vs_ldo7,avdd_hdmi";
                                        regulator-min-microvolt = <3300000>;
                                        regulator-max-microvolt = <3300000>;
                                };
 
-                               regulator@12 {
-                                       reg = <12>;
-                                       regulator-compatible = "ldo8";
+                               ldo8 {
                                        regulator-name = "+1.8vs_ldo8,avdd_hdmi_pll";
                                        regulator-min-microvolt = <1800000>;
                                        regulator-max-microvolt = <1800000>;
                                };
 
-                               regulator@13 {
-                                       reg = <13>;
-                                       regulator-compatible = "ldo9";
+                               ldo9 {
                                        regulator-name = "+2.85vs_ldo9,vdd_ddr_rx";
                                        regulator-min-microvolt = <2850000>;
                                        regulator-max-microvolt = <2850000>;
                                        regulator-always-on;
                                };
 
-                               regulator@14 {
-                                       reg = <14>;
-                                       regulator-compatible = "ldo_rtc";
+                               ldo_rtc {
                                        regulator-name = "+3.3vs_rtc";
                                        regulator-min-microvolt = <3300000>;
                                        regulator-max-microvolt = <3300000>;
index f0ba901676ac640ddf5488ba51eb59d5ce38fd58..eafeca65eb214dce8d43a3cf14974cb222d9195e 100644 (file)
                        vinldo9-supply = <&sm2_reg>;
 
                        regulators {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-
-                               sys_reg: regulator@0 {
-                                       reg = <0>;
-                                       regulator-compatible = "sys";
+                               sys_reg: sys {
                                        regulator-name = "vdd_sys";
                                        regulator-always-on;
                                };
 
-                               regulator@1 {
-                                       reg = <1>;
-                                       regulator-compatible = "sm0";
+                               sm0 {
                                        regulator-name = "vdd_sm0,vdd_core";
                                        regulator-min-microvolt = <1300000>;
                                        regulator-max-microvolt = <1300000>;
                                        regulator-always-on;
                                };
 
-                               regulator@2 {
-                                       reg = <2>;
-                                       regulator-compatible = "sm1";
+                               sm1 {
                                        regulator-name = "vdd_sm1,vdd_cpu";
                                        regulator-min-microvolt = <1125000>;
                                        regulator-max-microvolt = <1125000>;
                                        regulator-always-on;
                                };
 
-                               sm2_reg: regulator@3 {
-                                       reg = <3>;
-                                       regulator-compatible = "sm2";
+                               sm2_reg: sm2 {
                                        regulator-name = "vdd_sm2,vin_ldo*";
                                        regulator-min-microvolt = <3700000>;
                                        regulator-max-microvolt = <3700000>;
 
                                /* LDO0 is not connected to anything */
 
-                               regulator@5 {
-                                       reg = <5>;
-                                       regulator-compatible = "ldo1";
+                               ldo1 {
                                        regulator-name = "vdd_ldo1,avdd_pll*";
                                        regulator-min-microvolt = <1100000>;
                                        regulator-max-microvolt = <1100000>;
                                        regulator-always-on;
                                };
 
-                               regulator@6 {
-                                       reg = <6>;
-                                       regulator-compatible = "ldo2";
+                               ldo2 {
                                        regulator-name = "vdd_ldo2,vdd_rtc";
                                        regulator-min-microvolt = <1200000>;
                                        regulator-max-microvolt = <1200000>;
                                };
 
-                               regulator@7 {
-                                       reg = <7>;
-                                       regulator-compatible = "ldo3";
+                               ldo3 {
                                        regulator-name = "vdd_ldo3,avdd_usb*";
                                        regulator-min-microvolt = <3300000>;
                                        regulator-max-microvolt = <3300000>;
                                        regulator-always-on;
                                };
 
-                               regulator@8 {
-                                       reg = <8>;
-                                       regulator-compatible = "ldo4";
+                               ldo4 {
                                        regulator-name = "vdd_ldo4,avdd_osc,vddio_sys";
                                        regulator-min-microvolt = <1800000>;
                                        regulator-max-microvolt = <1800000>;
                                        regulator-always-on;
                                };
 
-                               regulator@9 {
-                                       reg = <9>;
-                                       regulator-compatible = "ldo5";
+                               ldo5 {
                                        regulator-name = "vdd_ldo5,vcore_mmc";
                                        regulator-min-microvolt = <2850000>;
                                        regulator-max-microvolt = <2850000>;
                                        regulator-always-on;
                                };
 
-                               regulator@10 {
-                                       reg = <10>;
-                                       regulator-compatible = "ldo6";
+                               ldo6 {
                                        regulator-name = "vdd_ldo6,avdd_vdac,vddio_vi,vddio_cam";
                                        regulator-min-microvolt = <1800000>;
                                        regulator-max-microvolt = <1800000>;
                                };
 
-                               regulator@11 {
-                                       reg = <11>;
-                                       regulator-compatible = "ldo7";
+                               ldo7 {
                                        regulator-name = "vdd_ldo7,avdd_hdmi,vdd_fuse";
                                        regulator-min-microvolt = <3300000>;
                                        regulator-max-microvolt = <3300000>;
                                };
 
-                               regulator@12 {
-                                       reg = <12>;
-                                       regulator-compatible = "ldo8";
+                               ldo8 {
                                        regulator-name = "vdd_ldo8,avdd_hdmi_pll";
                                        regulator-min-microvolt = <1800000>;
                                        regulator-max-microvolt = <1800000>;
                                };
 
-                               regulator@13 {
-                                       reg = <13>;
-                                       regulator-compatible = "ldo9";
+                               ldo9 {
                                        regulator-name = "vdd_ldo9,avdd_2v85,vdd_ddr_rx";
                                        regulator-min-microvolt = <2850000>;
                                        regulator-max-microvolt = <2850000>;
                                        regulator-always-on;
                                };
 
-                               regulator@14 {
-                                       reg = <14>;
-                                       regulator-compatible = "ldo_rtc";
+                               ldo_rtc {
                                        regulator-name = "vdd_rtc_out,vdd_cell";
                                        regulator-min-microvolt = <3300000>;
                                        regulator-max-microvolt = <3300000>;
                status = "okay";
        };
 
+       sdhci@c8000000 {
+               status = "okay";
+               power-gpios = <&gpio 86 0>; /* gpio PK6 */
+               bus-width = <4>;
+       };
+
        sdhci@c8000400 {
                status = "okay";
                cd-gpios = <&gpio 69 0>; /* gpio PI5 */
index f18cec9f6a77ae0614c010b785ad5e2017c6c219..5b3d8b157b336eafd58511500e87a4d9076828af 100644 (file)
                        vinldo9-supply = <&sm2_reg>;
 
                        regulators {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-
-                               sys_reg: regulator@0 {
-                                       reg = <0>;
-                                       regulator-compatible = "sys";
+                               sys_reg: sys {
                                        regulator-name = "vdd_sys";
                                        regulator-always-on;
                                };
 
-                               regulator@1 {
-                                       reg = <1>;
-                                       regulator-compatible = "sm0";
+                               sm0 {
                                        regulator-name = "vdd_sys_sm0,vdd_core";
                                        regulator-min-microvolt = <1200000>;
                                        regulator-max-microvolt = <1200000>;
                                        regulator-always-on;
                                };
 
-                               regulator@2 {
-                                       reg = <2>;
-                                       regulator-compatible = "sm1";
+                               sm1 {
                                        regulator-name = "vdd_sys_sm1,vdd_cpu";
                                        regulator-min-microvolt = <1000000>;
                                        regulator-max-microvolt = <1000000>;
                                        regulator-always-on;
                                };
 
-                               sm2_reg: regulator@3 {
-                                       reg = <3>;
-                                       regulator-compatible = "sm2";
+                               sm2_reg: sm2 {
                                        regulator-name = "vdd_sys_sm2,vin_ldo*";
                                        regulator-min-microvolt = <3700000>;
                                        regulator-max-microvolt = <3700000>;
                                        regulator-always-on;
                                };
 
-                               regulator@4 {
-                                       reg = <4>;
-                                       regulator-compatible = "ldo0";
+                               ldo0 {
                                        regulator-name = "vdd_ldo0,vddio_pex_clk";
                                        regulator-min-microvolt = <3300000>;
                                        regulator-max-microvolt = <3300000>;
                                };
 
-                               regulator@5 {
-                                       reg = <5>;
-                                       regulator-compatible = "ldo1";
+                               ldo1 {
                                        regulator-name = "vdd_ldo1,avdd_pll*";
                                        regulator-min-microvolt = <1100000>;
                                        regulator-max-microvolt = <1100000>;
                                        regulator-always-on;
                                };
 
-                               regulator@6 {
-                                       reg = <6>;
-                                       regulator-compatible = "ldo2";
+                               ldo2 {
                                        regulator-name = "vdd_ldo2,vdd_rtc";
                                        regulator-min-microvolt = <1200000>;
                                        regulator-max-microvolt = <1200000>;
                                };
 
-                               regulator@7 {
-                                       reg = <7>;
-                                       regulator-compatible = "ldo3";
+                               ldo3 {
                                        regulator-name = "vdd_ldo3,avdd_usb*";
                                        regulator-min-microvolt = <3300000>;
                                        regulator-max-microvolt = <3300000>;
                                        regulator-always-on;
                                };
 
-                               regulator@8 {
-                                       reg = <8>;
-                                       regulator-compatible = "ldo4";
+                               ldo4 {
                                        regulator-name = "vdd_ldo4,avdd_osc,vddio_sys";
                                        regulator-min-microvolt = <1800000>;
                                        regulator-max-microvolt = <1800000>;
                                        regulator-always-on;
                                };
 
-                               regulator@9 {
-                                       reg = <9>;
-                                       regulator-compatible = "ldo5";
+                               ldo5 {
                                        regulator-name = "vdd_ldo5,vcore_mmc";
                                        regulator-min-microvolt = <2850000>;
                                        regulator-max-microvolt = <2850000>;
                                };
 
-                               regulator@10 {
-                                       reg = <10>;
-                                       regulator-compatible = "ldo6";
+                               ldo6 {
                                        regulator-name = "vdd_ldo6,avdd_vdac";
                                        /*
                                         * According to the Tegra 2 Automotive
                                        regulator-max-microvolt = <2850000>;
                                };
 
-                               regulator@11 {
-                                       reg = <11>;
-                                       regulator-compatible = "ldo7";
+                               ldo7 {
                                        regulator-name = "vdd_ldo7,avdd_hdmi";
                                        regulator-min-microvolt = <3300000>;
                                        regulator-max-microvolt = <3300000>;
                                };
 
-                               regulator@12 {
-                                       reg = <12>;
-                                       regulator-compatible = "ldo8";
+                               ldo8 {
                                        regulator-name = "vdd_ldo8,avdd_hdmi_pll";
                                        regulator-min-microvolt = <1800000>;
                                        regulator-max-microvolt = <1800000>;
                                };
 
-                               regulator@13 {
-                                       reg = <13>;
-                                       regulator-compatible = "ldo9";
+                               ldo9 {
                                        regulator-name = "vdd_ldo9,vdd_ddr_rx,avdd_cam";
                                        /*
                                         * According to the Tegra 2 Automotive
                                        regulator-always-on;
                                };
 
-                               regulator@14 {
-                                       reg = <14>;
-                                       regulator-compatible = "ldo_rtc";
+                               ldo_rtc {
                                        regulator-name = "vdd_rtc_out";
                                        regulator-min-microvolt = <3300000>;
                                        regulator-max-microvolt = <3300000>;
index 3e5952fcfbc55cc5db7cb514c42191aef2ea28b0..bec8bb297ad827bc8d756b1788d90129b13eb935 100644 (file)
                                        "ld23_22";
                                nvidia,pull = <1>;
                        };
+                       drive_sdio1 {
+                               nvidia,pins = "drive_sdio1";
+                               nvidia,high-speed-mode = <0>;
+                               nvidia,schmitt = <1>;
+                               nvidia,low-power-mode = <3>;
+                               nvidia,pull-down-strength = <31>;
+                               nvidia,pull-up-strength = <31>;
+                               nvidia,slew-rate-rising = <3>;
+                               nvidia,slew-rate-falling = <3>;
+                       };
                };
        };
 
                        vinldo9-supply = <&sm2_reg>;
 
                        regulators {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-
-                               sys_reg: regulator@0 {
-                                       reg = <0>;
-                                       regulator-compatible = "sys";
+                               sys_reg: sys {
                                        regulator-name = "vdd_sys";
                                        regulator-always-on;
                                };
 
-                               regulator@1 {
-                                       reg = <1>;
-                                       regulator-compatible = "sm0";
+                               sm0 {
                                        regulator-name = "vdd_sm0,vdd_core";
                                        regulator-min-microvolt = <1200000>;
                                        regulator-max-microvolt = <1200000>;
                                        regulator-always-on;
                                };
 
-                               regulator@2 {
-                                       reg = <2>;
-                                       regulator-compatible = "sm1";
+                               sm1 {
                                        regulator-name = "vdd_sm1,vdd_cpu";
                                        regulator-min-microvolt = <1000000>;
                                        regulator-max-microvolt = <1000000>;
                                        regulator-always-on;
                                };
 
-                               sm2_reg: regulator@3 {
-                                       reg = <3>;
-                                       regulator-compatible = "sm2";
+                               sm2_reg: sm2 {
                                        regulator-name = "vdd_sm2,vin_ldo*";
                                        regulator-min-microvolt = <3700000>;
                                        regulator-max-microvolt = <3700000>;
 
                                /* LDO0 is not connected to anything */
 
-                               regulator@5 {
-                                       reg = <5>;
-                                       regulator-compatible = "ldo1";
+                               ldo1 {
                                        regulator-name = "vdd_ldo1,avdd_pll*";
                                        regulator-min-microvolt = <1100000>;
                                        regulator-max-microvolt = <1100000>;
                                        regulator-always-on;
                                };
 
-                               regulator@6 {
-                                       reg = <6>;
-                                       regulator-compatible = "ldo2";
+                               ldo2 {
                                        regulator-name = "vdd_ldo2,vdd_rtc";
                                        regulator-min-microvolt = <1200000>;
                                        regulator-max-microvolt = <1200000>;
                                };
 
-                               regulator@7 {
-                                       reg = <7>;
-                                       regulator-compatible = "ldo3";
+                               ldo3 {
                                        regulator-name = "vdd_ldo3,avdd_usb*";
                                        regulator-min-microvolt = <3300000>;
                                        regulator-max-microvolt = <3300000>;
                                        regulator-always-on;
                                };
 
-                               regulator@8 {
-                                       reg = <8>;
-                                       regulator-compatible = "ldo4";
+                               ldo4 {
                                        regulator-name = "vdd_ldo4,avdd_osc,vddio_sys";
                                        regulator-min-microvolt = <1800000>;
                                        regulator-max-microvolt = <1800000>;
                                        regulator-always-on;
                                };
 
-                               regulator@9 {
-                                       reg = <9>;
-                                       regulator-compatible = "ldo5";
+                               ldo5 {
                                        regulator-name = "vdd_ldo5,vcore_mmc";
                                        regulator-min-microvolt = <2850000>;
                                        regulator-max-microvolt = <2850000>;
                                        regulator-always-on;
                                };
 
-                               regulator@10 {
-                                       reg = <10>;
-                                       regulator-compatible = "ldo6";
+                               ldo6 {
                                        regulator-name = "vdd_ldo6,avdd_vdac";
                                        regulator-min-microvolt = <1800000>;
                                        regulator-max-microvolt = <1800000>;
                                };
 
-                               regulator@11 {
-                                       reg = <11>;
-                                       regulator-compatible = "ldo7";
+                               ldo7 {
                                        regulator-name = "vdd_ldo7,avdd_hdmi,vdd_fuse";
                                        regulator-min-microvolt = <3300000>;
                                        regulator-max-microvolt = <3300000>;
                                };
 
-                               regulator@12 {
-                                       reg = <12>;
-                                       regulator-compatible = "ldo8";
+                               ldo8 {
                                        regulator-name = "vdd_ldo8,avdd_hdmi_pll";
                                        regulator-min-microvolt = <1800000>;
                                        regulator-max-microvolt = <1800000>;
                                };
 
-                               regulator@13 {
-                                       reg = <13>;
-                                       regulator-compatible = "ldo9";
+                               ldo9 {
                                        regulator-name = "vdd_ldo9,avdd_2v85,vdd_ddr_rx";
                                        regulator-min-microvolt = <2850000>;
                                        regulator-max-microvolt = <2850000>;
                                        regulator-always-on;
                                };
 
-                               regulator@14 {
-                                       reg = <14>;
-                                       regulator-compatible = "ldo_rtc";
+                               ldo_rtc {
                                        regulator-name = "vdd_rtc_out,vdd_cell";
                                        regulator-min-microvolt = <3300000>;
                                        regulator-max-microvolt = <3300000>;
                status = "okay";
        };
 
+       sdhci@c8000000 {
+               status = "okay";
+               power-gpios = <&gpio 86 0>; /* gpio PK6 */
+               bus-width = <4>;
+       };
+
        sdhci@c8000400 {
                status = "okay";
                cd-gpios = <&gpio 69 0>; /* gpio PI5 */
index c636d002d6d8a104c779bdd4c2f94fcc6cda99d7..94a71c91beb580b2f88f080cbbeeeeefa5bc0ba2 100644 (file)
                        in20-supply = <&mbatt_reg>;
 
                        regulators {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-
-                               mbatt_reg: regulator@0 {
-                                       reg = <0>;
-                                       regulator-compatible = "mbatt";
+                               mbatt_reg: mbatt {
                                        regulator-name = "vbat_pmu";
                                        regulator-always-on;
                                };
 
-                               regulator@1 {
-                                       reg = <1>;
-                                       regulator-compatible = "sd1";
+                               sd1 {
                                        regulator-name = "nvvdd_sv1,vdd_cpu_pmu";
                                        regulator-min-microvolt = <1000000>;
                                        regulator-max-microvolt = <1000000>;
                                        regulator-always-on;
                                };
 
-                               regulator@2 {
-                                       reg = <2>;
-                                       regulator-compatible = "sd2";
+                               sd2 {
                                        regulator-name = "nvvdd_sv2,vdd_core";
                                        regulator-min-microvolt = <1200000>;
                                        regulator-max-microvolt = <1200000>;
                                        regulator-always-on;
                                };
 
-                               nvvdd_sv3_reg: regulator@3 {
-                                       reg = <3>;
-                                       regulator-compatible = "sd3";
+                               nvvdd_sv3_reg: sd3 {
                                        regulator-name = "nvvdd_sv3";
                                        regulator-min-microvolt = <1800000>;
                                        regulator-max-microvolt = <1800000>;
                                        regulator-always-on;
                                };
 
-                               regulator@4 {
-                                       reg = <4>;
-                                       regulator-compatible = "ldo1";
+                               ldo1 {
                                        regulator-name = "nvvdd_ldo1,vddio_rx_ddr,vcore_acc";
                                        regulator-min-microvolt = <3300000>;
                                        regulator-max-microvolt = <3300000>;
                                        regulator-always-on;
                                };
 
-                               regulator@5 {
-                                       reg = <5>;
-                                       regulator-compatible = "ldo2";
+                               ldo2 {
                                        regulator-name = "nvvdd_ldo2,avdd_pll*";
                                        regulator-min-microvolt = <1100000>;
                                        regulator-max-microvolt = <1100000>;
                                        regulator-always-on;
                                };
 
-                               regulator@6 {
-                                       reg = <6>;
-                                       regulator-compatible = "ldo3";
+                               ldo3 {
                                        regulator-name = "nvvdd_ldo3,vcom_1v8b";
                                        regulator-min-microvolt = <1800000>;
                                        regulator-max-microvolt = <1800000>;
                                        regulator-always-on;
                                };
 
-                               regulator@7 {
-                                       reg = <7>;
-                                       regulator-compatible = "ldo4";
+                               ldo4 {
                                        regulator-name = "nvvdd_ldo4,avdd_usb*";
                                        regulator-min-microvolt = <3300000>;
                                        regulator-max-microvolt = <3300000>;
                                        regulator-always-on;
                                };
 
-                               regulator@8 {
-                                       reg = <8>;
-                                       regulator-compatible = "ldo5";
+                               ldo5 {
                                        regulator-name = "nvvdd_ldo5,vcore_mmc,avdd_lcd1,vddio_1wire";
                                        regulator-min-microvolt = <2800000>;
                                        regulator-max-microvolt = <2800000>;
                                        regulator-always-on;
                                };
 
-                               regulator@9 {
-                                       reg = <9>;
-                                       regulator-compatible = "ldo6";
+                               ldo6 {
                                        regulator-name = "nvvdd_ldo6,avdd_hdmi_pll";
                                        regulator-min-microvolt = <1800000>;
                                        regulator-max-microvolt = <1800000>;
                                };
 
-                               regulator@10 {
-                                       reg = <10>;
-                                       regulator-compatible = "ldo7";
+                               ldo7 {
                                        regulator-name = "nvvdd_ldo7,avddio_audio";
                                        regulator-min-microvolt = <2800000>;
                                        regulator-max-microvolt = <2800000>;
                                        regulator-always-on;
                                };
 
-                               regulator@11 {
-                                       reg = <11>;
-                                       regulator-compatible = "ldo8";
+                               ldo8 {
                                        regulator-name = "nvvdd_ldo8,vcom_3v0,vcore_cmps";
                                        regulator-min-microvolt = <3000000>;
                                        regulator-max-microvolt = <3000000>;
                                };
 
-                               regulator@12 {
-                                       reg = <12>;
-                                       regulator-compatible = "ldo9";
+                               ldo9 {
                                        regulator-name = "nvvdd_ldo9,avdd_cam*";
                                        regulator-min-microvolt = <2800000>;
                                        regulator-max-microvolt = <2800000>;
                                };
 
-                               regulator@13 {
-                                       reg = <13>;
-                                       regulator-compatible = "ldo10";
+                               ldo10 {
                                        regulator-name = "nvvdd_ldo10,avdd_usb_ic_3v0";
                                        regulator-min-microvolt = <3000000>;
                                        regulator-max-microvolt = <3000000>;
                                        regulator-always-on;
                                };
 
-                               regulator@14 {
-                                       reg = <14>;
-                                       regulator-compatible = "ldo11";
+                               ldo11 {
                                        regulator-name = "nvvdd_ldo11,vddio_pex_clk,vcom_33,avdd_hdmi";
                                        regulator-min-microvolt = <3300000>;
                                        regulator-max-microvolt = <3300000>;
                                };
 
-                               regulator@15 {
-                                       reg = <15>;
-                                       regulator-compatible = "ldo12";
+                               ldo12 {
                                        regulator-name = "nvvdd_ldo12,vddio_sdio";
                                        regulator-min-microvolt = <2800000>;
                                        regulator-max-microvolt = <2800000>;
                                        regulator-always-on;
                                };
 
-                               regulator@16 {
-                                       reg = <16>;
-                                       regulator-compatible = "ldo13";
+                               ldo13 {
                                        regulator-name = "nvvdd_ldo13,vcore_phtn,vdd_af";
                                        regulator-min-microvolt = <2800000>;
                                        regulator-max-microvolt = <2800000>;
                                };
 
-                               regulator@17 {
-                                       reg = <17>;
-                                       regulator-compatible = "ldo14";
+                               ldo14 {
                                        regulator-name = "nvvdd_ldo14,avdd_vdac";
                                        regulator-min-microvolt = <2800000>;
                                        regulator-max-microvolt = <2800000>;
                                };
 
-                               regulator@18 {
-                                       reg = <18>;
-                                       regulator-compatible = "ldo15";
+                               ldo15 {
                                        regulator-name = "nvvdd_ldo15,vcore_temp,vddio_hdcp";
                                        regulator-min-microvolt = <3300000>;
                                        regulator-max-microvolt = <3300000>;
                                };
 
-                               regulator@19 {
-                                       reg = <19>;
-                                       regulator-compatible = "ldo16";
+                               ldo16 {
                                        regulator-name = "nvvdd_ldo16,vdd_dbrtr";
                                        regulator-min-microvolt = <1300000>;
                                        regulator-max-microvolt = <1300000>;
                                };
 
-                               regulator@20 {
-                                       reg = <20>;
-                                       regulator-compatible = "ldo17";
+                               ldo17 {
                                        regulator-name = "nvvdd_ldo17,vddio_mipi";
                                        regulator-min-microvolt = <1200000>;
                                        regulator-max-microvolt = <1200000>;
                                };
 
-                               regulator@21 {
-                                       reg = <21>;
-                                       regulator-compatible = "ldo18";
+                               ldo18 {
                                        regulator-name = "nvvdd_ldo18,vddio_vi,vcore_cam*";
                                        regulator-min-microvolt = <1800000>;
                                        regulator-max-microvolt = <1800000>;
                                };
 
-                               regulator@22 {
-                                       reg = <22>;
-                                       regulator-compatible = "ldo19";
+                               ldo19 {
                                        regulator-name = "nvvdd_ldo19,avdd_lcd2,vddio_lx";
                                        regulator-min-microvolt = <2800000>;
                                        regulator-max-microvolt = <2800000>;
                                };
 
-                               regulator@23 {
-                                       reg = <23>;
-                                       regulator-compatible = "ldo20";
+                               ldo20 {
                                        regulator-name = "nvvdd_ldo20,vddio_ddr_1v2,vddio_hsic,vcom_1v2";
                                        regulator-min-microvolt = <1200000>;
                                        regulator-max-microvolt = <1200000>;
                                        regulator-always-on;
                                };
 
-                               regulator@24 {
-                                       reg = <24>;
-                                       regulator-compatible = "out5v";
+                               out5v {
                                        regulator-name = "usb0_vbus_reg";
                                };
 
-                               regulator@25 {
-                                       reg = <25>;
-                                       regulator-compatible = "out33v";
+                               out33v {
                                        regulator-name = "pmu_out3v3";
                                };
 
-                               regulator@26 {
-                                       reg = <26>;
-                                       regulator-compatible = "bbat";
+                               bbat {
                                        regulator-name = "pmu_bbat";
                                        regulator-min-microvolt = <2400000>;
                                        regulator-max-microvolt = <2400000>;
                                        regulator-always-on;
                                };
 
-                               regulator@27 {
-                                       reg = <27>;
-                                       regulator-compatible = "sdby";
+                               sdby {
                                        regulator-name = "vdd_aon";
                                        regulator-always-on;
                                };
 
-                               regulator@28 {
-                                       reg = <28>;
-                                       regulator-compatible = "vrtc";
+                               vrtc {
                                        regulator-name = "vrtc,pmu_vccadc";
                                        regulator-always-on;
                                };
index f3a09d0d45bc801a012fe7ea97f73548384ae9ad..6934bca15247db509636a10d41505b7d27c94f75 100644 (file)
@@ -4,6 +4,12 @@
        compatible = "nvidia,tegra20";
        interrupt-parent = <&intc>;
 
+       timer@50004600 {
+               compatible = "arm,cortex-a9-twd-timer";
+               reg = <0x50040600 0x20>;
+               interrupts = <1 13 0x304>;
+       };
+
        intc: interrupt-controller {
                compatible = "arm,cortex-a9-gic";
                reg = <0x50041000 0x1000
                #interrupt-cells = <3>;
        };
 
+       timer@60005000 {
+               compatible = "nvidia,tegra20-timer";
+               reg = <0x60005000 0x60>;
+               interrupts = <0 0 0x04
+                             0 1 0x04
+                             0 41 0x04
+                             0 42 0x04>;
+       };
+
        apbdma: dma {
                compatible = "nvidia,tegra20-apbdma";
                reg = <0x6000a000 0x1200>;
                #pwm-cells = <2>;
        };
 
+       rtc {
+               compatible = "nvidia,tegra20-rtc";
+               reg = <0x7000e000 0x100>;
+               interrupts = <0 2 0x04>;
+       };
+
        i2c@7000c000 {
                compatible = "nvidia,tegra20-i2c";
                reg = <0x7000c000 0x100>;
index dd4222f00eca9b4dc82637976283235906d1b708..adc88aa50eb634e5c36b002f6a06420aa6917a7c 100644 (file)
                        gpio = <&gpio 83 0>; /* GPIO PK3 */
                };
        };
+
+       sdhci@78000400 {
+               status = "okay";
+               power-gpios = <&gpio 28 0>; /* gpio PD4 */
+               bus-width = <4>;
+       };
 };
 
index 0828f097ca860490b7edd786b619bf889535014a..08163e145d57d10691f85ae6de770321d5f168f4 100644 (file)
                        gpio = <&gpio 232 0>; /* GPIO PDD0 */
                };
        };
+
+       sdhci@78000400 {
+               status = "okay";
+               power-gpios = <&gpio 27 0>; /* gpio PD3 */
+               bus-width = <4>;
+       };
 };
index d10c9c5a3606df6fe6923a64557cc7e749015d1b..b245e6cf633823879ff10af11439c235038bc85b 100644 (file)
                                nvidia,pull = <2>;
                                nvidia,tristate = <0>;
                        };
+                       sdmmc3_clk_pa6 {
+                               nvidia,pins = "sdmmc3_clk_pa6";
+                               nvidia,function = "sdmmc3";
+                               nvidia,pull = <0>;
+                               nvidia,tristate = <0>;
+                       };
+                       sdmmc3_cmd_pa7 {
+                               nvidia,pins =   "sdmmc3_cmd_pa7",
+                                               "sdmmc3_dat0_pb7",
+                                               "sdmmc3_dat1_pb6",
+                                               "sdmmc3_dat2_pb5",
+                                               "sdmmc3_dat3_pb4";
+                               nvidia,function = "sdmmc3";
+                               nvidia,pull = <2>;
+                               nvidia,tristate = <0>;
+                       };
                        sdmmc4_clk_pcc4 {
                                nvidia,pins =   "sdmmc4_clk_pcc4",
                                                "sdmmc4_rst_n_pcc3";
                                nvidia,pull = <0>;
                                nvidia,tristate = <0>;
                        };
+                       sdio3 {
+                               nvidia,pins = "drive_sdio3";
+                               nvidia,high-speed-mode = <0>;
+                               nvidia,schmitt = <0>;
+                               nvidia,pull-down-strength = <46>;
+                               nvidia,pull-up-strength = <42>;
+                               nvidia,slew-rate-rising = <1>;
+                               nvidia,slew-rate-falling = <1>;
+                       };
                };
        };
 
                        vccio-supply = <&vdd_ac_bat_reg>;
 
                        regulators {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-
-                               vdd1_reg: regulator@0 {
-                                       reg = <0>;
-                                       regulator-compatible = "vdd1";
+                               vdd1_reg: vdd1 {
                                        regulator-name = "vddio_ddr_1v2";
                                        regulator-min-microvolt = <1200000>;
                                        regulator-max-microvolt = <1200000>;
                                        regulator-always-on;
                                };
 
-                               vdd2_reg: regulator@1 {
-                                       reg = <1>;
-                                       regulator-compatible = "vdd2";
+                               vdd2_reg: vdd2 {
                                        regulator-name = "vdd_1v5_gen";
                                        regulator-min-microvolt = <1500000>;
                                        regulator-max-microvolt = <1500000>;
                                        regulator-always-on;
                                };
 
-                               vddctrl_reg: regulator@2 {
-                                       reg = <2>;
-                                       regulator-compatible = "vddctrl";
+                               vddctrl_reg: vddctrl {
                                        regulator-name = "vdd_cpu,vdd_sys";
                                        regulator-min-microvolt = <1000000>;
                                        regulator-max-microvolt = <1000000>;
                                        regulator-always-on;
                                };
 
-                               vio_reg: regulator@3 {
-                                       reg = <3>;
-                                       regulator-compatible = "vio";
+                               vio_reg: vio {
                                        regulator-name = "vdd_1v8_gen";
                                        regulator-min-microvolt = <1800000>;
                                        regulator-max-microvolt = <1800000>;
                                        regulator-always-on;
                                };
 
-                               ldo1_reg: regulator@4 {
-                                       reg = <4>;
-                                       regulator-compatible = "ldo1";
+                               ldo1_reg: ldo1 {
                                        regulator-name = "vdd_pexa,vdd_pexb";
                                        regulator-min-microvolt = <1050000>;
                                        regulator-max-microvolt = <1050000>;
                                };
 
-                               ldo2_reg: regulator@5 {
-                                       reg = <5>;
-                                       regulator-compatible = "ldo2";
+                               ldo2_reg: ldo2 {
                                        regulator-name = "vdd_sata,avdd_plle";
                                        regulator-min-microvolt = <1050000>;
                                        regulator-max-microvolt = <1050000>;
 
                                /* LDO3 is not connected to anything */
 
-                               ldo4_reg: regulator@7 {
-                                       reg = <7>;
-                                       regulator-compatible = "ldo4";
+                               ldo4_reg: ldo4 {
                                        regulator-name = "vdd_rtc";
                                        regulator-min-microvolt = <1200000>;
                                        regulator-max-microvolt = <1200000>;
                                        regulator-always-on;
                                };
 
-                               ldo5_reg: regulator@8 {
-                                       reg = <8>;
-                                       regulator-compatible = "ldo5";
+                               ldo5_reg: ldo5 {
                                        regulator-name = "vddio_sdmmc,avdd_vdac";
                                        regulator-min-microvolt = <3300000>;
                                        regulator-max-microvolt = <3300000>;
                                        regulator-always-on;
                                };
 
-                               ldo6_reg: regulator@9 {
-                                       reg = <9>;
-                                       regulator-compatible = "ldo6";
+                               ldo6_reg: ldo6 {
                                        regulator-name = "avdd_dsi_csi,pwrdet_mipi";
                                        regulator-min-microvolt = <1200000>;
                                        regulator-max-microvolt = <1200000>;
                                };
 
-                               ldo7_reg: regulator@10 {
-                                       reg = <10>;
-                                       regulator-compatible = "ldo7";
+                               ldo7_reg: ldo7 {
                                        regulator-name = "vdd_pllm,x,u,a_p_c_s";
                                        regulator-min-microvolt = <1200000>;
                                        regulator-max-microvolt = <1200000>;
                                        regulator-always-on;
                                };
 
-                               ldo8_reg: regulator@11 {
-                                       reg = <11>;
-                                       regulator-compatible = "ldo8";
+                               ldo8_reg: ldo8 {
                                        regulator-name = "vdd_ddr_hs";
                                        regulator-min-microvolt = <1000000>;
                                        regulator-max-microvolt = <1000000>;
                        regulator-name = "vdd_com";
                        regulator-min-microvolt = <3300000>;
                        regulator-max-microvolt = <3300000>;
+                       regulator-always-on;
+                       regulator-boot-on;
                        enable-active-high;
                        gpio = <&gpio 24 0>; /* gpio PD0 */
                        vin-supply = <&sys_3v3_reg>;
index b1497c7d7d6851db3753c1210e974cb9e47888c2..81f5df4479a24aa6242932a9dc14be8ef09f9c32 100644 (file)
@@ -4,6 +4,12 @@
        compatible = "nvidia,tegra30";
        interrupt-parent = <&intc>;
 
+       timer@50004600 {
+               compatible = "arm,cortex-a9-twd-timer";
+               reg = <0x50040600 0x20>;
+               interrupts = <1 13 0xf04>;
+       };
+
        intc: interrupt-controller {
                compatible = "arm,cortex-a9-gic";
                reg = <0x50041000 0x1000
                #interrupt-cells = <3>;
        };
 
+       timer@60005000 {
+               compatible = "nvidia,tegra30-timer", "nvidia,tegra20-timer";
+               reg = <0x60005000 0x400>;
+               interrupts = <0 0 0x04
+                             0 1 0x04
+                             0 41 0x04
+                             0 42 0x04
+                             0 121 0x04
+                             0 122 0x04>;
+       };
+
        apbdma: dma {
                compatible = "nvidia,tegra30-apbdma", "nvidia,tegra20-apbdma";
                reg = <0x6000a000 0x1400>;
                #pwm-cells = <2>;
        };
 
+       rtc {
+               compatible = "nvidia,tegra30-rtc", "nvidia,tegra20-rtc";
+               reg = <0x7000e000 0x100>;
+               interrupts = <0 2 0x04>;
+       };
+
        i2c@7000c000 {
                compatible =  "nvidia,tegra30-i2c", "nvidia,tegra20-i2c";
                reg = <0x7000c000 0x100>;
index b459691655ab653182817134a5b358696bab18d8..330f833ac3b03e97b376bbcdcf418770b3431a23 100644 (file)
                ehci@d8007100 {
                        compatible = "via,vt8500-ehci";
                        reg = <0xd8007100 0x200>;
-                       interrupts = <43>;
+                       interrupts = <1>;
                };
 
                uhci@d8007300 {
                        compatible = "platform-uhci";
                        reg = <0xd8007300 0x200>;
-                       interrupts = <43>;
+                       interrupts = <0>;
                };
 
                fb@d8050800 {
index e0d538803cc338a171d71cff38393a96a0b25600..4fd5d980edde03d32ea1c725075ce0679a96c2ee 100644 (file)
@@ -218,7 +218,7 @@ static void __init vic_register(void __iomem *base, unsigned int irq,
        v->resume_sources = resume_sources;
        v->irq = irq;
        vic_id++;
-       v->domain = irq_domain_add_legacy(node, fls(valid_sources), irq, 0,
+       v->domain = irq_domain_add_simple(node, fls(valid_sources), irq,
                                          &vic_irqdomain_ops, v);
 }
 
@@ -350,7 +350,7 @@ static void __init vic_init_st(void __iomem *base, unsigned int irq_start,
        vic_register(base, irq_start, vic_sources, 0, node);
 }
 
-void __init __vic_init(void __iomem *base, unsigned int irq_start,
+void __init __vic_init(void __iomem *base, int irq_start,
                              u32 vic_sources, u32 resume_sources,
                              struct device_node *node)
 {
@@ -416,18 +416,12 @@ int __init vic_of_init(struct device_node *node, struct device_node *parent)
        if (WARN_ON(!regs))
                return -EIO;
 
-       irq_base = irq_alloc_descs(-1, 0, 32, numa_node_id());
-       if (WARN_ON(irq_base < 0))
-               goto out_unmap;
-
-       __vic_init(regs, irq_base, ~0, ~0, node);
+       /*
+        * Passing -1 as first IRQ makes the simple domain allocate descriptors
+        */
+       __vic_init(regs, -1, ~0, ~0, node);
 
        return 0;
-
- out_unmap:
-       iounmap(regs);
-
-       return -EIO;
 }
 #endif /* CONFIG OF */
 
index f78d259f8d23d900d4a2abb6461f8921ce74389c..2e1a825772074a1a6de833b741e99f8cdcab957b 100644 (file)
@@ -7,6 +7,7 @@ CONFIG_LOG_BUF_SHIFT=16
 # CONFIG_IPC_NS is not set
 # CONFIG_PID_NS is not set
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_PERF_EVENTS=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
@@ -20,7 +21,7 @@ CONFIG_MACH_ARMADILLO800EVA=y
 # CONFIG_SH_TIMER_TMU is not set
 CONFIG_ARM_THUMB=y
 CONFIG_CPU_BPREDICT_DISABLE=y
-# CONFIG_CACHE_L2X0 is not set
+CONFIG_CACHE_L2X0=y
 CONFIG_ARM_ERRATA_430973=y
 CONFIG_ARM_ERRATA_458693=y
 CONFIG_ARM_ERRATA_460075=y
index 67bc571ed0c37c331a179703866ba861b1cdd2c1..b175577d7abb5aec9541461e35407f0f9059c04a 100644 (file)
@@ -111,6 +111,7 @@ CONFIG_I2C=y
 CONFIG_I2C_GPIO=y
 CONFIG_SPI=y
 CONFIG_SPI_ATMEL=y
+CONFIG_PINCTRL_AT91=y
 # CONFIG_HWMON is not set
 CONFIG_WATCHDOG=y
 CONFIG_AT91SAM9X_WATCHDOG=y
index 78ed575feb1abac028168ab3ab847694165c68c2..bd012441b747f1dc88b87cde330f157d7deff758 100644 (file)
@@ -17,8 +17,9 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_IOSCHED_DEADLINE is not set
 # CONFIG_IOSCHED_CFQ is not set
-CONFIG_ARCH_MXC=y
-CONFIG_ARCH_IMX_V4_V5=y
+CONFIG_ARCH_MULTI_V4T=y
+CONFIG_ARCH_MULTI_V5=y
+# CONFIG_ARCH_MULTI_V7 is not set
 CONFIG_ARCH_MX1ADS=y
 CONFIG_MACH_SCB9328=y
 CONFIG_MACH_APF9328=y
index 66aa7a6db884c14668be9f20a6d27166c85a8c1f..a4965f372576b1c2ae31d289244e8728c6917ba0 100644 (file)
@@ -16,7 +16,8 @@ CONFIG_MODULE_UNLOAD=y
 CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
 # CONFIG_BLK_DEV_BSG is not set
-CONFIG_ARCH_MXC=y
+CONFIG_ARCH_MULTI_V6=y
+CONFIG_ARCH_MULTI_V7=y
 CONFIG_MACH_MX31LILLY=y
 CONFIG_MACH_MX31LITE=y
 CONFIG_MACH_PCM037=y
index c88b57886e791906f8f21459df939718a95be0b6..ce99e3e00efa1c13e9a6b3f2d9282f94d046c36c 100644 (file)
@@ -74,6 +74,8 @@ CONFIG_KEYBOARD_GPIO=y
 # CONFIG_INPUT_MOUSE is not set
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_ST1232=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_ADXL34X=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_SERIAL_SH_SCI=y
 CONFIG_SERIAL_SH_SCI_NR_UARTS=9
@@ -119,6 +121,8 @@ CONFIG_DMADEVICES=y
 CONFIG_SH_DMAE=y
 CONFIG_ASYNC_TX_DMA=y
 CONFIG_STAGING=y
+CONFIG_SENSORS_AK8975=y
+CONFIG_IIO=y
 # CONFIG_DNOTIFY is not set
 CONFIG_INOTIFY_USER=y
 CONFIG_VFAT_FS=y
index 306a2e2d3622b6b7696822cd0f03f6a4e32b3e73..7b79a0b0352fc3fc07fd82707c984088efcbb93b 100644 (file)
@@ -70,17 +70,31 @@ CONFIG_SERIAL_SH_SCI_NR_UARTS=8
 CONFIG_SERIAL_SH_SCI_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+CONFIG_I2C_SH_MOBILE=y
 # CONFIG_HWMON is not set
 # CONFIG_MFD_SUPPORT is not set
 CONFIG_FB=y
 CONFIG_FB_MODE_HELPERS=y
 CONFIG_FB_SH_MOBILE_LCDC=y
+CONFIG_FB_SH_MOBILE_HDMI=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_LOGO=y
 # CONFIG_LOGO_LINUX_MONO is not set
 # CONFIG_LOGO_LINUX_CLUT224 is not set
-# CONFIG_HID_SUPPORT is not set
-# CONFIG_USB_SUPPORT is not set
+# CONFIG_SND_SUPPORT_OLD_API is not set
+# CONFIG_SND_VERBOSE_PROCFS is not set
+# CONFIG_SND_DRIVERS is not set
+# CONFIG_SND_ARM is not set
+CONFIG_SND_SOC_SH4_FSI=y
+CONFIG_USB=y
+CONFIG_USB_RENESAS_USBHS_HCD=y
+CONFIG_USB_RENESAS_USBHS=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_RENESAS_USBHS_UDC=y
+CONFIG_DMADEVICES=y
+CONFIG_SH_DMAE=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_POSIX_ACL=y
index 53382b6c8bb43345ae75b8f1ea39ab509d161980..5b8215f424c5a72e283fb979b5d4828f1d386738 100644 (file)
@@ -69,6 +69,10 @@ CONFIG_SERIAL_SH_SCI=y
 CONFIG_SERIAL_SH_SCI_NR_UARTS=6
 CONFIG_SERIAL_SH_SCI_CONSOLE=y
 # CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+CONFIG_I2C_RCAR=y
+CONFIG_SPI=y
+CONFIG_SPI_SH_HSPI=y
 CONFIG_GPIO_SYSFS=y
 # CONFIG_HWMON is not set
 CONFIG_THERMAL=y
index 240b25eea56559bb0588af7a048d720c15bb54ed..86cfd2959c47552bb2bcf40bbe630e6e36dce6db 100644 (file)
@@ -57,7 +57,7 @@ CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_NAND=y
 CONFIG_MTD_NAND_ECC_SMC=y
-CONFIG_MTD_NAND_NOMADIK=y
+CONFIG_MTD_NAND_FSMC=y
 CONFIG_MTD_ONENAND=y
 CONFIG_MTD_ONENAND_VERIFY_WRITE=y
 CONFIG_MTD_ONENAND_GENERIC=y
index e2184f6c20b3d3e6eeb9338794fb37375a7d9709..fb29680d34dc081e9a24f893d946bf6db2b11ff5 100644 (file)
@@ -98,6 +98,7 @@ CONFIG_USB_PEGASUS=y
 CONFIG_USB_USBNET=y
 CONFIG_USB_NET_SMSC75XX=y
 CONFIG_USB_NET_SMSC95XX=y
+CONFIG_BRCMFMAC=m
 CONFIG_RT2X00=y
 CONFIG_RT2800USB=m
 CONFIG_INPUT_EVDEV=y
index 2ef95813fce00b887dbd05020b35675870a7c929..ab7c02c92ed352a9fb31e3c8c7c2bf06dc3d6d38 100644 (file)
  * assumes FIQs are enabled, and that the processor is in SVC mode.
  */
        .macro  save_and_disable_irqs, oldcpsr
+#ifdef CONFIG_CPU_V7M
+       mrs     \oldcpsr, primask
+#else
        mrs     \oldcpsr, cpsr
+#endif
        disable_irq
        .endm
 
  * guarantee that this will preserve the flags.
  */
        .macro  restore_irqs_notrace, oldcpsr
+#ifdef CONFIG_CPU_V7M
+       msr     primask, \oldcpsr
+#else
        msr     cpsr_c, \oldcpsr
+#endif
        .endm
 
        .macro restore_irqs, oldcpsr
 #endif
        .endm
 
-#ifdef CONFIG_THUMB2_KERNEL
+#if defined(CONFIG_CPU_V7M)
+       .macro  setmode, mode, reg
+       .endm
+#elif defined(CONFIG_THUMB2_KERNEL)
        .macro  setmode, mode, reg
        mov     \reg, #\mode
        msr     cpsr_c, \reg
index 5ef4d8015a6043432bbc86f8905e0d635deb1f23..d81443557617e1032f85a4a542a6153d2d97b320 100644 (file)
@@ -42,6 +42,8 @@
 #define vectors_high() (0)
 #endif
 
+#ifdef CONFIG_CPU_CP15
+
 extern unsigned long cr_no_alignment;  /* defined in entry-armv.S */
 extern unsigned long cr_alignment;     /* defined in entry-armv.S */
 
@@ -82,6 +84,13 @@ static inline void set_copro_access(unsigned int val)
        isb();
 }
 
-#endif
+#else /* ifdef CONFIG_CPU_CP15 */
+
+#define cr_no_alignment        UL(0)
+#define cr_alignment   UL(0)
+
+#endif /* ifdef CONFIG_CPU_CP15 / else */
+
+#endif /* ifndef __ASSEMBLY__ */
 
 #endif
index cb47d28cbe1f81c4cfb43de4d1f08dbcec9f0cf7..5bd8cb6d93ffc7fd531569b970626a9626bab055 100644 (file)
@@ -46,6 +46,9 @@ extern unsigned int processor_id;
                    : "cc");                                            \
                __val;                                                  \
        })
+#elif defined(CONFIG_CPU_V7M)
+#define read_cpuid(reg) (*(unsigned int *)0xe000ed00)
+#define read_cpuid_ext(reg) 0
 #else
 #define read_cpuid(reg) (processor_id)
 #define read_cpuid_ext(reg) 0
index 23004847bb057becd348b5d1e870235b633acedd..78d8e9b5544f59bb04dcc2068a40ea433ae81553 100644 (file)
@@ -91,6 +91,7 @@ static inline dma_addr_t virt_to_dma(struct device *dev, void *addr)
  */
 static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
 {
+       debug_dma_mapping_error(dev, dma_addr);
        return dma_addr == DMA_ERROR_CODE;
 }
 
index 59426a4595c9cb90bcb765843f89295bd20f6797..e847d23351eda71ada1bc200476ee7f427a4e8ac 100644 (file)
@@ -8,7 +8,7 @@
 #define        flat_argvp_envp_on_stack()              1
 #define        flat_old_ram_flag(flags)                (flags)
 #define        flat_reloc_valid(reloc, size)           ((reloc) <= (size))
-#define        flat_get_addr_from_rp(rp, relval, flags, persistent) get_unaligned(rp)
+#define        flat_get_addr_from_rp(rp, relval, flags, persistent) ((void)persistent,get_unaligned(rp))
 #define        flat_put_addr_at_rp(rp, val, relval)    put_unaligned(val,rp)
 #define        flat_get_relocate_addr(rel)             (rel)
 #define        flat_set_persistent(relval, p)          0
index cca9f15704ed82bb2726ce8898611be42d28b5ff..ea986586068a5e003c112e91d71b45dc6ab9fa00 100644 (file)
 # endif
 #endif
 
+#if defined(CONFIG_CPU_V7M)
+# ifdef _CACHE
+#  error "Multi-cache not supported on ARMv7-M"
+# else
+#  define _CACHE nop
+# endif
+#endif
+
 #if !defined(_CACHE) && !defined(MULTI_CACHE)
 #error Unknown cache maintenance model
 #endif
 
+#ifndef __ASSEMBLER__
+static inline void nop_flush_icache_all(void) { }
+static inline void nop_flush_kern_cache_all(void) { }
+static inline void nop_flush_kern_cache_louis(void) { }
+static inline void nop_flush_user_cache_all(void) { }
+static inline void nop_flush_user_cache_range(unsigned long a, unsigned long b, unsigned int c) { }
+
+static inline void nop_coherent_kern_range(unsigned long a, unsigned long b) { }
+static inline int nop_coherent_user_range(unsigned long a, unsigned long b) { return 0; }
+static inline void nop_flush_kern_dcache_area(void *a, size_t s) { }
+
+static inline void nop_dma_flush_range(const void *a, const void *b) { }
+
+static inline void nop_dma_map_area(const void *s, size_t l, int f) { }
+static inline void nop_dma_unmap_area(const void *s, size_t l, int f) { }
+#endif
+
 #ifndef MULTI_CACHE
 #define __cpuc_flush_icache_all                __glue(_CACHE,_flush_icache_all)
 #define __cpuc_flush_kern_all          __glue(_CACHE,_flush_kern_cache_all)
index 8cacbcda76da986d6cf0c95d6b604eb50c574b0c..1f2339cdac0b5134b57a918e9ad2164ce891e479 100644 (file)
 # endif
 #endif
 
+#ifdef CONFIG_CPU_ABRT_NOMMU
+# ifdef CPU_DABORT_HANDLER
+#  define MULTI_DABORT 1
+# else
+#  define CPU_DABORT_HANDLER nommu_early_abort
+# endif
+#endif
+
 #ifndef CPU_DABORT_HANDLER
 #error Unknown data abort handler type
 #endif
index ac1dd54724b6a073415cc6a6704284c81556d6da..f2f39bcf7945a29de90f59d6afdd79e67bd06f43 100644 (file)
 # endif
 #endif
 
+#ifdef CONFIG_CPU_V7M
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_v7m
+# endif
+#endif
+
 #ifndef MULTI_CPU
 #define cpu_proc_init                  __glue(CPU_NAME,_proc_init)
 #define cpu_proc_fin                   __glue(CPU_NAME,_proc_fin)
index c4c87bc1223195478a76547d0e756ddec961eb70..3b2c40b5bfa22de982fce4e79afc8ced0326dce1 100644 (file)
 
 #define L2X0_ADDR_FILTER_EN            1
 
+#define L2X0_CTRL_EN                   1
+
+#define L2X0_WAY_SIZE_SHIFT            3
+
 #ifndef __ASSEMBLY__
 extern void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask);
 #if defined(CONFIG_CACHE_L2X0) && defined(CONFIG_OF)
@@ -126,6 +130,7 @@ struct l2x0_regs {
        unsigned long filter_end;
        unsigned long prefetch_ctrl;
        unsigned long pwr_ctrl;
+       unsigned long ctrl;
 };
 
 extern struct l2x0_regs l2x0_saved_regs;
index e14af1a1a320c5305c129b91130e34b5e8b48a3a..2bebad36fc8382383429122623cbad7154acfc2e 100644 (file)
@@ -47,7 +47,7 @@
 struct device_node;
 struct pt_regs;
 
-void __vic_init(void __iomem *base, unsigned int irq_start, u32 vic_sources,
+void __vic_init(void __iomem *base, int irq_start, u32 vic_sources,
                u32 resume_sources, struct device_node *node);
 void vic_init(void __iomem *base, unsigned int irq_start, u32 vic_sources, u32 resume_sources);
 int vic_of_init(struct device_node *node, struct device_node *parent);
index c190bc992f0e6e917d2071c920312c7391beb5e3..01169dd723f12e06f0506c7b8d4d16732170b9aa 100644 (file)
@@ -98,12 +98,12 @@ static inline void decode_ctrl_reg(u32 reg,
 #define ARM_BASE_WCR           112
 
 /* Accessor macros for the debug registers. */
-#define ARM_DBG_READ(M, OP2, VAL) do {\
-       asm volatile("mrc p14, 0, %0, c0," #M ", " #OP2 : "=r" (VAL));\
+#define ARM_DBG_READ(N, M, OP2, VAL) do {\
+       asm volatile("mrc p14, 0, %0, " #N "," #M ", " #OP2 : "=r" (VAL));\
 } while (0)
 
-#define ARM_DBG_WRITE(M, OP2, VAL) do {\
-       asm volatile("mcr p14, 0, %0, c0," #M ", " #OP2 : : "r" (VAL));\
+#define ARM_DBG_WRITE(N, M, OP2, VAL) do {\
+       asm volatile("mcr p14, 0, %0, " #N "," #M ", " #OP2 : : "r" (VAL));\
 } while (0)
 
 struct notifier_block;
index 35c1ed89b93652688dc99ede919b55b0d5051b1d..f52a93d98667c754d1c1ec55207cbd183ec162f3 100644 (file)
@@ -374,7 +374,7 @@ extern void pci_iounmap(struct pci_dev *dev, void __iomem *addr);
 
 #ifdef CONFIG_MMU
 #define ARCH_HAS_VALID_PHYS_ADDR_RANGE
-extern int valid_phys_addr_range(unsigned long addr, size_t size);
+extern int valid_phys_addr_range(phys_addr_t addr, size_t size);
 extern int valid_mmap_phys_addr_range(unsigned long pfn, size_t size);
 extern int devmem_is_allowed(unsigned long pfn);
 #endif
index 1e6cca55c750486b98ef85ca5a04c9af471d64ea..3b763d6652a0aee4ba7a81bc591715c2084d1b10 100644 (file)
@@ -8,6 +8,16 @@
 /*
  * CPU interrupt mask handling.
  */
+#ifdef CONFIG_CPU_V7M
+#define IRQMASK_REG_NAME_R "primask"
+#define IRQMASK_REG_NAME_W "primask"
+#define IRQMASK_I_BIT  1
+#else
+#define IRQMASK_REG_NAME_R "cpsr"
+#define IRQMASK_REG_NAME_W "cpsr_c"
+#define IRQMASK_I_BIT  PSR_I_BIT
+#endif
+
 #if __LINUX_ARM_ARCH__ >= 6
 
 static inline unsigned long arch_local_irq_save(void)
@@ -15,7 +25,7 @@ static inline unsigned long arch_local_irq_save(void)
        unsigned long flags;
 
        asm volatile(
-               "       mrs     %0, cpsr        @ arch_local_irq_save\n"
+               "       mrs     %0, " IRQMASK_REG_NAME_R "      @ arch_local_irq_save\n"
                "       cpsid   i"
                : "=r" (flags) : : "memory", "cc");
        return flags;
@@ -129,7 +139,7 @@ static inline unsigned long arch_local_save_flags(void)
 {
        unsigned long flags;
        asm volatile(
-               "       mrs     %0, cpsr        @ local_save_flags"
+               "       mrs     %0, " IRQMASK_REG_NAME_R "      @ local_save_flags"
                : "=r" (flags) : : "memory", "cc");
        return flags;
 }
@@ -140,7 +150,7 @@ static inline unsigned long arch_local_save_flags(void)
 static inline void arch_local_irq_restore(unsigned long flags)
 {
        asm volatile(
-               "       msr     cpsr_c, %0      @ local_irq_restore"
+               "       msr     " IRQMASK_REG_NAME_W ", %0      @ local_irq_restore"
                :
                : "r" (flags)
                : "memory", "cc");
@@ -148,8 +158,8 @@ static inline void arch_local_irq_restore(unsigned long flags)
 
 static inline int arch_irqs_disabled_flags(unsigned long flags)
 {
-       return flags & PSR_I_BIT;
+       return flags & IRQMASK_I_BIT;
 }
 
-#endif
-#endif
+#endif /* ifdef __KERNEL__ */
+#endif /* ifndef __ASM_ARM_IRQFLAGS_H */
index 14965658a923c5e99c009292ddc99f06d013738a..5b53b53ab5cf80f71e65b5e5298d5462652c05b5 100644 (file)
@@ -5,18 +5,15 @@
 
 typedef struct {
 #ifdef CONFIG_CPU_HAS_ASID
-       unsigned int id;
-       raw_spinlock_t id_lock;
+       u64 id;
 #endif
        unsigned int kvm_seq;
 } mm_context_t;
 
 #ifdef CONFIG_CPU_HAS_ASID
-#define ASID(mm)       ((mm)->context.id & 255)
-
-/* init_mm.context.id_lock should be initialized. */
-#define INIT_MM_CONTEXT(name)                                                 \
-       .context.id_lock    = __RAW_SPIN_LOCK_UNLOCKED(name.context.id_lock),
+#define ASID_BITS      8
+#define ASID_MASK      ((~0ULL) << ASID_BITS)
+#define ASID(mm)       ((mm)->context.id & ~ASID_MASK)
 #else
 #define ASID(mm)       (0)
 #endif
index 0306bc642c0d4fe7abd0368fd51477935e496c05..a64f61cb23d1926cbf506b2088bd9473e12f3d31 100644 (file)
@@ -24,84 +24,8 @@ void __check_kvm_seq(struct mm_struct *mm);
 
 #ifdef CONFIG_CPU_HAS_ASID
 
-/*
- * On ARMv6, we have the following structure in the Context ID:
- *
- * 31                         7          0
- * +-------------------------+-----------+
- * |      process ID         |   ASID    |
- * +-------------------------+-----------+
- * |              context ID             |
- * +-------------------------------------+
- *
- * The ASID is used to tag entries in the CPU caches and TLBs.
- * The context ID is used by debuggers and trace logic, and
- * should be unique within all running processes.
- */
-#define ASID_BITS              8
-#define ASID_MASK              ((~0) << ASID_BITS)
-#define ASID_FIRST_VERSION     (1 << ASID_BITS)
-
-extern unsigned int cpu_last_asid;
-
-void __init_new_context(struct task_struct *tsk, struct mm_struct *mm);
-void __new_context(struct mm_struct *mm);
-void cpu_set_reserved_ttbr0(void);
-
-static inline void switch_new_context(struct mm_struct *mm)
-{
-       unsigned long flags;
-
-       __new_context(mm);
-
-       local_irq_save(flags);
-       cpu_switch_mm(mm->pgd, mm);
-       local_irq_restore(flags);
-}
-
-static inline void check_and_switch_context(struct mm_struct *mm,
-                                           struct task_struct *tsk)
-{
-       if (unlikely(mm->context.kvm_seq != init_mm.context.kvm_seq))
-               __check_kvm_seq(mm);
-
-       /*
-        * Required during context switch to avoid speculative page table
-        * walking with the wrong TTBR.
-        */
-       cpu_set_reserved_ttbr0();
-
-       if (!((mm->context.id ^ cpu_last_asid) >> ASID_BITS))
-               /*
-                * The ASID is from the current generation, just switch to the
-                * new pgd. This condition is only true for calls from
-                * context_switch() and interrupts are already disabled.
-                */
-               cpu_switch_mm(mm->pgd, mm);
-       else if (irqs_disabled())
-               /*
-                * Defer the new ASID allocation until after the context
-                * switch critical region since __new_context() cannot be
-                * called with interrupts disabled (it sends IPIs).
-                */
-               set_ti_thread_flag(task_thread_info(tsk), TIF_SWITCH_MM);
-       else
-               /*
-                * That is a direct call to switch_mm() or activate_mm() with
-                * interrupts enabled and a new context.
-                */
-               switch_new_context(mm);
-}
-
-#define init_new_context(tsk,mm)       (__init_new_context(tsk,mm),0)
-
-#define finish_arch_post_lock_switch \
-       finish_arch_post_lock_switch
-static inline void finish_arch_post_lock_switch(void)
-{
-       if (test_and_clear_thread_flag(TIF_SWITCH_MM))
-               switch_new_context(current->mm);
-}
+void check_and_switch_context(struct mm_struct *mm, struct task_struct *tsk);
+#define init_new_context(tsk,mm)       ({ mm->context.id = 0; })
 
 #else  /* !CONFIG_CPU_HAS_ASID */
 
@@ -143,6 +67,7 @@ static inline void finish_arch_post_lock_switch(void)
 #endif /* CONFIG_CPU_HAS_ASID */
 
 #define destroy_context(mm)            do { } while(0)
+#define activate_mm(prev,next)         switch_mm(prev, next, NULL)
 
 /*
  * This is called when "tsk" is about to enter lazy TLB mode.
@@ -186,6 +111,5 @@ switch_mm(struct mm_struct *prev, struct mm_struct *next,
 }
 
 #define deactivate_mm(tsk,mm)  do { } while (0)
-#define activate_mm(prev,next) switch_mm(prev, next, NULL)
 
 #endif
index 625cd621a436db1d24d1d9ee53dffe0fe0ff70d8..00416edeceadaf1f8b68583a7c6d2e979fb2b1d3 100644 (file)
@@ -21,4 +21,9 @@
 #define C(_x)                          PERF_COUNT_HW_CACHE_##_x
 #define CACHE_OP_UNSUPPORTED           0xFFFF
 
+struct pt_regs;
+extern unsigned long perf_instruction_pointer(struct pt_regs *regs);
+extern unsigned long perf_misc_flags(struct pt_regs *regs);
+#define perf_misc_flags(regs)  perf_misc_flags(regs)
+
 #endif /* __ARM_PERF_EVENT_H__ */
index a26170dce02e4b735ddab00a5ead32883e07b1b2..f24edad26c70fd34fb9182179ae87618bbb72da8 100644 (file)
@@ -67,19 +67,19 @@ struct arm_pmu {
        cpumask_t       active_irqs;
        char            *name;
        irqreturn_t     (*handle_irq)(int irq_num, void *dev);
-       void            (*enable)(struct hw_perf_event *evt, int idx);
-       void            (*disable)(struct hw_perf_event *evt, int idx);
+       void            (*enable)(struct perf_event *event);
+       void            (*disable)(struct perf_event *event);
        int             (*get_event_idx)(struct pmu_hw_events *hw_events,
-                                        struct hw_perf_event *hwc);
+                                        struct perf_event *event);
        int             (*set_event_filter)(struct hw_perf_event *evt,
                                            struct perf_event_attr *attr);
-       u32             (*read_counter)(int idx);
-       void            (*write_counter)(int idx, u32 val);
-       void            (*start)(void);
-       void            (*stop)(void);
+       u32             (*read_counter)(struct perf_event *event);
+       void            (*write_counter)(struct perf_event *event, u32 val);
+       void            (*start)(struct arm_pmu *);
+       void            (*stop)(struct arm_pmu *);
        void            (*reset)(void *);
-       int             (*request_irq)(irq_handler_t handler);
-       void            (*free_irq)(void);
+       int             (*request_irq)(struct arm_pmu *, irq_handler_t handler);
+       void            (*free_irq)(struct arm_pmu *);
        int             (*map_event)(struct perf_event *event);
        int             num_events;
        atomic_t        active_events;
@@ -93,15 +93,11 @@ struct arm_pmu {
 
 extern const struct dev_pm_ops armpmu_dev_pm_ops;
 
-int armpmu_register(struct arm_pmu *armpmu, char *name, int type);
+int armpmu_register(struct arm_pmu *armpmu, int type);
 
-u64 armpmu_event_update(struct perf_event *event,
-                       struct hw_perf_event *hwc,
-                       int idx);
+u64 armpmu_event_update(struct perf_event *event);
 
-int armpmu_event_set_period(struct perf_event *event,
-                           struct hw_perf_event *hwc,
-                           int idx);
+int armpmu_event_set_period(struct perf_event *event);
 
 int armpmu_map_event(struct perf_event *event,
                     const unsigned (*event_map)[PERF_COUNT_HW_MAX],
index 06e7d509eaac218864cc9d089ce9e6f4177c22f9..5e61b88867963d65f8aad66b7b80aca784827fce 100644 (file)
@@ -49,7 +49,14 @@ struct thread_struct {
 #ifdef CONFIG_MMU
 #define nommu_start_thread(regs) do { } while (0)
 #else
+#ifndef CONFIG_CPU_V7M
 #define nommu_start_thread(regs) regs->ARM_r10 = current->mm->start_data
+#else
+#define nommu_start_thread(regs) do {                                  \
+       regs->ARM_r10 = current->mm->start_data;                        \
+       regs->ARM_EXC_RET = 0xfffffffdL;                                \
+} while (0)
+#endif
 #endif
 
 #define start_thread(regs,pc,sp)                                       \
index 3d52ee1bfb3113e113f231807dba71bc739ceac0..67661e8003ee2684f0a62e914cdd7b65b57912fe 100644 (file)
 
 #ifndef __ASSEMBLY__
 struct pt_regs {
+#ifdef CONFIG_CPU_V7M
+       unsigned long uregs[20];
+#else
        unsigned long uregs[18];
+#endif
 };
 
 #define user_mode(regs)        \
@@ -45,6 +49,7 @@ struct pt_regs {
  */
 static inline int valid_user_regs(struct pt_regs *regs)
 {
+#ifndef CONFIG_CPU_V7M
        unsigned long mode = regs->ARM_cpsr & MODE_MASK;
 
        /*
@@ -67,6 +72,9 @@ static inline int valid_user_regs(struct pt_regs *regs)
                regs->ARM_cpsr |= USR_MODE;
 
        return 0;
+#else /* ifndef CONFIG_CPU_V7M */
+       return 1;
+#endif
 }
 
 static inline long regs_return_value(struct pt_regs *regs)
index dfd386d0c022189ad0b9574c21db22039122d405..720ea0320a6d58a28189911ed714a4e3262569e2 100644 (file)
@@ -11,6 +11,7 @@
 #define CPU_ARCH_ARMv5TEJ      7
 #define CPU_ARCH_ARMv6         8
 #define CPU_ARCH_ARMv7         9
+#define CPU_ARCH_ARMv7M                10
 
 #ifndef __ASSEMBLY__
 
index 77bd79f2ffdbd0344d096ca7fb2db809fb52d387..7e1f76027f666e252c35bd320d4518e110548c47 100644 (file)
@@ -200,8 +200,8 @@ extern int __put_user_8(void *, unsigned long long);
 #define USER_DS                        KERNEL_DS
 
 #define segment_eq(a,b)                (1)
-#define __addr_ok(addr)                (1)
-#define __range_ok(addr,size)  (0)
+#define __addr_ok(addr)                ((void)(addr),1)
+#define __range_ok(addr,size)  ((void)(addr),0)
 #define get_fs()               (KERNEL_DS)
 
 static inline void set_fs(mm_segment_t fs)
index ae05e56dd17d6eb2e270117172dbc327f27b82d2..5000397134b4e5ceb06521ecf1d22622a0918a82 100644 (file)
 
 #ifndef __ASSEMBLY__
 /* Explicitly size integers that represent pfns in the interface with
- * Xen so that we can have one ABI that works for 32 and 64 bit guests. */
+ * Xen so that we can have one ABI that works for 32 and 64 bit guests.
+ * Note that this means that the xen_pfn_t type may be capable of
+ * representing pfn's which the guest cannot represent in its own pfn
+ * type. However since pfn space is controlled by the guest this is
+ * fine since it simply wouldn't be able to create any sure pfns in
+ * the first place.
+ */
 typedef uint64_t xen_pfn_t;
+#define PRI_xen_pfn "llx"
 typedef uint64_t xen_ulong_t;
+#define PRI_xen_ulong "llx"
 /* Guest handles for primitive C types. */
 __DEFINE_GUEST_HANDLE(uchar, unsigned char);
 __DEFINE_GUEST_HANDLE(uint,  unsigned int);
-__DEFINE_GUEST_HANDLE(ulong, unsigned long);
 DEFINE_GUEST_HANDLE(char);
 DEFINE_GUEST_HANDLE(int);
-DEFINE_GUEST_HANDLE(long);
 DEFINE_GUEST_HANDLE(void);
 DEFINE_GUEST_HANDLE(uint64_t);
 DEFINE_GUEST_HANDLE(uint32_t);
index 174202318dfff2779ece119e7b45949b82f429e0..c6b9096cef9593fe6508f13768802e1fba98d64c 100644 (file)
@@ -10,7 +10,7 @@
 #include <xen/interface/grant_table.h>
 
 #define pfn_to_mfn(pfn)                        (pfn)
-#define phys_to_machine_mapping_valid  (1)
+#define phys_to_machine_mapping_valid(pfn) (1)
 #define mfn_to_pfn(mfn)                        (mfn)
 #define mfn_to_virt(m)                 (__va(mfn_to_pfn(m) << PAGE_SHIFT))
 
@@ -30,6 +30,8 @@ typedef struct xpaddr {
 #define XMADDR(x)      ((xmaddr_t) { .maddr = (x) })
 #define XPADDR(x)      ((xpaddr_t) { .paddr = (x) })
 
+#define INVALID_P2M_ENTRY      (~0UL)
+
 static inline xmaddr_t phys_to_machine(xpaddr_t phys)
 {
        unsigned offset = phys.paddr & ~PAGE_MASK;
@@ -74,9 +76,14 @@ static inline int m2p_remove_override(struct page *page, bool clear_pte)
        return 0;
 }
 
+static inline bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn)
+{
+       BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY);
+       return true;
+}
+
 static inline bool set_phys_to_machine(unsigned long pfn, unsigned long mfn)
 {
-       BUG();
-       return false;
+       return __set_phys_to_machine(pfn, mfn);
 }
 #endif /* _ASM_ARM_XEN_PAGE_H */
similarity index 59%
rename from arch/arm/plat-mxc/include/mach/debug-macro.S
rename to arch/arm/include/debug/imx.S
index 761e45f9456f1a8adfe3806b2b157dcc186e21ce..0b65d792f6640433a2bc51c3fed50525c899ef63 100644 (file)
  * published by the Free Software Foundation.
  *
  */
-#include <mach/hardware.h>
-
 #ifdef CONFIG_DEBUG_IMX1_UART
-#define UART_PADDR     MX1_UART1_BASE_ADDR
+#define UART_PADDR     0x00206000
 #elif defined (CONFIG_DEBUG_IMX25_UART)
-#define UART_PADDR     MX25_UART1_BASE_ADDR
+#define UART_PADDR     0x43f90000
 #elif defined (CONFIG_DEBUG_IMX21_IMX27_UART)
-#define UART_PADDR     MX2x_UART1_BASE_ADDR
+#define UART_PADDR     0x1000a000
 #elif defined (CONFIG_DEBUG_IMX31_IMX35_UART)
-#define UART_PADDR     MX3x_UART1_BASE_ADDR
+#define UART_PADDR     0x43f90000
 #elif defined (CONFIG_DEBUG_IMX51_UART)
-#define UART_PADDR     MX51_UART1_BASE_ADDR
+#define UART_PADDR     0x73fbc000
 #elif defined (CONFIG_DEBUG_IMX50_IMX53_UART)
-#define UART_PADDR     MX53_UART1_BASE_ADDR
+#define UART_PADDR     0x53fbc000
 #elif defined (CONFIG_DEBUG_IMX6Q_UART2)
-#define UART_PADDR     MX6Q_UART2_BASE_ADDR
+#define UART_PADDR     0x021e8000
 #elif defined (CONFIG_DEBUG_IMX6Q_UART4)
-#define UART_PADDR     MX6Q_UART4_BASE_ADDR
+#define UART_PADDR     0x021f0000
 #endif
 
-#define UART_VADDR     IMX_IO_ADDRESS(UART_PADDR)
+/*
+ * FIXME: This is a copy of IMX_IO_P2V in hardware.h, and needs to
+ * stay sync with that.  It's hard to maintain, and should be fixed
+ * globally for multi-platform build to use a fixed virtual address
+ * for low-level debug uart port across platforms.
+ */
+#define IMX_IO_P2V(x)  (                                               \
+                       (((x) & 0x80000000) >> 7) |                     \
+                       (0xf4000000 +                                   \
+                       (((x) & 0x50000000) >> 6) +                     \
+                       (((x) & 0x0b000000) >> 4) +                     \
+                       (((x) & 0x000fffff))))
+
+#define UART_VADDR     IMX_IO_P2V(UART_PADDR)
 
                .macro  addruart, rp, rv, tmp
                ldr     \rp, =UART_PADDR        @ physical
index 96ee0929790f5d5ad2156f2262c9efb809f7cc3e..2ae7d1be24670ae3e16836163b0b6b6aa5e5a2b4 100644 (file)
 
 /*
  * PSR bits
+ * Note on V7M there is no mode contained in the PSR
  */
 #define USR26_MODE     0x00000000
 #define FIQ26_MODE     0x00000001
 #define IRQ26_MODE     0x00000002
 #define SVC26_MODE     0x00000003
+#if defined(__KERNEL__) && defined(CONFIG_CPU_V7M)
+/*
+ * Use 0 here to get code right that creates a userspace
+ * or kernel space thread.
+ */
+#define USR_MODE       0x00000000
+#define SVC_MODE       0x00000000
+#else
 #define USR_MODE       0x00000010
+#define SVC_MODE       0x00000013
+#endif
 #define FIQ_MODE       0x00000011
 #define IRQ_MODE       0x00000012
-#define SVC_MODE       0x00000013
 #define ABT_MODE       0x00000017
 #define HYP_MODE       0x0000001a
 #define UND_MODE       0x0000001b
 #define SYSTEM_MODE    0x0000001f
 #define MODE32_BIT     0x00000010
 #define MODE_MASK      0x0000001f
-#define PSR_T_BIT      0x00000020
-#define PSR_F_BIT      0x00000040
-#define PSR_I_BIT      0x00000080
-#define PSR_A_BIT      0x00000100
-#define PSR_E_BIT      0x00000200
-#define PSR_J_BIT      0x01000000
-#define PSR_Q_BIT      0x08000000
+
+#define V4_PSR_T_BIT   0x00000020      /* >= V4T, but not V7M */
+#define V7M_PSR_T_BIT  0x01000000
+#if defined(__KERNEL__) && defined(CONFIG_CPU_V7M)
+#define PSR_T_BIT      V7M_PSR_T_BIT
+#else
+/* for compatibility */
+#define PSR_T_BIT      V4_PSR_T_BIT
+#endif
+
+#define PSR_F_BIT      0x00000040      /* >= V4, but not V7M */
+#define PSR_I_BIT      0x00000080      /* >= V4, but not V7M */
+#define PSR_A_BIT      0x00000100      /* >= V6, but not V7M */
+#define PSR_E_BIT      0x00000200      /* >= V6, but not V7M */
+#define PSR_J_BIT      0x01000000      /* >= V5J, but not V7M */
+#define PSR_Q_BIT      0x08000000      /* >= V5E, including V7M */
 #define PSR_V_BIT      0x10000000
 #define PSR_C_BIT      0x20000000
 #define PSR_Z_BIT      0x40000000
@@ -125,6 +144,7 @@ struct pt_regs {
 #define ARM_r1         uregs[1]
 #define ARM_r0         uregs[0]
 #define ARM_ORIG_r0    uregs[17]
+#define ARM_EXC_RET    uregs[18]
 
 /*
  * The size of the user-visible VFP state as seen by PTRACE_GET/SETVFPREGS
index ac03bdb4ae442a5e7b0a69cf0252ad84894c1b58..4da7cde70b5d3fac435bdbf13b3dcc9c298be4c7 100644 (file)
 #define __NR_process_vm_readv          (__NR_SYSCALL_BASE+376)
 #define __NR_process_vm_writev         (__NR_SYSCALL_BASE+377)
                                        /* 378 for kcmp */
+#define __NR_finit_module              (__NR_SYSCALL_BASE+379)
 
 /*
  * This may need to be greater than __NR_last_syscall+1 in order to
index c985b481192c2643e938425a57e3e6fc9866ba90..5fe9ace8a6683bdb75d3360201fcc2aab0d29ea4 100644 (file)
@@ -93,6 +93,9 @@ int main(void)
   DEFINE(S_PC,                 offsetof(struct pt_regs, ARM_pc));
   DEFINE(S_PSR,                        offsetof(struct pt_regs, ARM_cpsr));
   DEFINE(S_OLD_R0,             offsetof(struct pt_regs, ARM_ORIG_r0));
+#ifdef CONFIG_CPU_V7M
+  DEFINE(S_EXC_RET,            offsetof(struct pt_regs, ARM_EXC_RET));
+#endif
   DEFINE(S_FRAME_SIZE,         sizeof(struct pt_regs));
   BLANK();
 #ifdef CONFIG_CACHE_L2X0
index 831cd38c8d997b32f895fa077f3745c08879d99d..36e27df01b479ace6d19dd85a928777ba776ff71 100644 (file)
                CALL(sys_process_vm_readv)
                CALL(sys_process_vm_writev)
                CALL(sys_ni_syscall)    /* reserved for sys_kcmp */
+               CALL(sys_finit_module)
 #ifndef syscalls_counted
 .equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
 #define syscalls_counted
index 34711757ba59a958592d31ea527170c1356c282c..48d8dc033871fc3858366d446163780e5a9e74e6 100644 (file)
@@ -339,6 +339,9 @@ ENDPROC(ftrace_stub)
 
        .align  5
 ENTRY(vector_swi)
+#ifdef CONFIG_CPU_V7M
+       v7m_exception_entry
+#else
        sub     sp, sp, #S_FRAME_SIZE
        stmia   sp, {r0 - r12}                  @ Calling r0 - r12
  ARM(  add     r8, sp, #S_PC           )
@@ -349,6 +352,7 @@ ENTRY(vector_swi)
        str     lr, [sp, #S_PC]                 @ Save calling PC
        str     r8, [sp, #S_PSR]                @ Save CPSR
        str     r0, [sp, #S_OLD_R0]             @ Save OLD_R0
+#endif
        zero_fp
 
        /*
index 9a8531eadd3da437ccadd6f5b60eac6a16808607..33d9900d04ee13e06d13ee5c3e4094d39704bb58 100644 (file)
 #endif
        .endm
 
+#ifdef CONFIG_CPU_V7M
+/*
+ * ARMv7-M exception entry/exit macros.
+ *
+ * xPSR, ReturnAddress(), LR (R14), R12, R3, R2, R1, and R0 are
+ * automatically saved on the current stack (32 words) before
+ * switching to the exception stack (SP_main).
+ *
+ * If exception is taken while in user mode, SP_main is
+ * empty. Otherwise, SP_main is aligned to 64 bit automatically
+ * (CCR.STKALIGN set).
+ *
+ * Linux assumes that the interrupts are disabled when entering an
+ * exception handler and it may BUG if this is not the case. Interrupts
+ * are disabled during entry and reenabled in the exit macro.
+ *
+ * v7m_exception_fast_exit is used when returning from interrupts.
+ *
+ * v7m_exception_slow_exit is used when returning from SVC or PendSV.
+ * When returning to kernel mode, we don't return from exception.
+ */
+       .macro  v7m_exception_entry
+       @ determine the location of the registers saved by the core during
+       @ exception entry. Depending on the mode the cpu was in when the
+       @ exception happend that is either on the main or the process stack.
+       @ Bit 2 of EXC_RETURN stored in the lr register specifies which stack
+       @ was used.
+       tst     lr, #0x4
+       mrsne   r12, psp
+       moveq   r12, sp
+
+       @ we cannot rely on r0-r3 and r12 matching the value saved in the
+       @ exception frame because of tail-chaining. So these have to be
+       @ reloaded.
+       ldmia   r12!, {r0-r3}
+
+       @ Linux expects to have irqs off. Do it here before taking stack space
+       cpsid   i
+
+       sub     sp, #S_FRAME_SIZE-S_IP
+       stmdb   sp!, {r0-r11}
+
+       @ load saved r12, lr, return address and xPSR.
+       @ r0-r7 are used for signals and never touched from now on. Clobbering
+       @ r8-r12 is OK.
+       mov     r9, r12
+       ldmia   r9!, {r8, r10-r12}
+
+       @ calculate the original stack pointer value.
+       @ r9 currently points to the memory location just above the auto saved
+       @ xPSR. If the FP extension is implemented and bit 4 of EXC_RETURN is 0
+       @ then space was allocated for FP state. That is space for 18 32-bit
+       @ values. (If FP extension is unimplemented, bit 4 is 1.)
+       @ Additionally the cpu might automatically 8-byte align the stack. Bit 9
+       @ of the saved xPSR specifies if stack aligning took place. In this case
+       @ another 32-bit value is included in the stack.
+
+       tst     lr, #0x10
+       addeq   r9, r9, #576
+
+       tst     r12, 0x100
+       addne   r9, r9, #4
+
+       @ store saved r12 using str to have a register to hold the base for stm
+       str     r8, [sp, #S_IP]
+       add     r8, sp, #S_SP
+       @ store r13-r15, xPSR
+       stmia   r8!, {r9-r12}
+       @ store r0 once more and EXC_RETURN
+       stmia   r8, {r0, lr}
+       .endm
+
+       .macro  v7m_exception_fast_exit
+       @ registers r0-r3 and r12 are automatically restored on exception
+       @ return. r4-r7 were not clobbered in v7m_exception_entry so for
+       @ correctness they don't need to be restored. So only r8-r11 must be
+       @ restored here. The easiest way to do so is to restore r0-r7, too.
+       ldmia   sp!, {r0-r11}
+       add     sp, #S_FRAME_SIZE-S_IP
+       cpsie   i
+       bx      lr
+       .endm
+
+       .macro  v7m_exception_slow_exit ret_r0
+       cpsid   i
+       ldr     lr, [sp, #S_EXC_RET]    @ read exception LR
+       tst     lr, #0x8
+       bne     1f                      @ go to thread mode using exception return
+
+       /*
+        * return to kernel thread
+        * sp is already set up (and might be unset in pt_regs), so only
+        * restore r0-r12 and pc
+        */
+       ldmia   sp, {r0-r12}
+       ldr     lr, [sp, #S_PC]
+       add     sp, sp, #S_FRAME_SIZE
+       cpsie   i
+       bx      lr
+
+1:     /*
+        * return to userspace
+        */
+
+       @ read original r12, sp, lr, pc and xPSR
+       add     r12, sp, #S_IP
+       ldmia   r12, {r1-r5}
+
+       @ handle stack aligning
+       tst     r5, #0x100
+       subne   r2, r2, #4
+
+       @ skip over stack space for fp saving
+       tst     lr, #0x10
+       subeq   r2, r2, #576
+
+       @ write basic exception frame
+       stmdb   r2!, {r1, r3-r5}
+       ldmia   sp, {r1, r3-r5}
+       .if     \ret_r0
+       stmdb   r2!, {r0, r3-r5}
+       .else
+       stmdb   r2!, {r1, r3-r5}
+       .endif
+
+       @ restore process sp
+       msr     psp, r2
+
+       @ restore original r4-r11
+       ldmia   sp!, {r0-r11}
+
+       @ restore main sp
+       add     sp, sp, #S_FRAME_SIZE-S_IP
+
+       cpsie   i
+       bx      lr
+       .endm
+#endif /* CONFIG_CPU_V7M */
+
        @
        @ Store/load the USER SP and LR registers by switching to the SYS
        @ mode. Useful in Thumb-2 mode where "stm/ldm rd, {sp, lr}^" is not
        rfeia   sp!
        .endm
 
+#ifdef CONFIG_CPU_V7M
+       .macro  restore_user_regs, fast = 0, offset = 0
+       .if     \offset
+       add     sp, #\offset
+       .endif
+       v7m_exception_slow_exit ret_r0 = \fast
+       .endm
+#else  /* !CONFIG_CPU_V7M */
        .macro  restore_user_regs, fast = 0, offset = 0
        clrex                                   @ clear the exclusive monitor
        mov     r2, sp
        add     sp, sp, #S_FRAME_SIZE - S_SP
        movs    pc, lr                          @ return & move spsr_svc into cpsr
        .endm
+#endif /* CONFIG_CPU_V7M */
 
        .macro  get_thread_info, rd
        mov     \rd, sp
diff --git a/arch/arm/kernel/entry-v7m.S b/arch/arm/kernel/entry-v7m.S
new file mode 100644 (file)
index 0000000..a0991dc
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * linux/arch/arm/kernel/entry-v7m.S
+ *
+ * Copyright (C) 2008 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Low-level vector interface routines for the ARMv7-M architecture
+ */
+#include <asm/memory.h>
+#include <asm/glue.h>
+#include <asm/thread_notify.h>
+
+#include <mach/entry-macro.S>
+
+#include "entry-header.S"
+
+#ifdef CONFIG_PREEMPT
+#error "CONFIG_PREEMPT not supported on the current ARMv7M implementation"
+#endif
+#ifdef CONFIG_TRACE_IRQFLAGS
+#error "CONFIG_TRACE_IRQFLAGS not supported on the current ARMv7M implementation"
+#endif
+
+__invalid_entry:
+       v7m_exception_entry
+       adr     r0, strerr
+       mrs     r1, ipsr
+       mov     r2, lr
+       bl      printk
+       mov     r0, sp
+       bl      show_regs
+1:     b       1b
+ENDPROC(__invalid_entry)
+
+strerr:        .asciz  "\nUnhandled exception: IPSR = %08lx LR = %08lx\n"
+
+       .align  2
+__irq_entry:
+       v7m_exception_entry
+
+       @
+       @ Invoke the IRQ handler
+       @
+       mrs     r0, ipsr
+       and     r0, #0xff
+       sub     r0, #16                 @ IRQ number
+       mov     r1, sp
+       @ routine called with r0 = irq number, r1 = struct pt_regs *
+       bl      asm_do_IRQ
+
+       @
+       @ Check for any pending work if returning to user
+       @
+       ldr     lr, [sp, #S_EXC_RET]
+       tst     lr, #0x8                @ check the return stack
+       beq     2f                      @ returning to handler mode
+       get_thread_info tsk
+       ldr     r1, [tsk, #TI_FLAGS]
+       tst     r1, #_TIF_WORK_MASK
+       beq     2f                      @ no work pending
+       ldr     r1, =0xe000ed04         @ ICSR
+       mov     r0, #1 << 28            @ ICSR.PENDSVSET
+       str     r0, [r1]                @ raise PendSV
+
+2:
+       v7m_exception_fast_exit
+ENDPROC(__irq_entry)
+
+__pendsv_entry:
+       v7m_exception_entry
+
+       ldr     r1, =0xe000ed04         @ ICSR
+       mov     r0, #1 << 27            @ ICSR.PENDSVCLR
+       str     r0, [r1]                @ clear PendSV
+
+       @ execute the pending work, including reschedule
+       get_thread_info tsk
+       mov     why, #0
+       b       ret_to_user
+ENDPROC(__pendsv_entry)
+
+/*
+ * Register switch for ARMv7-M processors.
+ * r0 = previous task_struct, r1 = previous thread_info, r2 = next thread_info
+ * previous and next are guaranteed not to be the same.
+ */
+ENTRY(__switch_to)
+       .fnstart
+       .cantunwind
+       add     ip, r1, #TI_CPU_SAVE
+       stmia   ip!, {r4 - r11}         @ Store most regs on stack
+       str     sp, [ip], #4
+       str     lr, [ip], #4
+       mov     r5, r0
+       add     r4, r2, #TI_CPU_SAVE
+       ldr     r0, =thread_notify_head
+       mov     r1, #THREAD_NOTIFY_SWITCH
+       bl      atomic_notifier_call_chain
+       mov     ip, r4
+       mov     r0, r5
+       ldmia   ip!, {r4 - r11}         @ Load all regs saved previously
+       ldr     sp, [ip], #4
+       ldr     pc, [ip]
+       .fnend
+ENDPROC(__switch_to)
+
+       .data
+       .align  8
+/*
+ * Vector table (64 words => 256 bytes natural alignment)
+ */
+ENTRY(vector_table)
+       .long   0                       @ 0 - Reset stack pointer
+       .long   __invalid_entry         @ 1 - Reset
+       .long   __invalid_entry         @ 2 - NMI
+       .long   __invalid_entry         @ 3 - HardFault
+       .long   __invalid_entry         @ 4 - MemManage
+       .long   __invalid_entry         @ 5 - BusFault
+       .long   __invalid_entry         @ 6 - UsageFault
+       .long   __invalid_entry         @ 7 - Reserved
+       .long   __invalid_entry         @ 8 - Reserved
+       .long   __invalid_entry         @ 9 - Reserved
+       .long   __invalid_entry         @ 10 - Reserved
+       .long   vector_swi              @ 11 - SVCall
+       .long   __invalid_entry         @ 12 - Debug Monitor
+       .long   __invalid_entry         @ 13 - Reserved
+       .long   __pendsv_entry          @ 14 - PendSV
+       .long   __invalid_entry         @ 15 - SysTick
+       .rept   64 - 16
+       .long   __irq_entry             @ 16..64 - External Interrupts
+       .endr
index 854bd22380d335dba0e6761c317ccf6f45d3b447..2f560c575e0d67d926259846d8b0568d30f2ded1 100644 (file)
@@ -98,8 +98,9 @@ __mmap_switched:
        str     r9, [r4]                        @ Save processor ID
        str     r1, [r5]                        @ Save machine type
        str     r2, [r6]                        @ Save atags pointer
-       bic     r4, r0, #CR_A                   @ Clear 'A' bit
-       stmia   r7, {r0, r4}                    @ Save control register values
+       cmp     r7, #0
+       bicne   r4, r0, #CR_A                   @ Clear 'A' bit
+       stmneia r7, {r0, r4}                    @ Save control register values
        b       start_kernel
 ENDPROC(__mmap_switched)
 
@@ -113,7 +114,11 @@ __mmap_switched_data:
        .long   processor_id                    @ r4
        .long   __machine_arch_type             @ r5
        .long   __atags_pointer                 @ r6
+#ifdef CONFIG_CPU_CP15
        .long   cr_alignment                    @ r7
+#else
+       .long   0
+#endif
        .long   init_thread_union + THREAD_START_SP @ sp
        .size   __mmap_switched_data, . - __mmap_switched_data
 
index 278cfc144f448012100d594c0f81041cdfbf474c..c391c05ba69f0d46847a514e27ae8eb0b692495e 100644 (file)
@@ -44,10 +44,13 @@ ENTRY(stext)
 
        setmode PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9 @ ensure svc mode
                                                @ and irqs disabled
-#ifndef CONFIG_CPU_CP15
-       ldr     r9, =CONFIG_PROCESSOR_ID
-#else
+#if defined(CONFIG_CPU_CP15)
        mrc     p15, 0, r9, c0, c0              @ get processor id
+#elif defined(CONFIG_CPU_V7M)
+       ldr     r9, =0xe000ed00                 @ CPUID register address
+       ldr     r9, [r9]
+#else
+       ldr     r9, =CONFIG_PROCESSOR_ID
 #endif
        bl      __lookup_processor_type         @ r5=procinfo r9=cpuid
        movs    r10, r5                         @ invalid processor (r5=0)?
index 281bf3301241fba2a1ce1baafeaf3020b7cd57ff..05fdd68437953dd4f7a60af7413eb10cc6c7e984 100644 (file)
@@ -52,14 +52,14 @@ static u8 debug_arch;
 /* Maximum supported watchpoint length. */
 static u8 max_watchpoint_len;
 
-#define READ_WB_REG_CASE(OP2, M, VAL)          \
-       case ((OP2 << 4) + M):                  \
-               ARM_DBG_READ(c ## M, OP2, VAL); \
+#define READ_WB_REG_CASE(OP2, M, VAL)                  \
+       case ((OP2 << 4) + M):                          \
+               ARM_DBG_READ(c0, c ## M, OP2, VAL);     \
                break
 
-#define WRITE_WB_REG_CASE(OP2, M, VAL)         \
-       case ((OP2 << 4) + M):                  \
-               ARM_DBG_WRITE(c ## M, OP2, VAL);\
+#define WRITE_WB_REG_CASE(OP2, M, VAL)                 \
+       case ((OP2 << 4) + M):                          \
+               ARM_DBG_WRITE(c0, c ## M, OP2, VAL);    \
                break
 
 #define GEN_READ_WB_REG_CASES(OP2, VAL)                \
@@ -135,13 +135,12 @@ static u8 get_debug_arch(void)
        u32 didr;
 
        /* Do we implement the extended CPUID interface? */
-       if (((read_cpuid_id() >> 16) & 0xf) != 0xf) {
-               pr_warning("CPUID feature registers not supported. "
-                          "Assuming v6 debug is present.\n");
+       if (WARN_ONCE(((read_cpuid_id() >> 16) & 0xf) != 0xf,
+               "CPUID feature registers not supported. "
+               "Assuming v6 debug is present.\n"))
                return ARM_DEBUG_ARCH_V6;
-       }
 
-       ARM_DBG_READ(c0, 0, didr);
+       ARM_DBG_READ(c0, c0, 0, didr);
        return (didr >> 16) & 0xf;
 }
 
@@ -169,7 +168,7 @@ static int debug_exception_updates_fsr(void)
 static int get_num_wrp_resources(void)
 {
        u32 didr;
-       ARM_DBG_READ(c0, 0, didr);
+       ARM_DBG_READ(c0, c0, 0, didr);
        return ((didr >> 28) & 0xf) + 1;
 }
 
@@ -177,7 +176,7 @@ static int get_num_wrp_resources(void)
 static int get_num_brp_resources(void)
 {
        u32 didr;
-       ARM_DBG_READ(c0, 0, didr);
+       ARM_DBG_READ(c0, c0, 0, didr);
        return ((didr >> 24) & 0xf) + 1;
 }
 
@@ -228,19 +227,17 @@ static int get_num_brps(void)
  * be put into halting debug mode at any time by an external debugger
  * but there is nothing we can do to prevent that.
  */
-static int enable_monitor_mode(void)
+static int monitor_mode_enabled(void)
 {
        u32 dscr;
-       int ret = 0;
-
-       ARM_DBG_READ(c1, 0, dscr);
+       ARM_DBG_READ(c0, c1, 0, dscr);
+       return !!(dscr & ARM_DSCR_MDBGEN);
+}
 
-       /* Ensure that halting mode is disabled. */
-       if (WARN_ONCE(dscr & ARM_DSCR_HDBGEN,
-               "halting debug mode enabled. Unable to access hardware resources.\n")) {
-               ret = -EPERM;
-               goto out;
-       }
+static int enable_monitor_mode(void)
+{
+       u32 dscr;
+       ARM_DBG_READ(c0, c1, 0, dscr);
 
        /* If monitor mode is already enabled, just return. */
        if (dscr & ARM_DSCR_MDBGEN)
@@ -250,24 +247,26 @@ static int enable_monitor_mode(void)
        switch (get_debug_arch()) {
        case ARM_DEBUG_ARCH_V6:
        case ARM_DEBUG_ARCH_V6_1:
-               ARM_DBG_WRITE(c1, 0, (dscr | ARM_DSCR_MDBGEN));
+               ARM_DBG_WRITE(c0, c1, 0, (dscr | ARM_DSCR_MDBGEN));
                break;
        case ARM_DEBUG_ARCH_V7_ECP14:
        case ARM_DEBUG_ARCH_V7_1:
-               ARM_DBG_WRITE(c2, 2, (dscr | ARM_DSCR_MDBGEN));
+               ARM_DBG_WRITE(c0, c2, 2, (dscr | ARM_DSCR_MDBGEN));
+               isb();
                break;
        default:
-               ret = -ENODEV;
-               goto out;
+               return -ENODEV;
        }
 
        /* Check that the write made it through. */
-       ARM_DBG_READ(c1, 0, dscr);
-       if (!(dscr & ARM_DSCR_MDBGEN))
-               ret = -EPERM;
+       ARM_DBG_READ(c0, c1, 0, dscr);
+       if (WARN_ONCE(!(dscr & ARM_DSCR_MDBGEN),
+               "Failed to enable monitor mode on CPU %d.\n",
+               smp_processor_id()))
+               return -EPERM;
 
 out:
-       return ret;
+       return 0;
 }
 
 int hw_breakpoint_slots(int type)
@@ -328,14 +327,9 @@ int arch_install_hw_breakpoint(struct perf_event *bp)
 {
        struct arch_hw_breakpoint *info = counter_arch_bp(bp);
        struct perf_event **slot, **slots;
-       int i, max_slots, ctrl_base, val_base, ret = 0;
+       int i, max_slots, ctrl_base, val_base;
        u32 addr, ctrl;
 
-       /* Ensure that we are in monitor mode and halting mode is disabled. */
-       ret = enable_monitor_mode();
-       if (ret)
-               goto out;
-
        addr = info->address;
        ctrl = encode_ctrl_reg(info->ctrl) | 0x1;
 
@@ -362,10 +356,8 @@ int arch_install_hw_breakpoint(struct perf_event *bp)
                }
        }
 
-       if (WARN_ONCE(i == max_slots, "Can't find any breakpoint slot\n")) {
-               ret = -EBUSY;
-               goto out;
-       }
+       if (WARN_ONCE(i == max_slots, "Can't find any breakpoint slot\n"))
+               return -EBUSY;
 
        /* Override the breakpoint data with the step data. */
        if (info->step_ctrl.enabled) {
@@ -383,9 +375,7 @@ int arch_install_hw_breakpoint(struct perf_event *bp)
 
        /* Setup the control register. */
        write_wb_reg(ctrl_base + i, ctrl);
-
-out:
-       return ret;
+       return 0;
 }
 
 void arch_uninstall_hw_breakpoint(struct perf_event *bp)
@@ -596,6 +586,10 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp)
        int ret = 0;
        u32 offset, alignment_mask = 0x3;
 
+       /* Ensure that we are in monitor debug mode. */
+       if (!monitor_mode_enabled())
+               return -ENODEV;
+
        /* Build the arch_hw_breakpoint. */
        ret = arch_build_bp_info(bp);
        if (ret)
@@ -858,7 +852,7 @@ static int hw_breakpoint_pending(unsigned long addr, unsigned int fsr,
                local_irq_enable();
 
        /* We only handle watchpoints and hardware breakpoints. */
-       ARM_DBG_READ(c1, 0, dscr);
+       ARM_DBG_READ(c0, c1, 0, dscr);
 
        /* Perform perf callbacks. */
        switch (ARM_DSCR_MOE(dscr)) {
@@ -919,22 +913,29 @@ static void reset_ctrl_regs(void *unused)
        switch (debug_arch) {
        case ARM_DEBUG_ARCH_V6:
        case ARM_DEBUG_ARCH_V6_1:
-               /* ARMv6 cores just need to reset the registers. */
-               goto reset_regs;
+               /* ARMv6 cores clear the registers out of reset. */
+               goto out_mdbgen;
        case ARM_DEBUG_ARCH_V7_ECP14:
                /*
                 * Ensure sticky power-down is clear (i.e. debug logic is
                 * powered up).
                 */
-               asm volatile("mrc p14, 0, %0, c1, c5, 4" : "=r" (dbg_power));
+               ARM_DBG_READ(c1, c5, 4, dbg_power);
                if ((dbg_power & 0x1) == 0)
                        err = -EPERM;
+
+               /*
+                * Check whether we implement OS save and restore.
+                */
+               ARM_DBG_READ(c1, c1, 4, dbg_power);
+               if ((dbg_power & 0x9) == 0)
+                       goto clear_vcr;
                break;
        case ARM_DEBUG_ARCH_V7_1:
                /*
                 * Ensure the OS double lock is clear.
                 */
-               asm volatile("mrc p14, 0, %0, c1, c3, 4" : "=r" (dbg_power));
+               ARM_DBG_READ(c1, c3, 4, dbg_power);
                if ((dbg_power & 0x1) == 1)
                        err = -EPERM;
                break;
@@ -947,24 +948,29 @@ static void reset_ctrl_regs(void *unused)
        }
 
        /*
-        * Unconditionally clear the lock by writing a value
+        * Unconditionally clear the OS lock by writing a value
         * other than 0xC5ACCE55 to the access register.
         */
-       asm volatile("mcr p14, 0, %0, c1, c0, 4" : : "r" (0));
+       ARM_DBG_WRITE(c1, c0, 4, 0);
        isb();
 
        /*
         * Clear any configured vector-catch events before
         * enabling monitor mode.
         */
-       asm volatile("mcr p14, 0, %0, c0, c7, 0" : : "r" (0));
+clear_vcr:
+       ARM_DBG_WRITE(c0, c7, 0, 0);
        isb();
 
-reset_regs:
-       if (enable_monitor_mode())
+       if (cpumask_intersects(&debug_err_mask, cpumask_of(cpu))) {
+               pr_warning("CPU %d failed to disable vector catch\n", cpu);
                return;
+       }
 
-       /* We must also reset any reserved registers. */
+       /*
+        * The control/value register pairs are UNKNOWN out of reset so
+        * clear them to avoid spurious debug events.
+        */
        raw_num_brps = get_num_brp_resources();
        for (i = 0; i < raw_num_brps; ++i) {
                write_wb_reg(ARM_BASE_BCR + i, 0UL);
@@ -975,6 +981,19 @@ reset_regs:
                write_wb_reg(ARM_BASE_WCR + i, 0UL);
                write_wb_reg(ARM_BASE_WVR + i, 0UL);
        }
+
+       if (cpumask_intersects(&debug_err_mask, cpumask_of(cpu))) {
+               pr_warning("CPU %d failed to clear debug register pairs\n", cpu);
+               return;
+       }
+
+       /*
+        * Have a crack at enabling monitor mode. We don't actually need
+        * it yet, but reporting an error early is useful if it fails.
+        */
+out_mdbgen:
+       if (enable_monitor_mode())
+               cpumask_or(&debug_err_mask, &debug_err_mask, cpumask_of(cpu));
 }
 
 static int __cpuinit dbg_reset_notify(struct notifier_block *self,
@@ -992,8 +1011,6 @@ static struct notifier_block __cpuinitdata dbg_reset_nb = {
 
 static int __init arch_hw_breakpoint_init(void)
 {
-       u32 dscr;
-
        debug_arch = get_debug_arch();
 
        if (!debug_arch_supported()) {
@@ -1028,17 +1045,10 @@ static int __init arch_hw_breakpoint_init(void)
                core_num_brps, core_has_mismatch_brps() ? "(+1 reserved) " :
                "", core_num_wrps);
 
-       ARM_DBG_READ(c1, 0, dscr);
-       if (dscr & ARM_DSCR_HDBGEN) {
-               max_watchpoint_len = 4;
-               pr_warning("halting debug mode enabled. Assuming maximum watchpoint size of %u bytes.\n",
-                          max_watchpoint_len);
-       } else {
-               /* Work out the maximum supported watchpoint length. */
-               max_watchpoint_len = get_max_wp_len();
-               pr_info("maximum watchpoint size is %u bytes.\n",
-                               max_watchpoint_len);
-       }
+       /* Work out the maximum supported watchpoint length. */
+       max_watchpoint_len = get_max_wp_len();
+       pr_info("maximum watchpoint size is %u bytes.\n",
+                       max_watchpoint_len);
 
        /* Register debug fault handler. */
        hook_fault_code(FAULT_CODE_DEBUG, hw_breakpoint_pending, SIGTRAP,
index 16cedb42c0c39c0169008e45488b279cd9b32821..896165096d6a936572bdcfd0d21cc23f01cb9ea2 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/list.h>
 #include <linux/kallsyms.h>
 #include <linux/proc_fs.h>
+#include <linux/export.h>
 
 #include <asm/exception.h>
 #include <asm/mach/arch.h>
@@ -109,6 +110,7 @@ void set_irq_flags(unsigned int irq, unsigned int iflags)
        /* Order is clear bits in "clr" then set bits in "set" */
        irq_modify_status(irq, clr, set & ~clr);
 }
+EXPORT_SYMBOL_GPL(set_irq_flags);
 
 void __init init_IRQ(void)
 {
index 38c1a3b103a0684b5b579bb74ca07f38bb91eb13..83931290506704ad226e8a8cb2a15b52a33d4494 100644 (file)
@@ -366,7 +366,9 @@ void kprobe_arm_test_cases(void)
        TEST_UNSUPPORTED(".word 0xe04f0392 @ umaal r0, pc, r2, r3")
        TEST_UNSUPPORTED(".word 0xe0500090 @ undef")
        TEST_UNSUPPORTED(".word 0xe05fff9f @ undef")
+#endif
 
+#if __LINUX_ARM_ARCH__ >= 7
        TEST_RRR(  "mls         r0, r",1, VAL1,", r",2, VAL2,", r",3,  VAL3,"")
        TEST_RRR(  "mlshi       r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
        TEST_RR(   "mls         lr, r",1, VAL2,", r",2, VAL3,", r13")
@@ -456,6 +458,8 @@ void kprobe_arm_test_cases(void)
        TEST_UNSUPPORTED(".word 0xe1700090") /* Unallocated space */
 #if __LINUX_ARM_ARCH__ >= 6
        TEST_UNSUPPORTED("ldrex r2, [sp]")
+#endif
+#if (__LINUX_ARM_ARCH__ >= 7) || defined(CONFIG_CPU_32v6K)
        TEST_UNSUPPORTED("strexd        r0, r2, r3, [sp]")
        TEST_UNSUPPORTED("ldrexd        r2, r3, [sp]")
        TEST_UNSUPPORTED("strexb        r0, r2, [sp]")
index e29c3337ca8142aeb6f4bb755e3947d6aecd4fbe..8ef8c9337809cbe5ccb91b33525c38a379e9e986 100644 (file)
@@ -45,10 +45,9 @@ int machine_kexec_prepare(struct kimage *image)
        for (i = 0; i < image->nr_segments; i++) {
                current_segment = &image->segment[i];
 
-               err = memblock_is_region_memory(current_segment->mem,
-                                               current_segment->memsz);
-               if (err)
-                       return - EINVAL;
+               if (!memblock_is_region_memory(current_segment->mem,
+                                              current_segment->memsz))
+                       return -EINVAL;
 
                err = get_user(header, (__be32*)current_segment->buf);
                if (err)
index 93971b1a4f0bb0d38eebd573f8618e994273b079..1243deda5bbbbf7874c6ff883b6f7f400c526308 100644 (file)
@@ -86,16 +86,18 @@ armpmu_map_event(struct perf_event *event,
        return -ENOENT;
 }
 
-int
-armpmu_event_set_period(struct perf_event *event,
-                       struct hw_perf_event *hwc,
-                       int idx)
+int armpmu_event_set_period(struct perf_event *event)
 {
        struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
+       struct hw_perf_event *hwc = &event->hw;
        s64 left = local64_read(&hwc->period_left);
        s64 period = hwc->sample_period;
        int ret = 0;
 
+       /* The period may have been changed by PERF_EVENT_IOC_PERIOD */
+       if (unlikely(period != hwc->last_period))
+               left = period - (hwc->last_period - left);
+
        if (unlikely(left <= -period)) {
                left = period;
                local64_set(&hwc->period_left, left);
@@ -115,24 +117,22 @@ armpmu_event_set_period(struct perf_event *event,
 
        local64_set(&hwc->prev_count, (u64)-left);
 
-       armpmu->write_counter(idx, (u64)(-left) & 0xffffffff);
+       armpmu->write_counter(event, (u64)(-left) & 0xffffffff);
 
        perf_event_update_userpage(event);
 
        return ret;
 }
 
-u64
-armpmu_event_update(struct perf_event *event,
-                   struct hw_perf_event *hwc,
-                   int idx)
+u64 armpmu_event_update(struct perf_event *event)
 {
        struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
+       struct hw_perf_event *hwc = &event->hw;
        u64 delta, prev_raw_count, new_raw_count;
 
 again:
        prev_raw_count = local64_read(&hwc->prev_count);
-       new_raw_count = armpmu->read_counter(idx);
+       new_raw_count = armpmu->read_counter(event);
 
        if (local64_cmpxchg(&hwc->prev_count, prev_raw_count,
                             new_raw_count) != prev_raw_count)
@@ -155,7 +155,7 @@ armpmu_read(struct perf_event *event)
        if (hwc->idx < 0)
                return;
 
-       armpmu_event_update(event, hwc, hwc->idx);
+       armpmu_event_update(event);
 }
 
 static void
@@ -169,14 +169,13 @@ armpmu_stop(struct perf_event *event, int flags)
         * PERF_EF_UPDATE, see comments in armpmu_start().
         */
        if (!(hwc->state & PERF_HES_STOPPED)) {
-               armpmu->disable(hwc, hwc->idx);
-               armpmu_event_update(event, hwc, hwc->idx);
+               armpmu->disable(event);
+               armpmu_event_update(event);
                hwc->state |= PERF_HES_STOPPED | PERF_HES_UPTODATE;
        }
 }
 
-static void
-armpmu_start(struct perf_event *event, int flags)
+static void armpmu_start(struct perf_event *event, int flags)
 {
        struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
        struct hw_perf_event *hwc = &event->hw;
@@ -196,8 +195,8 @@ armpmu_start(struct perf_event *event, int flags)
         * get an interrupt too soon or *way* too late if the overflow has
         * happened since disabling.
         */
-       armpmu_event_set_period(event, hwc, hwc->idx);
-       armpmu->enable(hwc, hwc->idx);
+       armpmu_event_set_period(event);
+       armpmu->enable(event);
 }
 
 static void
@@ -229,7 +228,7 @@ armpmu_add(struct perf_event *event, int flags)
        perf_pmu_disable(event->pmu);
 
        /* If we don't have a space for the counter then finish early. */
-       idx = armpmu->get_event_idx(hw_events, hwc);
+       idx = armpmu->get_event_idx(hw_events, event);
        if (idx < 0) {
                err = idx;
                goto out;
@@ -240,7 +239,7 @@ armpmu_add(struct perf_event *event, int flags)
         * sure it is disabled.
         */
        event->hw.idx = idx;
-       armpmu->disable(hwc, idx);
+       armpmu->disable(event);
        hw_events->events[idx] = event;
 
        hwc->state = PERF_HES_STOPPED | PERF_HES_UPTODATE;
@@ -260,13 +259,12 @@ validate_event(struct pmu_hw_events *hw_events,
               struct perf_event *event)
 {
        struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
-       struct hw_perf_event fake_event = event->hw;
        struct pmu *leader_pmu = event->group_leader->pmu;
 
        if (event->pmu != leader_pmu || event->state <= PERF_EVENT_STATE_OFF)
                return 1;
 
-       return armpmu->get_event_idx(hw_events, &fake_event) >= 0;
+       return armpmu->get_event_idx(hw_events, event) >= 0;
 }
 
 static int
@@ -312,7 +310,7 @@ static irqreturn_t armpmu_dispatch_irq(int irq, void *dev)
 static void
 armpmu_release_hardware(struct arm_pmu *armpmu)
 {
-       armpmu->free_irq();
+       armpmu->free_irq(armpmu);
        pm_runtime_put_sync(&armpmu->plat_device->dev);
 }
 
@@ -326,7 +324,7 @@ armpmu_reserve_hardware(struct arm_pmu *armpmu)
                return -ENODEV;
 
        pm_runtime_get_sync(&pmu_device->dev);
-       err = armpmu->request_irq(armpmu_dispatch_irq);
+       err = armpmu->request_irq(armpmu, armpmu_dispatch_irq);
        if (err) {
                armpmu_release_hardware(armpmu);
                return err;
@@ -461,13 +459,13 @@ static void armpmu_enable(struct pmu *pmu)
        int enabled = bitmap_weight(hw_events->used_mask, armpmu->num_events);
 
        if (enabled)
-               armpmu->start();
+               armpmu->start(armpmu);
 }
 
 static void armpmu_disable(struct pmu *pmu)
 {
        struct arm_pmu *armpmu = to_arm_pmu(pmu);
-       armpmu->stop();
+       armpmu->stop(armpmu);
 }
 
 #ifdef CONFIG_PM_RUNTIME
@@ -513,12 +511,12 @@ static void __init armpmu_init(struct arm_pmu *armpmu)
        };
 }
 
-int armpmu_register(struct arm_pmu *armpmu, char *name, int type)
+int armpmu_register(struct arm_pmu *armpmu, int type)
 {
        armpmu_init(armpmu);
        pr_info("enabled with %s PMU driver, %d counters available\n",
                        armpmu->name, armpmu->num_events);
-       return perf_pmu_register(&armpmu->pmu, name, type);
+       return perf_pmu_register(&armpmu->pmu, armpmu->name, type);
 }
 
 /*
@@ -572,6 +570,10 @@ perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs)
 {
        struct frame_tail __user *tail;
 
+       if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
+               /* We don't support guest os callchain now */
+               return;
+       }
 
        tail = (struct frame_tail __user *)regs->ARM_fp - 1;
 
@@ -599,9 +601,41 @@ perf_callchain_kernel(struct perf_callchain_entry *entry, struct pt_regs *regs)
 {
        struct stackframe fr;
 
+       if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
+               /* We don't support guest os callchain now */
+               return;
+       }
+
        fr.fp = regs->ARM_fp;
        fr.sp = regs->ARM_sp;
        fr.lr = regs->ARM_lr;
        fr.pc = regs->ARM_pc;
        walk_stackframe(&fr, callchain_trace, entry);
 }
+
+unsigned long perf_instruction_pointer(struct pt_regs *regs)
+{
+       if (perf_guest_cbs && perf_guest_cbs->is_in_guest())
+               return perf_guest_cbs->get_guest_ip();
+
+       return instruction_pointer(regs);
+}
+
+unsigned long perf_misc_flags(struct pt_regs *regs)
+{
+       int misc = 0;
+
+       if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
+               if (perf_guest_cbs->is_user_mode())
+                       misc |= PERF_RECORD_MISC_GUEST_USER;
+               else
+                       misc |= PERF_RECORD_MISC_GUEST_KERNEL;
+       } else {
+               if (user_mode(regs))
+                       misc |= PERF_RECORD_MISC_USER;
+               else
+                       misc |= PERF_RECORD_MISC_KERNEL;
+       }
+
+       return misc;
+}
index 8d7d8d4de9d68ae8a8540335e525bf339b4f1354..9a4f6307a01620996f08c29ebec7c03d05ff05fd 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/kernel.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
+#include <linux/slab.h>
 #include <linux/spinlock.h>
 
 #include <asm/cputype.h>
@@ -45,7 +46,7 @@ const char *perf_pmu_name(void)
        if (!cpu_pmu)
                return NULL;
 
-       return cpu_pmu->pmu.name;
+       return cpu_pmu->name;
 }
 EXPORT_SYMBOL_GPL(perf_pmu_name);
 
@@ -70,7 +71,7 @@ static struct pmu_hw_events *cpu_pmu_get_cpu_events(void)
        return &__get_cpu_var(cpu_hw_events);
 }
 
-static void cpu_pmu_free_irq(void)
+static void cpu_pmu_free_irq(struct arm_pmu *cpu_pmu)
 {
        int i, irq, irqs;
        struct platform_device *pmu_device = cpu_pmu->plat_device;
@@ -86,7 +87,7 @@ static void cpu_pmu_free_irq(void)
        }
 }
 
-static int cpu_pmu_request_irq(irq_handler_t handler)
+static int cpu_pmu_request_irq(struct arm_pmu *cpu_pmu, irq_handler_t handler)
 {
        int i, err, irq, irqs;
        struct platform_device *pmu_device = cpu_pmu->plat_device;
@@ -147,7 +148,7 @@ static void __devinit cpu_pmu_init(struct arm_pmu *cpu_pmu)
 
        /* Ensure the PMU has sane values out of reset. */
        if (cpu_pmu && cpu_pmu->reset)
-               on_each_cpu(cpu_pmu->reset, NULL, 1);
+               on_each_cpu(cpu_pmu->reset, cpu_pmu, 1);
 }
 
 /*
@@ -163,7 +164,9 @@ static int __cpuinit cpu_pmu_notify(struct notifier_block *b,
                return NOTIFY_DONE;
 
        if (cpu_pmu && cpu_pmu->reset)
-               cpu_pmu->reset(NULL);
+               cpu_pmu->reset(cpu_pmu);
+       else
+               return NOTIFY_DONE;
 
        return NOTIFY_OK;
 }
@@ -195,13 +198,13 @@ static struct platform_device_id __devinitdata cpu_pmu_plat_device_ids[] = {
 /*
  * CPU PMU identification and probing.
  */
-static struct arm_pmu *__devinit probe_current_pmu(void)
+static int __devinit probe_current_pmu(struct arm_pmu *pmu)
 {
-       struct arm_pmu *pmu = NULL;
        int cpu = get_cpu();
        unsigned long cpuid = read_cpuid_id();
        unsigned long implementor = (cpuid & 0xFF000000) >> 24;
        unsigned long part_number = (cpuid & 0xFFF0);
+       int ret = -ENODEV;
 
        pr_info("probing PMU on CPU %d\n", cpu);
 
@@ -211,25 +214,25 @@ static struct arm_pmu *__devinit probe_current_pmu(void)
                case 0xB360:    /* ARM1136 */
                case 0xB560:    /* ARM1156 */
                case 0xB760:    /* ARM1176 */
-                       pmu = armv6pmu_init();
+                       ret = armv6pmu_init(pmu);
                        break;
                case 0xB020:    /* ARM11mpcore */
-                       pmu = armv6mpcore_pmu_init();
+                       ret = armv6mpcore_pmu_init(pmu);
                        break;
                case 0xC080:    /* Cortex-A8 */
-                       pmu = armv7_a8_pmu_init();
+                       ret = armv7_a8_pmu_init(pmu);
                        break;
                case 0xC090:    /* Cortex-A9 */
-                       pmu = armv7_a9_pmu_init();
+                       ret = armv7_a9_pmu_init(pmu);
                        break;
                case 0xC050:    /* Cortex-A5 */
-                       pmu = armv7_a5_pmu_init();
+                       ret = armv7_a5_pmu_init(pmu);
                        break;
                case 0xC0F0:    /* Cortex-A15 */
-                       pmu = armv7_a15_pmu_init();
+                       ret = armv7_a15_pmu_init(pmu);
                        break;
                case 0xC070:    /* Cortex-A7 */
-                       pmu = armv7_a7_pmu_init();
+                       ret = armv7_a7_pmu_init(pmu);
                        break;
                }
        /* Intel CPUs [xscale]. */
@@ -237,43 +240,54 @@ static struct arm_pmu *__devinit probe_current_pmu(void)
                part_number = (cpuid >> 13) & 0x7;
                switch (part_number) {
                case 1:
-                       pmu = xscale1pmu_init();
+                       ret = xscale1pmu_init(pmu);
                        break;
                case 2:
-                       pmu = xscale2pmu_init();
+                       ret = xscale2pmu_init(pmu);
                        break;
                }
        }
 
        put_cpu();
-       return pmu;
+       return ret;
 }
 
 static int __devinit cpu_pmu_device_probe(struct platform_device *pdev)
 {
        const struct of_device_id *of_id;
-       struct arm_pmu *(*init_fn)(void);
+       int (*init_fn)(struct arm_pmu *);
        struct device_node *node = pdev->dev.of_node;
+       struct arm_pmu *pmu;
+       int ret = -ENODEV;
 
        if (cpu_pmu) {
                pr_info("attempt to register multiple PMU devices!");
                return -ENOSPC;
        }
 
+       pmu = kzalloc(sizeof(struct arm_pmu), GFP_KERNEL);
+       if (!pmu) {
+               pr_info("failed to allocate PMU device!");
+               return -ENOMEM;
+       }
+
        if (node && (of_id = of_match_node(cpu_pmu_of_device_ids, pdev->dev.of_node))) {
                init_fn = of_id->data;
-               cpu_pmu = init_fn();
+               ret = init_fn(pmu);
        } else {
-               cpu_pmu = probe_current_pmu();
+               ret = probe_current_pmu(pmu);
        }
 
-       if (!cpu_pmu)
-               return -ENODEV;
+       if (ret) {
+               pr_info("failed to register PMU devices!");
+               kfree(pmu);
+               return ret;
+       }
 
+       cpu_pmu = pmu;
        cpu_pmu->plat_device = pdev;
        cpu_pmu_init(cpu_pmu);
-       register_cpu_notifier(&cpu_pmu_hotplug_notifier);
-       armpmu_register(cpu_pmu, cpu_pmu->name, PERF_TYPE_RAW);
+       armpmu_register(cpu_pmu, PERF_TYPE_RAW);
 
        return 0;
 }
@@ -290,6 +304,16 @@ static struct platform_driver cpu_pmu_driver = {
 
 static int __init register_pmu_driver(void)
 {
-       return platform_driver_register(&cpu_pmu_driver);
+       int err;
+
+       err = register_cpu_notifier(&cpu_pmu_hotplug_notifier);
+       if (err)
+               return err;
+
+       err = platform_driver_register(&cpu_pmu_driver);
+       if (err)
+               unregister_cpu_notifier(&cpu_pmu_hotplug_notifier);
+
+       return err;
 }
 device_initcall(register_pmu_driver);
index 6ccc0797174555ebc805a1aabe0bd77941badef0..f3e22ff8b6a2c2bc5f620e9b8a389cb17b56a136 100644 (file)
@@ -401,9 +401,10 @@ armv6_pmcr_counter_has_overflowed(unsigned long pmcr,
        return ret;
 }
 
-static inline u32
-armv6pmu_read_counter(int counter)
+static inline u32 armv6pmu_read_counter(struct perf_event *event)
 {
+       struct hw_perf_event *hwc = &event->hw;
+       int counter = hwc->idx;
        unsigned long value = 0;
 
        if (ARMV6_CYCLE_COUNTER == counter)
@@ -418,10 +419,11 @@ armv6pmu_read_counter(int counter)
        return value;
 }
 
-static inline void
-armv6pmu_write_counter(int counter,
-                      u32 value)
+static inline void armv6pmu_write_counter(struct perf_event *event, u32 value)
 {
+       struct hw_perf_event *hwc = &event->hw;
+       int counter = hwc->idx;
+
        if (ARMV6_CYCLE_COUNTER == counter)
                asm volatile("mcr   p15, 0, %0, c15, c12, 1" : : "r"(value));
        else if (ARMV6_COUNTER0 == counter)
@@ -432,12 +434,13 @@ armv6pmu_write_counter(int counter,
                WARN_ONCE(1, "invalid counter number (%d)\n", counter);
 }
 
-static void
-armv6pmu_enable_event(struct hw_perf_event *hwc,
-                     int idx)
+static void armv6pmu_enable_event(struct perf_event *event)
 {
        unsigned long val, mask, evt, flags;
+       struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
+       struct hw_perf_event *hwc = &event->hw;
        struct pmu_hw_events *events = cpu_pmu->get_hw_events();
+       int idx = hwc->idx;
 
        if (ARMV6_CYCLE_COUNTER == idx) {
                mask    = 0;
@@ -473,7 +476,8 @@ armv6pmu_handle_irq(int irq_num,
 {
        unsigned long pmcr = armv6_pmcr_read();
        struct perf_sample_data data;
-       struct pmu_hw_events *cpuc;
+       struct arm_pmu *cpu_pmu = (struct arm_pmu *)dev;
+       struct pmu_hw_events *cpuc = cpu_pmu->get_hw_events();
        struct pt_regs *regs;
        int idx;
 
@@ -489,7 +493,6 @@ armv6pmu_handle_irq(int irq_num,
         */
        armv6_pmcr_write(pmcr);
 
-       cpuc = &__get_cpu_var(cpu_hw_events);
        for (idx = 0; idx < cpu_pmu->num_events; ++idx) {
                struct perf_event *event = cpuc->events[idx];
                struct hw_perf_event *hwc;
@@ -506,13 +509,13 @@ armv6pmu_handle_irq(int irq_num,
                        continue;
 
                hwc = &event->hw;
-               armpmu_event_update(event, hwc, idx);
+               armpmu_event_update(event);
                perf_sample_data_init(&data, 0, hwc->last_period);
-               if (!armpmu_event_set_period(event, hwc, idx))
+               if (!armpmu_event_set_period(event))
                        continue;
 
                if (perf_event_overflow(event, &data, regs))
-                       cpu_pmu->disable(hwc, idx);
+                       cpu_pmu->disable(event);
        }
 
        /*
@@ -527,8 +530,7 @@ armv6pmu_handle_irq(int irq_num,
        return IRQ_HANDLED;
 }
 
-static void
-armv6pmu_start(void)
+static void armv6pmu_start(struct arm_pmu *cpu_pmu)
 {
        unsigned long flags, val;
        struct pmu_hw_events *events = cpu_pmu->get_hw_events();
@@ -540,8 +542,7 @@ armv6pmu_start(void)
        raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
-static void
-armv6pmu_stop(void)
+static void armv6pmu_stop(struct arm_pmu *cpu_pmu)
 {
        unsigned long flags, val;
        struct pmu_hw_events *events = cpu_pmu->get_hw_events();
@@ -555,10 +556,11 @@ armv6pmu_stop(void)
 
 static int
 armv6pmu_get_event_idx(struct pmu_hw_events *cpuc,
-                      struct hw_perf_event *event)
+                               struct perf_event *event)
 {
+       struct hw_perf_event *hwc = &event->hw;
        /* Always place a cycle counter into the cycle counter. */
-       if (ARMV6_PERFCTR_CPU_CYCLES == event->config_base) {
+       if (ARMV6_PERFCTR_CPU_CYCLES == hwc->config_base) {
                if (test_and_set_bit(ARMV6_CYCLE_COUNTER, cpuc->used_mask))
                        return -EAGAIN;
 
@@ -579,12 +581,13 @@ armv6pmu_get_event_idx(struct pmu_hw_events *cpuc,
        }
 }
 
-static void
-armv6pmu_disable_event(struct hw_perf_event *hwc,
-                      int idx)
+static void armv6pmu_disable_event(struct perf_event *event)
 {
        unsigned long val, mask, evt, flags;
+       struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
+       struct hw_perf_event *hwc = &event->hw;
        struct pmu_hw_events *events = cpu_pmu->get_hw_events();
+       int idx = hwc->idx;
 
        if (ARMV6_CYCLE_COUNTER == idx) {
                mask    = ARMV6_PMCR_CCOUNT_IEN;
@@ -613,12 +616,13 @@ armv6pmu_disable_event(struct hw_perf_event *hwc,
        raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
-static void
-armv6mpcore_pmu_disable_event(struct hw_perf_event *hwc,
-                             int idx)
+static void armv6mpcore_pmu_disable_event(struct perf_event *event)
 {
        unsigned long val, mask, flags, evt = 0;
+       struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
+       struct hw_perf_event *hwc = &event->hw;
        struct pmu_hw_events *events = cpu_pmu->get_hw_events();
+       int idx = hwc->idx;
 
        if (ARMV6_CYCLE_COUNTER == idx) {
                mask    = ARMV6_PMCR_CCOUNT_IEN;
@@ -649,24 +653,22 @@ static int armv6_map_event(struct perf_event *event)
                                &armv6_perf_cache_map, 0xFF);
 }
 
-static struct arm_pmu armv6pmu = {
-       .name                   = "v6",
-       .handle_irq             = armv6pmu_handle_irq,
-       .enable                 = armv6pmu_enable_event,
-       .disable                = armv6pmu_disable_event,
-       .read_counter           = armv6pmu_read_counter,
-       .write_counter          = armv6pmu_write_counter,
-       .get_event_idx          = armv6pmu_get_event_idx,
-       .start                  = armv6pmu_start,
-       .stop                   = armv6pmu_stop,
-       .map_event              = armv6_map_event,
-       .num_events             = 3,
-       .max_period             = (1LLU << 32) - 1,
-};
-
-static struct arm_pmu *__devinit armv6pmu_init(void)
+static int __devinit armv6pmu_init(struct arm_pmu *cpu_pmu)
 {
-       return &armv6pmu;
+       cpu_pmu->name           = "v6";
+       cpu_pmu->handle_irq     = armv6pmu_handle_irq;
+       cpu_pmu->enable         = armv6pmu_enable_event;
+       cpu_pmu->disable        = armv6pmu_disable_event;
+       cpu_pmu->read_counter   = armv6pmu_read_counter;
+       cpu_pmu->write_counter  = armv6pmu_write_counter;
+       cpu_pmu->get_event_idx  = armv6pmu_get_event_idx;
+       cpu_pmu->start          = armv6pmu_start;
+       cpu_pmu->stop           = armv6pmu_stop;
+       cpu_pmu->map_event      = armv6_map_event;
+       cpu_pmu->num_events     = 3;
+       cpu_pmu->max_period     = (1LLU << 32) - 1;
+
+       return 0;
 }
 
 /*
@@ -683,33 +685,31 @@ static int armv6mpcore_map_event(struct perf_event *event)
                                &armv6mpcore_perf_cache_map, 0xFF);
 }
 
-static struct arm_pmu armv6mpcore_pmu = {
-       .name                   = "v6mpcore",
-       .handle_irq             = armv6pmu_handle_irq,
-       .enable                 = armv6pmu_enable_event,
-       .disable                = armv6mpcore_pmu_disable_event,
-       .read_counter           = armv6pmu_read_counter,
-       .write_counter          = armv6pmu_write_counter,
-       .get_event_idx          = armv6pmu_get_event_idx,
-       .start                  = armv6pmu_start,
-       .stop                   = armv6pmu_stop,
-       .map_event              = armv6mpcore_map_event,
-       .num_events             = 3,
-       .max_period             = (1LLU << 32) - 1,
-};
-
-static struct arm_pmu *__devinit armv6mpcore_pmu_init(void)
+static int __devinit armv6mpcore_pmu_init(struct arm_pmu *cpu_pmu)
 {
-       return &armv6mpcore_pmu;
+       cpu_pmu->name           = "v6mpcore";
+       cpu_pmu->handle_irq     = armv6pmu_handle_irq;
+       cpu_pmu->enable         = armv6pmu_enable_event;
+       cpu_pmu->disable        = armv6mpcore_pmu_disable_event;
+       cpu_pmu->read_counter   = armv6pmu_read_counter;
+       cpu_pmu->write_counter  = armv6pmu_write_counter;
+       cpu_pmu->get_event_idx  = armv6pmu_get_event_idx;
+       cpu_pmu->start          = armv6pmu_start;
+       cpu_pmu->stop           = armv6pmu_stop;
+       cpu_pmu->map_event      = armv6mpcore_map_event;
+       cpu_pmu->num_events     = 3;
+       cpu_pmu->max_period     = (1LLU << 32) - 1;
+
+       return 0;
 }
 #else
-static struct arm_pmu *__devinit armv6pmu_init(void)
+static int armv6pmu_init(struct arm_pmu *cpu_pmu)
 {
-       return NULL;
+       return -ENODEV;
 }
 
-static struct arm_pmu *__devinit armv6mpcore_pmu_init(void)
+static int armv6mpcore_pmu_init(struct arm_pmu *cpu_pmu)
 {
-       return NULL;
+       return -ENODEV;
 }
 #endif /* CONFIG_CPU_V6 || CONFIG_CPU_V6K */
index bd4b090ebcfd8e2b6132a5d2e52a9eb890a34ea9..7d0cce85d17e56ea1049403b38b4d4532dc7d6b1 100644 (file)
@@ -18,8 +18,6 @@
 
 #ifdef CONFIG_CPU_V7
 
-static struct arm_pmu armv7pmu;
-
 /*
  * Common ARMv7 event types
  *
@@ -738,7 +736,8 @@ static const unsigned armv7_a7_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
  */
 #define        ARMV7_IDX_CYCLE_COUNTER 0
 #define        ARMV7_IDX_COUNTER0      1
-#define        ARMV7_IDX_COUNTER_LAST  (ARMV7_IDX_CYCLE_COUNTER + cpu_pmu->num_events - 1)
+#define        ARMV7_IDX_COUNTER_LAST(cpu_pmu) \
+       (ARMV7_IDX_CYCLE_COUNTER + cpu_pmu->num_events - 1)
 
 #define        ARMV7_MAX_COUNTERS      32
 #define        ARMV7_COUNTER_MASK      (ARMV7_MAX_COUNTERS - 1)
@@ -804,49 +803,34 @@ static inline int armv7_pmnc_has_overflowed(u32 pmnc)
        return pmnc & ARMV7_OVERFLOWED_MASK;
 }
 
-static inline int armv7_pmnc_counter_valid(int idx)
+static inline int armv7_pmnc_counter_valid(struct arm_pmu *cpu_pmu, int idx)
 {
-       return idx >= ARMV7_IDX_CYCLE_COUNTER && idx <= ARMV7_IDX_COUNTER_LAST;
+       return idx >= ARMV7_IDX_CYCLE_COUNTER &&
+               idx <= ARMV7_IDX_COUNTER_LAST(cpu_pmu);
 }
 
 static inline int armv7_pmnc_counter_has_overflowed(u32 pmnc, int idx)
 {
-       int ret = 0;
-       u32 counter;
-
-       if (!armv7_pmnc_counter_valid(idx)) {
-               pr_err("CPU%u checking wrong counter %d overflow status\n",
-                       smp_processor_id(), idx);
-       } else {
-               counter = ARMV7_IDX_TO_COUNTER(idx);
-               ret = pmnc & BIT(counter);
-       }
-
-       return ret;
+       return pmnc & BIT(ARMV7_IDX_TO_COUNTER(idx));
 }
 
 static inline int armv7_pmnc_select_counter(int idx)
 {
-       u32 counter;
-
-       if (!armv7_pmnc_counter_valid(idx)) {
-               pr_err("CPU%u selecting wrong PMNC counter %d\n",
-                       smp_processor_id(), idx);
-               return -EINVAL;
-       }
-
-       counter = ARMV7_IDX_TO_COUNTER(idx);
+       u32 counter = ARMV7_IDX_TO_COUNTER(idx);
        asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r" (counter));
        isb();
 
        return idx;
 }
 
-static inline u32 armv7pmu_read_counter(int idx)
+static inline u32 armv7pmu_read_counter(struct perf_event *event)
 {
+       struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
+       struct hw_perf_event *hwc = &event->hw;
+       int idx = hwc->idx;
        u32 value = 0;
 
-       if (!armv7_pmnc_counter_valid(idx))
+       if (!armv7_pmnc_counter_valid(cpu_pmu, idx))
                pr_err("CPU%u reading wrong counter %d\n",
                        smp_processor_id(), idx);
        else if (idx == ARMV7_IDX_CYCLE_COUNTER)
@@ -857,9 +841,13 @@ static inline u32 armv7pmu_read_counter(int idx)
        return value;
 }
 
-static inline void armv7pmu_write_counter(int idx, u32 value)
+static inline void armv7pmu_write_counter(struct perf_event *event, u32 value)
 {
-       if (!armv7_pmnc_counter_valid(idx))
+       struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
+       struct hw_perf_event *hwc = &event->hw;
+       int idx = hwc->idx;
+
+       if (!armv7_pmnc_counter_valid(cpu_pmu, idx))
                pr_err("CPU%u writing wrong counter %d\n",
                        smp_processor_id(), idx);
        else if (idx == ARMV7_IDX_CYCLE_COUNTER)
@@ -878,60 +866,28 @@ static inline void armv7_pmnc_write_evtsel(int idx, u32 val)
 
 static inline int armv7_pmnc_enable_counter(int idx)
 {
-       u32 counter;
-
-       if (!armv7_pmnc_counter_valid(idx)) {
-               pr_err("CPU%u enabling wrong PMNC counter %d\n",
-                       smp_processor_id(), idx);
-               return -EINVAL;
-       }
-
-       counter = ARMV7_IDX_TO_COUNTER(idx);
+       u32 counter = ARMV7_IDX_TO_COUNTER(idx);
        asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r" (BIT(counter)));
        return idx;
 }
 
 static inline int armv7_pmnc_disable_counter(int idx)
 {
-       u32 counter;
-
-       if (!armv7_pmnc_counter_valid(idx)) {
-               pr_err("CPU%u disabling wrong PMNC counter %d\n",
-                       smp_processor_id(), idx);
-               return -EINVAL;
-       }
-
-       counter = ARMV7_IDX_TO_COUNTER(idx);
+       u32 counter = ARMV7_IDX_TO_COUNTER(idx);
        asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r" (BIT(counter)));
        return idx;
 }
 
 static inline int armv7_pmnc_enable_intens(int idx)
 {
-       u32 counter;
-
-       if (!armv7_pmnc_counter_valid(idx)) {
-               pr_err("CPU%u enabling wrong PMNC counter IRQ enable %d\n",
-                       smp_processor_id(), idx);
-               return -EINVAL;
-       }
-
-       counter = ARMV7_IDX_TO_COUNTER(idx);
+       u32 counter = ARMV7_IDX_TO_COUNTER(idx);
        asm volatile("mcr p15, 0, %0, c9, c14, 1" : : "r" (BIT(counter)));
        return idx;
 }
 
 static inline int armv7_pmnc_disable_intens(int idx)
 {
-       u32 counter;
-
-       if (!armv7_pmnc_counter_valid(idx)) {
-               pr_err("CPU%u disabling wrong PMNC counter IRQ enable %d\n",
-                       smp_processor_id(), idx);
-               return -EINVAL;
-       }
-
-       counter = ARMV7_IDX_TO_COUNTER(idx);
+       u32 counter = ARMV7_IDX_TO_COUNTER(idx);
        asm volatile("mcr p15, 0, %0, c9, c14, 2" : : "r" (BIT(counter)));
        isb();
        /* Clear the overflow flag in case an interrupt is pending. */
@@ -956,7 +912,7 @@ static inline u32 armv7_pmnc_getreset_flags(void)
 }
 
 #ifdef DEBUG
-static void armv7_pmnc_dump_regs(void)
+static void armv7_pmnc_dump_regs(struct arm_pmu *cpu_pmu)
 {
        u32 val;
        unsigned int cnt;
@@ -981,7 +937,8 @@ static void armv7_pmnc_dump_regs(void)
        asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r" (val));
        printk(KERN_INFO "CCNT  =0x%08x\n", val);
 
-       for (cnt = ARMV7_IDX_COUNTER0; cnt <= ARMV7_IDX_COUNTER_LAST; cnt++) {
+       for (cnt = ARMV7_IDX_COUNTER0;
+                       cnt <= ARMV7_IDX_COUNTER_LAST(cpu_pmu); cnt++) {
                armv7_pmnc_select_counter(cnt);
                asm volatile("mrc p15, 0, %0, c9, c13, 2" : "=r" (val));
                printk(KERN_INFO "CNT[%d] count =0x%08x\n",
@@ -993,10 +950,19 @@ static void armv7_pmnc_dump_regs(void)
 }
 #endif
 
-static void armv7pmu_enable_event(struct hw_perf_event *hwc, int idx)
+static void armv7pmu_enable_event(struct perf_event *event)
 {
        unsigned long flags;
+       struct hw_perf_event *hwc = &event->hw;
+       struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
        struct pmu_hw_events *events = cpu_pmu->get_hw_events();
+       int idx = hwc->idx;
+
+       if (!armv7_pmnc_counter_valid(cpu_pmu, idx)) {
+               pr_err("CPU%u enabling wrong PMNC counter IRQ enable %d\n",
+                       smp_processor_id(), idx);
+               return;
+       }
 
        /*
         * Enable counter and interrupt, and set the counter to count
@@ -1014,7 +980,7 @@ static void armv7pmu_enable_event(struct hw_perf_event *hwc, int idx)
         * We only need to set the event for the cycle counter if we
         * have the ability to perform event filtering.
         */
-       if (armv7pmu.set_event_filter || idx != ARMV7_IDX_CYCLE_COUNTER)
+       if (cpu_pmu->set_event_filter || idx != ARMV7_IDX_CYCLE_COUNTER)
                armv7_pmnc_write_evtsel(idx, hwc->config_base);
 
        /*
@@ -1030,10 +996,19 @@ static void armv7pmu_enable_event(struct hw_perf_event *hwc, int idx)
        raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
-static void armv7pmu_disable_event(struct hw_perf_event *hwc, int idx)
+static void armv7pmu_disable_event(struct perf_event *event)
 {
        unsigned long flags;
+       struct hw_perf_event *hwc = &event->hw;
+       struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
        struct pmu_hw_events *events = cpu_pmu->get_hw_events();
+       int idx = hwc->idx;
+
+       if (!armv7_pmnc_counter_valid(cpu_pmu, idx)) {
+               pr_err("CPU%u disabling wrong PMNC counter IRQ enable %d\n",
+                       smp_processor_id(), idx);
+               return;
+       }
 
        /*
         * Disable counter and interrupt
@@ -1057,7 +1032,8 @@ static irqreturn_t armv7pmu_handle_irq(int irq_num, void *dev)
 {
        u32 pmnc;
        struct perf_sample_data data;
-       struct pmu_hw_events *cpuc;
+       struct arm_pmu *cpu_pmu = (struct arm_pmu *)dev;
+       struct pmu_hw_events *cpuc = cpu_pmu->get_hw_events();
        struct pt_regs *regs;
        int idx;
 
@@ -1077,7 +1053,6 @@ static irqreturn_t armv7pmu_handle_irq(int irq_num, void *dev)
         */
        regs = get_irq_regs();
 
-       cpuc = &__get_cpu_var(cpu_hw_events);
        for (idx = 0; idx < cpu_pmu->num_events; ++idx) {
                struct perf_event *event = cpuc->events[idx];
                struct hw_perf_event *hwc;
@@ -1094,13 +1069,13 @@ static irqreturn_t armv7pmu_handle_irq(int irq_num, void *dev)
                        continue;
 
                hwc = &event->hw;
-               armpmu_event_update(event, hwc, idx);
+               armpmu_event_update(event);
                perf_sample_data_init(&data, 0, hwc->last_period);
-               if (!armpmu_event_set_period(event, hwc, idx))
+               if (!armpmu_event_set_period(event))
                        continue;
 
                if (perf_event_overflow(event, &data, regs))
-                       cpu_pmu->disable(hwc, idx);
+                       cpu_pmu->disable(event);
        }
 
        /*
@@ -1115,7 +1090,7 @@ static irqreturn_t armv7pmu_handle_irq(int irq_num, void *dev)
        return IRQ_HANDLED;
 }
 
-static void armv7pmu_start(void)
+static void armv7pmu_start(struct arm_pmu *cpu_pmu)
 {
        unsigned long flags;
        struct pmu_hw_events *events = cpu_pmu->get_hw_events();
@@ -1126,7 +1101,7 @@ static void armv7pmu_start(void)
        raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
-static void armv7pmu_stop(void)
+static void armv7pmu_stop(struct arm_pmu *cpu_pmu)
 {
        unsigned long flags;
        struct pmu_hw_events *events = cpu_pmu->get_hw_events();
@@ -1138,10 +1113,12 @@ static void armv7pmu_stop(void)
 }
 
 static int armv7pmu_get_event_idx(struct pmu_hw_events *cpuc,
-                                 struct hw_perf_event *event)
+                                 struct perf_event *event)
 {
        int idx;
-       unsigned long evtype = event->config_base & ARMV7_EVTYPE_EVENT;
+       struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
+       struct hw_perf_event *hwc = &event->hw;
+       unsigned long evtype = hwc->config_base & ARMV7_EVTYPE_EVENT;
 
        /* Always place a cycle counter into the cycle counter. */
        if (evtype == ARMV7_PERFCTR_CPU_CYCLES) {
@@ -1192,11 +1169,14 @@ static int armv7pmu_set_event_filter(struct hw_perf_event *event,
 
 static void armv7pmu_reset(void *info)
 {
+       struct arm_pmu *cpu_pmu = (struct arm_pmu *)info;
        u32 idx, nb_cnt = cpu_pmu->num_events;
 
        /* The counter and interrupt enable registers are unknown at reset. */
-       for (idx = ARMV7_IDX_CYCLE_COUNTER; idx < nb_cnt; ++idx)
-               armv7pmu_disable_event(NULL, idx);
+       for (idx = ARMV7_IDX_CYCLE_COUNTER; idx < nb_cnt; ++idx) {
+               armv7_pmnc_disable_counter(idx);
+               armv7_pmnc_disable_intens(idx);
+       }
 
        /* Initialize & Reset PMNC: C and P bits */
        armv7_pmnc_write(ARMV7_PMNC_P | ARMV7_PMNC_C);
@@ -1232,17 +1212,18 @@ static int armv7_a7_map_event(struct perf_event *event)
                                &armv7_a7_perf_cache_map, 0xFF);
 }
 
-static struct arm_pmu armv7pmu = {
-       .handle_irq             = armv7pmu_handle_irq,
-       .enable                 = armv7pmu_enable_event,
-       .disable                = armv7pmu_disable_event,
-       .read_counter           = armv7pmu_read_counter,
-       .write_counter          = armv7pmu_write_counter,
-       .get_event_idx          = armv7pmu_get_event_idx,
-       .start                  = armv7pmu_start,
-       .stop                   = armv7pmu_stop,
-       .reset                  = armv7pmu_reset,
-       .max_period             = (1LLU << 32) - 1,
+static void armv7pmu_init(struct arm_pmu *cpu_pmu)
+{
+       cpu_pmu->handle_irq     = armv7pmu_handle_irq;
+       cpu_pmu->enable         = armv7pmu_enable_event;
+       cpu_pmu->disable        = armv7pmu_disable_event;
+       cpu_pmu->read_counter   = armv7pmu_read_counter;
+       cpu_pmu->write_counter  = armv7pmu_write_counter;
+       cpu_pmu->get_event_idx  = armv7pmu_get_event_idx;
+       cpu_pmu->start          = armv7pmu_start;
+       cpu_pmu->stop           = armv7pmu_stop;
+       cpu_pmu->reset          = armv7pmu_reset;
+       cpu_pmu->max_period     = (1LLU << 32) - 1;
 };
 
 static u32 __devinit armv7_read_num_pmnc_events(void)
@@ -1256,70 +1237,75 @@ static u32 __devinit armv7_read_num_pmnc_events(void)
        return nb_cnt + 1;
 }
 
-static struct arm_pmu *__devinit armv7_a8_pmu_init(void)
+static int __devinit armv7_a8_pmu_init(struct arm_pmu *cpu_pmu)
 {
-       armv7pmu.name           = "ARMv7 Cortex-A8";
-       armv7pmu.map_event      = armv7_a8_map_event;
-       armv7pmu.num_events     = armv7_read_num_pmnc_events();
-       return &armv7pmu;
+       armv7pmu_init(cpu_pmu);
+       cpu_pmu->name           = "ARMv7 Cortex-A8";
+       cpu_pmu->map_event      = armv7_a8_map_event;
+       cpu_pmu->num_events     = armv7_read_num_pmnc_events();
+       return 0;
 }
 
-static struct arm_pmu *__devinit armv7_a9_pmu_init(void)
+static int __devinit armv7_a9_pmu_init(struct arm_pmu *cpu_pmu)
 {
-       armv7pmu.name           = "ARMv7 Cortex-A9";
-       armv7pmu.map_event      = armv7_a9_map_event;
-       armv7pmu.num_events     = armv7_read_num_pmnc_events();
-       return &armv7pmu;
+       armv7pmu_init(cpu_pmu);
+       cpu_pmu->name           = "ARMv7 Cortex-A9";
+       cpu_pmu->map_event      = armv7_a9_map_event;
+       cpu_pmu->num_events     = armv7_read_num_pmnc_events();
+       return 0;
 }
 
-static struct arm_pmu *__devinit armv7_a5_pmu_init(void)
+static int __devinit armv7_a5_pmu_init(struct arm_pmu *cpu_pmu)
 {
-       armv7pmu.name           = "ARMv7 Cortex-A5";
-       armv7pmu.map_event      = armv7_a5_map_event;
-       armv7pmu.num_events     = armv7_read_num_pmnc_events();
-       return &armv7pmu;
+       armv7pmu_init(cpu_pmu);
+       cpu_pmu->name           = "ARMv7 Cortex-A5";
+       cpu_pmu->map_event      = armv7_a5_map_event;
+       cpu_pmu->num_events     = armv7_read_num_pmnc_events();
+       return 0;
 }
 
-static struct arm_pmu *__devinit armv7_a15_pmu_init(void)
+static int __devinit armv7_a15_pmu_init(struct arm_pmu *cpu_pmu)
 {
-       armv7pmu.name           = "ARMv7 Cortex-A15";
-       armv7pmu.map_event      = armv7_a15_map_event;
-       armv7pmu.num_events     = armv7_read_num_pmnc_events();
-       armv7pmu.set_event_filter = armv7pmu_set_event_filter;
-       return &armv7pmu;
+       armv7pmu_init(cpu_pmu);
+       cpu_pmu->name           = "ARMv7 Cortex-A15";
+       cpu_pmu->map_event      = armv7_a15_map_event;
+       cpu_pmu->num_events     = armv7_read_num_pmnc_events();
+       cpu_pmu->set_event_filter = armv7pmu_set_event_filter;
+       return 0;
 }
 
-static struct arm_pmu *__devinit armv7_a7_pmu_init(void)
+static int __devinit armv7_a7_pmu_init(struct arm_pmu *cpu_pmu)
 {
-       armv7pmu.name           = "ARMv7 Cortex-A7";
-       armv7pmu.map_event      = armv7_a7_map_event;
-       armv7pmu.num_events     = armv7_read_num_pmnc_events();
-       armv7pmu.set_event_filter = armv7pmu_set_event_filter;
-       return &armv7pmu;
+       armv7pmu_init(cpu_pmu);
+       cpu_pmu->name           = "ARMv7 Cortex-A7";
+       cpu_pmu->map_event      = armv7_a7_map_event;
+       cpu_pmu->num_events     = armv7_read_num_pmnc_events();
+       cpu_pmu->set_event_filter = armv7pmu_set_event_filter;
+       return 0;
 }
 #else
-static struct arm_pmu *__devinit armv7_a8_pmu_init(void)
+static inline int armv7_a8_pmu_init(struct arm_pmu *cpu_pmu)
 {
-       return NULL;
+       return -ENODEV;
 }
 
-static struct arm_pmu *__devinit armv7_a9_pmu_init(void)
+static inline int armv7_a9_pmu_init(struct arm_pmu *cpu_pmu)
 {
-       return NULL;
+       return -ENODEV;
 }
 
-static struct arm_pmu *__devinit armv7_a5_pmu_init(void)
+static inline int armv7_a5_pmu_init(struct arm_pmu *cpu_pmu)
 {
-       return NULL;
+       return -ENODEV;
 }
 
-static struct arm_pmu *__devinit armv7_a15_pmu_init(void)
+static inline int armv7_a15_pmu_init(struct arm_pmu *cpu_pmu)
 {
-       return NULL;
+       return -ENODEV;
 }
 
-static struct arm_pmu *__devinit armv7_a7_pmu_init(void)
+static inline int armv7_a7_pmu_init(struct arm_pmu *cpu_pmu)
 {
-       return NULL;
+       return -ENODEV;
 }
 #endif /* CONFIG_CPU_V7 */
index 426e19f380a2f935b7b1c9706a6c50613ce4e272..0c8265e53d5f7b079a49e80b70912e2edc1d7372 100644 (file)
@@ -224,7 +224,8 @@ xscale1pmu_handle_irq(int irq_num, void *dev)
 {
        unsigned long pmnc;
        struct perf_sample_data data;
-       struct pmu_hw_events *cpuc;
+       struct arm_pmu *cpu_pmu = (struct arm_pmu *)dev;
+       struct pmu_hw_events *cpuc = cpu_pmu->get_hw_events();
        struct pt_regs *regs;
        int idx;
 
@@ -248,7 +249,6 @@ xscale1pmu_handle_irq(int irq_num, void *dev)
 
        regs = get_irq_regs();
 
-       cpuc = &__get_cpu_var(cpu_hw_events);
        for (idx = 0; idx < cpu_pmu->num_events; ++idx) {
                struct perf_event *event = cpuc->events[idx];
                struct hw_perf_event *hwc;
@@ -260,13 +260,13 @@ xscale1pmu_handle_irq(int irq_num, void *dev)
                        continue;
 
                hwc = &event->hw;
-               armpmu_event_update(event, hwc, idx);
+               armpmu_event_update(event);
                perf_sample_data_init(&data, 0, hwc->last_period);
-               if (!armpmu_event_set_period(event, hwc, idx))
+               if (!armpmu_event_set_period(event))
                        continue;
 
                if (perf_event_overflow(event, &data, regs))
-                       cpu_pmu->disable(hwc, idx);
+                       cpu_pmu->disable(event);
        }
 
        irq_work_run();
@@ -280,11 +280,13 @@ xscale1pmu_handle_irq(int irq_num, void *dev)
        return IRQ_HANDLED;
 }
 
-static void
-xscale1pmu_enable_event(struct hw_perf_event *hwc, int idx)
+static void xscale1pmu_enable_event(struct perf_event *event)
 {
        unsigned long val, mask, evt, flags;
+       struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
+       struct hw_perf_event *hwc = &event->hw;
        struct pmu_hw_events *events = cpu_pmu->get_hw_events();
+       int idx = hwc->idx;
 
        switch (idx) {
        case XSCALE_CYCLE_COUNTER:
@@ -314,11 +316,13 @@ xscale1pmu_enable_event(struct hw_perf_event *hwc, int idx)
        raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
-static void
-xscale1pmu_disable_event(struct hw_perf_event *hwc, int idx)
+static void xscale1pmu_disable_event(struct perf_event *event)
 {
        unsigned long val, mask, evt, flags;
+       struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
+       struct hw_perf_event *hwc = &event->hw;
        struct pmu_hw_events *events = cpu_pmu->get_hw_events();
+       int idx = hwc->idx;
 
        switch (idx) {
        case XSCALE_CYCLE_COUNTER:
@@ -348,9 +352,10 @@ xscale1pmu_disable_event(struct hw_perf_event *hwc, int idx)
 
 static int
 xscale1pmu_get_event_idx(struct pmu_hw_events *cpuc,
-                       struct hw_perf_event *event)
+                               struct perf_event *event)
 {
-       if (XSCALE_PERFCTR_CCNT == event->config_base) {
+       struct hw_perf_event *hwc = &event->hw;
+       if (XSCALE_PERFCTR_CCNT == hwc->config_base) {
                if (test_and_set_bit(XSCALE_CYCLE_COUNTER, cpuc->used_mask))
                        return -EAGAIN;
 
@@ -366,8 +371,7 @@ xscale1pmu_get_event_idx(struct pmu_hw_events *cpuc,
        }
 }
 
-static void
-xscale1pmu_start(void)
+static void xscale1pmu_start(struct arm_pmu *cpu_pmu)
 {
        unsigned long flags, val;
        struct pmu_hw_events *events = cpu_pmu->get_hw_events();
@@ -379,8 +383,7 @@ xscale1pmu_start(void)
        raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
-static void
-xscale1pmu_stop(void)
+static void xscale1pmu_stop(struct arm_pmu *cpu_pmu)
 {
        unsigned long flags, val;
        struct pmu_hw_events *events = cpu_pmu->get_hw_events();
@@ -392,9 +395,10 @@ xscale1pmu_stop(void)
        raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
-static inline u32
-xscale1pmu_read_counter(int counter)
+static inline u32 xscale1pmu_read_counter(struct perf_event *event)
 {
+       struct hw_perf_event *hwc = &event->hw;
+       int counter = hwc->idx;
        u32 val = 0;
 
        switch (counter) {
@@ -412,9 +416,11 @@ xscale1pmu_read_counter(int counter)
        return val;
 }
 
-static inline void
-xscale1pmu_write_counter(int counter, u32 val)
+static inline void xscale1pmu_write_counter(struct perf_event *event, u32 val)
 {
+       struct hw_perf_event *hwc = &event->hw;
+       int counter = hwc->idx;
+
        switch (counter) {
        case XSCALE_CYCLE_COUNTER:
                asm volatile("mcr p14, 0, %0, c1, c0, 0" : : "r" (val));
@@ -434,24 +440,22 @@ static int xscale_map_event(struct perf_event *event)
                                &xscale_perf_cache_map, 0xFF);
 }
 
-static struct arm_pmu xscale1pmu = {
-       .name           = "xscale1",
-       .handle_irq     = xscale1pmu_handle_irq,
-       .enable         = xscale1pmu_enable_event,
-       .disable        = xscale1pmu_disable_event,
-       .read_counter   = xscale1pmu_read_counter,
-       .write_counter  = xscale1pmu_write_counter,
-       .get_event_idx  = xscale1pmu_get_event_idx,
-       .start          = xscale1pmu_start,
-       .stop           = xscale1pmu_stop,
-       .map_event      = xscale_map_event,
-       .num_events     = 3,
-       .max_period     = (1LLU << 32) - 1,
-};
-
-static struct arm_pmu *__devinit xscale1pmu_init(void)
+static int __devinit xscale1pmu_init(struct arm_pmu *cpu_pmu)
 {
-       return &xscale1pmu;
+       cpu_pmu->name           = "xscale1";
+       cpu_pmu->handle_irq     = xscale1pmu_handle_irq;
+       cpu_pmu->enable         = xscale1pmu_enable_event;
+       cpu_pmu->disable        = xscale1pmu_disable_event;
+       cpu_pmu->read_counter   = xscale1pmu_read_counter;
+       cpu_pmu->write_counter  = xscale1pmu_write_counter;
+       cpu_pmu->get_event_idx  = xscale1pmu_get_event_idx;
+       cpu_pmu->start          = xscale1pmu_start;
+       cpu_pmu->stop           = xscale1pmu_stop;
+       cpu_pmu->map_event      = xscale_map_event;
+       cpu_pmu->num_events     = 3;
+       cpu_pmu->max_period     = (1LLU << 32) - 1;
+
+       return 0;
 }
 
 #define XSCALE2_OVERFLOWED_MASK        0x01f
@@ -567,7 +571,8 @@ xscale2pmu_handle_irq(int irq_num, void *dev)
 {
        unsigned long pmnc, of_flags;
        struct perf_sample_data data;
-       struct pmu_hw_events *cpuc;
+       struct arm_pmu *cpu_pmu = (struct arm_pmu *)dev;
+       struct pmu_hw_events *cpuc = cpu_pmu->get_hw_events();
        struct pt_regs *regs;
        int idx;
 
@@ -585,7 +590,6 @@ xscale2pmu_handle_irq(int irq_num, void *dev)
 
        regs = get_irq_regs();
 
-       cpuc = &__get_cpu_var(cpu_hw_events);
        for (idx = 0; idx < cpu_pmu->num_events; ++idx) {
                struct perf_event *event = cpuc->events[idx];
                struct hw_perf_event *hwc;
@@ -597,13 +601,13 @@ xscale2pmu_handle_irq(int irq_num, void *dev)
                        continue;
 
                hwc = &event->hw;
-               armpmu_event_update(event, hwc, idx);
+               armpmu_event_update(event);
                perf_sample_data_init(&data, 0, hwc->last_period);
-               if (!armpmu_event_set_period(event, hwc, idx))
+               if (!armpmu_event_set_period(event))
                        continue;
 
                if (perf_event_overflow(event, &data, regs))
-                       cpu_pmu->disable(hwc, idx);
+                       cpu_pmu->disable(event);
        }
 
        irq_work_run();
@@ -617,11 +621,13 @@ xscale2pmu_handle_irq(int irq_num, void *dev)
        return IRQ_HANDLED;
 }
 
-static void
-xscale2pmu_enable_event(struct hw_perf_event *hwc, int idx)
+static void xscale2pmu_enable_event(struct perf_event *event)
 {
        unsigned long flags, ien, evtsel;
+       struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
+       struct hw_perf_event *hwc = &event->hw;
        struct pmu_hw_events *events = cpu_pmu->get_hw_events();
+       int idx = hwc->idx;
 
        ien = xscale2pmu_read_int_enable();
        evtsel = xscale2pmu_read_event_select();
@@ -661,11 +667,13 @@ xscale2pmu_enable_event(struct hw_perf_event *hwc, int idx)
        raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
-static void
-xscale2pmu_disable_event(struct hw_perf_event *hwc, int idx)
+static void xscale2pmu_disable_event(struct perf_event *event)
 {
        unsigned long flags, ien, evtsel, of_flags;
+       struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
+       struct hw_perf_event *hwc = &event->hw;
        struct pmu_hw_events *events = cpu_pmu->get_hw_events();
+       int idx = hwc->idx;
 
        ien = xscale2pmu_read_int_enable();
        evtsel = xscale2pmu_read_event_select();
@@ -713,7 +721,7 @@ xscale2pmu_disable_event(struct hw_perf_event *hwc, int idx)
 
 static int
 xscale2pmu_get_event_idx(struct pmu_hw_events *cpuc,
-                       struct hw_perf_event *event)
+                               struct perf_event *event)
 {
        int idx = xscale1pmu_get_event_idx(cpuc, event);
        if (idx >= 0)
@@ -727,8 +735,7 @@ out:
        return idx;
 }
 
-static void
-xscale2pmu_start(void)
+static void xscale2pmu_start(struct arm_pmu *cpu_pmu)
 {
        unsigned long flags, val;
        struct pmu_hw_events *events = cpu_pmu->get_hw_events();
@@ -740,8 +747,7 @@ xscale2pmu_start(void)
        raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
-static void
-xscale2pmu_stop(void)
+static void xscale2pmu_stop(struct arm_pmu *cpu_pmu)
 {
        unsigned long flags, val;
        struct pmu_hw_events *events = cpu_pmu->get_hw_events();
@@ -753,9 +759,10 @@ xscale2pmu_stop(void)
        raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
-static inline u32
-xscale2pmu_read_counter(int counter)
+static inline u32 xscale2pmu_read_counter(struct perf_event *event)
 {
+       struct hw_perf_event *hwc = &event->hw;
+       int counter = hwc->idx;
        u32 val = 0;
 
        switch (counter) {
@@ -779,9 +786,11 @@ xscale2pmu_read_counter(int counter)
        return val;
 }
 
-static inline void
-xscale2pmu_write_counter(int counter, u32 val)
+static inline void xscale2pmu_write_counter(struct perf_event *event, u32 val)
 {
+       struct hw_perf_event *hwc = &event->hw;
+       int counter = hwc->idx;
+
        switch (counter) {
        case XSCALE_CYCLE_COUNTER:
                asm volatile("mcr p14, 0, %0, c1, c1, 0" : : "r" (val));
@@ -801,33 +810,31 @@ xscale2pmu_write_counter(int counter, u32 val)
        }
 }
 
-static struct arm_pmu xscale2pmu = {
-       .name           = "xscale2",
-       .handle_irq     = xscale2pmu_handle_irq,
-       .enable         = xscale2pmu_enable_event,
-       .disable        = xscale2pmu_disable_event,
-       .read_counter   = xscale2pmu_read_counter,
-       .write_counter  = xscale2pmu_write_counter,
-       .get_event_idx  = xscale2pmu_get_event_idx,
-       .start          = xscale2pmu_start,
-       .stop           = xscale2pmu_stop,
-       .map_event      = xscale_map_event,
-       .num_events     = 5,
-       .max_period     = (1LLU << 32) - 1,
-};
-
-static struct arm_pmu *__devinit xscale2pmu_init(void)
+static int __devinit xscale2pmu_init(struct arm_pmu *cpu_pmu)
 {
-       return &xscale2pmu;
+       cpu_pmu->name           = "xscale2";
+       cpu_pmu->handle_irq     = xscale2pmu_handle_irq;
+       cpu_pmu->enable         = xscale2pmu_enable_event;
+       cpu_pmu->disable        = xscale2pmu_disable_event;
+       cpu_pmu->read_counter   = xscale2pmu_read_counter;
+       cpu_pmu->write_counter  = xscale2pmu_write_counter;
+       cpu_pmu->get_event_idx  = xscale2pmu_get_event_idx;
+       cpu_pmu->start          = xscale2pmu_start;
+       cpu_pmu->stop           = xscale2pmu_stop;
+       cpu_pmu->map_event      = xscale_map_event;
+       cpu_pmu->num_events     = 5;
+       cpu_pmu->max_period     = (1LLU << 32) - 1;
+
+       return 0;
 }
 #else
-static struct arm_pmu *__devinit xscale1pmu_init(void)
+static inline int xscale1pmu_init(struct arm_pmu *cpu_pmu)
 {
-       return NULL;
+       return -ENODEV;
 }
 
-static struct arm_pmu *__devinit xscale2pmu_init(void)
+static inline int xscale2pmu_init(struct arm_pmu *cpu_pmu)
 {
-       return NULL;
+       return -ENODEV;
 }
 #endif /* CONFIG_CPU_XSCALE */
index 90084a6de35a75ede68e451a4f521e3a4174fc92..585b9abae60649eaacd413444c99d3a60f424ad3 100644 (file)
@@ -70,6 +70,7 @@ EXPORT_SYMBOL(disable_hlt);
 void enable_hlt(void)
 {
        hlt_counter--;
+       BUG_ON(hlt_counter < 0);
 }
 
 EXPORT_SYMBOL(enable_hlt);
@@ -387,6 +388,10 @@ copy_thread(unsigned long clone_flags, unsigned long stack_start,
                *childregs = *regs;
                childregs->ARM_r0 = 0;
                childregs->ARM_sp = stack_start;
+#if defined CONFIG_CPU_V7M
+               /* Return to Thread mode with Process stack */
+               childregs->ARM_EXC_RET = 0xfffffffdUL;
+#endif
        } else {
                memset(childregs, 0, sizeof(struct pt_regs));
                thread->cpu_context.r4 = stk_sz;
index 739db3a1b2d279216336025d88586d3ffd07a0e0..55df1d59761f024aeb789d29d418cf2d2b51fa4b 100644 (file)
@@ -87,6 +87,9 @@ static const struct pt_regs_offset regoffset_table[] = {
        REG_OFFSET_NAME(pc),
        REG_OFFSET_NAME(cpsr),
        REG_OFFSET_NAME(ORIG_r0),
+#ifdef CONFIG_CPU_V7M
+       REG_OFFSET_NAME(EXC_RET),
+#endif
        REG_OFFSET_END,
 };
 
index da1d1aa20ad957ccd7021815014d12530de4f3a1..3cca0c80edd0c83c452919988b0d550f313db110 100644 (file)
@@ -128,7 +128,9 @@ struct stack {
        u32 und[3];
 } ____cacheline_aligned;
 
+#ifndef CONFIG_CPU_V7M
 static struct stack stacks[NR_CPUS];
+#endif
 
 char elf_platform[ELF_PLATFORM_SIZE];
 EXPORT_SYMBOL(elf_platform);
@@ -207,7 +209,7 @@ static const char *proc_arch[] = {
        "5TEJ",
        "6TEJ",
        "7",
-       "?(11)",
+       "7M",
        "?(12)",
        "?(13)",
        "?(14)",
@@ -216,6 +218,12 @@ static const char *proc_arch[] = {
        "?(17)",
 };
 
+#ifdef CONFIG_CPU_V7M
+static int __get_cpu_architecture(void)
+{
+       return CPU_ARCH_ARMv7M;
+}
+#else
 static int __get_cpu_architecture(void)
 {
        int cpu_arch;
@@ -248,6 +256,7 @@ static int __get_cpu_architecture(void)
 
        return cpu_arch;
 }
+#endif
 
 int __pure cpu_architecture(void)
 {
@@ -375,6 +384,7 @@ static void __init feat_v6_fixup(void)
  */
 void cpu_init(void)
 {
+#ifndef CONFIG_CPU_V7M
        unsigned int cpu = smp_processor_id();
        struct stack *stk = &stacks[cpu];
 
@@ -419,6 +429,7 @@ void cpu_init(void)
              "I" (offsetof(struct stack, und[0])),
              PLC (PSR_F_BIT | PSR_I_BIT | SVC_MODE)
            : "r14");
+#endif
 }
 
 int __cpu_logical_map[NR_CPUS];
index 8e20754dd31d5946f5297aae2023ae2c8d5cd572..fbc8b2623d82f08c8c2926375a7b8a31f943361b 100644 (file)
@@ -294,18 +294,24 @@ static void percpu_timer_setup(void);
 asmlinkage void __cpuinit secondary_start_kernel(void)
 {
        struct mm_struct *mm = &init_mm;
-       unsigned int cpu = smp_processor_id();
+       unsigned int cpu;
+
+       /*
+        * The identity mapping is uncached (strongly ordered), so
+        * switch away from it before attempting any exclusive accesses.
+        */
+       cpu_switch_mm(mm->pgd, mm);
+       enter_lazy_tlb(mm, current);
+       local_flush_tlb_all();
 
        /*
         * All kernel threads share the same mm context; grab a
         * reference and switch to it.
         */
+       cpu = smp_processor_id();
        atomic_inc(&mm->mm_count);
        current->active_mm = mm;
        cpumask_set_cpu(cpu, mm_cpumask(mm));
-       cpu_switch_mm(mm->pgd, mm);
-       enter_lazy_tlb(mm, current);
-       local_flush_tlb_all();
 
        printk("CPU%u: Booted secondary processor\n", cpu);
 
index e1f906989bb8161963d8a714073a8d84a8e2c2e6..b22d700fea2751c60b5dbad689ee0b18305108b3 100644 (file)
@@ -42,10 +42,10 @@ static void twd_set_mode(enum clock_event_mode mode,
 
        switch (mode) {
        case CLOCK_EVT_MODE_PERIODIC:
-               /* timer load already set up */
                ctrl = TWD_TIMER_CONTROL_ENABLE | TWD_TIMER_CONTROL_IT_ENABLE
                        | TWD_TIMER_CONTROL_PERIODIC;
-               __raw_writel(twd_timer_rate / HZ, twd_base + TWD_TIMER_LOAD);
+               __raw_writel(DIV_ROUND_CLOSEST(twd_timer_rate, HZ),
+                       twd_base + TWD_TIMER_LOAD);
                break;
        case CLOCK_EVT_MODE_ONESHOT:
                /* period set, and timer enabled in 'next_event' hook */
index b0179b89a04ce26062184aaf23f86c521fb3009c..12d976b59bd8adfde359311b4fdf0c78df139e83 100644 (file)
@@ -819,6 +819,7 @@ static void __init kuser_get_tls_init(unsigned long vectors)
 
 void __init early_trap_init(void *vectors_base)
 {
+#ifndef CONFIG_CPU_V7M
        unsigned long vectors = (unsigned long)vectors_base;
        extern char __stubs_start[], __stubs_end[];
        extern char __vectors_start[], __vectors_end[];
@@ -850,4 +851,5 @@ void __init early_trap_init(void *vectors_base)
 
        flush_icache_range(vectors, vectors + PAGE_SIZE);
        modify_domain(DOMAIN_USER, DOMAIN_CLIENT);
+#endif
 }
index 9d0a30032d7f0f2ae50f0cbe9eebb80d6da827a3..0dc53854a5d8eb423e468fe255cb0f7c1fa30e15 100644 (file)
@@ -45,6 +45,7 @@ int read_current_timer(unsigned long *timer_val)
        *timer_val = delay_timer->read_current_timer();
        return 0;
 }
+EXPORT_SYMBOL_GPL(read_current_timer);
 
 static void __timer_delay(unsigned long cycles)
 {
index b14207101938adb03c852a708a2261e4a58d6f3d..682abf13d0f476d09ed30f9d0b80f1de3d22fc88 100644 (file)
@@ -45,7 +45,6 @@ config SOC_AT91RM9200
 config SOC_AT91SAM9260
        bool "AT91SAM9260, AT91SAM9XE or AT91SAM9G20"
        select HAVE_AT91_DBGU0
-       select HAVE_NET_MACB
        select SOC_AT91SAM9
        help
          Select this if you are using one of Atmel's AT91SAM9260, AT91SAM9XE
@@ -63,7 +62,6 @@ config SOC_AT91SAM9263
        bool "AT91SAM9263"
        select HAVE_AT91_DBGU1
        select HAVE_FB_ATMEL
-       select HAVE_NET_MACB
        select SOC_AT91SAM9
 
 config SOC_AT91SAM9RL
@@ -76,7 +74,6 @@ config SOC_AT91SAM9G45
        bool "AT91SAM9G45 or AT91SAM9M10 families"
        select HAVE_AT91_DBGU1
        select HAVE_FB_ATMEL
-       select HAVE_NET_MACB
        select SOC_AT91SAM9
        help
          Select this if you are using one of Atmel's AT91SAM9G45 family SoC.
@@ -86,7 +83,6 @@ config SOC_AT91SAM9X5
        bool "AT91SAM9x5 family"
        select HAVE_AT91_DBGU0
        select HAVE_FB_ATMEL
-       select HAVE_NET_MACB
        select SOC_AT91SAM9
        help
          Select this if you are using one of Atmel's AT91SAM9x5 family SoC.
index b4f0565aff638af135c7797b430bbfeb2a29b439..a45473425f5e78ab36e44b71e50d25b41a47628d 100644 (file)
@@ -361,10 +361,10 @@ static unsigned int at91rm9200_default_irq_priority[NR_AIC_IRQS] __initdata = {
        0       /* Advanced Interrupt Controller (IRQ6) */
 };
 
-struct at91_init_soc __initdata at91rm9200_soc = {
+AT91_SOC_START(rm9200)
        .map_io = at91rm9200_map_io,
        .default_irq_priority = at91rm9200_default_irq_priority,
        .ioremap_registers = at91rm9200_ioremap_registers,
        .register_clocks = at91rm9200_register_clocks,
        .init = at91rm9200_initialize,
-};
+AT91_SOC_END
index ad29f93f20cab175555cd2a8c2974deff0fe31fd..46d30831c9a8c667b47036a4d1153b8a1b0e4ef5 100644 (file)
@@ -235,6 +235,9 @@ static struct clk_lookup periph_clocks_lookups[] = {
        CLKDEV_CON_ID("pioA", &pioA_clk),
        CLKDEV_CON_ID("pioB", &pioB_clk),
        CLKDEV_CON_ID("pioC", &pioC_clk),
+       CLKDEV_CON_DEV_ID(NULL, "fffff400.gpio", &pioA_clk),
+       CLKDEV_CON_DEV_ID(NULL, "fffff600.gpio", &pioB_clk),
+       CLKDEV_CON_DEV_ID(NULL, "fffff800.gpio", &pioC_clk),
 };
 
 static struct clk_lookup usart_clocks_lookups[] = {
@@ -390,10 +393,10 @@ static unsigned int at91sam9260_default_irq_priority[NR_AIC_IRQS] __initdata = {
        0,      /* Advanced Interrupt Controller */
 };
 
-struct at91_init_soc __initdata at91sam9260_soc = {
+AT91_SOC_START(sam9260)
        .map_io = at91sam9260_map_io,
        .default_irq_priority = at91sam9260_default_irq_priority,
        .ioremap_registers = at91sam9260_ioremap_registers,
        .register_clocks = at91sam9260_register_clocks,
        .init = at91sam9260_initialize,
-};
+AT91_SOC_END
index a76b8684f52d07328fcfe2f4a08726124b643f5a..0f24cfb9e54ad9b6df19908a88bb5d36e7c6bff4 100644 (file)
@@ -768,6 +768,14 @@ static inline void configure_ssc_pins(unsigned pins)
                at91_set_A_periph(AT91_PIN_PB21, 1);
 }
 
+static struct platform_device at91sam9260_ssc_dai_device = {
+       .name   = "atmel-ssc-dai",
+       .id     = 0,
+       .dev    = {
+               .parent = &(at91sam9260_ssc_device.dev),
+       },
+};
+
 /*
  * SSC controllers are accessed through library code, instead of any
  * kind of all-singing/all-dancing driver.  For example one could be
@@ -792,6 +800,7 @@ void __init at91_add_device_ssc(unsigned id, unsigned pins)
        }
 
        platform_device_register(pdev);
+       platform_device_register(&at91sam9260_ssc_dai_device);
 }
 
 #else
index 8d999eb1a137f1ed72529d296774c084d17da1a4..93a24e921aff8a71a615c6e9ebb07d46e40eb089 100644 (file)
@@ -334,10 +334,10 @@ static unsigned int at91sam9261_default_irq_priority[NR_AIC_IRQS] __initdata = {
        0,      /* Advanced Interrupt Controller */
 };
 
-struct at91_init_soc __initdata at91sam9261_soc = {
+AT91_SOC_START(sam9261)
        .map_io = at91sam9261_map_io,
        .default_irq_priority = at91sam9261_default_irq_priority,
        .ioremap_registers = at91sam9261_ioremap_registers,
        .register_clocks = at91sam9261_register_clocks,
        .init = at91sam9261_initialize,
-};
+AT91_SOC_END
index 6a01d0360dfb8940cbaaa2affc9bb58f88d702d9..f8ea0013623487afcecf67408713da575c0415f1 100644 (file)
@@ -212,6 +212,11 @@ static struct clk_lookup periph_clocks_lookups[] = {
        CLKDEV_CON_DEV_ID("spi_clk", "fffa4000.spi", &spi0_clk),
        CLKDEV_CON_DEV_ID("spi_clk", "fffa8000.spi", &spi1_clk),
        CLKDEV_CON_DEV_ID(NULL, "fff88000.i2c", &twi_clk),
+       CLKDEV_CON_DEV_ID(NULL, "fffff200.gpio", &pioA_clk),
+       CLKDEV_CON_DEV_ID(NULL, "fffff400.gpio", &pioB_clk),
+       CLKDEV_CON_DEV_ID(NULL, "fffff600.gpio", &pioCDE_clk),
+       CLKDEV_CON_DEV_ID(NULL, "fffff800.gpio", &pioCDE_clk),
+       CLKDEV_CON_DEV_ID(NULL, "fffffa00.gpio", &pioCDE_clk),
 };
 
 static struct clk_lookup usart_clocks_lookups[] = {
@@ -365,10 +370,10 @@ static unsigned int at91sam9263_default_irq_priority[NR_AIC_IRQS] __initdata = {
        0,      /* Advanced Interrupt Controller (IRQ1) */
 };
 
-struct at91_init_soc __initdata at91sam9263_soc = {
+AT91_SOC_START(sam9263)
        .map_io = at91sam9263_map_io,
        .default_irq_priority = at91sam9263_default_irq_priority,
        .ioremap_registers = at91sam9263_ioremap_registers,
        .register_clocks = at91sam9263_register_clocks,
        .init = at91sam9263_initialize,
-};
+AT91_SOC_END
index 84af1b506d92a0b1e9e88c885b1d57be95fbf40b..e6dd371d9f56da47689c4a4bb54a435729b517e6 100644 (file)
@@ -260,6 +260,12 @@ static struct clk_lookup periph_clocks_lookups[] = {
        CLKDEV_CON_DEV_ID(NULL, "fff88000.i2c", &twi1_clk),
        /* fake hclk clock */
        CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &uhphs_clk),
+       CLKDEV_CON_DEV_ID(NULL, "fffff200.gpio", &pioA_clk),
+       CLKDEV_CON_DEV_ID(NULL, "fffff400.gpio", &pioB_clk),
+       CLKDEV_CON_DEV_ID(NULL, "fffff600.gpio", &pioC_clk),
+       CLKDEV_CON_DEV_ID(NULL, "fffff800.gpio", &pioDE_clk),
+       CLKDEV_CON_DEV_ID(NULL, "fffffa00.gpio", &pioDE_clk),
+
        CLKDEV_CON_ID("pioA", &pioA_clk),
        CLKDEV_CON_ID("pioB", &pioB_clk),
        CLKDEV_CON_ID("pioC", &pioC_clk),
@@ -409,10 +415,10 @@ static unsigned int at91sam9g45_default_irq_priority[NR_AIC_IRQS] __initdata = {
        0,      /* Advanced Interrupt Controller (IRQ0) */
 };
 
-struct at91_init_soc __initdata at91sam9g45_soc = {
+AT91_SOC_START(sam9g45)
        .map_io = at91sam9g45_map_io,
        .default_irq_priority = at91sam9g45_default_irq_priority,
        .ioremap_registers = at91sam9g45_ioremap_registers,
        .register_clocks = at91sam9g45_register_clocks,
        .init = at91sam9g45_initialize,
-};
+AT91_SOC_END
index 732d3d3f4ec5f7f93430839330d0e473a8063c20..bf8a083a02abdeecf3e2e4a575a496fe20759f89 100644 (file)
@@ -171,10 +171,10 @@ static struct clk_lookup periph_clocks_lookups[] = {
        CLKDEV_CON_DEV_ID("dma_clk", "ffffec00.dma-controller", &dma_clk),
        CLKDEV_CON_DEV_ID(NULL, "f8010000.i2c", &twi0_clk),
        CLKDEV_CON_DEV_ID(NULL, "f8014000.i2c", &twi1_clk),
-       CLKDEV_CON_ID("pioA", &pioAB_clk),
-       CLKDEV_CON_ID("pioB", &pioAB_clk),
-       CLKDEV_CON_ID("pioC", &pioCD_clk),
-       CLKDEV_CON_ID("pioD", &pioCD_clk),
+       CLKDEV_CON_DEV_ID(NULL, "fffff400.gpio", &pioAB_clk),
+       CLKDEV_CON_DEV_ID(NULL, "fffff600.gpio", &pioAB_clk),
+       CLKDEV_CON_DEV_ID(NULL, "fffff800.gpio", &pioCD_clk),
+       CLKDEV_CON_DEV_ID(NULL, "fffffa00.gpio", &pioCD_clk),
        /* additional fake clock for macb_hclk */
        CLKDEV_CON_DEV_ID("hclk", "500000.ohci", &uhp_clk),
        CLKDEV_CON_DEV_ID("ohci_clk", "500000.ohci", &uhp_clk),
@@ -223,13 +223,10 @@ static void __init at91sam9n12_map_io(void)
 void __init at91sam9n12_initialize(void)
 {
        at91_extern_irq = (1 << AT91SAM9N12_ID_IRQ0);
-
-       /* Register GPIO subsystem (using DT) */
-       at91_gpio_init(NULL, 0);
 }
 
-struct at91_init_soc __initdata at91sam9n12_soc = {
+AT91_SOC_START(sam9n12)
        .map_io = at91sam9n12_map_io,
        .register_clocks = at91sam9n12_register_clocks,
        .init = at91sam9n12_initialize,
-};
+AT91_SOC_END
index 72e908412222615134fc0530cc339348093f76be..cbe72e44c13fff62dc537ce8db955408c0284ab1 100644 (file)
@@ -338,10 +338,10 @@ static unsigned int at91sam9rl_default_irq_priority[NR_AIC_IRQS] __initdata = {
        0,      /* Advanced Interrupt Controller */
 };
 
-struct at91_init_soc __initdata at91sam9rl_soc = {
+AT91_SOC_START(sam9rl)
        .map_io = at91sam9rl_map_io,
        .default_irq_priority = at91sam9rl_default_irq_priority,
        .ioremap_registers = at91sam9rl_ioremap_registers,
        .register_clocks = at91sam9rl_register_clocks,
        .init = at91sam9rl_initialize,
-};
+AT91_SOC_END
index e5035380dcbce16e806fb460625fd73d9a3c1153..56d13a4950a778f17c2d00a742c68edf02056a17 100644 (file)
@@ -234,10 +234,10 @@ static struct clk_lookup periph_clocks_lookups[] = {
        CLKDEV_CON_DEV_ID(NULL, "f8010000.i2c", &twi0_clk),
        CLKDEV_CON_DEV_ID(NULL, "f8014000.i2c", &twi1_clk),
        CLKDEV_CON_DEV_ID(NULL, "f8018000.i2c", &twi2_clk),
-       CLKDEV_CON_ID("pioA", &pioAB_clk),
-       CLKDEV_CON_ID("pioB", &pioAB_clk),
-       CLKDEV_CON_ID("pioC", &pioCD_clk),
-       CLKDEV_CON_ID("pioD", &pioCD_clk),
+       CLKDEV_CON_DEV_ID(NULL, "fffff400.gpio", &pioAB_clk),
+       CLKDEV_CON_DEV_ID(NULL, "fffff600.gpio", &pioAB_clk),
+       CLKDEV_CON_DEV_ID(NULL, "fffff800.gpio", &pioCD_clk),
+       CLKDEV_CON_DEV_ID(NULL, "fffffa00.gpio", &pioCD_clk),
        /* additional fake clock for macb_hclk */
        CLKDEV_CON_DEV_ID("hclk", "f802c000.ethernet", &macb0_clk),
        CLKDEV_CON_DEV_ID("hclk", "f8030000.ethernet", &macb1_clk),
@@ -313,18 +313,11 @@ static void __init at91sam9x5_map_io(void)
        at91_init_sram(0, AT91SAM9X5_SRAM_BASE, AT91SAM9X5_SRAM_SIZE);
 }
 
-void __init at91sam9x5_initialize(void)
-{
-       /* Register GPIO subsystem (using DT) */
-       at91_gpio_init(NULL, 0);
-}
-
 /* --------------------------------------------------------------------
  *  Interrupt initialization
  * -------------------------------------------------------------------- */
 
-struct at91_init_soc __initdata at91sam9x5_soc = {
+AT91_SOC_START(sam9x5)
        .map_io = at91sam9x5_map_io,
        .register_clocks = at91sam9x5_register_clocks,
-       .init = at91sam9x5_initialize,
-};
+AT91_SOC_END
index 3e37437a7a613222245df1f297e18cde4a02dc97..aa9b320bad5961877f36117111e19b06314cb7c6 100644 (file)
@@ -53,6 +53,8 @@ static void __init csb337_init_early(void)
 static struct macb_platform_data __initdata csb337_eth_data = {
        .phy_irq_pin    = AT91_PIN_PC2,
        .is_rmii        = 0,
+       /* The CSB337 bootloader stores the MAC the wrong-way around */
+       .rev_eth_addr   = 1,
 };
 
 static struct at91_usbh_data __initdata csb337_usbh_data = {
index e8f45c4e0ea8f01affd71c486d50ea1f42228e4c..3b6a94820fa08d506478de1300cf02858c24dd3e 100644 (file)
@@ -30,8 +30,6 @@
 static const struct of_device_id irq_of_match[] __initconst = {
 
        { .compatible = "atmel,at91rm9200-aic", .data = at91_aic_of_init },
-       { .compatible = "atmel,at91rm9200-gpio", .data = at91_gpio_of_irq_setup },
-       { .compatible = "atmel,at91sam9x5-gpio", .data = at91_gpio_of_irq_setup },
        { /*sentinel*/ }
 };
 
index 3ab2b86a3762a67da9b808386d39c51fb8cd2544..5b6a6f9a94f49f9c6ccc6e670fffa65a9f6c2122 100644 (file)
@@ -353,6 +353,22 @@ static struct i2c_board_info __initdata ek_i2c_devices[] = {
         },
 };
 
+static struct platform_device sam9g20ek_pcm_device = {
+       .name   = "atmel-pcm-audio",
+       .id = -1,
+};
+
+static struct platform_device sam9g20ek_audio_device = {
+       .name   = "at91sam9g20ek-audio",
+       .id     = -1,
+};
+
+static void __init ek_add_device_audio(void)
+{
+       platform_device_register(&sam9g20ek_pcm_device);
+       platform_device_register(&sam9g20ek_audio_device);
+}
+
 
 static void __init ek_board_init(void)
 {
@@ -394,6 +410,7 @@ static void __init ek_board_init(void)
        at91_set_B_periph(AT91_PIN_PC1, 0);
        /* SSC (for WM8731) */
        at91_add_device_ssc(AT91SAM9260_ID_SSC, ATMEL_SSC_TX);
+       ek_add_device_audio();
 }
 
 MACHINE_START(AT91SAM9G20EK, "Atmel AT91SAM9G20-EK")
index be42cf0e74bddd39ded6e1b54d7f17d351a24bc1..c5d7e1e9d7578cffc8265e9205c2a8e8162a311a 100644 (file)
@@ -23,8 +23,6 @@
 #include <linux/io.h>
 #include <linux/irqdomain.h>
 #include <linux/of_address.h>
-#include <linux/of_irq.h>
-#include <linux/of_gpio.h>
 
 #include <asm/mach/irq.h>
 
@@ -33,6 +31,8 @@
 
 #include "generic.h"
 
+#define MAX_NB_GPIO_PER_BANK   32
+
 struct at91_gpio_chip {
        struct gpio_chip        chip;
        struct at91_gpio_chip   *next;          /* Bank sharing same clock */
@@ -46,6 +46,7 @@ struct at91_gpio_chip {
 
 #define to_at91_gpio_chip(c) container_of(c, struct at91_gpio_chip, chip)
 
+static int at91_gpiolib_request(struct gpio_chip *chip, unsigned offset);
 static void at91_gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip);
 static void at91_gpiolib_set(struct gpio_chip *chip, unsigned offset, int val);
 static int at91_gpiolib_get(struct gpio_chip *chip, unsigned offset);
@@ -55,26 +56,27 @@ static int at91_gpiolib_direction_input(struct gpio_chip *chip,
                                        unsigned offset);
 static int at91_gpiolib_to_irq(struct gpio_chip *chip, unsigned offset);
 
-#define AT91_GPIO_CHIP(name, nr_gpio)                                  \
+#define AT91_GPIO_CHIP(name)                                           \
        {                                                               \
                .chip = {                                               \
                        .label            = name,                       \
+                       .request          = at91_gpiolib_request,       \
                        .direction_input  = at91_gpiolib_direction_input, \
                        .direction_output = at91_gpiolib_direction_output, \
                        .get              = at91_gpiolib_get,           \
                        .set              = at91_gpiolib_set,           \
                        .dbg_show         = at91_gpiolib_dbg_show,      \
                        .to_irq           = at91_gpiolib_to_irq,        \
-                       .ngpio            = nr_gpio,                    \
+                       .ngpio            = MAX_NB_GPIO_PER_BANK,       \
                },                                                      \
        }
 
 static struct at91_gpio_chip gpio_chip[] = {
-       AT91_GPIO_CHIP("pioA", 32),
-       AT91_GPIO_CHIP("pioB", 32),
-       AT91_GPIO_CHIP("pioC", 32),
-       AT91_GPIO_CHIP("pioD", 32),
-       AT91_GPIO_CHIP("pioE", 32),
+       AT91_GPIO_CHIP("pioA"),
+       AT91_GPIO_CHIP("pioB"),
+       AT91_GPIO_CHIP("pioC"),
+       AT91_GPIO_CHIP("pioD"),
+       AT91_GPIO_CHIP("pioE"),
 };
 
 static int gpio_banks;
@@ -89,7 +91,7 @@ static unsigned long at91_gpio_caps;
 
 static inline void __iomem *pin_to_controller(unsigned pin)
 {
-       pin /= 32;
+       pin /= MAX_NB_GPIO_PER_BANK;
        if (likely(pin < gpio_banks))
                return gpio_chip[pin].regbase;
 
@@ -98,7 +100,7 @@ static inline void __iomem *pin_to_controller(unsigned pin)
 
 static inline unsigned pin_to_mask(unsigned pin)
 {
-       return 1 << (pin % 32);
+       return 1 << (pin % MAX_NB_GPIO_PER_BANK);
 }
 
 
@@ -713,80 +715,6 @@ postcore_initcall(at91_gpio_debugfs_init);
  */
 static struct lock_class_key gpio_lock_class;
 
-#if defined(CONFIG_OF)
-static int at91_gpio_irq_map(struct irq_domain *h, unsigned int virq,
-                                                       irq_hw_number_t hw)
-{
-       struct at91_gpio_chip   *at91_gpio = h->host_data;
-
-       irq_set_lockdep_class(virq, &gpio_lock_class);
-
-       /*
-        * Can use the "simple" and not "edge" handler since it's
-        * shorter, and the AIC handles interrupts sanely.
-        */
-       irq_set_chip_and_handler(virq, &gpio_irqchip,
-                                handle_simple_irq);
-       set_irq_flags(virq, IRQF_VALID);
-       irq_set_chip_data(virq, at91_gpio);
-
-       return 0;
-}
-
-static struct irq_domain_ops at91_gpio_ops = {
-       .map    = at91_gpio_irq_map,
-       .xlate  = irq_domain_xlate_twocell,
-};
-
-int __init at91_gpio_of_irq_setup(struct device_node *node,
-                                    struct device_node *parent)
-{
-       struct at91_gpio_chip   *prev = NULL;
-       int                     alias_idx = of_alias_get_id(node, "gpio");
-       struct at91_gpio_chip   *at91_gpio = &gpio_chip[alias_idx];
-
-       /* Setup proper .irq_set_type function */
-       if (has_pio3())
-               gpio_irqchip.irq_set_type = alt_gpio_irq_type;
-       else
-               gpio_irqchip.irq_set_type = gpio_irq_type;
-
-       /* Disable irqs of this PIO controller */
-       __raw_writel(~0, at91_gpio->regbase + PIO_IDR);
-
-       /* Setup irq domain */
-       at91_gpio->domain = irq_domain_add_linear(node, at91_gpio->chip.ngpio,
-                                               &at91_gpio_ops, at91_gpio);
-       if (!at91_gpio->domain)
-               panic("at91_gpio.%d: couldn't allocate irq domain (DT).\n",
-                       at91_gpio->pioc_idx);
-
-       /* Setup chained handler */
-       if (at91_gpio->pioc_idx)
-               prev = &gpio_chip[at91_gpio->pioc_idx - 1];
-
-       /* The toplevel handler handles one bank of GPIOs, except
-        * on some SoC it can handles up to three...
-        * We only set up the handler for the first of the list.
-        */
-       if (prev && prev->next == at91_gpio)
-               return 0;
-
-       at91_gpio->pioc_virq = irq_create_mapping(irq_find_host(parent),
-                                                       at91_gpio->pioc_hwirq);
-       irq_set_chip_data(at91_gpio->pioc_virq, at91_gpio);
-       irq_set_chained_handler(at91_gpio->pioc_virq, gpio_irq_handler);
-
-       return 0;
-}
-#else
-int __init at91_gpio_of_irq_setup(struct device_node *node,
-                                    struct device_node *parent)
-{
-       return -EINVAL;
-}
-#endif
-
 /*
  * irqdomain initialization: pile up irqdomains on top of AIC range
  */
@@ -862,6 +790,16 @@ void __init at91_gpio_irq_setup(void)
 }
 
 /* gpiolib support */
+static int at91_gpiolib_request(struct gpio_chip *chip, unsigned offset)
+{
+       struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
+       void __iomem *pio = at91_gpio->regbase;
+       unsigned mask = 1 << offset;
+
+       __raw_writel(mask, pio + PIO_PER);
+       return 0;
+}
+
 static int at91_gpiolib_direction_input(struct gpio_chip *chip,
                                        unsigned offset)
 {
@@ -975,81 +913,11 @@ err:
        return -EINVAL;
 }
 
-#ifdef CONFIG_OF_GPIO
-static void __init of_at91_gpio_init_one(struct device_node *np)
-{
-       int alias_idx;
-       struct at91_gpio_chip *at91_gpio;
-
-       if (!np)
-               return;
-
-       alias_idx = of_alias_get_id(np, "gpio");
-       if (alias_idx >= MAX_GPIO_BANKS) {
-               pr_err("at91_gpio, failed alias idx(%d) > MAX_GPIO_BANKS(%d), ignoring.\n",
-                                               alias_idx, MAX_GPIO_BANKS);
-               return;
-       }
-
-       at91_gpio = &gpio_chip[alias_idx];
-       at91_gpio->chip.base = alias_idx * at91_gpio->chip.ngpio;
-
-       at91_gpio->regbase = of_iomap(np, 0);
-       if (!at91_gpio->regbase) {
-               pr_err("at91_gpio.%d, failed to map registers, ignoring.\n",
-                                                               alias_idx);
-               return;
-       }
-
-       /* Get the interrupts property */
-       if (of_property_read_u32(np, "interrupts", &at91_gpio->pioc_hwirq)) {
-               pr_err("at91_gpio.%d, failed to get interrupts property, ignoring.\n",
-                                                               alias_idx);
-               goto ioremap_err;
-       }
-
-       /* Get capabilities from compatibility property */
-       if (of_device_is_compatible(np, "atmel,at91sam9x5-gpio"))
-               at91_gpio_caps |= AT91_GPIO_CAP_PIO3;
-
-       /* Setup clock */
-       if (at91_gpio_setup_clk(alias_idx))
-               goto ioremap_err;
-
-       at91_gpio->chip.of_node = np;
-       gpio_banks = max(gpio_banks, alias_idx + 1);
-       at91_gpio->pioc_idx = alias_idx;
-       return;
-
-ioremap_err:
-       iounmap(at91_gpio->regbase);
-}
-
-static int __init of_at91_gpio_init(void)
-{
-       struct device_node *np = NULL;
-
-       /*
-        * This isn't ideal, but it gets things hooked up until this
-        * driver is converted into a platform_device
-        */
-       for_each_compatible_node(np, NULL, "atmel,at91rm9200-gpio")
-               of_at91_gpio_init_one(np);
-
-       return gpio_banks > 0 ? 0 : -EINVAL;
-}
-#else
-static int __init of_at91_gpio_init(void)
-{
-       return -EINVAL;
-}
-#endif
-
 static void __init at91_gpio_init_one(int idx, u32 regbase, int pioc_hwirq)
 {
        struct at91_gpio_chip *at91_gpio = &gpio_chip[idx];
 
-       at91_gpio->chip.base = idx * at91_gpio->chip.ngpio;
+       at91_gpio->chip.base = idx * MAX_NB_GPIO_PER_BANK;
        at91_gpio->pioc_hwirq = pioc_hwirq;
        at91_gpio->pioc_idx = idx;
 
@@ -1079,11 +947,11 @@ void __init at91_gpio_init(struct at91_gpio_bank *data, int nr_banks)
 
        BUG_ON(nr_banks > MAX_GPIO_BANKS);
 
-       if (of_at91_gpio_init() < 0) {
-               /* No GPIO controller found in device tree */
-               for (i = 0; i < nr_banks; i++)
-                       at91_gpio_init_one(i, data[i].regbase, data[i].id);
-       }
+       if (of_have_populated_dt())
+               return;
+
+       for (i = 0; i < nr_banks; i++)
+               at91_gpio_init_one(i, data[i].regbase, data[i].id);
 
        for (i = 0; i < gpio_banks; i++) {
                at91_gpio = &gpio_chip[i];
diff --git a/arch/arm/mach-at91/include/mach/at91rm9200_emac.h b/arch/arm/mach-at91/include/mach/at91rm9200_emac.h
deleted file mode 100644 (file)
index b8260cd..0000000
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * arch/arm/mach-at91/include/mach/at91rm9200_emac.h
- *
- * Copyright (C) 2005 Ivan Kokshaysky
- * Copyright (C) SAN People
- *
- * Ethernet MAC registers.
- * Based on AT91RM9200 datasheet revision E.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef AT91RM9200_EMAC_H
-#define AT91RM9200_EMAC_H
-
-#define        AT91_EMAC_CTL           0x00    /* Control Register */
-#define                AT91_EMAC_LB            (1 <<  0)       /* Loopback */
-#define                AT91_EMAC_LBL           (1 <<  1)       /* Loopback Local */
-#define                AT91_EMAC_RE            (1 <<  2)       /* Receive Enable */
-#define                AT91_EMAC_TE            (1 <<  3)       /* Transmit Enable */
-#define                AT91_EMAC_MPE           (1 <<  4)       /* Management Port Enable */
-#define                AT91_EMAC_CSR           (1 <<  5)       /* Clear Statistics Registers */
-#define                AT91_EMAC_INCSTAT       (1 <<  6)       /* Increment Statistics Registers */
-#define                AT91_EMAC_WES           (1 <<  7)       /* Write Enable for Statistics Registers */
-#define                AT91_EMAC_BP            (1 <<  8)       /* Back Pressure */
-
-#define        AT91_EMAC_CFG           0x04    /* Configuration Register */
-#define                AT91_EMAC_SPD           (1 <<  0)       /* Speed */
-#define                AT91_EMAC_FD            (1 <<  1)       /* Full Duplex */
-#define                AT91_EMAC_BR            (1 <<  2)       /* Bit Rate */
-#define                AT91_EMAC_CAF           (1 <<  4)       /* Copy All Frames */
-#define                AT91_EMAC_NBC           (1 <<  5)       /* No Broadcast */
-#define                AT91_EMAC_MTI           (1 <<  6)       /* Multicast Hash Enable */
-#define                AT91_EMAC_UNI           (1 <<  7)       /* Unicast Hash Enable */
-#define                AT91_EMAC_BIG           (1 <<  8)       /* Receive 1522 Bytes */
-#define                AT91_EMAC_EAE           (1 <<  9)       /* External Address Match Enable */
-#define                AT91_EMAC_CLK           (3 << 10)       /* MDC Clock Divisor */
-#define                AT91_EMAC_CLK_DIV8              (0 << 10)
-#define                AT91_EMAC_CLK_DIV16             (1 << 10)
-#define                AT91_EMAC_CLK_DIV32             (2 << 10)
-#define                AT91_EMAC_CLK_DIV64             (3 << 10)
-#define                AT91_EMAC_RTY           (1 << 12)       /* Retry Test */
-#define                AT91_EMAC_RMII          (1 << 13)       /* Reduce MII (RMII) */
-
-#define        AT91_EMAC_SR            0x08    /* Status Register */
-#define                AT91_EMAC_SR_LINK       (1 <<  0)       /* Link */
-#define                AT91_EMAC_SR_MDIO       (1 <<  1)       /* MDIO pin */
-#define                AT91_EMAC_SR_IDLE       (1 <<  2)       /* PHY idle */
-
-#define        AT91_EMAC_TAR           0x0c    /* Transmit Address Register */
-
-#define        AT91_EMAC_TCR           0x10    /* Transmit Control Register */
-#define                AT91_EMAC_LEN           (0x7ff << 0)    /* Transmit Frame Length */
-#define                AT91_EMAC_NCRC          (1     << 15)   /* No CRC */
-
-#define        AT91_EMAC_TSR           0x14    /* Transmit Status Register */
-#define                AT91_EMAC_TSR_OVR       (1 <<  0)       /* Transmit Buffer Overrun */
-#define                AT91_EMAC_TSR_COL       (1 <<  1)       /* Collision Occurred */
-#define                AT91_EMAC_TSR_RLE       (1 <<  2)       /* Retry Limit Exceeded */
-#define                AT91_EMAC_TSR_IDLE      (1 <<  3)       /* Transmitter Idle */
-#define                AT91_EMAC_TSR_BNQ       (1 <<  4)       /* Transmit Buffer not Queued */
-#define                AT91_EMAC_TSR_COMP      (1 <<  5)       /* Transmit Complete */
-#define                AT91_EMAC_TSR_UND       (1 <<  6)       /* Transmit Underrun */
-
-#define        AT91_EMAC_RBQP          0x18    /* Receive Buffer Queue Pointer */
-
-#define        AT91_EMAC_RSR           0x20    /* Receive Status Register */
-#define                AT91_EMAC_RSR_BNA       (1 <<  0)       /* Buffer Not Available */
-#define                AT91_EMAC_RSR_REC       (1 <<  1)       /* Frame Received */
-#define                AT91_EMAC_RSR_OVR       (1 <<  2)       /* RX Overrun */
-
-#define        AT91_EMAC_ISR           0x24    /* Interrupt Status Register */
-#define                AT91_EMAC_DONE          (1 <<  0)       /* Management Done */
-#define                AT91_EMAC_RCOM          (1 <<  1)       /* Receive Complete */
-#define                AT91_EMAC_RBNA          (1 <<  2)       /* Receive Buffer Not Available */
-#define                AT91_EMAC_TOVR          (1 <<  3)       /* Transmit Buffer Overrun */
-#define                AT91_EMAC_TUND          (1 <<  4)       /* Transmit Buffer Underrun */
-#define                AT91_EMAC_RTRY          (1 <<  5)       /* Retry Limit */
-#define                AT91_EMAC_TBRE          (1 <<  6)       /* Transmit Buffer Register Empty */
-#define                AT91_EMAC_TCOM          (1 <<  7)       /* Transmit Complete */
-#define                AT91_EMAC_TIDLE         (1 <<  8)       /* Transmit Idle */
-#define                AT91_EMAC_LINK          (1 <<  9)       /* Link */
-#define                AT91_EMAC_ROVR          (1 << 10)       /* RX Overrun */
-#define                AT91_EMAC_ABT           (1 << 11)       /* Abort */
-
-#define        AT91_EMAC_IER           0x28    /* Interrupt Enable Register */
-#define        AT91_EMAC_IDR           0x2c    /* Interrupt Disable Register */
-#define        AT91_EMAC_IMR           0x30    /* Interrupt Mask Register */
-
-#define        AT91_EMAC_MAN           0x34    /* PHY Maintenance Register */
-#define                AT91_EMAC_DATA          (0xffff << 0)   /* MDIO Data */
-#define                AT91_EMAC_REGA          (0x1f   << 18)  /* MDIO Register */
-#define                AT91_EMAC_PHYA          (0x1f   << 23)  /* MDIO PHY Address */
-#define                AT91_EMAC_RW            (3      << 28)  /* Read/Write operation */
-#define                        AT91_EMAC_RW_W          (1 << 28)
-#define                        AT91_EMAC_RW_R          (2 << 28)
-#define                AT91_EMAC_MAN_802_3     0x40020000      /* IEEE 802.3 value */
-
-/*
- * Statistics Registers.
- */
-#define AT91_EMAC_FRA          0x40    /* Frames Transmitted OK */
-#define AT91_EMAC_SCOL         0x44    /* Single Collision Frame */
-#define AT91_EMAC_MCOL         0x48    /* Multiple Collision Frame */
-#define AT91_EMAC_OK           0x4c    /* Frames Received OK */
-#define AT91_EMAC_SEQE         0x50    /* Frame Check Sequence Error */
-#define AT91_EMAC_ALE          0x54    /* Alignmemt Error */
-#define AT91_EMAC_DTE          0x58    /* Deffered Transmission Frame */
-#define AT91_EMAC_LCOL         0x5c    /* Late Collision */
-#define AT91_EMAC_ECOL         0x60    /* Excessive Collision */
-#define AT91_EMAC_TUE          0x64    /* Transmit Underrun Error */
-#define AT91_EMAC_CSE          0x68    /* Carrier Sense Error */
-#define AT91_EMAC_DRFC         0x6c    /* Discard RX Frame */
-#define AT91_EMAC_ROV          0x70    /* Receive Overrun */
-#define AT91_EMAC_CDE          0x74    /* Code Error */
-#define AT91_EMAC_ELR          0x78    /* Excessive Length Error */
-#define AT91_EMAC_RJB          0x7c    /* Receive Jabber */
-#define AT91_EMAC_USF          0x80    /* Undersize Frame */
-#define AT91_EMAC_SQEE         0x84    /* SQE Test Error */
-
-/*
- * Address Registers.
- */
-#define AT91_EMAC_HSL          0x90    /* Hash Address Low [31:0] */
-#define AT91_EMAC_HSH          0x94    /* Hash Address High [63:32] */
-#define AT91_EMAC_SA1L         0x98    /* Specific Address 1 Low, bytes 0-3 */
-#define AT91_EMAC_SA1H         0x9c    /* Specific Address 1 High, bytes 4-5 */
-#define AT91_EMAC_SA2L         0xa0    /* Specific Address 2 Low, bytes 0-3 */
-#define AT91_EMAC_SA2H         0xa4    /* Specific Address 2 High, bytes 4-5 */
-#define AT91_EMAC_SA3L         0xa8    /* Specific Address 3 Low, bytes 0-3 */
-#define AT91_EMAC_SA3H         0xac    /* Specific Address 3 High, bytes 4-5 */
-#define AT91_EMAC_SA4L         0xb0    /* Specific Address 4 Low, bytes 0-3 */
-#define AT91_EMAC_SA4H         0xb4    /* Specific Address 4 High, bytes 4-5 */
-
-#endif
index da9881b161e1e15dc0693a74c2ce2716a0ebd5d3..523daa92be10b4424dfd1a62d225d93decf0709a 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/mm.h>
 #include <linux/pm.h>
 #include <linux/of_address.h>
+#include <linux/pinctrl/machine.h>
 
 #include <asm/system_misc.h>
 #include <asm/mach/map.h>
@@ -448,7 +449,8 @@ void __init at91_dt_initialize(void)
        /* Register the processor-specific clocks */
        at91_boot_soc.register_clocks();
 
-       at91_boot_soc.init();
+       if (at91_boot_soc.init)
+               at91_boot_soc.init();
 }
 #endif
 
@@ -463,4 +465,6 @@ void __init at91_initialize(unsigned long main_clock)
        at91_boot_soc.register_clocks();
 
        at91_boot_soc.init();
+
+       pinctrl_provide_dummies();
 }
index a9cfeb15371959b06d800325b0d9896217842b02..9c6d3d4f9a23ab43d4ba7a1fb58624a0b774b8b4 100644 (file)
@@ -5,6 +5,7 @@
  */
 
 struct at91_init_soc {
+       int builtin;
        unsigned int *default_irq_priority;
        void (*map_io)(void);
        void (*ioremap_registers)(void);
@@ -22,9 +23,18 @@ extern struct at91_init_soc at91sam9rl_soc;
 extern struct at91_init_soc at91sam9x5_soc;
 extern struct at91_init_soc at91sam9n12_soc;
 
+#define AT91_SOC_START(_name)                          \
+struct at91_init_soc __initdata at91##_name##_soc      \
+ __used                                                        \
+                                               = {     \
+       .builtin        = 1,                            \
+
+#define AT91_SOC_END                                   \
+};
+
 static inline int at91_soc_is_enabled(void)
 {
-       return at91_boot_soc.init != NULL;
+       return at91_boot_soc.builtin;
 }
 
 #if !defined(CONFIG_SOC_AT91RM9200)
index 2c5fb4c7e509b8786fb1ba0d45cb974bc373f4d2..8a00cee8222802bdfacda361921f0f94b0497afd 100644 (file)
@@ -24,6 +24,8 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/physmap.h>
 #include <linux/mtd/partitions.h>
+#include <linux/usb/ehci_pdriver.h>
+#include <linux/usb/ohci_pdriver.h>
 #include <asm/setup.h>
 #include <asm/mach-types.h>
 #include <asm/hardware/gic.h>
@@ -32,6 +34,7 @@
 #include <asm/mach/time.h>
 #include <mach/cns3xxx.h>
 #include <mach/irqs.h>
+#include <mach/pm.h>
 #include "core.h"
 #include "devices.h"
 
@@ -125,13 +128,53 @@ static struct resource cns3xxx_usb_ehci_resources[] = {
 
 static u64 cns3xxx_usb_ehci_dma_mask = DMA_BIT_MASK(32);
 
+static int csn3xxx_usb_power_on(struct platform_device *pdev)
+{
+       /*
+        * EHCI and OHCI share the same clock and power,
+        * resetting twice would cause the 1st controller been reset.
+        * Therefore only do power up  at the first up device, and
+        * power down at the last down device.
+        *
+        * Set USB AHB INCR length to 16
+        */
+       if (atomic_inc_return(&usb_pwr_ref) == 1) {
+               cns3xxx_pwr_power_up(1 << PM_PLL_HM_PD_CTRL_REG_OFFSET_PLL_USB);
+               cns3xxx_pwr_clk_en(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST);
+               cns3xxx_pwr_soft_rst(1 << PM_SOFT_RST_REG_OFFST_USB_HOST);
+               __raw_writel((__raw_readl(MISC_CHIP_CONFIG_REG) | (0X2 << 24)),
+                       MISC_CHIP_CONFIG_REG);
+       }
+
+       return 0;
+}
+
+static void csn3xxx_usb_power_off(struct platform_device *pdev)
+{
+       /*
+        * EHCI and OHCI share the same clock and power,
+        * resetting twice would cause the 1st controller been reset.
+        * Therefore only do power up  at the first up device, and
+        * power down at the last down device.
+        */
+       if (atomic_dec_return(&usb_pwr_ref) == 0)
+               cns3xxx_pwr_clk_dis(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST);
+}
+
+static struct usb_ehci_pdata cns3xxx_usb_ehci_pdata = {
+       .port_power_off = 1,
+       .power_on       = csn3xxx_usb_power_on,
+       .power_off      = csn3xxx_usb_power_off,
+};
+
 static struct platform_device cns3xxx_usb_ehci_device = {
-       .name          = "cns3xxx-ehci",
+       .name          = "ehci-platform",
        .num_resources = ARRAY_SIZE(cns3xxx_usb_ehci_resources),
        .resource      = cns3xxx_usb_ehci_resources,
        .dev           = {
                .dma_mask          = &cns3xxx_usb_ehci_dma_mask,
                .coherent_dma_mask = DMA_BIT_MASK(32),
+               .platform_data     = &cns3xxx_usb_ehci_pdata,
        },
 };
 
@@ -149,13 +192,20 @@ static struct resource cns3xxx_usb_ohci_resources[] = {
 
 static u64 cns3xxx_usb_ohci_dma_mask = DMA_BIT_MASK(32);
 
+static struct usb_ohci_pdata cns3xxx_usb_ohci_pdata = {
+       .num_ports      = 1,
+       .power_on       = csn3xxx_usb_power_on,
+       .power_off      = csn3xxx_usb_power_off,
+};
+
 static struct platform_device cns3xxx_usb_ohci_device = {
-       .name          = "cns3xxx-ohci",
+       .name          = "ohci-platform",
        .num_resources = ARRAY_SIZE(cns3xxx_usb_ohci_resources),
        .resource      = cns3xxx_usb_ohci_resources,
        .dev           = {
                .dma_mask          = &cns3xxx_usb_ohci_dma_mask,
                .coherent_dma_mask = DMA_BIT_MASK(32),
+               .platform_data     = &cns3xxx_usb_ohci_pdata,
        },
 };
 
index 32ee3f89596738d988a00105c0358d4ff1a61f1b..d9bc3fa7bb228a8c9e7f2feca9bac83b88ac16f5 100644 (file)
@@ -762,16 +762,19 @@ static u8 da850_iis_serializer_direction[] = {
 };
 
 static struct snd_platform_data da850_evm_snd_data = {
-       .tx_dma_offset  = 0x2000,
-       .rx_dma_offset  = 0x2000,
-       .op_mode        = DAVINCI_MCASP_IIS_MODE,
-       .num_serializer = ARRAY_SIZE(da850_iis_serializer_direction),
-       .tdm_slots      = 2,
-       .serial_dir     = da850_iis_serializer_direction,
-       .asp_chan_q     = EVENTQ_0,
-       .version        = MCASP_VERSION_2,
-       .txnumevt       = 1,
-       .rxnumevt       = 1,
+       .tx_dma_offset          = 0x2000,
+       .rx_dma_offset          = 0x2000,
+       .op_mode                = DAVINCI_MCASP_IIS_MODE,
+       .num_serializer         = ARRAY_SIZE(da850_iis_serializer_direction),
+       .tdm_slots              = 2,
+       .serial_dir             = da850_iis_serializer_direction,
+       .asp_chan_q             = EVENTQ_0,
+       .ram_chan_q             = EVENTQ_1,
+       .version                = MCASP_VERSION_2,
+       .txnumevt               = 1,
+       .rxnumevt               = 1,
+       .sram_size_playback     = SZ_8K,
+       .sram_size_capture      = SZ_8K,
 };
 
 static const short da850_evm_mcasp_pins[] __initconst = {
@@ -1509,6 +1512,7 @@ static __init void da850_evm_init(void)
                pr_warning("da850_evm_init: mcasp mux setup failed: %d\n",
                                ret);
 
+       da850_evm_snd_data.sram_pool = sram_get_gen_pool();
        da8xx_register_mcasp(0, &da850_evm_snd_data);
 
        ret = davinci_cfg_reg_list(da850_lcdcntl_pins);
index b37bef1d5ffad9828f6734eb9a50262327ea950d..f723fe13d0f032c48126c1e745c894e296d7ccbf 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/irq.h>
 #include <plat/time.h>
 #include <linux/platform_data/usb-ehci-orion.h>
+#include <plat/irq.h>
 #include <plat/common.h>
 #include <plat/addr-map.h>
 #include "common.h"
@@ -109,8 +110,8 @@ static void __init dove_clk_init(void)
 
        orion_clkdev_add(NULL, "orion-ehci.0", usb0);
        orion_clkdev_add(NULL, "orion-ehci.1", usb1);
-       orion_clkdev_add(NULL, "mv643xx_eth.0", ge);
-       orion_clkdev_add("0", "sata_mv.0", sata);
+       orion_clkdev_add(NULL, "mv643xx_eth_port.0", ge);
+       orion_clkdev_add(NULL, "sata_mv.0", sata);
        orion_clkdev_add("0", "pcie", pex0);
        orion_clkdev_add("1", "pcie", pex1);
        orion_clkdev_add(NULL, "sdhci-dove.0", sdio0);
@@ -399,7 +400,7 @@ static void __init dove_dt_init(void)
                (dove_tclk + 499999) / 1000000);
 
 #ifdef CONFIG_CACHE_TAUROS2
-       tauros2_init();
+       tauros2_init(0);
 #endif
        dove_setup_cpu_mbus();
 
@@ -415,7 +416,6 @@ static void __init dove_dt_init(void)
        dove_ehci0_init();
        dove_ehci1_init();
        dove_pcie_init(1, 1);
-       dove_crypto_init();
 
        of_platform_populate(NULL, of_default_bus_match_table,
                             dove_auxdata_lookup, NULL);
index bb15b26041cb7d6bd13a5ca4d5532cb66632e2cc..0ef4435b16570dccde5af41737bf25987051270d 100644 (file)
@@ -10,6 +10,7 @@
 
 #include <linux/kernel.h>
 #include <linux/pci.h>
+#include <linux/clk.h>
 #include <video/vga.h>
 #include <asm/mach/pci.h>
 #include <asm/mach/arch.h>
@@ -188,6 +189,10 @@ static void __init add_pcie_port(int index, void __iomem *base)
 
        if (orion_pcie_link_up(base)) {
                struct pcie_port *pp = &pcie_port[num_pcie_ports++];
+               struct clk *clk = clk_get_sys("pcie", (index ? "1" : "0"));
+
+               if (!IS_ERR(clk))
+                       clk_prepare_enable(clk);
 
                printk(KERN_INFO "link up\n");
 
index da55107033ddad6490550722863ade8273695ffc..bb3b09aa9183a4628476703b448d5be88b882040 100644 (file)
@@ -63,6 +63,7 @@ config SOC_EXYNOS5250
        depends on ARCH_EXYNOS5
        select S5P_PM if PM
        select S5P_SLEEP if PM
+       select S5P_DEV_MFC
        select SAMSUNG_DMADEV
        help
          Enable EXYNOS5250 SoC support
index 6a45c9a9abe9115503ffcac36c4baca4d22c563f..fa8a13405c94388de84e9b9d5de36d47f6cfbf5e 100644 (file)
@@ -611,11 +611,6 @@ static struct clk exynos4_init_clocks_off[] = {
                .devname        = "exynos4210-spi.2",
                .enable         = exynos4_clk_ip_peril_ctrl,
                .ctrlbit        = (1 << 18),
-       }, {
-               .name           = "iis",
-               .devname        = "samsung-i2s.0",
-               .enable         = exynos4_clk_ip_peril_ctrl,
-               .ctrlbit        = (1 << 19),
        }, {
                .name           = "iis",
                .devname        = "samsung-i2s.1",
index c44ca1ee1b8d0196de2ac413bad5af226bc83bc9..2ca9391d9f171ba3cfefb745e3f229429af8e915 100644 (file)
@@ -664,7 +664,7 @@ static struct clk exynos5_init_clocks_off[] = {
                .ctrlbit        = (1 << 25),
        }, {
                .name           = "mfc",
-               .devname        = "s5p-mfc",
+               .devname        = "s5p-mfc-v6",
                .enable         = exynos5_clk_ip_mfc_ctrl,
                .ctrlbit        = (1 << 0),
        }, {
@@ -677,6 +677,11 @@ static struct clk exynos5_init_clocks_off[] = {
                .devname        = "s5p-mixer",
                .enable         = exynos5_clk_ip_disp1_ctrl,
                .ctrlbit        = (1 << 5),
+       }, {
+               .name           = "dp",
+               .devname        = "exynos-dp",
+               .enable         = exynos5_clk_ip_disp1_ctrl,
+               .ctrlbit        = (1 << 4),
        }, {
                .name           = "jpeg",
                .enable         = exynos5_clk_ip_gen_ctrl,
index 715b690e5009608c9d9bfa42b1bb6e2d595b79ee..1947be8e5f5bffec59d1542e8ebbbc6bbce36970 100644 (file)
@@ -47,6 +47,7 @@
 #include <plat/fimc-core.h>
 #include <plat/iic-core.h>
 #include <plat/tv-core.h>
+#include <plat/spi-core.h>
 #include <plat/regs-serial.h>
 
 #include "common.h"
@@ -346,6 +347,8 @@ static void __init exynos4_map_io(void)
 
        s5p_fb_setname(0, "exynos4-fb");
        s5p_hdmi_setname("exynos4-hdmi");
+
+       s3c64xx_spi_setname("exynos4210-spi");
 }
 
 static void __init exynos5_map_io(void)
@@ -366,6 +369,8 @@ static void __init exynos5_map_io(void)
        s3c_i2c0_setname("s3c2440-i2c");
        s3c_i2c1_setname("s3c2440-i2c");
        s3c_i2c2_setname("s3c2440-i2c");
+
+       s3c64xx_spi_setname("exynos4210-spi");
 }
 
 static void __init exynos4_init_clocks(int xtal)
index e58d786faf78c773636f10b168415df2c0ac61ef..eadf4b59e7d28e6ae1d254f0f86a398759d5f9bc 100644 (file)
@@ -99,6 +99,7 @@ static char const *exynos4_dt_compat[] __initdata = {
 
 DT_MACHINE_START(EXYNOS4210_DT, "Samsung Exynos4 (Flattened Device Tree)")
        /* Maintainer: Thomas Abraham <thomas.abraham@linaro.org> */
+       .smp            = smp_ops(exynos_smp_ops),
        .init_irq       = exynos4_init_irq,
        .map_io         = exynos4_dt_map_io,
        .handle_irq     = gic_handle_irq,
index db1cd8eacf2820caeeb8700c8fca0a0d35951703..b7f1154088bdeba2d144d0a7299ba9dc5324a1a3 100644 (file)
@@ -11,6 +11,8 @@
 
 #include <linux/of_platform.h>
 #include <linux/serial_core.h>
+#include <linux/memblock.h>
+#include <linux/of_fdt.h>
 
 #include <asm/mach/arch.h>
 #include <asm/hardware/gic.h>
@@ -18,6 +20,7 @@
 
 #include <plat/cpu.h>
 #include <plat/regs-serial.h>
+#include <plat/mfc.h>
 
 #include "common.h"
 
@@ -72,6 +75,7 @@ static const struct of_dev_auxdata exynos5250_auxdata_lookup[] __initconst = {
                                "exynos-gsc.2", NULL),
        OF_DEV_AUXDATA("samsung,exynos5-gsc", EXYNOS5_PA_GSC3,
                                "exynos-gsc.3", NULL),
+       OF_DEV_AUXDATA("samsung,mfc-v6", 0x11000000, "s5p-mfc-v6", NULL),
        {},
 };
 
@@ -92,6 +96,17 @@ static char const *exynos5250_dt_compat[] __initdata = {
        NULL
 };
 
+static void __init exynos5_reserve(void)
+{
+       struct s5p_mfc_dt_meminfo mfc_mem;
+
+       /* Reserve memory for MFC only if it's available */
+       mfc_mem.compatible = "samsung,mfc-v6";
+       if (of_scan_flat_dt(s5p_fdt_find_mfc_mem, &mfc_mem))
+               s5p_mfc_reserve_mem(mfc_mem.roff, mfc_mem.rsize, mfc_mem.loff,
+                               mfc_mem.lsize);
+}
+
 DT_MACHINE_START(EXYNOS5_DT, "SAMSUNG EXYNOS5 (Flattened Device Tree)")
        /* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
        .init_irq       = exynos5_init_irq,
@@ -103,4 +118,5 @@ DT_MACHINE_START(EXYNOS5_DT, "SAMSUNG EXYNOS5 (Flattened Device Tree)")
        .timer          = &exynos4_timer,
        .dt_compat      = exynos5250_dt_compat,
        .restart        = exynos5_restart,
+       .reserve        = exynos5_reserve,
 MACHINE_END
index c05d7aa84031b70a601598fd0a5542dfbf3056f3..0b3f88e3ce64eef430d9ad7b50e08f8e1c7ef780 100644 (file)
@@ -113,7 +113,6 @@ static struct s3c_sdhci_platdata nuri_hsmmc0_data __initdata = {
        .host_caps              = (MMC_CAP_8_BIT_DATA | MMC_CAP_4_BIT_DATA |
                                MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
                                MMC_CAP_ERASE),
-       .host_caps2             = MMC_CAP2_BROKEN_VOLTAGE,
        .cd_type                = S3C_SDHCI_CD_PERMANENT,
 };
 
index ebc9dd339a3899ae6170a24a0ddf2c1e44b1281d..a64c9c2ea9a2d34fd0455379a83eab5a4da212d9 100644 (file)
@@ -754,7 +754,6 @@ static struct s3c_sdhci_platdata universal_hsmmc0_data __initdata = {
        .max_width              = 8,
        .host_caps              = (MMC_CAP_8_BIT_DATA | MMC_CAP_4_BIT_DATA |
                                MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED),
-       .host_caps2             = MMC_CAP2_BROKEN_VOLTAGE,
        .cd_type                = S3C_SDHCI_CD_PERMANENT,
 };
 
similarity index 99%
rename from arch/arm/plat-mxc/3ds_debugboard.c
rename to arch/arm/mach-imx/3ds_debugboard.c
index 5c10ad05df740fe6d514ad61fea52b3cd01f12c5..1343773529665e876db7bf08e34b529bb3e80a81 100644 (file)
@@ -21,7 +21,7 @@
 #include <linux/regulator/machine.h>
 #include <linux/regulator/fixed.h>
 
-#include <mach/hardware.h>
+#include "hardware.h"
 
 /* LAN9217 ethernet base address */
 #define LAN9217_BASE_ADDR(n)   (n + 0x0)
index 8d276584650e810d349868ba4c154823cbe271aa..892631f1e4c877565e74888e573c65573ec21938 100644 (file)
@@ -1,3 +1,70 @@
+config ARCH_MXC
+       def_bool y if ARCH_MULTI_V4_V5 || ARCH_MULTI_V6_V7
+       select ARCH_REQUIRE_GPIOLIB
+       select ARM_PATCH_PHYS_VIRT
+       select AUTO_ZRELADDR if !ZBOOT_ROM
+       select CLKDEV_LOOKUP
+       select CLKSRC_MMIO
+       select GENERIC_CLOCKEVENTS
+       select GENERIC_IRQ_CHIP
+       select MULTI_IRQ_HANDLER
+       select SPARSE_IRQ
+       select USE_OF
+       help
+         Support for Freescale MXC/iMX-based family of processors
+
+menu "Freescale i.MX support"
+       depends on ARCH_MXC
+
+config MXC_IRQ_PRIOR
+       bool "Use IRQ priority"
+       help
+         Select this if you want to use prioritized IRQ handling.
+         This feature prevents higher priority ISR to be interrupted
+         by lower priority IRQ even IRQF_DISABLED flag is not set.
+         This may be useful in embedded applications, where are strong
+         requirements for timing.
+         Say N here, unless you have a specialized requirement.
+
+config MXC_TZIC
+       bool
+
+config MXC_AVIC
+       bool
+
+config MXC_DEBUG_BOARD
+       bool "Enable MXC debug board(for 3-stack)"
+       help
+         The debug board is an integral part of the MXC 3-stack(PDK)
+         platforms, it can be attached or removed from the peripheral
+         board. On debug board, several debug devices(ethernet, UART,
+         buttons, LEDs and JTAG) are implemented. Between the MCU and
+         these devices, a CPLD is added as a bridge which performs
+         data/address de-multiplexing and decode, signal level shift,
+         interrupt control and various board functions.
+
+config HAVE_EPIT
+       bool
+
+config MXC_USE_EPIT
+       bool "Use EPIT instead of GPT"
+       depends on HAVE_EPIT
+       help
+         Use EPIT as the system timer on systems that have it. Normally you
+         don't have a reason to do so as the EPIT has the same features and
+         uses the same clocks as the GPT. Anyway, on some systems the GPT
+         may be in use for other purposes.
+
+config MXC_ULPI
+       bool
+
+config ARCH_HAS_RNGA
+       bool
+
+config IRAM_ALLOC
+       bool
+       select GENERIC_ALLOCATOR
+
 config HAVE_IMX_GPC
        bool
 
@@ -7,6 +74,12 @@ config HAVE_IMX_MMDC
 config HAVE_IMX_SRC
        bool
 
+config IMX_HAVE_IOMUX_V1
+       bool
+
+config ARCH_MXC_IOMUX_V3
+       bool
+
 config ARCH_MX1
        bool
 
@@ -104,7 +177,7 @@ config      SOC_IMX51
        select PINCTRL_IMX51
        select SOC_IMX5
 
-if ARCH_IMX_V4_V5
+if ARCH_MULTI_V4T
 
 comment "MX1 platforms:"
 config MACH_MXLADS
@@ -133,6 +206,10 @@ config MACH_APF9328
        help
          Say Yes here if you are using the Armadeus APF9328 development board
 
+endif
+
+if ARCH_MULTI_V5
+
 comment "MX21 platforms:"
 
 config MACH_MX21ADS
@@ -384,7 +461,7 @@ config MACH_IMX27_DT
 
 endif
 
-if ARCH_IMX_V6_V7
+if ARCH_MULTI_V6
 
 comment "MX31 platforms:"
 
@@ -649,6 +726,10 @@ config MACH_VPR200
          Include support for VPR200 platform. This includes specific
          configurations for the board and its peripherals.
 
+endif
+
+if ARCH_MULTI_V7
+
 comment "i.MX5 platforms:"
 
 config MACH_MX50_RDP
@@ -766,3 +847,7 @@ config SOC_IMX6Q
          This enables support for Freescale i.MX6 Quad processor.
 
 endif
+
+source "arch/arm/mach-imx/devices/Kconfig"
+
+endmenu
index 895754aeb4f33f856a12009989743d02a894176c..fe47b71469c91863eeeb74dd7179f38fc4d5c264 100644 (file)
@@ -1,3 +1,5 @@
+obj-y := time.o cpu.o system.o irq-common.o
+
 obj-$(CONFIG_SOC_IMX1) += clk-imx1.o mm-imx1.o
 obj-$(CONFIG_SOC_IMX21) += clk-imx21.o mm-imx21.o
 
@@ -15,6 +17,24 @@ obj-$(CONFIG_SOC_IMX5) += cpu-imx5.o mm-imx5.o clk-imx51-imx53.o ehci-imx5.o $(i
 obj-$(CONFIG_COMMON_CLK) += clk-pllv1.o clk-pllv2.o clk-pllv3.o clk-gate2.o \
                            clk-pfd.o clk-busy.o clk.o
 
+obj-$(CONFIG_IMX_HAVE_IOMUX_V1) += iomux-v1.o
+obj-$(CONFIG_ARCH_MXC_IOMUX_V3) += iomux-v3.o
+
+obj-$(CONFIG_MXC_TZIC) += tzic.o
+obj-$(CONFIG_MXC_AVIC) += avic.o
+
+obj-$(CONFIG_IRAM_ALLOC) += iram_alloc.o
+obj-$(CONFIG_MXC_ULPI) += ulpi.o
+obj-$(CONFIG_MXC_USE_EPIT) += epit.o
+obj-$(CONFIG_MXC_DEBUG_BOARD) += 3ds_debugboard.o
+obj-$(CONFIG_CPU_FREQ_IMX)    += cpufreq.o
+obj-$(CONFIG_CPU_IDLE) += cpuidle.o
+
+ifdef CONFIG_SND_IMX_SOC
+obj-y += ssi-fiq.o
+obj-y += ssi-fiq-ksym.o
+endif
+
 # Support for CMOS sensor interface
 obj-$(CONFIG_MX1_VIDEO) += mx1-camera-fiq.o mx1-camera-fiq-ksym.o
 
@@ -89,3 +109,5 @@ obj-$(CONFIG_MACH_MX50_RDP) += mach-mx50_rdp.o
 
 obj-$(CONFIG_MACH_IMX51_DT) += imx51-dt.o
 obj-$(CONFIG_SOC_IMX53) += mach-imx53.o
+
+obj-y += devices/
similarity index 98%
rename from arch/arm/plat-mxc/avic.c
rename to arch/arm/mach-imx/avic.c
index cbd55c36def3e52d304fbd965ba9891b89d345e5..0eff23ed92b930c5e2c56b3b0c3753420ac09ff5 100644 (file)
 #include <linux/irqdomain.h>
 #include <linux/io.h>
 #include <linux/of.h>
-#include <mach/common.h>
 #include <asm/mach/irq.h>
 #include <asm/exception.h>
-#include <mach/hardware.h>
-#include <mach/irqs.h>
 
+#include "common.h"
+#include "hardware.h"
 #include "irq-common.h"
 
 #define AVIC_INTCNTL           0x00    /* int control reg */
index 516ddee1948e81dc207d1b91c29380452c6c970d..15f9d223cf0b9a7dcd489c2c603b46aaaaad604c 100644 (file)
@@ -22,9 +22,9 @@
 #include <linux/clkdev.h>
 #include <linux/err.h>
 
-#include <mach/hardware.h>
-#include <mach/common.h>
 #include "clk.h"
+#include "common.h"
+#include "hardware.h"
 
 /* CCM register addresses */
 #define IO_ADDR_CCM(off)       (MX1_IO_ADDRESS(MX1_CCM_BASE_ADDR + (off)))
@@ -82,7 +82,8 @@ int __init mx1_clocks_init(unsigned long fref)
                        pr_err("imx1 clk %d: register failed with %ld\n",
                                i, PTR_ERR(clk[i]));
 
-       clk_register_clkdev(clk[dma_gate], "ahb", "imx-dma");
+       clk_register_clkdev(clk[dma_gate], "ahb", "imx1-dma");
+       clk_register_clkdev(clk[hclk], "ipg", "imx1-dma");
        clk_register_clkdev(clk[csi_gate], NULL, "mx1-camera.0");
        clk_register_clkdev(clk[mma_gate], "mma", NULL);
        clk_register_clkdev(clk[usbd_gate], NULL, "imx_udc.0");
@@ -94,18 +95,18 @@ int __init mx1_clocks_init(unsigned long fref)
        clk_register_clkdev(clk[hclk], "ipg", "imx1-uart.1");
        clk_register_clkdev(clk[per1], "per", "imx1-uart.2");
        clk_register_clkdev(clk[hclk], "ipg", "imx1-uart.2");
-       clk_register_clkdev(clk[hclk], NULL, "imx-i2c.0");
+       clk_register_clkdev(clk[hclk], NULL, "imx1-i2c.0");
        clk_register_clkdev(clk[per2], "per", "imx1-cspi.0");
        clk_register_clkdev(clk[dummy], "ipg", "imx1-cspi.0");
        clk_register_clkdev(clk[per2], "per", "imx1-cspi.1");
        clk_register_clkdev(clk[dummy], "ipg", "imx1-cspi.1");
        clk_register_clkdev(clk[per2], NULL, "imx-mmc.0");
-       clk_register_clkdev(clk[per2], "per", "imx-fb.0");
-       clk_register_clkdev(clk[dummy], "ipg", "imx-fb.0");
-       clk_register_clkdev(clk[dummy], "ahb", "imx-fb.0");
+       clk_register_clkdev(clk[per2], "per", "imx1-fb.0");
+       clk_register_clkdev(clk[dummy], "ipg", "imx1-fb.0");
+       clk_register_clkdev(clk[dummy], "ahb", "imx1-fb.0");
        clk_register_clkdev(clk[hclk], "mshc", NULL);
        clk_register_clkdev(clk[per3], "ssi", NULL);
-       clk_register_clkdev(clk[clk32], NULL, "mxc_rtc.0");
+       clk_register_clkdev(clk[clk32], NULL, "imx1-rtc.0");
        clk_register_clkdev(clk[clko], "clko", NULL);
 
        mxc_timer_init(MX1_IO_ADDRESS(MX1_TIM1_BASE_ADDR), MX1_TIM1_INT);
index cf65148bc519a036b1dc8b7e4e5d6c9b57920c5a..d7ed66091a2ab60f0ef372ebf7ee57af8a4e4e6e 100644 (file)
@@ -25,9 +25,9 @@
 #include <linux/module.h>
 #include <linux/err.h>
 
-#include <mach/hardware.h>
-#include <mach/common.h>
 #include "clk.h"
+#include "common.h"
+#include "hardware.h"
 
 #define IO_ADDR_CCM(off)       (MX21_IO_ADDRESS(MX21_CCM_BASE_ADDR + (off)))
 
@@ -156,16 +156,16 @@ int __init mx21_clocks_init(unsigned long lref, unsigned long href)
        clk_register_clkdev(clk[cspi2_ipg_gate], "ipg", "imx21-cspi.1");
        clk_register_clkdev(clk[per2], "per", "imx21-cspi.2");
        clk_register_clkdev(clk[cspi3_ipg_gate], "ipg", "imx21-cspi.2");
-       clk_register_clkdev(clk[per3], "per", "imx-fb.0");
-       clk_register_clkdev(clk[lcdc_ipg_gate], "ipg", "imx-fb.0");
-       clk_register_clkdev(clk[lcdc_hclk_gate], "ahb", "imx-fb.0");
+       clk_register_clkdev(clk[per3], "per", "imx21-fb.0");
+       clk_register_clkdev(clk[lcdc_ipg_gate], "ipg", "imx21-fb.0");
+       clk_register_clkdev(clk[lcdc_hclk_gate], "ahb", "imx21-fb.0");
        clk_register_clkdev(clk[usb_gate], "per", "imx21-hcd.0");
        clk_register_clkdev(clk[usb_hclk_gate], "ahb", "imx21-hcd.0");
-       clk_register_clkdev(clk[nfc_gate], NULL, "mxc_nand.0");
-       clk_register_clkdev(clk[dma_hclk_gate], "ahb", "imx-dma");
-       clk_register_clkdev(clk[dma_gate], "ipg", "imx-dma");
+       clk_register_clkdev(clk[nfc_gate], NULL, "imx21-nand.0");
+       clk_register_clkdev(clk[dma_hclk_gate], "ahb", "imx21-dma");
+       clk_register_clkdev(clk[dma_gate], "ipg", "imx21-dma");
        clk_register_clkdev(clk[wdog_gate], NULL, "imx2-wdt.0");
-       clk_register_clkdev(clk[i2c_gate], NULL, "imx-i2c.0");
+       clk_register_clkdev(clk[i2c_gate], NULL, "imx21-i2c.0");
        clk_register_clkdev(clk[kpp_gate], NULL, "mxc-keypad");
        clk_register_clkdev(clk[owire_gate], NULL, "mxc_w1.0");
        clk_register_clkdev(clk[brom_gate], "brom", NULL);
index d20d4795f4eaebeb633c73ec441c36a661949a47..fd8b27f965dfde0f9294acdbc0e5d5f08ee4bf04 100644 (file)
 #include <linux/clkdev.h>
 #include <linux/err.h>
 
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/mx25.h>
 #include "clk.h"
+#include "common.h"
+#include "hardware.h"
+#include "mx25.h"
 
 #define CRM_BASE       MX25_IO_ADDRESS(MX25_CRM_BASE_ADDR)
 
@@ -197,7 +197,7 @@ int __init mx25_clocks_init(void)
        clk_register_clkdev(clk[ipg], "ipg", "fsl-usb2-udc");
        clk_register_clkdev(clk[usbotg_ahb], "ahb", "fsl-usb2-udc");
        clk_register_clkdev(clk[usb_div], "per", "fsl-usb2-udc");
-       clk_register_clkdev(clk[nfc_ipg_per], NULL, "mxc_nand.0");
+       clk_register_clkdev(clk[nfc_ipg_per], NULL, "imx25-nand.0");
        /* i.mx25 has the i.mx35 type cspi */
        clk_register_clkdev(clk[cspi1_ipg], NULL, "imx35-cspi.0");
        clk_register_clkdev(clk[cspi2_ipg], NULL, "imx35-cspi.1");
@@ -212,15 +212,15 @@ int __init mx25_clocks_init(void)
        clk_register_clkdev(clk[per10], "per", "mxc_pwm.3");
        clk_register_clkdev(clk[kpp_ipg], NULL, "imx-keypad");
        clk_register_clkdev(clk[tsc_ipg], NULL, "mx25-adc");
-       clk_register_clkdev(clk[i2c_ipg_per], NULL, "imx-i2c.0");
-       clk_register_clkdev(clk[i2c_ipg_per], NULL, "imx-i2c.1");
-       clk_register_clkdev(clk[i2c_ipg_per], NULL, "imx-i2c.2");
+       clk_register_clkdev(clk[i2c_ipg_per], NULL, "imx21-i2c.0");
+       clk_register_clkdev(clk[i2c_ipg_per], NULL, "imx21-i2c.1");
+       clk_register_clkdev(clk[i2c_ipg_per], NULL, "imx21-i2c.2");
        clk_register_clkdev(clk[fec_ipg], "ipg", "imx25-fec.0");
        clk_register_clkdev(clk[fec_ahb], "ahb", "imx25-fec.0");
        clk_register_clkdev(clk[dryice_ipg], NULL, "imxdi_rtc.0");
-       clk_register_clkdev(clk[lcdc_ipg_per], "per", "imx-fb.0");
-       clk_register_clkdev(clk[lcdc_ipg], "ipg", "imx-fb.0");
-       clk_register_clkdev(clk[lcdc_ahb], "ahb", "imx-fb.0");
+       clk_register_clkdev(clk[lcdc_ipg_per], "per", "imx21-fb.0");
+       clk_register_clkdev(clk[lcdc_ipg], "ipg", "imx21-fb.0");
+       clk_register_clkdev(clk[lcdc_ahb], "ahb", "imx21-fb.0");
        clk_register_clkdev(clk[wdt_ipg], NULL, "imx2-wdt.0");
        clk_register_clkdev(clk[ssi1_ipg], NULL, "imx-ssi.0");
        clk_register_clkdev(clk[ssi2_ipg], NULL, "imx-ssi.1");
@@ -230,9 +230,9 @@ int __init mx25_clocks_init(void)
        clk_register_clkdev(clk[esdhc2_ipg_per], "per", "sdhci-esdhc-imx25.1");
        clk_register_clkdev(clk[esdhc2_ipg], "ipg", "sdhci-esdhc-imx25.1");
        clk_register_clkdev(clk[esdhc2_ahb], "ahb", "sdhci-esdhc-imx25.1");
-       clk_register_clkdev(clk[csi_ipg_per], "per", "mx2-camera.0");
-       clk_register_clkdev(clk[csi_ipg], "ipg", "mx2-camera.0");
-       clk_register_clkdev(clk[csi_ahb], "ahb", "mx2-camera.0");
+       clk_register_clkdev(clk[csi_ipg_per], "per", "imx25-camera.0");
+       clk_register_clkdev(clk[csi_ipg], "ipg", "imx25-camera.0");
+       clk_register_clkdev(clk[csi_ahb], "ahb", "imx25-camera.0");
        clk_register_clkdev(clk[dummy], "audmux", NULL);
        clk_register_clkdev(clk[can1_ipg], NULL, "flexcan.0");
        clk_register_clkdev(clk[can2_ipg], NULL, "flexcan.1");
index 3b6b640eed247ea1b7848c7a7fa01801f0190cde..c3bddd3e2554c2e794746d88df14a5fa068dcd1f 100644 (file)
@@ -6,9 +6,9 @@
 #include <linux/clk-provider.h>
 #include <linux/of.h>
 
-#include <mach/common.h>
-#include <mach/hardware.h>
 #include "clk.h"
+#include "common.h"
+#include "hardware.h"
 
 #define IO_ADDR_CCM(off)       (MX27_IO_ADDRESS(MX27_CCM_BASE_ADDR + (off)))
 
@@ -211,19 +211,19 @@ int __init mx27_clocks_init(unsigned long fref)
        clk_register_clkdev(clk[gpt6_ipg_gate], "ipg", "imx-gpt.5");
        clk_register_clkdev(clk[per1_gate], "per", "imx-gpt.5");
        clk_register_clkdev(clk[pwm_ipg_gate], NULL, "mxc_pwm.0");
-       clk_register_clkdev(clk[per2_gate], "per", "mxc-mmc.0");
-       clk_register_clkdev(clk[sdhc1_ipg_gate], "ipg", "mxc-mmc.0");
-       clk_register_clkdev(clk[per2_gate], "per", "mxc-mmc.1");
-       clk_register_clkdev(clk[sdhc2_ipg_gate], "ipg", "mxc-mmc.1");
-       clk_register_clkdev(clk[per2_gate], "per", "mxc-mmc.2");
-       clk_register_clkdev(clk[sdhc2_ipg_gate], "ipg", "mxc-mmc.2");
+       clk_register_clkdev(clk[per2_gate], "per", "imx21-mmc.0");
+       clk_register_clkdev(clk[sdhc1_ipg_gate], "ipg", "imx21-mmc.0");
+       clk_register_clkdev(clk[per2_gate], "per", "imx21-mmc.1");
+       clk_register_clkdev(clk[sdhc2_ipg_gate], "ipg", "imx21-mmc.1");
+       clk_register_clkdev(clk[per2_gate], "per", "imx21-mmc.2");
+       clk_register_clkdev(clk[sdhc2_ipg_gate], "ipg", "imx21-mmc.2");
        clk_register_clkdev(clk[cspi1_ipg_gate], NULL, "imx27-cspi.0");
        clk_register_clkdev(clk[cspi2_ipg_gate], NULL, "imx27-cspi.1");
        clk_register_clkdev(clk[cspi3_ipg_gate], NULL, "imx27-cspi.2");
-       clk_register_clkdev(clk[per3_gate], "per", "imx-fb.0");
-       clk_register_clkdev(clk[lcdc_ipg_gate], "ipg", "imx-fb.0");
-       clk_register_clkdev(clk[lcdc_ahb_gate], "ahb", "imx-fb.0");
-       clk_register_clkdev(clk[csi_ahb_gate], "ahb", "mx2-camera.0");
+       clk_register_clkdev(clk[per3_gate], "per", "imx21-fb.0");
+       clk_register_clkdev(clk[lcdc_ipg_gate], "ipg", "imx21-fb.0");
+       clk_register_clkdev(clk[lcdc_ahb_gate], "ahb", "imx21-fb.0");
+       clk_register_clkdev(clk[csi_ahb_gate], "ahb", "imx27-camera.0");
        clk_register_clkdev(clk[usb_div], "per", "fsl-usb2-udc");
        clk_register_clkdev(clk[usb_ipg_gate], "ipg", "fsl-usb2-udc");
        clk_register_clkdev(clk[usb_ahb_gate], "ahb", "fsl-usb2-udc");
@@ -238,27 +238,27 @@ int __init mx27_clocks_init(unsigned long fref)
        clk_register_clkdev(clk[usb_ahb_gate], "ahb", "mxc-ehci.2");
        clk_register_clkdev(clk[ssi1_ipg_gate], NULL, "imx-ssi.0");
        clk_register_clkdev(clk[ssi2_ipg_gate], NULL, "imx-ssi.1");
-       clk_register_clkdev(clk[nfc_baud_gate], NULL, "mxc_nand.0");
+       clk_register_clkdev(clk[nfc_baud_gate], NULL, "imx27-nand.0");
        clk_register_clkdev(clk[vpu_baud_gate], "per", "coda-imx27.0");
        clk_register_clkdev(clk[vpu_ahb_gate], "ahb", "coda-imx27.0");
-       clk_register_clkdev(clk[dma_ahb_gate], "ahb", "imx-dma");
-       clk_register_clkdev(clk[dma_ipg_gate], "ipg", "imx-dma");
+       clk_register_clkdev(clk[dma_ahb_gate], "ahb", "imx27-dma");
+       clk_register_clkdev(clk[dma_ipg_gate], "ipg", "imx27-dma");
        clk_register_clkdev(clk[fec_ipg_gate], "ipg", "imx27-fec.0");
        clk_register_clkdev(clk[fec_ahb_gate], "ahb", "imx27-fec.0");
        clk_register_clkdev(clk[wdog_ipg_gate], NULL, "imx2-wdt.0");
-       clk_register_clkdev(clk[i2c1_ipg_gate], NULL, "imx-i2c.0");
-       clk_register_clkdev(clk[i2c2_ipg_gate], NULL, "imx-i2c.1");
+       clk_register_clkdev(clk[i2c1_ipg_gate], NULL, "imx21-i2c.0");
+       clk_register_clkdev(clk[i2c2_ipg_gate], NULL, "imx21-i2c.1");
        clk_register_clkdev(clk[owire_ipg_gate], NULL, "mxc_w1.0");
        clk_register_clkdev(clk[kpp_ipg_gate], NULL, "imx-keypad");
-       clk_register_clkdev(clk[emma_ahb_gate], "emma-ahb", "mx2-camera.0");
-       clk_register_clkdev(clk[emma_ipg_gate], "emma-ipg", "mx2-camera.0");
+       clk_register_clkdev(clk[emma_ahb_gate], "emma-ahb", "imx27-camera.0");
+       clk_register_clkdev(clk[emma_ipg_gate], "emma-ipg", "imx27-camera.0");
        clk_register_clkdev(clk[emma_ahb_gate], "ahb", "m2m-emmaprp.0");
        clk_register_clkdev(clk[emma_ipg_gate], "ipg", "m2m-emmaprp.0");
        clk_register_clkdev(clk[iim_ipg_gate], "iim", NULL);
        clk_register_clkdev(clk[gpio_ipg_gate], "gpio", NULL);
        clk_register_clkdev(clk[brom_ahb_gate], "brom", NULL);
        clk_register_clkdev(clk[ata_ahb_gate], "ata", NULL);
-       clk_register_clkdev(clk[rtc_ipg_gate], NULL, "mxc_rtc");
+       clk_register_clkdev(clk[rtc_ipg_gate], NULL, "imx21-rtc");
        clk_register_clkdev(clk[scc_ipg_gate], "scc", NULL);
        clk_register_clkdev(clk[cpu_div], "cpu", NULL);
        clk_register_clkdev(clk[emi_ahb_gate], "emi_ahb" , NULL);
index 1253af2d99715a63f157a9f838230895006d9323..8be64e0a4ace0bec7a33f64ad2c056dfd0ad6947 100644 (file)
 #include <linux/err.h>
 #include <linux/of.h>
 
-#include <mach/hardware.h>
-#include <mach/mx31.h>
-#include <mach/common.h>
-
 #include "clk.h"
+#include "common.h"
 #include "crmregs-imx3.h"
+#include "hardware.h"
+#include "mx31.h"
 
 static const char *mcu_main_sel[] = { "spll", "mpll", };
 static const char *per_sel[] = { "per_div", "ipg", };
@@ -124,10 +123,10 @@ int __init mx31_clocks_init(unsigned long fref)
        clk_register_clkdev(clk[cspi3_gate], NULL, "imx31-cspi.2");
        clk_register_clkdev(clk[pwm_gate], "pwm", NULL);
        clk_register_clkdev(clk[wdog_gate], NULL, "imx2-wdt.0");
-       clk_register_clkdev(clk[rtc_gate], NULL, "mxc_rtc");
+       clk_register_clkdev(clk[rtc_gate], NULL, "imx21-rtc");
        clk_register_clkdev(clk[epit1_gate], "epit", NULL);
        clk_register_clkdev(clk[epit2_gate], "epit", NULL);
-       clk_register_clkdev(clk[nfc], NULL, "mxc_nand.0");
+       clk_register_clkdev(clk[nfc], NULL, "imx27-nand.0");
        clk_register_clkdev(clk[ipu_gate], NULL, "ipu-core");
        clk_register_clkdev(clk[ipu_gate], NULL, "mx3_sdc_fb");
        clk_register_clkdev(clk[kpp_gate], NULL, "imx-keypad");
@@ -155,12 +154,12 @@ int __init mx31_clocks_init(unsigned long fref)
        clk_register_clkdev(clk[ipg], "ipg", "imx21-uart.3");
        clk_register_clkdev(clk[uart5_gate], "per", "imx21-uart.4");
        clk_register_clkdev(clk[ipg], "ipg", "imx21-uart.4");
-       clk_register_clkdev(clk[i2c1_gate], NULL, "imx-i2c.0");
-       clk_register_clkdev(clk[i2c2_gate], NULL, "imx-i2c.1");
-       clk_register_clkdev(clk[i2c3_gate], NULL, "imx-i2c.2");
+       clk_register_clkdev(clk[i2c1_gate], NULL, "imx21-i2c.0");
+       clk_register_clkdev(clk[i2c2_gate], NULL, "imx21-i2c.1");
+       clk_register_clkdev(clk[i2c3_gate], NULL, "imx21-i2c.2");
        clk_register_clkdev(clk[owire_gate], NULL, "mxc_w1.0");
-       clk_register_clkdev(clk[sdhc1_gate], NULL, "mxc-mmc.0");
-       clk_register_clkdev(clk[sdhc2_gate], NULL, "mxc-mmc.1");
+       clk_register_clkdev(clk[sdhc1_gate], NULL, "imx31-mmc.0");
+       clk_register_clkdev(clk[sdhc2_gate], NULL, "imx31-mmc.1");
        clk_register_clkdev(clk[ssi1_gate], NULL, "imx-ssi.0");
        clk_register_clkdev(clk[ssi2_gate], NULL, "imx-ssi.1");
        clk_register_clkdev(clk[firi_gate], "firi", NULL);
index 177259b523cda0e8ba704c8b2a523e6bf95c2411..66f3d65ea2755f0a522f2fdea52f9b9351fe5beb 100644 (file)
 #include <linux/of.h>
 #include <linux/err.h>
 
-#include <mach/hardware.h>
-#include <mach/common.h>
-
 #include "crmregs-imx3.h"
 #include "clk.h"
+#include "common.h"
+#include "hardware.h"
 
 struct arm_ahb_div {
        unsigned char arm, ahb, sel;
@@ -226,9 +225,9 @@ int __init mx35_clocks_init()
        clk_register_clkdev(clk[fec_gate], NULL, "imx27-fec.0");
        clk_register_clkdev(clk[gpt_gate], "per", "imx-gpt.0");
        clk_register_clkdev(clk[ipg], "ipg", "imx-gpt.0");
-       clk_register_clkdev(clk[i2c1_gate], NULL, "imx-i2c.0");
-       clk_register_clkdev(clk[i2c2_gate], NULL, "imx-i2c.1");
-       clk_register_clkdev(clk[i2c3_gate], NULL, "imx-i2c.2");
+       clk_register_clkdev(clk[i2c1_gate], NULL, "imx21-i2c.0");
+       clk_register_clkdev(clk[i2c2_gate], NULL, "imx21-i2c.1");
+       clk_register_clkdev(clk[i2c3_gate], NULL, "imx21-i2c.2");
        clk_register_clkdev(clk[ipu_gate], NULL, "ipu-core");
        clk_register_clkdev(clk[ipu_gate], NULL, "mx3_sdc_fb");
        clk_register_clkdev(clk[kpp_gate], NULL, "imx-keypad");
@@ -256,7 +255,7 @@ int __init mx35_clocks_init()
        clk_register_clkdev(clk[ipg], "ipg", "fsl-usb2-udc");
        clk_register_clkdev(clk[usbotg_gate], "ahb", "fsl-usb2-udc");
        clk_register_clkdev(clk[wdog_gate], NULL, "imx2-wdt.0");
-       clk_register_clkdev(clk[nfc_div], NULL, "mxc_nand.0");
+       clk_register_clkdev(clk[nfc_div], NULL, "imx25-nand.0");
        clk_register_clkdev(clk[csi_gate], NULL, "mx3-camera.0");
 
        clk_prepare_enable(clk[spba_gate]);
index a0bf84803eacee45978fc1b1deef41076db17f19..abb71f6b4d6051b8c64d28c61c32faceb83d75ac 100644 (file)
 #include <linux/of.h>
 #include <linux/err.h>
 
-#include <mach/hardware.h>
-#include <mach/common.h>
-
 #include "crm-regs-imx5.h"
 #include "clk.h"
+#include "common.h"
+#include "hardware.h"
 
 /* Low-power Audio Playback Mode clock */
 static const char *lp_apm_sel[] = { "osc", };
@@ -258,8 +257,8 @@ static void __init mx5_clocks_common_init(unsigned long rate_ckil,
        clk_register_clkdev(clk[cspi_ipg_gate], NULL, "imx35-cspi.2");
        clk_register_clkdev(clk[pwm1_ipg_gate], "pwm", "mxc_pwm.0");
        clk_register_clkdev(clk[pwm2_ipg_gate], "pwm", "mxc_pwm.1");
-       clk_register_clkdev(clk[i2c1_gate], NULL, "imx-i2c.0");
-       clk_register_clkdev(clk[i2c2_gate], NULL, "imx-i2c.1");
+       clk_register_clkdev(clk[i2c1_gate], NULL, "imx21-i2c.0");
+       clk_register_clkdev(clk[i2c2_gate], NULL, "imx21-i2c.1");
        clk_register_clkdev(clk[usboh3_per_gate], "per", "mxc-ehci.0");
        clk_register_clkdev(clk[usboh3_gate], "ipg", "mxc-ehci.0");
        clk_register_clkdev(clk[usboh3_gate], "ahb", "mxc-ehci.0");
@@ -272,7 +271,7 @@ static void __init mx5_clocks_common_init(unsigned long rate_ckil,
        clk_register_clkdev(clk[usboh3_per_gate], "per", "fsl-usb2-udc");
        clk_register_clkdev(clk[usboh3_gate], "ipg", "fsl-usb2-udc");
        clk_register_clkdev(clk[usboh3_gate], "ahb", "fsl-usb2-udc");
-       clk_register_clkdev(clk[nfc_gate], NULL, "mxc_nand");
+       clk_register_clkdev(clk[nfc_gate], NULL, "imx51-nand");
        clk_register_clkdev(clk[ssi1_ipg_gate], NULL, "imx-ssi.0");
        clk_register_clkdev(clk[ssi2_ipg_gate], NULL, "imx-ssi.1");
        clk_register_clkdev(clk[ssi3_ipg_gate], NULL, "imx-ssi.2");
@@ -345,7 +344,7 @@ int __init mx51_clocks_init(unsigned long rate_ckil, unsigned long rate_osc,
 
        mx5_clocks_common_init(rate_ckil, rate_osc, rate_ckih1, rate_ckih2);
 
-       clk_register_clkdev(clk[hsi2c_gate], NULL, "imx-i2c.2");
+       clk_register_clkdev(clk[hsi2c_gate], NULL, "imx21-i2c.2");
        clk_register_clkdev(clk[mx51_mipi], "mipi_hsp", NULL);
        clk_register_clkdev(clk[vpu_gate], NULL, "imx51-vpu.0");
        clk_register_clkdev(clk[fec_gate], NULL, "imx27-fec.0");
@@ -440,7 +439,7 @@ int __init mx53_clocks_init(unsigned long rate_ckil, unsigned long rate_osc,
        mx5_clocks_common_init(rate_ckil, rate_osc, rate_ckih1, rate_ckih2);
 
        clk_register_clkdev(clk[vpu_gate], NULL, "imx53-vpu.0");
-       clk_register_clkdev(clk[i2c3_gate], NULL, "imx-i2c.2");
+       clk_register_clkdev(clk[i2c3_gate], NULL, "imx21-i2c.2");
        clk_register_clkdev(clk[fec_gate], NULL, "imx25-fec.0");
        clk_register_clkdev(clk[ipu_gate], "bus", "imx53-ipu");
        clk_register_clkdev(clk[ipu_di0_gate], "di0", "imx53-ipu");
index 3ec242f3341ee7d6f64be258a75faadc16da6d29..e5a82bb95b526b7225bdd000c0d5665f6e3949c5 100644 (file)
@@ -19,8 +19,9 @@
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
-#include <mach/common.h>
+
 #include "clk.h"
+#include "common.h"
 
 #define CCGR0                          0x68
 #define CCGR1                          0x6c
index 02be73178912f14e53af58b26c700413c8402ba8..abff350ba24cab1976f9594ad9a699903e599bbc 100644 (file)
@@ -4,10 +4,10 @@
 #include <linux/slab.h>
 #include <linux/kernel.h>
 #include <linux/err.h>
-#include <mach/common.h>
-#include <mach/hardware.h>
 
 #include "clk.h"
+#include "common.h"
+#include "hardware.h"
 
 /**
  * pll v1
similarity index 99%
rename from arch/arm/plat-mxc/include/mach/common.h
rename to arch/arm/mach-imx/common.h
index ead901814c0d86395047420b14deda478540afda..ef8db6b348419e9c6d75a9b9ca837e854803c132 100644 (file)
@@ -79,6 +79,7 @@ extern void mxc_arch_reset_init(void __iomem *);
 extern int mx53_revision(void);
 extern int mx53_display_revision(void);
 extern void imx_set_aips(void __iomem *);
+extern int mxc_device_init(void);
 
 enum mxc_cpu_pwr_mode {
        WAIT_CLOCKED,           /* wfi only */
index 6914bcbf84e4287080d5e3849cb9a5e232c9674b..96ec64b5ff7d3e056ddfdea0f3918278732ea0c1 100644 (file)
@@ -11,8 +11,9 @@
  */
 #include <linux/module.h>
 #include <linux/io.h>
-#include <mach/hardware.h>
-#include <mach/iim.h>
+
+#include "iim.h"
+#include "hardware.h"
 
 static int mx25_cpu_rev = -1;
 
index ff38e1505f670306997d2aee412a9c71cc2e32a8..fe8d36f7e30ed95209ae218811c4420af52b5bee 100644 (file)
@@ -24,7 +24,7 @@
 #include <linux/io.h>
 #include <linux/module.h>
 
-#include <mach/hardware.h>
+#include "hardware.h"
 
 static int mx27_cpu_rev = -1;
 static int mx27_cpu_partnumber;
index 3f2345f0cdaf275659deef2b7adac0d5fc72a906..fde1860a25216ed9763fb7ba8256ed0b16757e70 100644 (file)
 
 #include <linux/module.h>
 #include <linux/io.h>
-#include <mach/hardware.h>
-#include <mach/iim.h>
-#include <mach/common.h>
+
+#include "common.h"
+#include "hardware.h"
+#include "iim.h"
 
 static int mx31_cpu_rev = -1;
 
index 846e46eb8cbfd87f2ad61131e7794fc27ca14e2a..ec3aaa098c1706b3d7cf88b9c608302777419aad 100644 (file)
@@ -10,8 +10,9 @@
  */
 #include <linux/module.h>
 #include <linux/io.h>
-#include <mach/hardware.h>
-#include <mach/iim.h>
+
+#include "hardware.h"
+#include "iim.h"
 
 static int mx35_cpu_rev = -1;
 
index 8eb15a2fcaf9307e047a16252ec25e0a5e59e9bb..d88760014ff96ab46277d3ef97e4f592105b5dbb 100644 (file)
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/module.h>
-#include <mach/hardware.h>
 #include <linux/io.h>
 
+#include "hardware.h"
+
 static int mx5_cpu_rev = -1;
 
 #define IIM_SREV 0x24
similarity index 97%
rename from arch/arm/plat-mxc/cpu.c
rename to arch/arm/mach-imx/cpu.c
index 220dd6f93126367efdbce0b1b7630fab4cec25d1..03fcbd082593b18eb32373f079dc15ae47392b8e 100644 (file)
@@ -1,7 +1,8 @@
 
 #include <linux/module.h>
 #include <linux/io.h>
-#include <mach/hardware.h>
+
+#include "hardware.h"
 
 unsigned int __mxc_cpu_type;
 EXPORT_SYMBOL(__mxc_cpu_type);
index 7b92cd6da6d3f1ae8330f75dcf4b879c7f492ec5..b9ef692b61a292bb75837a434edaacbd25b9c80e 100644 (file)
 
 #include <linux/bug.h>
 #include <linux/types.h>
-#include <mach/hardware.h>
 #include <linux/kernel.h>
 
+#include "hardware.h"
+
 static struct cpu_op mx51_cpu_op[] = {
        {
        .cpu_rate = 160000000,},
similarity index 99%
rename from arch/arm/plat-mxc/cpufreq.c
rename to arch/arm/mach-imx/cpufreq.c
index b5b6f80831307dc5051ced39d0ea841d43afa8bb..36e8b399447037a73eb5261381a39cd88d9ea2bf 100644 (file)
@@ -22,7 +22,8 @@
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/slab.h>
-#include <mach/hardware.h>
+
+#include "hardware.h"
 
 #define CLK32_FREQ     32768
 #define NANOSECOND     (1000 * 1000 * 1000)
index 3aad1e70de969fe2d76f2a741ea4525818916563..f9b5afc6bcd153028fb0dc0587c3d895ec81b602 100644 (file)
@@ -6,8 +6,7 @@
  * the terms of the GNU General Public License version 2 as published by the
  * Free Software Foundation.
  */
-#include <mach/mx1.h>
-#include <mach/devices-common.h>
+#include "devices/devices-common.h"
 
 extern const struct imx_imx_fb_data imx1_imx_fb_data;
 #define imx1_add_imx_fb(pdata) \
index 93ece55f75dfbf3014039968a6a740d7cecd1900..bd939328015901e3315a528653b7afeffd649679 100644 (file)
@@ -6,8 +6,7 @@
  * the terms of the GNU General Public License version 2 as published by the
  * Free Software Foundation.
  */
-#include <mach/mx21.h>
-#include <mach/devices-common.h>
+#include "devices/devices-common.h"
 
 extern const struct imx_imx21_hcd_data imx21_imx21_hcd_data;
 #define imx21_add_imx21_hcd(pdata)     \
index f8e03dd1f116f16a8f175403c6e6cd62756caa2d..0d2922bc575caa862a99b60c621d24da6d3e14ca 100644 (file)
@@ -6,8 +6,7 @@
  * the terms of the GNU General Public License version 2 as published by the
  * Free Software Foundation.
  */
-#include <mach/mx25.h>
-#include <mach/devices-common.h>
+#include "devices/devices-common.h"
 
 extern const struct imx_fec_data imx25_fec_data;
 #define imx25_add_fec(pdata)   \
index 04822932cdd1d13c260b4e950ccb51dec9f4ff39..8a1ad7972d4c0843a096dcf7d21810737b16075b 100644 (file)
@@ -6,8 +6,7 @@
  * the terms of the GNU General Public License version 2 as published by the
  * Free Software Foundation.
  */
-#include <mach/mx27.h>
-#include <mach/devices-common.h>
+#include "devices/devices-common.h"
 
 extern const struct imx_fec_data imx27_fec_data;
 #define imx27_add_fec(pdata)   \
index 8b2ceb45bb8344223dae53b974e345237c707479..e8d1611bbc8e325f29bf897cea68ffcc9c253aa8 100644 (file)
@@ -6,8 +6,7 @@
  * the terms of the GNU General Public License version 2 as published by the
  * Free Software Foundation.
  */
-#include <mach/mx31.h>
-#include <mach/devices-common.h>
+#include "devices/devices-common.h"
 
 extern const struct imx_fsl_usb2_udc_data imx31_fsl_usb2_udc_data;
 #define imx31_add_fsl_usb2_udc(pdata)  \
index c3e9f206ac2bdfdff093b2a082dbddd168aa4d05..e2675f1b141c0a0baedd8e5db9daa252a7541827 100644 (file)
@@ -6,8 +6,7 @@
  * the terms of the GNU General Public License version 2 as published by the
  * Free Software Foundation.
  */
-#include <mach/mx35.h>
-#include <mach/devices-common.h>
+#include "devices/devices-common.h"
 
 extern const struct imx_fec_data imx35_fec_data;
 #define imx35_add_fec(pdata)   \
index 7216667eaafcd2d259c2882a934b3f292c02ef21..2c290391f298653198784669e57fd48f72366922 100644 (file)
@@ -18,8 +18,7 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
-#include <mach/mx50.h>
-#include <mach/devices-common.h>
+#include "devices/devices-common.h"
 
 extern const struct imx_imx_uart_1irq_data imx50_imx_uart_data[];
 #define imx50_add_imx_uart(id, pdata)  \
index 9f1718725195414e0798a40d49c932838f7b4235..deee5baee88cf636627acb1c923b029e9d58b032 100644 (file)
@@ -6,8 +6,7 @@
  * the terms of the GNU General Public License version 2 as published by the
  * Free Software Foundation.
  */
-#include <mach/mx51.h>
-#include <mach/devices-common.h>
+#include "devices/devices-common.h"
 
 extern const struct imx_fec_data imx51_fec_data;
 #define imx51_add_fec(pdata)   \
similarity index 98%
rename from arch/arm/plat-mxc/devices/Makefile
rename to arch/arm/mach-imx/devices/Makefile
index 76f3195475d06abd27a9114cf3c64301a2ebdf52..2abe2a5144d0365312af9a6a9431ec9fd141a265 100644 (file)
@@ -1,3 +1,5 @@
+obj-y := devices.o
+
 obj-$(CONFIG_IMX_HAVE_PLATFORM_FEC) += platform-fec.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_FLEXCAN) += platform-flexcan.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_FSL_USB2_UDC) += platform-fsl-usb2-udc.o
similarity index 97%
rename from arch/arm/plat-mxc/include/mach/devices-common.h
rename to arch/arm/mach-imx/devices/devices-common.h
index eaf79d220c9a42d8c707218a5781073038ec2167..e4b790b9e2aaaea5d708371354ec83d9adc28844 100644 (file)
@@ -108,6 +108,7 @@ struct platform_device *__init imx_add_imxdi_rtc(
 
 #include <linux/platform_data/video-imxfb.h>
 struct imx_imx_fb_data {
+       const char *devid;
        resource_size_t iobase;
        resource_size_t iosize;
        resource_size_t irq;
@@ -118,6 +119,7 @@ struct platform_device *__init imx_add_imx_fb(
 
 #include <linux/platform_data/i2c-imx.h>
 struct imx_imx_i2c_data {
+       const char *devid;
        int id;
        resource_size_t iobase;
        resource_size_t iosize;
@@ -219,6 +221,7 @@ struct platform_device *__init imx_add_mx1_camera(
 
 #include <linux/platform_data/camera-mx2.h>
 struct imx_mx2_camera_data {
+       const char *devid;
        resource_size_t iobasecsi;
        resource_size_t iosizecsi;
        resource_size_t irqcsi;
@@ -244,6 +247,7 @@ struct platform_device *__init imx_add_mxc_ehci(
 
 #include <linux/platform_data/mmc-mxcmmc.h>
 struct imx_mxc_mmc_data {
+       const char *devid;
        int id;
        resource_size_t iobase;
        resource_size_t iosize;
@@ -256,6 +260,7 @@ struct platform_device *__init imx_add_mxc_mmc(
 
 #include <linux/platform_data/mtd-mxc_nand.h>
 struct imx_mxc_nand_data {
+       const char *devid;
        /*
         * id is traditionally 0, but -1 is more appropriate.  We use -1 for new
         * machines but don't change existing devices as the nand device usually
@@ -290,6 +295,7 @@ struct platform_device *__init imx_add_mxc_pwm(
 
 /* mxc_rtc */
 struct imx_mxc_rtc_data {
+       const char *devid;
        resource_size_t iobase;
        resource_size_t irq;
 };
@@ -326,7 +332,8 @@ struct platform_device *__init imx_add_spi_imx(
                const struct imx_spi_imx_data *data,
                const struct spi_imx_master *pdata);
 
-struct platform_device *imx_add_imx_dma(void);
+struct platform_device *imx_add_imx_dma(char *name, resource_size_t iobase,
+                                       int irq, int irq_err);
 struct platform_device *imx_add_imx_sdma(char *name,
        resource_size_t iobase, int irq, struct sdma_platform_data *pdata);
 
similarity index 92%
rename from arch/arm/plat-mxc/devices.c
rename to arch/arm/mach-imx/devices/devices.c
index 4d55a7a26e98fd92a1bda89dd5f266864c0ed55f..1b37482407f911461846fc95f0528a1ed2fc6b70 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/init.h>
 #include <linux/err.h>
 #include <linux/platform_device.h>
-#include <mach/common.h>
 
 struct device mxc_aips_bus = {
        .init_name      = "mxc_aips",
@@ -33,7 +32,7 @@ struct device mxc_ahb_bus = {
        .parent         = &platform_bus,
 };
 
-static int __init mxc_device_init(void)
+int __init mxc_device_init(void)
 {
        int ret;
 
@@ -46,4 +45,3 @@ static int __init mxc_device_init(void)
 done:
        return ret;
 }
-core_initcall(mxc_device_init);
similarity index 98%
rename from arch/arm/plat-mxc/devices/platform-ahci-imx.c
rename to arch/arm/mach-imx/devices/platform-ahci-imx.c
index ade4a1c4e2a39e4aac13479deb48af97fd142c0b..3d87dd9c284ae1d6f8b99afcc49521fdf0bddef8 100644 (file)
@@ -24,8 +24,9 @@
 #include <linux/device.h>
 #include <linux/dma-mapping.h>
 #include <asm/sizes.h>
-#include <mach/hardware.h>
-#include <mach/devices-common.h>
+
+#include "../hardware.h"
+#include "devices-common.h"
 
 #define imx_ahci_imx_data_entry_single(soc, _devid)            \
        {                                                               \
similarity index 97%
rename from arch/arm/plat-mxc/devices/platform-fec.c
rename to arch/arm/mach-imx/devices/platform-fec.c
index 0bae44e890db14e262cfdb46c50b09fb12279bf6..2cb188ad9a0a614422892a7ef64396bacdead050 100644 (file)
@@ -8,8 +8,9 @@
  */
 #include <linux/dma-mapping.h>
 #include <asm/sizes.h>
-#include <mach/hardware.h>
-#include <mach/devices-common.h>
+
+#include "../hardware.h"
+#include "devices-common.h"
 
 #define imx_fec_data_entry_single(soc, _devid)                         \
        {                                                               \
similarity index 96%
rename from arch/arm/plat-mxc/devices/platform-flexcan.c
rename to arch/arm/mach-imx/devices/platform-flexcan.c
index 4e8497af2eb19fa344d52e2413303b1ee53cde56..1078bf0a94ef1122a81d094100030175423f173e 100644 (file)
@@ -5,8 +5,8 @@
  * the terms of the GNU General Public License version 2 as published by the
  * Free Software Foundation.
  */
-#include <mach/hardware.h>
-#include <mach/devices-common.h>
+#include "../hardware.h"
+#include "devices-common.h"
 
 #define imx_flexcan_data_entry_single(soc, _id, _hwid, _size)          \
        {                                                               \
similarity index 96%
rename from arch/arm/plat-mxc/devices/platform-fsl-usb2-udc.c
rename to arch/arm/mach-imx/devices/platform-fsl-usb2-udc.c
index 848038f301fd24e518449beeb262018f95e367e6..37e44398197b4703b7130734d166963f9e894e01 100644 (file)
@@ -7,8 +7,9 @@
  * Free Software Foundation.
  */
 #include <linux/dma-mapping.h>
-#include <mach/hardware.h>
-#include <mach/devices-common.h>
+
+#include "../hardware.h"
+#include "devices-common.h"
 
 #define imx_fsl_usb2_udc_data_entry_single(soc)                                \
        {                                                               \
similarity index 96%
rename from arch/arm/plat-mxc/devices/platform-gpio-mxc.c
rename to arch/arm/mach-imx/devices/platform-gpio-mxc.c
index a7919a241032184b94d005846eff6c84e66fc0e7..26483fa94b75109d13ed56ace45af8ed9c44656d 100644 (file)
@@ -6,7 +6,7 @@
  * the terms of the GNU General Public License version 2 as published by the
  * Free Software Foundation.
  */
-#include <mach/devices-common.h>
+#include "devices-common.h"
 
 struct platform_device *__init mxc_register_gpio(char *name, int id,
        resource_size_t iobase, resource_size_t iosize, int irq, int irq_high)
similarity index 94%
rename from arch/arm/plat-mxc/devices/platform-gpio_keys.c
rename to arch/arm/mach-imx/devices/platform-gpio_keys.c
index 1c53a532ea0ec6e6ab44e33afcb6aeeda2795659..486282539c76e72dd01e7dfefa317491f1cedb4f 100644 (file)
@@ -16,8 +16,9 @@
  * Boston, MA  02110-1301, USA.
  */
 #include <asm/sizes.h>
-#include <mach/hardware.h>
-#include <mach/devices-common.h>
+
+#include "../hardware.h"
+#include "devices-common.h"
 
 struct platform_device *__init imx_add_gpio_keys(
                const struct gpio_keys_platform_data *pdata)
similarity index 63%
rename from arch/arm/plat-mxc/devices/platform-imx-dma.c
rename to arch/arm/mach-imx/devices/platform-imx-dma.c
index 7fa7e9c9246803f74e95c97719009b3387ad660a..ccdb5dc4ddbdde117ae662c92ae25786bfaae764 100644 (file)
@@ -6,12 +6,29 @@
  * the terms of the GNU General Public License version 2 as published by the
  * Free Software Foundation.
  */
-#include <mach/devices-common.h>
+#include "devices-common.h"
 
-struct platform_device __init __maybe_unused *imx_add_imx_dma(void)
+struct platform_device __init __maybe_unused *imx_add_imx_dma(char *name,
+       resource_size_t iobase, int irq, int irq_err)
 {
+       struct resource res[] = {
+               {
+                       .start = iobase,
+                       .end = iobase + SZ_4K - 1,
+                       .flags = IORESOURCE_MEM,
+               }, {
+                       .start = irq,
+                       .end = irq,
+                       .flags = IORESOURCE_IRQ,
+               }, {
+                       .start = irq_err,
+                       .end = irq_err,
+                       .flags = IORESOURCE_IRQ,
+               },
+       };
+
        return platform_device_register_resndata(&mxc_ahb_bus,
-                       "imx-dma", -1, NULL, 0, NULL, 0);
+                       name, -1, res, ARRAY_SIZE(res), NULL, 0);
 }
 
 struct platform_device __init __maybe_unused *imx_add_imx_sdma(char *name,
similarity index 79%
rename from arch/arm/plat-mxc/devices/platform-imx-fb.c
rename to arch/arm/mach-imx/devices/platform-imx-fb.c
index 2b0b5e0aa9989639286efb65de5adb9ecbcc704c..10b0ed39f07f9ff5cea15ca7fd5359f96506bd34 100644 (file)
@@ -7,11 +7,13 @@
  * Free Software Foundation.
  */
 #include <linux/dma-mapping.h>
-#include <mach/hardware.h>
-#include <mach/devices-common.h>
 
-#define imx_imx_fb_data_entry_single(soc, _size)                       \
+#include "../hardware.h"
+#include "devices-common.h"
+
+#define imx_imx_fb_data_entry_single(soc, _devid, _size)               \
        {                                                               \
+               .devid = _devid,                                        \
                .iobase = soc ## _LCDC_BASE_ADDR,                       \
                .iosize = _size,                                        \
                .irq = soc ## _INT_LCDC,                                \
 
 #ifdef CONFIG_SOC_IMX1
 const struct imx_imx_fb_data imx1_imx_fb_data __initconst =
-       imx_imx_fb_data_entry_single(MX1, SZ_4K);
+       imx_imx_fb_data_entry_single(MX1, "imx1-fb", SZ_4K);
 #endif /* ifdef CONFIG_SOC_IMX1 */
 
 #ifdef CONFIG_SOC_IMX21
 const struct imx_imx_fb_data imx21_imx_fb_data __initconst =
-       imx_imx_fb_data_entry_single(MX21, SZ_4K);
+       imx_imx_fb_data_entry_single(MX21, "imx21-fb", SZ_4K);
 #endif /* ifdef CONFIG_SOC_IMX21 */
 
 #ifdef CONFIG_SOC_IMX25
 const struct imx_imx_fb_data imx25_imx_fb_data __initconst =
-       imx_imx_fb_data_entry_single(MX25, SZ_16K);
+       imx_imx_fb_data_entry_single(MX25, "imx21-fb", SZ_16K);
 #endif /* ifdef CONFIG_SOC_IMX25 */
 
 #ifdef CONFIG_SOC_IMX27
 const struct imx_imx_fb_data imx27_imx_fb_data __initconst =
-       imx_imx_fb_data_entry_single(MX27, SZ_4K);
+       imx_imx_fb_data_entry_single(MX27, "imx21-fb", SZ_4K);
 #endif /* ifdef CONFIG_SOC_IMX27 */
 
 struct platform_device *__init imx_add_imx_fb(
similarity index 76%
rename from arch/arm/plat-mxc/devices/platform-imx-i2c.c
rename to arch/arm/mach-imx/devices/platform-imx-i2c.c
index 19ad580c0be348fb16d8bf93e3eb664b6ef1d431..8e30e5703cd204fadda337789bd292a9d14929d5 100644 (file)
@@ -6,34 +6,35 @@
  * the terms of the GNU General Public License version 2 as published by the
  * Free Software Foundation.
  */
-#include <mach/hardware.h>
-#include <mach/devices-common.h>
+#include "../hardware.h"
+#include "devices-common.h"
 
-#define imx_imx_i2c_data_entry_single(soc, _id, _hwid, _size)          \
+#define imx_imx_i2c_data_entry_single(soc, _devid, _id, _hwid, _size)  \
        {                                                               \
+               .devid = _devid,                                        \
                .id = _id,                                              \
                .iobase = soc ## _I2C ## _hwid ## _BASE_ADDR,           \
                .iosize = _size,                                        \
                .irq = soc ## _INT_I2C ## _hwid,                        \
        }
 
-#define imx_imx_i2c_data_entry(soc, _id, _hwid, _size)                 \
-       [_id] = imx_imx_i2c_data_entry_single(soc, _id, _hwid, _size)
+#define imx_imx_i2c_data_entry(soc, _devid, _id, _hwid, _size)         \
+       [_id] = imx_imx_i2c_data_entry_single(soc, _devid, _id, _hwid, _size)
 
 #ifdef CONFIG_SOC_IMX1
 const struct imx_imx_i2c_data imx1_imx_i2c_data __initconst =
-       imx_imx_i2c_data_entry_single(MX1, 0, , SZ_4K);
+       imx_imx_i2c_data_entry_single(MX1, "imx1-i2c", 0, , SZ_4K);
 #endif /* ifdef CONFIG_SOC_IMX1 */
 
 #ifdef CONFIG_SOC_IMX21
 const struct imx_imx_i2c_data imx21_imx_i2c_data __initconst =
-       imx_imx_i2c_data_entry_single(MX21, 0, , SZ_4K);
+       imx_imx_i2c_data_entry_single(MX21, "imx21-i2c", 0, , SZ_4K);
 #endif /* ifdef CONFIG_SOC_IMX21 */
 
 #ifdef CONFIG_SOC_IMX25
 const struct imx_imx_i2c_data imx25_imx_i2c_data[] __initconst = {
 #define imx25_imx_i2c_data_entry(_id, _hwid)                           \
-       imx_imx_i2c_data_entry(MX25, _id, _hwid, SZ_16K)
+       imx_imx_i2c_data_entry(MX25, "imx21-i2c", _id, _hwid, SZ_16K)
        imx25_imx_i2c_data_entry(0, 1),
        imx25_imx_i2c_data_entry(1, 2),
        imx25_imx_i2c_data_entry(2, 3),
@@ -43,7 +44,7 @@ const struct imx_imx_i2c_data imx25_imx_i2c_data[] __initconst = {
 #ifdef CONFIG_SOC_IMX27
 const struct imx_imx_i2c_data imx27_imx_i2c_data[] __initconst = {
 #define imx27_imx_i2c_data_entry(_id, _hwid)                           \
-       imx_imx_i2c_data_entry(MX27, _id, _hwid, SZ_4K)
+       imx_imx_i2c_data_entry(MX27, "imx21-i2c", _id, _hwid, SZ_4K)
        imx27_imx_i2c_data_entry(0, 1),
        imx27_imx_i2c_data_entry(1, 2),
 };
@@ -52,7 +53,7 @@ const struct imx_imx_i2c_data imx27_imx_i2c_data[] __initconst = {
 #ifdef CONFIG_SOC_IMX31
 const struct imx_imx_i2c_data imx31_imx_i2c_data[] __initconst = {
 #define imx31_imx_i2c_data_entry(_id, _hwid)                           \
-       imx_imx_i2c_data_entry(MX31, _id, _hwid, SZ_4K)
+       imx_imx_i2c_data_entry(MX31, "imx21-i2c", _id, _hwid, SZ_4K)
        imx31_imx_i2c_data_entry(0, 1),
        imx31_imx_i2c_data_entry(1, 2),
        imx31_imx_i2c_data_entry(2, 3),
@@ -62,7 +63,7 @@ const struct imx_imx_i2c_data imx31_imx_i2c_data[] __initconst = {
 #ifdef CONFIG_SOC_IMX35
 const struct imx_imx_i2c_data imx35_imx_i2c_data[] __initconst = {
 #define imx35_imx_i2c_data_entry(_id, _hwid)                           \
-       imx_imx_i2c_data_entry(MX35, _id, _hwid, SZ_4K)
+       imx_imx_i2c_data_entry(MX35, "imx21-i2c", _id, _hwid, SZ_4K)
        imx35_imx_i2c_data_entry(0, 1),
        imx35_imx_i2c_data_entry(1, 2),
        imx35_imx_i2c_data_entry(2, 3),
@@ -72,7 +73,7 @@ const struct imx_imx_i2c_data imx35_imx_i2c_data[] __initconst = {
 #ifdef CONFIG_SOC_IMX50
 const struct imx_imx_i2c_data imx50_imx_i2c_data[] __initconst = {
 #define imx50_imx_i2c_data_entry(_id, _hwid)                           \
-       imx_imx_i2c_data_entry(MX50, _id, _hwid, SZ_4K)
+       imx_imx_i2c_data_entry(MX50, "imx21-i2c", _id, _hwid, SZ_4K)
        imx50_imx_i2c_data_entry(0, 1),
        imx50_imx_i2c_data_entry(1, 2),
        imx50_imx_i2c_data_entry(2, 3),
@@ -82,10 +83,11 @@ const struct imx_imx_i2c_data imx50_imx_i2c_data[] __initconst = {
 #ifdef CONFIG_SOC_IMX51
 const struct imx_imx_i2c_data imx51_imx_i2c_data[] __initconst = {
 #define imx51_imx_i2c_data_entry(_id, _hwid)                           \
-       imx_imx_i2c_data_entry(MX51, _id, _hwid, SZ_4K)
+       imx_imx_i2c_data_entry(MX51, "imx21-i2c", _id, _hwid, SZ_4K)
        imx51_imx_i2c_data_entry(0, 1),
        imx51_imx_i2c_data_entry(1, 2),
        {
+               .devid = "imx21-i2c",
                .id = 2,
                .iobase = MX51_HSI2C_DMA_BASE_ADDR,
                .iosize = SZ_16K,
@@ -97,7 +99,7 @@ const struct imx_imx_i2c_data imx51_imx_i2c_data[] __initconst = {
 #ifdef CONFIG_SOC_IMX53
 const struct imx_imx_i2c_data imx53_imx_i2c_data[] __initconst = {
 #define imx53_imx_i2c_data_entry(_id, _hwid)                           \
-       imx_imx_i2c_data_entry(MX53, _id, _hwid, SZ_4K)
+       imx_imx_i2c_data_entry(MX53, "imx21-i2c", _id, _hwid, SZ_4K)
        imx53_imx_i2c_data_entry(0, 1),
        imx53_imx_i2c_data_entry(1, 2),
        imx53_imx_i2c_data_entry(2, 3),
@@ -120,7 +122,7 @@ struct platform_device *__init imx_add_imx_i2c(
                },
        };
 
-       return imx_add_platform_device("imx-i2c", data->id,
+       return imx_add_platform_device(data->devid, data->id,
                        res, ARRAY_SIZE(res),
                        pdata, sizeof(*pdata));
 }
similarity index 97%
rename from arch/arm/plat-mxc/devices/platform-imx-keypad.c
rename to arch/arm/mach-imx/devices/platform-imx-keypad.c
index 479c3e9f771f04be7105551e0286cda2a8dd21c3..8f22a4c98a4ce5957c262e719afb7ab3209f70f0 100644 (file)
@@ -6,8 +6,8 @@
  * the terms of the GNU General Public License version 2 as published by the
  * Free Software Foundation.
  */
-#include <mach/hardware.h>
-#include <mach/devices-common.h>
+#include "../hardware.h"
+#include "devices-common.h"
 
 #define imx_imx_keypad_data_entry_single(soc, _size)                   \
        {                                                               \
similarity index 98%
rename from arch/arm/plat-mxc/devices/platform-imx-ssi.c
rename to arch/arm/mach-imx/devices/platform-imx-ssi.c
index 21c6f30e1017403c386f2694aed6aeb81fd33339..bfcb8f3dfa8d712075876e84c3823d8a936aabb5 100644 (file)
@@ -6,8 +6,8 @@
  * the terms of the GNU General Public License version 2 as published by the
  * Free Software Foundation.
  */
-#include <mach/hardware.h>
-#include <mach/devices-common.h>
+#include "../hardware.h"
+#include "devices-common.h"
 
 #define imx_imx_ssi_data_entry(soc, _id, _hwid, _size)                 \
        [_id] = {                                                       \
similarity index 98%
rename from arch/arm/plat-mxc/devices/platform-imx-uart.c
rename to arch/arm/mach-imx/devices/platform-imx-uart.c
index d390f00bd29421e2dbe1d39a2f1c6b7392f7c529..67bf866a2cb6642008a78b968943ebf3bd4750f5 100644 (file)
@@ -6,8 +6,8 @@
  * the terms of the GNU General Public License version 2 as published by the
  * Free Software Foundation.
  */
-#include <mach/hardware.h>
-#include <mach/devices-common.h>
+#include "../hardware.h"
+#include "devices-common.h"
 
 #define imx_imx_uart_3irq_data_entry(soc, _id, _hwid, _size)           \
        [_id] = {                                                       \
similarity index 97%
rename from arch/arm/plat-mxc/devices/platform-imx2-wdt.c
rename to arch/arm/mach-imx/devices/platform-imx2-wdt.c
index 5e07ef2bf1c42510e59d384a9e0ea6c55f7d72a6..ec75d6413686d7f2004a83b96c16a4683bc630a1 100644 (file)
@@ -7,8 +7,9 @@
  * Free Software Foundation.
  */
 #include <asm/sizes.h>
-#include <mach/hardware.h>
-#include <mach/devices-common.h>
+
+#include "../hardware.h"
+#include "devices-common.h"
 
 #define imx_imx2_wdt_data_entry_single(soc, _id, _hwid, _size)         \
        {                                                               \
similarity index 94%
rename from arch/arm/plat-mxc/devices/platform-imx21-hcd.c
rename to arch/arm/mach-imx/devices/platform-imx21-hcd.c
index 5770a42f33bf3d0bea750e4d858adef0db7afbb8..30c81616a9a10acbab642bac56757e1122b1f198 100644 (file)
@@ -6,8 +6,8 @@
  * the terms of the GNU General Public License version 2 as published by the
  * Free Software Foundation.
  */
-#include <mach/hardware.h>
-#include <mach/devices-common.h>
+#include "../hardware.h"
+#include "devices-common.h"
 
 #define imx_imx21_hcd_data_entry_single(soc)                           \
        {                                                               \
similarity index 93%
rename from arch/arm/plat-mxc/devices/platform-imx27-coda.c
rename to arch/arm/mach-imx/devices/platform-imx27-coda.c
index 8b12aacdf3965020d06e936c2ee6c11581caee55..25bebc29e5461e156f7c400020074435d6707f05 100644 (file)
@@ -7,8 +7,8 @@
  * Free Software Foundation.
  */
 
-#include <mach/hardware.h>
-#include <mach/devices-common.h>
+#include "../hardware.h"
+#include "devices-common.h"
 
 #ifdef CONFIG_SOC_IMX27
 const struct imx_imx27_coda_data imx27_coda_data __initconst = {
similarity index 96%
rename from arch/arm/plat-mxc/devices/platform-imx_udc.c
rename to arch/arm/mach-imx/devices/platform-imx_udc.c
index 6fd675dfce14079bbdf97858350607072a607606..5ced7e4e2c71d1df2f89157cf8f720b38e5c4810 100644 (file)
@@ -6,8 +6,8 @@
  * the terms of the GNU General Public License version 2 as published by the
  * Free Software Foundation.
  */
-#include <mach/hardware.h>
-#include <mach/devices-common.h>
+#include "../hardware.h"
+#include "devices-common.h"
 
 #define imx_imx_udc_data_entry_single(soc, _size)                      \
        {                                                               \
similarity index 94%
rename from arch/arm/plat-mxc/devices/platform-imxdi_rtc.c
rename to arch/arm/mach-imx/devices/platform-imxdi_rtc.c
index 805336fdc2521cffa82268655f58a2216bb8e647..5bb490d556eaa9dab0d26ba77ba5d77e4aba1d5b 100644 (file)
@@ -7,8 +7,9 @@
  * Free Software Foundation.
  */
 #include <asm/sizes.h>
-#include <mach/hardware.h>
-#include <mach/devices-common.h>
+
+#include "../hardware.h"
+#include "devices-common.h"
 
 #define imx_imxdi_rtc_data_entry_single(soc)                           \
        {                                                               \
similarity index 98%
rename from arch/arm/plat-mxc/devices/platform-ipu-core.c
rename to arch/arm/mach-imx/devices/platform-ipu-core.c
index d1e33cc6f12e8cd9e5d332df58a4788ec2c61952..fc4dd7cedc1189019dea590e8a4caa6b0ebf6884 100644 (file)
@@ -7,8 +7,9 @@
  * Free Software Foundation.
  */
 #include <linux/dma-mapping.h>
-#include <mach/hardware.h>
-#include <mach/devices-common.h>
+
+#include "../hardware.h"
+#include "devices-common.h"
 
 #define imx_ipu_core_entry_single(soc)                                 \
 {                                                                      \
similarity index 94%
rename from arch/arm/plat-mxc/devices/platform-mx1-camera.c
rename to arch/arm/mach-imx/devices/platform-mx1-camera.c
index edcc581a30a9ea440034df1b122d2bec6aac30e9..2c678813108096ff13218b6cc736522169a1728a 100644 (file)
@@ -6,8 +6,8 @@
  * the terms of the GNU General Public License version 2 as published by the
  * Free Software Foundation.
  */
-#include <mach/hardware.h>
-#include <mach/devices-common.h>
+#include "../hardware.h"
+#include "devices-common.h"
 
 #define imx_mx1_camera_data_entry_single(soc, _size)                   \
        {                                                               \
similarity index 83%
rename from arch/arm/plat-mxc/devices/platform-mx2-camera.c
rename to arch/arm/mach-imx/devices/platform-mx2-camera.c
index 11eace953a09e5df8adecc4a4ec283327998cc1c..f4910160346b4fc89e5793a650f6717afcc4b6e3 100644 (file)
@@ -6,17 +6,19 @@
  * the terms of the GNU General Public License version 2 as published by the
  * Free Software Foundation.
  */
-#include <mach/hardware.h>
-#include <mach/devices-common.h>
+#include "../hardware.h"
+#include "devices-common.h"
 
-#define imx_mx2_camera_data_entry_single(soc)                          \
+#define imx_mx2_camera_data_entry_single(soc, _devid)                  \
        {                                                               \
+               .devid = _devid,                                        \
                .iobasecsi = soc ## _CSI_BASE_ADDR,                     \
                .iosizecsi = SZ_4K,                                     \
                .irqcsi = soc ## _INT_CSI,                              \
        }
-#define imx_mx2_camera_data_entry_single_emma(soc)                     \
+#define imx_mx2_camera_data_entry_single_emma(soc, _devid)             \
        {                                                               \
+               .devid = _devid,                                        \
                .iobasecsi = soc ## _CSI_BASE_ADDR,                     \
                .iosizecsi = SZ_32,                                     \
                .irqcsi = soc ## _INT_CSI,                              \
 
 #ifdef CONFIG_SOC_IMX25
 const struct imx_mx2_camera_data imx25_mx2_camera_data __initconst =
-       imx_mx2_camera_data_entry_single(MX25);
+       imx_mx2_camera_data_entry_single(MX25, "imx25-camera");
 #endif /* ifdef CONFIG_SOC_IMX25 */
 
 #ifdef CONFIG_SOC_IMX27
 const struct imx_mx2_camera_data imx27_mx2_camera_data __initconst =
-       imx_mx2_camera_data_entry_single_emma(MX27);
+       imx_mx2_camera_data_entry_single_emma(MX27, "imx27-camera");
 #endif /* ifdef CONFIG_SOC_IMX27 */
 
 struct platform_device *__init imx_add_mx2_camera(
@@ -58,7 +60,7 @@ struct platform_device *__init imx_add_mx2_camera(
                        .flags = IORESOURCE_IRQ,
                },
        };
-       return imx_add_platform_device_dmamask("mx2-camera", 0,
+       return imx_add_platform_device_dmamask(data->devid, 0,
                        res, data->iobaseemmaprp ? 4 : 2,
                        pdata, sizeof(*pdata), DMA_BIT_MASK(32));
 }
similarity index 97%
rename from arch/arm/plat-mxc/devices/platform-mxc-ehci.c
rename to arch/arm/mach-imx/devices/platform-mxc-ehci.c
index 35851d889aca2b63bf5e9952359de53b6f429510..5d4bbbfde641360d31815917c2a4c1e88d7fe64d 100644 (file)
@@ -7,8 +7,9 @@
  * Free Software Foundation.
  */
 #include <linux/dma-mapping.h>
-#include <mach/hardware.h>
-#include <mach/devices-common.h>
+
+#include "../hardware.h"
+#include "devices-common.h"
 
 #define imx_mxc_ehci_data_entry_single(soc, _id, hs)                   \
        {                                                               \
similarity index 76%
rename from arch/arm/plat-mxc/devices/platform-mxc-mmc.c
rename to arch/arm/mach-imx/devices/platform-mxc-mmc.c
index 540d3a7d92dfaacf8fd82cbd745327c7d2e094a9..7da19afa1bba75d56ee06b175c119d3109a15cdb 100644 (file)
@@ -7,24 +7,26 @@
  * Free Software Foundation.
  */
 #include <linux/dma-mapping.h>
-#include <mach/hardware.h>
-#include <mach/devices-common.h>
 
-#define imx_mxc_mmc_data_entry_single(soc, _id, _hwid, _size)          \
+#include "../hardware.h"
+#include "devices-common.h"
+
+#define imx_mxc_mmc_data_entry_single(soc, _devid, _id, _hwid, _size)  \
        {                                                               \
+               .devid = _devid,                                        \
                .id = _id,                                              \
                .iobase = soc ## _SDHC ## _hwid ## _BASE_ADDR,          \
                .iosize = _size,                                        \
                .irq = soc ## _INT_SDHC ## _hwid,                       \
                .dmareq = soc ## _DMA_REQ_SDHC ## _hwid,                \
        }
-#define imx_mxc_mmc_data_entry(soc, _id, _hwid, _size)                 \
-       [_id] = imx_mxc_mmc_data_entry_single(soc, _id, _hwid, _size)
+#define imx_mxc_mmc_data_entry(soc, _devid, _id, _hwid, _size)         \
+       [_id] = imx_mxc_mmc_data_entry_single(soc, _devid, _id, _hwid, _size)
 
 #ifdef CONFIG_SOC_IMX21
 const struct imx_mxc_mmc_data imx21_mxc_mmc_data[] __initconst = {
 #define imx21_mxc_mmc_data_entry(_id, _hwid)                           \
-       imx_mxc_mmc_data_entry(MX21, _id, _hwid, SZ_4K)
+       imx_mxc_mmc_data_entry(MX21, "imx21-mmc", _id, _hwid, SZ_4K)
        imx21_mxc_mmc_data_entry(0, 1),
        imx21_mxc_mmc_data_entry(1, 2),
 };
@@ -33,7 +35,7 @@ const struct imx_mxc_mmc_data imx21_mxc_mmc_data[] __initconst = {
 #ifdef CONFIG_SOC_IMX27
 const struct imx_mxc_mmc_data imx27_mxc_mmc_data[] __initconst = {
 #define imx27_mxc_mmc_data_entry(_id, _hwid)                           \
-       imx_mxc_mmc_data_entry(MX27, _id, _hwid, SZ_4K)
+       imx_mxc_mmc_data_entry(MX27, "imx21-mmc", _id, _hwid, SZ_4K)
        imx27_mxc_mmc_data_entry(0, 1),
        imx27_mxc_mmc_data_entry(1, 2),
 };
@@ -42,7 +44,7 @@ const struct imx_mxc_mmc_data imx27_mxc_mmc_data[] __initconst = {
 #ifdef CONFIG_SOC_IMX31
 const struct imx_mxc_mmc_data imx31_mxc_mmc_data[] __initconst = {
 #define imx31_mxc_mmc_data_entry(_id, _hwid)                           \
-       imx_mxc_mmc_data_entry(MX31, _id, _hwid, SZ_16K)
+       imx_mxc_mmc_data_entry(MX31, "imx31-mmc", _id, _hwid, SZ_16K)
        imx31_mxc_mmc_data_entry(0, 1),
        imx31_mxc_mmc_data_entry(1, 2),
 };
@@ -67,7 +69,7 @@ struct platform_device *__init imx_add_mxc_mmc(
                        .flags = IORESOURCE_DMA,
                },
        };
-       return imx_add_platform_device_dmamask("mxc-mmc", data->id,
+       return imx_add_platform_device_dmamask(data->devid, data->id,
                        res, ARRAY_SIZE(res),
                        pdata, sizeof(*pdata), DMA_BIT_MASK(32));
 }
similarity index 74%
rename from arch/arm/plat-mxc/devices/platform-mxc_nand.c
rename to arch/arm/mach-imx/devices/platform-mxc_nand.c
index 95b75cc70515efa8ffc0465cc44585b99ff70ede..7af1c53e42b50c669ad090ad1a513a748a530f38 100644 (file)
@@ -7,18 +7,21 @@
  * Free Software Foundation.
  */
 #include <asm/sizes.h>
-#include <mach/hardware.h>
-#include <mach/devices-common.h>
 
-#define imx_mxc_nand_data_entry_single(soc, _size)                     \
+#include "../hardware.h"
+#include "devices-common.h"
+
+#define imx_mxc_nand_data_entry_single(soc, _devid, _size)             \
        {                                                               \
+               .devid = _devid,                                        \
                .iobase = soc ## _NFC_BASE_ADDR,                        \
                .iosize = _size,                                        \
                .irq = soc ## _INT_NFC                                  \
        }
 
-#define imx_mxc_nandv3_data_entry_single(soc, _size)                   \
+#define imx_mxc_nandv3_data_entry_single(soc, _devid, _size)           \
        {                                                               \
+               .devid = _devid,                                        \
                .id = -1,                                               \
                .iobase = soc ## _NFC_BASE_ADDR,                        \
                .iosize = _size,                                        \
 
 #ifdef CONFIG_SOC_IMX21
 const struct imx_mxc_nand_data imx21_mxc_nand_data __initconst =
-       imx_mxc_nand_data_entry_single(MX21, SZ_4K);
+       imx_mxc_nand_data_entry_single(MX21, "imx21-nand", SZ_4K);
 #endif /* ifdef CONFIG_SOC_IMX21 */
 
 #ifdef CONFIG_SOC_IMX25
 const struct imx_mxc_nand_data imx25_mxc_nand_data __initconst =
-       imx_mxc_nand_data_entry_single(MX25, SZ_8K);
+       imx_mxc_nand_data_entry_single(MX25, "imx25-nand", SZ_8K);
 #endif /* ifdef CONFIG_SOC_IMX25 */
 
 #ifdef CONFIG_SOC_IMX27
 const struct imx_mxc_nand_data imx27_mxc_nand_data __initconst =
-       imx_mxc_nand_data_entry_single(MX27, SZ_4K);
+       imx_mxc_nand_data_entry_single(MX27, "imx27-nand", SZ_4K);
 #endif /* ifdef CONFIG_SOC_IMX27 */
 
 #ifdef CONFIG_SOC_IMX31
 const struct imx_mxc_nand_data imx31_mxc_nand_data __initconst =
-       imx_mxc_nand_data_entry_single(MX31, SZ_4K);
+       imx_mxc_nand_data_entry_single(MX31, "imx27-nand", SZ_4K);
 #endif
 
 #ifdef CONFIG_SOC_IMX35
 const struct imx_mxc_nand_data imx35_mxc_nand_data __initconst =
-       imx_mxc_nand_data_entry_single(MX35, SZ_8K);
+       imx_mxc_nand_data_entry_single(MX35, "imx25-nand", SZ_8K);
 #endif
 
 #ifdef CONFIG_SOC_IMX51
 const struct imx_mxc_nand_data imx51_mxc_nand_data __initconst =
-       imx_mxc_nandv3_data_entry_single(MX51, SZ_16K);
+       imx_mxc_nandv3_data_entry_single(MX51, "imx51-nand", SZ_16K);
 #endif
 
 struct platform_device *__init imx_add_mxc_nand(
@@ -76,7 +79,7 @@ struct platform_device *__init imx_add_mxc_nand(
                        .flags = IORESOURCE_MEM,
                },
        };
-       return imx_add_platform_device("mxc_nand", data->id,
+       return imx_add_platform_device(data->devid, data->id,
                        res, ARRAY_SIZE(res) - !data->axibase,
                        pdata, sizeof(*pdata));
 }
similarity index 97%
rename from arch/arm/plat-mxc/devices/platform-mxc_pwm.c
rename to arch/arm/mach-imx/devices/platform-mxc_pwm.c
index b0c4ae298111feefe47dc6d4701e0b73823c5af1..dcd289777687303ea6547431e953c173b1e4fec7 100644 (file)
@@ -6,8 +6,8 @@
  * the terms of the GNU General Public License version 2 as published by the
  * Free Software Foundation.
  */
-#include <mach/hardware.h>
-#include <mach/devices-common.h>
+#include "../hardware.h"
+#include "devices-common.h"
 
 #define imx_mxc_pwm_data_entry_single(soc, _id, _hwid, _size)          \
        {                                                               \
similarity index 95%
rename from arch/arm/plat-mxc/devices/platform-mxc_rnga.c
rename to arch/arm/mach-imx/devices/platform-mxc_rnga.c
index b4b7612b6e172c2dad8fccc81ab06f2585a73403..c58404badb592080d6ff3702200c6bebb97cdc0f 100644 (file)
@@ -6,8 +6,8 @@
  * the terms of the GNU General Public License version 2 as published by the
  * Free Software Foundation.
  */
-#include <mach/hardware.h>
-#include <mach/devices-common.h>
+#include "../hardware.h"
+#include "devices-common.h"
 
 struct imx_mxc_rnga_data {
        resource_size_t iobase;
similarity index 77%
rename from arch/arm/plat-mxc/devices/platform-mxc_rtc.c
rename to arch/arm/mach-imx/devices/platform-mxc_rtc.c
index a5c9ad5721c2a1374815cc737ede4c3436dfdba5..c7fffaadf847f75a9483464cb214fa47d8d4dd7e 100644 (file)
@@ -6,23 +6,24 @@
  * the terms of the GNU General Public License version 2 as published by the
  * Free Software Foundation.
  */
-#include <mach/hardware.h>
-#include <mach/devices-common.h>
+#include "../hardware.h"
+#include "devices-common.h"
 
-#define imx_mxc_rtc_data_entry_single(soc)                             \
+#define imx_mxc_rtc_data_entry_single(soc, _devid)                     \
        {                                                               \
+               .devid = _devid,                                        \
                .iobase = soc ## _RTC_BASE_ADDR,                        \
                .irq = soc ## _INT_RTC,                                 \
        }
 
 #ifdef CONFIG_SOC_IMX31
 const struct imx_mxc_rtc_data imx31_mxc_rtc_data __initconst =
-       imx_mxc_rtc_data_entry_single(MX31);
+       imx_mxc_rtc_data_entry_single(MX31, "imx21-rtc");
 #endif /* ifdef CONFIG_SOC_IMX31 */
 
 #ifdef CONFIG_SOC_IMX35
 const struct imx_mxc_rtc_data imx35_mxc_rtc_data __initconst =
-       imx_mxc_rtc_data_entry_single(MX35);
+       imx_mxc_rtc_data_entry_single(MX35, "imx21-rtc");
 #endif /* ifdef CONFIG_SOC_IMX35 */
 
 struct platform_device *__init imx_add_mxc_rtc(
@@ -40,6 +41,6 @@ struct platform_device *__init imx_add_mxc_rtc(
                },
        };
 
-       return imx_add_platform_device("mxc_rtc", -1,
+       return imx_add_platform_device(data->devid, -1,
                        res, ARRAY_SIZE(res), NULL, 0);
 }
similarity index 95%
rename from arch/arm/plat-mxc/devices/platform-mxc_w1.c
rename to arch/arm/mach-imx/devices/platform-mxc_w1.c
index 96fa5ea91fe8e701eb7192f7ee0e3c4653bdee28..88c18b720d63722a8d4732fe35aa6a60ba63a905 100644 (file)
@@ -6,8 +6,8 @@
  * the terms of the GNU General Public License version 2 as published by the
  * Free Software Foundation.
  */
-#include <mach/hardware.h>
-#include <mach/devices-common.h>
+#include "../hardware.h"
+#include "devices-common.h"
 
 #define imx_mxc_w1_data_entry_single(soc)                              \
        {                                                               \
similarity index 96%
rename from arch/arm/plat-mxc/devices/platform-pata_imx.c
rename to arch/arm/mach-imx/devices/platform-pata_imx.c
index 70e2f2a4471440bc200a63135db831775722ef39..e4ec11c8ce5546e681f80d22900bc733249ded83 100644 (file)
@@ -3,8 +3,8 @@
  * the terms of the GNU General Public License version 2 as published by the
  * Free Software Foundation.
  */
-#include <mach/hardware.h>
-#include <mach/devices-common.h>
+#include "../hardware.h"
+#include "devices-common.h"
 
 #define imx_pata_imx_data_entry_single(soc, _size)                     \
        {                                                               \
similarity index 98%
rename from arch/arm/plat-mxc/devices/platform-sdhci-esdhc-imx.c
rename to arch/arm/mach-imx/devices/platform-sdhci-esdhc-imx.c
index 3793e475cd954c5c7a39011998a9b3d333ce8a37..e66a4e316311e613e2b67d3738a8ebd21e2618b5 100644 (file)
@@ -6,10 +6,11 @@
  * Free Software Foundation.
  */
 
-#include <mach/hardware.h>
-#include <mach/devices-common.h>
 #include <linux/platform_data/mmc-esdhc-imx.h>
 
+#include "../hardware.h"
+#include "devices-common.h"
+
 #define imx_sdhci_esdhc_imx_data_entry_single(soc, _devid, _id, hwid) \
        {                                                               \
                .devid = _devid,                                        \
similarity index 98%
rename from arch/arm/plat-mxc/devices/platform-spi_imx.c
rename to arch/arm/mach-imx/devices/platform-spi_imx.c
index 9c50c14c8f927fbf8e28018f817128e41a70018c..8880bcb11e055329eb4fbab033d13df2ad8b6d77 100644 (file)
@@ -6,8 +6,8 @@
  * the terms of the GNU General Public License version 2 as published by the
  * Free Software Foundation.
  */
-#include <mach/hardware.h>
-#include <mach/devices-common.h>
+#include "../hardware.h"
+#include "devices-common.h"
 
 #define imx_spi_imx_data_entry_single(soc, type, _devid, _id, hwid, _size) \
        {                                                               \
index 412c583a24b01a7e35fc976572cdafc50e08e13e..27e40d17de9940dfa6631bd1680e4233f962205a 100644 (file)
 
 #include <linux/platform_device.h>
 #include <linux/io.h>
-
-#include <mach/hardware.h>
 #include <linux/platform_data/usb-ehci-mxc.h>
 
+#include "hardware.h"
+
 #define USBCTRL_OTGBASE_OFFSET 0x600
 
 #define MX25_OTG_SIC_SHIFT     29
index cd6e1f81508d2351152094f9c7d24a95fce4a848..448d9115539d391b7aa8f495a386e38d2f4e5066 100644 (file)
 
 #include <linux/platform_device.h>
 #include <linux/io.h>
-
-#include <mach/hardware.h>
 #include <linux/platform_data/usb-ehci-mxc.h>
 
+#include "hardware.h"
+
 #define USBCTRL_OTGBASE_OFFSET 0x600
 
 #define MX27_OTG_SIC_SHIFT     29
index 9a880c78af34081bdca578f8da106d86770054bf..05de4e1e39d7d74807bece3218b8e97402fbd5f6 100644 (file)
 
 #include <linux/platform_device.h>
 #include <linux/io.h>
-
-#include <mach/hardware.h>
 #include <linux/platform_data/usb-ehci-mxc.h>
 
+#include "hardware.h"
+
 #define USBCTRL_OTGBASE_OFFSET 0x600
 
 #define MX31_OTG_SIC_SHIFT     29
index 779e16eb65cb49aeaa58af79b19aac4e08b9bb47..a596f709a9372a6e729592f7cc401f19034cc441 100644 (file)
 
 #include <linux/platform_device.h>
 #include <linux/io.h>
-
-#include <mach/hardware.h>
 #include <linux/platform_data/usb-ehci-mxc.h>
 
+#include "hardware.h"
+
 #define USBCTRL_OTGBASE_OFFSET 0x600
 
 #define MX35_OTG_SIC_SHIFT     29
index cf8d00e5cce13a778af20eded054b75aa9427c09..e49710b10c68a2791026bcf97edd8b7128d071bc 100644 (file)
 
 #include <linux/platform_device.h>
 #include <linux/io.h>
-
-#include <mach/hardware.h>
 #include <linux/platform_data/usb-ehci-mxc.h>
 
+#include "hardware.h"
+
 #define MXC_OTG_OFFSET                 0
 #define MXC_H1_OFFSET                  0x200
 #define MXC_H2_OFFSET                  0x400
similarity index 99%
rename from arch/arm/plat-mxc/epit.c
rename to arch/arm/mach-imx/epit.c
index 88726f4dbbfa60b774e942176056c39f0b31fc66..04a5961beeac70c5567e0aa7f921a077f61df37b 100644 (file)
 #include <linux/clockchips.h>
 #include <linux/clk.h>
 #include <linux/err.h>
-
-#include <mach/hardware.h>
 #include <asm/mach/time.h>
-#include <mach/common.h>
+
+#include "common.h"
+#include "hardware.h"
 
 static struct clock_event_device clockevent_epit;
 static enum clock_event_mode clockevent_mode = CLOCK_EVT_MODE_UNUSED;
index 98aef571b9f839de8111cb8cb19e3dfe595b5adb..b4c70028d35991458ebf3afe4ea39d95784eac58 100644 (file)
 
 #include <asm/mach/arch.h>
 
-#include <mach/common.h>
-#include <mach/iomux-mx27.h>
-#include <mach/hardware.h>
-
+#include "common.h"
 #include "devices-imx27.h"
+#include "hardware.h"
+#include "iomux-mx27.h"
 
 static const int eukrea_mbimx27_pins[] __initconst = {
        /* UART2 */
index 0b84666792f05f7192954b3a57b2256d7e341031..e2b70f4c1a2c314a05b75a613e683b66c438754e 100644 (file)
 #include <linux/spi/spi.h>
 #include <video/platform_lcd.h>
 
-#include <mach/hardware.h>
-#include <mach/iomux-mx25.h>
-#include <mach/common.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
-#include <mach/mx25.h>
 
+#include "common.h"
 #include "devices-imx25.h"
+#include "hardware.h"
+#include "iomux-mx25.h"
+#include "mx25.h"
 
 static iomux_v3_cfg_t eukrea_mbimxsd_pads[] = {
        /* LCD */
index c6532a007d468ae68658c213d3656ee483cc2dfd..5a2d5ef12dd5141cb7c42e1df951857534dc4e76 100644 (file)
 #include <asm/mach/time.h>
 #include <asm/mach/map.h>
 
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/iomux-mx35.h>
-
+#include "common.h"
 #include "devices-imx35.h"
+#include "hardware.h"
+#include "iomux-mx35.h"
 
 static const struct fb_videomode fb_modedb[] = {
        {
index 8b0de30d7a3f3d2dba60032367b4b548657804b4..9be6c1e69d687d72fb764559acec849c83fa5a39 100644 (file)
 #include <asm/mach/time.h>
 #include <asm/mach/map.h>
 
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/iomux-mx51.h>
-
+#include "common.h"
 #include "devices-imx51.h"
+#include "hardware.h"
+#include "iomux-mx51.h"
 
 static iomux_v3_cfg_t eukrea_mbimxsd51_pads[] = {
        /* LED */
similarity index 94%
rename from arch/arm/plat-mxc/include/mach/hardware.h
rename to arch/arm/mach-imx/hardware.h
index ebf10654bb42ae477cfdeede23eedbcbc308c395..3ce7fa3bd43fbcefa6561c6a555e5e9b3254a7d1 100644 (file)
 
 #define IMX_IO_ADDRESS(x)      IOMEM(IMX_IO_P2V(x))
 
-#include <mach/mxc.h>
+#include "mxc.h"
 
-#include <mach/mx6q.h>
-#include <mach/mx50.h>
-#include <mach/mx51.h>
-#include <mach/mx53.h>
-#include <mach/mx3x.h>
-#include <mach/mx31.h>
-#include <mach/mx35.h>
-#include <mach/mx2x.h>
-#include <mach/mx21.h>
-#include <mach/mx27.h>
-#include <mach/mx1.h>
-#include <mach/mx25.h>
+#include "mx6q.h"
+#include "mx50.h"
+#include "mx51.h"
+#include "mx53.h"
+#include "mx3x.h"
+#include "mx31.h"
+#include "mx35.h"
+#include "mx2x.h"
+#include "mx21.h"
+#include "mx27.h"
+#include "mx1.h"
+#include "mx25.h"
 
 #define imx_map_entry(soc, name, _type)        {                               \
        .virtual = soc ## _IO_P2V(soc ## _ ## name ## _BASE_ADDR),      \
index b07b778dc9a80c7e06a8b462d8b110f744623020..3dec962b0770aa9f088829da920c76a44a9d4113 100644 (file)
@@ -13,7 +13,8 @@
 #include <linux/errno.h>
 #include <asm/cacheflush.h>
 #include <asm/cp15.h>
-#include <mach/common.h>
+
+#include "common.h"
 
 static inline void cpu_enter_lowpower(void)
 {
index e80d5235dac0201346aeac09ab9045608bfbe9b5..ebfae96543c47d2ef50c1e4653d9ec6f0dd3fee4 100644 (file)
 #include <linux/of_platform.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
-#include <mach/common.h>
-#include <mach/mx27.h>
+
+#include "common.h"
+#include "mx27.h"
 
 static const struct of_dev_auxdata imx27_auxdata_lookup[] __initconst = {
        OF_DEV_AUXDATA("fsl,imx27-uart", MX27_UART1_BASE_ADDR, "imx21-uart.0", NULL),
        OF_DEV_AUXDATA("fsl,imx27-uart", MX27_UART2_BASE_ADDR, "imx21-uart.1", NULL),
        OF_DEV_AUXDATA("fsl,imx27-uart", MX27_UART3_BASE_ADDR, "imx21-uart.2", NULL),
        OF_DEV_AUXDATA("fsl,imx27-fec", MX27_FEC_BASE_ADDR, "imx27-fec.0", NULL),
-       OF_DEV_AUXDATA("fsl,imx27-i2c", MX27_I2C1_BASE_ADDR, "imx-i2c.0", NULL),
-       OF_DEV_AUXDATA("fsl,imx27-i2c", MX27_I2C2_BASE_ADDR, "imx-i2c.1", NULL),
+       OF_DEV_AUXDATA("fsl,imx27-i2c", MX27_I2C1_BASE_ADDR, "imx21-i2c.0", NULL),
+       OF_DEV_AUXDATA("fsl,imx27-i2c", MX27_I2C2_BASE_ADDR, "imx21-i2c.1", NULL),
        OF_DEV_AUXDATA("fsl,imx27-cspi", MX27_CSPI1_BASE_ADDR, "imx27-cspi.0", NULL),
        OF_DEV_AUXDATA("fsl,imx27-cspi", MX27_CSPI2_BASE_ADDR, "imx27-cspi.1", NULL),
        OF_DEV_AUXDATA("fsl,imx27-cspi", MX27_CSPI3_BASE_ADDR, "imx27-cspi.2", NULL),
        OF_DEV_AUXDATA("fsl,imx27-wdt", MX27_WDOG_BASE_ADDR, "imx2-wdt.0", NULL),
-       OF_DEV_AUXDATA("fsl,imx27-nand", MX27_NFC_BASE_ADDR, "mxc_nand.0", NULL),
+       OF_DEV_AUXDATA("fsl,imx27-nand", MX27_NFC_BASE_ADDR, "imx27-nand.0", NULL),
        { /* sentinel */ }
 };
 
index a68ba207b2b790ce3d0bce0f41a134349647a6af..af476de2570e8727c1c4e9fe0ac0a77397da7985 100644 (file)
@@ -14,8 +14,9 @@
 #include <linux/of_platform.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
-#include <mach/common.h>
-#include <mach/mx31.h>
+
+#include "common.h"
+#include "mx31.h"
 
 static const struct of_dev_auxdata imx31_auxdata_lookup[] __initconst = {
        OF_DEV_AUXDATA("fsl,imx31-uart", MX31_UART1_BASE_ADDR,
index f233b4bb2342ded80353a25a8ad253b60fd7620d..50742990a136f07a02f0e2f99d4debdc9257f5ae 100644 (file)
@@ -15,8 +15,9 @@
 #include <linux/of_platform.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
-#include <mach/common.h>
-#include <mach/mx51.h>
+
+#include "common.h"
+#include "mx51.h"
 
 /*
  * Lookup table for attaching a specific name and platform_data pointer to
@@ -36,8 +37,8 @@ static const struct of_dev_auxdata imx51_auxdata_lookup[] __initconst = {
        OF_DEV_AUXDATA("fsl,imx51-ecspi", MX51_ECSPI1_BASE_ADDR, "imx51-ecspi.0", NULL),
        OF_DEV_AUXDATA("fsl,imx51-ecspi", MX51_ECSPI2_BASE_ADDR, "imx51-ecspi.1", NULL),
        OF_DEV_AUXDATA("fsl,imx51-cspi", MX51_CSPI_BASE_ADDR, "imx35-cspi.0", NULL),
-       OF_DEV_AUXDATA("fsl,imx51-i2c", MX51_I2C1_BASE_ADDR, "imx-i2c.0", NULL),
-       OF_DEV_AUXDATA("fsl,imx51-i2c", MX51_I2C2_BASE_ADDR, "imx-i2c.1", NULL),
+       OF_DEV_AUXDATA("fsl,imx51-i2c", MX51_I2C1_BASE_ADDR, "imx21-i2c.0", NULL),
+       OF_DEV_AUXDATA("fsl,imx51-i2c", MX51_I2C2_BASE_ADDR, "imx21-i2c.1", NULL),
        OF_DEV_AUXDATA("fsl,imx51-sdma", MX51_SDMA_BASE_ADDR, "imx35-sdma", NULL),
        OF_DEV_AUXDATA("fsl,imx51-wdt", MX51_WDOG1_BASE_ADDR, "imx2-wdt.0", NULL),
        { /* sentinel */ }
diff --git a/arch/arm/mach-imx/include/mach/dma-mx1-mx2.h b/arch/arm/mach-imx/include/mach/dma-mx1-mx2.h
deleted file mode 100644 (file)
index df5f522..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef __MACH_DMA_MX1_MX2_H__
-#define __MACH_DMA_MX1_MX2_H__
-/*
- * Don't use this header in new code, it will go away when all users are
- * converted to mach/dma-v1.h
- */
-
-#include <mach/dma-v1.h>
-
-#endif /* ifndef __MACH_DMA_MX1_MX2_H__ */
index 82bd4403b450a915ac2a8b83a627ddf00642a6fa..cabefbc5e7c16cbcaa7493e2e56373071335de30 100644 (file)
@@ -22,8 +22,9 @@
 #include <linux/spinlock.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx3.h>
+
+#include "hardware.h"
+#include "iomux-mx3.h"
 
 /*
  * IOMUX register (base) addresses
similarity index 99%
rename from arch/arm/plat-mxc/include/mach/iomux-mx1.h
rename to arch/arm/mach-imx/iomux-mx1.h
index 6b1507cf378e1bb1cede03777d47b45e26d21e12..95f4681d85d7a1a9e57126f01dff0cf14a16b501 100644 (file)
@@ -18,7 +18,7 @@
 #ifndef __MACH_IOMUX_MX1_H__
 #define __MACH_IOMUX_MX1_H__
 
-#include <mach/iomux-v1.h>
+#include "iomux-v1.h"
 
 #define PA0_AIN_SPI2_CLK       (GPIO_PORTA | GPIO_AIN | GPIO_OUT | 0)
 #define PA0_AF_ETMTRACESYNC    (GPIO_PORTA | GPIO_AF | 0)
similarity index 99%
rename from arch/arm/plat-mxc/include/mach/iomux-mx21.h
rename to arch/arm/mach-imx/iomux-mx21.h
index 1495dfda7834c8e0d0a7dc5fce1e2650b2913cb1..a70cffceb085eebcd789fb8a2ce744a293713e3a 100644 (file)
@@ -18,8 +18,8 @@
 #ifndef __MACH_IOMUX_MX21_H__
 #define __MACH_IOMUX_MX21_H__
 
-#include <mach/iomux-mx2x.h>
-#include <mach/iomux-v1.h>
+#include "iomux-mx2x.h"
+#include "iomux-v1.h"
 
 /* Primary GPIO pin functions */
 
similarity index 99%
rename from arch/arm/plat-mxc/include/mach/iomux-mx25.h
rename to arch/arm/mach-imx/iomux-mx25.h
index c61ec0fc10d47899c1ffc8dfb361fa1de73f273a..be51e838375cf84a0b6dbe5104fc556419b36eb2 100644 (file)
@@ -19,7 +19,7 @@
 #ifndef __MACH_IOMUX_MX25_H__
 #define __MACH_IOMUX_MX25_H__
 
-#include <mach/iomux-v3.h>
+#include "iomux-v3.h"
 
 /*
  * IOMUX/PAD Bit field definitions
similarity index 99%
rename from arch/arm/plat-mxc/include/mach/iomux-mx27.h
rename to arch/arm/mach-imx/iomux-mx27.h
index d9f9a6e32d80c809bf901ccfaef7f3acf168c692..218e99e89e86e62c0318f10def97c2413959b92d 100644 (file)
@@ -19,8 +19,8 @@
 #ifndef __MACH_IOMUX_MX27_H__
 #define __MACH_IOMUX_MX27_H__
 
-#include <mach/iomux-mx2x.h>
-#include <mach/iomux-v1.h>
+#include "iomux-mx2x.h"
+#include "iomux-v1.h"
 
 /* Primary GPIO pin functions */
 
similarity index 99%
rename from arch/arm/plat-mxc/include/mach/iomux-mx35.h
rename to arch/arm/mach-imx/iomux-mx35.h
index 3117c18bbbd9dcabb88408f51453df3cef85235f..90bfa6b5be6a41ec01c07e7934134501ba4cd690 100644 (file)
@@ -19,7 +19,7 @@
 #ifndef __MACH_IOMUX_MX35_H__
 #define __MACH_IOMUX_MX35_H__
 
-#include <mach/iomux-v3.h>
+#include "iomux-v3.h"
 
 /*
  * The naming convention for the pad modes is MX35_PAD_<padname>__<padmode>
similarity index 99%
rename from arch/arm/plat-mxc/include/mach/iomux-mx50.h
rename to arch/arm/mach-imx/iomux-mx50.h
index 98e7fd0b90830d27414515cc0cb1d8c99afd4fb1..00f56e0e8009ce1529ff8dc865d4165ede8b91bb 100644 (file)
@@ -19,7 +19,7 @@
 #ifndef __MACH_IOMUX_MX50_H__
 #define __MACH_IOMUX_MX50_H__
 
-#include <mach/iomux-v3.h>
+#include "iomux-v3.h"
 
 #define MX50_ELCDIF_PAD_CTRL   (PAD_CTL_PKE | PAD_CTL_DSE_HIGH)
 
similarity index 99%
rename from arch/arm/plat-mxc/include/mach/iomux-mx51.h
rename to arch/arm/mach-imx/iomux-mx51.h
index 2623e7a2e1907368d9d8e7926122199d9892c89c..75bbcc4aa2d27a1181e63c119603302fd2f6a91a 100644 (file)
@@ -13,7 +13,7 @@
 #ifndef __MACH_IOMUX_MX51_H__
 #define __MACH_IOMUX_MX51_H__
 
-#include <mach/iomux-v3.h>
+#include "iomux-v3.h"
 #define __NA_  0x000
 
 
similarity index 98%
rename from arch/arm/plat-mxc/iomux-v1.c
rename to arch/arm/mach-imx/iomux-v1.c
index 1f73963bc13e916e895433ffd5e5d7687e9e333d..2b156d1d9e216bf2d6b7a5c38064f8c79efb26e5 100644 (file)
 #include <linux/string.h>
 #include <linux/gpio.h>
 
-#include <mach/hardware.h>
 #include <asm/mach/map.h>
-#include <mach/iomux-v1.h>
+
+#include "hardware.h"
+#include "iomux-v1.h"
 
 static void __iomem *imx_iomuxv1_baseaddr;
 static unsigned imx_iomuxv1_numports;
similarity index 97%
rename from arch/arm/plat-mxc/iomux-v3.c
rename to arch/arm/mach-imx/iomux-v3.c
index 99a9cdb9d6be57b5a0de933865cbaa319435ffdf..9dae74bf47fcb5d96ad2c900a1fe9fead266bf2d 100644 (file)
 #include <linux/string.h>
 #include <linux/gpio.h>
 
-#include <mach/hardware.h>
 #include <asm/mach/map.h>
-#include <mach/iomux-v3.h>
+
+#include "hardware.h"
+#include "iomux-v3.h"
 
 static void __iomem *base;
 
similarity index 98%
rename from arch/arm/plat-mxc/iram_alloc.c
rename to arch/arm/mach-imx/iram_alloc.c
index 074c3869626aeaa2cf01d1967d0ba1288897a5f9..6c80424f678e3fad821aa8ea60685485db5ddb6e 100644 (file)
@@ -22,7 +22,8 @@
 #include <linux/module.h>
 #include <linux/spinlock.h>
 #include <linux/genalloc.h>
-#include <mach/iram.h>
+
+#include "iram.h"
 
 static unsigned long iram_phys_base;
 static void __iomem *iram_virt_base;
similarity index 94%
rename from arch/arm/plat-mxc/irq-common.h
rename to arch/arm/mach-imx/irq-common.h
index 6ccb3a14c693943b37d1aac199e2bf9de589535f..5b2dabba330fd7ad69c534aa3714bc821d77342a 100644 (file)
@@ -19,6 +19,9 @@
 #ifndef __PLAT_MXC_IRQ_COMMON_H__
 #define __PLAT_MXC_IRQ_COMMON_H__
 
+/* all normal IRQs can be FIQs */
+#define FIQ_START      0
+
 struct mxc_extra_irq
 {
        int (*set_priority)(unsigned char irq, unsigned char prio);
index c40a34c0048910c974789695b0ecb13374d3cb94..5f1510363ee76f469358be2c86a664eed70f9308 100644 (file)
@@ -14,7 +14,8 @@
 #include <asm/page.h>
 #include <asm/sizes.h>
 #include <asm/mach/map.h>
-#include <mach/hardware.h>
+
+#include "hardware.h"
 
 static struct map_desc imx_lluart_desc = {
 #ifdef CONFIG_DEBUG_IMX6Q_UART2
index 7b99a79722b6fbe638829ad8946877f11eb5c353..5c9bd2c66e6d595c51677259cd2ecf411bee7946 100644 (file)
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx1.h>
-
+#include "common.h"
 #include "devices-imx1.h"
+#include "hardware.h"
+#include "iomux-mx1.h"
 
 static const int apf9328_pins[] __initconst = {
        /* UART1 */
index 5985ed1b8c9875cffc99ab74233147912ae01eca..59bd6b06a6b5f1d549b87d4fb8a71e6ded3fe074 100644 (file)
 #include <linux/regulator/machine.h>
 #include <linux/regulator/fixed.h>
 
-#include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 #include <asm/memory.h>
 #include <asm/mach/map.h>
 
-#include <mach/common.h>
-#include <mach/iomux-mx3.h>
-#include <mach/ulpi.h>
-
+#include "common.h"
 #include "devices-imx31.h"
 #include "crmregs-imx3.h"
+#include "hardware.h"
+#include "iomux-mx3.h"
+#include "ulpi.h"
 
 static int armadillo5x0_pins[] = {
        /* UART1 */
index 9a9897749dd61b5b06b7a5d2037a72044acbc76f..3a39d5aec07a7cffbec8adf8a940ee20ccb9e7d4 100644 (file)
 #include <linux/init.h>
 #include <linux/platform_device.h>
 
-#include <mach/iomux-mx3.h>
-#include <mach/hardware.h>
-#include <mach/common.h>
-
 #include <asm/mach/time.h>
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 
+#include "common.h"
 #include "devices-imx31.h"
+#include "hardware.h"
+#include "iomux-mx3.h"
 
 static const struct imxuart_platform_data uart_pdata __initconst = {
        .flags = IMXUART_HAVE_RTSCTS,
index 2bb9e18d9ee134a078c664c966c2de6d2d4342f5..12a370646b450e5b313ad73b70d79d4b3fcf1c0b 100644 (file)
 #include <asm/mach/time.h>
 #include <asm/mach/map.h>
 
-#include <mach/eukrea-baseboards.h>
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx27.h>
-#include <mach/ulpi.h>
-
+#include "common.h"
 #include "devices-imx27.h"
+#include "eukrea-baseboards.h"
+#include "hardware.h"
+#include "iomux-mx27.h"
+#include "ulpi.h"
 
 static const int eukrea_cpuimx27_pins[] __initconst = {
        /* UART1 */
index d49b0ec6bdec839953f15775a03adb5546c17b6a..5a31bf8c8f4c528b1275d99b727be937917b8491 100644 (file)
 #include <asm/mach/time.h>
 #include <asm/mach/map.h>
 
-#include <mach/eukrea-baseboards.h>
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/iomux-mx35.h>
-
+#include "common.h"
 #include "devices-imx35.h"
+#include "eukrea-baseboards.h"
+#include "hardware.h"
+#include "iomux-mx35.h"
 
 static const struct imxuart_platform_data uart_pdata __initconst = {
        .flags = IMXUART_HAVE_RTSCTS,
index b87cc49ab1e8ec67e6504f54335115de95c3223d..b727de029c8f3dfc4a99fd1e68333086c06c9737 100644 (file)
 #include <linux/spi/spi.h>
 #include <linux/can/platform/mcp251x.h>
 
-#include <mach/eukrea-baseboards.h>
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx51.h>
-
 #include <asm/setup.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 
+#include "common.h"
 #include "devices-imx51.h"
 #include "cpu_op-mx51.h"
+#include "eukrea-baseboards.h"
+#include "hardware.h"
+#include "iomux-mx51.h"
 
 #define USBH1_RST              IMX_GPIO_NR(2, 28)
 #define ETH_RST                        IMX_GPIO_NR(2, 31)
index 017bbb70ea415b3b75c050dbf0952aa46374680c..75027a5ad8b75c2dbc8afd98a413dd855a59cca4 100644 (file)
 #include <linux/usb/otg.h>
 #include <linux/usb/ulpi.h>
 
-#include <mach/eukrea-baseboards.h>
-#include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 #include <asm/memory.h>
 #include <asm/mach/map.h>
-#include <mach/common.h>
-#include <mach/mx25.h>
-#include <mach/iomux-mx25.h>
 
+#include "common.h"
 #include "devices-imx25.h"
+#include "eukrea-baseboards.h"
+#include "hardware.h"
+#include "iomux-mx25.h"
+#include "mx25.h"
 
 static const struct imxuart_platform_data uart_pdata __initconst = {
        .flags = IMXUART_HAVE_RTSCTS,
index 141756f00ae5c8733795855bd31b994c8609a496..b74422679126fb7156087d0c2eedc0cfe94fd856 100644 (file)
 #include <asm/mach/time.h>
 #include <asm/system_info.h>
 #include <asm/memblock.h>
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx27.h>
 
+#include "common.h"
 #include "devices-imx27.h"
+#include "hardware.h"
+#include "iomux-mx27.h"
 
 #define TVP5150_RSTN (GPIO_PORTC + 18)
 #define TVP5150_PWDN (GPIO_PORTC + 19)
index 7381387a890558909ae69b3fd2fbeb621118e61c..53a8601129385d85c9314169ffa913e37ef69ba8 100644 (file)
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/iomux-mx27.h>
 
+#include "hardware.h"
+#include "common.h"
 #include "devices-imx27.h"
+#include "iomux-mx27.h"
 
 static const int mx27ipcam_pins[] __initconst = {
        /* UART1 */
index 1f45b9189229787343ca9465b4c2d3d0425c6758..fc8dce93137888bbd22d508833cad4ea78888b87 100644 (file)
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 #include <asm/mach/map.h>
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/iomux-mx27.h>
 
+#include "common.h"
 #include "devices-imx27.h"
+#include "hardware.h"
+#include "iomux-mx27.h"
 
 static const int mx27lite_pins[] __initconst = {
        /* UART1 */
index 29711e95579f7cb5a28bf9e29f359b14f78a7133..e71e62610eba239bef4d34ed4ff38df570cc30c2 100644 (file)
@@ -19,8 +19,9 @@
 #include <linux/of_platform.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
-#include <mach/common.h>
-#include <mach/mx53.h>
+
+#include "common.h"
+#include "mx53.h"
 
 /*
  * Lookup table for attaching a specific name and platform_data pointer to
@@ -42,9 +43,9 @@ static const struct of_dev_auxdata imx53_auxdata_lookup[] __initconst = {
        OF_DEV_AUXDATA("fsl,imx53-ecspi", MX53_ECSPI1_BASE_ADDR, "imx51-ecspi.0", NULL),
        OF_DEV_AUXDATA("fsl,imx53-ecspi", MX53_ECSPI2_BASE_ADDR, "imx51-ecspi.1", NULL),
        OF_DEV_AUXDATA("fsl,imx53-cspi", MX53_CSPI_BASE_ADDR, "imx35-cspi.0", NULL),
-       OF_DEV_AUXDATA("fsl,imx53-i2c", MX53_I2C1_BASE_ADDR, "imx-i2c.0", NULL),
-       OF_DEV_AUXDATA("fsl,imx53-i2c", MX53_I2C2_BASE_ADDR, "imx-i2c.1", NULL),
-       OF_DEV_AUXDATA("fsl,imx53-i2c", MX53_I2C3_BASE_ADDR, "imx-i2c.2", NULL),
+       OF_DEV_AUXDATA("fsl,imx53-i2c", MX53_I2C1_BASE_ADDR, "imx21-i2c.0", NULL),
+       OF_DEV_AUXDATA("fsl,imx53-i2c", MX53_I2C2_BASE_ADDR, "imx21-i2c.1", NULL),
+       OF_DEV_AUXDATA("fsl,imx53-i2c", MX53_I2C3_BASE_ADDR, "imx21-i2c.2", NULL),
        OF_DEV_AUXDATA("fsl,imx53-sdma", MX53_SDMA_BASE_ADDR, "imx35-sdma", NULL),
        OF_DEV_AUXDATA("fsl,imx53-wdt", MX53_WDOG1_BASE_ADDR, "imx2-wdt.0", NULL),
        { /* sentinel */ }
index 47c91f7185d2fb7cdef048388e5cf82620e68a87..978b6dd00de401e7662e0fc1e7d1aa003df57e20 100644 (file)
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 #include <asm/system_misc.h>
-#include <mach/common.h>
-#include <mach/cpuidle.h>
-#include <mach/hardware.h>
 
+#include "common.h"
+#include "cpuidle.h"
+#include "hardware.h"
 
 void imx6q_restart(char mode, const char *cmd)
 {
index 0330078ff7880a34c94e275c19d128b989762355..2e536ea53444f8007cecd23308fb15155b2bb0b4 100644 (file)
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
 
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx3.h>
-
+#include "common.h"
 #include "devices-imx31.h"
+#include "hardware.h"
+#include "iomux-mx3.h"
 
 #define KZM_ARM11_IO_ADDRESS(x) (IOMEM(                                        \
        IMX_IO_P2V_MODULE(x, MX31_CS4) ?:                               \
index 667f359a2e8b037e8d6a08933cf20435195e849d..06b483783e68d7abcff369b306dbda29c8a80574 100644 (file)
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx1.h>
-
+#include "common.h"
 #include "devices-imx1.h"
+#include "hardware.h"
+#include "iomux-mx1.h"
 
 static const int mx1ads_pins[] __initconst = {
        /* UART1 */
index ed22e3fe6ec888d08840d9b6cbc839c9ccfdf4d6..6adb3136bb08be1380b7d79e767e3153c3432536 100644 (file)
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/physmap.h>
 #include <linux/gpio.h>
-#include <mach/common.h>
-#include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 #include <asm/mach/map.h>
-#include <mach/iomux-mx21.h>
 
+#include "common.h"
 #include "devices-imx21.h"
+#include "hardware.h"
+#include "iomux-mx21.h"
 
 /*
  * Memory-mapped I/O on MX21ADS base board
index ce247fd1269ae094a57dc95065ba2256effb7e65..b1b03aa55bb8eec8352a7ccc69a2b5066c0bb546 100644 (file)
 #include <linux/platform_device.h>
 #include <linux/usb/otg.h>
 
-#include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 #include <asm/memory.h>
 #include <asm/mach/map.h>
-#include <mach/common.h>
-#include <mach/mx25.h>
-#include <mach/iomux-mx25.h>
 
+#include "common.h"
 #include "devices-imx25.h"
+#include "hardware.h"
+#include "iomux-mx25.h"
+#include "mx25.h"
 
 #define MX25PDK_CAN_PWDN       IMX_GPIO_NR(4, 6)
 
index 05996f39005c2dfcd2a6eb1df57b4fc92b2abc03..d0e547fa925fe40556d86b04d54ad3ef1c353be0 100644 (file)
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/iomux-mx27.h>
-#include <mach/ulpi.h>
-#include <mach/3ds_debugboard.h>
 
+#include "3ds_debugboard.h"
+#include "common.h"
 #include "devices-imx27.h"
+#include "hardware.h"
+#include "iomux-mx27.h"
+#include "ulpi.h"
 
 #define SD1_EN_GPIO            IMX_GPIO_NR(2, 25)
 #define OTG_PHY_RESET_GPIO     IMX_GPIO_NR(2, 23)
index 7dc59bac0e55cf8e30e1151064622a53cf172205..3d036f57f0e6c7558b890ec3fb26c337ffaac5fe 100644 (file)
 #include <linux/mtd/physmap.h>
 #include <linux/i2c.h>
 #include <linux/irq.h>
-#include <mach/common.h>
-#include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 #include <asm/mach/map.h>
-#include <mach/iomux-mx27.h>
 
+#include "common.h"
 #include "devices-imx27.h"
+#include "hardware.h"
+#include "iomux-mx27.h"
 
 /*
  * Base address of PBC controller, CS4
index 8915f937b7d54e00735bf2de1dd4c03730d2d5f9..bc301befdd06a2d9356bcb258710fd475113ac19 100644 (file)
 
 #include <media/soc_camera.h>
 
-#include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 #include <asm/memory.h>
 #include <asm/mach/map.h>
 #include <asm/memblock.h>
-#include <mach/common.h>
-#include <mach/iomux-mx3.h>
-#include <mach/3ds_debugboard.h>
-#include <mach/ulpi.h>
 
+#include "3ds_debugboard.h"
+#include "common.h"
 #include "devices-imx31.h"
+#include "hardware.h"
+#include "iomux-mx3.h"
+#include "ulpi.h"
 
 static int mx31_3ds_pins[] = {
        /* UART1 */
@@ -393,7 +393,7 @@ static struct regulator_init_data gpo_init = {
 };
 
 static struct regulator_consumer_supply vmmc2_consumers[] = {
-       REGULATOR_SUPPLY("vmmc", "mxc-mmc.0"),
+       REGULATOR_SUPPLY("vmmc", "imx31-mmc.0"),
 };
 
 static struct regulator_init_data vmmc2_init = {
index e774b07f48d33c70c0a678f3547fc8d1962d15bf..8b56f8883f3278d58bc5668ff49dd2377bbe9e02 100644 (file)
@@ -28,8 +28,6 @@
 #include <asm/mach/time.h>
 #include <asm/memory.h>
 #include <asm/mach/map.h>
-#include <mach/common.h>
-#include <mach/iomux-mx3.h>
 
 #ifdef CONFIG_MACH_MX31ADS_WM1133_EV1
 #include <linux/mfd/wm8350/audio.h>
 #include <linux/mfd/wm8350/pmic.h>
 #endif
 
+#include "common.h"
 #include "devices-imx31.h"
+#include "hardware.h"
+#include "iomux-mx3.h"
 
 /* Base address of PBC controller */
 #define PBC_BASE_ADDRESS       MX31_CS4_BASE_ADDR_VIRT
index 34b9bf075daff783eb332ab652347ac1e159b84f..08b9965c8b36658d75b5e93b5c05616864628088 100644 (file)
 #include <asm/mach/time.h>
 #include <asm/mach/map.h>
 
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/iomux-mx3.h>
-#include <mach/board-mx31lilly.h>
-#include <mach/ulpi.h>
-
+#include "board-mx31lilly.h"
+#include "common.h"
 #include "devices-imx31.h"
+#include "hardware.h"
+#include "iomux-mx3.h"
+#include "ulpi.h"
 
 /*
  * This file contains module-specific initialization routines for LILLY-1131.
index ef57cff5abfbf8bd72607e23395963bbe5d4d895..bdcd92e59518f054d15ca78c5b8c35032deedc98 100644 (file)
 #include <asm/page.h>
 #include <asm/setup.h>
 
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/board-mx31lite.h>
-#include <mach/iomux-mx3.h>
-#include <mach/ulpi.h>
-
+#include "board-mx31lite.h"
+#include "common.h"
 #include "devices-imx31.h"
+#include "hardware.h"
+#include "iomux-mx3.h"
+#include "ulpi.h"
 
 /*
  * This file contains the module-specific initialization routines.
index 459e754ef8c9162accb2d6b5c698af67cc52fa4d..2517cfa9f26bbb4519045f2653236dad709c9cb0 100644 (file)
 #include <asm/mach/time.h>
 #include <asm/mach/map.h>
 #include <asm/memblock.h>
-#include <mach/board-mx31moboard.h>
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx3.h>
-#include <mach/ulpi.h>
 #include <linux/platform_data/asoc-imx-ssi.h>
 
+#include "board-mx31moboard.h"
+#include "common.h"
 #include "devices-imx31.h"
+#include "hardware.h"
+#include "iomux-mx3.h"
+#include "ulpi.h"
 
 static unsigned int moboard_pins[] = {
        /* UART0 */
@@ -175,11 +175,11 @@ static const struct spi_imx_master moboard_spi1_pdata __initconst = {
 
 static struct regulator_consumer_supply sdhc_consumers[] = {
        {
-               .dev_name = "mxc-mmc.0",
+               .dev_name = "imx31-mmc.0",
                .supply = "sdhc0_vcc",
        },
        {
-               .dev_name = "mxc-mmc.1",
+               .dev_name = "imx31-mmc.1",
                .supply = "sdhc1_vcc",
        },
 };
index 504983c68aa8309bc8971ddbb18d8e35fb270505..5277da45d60c75a5ce7d7041745d7b9420485517 100644 (file)
 #include <asm/mach/map.h>
 #include <asm/memblock.h>
 
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/iomux-mx35.h>
-#include <mach/3ds_debugboard.h>
 #include <video/platform_lcd.h>
 
 #include <media/soc_camera.h>
 
+#include "3ds_debugboard.h"
+#include "common.h"
 #include "devices-imx35.h"
+#include "hardware.h"
+#include "iomux-mx35.h"
 
 #define GPIO_MC9S08DZ60_GPS_ENABLE 0
 #define GPIO_MC9S08DZ60_HDD_ENABLE 4
index 42b66e8d9615be75b2a4e4a3238ef04cedef360c..0c1f88a80bdc79080b0a2157db3fa39d73dabb61 100644 (file)
 #include <linux/delay.h>
 #include <linux/io.h>
 
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx50.h>
-
 #include <asm/irq.h>
 #include <asm/setup.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 
+#include "common.h"
 #include "devices-imx50.h"
+#include "hardware.h"
+#include "iomux-mx50.h"
 
 #define FEC_EN         IMX_GPIO_NR(6, 23)
 #define FEC_RESET_B    IMX_GPIO_NR(4, 12)
index 9ee84a4af63931c915a1d297a22a68ccaf1e688b..abc25bd1107be1e58cb0d889dd9aef27bd997320 100644 (file)
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/iomux-mx51.h>
-#include <mach/3ds_debugboard.h>
-
+#include "3ds_debugboard.h"
+#include "common.h"
 #include "devices-imx51.h"
+#include "hardware.h"
+#include "iomux-mx51.h"
 
 #define MX51_3DS_ECSPI2_CS     (GPIO_PORTC + 28)
 
index 7b31cbde8775409312da8d8b749c293c3ced850f..d9a84ca2199ac2391463787b66e6661542e6e064 100644 (file)
 #include <linux/spi/flash.h>
 #include <linux/spi/spi.h>
 
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx51.h>
-
 #include <asm/setup.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 
+#include "common.h"
 #include "devices-imx51.h"
 #include "cpu_op-mx51.h"
+#include "hardware.h"
+#include "iomux-mx51.h"
 
 #define BABBAGE_USB_HUB_RESET  IMX_GPIO_NR(1, 7)
 #define BABBAGE_USBH1_STP      IMX_GPIO_NR(1, 27)
index 0bf6d30aa32d71de42f0068c6c7663a2ffb4ac01..f4a8c7e108e19d05410388b7000c72b57a1ad97a 100644 (file)
 #include <linux/mtd/physmap.h>
 #include <linux/i2c.h>
 #include <linux/irq.h>
-#include <mach/common.h>
-#include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 #include <asm/mach/map.h>
 #include <linux/gpio.h>
-#include <mach/iomux-mx27.h>
 #include <linux/i2c/pca953x.h>
 
+#include "common.h"
 #include "devices-imx27.h"
+#include "hardware.h"
+#include "iomux-mx27.h"
 
 static const int mxt_td60_pins[] __initconst = {
        /* UART0 */
index de8516b7d69f36a77c51f44dcc224077f05d021e..eee369fa94a29ad5893e728e2240faaabcc1ae75 100644 (file)
 
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx27.h>
 #include <asm/mach/time.h>
-#include <mach/ulpi.h>
 
+#include "common.h"
 #include "devices-imx27.h"
+#include "hardware.h"
+#include "iomux-mx27.h"
+#include "ulpi.h"
 
 #define OTG_PHY_CS_GPIO (GPIO_PORTB + 23)
 #define USBH2_PHY_CS_GPIO (GPIO_PORTB + 24)
index e3c45130fb3cc8bad1929bdcd68b6227b2cc298f..547fef133f658f46d6627277a18cd9a3225c2907 100644 (file)
 #include <asm/mach/time.h>
 #include <asm/mach/map.h>
 #include <asm/memblock.h>
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx3.h>
-#include <mach/ulpi.h>
 
+#include "common.h"
 #include "devices-imx31.h"
+#include "hardware.h"
+#include "iomux-mx3.h"
 #include "pcm037.h"
+#include "ulpi.h"
 
 static enum pcm037_board_variant pcm037_instance = PCM037_PCM970;
 
index 11ffa81ad17db2d9501286df2201371ce3fdc0cc..8fd8255068eed31bce063e3db0d3b8a9f903c605 100644 (file)
 #include <linux/platform_device.h>
 #include <linux/spi/spi.h>
 
-#include <mach/common.h>
-#include <mach/iomux-mx3.h>
-
 #include <asm/mach-types.h>
 
 #include "pcm037.h"
+#include "common.h"
 #include "devices-imx31.h"
+#include "iomux-mx3.h"
 
 static unsigned int pcm037_eet_pins[] = {
        /* Reserve and hardwire GPIO 57 high - S6E63D6 chipselect */
index 95f49d936fd3bd442e6b806ac5945d62050a3ba8..4aa0d0798605d5cf2fc20ee64b26d2c1e0f7ed6d 100644 (file)
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 
-#include <mach/board-pcm038.h>
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx27.h>
-#include <mach/ulpi.h>
-
+#include "board-pcm038.h"
+#include "common.h"
 #include "devices-imx27.h"
+#include "hardware.h"
+#include "iomux-mx27.h"
+#include "ulpi.h"
 
 static const int pcm038_pins[] __initconst = {
        /* UART1 */
@@ -212,7 +211,7 @@ static const struct spi_imx_master pcm038_spi0_data __initconst = {
 
 static struct regulator_consumer_supply sdhc1_consumers[] = {
        {
-               .dev_name = "mxc-mmc.1",
+               .dev_name = "imx21-mmc.1",
                .supply = "sdhc_vcc",
        },
 };
index e4bd4387e344e653394a3b203ca91cbb7ec5cda0..92445440221eba9f2aace35fc1c3e6cd205a2e4b 100644 (file)
 #include <asm/mach/time.h>
 #include <asm/mach/map.h>
 
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/iomux-mx35.h>
-#include <mach/ulpi.h>
-
+#include "common.h"
 #include "devices-imx35.h"
+#include "hardware.h"
+#include "iomux-mx35.h"
+#include "ulpi.h"
 
 static const struct fb_videomode fb_modedb[] = {
        {
index fb25fbd3122633baae6bc964cbfac7779acd014f..96d9a91f8a3bb15efda2f4cb2be9a80b16db2a69 100644 (file)
 #include <linux/mtd/nand.h>
 #include <linux/gpio.h>
 
-#include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 #include <asm/mach/map.h>
-#include <mach/common.h>
 #include <asm/page.h>
 #include <asm/setup.h>
-#include <mach/iomux-mx3.h>
 
+#include "common.h"
 #include "devices-imx31.h"
+#include "hardware.h"
+#include "iomux-mx3.h"
 
 /* FPGA defines */
 #define QONG_FPGA_VERSION(major, minor, rev)   \
index 67ff38e9a3ca3434e9b16b4daba6f908eec77715..fc970409dbaf1cd782d6f7e86350469508a7ffca 100644 (file)
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx1.h>
-
+#include "common.h"
 #include "devices-imx1.h"
+#include "hardware.h"
+#include "iomux-mx1.h"
 
 /*
  * This scb9328 has a 32MiB flash
index 39eb7960e2a425a7ff604427b23e337fb697caed..3aecf91e428988bb364c3b0e46558aa6337ede8a 100644 (file)
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/iomux-mx35.h>
-
 #include <linux/i2c.h>
 #include <linux/i2c/at24.h>
 #include <linux/mfd/mc13xxx.h>
 
+#include "common.h"
 #include "devices-imx35.h"
+#include "hardware.h"
+#include "iomux-mx35.h"
 
 #define GPIO_LCDPWR    IMX_GPIO_NR(1, 2)
 #define GPIO_PMIC_INT  IMX_GPIO_NR(2, 0)
index 6d60d51868bc83932667cd7488a364e0b3f9efb6..7a146671e65a8768572840b138da9a3987f8cb49 100644 (file)
 
 #include <asm/mach/map.h>
 
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-v1.h>
+#include "common.h"
+#include "devices/devices-common.h"
+#include "hardware.h"
+#include "iomux-v1.h"
 
 static struct map_desc imx_io_desc[] __initdata = {
        imx_map_entry(MX1, IO, MT_DEVICE),
@@ -58,5 +59,7 @@ void __init imx1_soc_init(void)
                                                MX1_GPIO_INT_PORTC, 0);
        mxc_register_gpio("imx1-gpio", 3, MX1_GPIO4_BASE_ADDR, SZ_256,
                                                MX1_GPIO_INT_PORTD, 0);
+       imx_add_imx_dma("imx1-dma", MX1_DMA_BASE_ADDR,
+                       MX1_DMA_INT, MX1_DMA_ERR);
        pinctrl_provide_dummies();
 }
index d056dad0940dd3688d785fb721d7ed13939afbe0..d8ccd3a8ec531bec988e6a90353148983d8d7713 100644 (file)
 #include <linux/mm.h>
 #include <linux/init.h>
 #include <linux/pinctrl/machine.h>
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/devices-common.h>
 #include <asm/pgtable.h>
 #include <asm/mach/map.h>
-#include <mach/iomux-v1.h>
+
+#include "common.h"
+#include "devices/devices-common.h"
+#include "hardware.h"
+#include "iomux-v1.h"
 
 /* MX21 memory map definition */
 static struct map_desc imx21_io_desc[] __initdata = {
@@ -81,6 +82,8 @@ static const struct resource imx21_audmux_res[] __initconst = {
 
 void __init imx21_soc_init(void)
 {
+       mxc_device_init();
+
        mxc_register_gpio("imx21-gpio", 0, MX21_GPIO1_BASE_ADDR, SZ_256, MX21_INT_GPIO, 0);
        mxc_register_gpio("imx21-gpio", 1, MX21_GPIO2_BASE_ADDR, SZ_256, MX21_INT_GPIO, 0);
        mxc_register_gpio("imx21-gpio", 2, MX21_GPIO3_BASE_ADDR, SZ_256, MX21_INT_GPIO, 0);
@@ -89,7 +92,8 @@ void __init imx21_soc_init(void)
        mxc_register_gpio("imx21-gpio", 5, MX21_GPIO6_BASE_ADDR, SZ_256, MX21_INT_GPIO, 0);
 
        pinctrl_provide_dummies();
-       imx_add_imx_dma();
+       imx_add_imx_dma("imx21-dma", MX21_DMA_BASE_ADDR,
+                       MX21_INT_DMACH0, 0); /* No ERR irq */
        platform_device_register_simple("imx21-audmux", 0, imx21_audmux_res,
                                        ARRAY_SIZE(imx21_audmux_res));
 }
index f3f5c6542ab4850beca756ea0168d0ed659a8c0b..9357707bb7afc4fa5bbb586fcf1ac6fcb8a9bfc0 100644 (file)
 #include <asm/pgtable.h>
 #include <asm/mach/map.h>
 
-#include <mach/common.h>
-#include <mach/devices-common.h>
-#include <mach/hardware.h>
-#include <mach/mx25.h>
-#include <mach/iomux-v3.h>
+#include "common.h"
+#include "devices/devices-common.h"
+#include "hardware.h"
+#include "iomux-v3.h"
+#include "mx25.h"
 
 /*
  * This table defines static virtual address mappings for I/O regions.
@@ -89,6 +89,8 @@ static const struct resource imx25_audmux_res[] __initconst = {
 
 void __init imx25_soc_init(void)
 {
+       mxc_device_init();
+
        /* i.mx25 has the i.mx35 type gpio */
        mxc_register_gpio("imx35-gpio", 0, MX25_GPIO1_BASE_ADDR, SZ_16K, MX25_INT_GPIO1, 0);
        mxc_register_gpio("imx35-gpio", 1, MX25_GPIO2_BASE_ADDR, SZ_16K, MX25_INT_GPIO2, 0);
index e7e24afc45edb6f83a7fbc9de56a13568a6d348a..4f1be65a7b5fe62a6531a09d70aa623283086d6b 100644 (file)
 #include <linux/mm.h>
 #include <linux/init.h>
 #include <linux/pinctrl/machine.h>
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/devices-common.h>
 #include <asm/pgtable.h>
 #include <asm/mach/map.h>
-#include <mach/iomux-v1.h>
+
+#include "common.h"
+#include "devices/devices-common.h"
+#include "hardware.h"
+#include "iomux-v1.h"
 
 /* MX27 memory map definition */
 static struct map_desc imx27_io_desc[] __initdata = {
@@ -81,6 +82,8 @@ static const struct resource imx27_audmux_res[] __initconst = {
 
 void __init imx27_soc_init(void)
 {
+       mxc_device_init();
+
        /* i.mx27 has the i.mx21 type gpio */
        mxc_register_gpio("imx21-gpio", 0, MX27_GPIO1_BASE_ADDR, SZ_256, MX27_INT_GPIO, 0);
        mxc_register_gpio("imx21-gpio", 1, MX27_GPIO2_BASE_ADDR, SZ_256, MX27_INT_GPIO, 0);
@@ -90,7 +93,8 @@ void __init imx27_soc_init(void)
        mxc_register_gpio("imx21-gpio", 5, MX27_GPIO6_BASE_ADDR, SZ_256, MX27_INT_GPIO, 0);
 
        pinctrl_provide_dummies();
-       imx_add_imx_dma();
+       imx_add_imx_dma("imx27-dma", MX27_DMA_BASE_ADDR,
+                       MX27_INT_DMACH0, 0); /* No ERR irq */
        /* imx27 has the imx21 type audmux */
        platform_device_register_simple("imx21-audmux", 0, imx27_audmux_res,
                                        ARRAY_SIZE(imx27_audmux_res));
index 9d2c843bde02438ccd79b2b5552397b97aeb1b65..f718bf5e964ab41e08a7f0616b8e9b73a2c83ff0 100644 (file)
 #include <asm/hardware/cache-l2x0.h>
 #include <asm/mach/map.h>
 
-#include <mach/common.h>
-#include <mach/devices-common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-v3.h>
-
+#include "common.h"
 #include "crmregs-imx3.h"
+#include "devices/devices-common.h"
+#include "hardware.h"
+#include "iomux-v3.h"
 
 void __iomem *mx3_ccm_base;
 
@@ -176,6 +175,8 @@ void __init imx31_soc_init(void)
 
        imx3_init_l2x0();
 
+       mxc_device_init();
+
        mxc_register_gpio("imx31-gpio", 0, MX31_GPIO1_BASE_ADDR, SZ_16K, MX31_INT_GPIO1, 0);
        mxc_register_gpio("imx31-gpio", 1, MX31_GPIO2_BASE_ADDR, SZ_16K, MX31_INT_GPIO2, 0);
        mxc_register_gpio("imx31-gpio", 2, MX31_GPIO3_BASE_ADDR, SZ_16K, MX31_INT_GPIO3, 0);
@@ -272,6 +273,8 @@ void __init imx35_soc_init(void)
 
        imx3_init_l2x0();
 
+       mxc_device_init();
+
        mxc_register_gpio("imx35-gpio", 0, MX35_GPIO1_BASE_ADDR, SZ_16K, MX35_INT_GPIO1, 0);
        mxc_register_gpio("imx35-gpio", 1, MX35_GPIO2_BASE_ADDR, SZ_16K, MX35_INT_GPIO2, 0);
        mxc_register_gpio("imx35-gpio", 2, MX35_GPIO3_BASE_ADDR, SZ_16K, MX35_INT_GPIO3, 0);
index acb0aadb425541baabff4dc82f7d6a0b34c8ad09..f92caf1b30bacc5a86bd05ba1320e01eaafed014 100644 (file)
 
 #include <asm/mach/map.h>
 
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/devices-common.h>
-#include <mach/iomux-v3.h>
+#include "common.h"
+#include "devices/devices-common.h"
+#include "hardware.h"
+#include "iomux-v3.h"
 
 /*
  * Define the MX50 memory map.
@@ -138,6 +138,8 @@ static const struct resource imx51_audmux_res[] __initconst = {
 
 void __init imx50_soc_init(void)
 {
+       mxc_device_init();
+
        /* i.mx50 has the i.mx35 type gpio */
        mxc_register_gpio("imx35-gpio", 0, MX50_GPIO1_BASE_ADDR, SZ_16K, MX50_INT_GPIO1_LOW, MX50_INT_GPIO1_HIGH);
        mxc_register_gpio("imx35-gpio", 1, MX50_GPIO2_BASE_ADDR, SZ_16K, MX50_INT_GPIO2_LOW, MX50_INT_GPIO2_HIGH);
@@ -153,6 +155,8 @@ void __init imx50_soc_init(void)
 
 void __init imx51_soc_init(void)
 {
+       mxc_device_init();
+
        /* i.mx51 has the i.mx35 type gpio */
        mxc_register_gpio("imx35-gpio", 0, MX51_GPIO1_BASE_ADDR, SZ_16K, MX51_INT_GPIO1_LOW, MX51_INT_GPIO1_HIGH);
        mxc_register_gpio("imx35-gpio", 1, MX51_GPIO2_BASE_ADDR, SZ_16K, MX51_INT_GPIO2_LOW, MX51_INT_GPIO2_HIGH);
index 29e890f92055ef697f72f0b32b3fb7009a9a1c68..d4361b80c5fba0c60d5436bbdd0401ffd97b9a3f 100644 (file)
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/iomux-mx3.h>
-#include <mach/board-mx31lilly.h>
-
+#include "board-mx31lilly.h"
+#include "common.h"
 #include "devices-imx31.h"
+#include "hardware.h"
+#include "iomux-mx3.h"
 
 /*
  * This file contains board-specific initialization routines for the
index 83d17d9e0bc8677fd62ef31949ef55c0b64e72e4..5a160b7e4fceb9232c6b2c2db5b1138b3377a232 100644 (file)
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/iomux-mx3.h>
-#include <mach/board-mx31lite.h>
-
+#include "board-mx31lite.h"
+#include "common.h"
 #include "devices-imx31.h"
+#include "hardware.h"
+#include "iomux-mx3.h"
 
 /*
  * This file contains board-specific initialization routines for the
index cc285e50728601e9a7a83e369a27d9768a520c99..52d5b1574721adf5b2e7518bc5bb62b236c6171c 100644 (file)
 
 #include <linux/usb/otg.h>
 
-#include <mach/common.h>
-#include <mach/iomux-mx3.h>
-#include <mach/hardware.h>
-#include <mach/ulpi.h>
-
+#include "common.h"
 #include "devices-imx31.h"
+#include "hardware.h"
+#include "iomux-mx3.h"
+#include "ulpi.h"
 
 static unsigned int devboard_pins[] = {
        /* UART1 */
index 135c90e3a45f15b4969d61d10b9ae60c7383e223..a4f43e90f3c12afe42b9db69f3b4f038838a133c 100644 (file)
 
 #include <linux/usb/otg.h>
 
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx3.h>
-#include <mach/ulpi.h>
-
 #include <media/soc_camera.h>
 
+#include "common.h"
 #include "devices-imx31.h"
+#include "hardware.h"
+#include "iomux-mx3.h"
+#include "ulpi.h"
 
 static unsigned int marxbot_pins[] = {
        /* SDHC2 */
index fabb801e799420ad269519b109821aa4f6a69b58..04ae45dbfaa724a3bae40d11a8e3106239069ae0 100644 (file)
 #include <linux/usb/otg.h>
 #include <linux/usb/ulpi.h>
 
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx3.h>
-#include <mach/board-mx31moboard.h>
-#include <mach/ulpi.h>
-
 #include <media/soc_camera.h>
 
+#include "board-mx31moboard.h"
+#include "common.h"
 #include "devices-imx31.h"
+#include "hardware.h"
+#include "iomux-mx3.h"
+#include "ulpi.h"
 
 static unsigned int smartbot_pins[] = {
        /* UART1 */
index 9917e2ff51da9bdd6cf74823044dfcd985faba02..51c608234089a689bce5c92276cccb4d3a8d9e74 100644 (file)
 
 #include <asm/mach/arch.h>
 
-#include <mach/common.h>
-#include <mach/iomux-mx27.h>
-#include <mach/hardware.h>
-
+#include "common.h"
 #include "devices-imx27.h"
+#include "hardware.h"
+#include "iomux-mx27.h"
 
 static const int pcm970_pins[] __initconst = {
        /* SDHC */
index 2ac43e1a2dfd0b2028d13702b63b654656f8ea7c..3777b805b76ba8645c50c41993f8ba06b550927d 100644 (file)
@@ -16,8 +16,9 @@
 #include <asm/smp_scu.h>
 #include <asm/hardware/gic.h>
 #include <asm/mach/map.h>
-#include <mach/common.h>
-#include <mach/hardware.h>
+
+#include "common.h"
+#include "hardware.h"
 
 static void __iomem *scu_base;
 
index 6fcffa7db978d4b025bf6eed72ea4b0b99c417c7..56d02d064fbf941c3b070cced2bf2f2e88a9056e 100644 (file)
@@ -10,7 +10,8 @@
 #include <linux/kernel.h>
 #include <linux/suspend.h>
 #include <linux/io.h>
-#include <mach/hardware.h>
+
+#include "hardware.h"
 
 static int mx27_suspend_enter(suspend_state_t state)
 {
index 822103bdb7092eab3ba63c3260f9da4f587abc2f..6a07006ff0f48136591ff0909636cd73b774bf08 100644 (file)
@@ -9,10 +9,11 @@
  * http://www.gnu.org/copyleft/gpl.html
  */
 #include <linux/io.h>
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/devices-common.h>
+
+#include "common.h"
 #include "crmregs-imx3.h"
+#include "devices/devices-common.h"
+#include "hardware.h"
 
 /*
  * Set cpu low power mode before WFI instruction. This function is called
index 19621ed1ffa5852900e2ab285e3ea1c2b4c1c357..2e063c2deb9e2078edbccdfb0a52fd8dca9c7284 100644 (file)
 #include <asm/cacheflush.h>
 #include <asm/system_misc.h>
 #include <asm/tlbflush.h>
-#include <mach/common.h>
-#include <mach/cpuidle.h>
-#include <mach/hardware.h>
+
+#include "common.h"
+#include "cpuidle.h"
 #include "crm-regs-imx5.h"
+#include "hardware.h"
 
 /*
  * The WAIT_UNCLOCKED_POWER_OFF state only requires <= 500ns to exit.
index f7b0c2b1b90529849050dc45243b75f4bb4d0e68..a17543da602da4d8c5504961434bba5bfa2551b2 100644 (file)
@@ -18,8 +18,9 @@
 #include <asm/proc-fns.h>
 #include <asm/suspend.h>
 #include <asm/hardware/cache-l2x0.h>
-#include <mach/common.h>
-#include <mach/hardware.h>
+
+#include "common.h"
+#include "hardware.h"
 
 extern unsigned long phys_l2x0_saved_regs;
 
similarity index 97%
rename from arch/arm/plat-mxc/system.c
rename to arch/arm/mach-imx/system.c
index 3da78cfc5a94b6563d8276a0daa149edd3d9f954..695e0d73bf85e12308f878bcbfd322280b67ba76 100644 (file)
 #include <linux/err.h>
 #include <linux/delay.h>
 
-#include <mach/hardware.h>
-#include <mach/common.h>
 #include <asm/system_misc.h>
 #include <asm/proc-fns.h>
 #include <asm/mach-types.h>
 
+#include "common.h"
+#include "hardware.h"
+
 static void __iomem *wdog_base;
 
 /*
similarity index 99%
rename from arch/arm/plat-mxc/time.c
rename to arch/arm/mach-imx/time.c
index a17abcf983259064ff2a87664d81d3610b6ef3b1..f017302f6d09c94d5d97d4d63f47311d8ace4e7a 100644 (file)
 #include <linux/clk.h>
 #include <linux/err.h>
 
-#include <mach/hardware.h>
 #include <asm/sched_clock.h>
 #include <asm/mach/time.h>
-#include <mach/common.h>
+
+#include "common.h"
+#include "hardware.h"
 
 /*
  * There are 2 versions of the timer hardware on Freescale MXC hardware.
similarity index 98%
rename from arch/arm/plat-mxc/tzic.c
rename to arch/arm/mach-imx/tzic.c
index 3ed1adbc09f882bbafc0fe35fee22467a96734f8..9721161f208f10a0d8e65bd9ad69d762e8b85228 100644 (file)
 #include <asm/mach/irq.h>
 #include <asm/exception.h>
 
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/irqs.h>
-
+#include "common.h"
+#include "hardware.h"
 #include "irq-common.h"
 
 /*
similarity index 99%
rename from arch/arm/plat-mxc/ulpi.c
rename to arch/arm/mach-imx/ulpi.c
index d2963427184f64ae942ad7e02a70ea4cf27addc9..0f051957d10cf0ebc6cdc2c9e5102ffc672c4bda 100644 (file)
@@ -24,7 +24,7 @@
 #include <linux/usb/otg.h>
 #include <linux/usb/ulpi.h>
 
-#include <mach/ulpi.h>
+#include "ulpi.h"
 
 /* ULPIVIEW register bits */
 #define ULPIVW_WU              (1 << 31)       /* Wakeup */
index 1694f01ce2b6782deeb09c02b0ba1a5b4ade0918..6d6bde3e15fad4e4cf094a22c6ae6b8837a1580f 100644 (file)
@@ -410,6 +410,7 @@ void __init ixp4xx_pci_preinit(void)
                 * Enable the IO window to be way up high, at 0xfffffc00
                 */
                local_write_config(PCI_BASE_ADDRESS_5, 4, 0xfffffc01);
+               local_write_config(0x40, 4, 0x000080FF); /* No TRDY time limit */
        } else {
                printk("PCI: IXP4xx is target - No bus scan performed\n");
        }
index fdf91a160884407816d2ceb4fa577e1a9de97054..8c0c0e2d0727317078a93f2241763818acf1ac15 100644 (file)
@@ -67,15 +67,12 @@ static struct map_desc ixp4xx_io_desc[] __initdata = {
                .pfn            = __phys_to_pfn(IXP4XX_PCI_CFG_BASE_PHYS),
                .length         = IXP4XX_PCI_CFG_REGION_SIZE,
                .type           = MT_DEVICE
-       },
-#ifdef CONFIG_DEBUG_LL
-       {       /* Debug UART mapping */
-               .virtual        = (unsigned long)IXP4XX_DEBUG_UART_BASE_VIRT,
-               .pfn            = __phys_to_pfn(IXP4XX_DEBUG_UART_BASE_PHYS),
-               .length         = IXP4XX_DEBUG_UART_REGION_SIZE,
+       }, {    /* Queue Manager */
+               .virtual        = (unsigned long)IXP4XX_QMGR_BASE_VIRT,
+               .pfn            = __phys_to_pfn(IXP4XX_QMGR_BASE_PHYS),
+               .length         = IXP4XX_QMGR_REGION_SIZE,
                .type           = MT_DEVICE
-       }
-#endif
+       },
 };
 
 void __init ixp4xx_map_io(void)
index b800a031207c9db0eaaff139fb367b68374420f8..53b8348dfcc279c19fed814ac4f1d19afdafe5b6 100644 (file)
@@ -15,6 +15,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/flash.h>
 #include <asm/mach/pci.h>
+#include <asm/system_info.h>
 
 #define SLOT_ETHA              0x0B    /* IDSEL = AD21 */
 #define SLOT_ETHB              0x0C    /* IDSEL = AD20 */
@@ -329,7 +330,7 @@ static struct platform_device device_hss_tab[] = {
 };
 
 
-static struct platform_device *device_tab[6] __initdata = {
+static struct platform_device *device_tab[7] __initdata = {
        &device_flash,          /* index 0 */
 };
 
index 8c9f8d56449231c26f6c24ff74df7268063f6c77..ff686cbc5df44d54547b4816588fe808a5bdd424 100644 (file)
@@ -17,8 +17,8 @@
 #else
                mov     \rp, #0
 #endif
-                orr     \rv, \rp, #0xff000000  @ virtual
-               orr     \rv, \rv, #0x00b00000
+               orr     \rv, \rp, #0xfe000000   @ virtual
+               orr     \rv, \rv, #0x00f00000
                 orr     \rp, \rp, #0xc8000000  @ physical
                 .endm
 
index eb68b61ce975cdff4e96e0a411edec96832b8b2f..c5bae9c035d533e1bd1bba3246bf766e8a53c447 100644 (file)
  *
  * 0x50000000  0x10000000      ioremap'd       EXP BUS
  *
- * 0x6000000   0x00004000      ioremap'd       QMgr
+ * 0xC8000000  0x00013000      0xFEF00000      On-Chip Peripherals
  *
- * 0xC0000000  0x00001000      0xffbff000      PCI CFG
+ * 0xC0000000  0x00001000      0xFEF13000      PCI CFG
  *
- * 0xC4000000  0x00001000      0xffbfe000      EXP CFG
+ * 0xC4000000  0x00001000      0xFEF14000      EXP CFG
  *
- * 0xC8000000  0x00013000      0xffbeb000      On-Chip Peripherals
+ * 0x60000000  0x00004000      0xFEF15000      QMgr
  */
 
 /*
  * Queue Manager
  */
-#define IXP4XX_QMGR_BASE_PHYS          (0x60000000)
-#define IXP4XX_QMGR_REGION_SIZE                (0x00004000)
+#define IXP4XX_QMGR_BASE_PHYS          0x60000000
+#define IXP4XX_QMGR_BASE_VIRT          IOMEM(0xFEF15000)
+#define IXP4XX_QMGR_REGION_SIZE                0x00004000
 
 /*
- * Expansion BUS Configuration registers
+ * Peripheral space, including debug UART. Must be section-aligned so that
+ * it can be used with the low-level debug code.
  */
-#define IXP4XX_EXP_CFG_BASE_PHYS       (0xC4000000)
-#define IXP4XX_EXP_CFG_BASE_VIRT       IOMEM(0xFFBFE000)
-#define IXP4XX_EXP_CFG_REGION_SIZE     (0x00001000)
+#define IXP4XX_PERIPHERAL_BASE_PHYS    0xC8000000
+#define IXP4XX_PERIPHERAL_BASE_VIRT    IOMEM(0xFEF00000)
+#define IXP4XX_PERIPHERAL_REGION_SIZE  0x00013000
 
 /*
  * PCI Config registers
  */
-#define IXP4XX_PCI_CFG_BASE_PHYS       (0xC0000000)
-#define        IXP4XX_PCI_CFG_BASE_VIRT        IOMEM(0xFFBFF000)
-#define IXP4XX_PCI_CFG_REGION_SIZE     (0x00001000)
-
-/*
- * Peripheral space
- */
-#define IXP4XX_PERIPHERAL_BASE_PHYS    (0xC8000000)
-#define IXP4XX_PERIPHERAL_BASE_VIRT    IOMEM(0xFFBEB000)
-#define IXP4XX_PERIPHERAL_REGION_SIZE  (0x00013000)
+#define IXP4XX_PCI_CFG_BASE_PHYS       0xC0000000
+#define IXP4XX_PCI_CFG_BASE_VIRT       IOMEM(0xFEF13000)
+#define IXP4XX_PCI_CFG_REGION_SIZE     0x00001000
 
 /*
- * Debug UART
- *
- * This is basically a remap of UART1 into a region that is section
- * aligned so that it * can be used with the low-level debug code.
+ * Expansion BUS Configuration registers
  */
-#define        IXP4XX_DEBUG_UART_BASE_PHYS     (0xC8000000)
-#define        IXP4XX_DEBUG_UART_BASE_VIRT     IOMEM(0xffb00000)
-#define        IXP4XX_DEBUG_UART_REGION_SIZE   (0x00001000)
+#define IXP4XX_EXP_CFG_BASE_PHYS       0xC4000000
+#define IXP4XX_EXP_CFG_BASE_VIRT       0xFEF14000
+#define IXP4XX_EXP_CFG_REGION_SIZE     0x00001000
 
 #define IXP4XX_EXP_CS0_OFFSET  0x00
 #define IXP4XX_EXP_CS1_OFFSET   0x04
index 9e7cad2d54cb9e9add09c676378e7956b6d70b71..4de8da536dbb2aa11cc0e0ad03d00090fe31e7bb 100644 (file)
@@ -86,7 +86,7 @@ void qmgr_release_queue(unsigned int queue);
 
 static inline void qmgr_put_entry(unsigned int queue, u32 val)
 {
-       extern struct qmgr_regs __iomem *qmgr_regs;
+       struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT;
 #if DEBUG_QMGR
        BUG_ON(!qmgr_queue_descs[queue]); /* not yet requested */
 
@@ -99,7 +99,7 @@ static inline void qmgr_put_entry(unsigned int queue, u32 val)
 static inline u32 qmgr_get_entry(unsigned int queue)
 {
        u32 val;
-       extern struct qmgr_regs __iomem *qmgr_regs;
+       const struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT;
        val = __raw_readl(&qmgr_regs->acc[queue][0]);
 #if DEBUG_QMGR
        BUG_ON(!qmgr_queue_descs[queue]); /* not yet requested */
@@ -112,14 +112,14 @@ static inline u32 qmgr_get_entry(unsigned int queue)
 
 static inline int __qmgr_get_stat1(unsigned int queue)
 {
-       extern struct qmgr_regs __iomem *qmgr_regs;
+       const struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT;
        return (__raw_readl(&qmgr_regs->stat1[queue >> 3])
                >> ((queue & 7) << 2)) & 0xF;
 }
 
 static inline int __qmgr_get_stat2(unsigned int queue)
 {
-       extern struct qmgr_regs __iomem *qmgr_regs;
+       const struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT;
        BUG_ON(queue >= HALF_QUEUES);
        return (__raw_readl(&qmgr_regs->stat2[queue >> 4])
                >> ((queue & 0xF) << 1)) & 0x3;
@@ -145,7 +145,7 @@ static inline int qmgr_stat_empty(unsigned int queue)
  */
 static inline int qmgr_stat_below_low_watermark(unsigned int queue)
 {
-       extern struct qmgr_regs __iomem *qmgr_regs;
+       const struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT;
        if (queue >= HALF_QUEUES)
                return (__raw_readl(&qmgr_regs->statne_h) >>
                        (queue - HALF_QUEUES)) & 0x01;
@@ -172,7 +172,7 @@ static inline int qmgr_stat_above_high_watermark(unsigned int queue)
  */
 static inline int qmgr_stat_full(unsigned int queue)
 {
-       extern struct qmgr_regs __iomem *qmgr_regs;
+       const struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT;
        if (queue >= HALF_QUEUES)
                return (__raw_readl(&qmgr_regs->statf_h) >>
                        (queue - HALF_QUEUES)) & 0x01;
index a17ed79207a4fce30f67b405f758cd07b23f85ad..d4eb09a62863639ebb8205e2d203d4c9d089462f 100644 (file)
 /* NPE mailbox_status value for reset */
 #define RESET_MBOX_STAT                        0x0000F0F0
 
-const char *npe_names[] = { "NPE-A", "NPE-B", "NPE-C" };
+#define NPE_A_FIRMWARE "NPE-A"
+#define NPE_B_FIRMWARE "NPE-B"
+#define NPE_C_FIRMWARE "NPE-C"
+
+const char *npe_names[] = { NPE_A_FIRMWARE, NPE_B_FIRMWARE, NPE_C_FIRMWARE };
 
 #define print_npe(pri, npe, fmt, ...)                                  \
        printk(pri "%s: " fmt, npe_name(npe), ## __VA_ARGS__)
@@ -724,6 +728,9 @@ module_exit(npe_cleanup_module);
 
 MODULE_AUTHOR("Krzysztof Halasa");
 MODULE_LICENSE("GPL v2");
+MODULE_FIRMWARE(NPE_A_FIRMWARE);
+MODULE_FIRMWARE(NPE_B_FIRMWARE);
+MODULE_FIRMWARE(NPE_C_FIRMWARE);
 
 EXPORT_SYMBOL(npe_names);
 EXPORT_SYMBOL(npe_running);
index 852f7c9f87d06ff69c6defde901732a3926aea7d..9d1b6b7c394cfb5eb5ef2968065f97b5f2b875a7 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/module.h>
 #include <mach/qmgr.h>
 
-struct qmgr_regs __iomem *qmgr_regs;
+static struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT;
 static struct resource *mem_res;
 static spinlock_t qmgr_lock;
 static u32 used_sram_bitmap[4]; /* 128 16-dword pages */
@@ -293,12 +293,6 @@ static int qmgr_init(void)
        if (mem_res == NULL)
                return -EBUSY;
 
-       qmgr_regs = ioremap(IXP4XX_QMGR_BASE_PHYS, IXP4XX_QMGR_REGION_SIZE);
-       if (qmgr_regs == NULL) {
-               err = -ENOMEM;
-               goto error_map;
-       }
-
        /* reset qmgr registers */
        for (i = 0; i < 4; i++) {
                __raw_writel(0x33333333, &qmgr_regs->stat1[i]);
@@ -347,8 +341,6 @@ static int qmgr_init(void)
 error_irq2:
        free_irq(IRQ_IXP4XX_QM1, NULL);
 error_irq:
-       iounmap(qmgr_regs);
-error_map:
        release_mem_region(IXP4XX_QMGR_BASE_PHYS, IXP4XX_QMGR_REGION_SIZE);
        return err;
 }
@@ -359,7 +351,6 @@ static void qmgr_remove(void)
        free_irq(IRQ_IXP4XX_QM2, NULL);
        synchronize_irq(IRQ_IXP4XX_QM1);
        synchronize_irq(IRQ_IXP4XX_QM2);
-       iounmap(qmgr_regs);
        release_mem_region(IXP4XX_QMGR_BASE_PHYS, IXP4XX_QMGR_REGION_SIZE);
 }
 
@@ -369,7 +360,6 @@ module_exit(qmgr_remove);
 MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Krzysztof Halasa");
 
-EXPORT_SYMBOL(qmgr_regs);
 EXPORT_SYMBOL(qmgr_set_irq);
 EXPORT_SYMBOL(qmgr_enable_irq);
 EXPORT_SYMBOL(qmgr_disable_irq);
index 70c5a28824093f675880aab0c5c595206ac7e1d6..d94872fed8c0cb2a5529260cb2ceca68d1c75a14 100644 (file)
@@ -51,9 +51,7 @@ static void __init kirkwood_dt_init(void)
 
        kirkwood_setup_cpu_mbus();
 
-#ifdef CONFIG_CACHE_FEROCEON_L2
        kirkwood_l2_init();
-#endif
 
        /* Setup root of clk tree */
        kirkwood_clk_init();
index 3991077f58a26aa5f3a77c2ff005e7c7838a1edb..2c6c218fb79e217cf607da9ad510ac7dece3222f 100644 (file)
@@ -633,6 +633,7 @@ char * __init kirkwood_id(void)
 
 void __init kirkwood_l2_init(void)
 {
+#ifdef CONFIG_CACHE_FEROCEON_L2
 #ifdef CONFIG_CACHE_FEROCEON_L2_WRITETHROUGH
        writel(readl(L2_CONFIG_REG) | L2_WRITETHROUGH, L2_CONFIG_REG);
        feroceon_l2_init(1);
@@ -640,6 +641,7 @@ void __init kirkwood_l2_init(void)
        writel(readl(L2_CONFIG_REG) & ~L2_WRITETHROUGH, L2_CONFIG_REG);
        feroceon_l2_init(0);
 #endif
+#endif
 }
 
 void __init kirkwood_init(void)
@@ -657,9 +659,7 @@ void __init kirkwood_init(void)
 
        kirkwood_setup_cpu_mbus();
 
-#ifdef CONFIG_CACHE_FEROCEON_L2
        kirkwood_l2_init();
-#endif
 
        /* Setup root of clk tree */
        kirkwood_clk_init();
index bfa1eab91f4142cecb3bdd1ce4c4ec1b8e9a9698..ab7104fded399c60f3e7a780e150ed2f4e03be58 100644 (file)
 #include <linux/gpio.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
+#include <linux/mtd/fsmc.h>
 #include <linux/mtd/onenand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/i2c.h>
 #include <linux/io.h>
 #include <linux/pinctrl/machine.h>
+#include <linux/platform_data/pinctrl-nomadik.h>
 #include <asm/hardware/vic.h>
 #include <asm/sizes.h>
 #include <asm/mach-types.h>
 #include <asm/mach/flash.h>
 #include <asm/mach/time.h>
 
-#include <plat/gpio-nomadik.h>
 #include <plat/mtu.h>
-#include <plat/pincfg.h>
-
-#include <linux/platform_data/mtd-nomadik-nand.h>
-#include <mach/fsmc.h>
 
 #include "cpu-8815.h"
 
 #define SRC_CR_INIT_MASK       0x00007fff
 #define SRC_CR_INIT_VAL                0x2aaa8000
 
+#define ALE_OFF 0x1000000
+#define CLE_OFF 0x800000
+
 /* These addresses span 16MB, so use three individual pages */
 static struct resource nhk8815_nand_resources[] = {
        {
+               .name = "nand_data",
+               .start = 0x40000000,
+               .end = 0x40000000 + SZ_16K - 1,
+               .flags = IORESOURCE_MEM,
+       }, {
                .name = "nand_addr",
-               .start = NAND_IO_ADDR,
-               .end = NAND_IO_ADDR + 0xfff,
+               .start = 0x40000000 + ALE_OFF,
+               .end = 0x40000000 +ALE_OFF + SZ_16K - 1,
                .flags = IORESOURCE_MEM,
        }, {
                .name = "nand_cmd",
-               .start = NAND_IO_CMD,
-               .end = NAND_IO_CMD + 0xfff,
+               .start = 0x40000000 + CLE_OFF,
+               .end = 0x40000000 + CLE_OFF + SZ_16K - 1,
                .flags = IORESOURCE_MEM,
        }, {
-               .name = "nand_data",
-               .start = NAND_IO_DATA,
-               .end = NAND_IO_DATA + 0xfff,
+               .name  = "fsmc_regs",
+               .start = NOMADIK_FSMC_BASE,
+               .end   = NOMADIK_FSMC_BASE + SZ_4K - 1,
                .flags = IORESOURCE_MEM,
-       }
+       },
 };
 
-static int nhk8815_nand_init(void)
-{
-       /* FSMC setup for nand chip select (8-bit nand in 8815NHK) */
-       writel(0x0000000E, FSMC_PCR(0));
-       writel(0x000D0A00, FSMC_PMEM(0));
-       writel(0x00100A00, FSMC_PATT(0));
-
-       /* enable access to the chip select area */
-       writel(readl(FSMC_PCR(0)) | 0x04, FSMC_PCR(0));
-
-       return 0;
-}
-
 /*
  * These partitions are the same as those used in the 2.6.20 release
  * shipped by the vendor; the first two partitions are mandated
@@ -111,20 +103,28 @@ static struct mtd_partition nhk8815_partitions[] = {
        }
 };
 
-static struct nomadik_nand_platform_data nhk8815_nand_data = {
-       .parts          = nhk8815_partitions,
-       .nparts         = ARRAY_SIZE(nhk8815_partitions),
-       .options        = NAND_COPYBACK | NAND_CACHEPRG | NAND_NO_PADDING,
-       .init           = nhk8815_nand_init,
+static struct fsmc_nand_timings nhk8815_nand_timings = {
+       .thiz   = 0,
+       .thold  = 0x10,
+       .twait  = 0x0A,
+       .tset   = 0,
+};
+
+static struct fsmc_nand_platform_data nhk8815_nand_platform_data = {
+       .nand_timings = &nhk8815_nand_timings,
+       .partitions = nhk8815_partitions,
+       .nr_partitions = ARRAY_SIZE(nhk8815_partitions),
+       .width = FSMC_NAND_BW8,
 };
 
 static struct platform_device nhk8815_nand_device = {
-       .name           = "nomadik_nand",
-       .dev            = {
-               .platform_data = &nhk8815_nand_data,
+       .name = "fsmc-nand",
+       .id = -1,
+       .resource = nhk8815_nand_resources,
+       .num_resources = ARRAY_SIZE(nhk8815_nand_resources),
+       .dev = {
+               .platform_data = &nhk8815_nand_platform_data,
        },
-       .resource       = nhk8815_nand_resources,
-       .num_resources  = ARRAY_SIZE(nhk8815_nand_resources),
 };
 
 /* These are the partitions for the OneNand device, different from above */
@@ -179,6 +179,10 @@ static struct platform_device nhk8815_onenand_device = {
        .num_resources  = ARRAY_SIZE(nhk8815_onenand_resource),
 };
 
+/* bus control reg. and bus timing reg. for CS0..CS3 */
+#define FSMC_BCR(x)    (NOMADIK_FSMC_VA + (x << 3))
+#define FSMC_BTR(x)    (NOMADIK_FSMC_VA + (x << 3) + 0x04)
+
 static void __init nhk8815_onenand_init(void)
 {
 #ifdef CONFIG_MTD_ONENAND
index b617eaed0ce58695ac709b460ac29b8ac2d4b1d6..1273931303fb81599201ae0f70c1c71f503b9eda 100644 (file)
@@ -26,8 +26,8 @@
 #include <linux/irq.h>
 #include <linux/dma-mapping.h>
 #include <linux/platform_data/clk-nomadik.h>
+#include <linux/platform_data/pinctrl-nomadik.h>
 
-#include <plat/gpio-nomadik.h>
 #include <mach/hardware.h>
 #include <mach/irqs.h>
 #include <asm/mach/map.h>
index 6d14454d46094fc4bdd00c66cabff3a0abb800f9..0c2f6628299aa6bc2a7c95b567ff56344dd7df87 100644 (file)
@@ -4,8 +4,7 @@
 #include <linux/i2c-algo-bit.h>
 #include <linux/i2c-gpio.h>
 #include <linux/platform_device.h>
-#include <plat/gpio-nomadik.h>
-#include <plat/pincfg.h>
+#include <linux/platform_data/pinctrl-nomadik.h>
 
 /*
  * There are two busses in the 8815NHK.
diff --git a/arch/arm/mach-nomadik/include/mach/fsmc.h b/arch/arm/mach-nomadik/include/mach/fsmc.h
deleted file mode 100644 (file)
index 8c2c051..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-
-/* Definitions for the Nomadik FSMC "Flexible Static Memory controller" */
-
-#ifndef __ASM_ARCH_FSMC_H
-#define __ASM_ARCH_FSMC_H
-
-#include <mach/hardware.h>
-/*
- * Register list
- */
-
-/* bus control reg. and bus timing reg. for CS0..CS3 */
-#define FSMC_BCR(x)     (NOMADIK_FSMC_VA + (x << 3))
-#define FSMC_BTR(x)     (NOMADIK_FSMC_VA + (x << 3) + 0x04)
-
-/* PC-card and NAND:
- * PCR = control register
- * PMEM = memory timing
- * PATT = attribute timing
- * PIO = I/O timing
- * PECCR = ECC result
- */
-#define FSMC_PCR(x)     (NOMADIK_FSMC_VA + ((2 + x) << 5) + 0x00)
-#define FSMC_PMEM(x)    (NOMADIK_FSMC_VA + ((2 + x) << 5) + 0x08)
-#define FSMC_PATT(x)    (NOMADIK_FSMC_VA + ((2 + x) << 5) + 0x0c)
-#define FSMC_PIO(x)     (NOMADIK_FSMC_VA + ((2 + x) << 5) + 0x10)
-#define FSMC_PECCR(x)   (NOMADIK_FSMC_VA + ((2 + x) << 5) + 0x14)
-
-#endif /* __ASM_ARCH_FSMC_H */
index d661d138f27057d2dcc2130d741f6c0fa53bcb9d..6efc30c961a5806dbecff3fb595bab1abfbc9082 100644 (file)
@@ -3294,7 +3294,7 @@ static struct omap_clk omap44xx_clks[] = {
        CLK(NULL,       "auxclk5_src_ck",               &auxclk5_src_ck,        CK_443X),
        CLK(NULL,       "auxclk5_ck",                   &auxclk5_ck,    CK_443X),
        CLK(NULL,       "auxclkreq5_ck",                &auxclkreq5_ck, CK_443X),
-       CLK(NULL,       "gpmc_ck",                      &dummy_ck,      CK_443X),
+       CLK("omap-gpmc",        "fck",                          &dummy_ck,      CK_443X),
        CLK("omap_i2c.1",       "ick",                          &dummy_ck,      CK_443X),
        CLK("omap_i2c.2",       "ick",                          &dummy_ck,      CK_443X),
        CLK("omap_i2c.3",       "ick",                          &dummy_ck,      CK_443X),
index cbb879139c51fd915c7ea50d00a6e91ad730d8b3..512e79a842cb94760eddcf6223363511f08bac8c 100644 (file)
@@ -925,15 +925,18 @@ static int _clkdm_clk_hwmod_enable(struct clockdomain *clkdm)
        if (!clkdm || !arch_clkdm || !arch_clkdm->clkdm_clk_enable)
                return -EINVAL;
 
+       spin_lock_irqsave(&clkdm->lock, flags);
+
        /*
         * For arch's with no autodeps, clkcm_clk_enable
         * should be called for every clock instance or hwmod that is
         * enabled, so the clkdm can be force woken up.
         */
-       if ((atomic_inc_return(&clkdm->usecount) > 1) && autodeps)
+       if ((atomic_inc_return(&clkdm->usecount) > 1) && autodeps) {
+               spin_unlock_irqrestore(&clkdm->lock, flags);
                return 0;
+       }
 
-       spin_lock_irqsave(&clkdm->lock, flags);
        arch_clkdm->clkdm_clk_enable(clkdm);
        pwrdm_state_switch(clkdm->pwrdm.ptr);
        spin_unlock_irqrestore(&clkdm->lock, flags);
@@ -950,15 +953,19 @@ static int _clkdm_clk_hwmod_disable(struct clockdomain *clkdm)
        if (!clkdm || !arch_clkdm || !arch_clkdm->clkdm_clk_disable)
                return -EINVAL;
 
+       spin_lock_irqsave(&clkdm->lock, flags);
+
        if (atomic_read(&clkdm->usecount) == 0) {
+               spin_unlock_irqrestore(&clkdm->lock, flags);
                WARN_ON(1); /* underflow */
                return -ERANGE;
        }
 
-       if (atomic_dec_return(&clkdm->usecount) > 0)
+       if (atomic_dec_return(&clkdm->usecount) > 0) {
+               spin_unlock_irqrestore(&clkdm->lock, flags);
                return 0;
+       }
 
-       spin_lock_irqsave(&clkdm->lock, flags);
        arch_clkdm->clkdm_clk_disable(clkdm);
        pwrdm_state_switch(clkdm->pwrdm.ptr);
        spin_unlock_irqrestore(&clkdm->lock, flags);
index c8c211731d267a233b7b8ac56cd042f472d46985..cba60e05e32ecef6a6c97cbf6679b99f474d4a5a 100644 (file)
@@ -341,7 +341,7 @@ static void __init omap_init_dmic(void)
 
        oh = omap_hwmod_lookup("dmic");
        if (!oh) {
-               printk(KERN_ERR "Could not look up mcpdm hw_mod\n");
+               pr_err("Could not look up dmic hw_mod\n");
                return;
        }
 
index 5ac5cf30406a81aef651ae361bab6351903d4c3e..92b5718fa722ce129b240245fa5e60978bc77ffb 100644 (file)
@@ -868,9 +868,9 @@ static void __devexit gpmc_mem_exit(void)
 
 }
 
-static void __devinit gpmc_mem_init(void)
+static int __devinit gpmc_mem_init(void)
 {
-       int cs;
+       int cs, rc;
        unsigned long boot_rom_space = 0;
 
        /* never allocate the first page, to facilitate bug detection;
@@ -890,13 +890,21 @@ static void __devinit gpmc_mem_init(void)
                if (!gpmc_cs_mem_enabled(cs))
                        continue;
                gpmc_cs_get_memconf(cs, &base, &size);
-               if (gpmc_cs_insert_mem(cs, base, size) < 0)
-                       BUG();
+               rc = gpmc_cs_insert_mem(cs, base, size);
+               if (IS_ERR_VALUE(rc)) {
+                       while (--cs >= 0)
+                               if (gpmc_cs_mem_enabled(cs))
+                                       gpmc_cs_delete_mem(cs);
+                       return rc;
+               }
        }
+
+       return 0;
 }
 
 static __devinit int gpmc_probe(struct platform_device *pdev)
 {
+       int rc;
        u32 l;
        struct resource *res;
 
@@ -936,7 +944,13 @@ static __devinit int gpmc_probe(struct platform_device *pdev)
        dev_info(gpmc_dev, "GPMC revision %d.%d\n", GPMC_REVISION_MAJOR(l),
                 GPMC_REVISION_MINOR(l));
 
-       gpmc_mem_init();
+       rc = gpmc_mem_init();
+       if (IS_ERR_VALUE(rc)) {
+               clk_disable_unprepare(gpmc_l3_clk);
+               clk_put(gpmc_l3_clk);
+               dev_err(gpmc_dev, "failed to reserve memory\n");
+               return rc;
+       }
 
        if (IS_ERR_VALUE(gpmc_setup_irq()))
                dev_warn(gpmc_dev, "gpmc_setup_irq failed\n");
index 44f9aa7ec0c0a63e089137342accb6a52ab48ef7..69e46631a7cdc45142af9909d52c40b8e84286a3 100644 (file)
@@ -467,7 +467,7 @@ OMAP_SYS_TIMER(3_am33xx)
 #ifdef CONFIG_ARCH_OMAP4
 #ifdef CONFIG_LOCAL_TIMERS
 static DEFINE_TWD_LOCAL_TIMER(twd_local_timer,
-                             OMAP44XX_LOCAL_TWD_BASE, 29 + OMAP_INTC_START);
+                             OMAP44XX_LOCAL_TWD_BASE, 29);
 #endif
 
 static void __init omap4_timer_init(void)
index 749220f91a7079e8a4a1e65561189497e9743c36..4407b17305396267b56d407f3ae80fb3dd4ef8b4 100644 (file)
@@ -163,7 +163,7 @@ static struct clk_lookup s3c2440_clk_lookup[] = {
        CLKDEV_INIT(NULL, "clk_uart_baud3", &s3c2440_clk_fclk_n),
 };
 
-static int s3c2440_clk_add(struct device *dev, struct subsys_interface *sif)
+static int __init_refok s3c2440_clk_add(struct device *dev, struct subsys_interface *sif)
 {
        struct clk *clock_upll;
        struct clk *clock_h;
index ed5a95ece9eb2d365b7152cdb4bd5cfe508e672b..77ee0b732237d93de59c80632279a00dbf5dc2bd 100644 (file)
@@ -61,6 +61,7 @@
 #include <plat/nand-core.h>
 #include <plat/adc-core.h>
 #include <plat/rtc-core.h>
+#include <plat/spi-core.h>
 
 static struct map_desc s3c2416_iodesc[] __initdata = {
        IODESC_ENT(WATCHDOG),
@@ -132,6 +133,7 @@ void __init s3c2416_map_io(void)
        /* initialize device information early */
        s3c2416_default_sdhci0();
        s3c2416_default_sdhci1();
+       s3c64xx_spi_setname("s3c2443-spi");
 
        iotable_init(s3c2416_iodesc, ARRAY_SIZE(s3c2416_iodesc));
 }
index ab648ad8fa508651624054ca2d9693f9d34fb1e5..165b6a6b3daaa9450201db7b0c721f76c62574f2 100644 (file)
@@ -43,6 +43,7 @@
 #include <plat/nand-core.h>
 #include <plat/adc-core.h>
 #include <plat/rtc-core.h>
+#include <plat/spi-core.h>
 
 static struct map_desc s3c2443_iodesc[] __initdata = {
        IODESC_ENT(WATCHDOG),
@@ -100,6 +101,9 @@ void __init s3c2443_map_io(void)
        s3c24xx_gpiocfg_default.set_pull = s3c2443_gpio_setpull;
        s3c24xx_gpiocfg_default.get_pull = s3c2443_gpio_getpull;
 
+       /* initialize device information early */
+       s3c64xx_spi_setname("s3c2443-spi");
+
        iotable_init(s3c2443_iodesc, ARRAY_SIZE(s3c2443_iodesc));
 }
 
index 4e3fe57674c8b2cc1b93599fbef6c9563db211c6..4744c42ebdf514099e8f37b654ae625a3da21ba8 100644 (file)
@@ -20,6 +20,8 @@
 
 #include <linux/regulator/machine.h>
 
+#include <sound/wm0010.h>
+#include <sound/wm2200.h>
 #include <sound/wm5100.h>
 #include <sound/wm8996.h>
 #include <sound/wm8962.h>
@@ -33,14 +35,34 @@ static struct s3c64xx_spi_csinfo wm0010_spi_csinfo = {
        .line = S3C64XX_GPC(3),
 };
 
+static struct wm0010_pdata wm0010_pdata = {
+       .gpio_reset = S3C64XX_GPN(6),
+       .reset_active_high = 1, /* Active high for Glenfarclas Rev 2 */
+};
+
 static struct spi_board_info wm1253_devs[] = {
        [0] = {
                .modalias       = "wm0010",
+               .max_speed_hz   = 26 * 1000 * 1000,
                .bus_num        = 0,
                .chip_select    = 0,
                .mode           = SPI_MODE_0,
                .irq            = S3C_EINT(5),
                .controller_data = &wm0010_spi_csinfo,
+               .platform_data = &wm0010_pdata,
+       },
+};
+
+static struct spi_board_info balblair_devs[] = {
+       [0] = {
+               .modalias       = "wm0010",
+               .max_speed_hz   = 26 * 1000 * 1000,
+               .bus_num        = 0,
+               .chip_select    = 0,
+               .mode           = SPI_MODE_0,
+               .irq            = S3C_EINT(5),
+               .controller_data = &wm0010_spi_csinfo,
+               .platform_data = &wm0010_pdata,
        },
 };
 
@@ -166,12 +188,13 @@ static struct regulator_init_data wm8994_ldo2 = {
 
 static struct wm8994_pdata wm8994_pdata = {
        .gpio_base = CODEC_GPIO_BASE,
+       .micb2_delay = 150,
        .gpio_defaults = {
                0x3,          /* IRQ out, active high, CMOS */
        },
        .ldo = {
-                { .init_data = &wm8994_ldo1, },
-                { .init_data = &wm8994_ldo2, },
+                { .enable = S3C64XX_GPN(6), .init_data = &wm8994_ldo1, },
+                { .enable = S3C64XX_GPN(4), .init_data = &wm8994_ldo2, },
        },
 };
 
@@ -182,7 +205,7 @@ static const struct i2c_board_info wm1277_devs[] = {
        },
 };
 
-static struct arizona_pdata wm5102_pdata = {
+static struct arizona_pdata wm5102_reva_pdata = {
        .ldoena = S3C64XX_GPN(7),
        .gpio_base = CODEC_GPIO_BASE,
        .irq_active_high = true,
@@ -193,64 +216,131 @@ static struct arizona_pdata wm5102_pdata = {
        },
 };
 
-static struct s3c64xx_spi_csinfo wm5102_spi_csinfo = {
+static struct s3c64xx_spi_csinfo codec_spi_csinfo = {
        .line = S3C64XX_GPN(5),
 };
 
+static struct spi_board_info wm5102_reva_spi_devs[] = {
+       [0] = {
+               .modalias       = "wm5102",
+               .max_speed_hz   = 10 * 1000 * 1000,
+               .bus_num        = 0,
+               .chip_select    = 1,
+               .mode           = SPI_MODE_0,
+               .irq            = GLENFARCLAS_PMIC_IRQ_BASE +
+                                 WM831X_IRQ_GPIO_2,
+               .controller_data = &codec_spi_csinfo,
+               .platform_data = &wm5102_reva_pdata,
+       },
+};
+
+static struct arizona_pdata wm5102_pdata = {
+       .ldoena = S3C64XX_GPN(7),
+       .gpio_base = CODEC_GPIO_BASE,
+       .irq_active_high = true,
+       .micd_pol_gpio = CODEC_GPIO_BASE + 2,
+       .gpio_defaults = {
+               [2] = 0x10000, /* AIF3TXLRCLK */
+               [3] = 0x4,     /* OPCLK */
+       },
+};
+
 static struct spi_board_info wm5102_spi_devs[] = {
        [0] = {
                .modalias       = "wm5102",
                .max_speed_hz   = 10 * 1000 * 1000,
                .bus_num        = 0,
-               .chip_select    = 0,
+               .chip_select    = 1,
                .mode           = SPI_MODE_0,
                .irq            = GLENFARCLAS_PMIC_IRQ_BASE +
                                  WM831X_IRQ_GPIO_2,
-               .controller_data = &wm5102_spi_csinfo,
+               .controller_data = &codec_spi_csinfo,
                .platform_data = &wm5102_pdata,
        },
 };
 
+static struct spi_board_info wm5110_spi_devs[] = {
+       [0] = {
+               .modalias       = "wm5110",
+               .max_speed_hz   = 10 * 1000 * 1000,
+               .bus_num        = 0,
+               .chip_select    = 1,
+               .mode           = SPI_MODE_0,
+               .irq            = GLENFARCLAS_PMIC_IRQ_BASE +
+                                 WM831X_IRQ_GPIO_2,
+               .controller_data = &codec_spi_csinfo,
+               .platform_data = &wm5102_reva_pdata,
+       },
+};
+
 static const struct i2c_board_info wm6230_i2c_devs[] = {
        { I2C_BOARD_INFO("wm9081", 0x6c),
          .platform_data = &wm9081_pdata, },
 };
 
+static struct wm2200_pdata wm2200_pdata = {
+       .ldo_ena = S3C64XX_GPN(7),
+       .gpio_defaults = {
+               [2] = 0x0005,  /* GPIO3 24.576MHz output clock */
+       },
+};
+
+static const struct i2c_board_info wm2200_i2c[] = {
+       { I2C_BOARD_INFO("wm2200", 0x3a),
+         .platform_data = &wm2200_pdata, },
+};
+
 static __devinitdata const struct {
        u8 id;
+       u8 rev;
        const char *name;
        const struct i2c_board_info *i2c_devs;
        int num_i2c_devs;
        const struct spi_board_info *spi_devs;
        int num_spi_devs;
 } gf_mods[] = {
-       { .id = 0x01, .name = "1250-EV1 Springbank" },
-       { .id = 0x02, .name = "1251-EV1 Jura" },
-       { .id = 0x03, .name = "1252-EV1 Glenlivet" },
-       { .id = 0x11, .name = "6249-EV2 Glenfarclas", },
-       { .id = 0x14, .name = "6271-EV1 Lochnagar" },
-       { .id = 0x15, .name = "6320-EV1 Bells",
+       { .id = 0x01, .rev = 0xff, .name = "1250-EV1 Springbank" },
+       { .id = 0x02, .rev = 0xff, .name = "1251-EV1 Jura" },
+       { .id = 0x03, .rev = 0xff, .name = "1252-EV1 Glenlivet" },
+       { .id = 0x06, .rev = 0xff, .name = "WM8997-6721-CS96-EV1 Lapraoig" },
+       { .id = 0x07, .rev = 0xff, .name = "WM5110-6271 Deanston",
+         .spi_devs = wm5110_spi_devs,
+         .num_spi_devs = ARRAY_SIZE(wm5110_spi_devs) },
+       { .id = 0x08, .rev = 0xff, .name = "WM8903-6102 Tamdhu" },
+       { .id = 0x09, .rev = 0xff, .name = "WM1811A-6305 Adelphi" },
+       { .id = 0x0a, .rev = 0xff, .name = "WM8996-6272 Blackadder" },
+       { .id = 0x0b, .rev = 0xff, .name = "WM8994-6235 Benromach" },
+       { .id = 0x11, .rev = 0xff, .name = "6249-EV2 Glenfarclas", },
+       { .id = 0x14, .rev = 0xff, .name = "6271-EV1 Lochnagar" },
+       { .id = 0x15, .rev = 0xff, .name = "6320-EV1 Bells",
          .i2c_devs = wm6230_i2c_devs,
          .num_i2c_devs = ARRAY_SIZE(wm6230_i2c_devs) },
-       { .id = 0x21, .name = "1275-EV1 Mortlach" },
-       { .id = 0x25, .name = "1274-EV1 Glencadam" },
-       { .id = 0x31, .name = "1253-EV1 Tomatin",
+       { .id = 0x21, .rev = 0xff, .name = "1275-EV1 Mortlach" },
+       { .id = 0x25, .rev = 0xff, .name = "1274-EV1 Glencadam" },
+       { .id = 0x31, .rev = 0xff, .name = "1253-EV1 Tomatin",
          .spi_devs = wm1253_devs, .num_spi_devs = ARRAY_SIZE(wm1253_devs) },
-       { .id = 0x32, .name = "XXXX-EV1 Caol Illa" },
-       { .id = 0x33, .name = "XXXX-EV1 Oban" },
-       { .id = 0x34, .name = "WM0010-6320-CS42 Balblair" },
-       { .id = 0x39, .name = "1254-EV1 Dallas Dhu",
+       { .id = 0x32, .rev = 0xff, .name = "XXXX-EV1 Caol Illa" },
+       { .id = 0x33, .rev = 0xff, .name = "XXXX-EV1 Oban" },
+       { .id = 0x34, .rev = 0xff, .name = "WM0010-6320-CS42 Balblair",
+         .spi_devs = balblair_devs,
+         .num_spi_devs = ARRAY_SIZE(balblair_devs) },
+       { .id = 0x39, .rev = 0xff, .name = "1254-EV1 Dallas Dhu",
          .i2c_devs = wm1254_devs, .num_i2c_devs = ARRAY_SIZE(wm1254_devs) },
-       { .id = 0x3a, .name = "1259-EV1 Tobermory",
+       { .id = 0x3a, .rev = 0xff, .name = "1259-EV1 Tobermory",
          .i2c_devs = wm1259_devs, .num_i2c_devs = ARRAY_SIZE(wm1259_devs) },
-       { .id = 0x3b, .name = "1255-EV1 Kilchoman",
+       { .id = 0x3b, .rev = 0xff, .name = "1255-EV1 Kilchoman",
          .i2c_devs = wm1255_devs, .num_i2c_devs = ARRAY_SIZE(wm1255_devs) },
-       { .id = 0x3c, .name = "1273-EV1 Longmorn" },
-       { .id = 0x3d, .name = "1277-EV1 Littlemill",
+       { .id = 0x3c, .rev = 0xff, .name = "1273-EV1 Longmorn" },
+       { .id = 0x3d, .rev = 0xff, .name = "1277-EV1 Littlemill",
          .i2c_devs = wm1277_devs, .num_i2c_devs = ARRAY_SIZE(wm1277_devs) },
-       { .id = 0x3e, .name = "WM5102-6271-EV1-CS127 Amrut",
+       { .id = 0x3e, .rev = 0, .name = "WM5102-6271-EV1-CS127 Amrut",
+         .spi_devs = wm5102_reva_spi_devs,
+         .num_spi_devs = ARRAY_SIZE(wm5102_reva_spi_devs) },
+       { .id = 0x3e, .rev = -1, .name = "WM5102-6271-EV1-CS127 Amrut",
          .spi_devs = wm5102_spi_devs,
          .num_spi_devs = ARRAY_SIZE(wm5102_spi_devs) },
+       { .id = 0x3f, .rev = -1, .name = "WM2200-6271-CS90-M-REV1",
+         .i2c_devs = wm2200_i2c, .num_i2c_devs = ARRAY_SIZE(wm2200_i2c) },
 };
 
 static __devinit int wlf_gf_module_probe(struct i2c_client *i2c,
@@ -267,7 +357,8 @@ static __devinit int wlf_gf_module_probe(struct i2c_client *i2c,
        id = (ret & 0xfe) >> 2;
        rev = ret & 0x3;
        for (i = 0; i < ARRAY_SIZE(gf_mods); i++)
-               if (id == gf_mods[i].id)
+               if (id == gf_mods[i].id && (gf_mods[i].rev == 0xff ||
+                                           rev == gf_mods[i].rev))
                        break;
 
        if (i < ARRAY_SIZE(gf_mods)) {
index 13b7eaa45fd04de2627e35111526a38737567d5f..2abe95d0401f5a08818cbde8b8e4cc111ec052c5 100644 (file)
@@ -304,6 +304,13 @@ static struct regulator_consumer_supply wallvdd_consumers[] = {
        REGULATOR_SUPPLY("SPKVDDL", "1-001a"),
        REGULATOR_SUPPLY("SPKVDDR", "1-001a"),
 
+       REGULATOR_SUPPLY("SPKVDDL", "spi0.1"),
+       REGULATOR_SUPPLY("SPKVDDR", "spi0.1"),
+       REGULATOR_SUPPLY("SPKVDDL", "wm5102-codec"),
+       REGULATOR_SUPPLY("SPKVDDR", "wm5102-codec"),
+       REGULATOR_SUPPLY("SPKVDDL", "wm5110-codec"),
+       REGULATOR_SUPPLY("SPKVDDR", "wm5110-codec"),
+
        REGULATOR_SUPPLY("DC1VDD", "0-0034"),
        REGULATOR_SUPPLY("DC2VDD", "0-0034"),
        REGULATOR_SUPPLY("DC3VDD", "0-0034"),
@@ -597,6 +604,7 @@ static struct s3c2410_platform_i2c i2c0_pdata = {
 static struct regulator_consumer_supply pvdd_1v2_consumers[] __devinitdata = {
        REGULATOR_SUPPLY("DCVDD", "spi0.0"),
        REGULATOR_SUPPLY("AVDD", "spi0.0"),
+       REGULATOR_SUPPLY("AVDD", "spi0.1"),
 };
 
 static struct regulator_init_data pvdd_1v2 __devinitdata = {
@@ -621,6 +629,24 @@ static struct regulator_consumer_supply pvdd_1v8_consumers[] __devinitdata = {
        REGULATOR_SUPPLY("DCVDD", "1-001a"),
        REGULATOR_SUPPLY("AVDD", "1-001a"),
        REGULATOR_SUPPLY("DBVDD", "spi0.0"),
+
+       REGULATOR_SUPPLY("DBVDD", "1-003a"),
+       REGULATOR_SUPPLY("LDOVDD", "1-003a"),
+       REGULATOR_SUPPLY("CPVDD", "1-003a"),
+       REGULATOR_SUPPLY("AVDD", "1-003a"),
+       REGULATOR_SUPPLY("DBVDD1", "spi0.1"),
+       REGULATOR_SUPPLY("DBVDD2", "spi0.1"),
+       REGULATOR_SUPPLY("DBVDD3", "spi0.1"),
+       REGULATOR_SUPPLY("LDOVDD", "spi0.1"),
+       REGULATOR_SUPPLY("CPVDD", "spi0.1"),
+
+       REGULATOR_SUPPLY("DBVDD2", "wm5102-codec"),
+       REGULATOR_SUPPLY("DBVDD3", "wm5102-codec"),
+       REGULATOR_SUPPLY("CPVDD", "wm5102-codec"),
+
+       REGULATOR_SUPPLY("DBVDD2", "wm5110-codec"),
+       REGULATOR_SUPPLY("DBVDD3", "wm5110-codec"),
+       REGULATOR_SUPPLY("CPVDD", "wm5110-codec"),
 };
 
 static struct regulator_init_data pvdd_1v8 __devinitdata = {
@@ -685,6 +711,7 @@ static struct i2c_board_info i2c_devs1[] __devinitdata = {
          .irq = S3C_EINT(0),
          .platform_data = &glenfarclas_pmic_pdata },
 
+       { I2C_BOARD_INFO("wlf-gf-module", 0x20) },
        { I2C_BOARD_INFO("wlf-gf-module", 0x22) },
        { I2C_BOARD_INFO("wlf-gf-module", 0x24) },
        { I2C_BOARD_INFO("wlf-gf-module", 0x25) },
@@ -810,7 +837,7 @@ static void __init crag6410_machine_init(void)
        i2c_register_board_info(1, i2c_devs1, ARRAY_SIZE(i2c_devs1));
 
        samsung_keypad_set_platdata(&crag6410_keypad_data);
-       s3c64xx_spi0_set_platdata(NULL, 0, 1);
+       s3c64xx_spi0_set_platdata(NULL, 0, 2);
 
        platform_add_devices(crag6410_devices, ARRAY_SIZE(crag6410_devices));
 
index 6e6a0a9d6778b0b1fe41a6857cef015ee55bc39d..111e404a81fd44a8627025c975898e12f20598b7 100644 (file)
@@ -44,6 +44,7 @@
 #include <plat/sdhci.h>
 #include <plat/adc-core.h>
 #include <plat/fb-core.h>
+#include <plat/spi-core.h>
 #include <plat/gpio-cfg.h>
 #include <plat/regs-irqtype.h>
 #include <plat/regs-serial.h>
@@ -179,6 +180,7 @@ void __init s5p6440_map_io(void)
        /* initialize any device information early */
        s3c_adc_setname("s3c64xx-adc");
        s3c_fb_setname("s5p64x0-fb");
+       s3c64xx_spi_setname("s5p64x0-spi");
 
        s5p64x0_default_sdhci0();
        s5p64x0_default_sdhci1();
@@ -193,6 +195,7 @@ void __init s5p6450_map_io(void)
        /* initialize any device information early */
        s3c_adc_setname("s3c64xx-adc");
        s3c_fb_setname("s5p64x0-fb");
+       s3c64xx_spi_setname("s5p64x0-spi");
 
        s5p64x0_default_sdhci0();
        s5p64x0_default_sdhci1();
index 621908658861596a43e4817f6978e352eab7604d..cc6e561c99588430f7e3b99993d761ffebecf949 100644 (file)
@@ -45,6 +45,7 @@
 #include <plat/fb-core.h>
 #include <plat/iic-core.h>
 #include <plat/onenand-core.h>
+#include <plat/spi-core.h>
 #include <plat/regs-serial.h>
 #include <plat/watchdog-reset.h>
 
@@ -165,6 +166,8 @@ void __init s5pc100_map_io(void)
        s3c_onenand_setname("s5pc100-onenand");
        s3c_fb_setname("s5pc100-fb");
        s3c_cfcon_setname("s5pc100-pata");
+
+       s3c64xx_spi_setname("s5pc100-spi");
 }
 
 void __init s5pc100_init_clocks(int xtal)
index 4c9e9027df9aed2cbd0314ec1cebc0d80a1d3530..a0c50efe8145f167b4482a814e15329d7f32db27 100644 (file)
@@ -43,6 +43,7 @@
 #include <plat/iic-core.h>
 #include <plat/keypad-core.h>
 #include <plat/tv-core.h>
+#include <plat/spi-core.h>
 #include <plat/regs-serial.h>
 
 #include "common.h"
@@ -196,6 +197,8 @@ void __init s5pv210_map_io(void)
 
        /* setup TV devices */
        s5p_hdmi_setname("s5pv210-hdmi");
+
+       s3c64xx_spi_setname("s5pv210-spi");
 }
 
 void __init s5pv210_init_clocks(int xtal)
index 55e1dba4ffde08bb0de1b57dec5189e5970cd1fd..c72b31078c9948a9e8ac0d45814d1049ca4b4f20 100644 (file)
@@ -774,7 +774,6 @@ static void __init goni_pmic_init(void)
 /* MoviNAND */
 static struct s3c_sdhci_platdata goni_hsmmc0_data __initdata = {
        .max_width              = 4,
-       .host_caps2             = MMC_CAP2_BROKEN_VOLTAGE,
        .cd_type                = S3C_SDHCI_CD_PERMANENT,
 };
 
index 8ae100cc655c12c3cc23d3beb676c0ab9e2c8cfa..0750d9c7f00dae5ee1c827d0bb0d85098bfd23a6 100644 (file)
@@ -95,6 +95,7 @@ config MACH_MACKEREL
        select ARCH_REQUIRE_GPIOLIB
        select REGULATOR_FIXED_VOLTAGE if REGULATOR
        select SND_SOC_AK4642 if SND_SIMPLE_CARD
+       select USE_OF
 
 config MACH_KOTA2
        bool "KOTA2 board"
index 2912eab3b967bddedb8a42e39747e9612f04d237..499e6e3766660817fef28cc9022596ab11633dd3 100644 (file)
@@ -1196,7 +1196,7 @@ static void __init eva_init(void)
 
 #ifdef CONFIG_CACHE_L2X0
        /* Early BRESP enable, Shared attribute override enable, 32K*8way */
-       l2x0_init(__io(0xf0002000), 0x40440000, 0x82000fff);
+       l2x0_init(IOMEM(0xf0002000), 0x40440000, 0x82000fff);
 #endif
 
        i2c_register_board_info(0, i2c0_devices, ARRAY_SIZE(i2c0_devices));
@@ -1229,6 +1229,13 @@ static void __init eva_add_early_devices(void)
        shmobile_timer.init = eva_earlytimer_init;
 }
 
+#define RESCNT2 IOMEM(0xe6188020)
+static void eva_restart(char mode, const char *cmd)
+{
+       /* Do soft power on reset */
+       writel((1 << 31), RESCNT2);
+}
+
 static const char *eva_boards_compat_dt[] __initdata = {
        "renesas,armadillo800eva",
        NULL,
@@ -1243,4 +1250,5 @@ DT_MACHINE_START(ARMADILLO800EVA_DT, "armadillo800eva")
        .init_late      = shmobile_init_late,
        .timer          = &shmobile_timer,
        .dt_compat      = eva_boards_compat_dt,
+       .restart        = eva_restart,
 MACHINE_END
index 0a43f3189c21c176f41f13ee82062f837a9ab6f8..f63f2eeb0205d4361226a95ccb68fb5b34571bfa 100644 (file)
@@ -384,6 +384,8 @@ static struct regulator_consumer_supply fixed2v8_power_consumers[] =
 
 /* SDHI */
 static struct sh_mobile_sdhi_info sdhi0_info = {
+       .dma_slave_tx   = SHDMA_SLAVE_SDHI0_TX,
+       .dma_slave_rx   = SHDMA_SLAVE_SDHI0_RX,
        .tmio_flags     = TMIO_MMC_HAS_IDLE_WAIT,
        .tmio_caps      = MMC_CAP_SD_HIGHSPEED,
        .tmio_ocr_mask  = MMC_VDD_27_28 | MMC_VDD_28_29,
@@ -424,6 +426,8 @@ static struct platform_device sdhi0_device = {
 
 /* Micro SD */
 static struct sh_mobile_sdhi_info sdhi2_info = {
+       .dma_slave_tx   = SHDMA_SLAVE_SDHI2_TX,
+       .dma_slave_rx   = SHDMA_SLAVE_SDHI2_RX,
        .tmio_flags     = TMIO_MMC_HAS_IDLE_WAIT |
                          TMIO_MMC_USE_GPIO_CD |
                          TMIO_MMC_WRPROTECT_DISABLE,
@@ -557,7 +561,15 @@ static struct i2c_board_info i2c0_devices[] = {
        },
        {
                I2C_BOARD_INFO("r2025sd", 0x32),
-       }
+       },
+       {
+               I2C_BOARD_INFO("ak8975", 0x0c),
+               .irq = intcs_evt2irq(0x3380), /* IRQ28 */
+       },
+       {
+               I2C_BOARD_INFO("adxl34x", 0x1d),
+               .irq = intcs_evt2irq(0x3340), /* IRQ26 */
+       },
 };
 
 static struct i2c_board_info i2c1_devices[] = {
index 0c27c810cf99d0906b655f298091ffab257644fc..39b8f2e70638322e60b6463f4a506547ec5b607c 100644 (file)
@@ -1651,7 +1651,12 @@ static void __init mackerel_init(void)
        pm_clk_add(&hdmi_lcdc_device.dev, "hdmi");
 }
 
-MACHINE_START(MACKEREL, "mackerel")
+static const char *mackerel_boards_compat_dt[] __initdata = {
+       "renesas,mackerel",
+       NULL,
+};
+
+DT_MACHINE_START(MACKEREL_DT, "mackerel")
        .map_io         = sh7372_map_io,
        .init_early     = sh7372_add_early_devices,
        .init_irq       = sh7372_init_irq,
@@ -1659,4 +1664,5 @@ MACHINE_START(MACKEREL, "mackerel")
        .init_machine   = mackerel_init,
        .init_late      = sh7372_pm_init_late,
        .timer          = &shmobile_timer,
+       .dt_compat  = mackerel_boards_compat_dt,
 MACHINE_END
index b8a7525a4e2f17a9b4a7ded338fbe22b3b04f3fc..69f7f464eff84bb4446e76500e627d5e03e12d78 100644 (file)
@@ -30,6 +30,8 @@
 #include <linux/regulator/fixed.h>
 #include <linux/regulator/machine.h>
 #include <linux/smsc911x.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/sh_hspi.h>
 #include <linux/mmc/sh_mobile_sdhi.h>
 #include <linux/mfd/tmio.h>
 #include <mach/hardware.h>
@@ -126,10 +128,27 @@ static struct platform_device thermal_device = {
        .num_resources  = ARRAY_SIZE(thermal_resources),
 };
 
+/* HSPI */
+static struct resource hspi_resources[] = {
+       [0] = {
+               .start          = 0xFFFC7000,
+               .end            = 0xFFFC7018 - 1,
+               .flags          = IORESOURCE_MEM,
+       },
+};
+
+static struct platform_device hspi_device = {
+       .name   = "sh-hspi",
+       .id     = 0,
+       .resource       = hspi_resources,
+       .num_resources  = ARRAY_SIZE(hspi_resources),
+};
+
 static struct platform_device *marzen_devices[] __initdata = {
        &eth_device,
        &sdhi0_device,
        &thermal_device,
+       &hspi_device,
 };
 
 static void __init marzen_init(void)
@@ -163,6 +182,12 @@ static void __init marzen_init(void)
        gpio_request(GPIO_FN_SD0_CD, NULL);
        gpio_request(GPIO_FN_SD0_WP, NULL);
 
+       /* HSPI 0 */
+       gpio_request(GPIO_FN_HSPI_CLK0, NULL);
+       gpio_request(GPIO_FN_HSPI_CS0,  NULL);
+       gpio_request(GPIO_FN_HSPI_TX0,  NULL);
+       gpio_request(GPIO_FN_HSPI_RX0,  NULL);
+
        r8a7779_add_standard_devices();
        platform_add_devices(marzen_devices, ARRAY_SIZE(marzen_devices));
 }
index 3cafb6ab5e9aafb09e900b4821e291eab3493e29..e48509b938cf6d672dbf0fbba93e05545345002d 100644 (file)
 #include <linux/clkdev.h>
 #include <mach/common.h>
 
-#define FRQMR   0xffc80014
-#define MSTPCR0 0xffc80030
-#define MSTPCR1 0xffc80034
-#define MSTPCR3 0xffc8003c
-#define MSTPSR1 0xffc80044
-#define MSTPSR4 0xffc80048
-#define MSTPSR6 0xffc8004c
-#define MSTPCR4 0xffc80050
-#define MSTPCR5 0xffc80054
-#define MSTPCR6 0xffc80058
-#define MSTPCR7 0xffc80040
+#define FRQMR          IOMEM(0xffc80014)
+#define MSTPCR0                IOMEM(0xffc80030)
+#define MSTPCR1                IOMEM(0xffc80034)
+#define MSTPCR3                IOMEM(0xffc8003c)
+#define MSTPSR1                IOMEM(0xffc80044)
+#define MSTPSR4                IOMEM(0xffc80048)
+#define MSTPSR6                IOMEM(0xffc8004c)
+#define MSTPCR4                IOMEM(0xffc80050)
+#define MSTPCR5                IOMEM(0xffc80054)
+#define MSTPCR6                IOMEM(0xffc80058)
+#define MSTPCR7                IOMEM(0xffc80040)
 
 /* ioremap() through clock mapping mandatory to avoid
  * collision with ARM coherent DMA virtual memory range.
@@ -87,8 +87,10 @@ static struct clk div4_clks[DIV4_NR] = {
 };
 
 enum { MSTP323, MSTP322, MSTP321, MSTP320,
-       MSTP026, MSTP025, MSTP024, MSTP023, MSTP022, MSTP021,
+       MSTP030,
+       MSTP029, MSTP028, MSTP027, MSTP026, MSTP025, MSTP024, MSTP023, MSTP022, MSTP021,
        MSTP016, MSTP015, MSTP014,
+       MSTP007,
        MSTP_NR };
 
 static struct clk mstp_clks[MSTP_NR] = {
@@ -96,6 +98,10 @@ static struct clk mstp_clks[MSTP_NR] = {
        [MSTP322] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 22, 0), /* SDHI1 */
        [MSTP321] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 21, 0), /* SDHI2 */
        [MSTP320] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 20, 0), /* SDHI3 */
+       [MSTP030] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 30, 0), /* I2C0 */
+       [MSTP029] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 29, 0), /* I2C1 */
+       [MSTP028] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 28, 0), /* I2C2 */
+       [MSTP027] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 27, 0), /* I2C3 */
        [MSTP026] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 26, 0), /* SCIF0 */
        [MSTP025] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 25, 0), /* SCIF1 */
        [MSTP024] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 24, 0), /* SCIF2 */
@@ -105,6 +111,7 @@ static struct clk mstp_clks[MSTP_NR] = {
        [MSTP016] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 16, 0), /* TMU0 */
        [MSTP015] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 15, 0), /* TMU1 */
        [MSTP014] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 14, 0), /* TMU2 */
+       [MSTP007] = SH_CLK_MSTP32(&div4_clks[DIV4_S], MSTPCR0,  7, 0), /* HSPI */
 };
 
 static unsigned long mul4_recalc(struct clk *clk)
@@ -148,12 +155,19 @@ static struct clk_lookup lookups[] = {
        /* MSTP32 clocks */
        CLKDEV_DEV_ID("sh_tmu.0", &mstp_clks[MSTP016]), /* TMU00 */
        CLKDEV_DEV_ID("sh_tmu.1", &mstp_clks[MSTP016]), /* TMU01 */
+       CLKDEV_DEV_ID("i2c-rcar.0", &mstp_clks[MSTP030]), /* I2C0 */
+       CLKDEV_DEV_ID("i2c-rcar.1", &mstp_clks[MSTP029]), /* I2C1 */
+       CLKDEV_DEV_ID("i2c-rcar.2", &mstp_clks[MSTP028]), /* I2C2 */
+       CLKDEV_DEV_ID("i2c-rcar.3", &mstp_clks[MSTP027]), /* I2C3 */
        CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP026]), /* SCIF0 */
        CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[MSTP025]), /* SCIF1 */
        CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP024]), /* SCIF2 */
        CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP023]), /* SCIF3 */
        CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP022]), /* SCIF4 */
        CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP021]), /* SCIF6 */
+       CLKDEV_DEV_ID("sh-hspi.0", &mstp_clks[MSTP007]), /* HSPI0 */
+       CLKDEV_DEV_ID("sh-hspi.1", &mstp_clks[MSTP007]), /* HSPI1 */
+       CLKDEV_DEV_ID("sh-hspi.2", &mstp_clks[MSTP007]), /* HSPI2 */
        CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP323]), /* SDHI0 */
        CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP322]), /* SDHI1 */
        CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP321]), /* SDHI2 */
index eb98b45c508902c631153c093ed14aea877893d5..d65fbbe84678190522c1b6a40b3f830082ba47b0 100644 (file)
@@ -452,6 +452,10 @@ enum {
        SHDMA_SLAVE_SCIF5_RX,
        SHDMA_SLAVE_SCIF6_TX,
        SHDMA_SLAVE_SCIF6_RX,
+       SHDMA_SLAVE_FLCTL0_TX,
+       SHDMA_SLAVE_FLCTL0_RX,
+       SHDMA_SLAVE_FLCTL1_TX,
+       SHDMA_SLAVE_FLCTL1_RX,
        SHDMA_SLAVE_SDHI0_RX,
        SHDMA_SLAVE_SDHI0_TX,
        SHDMA_SLAVE_SDHI1_RX,
index 11bb1d9841975ef9be12c1591fae32c80903b55e..6649a77428d8feeed4d1209b5c381b494f2c595b 100644 (file)
@@ -590,6 +590,21 @@ static struct platform_device i2c1_device = {
        .num_resources  = ARRAY_SIZE(i2c1_resources),
 };
 
+static struct resource pmu_resources[] = {
+       [0] = {
+               .start  = evt2irq(0x19a0),
+               .end    = evt2irq(0x19a0),
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device pmu_device = {
+       .name   = "arm-pmu",
+       .id             = -1,
+       .num_resources = ARRAY_SIZE(pmu_resources),
+       .resource = pmu_resources,
+};
+
 static struct platform_device *r8a7740_late_devices[] __initdata = {
        &i2c0_device,
        &i2c1_device,
@@ -597,6 +612,7 @@ static struct platform_device *r8a7740_late_devices[] __initdata = {
        &dma1_device,
        &dma2_device,
        &usb_dma_device,
+       &pmu_device,
 };
 
 /*
@@ -747,7 +763,7 @@ static const char *r8a7740_boards_compat_dt[] __initdata = {
        NULL,
 };
 
-DT_MACHINE_START(SH7372_DT, "Generic R8A7740 (Flattened Device Tree)")
+DT_MACHINE_START(R8A7740_DT, "Generic R8A7740 (Flattened Device Tree)")
        .map_io         = r8a7740_map_io,
        .init_early     = r8a7740_add_early_devices_dt,
        .init_irq       = r8a7740_init_irq,
index 2917668f0091c1042a70e512f50c12bacdb3ebb2..7a1ad4f38539df32e176802e8c7f83086c82b69c 100644 (file)
@@ -229,6 +229,79 @@ static struct platform_device tmu01_device = {
        .num_resources  = ARRAY_SIZE(tmu01_resources),
 };
 
+/* I2C */
+static struct resource rcar_i2c0_res[] = {
+       {
+               .start  = 0xffc70000,
+               .end    = 0xffc70fff,
+               .flags  = IORESOURCE_MEM,
+       }, {
+               .start  = gic_spi(79),
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device i2c0_device = {
+       .name           = "i2c-rcar",
+       .id             = 0,
+       .resource       = rcar_i2c0_res,
+       .num_resources  = ARRAY_SIZE(rcar_i2c0_res),
+};
+
+static struct resource rcar_i2c1_res[] = {
+       {
+               .start  = 0xffc71000,
+               .end    = 0xffc71fff,
+               .flags  = IORESOURCE_MEM,
+       }, {
+               .start  = gic_spi(82),
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device i2c1_device = {
+       .name           = "i2c-rcar",
+       .id             = 1,
+       .resource       = rcar_i2c1_res,
+       .num_resources  = ARRAY_SIZE(rcar_i2c1_res),
+};
+
+static struct resource rcar_i2c2_res[] = {
+       {
+               .start  = 0xffc72000,
+               .end    = 0xffc72fff,
+               .flags  = IORESOURCE_MEM,
+       }, {
+               .start  = gic_spi(80),
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device i2c2_device = {
+       .name           = "i2c-rcar",
+       .id             = 2,
+       .resource       = rcar_i2c2_res,
+       .num_resources  = ARRAY_SIZE(rcar_i2c2_res),
+};
+
+static struct resource rcar_i2c3_res[] = {
+       {
+               .start  = 0xffc73000,
+               .end    = 0xffc73fff,
+               .flags  = IORESOURCE_MEM,
+       }, {
+               .start  = gic_spi(81),
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device i2c3_device = {
+       .name           = "i2c-rcar",
+       .id             = 3,
+       .resource       = rcar_i2c3_res,
+       .num_resources  = ARRAY_SIZE(rcar_i2c3_res),
+};
+
 static struct platform_device *r8a7779_early_devices[] __initdata = {
        &scif0_device,
        &scif1_device,
@@ -238,6 +311,10 @@ static struct platform_device *r8a7779_early_devices[] __initdata = {
        &scif5_device,
        &tmu00_device,
        &tmu01_device,
+       &i2c0_device,
+       &i2c1_device,
+       &i2c2_device,
+       &i2c3_device,
 };
 
 static struct platform_device *r8a7779_late_devices[] __initdata = {
@@ -247,7 +324,7 @@ void __init r8a7779_add_standard_devices(void)
 {
 #ifdef CONFIG_CACHE_L2X0
        /* Early BRESP enable, Shared attribute override enable, 64K*16way */
-       l2x0_init((void __iomem __force *)(0xf0100000), 0x40470000, 0x82000fff);
+       l2x0_init(IOMEM(0xf0100000), 0x40470000, 0x82000fff);
 #endif
        r8a7779_pm_init();
 
index a07954fbcd22b9017b588ef1f745bddf101bf419..a36011184c16c05d432de1cb0fbd678749a9ade8 100644 (file)
@@ -407,6 +407,26 @@ static const struct sh_dmae_slave_config sh7372_dmae_slaves[] = {
                .addr           = 0xe6c30060,
                .chcr           = CHCR_RX(XMIT_SZ_8BIT),
                .mid_rid        = 0x3e,
+       }, {
+               .slave_id       = SHDMA_SLAVE_FLCTL0_TX,
+               .addr           = 0xe6a30050,
+               .chcr           = CHCR_TX(XMIT_SZ_32BIT),
+               .mid_rid        = 0x83,
+       }, {
+               .slave_id       = SHDMA_SLAVE_FLCTL0_RX,
+               .addr           = 0xe6a30050,
+               .chcr           = CHCR_RX(XMIT_SZ_32BIT),
+               .mid_rid        = 0x83,
+       }, {
+               .slave_id       = SHDMA_SLAVE_FLCTL1_TX,
+               .addr           = 0xe6a30060,
+               .chcr           = CHCR_TX(XMIT_SZ_32BIT),
+               .mid_rid        = 0x87,
+       }, {
+               .slave_id       = SHDMA_SLAVE_FLCTL1_RX,
+               .addr           = 0xe6a30060,
+               .chcr           = CHCR_RX(XMIT_SZ_32BIT),
+               .mid_rid        = 0x87,
        }, {
                .slave_id       = SHDMA_SLAVE_SDHI0_TX,
                .addr           = 0xe6850030,
index b5015d0f1912bbad5126c219790dc11cf2a5f970..bc949fb7efe89b6d594a9ba6fe2ac92b3b226640 100644 (file)
@@ -24,8 +24,6 @@
 #include <linux/sched.h>
 #include <linux/mutex.h>
 
-#include <mach/dma.h>
-
 #include "apbio.h"
 
 #if defined(CONFIG_TEGRA20_APB_DMA)
@@ -71,7 +69,6 @@ bool tegra_apb_dma_init(void)
 
        dma_sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
        dma_sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
-       dma_sconfig.slave_id = TEGRA_DMA_REQ_SEL_CNTR;
        dma_sconfig.src_maxburst = 1;
        dma_sconfig.dst_maxburst = 1;
 
index 57e235f4ac74a81da9ff15619ca44a69bc0b1509..2053f74cf6ce0f143327b050596b2b9e50c0f6af 100644 (file)
@@ -41,7 +41,6 @@
 #include <asm/setup.h>
 
 #include <mach/iomap.h>
-#include <mach/irqs.h>
 
 #include "board.h"
 #include "clock.h"
@@ -104,8 +103,12 @@ static __initdata struct tegra_clk_init_table tegra_dt_clk_init_table[] = {
        { "pll_a",      "pll_p_out1",   56448000,       true },
        { "pll_a_out0", "pll_a",        11289600,       true },
        { "cdev1",      NULL,           0,              true },
+       { "blink",      "clk_32k",      32768,          true },
        { "i2s1",       "pll_a_out0",   11289600,       false},
        { "i2s2",       "pll_a_out0",   11289600,       false},
+       { "sdmmc1",     "pll_p",        48000000,       false},
+       { "sdmmc3",     "pll_p",        48000000,       false},
+       { "sdmmc4",     "pll_p",        48000000,       false},
        { NULL,         NULL,           0,              0},
 };
 
@@ -182,7 +185,7 @@ DT_MACHINE_START(TEGRA_DT, "nVidia Tegra20 (Flattened Device Tree)")
        .init_early     = tegra20_init_early,
        .init_irq       = tegra_dt_init_irq,
        .handle_irq     = gic_handle_irq,
-       .timer          = &tegra_timer,
+       .timer          = &tegra_sys_timer,
        .init_machine   = tegra_dt_init,
        .init_late      = tegra_dt_init_late,
        .restart        = tegra_assert_system_reset,
index e4a676d4ddf720316ba5c7e96ed72e9ac7ad3616..9e6f79a4cd9b66a9c72b70bcb55d0405b8d73aff 100644 (file)
@@ -62,11 +62,15 @@ static __initdata struct tegra_clk_init_table tegra_dt_clk_init_table[] = {
        { "pll_a_out0", "pll_a",        11289600,       true },
        { "extern1",    "pll_a_out0",   0,              true },
        { "clk_out_1",  "extern1",      0,              true },
+       { "blink",      "clk_32k",      32768,          true },
        { "i2s0",       "pll_a_out0",   11289600,       false},
        { "i2s1",       "pll_a_out0",   11289600,       false},
        { "i2s2",       "pll_a_out0",   11289600,       false},
        { "i2s3",       "pll_a_out0",   11289600,       false},
        { "i2s4",       "pll_a_out0",   11289600,       false},
+       { "sdmmc1",     "pll_p",        48000000,       false},
+       { "sdmmc3",     "pll_p",        48000000,       false},
+       { "sdmmc4",     "pll_p",        48000000,       false},
        { NULL,         NULL,           0,              0},
 };
 
@@ -89,7 +93,7 @@ DT_MACHINE_START(TEGRA30_DT, "NVIDIA Tegra30 (Flattened Device Tree)")
        .init_early     = tegra30_init_early,
        .init_irq       = tegra_dt_init_irq,
        .handle_irq     = gic_handle_irq,
-       .timer          = &tegra_timer,
+       .timer          = &tegra_sys_timer,
        .init_machine   = tegra30_dt_init,
        .init_late      = tegra_init_late,
        .restart        = tegra_assert_system_reset,
index f88e5143c767989e7cc8e634635d858055f9de61..91fbe733a21eae9be6a5e24df8740ab3d3474efd 100644 (file)
@@ -55,5 +55,5 @@ static inline int harmony_pcie_init(void) { return 0; }
 
 void __init tegra_paz00_wifikill_init(void);
 
-extern struct sys_timer tegra_timer;
+extern struct sys_timer tegra_sys_timer;
 #endif
index fd82085eca5d12eda4134759f1535bd6426f1c91..867bf8bf556159ffcb12584d6d1bb8788ab7b821 100644 (file)
@@ -27,8 +27,6 @@
 #include <linux/seq_file.h>
 #include <linux/slab.h>
 
-#include <mach/clk.h>
-
 #include "board.h"
 #include "clock.h"
 #include "tegra_cpu_car.h"
index 627bf0f4262ec01550242b8d52a8e384e2233c6a..a74d3c7d2e26836beac265f15db1c3c69b1575c7 100644 (file)
@@ -30,9 +30,6 @@
 #include <linux/io.h>
 #include <linux/suspend.h>
 
-
-#include <mach/clk.h>
-
 /* Frequency table index must be sequential starting at 0 */
 static struct cpufreq_frequency_table freq_table[] = {
        { 0, 216000 },
index 566e2f88899bdbde99595d4e166a1e87ad47f0aa..4e0b07c7963c89230c0f8d4709a990cce10bc4da 100644 (file)
 
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/cpu.h>
 #include <linux/cpuidle.h>
-#include <linux/hrtimer.h>
 
-#include <asm/proc-fns.h>
-
-#include <mach/iomap.h>
-
-static int tegra_idle_enter_lp3(struct cpuidle_device *dev,
-                               struct cpuidle_driver *drv, int index);
+#include <asm/cpuidle.h>
 
 struct cpuidle_driver tegra_idle_driver = {
        .name = "tegra_idle",
        .owner = THIS_MODULE,
+       .en_core_tk_irqen = 1,
        .state_count = 1,
        .states = {
-               [0] = {
-                       .enter                  = tegra_idle_enter_lp3,
-                       .exit_latency           = 10,
-                       .target_residency       = 10,
-                       .power_usage            = 600,
-                       .flags                  = CPUIDLE_FLAG_TIME_VALID,
-                       .name                   = "LP3",
-                       .desc                   = "CPU flow-controlled",
-               },
+               [0] = ARM_CPUIDLE_WFI_STATE_PWR(600),
        },
 };
 
 static DEFINE_PER_CPU(struct cpuidle_device, tegra_idle_device);
 
-static int tegra_idle_enter_lp3(struct cpuidle_device *dev,
-       struct cpuidle_driver *drv, int index)
-{
-       ktime_t enter, exit;
-       s64 us;
-
-       local_irq_disable();
-       local_fiq_disable();
-
-       enter = ktime_get();
-
-       cpu_do_idle();
-
-       exit = ktime_sub(ktime_get(), enter);
-       us = ktime_to_us(exit);
-
-       local_fiq_enable();
-       local_irq_enable();
-
-       dev->last_residency = us;
-
-       return index;
-}
-
 static int __init tegra_cpuidle_init(void)
 {
        int ret;
diff --git a/arch/arm/mach-tegra/include/mach/dma.h b/arch/arm/mach-tegra/include/mach/dma.h
deleted file mode 100644 (file)
index 3081cc6..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * arch/arm/mach-tegra/include/mach/dma.h
- *
- * Copyright (c) 2008-2009, NVIDIA Corporation.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-#ifndef __MACH_TEGRA_DMA_H
-#define __MACH_TEGRA_DMA_H
-
-#include <linux/list.h>
-
-#define TEGRA_DMA_REQ_SEL_CNTR                 0
-#define TEGRA_DMA_REQ_SEL_I2S_2                        1
-#define TEGRA_DMA_REQ_SEL_I2S_1                        2
-#define TEGRA_DMA_REQ_SEL_SPD_I                        3
-#define TEGRA_DMA_REQ_SEL_UI_I                 4
-#define TEGRA_DMA_REQ_SEL_MIPI                 5
-#define TEGRA_DMA_REQ_SEL_I2S2_2               6
-#define TEGRA_DMA_REQ_SEL_I2S2_1               7
-#define TEGRA_DMA_REQ_SEL_UARTA                        8
-#define TEGRA_DMA_REQ_SEL_UARTB                        9
-#define TEGRA_DMA_REQ_SEL_UARTC                        10
-#define TEGRA_DMA_REQ_SEL_SPI                  11
-#define TEGRA_DMA_REQ_SEL_AC97                 12
-#define TEGRA_DMA_REQ_SEL_ACMODEM              13
-#define TEGRA_DMA_REQ_SEL_SL4B                 14
-#define TEGRA_DMA_REQ_SEL_SL2B1                        15
-#define TEGRA_DMA_REQ_SEL_SL2B2                        16
-#define TEGRA_DMA_REQ_SEL_SL2B3                        17
-#define TEGRA_DMA_REQ_SEL_SL2B4                        18
-#define TEGRA_DMA_REQ_SEL_UARTD                        19
-#define TEGRA_DMA_REQ_SEL_UARTE                        20
-#define TEGRA_DMA_REQ_SEL_I2C                  21
-#define TEGRA_DMA_REQ_SEL_I2C2                 22
-#define TEGRA_DMA_REQ_SEL_I2C3                 23
-#define TEGRA_DMA_REQ_SEL_DVC_I2C              24
-#define TEGRA_DMA_REQ_SEL_OWR                  25
-#define TEGRA_DMA_REQ_SEL_INVALID              31
-
-#endif
diff --git a/arch/arm/mach-tegra/include/mach/irqs.h b/arch/arm/mach-tegra/include/mach/irqs.h
deleted file mode 100644 (file)
index aad1a2c..0000000
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * arch/arm/mach-tegra/include/mach/irqs.h
- *
- * Copyright (C) 2010 Google, Inc.
- *
- * Author:
- *     Colin Cross <ccross@google.com>
- *     Erik Gilling <konkers@google.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef __MACH_TEGRA_IRQS_H
-#define __MACH_TEGRA_IRQS_H
-
-#define INT_GIC_BASE                   0
-
-#define IRQ_LOCALTIMER                  29
-
-/* Primary Interrupt Controller */
-#define INT_PRI_BASE                   (INT_GIC_BASE + 32)
-#define INT_TMR1                       (INT_PRI_BASE + 0)
-#define INT_TMR2                       (INT_PRI_BASE + 1)
-#define INT_RTC                                (INT_PRI_BASE + 2)
-#define INT_I2S2                       (INT_PRI_BASE + 3)
-#define INT_SHR_SEM_INBOX_IBF          (INT_PRI_BASE + 4)
-#define INT_SHR_SEM_INBOX_IBE          (INT_PRI_BASE + 5)
-#define INT_SHR_SEM_OUTBOX_IBF         (INT_PRI_BASE + 6)
-#define INT_SHR_SEM_OUTBOX_IBE         (INT_PRI_BASE + 7)
-#define INT_VDE_UCQ_ERROR              (INT_PRI_BASE + 8)
-#define INT_VDE_SYNC_TOKEN             (INT_PRI_BASE + 9)
-#define INT_VDE_BSE_V                  (INT_PRI_BASE + 10)
-#define INT_VDE_BSE_A                  (INT_PRI_BASE + 11)
-#define INT_VDE_SXE                    (INT_PRI_BASE + 12)
-#define INT_I2S1                       (INT_PRI_BASE + 13)
-#define INT_SDMMC1                     (INT_PRI_BASE + 14)
-#define INT_SDMMC2                     (INT_PRI_BASE + 15)
-#define INT_XIO                                (INT_PRI_BASE + 16)
-#define INT_VDE                                (INT_PRI_BASE + 17)
-#define INT_AVP_UCQ                    (INT_PRI_BASE + 18)
-#define INT_SDMMC3                     (INT_PRI_BASE + 19)
-#define INT_USB                                (INT_PRI_BASE + 20)
-#define INT_USB2                       (INT_PRI_BASE + 21)
-#define INT_PRI_RES_22                 (INT_PRI_BASE + 22)
-#define INT_EIDE                       (INT_PRI_BASE + 23)
-#define INT_NANDFLASH                  (INT_PRI_BASE + 24)
-#define INT_VCP                                (INT_PRI_BASE + 25)
-#define INT_APB_DMA                    (INT_PRI_BASE + 26)
-#define INT_AHB_DMA                    (INT_PRI_BASE + 27)
-#define INT_GNT_0                      (INT_PRI_BASE + 28)
-#define INT_GNT_1                      (INT_PRI_BASE + 29)
-#define INT_OWR                                (INT_PRI_BASE + 30)
-#define INT_SDMMC4                     (INT_PRI_BASE + 31)
-
-/* Secondary Interrupt Controller */
-#define INT_SEC_BASE                   (INT_PRI_BASE + 32)
-#define INT_GPIO1                      (INT_SEC_BASE + 0)
-#define INT_GPIO2                      (INT_SEC_BASE + 1)
-#define INT_GPIO3                      (INT_SEC_BASE + 2)
-#define INT_GPIO4                      (INT_SEC_BASE + 3)
-#define INT_UARTA                      (INT_SEC_BASE + 4)
-#define INT_UARTB                      (INT_SEC_BASE + 5)
-#define INT_I2C                                (INT_SEC_BASE + 6)
-#define INT_SPI                                (INT_SEC_BASE + 7)
-#define INT_TWC                                (INT_SEC_BASE + 8)
-#define INT_TMR3                       (INT_SEC_BASE + 9)
-#define INT_TMR4                       (INT_SEC_BASE + 10)
-#define INT_FLOW_RSM0                  (INT_SEC_BASE + 11)
-#define INT_FLOW_RSM1                  (INT_SEC_BASE + 12)
-#define INT_SPDIF                      (INT_SEC_BASE + 13)
-#define INT_UARTC                      (INT_SEC_BASE + 14)
-#define INT_MIPI                       (INT_SEC_BASE + 15)
-#define INT_EVENTA                     (INT_SEC_BASE + 16)
-#define INT_EVENTB                     (INT_SEC_BASE + 17)
-#define INT_EVENTC                     (INT_SEC_BASE + 18)
-#define INT_EVENTD                     (INT_SEC_BASE + 19)
-#define INT_VFIR                       (INT_SEC_BASE + 20)
-#define INT_DVC                                (INT_SEC_BASE + 21)
-#define INT_SYS_STATS_MON              (INT_SEC_BASE + 22)
-#define INT_GPIO5                      (INT_SEC_BASE + 23)
-#define INT_CPU0_PMU_INTR              (INT_SEC_BASE + 24)
-#define INT_CPU1_PMU_INTR              (INT_SEC_BASE + 25)
-#define INT_SEC_RES_26                 (INT_SEC_BASE + 26)
-#define INT_S_LINK1                    (INT_SEC_BASE + 27)
-#define INT_APB_DMA_COP                        (INT_SEC_BASE + 28)
-#define INT_AHB_DMA_COP                        (INT_SEC_BASE + 29)
-#define INT_DMA_TX                     (INT_SEC_BASE + 30)
-#define INT_DMA_RX                     (INT_SEC_BASE + 31)
-
-/* Tertiary Interrupt Controller */
-#define INT_TRI_BASE                   (INT_SEC_BASE + 32)
-#define INT_HOST1X_COP_SYNCPT          (INT_TRI_BASE + 0)
-#define INT_HOST1X_MPCORE_SYNCPT       (INT_TRI_BASE + 1)
-#define INT_HOST1X_COP_GENERAL         (INT_TRI_BASE + 2)
-#define INT_HOST1X_MPCORE_GENERAL      (INT_TRI_BASE + 3)
-#define INT_MPE_GENERAL                        (INT_TRI_BASE + 4)
-#define INT_VI_GENERAL                 (INT_TRI_BASE + 5)
-#define INT_EPP_GENERAL                        (INT_TRI_BASE + 6)
-#define INT_ISP_GENERAL                        (INT_TRI_BASE + 7)
-#define INT_2D_GENERAL                 (INT_TRI_BASE + 8)
-#define INT_DISPLAY_GENERAL            (INT_TRI_BASE + 9)
-#define INT_DISPLAY_B_GENERAL          (INT_TRI_BASE + 10)
-#define INT_HDMI                       (INT_TRI_BASE + 11)
-#define INT_TVO_GENERAL                        (INT_TRI_BASE + 12)
-#define INT_MC_GENERAL                 (INT_TRI_BASE + 13)
-#define INT_EMC_GENERAL                        (INT_TRI_BASE + 14)
-#define INT_TRI_RES_15                 (INT_TRI_BASE + 15)
-#define INT_TRI_RES_16                 (INT_TRI_BASE + 16)
-#define INT_AC97                       (INT_TRI_BASE + 17)
-#define INT_SPI_2                      (INT_TRI_BASE + 18)
-#define INT_SPI_3                      (INT_TRI_BASE + 19)
-#define INT_I2C2                       (INT_TRI_BASE + 20)
-#define INT_KBC                                (INT_TRI_BASE + 21)
-#define INT_EXTERNAL_PMU               (INT_TRI_BASE + 22)
-#define INT_GPIO6                      (INT_TRI_BASE + 23)
-#define INT_TVDAC                      (INT_TRI_BASE + 24)
-#define INT_GPIO7                      (INT_TRI_BASE + 25)
-#define INT_UARTD                      (INT_TRI_BASE + 26)
-#define INT_UARTE                      (INT_TRI_BASE + 27)
-#define INT_I2C3                       (INT_TRI_BASE + 28)
-#define INT_SPI_4                      (INT_TRI_BASE + 29)
-#define INT_TRI_RES_30                 (INT_TRI_BASE + 30)
-#define INT_SW_RESERVED                        (INT_TRI_BASE + 31)
-
-/* Quaternary Interrupt Controller */
-#define INT_QUAD_BASE                  (INT_TRI_BASE + 32)
-#define INT_SNOR                       (INT_QUAD_BASE + 0)
-#define INT_USB3                       (INT_QUAD_BASE + 1)
-#define INT_PCIE_INTR                  (INT_QUAD_BASE + 2)
-#define INT_PCIE_MSI                   (INT_QUAD_BASE + 3)
-#define INT_QUAD_RES_4                 (INT_QUAD_BASE + 4)
-#define INT_QUAD_RES_5                 (INT_QUAD_BASE + 5)
-#define INT_QUAD_RES_6                 (INT_QUAD_BASE + 6)
-#define INT_QUAD_RES_7                 (INT_QUAD_BASE + 7)
-#define INT_APB_DMA_CH0                        (INT_QUAD_BASE + 8)
-#define INT_APB_DMA_CH1                        (INT_QUAD_BASE + 9)
-#define INT_APB_DMA_CH2                        (INT_QUAD_BASE + 10)
-#define INT_APB_DMA_CH3                        (INT_QUAD_BASE + 11)
-#define INT_APB_DMA_CH4                        (INT_QUAD_BASE + 12)
-#define INT_APB_DMA_CH5                        (INT_QUAD_BASE + 13)
-#define INT_APB_DMA_CH6                        (INT_QUAD_BASE + 14)
-#define INT_APB_DMA_CH7                        (INT_QUAD_BASE + 15)
-#define INT_APB_DMA_CH8                        (INT_QUAD_BASE + 16)
-#define INT_APB_DMA_CH9                        (INT_QUAD_BASE + 17)
-#define INT_APB_DMA_CH10               (INT_QUAD_BASE + 18)
-#define INT_APB_DMA_CH11               (INT_QUAD_BASE + 19)
-#define INT_APB_DMA_CH12               (INT_QUAD_BASE + 20)
-#define INT_APB_DMA_CH13               (INT_QUAD_BASE + 21)
-#define INT_APB_DMA_CH14               (INT_QUAD_BASE + 22)
-#define INT_APB_DMA_CH15               (INT_QUAD_BASE + 23)
-#define INT_QUAD_RES_24                        (INT_QUAD_BASE + 24)
-#define INT_QUAD_RES_25                        (INT_QUAD_BASE + 25)
-#define INT_QUAD_RES_26                        (INT_QUAD_BASE + 26)
-#define INT_QUAD_RES_27                        (INT_QUAD_BASE + 27)
-#define INT_QUAD_RES_28                        (INT_QUAD_BASE + 28)
-#define INT_QUAD_RES_29                        (INT_QUAD_BASE + 29)
-#define INT_QUAD_RES_30                        (INT_QUAD_BASE + 30)
-#define INT_QUAD_RES_31                        (INT_QUAD_BASE + 31)
-
-/* Tegra30 has 5 banks of 32 IRQs */
-#define INT_MAIN_NR                    (32 * 5)
-#define INT_GPIO_BASE                  (INT_PRI_BASE + INT_MAIN_NR)
-
-/* Tegra30 has 8 banks of 32 GPIOs */
-#define INT_GPIO_NR                    (32 * 8)
-
-#define TEGRA_NR_IRQS                  (INT_GPIO_BASE + INT_GPIO_NR)
-
-#define INT_BOARD_BASE                 TEGRA_NR_IRQS
-#define NR_BOARD_IRQS                  32
-
-#define NR_IRQS                                (INT_BOARD_BASE + NR_BOARD_IRQS)
-
-#endif
index 4752b1a68f35503a80ce58703d03dadf897561bb..06763fe7529de15655b72f7cf3ecd4040c5b76a0 100644 (file)
@@ -20,6 +20,8 @@
 #ifndef _MACH_TEGRA_POWERGATE_H_
 #define _MACH_TEGRA_POWERGATE_H_
 
+struct clk;
+
 #define TEGRA_POWERGATE_CPU    0
 #define TEGRA_POWERGATE_3D     1
 #define TEGRA_POWERGATE_VENC   2
index a8dba6489c9b5ee37cc95db9475622f47dcc0e31..e82e8b822f7c098da479b804b684dbd9d2562748 100644 (file)
@@ -43,6 +43,9 @@
 
 #include "board.h"
 
+/* Hack - need to parse this from DT */
+#define INT_PCIE_INTR 130
+
 /* register definitions */
 #define AFI_OFFSET     0x3800
 #define PADS_OFFSET    0x3000
index 81cb26591acf65a2351038cd8a339afb25aa1aff..e50870c720381812fed27a48df02afcf05067097 100644 (file)
@@ -24,7 +24,6 @@
 #include <asm/mach-types.h>
 #include <asm/smp_scu.h>
 
-#include <mach/clk.h>
 #include <mach/iomap.h>
 #include <mach/powergate.h>
 
index a36ae413e2b84fcee956b74577df8da740932cee..72ce709799dac5e55cff19b5d279d6e5aceca4b8 100644 (file)
@@ -22,8 +22,6 @@
 
 #include <asm/assembler.h>
 
-#include <mach/iomap.h>
-
 #include "sleep.h"
 #include "flowctrl.h"
 
index 777d9cee8b9000be99ab07bbc21211146960f35f..be7614b7c5cb5304e20d2b42fbfad4e75cec5568 100644 (file)
@@ -18,8 +18,6 @@
 
 #include <asm/assembler.h>
 
-#include <mach/iomap.h>
-
 #include "sleep.h"
 #include "flowctrl.h"
 
index cc9b5fd8c3d314d10c560074f9b833cb69bad4bc..9615ee39c353305c54cff1a8c269c92f11269d94 100644 (file)
@@ -27,8 +27,6 @@
 #include <linux/io.h>
 #include <linux/clk.h>
 
-#include <mach/iomap.h>
-
 #include "clock.h"
 #include "fuse.h"
 #include "tegra2_emc.h"
@@ -953,6 +951,7 @@ PERIPH_CLK(pcie_xclk,       NULL,             "pcie_xclk",  74,     0,      26000000,  mux_clk_m,
 static struct clk *tegra_list_clks[] = {
        &tegra_apbdma,
        &tegra_rtc,
+       &tegra_timer,
        &tegra_i2s1,
        &tegra_i2s2,
        &tegra_spdif_out,
index 5070d833bdd1ebbf3df1763353f155e66b97d04a..837c7b9ea63b1c6561a6fbb13397f36da2ff75a3 100644 (file)
@@ -25,8 +25,6 @@
 #include <linux/platform_device.h>
 #include <linux/platform_data/tegra_emc.h>
 
-#include <mach/iomap.h>
-
 #include "tegra2_emc.h"
 #include "fuse.h"
 
index 5cd502c271631d24a9c4e18af47afa5f8f752d1f..e9de5dfd94ec339e5f5c0c7c15eaad1f5a7944c4 100644 (file)
@@ -1199,7 +1199,7 @@ static long tegra30_pll_round_rate(struct clk_hw *hw, unsigned long rate,
 {
        struct clk_tegra *c = to_clk_tegra(hw);
        unsigned long input_rate = *prate;
-       unsigned long output_rate = *prate;
+       u64 output_rate = *prate;
        const struct clk_pll_freq_table *sel;
        struct clk_pll_freq_table cfg;
        int mul;
index d92cb556ae351fb81b1a581133ac6400a3d84352..3d2e5532a9ea27d4a9eb561ddd1db0f65ecf46a0 100644 (file)
@@ -1143,6 +1143,7 @@ struct clk *tegra_list_clks[] = {
        &tegra_apbdma,
        &tegra_rtc,
        &tegra_kbc,
+       &tegra_timer,
        &tegra_kfuse,
        &tegra_fuse,
        &tegra_fuse_burn,
index eccdce983043a46439b67610c3fe2488c937faca..74972fd7cc563583028d2707e0ed04da95915e80 100644 (file)
 #include <linux/clocksource.h>
 #include <linux/clk.h>
 #include <linux/io.h>
+#include <linux/of_irq.h>
 
 #include <asm/mach/time.h>
 #include <asm/smp_twd.h>
 #include <asm/sched_clock.h>
 
 #include <mach/iomap.h>
-#include <mach/irqs.h>
 
 #include "board.h"
 #include "clock.h"
@@ -158,30 +158,32 @@ static struct irqaction tegra_timer_irq = {
        .flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_TRIGGER_HIGH,
        .handler        = tegra_timer_interrupt,
        .dev_id         = &tegra_clockevent,
-       .irq            = INT_TMR3,
 };
 
-#ifdef CONFIG_HAVE_ARM_TWD
-static DEFINE_TWD_LOCAL_TIMER(twd_local_timer,
-                             TEGRA_ARM_PERIF_BASE + 0x600,
-                             IRQ_LOCALTIMER);
-
-static void __init tegra_twd_init(void)
-{
-       int err = twd_local_timer_register(&twd_local_timer);
-       if (err)
-               pr_err("twd_local_timer_register failed %d\n", err);
-}
-#else
-#define tegra_twd_init()       do {} while(0)
-#endif
+static const struct of_device_id timer_match[] __initconst = {
+       { .compatible = "nvidia,tegra20-timer" },
+       {}
+};
 
 static void __init tegra_init_timer(void)
 {
+       struct device_node *np;
        struct clk *clk;
        unsigned long rate;
        int ret;
 
+       np = of_find_matching_node(NULL, timer_match);
+       if (!np) {
+               pr_err("Failed to find timer DT node\n");
+               BUG();
+       }
+
+       tegra_timer_irq.irq = irq_of_parse_and_map(np, 2);
+       if (tegra_timer_irq.irq <= 0) {
+               pr_err("Failed to map timer IRQ\n");
+               BUG();
+       }
+
        clk = clk_get_sys("timer", NULL);
        if (IS_ERR(clk)) {
                pr_warn("Unable to get timer clock."
@@ -202,6 +204,8 @@ static void __init tegra_init_timer(void)
        else
                clk_prepare_enable(clk);
 
+       of_node_put(np);
+
        switch (rate) {
        case 12000000:
                timer_writel(0x000b, TIMERUS_USEC_CFG);
@@ -241,11 +245,13 @@ static void __init tegra_init_timer(void)
        tegra_clockevent.cpumask = cpu_all_mask;
        tegra_clockevent.irq = tegra_timer_irq.irq;
        clockevents_register_device(&tegra_clockevent);
-       tegra_twd_init();
+#ifdef CONFIG_HAVE_ARM_TWD
+       twd_local_timer_of_register();
+#endif
        register_persistent_clock(NULL, tegra_read_persistent_clock);
 }
 
-struct sys_timer tegra_timer = {
+struct sys_timer tegra_sys_timer = {
        .init = tegra_init_timer,
 };
 
index b8efac4daed89256a8e9dc0257c940af05033fa4..4f964fc202664ed37b5c9e55520efc0987ddffda 100644 (file)
@@ -251,6 +251,18 @@ static struct resource rtc_resources[] = {
  * but these are not yet used by the driver.
  */
 static struct resource fsmc_resources[] = {
+       {
+               .name  = "nand_addr",
+               .start = U300_NAND_CS0_PHYS_BASE + PLAT_NAND_ALE,
+               .end   = U300_NAND_CS0_PHYS_BASE + PLAT_NAND_ALE + SZ_16K - 1,
+               .flags = IORESOURCE_MEM,
+       },
+       {
+               .name  = "nand_cmd",
+               .start = U300_NAND_CS0_PHYS_BASE + PLAT_NAND_CLE,
+               .end   = U300_NAND_CS0_PHYS_BASE + PLAT_NAND_CLE + SZ_16K - 1,
+               .flags = IORESOURCE_MEM,
+       },
        {
                .name  = "nand_data",
                .start = U300_NAND_CS0_PHYS_BASE,
@@ -1445,7 +1457,6 @@ static struct platform_device pinctrl_device = {
 static struct u300_gpio_platform u300_gpio_plat = {
        .ports = 7,
        .gpio_base = 0,
-       .gpio_irq_base = IRQ_U300_GPIO_BASE,
        .pinctrl_device = &pinctrl_device,
 };
 
@@ -1496,8 +1507,6 @@ static struct fsmc_nand_platform_data nand_platform_data = {
        .nr_partitions = ARRAY_SIZE(u300_partitions),
        .options = NAND_SKIP_BBTSCAN,
        .width = FSMC_NAND_BW8,
-       .ale_off = PLAT_NAND_ALE,
-       .cle_off = PLAT_NAND_CLE,
 };
 
 static struct platform_device nand_device = {
@@ -1804,7 +1813,7 @@ MACHINE_START(U300, "Ericsson AB U335 S335/B335 Prototype Board")
        /* Maintainer: Linus Walleij <linus.walleij@stericsson.com> */
        .atag_offset    = 0x100,
        .map_io         = u300_map_io,
-       .nr_irqs        = NR_IRQS_U300,
+       .nr_irqs        = 0,
        .init_irq       = u300_init_irq,
        .handle_irq     = vic_handle_irq,
        .timer          = &u300_timer,
index e27425a63fa1418837b4becaa23256e0ccbe6706..21d5e76a6cd3da0f123233872c8ebbfa093fb3d5 100644 (file)
 #ifndef __MACH_IRQS_H
 #define __MACH_IRQS_H
 
-#define IRQ_U300_INTCON0_START         1
-#define IRQ_U300_INTCON1_START         33
+#define IRQ_U300_INTCON0_START         32
+#define IRQ_U300_INTCON1_START         64
 /* These are on INTCON0 - 30 lines */
-#define IRQ_U300_IRQ0_EXT              1
-#define IRQ_U300_IRQ1_EXT              2
-#define IRQ_U300_DMA                   3
-#define IRQ_U300_VIDEO_ENC_0           4
-#define IRQ_U300_VIDEO_ENC_1           5
-#define IRQ_U300_AAIF_RX               6
-#define IRQ_U300_AAIF_TX               7
-#define IRQ_U300_AAIF_VGPIO            8
-#define IRQ_U300_AAIF_WAKEUP           9
-#define IRQ_U300_PCM_I2S0_FRAME                10
-#define IRQ_U300_PCM_I2S0_FIFO         11
-#define IRQ_U300_PCM_I2S1_FRAME                12
-#define IRQ_U300_PCM_I2S1_FIFO         13
-#define IRQ_U300_XGAM_GAMCON           14
-#define IRQ_U300_XGAM_CDI              15
-#define IRQ_U300_XGAM_CDICON           16
-#define IRQ_U300_XGAM_PDI              18
-#define IRQ_U300_XGAM_PDICON           19
-#define IRQ_U300_XGAM_GAMEACC          20
-#define IRQ_U300_XGAM_MCIDCT           21
-#define IRQ_U300_APEX                  22
-#define IRQ_U300_UART0                 23
-#define IRQ_U300_SPI                   24
-#define IRQ_U300_TIMER_APP_OS          25
-#define IRQ_U300_TIMER_APP_DD          26
-#define IRQ_U300_TIMER_APP_GP1         27
-#define IRQ_U300_TIMER_APP_GP2         28
-#define IRQ_U300_TIMER_OS              29
-#define IRQ_U300_TIMER_MS              30
-#define IRQ_U300_KEYPAD_KEYBF          31
-#define IRQ_U300_KEYPAD_KEYBR          32
+#define IRQ_U300_IRQ0_EXT              32
+#define IRQ_U300_IRQ1_EXT              33
+#define IRQ_U300_DMA                   34
+#define IRQ_U300_VIDEO_ENC_0           35
+#define IRQ_U300_VIDEO_ENC_1           36
+#define IRQ_U300_AAIF_RX               37
+#define IRQ_U300_AAIF_TX               38
+#define IRQ_U300_AAIF_VGPIO            39
+#define IRQ_U300_AAIF_WAKEUP           40
+#define IRQ_U300_PCM_I2S0_FRAME                41
+#define IRQ_U300_PCM_I2S0_FIFO         42
+#define IRQ_U300_PCM_I2S1_FRAME                43
+#define IRQ_U300_PCM_I2S1_FIFO         44
+#define IRQ_U300_XGAM_GAMCON           45
+#define IRQ_U300_XGAM_CDI              46
+#define IRQ_U300_XGAM_CDICON           47
+#define IRQ_U300_XGAM_PDI              49
+#define IRQ_U300_XGAM_PDICON           50
+#define IRQ_U300_XGAM_GAMEACC          51
+#define IRQ_U300_XGAM_MCIDCT           52
+#define IRQ_U300_APEX                  53
+#define IRQ_U300_UART0                 54
+#define IRQ_U300_SPI                   55
+#define IRQ_U300_TIMER_APP_OS          56
+#define IRQ_U300_TIMER_APP_DD          57
+#define IRQ_U300_TIMER_APP_GP1         58
+#define IRQ_U300_TIMER_APP_GP2         59
+#define IRQ_U300_TIMER_OS              60
+#define IRQ_U300_TIMER_MS              61
+#define IRQ_U300_KEYPAD_KEYBF          62
+#define IRQ_U300_KEYPAD_KEYBR          63
 /* These are on INTCON1 - 32 lines */
-#define IRQ_U300_GPIO_PORT0            33
-#define IRQ_U300_GPIO_PORT1            34
-#define IRQ_U300_GPIO_PORT2            35
+#define IRQ_U300_GPIO_PORT0            64
+#define IRQ_U300_GPIO_PORT1            65
+#define IRQ_U300_GPIO_PORT2            66
 
 /* These are for DB3150, DB3200 and DB3350 */
-#define IRQ_U300_WDOG                  36
-#define IRQ_U300_EVHIST                        37
-#define IRQ_U300_MSPRO                 38
-#define IRQ_U300_MMCSD_MCIINTR0                39
-#define IRQ_U300_MMCSD_MCIINTR1                40
-#define IRQ_U300_I2C0                  41
-#define IRQ_U300_I2C1                  42
-#define IRQ_U300_RTC                   43
-#define IRQ_U300_NFIF                  44
-#define IRQ_U300_NFIF2                 45
+#define IRQ_U300_WDOG                  67
+#define IRQ_U300_EVHIST                        68
+#define IRQ_U300_MSPRO                 69
+#define IRQ_U300_MMCSD_MCIINTR0                70
+#define IRQ_U300_MMCSD_MCIINTR1                71
+#define IRQ_U300_I2C0                  72
+#define IRQ_U300_I2C1                  73
+#define IRQ_U300_RTC                   74
+#define IRQ_U300_NFIF                  75
+#define IRQ_U300_NFIF2                 76
 
 /* The DB3350-specific interrupt lines */
-#define IRQ_U300_ISP_F0                        46
-#define IRQ_U300_ISP_F1                        47
-#define IRQ_U300_ISP_F2                        48
-#define IRQ_U300_ISP_F3                        49
-#define IRQ_U300_ISP_F4                        50
-#define IRQ_U300_GPIO_PORT3            51
-#define IRQ_U300_SYSCON_PLL_LOCK       52
-#define IRQ_U300_UART1                 53
-#define IRQ_U300_GPIO_PORT4            54
-#define IRQ_U300_GPIO_PORT5            55
-#define IRQ_U300_GPIO_PORT6            56
-#define U300_VIC_IRQS_END              57
-
-/* Maximum 8*7 GPIO lines */
-#ifdef CONFIG_PINCTRL_COH901
-#define IRQ_U300_GPIO_BASE             (U300_VIC_IRQS_END)
-#define IRQ_U300_GPIO_END              (IRQ_U300_GPIO_BASE + 56)
-#else
-#define IRQ_U300_GPIO_END              (U300_VIC_IRQS_END)
-#endif
-
-#define NR_IRQS_U300                   (IRQ_U300_GPIO_END - IRQ_U300_INTCON0_START)
+#define IRQ_U300_ISP_F0                        77
+#define IRQ_U300_ISP_F1                        78
+#define IRQ_U300_ISP_F2                        79
+#define IRQ_U300_ISP_F3                        80
+#define IRQ_U300_ISP_F4                        81
+#define IRQ_U300_GPIO_PORT3            82
+#define IRQ_U300_SYSCON_PLL_LOCK       83
+#define IRQ_U300_UART1                 84
+#define IRQ_U300_GPIO_PORT4            85
+#define IRQ_U300_GPIO_PORT5            86
+#define IRQ_U300_GPIO_PORT6            87
+#define U300_VIC_IRQS_END              88
 
 #endif
index 070629a95625a9b7f3a5bfd0921d419a779966fc..33631c9f121802d447ecd38fa7f6bee4af955e18 100644 (file)
@@ -7,9 +7,8 @@
 #include <linux/platform_device.h>
 #include <linux/init.h>
 #include <linux/gpio.h>
+#include <linux/platform_data/pinctrl-nomadik.h>
 
-#include <plat/gpio-nomadik.h>
-#include <plat/pincfg.h>
 #include <plat/ste_dma40.h>
 
 #include <mach/devices.h>
index a267c6d30e374f19c491244ad23fd93b07aa85d1..c34d4efd0d5c46987775b47c1393349760d60c27 100644 (file)
@@ -9,10 +9,9 @@
 #include <linux/bug.h>
 #include <linux/string.h>
 #include <linux/pinctrl/machine.h>
+#include <linux/platform_data/pinctrl-nomadik.h>
 
 #include <asm/mach-types.h>
-#include <plat/pincfg.h>
-#include <plat/gpio-nomadik.h>
 
 #include <mach/hardware.h>
 
index 416d436111f29bbc64c267f104ab2838cf3db0ac..0a3dd601a400c4cddeba32a945d2461bde52797a 100644 (file)
 #include <linux/of_platform.h>
 #include <linux/leds.h>
 #include <linux/pinctrl/consumer.h>
+#include <linux/platform_data/pinctrl-nomadik.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/hardware/gic.h>
 
 #include <plat/ste_dma40.h>
-#include <plat/gpio-nomadik.h>
 
 #include <mach/hardware.h>
 #include <mach/setup.h>
index bcdfe6b1d4534e72dc952cfa989a98ac57d84b70..87a8f9fbb100b05b1c2eac4f9bbb9ed4da0f767b 100644 (file)
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/mfd/abx500/ab8500.h>
+#include <linux/platform_data/usb-musb-ux500.h>
+#include <linux/platform_data/pinctrl-nomadik.h>
 
 #include <asm/pmu.h>
 #include <asm/mach/map.h>
-#include <plat/gpio-nomadik.h>
 #include <mach/hardware.h>
 #include <mach/setup.h>
 #include <mach/devices.h>
-#include <linux/platform_data/usb-musb-ux500.h>
 #include <mach/db8500-regs.h>
 
 #include "devices-db8500.h"
index dfdd4a54668dfb4c85dfdb9a703f714b40a69bdc..692a77a1c1536eb045b714559b17d0e68aac78de 100644 (file)
@@ -11,8 +11,7 @@
 #include <linux/irq.h>
 #include <linux/slab.h>
 #include <linux/platform_device.h>
-
-#include <plat/gpio-nomadik.h>
+#include <linux/platform_data/pinctrl-nomadik.h>
 
 #include <mach/hardware.h>
 
diff --git a/arch/arm/mach-vt8500/include/mach/hardware.h b/arch/arm/mach-vt8500/include/mach/hardware.h
deleted file mode 100644 (file)
index db4163f..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-/* arch/arm/mach-vt8500/include/mach/hardware.h
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
diff --git a/arch/arm/mach-vt8500/include/mach/i8042.h b/arch/arm/mach-vt8500/include/mach/i8042.h
deleted file mode 100644 (file)
index cd7143c..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-/* arch/arm/mach-vt8500/include/mach/i8042.h
- *
- * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-extern unsigned long wmt_i8042_base __initdata;
-extern int wmt_i8042_kbd_irq;
-extern int wmt_i8042_aux_irq;
diff --git a/arch/arm/mach-vt8500/include/mach/restart.h b/arch/arm/mach-vt8500/include/mach/restart.h
deleted file mode 100644 (file)
index 7389795..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/* linux/arch/arm/mach-vt8500/restart.h
- *
- * Copyright (C) 2012 Tony Prisk <linux@prisktech.co.nz>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-void vt8500_setup_restart(void);
-void vt8500_restart(char mode, const char *cmd);
index 050e1833f2d0078ed62134a0305cc71bc0378b8b..3dd21a47881ff2c83ed384e36faa77213ad834f7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  arch/arm/mach-vt8500/timer_dt.c
+ *  arch/arm/mach-vt8500/timer.c
  *
  *  Copyright (C) 2012 Tony Prisk <linux@prisktech.co.nz>
  *  Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
index 8d3871f110a5533ba6f1db6c42302a798de52edb..a5bd28692b06e96eae2c8a3cf2339d81ccd9b796 100644 (file)
@@ -31,8 +31,6 @@
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
 
-#include <mach/restart.h>
-
 #include "common.h"
 
 #define LEGACY_GPIO_BASE       0xD8110000
index b9f60ebe3bc4f13f3dc13e4e4531da549890eca4..9bb58f79489459b7ee369c9639f2f02dc6660311 100644 (file)
@@ -856,8 +856,10 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
                if (thumb2_32b) {
                        offset.un = 0;
                        handler = do_alignment_t32_to_handler(&instr, regs, &offset);
-               } else
+               } else {
+                       offset.un = 0;
                        handler = do_alignment_ldmstm;
+               }
                break;
 
        default:
@@ -962,12 +964,14 @@ static int __init alignment_init(void)
                return -ENOMEM;
 #endif
 
+#ifdef CONFIG_CPU_CP15
        if (cpu_is_v6_unaligned()) {
                cr_alignment &= ~CR_A;
                cr_no_alignment &= ~CR_A;
                set_cr(cr_alignment);
                ai_usermode = safe_usermode(ai_usermode, false);
        }
+#endif
 
        hook_fault_code(FAULT_CODE_ALIGNMENT, do_alignment, SIGBUS, BUS_ADRALN,
                        "alignment exception");
diff --git a/arch/arm/mm/cache-aurora-l2.h b/arch/arm/mm/cache-aurora-l2.h
new file mode 100644 (file)
index 0000000..c861247
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * AURORA shared L2 cache controller support
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Yehuda Yitschak <yehuday@marvell.com>
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __ASM_ARM_HARDWARE_AURORA_L2_H
+#define __ASM_ARM_HARDWARE_AURORA_L2_H
+
+#define AURORA_SYNC_REG                    0x700
+#define AURORA_RANGE_BASE_ADDR_REG  0x720
+#define AURORA_FLUSH_PHY_ADDR_REG   0x7f0
+#define AURORA_INVAL_RANGE_REG     0x774
+#define AURORA_CLEAN_RANGE_REG     0x7b4
+#define AURORA_FLUSH_RANGE_REG     0x7f4
+
+#define AURORA_ACR_REPLACEMENT_OFFSET      27
+#define AURORA_ACR_REPLACEMENT_MASK         \
+       (0x3 << AURORA_ACR_REPLACEMENT_OFFSET)
+#define AURORA_ACR_REPLACEMENT_TYPE_WAYRR    \
+       (0 << AURORA_ACR_REPLACEMENT_OFFSET)
+#define AURORA_ACR_REPLACEMENT_TYPE_LFSR     \
+       (1 << AURORA_ACR_REPLACEMENT_OFFSET)
+#define AURORA_ACR_REPLACEMENT_TYPE_SEMIPLRU \
+       (3 << AURORA_ACR_REPLACEMENT_OFFSET)
+
+#define AURORA_ACR_FORCE_WRITE_POLICY_OFFSET   0
+#define AURORA_ACR_FORCE_WRITE_POLICY_MASK     \
+       (0x3 << AURORA_ACR_FORCE_WRITE_POLICY_OFFSET)
+#define AURORA_ACR_FORCE_WRITE_POLICY_DIS      \
+       (0 << AURORA_ACR_FORCE_WRITE_POLICY_OFFSET)
+#define AURORA_ACR_FORCE_WRITE_BACK_POLICY     \
+       (1 << AURORA_ACR_FORCE_WRITE_POLICY_OFFSET)
+#define AURORA_ACR_FORCE_WRITE_THRO_POLICY     \
+       (2 << AURORA_ACR_FORCE_WRITE_POLICY_OFFSET)
+
+#define MAX_RANGE_SIZE         1024
+
+#define AURORA_WAY_SIZE_SHIFT  2
+
+#define AURORA_CTRL_FW         0x100
+
+/* chose a number outside L2X0_CACHE_ID_PART_MASK to be sure to make
+ * the distinction between a number coming from hardware and a number
+ * coming from the device tree */
+#define AURORA_CACHE_ID               0x100
+
+#endif /* __ASM_ARM_HARDWARE_AURORA_L2_H */
index 8a97e6443c62935f3083a950590cd13ce6b4de90..bfb5986b32cb69c36a5945dfabd5c7aa9042b0a5 100644 (file)
@@ -25,6 +25,7 @@
 
 #include <asm/cacheflush.h>
 #include <asm/hardware/cache-l2x0.h>
+#include "cache-aurora-l2.h"
 
 #define CACHE_LINE_SIZE                32
 
@@ -33,15 +34,22 @@ static DEFINE_RAW_SPINLOCK(l2x0_lock);
 static u32 l2x0_way_mask;      /* Bitmask of active ways */
 static u32 l2x0_size;
 static unsigned long sync_reg_offset = L2X0_CACHE_SYNC;
+static int l2_wt_override;
+
+/* Aurora don't have the cache ID register available, so we have to
+ * pass it though the device tree */
+static u32  cache_id_part_number_from_dt;
 
 struct l2x0_regs l2x0_saved_regs;
 
 struct l2x0_of_data {
        void (*setup)(const struct device_node *, u32 *, u32 *);
        void (*save)(void);
-       void (*resume)(void);
+       struct outer_cache_fns outer_cache;
 };
 
+static bool of_init = false;
+
 static inline void cache_wait_way(void __iomem *reg, unsigned long mask)
 {
        /* wait for cache operation by line or way to complete */
@@ -168,7 +176,7 @@ static void l2x0_inv_all(void)
        /* invalidate all ways */
        raw_spin_lock_irqsave(&l2x0_lock, flags);
        /* Invalidating when L2 is enabled is a nono */
-       BUG_ON(readl(l2x0_base + L2X0_CTRL) & 1);
+       BUG_ON(readl(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN);
        writel_relaxed(l2x0_way_mask, l2x0_base + L2X0_INV_WAY);
        cache_wait_way(l2x0_base + L2X0_INV_WAY, l2x0_way_mask);
        cache_sync();
@@ -276,6 +284,98 @@ static void l2x0_flush_range(unsigned long start, unsigned long end)
        raw_spin_unlock_irqrestore(&l2x0_lock, flags);
 }
 
+/*
+ * Note that the end addresses passed to Linux primitives are
+ * noninclusive, while the hardware cache range operations use
+ * inclusive start and end addresses.
+ */
+static unsigned long calc_range_end(unsigned long start, unsigned long end)
+{
+       /*
+        * Limit the number of cache lines processed at once,
+        * since cache range operations stall the CPU pipeline
+        * until completion.
+        */
+       if (end > start + MAX_RANGE_SIZE)
+               end = start + MAX_RANGE_SIZE;
+
+       /*
+        * Cache range operations can't straddle a page boundary.
+        */
+       if (end > PAGE_ALIGN(start+1))
+               end = PAGE_ALIGN(start+1);
+
+       return end;
+}
+
+/*
+ * Make sure 'start' and 'end' reference the same page, as L2 is PIPT
+ * and range operations only do a TLB lookup on the start address.
+ */
+static void aurora_pa_range(unsigned long start, unsigned long end,
+                       unsigned long offset)
+{
+       unsigned long flags;
+
+       raw_spin_lock_irqsave(&l2x0_lock, flags);
+       writel_relaxed(start, l2x0_base + AURORA_RANGE_BASE_ADDR_REG);
+       writel_relaxed(end, l2x0_base + offset);
+       raw_spin_unlock_irqrestore(&l2x0_lock, flags);
+
+       cache_sync();
+}
+
+static void aurora_inv_range(unsigned long start, unsigned long end)
+{
+       /*
+        * round start and end adresses up to cache line size
+        */
+       start &= ~(CACHE_LINE_SIZE - 1);
+       end = ALIGN(end, CACHE_LINE_SIZE);
+
+       /*
+        * Invalidate all full cache lines between 'start' and 'end'.
+        */
+       while (start < end) {
+               unsigned long range_end = calc_range_end(start, end);
+               aurora_pa_range(start, range_end - CACHE_LINE_SIZE,
+                               AURORA_INVAL_RANGE_REG);
+               start = range_end;
+       }
+}
+
+static void aurora_clean_range(unsigned long start, unsigned long end)
+{
+       /*
+        * If L2 is forced to WT, the L2 will always be clean and we
+        * don't need to do anything here.
+        */
+       if (!l2_wt_override) {
+               start &= ~(CACHE_LINE_SIZE - 1);
+               end = ALIGN(end, CACHE_LINE_SIZE);
+               while (start != end) {
+                       unsigned long range_end = calc_range_end(start, end);
+                       aurora_pa_range(start, range_end - CACHE_LINE_SIZE,
+                                       AURORA_CLEAN_RANGE_REG);
+                       start = range_end;
+               }
+       }
+}
+
+static void aurora_flush_range(unsigned long start, unsigned long end)
+{
+       if (!l2_wt_override) {
+               start &= ~(CACHE_LINE_SIZE - 1);
+               end = ALIGN(end, CACHE_LINE_SIZE);
+               while (start != end) {
+                       unsigned long range_end = calc_range_end(start, end);
+                       aurora_pa_range(start, range_end - CACHE_LINE_SIZE,
+                                       AURORA_FLUSH_RANGE_REG);
+                       start = range_end;
+               }
+       }
+}
+
 static void l2x0_disable(void)
 {
        unsigned long flags;
@@ -292,11 +392,18 @@ static void l2x0_unlock(u32 cache_id)
        int lockregs;
        int i;
 
-       if (cache_id == L2X0_CACHE_ID_PART_L310)
+       switch (cache_id) {
+       case L2X0_CACHE_ID_PART_L310:
                lockregs = 8;
-       else
+               break;
+       case AURORA_CACHE_ID:
+               lockregs = 4;
+               break;
+       default:
                /* L210 and unknown types */
                lockregs = 1;
+               break;
+       }
 
        for (i = 0; i < lockregs; i++) {
                writel_relaxed(0x0, l2x0_base + L2X0_LOCKDOWN_WAY_D_BASE +
@@ -312,18 +419,22 @@ void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask)
        u32 cache_id;
        u32 way_size = 0;
        int ways;
+       int way_size_shift = L2X0_WAY_SIZE_SHIFT;
        const char *type;
 
        l2x0_base = base;
-
-       cache_id = readl_relaxed(l2x0_base + L2X0_CACHE_ID);
+       if (cache_id_part_number_from_dt)
+               cache_id = cache_id_part_number_from_dt;
+       else
+               cache_id = readl_relaxed(l2x0_base + L2X0_CACHE_ID)
+                       & L2X0_CACHE_ID_PART_MASK;
        aux = readl_relaxed(l2x0_base + L2X0_AUX_CTRL);
 
        aux &= aux_mask;
        aux |= aux_val;
 
        /* Determine the number of ways */
-       switch (cache_id & L2X0_CACHE_ID_PART_MASK) {
+       switch (cache_id) {
        case L2X0_CACHE_ID_PART_L310:
                if (aux & (1 << 16))
                        ways = 16;
@@ -340,6 +451,14 @@ void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask)
                ways = (aux >> 13) & 0xf;
                type = "L210";
                break;
+
+       case AURORA_CACHE_ID:
+               sync_reg_offset = AURORA_SYNC_REG;
+               ways = (aux >> 13) & 0xf;
+               ways = 2 << ((ways + 1) >> 2);
+               way_size_shift = AURORA_WAY_SIZE_SHIFT;
+               type = "Aurora";
+               break;
        default:
                /* Assume unknown chips have 8 ways */
                ways = 8;
@@ -353,7 +472,8 @@ void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask)
         * L2 cache Size =  Way size * Number of ways
         */
        way_size = (aux & L2X0_AUX_CTRL_WAY_SIZE_MASK) >> 17;
-       way_size = 1 << (way_size + 3);
+       way_size = 1 << (way_size + way_size_shift);
+
        l2x0_size = ways * way_size * SZ_1K;
 
        /*
@@ -361,7 +481,7 @@ void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask)
         * If you are booting from non-secure mode
         * accessing the below registers will fault.
         */
-       if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & 1)) {
+       if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) {
                /* Make sure that I&D is not locked down when starting */
                l2x0_unlock(cache_id);
 
@@ -371,7 +491,7 @@ void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask)
                l2x0_inv_all();
 
                /* enable L2X0 */
-               writel_relaxed(1, l2x0_base + L2X0_CTRL);
+               writel_relaxed(L2X0_CTRL_EN, l2x0_base + L2X0_CTRL);
        }
 
        /* Re-read it in case some bits are reserved. */
@@ -380,13 +500,15 @@ void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask)
        /* Save the value for resuming. */
        l2x0_saved_regs.aux_ctrl = aux;
 
-       outer_cache.inv_range = l2x0_inv_range;
-       outer_cache.clean_range = l2x0_clean_range;
-       outer_cache.flush_range = l2x0_flush_range;
-       outer_cache.sync = l2x0_cache_sync;
-       outer_cache.flush_all = l2x0_flush_all;
-       outer_cache.inv_all = l2x0_inv_all;
-       outer_cache.disable = l2x0_disable;
+       if (!of_init) {
+               outer_cache.inv_range = l2x0_inv_range;
+               outer_cache.clean_range = l2x0_clean_range;
+               outer_cache.flush_range = l2x0_flush_range;
+               outer_cache.sync = l2x0_cache_sync;
+               outer_cache.flush_all = l2x0_flush_all;
+               outer_cache.inv_all = l2x0_inv_all;
+               outer_cache.disable = l2x0_disable;
+       }
 
        printk(KERN_INFO "%s cache controller enabled\n", type);
        printk(KERN_INFO "l2x0: %d ways, CACHE_ID 0x%08x, AUX_CTRL 0x%08x, Cache size: %d B\n",
@@ -491,9 +613,15 @@ static void __init pl310_save(void)
        }
 }
 
+static void aurora_save(void)
+{
+       l2x0_saved_regs.ctrl = readl_relaxed(l2x0_base + L2X0_CTRL);
+       l2x0_saved_regs.aux_ctrl = readl_relaxed(l2x0_base + L2X0_AUX_CTRL);
+}
+
 static void l2x0_resume(void)
 {
-       if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & 1)) {
+       if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) {
                /* restore aux ctrl and enable l2 */
                l2x0_unlock(readl_relaxed(l2x0_base + L2X0_CACHE_ID));
 
@@ -502,7 +630,7 @@ static void l2x0_resume(void)
 
                l2x0_inv_all();
 
-               writel_relaxed(1, l2x0_base + L2X0_CTRL);
+               writel_relaxed(L2X0_CTRL_EN, l2x0_base + L2X0_CTRL);
        }
 }
 
@@ -510,7 +638,7 @@ static void pl310_resume(void)
 {
        u32 l2x0_revision;
 
-       if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & 1)) {
+       if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) {
                /* restore pl310 setup */
                writel_relaxed(l2x0_saved_regs.tag_latency,
                        l2x0_base + L2X0_TAG_LATENCY_CTRL);
@@ -536,22 +664,108 @@ static void pl310_resume(void)
        l2x0_resume();
 }
 
+static void aurora_resume(void)
+{
+       if (!(readl(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) {
+               writel(l2x0_saved_regs.aux_ctrl, l2x0_base + L2X0_AUX_CTRL);
+               writel(l2x0_saved_regs.ctrl, l2x0_base + L2X0_CTRL);
+       }
+}
+
+static void __init aurora_broadcast_l2_commands(void)
+{
+       __u32 u;
+       /* Enable Broadcasting of cache commands to L2*/
+       __asm__ __volatile__("mrc p15, 1, %0, c15, c2, 0" : "=r"(u));
+       u |= AURORA_CTRL_FW;            /* Set the FW bit */
+       __asm__ __volatile__("mcr p15, 1, %0, c15, c2, 0\n" : : "r"(u));
+       isb();
+}
+
+static void __init aurora_of_setup(const struct device_node *np,
+                               u32 *aux_val, u32 *aux_mask)
+{
+       u32 val = AURORA_ACR_REPLACEMENT_TYPE_SEMIPLRU;
+       u32 mask =  AURORA_ACR_REPLACEMENT_MASK;
+
+       of_property_read_u32(np, "cache-id-part",
+                       &cache_id_part_number_from_dt);
+
+       /* Determine and save the write policy */
+       l2_wt_override = of_property_read_bool(np, "wt-override");
+
+       if (l2_wt_override) {
+               val |= AURORA_ACR_FORCE_WRITE_THRO_POLICY;
+               mask |= AURORA_ACR_FORCE_WRITE_POLICY_MASK;
+       }
+
+       *aux_val &= ~mask;
+       *aux_val |= val;
+       *aux_mask &= ~mask;
+}
+
 static const struct l2x0_of_data pl310_data = {
-       pl310_of_setup,
-       pl310_save,
-       pl310_resume,
+       .setup = pl310_of_setup,
+       .save  = pl310_save,
+       .outer_cache = {
+               .resume      = pl310_resume,
+               .inv_range   = l2x0_inv_range,
+               .clean_range = l2x0_clean_range,
+               .flush_range = l2x0_flush_range,
+               .sync        = l2x0_cache_sync,
+               .flush_all   = l2x0_flush_all,
+               .inv_all     = l2x0_inv_all,
+               .disable     = l2x0_disable,
+               .set_debug   = pl310_set_debug,
+       },
 };
 
 static const struct l2x0_of_data l2x0_data = {
-       l2x0_of_setup,
-       NULL,
-       l2x0_resume,
+       .setup = l2x0_of_setup,
+       .save  = NULL,
+       .outer_cache = {
+               .resume      = l2x0_resume,
+               .inv_range   = l2x0_inv_range,
+               .clean_range = l2x0_clean_range,
+               .flush_range = l2x0_flush_range,
+               .sync        = l2x0_cache_sync,
+               .flush_all   = l2x0_flush_all,
+               .inv_all     = l2x0_inv_all,
+               .disable     = l2x0_disable,
+       },
+};
+
+static const struct l2x0_of_data aurora_with_outer_data = {
+       .setup = aurora_of_setup,
+       .save  = aurora_save,
+       .outer_cache = {
+               .resume      = aurora_resume,
+               .inv_range   = aurora_inv_range,
+               .clean_range = aurora_clean_range,
+               .flush_range = aurora_flush_range,
+               .sync        = l2x0_cache_sync,
+               .flush_all   = l2x0_flush_all,
+               .inv_all     = l2x0_inv_all,
+               .disable     = l2x0_disable,
+       },
+};
+
+static const struct l2x0_of_data aurora_no_outer_data = {
+       .setup = aurora_of_setup,
+       .save  = aurora_save,
+       .outer_cache = {
+               .resume      = aurora_resume,
+       },
 };
 
 static const struct of_device_id l2x0_ids[] __initconst = {
        { .compatible = "arm,pl310-cache", .data = (void *)&pl310_data },
        { .compatible = "arm,l220-cache", .data = (void *)&l2x0_data },
        { .compatible = "arm,l210-cache", .data = (void *)&l2x0_data },
+       { .compatible = "marvell,aurora-system-cache",
+         .data = (void *)&aurora_no_outer_data},
+       { .compatible = "marvell,aurora-outer-cache",
+         .data = (void *)&aurora_with_outer_data},
        {}
 };
 
@@ -577,17 +791,24 @@ int __init l2x0_of_init(u32 aux_val, u32 aux_mask)
        data = of_match_node(l2x0_ids, np)->data;
 
        /* L2 configuration can only be changed if the cache is disabled */
-       if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & 1)) {
+       if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) {
                if (data->setup)
                        data->setup(np, &aux_val, &aux_mask);
+
+               /* For aurora cache in no outer mode select the
+                * correct mode using the coprocessor*/
+               if (data == &aurora_no_outer_data)
+                       aurora_broadcast_l2_commands();
        }
 
        if (data->save)
                data->save();
 
+       of_init = true;
        l2x0_init(l2x0_base, aux_val, aux_mask);
 
-       outer_cache.resume = data->resume;
+       memcpy(&outer_cache, &data->outer_cache, sizeof(outer_cache));
+
        return 0;
 }
 #endif
index 4e07eec1270dd3b3fa51860fbc735a5d1fb9e18b..05f08771fdec82746a974a9d44a6fd78059d2257 100644 (file)
@@ -2,6 +2,9 @@
  *  linux/arch/arm/mm/context.c
  *
  *  Copyright (C) 2002-2003 Deep Blue Solutions Ltd, all rights reserved.
+ *  Copyright (C) 2012 ARM Limited
+ *
+ *  Author: Will Deacon <will.deacon@arm.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
 #include <linux/percpu.h>
 
 #include <asm/mmu_context.h>
+#include <asm/smp_plat.h>
 #include <asm/thread_notify.h>
 #include <asm/tlbflush.h>
 
+/*
+ * On ARMv6, we have the following structure in the Context ID:
+ *
+ * 31                         7          0
+ * +-------------------------+-----------+
+ * |      process ID         |   ASID    |
+ * +-------------------------+-----------+
+ * |              context ID             |
+ * +-------------------------------------+
+ *
+ * The ASID is used to tag entries in the CPU caches and TLBs.
+ * The context ID is used by debuggers and trace logic, and
+ * should be unique within all running processes.
+ */
+#define ASID_FIRST_VERSION     (1ULL << ASID_BITS)
+#define NUM_USER_ASIDS         (ASID_FIRST_VERSION - 1)
+
+#define ASID_TO_IDX(asid)      ((asid & ~ASID_MASK) - 1)
+#define IDX_TO_ASID(idx)       ((idx + 1) & ~ASID_MASK)
+
 static DEFINE_RAW_SPINLOCK(cpu_asid_lock);
-unsigned int cpu_last_asid = ASID_FIRST_VERSION;
+static atomic64_t asid_generation = ATOMIC64_INIT(ASID_FIRST_VERSION);
+static DECLARE_BITMAP(asid_map, NUM_USER_ASIDS);
+
+static DEFINE_PER_CPU(atomic64_t, active_asids);
+static DEFINE_PER_CPU(u64, reserved_asids);
+static cpumask_t tlb_flush_pending;
 
 #ifdef CONFIG_ARM_LPAE
-void cpu_set_reserved_ttbr0(void)
+static void cpu_set_reserved_ttbr0(void)
 {
        unsigned long ttbl = __pa(swapper_pg_dir);
        unsigned long ttbh = 0;
@@ -37,7 +66,7 @@ void cpu_set_reserved_ttbr0(void)
        isb();
 }
 #else
-void cpu_set_reserved_ttbr0(void)
+static void cpu_set_reserved_ttbr0(void)
 {
        u32 ttb;
        /* Copy TTBR1 into TTBR0 */
@@ -84,124 +113,104 @@ static int __init contextidr_notifier_init(void)
 arch_initcall(contextidr_notifier_init);
 #endif
 
-/*
- * We fork()ed a process, and we need a new context for the child
- * to run in.
- */
-void __init_new_context(struct task_struct *tsk, struct mm_struct *mm)
+static void flush_context(unsigned int cpu)
 {
-       mm->context.id = 0;
-       raw_spin_lock_init(&mm->context.id_lock);
-}
+       int i;
+       u64 asid;
+
+       /* Update the list of reserved ASIDs and the ASID bitmap. */
+       bitmap_clear(asid_map, 0, NUM_USER_ASIDS);
+       for_each_possible_cpu(i) {
+               if (i == cpu) {
+                       asid = 0;
+               } else {
+                       asid = atomic64_xchg(&per_cpu(active_asids, i), 0);
+                       __set_bit(ASID_TO_IDX(asid), asid_map);
+               }
+               per_cpu(reserved_asids, i) = asid;
+       }
 
-static void flush_context(void)
-{
-       cpu_set_reserved_ttbr0();
-       local_flush_tlb_all();
-       if (icache_is_vivt_asid_tagged()) {
+       /* Queue a TLB invalidate and flush the I-cache if necessary. */
+       if (!tlb_ops_need_broadcast())
+               cpumask_set_cpu(cpu, &tlb_flush_pending);
+       else
+               cpumask_setall(&tlb_flush_pending);
+
+       if (icache_is_vivt_asid_tagged())
                __flush_icache_all();
-               dsb();
-       }
 }
 
-#ifdef CONFIG_SMP
+static int is_reserved_asid(u64 asid)
+{
+       int cpu;
+       for_each_possible_cpu(cpu)
+               if (per_cpu(reserved_asids, cpu) == asid)
+                       return 1;
+       return 0;
+}
 
-static void set_mm_context(struct mm_struct *mm, unsigned int asid)
+static void new_context(struct mm_struct *mm, unsigned int cpu)
 {
-       unsigned long flags;
+       u64 asid = mm->context.id;
+       u64 generation = atomic64_read(&asid_generation);
 
-       /*
-        * Locking needed for multi-threaded applications where the
-        * same mm->context.id could be set from different CPUs during
-        * the broadcast. This function is also called via IPI so the
-        * mm->context.id_lock has to be IRQ-safe.
-        */
-       raw_spin_lock_irqsave(&mm->context.id_lock, flags);
-       if (likely((mm->context.id ^ cpu_last_asid) >> ASID_BITS)) {
+       if (asid != 0 && is_reserved_asid(asid)) {
                /*
-                * Old version of ASID found. Set the new one and
-                * reset mm_cpumask(mm).
+                * Our current ASID was active during a rollover, we can
+                * continue to use it and this was just a false alarm.
                 */
-               mm->context.id = asid;
+               asid = generation | (asid & ~ASID_MASK);
+       } else {
+               /*
+                * Allocate a free ASID. If we can't find one, take a
+                * note of the currently active ASIDs and mark the TLBs
+                * as requiring flushes.
+                */
+               asid = find_first_zero_bit(asid_map, NUM_USER_ASIDS);
+               if (asid == NUM_USER_ASIDS) {
+                       generation = atomic64_add_return(ASID_FIRST_VERSION,
+                                                        &asid_generation);
+                       flush_context(cpu);
+                       asid = find_first_zero_bit(asid_map, NUM_USER_ASIDS);
+               }
+               __set_bit(asid, asid_map);
+               asid = generation | IDX_TO_ASID(asid);
                cpumask_clear(mm_cpumask(mm));
        }
-       raw_spin_unlock_irqrestore(&mm->context.id_lock, flags);
 
-       /*
-        * Set the mm_cpumask(mm) bit for the current CPU.
-        */
-       cpumask_set_cpu(smp_processor_id(), mm_cpumask(mm));
+       mm->context.id = asid;
 }
 
-/*
- * Reset the ASID on the current CPU. This function call is broadcast
- * from the CPU handling the ASID rollover and holding cpu_asid_lock.
- */
-static void reset_context(void *info)
+void check_and_switch_context(struct mm_struct *mm, struct task_struct *tsk)
 {
-       unsigned int asid;
+       unsigned long flags;
        unsigned int cpu = smp_processor_id();
-       struct mm_struct *mm = current->active_mm;
-
-       smp_rmb();
-       asid = cpu_last_asid + cpu + 1;
-
-       flush_context();
-       set_mm_context(mm, asid);
-
-       /* set the new ASID */
-       cpu_switch_mm(mm->pgd, mm);
-}
 
-#else
+       if (unlikely(mm->context.kvm_seq != init_mm.context.kvm_seq))
+               __check_kvm_seq(mm);
 
-static inline void set_mm_context(struct mm_struct *mm, unsigned int asid)
-{
-       mm->context.id = asid;
-       cpumask_copy(mm_cpumask(mm), cpumask_of(smp_processor_id()));
-}
+       if (!((mm->context.id ^ atomic64_read(&asid_generation)) >> ASID_BITS)
+           && atomic64_xchg(&per_cpu(active_asids, cpu), mm->context.id))
+               goto switch_mm_fastpath;
 
-#endif
-
-void __new_context(struct mm_struct *mm)
-{
-       unsigned int asid;
-
-       raw_spin_lock(&cpu_asid_lock);
-#ifdef CONFIG_SMP
        /*
-        * Check the ASID again, in case the change was broadcast from
-        * another CPU before we acquired the lock.
+        * Required during context switch to avoid speculative page table
+        * walking with the wrong TTBR.
         */
-       if (unlikely(((mm->context.id ^ cpu_last_asid) >> ASID_BITS) == 0)) {
-               cpumask_set_cpu(smp_processor_id(), mm_cpumask(mm));
-               raw_spin_unlock(&cpu_asid_lock);
-               return;
-       }
-#endif
-       /*
-        * At this point, it is guaranteed that the current mm (with
-        * an old ASID) isn't active on any other CPU since the ASIDs
-        * are changed simultaneously via IPI.
-        */
-       asid = ++cpu_last_asid;
-       if (asid == 0)
-               asid = cpu_last_asid = ASID_FIRST_VERSION;
+       cpu_set_reserved_ttbr0();
 
-       /*
-        * If we've used up all our ASIDs, we need
-        * to start a new version and flush the TLB.
-        */
-       if (unlikely((asid & ~ASID_MASK) == 0)) {
-               asid = cpu_last_asid + smp_processor_id() + 1;
-               flush_context();
-#ifdef CONFIG_SMP
-               smp_wmb();
-               smp_call_function(reset_context, NULL, 1);
-#endif
-               cpu_last_asid += NR_CPUS;
-       }
+       raw_spin_lock_irqsave(&cpu_asid_lock, flags);
+       /* Check that our ASID belongs to the current generation. */
+       if ((mm->context.id ^ atomic64_read(&asid_generation)) >> ASID_BITS)
+               new_context(mm, cpu);
 
-       set_mm_context(mm, asid);
-       raw_spin_unlock(&cpu_asid_lock);
+       atomic64_set(&per_cpu(active_asids, cpu), mm->context.id);
+       cpumask_set_cpu(cpu, mm_cpumask(mm));
+
+       if (cpumask_test_and_clear_cpu(cpu, &tlb_flush_pending))
+               local_flush_tlb_all();
+       raw_spin_unlock_irqrestore(&cpu_asid_lock, flags);
+
+switch_mm_fastpath:
+       cpu_switch_mm(mm->pgd, mm);
 }
index 477a2d23ddf17efb95af55cebbc25d35793a417d..58bc3e4d3bd0a76094d8a2a40c0be9bece4eaf7a 100644 (file)
@@ -610,7 +610,7 @@ static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
                         gfp_t gfp, pgprot_t prot, bool is_coherent, const void *caller)
 {
        u64 mask = get_coherent_dma_mask(dev);
-       struct page *page;
+       struct page *page = NULL;
        void *addr;
 
 #ifdef CONFIG_DMA_API_DEBUG
index ce8cb1970d7ae393da39208c929e8a1d983f91c2..89f2b7f7b042254132d13e226c7465fb338f4303 100644 (file)
@@ -279,7 +279,7 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
  * You really shouldn't be using read() or write() on /dev/mem.  This
  * might go away in the future.
  */
-int valid_phys_addr_range(unsigned long addr, size_t size)
+int valid_phys_addr_range(phys_addr_t addr, size_t size)
 {
        if (addr < PHYS_OFFSET)
                return 0;
index 941dfb9e9a78635680d85225169d0edd187aea8c..b675918a593b8cb2131a8f6f98e9c40ef2cd22b5 100644 (file)
@@ -97,6 +97,7 @@ static struct cachepolicy cache_policies[] __initdata = {
        }
 };
 
+#ifdef CONFIG_CPU_CP15
 /*
  * These are useful for identifying cache coherency
  * problems by allowing the cache or the cache and
@@ -195,6 +196,22 @@ void adjust_cr(unsigned long mask, unsigned long set)
 }
 #endif
 
+#else
+
+static int __init early_cachepolicy(char *p)
+{
+       pr_warning("cachepolicy kernel parameter not supported without cp15\n");
+}
+early_param("cachepolicy", early_cachepolicy);
+
+static int __init noalign_setup(char *__unused)
+{
+       pr_warning("noalign kernel parameter not supported without cp15\n");
+}
+__setup("noalign", noalign_setup);
+
+#endif
+
 #define PROT_PTE_DEVICE                L_PTE_PRESENT|L_PTE_YOUNG|L_PTE_DIRTY|L_PTE_XN
 #define PROT_SECT_DEVICE       PMD_TYPE_SECT|PMD_SECT_AP_WRITE
 
index d51225f90ae2d5d3af909ec87d29910bea4f23d5..4bc8ae5ae3ab35740025bd8deb0e0b07aeb9d08b 100644 (file)
 
 void __init arm_mm_memblock_reserve(void)
 {
+#ifndef CONFIG_CPU_V7M
        /*
         * Register the exception vector page.
         * some architectures which the DRAM is the exception vector to trap,
         * alloc_page breaks with error, although it is not NULL, but "0."
         */
        memblock_reserve(CONFIG_VECTORS_BASE, PAGE_SIZE);
+#endif
 }
 
 void __init sanity_check_meminfo(void)
index 846d279f31764d7803fc6144df9517087286c768..42cc833aa02f7b43aa6e851328a4ef5e4734b30e 100644 (file)
@@ -57,7 +57,7 @@ ENTRY(cpu_v7_reset)
  THUMB(        bic     r1, r1, #1 << 30 )              @ SCTLR.TE (Thumb exceptions)
        mcr     p15, 0, r1, c1, c0, 0           @ disable MMU
        isb
-       mov     pc, r0
+       bx      r0
 ENDPROC(cpu_v7_reset)
        .popsection
 
diff --git a/arch/arm/mm/proc-v7m.S b/arch/arm/mm/proc-v7m.S
new file mode 100644 (file)
index 0000000..2b8eb97
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ *  linux/arch/arm/mm/proc-v7m.S
+ *
+ *  Copyright (C) 2008 ARM Ltd.
+ *  Copyright (C) 2001 Deep Blue Solutions Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ *  This is the "shell" of the ARMv7-M processor support.
+ */
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+
+ENTRY(cpu_v7m_proc_init)
+       mov     pc, lr
+ENDPROC(cpu_v7m_proc_init)
+
+ENTRY(cpu_v7m_proc_fin)
+       mov     pc, lr
+ENDPROC(cpu_v7m_proc_fin)
+
+/*
+ *     cpu_v7m_reset(loc)
+ *
+ *     Perform a soft reset of the system.  Put the CPU into the
+ *     same state as it would be if it had been reset, and branch
+ *     to what would be the reset vector.
+ *
+ *     - loc   - location to jump to for soft reset
+ */
+       .align  5
+ENTRY(cpu_v7m_reset)
+       mov     pc, r0
+ENDPROC(cpu_v7m_reset)
+
+/*
+ *     cpu_v7m_do_idle()
+ *
+ *     Idle the processor (eg, wait for interrupt).
+ *
+ *     IRQs are already disabled.
+ */
+ENTRY(cpu_v7m_do_idle)
+       wfi
+       mov     pc, lr
+ENDPROC(cpu_v7m_do_idle)
+
+ENTRY(cpu_v7m_dcache_clean_area)
+       mov     pc, lr
+ENDPROC(cpu_v7m_dcache_clean_area)
+
+/*
+ * There is no MMU, so here is nothing to do.
+ */
+ENTRY(cpu_v7m_switch_mm)
+       mov     pc, lr
+ENDPROC(cpu_v7m_switch_mm)
+
+cpu_v7m_name:
+       .ascii  "ARMv7-M Processor"
+       .align
+
+       .section ".text.init", #alloc, #execinstr
+
+/*
+ *     __v7m_setup
+ *
+ *     This should be able to cover all ARMv7-M cores.
+ */
+__v7m_setup:
+       @ Configure the vector table base address
+       ldr     r0, =0xe000ed08         @ vector table base address
+       ldr     r12, =vector_table
+       str     r12, [r0]
+
+       @ Lower the priority of the SVC and PendSV exceptions
+       ldr     r0, =0xe000ed1c
+       mov     r5, #0x80000000
+       str     r5, [r0]                @ set SVC priority
+       ldr     r0, =0xe000ed20
+       mov     r5, #0x00800000
+       str     r5, [r0]                @ set PendSV priority
+
+       @ SVC to run the kernel in this mode
+       adr     r0, BSYM(1f)
+       ldr     r5, [r12, #11 * 4]      @ read the SVC vector entry
+       str     r0, [r12, #11 * 4]      @ write the temporary SVC vector entry
+       mov     r6, lr                  @ save LR
+       mov     r7, sp                  @ save SP
+       ldr     sp, =__v7m_setup_stack_top
+       cpsie   i
+       svc     #0
+1:     cpsid   i
+       str     r5, [r12, #11 * 4]      @ restore the original SVC vector entry
+       mov     lr, r6                  @ restore LR
+       mov     sp, r7                  @ restore SP
+
+       @ Special-purpose control register
+       mov     r0, #1
+       msr     control, r0             @ Thread mode has unpriviledged access
+
+       @ Configure the System Control Register
+       ldr     r0, =0xe000ed14         @ system control register
+       ldr     r12, [r0]
+       orr     r12, #1 << 9            @ STKALIGN
+       str     r12, [r0]
+       mov     pc, lr
+ENDPROC(__v7m_setup)
+
+       .align  2
+       .type   v7m_processor_functions, #object
+ENTRY(v7m_processor_functions)
+       .word   nommu_early_abort
+       .word   cpu_v7m_proc_init
+       .word   cpu_v7m_proc_fin
+       .word   cpu_v7m_reset
+       .word   cpu_v7m_do_idle
+       .word   cpu_v7m_dcache_clean_area
+       .word   cpu_v7m_switch_mm
+       .word   0                       @ cpu_v7m_set_pte_ext
+       .word   legacy_pabort
+       .size   v7m_processor_functions, . - v7m_processor_functions
+
+       .type   cpu_arch_name, #object
+cpu_arch_name:
+       .asciz  "armv7m"
+       .size   cpu_arch_name, . - cpu_arch_name
+
+       .type   cpu_elf_name, #object
+cpu_elf_name:
+       .asciz  "v7m"
+       .size   cpu_elf_name, . - cpu_elf_name
+       .align
+
+       .section ".proc.info.init", #alloc, #execinstr
+
+       /*
+        * Match any ARMv7-M processor core.
+        */
+       .type   __v7m_proc_info, #object
+__v7m_proc_info:
+       .long   0x000f0000              @ Required ID value
+       .long   0x000f0000              @ Mask for ID
+       .long   0                       @ proc_info_list.__cpu_mm_mmu_flags
+       .long   0                       @ proc_info_list.__cpu_io_mmu_flags
+       b       __v7m_setup             @ proc_info_list.__cpu_flush
+       .long   cpu_arch_name
+       .long   cpu_elf_name
+       .long   HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
+       .long   cpu_v7m_name
+       .long   v7m_processor_functions @ proc_info_list.proc
+       .long   0                       @ proc_info_list.tlb
+       .long   0                       @ proc_info_list.user
+       .long   0                       @ proc_info_list.cache
+       .size   __v7m_proc_info, . - __v7m_proc_info
+
+__v7m_setup_stack:
+       .space  4 * 8                           @ 8 registers
+__v7m_setup_stack_top:
index bf312c354a214761646a3a3738fb6080b84fff33..0f5a5f2a2c7bbc1bb79668ac291dde283741be7a 100644 (file)
@@ -17,7 +17,6 @@ struct arm_vmregion {
        struct list_head        vm_list;
        unsigned long           vm_start;
        unsigned long           vm_end;
-       void                    *priv;
        int                     vm_active;
        const void              *caller;
 };
diff --git a/arch/arm/plat-mxc/Kconfig b/arch/arm/plat-mxc/Kconfig
deleted file mode 100644 (file)
index 88e1e2e..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-if ARCH_MXC
-
-source "arch/arm/plat-mxc/devices/Kconfig"
-
-menu "Freescale MXC Implementations"
-
-choice
-       prompt "Freescale CPU family:"
-       default ARCH_IMX_V6_V7
-
-config ARCH_IMX_V4_V5
-       bool "i.MX1, i.MX21, i.MX25, i.MX27"
-       select ARM_PATCH_PHYS_VIRT
-       select AUTO_ZRELADDR if !ZBOOT_ROM
-       help
-         This enables support for systems based on the Freescale i.MX ARMv4
-         and ARMv5 SoCs
-
-config ARCH_IMX_V6_V7
-       bool "i.MX3, i.MX5, i.MX6"
-       select ARM_PATCH_PHYS_VIRT
-       select AUTO_ZRELADDR if !ZBOOT_ROM
-       select MIGHT_HAVE_CACHE_L2X0
-       help
-         This enables support for systems based on the Freescale i.MX3, i.MX5
-         and i.MX6 family.
-
-endchoice
-
-source "arch/arm/mach-imx/Kconfig"
-
-endmenu
-
-config MXC_IRQ_PRIOR
-       bool "Use IRQ priority"
-       help
-         Select this if you want to use prioritized IRQ handling.
-         This feature prevents higher priority ISR to be interrupted
-         by lower priority IRQ even IRQF_DISABLED flag is not set.
-         This may be useful in embedded applications, where are strong
-         requirements for timing.
-         Say N here, unless you have a specialized requirement.
-
-config MXC_TZIC
-       bool
-
-config MXC_AVIC
-       bool
-
-config MXC_DEBUG_BOARD
-       bool "Enable MXC debug board(for 3-stack)"
-       help
-         The debug board is an integral part of the MXC 3-stack(PDK)
-         platforms, it can be attached or removed from the peripheral
-         board. On debug board, several debug devices(ethernet, UART,
-         buttons, LEDs and JTAG) are implemented. Between the MCU and
-         these devices, a CPLD is added as a bridge which performs
-         data/address de-multiplexing and decode, signal level shift,
-         interrupt control and various board functions.
-
-config HAVE_EPIT
-       bool
-
-config MXC_USE_EPIT
-       bool "Use EPIT instead of GPT"
-       depends on HAVE_EPIT
-       help
-         Use EPIT as the system timer on systems that have it. Normally you
-         don't have a reason to do so as the EPIT has the same features and
-         uses the same clocks as the GPT. Anyway, on some systems the GPT
-         may be in use for other purposes.
-
-config MXC_ULPI
-       bool
-
-config ARCH_HAS_RNGA
-       bool
-
-config IMX_HAVE_IOMUX_V1
-       bool
-
-config ARCH_MXC_IOMUX_V3
-       bool
-
-config IRAM_ALLOC
-       bool
-       select GENERIC_ALLOCATOR
-
-endif
diff --git a/arch/arm/plat-mxc/Makefile b/arch/arm/plat-mxc/Makefile
deleted file mode 100644 (file)
index 149237e..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-#
-# Makefile for the linux kernel.
-#
-
-# Common support
-obj-y := time.o devices.o cpu.o system.o irq-common.o
-
-obj-$(CONFIG_MXC_TZIC) += tzic.o
-obj-$(CONFIG_MXC_AVIC) += avic.o
-
-obj-$(CONFIG_IMX_HAVE_IOMUX_V1) += iomux-v1.o
-obj-$(CONFIG_ARCH_MXC_IOMUX_V3) += iomux-v3.o
-obj-$(CONFIG_IRAM_ALLOC) += iram_alloc.o
-obj-$(CONFIG_MXC_ULPI) += ulpi.o
-obj-$(CONFIG_MXC_USE_EPIT) += epit.o
-obj-$(CONFIG_MXC_DEBUG_BOARD) += 3ds_debugboard.o
-obj-$(CONFIG_CPU_FREQ_IMX)    += cpufreq.o
-obj-$(CONFIG_CPU_IDLE) += cpuidle.o
-ifdef CONFIG_SND_IMX_SOC
-obj-y += ssi-fiq.o
-obj-y += ssi-fiq-ksym.o
-endif
-
-obj-y += devices/
diff --git a/arch/arm/plat-mxc/include/mach/irqs.h b/arch/arm/plat-mxc/include/mach/irqs.h
deleted file mode 100644 (file)
index d73f5e8..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- *  Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __ASM_ARCH_MXC_IRQS_H__
-#define __ASM_ARCH_MXC_IRQS_H__
-
-extern int imx_irq_set_priority(unsigned char irq, unsigned char prio);
-
-/* all normal IRQs can be FIQs */
-#define FIQ_START      0
-/* switch between IRQ and FIQ */
-extern int mxc_set_irq_fiq(unsigned int irq, unsigned int type);
-
-#endif /* __ASM_ARCH_MXC_IRQS_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/timex.h b/arch/arm/plat-mxc/include/mach/timex.h
deleted file mode 100644 (file)
index 10343d1..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- *  Copyright (C) 1999 ARM Limited
- * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef __ASM_ARCH_MXC_TIMEX_H__
-#define __ASM_ARCH_MXC_TIMEX_H__
-
-/* Bogus value */
-#define CLOCK_TICK_RATE        12345678
-
-#endif                         /* __ASM_ARCH_MXC_TIMEX_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/uncompress.h b/arch/arm/plat-mxc/include/mach/uncompress.h
deleted file mode 100644 (file)
index 477971b..0000000
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- *  arch/arm/plat-mxc/include/mach/uncompress.h
- *
- *  Copyright (C) 1999 ARM Limited
- *  Copyright (C) Shane Nay (shane@minirl.com)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-#ifndef __ASM_ARCH_MXC_UNCOMPRESS_H__
-#define __ASM_ARCH_MXC_UNCOMPRESS_H__
-
-#define __MXC_BOOT_UNCOMPRESS
-
-#include <asm/mach-types.h>
-
-unsigned long uart_base;
-
-#define UART(x) (*(volatile unsigned long *)(uart_base + (x)))
-
-#define USR2 0x98
-#define USR2_TXFE (1<<14)
-#define TXR  0x40
-#define UCR1 0x80
-#define UCR1_UARTEN 1
-
-/*
- * The following code assumes the serial port has already been
- * initialized by the bootloader.  We search for the first enabled
- * port in the most probable order.  If you didn't setup a port in
- * your bootloader then nothing will appear (which might be desired).
- *
- * This does not append a newline
- */
-
-static void putc(int ch)
-{
-       if (!uart_base)
-               return;
-       if (!(UART(UCR1) & UCR1_UARTEN))
-               return;
-
-       while (!(UART(USR2) & USR2_TXFE))
-               barrier();
-
-       UART(TXR) = ch;
-}
-
-static inline void flush(void)
-{
-}
-
-#define MX1_UART1_BASE_ADDR    0x00206000
-#define MX25_UART1_BASE_ADDR   0x43f90000
-#define MX2X_UART1_BASE_ADDR   0x1000a000
-#define MX3X_UART1_BASE_ADDR   0x43F90000
-#define MX3X_UART2_BASE_ADDR   0x43F94000
-#define MX3X_UART5_BASE_ADDR   0x43FB4000
-#define MX51_UART1_BASE_ADDR   0x73fbc000
-#define MX50_UART1_BASE_ADDR   0x53fbc000
-#define MX53_UART1_BASE_ADDR   0x53fbc000
-
-static __inline__ void __arch_decomp_setup(unsigned long arch_id)
-{
-       switch (arch_id) {
-       case MACH_TYPE_MX1ADS:
-       case MACH_TYPE_SCB9328:
-               uart_base = MX1_UART1_BASE_ADDR;
-               break;
-       case MACH_TYPE_MX25_3DS:
-               uart_base = MX25_UART1_BASE_ADDR;
-               break;
-       case MACH_TYPE_IMX27LITE:
-       case MACH_TYPE_MX27_3DS:
-       case MACH_TYPE_MX27ADS:
-       case MACH_TYPE_PCM038:
-       case MACH_TYPE_MX21ADS:
-       case MACH_TYPE_PCA100:
-       case MACH_TYPE_MXT_TD60:
-       case MACH_TYPE_IMX27IPCAM:
-               uart_base = MX2X_UART1_BASE_ADDR;
-               break;
-       case MACH_TYPE_MX31LITE:
-       case MACH_TYPE_ARMADILLO5X0:
-       case MACH_TYPE_MX31MOBOARD:
-       case MACH_TYPE_QONG:
-       case MACH_TYPE_MX31_3DS:
-       case MACH_TYPE_PCM037:
-       case MACH_TYPE_MX31ADS:
-       case MACH_TYPE_MX35_3DS:
-       case MACH_TYPE_PCM043:
-       case MACH_TYPE_LILLY1131:
-       case MACH_TYPE_VPR200:
-       case MACH_TYPE_EUKREA_CPUIMX35SD:
-               uart_base = MX3X_UART1_BASE_ADDR;
-               break;
-       case MACH_TYPE_MAGX_ZN5:
-               uart_base = MX3X_UART2_BASE_ADDR;
-               break;
-       case MACH_TYPE_BUG:
-               uart_base = MX3X_UART5_BASE_ADDR;
-               break;
-       case MACH_TYPE_MX51_BABBAGE:
-       case MACH_TYPE_EUKREA_CPUIMX51SD:
-       case MACH_TYPE_MX51_3DS:
-               uart_base = MX51_UART1_BASE_ADDR;
-               break;
-       case MACH_TYPE_MX50_RDP:
-               uart_base = MX50_UART1_BASE_ADDR;
-               break;
-       case MACH_TYPE_MX53_EVK:
-       case MACH_TYPE_MX53_LOCO:
-       case MACH_TYPE_MX53_SMD:
-       case MACH_TYPE_MX53_ARD:
-               uart_base = MX53_UART1_BASE_ADDR;
-               break;
-       default:
-               break;
-       }
-}
-
-#define arch_decomp_setup()    __arch_decomp_setup(arch_id)
-#define arch_decomp_wdog()
-
-#endif                         /* __ASM_ARCH_MXC_UNCOMPRESS_H__ */
diff --git a/arch/arm/plat-nomadik/include/plat/gpio-nomadik.h b/arch/arm/plat-nomadik/include/plat/gpio-nomadik.h
deleted file mode 100644 (file)
index c08a54d..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Structures and registers for GPIO access in the Nomadik SoC
- *
- * Copyright (C) 2008 STMicroelectronics
- *     Author: Prafulla WADASKAR <prafulla.wadaskar@st.com>
- * Copyright (C) 2009 Alessandro Rubini <rubini@unipv.it>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __PLAT_NOMADIK_GPIO
-#define __PLAT_NOMADIK_GPIO
-
-/*
- * "nmk_gpio" and "NMK_GPIO" stand for "Nomadik GPIO", leaving
- * the "gpio" namespace for generic and cross-machine functions
- */
-
-/* Register in the logic block */
-#define NMK_GPIO_DAT   0x00
-#define NMK_GPIO_DATS  0x04
-#define NMK_GPIO_DATC  0x08
-#define NMK_GPIO_PDIS  0x0c
-#define NMK_GPIO_DIR   0x10
-#define NMK_GPIO_DIRS  0x14
-#define NMK_GPIO_DIRC  0x18
-#define NMK_GPIO_SLPC  0x1c
-#define NMK_GPIO_AFSLA 0x20
-#define NMK_GPIO_AFSLB 0x24
-#define NMK_GPIO_LOWEMI        0x28
-
-#define NMK_GPIO_RIMSC 0x40
-#define NMK_GPIO_FIMSC 0x44
-#define NMK_GPIO_IS    0x48
-#define NMK_GPIO_IC    0x4c
-#define NMK_GPIO_RWIMSC        0x50
-#define NMK_GPIO_FWIMSC        0x54
-#define NMK_GPIO_WKS   0x58
-
-/* Alternate functions: function C is set in hw by setting both A and B */
-#define NMK_GPIO_ALT_GPIO      0
-#define NMK_GPIO_ALT_A 1
-#define NMK_GPIO_ALT_B 2
-#define NMK_GPIO_ALT_C (NMK_GPIO_ALT_A | NMK_GPIO_ALT_B)
-
-#define NMK_GPIO_ALT_CX_SHIFT 2
-#define NMK_GPIO_ALT_C1        ((1<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C)
-#define NMK_GPIO_ALT_C2        ((2<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C)
-#define NMK_GPIO_ALT_C3        ((3<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C)
-#define NMK_GPIO_ALT_C4        ((4<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C)
-
-/* Pull up/down values */
-enum nmk_gpio_pull {
-       NMK_GPIO_PULL_NONE,
-       NMK_GPIO_PULL_UP,
-       NMK_GPIO_PULL_DOWN,
-};
-
-/* Sleep mode */
-enum nmk_gpio_slpm {
-       NMK_GPIO_SLPM_INPUT,
-       NMK_GPIO_SLPM_WAKEUP_ENABLE = NMK_GPIO_SLPM_INPUT,
-       NMK_GPIO_SLPM_NOCHANGE,
-       NMK_GPIO_SLPM_WAKEUP_DISABLE = NMK_GPIO_SLPM_NOCHANGE,
-};
-
-extern int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode);
-extern int nmk_gpio_set_pull(int gpio, enum nmk_gpio_pull pull);
-#ifdef CONFIG_PINCTRL_NOMADIK
-extern int nmk_gpio_set_mode(int gpio, int gpio_mode);
-#else
-static inline int nmk_gpio_set_mode(int gpio, int gpio_mode)
-{
-       return -ENODEV;
-}
-#endif
-extern int nmk_gpio_get_mode(int gpio);
-
-extern void nmk_gpio_wakeups_suspend(void);
-extern void nmk_gpio_wakeups_resume(void);
-
-extern void nmk_gpio_clocks_enable(void);
-extern void nmk_gpio_clocks_disable(void);
-
-extern void nmk_gpio_read_pull(int gpio_bank, u32 *pull_up);
-
-/*
- * Platform data to register a block: only the initial gpio/irq number.
- */
-struct nmk_gpio_platform_data {
-       char *name;
-       int first_gpio;
-       int first_irq;
-       int num_gpio;
-       u32 (*get_secondary_status)(unsigned int bank);
-       void (*set_ioforce)(bool enable);
-       bool supports_sleepmode;
-};
-
-#endif /* __PLAT_NOMADIK_GPIO */
index c7a4c0902b386f90e8e6d37a21fc7ead498b6ea5..5a4678edd65a9a8eb31a766fd566ee86a968e8f9 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/smc91x.h>
 
 #include <mach/hardware.h>
+#include "../mach-omap2/debug-devices.h"
 
 /* Many OMAP development platforms reuse the same "debug board"; these
  * platforms include H2, H3, H4, and Perseus2.
index f4a4cd014795d676d85ffdc05622a4ac3e889a5c..1957a8516e938e2d9f42b690903211095e6ed959 100644 (file)
 #define OMAP_UART_WER_MOD_WKUP 0X7F
 
 /* Enable XON/XOFF flow control on output */
-#define OMAP_UART_SW_TX                0x8
+#define OMAP_UART_SW_TX                0x04
 
 /* Enable XON/XOFF flow control on input */
-#define OMAP_UART_SW_RX                0x2
+#define OMAP_UART_SW_RX                0x04
 
 #define OMAP_UART_SYSC_RESET   0X07
 #define OMAP_UART_TCR_TRIG     0X0F
index 65fce44dce342b3650637b53beaeb0e8f1d2c3d8..b780470d03ea2f80804bdd9cfdbcda389e78a655 100644 (file)
 #define OMAP5UART4             OMAP4UART4
 #define ZOOM_UART              95              /* Only on zoom2/3 */
 
-/* This is only used by 8250.c for omap1510 */
-#define is_omap_port(pt)       ({int __ret = 0;                        \
-                       if ((pt)->port.mapbase == OMAP1_UART1_BASE ||   \
-                           (pt)->port.mapbase == OMAP1_UART2_BASE ||   \
-                           (pt)->port.mapbase == OMAP1_UART3_BASE)     \
-                               __ret = 1;                              \
-                       __ret;                                          \
-                       })
-
 #ifndef __ASSEMBLER__
 
 struct omap_board_data;
index 012bbd0b8d81063fa7db1547f440b7ca97adca74..47c9fad43f00124ce8e78e3f04b141f716034cd6 100644 (file)
@@ -389,6 +389,72 @@ int __init s3c24xx_register_baseclocks(unsigned long xtal)
 
 static struct dentry *clk_debugfs_root;
 
+static void clock_tree_show_one(struct seq_file *s, struct clk *c, int level)
+{
+       struct clk *child;
+       const char *state;
+       char buf[255] = { 0 };
+       int n = 0;
+
+       if (c->name)
+               n = snprintf(buf, sizeof(buf) - 1, "%s", c->name);
+
+       if (c->devname)
+               n += snprintf(buf + n, sizeof(buf) - 1 - n, ":%s", c->devname);
+
+       state = (c->usage > 0) ? "on" : "off";
+
+       seq_printf(s, "%*s%-*s %-6s %-3d %-10lu\n",
+                  level * 3 + 1, "",
+                  50 - level * 3, buf,
+                  state, c->usage, clk_get_rate(c));
+
+       list_for_each_entry(child, &clocks, list) {
+               if (child->parent != c)
+                       continue;
+
+               clock_tree_show_one(s, child, level + 1);
+       }
+}
+
+static int clock_tree_show(struct seq_file *s, void *data)
+{
+       struct clk *c;
+       unsigned long flags;
+
+       seq_printf(s, " clock state ref rate\n");
+       seq_printf(s, "----------------------------------------------------\n");
+
+       spin_lock_irqsave(&clocks_lock, flags);
+
+       list_for_each_entry(c, &clocks, list)
+               if (c->parent == NULL)
+                       clock_tree_show_one(s, c, 0);
+
+       spin_unlock_irqrestore(&clocks_lock, flags);
+       return 0;
+}
+
+static int clock_tree_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, clock_tree_show, inode->i_private);
+}
+
+static const struct file_operations clock_tree_fops = {
+       .open           = clock_tree_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static int clock_rate_show(void *data, u64 *val)
+{
+       struct clk *c = data;
+       *val = clk_get_rate(c);
+       return 0;
+}
+DEFINE_SIMPLE_ATTRIBUTE(clock_rate_fops, clock_rate_show, NULL, "%llu\n");
+
 static int clk_debugfs_register_one(struct clk *c)
 {
        int err;
@@ -411,7 +477,7 @@ static int clk_debugfs_register_one(struct clk *c)
                goto err_out;
        }
 
-       d = debugfs_create_u32("rate", S_IRUGO, c->dent, (u32 *)&c->rate);
+       d = debugfs_create_file("rate", S_IRUGO, c->dent, c, &clock_rate_fops);
        if (!d) {
                err = -ENOMEM;
                goto err_out;
@@ -446,13 +512,18 @@ static int __init clk_debugfs_init(void)
 {
        struct clk *c;
        struct dentry *d;
-       int err;
+       int err = -ENOMEM;
 
        d = debugfs_create_dir("clock", NULL);
        if (!d)
                return -ENOMEM;
        clk_debugfs_root = d;
 
+       d = debugfs_create_file("clock_tree", S_IRUGO, clk_debugfs_root, NULL,
+                                &clock_tree_fops);
+       if (!d)
+               goto err_out;
+
        list_for_each_entry(c, &clocks, list) {
                err = clk_debugfs_register(c);
                if (err)
index 03f654d55effb2f10355c914ab206730928759f7..52dfa8f914c7384e7ddaabb99b0a14cde456beb2 100644 (file)
@@ -933,6 +933,7 @@ struct platform_device s5p_device_mfc_r = {
                .coherent_dma_mask      = DMA_BIT_MASK(32),
        },
 };
+
 #endif /* CONFIG_S5P_DEV_MFC */
 
 /* MIPI CSIS */
index 1fe6917f6a2a75e9f36cce7c28f46ef13228f113..dfd8b7af8c7ac93db4bf6d3d28371a072793c1d9 100644 (file)
@@ -48,6 +48,7 @@ struct samsung_gpio_cfg;
  * @config: special function and pull-resistor control information.
  * @lock: Lock for exclusive access to this gpio bank.
  * @pm_save: Save information for suspend/resume support.
+ * @bitmap_gpio_int: Bitmap for representing GPIO interrupt or not.
  *
  * This wrapper provides the necessary information for the Samsung
  * specific gpios being registered with gpiolib.
@@ -71,6 +72,7 @@ struct samsung_gpio_chip {
 #ifdef CONFIG_PM
        u32                     pm_save[4];
 #endif
+       u32                     bitmap_gpio_int;
 };
 
 static inline struct samsung_gpio_chip *to_samsung_gpio(struct gpio_chip *gpc)
index ac13227272f04c92dccd8b7a5933424889e0e7ae..e6d7c42d68b637e58e20b0186b7326df8a2a279d 100644 (file)
 #ifndef __PLAT_SAMSUNG_MFC_H
 #define __PLAT_SAMSUNG_MFC_H __FILE__
 
+struct s5p_mfc_dt_meminfo {
+       unsigned long   loff;
+       unsigned long   lsize;
+       unsigned long   roff;
+       unsigned long   rsize;
+       char            *compatible;
+};
+
 /**
  * s5p_mfc_reserve_mem - function to early reserve memory for MFC driver
  * @rbase:     base address for MFC 'right' memory interface
@@ -24,4 +32,7 @@
 void __init s5p_mfc_reserve_mem(phys_addr_t rbase, unsigned int rsize,
                                phys_addr_t lbase, unsigned int lsize);
 
+int __init s5p_fdt_find_mfc_mem(unsigned long node, const char *uname,
+                               int depth, void *data);
+
 #endif /* __PLAT_SAMSUNG_MFC_H */
diff --git a/arch/arm/plat-samsung/include/plat/spi-core.h b/arch/arm/plat-samsung/include/plat/spi-core.h
new file mode 100644 (file)
index 0000000..0b9428a
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2012 Heiko Stuebner <heiko@sntech.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __PLAT_S3C_SPI_CORE_H
+#define __PLAT_S3C_SPI_CORE_H
+
+/* These functions are only for use with the core support code, such as
+ * the cpu specific initialisation code
+ */
+
+/* re-define device name depending on support. */
+static inline void s3c64xx_spi_setname(char *name)
+{
+#ifdef CONFIG_S3C64XX_DEV_SPI0
+       s3c64xx_device_spi0.name = name;
+#endif
+#ifdef CONFIG_S3C64XX_DEV_SPI1
+       s3c64xx_device_spi1.name = name;
+#endif
+#ifdef CONFIG_S3C64XX_DEV_SPI2
+       s3c64xx_device_spi2.name = name;
+#endif
+}
+
+#endif /* __PLAT_S3C_SPI_CORE_H */
index ad6089465e2afba33b49cc1def128c3c0f9a2cd5..5ec104b5408b37d58e25efa202439110150a21c2 100644 (file)
@@ -14,6 +14,8 @@
 #include <linux/dma-mapping.h>
 #include <linux/memblock.h>
 #include <linux/ioport.h>
+#include <linux/of_fdt.h>
+#include <linux/of.h>
 
 #include <mach/map.h>
 #include <plat/devs.h>
@@ -69,3 +71,35 @@ static int __init s5p_mfc_memory_init(void)
        return 0;
 }
 device_initcall(s5p_mfc_memory_init);
+
+#ifdef CONFIG_OF
+int __init s5p_fdt_find_mfc_mem(unsigned long node, const char *uname,
+                               int depth, void *data)
+{
+       __be32 *prop;
+       unsigned long len;
+       struct s5p_mfc_dt_meminfo *mfc_mem = data;
+
+       if (!data)
+               return 0;
+
+       if (!of_flat_dt_is_compatible(node, mfc_mem->compatible))
+               return 0;
+
+       prop = of_get_flat_dt_prop(node, "samsung,mfc-l", &len);
+       if (!prop || (len != 2 * sizeof(unsigned long)))
+               return 0;
+
+       mfc_mem->loff = be32_to_cpu(prop[0]);
+       mfc_mem->lsize = be32_to_cpu(prop[1]);
+
+       prop = of_get_flat_dt_prop(node, "samsung,mfc-r", &len);
+       if (!prop || (len != 2 * sizeof(unsigned long)))
+               return 0;
+
+       mfc_mem->roff = be32_to_cpu(prop[0]);
+       mfc_mem->rsize = be32_to_cpu(prop[1]);
+
+       return 1;
+}
+#endif
index 23557d30e44ceb9e6124f4cb19b9851325db67ea..bae56131a50a44e7dc7fff38beef9cc8e9d7cbe2 100644 (file)
@@ -185,7 +185,7 @@ int __init s5p_register_gpio_interrupt(int pin)
 
        /* check if the group has been already registered */
        if (my_chip->irq_base)
-               return my_chip->irq_base + offset;
+               goto success;
 
        /* register gpio group */
        ret = s5p_gpioint_add(my_chip);
@@ -193,9 +193,13 @@ int __init s5p_register_gpio_interrupt(int pin)
                my_chip->chip.to_irq = samsung_gpiolib_to_irq;
                printk(KERN_INFO "Registered interrupt support for gpio group %d.\n",
                       group);
-               return my_chip->irq_base + offset;
+               goto success;
        }
        return ret;
+success:
+       my_chip->bitmap_gpio_int |= BIT(offset);
+
+       return my_chip->irq_base + offset;
 }
 
 int __init s5p_register_gpioint_bank(int chain_irq, int start, int nr_groups)
index 635cb1865e4d56af08b8579eb72dbaadfa77f211..cd60a81163e938a78b55b40fa9df6009408f5b57 100644 (file)
@@ -5,6 +5,6 @@
 #
 
 include/generated/mach-types.h: $(src)/gen-mach-types $(src)/mach-types
-       @echo '  Generating $@'
+       $(kecho) '  Generating $@'
        @mkdir -p $(dir $@)
        $(Q)$(AWK) -f $^ > $@ || { rm -f $@; /bin/false; }
index dbd1330c01966c20667853b6d9de97754b869d91..859a9bb002d54875e5089a940442d5015a9fe1a4 100644 (file)
@@ -33,7 +33,7 @@
 #include <xen/page.h>
 #include <xen/grant_table.h>
 
-int arch_gnttab_map_shared(unsigned long *frames, unsigned long nr_gframes,
+int arch_gnttab_map_shared(xen_pfn_t *frames, unsigned long nr_gframes,
                           unsigned long max_nr_gframes,
                           void **__shared)
 {
index 75b212d5db9dc87a0aef84b878cda7d0a1d395ea..138fc9cfd783d203642e4010863e80a054105584 100644 (file)
@@ -24,6 +24,7 @@ config ARM64
        select HAVE_PERF_EVENTS
        select HAVE_SPARSE_IRQ
        select IRQ_DOMAIN
+       select MODULES_USE_ELF_RELA
        select NO_BOOTMEM
        select OF
        select OF_EARLY_FLATTREE
index fe77e51a7847bf872ebcc7cb18102d71c1b0af4a..a581a2205938db09064604a53244b756ca650d0a 100644 (file)
@@ -18,7 +18,6 @@ generic-y += ipcbuf.h
 generic-y += irq_regs.h
 generic-y += kdebug.h
 generic-y += kmap_types.h
-generic-y += linkage.h
 generic-y += local.h
 generic-y += local64.h
 generic-y += mman.h
index 74a2a7d304a959159e3cf69c94f0ede77a8232c2..54f6116697f7fa2d26fc4dafa5bcae05e02ed7d0 100644 (file)
@@ -114,7 +114,7 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
  *  I/O port access primitives.
  */
 #define IO_SPACE_LIMIT         0xffff
-#define PCI_IOBASE             ((void __iomem *)0xffffffbbfffe0000UL)
+#define PCI_IOBASE             ((void __iomem *)(MODULES_VADDR - SZ_2M))
 
 static inline u8 inb(unsigned long addr)
 {
@@ -225,9 +225,9 @@ extern void __iounmap(volatile void __iomem *addr);
 #define PROT_DEVICE_nGnRE      (PROT_DEFAULT | PTE_XN | PTE_ATTRINDX(MT_DEVICE_nGnRE))
 #define PROT_NORMAL_NC         (PROT_DEFAULT | PTE_ATTRINDX(MT_NORMAL_NC))
 
-#define ioremap(addr, size)            __ioremap((addr), (size), PROT_DEVICE_nGnRE)
-#define ioremap_nocache(addr, size)    __ioremap((addr), (size), PROT_DEVICE_nGnRE)
-#define ioremap_wc(addr, size)         __ioremap((addr), (size), PROT_NORMAL_NC)
+#define ioremap(addr, size)            __ioremap((addr), (size), __pgprot(PROT_DEVICE_nGnRE))
+#define ioremap_nocache(addr, size)    __ioremap((addr), (size), __pgprot(PROT_DEVICE_nGnRE))
+#define ioremap_wc(addr, size)         __ioremap((addr), (size), __pgprot(PROT_NORMAL_NC))
 #define iounmap                                __iounmap
 
 #define ARCH_HAS_IOREMAP_WC
diff --git a/arch/arm64/include/asm/linkage.h b/arch/arm64/include/asm/linkage.h
new file mode 100644 (file)
index 0000000..636c1bc
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef __ASM_LINKAGE_H
+#define __ASM_LINKAGE_H
+
+#define __ALIGN                .align 4
+#define __ALIGN_STR    ".align 4"
+
+#endif
index d6331acaf64ed3d2f975296a19f8c1ec2fe56966..42471d07d972fa6ef3ee3ab52975bc86935835f7 100644 (file)
@@ -92,30 +92,20 @@ static inline void start_thread_common(struct pt_regs *regs, unsigned long pc)
 static inline void start_thread(struct pt_regs *regs, unsigned long pc,
                                unsigned long sp)
 {
-       unsigned long *stack = (unsigned long *)sp;
-
        start_thread_common(regs, pc);
        regs->pstate = PSR_MODE_EL0t;
        regs->sp = sp;
-       regs->regs[2] = stack[2];       /* x2 (envp) */
-       regs->regs[1] = stack[1];       /* x1 (argv) */
-       regs->regs[0] = stack[0];       /* x0 (argc) */
 }
 
 #ifdef CONFIG_COMPAT
 static inline void compat_start_thread(struct pt_regs *regs, unsigned long pc,
                                       unsigned long sp)
 {
-       unsigned int *stack = (unsigned int *)sp;
-
        start_thread_common(regs, pc);
        regs->pstate = COMPAT_PSR_MODE_USR;
        if (pc & 1)
                regs->pstate |= COMPAT_PSR_T_BIT;
        regs->compat_sp = sp;
-       regs->regs[2] = stack[2];       /* x2 (envp) */
-       regs->regs[1] = stack[1];       /* x1 (argv) */
-       regs->regs[0] = stack[0];       /* x0 (argc) */
 }
 #endif
 
index 9b131b4efa0bb1caaa51348be06be65950d10aca..6913643bbe54ebd5005bfeb74302329fa5e2d0f5 100644 (file)
@@ -79,13 +79,14 @@ struct user_fpsimd_state {
 
 struct user_hwdebug_state {
        __u32           dbg_info;
+       __u32           pad;
        struct {
                __u64   addr;
                __u32   ctrl;
+               __u32   pad;
        }               dbg_regs[16];
 };
 
-
 #endif /* __ASSEMBLY__ */
 
 #endif /* _UAPI__ASM_PTRACE_H */
index 2ea3968367c265f99830db7f365668919f5f6a7c..6e1e77f1831c0cb0bf31306822ebc72ba8d3158a 100644 (file)
@@ -234,28 +234,33 @@ static int ptrace_hbp_fill_attr_ctrl(unsigned int note_type,
                                     struct arch_hw_breakpoint_ctrl ctrl,
                                     struct perf_event_attr *attr)
 {
-       int err, len, type;
+       int err, len, type, disabled = !ctrl.enabled;
 
-       err = arch_bp_generic_fields(ctrl, &len, &type);
-       if (err)
-               return err;
-
-       switch (note_type) {
-       case NT_ARM_HW_BREAK:
-               if ((type & HW_BREAKPOINT_X) != type)
-                       return -EINVAL;
-               break;
-       case NT_ARM_HW_WATCH:
-               if ((type & HW_BREAKPOINT_RW) != type)
+       if (disabled) {
+               len = 0;
+               type = HW_BREAKPOINT_EMPTY;
+       } else {
+               err = arch_bp_generic_fields(ctrl, &len, &type);
+               if (err)
+                       return err;
+
+               switch (note_type) {
+               case NT_ARM_HW_BREAK:
+                       if ((type & HW_BREAKPOINT_X) != type)
+                               return -EINVAL;
+                       break;
+               case NT_ARM_HW_WATCH:
+                       if ((type & HW_BREAKPOINT_RW) != type)
+                               return -EINVAL;
+                       break;
+               default:
                        return -EINVAL;
-               break;
-       default:
-               return -EINVAL;
+               }
        }
 
        attr->bp_len    = len;
        attr->bp_type   = type;
-       attr->disabled  = !ctrl.enabled;
+       attr->disabled  = disabled;
 
        return 0;
 }
@@ -372,7 +377,7 @@ static int ptrace_hbp_set_addr(unsigned int note_type,
 
 #define PTRACE_HBP_ADDR_SZ     sizeof(u64)
 #define PTRACE_HBP_CTRL_SZ     sizeof(u32)
-#define PTRACE_HBP_REG_OFF     sizeof(u32)
+#define PTRACE_HBP_PAD_SZ      sizeof(u32)
 
 static int hw_break_get(struct task_struct *target,
                        const struct user_regset *regset,
@@ -380,7 +385,7 @@ static int hw_break_get(struct task_struct *target,
                        void *kbuf, void __user *ubuf)
 {
        unsigned int note_type = regset->core_note_type;
-       int ret, idx = 0, offset = PTRACE_HBP_REG_OFF, limit;
+       int ret, idx = 0, offset, limit;
        u32 info, ctrl;
        u64 addr;
 
@@ -389,11 +394,20 @@ static int hw_break_get(struct task_struct *target,
        if (ret)
                return ret;
 
-       ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &info, 0, 4);
+       ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &info, 0,
+                                 sizeof(info));
+       if (ret)
+               return ret;
+
+       /* Pad */
+       offset = offsetof(struct user_hwdebug_state, pad);
+       ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, offset,
+                                      offset + PTRACE_HBP_PAD_SZ);
        if (ret)
                return ret;
 
        /* (address, ctrl) registers */
+       offset = offsetof(struct user_hwdebug_state, dbg_regs);
        limit = regset->n * regset->size;
        while (count && offset < limit) {
                ret = ptrace_hbp_get_addr(note_type, target, idx, &addr);
@@ -413,6 +427,13 @@ static int hw_break_get(struct task_struct *target,
                if (ret)
                        return ret;
                offset += PTRACE_HBP_CTRL_SZ;
+
+               ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
+                                              offset,
+                                              offset + PTRACE_HBP_PAD_SZ);
+               if (ret)
+                       return ret;
+               offset += PTRACE_HBP_PAD_SZ;
                idx++;
        }
 
@@ -425,12 +446,13 @@ static int hw_break_set(struct task_struct *target,
                        const void *kbuf, const void __user *ubuf)
 {
        unsigned int note_type = regset->core_note_type;
-       int ret, idx = 0, offset = PTRACE_HBP_REG_OFF, limit;
+       int ret, idx = 0, offset, limit;
        u32 ctrl;
        u64 addr;
 
-       /* Resource info */
-       ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 0, 4);
+       /* Resource info and pad */
+       offset = offsetof(struct user_hwdebug_state, dbg_regs);
+       ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 0, offset);
        if (ret)
                return ret;
 
@@ -454,6 +476,13 @@ static int hw_break_set(struct task_struct *target,
                if (ret)
                        return ret;
                offset += PTRACE_HBP_CTRL_SZ;
+
+               ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
+                                               offset,
+                                               offset + PTRACE_HBP_PAD_SZ);
+               if (ret)
+                       return ret;
+               offset += PTRACE_HBP_PAD_SZ;
                idx++;
        }
 
index 48ffb9fb3fe3619c6bc600452554e6e76b29ec51..7665a9bfdb1e53ebe689033eac02a78d8cf7ab99 100644 (file)
@@ -170,7 +170,19 @@ static void __init setup_machine_fdt(phys_addr_t dt_phys)
 
 void __init early_init_dt_add_memory_arch(u64 base, u64 size)
 {
+       base &= PAGE_MASK;
        size &= PAGE_MASK;
+       if (base + size < PHYS_OFFSET) {
+               pr_warning("Ignoring memory block 0x%llx - 0x%llx\n",
+                          base, base + size);
+               return;
+       }
+       if (base < PHYS_OFFSET) {
+               pr_warning("Ignoring memory range 0x%llx - 0x%llx\n",
+                          base, PHYS_OFFSET);
+               size -= PHYS_OFFSET - base;
+               base = PHYS_OFFSET;
+       }
        memblock_add(base, size);
 }
 
index b711525be21fb0116ecdfacdeeb7d0d7ca89ec73..226b6bf6e9c296ffbc0c94599b17222d69cae15d 100644 (file)
@@ -46,7 +46,6 @@
 #include <asm/sections.h>
 #include <asm/tlbflush.h>
 #include <asm/ptrace.h>
-#include <asm/mmu_context.h>
 
 /*
  * as from 2.5, kernels no longer have an init_tasks structure
index 17948fc7d663b21269f3ae738ea545b0df9ceb09..ba457943a16b26f8fb3301ef2f65e192ccbe3c94 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/sched.h>
 #include <linux/signal.h>
 #include <linux/slab.h>
+#include <linux/timekeeper_internal.h>
 #include <linux/vmalloc.h>
 
 #include <asm/cacheflush.h>
@@ -222,11 +223,10 @@ struct vm_area_struct *get_gate_vma(struct mm_struct *mm)
 /*
  * Update the vDSO data page to keep in sync with kernel timekeeping.
  */
-void update_vsyscall(struct timespec *ts, struct timespec *wtm,
-                    struct clocksource *clock, u32 mult)
+void update_vsyscall(struct timekeeper *tk)
 {
        struct timespec xtime_coarse;
-       u32 use_syscall = strcmp(clock->name, "arch_sys_counter");
+       u32 use_syscall = strcmp(tk->clock->name, "arch_sys_counter");
 
        ++vdso_data->tb_seq_count;
        smp_wmb();
@@ -237,13 +237,13 @@ void update_vsyscall(struct timespec *ts, struct timespec *wtm,
        vdso_data->xtime_coarse_nsec            = xtime_coarse.tv_nsec;
 
        if (!use_syscall) {
-               vdso_data->cs_cycle_last        = clock->cycle_last;
-               vdso_data->xtime_clock_sec      = ts->tv_sec;
-               vdso_data->xtime_clock_nsec     = ts->tv_nsec;
-               vdso_data->cs_mult              = mult;
-               vdso_data->cs_shift             = clock->shift;
-               vdso_data->wtm_clock_sec        = wtm->tv_sec;
-               vdso_data->wtm_clock_nsec       = wtm->tv_nsec;
+               vdso_data->cs_cycle_last        = tk->clock->cycle_last;
+               vdso_data->xtime_clock_sec      = tk->xtime_sec;
+               vdso_data->xtime_clock_nsec     = tk->xtime_nsec >> tk->shift;
+               vdso_data->cs_mult              = tk->mult;
+               vdso_data->cs_shift             = tk->shift;
+               vdso_data->wtm_clock_sec        = tk->wall_to_monotonic.tv_sec;
+               vdso_data->wtm_clock_nsec       = tk->wall_to_monotonic.tv_nsec;
        }
 
        smp_wmb();
index 1909a69983caceafe6034c365920c23a81e20bcf..afadae6682ed8b867f6165b0e92860f0f0cc566d 100644 (file)
@@ -36,6 +36,8 @@
 #include <asm/pgtable.h>
 #include <asm/tlbflush.h>
 
+static const char *fault_name(unsigned int esr);
+
 /*
  * Dump out the page tables associated with 'addr' in mm 'mm'.
  */
@@ -112,8 +114,9 @@ static void __do_user_fault(struct task_struct *tsk, unsigned long addr,
        struct siginfo si;
 
        if (show_unhandled_signals) {
-               pr_info("%s[%d]: unhandled page fault (%d) at 0x%08lx, code 0x%03x\n",
-                       tsk->comm, task_pid_nr(tsk), sig, addr, esr);
+               pr_info("%s[%d]: unhandled %s (%d) at 0x%08lx, esr 0x%03x\n",
+                       tsk->comm, task_pid_nr(tsk), fault_name(esr), sig,
+                       addr, esr);
                show_pte(tsk->mm, addr);
                show_regs(regs);
        }
@@ -450,6 +453,12 @@ static struct fault_info {
        { do_bad,               SIGBUS,  0,             "unknown 63"                    },
 };
 
+static const char *fault_name(unsigned int esr)
+{
+       const struct fault_info *inf = fault_info + (esr & 63);
+       return inf->name;
+}
+
 /*
  * Dispatch a data abort to the relevant handler.
  */
index 06e73bf665e92cba042590dbe68a50a463d50f76..09f9fa800b33400d79ce08433c648936cdb1bfb6 100644 (file)
@@ -80,7 +80,6 @@ config PLATFORM_AT32AP
        select ARCH_REQUIRE_GPIOLIB
        select GENERIC_ALLOCATOR
        select HAVE_FB_ATMEL
-       select HAVE_NET_MACB
 
 #
 # CPU types
index 5a0625aad6a0a45fa773f2bffc9994b1c4577e4a..9d1f5b381b8967b74a335994abb966eee71d0063 100644 (file)
@@ -1,4 +1,3 @@
-include include/asm-generic/Kbuild.asm
 
 generic-y += auxvec.h
 generic-y += bitsperlong.h
@@ -17,6 +16,7 @@ generic-y += ipcbuf.h
 generic-y += irq_regs.h
 generic-y += kdebug.h
 generic-y += kmap_types.h
+generic-y += kvm_para.h
 generic-y += local64.h
 generic-y += local.h
 generic-y += mman.h
@@ -43,7 +43,3 @@ generic-y += ucontext.h
 generic-y += unaligned.h
 generic-y += user.h
 generic-y += xor.h
-
-header-y += bfin_sport.h
-header-y += cachectl.h
-header-y += fixed_code.h
index f8907ea6b5b66d3a72e9abd30a028b49299789f7..50b9dfd4839f7b5bf12ccb5a9e8e0063f689e125 100644 (file)
@@ -5,65 +5,12 @@
  *
  * Licensed under the GPL-2 or later.
  */
-
 #ifndef __BFIN_SPORT_H__
 #define __BFIN_SPORT_H__
 
-/* Sport mode: it can be set to TDM, i2s or others */
-#define NORM_MODE      0x0
-#define TDM_MODE       0x1
-#define I2S_MODE       0x2
-#define NDSO_MODE      0x3
-
-/* Data format, normal, a-law or u-law */
-#define NORM_FORMAT    0x0
-#define ALAW_FORMAT    0x2
-#define ULAW_FORMAT    0x3
-
-/* Function driver which use sport must initialize the structure */
-struct sport_config {
-       /* TDM (multichannels), I2S or other mode */
-       unsigned int mode:3;
-       unsigned int polled;    /* use poll instead of irq when set */
-
-       /* if TDM mode is selected, channels must be set */
-       int channels;   /* Must be in 8 units */
-       unsigned int frame_delay:4;     /* Delay between frame sync pulse and first bit */
-
-       /* I2S mode */
-       unsigned int right_first:1;     /* Right stereo channel first */
-
-       /* In mormal mode, the following item need to be set */
-       unsigned int lsb_first:1;       /* order of transmit or receive data */
-       unsigned int fsync:1;   /* Frame sync required */
-       unsigned int data_indep:1;      /* data independent frame sync generated */
-       unsigned int act_low:1; /* Active low TFS */
-       unsigned int late_fsync:1;      /* Late frame sync */
-       unsigned int tckfe:1;
-       unsigned int sec_en:1;  /* Secondary side enabled */
-
-       /* Choose clock source */
-       unsigned int int_clk:1; /* Internal or external clock */
-
-       /* If external clock is used, the following fields are ignored */
-       int serial_clk;
-       int fsync_clk;
-
-       unsigned int data_format:2;     /* Normal, u-law or a-law */
-
-       int word_len;           /* How length of the word in bits, 3-32 bits */
-       int dma_enabled;
-};
-
-/* Userspace interface */
-#define SPORT_IOC_MAGIC                'P'
-#define SPORT_IOC_CONFIG       _IOWR('P', 0x01, struct sport_config)
-#define SPORT_IOC_GET_SYSTEMCLOCK         _IOR('P', 0x02, unsigned long)
-#define SPORT_IOC_SET_BAUDRATE            _IOW('P', 0x03, unsigned long)
-
-#ifdef __KERNEL__
 
 #include <linux/types.h>
+#include <uapi/asm/bfin_sport.h>
 
 /*
  * All Blackfin system MMRs are padded to 32bits even if the register
@@ -122,76 +69,3 @@ struct bfin_snd_platform_data {
 })
 
 #endif
-
-/* SPORT_TCR1 Masks */
-#define TSPEN          0x0001  /* TX enable */
-#define ITCLK          0x0002  /* Internal TX Clock Select */
-#define TDTYPE         0x000C  /* TX Data Formatting Select */
-#define DTYPE_NORM     0x0000  /* Data Format Normal */
-#define DTYPE_ULAW     0x0008  /* Compand Using u-Law */
-#define DTYPE_ALAW     0x000C  /* Compand Using A-Law */
-#define TLSBIT         0x0010  /* TX Bit Order */
-#define ITFS           0x0200  /* Internal TX Frame Sync Select */
-#define TFSR           0x0400  /* TX Frame Sync Required Select */
-#define DITFS          0x0800  /* Data Independent TX Frame Sync Select */
-#define LTFS           0x1000  /* Low TX Frame Sync Select */
-#define LATFS          0x2000  /* Late TX Frame Sync Select */
-#define TCKFE          0x4000  /* TX Clock Falling Edge Select */
-
-/* SPORT_TCR2 Masks */
-#define SLEN           0x001F  /* SPORT TX Word Length (2 - 31) */
-#define DP_SLEN(x)     BFIN_DEPOSIT(SLEN, x)
-#define EX_SLEN(x)     BFIN_EXTRACT(SLEN, x)
-#define TXSE           0x0100  /* TX Secondary Enable */
-#define TSFSE          0x0200  /* TX Stereo Frame Sync Enable */
-#define TRFST          0x0400  /* TX Right-First Data Order */
-
-/* SPORT_RCR1 Masks */
-#define RSPEN          0x0001  /* RX enable */
-#define IRCLK          0x0002  /* Internal RX Clock Select */
-#define RDTYPE         0x000C  /* RX Data Formatting Select */
-/* DTYPE_* defined above */
-#define RLSBIT         0x0010  /* RX Bit Order */
-#define IRFS           0x0200  /* Internal RX Frame Sync Select */
-#define RFSR           0x0400  /* RX Frame Sync Required Select */
-#define LRFS           0x1000  /* Low RX Frame Sync Select */
-#define LARFS          0x2000  /* Late RX Frame Sync Select */
-#define RCKFE          0x4000  /* RX Clock Falling Edge Select */
-
-/* SPORT_RCR2 Masks */
-/* SLEN defined above */
-#define RXSE           0x0100  /* RX Secondary Enable */
-#define RSFSE          0x0200  /* RX Stereo Frame Sync Enable */
-#define RRFST          0x0400  /* Right-First Data Order */
-
-/* SPORT_STAT Masks */
-#define RXNE           0x0001  /* RX FIFO Not Empty Status */
-#define RUVF           0x0002  /* RX Underflow Status */
-#define ROVF           0x0004  /* RX Overflow Status */
-#define TXF            0x0008  /* TX FIFO Full Status */
-#define TUVF           0x0010  /* TX Underflow Status */
-#define TOVF           0x0020  /* TX Overflow Status */
-#define TXHRE          0x0040  /* TX Hold Register Empty */
-
-/* SPORT_MCMC1 Masks */
-#define SP_WOFF                0x03FF  /* Multichannel Window Offset Field */
-#define DP_SP_WOFF(x)  BFIN_DEPOSIT(SP_WOFF, x)
-#define EX_SP_WOFF(x)  BFIN_EXTRACT(SP_WOFF, x)
-#define SP_WSIZE       0xF000  /* Multichannel Window Size Field */
-#define DP_SP_WSIZE(x) BFIN_DEPOSIT(SP_WSIZE, x)
-#define EX_SP_WSIZE(x) BFIN_EXTRACT(SP_WSIZE, x)
-
-/* SPORT_MCMC2 Masks */
-#define MCCRM          0x0003  /* Multichannel Clock Recovery Mode */
-#define REC_BYPASS     0x0000  /* Bypass Mode (No Clock Recovery) */
-#define REC_2FROM4     0x0002  /* Recover 2 MHz Clock from 4 MHz Clock */
-#define REC_8FROM16    0x0003  /* Recover 8 MHz Clock from 16 MHz Clock */
-#define MCDTXPE                0x0004  /* Multichannel DMA Transmit Packing */
-#define MCDRXPE                0x0008  /* Multichannel DMA Receive Packing */
-#define MCMEN          0x0010  /* Multichannel Frame Mode Enable */
-#define FSDR           0x0080  /* Multichannel Frame Sync to Data Relationship */
-#define MFD            0xF000  /* Multichannel Frame Delay */
-#define DP_MFD(x)      BFIN_DEPOSIT(MFD, x)
-#define EX_MFD(x)      BFIN_EXTRACT(MFD, x)
-
-#endif
index f4a0727874365bc748cfb80a72cd5d8e1e850a6b..90c3c006557deac76c01cf03b508dac3659bead3 100644 (file)
@@ -61,7 +61,7 @@ struct bfin_twi_iface {
        int                     cur_msg;
        u16                     saved_clkdiv;
        u16                     saved_control;
-       struct bfin_twi_regs    *regs_base;
+       struct bfin_twi_regs __iomem *regs_base;
 };
 
 #define DEFINE_TWI_REG(reg_name, reg) \
index 5395088b2d0ed4778fa5de6b0a4a5289199e636c..bc330f06207bfed4a54a7a9a375c8603134fc55e 100644 (file)
@@ -6,11 +6,11 @@
  *
  * Licensed under the GPL-2 or later.
  */
-
 #ifndef __BFIN_ASM_FIXED_CODE_H__
 #define __BFIN_ASM_FIXED_CODE_H__
 
-#ifdef __KERNEL__
+#include <uapi/asm/fixed_code.h>
+
 #ifndef __ASSEMBLY__
 #include <linux/linkage.h>
 #include <linux/ptrace.h>
@@ -28,29 +28,3 @@ extern void safe_user_instruction(void);
 extern void sigreturn_stub(void);
 #endif
 #endif
-
-#ifndef CONFIG_PHY_RAM_BASE_ADDRESS
-#define CONFIG_PHY_RAM_BASE_ADDRESS    0x0
-#endif
-
-#define FIXED_CODE_START       (CONFIG_PHY_RAM_BASE_ADDRESS + 0x400)
-
-#define SIGRETURN_STUB         (CONFIG_PHY_RAM_BASE_ADDRESS + 0x400)
-
-#define ATOMIC_SEQS_START      (CONFIG_PHY_RAM_BASE_ADDRESS + 0x410)
-
-#define ATOMIC_XCHG32          (CONFIG_PHY_RAM_BASE_ADDRESS + 0x410)
-#define ATOMIC_CAS32           (CONFIG_PHY_RAM_BASE_ADDRESS + 0x420)
-#define ATOMIC_ADD32           (CONFIG_PHY_RAM_BASE_ADDRESS + 0x430)
-#define ATOMIC_SUB32           (CONFIG_PHY_RAM_BASE_ADDRESS + 0x440)
-#define ATOMIC_IOR32           (CONFIG_PHY_RAM_BASE_ADDRESS + 0x450)
-#define ATOMIC_AND32           (CONFIG_PHY_RAM_BASE_ADDRESS + 0x460)
-#define ATOMIC_XOR32           (CONFIG_PHY_RAM_BASE_ADDRESS + 0x470)
-
-#define ATOMIC_SEQS_END                (CONFIG_PHY_RAM_BASE_ADDRESS + 0x480)
-
-#define SAFE_USER_INSTRUCTION   (CONFIG_PHY_RAM_BASE_ADDRESS + 0x480)
-
-#define FIXED_CODE_END         (CONFIG_PHY_RAM_BASE_ADDRESS + 0x490)
-
-#endif
index 10d8641180f2c24339c1abd7f81dd8008afebc7d..14ea93388c058d99fe576a0c1084284f64912678 100644 (file)
  *
  * Licensed under the GPL-2 or later.
  */
-
 #ifndef _BFIN_PTRACE_H
 #define _BFIN_PTRACE_H
 
-/*
- * GCC defines register number like this:
- * -----------------------------
- *       0 - 7 are data registers R0-R7
- *       8 - 15 are address registers P0-P7
- *      16 - 31 dsp registers I/B/L0 -- I/B/L3 & M0--M3
- *      32 - 33 A registers A0 & A1
- *      34 -    status register
- * -----------------------------
- *
- * We follows above, except:
- *      32-33 --- Low 32-bit of A0&1
- *      34-35 --- High 8-bit of A0&1
- */
+#include <uapi/asm/ptrace.h>
 
 #ifndef __ASSEMBLY__
 
-struct task_struct;
-
-/* this struct defines the way the registers are stored on the
-   stack during a system call. */
-
-struct pt_regs {
-       long orig_pc;
-       long ipend;
-       long seqstat;
-       long rete;
-       long retn;
-       long retx;
-       long pc;                /* PC == RETI */
-       long rets;
-       long reserved;          /* Used as scratch during system calls */
-       long astat;
-       long lb1;
-       long lb0;
-       long lt1;
-       long lt0;
-       long lc1;
-       long lc0;
-       long a1w;
-       long a1x;
-       long a0w;
-       long a0x;
-       long b3;
-       long b2;
-       long b1;
-       long b0;
-       long l3;
-       long l2;
-       long l1;
-       long l0;
-       long m3;
-       long m2;
-       long m1;
-       long m0;
-       long i3;
-       long i2;
-       long i1;
-       long i0;
-       long usp;
-       long fp;
-       long p5;
-       long p4;
-       long p3;
-       long p2;
-       long p1;
-       long p0;
-       long r7;
-       long r6;
-       long r5;
-       long r4;
-       long r3;
-       long r2;
-       long r1;
-       long r0;
-       long orig_r0;
-       long orig_p0;
-       long syscfg;
-};
-
-/* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
-#define PTRACE_GETREGS            12
-#define PTRACE_SETREGS            13   /* ptrace signal  */
-
-#define PTRACE_GETFDPIC           31   /* get the ELF fdpic loadmap address */
-#define PTRACE_GETFDPIC_EXEC       0   /* [addr] request the executable loadmap */
-#define PTRACE_GETFDPIC_INTERP     1   /* [addr] request the interpreter loadmap */
-
-#define PS_S  (0x0002)
-
-#ifdef __KERNEL__
-
 /* user_mode returns true if only one bit is set in IPEND, other than the
    master interrupt enable.  */
 #define user_mode(regs) (!(((regs)->ipend & ~0x10) & (((regs)->ipend & ~0x10) - 1)))
@@ -126,75 +37,5 @@ extern int is_user_addr_valid(struct task_struct *child,
 
 #include <asm-generic/ptrace.h>
 
-#endif  /*  __KERNEL__  */
-
 #endif                         /* __ASSEMBLY__ */
-
-/*
- * Offsets used by 'ptrace' system call interface.
- */
-
-#define PT_R0 204
-#define PT_R1 200
-#define PT_R2 196
-#define PT_R3 192
-#define PT_R4 188
-#define PT_R5 184
-#define PT_R6 180
-#define PT_R7 176
-#define PT_P0 172
-#define PT_P1 168
-#define PT_P2 164
-#define PT_P3 160
-#define PT_P4 156
-#define PT_P5 152
-#define PT_FP 148
-#define PT_USP 144
-#define PT_I0 140
-#define PT_I1 136
-#define PT_I2 132
-#define PT_I3 128
-#define PT_M0 124
-#define PT_M1 120
-#define PT_M2 116
-#define PT_M3 112
-#define PT_L0 108
-#define PT_L1 104
-#define PT_L2 100
-#define PT_L3 96
-#define PT_B0 92
-#define PT_B1 88
-#define PT_B2 84
-#define PT_B3 80
-#define PT_A0X 76
-#define PT_A0W 72
-#define PT_A1X 68
-#define PT_A1W 64
-#define PT_LC0 60
-#define PT_LC1 56
-#define PT_LT0 52
-#define PT_LT1 48
-#define PT_LB0 44
-#define PT_LB1 40
-#define PT_ASTAT 36
-#define PT_RESERVED 32
-#define PT_RETS 28
-#define PT_PC 24
-#define PT_RETX 20
-#define PT_RETN 16
-#define PT_RETE 12
-#define PT_SEQSTAT 8
-#define PT_IPEND 4
-
-#define PT_ORIG_R0 208
-#define PT_ORIG_P0 212
-#define PT_SYSCFG 216
-#define PT_TEXT_ADDR 220
-#define PT_TEXT_END_ADDR 224
-#define PT_DATA_ADDR 228
-#define PT_FDPIC_EXEC 232
-#define PT_FDPIC_INTERP 236
-
-#define PT_LAST_PSEUDO PT_FDPIC_INTERP
-
 #endif                         /* _BFIN_PTRACE_H */
index 5cc111502822f70a970a6c91daf9971c3386cc84..3ee7b42161507fccc091fbb003ef350107f27e51 100644 (file)
@@ -89,7 +89,7 @@ struct exception_table_entry {
        ({                                                      \
                int _err = 0;                                   \
                typeof(*(p)) _x = (x);                          \
-               typeof(*(p)) *_p = (p);                         \
+               typeof(*(p)) __user *_p = (p);                          \
                if (!access_ok(VERIFY_WRITE, _p, sizeof(*(_p)))) {\
                        _err = -EFAULT;                         \
                }                                               \
@@ -108,8 +108,8 @@ struct exception_table_entry {
                        long _xl, _xh;                          \
                        _xl = ((long *)&_x)[0];                 \
                        _xh = ((long *)&_x)[1];                 \
-                       __put_user_asm(_xl, ((long *)_p)+0, );  \
-                       __put_user_asm(_xh, ((long *)_p)+1, );  \
+                       __put_user_asm(_xl, ((long __user *)_p)+0, );   \
+                       __put_user_asm(_xh, ((long __user *)_p)+1, );   \
                } break;                                        \
                default:                                        \
                        _err = __put_user_bad();                \
@@ -136,7 +136,7 @@ static inline int bad_user_access_length(void)
  * aliasing issues.
  */
 
-#define __ptr(x) ((unsigned long *)(x))
+#define __ptr(x) ((unsigned long __force *)(x))
 
 #define __put_user_asm(x,p,bhw)                                \
        __asm__ (#bhw"[%1] = %0;\n\t"                   \
@@ -216,12 +216,12 @@ copy_to_user(void __user *to, const void *from, unsigned long n)
  */
 
 static inline long __must_check
-strncpy_from_user(char *dst, const char *src, long count)
+strncpy_from_user(char *dst, const char __user *src, long count)
 {
        char *tmp;
        if (!access_ok(VERIFY_READ, src, 1))
                return -EFAULT;
-       strncpy(dst, src, count);
+       strncpy(dst, (const char __force *)src, count);
        for (tmp = dst; *tmp && count > 0; tmp++, count--) ;
        return (tmp - dst);
 }
@@ -237,18 +237,18 @@ strncpy_from_user(char *dst, const char *src, long count)
  * On exception, returns 0.
  * If the string is too long, returns a value greater than n.
  */
-static inline long __must_check strnlen_user(const char *src, long n)
+static inline long __must_check strnlen_user(const char __user *src, long n)
 {
        if (!access_ok(VERIFY_READ, src, 1))
                return 0;
-       return strnlen(src, n) + 1;
+       return strnlen((const char __force *)src, n) + 1;
 }
 
-static inline long __must_check strlen_user(const char *src)
+static inline long __must_check strlen_user(const char __user *src)
 {
        if (!access_ok(VERIFY_READ, src, 1))
                return 0;
-       return strlen(src) + 1;
+       return strlen((const char __force *)src) + 1;
 }
 
 /*
@@ -256,11 +256,11 @@ static inline long __must_check strlen_user(const char *src)
  */
 
 static inline unsigned long __must_check
-__clear_user(void *to, unsigned long n)
+__clear_user(void __user *to, unsigned long n)
 {
        if (!access_ok(VERIFY_WRITE, to, n))
                return n;
-       memset(to, 0, n);
+       memset((void __force *)to, 0, n);
        return 0;
 }
 
index 5b2a0748d7d3e8b215c0d2aba4a3df3319743858..a5aa9bd5fed59492c3c629ddd1a19a7acdef7f25 100644 (file)
  *
  * Licensed under the GPL-2 or later.
  */
-
 #ifndef __ASM_BFIN_UNISTD_H
 #define __ASM_BFIN_UNISTD_H
-/*
- * This file contains the system call numbers.
- */
-#define __NR_restart_syscall     0
-#define __NR_exit                1
-                               /* 2 __NR_fork not supported on nommu */
-#define __NR_read                3
-#define __NR_write               4
-#define __NR_open                5
-#define __NR_close               6
-                               /* 7 __NR_waitpid obsolete */
-#define __NR_creat               8
-#define __NR_link                9
-#define __NR_unlink             10
-#define __NR_execve             11
-#define __NR_chdir              12
-#define __NR_time               13
-#define __NR_mknod              14
-#define __NR_chmod              15
-#define __NR_chown              16
-                               /* 17 __NR_break obsolete */
-                               /* 18 __NR_oldstat obsolete */
-#define __NR_lseek              19
-#define __NR_getpid             20
-#define __NR_mount              21
-                               /* 22 __NR_umount obsolete */
-#define __NR_setuid             23
-#define __NR_getuid             24
-#define __NR_stime              25
-#define __NR_ptrace             26
-#define __NR_alarm              27
-                               /* 28 __NR_oldfstat obsolete */
-#define __NR_pause              29
-                               /* 30 __NR_utime obsolete */
-                               /* 31 __NR_stty obsolete */
-                               /* 32 __NR_gtty obsolete */
-#define __NR_access             33
-#define __NR_nice               34
-                               /* 35 __NR_ftime obsolete */
-#define __NR_sync               36
-#define __NR_kill               37
-#define __NR_rename             38
-#define __NR_mkdir              39
-#define __NR_rmdir              40
-#define __NR_dup                41
-#define __NR_pipe               42
-#define __NR_times              43
-                               /* 44 __NR_prof obsolete */
-#define __NR_brk                45
-#define __NR_setgid             46
-#define __NR_getgid             47
-                               /* 48 __NR_signal obsolete */
-#define __NR_geteuid            49
-#define __NR_getegid            50
-#define __NR_acct               51
-#define __NR_umount2            52
-                               /* 53 __NR_lock obsolete */
-#define __NR_ioctl              54
-#define __NR_fcntl              55
-                               /* 56 __NR_mpx obsolete */
-#define __NR_setpgid            57
-                               /* 58 __NR_ulimit obsolete */
-                               /* 59 __NR_oldolduname obsolete */
-#define __NR_umask              60
-#define __NR_chroot             61
-#define __NR_ustat              62
-#define __NR_dup2               63
-#define __NR_getppid            64
-#define __NR_getpgrp            65
-#define __NR_setsid             66
-                               /* 67 __NR_sigaction obsolete */
-#define __NR_sgetmask           68
-#define __NR_ssetmask           69
-#define __NR_setreuid           70
-#define __NR_setregid           71
-                               /* 72 __NR_sigsuspend obsolete */
-                               /* 73 __NR_sigpending obsolete */
-#define __NR_sethostname        74
-#define __NR_setrlimit          75
-                               /* 76 __NR_old_getrlimit obsolete */
-#define __NR_getrusage          77
-#define __NR_gettimeofday       78
-#define __NR_settimeofday       79
-#define __NR_getgroups          80
-#define __NR_setgroups          81
-                               /* 82 __NR_select obsolete */
-#define __NR_symlink            83
-                               /* 84 __NR_oldlstat obsolete */
-#define __NR_readlink           85
-                               /* 86 __NR_uselib obsolete */
-                               /* 87 __NR_swapon obsolete */
-#define __NR_reboot             88
-                               /* 89 __NR_readdir obsolete */
-                               /* 90 __NR_mmap obsolete */
-#define __NR_munmap             91
-#define __NR_truncate           92
-#define __NR_ftruncate          93
-#define __NR_fchmod             94
-#define __NR_fchown             95
-#define __NR_getpriority        96
-#define __NR_setpriority        97
-                               /* 98 __NR_profil obsolete */
-#define __NR_statfs             99
-#define __NR_fstatfs           100
-                               /* 101 __NR_ioperm */
-                               /* 102 __NR_socketcall obsolete */
-#define __NR_syslog            103
-#define __NR_setitimer         104
-#define __NR_getitimer         105
-#define __NR_stat              106
-#define __NR_lstat             107
-#define __NR_fstat             108
-                               /* 109 __NR_olduname obsolete */
-                               /* 110 __NR_iopl obsolete */
-#define __NR_vhangup           111
-                               /* 112 __NR_idle obsolete */
-                               /* 113 __NR_vm86old */
-#define __NR_wait4             114
-                               /* 115 __NR_swapoff obsolete */
-#define __NR_sysinfo           116
-                               /* 117 __NR_ipc oboslete */
-#define __NR_fsync             118
-                               /* 119 __NR_sigreturn obsolete */
-#define __NR_clone             120
-#define __NR_setdomainname     121
-#define __NR_uname             122
-                               /* 123 __NR_modify_ldt obsolete */
-#define __NR_adjtimex          124
-#define __NR_mprotect          125
-                               /* 126 __NR_sigprocmask obsolete */
-                               /* 127 __NR_create_module obsolete */
-#define __NR_init_module       128
-#define __NR_delete_module     129
-                               /* 130 __NR_get_kernel_syms obsolete */
-#define __NR_quotactl          131
-#define __NR_getpgid           132
-#define __NR_fchdir            133
-#define __NR_bdflush           134
-                               /* 135 was sysfs */
-#define __NR_personality       136
-                               /* 137 __NR_afs_syscall */
-#define __NR_setfsuid          138
-#define __NR_setfsgid          139
-#define __NR__llseek           140
-#define __NR_getdents          141
-                               /* 142 __NR__newselect obsolete */
-#define __NR_flock             143
-                               /* 144 __NR_msync obsolete */
-#define __NR_readv             145
-#define __NR_writev            146
-#define __NR_getsid            147
-#define __NR_fdatasync         148
-#define __NR__sysctl           149
-                               /* 150 __NR_mlock */
-                               /* 151 __NR_munlock */
-                               /* 152 __NR_mlockall */
-                               /* 153 __NR_munlockall */
-#define __NR_sched_setparam            154
-#define __NR_sched_getparam            155
-#define __NR_sched_setscheduler                156
-#define __NR_sched_getscheduler                157
-#define __NR_sched_yield               158
-#define __NR_sched_get_priority_max    159
-#define __NR_sched_get_priority_min    160
-#define __NR_sched_rr_get_interval     161
-#define __NR_nanosleep         162
-#define __NR_mremap            163
-#define __NR_setresuid         164
-#define __NR_getresuid         165
-                               /* 166 __NR_vm86 */
-                               /* 167 __NR_query_module */
-                               /* 168 __NR_poll */
-#define __NR_nfsservctl                169
-#define __NR_setresgid         170
-#define __NR_getresgid         171
-#define __NR_prctl             172
-#define __NR_rt_sigreturn      173
-#define __NR_rt_sigaction      174
-#define __NR_rt_sigprocmask    175
-#define __NR_rt_sigpending     176
-#define __NR_rt_sigtimedwait   177
-#define __NR_rt_sigqueueinfo   178
-#define __NR_rt_sigsuspend     179
-#define __NR_pread             180
-#define __NR_pwrite            181
-#define __NR_lchown            182
-#define __NR_getcwd            183
-#define __NR_capget            184
-#define __NR_capset            185
-#define __NR_sigaltstack       186
-#define __NR_sendfile          187
-                               /* 188 __NR_getpmsg */
-                               /* 189 __NR_putpmsg */
-#define __NR_vfork             190
-#define __NR_getrlimit         191
-#define __NR_mmap2             192
-#define __NR_truncate64                193
-#define __NR_ftruncate64       194
-#define __NR_stat64            195
-#define __NR_lstat64           196
-#define __NR_fstat64           197
-#define __NR_chown32           198
-#define __NR_getuid32          199
-#define __NR_getgid32          200
-#define __NR_geteuid32         201
-#define __NR_getegid32         202
-#define __NR_setreuid32                203
-#define __NR_setregid32                204
-#define __NR_getgroups32       205
-#define __NR_setgroups32       206
-#define __NR_fchown32          207
-#define __NR_setresuid32       208
-#define __NR_getresuid32       209
-#define __NR_setresgid32       210
-#define __NR_getresgid32       211
-#define __NR_lchown32          212
-#define __NR_setuid32          213
-#define __NR_setgid32          214
-#define __NR_setfsuid32                215
-#define __NR_setfsgid32                216
-#define __NR_pivot_root                217
-                               /* 218 __NR_mincore */
-                               /* 219 __NR_madvise */
-#define __NR_getdents64                220
-#define __NR_fcntl64           221
-                               /* 222 reserved for TUX */
-                               /* 223 reserved for TUX */
-#define __NR_gettid            224
-#define __NR_readahead         225
-#define __NR_setxattr          226
-#define __NR_lsetxattr         227
-#define __NR_fsetxattr         228
-#define __NR_getxattr          229
-#define __NR_lgetxattr         230
-#define __NR_fgetxattr         231
-#define __NR_listxattr         232
-#define __NR_llistxattr                233
-#define __NR_flistxattr                234
-#define __NR_removexattr       235
-#define __NR_lremovexattr      236
-#define __NR_fremovexattr      237
-#define __NR_tkill             238
-#define __NR_sendfile64                239
-#define __NR_futex             240
-#define __NR_sched_setaffinity 241
-#define __NR_sched_getaffinity 242
-                               /* 243 __NR_set_thread_area */
-                               /* 244 __NR_get_thread_area */
-#define __NR_io_setup          245
-#define __NR_io_destroy                246
-#define __NR_io_getevents      247
-#define __NR_io_submit         248
-#define __NR_io_cancel         249
-                               /* 250 __NR_alloc_hugepages */
-                               /* 251 __NR_free_hugepages */
-#define __NR_exit_group                252
-#define __NR_lookup_dcookie     253
-#define __NR_bfin_spinlock      254
-
-#define __NR_epoll_create      255
-#define __NR_epoll_ctl         256
-#define __NR_epoll_wait                257
-                               /* 258 __NR_remap_file_pages */
-#define __NR_set_tid_address   259
-#define __NR_timer_create      260
-#define __NR_timer_settime     261
-#define __NR_timer_gettime     262
-#define __NR_timer_getoverrun  263
-#define __NR_timer_delete      264
-#define __NR_clock_settime     265
-#define __NR_clock_gettime     266
-#define __NR_clock_getres      267
-#define __NR_clock_nanosleep   268
-#define __NR_statfs64          269
-#define __NR_fstatfs64         270
-#define __NR_tgkill            271
-#define __NR_utimes            272
-#define __NR_fadvise64_64      273
-                               /* 274 __NR_vserver */
-                               /* 275 __NR_mbind */
-                               /* 276 __NR_get_mempolicy */
-                               /* 277 __NR_set_mempolicy */
-#define __NR_mq_open           278
-#define __NR_mq_unlink         279
-#define __NR_mq_timedsend      280
-#define __NR_mq_timedreceive   281
-#define __NR_mq_notify         282
-#define __NR_mq_getsetattr     283
-#define __NR_kexec_load                284
-#define __NR_waitid            285
-#define __NR_add_key           286
-#define __NR_request_key       287
-#define __NR_keyctl            288
-#define __NR_ioprio_set                289
-#define __NR_ioprio_get                290
-#define __NR_inotify_init      291
-#define __NR_inotify_add_watch 292
-#define __NR_inotify_rm_watch  293
-                               /* 294 __NR_migrate_pages */
-#define __NR_openat            295
-#define __NR_mkdirat           296
-#define __NR_mknodat           297
-#define __NR_fchownat          298
-#define __NR_futimesat         299
-#define __NR_fstatat64         300
-#define __NR_unlinkat          301
-#define __NR_renameat          302
-#define __NR_linkat            303
-#define __NR_symlinkat         304
-#define __NR_readlinkat                305
-#define __NR_fchmodat          306
-#define __NR_faccessat         307
-#define __NR_pselect6          308
-#define __NR_ppoll             309
-#define __NR_unshare           310
-
-/* Blackfin private syscalls */
-#define __NR_sram_alloc                311
-#define __NR_sram_free         312
-#define __NR_dma_memcpy                313
-
-/* socket syscalls */
-#define __NR_accept            314
-#define __NR_bind              315
-#define __NR_connect           316
-#define __NR_getpeername       317
-#define __NR_getsockname       318
-#define __NR_getsockopt                319
-#define __NR_listen            320
-#define __NR_recv              321
-#define __NR_recvfrom          322
-#define __NR_recvmsg           323
-#define __NR_send              324
-#define __NR_sendmsg           325
-#define __NR_sendto            326
-#define __NR_setsockopt                327
-#define __NR_shutdown          328
-#define __NR_socket            329
-#define __NR_socketpair                330
-
-/* sysv ipc syscalls */
-#define __NR_semctl            331
-#define __NR_semget            332
-#define __NR_semop             333
-#define __NR_msgctl            334
-#define __NR_msgget            335
-#define __NR_msgrcv            336
-#define __NR_msgsnd            337
-#define __NR_shmat             338
-#define __NR_shmctl            339
-#define __NR_shmdt             340
-#define __NR_shmget            341
 
-#define __NR_splice            342
-#define __NR_sync_file_range   343
-#define __NR_tee               344
-#define __NR_vmsplice          345
+#include <uapi/asm/unistd.h>
 
-#define __NR_epoll_pwait       346
-#define __NR_utimensat         347
-#define __NR_signalfd          348
-#define __NR_timerfd_create    349
-#define __NR_eventfd           350
-#define __NR_pread64           351
-#define __NR_pwrite64          352
-#define __NR_fadvise64         353
-#define __NR_set_robust_list   354
-#define __NR_get_robust_list   355
-#define __NR_fallocate         356
-#define __NR_semtimedop                357
-#define __NR_timerfd_settime   358
-#define __NR_timerfd_gettime   359
-#define __NR_signalfd4         360
-#define __NR_eventfd2          361
-#define __NR_epoll_create1     362
-#define __NR_dup3              363
-#define __NR_pipe2             364
-#define __NR_inotify_init1     365
-#define __NR_preadv            366
-#define __NR_pwritev           367
-#define __NR_rt_tgsigqueueinfo 368
-#define __NR_perf_event_open   369
-#define __NR_recvmmsg          370
-#define __NR_fanotify_init     371
-#define __NR_fanotify_mark     372
-#define __NR_prlimit64         373
-#define __NR_cacheflush                374
-#define __NR_name_to_handle_at 375
-#define __NR_open_by_handle_at 376
-#define __NR_clock_adjtime     377
-#define __NR_syncfs            378
-#define __NR_setns             379
-#define __NR_sendmmsg          380
-#define __NR_process_vm_readv  381
-#define __NR_process_vm_writev 382
-
-#define __NR_syscall           383
-#define NR_syscalls            __NR_syscall
-
-/* Old optional stuff no one actually uses */
-#define __IGNORE_sysfs
-#define __IGNORE_uselib
-
-/* Implement the newer interfaces */
-#define __IGNORE_mmap
-#define __IGNORE_poll
-#define __IGNORE_select
-#define __IGNORE_utime
-
-/* Not relevant on no-mmu */
-#define __IGNORE_swapon
-#define __IGNORE_swapoff
-#define __IGNORE_msync
-#define __IGNORE_mlock
-#define __IGNORE_munlock
-#define __IGNORE_mlockall
-#define __IGNORE_munlockall
-#define __IGNORE_mincore
-#define __IGNORE_madvise
-#define __IGNORE_remap_file_pages
-#define __IGNORE_mbind
-#define __IGNORE_get_mempolicy
-#define __IGNORE_set_mempolicy
-#define __IGNORE_migrate_pages
-#define __IGNORE_move_pages
-#define __IGNORE_getcpu
-
-#ifdef __KERNEL__
 #define __ARCH_WANT_STAT64
 #define __ARCH_WANT_SYS_ALARM
 #define __ARCH_WANT_SYS_GETHOSTNAME
  */
 #define cond_syscall(x) asm(".weak\t_" #x "\n\t.set\t_" #x ",_sys_ni_syscall");
 
-#endif /* __KERNEL__ */
-
 #endif                         /* __ASM_BFIN_UNISTD_H */
index baebb3da1d44160fc6f6f259886656e6f494b167..0bd28f77abc35fd0dc47e26e70f3defa90b0341f 100644 (file)
@@ -1,3 +1,19 @@
 # UAPI Header export list
 include include/uapi/asm-generic/Kbuild.asm
 
+header-y += bfin_sport.h
+header-y += byteorder.h
+header-y += cachectl.h
+header-y += fcntl.h
+header-y += fixed_code.h
+header-y += ioctls.h
+header-y += kvm_para.h
+header-y += poll.h
+header-y += posix_types.h
+header-y += ptrace.h
+header-y += sigcontext.h
+header-y += siginfo.h
+header-y += signal.h
+header-y += stat.h
+header-y += swab.h
+header-y += unistd.h
diff --git a/arch/blackfin/include/uapi/asm/bfin_sport.h b/arch/blackfin/include/uapi/asm/bfin_sport.h
new file mode 100644 (file)
index 0000000..c086de8
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * bfin_sport.h - interface to Blackfin SPORTs
+ *
+ * Copyright 2004-2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef _UAPI__BFIN_SPORT_H__
+#define _UAPI__BFIN_SPORT_H__
+
+/* Sport mode: it can be set to TDM, i2s or others */
+#define NORM_MODE      0x0
+#define TDM_MODE       0x1
+#define I2S_MODE       0x2
+#define NDSO_MODE      0x3
+
+/* Data format, normal, a-law or u-law */
+#define NORM_FORMAT    0x0
+#define ALAW_FORMAT    0x2
+#define ULAW_FORMAT    0x3
+
+/* Function driver which use sport must initialize the structure */
+struct sport_config {
+       /* TDM (multichannels), I2S or other mode */
+       unsigned int mode:3;
+       unsigned int polled;    /* use poll instead of irq when set */
+
+       /* if TDM mode is selected, channels must be set */
+       int channels;   /* Must be in 8 units */
+       unsigned int frame_delay:4;     /* Delay between frame sync pulse and first bit */
+
+       /* I2S mode */
+       unsigned int right_first:1;     /* Right stereo channel first */
+
+       /* In mormal mode, the following item need to be set */
+       unsigned int lsb_first:1;       /* order of transmit or receive data */
+       unsigned int fsync:1;   /* Frame sync required */
+       unsigned int data_indep:1;      /* data independent frame sync generated */
+       unsigned int act_low:1; /* Active low TFS */
+       unsigned int late_fsync:1;      /* Late frame sync */
+       unsigned int tckfe:1;
+       unsigned int sec_en:1;  /* Secondary side enabled */
+
+       /* Choose clock source */
+       unsigned int int_clk:1; /* Internal or external clock */
+
+       /* If external clock is used, the following fields are ignored */
+       int serial_clk;
+       int fsync_clk;
+
+       unsigned int data_format:2;     /* Normal, u-law or a-law */
+
+       int word_len;           /* How length of the word in bits, 3-32 bits */
+       int dma_enabled;
+};
+
+/* Userspace interface */
+#define SPORT_IOC_MAGIC                'P'
+#define SPORT_IOC_CONFIG       _IOWR('P', 0x01, struct sport_config)
+#define SPORT_IOC_GET_SYSTEMCLOCK         _IOR('P', 0x02, unsigned long)
+#define SPORT_IOC_SET_BAUDRATE            _IOW('P', 0x03, unsigned long)
+
+
+/* SPORT_TCR1 Masks */
+#define TSPEN          0x0001  /* TX enable */
+#define ITCLK          0x0002  /* Internal TX Clock Select */
+#define TDTYPE         0x000C  /* TX Data Formatting Select */
+#define DTYPE_NORM     0x0000  /* Data Format Normal */
+#define DTYPE_ULAW     0x0008  /* Compand Using u-Law */
+#define DTYPE_ALAW     0x000C  /* Compand Using A-Law */
+#define TLSBIT         0x0010  /* TX Bit Order */
+#define ITFS           0x0200  /* Internal TX Frame Sync Select */
+#define TFSR           0x0400  /* TX Frame Sync Required Select */
+#define DITFS          0x0800  /* Data Independent TX Frame Sync Select */
+#define LTFS           0x1000  /* Low TX Frame Sync Select */
+#define LATFS          0x2000  /* Late TX Frame Sync Select */
+#define TCKFE          0x4000  /* TX Clock Falling Edge Select */
+
+/* SPORT_TCR2 Masks */
+#define SLEN           0x001F  /* SPORT TX Word Length (2 - 31) */
+#define DP_SLEN(x)     BFIN_DEPOSIT(SLEN, x)
+#define EX_SLEN(x)     BFIN_EXTRACT(SLEN, x)
+#define TXSE           0x0100  /* TX Secondary Enable */
+#define TSFSE          0x0200  /* TX Stereo Frame Sync Enable */
+#define TRFST          0x0400  /* TX Right-First Data Order */
+
+/* SPORT_RCR1 Masks */
+#define RSPEN          0x0001  /* RX enable */
+#define IRCLK          0x0002  /* Internal RX Clock Select */
+#define RDTYPE         0x000C  /* RX Data Formatting Select */
+/* DTYPE_* defined above */
+#define RLSBIT         0x0010  /* RX Bit Order */
+#define IRFS           0x0200  /* Internal RX Frame Sync Select */
+#define RFSR           0x0400  /* RX Frame Sync Required Select */
+#define LRFS           0x1000  /* Low RX Frame Sync Select */
+#define LARFS          0x2000  /* Late RX Frame Sync Select */
+#define RCKFE          0x4000  /* RX Clock Falling Edge Select */
+
+/* SPORT_RCR2 Masks */
+/* SLEN defined above */
+#define RXSE           0x0100  /* RX Secondary Enable */
+#define RSFSE          0x0200  /* RX Stereo Frame Sync Enable */
+#define RRFST          0x0400  /* Right-First Data Order */
+
+/* SPORT_STAT Masks */
+#define RXNE           0x0001  /* RX FIFO Not Empty Status */
+#define RUVF           0x0002  /* RX Underflow Status */
+#define ROVF           0x0004  /* RX Overflow Status */
+#define TXF            0x0008  /* TX FIFO Full Status */
+#define TUVF           0x0010  /* TX Underflow Status */
+#define TOVF           0x0020  /* TX Overflow Status */
+#define TXHRE          0x0040  /* TX Hold Register Empty */
+
+/* SPORT_MCMC1 Masks */
+#define SP_WOFF                0x03FF  /* Multichannel Window Offset Field */
+#define DP_SP_WOFF(x)  BFIN_DEPOSIT(SP_WOFF, x)
+#define EX_SP_WOFF(x)  BFIN_EXTRACT(SP_WOFF, x)
+#define SP_WSIZE       0xF000  /* Multichannel Window Size Field */
+#define DP_SP_WSIZE(x) BFIN_DEPOSIT(SP_WSIZE, x)
+#define EX_SP_WSIZE(x) BFIN_EXTRACT(SP_WSIZE, x)
+
+/* SPORT_MCMC2 Masks */
+#define MCCRM          0x0003  /* Multichannel Clock Recovery Mode */
+#define REC_BYPASS     0x0000  /* Bypass Mode (No Clock Recovery) */
+#define REC_2FROM4     0x0002  /* Recover 2 MHz Clock from 4 MHz Clock */
+#define REC_8FROM16    0x0003  /* Recover 8 MHz Clock from 16 MHz Clock */
+#define MCDTXPE                0x0004  /* Multichannel DMA Transmit Packing */
+#define MCDRXPE                0x0008  /* Multichannel DMA Receive Packing */
+#define MCMEN          0x0010  /* Multichannel Frame Mode Enable */
+#define FSDR           0x0080  /* Multichannel Frame Sync to Data Relationship */
+#define MFD            0xF000  /* Multichannel Frame Delay */
+#define DP_MFD(x)      BFIN_DEPOSIT(MFD, x)
+#define EX_MFD(x)      BFIN_EXTRACT(MFD, x)
+
+#endif /* _UAPI__BFIN_SPORT_H__ */
diff --git a/arch/blackfin/include/uapi/asm/fixed_code.h b/arch/blackfin/include/uapi/asm/fixed_code.h
new file mode 100644 (file)
index 0000000..3bef1dc
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * This file defines the fixed addresses where userspace programs
+ * can find atomic code sequences.
+ *
+ * Copyright 2007-2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef _UAPI__BFIN_ASM_FIXED_CODE_H__
+#define _UAPI__BFIN_ASM_FIXED_CODE_H__
+
+
+#ifndef CONFIG_PHY_RAM_BASE_ADDRESS
+#define CONFIG_PHY_RAM_BASE_ADDRESS    0x0
+#endif
+
+#define FIXED_CODE_START       (CONFIG_PHY_RAM_BASE_ADDRESS + 0x400)
+
+#define SIGRETURN_STUB         (CONFIG_PHY_RAM_BASE_ADDRESS + 0x400)
+
+#define ATOMIC_SEQS_START      (CONFIG_PHY_RAM_BASE_ADDRESS + 0x410)
+
+#define ATOMIC_XCHG32          (CONFIG_PHY_RAM_BASE_ADDRESS + 0x410)
+#define ATOMIC_CAS32           (CONFIG_PHY_RAM_BASE_ADDRESS + 0x420)
+#define ATOMIC_ADD32           (CONFIG_PHY_RAM_BASE_ADDRESS + 0x430)
+#define ATOMIC_SUB32           (CONFIG_PHY_RAM_BASE_ADDRESS + 0x440)
+#define ATOMIC_IOR32           (CONFIG_PHY_RAM_BASE_ADDRESS + 0x450)
+#define ATOMIC_AND32           (CONFIG_PHY_RAM_BASE_ADDRESS + 0x460)
+#define ATOMIC_XOR32           (CONFIG_PHY_RAM_BASE_ADDRESS + 0x470)
+
+#define ATOMIC_SEQS_END                (CONFIG_PHY_RAM_BASE_ADDRESS + 0x480)
+
+#define SAFE_USER_INSTRUCTION   (CONFIG_PHY_RAM_BASE_ADDRESS + 0x480)
+
+#define FIXED_CODE_END         (CONFIG_PHY_RAM_BASE_ADDRESS + 0x490)
+
+#endif /* _UAPI__BFIN_ASM_FIXED_CODE_H__ */
diff --git a/arch/blackfin/include/uapi/asm/ptrace.h b/arch/blackfin/include/uapi/asm/ptrace.h
new file mode 100644 (file)
index 0000000..fd48bd0
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+ * Copyright 2004-2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef _UAPI_BFIN_PTRACE_H
+#define _UAPI_BFIN_PTRACE_H
+
+/*
+ * GCC defines register number like this:
+ * -----------------------------
+ *       0 - 7 are data registers R0-R7
+ *       8 - 15 are address registers P0-P7
+ *      16 - 31 dsp registers I/B/L0 -- I/B/L3 & M0--M3
+ *      32 - 33 A registers A0 & A1
+ *      34 -    status register
+ * -----------------------------
+ *
+ * We follows above, except:
+ *      32-33 --- Low 32-bit of A0&1
+ *      34-35 --- High 8-bit of A0&1
+ */
+
+#ifndef __ASSEMBLY__
+
+struct task_struct;
+
+/* this struct defines the way the registers are stored on the
+   stack during a system call. */
+
+struct pt_regs {
+       long orig_pc;
+       long ipend;
+       long seqstat;
+       long rete;
+       long retn;
+       long retx;
+       long pc;                /* PC == RETI */
+       long rets;
+       long reserved;          /* Used as scratch during system calls */
+       long astat;
+       long lb1;
+       long lb0;
+       long lt1;
+       long lt0;
+       long lc1;
+       long lc0;
+       long a1w;
+       long a1x;
+       long a0w;
+       long a0x;
+       long b3;
+       long b2;
+       long b1;
+       long b0;
+       long l3;
+       long l2;
+       long l1;
+       long l0;
+       long m3;
+       long m2;
+       long m1;
+       long m0;
+       long i3;
+       long i2;
+       long i1;
+       long i0;
+       long usp;
+       long fp;
+       long p5;
+       long p4;
+       long p3;
+       long p2;
+       long p1;
+       long p0;
+       long r7;
+       long r6;
+       long r5;
+       long r4;
+       long r3;
+       long r2;
+       long r1;
+       long r0;
+       long orig_r0;
+       long orig_p0;
+       long syscfg;
+};
+
+/* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
+#define PTRACE_GETREGS            12
+#define PTRACE_SETREGS            13   /* ptrace signal  */
+
+#define PTRACE_GETFDPIC           31   /* get the ELF fdpic loadmap address */
+#define PTRACE_GETFDPIC_EXEC       0   /* [addr] request the executable loadmap */
+#define PTRACE_GETFDPIC_INTERP     1   /* [addr] request the interpreter loadmap */
+
+#define PS_S  (0x0002)
+
+
+#endif                         /* __ASSEMBLY__ */
+
+/*
+ * Offsets used by 'ptrace' system call interface.
+ */
+
+#define PT_R0 204
+#define PT_R1 200
+#define PT_R2 196
+#define PT_R3 192
+#define PT_R4 188
+#define PT_R5 184
+#define PT_R6 180
+#define PT_R7 176
+#define PT_P0 172
+#define PT_P1 168
+#define PT_P2 164
+#define PT_P3 160
+#define PT_P4 156
+#define PT_P5 152
+#define PT_FP 148
+#define PT_USP 144
+#define PT_I0 140
+#define PT_I1 136
+#define PT_I2 132
+#define PT_I3 128
+#define PT_M0 124
+#define PT_M1 120
+#define PT_M2 116
+#define PT_M3 112
+#define PT_L0 108
+#define PT_L1 104
+#define PT_L2 100
+#define PT_L3 96
+#define PT_B0 92
+#define PT_B1 88
+#define PT_B2 84
+#define PT_B3 80
+#define PT_A0X 76
+#define PT_A0W 72
+#define PT_A1X 68
+#define PT_A1W 64
+#define PT_LC0 60
+#define PT_LC1 56
+#define PT_LT0 52
+#define PT_LT1 48
+#define PT_LB0 44
+#define PT_LB1 40
+#define PT_ASTAT 36
+#define PT_RESERVED 32
+#define PT_RETS 28
+#define PT_PC 24
+#define PT_RETX 20
+#define PT_RETN 16
+#define PT_RETE 12
+#define PT_SEQSTAT 8
+#define PT_IPEND 4
+
+#define PT_ORIG_R0 208
+#define PT_ORIG_P0 212
+#define PT_SYSCFG 216
+#define PT_TEXT_ADDR 220
+#define PT_TEXT_END_ADDR 224
+#define PT_DATA_ADDR 228
+#define PT_FDPIC_EXEC 232
+#define PT_FDPIC_INTERP 236
+
+#define PT_LAST_PSEUDO PT_FDPIC_INTERP
+
+#endif /* _UAPI_BFIN_PTRACE_H */
diff --git a/arch/blackfin/include/uapi/asm/unistd.h b/arch/blackfin/include/uapi/asm/unistd.h
new file mode 100644 (file)
index 0000000..a451164
--- /dev/null
@@ -0,0 +1,437 @@
+/*
+ * Copyright 2004-2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef _UAPI__ASM_BFIN_UNISTD_H
+#define _UAPI__ASM_BFIN_UNISTD_H
+/*
+ * This file contains the system call numbers.
+ */
+#define __NR_restart_syscall     0
+#define __NR_exit                1
+                               /* 2 __NR_fork not supported on nommu */
+#define __NR_read                3
+#define __NR_write               4
+#define __NR_open                5
+#define __NR_close               6
+                               /* 7 __NR_waitpid obsolete */
+#define __NR_creat               8
+#define __NR_link                9
+#define __NR_unlink             10
+#define __NR_execve             11
+#define __NR_chdir              12
+#define __NR_time               13
+#define __NR_mknod              14
+#define __NR_chmod              15
+#define __NR_chown              16
+                               /* 17 __NR_break obsolete */
+                               /* 18 __NR_oldstat obsolete */
+#define __NR_lseek              19
+#define __NR_getpid             20
+#define __NR_mount              21
+                               /* 22 __NR_umount obsolete */
+#define __NR_setuid             23
+#define __NR_getuid             24
+#define __NR_stime              25
+#define __NR_ptrace             26
+#define __NR_alarm              27
+                               /* 28 __NR_oldfstat obsolete */
+#define __NR_pause              29
+                               /* 30 __NR_utime obsolete */
+                               /* 31 __NR_stty obsolete */
+                               /* 32 __NR_gtty obsolete */
+#define __NR_access             33
+#define __NR_nice               34
+                               /* 35 __NR_ftime obsolete */
+#define __NR_sync               36
+#define __NR_kill               37
+#define __NR_rename             38
+#define __NR_mkdir              39
+#define __NR_rmdir              40
+#define __NR_dup                41
+#define __NR_pipe               42
+#define __NR_times              43
+                               /* 44 __NR_prof obsolete */
+#define __NR_brk                45
+#define __NR_setgid             46
+#define __NR_getgid             47
+                               /* 48 __NR_signal obsolete */
+#define __NR_geteuid            49
+#define __NR_getegid            50
+#define __NR_acct               51
+#define __NR_umount2            52
+                               /* 53 __NR_lock obsolete */
+#define __NR_ioctl              54
+#define __NR_fcntl              55
+                               /* 56 __NR_mpx obsolete */
+#define __NR_setpgid            57
+                               /* 58 __NR_ulimit obsolete */
+                               /* 59 __NR_oldolduname obsolete */
+#define __NR_umask              60
+#define __NR_chroot             61
+#define __NR_ustat              62
+#define __NR_dup2               63
+#define __NR_getppid            64
+#define __NR_getpgrp            65
+#define __NR_setsid             66
+                               /* 67 __NR_sigaction obsolete */
+#define __NR_sgetmask           68
+#define __NR_ssetmask           69
+#define __NR_setreuid           70
+#define __NR_setregid           71
+                               /* 72 __NR_sigsuspend obsolete */
+                               /* 73 __NR_sigpending obsolete */
+#define __NR_sethostname        74
+#define __NR_setrlimit          75
+                               /* 76 __NR_old_getrlimit obsolete */
+#define __NR_getrusage          77
+#define __NR_gettimeofday       78
+#define __NR_settimeofday       79
+#define __NR_getgroups          80
+#define __NR_setgroups          81
+                               /* 82 __NR_select obsolete */
+#define __NR_symlink            83
+                               /* 84 __NR_oldlstat obsolete */
+#define __NR_readlink           85
+                               /* 86 __NR_uselib obsolete */
+                               /* 87 __NR_swapon obsolete */
+#define __NR_reboot             88
+                               /* 89 __NR_readdir obsolete */
+                               /* 90 __NR_mmap obsolete */
+#define __NR_munmap             91
+#define __NR_truncate           92
+#define __NR_ftruncate          93
+#define __NR_fchmod             94
+#define __NR_fchown             95
+#define __NR_getpriority        96
+#define __NR_setpriority        97
+                               /* 98 __NR_profil obsolete */
+#define __NR_statfs             99
+#define __NR_fstatfs           100
+                               /* 101 __NR_ioperm */
+                               /* 102 __NR_socketcall obsolete */
+#define __NR_syslog            103
+#define __NR_setitimer         104
+#define __NR_getitimer         105
+#define __NR_stat              106
+#define __NR_lstat             107
+#define __NR_fstat             108
+                               /* 109 __NR_olduname obsolete */
+                               /* 110 __NR_iopl obsolete */
+#define __NR_vhangup           111
+                               /* 112 __NR_idle obsolete */
+                               /* 113 __NR_vm86old */
+#define __NR_wait4             114
+                               /* 115 __NR_swapoff obsolete */
+#define __NR_sysinfo           116
+                               /* 117 __NR_ipc oboslete */
+#define __NR_fsync             118
+                               /* 119 __NR_sigreturn obsolete */
+#define __NR_clone             120
+#define __NR_setdomainname     121
+#define __NR_uname             122
+                               /* 123 __NR_modify_ldt obsolete */
+#define __NR_adjtimex          124
+#define __NR_mprotect          125
+                               /* 126 __NR_sigprocmask obsolete */
+                               /* 127 __NR_create_module obsolete */
+#define __NR_init_module       128
+#define __NR_delete_module     129
+                               /* 130 __NR_get_kernel_syms obsolete */
+#define __NR_quotactl          131
+#define __NR_getpgid           132
+#define __NR_fchdir            133
+#define __NR_bdflush           134
+                               /* 135 was sysfs */
+#define __NR_personality       136
+                               /* 137 __NR_afs_syscall */
+#define __NR_setfsuid          138
+#define __NR_setfsgid          139
+#define __NR__llseek           140
+#define __NR_getdents          141
+                               /* 142 __NR__newselect obsolete */
+#define __NR_flock             143
+                               /* 144 __NR_msync obsolete */
+#define __NR_readv             145
+#define __NR_writev            146
+#define __NR_getsid            147
+#define __NR_fdatasync         148
+#define __NR__sysctl           149
+                               /* 150 __NR_mlock */
+                               /* 151 __NR_munlock */
+                               /* 152 __NR_mlockall */
+                               /* 153 __NR_munlockall */
+#define __NR_sched_setparam            154
+#define __NR_sched_getparam            155
+#define __NR_sched_setscheduler                156
+#define __NR_sched_getscheduler                157
+#define __NR_sched_yield               158
+#define __NR_sched_get_priority_max    159
+#define __NR_sched_get_priority_min    160
+#define __NR_sched_rr_get_interval     161
+#define __NR_nanosleep         162
+#define __NR_mremap            163
+#define __NR_setresuid         164
+#define __NR_getresuid         165
+                               /* 166 __NR_vm86 */
+                               /* 167 __NR_query_module */
+                               /* 168 __NR_poll */
+#define __NR_nfsservctl                169
+#define __NR_setresgid         170
+#define __NR_getresgid         171
+#define __NR_prctl             172
+#define __NR_rt_sigreturn      173
+#define __NR_rt_sigaction      174
+#define __NR_rt_sigprocmask    175
+#define __NR_rt_sigpending     176
+#define __NR_rt_sigtimedwait   177
+#define __NR_rt_sigqueueinfo   178
+#define __NR_rt_sigsuspend     179
+#define __NR_pread             180
+#define __NR_pwrite            181
+#define __NR_lchown            182
+#define __NR_getcwd            183
+#define __NR_capget            184
+#define __NR_capset            185
+#define __NR_sigaltstack       186
+#define __NR_sendfile          187
+                               /* 188 __NR_getpmsg */
+                               /* 189 __NR_putpmsg */
+#define __NR_vfork             190
+#define __NR_getrlimit         191
+#define __NR_mmap2             192
+#define __NR_truncate64                193
+#define __NR_ftruncate64       194
+#define __NR_stat64            195
+#define __NR_lstat64           196
+#define __NR_fstat64           197
+#define __NR_chown32           198
+#define __NR_getuid32          199
+#define __NR_getgid32          200
+#define __NR_geteuid32         201
+#define __NR_getegid32         202
+#define __NR_setreuid32                203
+#define __NR_setregid32                204
+#define __NR_getgroups32       205
+#define __NR_setgroups32       206
+#define __NR_fchown32          207
+#define __NR_setresuid32       208
+#define __NR_getresuid32       209
+#define __NR_setresgid32       210
+#define __NR_getresgid32       211
+#define __NR_lchown32          212
+#define __NR_setuid32          213
+#define __NR_setgid32          214
+#define __NR_setfsuid32                215
+#define __NR_setfsgid32                216
+#define __NR_pivot_root                217
+                               /* 218 __NR_mincore */
+                               /* 219 __NR_madvise */
+#define __NR_getdents64                220
+#define __NR_fcntl64           221
+                               /* 222 reserved for TUX */
+                               /* 223 reserved for TUX */
+#define __NR_gettid            224
+#define __NR_readahead         225
+#define __NR_setxattr          226
+#define __NR_lsetxattr         227
+#define __NR_fsetxattr         228
+#define __NR_getxattr          229
+#define __NR_lgetxattr         230
+#define __NR_fgetxattr         231
+#define __NR_listxattr         232
+#define __NR_llistxattr                233
+#define __NR_flistxattr                234
+#define __NR_removexattr       235
+#define __NR_lremovexattr      236
+#define __NR_fremovexattr      237
+#define __NR_tkill             238
+#define __NR_sendfile64                239
+#define __NR_futex             240
+#define __NR_sched_setaffinity 241
+#define __NR_sched_getaffinity 242
+                               /* 243 __NR_set_thread_area */
+                               /* 244 __NR_get_thread_area */
+#define __NR_io_setup          245
+#define __NR_io_destroy                246
+#define __NR_io_getevents      247
+#define __NR_io_submit         248
+#define __NR_io_cancel         249
+                               /* 250 __NR_alloc_hugepages */
+                               /* 251 __NR_free_hugepages */
+#define __NR_exit_group                252
+#define __NR_lookup_dcookie     253
+#define __NR_bfin_spinlock      254
+
+#define __NR_epoll_create      255
+#define __NR_epoll_ctl         256
+#define __NR_epoll_wait                257
+                               /* 258 __NR_remap_file_pages */
+#define __NR_set_tid_address   259
+#define __NR_timer_create      260
+#define __NR_timer_settime     261
+#define __NR_timer_gettime     262
+#define __NR_timer_getoverrun  263
+#define __NR_timer_delete      264
+#define __NR_clock_settime     265
+#define __NR_clock_gettime     266
+#define __NR_clock_getres      267
+#define __NR_clock_nanosleep   268
+#define __NR_statfs64          269
+#define __NR_fstatfs64         270
+#define __NR_tgkill            271
+#define __NR_utimes            272
+#define __NR_fadvise64_64      273
+                               /* 274 __NR_vserver */
+                               /* 275 __NR_mbind */
+                               /* 276 __NR_get_mempolicy */
+                               /* 277 __NR_set_mempolicy */
+#define __NR_mq_open           278
+#define __NR_mq_unlink         279
+#define __NR_mq_timedsend      280
+#define __NR_mq_timedreceive   281
+#define __NR_mq_notify         282
+#define __NR_mq_getsetattr     283
+#define __NR_kexec_load                284
+#define __NR_waitid            285
+#define __NR_add_key           286
+#define __NR_request_key       287
+#define __NR_keyctl            288
+#define __NR_ioprio_set                289
+#define __NR_ioprio_get                290
+#define __NR_inotify_init      291
+#define __NR_inotify_add_watch 292
+#define __NR_inotify_rm_watch  293
+                               /* 294 __NR_migrate_pages */
+#define __NR_openat            295
+#define __NR_mkdirat           296
+#define __NR_mknodat           297
+#define __NR_fchownat          298
+#define __NR_futimesat         299
+#define __NR_fstatat64         300
+#define __NR_unlinkat          301
+#define __NR_renameat          302
+#define __NR_linkat            303
+#define __NR_symlinkat         304
+#define __NR_readlinkat                305
+#define __NR_fchmodat          306
+#define __NR_faccessat         307
+#define __NR_pselect6          308
+#define __NR_ppoll             309
+#define __NR_unshare           310
+
+/* Blackfin private syscalls */
+#define __NR_sram_alloc                311
+#define __NR_sram_free         312
+#define __NR_dma_memcpy                313
+
+/* socket syscalls */
+#define __NR_accept            314
+#define __NR_bind              315
+#define __NR_connect           316
+#define __NR_getpeername       317
+#define __NR_getsockname       318
+#define __NR_getsockopt                319
+#define __NR_listen            320
+#define __NR_recv              321
+#define __NR_recvfrom          322
+#define __NR_recvmsg           323
+#define __NR_send              324
+#define __NR_sendmsg           325
+#define __NR_sendto            326
+#define __NR_setsockopt                327
+#define __NR_shutdown          328
+#define __NR_socket            329
+#define __NR_socketpair                330
+
+/* sysv ipc syscalls */
+#define __NR_semctl            331
+#define __NR_semget            332
+#define __NR_semop             333
+#define __NR_msgctl            334
+#define __NR_msgget            335
+#define __NR_msgrcv            336
+#define __NR_msgsnd            337
+#define __NR_shmat             338
+#define __NR_shmctl            339
+#define __NR_shmdt             340
+#define __NR_shmget            341
+
+#define __NR_splice            342
+#define __NR_sync_file_range   343
+#define __NR_tee               344
+#define __NR_vmsplice          345
+
+#define __NR_epoll_pwait       346
+#define __NR_utimensat         347
+#define __NR_signalfd          348
+#define __NR_timerfd_create    349
+#define __NR_eventfd           350
+#define __NR_pread64           351
+#define __NR_pwrite64          352
+#define __NR_fadvise64         353
+#define __NR_set_robust_list   354
+#define __NR_get_robust_list   355
+#define __NR_fallocate         356
+#define __NR_semtimedop                357
+#define __NR_timerfd_settime   358
+#define __NR_timerfd_gettime   359
+#define __NR_signalfd4         360
+#define __NR_eventfd2          361
+#define __NR_epoll_create1     362
+#define __NR_dup3              363
+#define __NR_pipe2             364
+#define __NR_inotify_init1     365
+#define __NR_preadv            366
+#define __NR_pwritev           367
+#define __NR_rt_tgsigqueueinfo 368
+#define __NR_perf_event_open   369
+#define __NR_recvmmsg          370
+#define __NR_fanotify_init     371
+#define __NR_fanotify_mark     372
+#define __NR_prlimit64         373
+#define __NR_cacheflush                374
+#define __NR_name_to_handle_at 375
+#define __NR_open_by_handle_at 376
+#define __NR_clock_adjtime     377
+#define __NR_syncfs            378
+#define __NR_setns             379
+#define __NR_sendmmsg          380
+#define __NR_process_vm_readv  381
+#define __NR_process_vm_writev 382
+
+#define __NR_syscall           383
+#define NR_syscalls            __NR_syscall
+
+/* Old optional stuff no one actually uses */
+#define __IGNORE_sysfs
+#define __IGNORE_uselib
+
+/* Implement the newer interfaces */
+#define __IGNORE_mmap
+#define __IGNORE_poll
+#define __IGNORE_select
+#define __IGNORE_utime
+
+/* Not relevant on no-mmu */
+#define __IGNORE_swapon
+#define __IGNORE_swapoff
+#define __IGNORE_msync
+#define __IGNORE_mlock
+#define __IGNORE_munlock
+#define __IGNORE_mlockall
+#define __IGNORE_munlockall
+#define __IGNORE_mincore
+#define __IGNORE_madvise
+#define __IGNORE_remap_file_pages
+#define __IGNORE_mbind
+#define __IGNORE_get_mempolicy
+#define __IGNORE_set_mempolicy
+#define __IGNORE_migrate_pages
+#define __IGNORE_move_pages
+#define __IGNORE_getcpu
+
+
+#endif /* _UAPI__ASM_BFIN_UNISTD_H */
index 7a192e1290b1a335dd52ff48c001dcc80b3ac63c..1f0fc7a66f5ff74019f4adf27b9d2fe341c4bcef 100644 (file)
@@ -1,4 +1 @@
-header-y += user.h
-header-y += svinto.h
-header-y += sv_addr_ag.h
-header-y += sv_addr.agh
+# CRISv10 arch
index 35f2fc4f993e793b1fd29c56300614dd9a263960..2fd65c7e15c9044937db1c699e38273e5fb21bc1 100644 (file)
@@ -1,2 +1 @@
-header-y += user.h
-header-y += cryptocop.h
+# CRISv32 arch
index e1cd83dfabb5f1f82a43b9d09a6028c6a3662770..716e434e926947be35c7987f1adfed40761c569a 100644 (file)
  * The device /dev/cryptocop is accessible using this driver using
  * CRYPTOCOP_MAJOR (254) and minor number 0.
  */
-
 #ifndef CRYPTOCOP_H
 #define CRYPTOCOP_H
 
-#include <linux/uio.h>
-
-
-#define CRYPTOCOP_SESSION_ID_NONE (0)
-
-typedef unsigned long long int cryptocop_session_id;
-
-/* cryptocop ioctls */
-#define ETRAXCRYPTOCOP_IOCTYPE         (250)
-
-#define CRYPTOCOP_IO_CREATE_SESSION    _IOWR(ETRAXCRYPTOCOP_IOCTYPE, 1, struct strcop_session_op)
-#define CRYPTOCOP_IO_CLOSE_SESSION     _IOW(ETRAXCRYPTOCOP_IOCTYPE, 2, struct strcop_session_op)
-#define CRYPTOCOP_IO_PROCESS_OP        _IOWR(ETRAXCRYPTOCOP_IOCTYPE, 3, struct strcop_crypto_op)
-#define CRYPTOCOP_IO_MAXNR             (3)
-
-typedef enum {
-       cryptocop_cipher_des = 0,
-       cryptocop_cipher_3des = 1,
-       cryptocop_cipher_aes = 2,
-       cryptocop_cipher_m2m = 3, /* mem2mem is essentially a NULL cipher with blocklength=1 */
-       cryptocop_cipher_none
-} cryptocop_cipher_type;
-
-typedef enum {
-       cryptocop_digest_sha1 = 0,
-       cryptocop_digest_md5 = 1,
-       cryptocop_digest_none
-} cryptocop_digest_type;
-
-typedef enum {
-       cryptocop_csum_le = 0,
-       cryptocop_csum_be = 1,
-       cryptocop_csum_none
-} cryptocop_csum_type;
-
-typedef enum {
-       cryptocop_cipher_mode_ecb = 0,
-       cryptocop_cipher_mode_cbc,
-       cryptocop_cipher_mode_none
-} cryptocop_cipher_mode;
-
-typedef enum {
-       cryptocop_3des_eee = 0,
-       cryptocop_3des_eed = 1,
-       cryptocop_3des_ede = 2,
-       cryptocop_3des_edd = 3,
-       cryptocop_3des_dee = 4,
-       cryptocop_3des_ded = 5,
-       cryptocop_3des_dde = 6,
-       cryptocop_3des_ddd = 7
-} cryptocop_3des_mode;
-
-/* Usermode accessible (ioctl) operations. */
-struct strcop_session_op{
-       cryptocop_session_id    ses_id;
-
-       cryptocop_cipher_type   cipher; /* AES, DES, 3DES, m2m, none */
-
-       cryptocop_cipher_mode   cmode; /* ECB, CBC, none */
-       cryptocop_3des_mode     des3_mode;
-
-       cryptocop_digest_type   digest; /* MD5, SHA1, none */
-
-       cryptocop_csum_type     csum;   /* BE, LE, none */
-
-       unsigned char           *key;
-       size_t                  keylen;
-};
-
-#define CRYPTOCOP_CSUM_LENGTH         (2)
-#define CRYPTOCOP_MAX_DIGEST_LENGTH   (20)  /* SHA-1 20, MD5 16 */
-#define CRYPTOCOP_MAX_IV_LENGTH       (16)  /* (3)DES==8, AES == 16 */
-#define CRYPTOCOP_MAX_KEY_LENGTH      (32)
-
-struct strcop_crypto_op{
-       cryptocop_session_id ses_id;
-
-       /* Indata. */
-       unsigned char            *indata;
-       size_t                   inlen; /* Total indata length. */
-
-       /* Cipher configuration. */
-       unsigned char            do_cipher:1;
-       unsigned char            decrypt:1; /* 1 == decrypt, 0 == encrypt */
-       unsigned char            cipher_explicit:1;
-       size_t                   cipher_start;
-       size_t                   cipher_len;
-       /* cipher_iv is used if do_cipher and cipher_explicit and the cipher
-          mode is CBC.  The length is controlled by the type of cipher,
-          e.g. DES/3DES 8 octets and AES 16 octets. */
-       unsigned char            cipher_iv[CRYPTOCOP_MAX_IV_LENGTH];
-       /* Outdata. */
-       unsigned char            *cipher_outdata;
-       size_t                   cipher_outlen;
-
-       /* digest configuration. */
-       unsigned char            do_digest:1;
-       size_t                   digest_start;
-       size_t                   digest_len;
-       /* Outdata.  The actual length is determined by the type of the digest. */
-       unsigned char            digest[CRYPTOCOP_MAX_DIGEST_LENGTH];
-
-       /* Checksum configuration. */
-       unsigned char            do_csum:1;
-       size_t                   csum_start;
-       size_t                   csum_len;
-       /* Outdata. */
-       unsigned char            csum[CRYPTOCOP_CSUM_LENGTH];
-};
+#include <uapi/arch-v32/arch/cryptocop.h>
 
 
-
-#ifdef __KERNEL__
-
 /********** The API to use from inside the kernel. ************/
 
 #include <arch/hwregs/dma.h>
@@ -267,6 +155,4 @@ int cryptocop_job_queue_insert_crypto(struct cryptocop_operation *operation);
 
 int cryptocop_job_queue_insert_user_job(struct cryptocop_operation *operation);
 
-#endif /* __KERNEL__ */
-
 #endif /* CRYPTOCOP_H */
index f171a6600fbcac6424376d65aeb35424d57e2b6e..f13275522f4d688ed5dff599045395be62b529d1 100644 (file)
@@ -118,7 +118,7 @@ static  inline int arch_write_trylock(arch_rwlock_t *rw)
                ret = 1;
        }
        arch_spin_unlock(&rw->slock);
-       return 1;
+       return ret;
 }
 
 #define _raw_read_lock_flags(lock, flags) _raw_read_lock(lock)
index 6d43a951b5ec0b5b217ca8a51405cfa274be5ffb..81e59208945ec854663bc6bcf9d50788b3ee6596 100644 (file)
@@ -1,12 +1,7 @@
-include include/asm-generic/Kbuild.asm
 
 header-y += arch-v10/
 header-y += arch-v32/
 
-header-y += ethernet.h
-header-y += etraxgpio.h
-header-y += rs485.h
-header-y += sync_serial.h
 
 generic-y += clkdev.h
 generic-y += exec.h
index 6618893bfe8ed2ce1e073025b996fe43dfd71f84..2de84d7061c7015aa8adea1374671e5dcae54c33 100644 (file)
@@ -1,9 +1,8 @@
 #ifndef _CRIS_PTRACE_H
 #define _CRIS_PTRACE_H
 
-#include <arch/ptrace.h>
+#include <uapi/asm/ptrace.h>
 
-#ifdef __KERNEL__
 
 /* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
 #define PTRACE_GETREGS            12
@@ -11,6 +10,4 @@
 
 #define profile_pc(regs) instruction_pointer(regs)
 
-#endif /* __KERNEL__ */
-
 #endif /* _CRIS_PTRACE_H */
index ea6af9aad76c25c92d255c842ea95f0aeba27fbe..b3c5ef05011fc7e49fcc1693940bdae671510a6d 100644 (file)
@@ -1,12 +1,8 @@
 #ifndef _ASM_CRIS_SIGNAL_H
 #define _ASM_CRIS_SIGNAL_H
 
-#include <linux/types.h>
+#include <uapi/asm/signal.h>
 
-/* Avoid too many header ordering problems.  */
-struct siginfo;
-
-#ifdef __KERNEL__
 /* Most things should be clean enough to redefine this at will, if care
    is taken to make libc match.  */
 
@@ -20,95 +16,6 @@ typedef struct {
        unsigned long sig[_NSIG_WORDS];
 } sigset_t;
 
-#else
-/* Here we must cater to libcs that poke about in kernel headers.  */
-
-#define NSIG           32
-typedef unsigned long sigset_t;
-
-#endif /* __KERNEL__ */
-
-#define SIGHUP          1
-#define SIGINT          2
-#define SIGQUIT                 3
-#define SIGILL          4
-#define SIGTRAP                 5
-#define SIGABRT                 6
-#define SIGIOT          6
-#define SIGBUS          7
-#define SIGFPE          8
-#define SIGKILL                 9
-#define SIGUSR1                10
-#define SIGSEGV                11
-#define SIGUSR2                12
-#define SIGPIPE                13
-#define SIGALRM                14
-#define SIGTERM                15
-#define SIGSTKFLT      16
-#define SIGCHLD                17
-#define SIGCONT                18
-#define SIGSTOP                19
-#define SIGTSTP                20
-#define SIGTTIN                21
-#define SIGTTOU                22
-#define SIGURG         23
-#define SIGXCPU                24
-#define SIGXFSZ                25
-#define SIGVTALRM      26
-#define SIGPROF                27
-#define SIGWINCH       28
-#define SIGIO          29
-#define SIGPOLL                SIGIO
-/*
-#define SIGLOST                29
-*/
-#define SIGPWR         30
-#define SIGSYS          31
-#define        SIGUNUSED       31
-
-/* These should not be considered constants from userland.  */
-#define SIGRTMIN        32
-#define SIGRTMAX        _NSIG
-
-/*
- * SA_FLAGS values:
- *
- * SA_ONSTACK indicates that a registered stack_t will be used.
- * SA_RESTART flag to get restarting signals (which were the default long ago)
- * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
- * SA_RESETHAND clears the handler when the signal is delivered.
- * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
- * SA_NODEFER prevents the current signal from being masked in the handler.
- *
- * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
- * Unix names RESETHAND and NODEFER respectively.
- */
-
-#define SA_NOCLDSTOP   0x00000001u
-#define SA_NOCLDWAIT   0x00000002u
-#define SA_SIGINFO     0x00000004u
-#define SA_ONSTACK     0x08000000u
-#define SA_RESTART     0x10000000u
-#define SA_NODEFER     0x40000000u
-#define SA_RESETHAND   0x80000000u
-
-#define SA_NOMASK      SA_NODEFER
-#define SA_ONESHOT     SA_RESETHAND
-
-#define SA_RESTORER    0x04000000
-
-/* 
- * sigaltstack controls
- */
-#define SS_ONSTACK     1
-#define SS_DISABLE     2
-
-#define MINSIGSTKSZ    2048
-#define SIGSTKSZ       8192
-
-#include <asm-generic/signal-defs.h>
-
-#ifdef __KERNEL__
 struct old_sigaction {
        __sighandler_t sa_handler;
        old_sigset_t sa_mask;
@@ -126,31 +33,6 @@ struct sigaction {
 struct k_sigaction {
        struct sigaction sa;
 };
-#else
-/* Here we must cater to libcs that poke about in kernel headers.  */
-
-struct sigaction {
-       union {
-         __sighandler_t _sa_handler;
-         void (*_sa_sigaction)(int, struct siginfo *, void *);
-       } _u;
-       sigset_t sa_mask;
-       unsigned long sa_flags;
-       void (*sa_restorer)(void);
-};
-
-#define sa_handler     _u._sa_handler
-#define sa_sigaction   _u._sa_sigaction
-
-#endif /* __KERNEL__ */
-
-typedef struct sigaltstack {
-       void *ss_sp;
-       int ss_flags;
-       size_t ss_size;
-} stack_t;
-
-#ifdef __KERNEL__
 #include <asm/sigcontext.h>
 
 /* here we could define asm-optimized sigaddset, sigdelset etc. operations. 
@@ -158,6 +40,4 @@ typedef struct sigaltstack {
  */
 #define ptrace_signal_deliver(regs, cookie) do { } while (0)
 
-#endif /* __KERNEL__ */
-
 #endif
index 80668e88419c3a43797c10632b60c24e6cb456c6..991b6ace1ba9b25886ecb22aee4217ca6cd9230c 100644 (file)
@@ -1,8 +1,7 @@
 #ifndef _CRIS_SWAB_H
 #define _CRIS_SWAB_H
 
-#ifdef __KERNEL__
 #include <arch/swab.h>
-#endif /* __KERNEL__ */
+#include <uapi/asm/swab.h>
 
 #endif /* _CRIS_SWAB_H */
index 1265109f4ce3b485ac68623a889cd5a5621c079b..1991cd9e4083dae7b2e2f8b2fcc0b8e67ad49f29 100644 (file)
@@ -1,47 +1,8 @@
 #ifndef _CRIS_TERMIOS_H
 #define _CRIS_TERMIOS_H
 
-#include <asm/termbits.h>
-#include <asm/ioctls.h>
-#include <asm/rs485.h>
-#include <linux/serial.h>
+#include <uapi/asm/termios.h>
 
-struct winsize {
-       unsigned short ws_row;
-       unsigned short ws_col;
-       unsigned short ws_xpixel;
-       unsigned short ws_ypixel;
-};
-
-#define NCC 8
-struct termio {
-       unsigned short c_iflag;         /* input mode flags */
-       unsigned short c_oflag;         /* output mode flags */
-       unsigned short c_cflag;         /* control mode flags */
-       unsigned short c_lflag;         /* local mode flags */
-       unsigned char c_line;           /* line discipline */
-       unsigned char c_cc[NCC];        /* control characters */
-};
-
-/* modem lines */
-#define TIOCM_LE       0x001
-#define TIOCM_DTR      0x002
-#define TIOCM_RTS      0x004
-#define TIOCM_ST       0x008
-#define TIOCM_SR       0x010
-#define TIOCM_CTS      0x020
-#define TIOCM_CAR      0x040
-#define TIOCM_RNG      0x080
-#define TIOCM_DSR      0x100
-#define TIOCM_CD       TIOCM_CAR
-#define TIOCM_RI       TIOCM_RNG
-#define TIOCM_OUT1     0x2000
-#define TIOCM_OUT2     0x4000
-#define TIOCM_LOOP     0x8000
-
-/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
-
-#ifdef __KERNEL__
 
 /*     intr=^C         quit=^\         erase=del       kill=^U
        eof=^D          vtime=\0        vmin=\1         sxtc=\0
@@ -87,6 +48,4 @@ struct termio {
 #define user_termios_to_kernel_termios_1(k, u) copy_from_user(k, u, sizeof(struct termios))
 #define kernel_termios_to_user_termios_1(u, k) copy_to_user(u, k, sizeof(struct termios))
 
-#endif /* __KERNEL__ */
-
 #endif /* _CRIS_TERMIOS_H */
index adaf82780bb4df9d97ec990087c47522faefccaa..a3cac7757c7ff6819db128ddea6ff519046e9b85 100644 (file)
@@ -1,15 +1,12 @@
 #ifndef _ETRAX_TYPES_H
 #define _ETRAX_TYPES_H
 
-#include <asm-generic/int-ll64.h>
+#include <uapi/asm/types.h>
 
 /*
  * These aren't exported outside the kernel to avoid name space clashes
  */
-#ifdef __KERNEL__
 
 #define BITS_PER_LONG 32
 
-#endif /* __KERNEL__ */
-
 #endif
index 51873a446f87e870f44db25c3dcfd2d1522eb0d2..4fb59e1070246fb1ea228ad9d72f36b85acb6d24 100644 (file)
@@ -1,347 +1,8 @@
 #ifndef _ASM_CRIS_UNISTD_H_
 #define _ASM_CRIS_UNISTD_H_
 
-/*
- * This file contains the system call numbers, and stub macros for libc.
- */
-
-#define __NR_restart_syscall      0
-#define __NR_exit                1
-#define __NR_fork                2
-#define __NR_read                3
-#define __NR_write               4
-#define __NR_open                5
-#define __NR_close               6
-#define __NR_waitpid             7
-#define __NR_creat               8
-#define __NR_link                9
-#define __NR_unlink             10
-#define __NR_execve             11
-#define __NR_chdir              12
-#define __NR_time               13
-#define __NR_mknod              14
-#define __NR_chmod              15
-#define __NR_lchown             16
-#define __NR_break              17
-#define __NR_oldstat            18
-#define __NR_lseek              19
-#define __NR_getpid             20
-#define __NR_mount              21
-#define __NR_umount             22
-#define __NR_setuid             23
-#define __NR_getuid             24
-#define __NR_stime              25
-#define __NR_ptrace             26
-#define __NR_alarm              27
-#define __NR_oldfstat           28
-#define __NR_pause              29
-#define __NR_utime              30
-#define __NR_stty               31
-#define __NR_gtty               32
-#define __NR_access             33
-#define __NR_nice               34
-#define __NR_ftime              35
-#define __NR_sync               36
-#define __NR_kill               37
-#define __NR_rename             38
-#define __NR_mkdir              39
-#define __NR_rmdir              40
-#define __NR_dup                41
-#define __NR_pipe               42
-#define __NR_times              43
-#define __NR_prof               44
-#define __NR_brk                45
-#define __NR_setgid             46
-#define __NR_getgid             47
-#define __NR_signal             48
-#define __NR_geteuid            49
-#define __NR_getegid            50
-#define __NR_acct               51
-#define __NR_umount2            52
-#define __NR_lock               53
-#define __NR_ioctl              54
-#define __NR_fcntl              55
-#define __NR_mpx                56
-#define __NR_setpgid            57
-#define __NR_ulimit             58
-#define __NR_oldolduname        59
-#define __NR_umask              60
-#define __NR_chroot             61
-#define __NR_ustat              62
-#define __NR_dup2               63
-#define __NR_getppid            64
-#define __NR_getpgrp            65
-#define __NR_setsid             66
-#define __NR_sigaction          67
-#define __NR_sgetmask           68
-#define __NR_ssetmask           69
-#define __NR_setreuid           70
-#define __NR_setregid           71
-#define __NR_sigsuspend                 72
-#define __NR_sigpending                 73
-#define __NR_sethostname        74
-#define __NR_setrlimit          75
-#define __NR_getrlimit          76
-#define __NR_getrusage          77
-#define __NR_gettimeofday       78
-#define __NR_settimeofday       79
-#define __NR_getgroups          80
-#define __NR_setgroups          81
-#define __NR_select             82
-#define __NR_symlink            83
-#define __NR_oldlstat           84
-#define __NR_readlink           85
-#define __NR_uselib             86
-#define __NR_swapon             87
-#define __NR_reboot             88
-#define __NR_readdir            89
-#define __NR_mmap               90
-#define __NR_munmap             91
-#define __NR_truncate           92
-#define __NR_ftruncate          93
-#define __NR_fchmod             94
-#define __NR_fchown             95
-#define __NR_getpriority        96
-#define __NR_setpriority        97
-#define __NR_profil             98
-#define __NR_statfs             99
-#define __NR_fstatfs           100
-#define __NR_ioperm            101
-#define __NR_socketcall                102
-#define __NR_syslog            103
-#define __NR_setitimer         104
-#define __NR_getitimer         105
-#define __NR_stat              106
-#define __NR_lstat             107
-#define __NR_fstat             108
-#define __NR_olduname          109
-#define __NR_iopl              110
-#define __NR_vhangup           111
-#define __NR_idle              112
-#define __NR_vm86              113
-#define __NR_wait4             114
-#define __NR_swapoff           115
-#define __NR_sysinfo           116
-#define __NR_ipc               117
-#define __NR_fsync             118
-#define __NR_sigreturn         119
-#define __NR_clone             120
-#define __NR_setdomainname     121
-#define __NR_uname             122
-#define __NR_modify_ldt                123
-#define __NR_adjtimex          124
-#define __NR_mprotect          125
-#define __NR_sigprocmask       126
-#define __NR_create_module     127
-#define __NR_init_module       128
-#define __NR_delete_module     129
-#define __NR_get_kernel_syms   130
-#define __NR_quotactl          131
-#define __NR_getpgid           132
-#define __NR_fchdir            133
-#define __NR_bdflush           134
-#define __NR_sysfs             135
-#define __NR_personality       136
-#define __NR_afs_syscall       137 /* Syscall for Andrew File System */
-#define __NR_setfsuid          138
-#define __NR_setfsgid          139
-#define __NR__llseek           140
-#define __NR_getdents          141
-#define __NR__newselect                142
-#define __NR_flock             143
-#define __NR_msync             144
-#define __NR_readv             145
-#define __NR_writev            146
-#define __NR_getsid            147
-#define __NR_fdatasync         148
-#define __NR__sysctl           149
-#define __NR_mlock             150
-#define __NR_munlock           151
-#define __NR_mlockall          152
-#define __NR_munlockall                153
-#define __NR_sched_setparam            154
-#define __NR_sched_getparam            155
-#define __NR_sched_setscheduler                156
-#define __NR_sched_getscheduler                157
-#define __NR_sched_yield               158
-#define __NR_sched_get_priority_max    159
-#define __NR_sched_get_priority_min    160
-#define __NR_sched_rr_get_interval     161
-#define __NR_nanosleep         162
-#define __NR_mremap            163
-#define __NR_setresuid         164
-#define __NR_getresuid         165
-
-#define __NR_query_module      167
-#define __NR_poll              168
-#define __NR_nfsservctl                169
-#define __NR_setresgid         170
-#define __NR_getresgid         171
-#define __NR_prctl              172
-#define __NR_rt_sigreturn      173
-#define __NR_rt_sigaction      174
-#define __NR_rt_sigprocmask    175
-#define __NR_rt_sigpending     176
-#define __NR_rt_sigtimedwait   177
-#define __NR_rt_sigqueueinfo   178
-#define __NR_rt_sigsuspend     179
-#define __NR_pread64           180
-#define __NR_pwrite64          181
-#define __NR_chown             182
-#define __NR_getcwd            183
-#define __NR_capget            184
-#define __NR_capset            185
-#define __NR_sigaltstack       186
-#define __NR_sendfile          187
-#define __NR_getpmsg           188     /* some people actually want streams */
-#define __NR_putpmsg           189     /* some people actually want streams */
-#define __NR_vfork             190
-#define __NR_ugetrlimit                191     /* SuS compliant getrlimit */
-#define __NR_mmap2             192
-#define __NR_truncate64                193
-#define __NR_ftruncate64       194
-#define __NR_stat64            195
-#define __NR_lstat64           196
-#define __NR_fstat64           197
-#define __NR_lchown32          198
-#define __NR_getuid32          199
-#define __NR_getgid32          200
-#define __NR_geteuid32         201
-#define __NR_getegid32         202
-#define __NR_setreuid32                203
-#define __NR_setregid32                204
-#define __NR_getgroups32       205
-#define __NR_setgroups32       206
-#define __NR_fchown32          207
-#define __NR_setresuid32       208
-#define __NR_getresuid32       209
-#define __NR_setresgid32       210
-#define __NR_getresgid32       211
-#define __NR_chown32           212
-#define __NR_setuid32          213
-#define __NR_setgid32          214
-#define __NR_setfsuid32                215
-#define __NR_setfsgid32                216
-#define __NR_pivot_root                217
-#define __NR_mincore           218
-#define __NR_madvise           219
-#define __NR_getdents64                220
-#define __NR_fcntl64           221
-/* 223 is unused */
-#define __NR_gettid             224
-#define __NR_readahead          225
-#define __NR_setxattr          226
-#define __NR_lsetxattr         227
-#define __NR_fsetxattr         228
-#define __NR_getxattr          229
-#define __NR_lgetxattr         230
-#define __NR_fgetxattr         231
-#define __NR_listxattr         232
-#define __NR_llistxattr                233
-#define __NR_flistxattr                234
-#define __NR_removexattr       235
-#define __NR_lremovexattr      236
-#define __NR_fremovexattr      237
-#define __NR_tkill             238
-#define __NR_sendfile64                239
-#define __NR_futex             240
-#define __NR_sched_setaffinity 241
-#define __NR_sched_getaffinity 242
-#define __NR_set_thread_area   243
-#define __NR_get_thread_area   244
-#define __NR_io_setup          245
-#define __NR_io_destroy                246
-#define __NR_io_getevents      247
-#define __NR_io_submit         248
-#define __NR_io_cancel         249
-#define __NR_fadvise64         250
-/* 251 is available for reuse (was briefly sys_set_zone_reclaim) */
-#define __NR_exit_group                252
-#define __NR_lookup_dcookie    253
-#define __NR_epoll_create      254
-#define __NR_epoll_ctl         255
-#define __NR_epoll_wait                256
-#define __NR_remap_file_pages  257
-#define __NR_set_tid_address   258
-#define __NR_timer_create      259
-#define __NR_timer_settime     (__NR_timer_create+1)
-#define __NR_timer_gettime     (__NR_timer_create+2)
-#define __NR_timer_getoverrun  (__NR_timer_create+3)
-#define __NR_timer_delete      (__NR_timer_create+4)
-#define __NR_clock_settime     (__NR_timer_create+5)
-#define __NR_clock_gettime     (__NR_timer_create+6)
-#define __NR_clock_getres      (__NR_timer_create+7)
-#define __NR_clock_nanosleep   (__NR_timer_create+8)
-#define __NR_statfs64          268
-#define __NR_fstatfs64         269
-#define __NR_tgkill            270
-#define __NR_utimes            271
-#define __NR_fadvise64_64      272
-#define __NR_vserver           273
-#define __NR_mbind             274
-#define __NR_get_mempolicy     275
-#define __NR_set_mempolicy     276
-#define __NR_mq_open           277
-#define __NR_mq_unlink         (__NR_mq_open+1)
-#define __NR_mq_timedsend      (__NR_mq_open+2)
-#define __NR_mq_timedreceive   (__NR_mq_open+3)
-#define __NR_mq_notify         (__NR_mq_open+4)
-#define __NR_mq_getsetattr     (__NR_mq_open+5)
-#define __NR_kexec_load                283
-#define __NR_waitid            284
-/* #define __NR_sys_setaltroot 285 */
-#define __NR_add_key           286
-#define __NR_request_key       287
-#define __NR_keyctl            288
-#define __NR_ioprio_set                289
-#define __NR_ioprio_get                290
-#define __NR_inotify_init      291
-#define __NR_inotify_add_watch 292
-#define __NR_inotify_rm_watch  293
-#define __NR_migrate_pages     294
-#define __NR_openat            295
-#define __NR_mkdirat           296
-#define __NR_mknodat           297
-#define __NR_fchownat          298
-#define __NR_futimesat         299
-#define __NR_fstatat64         300
-#define __NR_unlinkat          301
-#define __NR_renameat          302
-#define __NR_linkat            303
-#define __NR_symlinkat         304
-#define __NR_readlinkat                305
-#define __NR_fchmodat          306
-#define __NR_faccessat         307
-#define __NR_pselect6          308
-#define __NR_ppoll             309
-#define __NR_unshare           310
-#define __NR_set_robust_list   311
-#define __NR_get_robust_list   312
-#define __NR_splice            313
-#define __NR_sync_file_range   314
-#define __NR_tee               315
-#define __NR_vmsplice          316
-#define __NR_move_pages                317
-#define __NR_getcpu            318
-#define __NR_epoll_pwait       319
-#define __NR_utimensat         320
-#define __NR_signalfd          321
-#define __NR_timerfd_create    322
-#define __NR_eventfd           323
-#define __NR_fallocate         324
-#define __NR_timerfd_settime   325
-#define __NR_timerfd_gettime   326
-#define __NR_signalfd4         327
-#define __NR_eventfd2          328
-#define __NR_epoll_create1     329
-#define __NR_dup3              330
-#define __NR_pipe2             331
-#define __NR_inotify_init1     332
-#define __NR_preadv            333
-#define __NR_pwritev           334
-#define __NR_setns             335
+#include <uapi/asm/unistd.h>
 
-#ifdef __KERNEL__
 
 #define NR_syscalls 336
 
  */
 #define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
 
-#endif /* __KERNEL__ */
 #endif /* _ASM_CRIS_UNISTD_H_ */
index aafaa5aa54d46bb9a93a8137a22344408298223f..9048c87a782b51a8e164fecd1791d00b211e2a1c 100644 (file)
@@ -1 +1,5 @@
 # UAPI Header export list
+header-y += sv_addr.agh
+header-y += sv_addr_ag.h
+header-y += svinto.h
+header-y += user.h
index aafaa5aa54d46bb9a93a8137a22344408298223f..59efffd16b6112979cc92d75ce4b480bafa3c570 100644 (file)
@@ -1 +1,3 @@
 # UAPI Header export list
+header-y += cryptocop.h
+header-y += user.h
diff --git a/arch/cris/include/uapi/arch-v32/arch/cryptocop.h b/arch/cris/include/uapi/arch-v32/arch/cryptocop.h
new file mode 100644 (file)
index 0000000..694fd13
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * The device /dev/cryptocop is accessible using this driver using
+ * CRYPTOCOP_MAJOR (254) and minor number 0.
+ */
+
+#ifndef _UAPICRYPTOCOP_H
+#define _UAPICRYPTOCOP_H
+
+#include <linux/uio.h>
+
+
+#define CRYPTOCOP_SESSION_ID_NONE (0)
+
+typedef unsigned long long int cryptocop_session_id;
+
+/* cryptocop ioctls */
+#define ETRAXCRYPTOCOP_IOCTYPE         (250)
+
+#define CRYPTOCOP_IO_CREATE_SESSION    _IOWR(ETRAXCRYPTOCOP_IOCTYPE, 1, struct strcop_session_op)
+#define CRYPTOCOP_IO_CLOSE_SESSION     _IOW(ETRAXCRYPTOCOP_IOCTYPE, 2, struct strcop_session_op)
+#define CRYPTOCOP_IO_PROCESS_OP        _IOWR(ETRAXCRYPTOCOP_IOCTYPE, 3, struct strcop_crypto_op)
+#define CRYPTOCOP_IO_MAXNR             (3)
+
+typedef enum {
+       cryptocop_cipher_des = 0,
+       cryptocop_cipher_3des = 1,
+       cryptocop_cipher_aes = 2,
+       cryptocop_cipher_m2m = 3, /* mem2mem is essentially a NULL cipher with blocklength=1 */
+       cryptocop_cipher_none
+} cryptocop_cipher_type;
+
+typedef enum {
+       cryptocop_digest_sha1 = 0,
+       cryptocop_digest_md5 = 1,
+       cryptocop_digest_none
+} cryptocop_digest_type;
+
+typedef enum {
+       cryptocop_csum_le = 0,
+       cryptocop_csum_be = 1,
+       cryptocop_csum_none
+} cryptocop_csum_type;
+
+typedef enum {
+       cryptocop_cipher_mode_ecb = 0,
+       cryptocop_cipher_mode_cbc,
+       cryptocop_cipher_mode_none
+} cryptocop_cipher_mode;
+
+typedef enum {
+       cryptocop_3des_eee = 0,
+       cryptocop_3des_eed = 1,
+       cryptocop_3des_ede = 2,
+       cryptocop_3des_edd = 3,
+       cryptocop_3des_dee = 4,
+       cryptocop_3des_ded = 5,
+       cryptocop_3des_dde = 6,
+       cryptocop_3des_ddd = 7
+} cryptocop_3des_mode;
+
+/* Usermode accessible (ioctl) operations. */
+struct strcop_session_op{
+       cryptocop_session_id    ses_id;
+
+       cryptocop_cipher_type   cipher; /* AES, DES, 3DES, m2m, none */
+
+       cryptocop_cipher_mode   cmode; /* ECB, CBC, none */
+       cryptocop_3des_mode     des3_mode;
+
+       cryptocop_digest_type   digest; /* MD5, SHA1, none */
+
+       cryptocop_csum_type     csum;   /* BE, LE, none */
+
+       unsigned char           *key;
+       size_t                  keylen;
+};
+
+#define CRYPTOCOP_CSUM_LENGTH         (2)
+#define CRYPTOCOP_MAX_DIGEST_LENGTH   (20)  /* SHA-1 20, MD5 16 */
+#define CRYPTOCOP_MAX_IV_LENGTH       (16)  /* (3)DES==8, AES == 16 */
+#define CRYPTOCOP_MAX_KEY_LENGTH      (32)
+
+struct strcop_crypto_op{
+       cryptocop_session_id ses_id;
+
+       /* Indata. */
+       unsigned char            *indata;
+       size_t                   inlen; /* Total indata length. */
+
+       /* Cipher configuration. */
+       unsigned char            do_cipher:1;
+       unsigned char            decrypt:1; /* 1 == decrypt, 0 == encrypt */
+       unsigned char            cipher_explicit:1;
+       size_t                   cipher_start;
+       size_t                   cipher_len;
+       /* cipher_iv is used if do_cipher and cipher_explicit and the cipher
+          mode is CBC.  The length is controlled by the type of cipher,
+          e.g. DES/3DES 8 octets and AES 16 octets. */
+       unsigned char            cipher_iv[CRYPTOCOP_MAX_IV_LENGTH];
+       /* Outdata. */
+       unsigned char            *cipher_outdata;
+       size_t                   cipher_outlen;
+
+       /* digest configuration. */
+       unsigned char            do_digest:1;
+       size_t                   digest_start;
+       size_t                   digest_len;
+       /* Outdata.  The actual length is determined by the type of the digest. */
+       unsigned char            digest[CRYPTOCOP_MAX_DIGEST_LENGTH];
+
+       /* Checksum configuration. */
+       unsigned char            do_csum:1;
+       size_t                   csum_start;
+       size_t                   csum_len;
+       /* Outdata. */
+       unsigned char            csum[CRYPTOCOP_CSUM_LENGTH];
+};
+
+
+
+
+#endif /* _UAPICRYPTOCOP_H */
index f50236ae9ca38ad5a3bbd70b0c83393d6bd90375..7d47b366ad82b49d2ea19e734b8d7be859f95080 100644 (file)
@@ -3,3 +3,37 @@ include include/uapi/asm-generic/Kbuild.asm
 
 header-y += arch-v10/
 header-y += arch-v32/
+header-y += auxvec.h
+header-y += bitsperlong.h
+header-y += byteorder.h
+header-y += errno.h
+header-y += ethernet.h
+header-y += etraxgpio.h
+header-y += fcntl.h
+header-y += ioctl.h
+header-y += ioctls.h
+header-y += ipcbuf.h
+header-y += mman.h
+header-y += msgbuf.h
+header-y += param.h
+header-y += poll.h
+header-y += posix_types.h
+header-y += ptrace.h
+header-y += resource.h
+header-y += rs485.h
+header-y += sembuf.h
+header-y += setup.h
+header-y += shmbuf.h
+header-y += sigcontext.h
+header-y += siginfo.h
+header-y += signal.h
+header-y += socket.h
+header-y += sockios.h
+header-y += stat.h
+header-y += statfs.h
+header-y += swab.h
+header-y += sync_serial.h
+header-y += termbits.h
+header-y += termios.h
+header-y += types.h
+header-y += unistd.h
diff --git a/arch/cris/include/uapi/asm/ptrace.h b/arch/cris/include/uapi/asm/ptrace.h
new file mode 100644 (file)
index 0000000..c689c9b
--- /dev/null
@@ -0,0 +1 @@
+#include <arch/ptrace.h>
diff --git a/arch/cris/include/uapi/asm/signal.h b/arch/cris/include/uapi/asm/signal.h
new file mode 100644 (file)
index 0000000..2162494
--- /dev/null
@@ -0,0 +1,122 @@
+#ifndef _UAPI_ASM_CRIS_SIGNAL_H
+#define _UAPI_ASM_CRIS_SIGNAL_H
+
+#include <linux/types.h>
+
+/* Avoid too many header ordering problems.  */
+struct siginfo;
+
+#ifndef __KERNEL__
+/* Here we must cater to libcs that poke about in kernel headers.  */
+
+#define NSIG           32
+typedef unsigned long sigset_t;
+
+#endif /* __KERNEL__ */
+
+#define SIGHUP          1
+#define SIGINT          2
+#define SIGQUIT                 3
+#define SIGILL          4
+#define SIGTRAP                 5
+#define SIGABRT                 6
+#define SIGIOT          6
+#define SIGBUS          7
+#define SIGFPE          8
+#define SIGKILL                 9
+#define SIGUSR1                10
+#define SIGSEGV                11
+#define SIGUSR2                12
+#define SIGPIPE                13
+#define SIGALRM                14
+#define SIGTERM                15
+#define SIGSTKFLT      16
+#define SIGCHLD                17
+#define SIGCONT                18
+#define SIGSTOP                19
+#define SIGTSTP                20
+#define SIGTTIN                21
+#define SIGTTOU                22
+#define SIGURG         23
+#define SIGXCPU                24
+#define SIGXFSZ                25
+#define SIGVTALRM      26
+#define SIGPROF                27
+#define SIGWINCH       28
+#define SIGIO          29
+#define SIGPOLL                SIGIO
+/*
+#define SIGLOST                29
+*/
+#define SIGPWR         30
+#define SIGSYS          31
+#define        SIGUNUSED       31
+
+/* These should not be considered constants from userland.  */
+#define SIGRTMIN        32
+#define SIGRTMAX        _NSIG
+
+/*
+ * SA_FLAGS values:
+ *
+ * SA_ONSTACK indicates that a registered stack_t will be used.
+ * SA_RESTART flag to get restarting signals (which were the default long ago)
+ * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
+ * SA_RESETHAND clears the handler when the signal is delivered.
+ * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
+ * SA_NODEFER prevents the current signal from being masked in the handler.
+ *
+ * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
+ * Unix names RESETHAND and NODEFER respectively.
+ */
+
+#define SA_NOCLDSTOP   0x00000001u
+#define SA_NOCLDWAIT   0x00000002u
+#define SA_SIGINFO     0x00000004u
+#define SA_ONSTACK     0x08000000u
+#define SA_RESTART     0x10000000u
+#define SA_NODEFER     0x40000000u
+#define SA_RESETHAND   0x80000000u
+
+#define SA_NOMASK      SA_NODEFER
+#define SA_ONESHOT     SA_RESETHAND
+
+#define SA_RESTORER    0x04000000
+
+/* 
+ * sigaltstack controls
+ */
+#define SS_ONSTACK     1
+#define SS_DISABLE     2
+
+#define MINSIGSTKSZ    2048
+#define SIGSTKSZ       8192
+
+#include <asm-generic/signal-defs.h>
+
+#ifndef __KERNEL__
+/* Here we must cater to libcs that poke about in kernel headers.  */
+
+struct sigaction {
+       union {
+         __sighandler_t _sa_handler;
+         void (*_sa_sigaction)(int, struct siginfo *, void *);
+       } _u;
+       sigset_t sa_mask;
+       unsigned long sa_flags;
+       void (*sa_restorer)(void);
+};
+
+#define sa_handler     _u._sa_handler
+#define sa_sigaction   _u._sa_sigaction
+
+#endif /* __KERNEL__ */
+
+typedef struct sigaltstack {
+       void *ss_sp;
+       int ss_flags;
+       size_t ss_size;
+} stack_t;
+
+
+#endif /* _UAPI_ASM_CRIS_SIGNAL_H */
diff --git a/arch/cris/include/uapi/asm/swab.h b/arch/cris/include/uapi/asm/swab.h
new file mode 100644 (file)
index 0000000..4adf1e9
--- /dev/null
@@ -0,0 +1,3 @@
+/*
+ * CRIS byte swapping.
+ */
diff --git a/arch/cris/include/uapi/asm/termios.h b/arch/cris/include/uapi/asm/termios.h
new file mode 100644 (file)
index 0000000..0a0386a
--- /dev/null
@@ -0,0 +1,45 @@
+#ifndef _UAPI_CRIS_TERMIOS_H
+#define _UAPI_CRIS_TERMIOS_H
+
+#include <asm/termbits.h>
+#include <asm/ioctls.h>
+#include <asm/rs485.h>
+#include <linux/serial.h>
+
+struct winsize {
+       unsigned short ws_row;
+       unsigned short ws_col;
+       unsigned short ws_xpixel;
+       unsigned short ws_ypixel;
+};
+
+#define NCC 8
+struct termio {
+       unsigned short c_iflag;         /* input mode flags */
+       unsigned short c_oflag;         /* output mode flags */
+       unsigned short c_cflag;         /* control mode flags */
+       unsigned short c_lflag;         /* local mode flags */
+       unsigned char c_line;           /* line discipline */
+       unsigned char c_cc[NCC];        /* control characters */
+};
+
+/* modem lines */
+#define TIOCM_LE       0x001
+#define TIOCM_DTR      0x002
+#define TIOCM_RTS      0x004
+#define TIOCM_ST       0x008
+#define TIOCM_SR       0x010
+#define TIOCM_CTS      0x020
+#define TIOCM_CAR      0x040
+#define TIOCM_RNG      0x080
+#define TIOCM_DSR      0x100
+#define TIOCM_CD       TIOCM_CAR
+#define TIOCM_RI       TIOCM_RNG
+#define TIOCM_OUT1     0x2000
+#define TIOCM_OUT2     0x4000
+#define TIOCM_LOOP     0x8000
+
+/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
+
+
+#endif /* _UAPI_CRIS_TERMIOS_H */
diff --git a/arch/cris/include/uapi/asm/types.h b/arch/cris/include/uapi/asm/types.h
new file mode 100644 (file)
index 0000000..9ec9d4c
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/int-ll64.h>
diff --git a/arch/cris/include/uapi/asm/unistd.h b/arch/cris/include/uapi/asm/unistd.h
new file mode 100644 (file)
index 0000000..4884289
--- /dev/null
@@ -0,0 +1,344 @@
+#ifndef _UAPI_ASM_CRIS_UNISTD_H_
+#define _UAPI_ASM_CRIS_UNISTD_H_
+
+/*
+ * This file contains the system call numbers, and stub macros for libc.
+ */
+
+#define __NR_restart_syscall      0
+#define __NR_exit                1
+#define __NR_fork                2
+#define __NR_read                3
+#define __NR_write               4
+#define __NR_open                5
+#define __NR_close               6
+#define __NR_waitpid             7
+#define __NR_creat               8
+#define __NR_link                9
+#define __NR_unlink             10
+#define __NR_execve             11
+#define __NR_chdir              12
+#define __NR_time               13
+#define __NR_mknod              14
+#define __NR_chmod              15
+#define __NR_lchown             16
+#define __NR_break              17
+#define __NR_oldstat            18
+#define __NR_lseek              19
+#define __NR_getpid             20
+#define __NR_mount              21
+#define __NR_umount             22
+#define __NR_setuid             23
+#define __NR_getuid             24
+#define __NR_stime              25
+#define __NR_ptrace             26
+#define __NR_alarm              27
+#define __NR_oldfstat           28
+#define __NR_pause              29
+#define __NR_utime              30
+#define __NR_stty               31
+#define __NR_gtty               32
+#define __NR_access             33
+#define __NR_nice               34
+#define __NR_ftime              35
+#define __NR_sync               36
+#define __NR_kill               37
+#define __NR_rename             38
+#define __NR_mkdir              39
+#define __NR_rmdir              40
+#define __NR_dup                41
+#define __NR_pipe               42
+#define __NR_times              43
+#define __NR_prof               44
+#define __NR_brk                45
+#define __NR_setgid             46
+#define __NR_getgid             47
+#define __NR_signal             48
+#define __NR_geteuid            49
+#define __NR_getegid            50
+#define __NR_acct               51
+#define __NR_umount2            52
+#define __NR_lock               53
+#define __NR_ioctl              54
+#define __NR_fcntl              55
+#define __NR_mpx                56
+#define __NR_setpgid            57
+#define __NR_ulimit             58
+#define __NR_oldolduname        59
+#define __NR_umask              60
+#define __NR_chroot             61
+#define __NR_ustat              62
+#define __NR_dup2               63
+#define __NR_getppid            64
+#define __NR_getpgrp            65
+#define __NR_setsid             66
+#define __NR_sigaction          67
+#define __NR_sgetmask           68
+#define __NR_ssetmask           69
+#define __NR_setreuid           70
+#define __NR_setregid           71
+#define __NR_sigsuspend                 72
+#define __NR_sigpending                 73
+#define __NR_sethostname        74
+#define __NR_setrlimit          75
+#define __NR_getrlimit          76
+#define __NR_getrusage          77
+#define __NR_gettimeofday       78
+#define __NR_settimeofday       79
+#define __NR_getgroups          80
+#define __NR_setgroups          81
+#define __NR_select             82
+#define __NR_symlink            83
+#define __NR_oldlstat           84
+#define __NR_readlink           85
+#define __NR_uselib             86
+#define __NR_swapon             87
+#define __NR_reboot             88
+#define __NR_readdir            89
+#define __NR_mmap               90
+#define __NR_munmap             91
+#define __NR_truncate           92
+#define __NR_ftruncate          93
+#define __NR_fchmod             94
+#define __NR_fchown             95
+#define __NR_getpriority        96
+#define __NR_setpriority        97
+#define __NR_profil             98
+#define __NR_statfs             99
+#define __NR_fstatfs           100
+#define __NR_ioperm            101
+#define __NR_socketcall                102
+#define __NR_syslog            103
+#define __NR_setitimer         104
+#define __NR_getitimer         105
+#define __NR_stat              106
+#define __NR_lstat             107
+#define __NR_fstat             108
+#define __NR_olduname          109
+#define __NR_iopl              110
+#define __NR_vhangup           111
+#define __NR_idle              112
+#define __NR_vm86              113
+#define __NR_wait4             114
+#define __NR_swapoff           115
+#define __NR_sysinfo           116
+#define __NR_ipc               117
+#define __NR_fsync             118
+#define __NR_sigreturn         119
+#define __NR_clone             120
+#define __NR_setdomainname     121
+#define __NR_uname             122
+#define __NR_modify_ldt                123
+#define __NR_adjtimex          124
+#define __NR_mprotect          125
+#define __NR_sigprocmask       126
+#define __NR_create_module     127
+#define __NR_init_module       128
+#define __NR_delete_module     129
+#define __NR_get_kernel_syms   130
+#define __NR_quotactl          131
+#define __NR_getpgid           132
+#define __NR_fchdir            133
+#define __NR_bdflush           134
+#define __NR_sysfs             135
+#define __NR_personality       136
+#define __NR_afs_syscall       137 /* Syscall for Andrew File System */
+#define __NR_setfsuid          138
+#define __NR_setfsgid          139
+#define __NR__llseek           140
+#define __NR_getdents          141
+#define __NR__newselect                142
+#define __NR_flock             143
+#define __NR_msync             144
+#define __NR_readv             145
+#define __NR_writev            146
+#define __NR_getsid            147
+#define __NR_fdatasync         148
+#define __NR__sysctl           149
+#define __NR_mlock             150
+#define __NR_munlock           151
+#define __NR_mlockall          152
+#define __NR_munlockall                153
+#define __NR_sched_setparam            154
+#define __NR_sched_getparam            155
+#define __NR_sched_setscheduler                156
+#define __NR_sched_getscheduler                157
+#define __NR_sched_yield               158
+#define __NR_sched_get_priority_max    159
+#define __NR_sched_get_priority_min    160
+#define __NR_sched_rr_get_interval     161
+#define __NR_nanosleep         162
+#define __NR_mremap            163
+#define __NR_setresuid         164
+#define __NR_getresuid         165
+
+#define __NR_query_module      167
+#define __NR_poll              168
+#define __NR_nfsservctl                169
+#define __NR_setresgid         170
+#define __NR_getresgid         171
+#define __NR_prctl              172
+#define __NR_rt_sigreturn      173
+#define __NR_rt_sigaction      174
+#define __NR_rt_sigprocmask    175
+#define __NR_rt_sigpending     176
+#define __NR_rt_sigtimedwait   177
+#define __NR_rt_sigqueueinfo   178
+#define __NR_rt_sigsuspend     179
+#define __NR_pread64           180
+#define __NR_pwrite64          181
+#define __NR_chown             182
+#define __NR_getcwd            183
+#define __NR_capget            184
+#define __NR_capset            185
+#define __NR_sigaltstack       186
+#define __NR_sendfile          187
+#define __NR_getpmsg           188     /* some people actually want streams */
+#define __NR_putpmsg           189     /* some people actually want streams */
+#define __NR_vfork             190
+#define __NR_ugetrlimit                191     /* SuS compliant getrlimit */
+#define __NR_mmap2             192
+#define __NR_truncate64                193
+#define __NR_ftruncate64       194
+#define __NR_stat64            195
+#define __NR_lstat64           196
+#define __NR_fstat64           197
+#define __NR_lchown32          198
+#define __NR_getuid32          199
+#define __NR_getgid32          200
+#define __NR_geteuid32         201
+#define __NR_getegid32         202
+#define __NR_setreuid32                203
+#define __NR_setregid32                204
+#define __NR_getgroups32       205
+#define __NR_setgroups32       206
+#define __NR_fchown32          207
+#define __NR_setresuid32       208
+#define __NR_getresuid32       209
+#define __NR_setresgid32       210
+#define __NR_getresgid32       211
+#define __NR_chown32           212
+#define __NR_setuid32          213
+#define __NR_setgid32          214
+#define __NR_setfsuid32                215
+#define __NR_setfsgid32                216
+#define __NR_pivot_root                217
+#define __NR_mincore           218
+#define __NR_madvise           219
+#define __NR_getdents64                220
+#define __NR_fcntl64           221
+/* 223 is unused */
+#define __NR_gettid             224
+#define __NR_readahead          225
+#define __NR_setxattr          226
+#define __NR_lsetxattr         227
+#define __NR_fsetxattr         228
+#define __NR_getxattr          229
+#define __NR_lgetxattr         230
+#define __NR_fgetxattr         231
+#define __NR_listxattr         232
+#define __NR_llistxattr                233
+#define __NR_flistxattr                234
+#define __NR_removexattr       235
+#define __NR_lremovexattr      236
+#define __NR_fremovexattr      237
+#define __NR_tkill             238
+#define __NR_sendfile64                239
+#define __NR_futex             240
+#define __NR_sched_setaffinity 241
+#define __NR_sched_getaffinity 242
+#define __NR_set_thread_area   243
+#define __NR_get_thread_area   244
+#define __NR_io_setup          245
+#define __NR_io_destroy                246
+#define __NR_io_getevents      247
+#define __NR_io_submit         248
+#define __NR_io_cancel         249
+#define __NR_fadvise64         250
+/* 251 is available for reuse (was briefly sys_set_zone_reclaim) */
+#define __NR_exit_group                252
+#define __NR_lookup_dcookie    253
+#define __NR_epoll_create      254
+#define __NR_epoll_ctl         255
+#define __NR_epoll_wait                256
+#define __NR_remap_file_pages  257
+#define __NR_set_tid_address   258
+#define __NR_timer_create      259
+#define __NR_timer_settime     (__NR_timer_create+1)
+#define __NR_timer_gettime     (__NR_timer_create+2)
+#define __NR_timer_getoverrun  (__NR_timer_create+3)
+#define __NR_timer_delete      (__NR_timer_create+4)
+#define __NR_clock_settime     (__NR_timer_create+5)
+#define __NR_clock_gettime     (__NR_timer_create+6)
+#define __NR_clock_getres      (__NR_timer_create+7)
+#define __NR_clock_nanosleep   (__NR_timer_create+8)
+#define __NR_statfs64          268
+#define __NR_fstatfs64         269
+#define __NR_tgkill            270
+#define __NR_utimes            271
+#define __NR_fadvise64_64      272
+#define __NR_vserver           273
+#define __NR_mbind             274
+#define __NR_get_mempolicy     275
+#define __NR_set_mempolicy     276
+#define __NR_mq_open           277
+#define __NR_mq_unlink         (__NR_mq_open+1)
+#define __NR_mq_timedsend      (__NR_mq_open+2)
+#define __NR_mq_timedreceive   (__NR_mq_open+3)
+#define __NR_mq_notify         (__NR_mq_open+4)
+#define __NR_mq_getsetattr     (__NR_mq_open+5)
+#define __NR_kexec_load                283
+#define __NR_waitid            284
+/* #define __NR_sys_setaltroot 285 */
+#define __NR_add_key           286
+#define __NR_request_key       287
+#define __NR_keyctl            288
+#define __NR_ioprio_set                289
+#define __NR_ioprio_get                290
+#define __NR_inotify_init      291
+#define __NR_inotify_add_watch 292
+#define __NR_inotify_rm_watch  293
+#define __NR_migrate_pages     294
+#define __NR_openat            295
+#define __NR_mkdirat           296
+#define __NR_mknodat           297
+#define __NR_fchownat          298
+#define __NR_futimesat         299
+#define __NR_fstatat64         300
+#define __NR_unlinkat          301
+#define __NR_renameat          302
+#define __NR_linkat            303
+#define __NR_symlinkat         304
+#define __NR_readlinkat                305
+#define __NR_fchmodat          306
+#define __NR_faccessat         307
+#define __NR_pselect6          308
+#define __NR_ppoll             309
+#define __NR_unshare           310
+#define __NR_set_robust_list   311
+#define __NR_get_robust_list   312
+#define __NR_splice            313
+#define __NR_sync_file_range   314
+#define __NR_tee               315
+#define __NR_vmsplice          316
+#define __NR_move_pages                317
+#define __NR_getcpu            318
+#define __NR_epoll_pwait       319
+#define __NR_utimensat         320
+#define __NR_signalfd          321
+#define __NR_timerfd_create    322
+#define __NR_eventfd           323
+#define __NR_fallocate         324
+#define __NR_timerfd_settime   325
+#define __NR_timerfd_gettime   326
+#define __NR_signalfd4         327
+#define __NR_eventfd2          328
+#define __NR_epoll_create1     329
+#define __NR_dup3              330
+#define __NR_pipe2             331
+#define __NR_inotify_init1     332
+#define __NR_preadv            333
+#define __NR_pwritev           334
+#define __NR_setns             335
+
+#endif /* _UAPI_ASM_CRIS_UNISTD_H_ */
index dd7b8e983221e50104360d3ff11db0391625a77b..a5fd88d816a6c590d145808eecdd7196b9a4ee72 100644 (file)
@@ -1,3 +1,4 @@
+#include <linux/kbuild.h>
 #include <linux/sched.h>
 #include <asm/thread_info.h>
 
@@ -7,11 +8,6 @@
  * and format the required data.
  */
 
-#define DEFINE(sym, val) \
-       asm volatile("\n->" #sym " %0 " #val : : "i" (val))
-
-#define BLANK() asm volatile("\n->" : : )
-
 #if !defined(CONFIG_ETRAX_ARCH_V10) && !defined(CONFIG_ETRAX_ARCH_V32)
 #error One of ARCH v10 and ARCH v32 must be true!
 #endif
index 3364b6966d268b3f82fda0ae501be048b6d858c1..3bfa9b30f448b3f464d5087ba622f6dde4523446 100644 (file)
@@ -1,8 +1,5 @@
-include include/asm-generic/Kbuild.asm
 
-header-y += registers.h
 header-y += ucontext.h
-header-y += user.h
 
 generic-y += auxvec.h
 generic-y += bug.h
index 3e258043337b322a44322bfda4b2eb1f70595df5..468fbb0781cdfb9a4ebc6d2b1b2a7ccb16c55dd3 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Atomic operations for the Hexagon architecture
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  *
  * This program is free software; you can redistribute it and/or modify
index a4ed6e26cb1df2948d4ac74132854ca3865d5665..1041a8e70ce85cea7e8b2d9372dbb8fef19c8496 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Memory barrier definitions for the Hexagon architecture
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index 4caa649ad78b06551120f7be0749e2e986892132..9b1e4afbab3c6530c2e28b0179ac0597ed567137 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Bit operations for the Hexagon architecture
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  *
  * This program is free software; you can redistribute it and/or modify
index 0f01de2eb4abf9fc8b6bc58d548c652782221ff5..f4ca594fdf8c258a13d1d2e99849a820041442f8 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Cache definitions for the Hexagon architecture
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index 6865c1be927a1662bbf4c27148dfbadf7d0e6945..49e0896ec2401464f93ef32ba4f279d1ca88181c 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Cache flush operations for the Hexagon architecture
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index 3ce4ecd44f824c54502f8b2e39e7b636d3b663aa..46ec8a7fd65f876a0de86d36abd5392bf505c1c2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index c5f9527e1df6983c4a7c90694781596377c64e13..9e7802911a57f22b01d9f6852d3c11b2f34c1869 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * xchg/cmpxchg operations for the Hexagon architecture
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  *
  * This program is free software; you can redistribute it and/or modify
index 9ab12e9a872bcaf025396e09ef58384e3971f34c..53079719d6678d4105437986a371f901966a4c39 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index 233ed3d2d25e61ede6d63ccff367f860c969f421..85e9935660cbaf70626f61bda3e6a4a3f60cc0ef 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * DMA operations for the Hexagon architecture
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index da6d2f61a93a9ff2491f81cd677dd14c8d68631d..9e34ff49f3b7d22536c4c9111e885bdf105f344e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index 82b499621e052f2a272cd137c81f23c84fe2ccf3..1ba4b3bff5edee550741adfb7762e6eb7f34bae2 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * ELF definitions for the Hexagon architecture
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index 350e6d497d44732edf3270609a965eb0e07322f5..c32b2132614bae75f7f0fbf1fee5906754d43e55 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Process execution related definitions for the Hexagon architecture
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index b27f4941645b3fedefc9297b60795e07b46c9c3c..b75b6bf4269c6a3e2a3152f1402f5ae63cfd5a65 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Fixmap support for Hexagon - enough to support highmem features
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index 182cb9d547691748075b632acd29878655a107a5..c144bee6cabe506afc9f99071ad741c9727da8d7 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Declarations for to Hexagon Virtal Machine.
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index 1c02186d2e9a18da7639248570e57bd91f2a49c5..ca587737fb2af875d5ee1edd21942092c9333182 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index b3acc2cc71bff7277cedb0dc32c5c291bc523d4b..e527cfeff5bac6dd18473deb1930ffc77034c13f 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * IO definitions for the Hexagon architecture
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index ded8c15cf3e50548348f13acde7bcbe33871536c..51661db389d6f0c9f14cdecdc57f60a45408a790 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index ec1523655416f641cae39ca3a98afb20db960104..e5fd9492d60fbcdc65259e1f6d38d62dbeea6ac6 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * IRQ support for the Hexagon architecture
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index 9e8779702f100b0dd651871738ed332bf90b2eea..32a6fb66944a96e889a2b861d0f461b3a115d332 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * arch/hexagon/include/asm/kgdb.h - Hexagon KGDB Support
  *
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index a00b85f680b8f0ef63386623f9b7fbe05110bbce..31b4cbe7e5831c3c9e59d6b874a749c0f5ba0423 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index 72e5dcda79f5078ad227445eaa0ce480d3efa4f4..af16e977c55ee4a43cb56e0087c13935640541cf 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Memory layout definitions for the Hexagon architecture
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index 30a5d8d2659d9f4acf1ba7bb0ee06208673746e5..2288b19fd0f2d09cf3107419fac8d05775053ea3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index b4fe5a5411b6f9cba29a590a68b5fa879cdbd82e..d423d2e73c3088d428e1a48de233d2f0d752dc05 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * MM context support for the Hexagon architecture
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index 72ba494e6d7d5e2e8452465e6eb5ec8947e9aedd..6b4323acef44161a0970d00473029b96e9d52613 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index edd97626c482eb3b3e71e74f75699b55eebe9cf9..692adc213429a3e2d85a6c7955e43d54ba62261e 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Page management definitions for the Hexagon architecture
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index 8b8526b491c7ae8d57a10583d8e23d7cedb56d2e..430978b1de381a54aeb09732541138aa8879056b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index 13443c7751315e3b8e7c25e1b0f28ab8da6fa3d5..679bf6d664871377ef33a7c16f5cb6b25169c253 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Page table support for the Hexagon architecture
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index ca619bf225ef3d5402c02fe0c5ce65b7843c8a7b..20d55f69fe5571cd6a32a1515dbf1db7eb70db61 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Page table support for the Hexagon architecture
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index e8ea459002a4cf6adfc824092c87b94a5cacc891..a03323ab9d44040a3db7902b1215615ff9fc5ef2 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Process/processor support for the Hexagon architecture
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index 87c869a6a897d9e52a17d5f75e0886252458c5fa..2b9b974e09522bcbaac7e0e4deac5935694d31e0 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * SMP definitions for the Hexagon architecture
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index 168a920485a85973d1e78ec4406eacbdd6e9a675..12ca4ebc033855c93879c81bafc65af93b9bde97 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Spinlock support for the Hexagon architecture
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  *
  * This program is free software; you can redistribute it and/or modify
index 99b5a7575c21416449c856e17e9a85b15088a6fc..7a906b5214a430602b851775388057bfbc9b59c3 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Spinlock support for the Hexagon architecture
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index f4489c15942c39cd905eef8760135b69dd371c80..7d37f47a1d070213c9ffbf1c8c2ba6047ffb9958 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index 089dd82687919b827f03748cf2bf1c59b9947d73..18b44b557fbc0cf08833bf9ca0ffb795cb1f10cb 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index 28ca0dfb6064fc97d9e414f8ea93e5091ba561b1..96745e7b3e3ca5c02119d206eb82f8f1049eebcc 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Task switching definitions for the Hexagon architecture
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index 3e7d61d38d9761f076c70ccb9dc329ed390c3558..fb0e9d48faa668fe62dc174ac13bf3b5b8a67c87 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Syscall support for the Hexagon architecture
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index e4a0aad69cbbb0164bbe3cbbb007aade36c31df7..f7c32406a711a5b619d53037fe76d8689107e3c6 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Thread support for the Hexagon architecture
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index 081b82cac9a9d18d02c343d0c42d9878c7115bf6..deda170c03b8ccc8bb336bbb86318534ca424506 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index d80db239a7b6a341f591da7bb237b2daea3b94cb..79912b8c1e5baef2f47c9ebf4135797d60e4136f 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Timer support for Hexagon
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index b11c62b23f31050f285bbc1f5723d3a840fb2bde..f63fe132f072ca8323a63d9363178a513d7a28a2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index 473abde01d62aa4e7a4c5cf5a7105730da69c781..2f00772cc08a551df873985b29647ac388fb1e55 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index b89a90251225aa74a9daba05f21b6827fd1901ee..62d95a9705c4a319f3ba750bc58a3af702b1618e 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * TLB flush support for Hexagon
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index 6a407f6e5e24bac942576b048e1a726771446578..ec11285012cf1d3e82943c6c777190acde5a2772 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Trap support for Hexagon
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index 7e706eadbf0a2f7f80a10fd5e79bc5de994c634c..e4127e4d6a5bbde7f1d0ec42017df98353177c93 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * User memory access support for Hexagon
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index 2d95cbba3572cac44663978261d5ea3be6091284..ed08e6c6886d8774e4f892419b2eae25561bbaa9 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * vDSO implementation for Hexagon
  *
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index cacda36ef5d5cd2ccb44fe6f843bb1de857b1387..9b0e9c50ceda4bc09e94c4376bfcec1746b7529b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index 580462de5cca35eb2c0b1e011708d3322e844307..9a94de7969bb5e192f57bb9d5bc6ca877376f23c 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Hexagon VM page table entry definitions
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index baebb3da1d44160fc6f6f259886656e6f494b167..c31706c38631b75779b0f472667d5f01fe2c0936 100644 (file)
@@ -1,3 +1,15 @@
 # UAPI Header export list
 include include/uapi/asm-generic/Kbuild.asm
 
+header-y += bitsperlong.h
+header-y += byteorder.h
+header-y += kvm_para.h
+header-y += param.h
+header-y += ptrace.h
+header-y += registers.h
+header-y += setup.h
+header-y += sigcontext.h
+header-y += signal.h
+header-y += swab.h
+header-y += unistd.h
+header-y += user.h
similarity index 92%
rename from arch/hexagon/include/asm/bitsperlong.h
rename to arch/hexagon/include/uapi/asm/bitsperlong.h
index 2701cae3426e6f3c7ed7834bcfbf853a3dc73282..4a658151383d2538357e3c1e0a57bdbdc37ba186 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
similarity index 92%
rename from arch/hexagon/include/asm/byteorder.h
rename to arch/hexagon/include/uapi/asm/byteorder.h
index 0e19b9fe4ca6806d8caf9c331a84a382511d9c30..e31f3f7d9a455feee14ec3af79aaa31533bda862 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
similarity index 91%
rename from arch/hexagon/include/asm/param.h
rename to arch/hexagon/include/uapi/asm/param.h
index 285344bbd03677a1a883ab5884859d3c62c2cfe6..5cec8c0417fbee62ae36869cc44dd7172560b237 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
similarity index 94%
rename from arch/hexagon/include/asm/ptrace.h
rename to arch/hexagon/include/uapi/asm/ptrace.h
index 3d2f607cd63cc98c562693c9103415b038b1dd08..8ef784047a740248cdbca67377a656721b6b0769 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Ptrace definitions for the Hexagon architecture
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
similarity index 85%
rename from arch/hexagon/include/asm/registers.h
rename to arch/hexagon/include/uapi/asm/registers.h
index 4dd741be855d209ecf23e86586be29e287450efa..c20406f63b5cb2ab1bffc1aa48007f0f84a90344 100644 (file)
@@ -1,23 +1,8 @@
 /*
  * Register definitions for the Hexagon architecture
- *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
  */
 
+
 #ifndef _ASM_REGISTERS_H
 #define _ASM_REGISTERS_H
 
similarity index 92%
rename from arch/hexagon/include/asm/setup.h
rename to arch/hexagon/include/uapi/asm/setup.h
index 3b754c50bc0a18b298b60fa9cb6ea4251459de03..e48285e4af967241e896e5940ea5bf013551b908 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
similarity index 93%
rename from arch/hexagon/include/asm/sigcontext.h
rename to arch/hexagon/include/uapi/asm/sigcontext.h
index ce6dcd995220067fdd5e99be5b3080e2f2e237af..b6ba5369ccc69131ee3b4c53e74f54c7853683cf 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
similarity index 92%
rename from arch/hexagon/include/asm/signal.h
rename to arch/hexagon/include/uapi/asm/signal.h
index 471c0562e17b6cae9401dcc19731869234bd0b3f..939556817d340fa5e48dc8c46b57bd6e41d17bfd 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
similarity index 91%
rename from arch/hexagon/include/asm/swab.h
rename to arch/hexagon/include/uapi/asm/swab.h
index 99cf0be3fb832e5043e9e162e56037c69bc41c64..9069e9247a2e26f476dc960b80008859f8bdb801 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
similarity index 93%
rename from arch/hexagon/include/asm/unistd.h
rename to arch/hexagon/include/uapi/asm/unistd.h
index c0d5565030ae34680f944446ad9840bbd918da2b..81312d6a52e687d1a3f75f22997ce09cd261610a 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Syscall support for Hexagon
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
similarity index 63%
rename from arch/hexagon/include/asm/user.h
rename to arch/hexagon/include/uapi/asm/user.h
index 3a55078543d1739fc94cccc48c07e1ab6218ba63..cef13ee1413f483567bb820ad4d893a2eccd3ee0 100644 (file)
@@ -1,21 +1,3 @@
-/*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
 #ifndef HEXAGON_ASM_USER_H
 #define HEXAGON_ASM_USER_H
 
index 89ffa514611f51754ef1ed3fe3c33e1149ac3f5b..2d5e84d3b00d69a738eb52e90388a184fb790d54 100644 (file)
@@ -5,7 +5,7 @@
  * Kevin Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
  * Copyright (C) 2000 MIPS Technologies, Inc.
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index 2b48751aa5f75848c0e4d7674c412a479390ac5a..65c7bdcf565ef94b02882a30a6be129075cee511 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * DMA implementation for Hexagon
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index 8e6b819125a3e8f10760e2a6f9bef5c6a28431ec..d859402c73bac00251cfde0109ce6a42bab7bf72 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Early kernel startup code for Hexagon
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  *
  * This program is free software; you can redistribute it and/or modify
index 7f1892471805c189e49798c513a468dc05a40086..32b1379d68772a7077929d6bb95f7ea09590458b 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Export of symbols defined in assembly files and/or libgcc.
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index d4416a1a431ed77ee06aedf6de65bdc93e1a07ed..85883e1fdc12e950898239ba1f608934e5fe225f 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * First-level interrupt controller model for Hexagon.
  *
- * Copyright (c) 2010-2011 Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index fe4aa1bcca503fc5ad67c682f671065503b0cb9b..344645370646bfdb91ffa1e21c0a9a93e060ab52 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * arch/hexagon/kernel/kgdb.c - Hexagon KGDB Support
  *
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index 61a76bae3668e61be566c3dd4c08d2decac1f53b..477d07a5646c59691a9603dd9069ce3dac8eb1de 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Kernel module loader for Hexagon
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index af51de63b8359fface711d6b89424afc7f2d937d..9f6d7411b5747d87901e59733c1d1646ec72d631 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Process creation support for Hexagon
  *
- * Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index 96c3b2c4dbaded2a24bb0c62a13a5f669637c90d..670b1b0bee63bf740e5979a28a12298b8b8084a8 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Ptrace support for Hexagon
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index 4d72fc58e9b18f4e2ad804ddbf2681dfe4d4e1f0..6aeabc962b3b41348ea84e55970d4b2db67cd25d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index 1202f78d25cb9ab8ca08f6ea339546424f20b497..94a38783500870f06945f993e0840fbc01b0cb75 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Arch related setup for Hexagon
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index 1ea16bec7b91385ca9bb9de3563d44e0958546af..5047b8b879c02376f44c9b06114ce1facde7b013 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Signal support for Hexagon processor
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index 149fbefc1a4d36988d6f5ce3422aaac57d029b60..8e095dffd070da9b57fa03ab67b93014013e7e0d 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * SMP support for Hexagon
  *
- * Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index 11c597b2ac59ef2ac3b3c0e731170758d13b9081..f94918b449a8aa4258a5f04cc98c7b42b1b27fda 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Stacktrace support for Hexagon
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index 25a9bfe3445d941f3386e05dd8ae5c0c2ece0f95..319fa6494f58cd70c8823619fce09972e9846af3 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Hexagon system calls
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index c550f4177ab84f8e9875c784cab2a49b8902347c..7024b1ddc08a3f1519fb8ce347da44b7617d0a28 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * System call table for Hexagon
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index 36ba641857112e1382579d16bd8badf1942115ae..9903fad997f3e2dc210b85905e832d268df31b5b 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Time related functions for Hexagon architecture
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index ba4475184432b86245e8f6677fbc8cfad3ae2840..352f27e809fdde4bfb99a640f7656ad65eb9bb70 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * CPU topology for Hexagon
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index 06c36c036b981edb77b2d66598281a50c8418080..18110a9056b02b0ec47150f5cd6915481102468e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index f08857d0715b87d3162d4fcd2fbadfad68df0e3b..a41eeb8eeaa1a7734e7d170ec679c1438e70adc9 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Kernel traps/events for Hexagon processor
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index 5d39f42f7085bb1fec3c44a101dceb3615c0cc2d..0bf5a87e4d0a9b7f5e57a2831fbb81118285549d 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * vDSO implementation for Hexagon
  *
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index 5b99066cbc8d40d118ed2d688ee3b50b0cd4b721..cd71673ac25983cebe108f19a58efd656a523b03 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Event entry/exit for Hexagon
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index 591fc1b68635e00b86bb2ba73134d2e71d5c0125..9b5a4a295a68ba1afbec0f636c58ed072e02a013 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Mostly IRQ support for Hexagon
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index aebb35b6465e914531f081aeeeea0ebfe6e80e95..80967f2192b37aee002b0f05c0aff64cd5e02f16 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Initial page table for Linux kernel under Hexagon VM,
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index 24d7fcac4ff262808b23beb83e3ee561eebf4b3e..9fb77b3f6cf2950391c0eedf980187ce3f357c85 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Hexagon VM instruction support
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index 0decf2f58e3202f8857d2147fe876e7817d2a3ec..62c6df91b3bb3f64523d5551082ce47db20b80ab 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Context switch support for Hexagon
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index 97a4b50b00dfce0f2fff21473a40bfbc91517d10..620f42cc582a17180083058a001d3464b57ac907 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Event jump tables
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index 071d3c30edfbe60da04634d33b0a0ec41a170ef1..14e793f6abbfff6a4313720710646826233be8ea 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Linker script for Hexagon kernel
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index 93005522d52b1af1c15a47262519262986e50fde..8169f78a46a70f5bc0359b4fa006070772116d59 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Checksum functions for Hexagon
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index 8ae47ba0e7057fe3c70897bd29ae49c1f374c1eb..885c9626d5e08b4a9472359419beba4bfbf8d972 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * I/O access functions for Hexagon
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index 2101c339566524ea44b68947f21790674e6dac20..81c561c4b4d606ee7159f18742a2d5fe4c81b20d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  *
  * This program is free software; you can redistribute it and/or modify
index 26d961439ab0c8de3d717a26c3f75c598c8f4c82..9341889ea3f67877e64819fdd43e26301838a2b4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011 Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index c5cf6ee2758777de0d948b55eb315fe8cfd3d7af..fe14ccf285613c39f8801a8ca29389c5df6afa44 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Cache management functions for Hexagon
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index 8eb1d4d61a3d55118c29b120890049a185853d08..7fc94f3e66425b8d3020e808420cda7b9b78ba58 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * User memory copy functions for kernel
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index cb9740ed9e7dd867672e3fbf0b54beeb9f3c1570..0cfbcc09d1d942d47aa594b90f773de80a971372 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * User memory copying routines for the Hexagon Kernel
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index 08d7d7b23daa70f70e4f3edc75be620254cffdbd..254d8cc766bb9f7746425c83326ef2290e43d57c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index b57d741750b22225d9c20cf287306161e8ba4246..69ffcfd2879450de9fd16538be3d4acc7ee9e5f7 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Memory subsystem initialization for Hexagon
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index 3a37bc3b01163b02b3c96dcd21f4f0d69f465d5b..5905fd5f97f666fa9379c7860699fe9bf8807407 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * I/O remap functions for Hexagon
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index b175e2d42b895aaf3d27e62fc3a2c0fa3c52e8e9..19760a4611d97a7e7eed513d411436d3e1eae03b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index 5c6a16c7c72ac9527e6858fd82f17428524fba5b..0eecb7a768fe0edd87ece9e8b9c55974ab9e74b1 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * User string length functions for kernel
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index e748108b47a7f7a8c93350137874eae96866a677..34127261c2b7124d4fc43e36ddb7bb84dcf7900b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index 513b74cb397eb4dffab84d240367f2e71d8a4263..308ef0ce648baeb77ed933a6c30de55a94d96438 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Memory fault handling for Hexagon
  *
- * Copyright (c) 2010-2011 Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index c6ff415754615dd5be37bc032823c2b9e8dd0845..9647d00cb761002c3d4370df41785b740f6c980c 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Hexagon Virtual Machine TLB functions
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
index 4a159da23633dbf359c9886513958ce49e842ce7..dd02f09b6eda6e2b41f1dd643a6ff550625a15e0 100644 (file)
@@ -1,3 +1,4 @@
 
 generic-y += clkdev.h
 generic-y += exec.h
+generic-y += kvm_para.h
index 2c26321c28c3c0f504503c3d64421c95824bd585..74a7cc3293bc3aa279c735e4144a8cd7439d0172 100644 (file)
@@ -90,7 +90,7 @@ phys_to_virt (unsigned long address)
 
 #define ARCH_HAS_VALID_PHYS_ADDR_RANGE
 extern u64 kern_mem_attribute (unsigned long phys_addr, unsigned long size);
-extern int valid_phys_addr_range (unsigned long addr, size_t count); /* efi.c */
+extern int valid_phys_addr_range (phys_addr_t addr, size_t count); /* efi.c */
 extern int valid_mmap_phys_addr_range (unsigned long pfn, size_t count);
 
 /*
diff --git a/arch/ia64/include/asm/kvm_para.h b/arch/ia64/include/asm/kvm_para.h
deleted file mode 100644 (file)
index 47c00f9..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2007 Xiantao Zhang <xiantao.zhang@intel.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- */
-#ifndef __IA64_KVM_PARA_H
-#define __IA64_KVM_PARA_H
-
-#include <uapi/asm/kvm_para.h>
-
-
-static inline unsigned int kvm_arch_para_features(void)
-{
-       return 0;
-}
-
-static inline bool kvm_check_and_clear_guest_paused(void)
-{
-       return false;
-}
-
-#endif
index d37bbd48637fd80f52f01b3a0592f341feabb030..f034563aeae547c44b0e3a2a99b4ab535917cee1 100644 (file)
@@ -870,7 +870,7 @@ kern_mem_attribute (unsigned long phys_addr, unsigned long size)
 EXPORT_SYMBOL(kern_mem_attribute);
 
 int
-valid_phys_addr_range (unsigned long phys_addr, unsigned long size)
+valid_phys_addr_range (phys_addr_t phys_addr, unsigned long size)
 {
        u64 attr;
 
index c4eb79edecec04d58d5ad681c389118a3472cec5..aad3b0bad7dea9872ba350dff598ed1d662040cd 100644 (file)
@@ -35,7 +35,7 @@ endchoice
 if M68KCLASSIC
 
 config M68000
-       bool
+       bool "MC68000"
        select CPU_HAS_NO_BITFIELDS
        select CPU_HAS_NO_MULDIV64
        select CPU_HAS_NO_UNALIGNED
index 7636751f2f8731626aef410e846ec7cfef15035f..2f02acfb8edf4647e28ada0e48801b68c0c965f3 100644 (file)
@@ -92,7 +92,7 @@ endif
 head-y                         := arch/m68k/kernel/head.o
 head-$(CONFIG_SUN3)            := arch/m68k/kernel/sun3-head.o
 head-$(CONFIG_M68360)          := arch/m68k/platform/68360/head.o
-head-$(CONFIG_M68000)          := arch/m68k/platform/68328/head.o
+head-$(CONFIG_M68000)          := arch/m68k/platform/68000/head.o
 head-$(CONFIG_COLDFIRE)                := arch/m68k/platform/coldfire/head.o
 
 core-y                         += arch/m68k/kernel/    arch/m68k/mm/
@@ -114,9 +114,7 @@ core-$(CONFIG_M68040)               += arch/m68k/fpsp040/
 core-$(CONFIG_M68060)          += arch/m68k/ifpsp060/
 core-$(CONFIG_M68KFPU_EMU)     += arch/m68k/math-emu/
 core-$(CONFIG_M68360)          += arch/m68k/platform/68360/
-core-$(CONFIG_M68000)          += arch/m68k/platform/68328/
-core-$(CONFIG_M68EZ328)                += arch/m68k/platform/68EZ328/
-core-$(CONFIG_M68VZ328)                += arch/m68k/platform/68VZ328/
+core-$(CONFIG_M68000)          += arch/m68k/platform/68000/
 core-$(CONFIG_COLDFIRE)                += arch/m68k/platform/coldfire/
 
 
index ecb540810ab3ace200ae66368d700d97b4abf0d2..fe821a2da2979856d054d82ffc461292b7cc3225 100644 (file)
@@ -1,6 +1,5 @@
-include include/asm-generic/Kbuild.asm
-header-y += cachectl.h
 
+generic-y += auxvec.h
 generic-y += bitsperlong.h
 generic-y += clkdev.h
 generic-y += cputime.h
@@ -9,6 +8,7 @@ generic-y += emergency-restart.h
 generic-y += errno.h
 generic-y += exec.h
 generic-y += futex.h
+generic-y += hw_irq.h
 generic-y += ioctl.h
 generic-y += ipcbuf.h
 generic-y += irq_regs.h
@@ -18,13 +18,22 @@ generic-y += kvm_para.h
 generic-y += local64.h
 generic-y += local.h
 generic-y += mman.h
+generic-y += msgbuf.h
 generic-y += mutex.h
 generic-y += percpu.h
 generic-y += resource.h
 generic-y += scatterlist.h
 generic-y += sections.h
+generic-y += sembuf.h
+generic-y += shmbuf.h
+generic-y += shmparam.h
 generic-y += siginfo.h
+generic-y += socket.h
+generic-y += sockios.h
+generic-y += spinlock.h
 generic-y += statfs.h
+generic-y += termbits.h
+generic-y += termios.h
 generic-y += topology.h
 generic-y += types.h
 generic-y += word-at-a-time.h
diff --git a/arch/m68k/include/asm/auxvec.h b/arch/m68k/include/asm/auxvec.h
deleted file mode 100644 (file)
index 844d6d5..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-#ifndef __ASMm68k_AUXVEC_H
-#define __ASMm68k_AUXVEC_H
-
-#endif
diff --git a/arch/m68k/include/asm/hw_irq.h b/arch/m68k/include/asm/hw_irq.h
deleted file mode 100644 (file)
index eacef09..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __ASM_M68K_HW_IRQ_H
-#define __ASM_M68K_HW_IRQ_H
-
-/* Dummy include. */
-
-#endif
diff --git a/arch/m68k/include/asm/msgbuf.h b/arch/m68k/include/asm/msgbuf.h
deleted file mode 100644 (file)
index 243cb79..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-#ifndef _M68K_MSGBUF_H
-#define _M68K_MSGBUF_H
-
-/*
- * The msqid64_ds structure for m68k architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 64-bit time_t to solve y2038 problem
- * - 2 miscellaneous 32-bit values
- */
-
-struct msqid64_ds {
-       struct ipc64_perm msg_perm;
-       __kernel_time_t msg_stime;      /* last msgsnd time */
-       unsigned long   __unused1;
-       __kernel_time_t msg_rtime;      /* last msgrcv time */
-       unsigned long   __unused2;
-       __kernel_time_t msg_ctime;      /* last change time */
-       unsigned long   __unused3;
-       unsigned long  msg_cbytes;      /* current number of bytes on queue */
-       unsigned long  msg_qnum;        /* number of messages in queue */
-       unsigned long  msg_qbytes;      /* max number of bytes on queue */
-       __kernel_pid_t msg_lspid;       /* pid of last msgsnd */
-       __kernel_pid_t msg_lrpid;       /* last receive pid */
-       unsigned long  __unused4;
-       unsigned long  __unused5;
-};
-
-#endif /* _M68K_MSGBUF_H */
index 5e08b597f012192e8a5f8cd4cc4d0a20690b485d..0f717045bddef4094584fe9c5be624e9ee2d4927 100644 (file)
@@ -1,82 +1,10 @@
 #ifndef _M68K_PTRACE_H
 #define _M68K_PTRACE_H
 
-#define PT_D1     0
-#define PT_D2     1
-#define PT_D3     2
-#define PT_D4     3
-#define PT_D5     4
-#define PT_D6     5
-#define PT_D7     6
-#define PT_A0     7
-#define PT_A1     8
-#define PT_A2     9
-#define PT_A3     10
-#define PT_A4     11
-#define PT_A5     12
-#define PT_A6     13
-#define PT_D0     14
-#define PT_USP    15
-#define PT_ORIG_D0 16
-#define PT_SR     17
-#define PT_PC     18
+#include <uapi/asm/ptrace.h>
 
 #ifndef __ASSEMBLY__
 
-/* this struct defines the way the registers are stored on the
-   stack during a system call. */
-
-struct pt_regs {
-  long     d1;
-  long     d2;
-  long     d3;
-  long     d4;
-  long     d5;
-  long     a0;
-  long     a1;
-  long     a2;
-  long     d0;
-  long     orig_d0;
-  long     stkadj;
-#ifdef CONFIG_COLDFIRE
-  unsigned format :  4; /* frame format specifier */
-  unsigned vector : 12; /* vector offset */
-  unsigned short sr;
-  unsigned long  pc;
-#else
-  unsigned short sr;
-  unsigned long  pc;
-  unsigned format :  4; /* frame format specifier */
-  unsigned vector : 12; /* vector offset */
-#endif
-};
-
-/*
- * This is the extended stack used by signal handlers and the context
- * switcher: it's pushed after the normal "struct pt_regs".
- */
-struct switch_stack {
-       unsigned long  d6;
-       unsigned long  d7;
-       unsigned long  a3;
-       unsigned long  a4;
-       unsigned long  a5;
-       unsigned long  a6;
-       unsigned long  retpc;
-};
-
-/* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
-#define PTRACE_GETREGS            12
-#define PTRACE_SETREGS            13
-#define PTRACE_GETFPREGS          14
-#define PTRACE_SETFPREGS          15
-
-#define PTRACE_GET_THREAD_AREA    25
-
-#define PTRACE_SINGLEBLOCK     33      /* resume execution until next branch */
-
-#ifdef __KERNEL__
-
 #ifndef PS_S
 #define PS_S  (0x2000)
 #define PS_M  (0x1000)
@@ -94,6 +22,5 @@ struct switch_stack {
 #define arch_has_block_step()  (1)
 #endif
 
-#endif /* __KERNEL__ */
 #endif /* __ASSEMBLY__ */
 #endif /* _M68K_PTRACE_H */
diff --git a/arch/m68k/include/asm/sembuf.h b/arch/m68k/include/asm/sembuf.h
deleted file mode 100644 (file)
index 2308052..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-#ifndef _M68K_SEMBUF_H
-#define _M68K_SEMBUF_H
-
-/*
- * The semid64_ds structure for m68k architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 64-bit time_t to solve y2038 problem
- * - 2 miscellaneous 32-bit values
- */
-
-struct semid64_ds {
-       struct ipc64_perm sem_perm;             /* permissions .. see ipc.h */
-       __kernel_time_t sem_otime;              /* last semop time */
-       unsigned long   __unused1;
-       __kernel_time_t sem_ctime;              /* last change time */
-       unsigned long   __unused2;
-       unsigned long   sem_nsems;              /* no. of semaphores in array */
-       unsigned long   __unused3;
-       unsigned long   __unused4;
-};
-
-#endif /* _M68K_SEMBUF_H */
index 00c2c5397d37ee787eaeac0df751e220c3cefa26..65e78a2dad64a9840fdb96bdc898e8b848f52331 100644 (file)
 **   Redesign of the boot information structure; moved boot information
 **   structure to bootinfo.h
 */
-
 #ifndef _M68K_SETUP_H
 #define _M68K_SETUP_H
 
+#include <uapi/asm/setup.h>
 
 
-    /*
-     *  Linux/m68k Architectures
-     */
-
-#define MACH_AMIGA    1
-#define MACH_ATARI    2
-#define MACH_MAC      3
-#define MACH_APOLLO   4
-#define MACH_SUN3     5
-#define MACH_MVME147  6
-#define MACH_MVME16x  7
-#define MACH_BVME6000 8
-#define MACH_HP300    9
-#define MACH_Q40     10
-#define MACH_SUN3X   11
-#define MACH_M54XX   12
-
-#define COMMAND_LINE_SIZE 256
-
-#ifdef __KERNEL__
-
 #define CL_SIZE COMMAND_LINE_SIZE
 
 #ifndef __ASSEMBLY__
@@ -194,63 +173,6 @@ extern unsigned long m68k_machtype;
 #  define MACH_TYPE (m68k_machtype)
 #endif
 
-#endif /* __KERNEL__ */
-
-
-    /*
-     *  CPU, FPU and MMU types
-     *
-     *  Note: we may rely on the following equalities:
-     *
-     *      CPU_68020 == MMU_68851
-     *      CPU_68030 == MMU_68030
-     *      CPU_68040 == FPU_68040 == MMU_68040
-     *      CPU_68060 == FPU_68060 == MMU_68060
-     */
-
-#define CPUB_68020     0
-#define CPUB_68030     1
-#define CPUB_68040     2
-#define CPUB_68060     3
-#define CPUB_COLDFIRE  4
-
-#define CPU_68020      (1<<CPUB_68020)
-#define CPU_68030      (1<<CPUB_68030)
-#define CPU_68040      (1<<CPUB_68040)
-#define CPU_68060      (1<<CPUB_68060)
-#define CPU_COLDFIRE   (1<<CPUB_COLDFIRE)
-
-#define FPUB_68881     0
-#define FPUB_68882     1
-#define FPUB_68040     2                       /* Internal FPU */
-#define FPUB_68060     3                       /* Internal FPU */
-#define FPUB_SUNFPA    4                       /* Sun-3 FPA */
-#define FPUB_COLDFIRE  5                       /* ColdFire FPU */
-
-#define FPU_68881      (1<<FPUB_68881)
-#define FPU_68882      (1<<FPUB_68882)
-#define FPU_68040      (1<<FPUB_68040)
-#define FPU_68060      (1<<FPUB_68060)
-#define FPU_SUNFPA     (1<<FPUB_SUNFPA)
-#define FPU_COLDFIRE   (1<<FPUB_COLDFIRE)
-
-#define MMUB_68851     0
-#define MMUB_68030     1                       /* Internal MMU */
-#define MMUB_68040     2                       /* Internal MMU */
-#define MMUB_68060     3                       /* Internal MMU */
-#define MMUB_APOLLO    4                       /* Custom Apollo */
-#define MMUB_SUN3      5                       /* Custom Sun-3 */
-#define MMUB_COLDFIRE  6                       /* Internal MMU */
-
-#define MMU_68851      (1<<MMUB_68851)
-#define MMU_68030      (1<<MMUB_68030)
-#define MMU_68040      (1<<MMUB_68040)
-#define MMU_68060      (1<<MMUB_68060)
-#define MMU_SUN3       (1<<MMUB_SUN3)
-#define MMU_APOLLO     (1<<MMUB_APOLLO)
-#define MMU_COLDFIRE   (1<<MMUB_COLDFIRE)
-
-#ifdef __KERNEL__
 
 #ifndef __ASSEMBLY__
 extern unsigned long m68k_cputype;
@@ -385,6 +307,4 @@ extern int m68k_realnum_memory;             /* real # of memory blocks found */
 extern struct mem_info m68k_memory[NUM_MEMINFO];/* memory description */
 #endif
 
-#endif /* __KERNEL__ */
-
 #endif /* _M68K_SETUP_H */
diff --git a/arch/m68k/include/asm/shmbuf.h b/arch/m68k/include/asm/shmbuf.h
deleted file mode 100644 (file)
index f8928d6..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-#ifndef _M68K_SHMBUF_H
-#define _M68K_SHMBUF_H
-
-/*
- * The shmid64_ds structure for m68k architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 64-bit time_t to solve y2038 problem
- * - 2 miscellaneous 32-bit values
- */
-
-struct shmid64_ds {
-       struct ipc64_perm       shm_perm;       /* operation perms */
-       size_t                  shm_segsz;      /* size of segment (bytes) */
-       __kernel_time_t         shm_atime;      /* last attach time */
-       unsigned long           __unused1;
-       __kernel_time_t         shm_dtime;      /* last detach time */
-       unsigned long           __unused2;
-       __kernel_time_t         shm_ctime;      /* last change time */
-       unsigned long           __unused3;
-       __kernel_pid_t          shm_cpid;       /* pid of creator */
-       __kernel_pid_t          shm_lpid;       /* pid of last operator */
-       unsigned long           shm_nattch;     /* no. of current attaches */
-       unsigned long           __unused4;
-       unsigned long           __unused5;
-};
-
-struct shminfo64 {
-       unsigned long   shmmax;
-       unsigned long   shmmin;
-       unsigned long   shmmni;
-       unsigned long   shmseg;
-       unsigned long   shmall;
-       unsigned long   __unused1;
-       unsigned long   __unused2;
-       unsigned long   __unused3;
-       unsigned long   __unused4;
-};
-
-#endif /* _M68K_SHMBUF_H */
diff --git a/arch/m68k/include/asm/shmparam.h b/arch/m68k/include/asm/shmparam.h
deleted file mode 100644 (file)
index 558892a..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _M68K_SHMPARAM_H
-#define _M68K_SHMPARAM_H
-
-#define        SHMLBA PAGE_SIZE                 /* attach addr a multiple of this */
-
-#endif /* _M68K_SHMPARAM_H */
index 60e88660169c4575f53bb26d429b095abfd04a4e..67e489d8d1bd6450945b3b5a4320eaa4d1840953 100644 (file)
@@ -1,12 +1,8 @@
 #ifndef _M68K_SIGNAL_H
 #define _M68K_SIGNAL_H
 
-#include <linux/types.h>
+#include <uapi/asm/signal.h>
 
-/* Avoid too many header ordering problems.  */
-struct siginfo;
-
-#ifdef __KERNEL__
 /* Most things should be clean enough to redefine this at will, if care
    is taken to make libc match.  */
 
@@ -20,92 +16,6 @@ typedef struct {
        unsigned long sig[_NSIG_WORDS];
 } sigset_t;
 
-#else
-/* Here we must cater to libcs that poke about in kernel headers.  */
-
-#define NSIG           32
-typedef unsigned long sigset_t;
-
-#endif /* __KERNEL__ */
-
-#define SIGHUP          1
-#define SIGINT          2
-#define SIGQUIT                 3
-#define SIGILL          4
-#define SIGTRAP                 5
-#define SIGABRT                 6
-#define SIGIOT          6
-#define SIGBUS          7
-#define SIGFPE          8
-#define SIGKILL                 9
-#define SIGUSR1                10
-#define SIGSEGV                11
-#define SIGUSR2                12
-#define SIGPIPE                13
-#define SIGALRM                14
-#define SIGTERM                15
-#define SIGSTKFLT      16
-#define SIGCHLD                17
-#define SIGCONT                18
-#define SIGSTOP                19
-#define SIGTSTP                20
-#define SIGTTIN                21
-#define SIGTTOU                22
-#define SIGURG         23
-#define SIGXCPU                24
-#define SIGXFSZ                25
-#define SIGVTALRM      26
-#define SIGPROF                27
-#define SIGWINCH       28
-#define SIGIO          29
-#define SIGPOLL                SIGIO
-/*
-#define SIGLOST                29
-*/
-#define SIGPWR         30
-#define SIGSYS         31
-#define        SIGUNUSED       31
-
-/* These should not be considered constants from userland.  */
-#define SIGRTMIN       32
-#define SIGRTMAX       _NSIG
-
-/*
- * SA_FLAGS values:
- *
- * SA_ONSTACK indicates that a registered stack_t will be used.
- * SA_RESTART flag to get restarting signals (which were the default long ago)
- * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
- * SA_RESETHAND clears the handler when the signal is delivered.
- * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
- * SA_NODEFER prevents the current signal from being masked in the handler.
- *
- * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
- * Unix names RESETHAND and NODEFER respectively.
- */
-#define SA_NOCLDSTOP   0x00000001
-#define SA_NOCLDWAIT   0x00000002
-#define SA_SIGINFO     0x00000004
-#define SA_ONSTACK     0x08000000
-#define SA_RESTART     0x10000000
-#define SA_NODEFER     0x40000000
-#define SA_RESETHAND   0x80000000
-
-#define SA_NOMASK      SA_NODEFER
-#define SA_ONESHOT     SA_RESETHAND
-
-/*
- * sigaltstack controls
- */
-#define SS_ONSTACK     1
-#define SS_DISABLE     2
-
-#define MINSIGSTKSZ    2048
-#define SIGSTKSZ       8192
-
-#include <asm-generic/signal-defs.h>
-
-#ifdef __KERNEL__
 struct old_sigaction {
        __sighandler_t sa_handler;
        old_sigset_t sa_mask;
@@ -123,31 +33,6 @@ struct sigaction {
 struct k_sigaction {
        struct sigaction sa;
 };
-#else
-/* Here we must cater to libcs that poke about in kernel headers.  */
-
-struct sigaction {
-       union {
-         __sighandler_t _sa_handler;
-         void (*_sa_sigaction)(int, struct siginfo *, void *);
-       } _u;
-       sigset_t sa_mask;
-       unsigned long sa_flags;
-       void (*sa_restorer)(void);
-};
-
-#define sa_handler     _u._sa_handler
-#define sa_sigaction   _u._sa_sigaction
-
-#endif /* __KERNEL__ */
-
-typedef struct sigaltstack {
-       void __user *ss_sp;
-       int ss_flags;
-       size_t ss_size;
-} stack_t;
-
-#ifdef __KERNEL__
 #include <asm/sigcontext.h>
 
 #ifndef CONFIG_CPU_HAS_NO_BITFIELDS
@@ -208,5 +93,4 @@ struct pt_regs;
 extern void ptrace_signal_deliver(struct pt_regs *regs, void *cookie);
 #endif /* __uClinux__ */
 
-#endif /* __KERNEL__ */
 #endif /* _M68K_SIGNAL_H */
diff --git a/arch/m68k/include/asm/socket.h b/arch/m68k/include/asm/socket.h
deleted file mode 100644 (file)
index d1be684..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-#ifndef _ASM_SOCKET_H
-#define _ASM_SOCKET_H
-
-#include <asm/sockios.h>
-
-/* For setsockopt(2) */
-#define SOL_SOCKET     1
-
-#define SO_DEBUG       1
-#define SO_REUSEADDR   2
-#define SO_TYPE                3
-#define SO_ERROR       4
-#define SO_DONTROUTE   5
-#define SO_BROADCAST   6
-#define SO_SNDBUF      7
-#define SO_RCVBUF      8
-#define SO_SNDBUFFORCE 32
-#define SO_RCVBUFFORCE 33
-#define SO_KEEPALIVE   9
-#define SO_OOBINLINE   10
-#define SO_NO_CHECK    11
-#define SO_PRIORITY    12
-#define SO_LINGER      13
-#define SO_BSDCOMPAT   14
-/* To add :#define SO_REUSEPORT 15 */
-#define SO_PASSCRED    16
-#define SO_PEERCRED    17
-#define SO_RCVLOWAT    18
-#define SO_SNDLOWAT    19
-#define SO_RCVTIMEO    20
-#define SO_SNDTIMEO    21
-
-/* Security levels - as per NRL IPv6 - don't actually do anything */
-#define SO_SECURITY_AUTHENTICATION             22
-#define SO_SECURITY_ENCRYPTION_TRANSPORT       23
-#define SO_SECURITY_ENCRYPTION_NETWORK         24
-
-#define SO_BINDTODEVICE        25
-
-/* Socket filtering */
-#define SO_ATTACH_FILTER        26
-#define SO_DETACH_FILTER        27
-
-#define SO_PEERNAME             28
-#define SO_TIMESTAMP           29
-#define SCM_TIMESTAMP          SO_TIMESTAMP
-
-#define SO_ACCEPTCONN          30
-
-#define SO_PEERSEC             31
-#define SO_PASSSEC             34
-#define SO_TIMESTAMPNS         35
-#define SCM_TIMESTAMPNS                SO_TIMESTAMPNS
-
-#define SO_MARK                        36
-
-#define SO_TIMESTAMPING                37
-#define SCM_TIMESTAMPING       SO_TIMESTAMPING
-
-#define SO_PROTOCOL            38
-#define SO_DOMAIN              39
-
-#define SO_RXQ_OVFL             40
-
-#define SO_WIFI_STATUS         41
-#define SCM_WIFI_STATUS                SO_WIFI_STATUS
-#define SO_PEEK_OFF            42
-
-/* Instruct lower device to use last 4-bytes of skb data as FCS */
-#define SO_NOFCS               43
-
-#endif /* _ASM_SOCKET_H */
diff --git a/arch/m68k/include/asm/sockios.h b/arch/m68k/include/asm/sockios.h
deleted file mode 100644 (file)
index c04a239..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef __ARCH_M68K_SOCKIOS__
-#define __ARCH_M68K_SOCKIOS__
-
-/* Socket-level I/O control calls. */
-#define FIOSETOWN      0x8901
-#define SIOCSPGRP      0x8902
-#define FIOGETOWN      0x8903
-#define SIOCGPGRP      0x8904
-#define SIOCATMARK     0x8905
-#define SIOCGSTAMP     0x8906          /* Get stamp (timeval) */
-#define SIOCGSTAMPNS   0x8907          /* Get stamp (timespec) */
-
-#endif /* __ARCH_M68K_SOCKIOS__ */
diff --git a/arch/m68k/include/asm/spinlock.h b/arch/m68k/include/asm/spinlock.h
deleted file mode 100644 (file)
index 20f46e2..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __M68K_SPINLOCK_H
-#define __M68K_SPINLOCK_H
-
-#error "m68k doesn't do SMP yet"
-
-#endif
diff --git a/arch/m68k/include/asm/termbits.h b/arch/m68k/include/asm/termbits.h
deleted file mode 100644 (file)
index aea1e37..0000000
+++ /dev/null
@@ -1,201 +0,0 @@
-#ifndef __ARCH_M68K_TERMBITS_H__
-#define __ARCH_M68K_TERMBITS_H__
-
-#include <linux/posix_types.h>
-
-typedef unsigned char  cc_t;
-typedef unsigned int   speed_t;
-typedef unsigned int   tcflag_t;
-
-#define NCCS 19
-struct termios {
-       tcflag_t c_iflag;               /* input mode flags */
-       tcflag_t c_oflag;               /* output mode flags */
-       tcflag_t c_cflag;               /* control mode flags */
-       tcflag_t c_lflag;               /* local mode flags */
-       cc_t c_line;                    /* line discipline */
-       cc_t c_cc[NCCS];                /* control characters */
-};
-
-struct termios2 {
-       tcflag_t c_iflag;               /* input mode flags */
-       tcflag_t c_oflag;               /* output mode flags */
-       tcflag_t c_cflag;               /* control mode flags */
-       tcflag_t c_lflag;               /* local mode flags */
-       cc_t c_line;                    /* line discipline */
-       cc_t c_cc[NCCS];                /* control characters */
-       speed_t c_ispeed;               /* input speed */
-       speed_t c_ospeed;               /* output speed */
-};
-
-struct ktermios {
-       tcflag_t c_iflag;               /* input mode flags */
-       tcflag_t c_oflag;               /* output mode flags */
-       tcflag_t c_cflag;               /* control mode flags */
-       tcflag_t c_lflag;               /* local mode flags */
-       cc_t c_line;                    /* line discipline */
-       cc_t c_cc[NCCS];                /* control characters */
-       speed_t c_ispeed;               /* input speed */
-       speed_t c_ospeed;               /* output speed */
-};
-
-/* c_cc characters */
-#define VINTR 0
-#define VQUIT 1
-#define VERASE 2
-#define VKILL 3
-#define VEOF 4
-#define VTIME 5
-#define VMIN 6
-#define VSWTC 7
-#define VSTART 8
-#define VSTOP 9
-#define VSUSP 10
-#define VEOL 11
-#define VREPRINT 12
-#define VDISCARD 13
-#define VWERASE 14
-#define VLNEXT 15
-#define VEOL2 16
-
-
-/* c_iflag bits */
-#define IGNBRK 0000001
-#define BRKINT 0000002
-#define IGNPAR 0000004
-#define PARMRK 0000010
-#define INPCK  0000020
-#define ISTRIP 0000040
-#define INLCR  0000100
-#define IGNCR  0000200
-#define ICRNL  0000400
-#define IUCLC  0001000
-#define IXON   0002000
-#define IXANY  0004000
-#define IXOFF  0010000
-#define IMAXBEL        0020000
-#define IUTF8  0040000
-
-/* c_oflag bits */
-#define OPOST  0000001
-#define OLCUC  0000002
-#define ONLCR  0000004
-#define OCRNL  0000010
-#define ONOCR  0000020
-#define ONLRET 0000040
-#define OFILL  0000100
-#define OFDEL  0000200
-#define NLDLY  0000400
-#define   NL0  0000000
-#define   NL1  0000400
-#define CRDLY  0003000
-#define   CR0  0000000
-#define   CR1  0001000
-#define   CR2  0002000
-#define   CR3  0003000
-#define TABDLY 0014000
-#define   TAB0 0000000
-#define   TAB1 0004000
-#define   TAB2 0010000
-#define   TAB3 0014000
-#define   XTABS        0014000
-#define BSDLY  0020000
-#define   BS0  0000000
-#define   BS1  0020000
-#define VTDLY  0040000
-#define   VT0  0000000
-#define   VT1  0040000
-#define FFDLY  0100000
-#define   FF0  0000000
-#define   FF1  0100000
-
-/* c_cflag bit meaning */
-#define CBAUD  0010017
-#define  B0    0000000         /* hang up */
-#define  B50   0000001
-#define  B75   0000002
-#define  B110  0000003
-#define  B134  0000004
-#define  B150  0000005
-#define  B200  0000006
-#define  B300  0000007
-#define  B600  0000010
-#define  B1200 0000011
-#define  B1800 0000012
-#define  B2400 0000013
-#define  B4800 0000014
-#define  B9600 0000015
-#define  B19200        0000016
-#define  B38400        0000017
-#define EXTA B19200
-#define EXTB B38400
-#define CSIZE  0000060
-#define   CS5  0000000
-#define   CS6  0000020
-#define   CS7  0000040
-#define   CS8  0000060
-#define CSTOPB 0000100
-#define CREAD  0000200
-#define PARENB 0000400
-#define PARODD 0001000
-#define HUPCL  0002000
-#define CLOCAL 0004000
-#define CBAUDEX 0010000
-#define    BOTHER 0010000
-#define    B57600 0010001
-#define   B115200 0010002
-#define   B230400 0010003
-#define   B460800 0010004
-#define   B500000 0010005
-#define   B576000 0010006
-#define   B921600 0010007
-#define  B1000000 0010010
-#define  B1152000 0010011
-#define  B1500000 0010012
-#define  B2000000 0010013
-#define  B2500000 0010014
-#define  B3000000 0010015
-#define  B3500000 0010016
-#define  B4000000 0010017
-#define CIBAUD   002003600000          /* input baud rate */
-#define CMSPAR   010000000000          /* mark or space (stick) parity */
-#define CRTSCTS          020000000000          /* flow control */
-
-#define IBSHIFT        16                      /* Shift from CBAUD to CIBAUD */
-
-/* c_lflag bits */
-#define ISIG   0000001
-#define ICANON 0000002
-#define XCASE  0000004
-#define ECHO   0000010
-#define ECHOE  0000020
-#define ECHOK  0000040
-#define ECHONL 0000100
-#define NOFLSH 0000200
-#define TOSTOP 0000400
-#define ECHOCTL        0001000
-#define ECHOPRT        0002000
-#define ECHOKE 0004000
-#define FLUSHO 0010000
-#define PENDIN 0040000
-#define IEXTEN 0100000
-#define EXTPROC        0200000
-
-
-/* tcflow() and TCXONC use these */
-#define        TCOOFF          0
-#define        TCOON           1
-#define        TCIOFF          2
-#define        TCION           3
-
-/* tcflush() and TCFLSH use these */
-#define        TCIFLUSH        0
-#define        TCOFLUSH        1
-#define        TCIOFLUSH       2
-
-/* tcsetattr uses these */
-#define        TCSANOW         0
-#define        TCSADRAIN       1
-#define        TCSAFLUSH       2
-
-#endif /* __ARCH_M68K_TERMBITS_H__ */
diff --git a/arch/m68k/include/asm/termios.h b/arch/m68k/include/asm/termios.h
deleted file mode 100644 (file)
index 0823032..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-#ifndef _M68K_TERMIOS_H
-#define _M68K_TERMIOS_H
-
-#include <asm/termbits.h>
-#include <asm/ioctls.h>
-
-struct winsize {
-       unsigned short ws_row;
-       unsigned short ws_col;
-       unsigned short ws_xpixel;
-       unsigned short ws_ypixel;
-};
-
-#define NCC 8
-struct termio {
-       unsigned short c_iflag;         /* input mode flags */
-       unsigned short c_oflag;         /* output mode flags */
-       unsigned short c_cflag;         /* control mode flags */
-       unsigned short c_lflag;         /* local mode flags */
-       unsigned char c_line;           /* line discipline */
-       unsigned char c_cc[NCC];        /* control characters */
-};
-
-#ifdef __KERNEL__
-/*     intr=^C         quit=^|         erase=del       kill=^U
-       eof=^D          vtime=\0        vmin=\1         sxtc=\0
-       start=^Q        stop=^S         susp=^Z         eol=\0
-       reprint=^R      discard=^U      werase=^W       lnext=^V
-       eol2=\0
-*/
-#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0"
-#endif
-
-/* modem lines */
-#define TIOCM_LE       0x001
-#define TIOCM_DTR      0x002
-#define TIOCM_RTS      0x004
-#define TIOCM_ST       0x008
-#define TIOCM_SR       0x010
-#define TIOCM_CTS      0x020
-#define TIOCM_CAR      0x040
-#define TIOCM_RNG      0x080
-#define TIOCM_DSR      0x100
-#define TIOCM_CD       TIOCM_CAR
-#define TIOCM_RI       TIOCM_RNG
-#define TIOCM_OUT1     0x2000
-#define TIOCM_OUT2     0x4000
-#define TIOCM_LOOP     0x8000
-
-/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
-
-#ifdef __KERNEL__
-
-/*
- * Translate a "termio" structure into a "termios". Ugh.
- */
-#define user_termio_to_kernel_termios(termios, termio) \
-({ \
-       unsigned short tmp; \
-       get_user(tmp, &(termio)->c_iflag); \
-       (termios)->c_iflag = (0xffff0000 & ((termios)->c_iflag)) | tmp; \
-       get_user(tmp, &(termio)->c_oflag); \
-       (termios)->c_oflag = (0xffff0000 & ((termios)->c_oflag)) | tmp; \
-       get_user(tmp, &(termio)->c_cflag); \
-       (termios)->c_cflag = (0xffff0000 & ((termios)->c_cflag)) | tmp; \
-       get_user(tmp, &(termio)->c_lflag); \
-       (termios)->c_lflag = (0xffff0000 & ((termios)->c_lflag)) | tmp; \
-       get_user((termios)->c_line, &(termio)->c_line); \
-       copy_from_user((termios)->c_cc, (termio)->c_cc, NCC); \
-})
-
-/*
- * Translate a "termios" structure into a "termio". Ugh.
- */
-#define kernel_termios_to_user_termio(termio, termios) \
-({ \
-       put_user((termios)->c_iflag, &(termio)->c_iflag); \
-       put_user((termios)->c_oflag, &(termio)->c_oflag); \
-       put_user((termios)->c_cflag, &(termio)->c_cflag); \
-       put_user((termios)->c_lflag, &(termio)->c_lflag); \
-       put_user((termios)->c_line,  &(termio)->c_line); \
-       copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
-})
-
-#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios2))
-#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios2))
-#define user_termios_to_kernel_termios_1(k, u) copy_from_user(k, u, sizeof(struct termios))
-#define kernel_termios_to_user_termios_1(u, k) copy_to_user(u, k, sizeof(struct termios))
-
-#endif /* __KERNEL__ */
-
-#endif /* _M68K_TERMIOS_H */
index 508afdc1d43507b5d1d3e5f0eea9d9879fde0426..0aa165405966bf73b93db896e252afab1b3ed2a8 100644 (file)
 #ifndef _ASM_M68K_UNISTD_H_
 #define _ASM_M68K_UNISTD_H_
 
-/*
- * This file contains the system call numbers.
- */
-
-#define __NR_restart_syscall     0
-#define __NR_exit                1
-#define __NR_fork                2
-#define __NR_read                3
-#define __NR_write               4
-#define __NR_open                5
-#define __NR_close               6
-#define __NR_waitpid             7
-#define __NR_creat               8
-#define __NR_link                9
-#define __NR_unlink             10
-#define __NR_execve             11
-#define __NR_chdir              12
-#define __NR_time               13
-#define __NR_mknod              14
-#define __NR_chmod              15
-#define __NR_chown              16
-/*#define __NR_break            17*/
-#define __NR_oldstat            18
-#define __NR_lseek              19
-#define __NR_getpid             20
-#define __NR_mount              21
-#define __NR_umount             22
-#define __NR_setuid             23
-#define __NR_getuid             24
-#define __NR_stime              25
-#define __NR_ptrace             26
-#define __NR_alarm              27
-#define __NR_oldfstat           28
-#define __NR_pause              29
-#define __NR_utime              30
-/*#define __NR_stty             31*/
-/*#define __NR_gtty             32*/
-#define __NR_access             33
-#define __NR_nice               34
-/*#define __NR_ftime            35*/
-#define __NR_sync               36
-#define __NR_kill               37
-#define __NR_rename             38
-#define __NR_mkdir              39
-#define __NR_rmdir              40
-#define __NR_dup                41
-#define __NR_pipe               42
-#define __NR_times              43
-/*#define __NR_prof             44*/
-#define __NR_brk                45
-#define __NR_setgid             46
-#define __NR_getgid             47
-#define __NR_signal             48
-#define __NR_geteuid            49
-#define __NR_getegid            50
-#define __NR_acct               51
-#define __NR_umount2            52
-/*#define __NR_lock             53*/
-#define __NR_ioctl              54
-#define __NR_fcntl              55
-/*#define __NR_mpx              56*/
-#define __NR_setpgid            57
-/*#define __NR_ulimit           58*/
-/*#define __NR_oldolduname      59*/
-#define __NR_umask              60
-#define __NR_chroot             61
-#define __NR_ustat              62
-#define __NR_dup2               63
-#define __NR_getppid            64
-#define __NR_getpgrp            65
-#define __NR_setsid             66
-#define __NR_sigaction          67
-#define __NR_sgetmask           68
-#define __NR_ssetmask           69
-#define __NR_setreuid           70
-#define __NR_setregid           71
-#define __NR_sigsuspend                 72
-#define __NR_sigpending                 73
-#define __NR_sethostname        74
-#define __NR_setrlimit          75
-#define __NR_getrlimit          76
-#define __NR_getrusage          77
-#define __NR_gettimeofday       78
-#define __NR_settimeofday       79
-#define __NR_getgroups          80
-#define __NR_setgroups          81
-#define __NR_select             82
-#define __NR_symlink            83
-#define __NR_oldlstat           84
-#define __NR_readlink           85
-#define __NR_uselib             86
-#define __NR_swapon             87
-#define __NR_reboot             88
-#define __NR_readdir            89
-#define __NR_mmap               90
-#define __NR_munmap             91
-#define __NR_truncate           92
-#define __NR_ftruncate          93
-#define __NR_fchmod             94
-#define __NR_fchown             95
-#define __NR_getpriority        96
-#define __NR_setpriority        97
-/*#define __NR_profil           98*/
-#define __NR_statfs             99
-#define __NR_fstatfs           100
-/*#define __NR_ioperm          101*/
-#define __NR_socketcall                102
-#define __NR_syslog            103
-#define __NR_setitimer         104
-#define __NR_getitimer         105
-#define __NR_stat              106
-#define __NR_lstat             107
-#define __NR_fstat             108
-/*#define __NR_olduname                109*/
-/*#define __NR_iopl            110*/ /* not supported */
-#define __NR_vhangup           111
-/*#define __NR_idle            112*/ /* Obsolete */
-/*#define __NR_vm86            113*/ /* not supported */
-#define __NR_wait4             114
-#define __NR_swapoff           115
-#define __NR_sysinfo           116
-#define __NR_ipc               117
-#define __NR_fsync             118
-#define __NR_sigreturn         119
-#define __NR_clone             120
-#define __NR_setdomainname     121
-#define __NR_uname             122
-#define __NR_cacheflush                123
-#define __NR_adjtimex          124
-#define __NR_mprotect          125
-#define __NR_sigprocmask       126
-#define __NR_create_module     127
-#define __NR_init_module       128
-#define __NR_delete_module     129
-#define __NR_get_kernel_syms   130
-#define __NR_quotactl          131
-#define __NR_getpgid           132
-#define __NR_fchdir            133
-#define __NR_bdflush           134
-#define __NR_sysfs             135
-#define __NR_personality       136
-/*#define __NR_afs_syscall     137*/ /* Syscall for Andrew File System */
-#define __NR_setfsuid          138
-#define __NR_setfsgid          139
-#define __NR__llseek           140
-#define __NR_getdents          141
-#define __NR__newselect                142
-#define __NR_flock             143
-#define __NR_msync             144
-#define __NR_readv             145
-#define __NR_writev            146
-#define __NR_getsid            147
-#define __NR_fdatasync         148
-#define __NR__sysctl           149
-#define __NR_mlock             150
-#define __NR_munlock           151
-#define __NR_mlockall          152
-#define __NR_munlockall                153
-#define __NR_sched_setparam            154
-#define __NR_sched_getparam            155
-#define __NR_sched_setscheduler                156
-#define __NR_sched_getscheduler                157
-#define __NR_sched_yield               158
-#define __NR_sched_get_priority_max    159
-#define __NR_sched_get_priority_min    160
-#define __NR_sched_rr_get_interval     161
-#define __NR_nanosleep         162
-#define __NR_mremap            163
-#define __NR_setresuid         164
-#define __NR_getresuid         165
-#define __NR_getpagesize       166
-#define __NR_query_module      167
-#define __NR_poll              168
-#define __NR_nfsservctl                169
-#define __NR_setresgid         170
-#define __NR_getresgid         171
-#define __NR_prctl             172
-#define __NR_rt_sigreturn      173
-#define __NR_rt_sigaction      174
-#define __NR_rt_sigprocmask    175
-#define __NR_rt_sigpending     176
-#define __NR_rt_sigtimedwait   177
-#define __NR_rt_sigqueueinfo   178
-#define __NR_rt_sigsuspend     179
-#define __NR_pread64           180
-#define __NR_pwrite64          181
-#define __NR_lchown            182
-#define __NR_getcwd            183
-#define __NR_capget            184
-#define __NR_capset            185
-#define __NR_sigaltstack       186
-#define __NR_sendfile          187
-#define __NR_getpmsg           188     /* some people actually want streams */
-#define __NR_putpmsg           189     /* some people actually want streams */
-#define __NR_vfork             190
-#define __NR_ugetrlimit                191
-#define __NR_mmap2             192
-#define __NR_truncate64                193
-#define __NR_ftruncate64       194
-#define __NR_stat64            195
-#define __NR_lstat64           196
-#define __NR_fstat64           197
-#define __NR_chown32           198
-#define __NR_getuid32          199
-#define __NR_getgid32          200
-#define __NR_geteuid32         201
-#define __NR_getegid32         202
-#define __NR_setreuid32                203
-#define __NR_setregid32                204
-#define __NR_getgroups32       205
-#define __NR_setgroups32       206
-#define __NR_fchown32          207
-#define __NR_setresuid32       208
-#define __NR_getresuid32       209
-#define __NR_setresgid32       210
-#define __NR_getresgid32       211
-#define __NR_lchown32          212
-#define __NR_setuid32          213
-#define __NR_setgid32          214
-#define __NR_setfsuid32                215
-#define __NR_setfsgid32                216
-#define __NR_pivot_root                217
-/* 218*/
-/* 219*/
-#define __NR_getdents64                220
-#define __NR_gettid            221
-#define __NR_tkill             222
-#define __NR_setxattr          223
-#define __NR_lsetxattr         224
-#define __NR_fsetxattr         225
-#define __NR_getxattr          226
-#define __NR_lgetxattr         227
-#define __NR_fgetxattr         228
-#define __NR_listxattr         229
-#define __NR_llistxattr                230
-#define __NR_flistxattr                231
-#define __NR_removexattr       232
-#define __NR_lremovexattr      233
-#define __NR_fremovexattr      234
-#define __NR_futex             235
-#define __NR_sendfile64                236
-#define __NR_mincore           237
-#define __NR_madvise           238
-#define __NR_fcntl64           239
-#define __NR_readahead         240
-#define __NR_io_setup          241
-#define __NR_io_destroy                242
-#define __NR_io_getevents      243
-#define __NR_io_submit         244
-#define __NR_io_cancel         245
-#define __NR_fadvise64         246
-#define __NR_exit_group                247
-#define __NR_lookup_dcookie    248
-#define __NR_epoll_create      249
-#define __NR_epoll_ctl         250
-#define __NR_epoll_wait                251
-#define __NR_remap_file_pages  252
-#define __NR_set_tid_address   253
-#define __NR_timer_create      254
-#define __NR_timer_settime     255
-#define __NR_timer_gettime     256
-#define __NR_timer_getoverrun  257
-#define __NR_timer_delete      258
-#define __NR_clock_settime     259
-#define __NR_clock_gettime     260
-#define __NR_clock_getres      261
-#define __NR_clock_nanosleep   262
-#define __NR_statfs64          263
-#define __NR_fstatfs64         264
-#define __NR_tgkill            265
-#define __NR_utimes            266
-#define __NR_fadvise64_64      267
-#define __NR_mbind             268
-#define __NR_get_mempolicy     269
-#define __NR_set_mempolicy     270
-#define __NR_mq_open           271
-#define __NR_mq_unlink         272
-#define __NR_mq_timedsend      273
-#define __NR_mq_timedreceive   274
-#define __NR_mq_notify         275
-#define __NR_mq_getsetattr     276
-#define __NR_waitid            277
-/*#define __NR_vserver         278*/
-#define __NR_add_key           279
-#define __NR_request_key       280
-#define __NR_keyctl            281
-#define __NR_ioprio_set                282
-#define __NR_ioprio_get                283
-#define __NR_inotify_init      284
-#define __NR_inotify_add_watch 285
-#define __NR_inotify_rm_watch  286
-#define __NR_migrate_pages     287
-#define __NR_openat            288
-#define __NR_mkdirat           289
-#define __NR_mknodat           290
-#define __NR_fchownat          291
-#define __NR_futimesat         292
-#define __NR_fstatat64         293
-#define __NR_unlinkat          294
-#define __NR_renameat          295
-#define __NR_linkat            296
-#define __NR_symlinkat         297
-#define __NR_readlinkat                298
-#define __NR_fchmodat          299
-#define __NR_faccessat         300
-#define __NR_pselect6          301
-#define __NR_ppoll             302
-#define __NR_unshare           303
-#define __NR_set_robust_list   304
-#define __NR_get_robust_list   305
-#define __NR_splice            306
-#define __NR_sync_file_range   307
-#define __NR_tee               308
-#define __NR_vmsplice          309
-#define __NR_move_pages                310
-#define __NR_sched_setaffinity 311
-#define __NR_sched_getaffinity 312
-#define __NR_kexec_load                313
-#define __NR_getcpu            314
-#define __NR_epoll_pwait       315
-#define __NR_utimensat         316
-#define __NR_signalfd          317
-#define __NR_timerfd_create    318
-#define __NR_eventfd           319
-#define __NR_fallocate         320
-#define __NR_timerfd_settime   321
-#define __NR_timerfd_gettime   322
-#define __NR_signalfd4         323
-#define __NR_eventfd2          324
-#define __NR_epoll_create1     325
-#define __NR_dup3              326
-#define __NR_pipe2             327
-#define __NR_inotify_init1     328
-#define __NR_preadv            329
-#define __NR_pwritev           330
-#define __NR_rt_tgsigqueueinfo 331
-#define __NR_perf_event_open   332
-#define __NR_get_thread_area   333
-#define __NR_set_thread_area   334
-#define __NR_atomic_cmpxchg_32 335
-#define __NR_atomic_barrier    336
-#define __NR_fanotify_init     337
-#define __NR_fanotify_mark     338
-#define __NR_prlimit64         339
-#define __NR_name_to_handle_at 340
-#define __NR_open_by_handle_at 341
-#define __NR_clock_adjtime     342
-#define __NR_syncfs            343
-#define __NR_setns             344
-#define __NR_process_vm_readv  345
-#define __NR_process_vm_writev 346
+#include <uapi/asm/unistd.h>
 
-#ifdef __KERNEL__
 
-#define NR_syscalls            347
+#define NR_syscalls            348
 
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_OLD_STAT
  */
 #define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
 
-#endif /* __KERNEL__ */
 #endif /* _ASM_M68K_UNISTD_H_ */
index baebb3da1d44160fc6f6f259886656e6f494b167..aebdbf5a4db463ca3367d43000c1261876112fc4 100644 (file)
@@ -1,3 +1,18 @@
 # UAPI Header export list
 include include/uapi/asm-generic/Kbuild.asm
 
+header-y += a.out.h
+header-y += byteorder.h
+header-y += cachectl.h
+header-y += fcntl.h
+header-y += ioctls.h
+header-y += param.h
+header-y += poll.h
+header-y += posix_types.h
+header-y += ptrace.h
+header-y += setup.h
+header-y += sigcontext.h
+header-y += signal.h
+header-y += stat.h
+header-y += swab.h
+header-y += unistd.h
diff --git a/arch/m68k/include/uapi/asm/ptrace.h b/arch/m68k/include/uapi/asm/ptrace.h
new file mode 100644 (file)
index 0000000..caf92fd
--- /dev/null
@@ -0,0 +1,79 @@
+#ifndef _UAPI_M68K_PTRACE_H
+#define _UAPI_M68K_PTRACE_H
+
+#define PT_D1     0
+#define PT_D2     1
+#define PT_D3     2
+#define PT_D4     3
+#define PT_D5     4
+#define PT_D6     5
+#define PT_D7     6
+#define PT_A0     7
+#define PT_A1     8
+#define PT_A2     9
+#define PT_A3     10
+#define PT_A4     11
+#define PT_A5     12
+#define PT_A6     13
+#define PT_D0     14
+#define PT_USP    15
+#define PT_ORIG_D0 16
+#define PT_SR     17
+#define PT_PC     18
+
+#ifndef __ASSEMBLY__
+
+/* this struct defines the way the registers are stored on the
+   stack during a system call. */
+
+struct pt_regs {
+  long     d1;
+  long     d2;
+  long     d3;
+  long     d4;
+  long     d5;
+  long     a0;
+  long     a1;
+  long     a2;
+  long     d0;
+  long     orig_d0;
+  long     stkadj;
+#ifdef CONFIG_COLDFIRE
+  unsigned format :  4; /* frame format specifier */
+  unsigned vector : 12; /* vector offset */
+  unsigned short sr;
+  unsigned long  pc;
+#else
+  unsigned short sr;
+  unsigned long  pc;
+  unsigned format :  4; /* frame format specifier */
+  unsigned vector : 12; /* vector offset */
+#endif
+};
+
+/*
+ * This is the extended stack used by signal handlers and the context
+ * switcher: it's pushed after the normal "struct pt_regs".
+ */
+struct switch_stack {
+       unsigned long  d6;
+       unsigned long  d7;
+       unsigned long  a3;
+       unsigned long  a4;
+       unsigned long  a5;
+       unsigned long  a6;
+       unsigned long  retpc;
+};
+
+/* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
+#define PTRACE_GETREGS            12
+#define PTRACE_SETREGS            13
+#define PTRACE_GETFPREGS          14
+#define PTRACE_SETFPREGS          15
+
+#define PTRACE_GET_THREAD_AREA    25
+
+#define PTRACE_SINGLEBLOCK     33      /* resume execution until next branch */
+
+#endif /* __ASSEMBLY__ */
+#endif /* _UAPI_M68K_PTRACE_H */
diff --git a/arch/m68k/include/uapi/asm/setup.h b/arch/m68k/include/uapi/asm/setup.h
new file mode 100644 (file)
index 0000000..85579bf
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+** asm/setup.h -- Definition of the Linux/m68k setup information
+**
+** Copyright 1992 by Greg Harp
+**
+** This file is subject to the terms and conditions of the GNU General Public
+** License.  See the file COPYING in the main directory of this archive
+** for more details.
+**
+** Created 09/29/92 by Greg Harp
+**
+** 5/2/94 Roman Hodek:
+**   Added bi_atari part of the machine dependent union bi_un; for now it
+**   contains just a model field to distinguish between TT and Falcon.
+** 26/7/96 Roman Zippel:
+**   Renamed to setup.h; added some useful macros to allow gcc some
+**   optimizations if possible.
+** 5/10/96 Geert Uytterhoeven:
+**   Redesign of the boot information structure; moved boot information
+**   structure to bootinfo.h
+*/
+
+#ifndef _UAPI_M68K_SETUP_H
+#define _UAPI_M68K_SETUP_H
+
+
+
+    /*
+     *  Linux/m68k Architectures
+     */
+
+#define MACH_AMIGA    1
+#define MACH_ATARI    2
+#define MACH_MAC      3
+#define MACH_APOLLO   4
+#define MACH_SUN3     5
+#define MACH_MVME147  6
+#define MACH_MVME16x  7
+#define MACH_BVME6000 8
+#define MACH_HP300    9
+#define MACH_Q40     10
+#define MACH_SUN3X   11
+#define MACH_M54XX   12
+
+#define COMMAND_LINE_SIZE 256
+
+
+
+    /*
+     *  CPU, FPU and MMU types
+     *
+     *  Note: we may rely on the following equalities:
+     *
+     *      CPU_68020 == MMU_68851
+     *      CPU_68030 == MMU_68030
+     *      CPU_68040 == FPU_68040 == MMU_68040
+     *      CPU_68060 == FPU_68060 == MMU_68060
+     */
+
+#define CPUB_68020     0
+#define CPUB_68030     1
+#define CPUB_68040     2
+#define CPUB_68060     3
+#define CPUB_COLDFIRE  4
+
+#define CPU_68020      (1<<CPUB_68020)
+#define CPU_68030      (1<<CPUB_68030)
+#define CPU_68040      (1<<CPUB_68040)
+#define CPU_68060      (1<<CPUB_68060)
+#define CPU_COLDFIRE   (1<<CPUB_COLDFIRE)
+
+#define FPUB_68881     0
+#define FPUB_68882     1
+#define FPUB_68040     2                       /* Internal FPU */
+#define FPUB_68060     3                       /* Internal FPU */
+#define FPUB_SUNFPA    4                       /* Sun-3 FPA */
+#define FPUB_COLDFIRE  5                       /* ColdFire FPU */
+
+#define FPU_68881      (1<<FPUB_68881)
+#define FPU_68882      (1<<FPUB_68882)
+#define FPU_68040      (1<<FPUB_68040)
+#define FPU_68060      (1<<FPUB_68060)
+#define FPU_SUNFPA     (1<<FPUB_SUNFPA)
+#define FPU_COLDFIRE   (1<<FPUB_COLDFIRE)
+
+#define MMUB_68851     0
+#define MMUB_68030     1                       /* Internal MMU */
+#define MMUB_68040     2                       /* Internal MMU */
+#define MMUB_68060     3                       /* Internal MMU */
+#define MMUB_APOLLO    4                       /* Custom Apollo */
+#define MMUB_SUN3      5                       /* Custom Sun-3 */
+#define MMUB_COLDFIRE  6                       /* Internal MMU */
+
+#define MMU_68851      (1<<MMUB_68851)
+#define MMU_68030      (1<<MMUB_68030)
+#define MMU_68040      (1<<MMUB_68040)
+#define MMU_68060      (1<<MMUB_68060)
+#define MMU_SUN3       (1<<MMUB_SUN3)
+#define MMU_APOLLO     (1<<MMUB_APOLLO)
+#define MMU_COLDFIRE   (1<<MMUB_COLDFIRE)
+
+
+#endif /* _UAPI_M68K_SETUP_H */
diff --git a/arch/m68k/include/uapi/asm/signal.h b/arch/m68k/include/uapi/asm/signal.h
new file mode 100644 (file)
index 0000000..2b450f3
--- /dev/null
@@ -0,0 +1,118 @@
+#ifndef _UAPI_M68K_SIGNAL_H
+#define _UAPI_M68K_SIGNAL_H
+
+#include <linux/types.h>
+
+/* Avoid too many header ordering problems.  */
+struct siginfo;
+
+#ifndef __KERNEL__
+/* Here we must cater to libcs that poke about in kernel headers.  */
+
+#define NSIG           32
+typedef unsigned long sigset_t;
+
+#endif /* __KERNEL__ */
+
+#define SIGHUP          1
+#define SIGINT          2
+#define SIGQUIT                 3
+#define SIGILL          4
+#define SIGTRAP                 5
+#define SIGABRT                 6
+#define SIGIOT          6
+#define SIGBUS          7
+#define SIGFPE          8
+#define SIGKILL                 9
+#define SIGUSR1                10
+#define SIGSEGV                11
+#define SIGUSR2                12
+#define SIGPIPE                13
+#define SIGALRM                14
+#define SIGTERM                15
+#define SIGSTKFLT      16
+#define SIGCHLD                17
+#define SIGCONT                18
+#define SIGSTOP                19
+#define SIGTSTP                20
+#define SIGTTIN                21
+#define SIGTTOU                22
+#define SIGURG         23
+#define SIGXCPU                24
+#define SIGXFSZ                25
+#define SIGVTALRM      26
+#define SIGPROF                27
+#define SIGWINCH       28
+#define SIGIO          29
+#define SIGPOLL                SIGIO
+/*
+#define SIGLOST                29
+*/
+#define SIGPWR         30
+#define SIGSYS         31
+#define        SIGUNUSED       31
+
+/* These should not be considered constants from userland.  */
+#define SIGRTMIN       32
+#define SIGRTMAX       _NSIG
+
+/*
+ * SA_FLAGS values:
+ *
+ * SA_ONSTACK indicates that a registered stack_t will be used.
+ * SA_RESTART flag to get restarting signals (which were the default long ago)
+ * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
+ * SA_RESETHAND clears the handler when the signal is delivered.
+ * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
+ * SA_NODEFER prevents the current signal from being masked in the handler.
+ *
+ * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
+ * Unix names RESETHAND and NODEFER respectively.
+ */
+#define SA_NOCLDSTOP   0x00000001
+#define SA_NOCLDWAIT   0x00000002
+#define SA_SIGINFO     0x00000004
+#define SA_ONSTACK     0x08000000
+#define SA_RESTART     0x10000000
+#define SA_NODEFER     0x40000000
+#define SA_RESETHAND   0x80000000
+
+#define SA_NOMASK      SA_NODEFER
+#define SA_ONESHOT     SA_RESETHAND
+
+/*
+ * sigaltstack controls
+ */
+#define SS_ONSTACK     1
+#define SS_DISABLE     2
+
+#define MINSIGSTKSZ    2048
+#define SIGSTKSZ       8192
+
+#include <asm-generic/signal-defs.h>
+
+#ifndef __KERNEL__
+/* Here we must cater to libcs that poke about in kernel headers.  */
+
+struct sigaction {
+       union {
+         __sighandler_t _sa_handler;
+         void (*_sa_sigaction)(int, struct siginfo *, void *);
+       } _u;
+       sigset_t sa_mask;
+       unsigned long sa_flags;
+       void (*sa_restorer)(void);
+};
+
+#define sa_handler     _u._sa_handler
+#define sa_sigaction   _u._sa_sigaction
+
+#endif /* __KERNEL__ */
+
+typedef struct sigaltstack {
+       void __user *ss_sp;
+       int ss_flags;
+       size_t ss_size;
+} stack_t;
+
+#endif /* _UAPI_M68K_SIGNAL_H */
diff --git a/arch/m68k/include/uapi/asm/termios.h b/arch/m68k/include/uapi/asm/termios.h
new file mode 100644 (file)
index 0000000..ce2142c
--- /dev/null
@@ -0,0 +1,44 @@
+#ifndef _UAPI_M68K_TERMIOS_H
+#define _UAPI_M68K_TERMIOS_H
+
+#include <asm/termbits.h>
+#include <asm/ioctls.h>
+
+struct winsize {
+       unsigned short ws_row;
+       unsigned short ws_col;
+       unsigned short ws_xpixel;
+       unsigned short ws_ypixel;
+};
+
+#define NCC 8
+struct termio {
+       unsigned short c_iflag;         /* input mode flags */
+       unsigned short c_oflag;         /* output mode flags */
+       unsigned short c_cflag;         /* control mode flags */
+       unsigned short c_lflag;         /* local mode flags */
+       unsigned char c_line;           /* line discipline */
+       unsigned char c_cc[NCC];        /* control characters */
+};
+
+
+/* modem lines */
+#define TIOCM_LE       0x001
+#define TIOCM_DTR      0x002
+#define TIOCM_RTS      0x004
+#define TIOCM_ST       0x008
+#define TIOCM_SR       0x010
+#define TIOCM_CTS      0x020
+#define TIOCM_CAR      0x040
+#define TIOCM_RNG      0x080
+#define TIOCM_DSR      0x100
+#define TIOCM_CD       TIOCM_CAR
+#define TIOCM_RI       TIOCM_RNG
+#define TIOCM_OUT1     0x2000
+#define TIOCM_OUT2     0x4000
+#define TIOCM_LOOP     0x8000
+
+/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
+
+
+#endif /* _UAPI_M68K_TERMIOS_H */
diff --git a/arch/m68k/include/uapi/asm/unistd.h b/arch/m68k/include/uapi/asm/unistd.h
new file mode 100644 (file)
index 0000000..b94bfbf
--- /dev/null
@@ -0,0 +1,357 @@
+#ifndef _UAPI_ASM_M68K_UNISTD_H_
+#define _UAPI_ASM_M68K_UNISTD_H_
+
+/*
+ * This file contains the system call numbers.
+ */
+
+#define __NR_restart_syscall     0
+#define __NR_exit                1
+#define __NR_fork                2
+#define __NR_read                3
+#define __NR_write               4
+#define __NR_open                5
+#define __NR_close               6
+#define __NR_waitpid             7
+#define __NR_creat               8
+#define __NR_link                9
+#define __NR_unlink             10
+#define __NR_execve             11
+#define __NR_chdir              12
+#define __NR_time               13
+#define __NR_mknod              14
+#define __NR_chmod              15
+#define __NR_chown              16
+/*#define __NR_break            17*/
+#define __NR_oldstat            18
+#define __NR_lseek              19
+#define __NR_getpid             20
+#define __NR_mount              21
+#define __NR_umount             22
+#define __NR_setuid             23
+#define __NR_getuid             24
+#define __NR_stime              25
+#define __NR_ptrace             26
+#define __NR_alarm              27
+#define __NR_oldfstat           28
+#define __NR_pause              29
+#define __NR_utime              30
+/*#define __NR_stty             31*/
+/*#define __NR_gtty             32*/
+#define __NR_access             33
+#define __NR_nice               34
+/*#define __NR_ftime            35*/
+#define __NR_sync               36
+#define __NR_kill               37
+#define __NR_rename             38
+#define __NR_mkdir              39
+#define __NR_rmdir              40
+#define __NR_dup                41
+#define __NR_pipe               42
+#define __NR_times              43
+/*#define __NR_prof             44*/
+#define __NR_brk                45
+#define __NR_setgid             46
+#define __NR_getgid             47
+#define __NR_signal             48
+#define __NR_geteuid            49
+#define __NR_getegid            50
+#define __NR_acct               51
+#define __NR_umount2            52
+/*#define __NR_lock             53*/
+#define __NR_ioctl              54
+#define __NR_fcntl              55
+/*#define __NR_mpx              56*/
+#define __NR_setpgid            57
+/*#define __NR_ulimit           58*/
+/*#define __NR_oldolduname      59*/
+#define __NR_umask              60
+#define __NR_chroot             61
+#define __NR_ustat              62
+#define __NR_dup2               63
+#define __NR_getppid            64
+#define __NR_getpgrp            65
+#define __NR_setsid             66
+#define __NR_sigaction          67
+#define __NR_sgetmask           68
+#define __NR_ssetmask           69
+#define __NR_setreuid           70
+#define __NR_setregid           71
+#define __NR_sigsuspend                 72
+#define __NR_sigpending                 73
+#define __NR_sethostname        74
+#define __NR_setrlimit          75
+#define __NR_getrlimit          76
+#define __NR_getrusage          77
+#define __NR_gettimeofday       78
+#define __NR_settimeofday       79
+#define __NR_getgroups          80
+#define __NR_setgroups          81
+#define __NR_select             82
+#define __NR_symlink            83
+#define __NR_oldlstat           84
+#define __NR_readlink           85
+#define __NR_uselib             86
+#define __NR_swapon             87
+#define __NR_reboot             88
+#define __NR_readdir            89
+#define __NR_mmap               90
+#define __NR_munmap             91
+#define __NR_truncate           92
+#define __NR_ftruncate          93
+#define __NR_fchmod             94
+#define __NR_fchown             95
+#define __NR_getpriority        96
+#define __NR_setpriority        97
+/*#define __NR_profil           98*/
+#define __NR_statfs             99
+#define __NR_fstatfs           100
+/*#define __NR_ioperm          101*/
+#define __NR_socketcall                102
+#define __NR_syslog            103
+#define __NR_setitimer         104
+#define __NR_getitimer         105
+#define __NR_stat              106
+#define __NR_lstat             107
+#define __NR_fstat             108
+/*#define __NR_olduname                109*/
+/*#define __NR_iopl            110*/ /* not supported */
+#define __NR_vhangup           111
+/*#define __NR_idle            112*/ /* Obsolete */
+/*#define __NR_vm86            113*/ /* not supported */
+#define __NR_wait4             114
+#define __NR_swapoff           115
+#define __NR_sysinfo           116
+#define __NR_ipc               117
+#define __NR_fsync             118
+#define __NR_sigreturn         119
+#define __NR_clone             120
+#define __NR_setdomainname     121
+#define __NR_uname             122
+#define __NR_cacheflush                123
+#define __NR_adjtimex          124
+#define __NR_mprotect          125
+#define __NR_sigprocmask       126
+#define __NR_create_module     127
+#define __NR_init_module       128
+#define __NR_delete_module     129
+#define __NR_get_kernel_syms   130
+#define __NR_quotactl          131
+#define __NR_getpgid           132
+#define __NR_fchdir            133
+#define __NR_bdflush           134
+#define __NR_sysfs             135
+#define __NR_personality       136
+/*#define __NR_afs_syscall     137*/ /* Syscall for Andrew File System */
+#define __NR_setfsuid          138
+#define __NR_setfsgid          139
+#define __NR__llseek           140
+#define __NR_getdents          141
+#define __NR__newselect                142
+#define __NR_flock             143
+#define __NR_msync             144
+#define __NR_readv             145
+#define __NR_writev            146
+#define __NR_getsid            147
+#define __NR_fdatasync         148
+#define __NR__sysctl           149
+#define __NR_mlock             150
+#define __NR_munlock           151
+#define __NR_mlockall          152
+#define __NR_munlockall                153
+#define __NR_sched_setparam            154
+#define __NR_sched_getparam            155
+#define __NR_sched_setscheduler                156
+#define __NR_sched_getscheduler                157
+#define __NR_sched_yield               158
+#define __NR_sched_get_priority_max    159
+#define __NR_sched_get_priority_min    160
+#define __NR_sched_rr_get_interval     161
+#define __NR_nanosleep         162
+#define __NR_mremap            163
+#define __NR_setresuid         164
+#define __NR_getresuid         165
+#define __NR_getpagesize       166
+#define __NR_query_module      167
+#define __NR_poll              168
+#define __NR_nfsservctl                169
+#define __NR_setresgid         170
+#define __NR_getresgid         171
+#define __NR_prctl             172
+#define __NR_rt_sigreturn      173
+#define __NR_rt_sigaction      174
+#define __NR_rt_sigprocmask    175
+#define __NR_rt_sigpending     176
+#define __NR_rt_sigtimedwait   177
+#define __NR_rt_sigqueueinfo   178
+#define __NR_rt_sigsuspend     179
+#define __NR_pread64           180
+#define __NR_pwrite64          181
+#define __NR_lchown            182
+#define __NR_getcwd            183
+#define __NR_capget            184
+#define __NR_capset            185
+#define __NR_sigaltstack       186
+#define __NR_sendfile          187
+#define __NR_getpmsg           188     /* some people actually want streams */
+#define __NR_putpmsg           189     /* some people actually want streams */
+#define __NR_vfork             190
+#define __NR_ugetrlimit                191
+#define __NR_mmap2             192
+#define __NR_truncate64                193
+#define __NR_ftruncate64       194
+#define __NR_stat64            195
+#define __NR_lstat64           196
+#define __NR_fstat64           197
+#define __NR_chown32           198
+#define __NR_getuid32          199
+#define __NR_getgid32          200
+#define __NR_geteuid32         201
+#define __NR_getegid32         202
+#define __NR_setreuid32                203
+#define __NR_setregid32                204
+#define __NR_getgroups32       205
+#define __NR_setgroups32       206
+#define __NR_fchown32          207
+#define __NR_setresuid32       208
+#define __NR_getresuid32       209
+#define __NR_setresgid32       210
+#define __NR_getresgid32       211
+#define __NR_lchown32          212
+#define __NR_setuid32          213
+#define __NR_setgid32          214
+#define __NR_setfsuid32                215
+#define __NR_setfsgid32                216
+#define __NR_pivot_root                217
+/* 218*/
+/* 219*/
+#define __NR_getdents64                220
+#define __NR_gettid            221
+#define __NR_tkill             222
+#define __NR_setxattr          223
+#define __NR_lsetxattr         224
+#define __NR_fsetxattr         225
+#define __NR_getxattr          226
+#define __NR_lgetxattr         227
+#define __NR_fgetxattr         228
+#define __NR_listxattr         229
+#define __NR_llistxattr                230
+#define __NR_flistxattr                231
+#define __NR_removexattr       232
+#define __NR_lremovexattr      233
+#define __NR_fremovexattr      234
+#define __NR_futex             235
+#define __NR_sendfile64                236
+#define __NR_mincore           237
+#define __NR_madvise           238
+#define __NR_fcntl64           239
+#define __NR_readahead         240
+#define __NR_io_setup          241
+#define __NR_io_destroy                242
+#define __NR_io_getevents      243
+#define __NR_io_submit         244
+#define __NR_io_cancel         245
+#define __NR_fadvise64         246
+#define __NR_exit_group                247
+#define __NR_lookup_dcookie    248
+#define __NR_epoll_create      249
+#define __NR_epoll_ctl         250
+#define __NR_epoll_wait                251
+#define __NR_remap_file_pages  252
+#define __NR_set_tid_address   253
+#define __NR_timer_create      254
+#define __NR_timer_settime     255
+#define __NR_timer_gettime     256
+#define __NR_timer_getoverrun  257
+#define __NR_timer_delete      258
+#define __NR_clock_settime     259
+#define __NR_clock_gettime     260
+#define __NR_clock_getres      261
+#define __NR_clock_nanosleep   262
+#define __NR_statfs64          263
+#define __NR_fstatfs64         264
+#define __NR_tgkill            265
+#define __NR_utimes            266
+#define __NR_fadvise64_64      267
+#define __NR_mbind             268
+#define __NR_get_mempolicy     269
+#define __NR_set_mempolicy     270
+#define __NR_mq_open           271
+#define __NR_mq_unlink         272
+#define __NR_mq_timedsend      273
+#define __NR_mq_timedreceive   274
+#define __NR_mq_notify         275
+#define __NR_mq_getsetattr     276
+#define __NR_waitid            277
+/*#define __NR_vserver         278*/
+#define __NR_add_key           279
+#define __NR_request_key       280
+#define __NR_keyctl            281
+#define __NR_ioprio_set                282
+#define __NR_ioprio_get                283
+#define __NR_inotify_init      284
+#define __NR_inotify_add_watch 285
+#define __NR_inotify_rm_watch  286
+#define __NR_migrate_pages     287
+#define __NR_openat            288
+#define __NR_mkdirat           289
+#define __NR_mknodat           290
+#define __NR_fchownat          291
+#define __NR_futimesat         292
+#define __NR_fstatat64         293
+#define __NR_unlinkat          294
+#define __NR_renameat          295
+#define __NR_linkat            296
+#define __NR_symlinkat         297
+#define __NR_readlinkat                298
+#define __NR_fchmodat          299
+#define __NR_faccessat         300
+#define __NR_pselect6          301
+#define __NR_ppoll             302
+#define __NR_unshare           303
+#define __NR_set_robust_list   304
+#define __NR_get_robust_list   305
+#define __NR_splice            306
+#define __NR_sync_file_range   307
+#define __NR_tee               308
+#define __NR_vmsplice          309
+#define __NR_move_pages                310
+#define __NR_sched_setaffinity 311
+#define __NR_sched_getaffinity 312
+#define __NR_kexec_load                313
+#define __NR_getcpu            314
+#define __NR_epoll_pwait       315
+#define __NR_utimensat         316
+#define __NR_signalfd          317
+#define __NR_timerfd_create    318
+#define __NR_eventfd           319
+#define __NR_fallocate         320
+#define __NR_timerfd_settime   321
+#define __NR_timerfd_gettime   322
+#define __NR_signalfd4         323
+#define __NR_eventfd2          324
+#define __NR_epoll_create1     325
+#define __NR_dup3              326
+#define __NR_pipe2             327
+#define __NR_inotify_init1     328
+#define __NR_preadv            329
+#define __NR_pwritev           330
+#define __NR_rt_tgsigqueueinfo 331
+#define __NR_perf_event_open   332
+#define __NR_get_thread_area   333
+#define __NR_set_thread_area   334
+#define __NR_atomic_cmpxchg_32 335
+#define __NR_atomic_barrier    336
+#define __NR_fanotify_init     337
+#define __NR_fanotify_mark     338
+#define __NR_prlimit64         339
+#define __NR_name_to_handle_at 340
+#define __NR_open_by_handle_at 341
+#define __NR_clock_adjtime     342
+#define __NR_syncfs            343
+#define __NR_setns             344
+#define __NR_process_vm_readv  345
+#define __NR_process_vm_writev 346
+#define __NR_kcmp              347
+
+#endif /* _UAPI_ASM_M68K_UNISTD_H_ */
index ce827b376110a6a815b4ccece0a066e5ad66cc59..4fc2e29b771b51eb2e2189a4c050c5e05510bc2b 100644 (file)
@@ -367,4 +367,5 @@ ENTRY(sys_call_table)
        .long sys_setns
        .long sys_process_vm_readv      /* 345 */
        .long sys_process_vm_writev
+       .long sys_kcmp
 
diff --git a/arch/m68k/platform/68000/Makefile b/arch/m68k/platform/68000/Makefile
new file mode 100644 (file)
index 0000000..1eab70c
--- /dev/null
@@ -0,0 +1,18 @@
+##################################################
+#
+# Makefile for 68000 core based cpus
+#
+# 2012.10.21, Luis Alves <ljalvs@gmail.com>
+#             Merged all 68000 based cpu's config
+#             files into a single directory.
+#
+
+# 68328, 68EZ328, 68VZ328
+
+obj-y                  += entry.o ints.o timers.o
+obj-$(CONFIG_M68328)   += m68328.o
+obj-$(CONFIG_M68EZ328) += m68EZ328.o
+obj-$(CONFIG_M68VZ328) += m68VZ328.o
+obj-$(CONFIG_ROM)      += romvec.o
+
+extra-y                := head.o
diff --git a/arch/m68k/platform/68000/head.S b/arch/m68k/platform/68000/head.S
new file mode 100644 (file)
index 0000000..536ef96
--- /dev/null
@@ -0,0 +1,240 @@
+/*
+ * head.S - Common startup code for 68000 core based CPU's
+ *
+ * 2012.10.21, Luis Alves <ljalvs@gmail.com>, Single head.S file for all
+ *             68000 core based CPU's. Based on the sources from:
+ *             Coldfire by Greg Ungerer <gerg@snapgear.com>
+ *             68328 by D. Jeff Dionne <jeff@ryeham.ee.ryerson.ca>,
+ *                      Kenneth Albanowski <kjahds@kjahds.com>,
+ *                      The Silver Hammer Group, Ltd.
+ *
+ */
+
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <asm/asm-offsets.h>
+#include <asm/thread_info.h>
+
+
+/*****************************************************************************
+ * UCSIMM and UCDIMM use CONFIG_MEMORY_RESERVE to reserve some RAM
+ *****************************************************************************/
+#ifdef CONFIG_MEMORY_RESERVE
+#define RAMEND (CONFIG_RAMBASE+CONFIG_RAMSIZE)-(CONFIG_MEMORY_RESERVE*0x100000)
+#else
+#define RAMEND (CONFIG_RAMBASE+CONFIG_RAMSIZE)
+#endif
+/*****************************************************************************/
+
+.global _start
+.global _rambase
+.global _ramvec
+.global _ramstart
+.global _ramend
+
+#if defined(CONFIG_PILOT) || defined(CONFIG_INIT_LCD)
+.global bootlogo_bits
+#endif
+
+/* Defining DEBUG_HEAD_CODE, serial port in 68x328 is inited */
+/* #define DEBUG_HEAD_CODE */
+#undef DEBUG_HEAD_CODE
+
+.data
+
+/*****************************************************************************
+ * RAM setup pointers. Used by the kernel to determine RAM location and size.
+ *****************************************************************************/
+
+_rambase:
+       .long   0
+_ramvec:
+       .long   0
+_ramstart:
+       .long   0
+_ramend:
+       .long   0
+
+__HEAD
+
+/*****************************************************************************
+ * Entry point, where all begins!
+ *****************************************************************************/
+
+_start:
+
+/* Pilot need this specific signature at the start of ROM */
+#ifdef CONFIG_PILOT
+       .byte   0x4e, 0xfa, 0x00, 0x0a          /* bra opcode (jmp 10 bytes) */
+       .byte   'b', 'o', 'o', 't'
+       .word   10000
+       nop
+       moveq   #0, %d0
+       movew   %d0, 0xfffff618                 /* Watchdog off */
+       movel   #0x00011f07, 0xfffff114         /* CS A1 Mask */
+#endif /* CONFIG_PILOT */
+
+       movew   #0x2700, %sr                    /* disable all interrupts */
+
+/*****************************************************************************
+ * Setup PLL and wait for it to settle (in 68x328 cpu's).
+ * Also, if enabled, init serial port.
+ *****************************************************************************/
+#if defined(CONFIG_M68328) || \
+    defined(CONFIG_M68EZ328) || \
+    defined(CONFIG_M68VZ328)
+
+/* Serial port setup. Should only be needed if debugging this startup code. */
+#ifdef DEBUG_HEAD_CODE
+       movew   #0x0800, 0xfffff906             /* Ignore CTS */
+       movew   #0x010b, 0xfffff902             /* BAUD to 9600 */
+       movew   #0xe100, 0xfffff900             /* enable */
+#endif /* DEBUG_HEAD */
+
+#ifdef CONFIG_PILOT
+       movew   #0x2410, 0xfffff200             /* PLLCR */
+#else
+       movew   #0x2400, 0xfffff200             /* PLLCR */
+#endif
+       movew   #0x0123, 0xfffff202             /* PLLFSR */
+       moveq   #0, %d0
+       movew   #16384, %d0                     /* PLL settle wait loop */
+_pll_settle:
+       subw    #1, %d0
+       bne     _pll_settle
+#endif /* CONFIG_M68x328 */
+
+
+/*****************************************************************************
+ * If running kernel from ROM some specific initialization has to be done.
+ * (Assuming that everything is already init'ed when running from RAM)
+ *****************************************************************************/
+#ifdef CONFIG_ROMKERNEL
+
+/*****************************************************************************
+ * Init chip registers (uCsimm specific)
+ *****************************************************************************/
+#ifdef CONFIG_UCSIMM
+       moveb   #0x00, 0xfffffb0b       /* Watchdog off */
+       moveb   #0x10, 0xfffff000       /* SCR */
+       moveb   #0x00, 0xfffff40b       /* enable chip select */
+       moveb   #0x00, 0xfffff423       /* enable /DWE */
+       moveb   #0x08, 0xfffffd0d       /* disable hardmap */
+       moveb   #0x07, 0xfffffd0e       /* level 7 interrupt clear */
+       movew   #0x8600, 0xfffff100     /* FLASH at 0x10c00000 */
+       movew   #0x018b, 0xfffff110     /* 2Meg, enable, 0ws */
+       movew   #0x8f00, 0xfffffc00     /* DRAM configuration */
+       movew   #0x9667, 0xfffffc02     /* DRAM control */
+       movew   #0x0000, 0xfffff106     /* DRAM at 0x00000000 */
+       movew   #0x068f, 0xfffff116     /* 8Meg, enable, 0ws */
+       moveb   #0x40, 0xfffff300       /* IVR */
+       movel   #0x007FFFFF, %d0        /* IMR */
+       movel   %d0, 0xfffff304
+       moveb   0xfffff42b, %d0
+       andb    #0xe0, %d0
+       moveb   %d0, 0xfffff42b
+#endif
+
+/*****************************************************************************
+ * Init LCD controller.
+ * (Assuming that LCD controller is already init'ed when running from RAM)
+ *****************************************************************************/
+#ifdef CONFIG_INIT_LCD
+#ifdef CONFIG_PILOT
+       moveb   #0, 0xfffffA27                  /* LCKCON */
+       movel   #_start, 0xfffffA00             /* LSSA */
+       moveb   #0xa, 0xfffffA05                /* LVPW */
+       movew   #0x9f, 0xFFFFFa08               /* LXMAX */
+       movew   #0x9f, 0xFFFFFa0a               /* LYMAX */
+       moveb   #9, 0xfffffa29                  /* LBAR */
+       moveb   #0, 0xfffffa25                  /* LPXCD */
+       moveb   #0x04, 0xFFFFFa20               /* LPICF */
+       moveb   #0x58, 0xfffffA27               /* LCKCON */
+       moveb   #0x85, 0xfffff429               /* PFDATA */
+       moveb   #0xd8, 0xfffffA27               /* LCKCON */
+       moveb   #0xc5, 0xfffff429               /* PFDATA */
+       moveb   #0xd5, 0xfffff429               /* PFDATA */
+       movel   #bootlogo_bits, 0xFFFFFA00      /* LSSA */
+       moveb   #10, 0xFFFFFA05                 /* LVPW */
+       movew   #160, 0xFFFFFA08                /* LXMAX */
+       movew   #160, 0xFFFFFA0A                /* LYMAX */
+#else /* CONFIG_PILOT */
+       movel   #bootlogo_bits, 0xfffffA00      /* LSSA */
+       moveb   #0x28, 0xfffffA05               /* LVPW */
+       movew   #0x280, 0xFFFFFa08              /* LXMAX */
+       movew   #0x1df, 0xFFFFFa0a              /* LYMAX */
+       moveb   #0, 0xfffffa29                  /* LBAR */
+       moveb   #0, 0xfffffa25                  /* LPXCD */
+       moveb   #0x08, 0xFFFFFa20               /* LPICF */
+       moveb   #0x01, 0xFFFFFA21               /* -ve pol */
+       moveb   #0x81, 0xfffffA27               /* LCKCON */
+       movew   #0xff00, 0xfffff412             /* LCD pins */
+#endif /* CONFIG_PILOT */
+#endif /* CONFIG_INIT_LCD */
+
+/*****************************************************************************
+ * Kernel is running from FLASH/ROM (XIP)
+ * Copy init text & data to RAM
+ *****************************************************************************/
+       moveal  #_etext, %a0
+       moveal  #_sdata, %a1
+       moveal  #__bss_start, %a2
+_copy_initmem:
+       movel   %a0@+, %a1@+
+       cmpal   %a1, %a2
+       bhi     _copy_initmem
+#endif /* CONFIG_ROMKERNEL */
+
+/*****************************************************************************
+ * Setup basic memory information for kernel
+ *****************************************************************************/
+       movel   #CONFIG_VECTORBASE,_ramvec      /* set vector base location */
+       movel   #CONFIG_RAMBASE,_rambase        /* set the base of RAM */
+       movel   #RAMEND, _ramend                /* set end ram addr */
+       lea     __bss_stop,%a1
+       movel   %a1,_ramstart
+
+/*****************************************************************************
+ * If the kernel is in RAM, move romfs to right above bss and
+ * adjust _ramstart to where romfs ends.
+ *
+ * (Do this only if CONFIG_MTD_UCLINUX is true)
+ *****************************************************************************/
+
+#if defined(CONFIG_ROMFS_FS) && defined(CONFIG_RAMKERNEL) && \
+    defined(CONFIG_MTD_UCLINUX)
+       lea     __bss_start, %a0                /* get start of bss */
+       lea     __bss_stop, %a1                 /* set up destination  */
+       movel   %a0, %a2                        /* copy of bss start */
+
+       movel   8(%a0), %d0                     /* get size of ROMFS */
+       addql   #8, %d0                         /* allow for rounding */
+       andl    #0xfffffffc, %d0                /* whole words */
+
+       addl    %d0, %a0                        /* copy from end */
+       addl    %d0, %a1                        /* copy from end */
+       movel   %a1, _ramstart                  /* set start of ram */
+_copy_romfs:
+       movel   -(%a0), -(%a1)                  /* copy dword */
+       cmpl    %a0, %a2                        /* check if at end */
+       bne     _copy_romfs
+#endif /* CONFIG_ROMFS_FS && CONFIG_RAMKERNEL && CONFIG_MTD_UCLINUX */
+
+/*****************************************************************************
+ * Clear bss region
+ *****************************************************************************/
+       lea     __bss_start, %a0                /* get start of bss */
+       lea     __bss_stop, %a1                 /* get end of bss */
+_clear_bss:
+       movel   #0, (%a0)+                      /* clear each word */
+       cmpl    %a0, %a1                        /* check if at end */
+       bne     _clear_bss
+
+/*****************************************************************************
+ * Load the current task pointer and stack.
+ *****************************************************************************/
+       lea     init_thread_union,%a0
+       lea     THREAD_SIZE(%a0),%sp
+       jsr     start_kernel                    /* start Linux kernel */
+_exit:
+       jmp     _exit                           /* should never get here */
similarity index 98%
rename from arch/m68k/platform/68328/ints.c
rename to arch/m68k/platform/68000/ints.c
index b3810febb3e32562457080eee6d1c10050113756..cda49b12d7be9ce40520bcd55544351cf9a81d0e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/arch/m68knommu/platform/68328/ints.c
+ * ints.c - Generic interrupt controller support
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file COPYING in the main directory of this archive
similarity index 97%
rename from arch/m68k/platform/68328/config.c
rename to arch/m68k/platform/68000/m68328.c
index 8c20e891e9811a6c12880ce2c57a71eb5eddee7d..a86eb66835aaaf11b7125960987a44ea9c84941d 100644 (file)
@@ -1,7 +1,7 @@
 /***************************************************************************/
 
 /*
- *  linux/arch/m68knommu/platform/68328/config.c
+ *  m68328.c - 68328 specific config
  *
  *  Copyright (C) 1993 Hamish Macdonald
  *  Copyright (C) 1999 D. Jeff Dionne
similarity index 97%
rename from arch/m68k/platform/68EZ328/config.c
rename to arch/m68k/platform/68000/m68EZ328.c
index 4f158d551f02c43595aaa75bef572a7e717edeff..a6eb72d750084f9a19dae6a6d43a80724a8a9d7f 100644 (file)
@@ -1,7 +1,7 @@
 /***************************************************************************/
 
 /*
- *  linux/arch/m68knommu/platform/68EZ328/config.c
+ *  m68EZ328.c - 68EZ328 specific config
  *
  *  Copyright (C) 1993 Hamish Macdonald
  *  Copyright (C) 1999 D. Jeff Dionne
similarity index 98%
rename from arch/m68k/platform/68VZ328/config.c
rename to arch/m68k/platform/68000/m68VZ328.c
index 2ed8dc305e425fe5565609fa5161a01394cdf7c3..eb6964fbec09a7f703702b2f8219d5c27f85e564 100644 (file)
@@ -1,7 +1,7 @@
 /***************************************************************************/
 
 /*
- *  linux/arch/m68knommu/platform/68VZ328/config.c
+ *  m68VZ328.c - 68VZ328 specific config
  *
  *  Copyright (C) 1993 Hamish Macdonald
  *  Copyright (C) 1999 D. Jeff Dionne
@@ -28,7 +28,7 @@
 #include <asm/bootstd.h>
 
 #ifdef CONFIG_INIT_LCD
-#include "bootlogo.h"
+#include "bootlogo-vz.h"
 #endif
 
 /***************************************************************************/
similarity index 94%
rename from arch/m68k/platform/68328/romvec.S
rename to arch/m68k/platform/68000/romvec.S
index 31084466eae8e925755510ca588bdaecc35c9174..15c70cd6453fa2a995334e4b45d21fe62c314b66 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/arch/m68knommu/platform/68328/romvec.S
+ * romvec.S - Vector table for 68000 cpus
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file COPYING in the main directory of this archive
similarity index 98%
rename from arch/m68k/platform/68328/timers.c
rename to arch/m68k/platform/68000/timers.c
index f4dc9b29560940485c28208bbcba493d0271202a..ec30acbfe6db0507a74e2495db5ea24b31ca0e8d 100644 (file)
@@ -1,7 +1,7 @@
 /***************************************************************************/
 
 /*
- *  linux/arch/m68knommu/platform/68328/timers.c
+ *  timers.c - Generic hardware timer support.
  *
  *  Copyright (C) 1993 Hamish Macdonald
  *  Copyright (C) 1999 D. Jeff Dionne
diff --git a/arch/m68k/platform/68328/Makefile b/arch/m68k/platform/68328/Makefile
deleted file mode 100644 (file)
index ee61bf8..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-#
-# Makefile for arch/m68knommu/platform/68328.
-#
-
-model-y                          := ram
-model-$(CONFIG_ROMKERNEL) := rom
-
-head-y                 = head-$(model-y).o
-head-$(CONFIG_PILOT)   = head-pilot.o
-head-$(CONFIG_DRAGEN2) = head-de2.o
-
-obj-y                  += entry.o ints.o timers.o
-obj-$(CONFIG_M68328)   += config.o
-obj-$(CONFIG_ROM)      += romvec.o
-
-extra-y                        := head.o
-
-$(obj)/head.o: $(obj)/$(head-y)
-       ln -sf $(head-y) $(obj)/head.o
-
-clean-files := $(obj)/head.o $(head-y)
diff --git a/arch/m68k/platform/68328/head-de2.S b/arch/m68k/platform/68328/head-de2.S
deleted file mode 100644 (file)
index 537d324..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-
-#define        MEM_END 0x00800000      /* Memory size 8Mb */
-
-#undef CRT_DEBUG
-
-.macro PUTC CHAR
-#ifdef CRT_DEBUG
-       moveq   #\CHAR, %d7
-       jsr     putc
-#endif
-.endm
-
-       .global _start
-       .global _rambase
-       .global _ramvec
-       .global _ramstart
-       .global _ramend
-       
-       .data
-
-/*
- *     Set up the usable of RAM stuff
- */
-_rambase:
-       .long   0
-_ramvec:
-       .long   0
-_ramstart:
-       .long   0
-_ramend:
-       .long   0
-
-       .text
-
-_start:
-
-/*
- * Setup initial stack
- */
-       /* disable all interrupts */
-       movew   #0x2700, %sr
-       movel   #-1, 0xfffff304
-       movel   #MEM_END-4, %sp
-
-       PUTC    '\r'
-       PUTC    '\n'
-       PUTC    'A'
-       PUTC    'B'
-
-/*
- *     Determine end of RAM
- */
-
-       movel   #MEM_END, %a0
-       movel   %a0, _ramend
-
-       PUTC    'C'
-
-/*
- *     Move ROM filesystem above bss :-)
- */
-
-       moveal  #__bss_start, %a0               /* romfs at the start of bss */
-       moveal  #__bss_stop, %a1                /* Set up destination  */
-       movel   %a0, %a2                        /* Copy of bss start */
-
-       movel   8(%a0), %d1                     /* Get size of ROMFS */
-       addql   #8, %d1                         /* Allow for rounding */
-       andl    #0xfffffffc, %d1        /* Whole words */
-
-       addl    %d1, %a0                        /* Copy from end */
-       addl    %d1, %a1                        /* Copy from end */
-       movel   %a1, _ramstart          /* Set start of ram */
-
-1:
-       movel   -(%a0), %d0                     /* Copy dword */
-       movel   %d0, -(%a1)
-       cmpl    %a0, %a2                        /* Check if at end */
-       bne     1b
-
-       PUTC    'D'
-
-/*
- * Initialize BSS segment to 0
- */
-
-       lea     __bss_start, %a0
-       lea     __bss_stop, %a1
-
-       /* Copy 0 to %a0 until %a0 == %a1 */
-2:     cmpal   %a0, %a1
-       beq     1f
-       clrl    (%a0)+
-       bra     2b
-1:
-
-       PUTC    'E'
-
-/*
- * Load the current task pointer and stack
- */
-
-       lea     init_thread_union, %a0
-       lea     0x2000(%a0), %sp
-
-       PUTC    'F'
-       PUTC    '\r'
-       PUTC    '\n'
-
-/*
- * Go
- */
-
-       jmp     start_kernel
-
-/*
- * Local functions
- */
-#ifdef CRT_DEBUG
-putc:
-       moveb   %d7, 0xfffff907
-1:
-       movew   0xfffff906, %d7
-       andw    #0x2000, %d7
-       beq     1b
-       rts
-#endif
diff --git a/arch/m68k/platform/68328/head-pilot.S b/arch/m68k/platform/68328/head-pilot.S
deleted file mode 100644 (file)
index 45a9dad..0000000
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * linux/arch/m68knommu/platform/68328/head-pilot.S
- * - A startup file for the MC68328
- *
- * Copyright (C) 1998  D. Jeff Dionne <jeff@ryeham.ee.ryerson.ca>,
- *                     Kenneth Albanowski <kjahds@kjahds.com>,
- *                     The Silver Hammer Group, Ltd.
- *
- * (c) 1995, Dionne & Associates
- * (c) 1995, DKG Display Tech.
- */
-
-#define ASSEMBLY
-
-#define IMMED #
-#define        DBG_PUTC(x)     moveb IMMED x, 0xfffff907
-
-
-.global _stext
-.global _start
-
-.global _rambase
-.global _ramvec
-.global _ramstart
-.global _ramend
-
-.global bootlogo_bits
-
-/*****************************************************************************/
-
-.data
-
-/*
- *      Set up the usable of RAM stuff. Size of RAM is determined then
- *      an initial stack set up at the end.
- */
-.align 4
-_ramvec:
-.long   0
-_rambase:
-.long   0
-_ramstart:
-.long   0
-_ramend:
-.long   0
-
-.text
-       
-_start:
-_stext:
-
-
-#ifdef CONFIG_M68328
-
-#ifdef CONFIG_PILOT
-       .byte 0x4e, 0xfa, 0x00, 0x0a /* Jmp +X bytes */
-       .byte 'b', 'o', 'o', 't'
-       .word 10000
-
-       nop
-#endif
-
-       moveq   #0, %d0
-       movew   %d0, 0xfffff618 /* Watchdog off */
-       movel   #0x00011f07, 0xfffff114 /* CS A1 Mask */
-
-       movew   #0x0800, 0xfffff906 /* Ignore CTS */
-       movew   #0x010b, 0xfffff902 /* BAUD to 9600 */
-
-       movew   #0x2410, 0xfffff200 /* PLLCR */
-       movew   #0x123, 0xfffff202 /* PLLFSR */
-
-#ifdef CONFIG_PILOT
-       moveb   #0, 0xfffffA27 /* LCKCON */
-       movel   #_start, 0xfffffA00 /* LSSA */
-       moveb   #0xa, 0xfffffA05 /* LVPW */
-       movew   #0x9f, 0xFFFFFa08 /* LXMAX */
-       movew   #0x9f, 0xFFFFFa0a /* LYMAX */
-       moveb   #9, 0xfffffa29 /* LBAR */
-       moveb   #0, 0xfffffa25 /* LPXCD */
-       moveb   #0x04, 0xFFFFFa20 /* LPICF */
-       moveb   #0x58, 0xfffffA27 /* LCKCON */
-       moveb   #0x85, 0xfffff429 /* PFDATA */
-       moveb   #0xd8, 0xfffffA27 /* LCKCON */
-       moveb   #0xc5, 0xfffff429 /* PFDATA */
-       moveb   #0xd5, 0xfffff429 /* PFDATA */
-
-       moveal  #0x00100000, %a3
-       moveal  #0x100ffc00, %a4
-#endif /* CONFIG_PILOT */
-
-#endif /* CONFIG_M68328 */
-
-       movew   #0x2700, %sr
-       lea     %a4@(-4), %sp
-
-       DBG_PUTC('\r')
-       DBG_PUTC('\n')
-       DBG_PUTC('A')
-
-       moveq   #0,%d0
-       movew   #16384, %d0  /* PLL settle wait loop */
-L0:
-       subw    #1, %d0
-       bne     L0
-
-       DBG_PUTC('B')
-
-       /* Copy command line from beginning of RAM (+16) to end of bss */
-       movel   #CONFIG_VECTORBASE, %d7
-       addl    #16, %d7
-       moveal  %d7, %a0
-       moveal  #__bss_stop, %a1
-       lea     %a1@(512), %a2
-
-       DBG_PUTC('C')
-
-       /* Copy %a0 to %a1 until %a1 == %a2 */
-L2:
-       movel   %a0@+, %d0
-       movel   %d0, %a1@+
-       cmpal   %a1, %a2
-       bhi     L2
-
-       /* Copy data+init segment from ROM to RAM */
-       moveal  #_etext, %a0
-       moveal  #_sdata, %a1
-       moveal  #__init_end, %a2
-
-       DBG_PUTC('D')
-
-       /* Copy %a0 to %a1 until %a1 == %a2 */
-LD1:
-       movel   %a0@+, %d0
-       movel   %d0, %a1@+
-       cmpal   %a1, %a2
-       bhi     LD1
-
-       DBG_PUTC('E')
-
-       moveal  #__bss_start, %a0
-       moveal  #__bss_stop, %a1
-
-       /* Copy 0 to %a0 until %a0 == %a1 */
-L1:
-       movel   #0, %a0@+
-       cmpal   %a0, %a1
-       bhi     L1
-
-       DBG_PUTC('F')
-
-       /* Copy command line from end of bss to command line */
-       moveal  #__bss_stop, %a0
-       moveal  #command_line, %a1
-       lea     %a1@(512), %a2
-
-       DBG_PUTC('G')
-
-       /* Copy %a0 to %a1 until %a1 == %a2 */
-L3:
-       movel   %a0@+, %d0
-       movel   %d0, %a1@+
-       cmpal   %a1, %a2
-       bhi     L3
-
-       movel   #_sdata, %d0    
-       movel   %d0, _rambase   
-       movel   #__bss_stop, %d0
-       movel   %d0, _ramstart
-
-       movel   %a4, %d0
-       subl    #4096, %d0      /* Reserve 4K of stack */
-       moveq   #79, %d7
-       movel   %d0, _ramend
-
-       pea     0
-       pea     env
-       pea     %sp@(4)
-       pea     0
-
-       DBG_PUTC('H')
-
-#ifdef CONFIG_PILOT
-       movel   #bootlogo_bits, 0xFFFFFA00
-       moveb   #10, 0xFFFFFA05
-       movew   #160, 0xFFFFFA08
-       movew   #160, 0xFFFFFA0A
-#endif /* CONFIG_PILOT */
-
-       DBG_PUTC('I')
-
-       lea     init_thread_union, %a0
-       lea     0x2000(%a0), %sp
-
-       DBG_PUTC('J')
-       DBG_PUTC('\r')
-       DBG_PUTC('\n')
-
-       jsr     start_kernel
-_exit:
-
-       jmp     _exit
-
-
-       .data
-env:
-       .long   0
diff --git a/arch/m68k/platform/68328/head-ram.S b/arch/m68k/platform/68328/head-ram.S
deleted file mode 100644 (file)
index 5189ef9..0000000
+++ /dev/null
@@ -1,141 +0,0 @@
-
-       .global __main
-       .global __rom_start
-
-        .global _rambase
-        .global _ramstart
-       
-       .global splash_bits
-       .global _start
-       .global _stext
-       .global _edata
-
-#define DEBUG
-#define ROM_OFFSET 0x10C00000
-#define STACK_GAURD 0x10
-
-       .text
-       
-_start:
-_stext:
-       movew   #0x2700, %sr            /* Exceptions off! */
-
-#if 0
-       /* Init chip registers.  uCsimm specific */
-       moveb   #0x00,   0xfffffb0b     /* Watchdog off */
-       moveb   #0x10,   0xfffff000     /* SCR */
-
-       movew   #0x2400, 0xfffff200     /* PLLCR */
-       movew   #0x0123, 0xfffff202     /* PLLFSR */
-
-       moveb   #0x00,   0xfffff40b     /* enable chip select */
-       moveb   #0x00,   0xfffff423     /* enable /DWE */
-       moveb   #0x08,   0xfffffd0d     /* disable hardmap */
-       moveb   #0x07,   0xfffffd0e     /* level 7 interrupt clear */
-
-       movew   #0x8600, 0xfffff100     /* FLASH at 0x10c00000 */
-       movew   #0x018b, 0xfffff110     /* 2Meg, enable, 0ws */
-
-       movew   #0x8f00, 0xfffffc00     /* DRAM configuration */
-       movew   #0x9667, 0xfffffc02     /* DRAM control */
-       movew   #0x0000, 0xfffff106     /* DRAM at 0x00000000 */
-       movew   #0x068f, 0xfffff116     /* 8Meg, enable, 0ws */
-
-       moveb   #0x40,   0xfffff300     /* IVR */
-       movel   #0x007FFFFF, %d0        /* IMR */
-       movel   %d0,     0xfffff304
-
-       moveb   0xfffff42b, %d0
-       andb    #0xe0,   %d0
-       moveb   %d0,     0xfffff42b
-
-       moveb   #0x08,   0xfffff907     /* Ignore CTS */
-       movew   #0x010b, 0xfffff902     /* BAUD to 9600 */
-       movew   #0xe100, 0xfffff900     /* enable */
-#endif
-
-       movew   #16384, %d0  /* PLL settle wait loop */
-L0:
-       subw    #1, %d0
-       bne     L0
-#ifdef DEBUG
-       moveq   #70, %d7                /* 'F' */
-       moveb   %d7,0xfffff907          /* No absolute addresses */
-pclp1:
-       movew   0xfffff906, %d7
-       andw    #0x2000, %d7
-       beq     pclp1
-#endif /* DEBUG */
-
-#ifdef DEBUG
-       moveq   #82, %d7                /* 'R' */
-       moveb   %d7,0xfffff907          /* No absolute addresses */
-pclp3:
-       movew   0xfffff906, %d7
-       andw    #0x2000, %d7
-       beq     pclp3
-#endif /* DEBUG */
-       moveal  #0x007ffff0, %ssp
-       moveal  #__bss_start, %a0
-       moveal  #__bss_stop, %a1
-
-       /* Copy 0 to %a0 until %a0 >= %a1 */
-L1:
-       movel   #0, %a0@+
-       cmpal   %a0, %a1
-       bhi     L1
-
-#ifdef DEBUG
-       moveq   #67, %d7                /* 'C' */
-       jsr     putc
-#endif /* DEBUG */
-
-       pea     0
-       pea     env
-       pea     %sp@(4)
-       pea     0
-
-#ifdef DEBUG
-       moveq   #70, %d7                /* 'F' */
-       jsr     putc
-#endif /* DEBUG */
-
-lp:
-       jsr     start_kernel
-        jmp lp
-_exit:
-
-       jmp     _exit
-
-__main:
-       /* nothing */
-       rts
-
-#ifdef DEBUG
-putc:
-       moveb   %d7,0xfffff907
-pclp:
-       movew   0xfffff906, %d7
-       andw    #0x2000, %d7
-       beq     pclp
-       rts
-#endif /* DEBUG */
-
-       .data
-
-/*
- *      Set up the usable of RAM stuff. Size of RAM is determined then
- *      an initial stack set up at the end.
- */
-.align 4
-_ramvec:
-.long   0
-_rambase:
-.long   0
-_ramstart:
-.long   0
-_ramend:
-.long   0
-
-env:
-       .long   0
diff --git a/arch/m68k/platform/68328/head-rom.S b/arch/m68k/platform/68328/head-rom.S
deleted file mode 100644 (file)
index 3dff98b..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-       
-       .global _start
-       .global _stext
-
-       .global _rambase
-       .global _ramvec
-       .global _ramstart
-       .global _ramend
-
-#ifdef CONFIG_INIT_LCD
-       .global bootlogo_bits
-#endif
-
-       .data
-
-/*
- *      Set up the usable of RAM stuff. Size of RAM is determined then
- *      an initial stack set up at the end.
- */
-.align 4
-_ramvec:
-.long   0
-_rambase:
-.long   0
-_ramstart:
-.long   0
-_ramend:
-.long   0
-
-#define        RAMEND  (CONFIG_RAMBASE + CONFIG_RAMSIZE)
-
-       .text
-_start:
-_stext:        movew   #0x2700,%sr
-#ifdef CONFIG_INIT_LCD
-       movel   #bootlogo_bits, 0xfffffA00 /* LSSA */
-       moveb   #0x28,   0xfffffA05     /* LVPW */
-       movew   #0x280,  0xFFFFFa08     /* LXMAX */
-       movew   #0x1df,  0xFFFFFa0a     /* LYMAX */
-       moveb   #0,      0xfffffa29     /* LBAR */
-       moveb   #0,      0xfffffa25     /* LPXCD */
-       moveb   #0x08,   0xFFFFFa20     /* LPICF */
-       moveb   #0x01,   0xFFFFFA21     /* -ve pol */
-       moveb   #0x81,   0xfffffA27     /* LCKCON */
-       movew   #0xff00, 0xfffff412     /* LCD pins */
-#endif
-       moveal  #RAMEND-CONFIG_MEMORY_RESERVE*0x100000 - 0x10, %sp
-       movew   #32767, %d0  /* PLL settle wait loop */
-1:     subq    #1, %d0
-       bne     1b
-
-       /* Copy data segment from ROM to RAM */
-       moveal  #_etext, %a0
-       moveal  #_sdata, %a1
-       moveal  #_edata, %a2
-
-       /* Copy %a0 to %a1 until %a1 == %a2 */
-1:     movel   %a0@+, %a1@+
-       cmpal   %a1, %a2
-       bhi     1b
-
-       moveal  #__bss_start, %a0
-       moveal  #__bss_stop, %a1
-       /* Copy 0 to %a0 until %a0 == %a1 */
-       
-1:
-       clrl    %a0@+
-       cmpal   %a0, %a1
-       bhi     1b
-
-        movel   #_sdata, %d0    
-        movel   %d0, _rambase        
-        movel   #__bss_stop, %d0
-        movel   %d0, _ramstart
-       movel   #RAMEND-CONFIG_MEMORY_RESERVE*0x100000, %d0
-       movel   %d0, _ramend
-       movel   #CONFIG_VECTORBASE,     %d0
-       movel   %d0, _ramvec
-       
-/*
- * load the current task pointer and stack
- */
-       lea     init_thread_union, %a0
-       lea     0x2000(%a0), %sp
-
-1:     jsr     start_kernel
-        bra 1b
-_exit:
-
-       jmp     _exit
-
-
-putc:
-       moveb   %d7,0xfffff907
-1:
-       movew   0xfffff906, %d7
-       andw    #0x2000, %d7
-       beq     1b
-       rts
-
-       .data
-env:
-       .long   0
-       .text
-
diff --git a/arch/m68k/platform/68EZ328/Makefile b/arch/m68k/platform/68EZ328/Makefile
deleted file mode 100644 (file)
index b44d799..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-#
-# Makefile for arch/m68knommu/platform/68EZ328.
-#
-
-obj-y := config.o
diff --git a/arch/m68k/platform/68VZ328/Makefile b/arch/m68k/platform/68VZ328/Makefile
deleted file mode 100644 (file)
index 8166741..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-#
-# Makefile for arch/m68k/platform/68VZ328.
-#
-
-obj-y          := config.o
index 8653072d7e9f061479c5b11c5de056337cfdac7a..4a159da23633dbf359c9886513958ce49e842ce7 100644 (file)
@@ -1,5 +1,3 @@
-include include/asm-generic/Kbuild.asm
 
-header-y  += elf.h
 generic-y += clkdev.h
 generic-y += exec.h
index 640ddd4b6a9b2cf6bc58e159a46bf9490069e188..659024449064887f303966e707d255b2faed4220 100644 (file)
  * License. See the file "COPYING" in the main directory of this archive
  * for more details.
  */
-
 #ifndef _ASM_MICROBLAZE_ELF_H
 #define _ASM_MICROBLAZE_ELF_H
 
-/*
- * Note there is no "official" ELF designation for Microblaze.
- * I've snaffled the value from the microblaze binutils source code
- * /binutils/microblaze/include/elf/microblaze.h
- */
-#define EM_MICROBLAZE          189
-#define EM_MICROBLAZE_OLD      0xbaab
-#define ELF_ARCH               EM_MICROBLAZE
-
-/*
- * This is used to ensure we don't load something for the wrong architecture.
- */
-#define elf_check_arch(x)      ((x)->e_machine == EM_MICROBLAZE \
-                                || (x)->e_machine == EM_MICROBLAZE_OLD)
-
-/*
- * These are used to set parameters in the core dumps.
- */
-#define ELF_CLASS      ELFCLASS32
+#include <uapi/asm/elf.h>
 
 #ifndef __uClinux__
-
-/*
- * ELF register definitions..
- */
-
-#include <asm/ptrace.h>
-#include <asm/byteorder.h>
-
 #ifndef ELF_GREG_T
-#define ELF_GREG_T
-typedef unsigned long elf_greg_t;
 #endif
-
 #ifndef ELF_NGREG
-#define ELF_NGREG (sizeof(struct pt_regs) / sizeof(elf_greg_t))
 #endif
-
 #ifndef ELF_GREGSET_T
-#define ELF_GREGSET_T
-typedef elf_greg_t elf_gregset_t[ELF_NGREG];
 #endif
-
 #ifndef ELF_FPREGSET_T
-#define ELF_FPREGSET_T
-
-/* TBD */
-#define ELF_NFPREG     33      /* includes fsr */
-typedef unsigned long elf_fpreg_t;
-typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
-
-/* typedef struct user_fpu_struct elf_fpregset_t; */
 #endif
-
-/* This is the location that an ET_DYN program is loaded if exec'ed.  Typical
- * use of this is to invoke "./ld.so someprog" to test out a new version of
- * the loader.  We need to make sure that it is out of the way of the program
- * that it will "exec", and that there is sufficient room for the brk.
- */
-
-#define ELF_ET_DYN_BASE         (0x08000000)
-
 #ifdef __MICROBLAZEEL__
-#define ELF_DATA       ELFDATA2LSB
 #else
-#define ELF_DATA       ELFDATA2MSB
 #endif
-
-#define ELF_EXEC_PAGESIZE      PAGE_SIZE
-
-
-#define ELF_CORE_COPY_REGS(_dest, _regs)                       \
-       memcpy((char *) &_dest, (char *) _regs,         \
-       sizeof(struct pt_regs));
-
-/* This yields a mask that user programs can use to figure out what
- * instruction set this CPU supports.  This could be done in user space,
- * but it's not easy, and we've already done it here.
- */
-#define ELF_HWCAP      (0)
-
-/* This yields a string that ld.so will use to load implementation
- * specific libraries for optimization.  This is more specific in
- * intent than poking at uname or /proc/cpuinfo.
-
- * For the moment, we have only optimizations for the Intel generations,
- * but that could change...
- */
-#define ELF_PLATFORM  (NULL)
-
-/* Added _f parameter. Is this definition correct: TBD */
-#define ELF_PLAT_INIT(_r, _f)                          \
-do {                                                   \
-       _r->r1 =  _r->r1 =  _r->r2 =  _r->r3 =          \
-       _r->r4 =  _r->r5 =  _r->r6 =  _r->r7 =          \
-       _r->r8 =  _r->r9 =  _r->r10 = _r->r11 =         \
-       _r->r12 = _r->r13 = _r->r14 = _r->r15 =         \
-       _r->r16 = _r->r17 = _r->r18 = _r->r19 =         \
-       _r->r20 = _r->r21 = _r->r22 = _r->r23 =         \
-       _r->r24 = _r->r25 = _r->r26 = _r->r27 =         \
-       _r->r28 = _r->r29 = _r->r30 = _r->r31 =         \
-       0;                                              \
-} while (0)
-
-#ifdef __KERNEL__
 #define SET_PERSONALITY(ex) \
        set_personality(PER_LINUX_32BIT | (current->personality & (~PER_MASK)))
-#endif
-
 #endif /* __uClinux__ */
-
 #endif /* _ASM_MICROBLAZE_ELF_H */
diff --git a/arch/microblaze/include/asm/kvm_para.h b/arch/microblaze/include/asm/kvm_para.h
deleted file mode 100644 (file)
index 14fab8f..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/kvm_para.h>
index 94e92c8058592f786cfd6fac942c90b308664e85..3732bcf186fd5b6a3438464b9a570a914501fdc0 100644 (file)
@@ -5,56 +5,12 @@
  * License. See the file "COPYING" in the main directory of this archive
  * for more details.
  */
-
 #ifndef _ASM_MICROBLAZE_PTRACE_H
 #define _ASM_MICROBLAZE_PTRACE_H
 
-#ifndef __ASSEMBLY__
-
-typedef unsigned long microblaze_reg_t;
+#include <uapi/asm/ptrace.h>
 
-struct pt_regs {
-       microblaze_reg_t r0;
-       microblaze_reg_t r1;
-       microblaze_reg_t r2;
-       microblaze_reg_t r3;
-       microblaze_reg_t r4;
-       microblaze_reg_t r5;
-       microblaze_reg_t r6;
-       microblaze_reg_t r7;
-       microblaze_reg_t r8;
-       microblaze_reg_t r9;
-       microblaze_reg_t r10;
-       microblaze_reg_t r11;
-       microblaze_reg_t r12;
-       microblaze_reg_t r13;
-       microblaze_reg_t r14;
-       microblaze_reg_t r15;
-       microblaze_reg_t r16;
-       microblaze_reg_t r17;
-       microblaze_reg_t r18;
-       microblaze_reg_t r19;
-       microblaze_reg_t r20;
-       microblaze_reg_t r21;
-       microblaze_reg_t r22;
-       microblaze_reg_t r23;
-       microblaze_reg_t r24;
-       microblaze_reg_t r25;
-       microblaze_reg_t r26;
-       microblaze_reg_t r27;
-       microblaze_reg_t r28;
-       microblaze_reg_t r29;
-       microblaze_reg_t r30;
-       microblaze_reg_t r31;
-       microblaze_reg_t pc;
-       microblaze_reg_t msr;
-       microblaze_reg_t ear;
-       microblaze_reg_t esr;
-       microblaze_reg_t fsr;
-       int pt_mode;
-};
-
-#ifdef __KERNEL__
+#ifndef __ASSEMBLY__
 #define kernel_mode(regs)              ((regs)->pt_mode)
 #define user_mode(regs)                        (!kernel_mode(regs))
 
@@ -66,19 +22,5 @@ static inline long regs_return_value(struct pt_regs *regs)
        return regs->r3;
 }
 
-#else /* __KERNEL__ */
-
-/* pt_regs offsets used by gdbserver etc in ptrace syscalls */
-#define PT_GPR(n)      ((n) * sizeof(microblaze_reg_t))
-#define PT_PC          (32 * sizeof(microblaze_reg_t))
-#define PT_MSR         (33 * sizeof(microblaze_reg_t))
-#define PT_EAR         (34 * sizeof(microblaze_reg_t))
-#define PT_ESR         (35 * sizeof(microblaze_reg_t))
-#define PT_FSR         (36 * sizeof(microblaze_reg_t))
-#define PT_KERNEL_MODE (37 * sizeof(microblaze_reg_t))
-
-#endif /* __KERNEL */
-
 #endif /* __ASSEMBLY__ */
-
 #endif /* _ASM_MICROBLAZE_PTRACE_H */
index 0061aa13a340a3ca8be926a2e056b4a808e923cc..0e0b0a5ec7568655e35a220635ffd07eac18f65e 100644 (file)
@@ -7,15 +7,12 @@
  * License. See the file "COPYING" in the main directory of this archive
  * for more details.
  */
-
 #ifndef _ASM_MICROBLAZE_SETUP_H
 #define _ASM_MICROBLAZE_SETUP_H
 
-#define COMMAND_LINE_SIZE      256
+#include <uapi/asm/setup.h>
 
 # ifndef __ASSEMBLY__
-
-#  ifdef __KERNEL__
 extern unsigned int boot_cpuid; /* move to smp.h */
 
 extern char cmd_line[COMMAND_LINE_SIZE];
@@ -53,6 +50,5 @@ void free_init_pages(char *what, unsigned long begin, unsigned long end);
 extern void *alloc_maybe_bootmem(size_t size, gfp_t mask);
 extern void *zalloc_maybe_bootmem(size_t size, gfp_t mask);
 
-#  endif/* __KERNEL__ */
 # endif /* __ASSEMBLY__ */
 #endif /* _ASM_MICROBLAZE_SETUP_H */
index 6985e6e9d826a689e6049308e663d06dcfdf070f..0458cef3a890640efac09660fee8f731c718035e 100644 (file)
  * License. See the file "COPYING" in the main directory of this archive
  * for more details.
  */
-
 #ifndef _ASM_MICROBLAZE_UNISTD_H
 #define _ASM_MICROBLAZE_UNISTD_H
 
-#define __NR_restart_syscall   0 /* ok */
-#define __NR_exit              1 /* ok */
-#define __NR_fork              2 /* not for no MMU - weird */
-#define __NR_read              3 /* ok */
-#define __NR_write             4 /* ok */
-#define __NR_open              5 /* openat */
-#define __NR_close             6 /* ok */
-#define __NR_waitpid           7 /* waitid */
-#define __NR_creat             8 /* openat */
-#define __NR_link              9 /* linkat */
-#define __NR_unlink            10 /* unlinkat */
-#define __NR_execve            11 /* ok */
-#define __NR_chdir             12 /* ok */
-#define __NR_time              13 /* obsolete -> sys_gettimeofday */
-#define __NR_mknod             14 /* mknodat */
-#define __NR_chmod             15 /* fchmodat */
-#define __NR_lchown            16 /* ok */
-#define __NR_break             17 /* don't know */
-#define __NR_oldstat           18 /* remove */
-#define __NR_lseek             19 /* ok */
-#define __NR_getpid            20 /* ok */
-#define __NR_mount             21 /* ok */
-#define __NR_umount            22 /* ok */  /* use only umount2 */
-#define __NR_setuid            23 /* ok */
-#define __NR_getuid            24 /* ok */
-#define __NR_stime             25 /* obsolete -> sys_settimeofday */
-#define __NR_ptrace            26 /* ok */
-#define __NR_alarm             27 /* obsolete -> sys_setitimer */
-#define __NR_oldfstat          28 /* remove */
-#define __NR_pause             29 /* obsolete -> sys_rt_sigtimedwait */
-#define __NR_utime             30 /* obsolete -> sys_utimesat */
-#define __NR_stty              31 /* remove */
-#define __NR_gtty              32 /* remove */
-#define __NR_access            33 /* faccessat */
-/* can be implemented by sys_setpriority */
-#define __NR_nice              34
-#define __NR_ftime             35 /* remove */
-#define __NR_sync              36 /* ok */
-#define __NR_kill              37 /* ok */
-#define __NR_rename            38 /* renameat */
-#define __NR_mkdir             39 /* mkdirat */
-#define __NR_rmdir             40 /* unlinkat */
-#define __NR_dup               41 /* ok */
-#define __NR_pipe              42 /* ok */
-#define __NR_times             43 /* ok */
-#define __NR_prof              44 /* remove */
-#define __NR_brk               45 /* ok -mmu, nommu specific */
-#define __NR_setgid            46 /* ok */
-#define __NR_getgid            47 /* ok */
-#define __NR_signal            48 /* obsolete -> sys_rt_sigaction */
-#define __NR_geteuid           49 /* ok */
-#define __NR_getegid           50 /* ok */
-#define __NR_acct              51 /* add it and then I can disable it */
-#define __NR_umount2           52 /* remove */
-#define __NR_lock              53 /* remove */
-#define __NR_ioctl             54 /* ok */
-#define __NR_fcntl             55 /* ok -> 64bit version*/
-#define __NR_mpx               56 /* remove */
-#define __NR_setpgid           57 /* ok */
-#define __NR_ulimit            58 /* remove */
-#define __NR_oldolduname       59 /* remove */
-#define __NR_umask             60 /* ok */
-#define __NR_chroot            61 /* ok */
-#define __NR_ustat             62 /* obsolete -> statfs64 */
-#define __NR_dup2              63 /* ok */
-#define __NR_getppid           64 /* ok */
-#define __NR_getpgrp           65 /* obsolete -> sys_getpgid */
-#define __NR_setsid            66 /* ok */
-#define __NR_sigaction         67 /* obsolete -> rt_sigaction */
-#define __NR_sgetmask          68 /* obsolete -> sys_rt_sigprocmask */
-#define __NR_ssetmask          69 /* obsolete ->sys_rt_sigprocmask */
-#define __NR_setreuid          70 /* ok */
-#define __NR_setregid          71 /* ok */
-#define __NR_sigsuspend                72 /* obsolete -> rt_sigsuspend */
-#define __NR_sigpending                73 /* obsolete -> sys_rt_sigpending */
-#define __NR_sethostname       74 /* ok */
-#define __NR_setrlimit         75 /* ok */
-#define __NR_getrlimit         76 /* ok Back compatible 2G limited rlimit */
-#define __NR_getrusage         77 /* ok */
-#define __NR_gettimeofday      78 /* ok */
-#define __NR_settimeofday      79 /* ok */
-#define __NR_getgroups         80 /* ok */
-#define __NR_setgroups         81 /* ok */
-#define __NR_select            82 /* obsolete -> sys_pselect7 */
-#define __NR_symlink           83 /* symlinkat */
-#define __NR_oldlstat          84 /* remove */
-#define __NR_readlink          85 /* obsolete -> sys_readlinkat */
-#define __NR_uselib            86 /* remove */
-#define __NR_swapon            87 /* ok */
-#define __NR_reboot            88 /* ok */
-#define __NR_readdir           89 /* remove ? */
-#define __NR_mmap              90 /* obsolete -> sys_mmap2 */
-#define __NR_munmap            91 /* ok - mmu and nommu */
-#define __NR_truncate          92 /* ok or truncate64 */
-#define __NR_ftruncate         93 /* ok or ftruncate64 */
-#define __NR_fchmod            94 /* ok */
-#define __NR_fchown            95 /* ok */
-#define __NR_getpriority       96 /* ok */
-#define __NR_setpriority       97 /* ok */
-#define __NR_profil            98 /* remove */
-#define __NR_statfs            99 /* ok or statfs64 */
-#define __NR_fstatfs           100  /* ok or fstatfs64 */
-#define __NR_ioperm            101 /* remove */
-#define __NR_socketcall                102 /* remove */
-#define __NR_syslog            103 /* ok */
-#define __NR_setitimer         104 /* ok */
-#define __NR_getitimer         105 /* ok */
-#define __NR_stat              106 /* remove */
-#define __NR_lstat             107 /* remove */
-#define __NR_fstat             108 /* remove */
-#define __NR_olduname          109 /* remove */
-#define __NR_iopl              110 /* remove */
-#define __NR_vhangup           111 /* ok */
-#define __NR_idle              112 /* remove */
-#define __NR_vm86old           113 /* remove */
-#define __NR_wait4             114 /* obsolete -> waitid */
-#define __NR_swapoff           115 /* ok */
-#define __NR_sysinfo           116 /* ok */
-#define __NR_ipc               117 /* remove - direct call */
-#define __NR_fsync             118 /* ok */
-#define __NR_sigreturn         119 /* obsolete -> sys_rt_sigreturn */
-#define __NR_clone             120 /* ok */
-#define __NR_setdomainname     121 /* ok */
-#define __NR_uname             122 /* remove */
-#define __NR_modify_ldt                123 /* remove */
-#define __NR_adjtimex          124 /* ok */
-#define __NR_mprotect          125 /* remove */
-#define __NR_sigprocmask       126 /* obsolete -> sys_rt_sigprocmask */
-#define __NR_create_module     127 /* remove */
-#define __NR_init_module       128 /* ok */
-#define __NR_delete_module     129 /* ok */
-#define __NR_get_kernel_syms   130 /* remove */
-#define __NR_quotactl          131 /* ok */
-#define __NR_getpgid           132 /* ok */
-#define __NR_fchdir            133 /* ok */
-#define __NR_bdflush           134 /* remove */
-#define __NR_sysfs             135 /* needed for busybox */
-#define __NR_personality       136 /* ok */
-#define __NR_afs_syscall       137 /* Syscall for Andrew File System */
-#define __NR_setfsuid          138 /* ok */
-#define __NR_setfsgid          139 /* ok */
-#define __NR__llseek           140 /* remove only lseek */
-#define __NR_getdents          141 /* ok or getdents64 */
-#define __NR__newselect                142 /* remove */
-#define __NR_flock             143 /* ok */
-#define __NR_msync             144 /* remove */
-#define __NR_readv             145 /* ok */
-#define __NR_writev            146 /* ok */
-#define __NR_getsid            147 /* ok */
-#define __NR_fdatasync         148 /* ok */
-#define __NR__sysctl           149 /* remove */
-#define __NR_mlock             150 /* ok - nommu or mmu */
-#define __NR_munlock           151 /* ok - nommu or mmu */
-#define __NR_mlockall          152 /* ok - nommu or mmu */
-#define __NR_munlockall                153 /* ok - nommu or mmu */
-#define __NR_sched_setparam            154 /* ok */
-#define __NR_sched_getparam            155 /* ok */
-#define __NR_sched_setscheduler                156 /* ok */
-#define __NR_sched_getscheduler                157 /* ok */
-#define __NR_sched_yield               158 /* ok */
-#define __NR_sched_get_priority_max    159 /* ok */
-#define __NR_sched_get_priority_min    160 /* ok */
-#define __NR_sched_rr_get_interval     161 /* ok */
-#define __NR_nanosleep         162 /* ok */
-#define __NR_mremap            163 /* ok - nommu or mmu */
-#define __NR_setresuid         164 /* ok */
-#define __NR_getresuid         165 /* ok */
-#define __NR_vm86              166 /* remove */
-#define __NR_query_module      167 /* ok */
-#define __NR_poll              168 /* obsolete -> sys_ppoll */
-#define __NR_nfsservctl                169 /* ok */
-#define __NR_setresgid         170 /* ok */
-#define __NR_getresgid         171 /* ok */
-#define __NR_prctl             172 /* ok */
-#define __NR_rt_sigreturn      173 /* ok */
-#define __NR_rt_sigaction      174 /* ok */
-#define __NR_rt_sigprocmask    175 /* ok */
-#define __NR_rt_sigpending     176 /* ok */
-#define __NR_rt_sigtimedwait   177 /* ok */
-#define __NR_rt_sigqueueinfo   178 /* ok */
-#define __NR_rt_sigsuspend     179 /* ok */
-#define __NR_pread64           180 /* ok */
-#define __NR_pwrite64          181 /* ok */
-#define __NR_chown             182 /* obsolete -> fchownat */
-#define __NR_getcwd            183 /* ok */
-#define __NR_capget            184 /* ok */
-#define __NR_capset            185 /* ok */
-#define __NR_sigaltstack       186 /* remove */
-#define __NR_sendfile          187 /* ok -> exist 64bit version*/
-#define __NR_getpmsg           188 /* remove */
-/* remove - some people actually want streams */
-#define __NR_putpmsg           189
-/* for noMMU - group with clone -> maybe remove */
-#define __NR_vfork             190
-#define __NR_ugetrlimit                191 /* remove - SuS compliant getrlimit */
-#define __NR_mmap2             192 /* ok */
-#define __NR_truncate64                193 /* ok */
-#define __NR_ftruncate64       194 /* ok */
-#define __NR_stat64            195 /* remove _ARCH_WANT_STAT64 */
-#define __NR_lstat64           196 /* remove _ARCH_WANT_STAT64 */
-#define __NR_fstat64           197 /* remove _ARCH_WANT_STAT64 */
-#define __NR_lchown32          198 /* ok - without 32 */
-#define __NR_getuid32          199 /* ok - without 32 */
-#define __NR_getgid32          200 /* ok - without 32 */
-#define __NR_geteuid32         201 /* ok - without 32 */
-#define __NR_getegid32         202 /* ok - without 32 */
-#define __NR_setreuid32                203 /* ok - without 32 */
-#define __NR_setregid32                204 /* ok - without 32 */
-#define __NR_getgroups32       205 /* ok - without 32 */
-#define __NR_setgroups32       206 /* ok - without 32 */
-#define __NR_fchown32          207 /* ok - without 32 */
-#define __NR_setresuid32       208 /* ok - without 32 */
-#define __NR_getresuid32       209 /* ok - without 32 */
-#define __NR_setresgid32       210 /* ok - without 32 */
-#define __NR_getresgid32       211 /* ok - without 32 */
-#define __NR_chown32           212 /* ok - without 32 -obsolete -> fchownat */
-#define __NR_setuid32          213 /* ok - without 32 */
-#define __NR_setgid32          214 /* ok - without 32 */
-#define __NR_setfsuid32                215 /* ok - without 32 */
-#define __NR_setfsgid32                216 /* ok - without 32 */
-#define __NR_pivot_root                217 /* ok */
-#define __NR_mincore           218 /* ok */
-#define __NR_madvise           219 /* ok */
-#define __NR_getdents64                220 /* ok */
-#define __NR_fcntl64           221 /* ok */
-/* 223 is unused */
-#define __NR_gettid            224 /* ok */
-#define __NR_readahead         225 /* ok */
-#define __NR_setxattr          226 /* ok */
-#define __NR_lsetxattr         227 /* ok */
-#define __NR_fsetxattr         228 /* ok */
-#define __NR_getxattr          229 /* ok */
-#define __NR_lgetxattr         230 /* ok */
-#define __NR_fgetxattr         231 /* ok */
-#define __NR_listxattr         232 /* ok */
-#define __NR_llistxattr                233 /* ok */
-#define __NR_flistxattr                234 /* ok */
-#define __NR_removexattr       235 /* ok */
-#define __NR_lremovexattr      236 /* ok */
-#define __NR_fremovexattr      237 /* ok */
-#define __NR_tkill             238 /* ok */
-#define __NR_sendfile64                239 /* ok */
-#define __NR_futex             240 /* ok */
-#define __NR_sched_setaffinity 241 /* ok */
-#define __NR_sched_getaffinity 242 /* ok */
-#define __NR_set_thread_area   243 /* remove */
-#define __NR_get_thread_area   244 /* remove */
-#define __NR_io_setup          245 /* ok */
-#define __NR_io_destroy                246 /* ok */
-#define __NR_io_getevents      247 /* ok */
-#define __NR_io_submit         248 /* ok */
-#define __NR_io_cancel         249 /* ok */
-#define __NR_fadvise64         250 /* remove -> sys_fadvise64_64 */
-/* 251 is available for reuse (was briefly sys_set_zone_reclaim) */
-#define __NR_exit_group                252 /* ok */
-#define __NR_lookup_dcookie    253 /* ok */
-#define __NR_epoll_create      254 /* ok */
-#define __NR_epoll_ctl         255 /* ok */
-#define __NR_epoll_wait                256 /* obsolete -> sys_epoll_pwait */
-#define __NR_remap_file_pages  257 /* only for mmu */
-#define __NR_set_tid_address   258 /* ok */
-#define __NR_timer_create      259 /* ok */
-#define __NR_timer_settime     (__NR_timer_create+1) /* 260 */ /* ok */
-#define __NR_timer_gettime     (__NR_timer_create+2) /* 261 */ /* ok */
-#define __NR_timer_getoverrun  (__NR_timer_create+3) /* 262 */ /* ok */
-#define __NR_timer_delete      (__NR_timer_create+4) /* 263 */ /* ok */
-#define __NR_clock_settime     (__NR_timer_create+5) /* 264 */ /* ok */
-#define __NR_clock_gettime     (__NR_timer_create+6) /* 265 */ /* ok */
-#define __NR_clock_getres      (__NR_timer_create+7) /* 266 */ /* ok */
-#define __NR_clock_nanosleep   (__NR_timer_create+8) /* 267 */ /* ok */
-#define __NR_statfs64          268 /* ok */
-#define __NR_fstatfs64         269 /* ok */
-#define __NR_tgkill            270 /* ok */
-#define __NR_utimes            271 /* obsolete -> sys_futimesat */
-#define __NR_fadvise64_64      272 /* ok */
-#define __NR_vserver           273 /* ok */
-#define __NR_mbind             274 /* only for mmu */
-#define __NR_get_mempolicy     275 /* only for mmu */
-#define __NR_set_mempolicy     276 /* only for mmu */
-#define __NR_mq_open           277 /* ok */
-#define __NR_mq_unlink         (__NR_mq_open+1) /* 278 */ /* ok */
-#define __NR_mq_timedsend      (__NR_mq_open+2) /* 279 */ /* ok */
-#define __NR_mq_timedreceive   (__NR_mq_open+3) /* 280 */ /* ok */
-#define __NR_mq_notify         (__NR_mq_open+4) /* 281 */ /* ok */
-#define __NR_mq_getsetattr     (__NR_mq_open+5) /* 282 */ /* ok */
-#define __NR_kexec_load                283 /* ok */
-#define __NR_waitid            284 /* ok */
-/* #define __NR_sys_setaltroot 285 */
-#define __NR_add_key           286 /* ok */
-#define __NR_request_key       287 /* ok */
-#define __NR_keyctl            288 /* ok */
-#define __NR_ioprio_set                289 /* ok */
-#define __NR_ioprio_get                290 /* ok */
-#define __NR_inotify_init      291 /* ok */
-#define __NR_inotify_add_watch 292 /* ok */
-#define __NR_inotify_rm_watch  293 /* ok */
-#define __NR_migrate_pages     294 /* mmu */
-#define __NR_openat            295 /* ok */
-#define __NR_mkdirat           296 /* ok */
-#define __NR_mknodat           297 /* ok */
-#define __NR_fchownat          298 /* ok */
-#define __NR_futimesat         299 /* obsolete -> sys_utimesat */
-#define __NR_fstatat64         300 /* stat64 */
-#define __NR_unlinkat          301 /* ok */
-#define __NR_renameat          302 /* ok */
-#define __NR_linkat            303 /* ok */
-#define __NR_symlinkat         304 /* ok */
-#define __NR_readlinkat                305 /* ok */
-#define __NR_fchmodat          306 /* ok */
-#define __NR_faccessat         307 /* ok */
-#define __NR_pselect6          308 /* obsolete -> sys_pselect7 */
-#define __NR_ppoll             309 /* ok */
-#define __NR_unshare           310 /* ok */
-#define __NR_set_robust_list   311 /* ok */
-#define __NR_get_robust_list   312 /* ok */
-#define __NR_splice            313 /* ok */
-#define __NR_sync_file_range   314 /* ok */
-#define __NR_tee               315 /* ok */
-#define __NR_vmsplice          316 /* ok */
-#define __NR_move_pages                317 /* mmu */
-#define __NR_getcpu            318 /* ok */
-#define __NR_epoll_pwait       319 /* ok */
-#define __NR_utimensat         320 /* ok */
-#define __NR_signalfd          321 /* ok */
-#define __NR_timerfd_create    322 /* ok */
-#define __NR_eventfd           323 /* ok */
-#define __NR_fallocate         324 /* ok */
-#define __NR_semtimedop                325 /* ok - semaphore group */
-#define __NR_timerfd_settime   326 /* ok */
-#define __NR_timerfd_gettime   327 /* ok */
-/* sysv ipc syscalls */
-#define __NR_semctl            328 /* ok */
-#define __NR_semget            329 /* ok */
-#define __NR_semop             330 /* ok */
-#define __NR_msgctl            331 /* ok */
-#define __NR_msgget            332 /* ok */
-#define __NR_msgrcv            333 /* ok */
-#define __NR_msgsnd            334 /* ok */
-#define __NR_shmat             335 /* ok */
-#define __NR_shmctl            336 /* ok */
-#define __NR_shmdt             337 /* ok */
-#define __NR_shmget            338 /* ok */
-
-
-#define __NR_signalfd4         339 /* new */
-#define __NR_eventfd2          340 /* new */
-#define __NR_epoll_create1     341 /* new */
-#define __NR_dup3              342 /* new */
-#define __NR_pipe2             343 /* new */
-#define __NR_inotify_init1     344 /* new */
-#define __NR_socket            345 /* new */
-#define __NR_socketpair                346 /* new */
-#define __NR_bind              347 /* new */
-#define __NR_listen            348 /* new */
-#define __NR_accept            349 /* new */
-#define __NR_connect           350 /* new */
-#define __NR_getsockname       351 /* new */
-#define __NR_getpeername       352 /* new */
-#define __NR_sendto            353 /* new */
-#define __NR_send              354 /* new */
-#define __NR_recvfrom          355 /* new */
-#define __NR_recv              356 /* new */
-#define __NR_setsockopt                357 /* new */
-#define __NR_getsockopt                358 /* new */
-#define __NR_shutdown          359 /* new */
-#define __NR_sendmsg           360 /* new */
-#define __NR_recvmsg           361 /* new */
-#define __NR_accept4           362 /* new */
-#define __NR_preadv            363 /* new */
-#define __NR_pwritev           364 /* new */
-#define __NR_rt_tgsigqueueinfo 365 /* new */
-#define __NR_perf_event_open   366 /* new */
-#define __NR_recvmmsg          367 /* new */
-#define __NR_fanotify_init     368
-#define __NR_fanotify_mark     369
-#define __NR_prlimit64         370
-#define __NR_name_to_handle_at 371
-#define __NR_open_by_handle_at 372
-#define __NR_clock_adjtime     373
-#define __NR_syncfs            374
-#define __NR_setns             375
-#define __NR_sendmmsg          376
-#define __NR_process_vm_readv  377
-#define __NR_process_vm_writev 378
-
-#define __NR_syscalls          379
+#include <uapi/asm/unistd.h>
 
-#ifdef __KERNEL__
 #ifndef __ASSEMBLY__
 
 /* #define __ARCH_WANT_OLD_READDIR */
 #define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
 
 #endif /* __ASSEMBLY__ */
-#endif /* __KERNEL__ */
 #endif /* _ASM_MICROBLAZE_UNISTD_H */
index baebb3da1d44160fc6f6f259886656e6f494b167..6d7d7f4aaae8679846945e11c5ab0872c5cfdfb5 100644 (file)
@@ -1,3 +1,35 @@
 # UAPI Header export list
 include include/uapi/asm-generic/Kbuild.asm
 
+header-y += auxvec.h
+header-y += bitsperlong.h
+header-y += byteorder.h
+header-y += elf.h
+header-y += errno.h
+header-y += fcntl.h
+header-y += ioctl.h
+header-y += ioctls.h
+header-y += ipcbuf.h
+header-y += kvm_para.h
+header-y += mman.h
+header-y += msgbuf.h
+header-y += param.h
+header-y += poll.h
+header-y += posix_types.h
+header-y += ptrace.h
+header-y += resource.h
+header-y += sembuf.h
+header-y += setup.h
+header-y += shmbuf.h
+header-y += sigcontext.h
+header-y += siginfo.h
+header-y += signal.h
+header-y += socket.h
+header-y += sockios.h
+header-y += stat.h
+header-y += statfs.h
+header-y += swab.h
+header-y += termbits.h
+header-y += termios.h
+header-y += types.h
+header-y += unistd.h
diff --git a/arch/microblaze/include/uapi/asm/elf.h b/arch/microblaze/include/uapi/asm/elf.h
new file mode 100644 (file)
index 0000000..7eabd83
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu>
+ * Copyright (C) 2008-2009 PetaLogix
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _UAPI_ASM_MICROBLAZE_ELF_H
+#define _UAPI_ASM_MICROBLAZE_ELF_H
+
+/*
+ * Note there is no "official" ELF designation for Microblaze.
+ * I've snaffled the value from the microblaze binutils source code
+ * /binutils/microblaze/include/elf/microblaze.h
+ */
+#define EM_MICROBLAZE          189
+#define EM_MICROBLAZE_OLD      0xbaab
+#define ELF_ARCH               EM_MICROBLAZE
+
+/*
+ * This is used to ensure we don't load something for the wrong architecture.
+ */
+#define elf_check_arch(x)      ((x)->e_machine == EM_MICROBLAZE \
+                                || (x)->e_machine == EM_MICROBLAZE_OLD)
+
+/*
+ * These are used to set parameters in the core dumps.
+ */
+#define ELF_CLASS      ELFCLASS32
+
+#ifndef __uClinux__
+
+/*
+ * ELF register definitions..
+ */
+
+#include <asm/ptrace.h>
+#include <asm/byteorder.h>
+
+#ifndef ELF_GREG_T
+#define ELF_GREG_T
+typedef unsigned long elf_greg_t;
+#endif
+
+#ifndef ELF_NGREG
+#define ELF_NGREG (sizeof(struct pt_regs) / sizeof(elf_greg_t))
+#endif
+
+#ifndef ELF_GREGSET_T
+#define ELF_GREGSET_T
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+#endif
+
+#ifndef ELF_FPREGSET_T
+#define ELF_FPREGSET_T
+
+/* TBD */
+#define ELF_NFPREG     33      /* includes fsr */
+typedef unsigned long elf_fpreg_t;
+typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
+
+/* typedef struct user_fpu_struct elf_fpregset_t; */
+#endif
+
+/* This is the location that an ET_DYN program is loaded if exec'ed.  Typical
+ * use of this is to invoke "./ld.so someprog" to test out a new version of
+ * the loader.  We need to make sure that it is out of the way of the program
+ * that it will "exec", and that there is sufficient room for the brk.
+ */
+
+#define ELF_ET_DYN_BASE         (0x08000000)
+
+#ifdef __MICROBLAZEEL__
+#define ELF_DATA       ELFDATA2LSB
+#else
+#define ELF_DATA       ELFDATA2MSB
+#endif
+
+#define ELF_EXEC_PAGESIZE      PAGE_SIZE
+
+
+#define ELF_CORE_COPY_REGS(_dest, _regs)                       \
+       memcpy((char *) &_dest, (char *) _regs,         \
+       sizeof(struct pt_regs));
+
+/* This yields a mask that user programs can use to figure out what
+ * instruction set this CPU supports.  This could be done in user space,
+ * but it's not easy, and we've already done it here.
+ */
+#define ELF_HWCAP      (0)
+
+/* This yields a string that ld.so will use to load implementation
+ * specific libraries for optimization.  This is more specific in
+ * intent than poking at uname or /proc/cpuinfo.
+
+ * For the moment, we have only optimizations for the Intel generations,
+ * but that could change...
+ */
+#define ELF_PLATFORM  (NULL)
+
+/* Added _f parameter. Is this definition correct: TBD */
+#define ELF_PLAT_INIT(_r, _f)                          \
+do {                                                   \
+       _r->r1 =  _r->r1 =  _r->r2 =  _r->r3 =          \
+       _r->r4 =  _r->r5 =  _r->r6 =  _r->r7 =          \
+       _r->r8 =  _r->r9 =  _r->r10 = _r->r11 =         \
+       _r->r12 = _r->r13 = _r->r14 = _r->r15 =         \
+       _r->r16 = _r->r17 = _r->r18 = _r->r19 =         \
+       _r->r20 = _r->r21 = _r->r22 = _r->r23 =         \
+       _r->r24 = _r->r25 = _r->r26 = _r->r27 =         \
+       _r->r28 = _r->r29 = _r->r30 = _r->r31 =         \
+       0;                                              \
+} while (0)
+
+
+#endif /* __uClinux__ */
+
+#endif /* _UAPI_ASM_MICROBLAZE_ELF_H */
diff --git a/arch/microblaze/include/uapi/asm/ptrace.h b/arch/microblaze/include/uapi/asm/ptrace.h
new file mode 100644 (file)
index 0000000..d31238a
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _UAPI_ASM_MICROBLAZE_PTRACE_H
+#define _UAPI_ASM_MICROBLAZE_PTRACE_H
+
+#ifndef __ASSEMBLY__
+
+typedef unsigned long microblaze_reg_t;
+
+struct pt_regs {
+       microblaze_reg_t r0;
+       microblaze_reg_t r1;
+       microblaze_reg_t r2;
+       microblaze_reg_t r3;
+       microblaze_reg_t r4;
+       microblaze_reg_t r5;
+       microblaze_reg_t r6;
+       microblaze_reg_t r7;
+       microblaze_reg_t r8;
+       microblaze_reg_t r9;
+       microblaze_reg_t r10;
+       microblaze_reg_t r11;
+       microblaze_reg_t r12;
+       microblaze_reg_t r13;
+       microblaze_reg_t r14;
+       microblaze_reg_t r15;
+       microblaze_reg_t r16;
+       microblaze_reg_t r17;
+       microblaze_reg_t r18;
+       microblaze_reg_t r19;
+       microblaze_reg_t r20;
+       microblaze_reg_t r21;
+       microblaze_reg_t r22;
+       microblaze_reg_t r23;
+       microblaze_reg_t r24;
+       microblaze_reg_t r25;
+       microblaze_reg_t r26;
+       microblaze_reg_t r27;
+       microblaze_reg_t r28;
+       microblaze_reg_t r29;
+       microblaze_reg_t r30;
+       microblaze_reg_t r31;
+       microblaze_reg_t pc;
+       microblaze_reg_t msr;
+       microblaze_reg_t ear;
+       microblaze_reg_t esr;
+       microblaze_reg_t fsr;
+       int pt_mode;
+};
+
+#ifndef __KERNEL__
+
+/* pt_regs offsets used by gdbserver etc in ptrace syscalls */
+#define PT_GPR(n)      ((n) * sizeof(microblaze_reg_t))
+#define PT_PC          (32 * sizeof(microblaze_reg_t))
+#define PT_MSR         (33 * sizeof(microblaze_reg_t))
+#define PT_EAR         (34 * sizeof(microblaze_reg_t))
+#define PT_ESR         (35 * sizeof(microblaze_reg_t))
+#define PT_FSR         (36 * sizeof(microblaze_reg_t))
+#define PT_KERNEL_MODE (37 * sizeof(microblaze_reg_t))
+
+#endif /* __KERNEL */
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _UAPI_ASM_MICROBLAZE_PTRACE_H */
diff --git a/arch/microblaze/include/uapi/asm/setup.h b/arch/microblaze/include/uapi/asm/setup.h
new file mode 100644 (file)
index 0000000..76bc2ac
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu>
+ * Copyright (C) 2007-2009 PetaLogix
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _UAPI_ASM_MICROBLAZE_SETUP_H
+#define _UAPI_ASM_MICROBLAZE_SETUP_H
+
+#define COMMAND_LINE_SIZE      256
+
+# ifndef __ASSEMBLY__
+
+# endif /* __ASSEMBLY__ */
+#endif /* _UAPI_ASM_MICROBLAZE_SETUP_H */
diff --git a/arch/microblaze/include/uapi/asm/unistd.h b/arch/microblaze/include/uapi/asm/unistd.h
new file mode 100644 (file)
index 0000000..bbeaa2d
--- /dev/null
@@ -0,0 +1,400 @@
+/*
+ * Copyright (C) 2007-2008 Michal Simek <monstr@monstr.eu>
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _UAPI_ASM_MICROBLAZE_UNISTD_H
+#define _UAPI_ASM_MICROBLAZE_UNISTD_H
+
+#define __NR_restart_syscall   0 /* ok */
+#define __NR_exit              1 /* ok */
+#define __NR_fork              2 /* not for no MMU - weird */
+#define __NR_read              3 /* ok */
+#define __NR_write             4 /* ok */
+#define __NR_open              5 /* openat */
+#define __NR_close             6 /* ok */
+#define __NR_waitpid           7 /* waitid */
+#define __NR_creat             8 /* openat */
+#define __NR_link              9 /* linkat */
+#define __NR_unlink            10 /* unlinkat */
+#define __NR_execve            11 /* ok */
+#define __NR_chdir             12 /* ok */
+#define __NR_time              13 /* obsolete -> sys_gettimeofday */
+#define __NR_mknod             14 /* mknodat */
+#define __NR_chmod             15 /* fchmodat */
+#define __NR_lchown            16 /* ok */
+#define __NR_break             17 /* don't know */
+#define __NR_oldstat           18 /* remove */
+#define __NR_lseek             19 /* ok */
+#define __NR_getpid            20 /* ok */
+#define __NR_mount             21 /* ok */
+#define __NR_umount            22 /* ok */  /* use only umount2 */
+#define __NR_setuid            23 /* ok */
+#define __NR_getuid            24 /* ok */
+#define __NR_stime             25 /* obsolete -> sys_settimeofday */
+#define __NR_ptrace            26 /* ok */
+#define __NR_alarm             27 /* obsolete -> sys_setitimer */
+#define __NR_oldfstat          28 /* remove */
+#define __NR_pause             29 /* obsolete -> sys_rt_sigtimedwait */
+#define __NR_utime             30 /* obsolete -> sys_utimesat */
+#define __NR_stty              31 /* remove */
+#define __NR_gtty              32 /* remove */
+#define __NR_access            33 /* faccessat */
+/* can be implemented by sys_setpriority */
+#define __NR_nice              34
+#define __NR_ftime             35 /* remove */
+#define __NR_sync              36 /* ok */
+#define __NR_kill              37 /* ok */
+#define __NR_rename            38 /* renameat */
+#define __NR_mkdir             39 /* mkdirat */
+#define __NR_rmdir             40 /* unlinkat */
+#define __NR_dup               41 /* ok */
+#define __NR_pipe              42 /* ok */
+#define __NR_times             43 /* ok */
+#define __NR_prof              44 /* remove */
+#define __NR_brk               45 /* ok -mmu, nommu specific */
+#define __NR_setgid            46 /* ok */
+#define __NR_getgid            47 /* ok */
+#define __NR_signal            48 /* obsolete -> sys_rt_sigaction */
+#define __NR_geteuid           49 /* ok */
+#define __NR_getegid           50 /* ok */
+#define __NR_acct              51 /* add it and then I can disable it */
+#define __NR_umount2           52 /* remove */
+#define __NR_lock              53 /* remove */
+#define __NR_ioctl             54 /* ok */
+#define __NR_fcntl             55 /* ok -> 64bit version*/
+#define __NR_mpx               56 /* remove */
+#define __NR_setpgid           57 /* ok */
+#define __NR_ulimit            58 /* remove */
+#define __NR_oldolduname       59 /* remove */
+#define __NR_umask             60 /* ok */
+#define __NR_chroot            61 /* ok */
+#define __NR_ustat             62 /* obsolete -> statfs64 */
+#define __NR_dup2              63 /* ok */
+#define __NR_getppid           64 /* ok */
+#define __NR_getpgrp           65 /* obsolete -> sys_getpgid */
+#define __NR_setsid            66 /* ok */
+#define __NR_sigaction         67 /* obsolete -> rt_sigaction */
+#define __NR_sgetmask          68 /* obsolete -> sys_rt_sigprocmask */
+#define __NR_ssetmask          69 /* obsolete ->sys_rt_sigprocmask */
+#define __NR_setreuid          70 /* ok */
+#define __NR_setregid          71 /* ok */
+#define __NR_sigsuspend                72 /* obsolete -> rt_sigsuspend */
+#define __NR_sigpending                73 /* obsolete -> sys_rt_sigpending */
+#define __NR_sethostname       74 /* ok */
+#define __NR_setrlimit         75 /* ok */
+#define __NR_getrlimit         76 /* ok Back compatible 2G limited rlimit */
+#define __NR_getrusage         77 /* ok */
+#define __NR_gettimeofday      78 /* ok */
+#define __NR_settimeofday      79 /* ok */
+#define __NR_getgroups         80 /* ok */
+#define __NR_setgroups         81 /* ok */
+#define __NR_select            82 /* obsolete -> sys_pselect7 */
+#define __NR_symlink           83 /* symlinkat */
+#define __NR_oldlstat          84 /* remove */
+#define __NR_readlink          85 /* obsolete -> sys_readlinkat */
+#define __NR_uselib            86 /* remove */
+#define __NR_swapon            87 /* ok */
+#define __NR_reboot            88 /* ok */
+#define __NR_readdir           89 /* remove ? */
+#define __NR_mmap              90 /* obsolete -> sys_mmap2 */
+#define __NR_munmap            91 /* ok - mmu and nommu */
+#define __NR_truncate          92 /* ok or truncate64 */
+#define __NR_ftruncate         93 /* ok or ftruncate64 */
+#define __NR_fchmod            94 /* ok */
+#define __NR_fchown            95 /* ok */
+#define __NR_getpriority       96 /* ok */
+#define __NR_setpriority       97 /* ok */
+#define __NR_profil            98 /* remove */
+#define __NR_statfs            99 /* ok or statfs64 */
+#define __NR_fstatfs           100  /* ok or fstatfs64 */
+#define __NR_ioperm            101 /* remove */
+#define __NR_socketcall                102 /* remove */
+#define __NR_syslog            103 /* ok */
+#define __NR_setitimer         104 /* ok */
+#define __NR_getitimer         105 /* ok */
+#define __NR_stat              106 /* remove */
+#define __NR_lstat             107 /* remove */
+#define __NR_fstat             108 /* remove */
+#define __NR_olduname          109 /* remove */
+#define __NR_iopl              110 /* remove */
+#define __NR_vhangup           111 /* ok */
+#define __NR_idle              112 /* remove */
+#define __NR_vm86old           113 /* remove */
+#define __NR_wait4             114 /* obsolete -> waitid */
+#define __NR_swapoff           115 /* ok */
+#define __NR_sysinfo           116 /* ok */
+#define __NR_ipc               117 /* remove - direct call */
+#define __NR_fsync             118 /* ok */
+#define __NR_sigreturn         119 /* obsolete -> sys_rt_sigreturn */
+#define __NR_clone             120 /* ok */
+#define __NR_setdomainname     121 /* ok */
+#define __NR_uname             122 /* remove */
+#define __NR_modify_ldt                123 /* remove */
+#define __NR_adjtimex          124 /* ok */
+#define __NR_mprotect          125 /* remove */
+#define __NR_sigprocmask       126 /* obsolete -> sys_rt_sigprocmask */
+#define __NR_create_module     127 /* remove */
+#define __NR_init_module       128 /* ok */
+#define __NR_delete_module     129 /* ok */
+#define __NR_get_kernel_syms   130 /* remove */
+#define __NR_quotactl          131 /* ok */
+#define __NR_getpgid           132 /* ok */
+#define __NR_fchdir            133 /* ok */
+#define __NR_bdflush           134 /* remove */
+#define __NR_sysfs             135 /* needed for busybox */
+#define __NR_personality       136 /* ok */
+#define __NR_afs_syscall       137 /* Syscall for Andrew File System */
+#define __NR_setfsuid          138 /* ok */
+#define __NR_setfsgid          139 /* ok */
+#define __NR__llseek           140 /* remove only lseek */
+#define __NR_getdents          141 /* ok or getdents64 */
+#define __NR__newselect                142 /* remove */
+#define __NR_flock             143 /* ok */
+#define __NR_msync             144 /* remove */
+#define __NR_readv             145 /* ok */
+#define __NR_writev            146 /* ok */
+#define __NR_getsid            147 /* ok */
+#define __NR_fdatasync         148 /* ok */
+#define __NR__sysctl           149 /* remove */
+#define __NR_mlock             150 /* ok - nommu or mmu */
+#define __NR_munlock           151 /* ok - nommu or mmu */
+#define __NR_mlockall          152 /* ok - nommu or mmu */
+#define __NR_munlockall                153 /* ok - nommu or mmu */
+#define __NR_sched_setparam            154 /* ok */
+#define __NR_sched_getparam            155 /* ok */
+#define __NR_sched_setscheduler                156 /* ok */
+#define __NR_sched_getscheduler                157 /* ok */
+#define __NR_sched_yield               158 /* ok */
+#define __NR_sched_get_priority_max    159 /* ok */
+#define __NR_sched_get_priority_min    160 /* ok */
+#define __NR_sched_rr_get_interval     161 /* ok */
+#define __NR_nanosleep         162 /* ok */
+#define __NR_mremap            163 /* ok - nommu or mmu */
+#define __NR_setresuid         164 /* ok */
+#define __NR_getresuid         165 /* ok */
+#define __NR_vm86              166 /* remove */
+#define __NR_query_module      167 /* ok */
+#define __NR_poll              168 /* obsolete -> sys_ppoll */
+#define __NR_nfsservctl                169 /* ok */
+#define __NR_setresgid         170 /* ok */
+#define __NR_getresgid         171 /* ok */
+#define __NR_prctl             172 /* ok */
+#define __NR_rt_sigreturn      173 /* ok */
+#define __NR_rt_sigaction      174 /* ok */
+#define __NR_rt_sigprocmask    175 /* ok */
+#define __NR_rt_sigpending     176 /* ok */
+#define __NR_rt_sigtimedwait   177 /* ok */
+#define __NR_rt_sigqueueinfo   178 /* ok */
+#define __NR_rt_sigsuspend     179 /* ok */
+#define __NR_pread64           180 /* ok */
+#define __NR_pwrite64          181 /* ok */
+#define __NR_chown             182 /* obsolete -> fchownat */
+#define __NR_getcwd            183 /* ok */
+#define __NR_capget            184 /* ok */
+#define __NR_capset            185 /* ok */
+#define __NR_sigaltstack       186 /* remove */
+#define __NR_sendfile          187 /* ok -> exist 64bit version*/
+#define __NR_getpmsg           188 /* remove */
+/* remove - some people actually want streams */
+#define __NR_putpmsg           189
+/* for noMMU - group with clone -> maybe remove */
+#define __NR_vfork             190
+#define __NR_ugetrlimit                191 /* remove - SuS compliant getrlimit */
+#define __NR_mmap2             192 /* ok */
+#define __NR_truncate64                193 /* ok */
+#define __NR_ftruncate64       194 /* ok */
+#define __NR_stat64            195 /* remove _ARCH_WANT_STAT64 */
+#define __NR_lstat64           196 /* remove _ARCH_WANT_STAT64 */
+#define __NR_fstat64           197 /* remove _ARCH_WANT_STAT64 */
+#define __NR_lchown32          198 /* ok - without 32 */
+#define __NR_getuid32          199 /* ok - without 32 */
+#define __NR_getgid32          200 /* ok - without 32 */
+#define __NR_geteuid32         201 /* ok - without 32 */
+#define __NR_getegid32         202 /* ok - without 32 */
+#define __NR_setreuid32                203 /* ok - without 32 */
+#define __NR_setregid32                204 /* ok - without 32 */
+#define __NR_getgroups32       205 /* ok - without 32 */
+#define __NR_setgroups32       206 /* ok - without 32 */
+#define __NR_fchown32          207 /* ok - without 32 */
+#define __NR_setresuid32       208 /* ok - without 32 */
+#define __NR_getresuid32       209 /* ok - without 32 */
+#define __NR_setresgid32       210 /* ok - without 32 */
+#define __NR_getresgid32       211 /* ok - without 32 */
+#define __NR_chown32           212 /* ok - without 32 -obsolete -> fchownat */
+#define __NR_setuid32          213 /* ok - without 32 */
+#define __NR_setgid32          214 /* ok - without 32 */
+#define __NR_setfsuid32                215 /* ok - without 32 */
+#define __NR_setfsgid32                216 /* ok - without 32 */
+#define __NR_pivot_root                217 /* ok */
+#define __NR_mincore           218 /* ok */
+#define __NR_madvise           219 /* ok */
+#define __NR_getdents64                220 /* ok */
+#define __NR_fcntl64           221 /* ok */
+/* 223 is unused */
+#define __NR_gettid            224 /* ok */
+#define __NR_readahead         225 /* ok */
+#define __NR_setxattr          226 /* ok */
+#define __NR_lsetxattr         227 /* ok */
+#define __NR_fsetxattr         228 /* ok */
+#define __NR_getxattr          229 /* ok */
+#define __NR_lgetxattr         230 /* ok */
+#define __NR_fgetxattr         231 /* ok */
+#define __NR_listxattr         232 /* ok */
+#define __NR_llistxattr                233 /* ok */
+#define __NR_flistxattr                234 /* ok */
+#define __NR_removexattr       235 /* ok */
+#define __NR_lremovexattr      236 /* ok */
+#define __NR_fremovexattr      237 /* ok */
+#define __NR_tkill             238 /* ok */
+#define __NR_sendfile64                239 /* ok */
+#define __NR_futex             240 /* ok */
+#define __NR_sched_setaffinity 241 /* ok */
+#define __NR_sched_getaffinity 242 /* ok */
+#define __NR_set_thread_area   243 /* remove */
+#define __NR_get_thread_area   244 /* remove */
+#define __NR_io_setup          245 /* ok */
+#define __NR_io_destroy                246 /* ok */
+#define __NR_io_getevents      247 /* ok */
+#define __NR_io_submit         248 /* ok */
+#define __NR_io_cancel         249 /* ok */
+#define __NR_fadvise64         250 /* remove -> sys_fadvise64_64 */
+/* 251 is available for reuse (was briefly sys_set_zone_reclaim) */
+#define __NR_exit_group                252 /* ok */
+#define __NR_lookup_dcookie    253 /* ok */
+#define __NR_epoll_create      254 /* ok */
+#define __NR_epoll_ctl         255 /* ok */
+#define __NR_epoll_wait                256 /* obsolete -> sys_epoll_pwait */
+#define __NR_remap_file_pages  257 /* only for mmu */
+#define __NR_set_tid_address   258 /* ok */
+#define __NR_timer_create      259 /* ok */
+#define __NR_timer_settime     (__NR_timer_create+1) /* 260 */ /* ok */
+#define __NR_timer_gettime     (__NR_timer_create+2) /* 261 */ /* ok */
+#define __NR_timer_getoverrun  (__NR_timer_create+3) /* 262 */ /* ok */
+#define __NR_timer_delete      (__NR_timer_create+4) /* 263 */ /* ok */
+#define __NR_clock_settime     (__NR_timer_create+5) /* 264 */ /* ok */
+#define __NR_clock_gettime     (__NR_timer_create+6) /* 265 */ /* ok */
+#define __NR_clock_getres      (__NR_timer_create+7) /* 266 */ /* ok */
+#define __NR_clock_nanosleep   (__NR_timer_create+8) /* 267 */ /* ok */
+#define __NR_statfs64          268 /* ok */
+#define __NR_fstatfs64         269 /* ok */
+#define __NR_tgkill            270 /* ok */
+#define __NR_utimes            271 /* obsolete -> sys_futimesat */
+#define __NR_fadvise64_64      272 /* ok */
+#define __NR_vserver           273 /* ok */
+#define __NR_mbind             274 /* only for mmu */
+#define __NR_get_mempolicy     275 /* only for mmu */
+#define __NR_set_mempolicy     276 /* only for mmu */
+#define __NR_mq_open           277 /* ok */
+#define __NR_mq_unlink         (__NR_mq_open+1) /* 278 */ /* ok */
+#define __NR_mq_timedsend      (__NR_mq_open+2) /* 279 */ /* ok */
+#define __NR_mq_timedreceive   (__NR_mq_open+3) /* 280 */ /* ok */
+#define __NR_mq_notify         (__NR_mq_open+4) /* 281 */ /* ok */
+#define __NR_mq_getsetattr     (__NR_mq_open+5) /* 282 */ /* ok */
+#define __NR_kexec_load                283 /* ok */
+#define __NR_waitid            284 /* ok */
+/* #define __NR_sys_setaltroot 285 */
+#define __NR_add_key           286 /* ok */
+#define __NR_request_key       287 /* ok */
+#define __NR_keyctl            288 /* ok */
+#define __NR_ioprio_set                289 /* ok */
+#define __NR_ioprio_get                290 /* ok */
+#define __NR_inotify_init      291 /* ok */
+#define __NR_inotify_add_watch 292 /* ok */
+#define __NR_inotify_rm_watch  293 /* ok */
+#define __NR_migrate_pages     294 /* mmu */
+#define __NR_openat            295 /* ok */
+#define __NR_mkdirat           296 /* ok */
+#define __NR_mknodat           297 /* ok */
+#define __NR_fchownat          298 /* ok */
+#define __NR_futimesat         299 /* obsolete -> sys_utimesat */
+#define __NR_fstatat64         300 /* stat64 */
+#define __NR_unlinkat          301 /* ok */
+#define __NR_renameat          302 /* ok */
+#define __NR_linkat            303 /* ok */
+#define __NR_symlinkat         304 /* ok */
+#define __NR_readlinkat                305 /* ok */
+#define __NR_fchmodat          306 /* ok */
+#define __NR_faccessat         307 /* ok */
+#define __NR_pselect6          308 /* obsolete -> sys_pselect7 */
+#define __NR_ppoll             309 /* ok */
+#define __NR_unshare           310 /* ok */
+#define __NR_set_robust_list   311 /* ok */
+#define __NR_get_robust_list   312 /* ok */
+#define __NR_splice            313 /* ok */
+#define __NR_sync_file_range   314 /* ok */
+#define __NR_tee               315 /* ok */
+#define __NR_vmsplice          316 /* ok */
+#define __NR_move_pages                317 /* mmu */
+#define __NR_getcpu            318 /* ok */
+#define __NR_epoll_pwait       319 /* ok */
+#define __NR_utimensat         320 /* ok */
+#define __NR_signalfd          321 /* ok */
+#define __NR_timerfd_create    322 /* ok */
+#define __NR_eventfd           323 /* ok */
+#define __NR_fallocate         324 /* ok */
+#define __NR_semtimedop                325 /* ok - semaphore group */
+#define __NR_timerfd_settime   326 /* ok */
+#define __NR_timerfd_gettime   327 /* ok */
+/* sysv ipc syscalls */
+#define __NR_semctl            328 /* ok */
+#define __NR_semget            329 /* ok */
+#define __NR_semop             330 /* ok */
+#define __NR_msgctl            331 /* ok */
+#define __NR_msgget            332 /* ok */
+#define __NR_msgrcv            333 /* ok */
+#define __NR_msgsnd            334 /* ok */
+#define __NR_shmat             335 /* ok */
+#define __NR_shmctl            336 /* ok */
+#define __NR_shmdt             337 /* ok */
+#define __NR_shmget            338 /* ok */
+
+
+#define __NR_signalfd4         339 /* new */
+#define __NR_eventfd2          340 /* new */
+#define __NR_epoll_create1     341 /* new */
+#define __NR_dup3              342 /* new */
+#define __NR_pipe2             343 /* new */
+#define __NR_inotify_init1     344 /* new */
+#define __NR_socket            345 /* new */
+#define __NR_socketpair                346 /* new */
+#define __NR_bind              347 /* new */
+#define __NR_listen            348 /* new */
+#define __NR_accept            349 /* new */
+#define __NR_connect           350 /* new */
+#define __NR_getsockname       351 /* new */
+#define __NR_getpeername       352 /* new */
+#define __NR_sendto            353 /* new */
+#define __NR_send              354 /* new */
+#define __NR_recvfrom          355 /* new */
+#define __NR_recv              356 /* new */
+#define __NR_setsockopt                357 /* new */
+#define __NR_getsockopt                358 /* new */
+#define __NR_shutdown          359 /* new */
+#define __NR_sendmsg           360 /* new */
+#define __NR_recvmsg           361 /* new */
+#define __NR_accept4           362 /* new */
+#define __NR_preadv            363 /* new */
+#define __NR_pwritev           364 /* new */
+#define __NR_rt_tgsigqueueinfo 365 /* new */
+#define __NR_perf_event_open   366 /* new */
+#define __NR_recvmmsg          367 /* new */
+#define __NR_fanotify_init     368
+#define __NR_fanotify_mark     369
+#define __NR_prlimit64         370
+#define __NR_name_to_handle_at 371
+#define __NR_open_by_handle_at 372
+#define __NR_clock_adjtime     373
+#define __NR_syncfs            374
+#define __NR_setns             375
+#define __NR_sendmmsg          376
+#define __NR_process_vm_readv  377
+#define __NR_process_vm_writev 378
+
+#define __NR_syscalls          379
+
+#endif /* _UAPI_ASM_MICROBLAZE_UNISTD_H */
index 4183e62f178cd9d85027c32e95392f2f51f409ad..ce6c9a6907311c72e4db62de0bf4db219567a2ab 100644 (file)
@@ -19,6 +19,7 @@ config MIPS
        select HAVE_KRETPROBES
        select HAVE_DEBUG_KMEMLEAK
        select ARCH_BINFMT_ELF_RANDOMIZE_PIE
+       select HAVE_ARCH_TRANSPARENT_HUGEPAGE
        select RTC_LIB if !MACH_LOONGSON
        select GENERIC_ATOMIC64 if !64BIT
        select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
@@ -776,6 +777,7 @@ config CAVIUM_OCTEON_REFERENCE_BOARD
        select DMA_COHERENT
        select SYS_SUPPORTS_64BIT_KERNEL
        select SYS_SUPPORTS_BIG_ENDIAN
+       select EDAC_SUPPORT
        select SYS_SUPPORTS_HOTPLUG_CPU
        select SYS_HAS_EARLY_PRINTK
        select SYS_HAS_CPU_CAVIUM_OCTEON
@@ -1079,6 +1081,9 @@ config SYS_SUPPORTS_HUGETLBFS
        depends on CPU_SUPPORTS_HUGEPAGES && 64BIT
        default y
 
+config MIPS_HUGE_TLB_SUPPORT
+       def_bool HUGETLB_PAGE || TRANSPARENT_HUGEPAGE
+
 config IRQ_CPU
        bool
 
@@ -1370,6 +1375,7 @@ config CPU_R4X00
        depends on SYS_HAS_CPU_R4X00
        select CPU_SUPPORTS_32BIT_KERNEL
        select CPU_SUPPORTS_64BIT_KERNEL
+       select CPU_SUPPORTS_HUGEPAGES
        help
          MIPS Technologies R4000-series processors other than 4300, including
          the R4000, R4400, R4600, and 4700.
@@ -1380,12 +1386,14 @@ config CPU_TX49XX
        select CPU_HAS_PREFETCH
        select CPU_SUPPORTS_32BIT_KERNEL
        select CPU_SUPPORTS_64BIT_KERNEL
+       select CPU_SUPPORTS_HUGEPAGES
 
 config CPU_R5000
        bool "R5000"
        depends on SYS_HAS_CPU_R5000
        select CPU_SUPPORTS_32BIT_KERNEL
        select CPU_SUPPORTS_64BIT_KERNEL
+       select CPU_SUPPORTS_HUGEPAGES
        help
          MIPS Technologies R5000-series processors other than the Nevada.
 
@@ -1394,6 +1402,7 @@ config CPU_R5432
        depends on SYS_HAS_CPU_R5432
        select CPU_SUPPORTS_32BIT_KERNEL
        select CPU_SUPPORTS_64BIT_KERNEL
+       select CPU_SUPPORTS_HUGEPAGES
 
 config CPU_R5500
        bool "R5500"
@@ -1419,6 +1428,7 @@ config CPU_NEVADA
        depends on SYS_HAS_CPU_NEVADA
        select CPU_SUPPORTS_32BIT_KERNEL
        select CPU_SUPPORTS_64BIT_KERNEL
+       select CPU_SUPPORTS_HUGEPAGES
        help
          QED / PMC-Sierra RM52xx-series ("Nevada") processors.
 
@@ -1439,6 +1449,7 @@ config CPU_R10000
        select CPU_SUPPORTS_32BIT_KERNEL
        select CPU_SUPPORTS_64BIT_KERNEL
        select CPU_SUPPORTS_HIGHMEM
+       select CPU_SUPPORTS_HUGEPAGES
        help
          MIPS Technologies R10000-series processors.
 
@@ -1449,6 +1460,7 @@ config CPU_RM7000
        select CPU_SUPPORTS_32BIT_KERNEL
        select CPU_SUPPORTS_64BIT_KERNEL
        select CPU_SUPPORTS_HIGHMEM
+       select CPU_SUPPORTS_HUGEPAGES
 
 config CPU_RM9000
        bool "RM9000"
@@ -1457,6 +1469,7 @@ config CPU_RM9000
        select CPU_SUPPORTS_32BIT_KERNEL
        select CPU_SUPPORTS_64BIT_KERNEL
        select CPU_SUPPORTS_HIGHMEM
+       select CPU_SUPPORTS_HUGEPAGES
        select WEAK_ORDERING
 
 config CPU_SB1
@@ -1465,6 +1478,7 @@ config CPU_SB1
        select CPU_SUPPORTS_32BIT_KERNEL
        select CPU_SUPPORTS_64BIT_KERNEL
        select CPU_SUPPORTS_HIGHMEM
+       select CPU_SUPPORTS_HUGEPAGES
        select WEAK_ORDERING
 
 config CPU_CAVIUM_OCTEON
@@ -1528,9 +1542,9 @@ config CPU_XLR
        select CPU_SUPPORTS_32BIT_KERNEL
        select CPU_SUPPORTS_64BIT_KERNEL
        select CPU_SUPPORTS_HIGHMEM
+       select CPU_SUPPORTS_HUGEPAGES
        select WEAK_ORDERING
        select WEAK_REORDERING_BEYOND_LLSC
-       select CPU_SUPPORTS_HUGEPAGES
        help
          Netlogic Microsystems XLR/XLS processors.
 
@@ -1591,6 +1605,7 @@ config CPU_LOONGSON2
        select CPU_SUPPORTS_32BIT_KERNEL
        select CPU_SUPPORTS_64BIT_KERNEL
        select CPU_SUPPORTS_HIGHMEM
+       select CPU_SUPPORTS_HUGEPAGES
 
 config CPU_LOONGSON1
        bool
index 407ebc00e661f974bbaec96a345afcea8f6b6409..cb83d8d21aef33877d718b7494e0afa11b8b9a99 100644 (file)
@@ -6,7 +6,7 @@
 #
 
 obj-y += prom.o time.o clocks.o platform.o power.o setup.o \
-       sleeper.o dma.o dbdma.o vss.o irq.o
+       sleeper.o dma.o dbdma.o vss.o irq.o usb.o
 
 # optional gpiolib support
 ifeq ($(CONFIG_ALCHEMY_GPIO_INDIRECT),)
index c0f3ce6dcb56d448bcb2184c5fdc2c61498a8d7c..7af941d8e717089cdb78b016368774a09e3bd4ef 100644 (file)
@@ -17,6 +17,8 @@
 #include <linux/platform_device.h>
 #include <linux/serial_8250.h>
 #include <linux/slab.h>
+#include <linux/usb/ehci_pdriver.h>
+#include <linux/usb/ohci_pdriver.h>
 
 #include <asm/mach-au1x00/au1000.h>
 #include <asm/mach-au1x00/au1xxx_dbdma.h>
@@ -122,6 +124,53 @@ static void __init alchemy_setup_uarts(int ctype)
 static u64 alchemy_ohci_dmamask = DMA_BIT_MASK(32);
 static u64 __maybe_unused alchemy_ehci_dmamask = DMA_BIT_MASK(32);
 
+/* Power on callback for the ehci platform driver */
+static int alchemy_ehci_power_on(struct platform_device *pdev)
+{
+       return alchemy_usb_control(ALCHEMY_USB_EHCI0, 1);
+}
+
+/* Power off/suspend callback for the ehci platform driver */
+static void alchemy_ehci_power_off(struct platform_device *pdev)
+{
+       alchemy_usb_control(ALCHEMY_USB_EHCI0, 0);
+}
+
+static struct usb_ehci_pdata alchemy_ehci_pdata = {
+       .no_io_watchdog = 1,
+       .power_on       = alchemy_ehci_power_on,
+       .power_off      = alchemy_ehci_power_off,
+       .power_suspend  = alchemy_ehci_power_off,
+};
+
+/* Power on callback for the ohci platform driver */
+static int alchemy_ohci_power_on(struct platform_device *pdev)
+{
+       int unit;
+
+       unit = (pdev->id == 1) ?
+               ALCHEMY_USB_OHCI1 : ALCHEMY_USB_OHCI0;
+
+       return alchemy_usb_control(unit, 1);
+}
+
+/* Power off/suspend callback for the ohci platform driver */
+static void alchemy_ohci_power_off(struct platform_device *pdev)
+{
+       int unit;
+
+       unit = (pdev->id == 1) ?
+               ALCHEMY_USB_OHCI1 : ALCHEMY_USB_OHCI0;
+
+       alchemy_usb_control(unit, 0);
+}
+
+static struct usb_ohci_pdata alchemy_ohci_pdata = {
+       .power_on               = alchemy_ohci_power_on,
+       .power_off              = alchemy_ohci_power_off,
+       .power_suspend          = alchemy_ohci_power_off,
+};
+
 static unsigned long alchemy_ohci_data[][2] __initdata = {
        [ALCHEMY_CPU_AU1000] = { AU1000_USB_OHCI_PHYS_ADDR, AU1000_USB_HOST_INT },
        [ALCHEMY_CPU_AU1500] = { AU1000_USB_OHCI_PHYS_ADDR, AU1500_USB_HOST_INT },
@@ -169,9 +218,10 @@ static void __init alchemy_setup_usb(int ctype)
        res[1].start = alchemy_ohci_data[ctype][1];
        res[1].end = res[1].start;
        res[1].flags = IORESOURCE_IRQ;
-       pdev->name = "au1xxx-ohci";
+       pdev->name = "ohci-platform";
        pdev->id = 0;
        pdev->dev.dma_mask = &alchemy_ohci_dmamask;
+       pdev->dev.platform_data = &alchemy_ohci_pdata;
 
        if (platform_device_register(pdev))
                printk(KERN_INFO "Alchemy USB: cannot add OHCI0\n");
@@ -188,9 +238,10 @@ static void __init alchemy_setup_usb(int ctype)
                res[1].start = alchemy_ehci_data[ctype][1];
                res[1].end = res[1].start;
                res[1].flags = IORESOURCE_IRQ;
-               pdev->name = "au1xxx-ehci";
+               pdev->name = "ehci-platform";
                pdev->id = 0;
                pdev->dev.dma_mask = &alchemy_ehci_dmamask;
+               pdev->dev.platform_data = &alchemy_ehci_pdata;
 
                if (platform_device_register(pdev))
                        printk(KERN_INFO "Alchemy USB: cannot add EHCI0\n");
@@ -207,9 +258,10 @@ static void __init alchemy_setup_usb(int ctype)
                res[1].start = AU1300_USB_INT;
                res[1].end = res[1].start;
                res[1].flags = IORESOURCE_IRQ;
-               pdev->name = "au1xxx-ohci";
+               pdev->name = "ohci-platform";
                pdev->id = 1;
                pdev->dev.dma_mask = &alchemy_ohci_dmamask;
+               pdev->dev.platform_data = &alchemy_ohci_pdata;
 
                if (platform_device_register(pdev))
                        printk(KERN_INFO "Alchemy USB: cannot add OHCI1\n");
index d43ceff5be4782b7024ae0f04ad73f278d4d7486..48a4c70b3842276486d88179b1919917106e773e 100644 (file)
@@ -43,8 +43,8 @@ static void early_nvram_init(void)
 #ifdef CONFIG_BCM47XX_SSB
        case BCM47XX_BUS_TYPE_SSB:
                mcore_ssb = &bcm47xx_bus.ssb.mipscore;
-               base = mcore_ssb->flash_window;
-               lim = mcore_ssb->flash_window_size;
+               base = mcore_ssb->pflash.window;
+               lim = mcore_ssb->pflash.window_size;
                break;
 #endif
 #ifdef CONFIG_BCM47XX_BCMA
index e9f9ec8d443b5b959ef4b164b0a46197cad7ebb9..e80d585731aa8ed8d2e89597e2ddeb65150ce036 100644 (file)
@@ -156,10 +156,10 @@ static int __init wgt634u_init(void)
                                            SSB_CHIPCO_IRQ_GPIO);
                }
 
-               wgt634u_flash_data.width = mcore->flash_buswidth;
-               wgt634u_flash_resource.start = mcore->flash_window;
-               wgt634u_flash_resource.end = mcore->flash_window
-                                          + mcore->flash_window_size
+               wgt634u_flash_data.width = mcore->pflash.buswidth;
+               wgt634u_flash_resource.start = mcore->pflash.window;
+               wgt634u_flash_resource.end = mcore->pflash.window
+                                          + mcore->pflash.window_size
                                           - 1;
                return platform_add_devices(wgt634u_devices,
                                            ARRAY_SIZE(wgt634u_devices));
index 04dd8ff0e0d8979b639c60b932be4eabee951903..60ed700a956d6b2c3f9abe05ead4a9c1d6e9c8f3 100644 (file)
@@ -4,9 +4,11 @@
  * for more details.
  *
  * Copyright (C) 2004-2007 Cavium Networks
- * Copyright (C) 2008 Wind River Systems
+ * Copyright (C) 2008, 2009 Wind River Systems
+ *   written by Ralf Baechle <ralf@linux-mips.org>
  */
 #include <linux/init.h>
+#include <linux/kernel.h>
 #include <linux/console.h>
 #include <linux/delay.h>
 #include <linux/export.h>
@@ -821,3 +823,29 @@ void __init device_tree_init(void)
        }
        unflatten_device_tree();
 }
+
+static char *edac_device_names[] = {
+       "co_l2c_edac",
+       "co_lmc_edac",
+       "co_pc_edac",
+};
+
+static int __init edac_devinit(void)
+{
+       struct platform_device *dev;
+       int i, err = 0;
+       char *name;
+
+       for (i = 0; i < ARRAY_SIZE(edac_device_names); i++) {
+               name = edac_device_names[i];
+               dev = platform_device_register_simple(name, -1, NULL, 0);
+               if (IS_ERR(dev)) {
+                       pr_err("Registation of %s failed!\n", name);
+                       err = PTR_ERR(dev);
+               }
+       }
+
+       return err;
+}
+
+device_initcall(edac_devinit);
index 75165dfa60c10990216691c95c2f25530b0a1fdf..014ba4bbba7d25ff8c2662852955c193da8c7b0d 100644 (file)
@@ -1,7 +1,11 @@
 CONFIG_CAVIUM_OCTEON_REFERENCE_BOARD=y
+CONFIG_CAVIUM_CN63XXP1=y
 CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE=2
 CONFIG_SPARSEMEM_MANUAL=y
+CONFIG_TRANSPARENT_HUGEPAGE=y
 CONFIG_SMP=y
+CONFIG_NR_CPUS=32
+CONFIG_HZ_100=y
 CONFIG_PREEMPT=y
 CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
@@ -11,16 +15,15 @@ CONFIG_BSD_PROCESS_ACCT_V3=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_RELAY=y
 CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EXPERT=y
-# CONFIG_PCSPKR_PLATFORM is not set
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
+CONFIG_PCI=y
+CONFIG_PCI_MSI=y
 CONFIG_MIPS32_COMPAT=y
 CONFIG_MIPS32_O32=y
 CONFIG_MIPS32_N32=y
@@ -42,22 +45,68 @@ CONFIG_IP_PIMSM_V1=y
 CONFIG_IP_PIMSM_V2=y
 CONFIG_SYN_COOKIES=y
 # CONFIG_INET_LRO is not set
-# CONFIG_IPV6 is not set
+CONFIG_IPV6=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_OF_PARTS is not set
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_CFI=y
 CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_SLRAM=y
+CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
-# CONFIG_MISC_DEVICES is not set
+CONFIG_EEPROM_AT24=y
+CONFIG_EEPROM_AT25=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_ATA=y
+CONFIG_SATA_AHCI=y
+CONFIG_PATA_OCTEON_CF=y
+CONFIG_SATA_SIL=y
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
 CONFIG_MII=y
-# CONFIG_NETDEV_10000 is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_NET_VENDOR_ADAPTEC is not set
+# CONFIG_NET_VENDOR_ALTEON is not set
+# CONFIG_NET_VENDOR_AMD is not set
+# CONFIG_NET_VENDOR_ATHEROS is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_BROCADE is not set
+# CONFIG_NET_VENDOR_CHELSIO is not set
+# CONFIG_NET_VENDOR_CISCO is not set
+# CONFIG_NET_VENDOR_DEC is not set
+# CONFIG_NET_VENDOR_DLINK is not set
+# CONFIG_NET_VENDOR_EMULEX is not set
+# CONFIG_NET_VENDOR_EXAR is not set
+# CONFIG_NET_VENDOR_HP is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MELLANOX is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_MYRI is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_NVIDIA is not set
+# CONFIG_NET_VENDOR_OKI is not set
+# CONFIG_NET_PACKET_ENGINE is not set
+# CONFIG_NET_VENDOR_QLOGIC is not set
+# CONFIG_NET_VENDOR_REALTEK is not set
+# CONFIG_NET_VENDOR_RDC is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SILAN is not set
+# CONFIG_NET_VENDOR_SIS is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_SUN is not set
+# CONFIG_NET_VENDOR_TEHUTI is not set
+# CONFIG_NET_VENDOR_TI is not set
+# CONFIG_NET_VENDOR_TOSHIBA is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_MARVELL_PHY=y
+CONFIG_BROADCOM_PHY=y
+CONFIG_BCM87XX_PHY=y
+# CONFIG_WLAN is not set
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
@@ -66,24 +115,39 @@ CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_NR_UARTS=2
 CONFIG_SERIAL_8250_RUNTIME_UARTS=2
 # CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+CONFIG_I2C_OCTEON=y
+CONFIG_SPI=y
+CONFIG_SPI_OCTEON=y
 # CONFIG_HWMON is not set
 CONFIG_WATCHDOG=y
 # CONFIG_USB_SUPPORT is not set
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_DS1307=y
+CONFIG_STAGING=y
+CONFIG_OCTEON_ETHERNET=y
+# CONFIG_NET_VENDOR_SILICOM is not set
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_TMPFS=y
-# CONFIG_NETWORK_FILESYSTEMS is not set
-CONFIG_NLS=y
+CONFIG_HUGETLBFS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_V4_1=y
+CONFIG_ROOT_NFS=y
 CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
 CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_UTF8=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_FS=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_SPINLOCK=y
-CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_SCHED_DEBUG is not set
 CONFIG_DEBUG_INFO=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
-# CONFIG_EARLY_PRINTK is not set
 CONFIG_SECURITY=y
 CONFIG_SECURITY_NETWORK=y
 CONFIG_CRYPTO_CBC=y
index 17a36c12517296f95f772396670f0610a7f29b86..face9d26e6d5a1558c93cd149e60eb742fad8619 100644 (file)
@@ -233,6 +233,7 @@ CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_ROOT_HUB_TT=y
 CONFIG_USB_EHCI_TT_NEWSCHED=y
 CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_HCD_PLATFORM=y
 CONFIG_USB_UHCI_HCD=y
 CONFIG_USB_STORAGE=y
 CONFIG_NEW_LEDS=y
index c48998ffd198ebc8c34d6d90b6887019a566ed8b..14752dde754018170930faa0aabfbd049b2a4312 100644 (file)
@@ -346,8 +346,10 @@ CONFIG_USB=y
 CONFIG_USB_DYNAMIC_MINORS=y
 CONFIG_USB_SUSPEND=y
 CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_HCD_PLATFORM=y
 CONFIG_USB_EHCI_ROOT_HUB_TT=y
 CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_HCD_PLATFORM=y
 CONFIG_USB_STORAGE=y
 CONFIG_MMC=y
 CONFIG_MMC_CLKGATE=y
index 48a40aefaf58fa615985e2f41eb07b7c2dbf04d6..fb64589015fc2bb6841e4e23676d030003590940 100644 (file)
@@ -291,6 +291,7 @@ CONFIG_USB_MON=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_ROOT_HUB_TT=y
 CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_HCD_PLATFORM=y
 CONFIG_USB_STORAGE=m
 CONFIG_USB_LIBUSUAL=y
 CONFIG_USB_SERIAL=y
index 80cff8bea8e82beddd5dde7b13aa0610c7799799..7eb75543ca1a23b5be78e89ae3ec33b0f3d446db 100644 (file)
@@ -76,6 +76,7 @@ CONFIG_HID_GENERIC=m
 CONFIG_USB=y
 CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
 CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_HCD_PLATFORM=y
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
 CONFIG_USB_STORAGE=m
 CONFIG_USB_SERIAL=m
index 46c61edcdf7b68440e54ce6d6032daa5075f7685..459018acb618490210d6b102410d8f503a7467ca 100644 (file)
@@ -581,6 +581,7 @@ CONFIG_USB_MON=m
 CONFIG_USB_EHCI_HCD=m
 CONFIG_USB_EHCI_ROOT_HUB_TT=y
 CONFIG_USB_OHCI_HCD=m
+CONFIG_USB_OHCI_HCD_PLATFORM=y
 CONFIG_USB_UHCI_HCD=m
 CONFIG_USB_U132_HCD=m
 CONFIG_USB_SL811_HCD=m
index 52c4e914f95aef97ce72af5fd186678cc7ce9081..90112adb194082a1e41b945d45a7c7091962e3bc 100644 (file)
@@ -243,9 +243,9 @@ enum cpu_type_enum {
         */
        CPU_R4000PC, CPU_R4000SC, CPU_R4000MC, CPU_R4200, CPU_R4300, CPU_R4310,
        CPU_R4400PC, CPU_R4400SC, CPU_R4400MC, CPU_R4600, CPU_R4640, CPU_R4650,
-       CPU_R4700, CPU_R5000, CPU_R5000A, CPU_R5500, CPU_NEVADA, CPU_R5432,
-       CPU_R10000, CPU_R12000, CPU_R14000, CPU_VR41XX, CPU_VR4111, CPU_VR4121,
-       CPU_VR4122, CPU_VR4131, CPU_VR4133, CPU_VR4181, CPU_VR4181A, CPU_RM7000,
+       CPU_R4700, CPU_R5000, CPU_R5500, CPU_NEVADA, CPU_R5432, CPU_R10000,
+       CPU_R12000, CPU_R14000, CPU_VR41XX, CPU_VR4111, CPU_VR4121, CPU_VR4122,
+       CPU_VR4131, CPU_VR4133, CPU_VR4181, CPU_VR4181A, CPU_RM7000,
        CPU_SR71000, CPU_RM9000, CPU_TX49XX,
 
        /*
index eb742895dcbe97a3e7c81813c76eeec2e41bac02..881b980c72d29865ac3ff633f15c7e396ddec76c 100644 (file)
 #define PM_HUGE_MASK   PM_64M
 #elif defined(CONFIG_PAGE_SIZE_64KB)
 #define PM_HUGE_MASK   PM_256M
-#elif defined(CONFIG_HUGETLB_PAGE)
+#elif defined(CONFIG_MIPS_HUGE_TLB_SUPPORT)
 #error Bad page size configuration for hugetlbfs!
 #endif
 
index da9bd7d270d18a761f74f6168653d2eb16da7118..31ab10f02bad555724dffa1e58556bd6508cd79b 100644 (file)
 #define PAGE_SHIFT     16
 #endif
 #define PAGE_SIZE      (_AC(1,UL) << PAGE_SHIFT)
-#define PAGE_MASK       (~((1 << PAGE_SHIFT) - 1))
+#define PAGE_MASK       (~(PAGE_SIZE - 1))
 
-#ifdef CONFIG_HUGETLB_PAGE
+#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
 #define HPAGE_SHIFT    (PAGE_SHIFT + PAGE_SHIFT - 3)
 #define HPAGE_SIZE     (_AC(1,UL) << HPAGE_SHIFT)
 #define HPAGE_MASK     (~(HPAGE_SIZE - 1))
 #define HUGETLB_PAGE_ORDER     (HPAGE_SHIFT - PAGE_SHIFT)
-#else /* !CONFIG_HUGETLB_PAGE */
+#else /* !CONFIG_MIPS_HUGE_TLB_SUPPORT */
 #define HPAGE_SHIFT    ({BUILD_BUG(); 0; })
 #define HPAGE_SIZE     ({BUILD_BUG(); 0; })
 #define HPAGE_MASK     ({BUILD_BUG(); 0; })
 #define HUGETLB_PAGE_ORDER     ({BUILD_BUG(); 0; })
-#endif /* CONFIG_HUGETLB_PAGE */
+#endif /* CONFIG_MIPS_HUGE_TLB_SUPPORT */
 
 #ifndef __ASSEMBLY__
 
index f5b521d5a67d744e3f250c5a99e5023c77deaee0..c63191055e695c5a49812f3f32ed0c913d941a0a 100644 (file)
@@ -175,7 +175,7 @@ static inline int pmd_none(pmd_t pmd)
 
 static inline int pmd_bad(pmd_t pmd)
 {
-#ifdef CONFIG_HUGETLB_PAGE
+#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
        /* pmd_huge(pmd) but inline */
        if (unlikely(pmd_val(pmd) & _PAGE_HUGE))
                return 0;
index da4ba49adcf652fb9522c8c0b171f14aa4ab5247..1a222c4d8e0d78d81cdf559ecce98bd82bce2bdb 100644 (file)
@@ -94,7 +94,7 @@
 /* set:pagecache unset:swap */
 #define _PAGE_FILE             (_PAGE_MODIFIED)
 
-#ifdef CONFIG_HUGETLB_PAGE
+#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
 /* huge tlb page */
 #define _PAGE_HUGE_SHIFT       (_PAGE_MODIFIED_SHIFT + 1)
 #define _PAGE_HUGE             (1 << _PAGE_HUGE_SHIFT)
 #define _PAGE_HUGE             ({BUG(); 1; })  /* Dummy value */
 #endif
 
+#if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
+/* huge tlb page */
+#define _PAGE_SPLITTING_SHIFT  (_PAGE_HUGE_SHIFT + 1)
+#define _PAGE_SPLITTING                (1 << _PAGE_SPLITTING_SHIFT)
+#else
+#define _PAGE_SPLITTING_SHIFT  (_PAGE_HUGE_SHIFT)
+#define _PAGE_SPLITTING                ({BUG(); 1; })  /* Dummy value */
+#endif
+
 /* Page cannot be executed */
-#define _PAGE_NO_EXEC_SHIFT    (cpu_has_rixi ? _PAGE_HUGE_SHIFT + 1 : _PAGE_HUGE_SHIFT)
+#define _PAGE_NO_EXEC_SHIFT    (cpu_has_rixi ? _PAGE_SPLITTING_SHIFT + 1 : _PAGE_SPLITTING_SHIFT)
 #define _PAGE_NO_EXEC          ({BUG_ON(!cpu_has_rixi); 1 << _PAGE_NO_EXEC_SHIFT; })
 
 /* Page cannot be read */
index c02158be836cc6793393eb4f3f3c094b3df1043f..f4f112b978717ce9054ad0728ac6c1e156983085 100644 (file)
@@ -8,6 +8,7 @@
 #ifndef _ASM_PGTABLE_H
 #define _ASM_PGTABLE_H
 
+#include <linux/mmzone.h>
 #ifdef CONFIG_32BIT
 #include <asm/pgtable-32.h>
 #endif
@@ -89,12 +90,19 @@ static inline int is_zero_pfn(unsigned long pfn)
 
 extern void paging_init(void);
 
+#define pmd_pgprot(x)          __pgprot(pmd_val(x) & ~_PAGE_CHG_MASK)
+
 /*
  * Conversion functions: convert a page and protection to a page entry,
  * and a page entry and page directory to the page they refer to.
  */
 #define pmd_phys(pmd)          virt_to_phys((void *)pmd_val(pmd))
-#define pmd_page(pmd)          (pfn_to_page(pmd_phys(pmd) >> PAGE_SHIFT))
+
+#define __pmd_page(pmd)                (pfn_to_page(pmd_phys(pmd) >> PAGE_SHIFT))
+#ifndef CONFIG_TRANSPARENT_HUGEPAGE
+#define pmd_page(pmd)          __pmd_page(pmd)
+#endif /* CONFIG_TRANSPARENT_HUGEPAGE  */
+
 #define pmd_page_vaddr(pmd)    pmd_val(pmd)
 
 #if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32)
@@ -107,7 +115,6 @@ static inline void set_pte(pte_t *ptep, pte_t pte)
        ptep->pte_high = pte.pte_high;
        smp_wmb();
        ptep->pte_low = pte.pte_low;
-       //printk("pte_high %x pte_low %x\n", ptep->pte_high, ptep->pte_low);
 
        if (pte.pte_low & _PAGE_GLOBAL) {
                pte_t *buddy = ptep_buddy(ptep);
@@ -375,6 +382,14 @@ static inline void update_mmu_cache(struct vm_area_struct *vma,
        __update_cache(vma, address, pte);
 }
 
+static inline void update_mmu_cache_pmd(struct vm_area_struct *vma,
+       unsigned long address, pmd_t *pmdp)
+{
+       pte_t pte = *(pte_t *)pmdp;
+
+       __update_tlb(vma, address, pte);
+}
+
 #define kern_addr_valid(addr)  (1)
 
 #ifdef CONFIG_64BIT_PHYS_ADDR
@@ -394,6 +409,157 @@ static inline int io_remap_pfn_range(struct vm_area_struct *vma,
                remap_pfn_range(vma, vaddr, pfn, size, prot)
 #endif
 
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+
+extern int has_transparent_hugepage(void);
+
+static inline int pmd_trans_huge(pmd_t pmd)
+{
+       return !!(pmd_val(pmd) & _PAGE_HUGE);
+}
+
+static inline pmd_t pmd_mkhuge(pmd_t pmd)
+{
+       pmd_val(pmd) |= _PAGE_HUGE;
+
+       return pmd;
+}
+
+static inline int pmd_trans_splitting(pmd_t pmd)
+{
+       return !!(pmd_val(pmd) & _PAGE_SPLITTING);
+}
+
+static inline pmd_t pmd_mksplitting(pmd_t pmd)
+{
+       pmd_val(pmd) |= _PAGE_SPLITTING;
+
+       return pmd;
+}
+
+extern void set_pmd_at(struct mm_struct *mm, unsigned long addr,
+                      pmd_t *pmdp, pmd_t pmd);
+
+#define __HAVE_ARCH_PMDP_SPLITTING_FLUSH
+/* Extern to avoid header file madness */
+extern void pmdp_splitting_flush(struct vm_area_struct *vma,
+                                       unsigned long address,
+                                       pmd_t *pmdp);
+
+#define __HAVE_ARCH_PMD_WRITE
+static inline int pmd_write(pmd_t pmd)
+{
+       return !!(pmd_val(pmd) & _PAGE_WRITE);
+}
+
+static inline pmd_t pmd_wrprotect(pmd_t pmd)
+{
+       pmd_val(pmd) &= ~(_PAGE_WRITE | _PAGE_SILENT_WRITE);
+       return pmd;
+}
+
+static inline pmd_t pmd_mkwrite(pmd_t pmd)
+{
+       pmd_val(pmd) |= _PAGE_WRITE;
+       if (pmd_val(pmd) & _PAGE_MODIFIED)
+               pmd_val(pmd) |= _PAGE_SILENT_WRITE;
+
+       return pmd;
+}
+
+static inline int pmd_dirty(pmd_t pmd)
+{
+       return !!(pmd_val(pmd) & _PAGE_MODIFIED);
+}
+
+static inline pmd_t pmd_mkclean(pmd_t pmd)
+{
+       pmd_val(pmd) &= ~(_PAGE_MODIFIED | _PAGE_SILENT_WRITE);
+       return pmd;
+}
+
+static inline pmd_t pmd_mkdirty(pmd_t pmd)
+{
+       pmd_val(pmd) |= _PAGE_MODIFIED;
+       if (pmd_val(pmd) & _PAGE_WRITE)
+               pmd_val(pmd) |= _PAGE_SILENT_WRITE;
+
+       return pmd;
+}
+
+static inline int pmd_young(pmd_t pmd)
+{
+       return !!(pmd_val(pmd) & _PAGE_ACCESSED);
+}
+
+static inline pmd_t pmd_mkold(pmd_t pmd)
+{
+       pmd_val(pmd) &= ~(_PAGE_ACCESSED|_PAGE_SILENT_READ);
+
+       return pmd;
+}
+
+static inline pmd_t pmd_mkyoung(pmd_t pmd)
+{
+       pmd_val(pmd) |= _PAGE_ACCESSED;
+
+       if (cpu_has_rixi) {
+               if (!(pmd_val(pmd) & _PAGE_NO_READ))
+                       pmd_val(pmd) |= _PAGE_SILENT_READ;
+       } else {
+               if (pmd_val(pmd) & _PAGE_READ)
+                       pmd_val(pmd) |= _PAGE_SILENT_READ;
+       }
+
+       return pmd;
+}
+
+/* Extern to avoid header file madness */
+extern pmd_t mk_pmd(struct page *page, pgprot_t prot);
+
+static inline unsigned long pmd_pfn(pmd_t pmd)
+{
+       return pmd_val(pmd) >> _PFN_SHIFT;
+}
+
+static inline struct page *pmd_page(pmd_t pmd)
+{
+       if (pmd_trans_huge(pmd))
+               return pfn_to_page(pmd_pfn(pmd));
+
+       return pfn_to_page(pmd_phys(pmd) >> PAGE_SHIFT);
+}
+
+static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
+{
+       pmd_val(pmd) = (pmd_val(pmd) & _PAGE_CHG_MASK) | pgprot_val(newprot);
+       return pmd;
+}
+
+static inline pmd_t pmd_mknotpresent(pmd_t pmd)
+{
+       pmd_val(pmd) &= ~(_PAGE_PRESENT | _PAGE_VALID | _PAGE_DIRTY);
+
+       return pmd;
+}
+
+/*
+ * The generic version pmdp_get_and_clear uses a version of pmd_clear() with a
+ * different prototype.
+ */
+#define __HAVE_ARCH_PMDP_GET_AND_CLEAR
+static inline pmd_t pmdp_get_and_clear(struct mm_struct *mm,
+                                      unsigned long address, pmd_t *pmdp)
+{
+       pmd_t old = *pmdp;
+
+       pmd_clear(pmdp);
+
+       return old;
+}
+
+#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
+
 #include <asm-generic/pgtable.h>
 
 /*
index 4461198361c9760fa5afed8a101af0fa89207bc0..65900dab3ad382825143d66d7f206f93d561e34d 100644 (file)
@@ -6,7 +6,7 @@
  * SECTION_SIZE_BITS           2^N: how big each section will be
  * MAX_PHYSMEM_BITS            2^N: how much memory we can have in that space
  */
-#if defined(CONFIG_HUGETLB_PAGE) && defined(CONFIG_PAGE_SIZE_64KB)
+#if defined(CONFIG_MIPS_HUGE_TLB_SUPPORT) && defined(CONFIG_PAGE_SIZE_64KB)
 # define SECTION_SIZE_BITS     29
 #else
 # define SECTION_SIZE_BITS     28
index bb8f5c29c3d9f9a5e0c72c4497993fec46fcfae2..89571466524e00a94e2574797814966017a31196 100644 (file)
@@ -12,5 +12,6 @@
  * TLB debugging functions:
  */
 extern void dump_tlb_all(void);
+extern void dump_current_addr(unsigned long addr);
 
 #endif /* __ASM_TLBDEBUG_H */
index 2d9304c2b54cb0e8508e3a9dd397486ac977d1bb..df1e3e455f9a872c70c2c110755cdf1e0b8cfe03 100644 (file)
@@ -11,7 +11,7 @@
 #include <linux/interrupt.h>
 #include <linux/export.h>
 #include <asm/checksum.h>
-#include <asm/pgtable.h>
+#include <linux/mm.h>
 #include <asm/uaccess.h>
 #include <asm/ftrace.h>
 
index d27ca340d46dcbe6cb680f24b8c4e49e0bad1ebc..42579d217205425fdfa0aff0d0ccdec7dbe98f97 100644 (file)
 #include <asm/thread_info.h>
 #include <asm/unistd.h>
 
-/* This duplicates the definition from <linux/sched.h> */
-#define PT_TRACESYS    0x00000002      /* tracing system calls */
-
-/* This duplicates the definition from <asm/signal.h> */
-#define SIGILL         4               /* Illegal instruction (ANSI).  */
-
 #ifndef CONFIG_MIPS32_O32
 /* No O32, so define handle_sys here */
 #define handle_sysn32 handle_sys
index a99c1d3fc56769dc91f58ce64e117e0eb8533b44..2d7a91aa83607c67c11616443bf45109ddc9b14f 100644 (file)
@@ -5,11 +5,14 @@
  * Copyright (C) 1999 by Silicon Graphics, Inc.
  */
 #include <linux/kernel.h>
+#include <linux/hugetlb.h>
 #include <linux/mm.h>
+#include <linux/sched.h>
 
 #include <asm/mipsregs.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
+#include <asm/current.h>
 #include <asm/tlbdebug.h>
 
 static inline const char *msk2str(unsigned int mask)
@@ -111,3 +114,47 @@ void dump_tlb_all(void)
 {
        dump_tlb(0, current_cpu_data.tlbsize - 1);
 }
+
+void dump_current_addr(unsigned long addr)
+{
+       pgd_t *pgdp;
+       pud_t *pudp;
+       pmd_t *pmdp;
+       pte_t *ptep;
+       pte_t pte;
+
+       printk("Dumping for address %lx\n", addr);
+       pgdp = pgd_offset(current->mm, addr);
+       printk("pgd %lx\n", pgd_val(*pgdp));
+
+       pudp = pud_offset(pgdp, addr);
+       printk("pud %lx", pud_val(*pudp));
+#ifndef __PAGETABLE_PMD_FOLDED
+       if (pud_val(*pudp) == (unsigned long) invalid_pmd_table) {
+               printk("  (invalid_pmd_table)\n");
+
+               return;
+       }
+#endif
+       printk("\n");
+
+       pmdp = pmd_offset(pudp, addr);
+       printk("pmd  %lx", pmd_val(*pmdp));
+       if (pmd_huge(*pmdp)) {
+               printk("  pmd is huge\n");
+
+               return;
+       }
+       if (pmd_val(*pmdp) == (unsigned long) invalid_pte_table) {
+               printk("  (invalid_pte_table)\n");
+
+               return;
+       }
+       printk("\n");
+
+       ptep = pte_offset_map(pmdp, addr);
+       pte = *ptep;
+       printk("pte %lx\n", pte_val(pte));
+       if (pte_huge(pte))
+               printk("  pte is huge\n");
+}
index e92d59c4bd789e783809a5ed15e3e19c7f965ced..2874bf224418348f42432c631f1928ab417ecca0 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/phy.h>
 #include <linux/serial_8250.h>
 #include <linux/stmmac.h>
+#include <linux/usb/ehci_pdriver.h>
 #include <asm-generic/sizes.h>
 
 #include <loongson1.h>
@@ -107,13 +108,18 @@ static struct resource ls1x_ehci_resources[] = {
        },
 };
 
+static struct usb_ehci_pdata ls1x_ehci_pdata = {
+       .port_power_off = 1,
+};
+
 struct platform_device ls1x_ehci_device = {
-       .name           = "ls1x-ehci",
+       .name           = "ehci-platform",
        .id             = -1,
        .num_resources  = ARRAY_SIZE(ls1x_ehci_resources),
        .resource       = ls1x_ehci_resources,
        .dev            = {
                .dma_mask = &ls1x_ehci_dmamask,
+               .platform_data = &ls1x_ehci_pdata,
        },
 };
 
index 44e69e7a4519110b3efd1e30a755a8ec3e0692ea..9f67553762d5e606bb8aeced4766598d4f86d455 100644 (file)
@@ -5,6 +5,7 @@
  *
  * Copyright (C) 2005-2007 Cavium Networks
  */
+#include <linux/export.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
@@ -28,6 +29,7 @@
 #include <asm/octeon/octeon.h>
 
 unsigned long long cache_err_dcache[NR_CPUS];
+EXPORT_SYMBOL_GPL(cache_err_dcache);
 
 /**
  * Octeon automatically flushes the dcache on tlb changes, so
@@ -288,42 +290,42 @@ void __cpuinit octeon_cache_init(void)
  * Handle a cache error exception
  */
 
-static void  cache_parity_error_octeon(int non_recoverable)
+static RAW_NOTIFIER_HEAD(co_cache_error_chain);
+
+int register_co_cache_error_notifier(struct notifier_block *nb)
 {
-       unsigned long coreid = cvmx_get_core_num();
-       uint64_t icache_err = read_octeon_c0_icacheerr();
-
-       pr_err("Cache error exception:\n");
-       pr_err("cp0_errorepc == %lx\n", read_c0_errorepc());
-       if (icache_err & 1) {
-               pr_err("CacheErr (Icache) == %llx\n",
-                      (unsigned long long)icache_err);
-               write_octeon_c0_icacheerr(0);
-       }
-       if (cache_err_dcache[coreid] & 1) {
-               pr_err("CacheErr (Dcache) == %llx\n",
-                      (unsigned long long)cache_err_dcache[coreid]);
-               cache_err_dcache[coreid] = 0;
-       }
+       return raw_notifier_chain_register(&co_cache_error_chain, nb);
+}
+EXPORT_SYMBOL_GPL(register_co_cache_error_notifier);
 
-       if (non_recoverable)
-               panic("Can't handle cache error: nested exception");
+int unregister_co_cache_error_notifier(struct notifier_block *nb)
+{
+       return raw_notifier_chain_unregister(&co_cache_error_chain, nb);
+}
+EXPORT_SYMBOL_GPL(unregister_co_cache_error_notifier);
+
+static inline int co_cache_error_call_notifiers(unsigned long val)
+{
+       return raw_notifier_call_chain(&co_cache_error_chain, val, NULL);
 }
 
 /**
  * Called when the the exception is recoverable
  */
-
 asmlinkage void cache_parity_error_octeon_recoverable(void)
 {
-       cache_parity_error_octeon(0);
+       co_cache_error_call_notifiers(0);
 }
 
 /**
  * Called when the the exception is not recoverable
+ *
+ * The issue not that the cache error exception itself was non-recoverable
+ * but that due to nesting of exception may have lost some state so can't
+ * continue.
  */
-
 asmlinkage void cache_parity_error_octeon_non_recoverable(void)
 {
-       cache_parity_error_octeon(1);
+       co_cache_error_call_notifiers(1);
+       panic("Can't handle cache error: nested exception");
 }
index 25407794edb4ff875bba1acb9ac5c4fa632ae78c..ee331bbd8f8aa13c263b8aa31c6bfdbab75e1101 100644 (file)
@@ -11,6 +11,7 @@
 #include <asm/fixmap.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
+#include <asm/tlbflush.h>
 
 void pgd_init(unsigned long page)
 {
@@ -61,6 +62,36 @@ void pmd_init(unsigned long addr, unsigned long pagetable)
 }
 #endif
 
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+
+void pmdp_splitting_flush(struct vm_area_struct *vma,
+                        unsigned long address,
+                        pmd_t *pmdp)
+{
+       if (!pmd_trans_splitting(*pmdp)) {
+               pmd_t pmd = pmd_mksplitting(*pmdp);
+               set_pmd_at(vma->vm_mm, address, pmdp, pmd);
+       }
+}
+
+#endif
+
+pmd_t mk_pmd(struct page *page, pgprot_t prot)
+{
+       pmd_t pmd;
+
+       pmd_val(pmd) = (page_to_pfn(page) << _PFN_SHIFT) | pgprot_val(prot);
+
+       return pmd;
+}
+
+void set_pmd_at(struct mm_struct *mm, unsigned long addr,
+               pmd_t *pmdp, pmd_t pmd)
+{
+       *pmdp = pmd;
+       flush_tlb_all();
+}
+
 void __init pagetable_init(void)
 {
        unsigned long vaddr;
index 4b9b935a070e0c4d0160f2c259c3dc553c40b35e..94ad86d055c5e15df38d4748824870804a3aedfc 100644 (file)
@@ -305,7 +305,7 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte)
        pudp = pud_offset(pgdp, address);
        pmdp = pmd_offset(pudp, address);
        idx = read_c0_index();
-#ifdef CONFIG_HUGETLB_PAGE
+#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
        /* this could be a huge page  */
        if (pmd_huge(*pmdp)) {
                unsigned long lo;
@@ -377,6 +377,26 @@ void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
        EXIT_CRITICAL(flags);
 }
 
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+
+int __init has_transparent_hugepage(void)
+{
+       unsigned int mask;
+       unsigned long flags;
+
+       ENTER_CRITICAL(flags);
+       write_c0_pagemask(PM_HUGE_MASK);
+       back_to_back_c0_hazard();
+       mask = read_c0_pagemask();
+       write_c0_pagemask(PM_DEFAULT_MASK);
+
+       EXIT_CRITICAL(flags);
+
+       return mask == PM_HUGE_MASK;
+}
+
+#endif /* CONFIG_TRANSPARENT_HUGEPAGE  */
+
 static int __cpuinitdata ntlb;
 static int __init set_ntlb(char *str)
 {
index 2833dcb67b5adeaf838536580728176bbc715a77..c4fa6fcdbff64cb4b0a8bc8c58b73cb7c43fa6f0 100644 (file)
@@ -158,7 +158,7 @@ enum label_id {
        label_smp_pgtable_change,
        label_r3000_write_probe_fail,
        label_large_segbits_fault,
-#ifdef CONFIG_HUGETLB_PAGE
+#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
        label_tlb_huge_update,
 #endif
 };
@@ -177,7 +177,7 @@ UASM_L_LA(_nopage_tlbm)
 UASM_L_LA(_smp_pgtable_change)
 UASM_L_LA(_r3000_write_probe_fail)
 UASM_L_LA(_large_segbits_fault)
-#ifdef CONFIG_HUGETLB_PAGE
+#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
 UASM_L_LA(_tlb_huge_update)
 #endif
 
@@ -206,19 +206,53 @@ static void uasm_bgezl_label(struct uasm_label **l, u32 **p, int instance)
 }
 
 /*
- * For debug purposes.
+ * pgtable bits are assigned dynamically depending on processor feature
+ * and statically based on kernel configuration.  This spits out the actual
+ * values the kernel is using.  Required to make sense from disassembled
+ * TLB exception handlers.
  */
-static inline void dump_handler(const u32 *handler, int count)
+static void output_pgtable_bits_defines(void)
+{
+#define pr_define(fmt, ...)                                    \
+       pr_debug("#define " fmt, ##__VA_ARGS__)
+
+       pr_debug("#include <asm/asm.h>\n");
+       pr_debug("#include <asm/regdef.h>\n");
+       pr_debug("\n");
+
+       pr_define("_PAGE_PRESENT_SHIFT %d\n", _PAGE_PRESENT_SHIFT);
+       pr_define("_PAGE_READ_SHIFT %d\n", _PAGE_READ_SHIFT);
+       pr_define("_PAGE_WRITE_SHIFT %d\n", _PAGE_WRITE_SHIFT);
+       pr_define("_PAGE_ACCESSED_SHIFT %d\n", _PAGE_ACCESSED_SHIFT);
+       pr_define("_PAGE_MODIFIED_SHIFT %d\n", _PAGE_MODIFIED_SHIFT);
+       pr_define("_PAGE_HUGE_SHIFT %d\n", _PAGE_HUGE_SHIFT);
+       pr_define("_PAGE_SPLITTING_SHIFT %d\n", _PAGE_SPLITTING_SHIFT);
+       if (cpu_has_rixi) {
+               pr_define("_PAGE_NO_EXEC_SHIFT %d\n", _PAGE_NO_EXEC_SHIFT);
+               pr_define("_PAGE_NO_READ_SHIFT %d\n", _PAGE_NO_READ_SHIFT);
+       }
+       pr_define("_PAGE_GLOBAL_SHIFT %d\n", _PAGE_GLOBAL_SHIFT);
+       pr_define("_PAGE_VALID_SHIFT %d\n", _PAGE_VALID_SHIFT);
+       pr_define("_PAGE_DIRTY_SHIFT %d\n", _PAGE_DIRTY_SHIFT);
+       pr_define("_PFN_SHIFT %d\n", _PFN_SHIFT);
+       pr_debug("\n");
+}
+
+static inline void dump_handler(const char *symbol, const u32 *handler, int count)
 {
        int i;
 
+       pr_debug("LEAF(%s)\n", symbol);
+
        pr_debug("\t.set push\n");
        pr_debug("\t.set noreorder\n");
 
        for (i = 0; i < count; i++)
-               pr_debug("\t%p\t.word 0x%08x\n", &handler[i], handler[i]);
+               pr_debug("\t.word\t0x%08x\t\t# %p\n", handler[i], &handler[i]);
 
-       pr_debug("\t.set pop\n");
+       pr_debug("\t.set\tpop\n");
+
+       pr_debug("\tEND(%s)\n", symbol);
 }
 
 /* The only general purpose registers allowed in TLB handlers. */
@@ -401,7 +435,7 @@ static void __cpuinit build_r3000_tlb_refill_handler(void)
 
        memcpy((void *)ebase, tlb_handler, 0x80);
 
-       dump_handler((u32 *)ebase, 32);
+       dump_handler("r3000_tlb_refill", (u32 *)ebase, 32);
 }
 #endif /* CONFIG_MIPS_PGD_C0_CONTEXT */
 
@@ -443,7 +477,6 @@ static void __cpuinit __maybe_unused build_tlb_probe_entry(u32 **p)
        case CPU_R4600:
        case CPU_R4700:
        case CPU_R5000:
-       case CPU_R5000A:
        case CPU_NEVADA:
                uasm_i_nop(p);
                uasm_i_tlbp(p);
@@ -517,7 +550,6 @@ static void __cpuinit build_tlb_write_entry(u32 **p, struct uasm_label **l,
                break;
 
        case CPU_R5000:
-       case CPU_R5000A:
        case CPU_NEVADA:
                uasm_i_nop(p); /* QED specifies 2 nops hazard */
                uasm_i_nop(p); /* QED specifies 2 nops hazard */
@@ -629,7 +661,7 @@ static __cpuinit __maybe_unused void build_convert_pte_to_entrylo(u32 **p,
        }
 }
 
-#ifdef CONFIG_HUGETLB_PAGE
+#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
 
 static __cpuinit void build_restore_pagemask(u32 **p,
                                             struct uasm_reloc **r,
@@ -755,7 +787,7 @@ static __cpuinit void build_huge_handler_tail(u32 **p,
        build_huge_update_entries(p, pte, ptr);
        build_huge_tlb_write_entry(p, l, r, pte, tlb_indexed, 0);
 }
-#endif /* CONFIG_HUGETLB_PAGE */
+#endif /* CONFIG_MIPS_HUGE_TLB_SUPPORT */
 
 #ifdef CONFIG_64BIT
 /*
@@ -1200,7 +1232,7 @@ build_fast_tlb_refill_handler (u32 **p, struct uasm_label **l,
        /* Adjust the context during the load latency. */
        build_adjust_context(p, tmp);
 
-#ifdef CONFIG_HUGETLB_PAGE
+#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
        uasm_il_bbit1(p, r, scratch, ilog2(_PAGE_HUGE), label_tlb_huge_update);
        /*
         * The in the LWX case we don't want to do the load in the
@@ -1209,7 +1241,7 @@ build_fast_tlb_refill_handler (u32 **p, struct uasm_label **l,
         */
        if (use_lwx_insns())
                uasm_i_nop(p);
-#endif /* CONFIG_HUGETLB_PAGE */
+#endif /* CONFIG_MIPS_HUGE_TLB_SUPPORT */
 
 
        /* build_update_entries */
@@ -1312,7 +1344,7 @@ static void __cpuinit build_r4000_tlb_refill_handler(void)
                build_get_pgde32(&p, K0, K1); /* get pgd in K1 */
 #endif
 
-#ifdef CONFIG_HUGETLB_PAGE
+#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
                build_is_huge_pte(&p, &r, K0, K1, label_tlb_huge_update);
 #endif
 
@@ -1322,7 +1354,7 @@ static void __cpuinit build_r4000_tlb_refill_handler(void)
                uasm_l_leave(&l, p);
                uasm_i_eret(&p); /* return from trap */
        }
-#ifdef CONFIG_HUGETLB_PAGE
+#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
        uasm_l_tlb_huge_update(&l, p);
        build_huge_update_entries(&p, htlb_info.huge_pte, K1);
        build_huge_tlb_write_entry(&p, &l, &r, K0, tlb_random,
@@ -1367,7 +1399,7 @@ static void __cpuinit build_r4000_tlb_refill_handler(void)
                uasm_copy_handler(relocs, labels, tlb_handler, p, f);
                final_len = p - tlb_handler;
        } else {
-#if defined(CONFIG_HUGETLB_PAGE)
+#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
                const enum label_id ls = label_tlb_huge_update;
 #else
                const enum label_id ls = label_vmalloc;
@@ -1436,7 +1468,7 @@ static void __cpuinit build_r4000_tlb_refill_handler(void)
 
        memcpy((void *)ebase, final_handler, 0x100);
 
-       dump_handler((u32 *)ebase, 64);
+       dump_handler("r4000_tlb_refill", (u32 *)ebase, 64);
 }
 
 /*
@@ -1493,7 +1525,8 @@ static void __cpuinit build_r4000_setup_pgd(void)
        pr_debug("Wrote tlbmiss_handler_setup_pgd (%u instructions).\n",
                 (unsigned int)(p - tlbmiss_handler_setup_pgd));
 
-       dump_handler(tlbmiss_handler_setup_pgd,
+       dump_handler("tlbmiss_handler",
+                    tlbmiss_handler_setup_pgd,
                     ARRAY_SIZE(tlbmiss_handler_setup_pgd));
 }
 #endif
@@ -1763,7 +1796,7 @@ static void __cpuinit build_r3000_tlb_load_handler(void)
        pr_debug("Wrote TLB load handler fastpath (%u instructions).\n",
                 (unsigned int)(p - handle_tlbl));
 
-       dump_handler(handle_tlbl, ARRAY_SIZE(handle_tlbl));
+       dump_handler("r3000_tlb_load", handle_tlbl, ARRAY_SIZE(handle_tlbl));
 }
 
 static void __cpuinit build_r3000_tlb_store_handler(void)
@@ -1793,7 +1826,7 @@ static void __cpuinit build_r3000_tlb_store_handler(void)
        pr_debug("Wrote TLB store handler fastpath (%u instructions).\n",
                 (unsigned int)(p - handle_tlbs));
 
-       dump_handler(handle_tlbs, ARRAY_SIZE(handle_tlbs));
+       dump_handler("r3000_tlb_store", handle_tlbs, ARRAY_SIZE(handle_tlbs));
 }
 
 static void __cpuinit build_r3000_tlb_modify_handler(void)
@@ -1823,7 +1856,7 @@ static void __cpuinit build_r3000_tlb_modify_handler(void)
        pr_debug("Wrote TLB modify handler fastpath (%u instructions).\n",
                 (unsigned int)(p - handle_tlbm));
 
-       dump_handler(handle_tlbm, ARRAY_SIZE(handle_tlbm));
+       dump_handler("r3000_tlb_modify", handle_tlbm, ARRAY_SIZE(handle_tlbm));
 }
 #endif /* CONFIG_MIPS_PGD_C0_CONTEXT */
 
@@ -1842,7 +1875,7 @@ build_r4000_tlbchange_handler_head(u32 **p, struct uasm_label **l,
        build_get_pgde32(p, wr.r1, wr.r2); /* get pgd in ptr */
 #endif
 
-#ifdef CONFIG_HUGETLB_PAGE
+#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
        /*
         * For huge tlb entries, pmd doesn't contain an address but
         * instead contains the tlb pte. Check the PAGE_HUGE bit and
@@ -1958,7 +1991,7 @@ static void __cpuinit build_r4000_tlb_load_handler(void)
        build_make_valid(&p, &r, wr.r1, wr.r2);
        build_r4000_tlbchange_handler_tail(&p, &l, &r, wr.r1, wr.r2);
 
-#ifdef CONFIG_HUGETLB_PAGE
+#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
        /*
         * This is the entry point when build_r4000_tlbchange_handler_head
         * spots a huge page.
@@ -2030,7 +2063,7 @@ static void __cpuinit build_r4000_tlb_load_handler(void)
        pr_debug("Wrote TLB load handler fastpath (%u instructions).\n",
                 (unsigned int)(p - handle_tlbl));
 
-       dump_handler(handle_tlbl, ARRAY_SIZE(handle_tlbl));
+       dump_handler("r4000_tlb_load", handle_tlbl, ARRAY_SIZE(handle_tlbl));
 }
 
 static void __cpuinit build_r4000_tlb_store_handler(void)
@@ -2051,7 +2084,7 @@ static void __cpuinit build_r4000_tlb_store_handler(void)
        build_make_write(&p, &r, wr.r1, wr.r2);
        build_r4000_tlbchange_handler_tail(&p, &l, &r, wr.r1, wr.r2);
 
-#ifdef CONFIG_HUGETLB_PAGE
+#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
        /*
         * This is the entry point when
         * build_r4000_tlbchange_handler_head spots a huge page.
@@ -2077,7 +2110,7 @@ static void __cpuinit build_r4000_tlb_store_handler(void)
        pr_debug("Wrote TLB store handler fastpath (%u instructions).\n",
                 (unsigned int)(p - handle_tlbs));
 
-       dump_handler(handle_tlbs, ARRAY_SIZE(handle_tlbs));
+       dump_handler("r4000_tlb_store", handle_tlbs, ARRAY_SIZE(handle_tlbs));
 }
 
 static void __cpuinit build_r4000_tlb_modify_handler(void)
@@ -2099,7 +2132,7 @@ static void __cpuinit build_r4000_tlb_modify_handler(void)
        build_make_write(&p, &r, wr.r1, wr.r2);
        build_r4000_tlbchange_handler_tail(&p, &l, &r, wr.r1, wr.r2);
 
-#ifdef CONFIG_HUGETLB_PAGE
+#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
        /*
         * This is the entry point when
         * build_r4000_tlbchange_handler_head spots a huge page.
@@ -2125,7 +2158,7 @@ static void __cpuinit build_r4000_tlb_modify_handler(void)
        pr_debug("Wrote TLB modify handler fastpath (%u instructions).\n",
                 (unsigned int)(p - handle_tlbm));
 
-       dump_handler(handle_tlbm, ARRAY_SIZE(handle_tlbm));
+       dump_handler("r4000_tlb_modify", handle_tlbm, ARRAY_SIZE(handle_tlbm));
 }
 
 void __cpuinit build_tlb_refill_handler(void)
@@ -2137,6 +2170,8 @@ void __cpuinit build_tlb_refill_handler(void)
         */
        static int run_once = 0;
 
+       output_pgtable_bits_defines();
+
 #ifdef CONFIG_64BIT
        check_for_high_segbits = current_cpu_data.vmbits > (PGDIR_SHIFT + PGD_ORDER + PAGE_SHIFT - 3);
 #endif
index 71b44d82621db706844aacfb52f698128a6f58b6..507230eeb7685e9292eb533e7932441db11e92e0 100644 (file)
@@ -15,6 +15,8 @@
 #include <linux/serial_8250.h>
 #include <linux/serial_reg.h>
 #include <linux/i2c.h>
+#include <linux/usb/ehci_pdriver.h>
+#include <linux/usb/ohci_pdriver.h>
 
 #include <asm/netlogic/haldefs.h>
 #include <asm/netlogic/xlr/iomap.h>
@@ -123,12 +125,18 @@ static u64 xls_usb_dmamask = ~(u32)0;
                },                                                      \
        }
 
+static struct usb_ehci_pdata xls_usb_ehci_pdata = {
+       .caps_offset    = 0,
+};
+
+static struct usb_ohci_pdata xls_usb_ohci_pdata;
+
 static struct platform_device xls_usb_ehci_device =
-                        USB_PLATFORM_DEV("ehci-xls", 0, PIC_USB_IRQ);
+                        USB_PLATFORM_DEV("ehci-platform", 0, PIC_USB_IRQ);
 static struct platform_device xls_usb_ohci_device_0 =
-                        USB_PLATFORM_DEV("ohci-xls-0", 1, PIC_USB_IRQ);
+                        USB_PLATFORM_DEV("ohci-platform", 1, PIC_USB_IRQ);
 static struct platform_device xls_usb_ohci_device_1 =
-                        USB_PLATFORM_DEV("ohci-xls-1", 2, PIC_USB_IRQ);
+                        USB_PLATFORM_DEV("ohci-platform", 2, PIC_USB_IRQ);
 
 static struct platform_device *xls_platform_devices[] = {
        &xls_usb_ehci_device,
@@ -172,14 +180,17 @@ int xls_platform_usb_init(void)
        memres = CPHYSADDR((unsigned long)usb_mmio);
        xls_usb_ehci_device.resource[0].start = memres;
        xls_usb_ehci_device.resource[0].end = memres + 0x400 - 1;
+       xls_usb_ehci_device.dev.platform_data = &xls_usb_ehci_pdata;
 
        memres += 0x400;
        xls_usb_ohci_device_0.resource[0].start = memres;
        xls_usb_ohci_device_0.resource[0].end = memres + 0x400 - 1;
+       xls_usb_ohci_device_0.dev.platform_data = &xls_usb_ohci_pdata;
 
        memres += 0x400;
        xls_usb_ohci_device_1.resource[0].start = memres;
        xls_usb_ohci_device_1.resource[0].end = memres + 0x400 - 1;
+       xls_usb_ohci_device_1.dev.platform_data = &xls_usb_ohci_pdata;
 
        return platform_add_devices(xls_platform_devices,
                                ARRAY_SIZE(xls_platform_devices));
index 4b0c347d7a8241d1279a11efc84c873ee2a85650..8eb2ee345d0322dfc326e8b64769ce89aedd19f1 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/interrupt.h>
 #include <linux/time.h>
 #include <linux/delay.h>
+#include <linux/platform_device.h>
 #include <linux/swiotlb.h>
 
 #include <asm/time.h>
@@ -704,6 +705,9 @@ static int __init octeon_pci_setup(void)
         */
        cvmx_write_csr(CVMX_NPI_PCI_INT_SUM2, -1);
 
+       if (IS_ERR(platform_device_register_simple("co_pci_edac", 0, NULL, 0)))
+               pr_err("Registation of co_pci_edac failed!\n");
+
        octeon_pci_dma_init();
 
        return 0;
index 5264cc09a27bacbe2057ca7a66e50645a3eefd04..0a8faeaa7b70e4c3c9e893dde55e377c31e85f9a 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/serial.h>
 #include <linux/serial_pnx8xxx.h>
 #include <linux/platform_device.h>
+#include <linux/usb/ohci_pdriver.h>
 
 #include <int.h>
 #include <usb.h>
@@ -96,12 +97,40 @@ static u64 ohci_dmamask = DMA_BIT_MASK(32);
 
 static u64 uart_dmamask = DMA_BIT_MASK(32);
 
+static int pnx8550_usb_ohci_power_on(struct platform_device *pdev)
+{
+       /*
+        * Set register CLK48CTL to enable and 48MHz
+        */
+       outl(0x00000003, PCI_BASE | 0x0004770c);
+
+       /*
+        * Set register CLK12CTL to enable and 48MHz
+        */
+       outl(0x00000003, PCI_BASE | 0x00047710);
+
+       udelay(100);
+
+       return 0;
+}
+
+static void pnx8550_usb_ohci_power_off(struct platform_device *pdev)
+{
+       udelay(10);
+}
+
+static struct usb_ohci_pdata pnx8550_usb_ohci_pdata = {
+       .power_on       = pnx8550_usb_ohci_power_on,
+       .power_off      = pnx8550_usb_ohci_power_off,
+};
+
 static struct platform_device pnx8550_usb_ohci_device = {
-       .name           = "pnx8550-ohci",
+       .name           = "ohci-platform",
        .id             = -1,
        .dev = {
                .dma_mask               = &ohci_dmamask,
                .coherent_dma_mask      = DMA_BIT_MASK(32),
+               .platform_data          = &pnx8550_usb_ohci_pdata,
        },
        .num_resources  = ARRAY_SIZE(pnx8550_usb_ohci_resources),
        .resource       = pnx8550_usb_ohci_resources,
index 458371a1565aa2fdcbaa75e27ab398d8741019a9..bac8debecffb067ca8b550e0773a3c7c204d1e0b 100644 (file)
@@ -1,6 +1,5 @@
-include include/asm-generic/Kbuild.asm
 
-header-y += pdc.h
-generic-y += clkdev.h
-generic-y += word-at-a-time.h
-generic-y += exec.h
+generic-y += word-at-a-time.h auxvec.h user.h cputime.h emergency-restart.h \
+         segment.h topology.h vga.h device.h percpu.h hw_irq.h mutex.h \
+         div64.h irq_regs.h kdebug.h kvm_para.h local64.h local.h param.h \
+         poll.h xor.h clkdev.h exec.h
diff --git a/arch/parisc/include/asm/auxvec.h b/arch/parisc/include/asm/auxvec.h
deleted file mode 100644 (file)
index 9c3ac4b..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-#ifndef __ASMPARISC_AUXVEC_H
-#define __ASMPARISC_AUXVEC_H
-
-#endif
diff --git a/arch/parisc/include/asm/compat_signal.h b/arch/parisc/include/asm/compat_signal.h
deleted file mode 100644 (file)
index 6ad02c3..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-/* Use generic */
-#include <asm-generic/compat_signal.h>
diff --git a/arch/parisc/include/asm/cputime.h b/arch/parisc/include/asm/cputime.h
deleted file mode 100644 (file)
index dcdf2fb..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __PARISC_CPUTIME_H
-#define __PARISC_CPUTIME_H
-
-#include <asm-generic/cputime.h>
-
-#endif /* __PARISC_CPUTIME_H */
diff --git a/arch/parisc/include/asm/device.h b/arch/parisc/include/asm/device.h
deleted file mode 100644 (file)
index d8f9872..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-/*
- * Arch specific extensions to struct device
- *
- * This file is released under the GPLv2
- */
-#include <asm-generic/device.h>
-
diff --git a/arch/parisc/include/asm/div64.h b/arch/parisc/include/asm/div64.h
deleted file mode 100644 (file)
index 6cd978c..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/div64.h>
diff --git a/arch/parisc/include/asm/emergency-restart.h b/arch/parisc/include/asm/emergency-restart.h
deleted file mode 100644 (file)
index 108d8c4..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASM_EMERGENCY_RESTART_H
-#define _ASM_EMERGENCY_RESTART_H
-
-#include <asm-generic/emergency-restart.h>
-
-#endif /* _ASM_EMERGENCY_RESTART_H */
diff --git a/arch/parisc/include/asm/hw_irq.h b/arch/parisc/include/asm/hw_irq.h
deleted file mode 100644 (file)
index 6707f7d..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef _ASM_HW_IRQ_H
-#define _ASM_HW_IRQ_H
-
-/*
- *     linux/include/asm/hw_irq.h
- */
-
-#endif
diff --git a/arch/parisc/include/asm/irq_regs.h b/arch/parisc/include/asm/irq_regs.h
deleted file mode 100644 (file)
index 3dd9c0b..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/irq_regs.h>
diff --git a/arch/parisc/include/asm/kdebug.h b/arch/parisc/include/asm/kdebug.h
deleted file mode 100644 (file)
index 6ece1b0..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/kdebug.h>
diff --git a/arch/parisc/include/asm/kvm_para.h b/arch/parisc/include/asm/kvm_para.h
deleted file mode 100644 (file)
index 14fab8f..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/kvm_para.h>
diff --git a/arch/parisc/include/asm/local.h b/arch/parisc/include/asm/local.h
deleted file mode 100644 (file)
index c11c530..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/local.h>
diff --git a/arch/parisc/include/asm/local64.h b/arch/parisc/include/asm/local64.h
deleted file mode 100644 (file)
index 36c93b5..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/local64.h>
diff --git a/arch/parisc/include/asm/mutex.h b/arch/parisc/include/asm/mutex.h
deleted file mode 100644 (file)
index 458c1f7..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-/*
- * Pull in the generic implementation for the mutex fastpath.
- *
- * TODO: implement optimized primitives instead, or leave the generic
- * implementation in place, or pick the atomic_xchg() based generic
- * implementation. (see asm-generic/mutex-xchg.h for details)
- */
-
-#include <asm-generic/mutex-dec.h>
diff --git a/arch/parisc/include/asm/param.h b/arch/parisc/include/asm/param.h
deleted file mode 100644 (file)
index 965d454..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/param.h>
index 7f0f2d23059d3f1acbb1990c04016025446643d2..7eb616e4bf8aee7cc2e89b8b05b11ed9dc76228f 100644 (file)
 #ifndef _PARISC_PDC_H
 #define _PARISC_PDC_H
 
-/*
- *     PDC return values ...
- *     All PDC calls return a subset of these errors. 
- */
-
-#define PDC_WARN                 3     /* Call completed with a warning */
-#define PDC_REQ_ERR_1            2     /* See above                     */
-#define PDC_REQ_ERR_0            1     /* Call would generate a requestor error */
-#define PDC_OK                   0     /* Call completed successfully  */
-#define PDC_BAD_PROC            -1     /* Called non-existent procedure*/
-#define PDC_BAD_OPTION          -2     /* Called with non-existent option */
-#define PDC_ERROR               -3     /* Call could not complete without an error */
-#define PDC_NE_MOD              -5     /* Module not found             */
-#define PDC_NE_CELL_MOD                 -7     /* Cell module not found        */
-#define PDC_INVALID_ARG                -10     /* Called with an invalid argument */
-#define PDC_BUS_POW_WARN       -12     /* Call could not complete in allowed power budget */
-#define PDC_NOT_NARROW         -17     /* Narrow mode not supported    */
-
-/*
- *     PDC entry points...
- */
-
-#define PDC_POW_FAIL   1               /* perform a power-fail         */
-#define PDC_POW_FAIL_PREPARE   0       /* prepare for powerfail        */
-
-#define PDC_CHASSIS    2               /* PDC-chassis functions        */
-#define PDC_CHASSIS_DISP       0       /* update chassis display       */
-#define PDC_CHASSIS_WARN       1       /* return chassis warnings      */
-#define PDC_CHASSIS_DISPWARN   2       /* update&return chassis status */
-#define PDC_RETURN_CHASSIS_INFO 128    /* HVERSION dependent: return chassis LED/LCD info  */
-
-#define PDC_PIM         3               /* Get PIM data                 */
-#define PDC_PIM_HPMC            0       /* Transfer HPMC data           */
-#define PDC_PIM_RETURN_SIZE     1       /* Get Max buffer needed for PIM*/
-#define PDC_PIM_LPMC            2       /* Transfer HPMC data           */
-#define PDC_PIM_SOFT_BOOT       3       /* Transfer Soft Boot data      */
-#define PDC_PIM_TOC             4       /* Transfer TOC data            */
-
-#define PDC_MODEL      4               /* PDC model information call   */
-#define PDC_MODEL_INFO         0       /* returns information          */
-#define PDC_MODEL_BOOTID       1       /* set the BOOT_ID              */
-#define PDC_MODEL_VERSIONS     2       /* returns cpu-internal versions*/
-#define PDC_MODEL_SYSMODEL     3       /* return system model info     */
-#define PDC_MODEL_ENSPEC       4       /* enable specific option       */
-#define PDC_MODEL_DISPEC       5       /* disable specific option      */
-#define PDC_MODEL_CPU_ID       6       /* returns cpu-id (only newer machines!) */
-#define PDC_MODEL_CAPABILITIES 7       /* returns OS32/OS64-flags      */
-/* Values for PDC_MODEL_CAPABILITIES non-equivalent virtual aliasing support */
-#define  PDC_MODEL_OS64                        (1 << 0)
-#define  PDC_MODEL_OS32                        (1 << 1)
-#define  PDC_MODEL_IOPDIR_FDC          (1 << 2)
-#define  PDC_MODEL_NVA_MASK            (3 << 4)
-#define  PDC_MODEL_NVA_SUPPORTED       (0 << 4)
-#define  PDC_MODEL_NVA_SLOW            (1 << 4)
-#define  PDC_MODEL_NVA_UNSUPPORTED     (3 << 4)
-#define PDC_MODEL_GET_BOOT__OP 8       /* returns boot test options    */
-#define PDC_MODEL_SET_BOOT__OP 9       /* set boot test options        */
-
-#define PA89_INSTRUCTION_SET   0x4     /* capatibilies returned        */
-#define PA90_INSTRUCTION_SET   0x8
-
-#define PDC_CACHE      5               /* return/set cache (& TLB) info*/
-#define PDC_CACHE_INFO         0       /* returns information          */
-#define PDC_CACHE_SET_COH      1       /* set coherence state          */
-#define PDC_CACHE_RET_SPID     2       /* returns space-ID bits        */
-
-#define PDC_HPA                6               /* return HPA of processor      */
-#define PDC_HPA_PROCESSOR      0
-#define PDC_HPA_MODULES                1
-
-#define PDC_COPROC     7               /* Co-Processor (usually FP unit(s)) */
-#define PDC_COPROC_CFG         0       /* Co-Processor Cfg (FP unit(s) enabled?) */
-
-#define PDC_IODC       8               /* talk to IODC                 */
-#define PDC_IODC_READ          0       /* read IODC entry point        */
-/*      PDC_IODC_RI_                    * INDEX parameter of PDC_IODC_READ */
-#define PDC_IODC_RI_DATA_BYTES 0       /* IODC Data Bytes              */
-/*                             1, 2       obsolete - HVERSION dependent*/
-#define PDC_IODC_RI_INIT       3       /* Initialize module            */
-#define PDC_IODC_RI_IO         4       /* Module input/output          */
-#define PDC_IODC_RI_SPA                5       /* Module input/output          */
-#define PDC_IODC_RI_CONFIG     6       /* Module input/output          */
-/*                             7         obsolete - HVERSION dependent */
-#define PDC_IODC_RI_TEST       8       /* Module input/output          */
-#define PDC_IODC_RI_TLB                9       /* Module input/output          */
-#define PDC_IODC_NINIT         2       /* non-destructive init         */
-#define PDC_IODC_DINIT         3       /* destructive init             */
-#define PDC_IODC_MEMERR                4       /* check for memory errors      */
-#define PDC_IODC_INDEX_DATA    0       /* get first 16 bytes from mod IODC */
-#define PDC_IODC_BUS_ERROR     -4      /* bus error return value       */
-#define PDC_IODC_INVALID_INDEX -5      /* invalid index return value   */
-#define PDC_IODC_COUNT         -6      /* count is too small           */
-
-#define PDC_TOD                9               /* time-of-day clock (TOD)      */
-#define PDC_TOD_READ           0       /* read TOD                     */
-#define PDC_TOD_WRITE          1       /* write TOD                    */
-
-
-#define PDC_STABLE     10              /* stable storage (sprockets)   */
-#define PDC_STABLE_READ                0
-#define PDC_STABLE_WRITE       1
-#define PDC_STABLE_RETURN_SIZE 2
-#define PDC_STABLE_VERIFY_CONTENTS 3
-#define PDC_STABLE_INITIALIZE  4
-
-#define PDC_NVOLATILE  11              /* often not implemented        */
-
-#define PDC_ADD_VALID  12              /* Memory validation PDC call   */
-#define PDC_ADD_VALID_VERIFY   0       /* Make PDC_ADD_VALID verify region */
-
-#define PDC_INSTR      15              /* get instr to invoke PDCE_CHECK() */
-
-#define PDC_PROC       16              /* (sprockets)                  */
-
-#define PDC_CONFIG     16              /* (sprockets)                  */
-#define PDC_CONFIG_DECONFIG    0
-#define PDC_CONFIG_DRECONFIG   1
-#define PDC_CONFIG_DRETURN_CONFIG 2
-
-#define PDC_BLOCK_TLB  18              /* manage hardware block-TLB    */
-#define PDC_BTLB_INFO          0       /* returns parameter            */
-#define PDC_BTLB_INSERT                1       /* insert BTLB entry            */
-#define PDC_BTLB_PURGE         2       /* purge BTLB entries           */
-#define PDC_BTLB_PURGE_ALL     3       /* purge all BTLB entries       */
-
-#define PDC_TLB                19              /* manage hardware TLB miss handling */
-#define PDC_TLB_INFO           0       /* returns parameter            */
-#define PDC_TLB_SETUP          1       /* set up miss handling         */
-
-#define PDC_MEM                20              /* Manage memory                */
-#define PDC_MEM_MEMINFO                0
-#define PDC_MEM_ADD_PAGE       1
-#define PDC_MEM_CLEAR_PDT      2
-#define PDC_MEM_READ_PDT       3
-#define PDC_MEM_RESET_CLEAR    4
-#define PDC_MEM_GOODMEM                5
-#define PDC_MEM_TABLE          128     /* Non contig mem map (sprockets) */
-#define PDC_MEM_RETURN_ADDRESS_TABLE   PDC_MEM_TABLE
-#define PDC_MEM_GET_MEMORY_SYSTEM_TABLES_SIZE  131
-#define PDC_MEM_GET_MEMORY_SYSTEM_TABLES       132
-#define PDC_MEM_GET_PHYSICAL_LOCATION_FROM_MEMORY_ADDRESS 133
-
-#define PDC_MEM_RET_SBE_REPLACED       5       /* PDC_MEM return values */
-#define PDC_MEM_RET_DUPLICATE_ENTRY    4
-#define PDC_MEM_RET_BUF_SIZE_SMALL     1
-#define PDC_MEM_RET_PDT_FULL           -11
-#define PDC_MEM_RET_INVALID_PHYSICAL_LOCATION ~0ULL
-
-#define PDC_PSW                21              /* Get/Set default System Mask  */
-#define PDC_PSW_MASK           0       /* Return mask                  */
-#define PDC_PSW_GET_DEFAULTS   1       /* Return defaults              */
-#define PDC_PSW_SET_DEFAULTS   2       /* Set default                  */
-#define PDC_PSW_ENDIAN_BIT     1       /* set for big endian           */
-#define PDC_PSW_WIDE_BIT       2       /* set for wide mode            */ 
-
-#define PDC_SYSTEM_MAP 22              /* find system modules          */
-#define PDC_FIND_MODULE        0
-#define PDC_FIND_ADDRESS       1
-#define PDC_TRANSLATE_PATH     2
-
-#define PDC_SOFT_POWER 23              /* soft power switch            */
-#define PDC_SOFT_POWER_INFO    0       /* return info about the soft power switch */
-#define PDC_SOFT_POWER_ENABLE  1       /* enable/disable soft power switch */
-
-
-/* HVERSION dependent */
-
-/* The PDC_MEM_MAP calls */
-#define PDC_MEM_MAP    128             /* on s700: return page info    */
-#define PDC_MEM_MAP_HPA                0       /* returns hpa of a module      */
-
-#define PDC_EEPROM     129             /* EEPROM access                */
-#define PDC_EEPROM_READ_WORD   0
-#define PDC_EEPROM_WRITE_WORD  1
-#define PDC_EEPROM_READ_BYTE   2
-#define PDC_EEPROM_WRITE_BYTE  3
-#define PDC_EEPROM_EEPROM_PASSWORD -1000
-
-#define PDC_NVM                130             /* NVM (non-volatile memory) access */
-#define PDC_NVM_READ_WORD      0
-#define PDC_NVM_WRITE_WORD     1
-#define PDC_NVM_READ_BYTE      2
-#define PDC_NVM_WRITE_BYTE     3
-
-#define PDC_SEED_ERROR 132             /* (sprockets)                  */
-
-#define PDC_IO         135             /* log error info, reset IO system */
-#define PDC_IO_READ_AND_CLEAR_ERRORS   0
-#define PDC_IO_RESET                   1
-#define PDC_IO_RESET_DEVICES           2
-/* sets bits 6&7 (little endian) of the HcControl Register */
-#define PDC_IO_USB_SUSPEND     0xC000000000000000
-#define PDC_IO_EEPROM_IO_ERR_TABLE_FULL        -5      /* return value */
-#define PDC_IO_NO_SUSPEND              -6      /* return value */
-
-#define PDC_BROADCAST_RESET 136                /* reset all processors         */
-#define PDC_DO_RESET           0       /* option: perform a broadcast reset */
-#define PDC_DO_FIRM_TEST_RESET 1       /* Do broadcast reset with bitmap */
-#define PDC_BR_RECONFIGURATION 2       /* reset w/reconfiguration      */
-#define PDC_FIRM_TEST_MAGIC    0xab9ec36fUL    /* for this reboot only */
-
-#define PDC_LAN_STATION_ID 138         /* Hversion dependent mechanism for */
-#define PDC_LAN_STATION_ID_READ        0       /* getting the lan station address  */
-
-#define        PDC_LAN_STATION_ID_SIZE 6
-
-#define PDC_CHECK_RANGES 139           /* (sprockets)                  */
-
-#define PDC_NV_SECTIONS        141             /* (sprockets)                  */
-
-#define PDC_PERFORMANCE        142             /* performance monitoring       */
-
-#define PDC_SYSTEM_INFO        143             /* system information           */
-#define PDC_SYSINFO_RETURN_INFO_SIZE   0
-#define PDC_SYSINFO_RRETURN_SYS_INFO   1
-#define PDC_SYSINFO_RRETURN_ERRORS     2
-#define PDC_SYSINFO_RRETURN_WARNINGS   3
-#define PDC_SYSINFO_RETURN_REVISIONS   4
-#define PDC_SYSINFO_RRETURN_DIAGNOSE   5
-#define PDC_SYSINFO_RRETURN_HV_DIAGNOSE        1005
-
-#define PDC_RDR                144             /* (sprockets)                  */
-#define PDC_RDR_READ_BUFFER    0
-#define PDC_RDR_READ_SINGLE    1
-#define PDC_RDR_WRITE_SINGLE   2
-
-#define PDC_INTRIGUE   145             /* (sprockets)                  */
-#define PDC_INTRIGUE_WRITE_BUFFER       0
-#define PDC_INTRIGUE_GET_SCRATCH_BUFSIZE 1
-#define PDC_INTRIGUE_START_CPU_COUNTERS         2
-#define PDC_INTRIGUE_STOP_CPU_COUNTERS  3
-
-#define PDC_STI                146             /* STI access                   */
-/* same as PDC_PCI_XXX values (see below) */
-
-/* Legacy PDC definitions for same stuff */
-#define PDC_PCI_INDEX  147
-#define PDC_PCI_INTERFACE_INFO         0
-#define PDC_PCI_SLOT_INFO              1
-#define PDC_PCI_INFLIGHT_BYTES         2
-#define PDC_PCI_READ_CONFIG            3
-#define PDC_PCI_WRITE_CONFIG           4
-#define PDC_PCI_READ_PCI_IO            5
-#define PDC_PCI_WRITE_PCI_IO           6
-#define PDC_PCI_READ_CONFIG_DELAY      7
-#define PDC_PCI_UPDATE_CONFIG_DELAY    8
-#define PDC_PCI_PCI_PATH_TO_PCI_HPA    9
-#define PDC_PCI_PCI_HPA_TO_PCI_PATH    10
-#define PDC_PCI_PCI_PATH_TO_PCI_BUS    11
-#define PDC_PCI_PCI_RESERVED           12
-#define PDC_PCI_PCI_INT_ROUTE_SIZE     13
-#define PDC_PCI_GET_INT_TBL_SIZE       PDC_PCI_PCI_INT_ROUTE_SIZE
-#define PDC_PCI_PCI_INT_ROUTE          14
-#define PDC_PCI_GET_INT_TBL            PDC_PCI_PCI_INT_ROUTE 
-#define PDC_PCI_READ_MON_TYPE          15
-#define PDC_PCI_WRITE_MON_TYPE         16
-
-
-/* Get SCSI Interface Card info:  SDTR, SCSI ID, mode (SE vs LVD) */
-#define PDC_INITIATOR  163
-#define PDC_GET_INITIATOR      0
-#define PDC_SET_INITIATOR      1
-#define PDC_DELETE_INITIATOR   2
-#define PDC_RETURN_TABLE_SIZE  3
-#define PDC_RETURN_TABLE       4
-
-#define PDC_LINK       165             /* (sprockets)                  */
-#define PDC_LINK_PCI_ENTRY_POINTS      0  /* list (Arg1) = 0 */
-#define PDC_LINK_USB_ENTRY_POINTS      1  /* list (Arg1) = 1 */
-
-/* cl_class
- * page 3-33 of IO-Firmware ARS
- * IODC ENTRY_INIT(Search first) RET[1]
- */
-#define        CL_NULL         0       /* invalid */
-#define        CL_RANDOM       1       /* random access (as disk) */
-#define        CL_SEQU         2       /* sequential access (as tape) */
-#define        CL_DUPLEX       7       /* full-duplex point-to-point (RS-232, Net) */
-#define        CL_KEYBD        8       /* half-duplex console (HIL Keyboard) */
-#define        CL_DISPL        9       /* half-duplex console (display) */
-#define        CL_FC           10      /* FiberChannel access media */
-
-/* IODC ENTRY_INIT() */
-#define ENTRY_INIT_SRCH_FRST   2
-#define ENTRY_INIT_SRCH_NEXT   3
-#define ENTRY_INIT_MOD_DEV     4
-#define ENTRY_INIT_DEV         5
-#define ENTRY_INIT_MOD         6
-#define ENTRY_INIT_MSG         9
-
-/* IODC ENTRY_IO() */
-#define ENTRY_IO_BOOTIN                0
-#define ENTRY_IO_BOOTOUT       1
-#define ENTRY_IO_CIN           2
-#define ENTRY_IO_COUT          3
-#define ENTRY_IO_CLOSE         4
-#define ENTRY_IO_GETMSG                9
-#define ENTRY_IO_BBLOCK_IN     16
-#define ENTRY_IO_BBLOCK_OUT    17
-
-/* IODC ENTRY_SPA() */
-
-/* IODC ENTRY_CONFIG() */
-
-/* IODC ENTRY_TEST() */
-
-/* IODC ENTRY_TLB() */
-
-/* constants for OS (NVM...) */
-#define OS_ID_NONE             0       /* Undefined OS ID      */
-#define OS_ID_HPUX             1       /* HP-UX OS             */
-#define OS_ID_MPEXL            2       /* MPE XL OS            */
-#define OS_ID_OSF              3       /* OSF OS               */
-#define OS_ID_HPRT             4       /* HP-RT OS             */
-#define OS_ID_NOVEL            5       /* NOVELL OS            */
-#define OS_ID_LINUX            6       /* Linux                */
-
-
-/* constants for PDC_CHASSIS */
-#define OSTAT_OFF              0
-#define OSTAT_FLT              1 
-#define OSTAT_TEST             2
-#define OSTAT_INIT             3
-#define OSTAT_SHUT             4
-#define OSTAT_WARN             5
-#define OSTAT_RUN              6
-#define OSTAT_ON               7
-
-/* Page Zero constant offsets used by the HPMC handler */
-#define BOOT_CONSOLE_HPA_OFFSET  0x3c0
-#define BOOT_CONSOLE_SPA_OFFSET  0x3c4
-#define BOOT_CONSOLE_PATH_OFFSET 0x3a8
-
-/* size of the pdc_result buffer for firmware.c */
-#define NUM_PDC_RESULT 32
+#include <uapi/asm/pdc.h>
 
 #if !defined(__ASSEMBLY__)
 
-#include <linux/types.h>
-
-#ifdef __KERNEL__
-
 extern int pdc_type;
 
 /* Values for pdc_type */
@@ -673,88 +335,5 @@ static inline char * os_id_to_string(u16 os_id) {
        }
 }
 
-#endif /* __KERNEL__ */
-
-/* flags of the device_path */
-#define        PF_AUTOBOOT     0x80
-#define        PF_AUTOSEARCH   0x40
-#define        PF_TIMER        0x0F
-
-struct device_path {           /* page 1-69 */
-       unsigned char flags;    /* flags see above! */
-       unsigned char bc[6];    /* bus converter routing info */
-       unsigned char mod;
-       unsigned int  layers[6];/* device-specific layer-info */
-} __attribute__((aligned(8))) ;
-
-struct pz_device {
-       struct  device_path dp; /* see above */
-       /* struct       iomod *hpa; */
-       unsigned int hpa;       /* HPA base address */
-       /* char *spa; */
-       unsigned int spa;       /* SPA base address */
-       /* int  (*iodc_io)(struct iomod*, ...); */
-       unsigned int iodc_io;   /* device entry point */
-       short   pad;            /* reserved */
-       unsigned short cl_class;/* see below */
-} __attribute__((aligned(8))) ;
-
-struct zeropage {
-       /* [0x000] initialize vectors (VEC) */
-       unsigned int    vec_special;            /* must be zero */
-       /* int  (*vec_pow_fail)(void);*/
-       unsigned int    vec_pow_fail; /* power failure handler */
-       /* int  (*vec_toc)(void); */
-       unsigned int    vec_toc;
-       unsigned int    vec_toclen;
-       /* int  (*vec_rendz)(void); */
-       unsigned int vec_rendz;
-       int     vec_pow_fail_flen;
-       int     vec_pad[10];            
-       
-       /* [0x040] reserved processor dependent */
-       int     pad0[112];
-
-       /* [0x200] reserved */
-       int     pad1[84];
-
-       /* [0x350] memory configuration (MC) */
-       int     memc_cont;              /* contiguous mem size (bytes) */
-       int     memc_phsize;            /* physical memory size */
-       int     memc_adsize;            /* additional mem size, bytes of SPA space used by PDC */
-       unsigned int mem_pdc_hi;        /* used for 64-bit */
-
-       /* [0x360] various parameters for the boot-CPU */
-       /* unsigned int *mem_booterr[8]; */
-       unsigned int mem_booterr[8];    /* ptr to boot errors */
-       unsigned int mem_free;          /* first location, where OS can be loaded */
-       /* struct iomod *mem_hpa; */
-       unsigned int mem_hpa;           /* HPA of the boot-CPU */
-       /* int (*mem_pdc)(int, ...); */
-       unsigned int mem_pdc;           /* PDC entry point */
-       unsigned int mem_10msec;        /* number of clock ticks in 10msec */
-
-       /* [0x390] initial memory module (IMM) */
-       /* struct iomod *imm_hpa; */
-       unsigned int imm_hpa;           /* HPA of the IMM */
-       int     imm_soft_boot;          /* 0 = was hard boot, 1 = was soft boot */
-       unsigned int    imm_spa_size;           /* SPA size of the IMM in bytes */
-       unsigned int    imm_max_mem;            /* bytes of mem in IMM */
-
-       /* [0x3A0] boot console, display device and keyboard */
-       struct pz_device mem_cons;      /* description of console device */
-       struct pz_device mem_boot;      /* description of boot device */
-       struct pz_device mem_kbd;       /* description of keyboard device */
-
-       /* [0x430] reserved */
-       int     pad430[116];
-
-       /* [0x600] processor dependent */
-       __u32   pad600[1];
-       __u32   proc_sti;               /* pointer to STI ROM */
-       __u32   pad608[126];
-};
-
 #endif /* !defined(__ASSEMBLY__) */
-
 #endif /* _PARISC_PDC_H */
diff --git a/arch/parisc/include/asm/percpu.h b/arch/parisc/include/asm/percpu.h
deleted file mode 100644 (file)
index a0dcd19..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef _PARISC_PERCPU_H
-#define _PARISC_PERCPU_H
-
-#include <asm-generic/percpu.h>
-
-#endif 
-
diff --git a/arch/parisc/include/asm/poll.h b/arch/parisc/include/asm/poll.h
deleted file mode 100644 (file)
index c98509d..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/poll.h>
index 250ae35aa06220d7b4a3072ac447d0b14271eee6..a2db278a5def69c4a6ac4745c3685e45600df156 100644 (file)
@@ -1,49 +1,11 @@
-#ifndef _PARISC_PTRACE_H
-#define _PARISC_PTRACE_H
-
 /* written by Philipp Rumpf, Copyright (C) 1999 SuSE GmbH Nuernberg
 ** Copyright (C) 2000 Grant Grundler, Hewlett-Packard
 */
+#ifndef _PARISC_PTRACE_H
+#define _PARISC_PTRACE_H
 
-#include <linux/types.h>
-
-/* This struct defines the way the registers are stored on the 
- * stack during a system call.
- *
- * N.B. gdb/strace care about the size and offsets within this
- * structure. If you change things, you may break object compatibility
- * for those applications.
- */
-
-struct pt_regs {
-       unsigned long gr[32];   /* PSW is in gr[0] */
-       __u64 fr[32];
-       unsigned long sr[ 8];
-       unsigned long iasq[2];
-       unsigned long iaoq[2];
-       unsigned long cr27;
-       unsigned long pad0;     /* available for other uses */
-       unsigned long orig_r28;
-       unsigned long ksp;
-       unsigned long kpc;
-       unsigned long sar;      /* CR11 */
-       unsigned long iir;      /* CR19 */
-       unsigned long isr;      /* CR20 */
-       unsigned long ior;      /* CR21 */
-       unsigned long ipsw;     /* CR22 */
-};
-
-/*
- * The numbers chosen here are somewhat arbitrary but absolutely MUST
- * not overlap with any of the number assigned in <linux/ptrace.h>.
- *
- * These ones are taken from IA-64 on the assumption that theirs are
- * the most correct (and we also want to support PTRACE_SINGLEBLOCK
- * since we have taken branch traps too)
- */
-#define PTRACE_SINGLEBLOCK     12      /* resume execution until next branch */
+#include <uapi/asm/ptrace.h>
 
-#ifdef __KERNEL__
 
 #define task_regs(task) ((struct pt_regs *) ((char *)(task) + TASK_REGS))
 
@@ -58,6 +20,4 @@ struct pt_regs {
 unsigned long profile_pc(struct pt_regs *);
 
 
-#endif /* __KERNEL__ */
-
 #endif
diff --git a/arch/parisc/include/asm/real.h b/arch/parisc/include/asm/real.h
deleted file mode 100644 (file)
index 82acb25..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-#ifndef _PARISC_REAL_H
-#define _PARISC_REAL_H
-
-
-#endif
diff --git a/arch/parisc/include/asm/segment.h b/arch/parisc/include/asm/segment.h
deleted file mode 100644 (file)
index 26794dd..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __PARISC_SEGMENT_H
-#define __PARISC_SEGMENT_H
-
-/* Only here because we have some old header files that expect it.. */
-
-#endif
index c20356375d1d5630f07d98ed27212b6e5d08a257..21abf4fc169a3086123327a6528dd302498a1b8b 100644 (file)
 #ifndef _ASM_PARISC_SIGNAL_H
 #define _ASM_PARISC_SIGNAL_H
 
-#define SIGHUP          1
-#define SIGINT          2
-#define SIGQUIT                 3
-#define SIGILL          4
-#define SIGTRAP                 5
-#define SIGABRT                 6
-#define SIGIOT          6
-#define SIGEMT          7
-#define SIGFPE          8
-#define SIGKILL                 9
-#define SIGBUS         10
-#define SIGSEGV                11
-#define SIGSYS         12 /* Linux doesn't use this */
-#define SIGPIPE                13
-#define SIGALRM                14
-#define SIGTERM                15
-#define SIGUSR1                16
-#define SIGUSR2                17
-#define SIGCHLD                18
-#define SIGPWR         19
-#define SIGVTALRM      20
-#define SIGPROF                21
-#define SIGIO          22
-#define SIGPOLL                SIGIO
-#define SIGWINCH       23
-#define SIGSTOP                24
-#define SIGTSTP                25
-#define SIGCONT                26
-#define SIGTTIN                27
-#define SIGTTOU                28
-#define SIGURG         29
-#define SIGLOST                30 /* Linux doesn't use this either */
-#define        SIGUNUSED       31
-#define SIGRESERVE     SIGUNUSED
+#include <uapi/asm/signal.h>
 
-#define SIGXCPU                33
-#define SIGXFSZ                34
-#define SIGSTKFLT      36
-
-/* These should not be considered constants from userland.  */
-#define SIGRTMIN       37
-#define SIGRTMAX       _NSIG /* it's 44 under HP/UX */
-
-/*
- * SA_FLAGS values:
- *
- * SA_ONSTACK indicates that a registered stack_t will be used.
- * SA_RESTART flag to get restarting signals (which were the default long ago)
- * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
- * SA_RESETHAND clears the handler when the signal is delivered.
- * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
- * SA_NODEFER prevents the current signal from being masked in the handler.
- *
- * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
- * Unix names RESETHAND and NODEFER respectively.
- */
-#define SA_ONSTACK     0x00000001
-#define SA_RESETHAND   0x00000004
-#define SA_NOCLDSTOP   0x00000008
-#define SA_SIGINFO     0x00000010
-#define SA_NODEFER     0x00000020
-#define SA_RESTART     0x00000040
-#define SA_NOCLDWAIT   0x00000080
-#define _SA_SIGGFAULT  0x00000100 /* HPUX */
-
-#define SA_NOMASK      SA_NODEFER
-#define SA_ONESHOT     SA_RESETHAND
-
-#define SA_RESTORER    0x04000000 /* obsolete -- ignored */
-
-/* 
- * sigaltstack controls
- */
-#define SS_ONSTACK     1
-#define SS_DISABLE     2
-
-#define MINSIGSTKSZ    2048
-#define SIGSTKSZ       8192
-
-#ifdef __KERNEL__
 
 #define _NSIG          64
 /* bits-per-word, where word apparently means 'long' not 'int' */
 #define _NSIG_BPW      BITS_PER_LONG
 #define _NSIG_WORDS    (_NSIG / _NSIG_BPW)
 
-#endif /* __KERNEL__ */
-
-#define SIG_BLOCK          0   /* for blocking signals */
-#define SIG_UNBLOCK        1   /* for unblocking signals */
-#define SIG_SETMASK        2   /* for setting the signal mask */
-
-#define SIG_DFL        ((__sighandler_t)0)     /* default signal handling */
-#define SIG_IGN        ((__sighandler_t)1)     /* ignore signal */
-#define SIG_ERR        ((__sighandler_t)-1)    /* error return from signal */
-
 # ifndef __ASSEMBLY__
-
-#  include <linux/types.h>
-
-/* Avoid too many header ordering problems.  */
-struct siginfo;
-
-/* Type of a signal handler.  */
 #ifdef CONFIG_64BIT
-/* function pointers on 64-bit parisc are pointers to little structs and the
- * compiler doesn't support code which changes or tests the address of
- * the function in the little struct.  This is really ugly -PB
- */
-typedef char __user *__sighandler_t;
 #else
-typedef void __signalfn_t(int);
-typedef __signalfn_t __user *__sighandler_t;
 #endif
 
-typedef struct sigaltstack {
-       void __user *ss_sp;
-       int ss_flags;
-       size_t ss_size;
-} stack_t;
-
-#ifdef __KERNEL__
-
 /* Most things should be clean enough to redefine this at will, if care
    is taken to make libc match.  */
 
@@ -148,6 +38,5 @@ struct k_sigaction {
 
 #include <asm/sigcontext.h>
 
-#endif /* __KERNEL__ */
 #endif /* !__ASSEMBLY */
 #endif /* _ASM_PARISC_SIGNAL_H */
index a2a57a4548af7bd6d7c745a54d755d6a8fa0418e..9bbc0c8974ea90fc6fc6b68c4614936007512952 100644 (file)
@@ -1,45 +1,8 @@
 #ifndef _PARISC_TERMIOS_H
 #define _PARISC_TERMIOS_H
 
-#include <asm/termbits.h>
-#include <asm/ioctls.h>
+#include <uapi/asm/termios.h>
 
-struct winsize {
-       unsigned short ws_row;
-       unsigned short ws_col;
-       unsigned short ws_xpixel;
-       unsigned short ws_ypixel;
-};
-
-#define NCC 8
-struct termio {
-       unsigned short c_iflag;         /* input mode flags */
-       unsigned short c_oflag;         /* output mode flags */
-       unsigned short c_cflag;         /* control mode flags */
-       unsigned short c_lflag;         /* local mode flags */
-       unsigned char c_line;           /* line discipline */
-       unsigned char c_cc[NCC];        /* control characters */
-};
-
-/* modem lines */
-#define TIOCM_LE       0x001
-#define TIOCM_DTR      0x002
-#define TIOCM_RTS      0x004
-#define TIOCM_ST       0x008
-#define TIOCM_SR       0x010
-#define TIOCM_CTS      0x020
-#define TIOCM_CAR      0x040
-#define TIOCM_RNG      0x080
-#define TIOCM_DSR      0x100
-#define TIOCM_CD       TIOCM_CAR
-#define TIOCM_RI       TIOCM_RNG
-#define TIOCM_OUT1     0x2000
-#define TIOCM_OUT2     0x4000
-#define TIOCM_LOOP     0x8000
-
-/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
-
-#ifdef __KERNEL__
 
 /*     intr=^C         quit=^\         erase=del       kill=^U
        eof=^D          vtime=\0        vmin=\1         sxtc=\0
@@ -85,6 +48,4 @@ struct termio {
 #define user_termios_to_kernel_termios_1(k, u) copy_from_user(k, u, sizeof(struct termios))
 #define kernel_termios_to_user_termios_1(u, k) copy_to_user(u, k, sizeof(struct termios))
 
-#endif /* __KERNEL__ */
-
 #endif /* _PARISC_TERMIOS_H */
diff --git a/arch/parisc/include/asm/topology.h b/arch/parisc/include/asm/topology.h
deleted file mode 100644 (file)
index d8133eb..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASM_PARISC_TOPOLOGY_H
-#define _ASM_PARISC_TOPOLOGY_H
-
-#include <asm-generic/topology.h>
-
-#endif /* _ASM_PARISC_TOPOLOGY_H */
index 4dab76b70ec9bf26df9e74a56bd317ce9ef7c9de..55512e26b0c20a9921c6165e387b6f988afdd6c9 100644 (file)
@@ -1,840 +1,8 @@
 #ifndef _ASM_PARISC_UNISTD_H_
 #define _ASM_PARISC_UNISTD_H_
 
-/*
- * This file contains the system call numbers.
- */
-
-/*
- *   HP-UX system calls get their native numbers for binary compatibility.
- */
-
-#define __NR_HPUX_exit                    1
-#define __NR_HPUX_fork                    2
-#define __NR_HPUX_read                    3
-#define __NR_HPUX_write                   4
-#define __NR_HPUX_open                    5
-#define __NR_HPUX_close                   6
-#define __NR_HPUX_wait                    7
-#define __NR_HPUX_creat                   8
-#define __NR_HPUX_link                    9
-#define __NR_HPUX_unlink                 10
-#define __NR_HPUX_execv                  11
-#define __NR_HPUX_chdir                  12
-#define __NR_HPUX_time                   13
-#define __NR_HPUX_mknod                  14
-#define __NR_HPUX_chmod                  15
-#define __NR_HPUX_chown                  16
-#define __NR_HPUX_break                  17
-#define __NR_HPUX_lchmod                 18
-#define __NR_HPUX_lseek                  19
-#define __NR_HPUX_getpid                 20
-#define __NR_HPUX_mount                  21
-#define __NR_HPUX_umount                 22
-#define __NR_HPUX_setuid                 23
-#define __NR_HPUX_getuid                 24
-#define __NR_HPUX_stime                  25
-#define __NR_HPUX_ptrace                 26
-#define __NR_HPUX_alarm                  27
-#define __NR_HPUX_oldfstat               28
-#define __NR_HPUX_pause                  29
-#define __NR_HPUX_utime                  30
-#define __NR_HPUX_stty                   31
-#define __NR_HPUX_gtty                   32
-#define __NR_HPUX_access                 33
-#define __NR_HPUX_nice                   34
-#define __NR_HPUX_ftime                  35
-#define __NR_HPUX_sync                   36
-#define __NR_HPUX_kill                   37
-#define __NR_HPUX_stat                   38
-#define __NR_HPUX_setpgrp3               39
-#define __NR_HPUX_lstat                  40
-#define __NR_HPUX_dup                    41
-#define __NR_HPUX_pipe                   42
-#define __NR_HPUX_times                  43
-#define __NR_HPUX_profil                 44
-#define __NR_HPUX_ki_call                45
-#define __NR_HPUX_setgid                 46
-#define __NR_HPUX_getgid                 47
-#define __NR_HPUX_sigsys                 48
-#define __NR_HPUX_reserved1              49
-#define __NR_HPUX_reserved2              50
-#define __NR_HPUX_acct                   51
-#define __NR_HPUX_set_userthreadid       52
-#define __NR_HPUX_oldlock                53
-#define __NR_HPUX_ioctl                  54
-#define __NR_HPUX_reboot                 55
-#define __NR_HPUX_symlink                56
-#define __NR_HPUX_utssys                 57
-#define __NR_HPUX_readlink               58
-#define __NR_HPUX_execve                 59
-#define __NR_HPUX_umask                  60
-#define __NR_HPUX_chroot                 61
-#define __NR_HPUX_fcntl                  62
-#define __NR_HPUX_ulimit                 63
-#define __NR_HPUX_getpagesize            64
-#define __NR_HPUX_mremap                 65
-#define __NR_HPUX_vfork                  66
-#define __NR_HPUX_vread                  67
-#define __NR_HPUX_vwrite                 68
-#define __NR_HPUX_sbrk                   69
-#define __NR_HPUX_sstk                   70
-#define __NR_HPUX_mmap                   71
-#define __NR_HPUX_vadvise                72
-#define __NR_HPUX_munmap                 73
-#define __NR_HPUX_mprotect               74
-#define __NR_HPUX_madvise                75
-#define __NR_HPUX_vhangup                76
-#define __NR_HPUX_swapoff                77
-#define __NR_HPUX_mincore                78
-#define __NR_HPUX_getgroups              79
-#define __NR_HPUX_setgroups              80
-#define __NR_HPUX_getpgrp2               81
-#define __NR_HPUX_setpgrp2               82
-#define __NR_HPUX_setitimer              83
-#define __NR_HPUX_wait3                  84
-#define __NR_HPUX_swapon                 85
-#define __NR_HPUX_getitimer              86
-#define __NR_HPUX_gethostname42          87
-#define __NR_HPUX_sethostname42          88
-#define __NR_HPUX_getdtablesize          89
-#define __NR_HPUX_dup2                   90
-#define __NR_HPUX_getdopt                91
-#define __NR_HPUX_fstat                  92
-#define __NR_HPUX_select                 93
-#define __NR_HPUX_setdopt                94
-#define __NR_HPUX_fsync                  95
-#define __NR_HPUX_setpriority            96
-#define __NR_HPUX_socket_old             97
-#define __NR_HPUX_connect_old            98
-#define __NR_HPUX_accept_old             99
-#define __NR_HPUX_getpriority           100
-#define __NR_HPUX_send_old              101
-#define __NR_HPUX_recv_old              102
-#define __NR_HPUX_socketaddr_old        103
-#define __NR_HPUX_bind_old              104
-#define __NR_HPUX_setsockopt_old        105
-#define __NR_HPUX_listen_old            106
-#define __NR_HPUX_vtimes_old            107
-#define __NR_HPUX_sigvector             108
-#define __NR_HPUX_sigblock              109
-#define __NR_HPUX_siggetmask            110
-#define __NR_HPUX_sigpause              111
-#define __NR_HPUX_sigstack              112
-#define __NR_HPUX_recvmsg_old           113
-#define __NR_HPUX_sendmsg_old           114
-#define __NR_HPUX_vtrace_old            115
-#define __NR_HPUX_gettimeofday          116
-#define __NR_HPUX_getrusage             117
-#define __NR_HPUX_getsockopt_old        118
-#define __NR_HPUX_resuba_old            119
-#define __NR_HPUX_readv                 120
-#define __NR_HPUX_writev                121
-#define __NR_HPUX_settimeofday          122
-#define __NR_HPUX_fchown                123
-#define __NR_HPUX_fchmod                124
-#define __NR_HPUX_recvfrom_old          125
-#define __NR_HPUX_setresuid             126
-#define __NR_HPUX_setresgid             127
-#define __NR_HPUX_rename                128
-#define __NR_HPUX_truncate              129
-#define __NR_HPUX_ftruncate             130
-#define __NR_HPUX_flock_old             131
-#define __NR_HPUX_sysconf               132
-#define __NR_HPUX_sendto_old            133
-#define __NR_HPUX_shutdown_old          134
-#define __NR_HPUX_socketpair_old        135
-#define __NR_HPUX_mkdir                 136
-#define __NR_HPUX_rmdir                 137
-#define __NR_HPUX_utimes_old            138
-#define __NR_HPUX_sigcleanup_old        139
-#define __NR_HPUX_setcore               140
-#define __NR_HPUX_getpeername_old       141
-#define __NR_HPUX_gethostid             142
-#define __NR_HPUX_sethostid             143
-#define __NR_HPUX_getrlimit             144
-#define __NR_HPUX_setrlimit             145
-#define __NR_HPUX_killpg_old            146
-#define __NR_HPUX_cachectl              147
-#define __NR_HPUX_quotactl              148
-#define __NR_HPUX_get_sysinfo           149
-#define __NR_HPUX_getsockname_old       150
-#define __NR_HPUX_privgrp               151
-#define __NR_HPUX_rtprio                152
-#define __NR_HPUX_plock                 153
-#define __NR_HPUX_reserved3             154
-#define __NR_HPUX_lockf                 155
-#define __NR_HPUX_semget                156
-#define __NR_HPUX_osemctl               157
-#define __NR_HPUX_semop                 158
-#define __NR_HPUX_msgget                159
-#define __NR_HPUX_omsgctl               160
-#define __NR_HPUX_msgsnd                161
-#define __NR_HPUX_msgrecv               162
-#define __NR_HPUX_shmget                163
-#define __NR_HPUX_oshmctl               164
-#define __NR_HPUX_shmat                 165
-#define __NR_HPUX_shmdt                 166
-#define __NR_HPUX_m68020_advise         167
-/* [168,189] are for Discless/DUX */
-#define __NR_HPUX_csp                   168
-#define __NR_HPUX_cluster               169
-#define __NR_HPUX_mkrnod                170
-#define __NR_HPUX_test                  171
-#define __NR_HPUX_unsp_open             172
-#define __NR_HPUX_reserved4             173
-#define __NR_HPUX_getcontext_old        174
-#define __NR_HPUX_osetcontext           175
-#define __NR_HPUX_bigio                 176
-#define __NR_HPUX_pipenode              177
-#define __NR_HPUX_lsync                 178
-#define __NR_HPUX_getmachineid          179
-#define __NR_HPUX_cnodeid               180
-#define __NR_HPUX_cnodes                181
-#define __NR_HPUX_swapclients           182
-#define __NR_HPUX_rmt_process           183
-#define __NR_HPUX_dskless_stats         184
-#define __NR_HPUX_sigprocmask           185
-#define __NR_HPUX_sigpending            186
-#define __NR_HPUX_sigsuspend            187
-#define __NR_HPUX_sigaction             188
-#define __NR_HPUX_reserved5             189
-#define __NR_HPUX_nfssvc                190
-#define __NR_HPUX_getfh                 191
-#define __NR_HPUX_getdomainname         192
-#define __NR_HPUX_setdomainname         193
-#define __NR_HPUX_async_daemon          194
-#define __NR_HPUX_getdirentries         195
-#define __NR_HPUX_statfs                196
-#define __NR_HPUX_fstatfs               197
-#define __NR_HPUX_vfsmount              198
-#define __NR_HPUX_reserved6             199
-#define __NR_HPUX_waitpid               200
-/* 201 - 223 missing */
-#define __NR_HPUX_sigsetreturn          224
-#define __NR_HPUX_sigsetstatemask       225
-/* 226 missing */
-#define __NR_HPUX_cs                    227
-#define __NR_HPUX_cds                   228
-#define __NR_HPUX_set_no_trunc          229
-#define __NR_HPUX_pathconf              230
-#define __NR_HPUX_fpathconf             231
-/* 232, 233 missing */
-#define __NR_HPUX_nfs_fcntl             234
-#define __NR_HPUX_ogetacl               235
-#define __NR_HPUX_ofgetacl              236
-#define __NR_HPUX_osetacl               237
-#define __NR_HPUX_ofsetacl              238
-#define __NR_HPUX_pstat                 239
-#define __NR_HPUX_getaudid              240
-#define __NR_HPUX_setaudid              241
-#define __NR_HPUX_getaudproc            242
-#define __NR_HPUX_setaudproc            243
-#define __NR_HPUX_getevent              244
-#define __NR_HPUX_setevent              245
-#define __NR_HPUX_audwrite              246
-#define __NR_HPUX_audswitch             247
-#define __NR_HPUX_audctl                248
-#define __NR_HPUX_ogetaccess            249
-#define __NR_HPUX_fsctl                 250
-/* 251 - 258 missing */
-#define __NR_HPUX_swapfs                259
-#define __NR_HPUX_fss                   260
-/* 261 - 266 missing */
-#define __NR_HPUX_tsync                 267
-#define __NR_HPUX_getnumfds             268
-#define __NR_HPUX_poll                  269
-#define __NR_HPUX_getmsg                270
-#define __NR_HPUX_putmsg                271
-#define __NR_HPUX_fchdir                272
-#define __NR_HPUX_getmount_cnt          273
-#define __NR_HPUX_getmount_entry        274
-#define __NR_HPUX_accept                275
-#define __NR_HPUX_bind                  276
-#define __NR_HPUX_connect               277
-#define __NR_HPUX_getpeername           278
-#define __NR_HPUX_getsockname           279
-#define __NR_HPUX_getsockopt            280
-#define __NR_HPUX_listen                281
-#define __NR_HPUX_recv                  282
-#define __NR_HPUX_recvfrom              283
-#define __NR_HPUX_recvmsg               284
-#define __NR_HPUX_send                  285
-#define __NR_HPUX_sendmsg               286
-#define __NR_HPUX_sendto                287
-#define __NR_HPUX_setsockopt            288
-#define __NR_HPUX_shutdown              289
-#define __NR_HPUX_socket                290
-#define __NR_HPUX_socketpair            291
-#define __NR_HPUX_proc_open             292
-#define __NR_HPUX_proc_close            293
-#define __NR_HPUX_proc_send             294
-#define __NR_HPUX_proc_recv             295
-#define __NR_HPUX_proc_sendrecv         296
-#define __NR_HPUX_proc_syscall          297
-/* 298 - 311 missing */
-#define __NR_HPUX_semctl                312
-#define __NR_HPUX_msgctl                313
-#define __NR_HPUX_shmctl                314
-#define __NR_HPUX_mpctl                 315
-#define __NR_HPUX_exportfs              316
-#define __NR_HPUX_getpmsg               317
-#define __NR_HPUX_putpmsg               318
-/* 319 missing */
-#define __NR_HPUX_msync                 320
-#define __NR_HPUX_msleep                321
-#define __NR_HPUX_mwakeup               322
-#define __NR_HPUX_msem_init             323
-#define __NR_HPUX_msem_remove           324
-#define __NR_HPUX_adjtime               325
-#define __NR_HPUX_kload                 326
-#define __NR_HPUX_fattach               327
-#define __NR_HPUX_fdetach               328
-#define __NR_HPUX_serialize             329
-#define __NR_HPUX_statvfs               330
-#define __NR_HPUX_fstatvfs              331
-#define __NR_HPUX_lchown                332
-#define __NR_HPUX_getsid                333
-#define __NR_HPUX_sysfs                 334
-/* 335, 336 missing */
-#define __NR_HPUX_sched_setparam        337
-#define __NR_HPUX_sched_getparam        338
-#define __NR_HPUX_sched_setscheduler    339
-#define __NR_HPUX_sched_getscheduler    340
-#define __NR_HPUX_sched_yield           341
-#define __NR_HPUX_sched_get_priority_max 342
-#define __NR_HPUX_sched_get_priority_min 343
-#define __NR_HPUX_sched_rr_get_interval 344
-#define __NR_HPUX_clock_settime         345
-#define __NR_HPUX_clock_gettime         346
-#define __NR_HPUX_clock_getres          347
-#define __NR_HPUX_timer_create          348
-#define __NR_HPUX_timer_delete          349
-#define __NR_HPUX_timer_settime         350
-#define __NR_HPUX_timer_gettime         351
-#define __NR_HPUX_timer_getoverrun      352
-#define __NR_HPUX_nanosleep             353
-#define __NR_HPUX_toolbox               354
-/* 355 missing */
-#define __NR_HPUX_getdents              356
-#define __NR_HPUX_getcontext            357
-#define __NR_HPUX_sysinfo               358
-#define __NR_HPUX_fcntl64               359
-#define __NR_HPUX_ftruncate64           360
-#define __NR_HPUX_fstat64               361
-#define __NR_HPUX_getdirentries64       362
-#define __NR_HPUX_getrlimit64           363
-#define __NR_HPUX_lockf64               364
-#define __NR_HPUX_lseek64               365
-#define __NR_HPUX_lstat64               366
-#define __NR_HPUX_mmap64                367
-#define __NR_HPUX_setrlimit64           368
-#define __NR_HPUX_stat64                369
-#define __NR_HPUX_truncate64            370
-#define __NR_HPUX_ulimit64              371
-#define __NR_HPUX_pread                 372
-#define __NR_HPUX_preadv                373
-#define __NR_HPUX_pwrite                374
-#define __NR_HPUX_pwritev               375
-#define __NR_HPUX_pread64               376
-#define __NR_HPUX_preadv64              377
-#define __NR_HPUX_pwrite64              378
-#define __NR_HPUX_pwritev64             379
-#define __NR_HPUX_setcontext            380
-#define __NR_HPUX_sigaltstack           381
-#define __NR_HPUX_waitid                382
-#define __NR_HPUX_setpgrp               383
-#define __NR_HPUX_recvmsg2              384
-#define __NR_HPUX_sendmsg2              385
-#define __NR_HPUX_socket2               386
-#define __NR_HPUX_socketpair2           387
-#define __NR_HPUX_setregid              388
-#define __NR_HPUX_lwp_create            389
-#define __NR_HPUX_lwp_terminate         390
-#define __NR_HPUX_lwp_wait              391
-#define __NR_HPUX_lwp_suspend           392
-#define __NR_HPUX_lwp_resume            393
-/* 394 missing */
-#define __NR_HPUX_lwp_abort_syscall     395
-#define __NR_HPUX_lwp_info              396
-#define __NR_HPUX_lwp_kill              397
-#define __NR_HPUX_ksleep                398
-#define __NR_HPUX_kwakeup               399
-/* 400 missing */
-#define __NR_HPUX_pstat_getlwp          401
-#define __NR_HPUX_lwp_exit              402
-#define __NR_HPUX_lwp_continue          403
-#define __NR_HPUX_getacl                404
-#define __NR_HPUX_fgetacl               405
-#define __NR_HPUX_setacl                406
-#define __NR_HPUX_fsetacl               407
-#define __NR_HPUX_getaccess             408
-#define __NR_HPUX_lwp_mutex_init        409
-#define __NR_HPUX_lwp_mutex_lock_sys    410
-#define __NR_HPUX_lwp_mutex_unlock      411
-#define __NR_HPUX_lwp_cond_init         412
-#define __NR_HPUX_lwp_cond_signal       413
-#define __NR_HPUX_lwp_cond_broadcast    414
-#define __NR_HPUX_lwp_cond_wait_sys     415
-#define __NR_HPUX_lwp_getscheduler      416
-#define __NR_HPUX_lwp_setscheduler      417
-#define __NR_HPUX_lwp_getstate          418
-#define __NR_HPUX_lwp_setstate          419
-#define __NR_HPUX_lwp_detach            420
-#define __NR_HPUX_mlock                 421
-#define __NR_HPUX_munlock               422
-#define __NR_HPUX_mlockall              423
-#define __NR_HPUX_munlockall            424
-#define __NR_HPUX_shm_open              425
-#define __NR_HPUX_shm_unlink            426
-#define __NR_HPUX_sigqueue              427
-#define __NR_HPUX_sigwaitinfo           428
-#define __NR_HPUX_sigtimedwait          429
-#define __NR_HPUX_sigwait               430
-#define __NR_HPUX_aio_read              431
-#define __NR_HPUX_aio_write             432
-#define __NR_HPUX_lio_listio            433
-#define __NR_HPUX_aio_error             434
-#define __NR_HPUX_aio_return            435
-#define __NR_HPUX_aio_cancel            436
-#define __NR_HPUX_aio_suspend           437
-#define __NR_HPUX_aio_fsync             438
-#define __NR_HPUX_mq_open               439
-#define __NR_HPUX_mq_close              440
-#define __NR_HPUX_mq_unlink             441
-#define __NR_HPUX_mq_send               442
-#define __NR_HPUX_mq_receive            443
-#define __NR_HPUX_mq_notify             444
-#define __NR_HPUX_mq_setattr            445
-#define __NR_HPUX_mq_getattr            446
-#define __NR_HPUX_ksem_open             447
-#define __NR_HPUX_ksem_unlink           448
-#define __NR_HPUX_ksem_close            449
-#define __NR_HPUX_ksem_post             450
-#define __NR_HPUX_ksem_wait             451
-#define __NR_HPUX_ksem_read             452
-#define __NR_HPUX_ksem_trywait          453
-#define __NR_HPUX_lwp_rwlock_init       454
-#define __NR_HPUX_lwp_rwlock_destroy    455
-#define __NR_HPUX_lwp_rwlock_rdlock_sys 456
-#define __NR_HPUX_lwp_rwlock_wrlock_sys 457
-#define __NR_HPUX_lwp_rwlock_tryrdlock  458
-#define __NR_HPUX_lwp_rwlock_trywrlock  459
-#define __NR_HPUX_lwp_rwlock_unlock     460
-#define __NR_HPUX_ttrace                461
-#define __NR_HPUX_ttrace_wait           462
-#define __NR_HPUX_lf_wire_mem           463
-#define __NR_HPUX_lf_unwire_mem         464
-#define __NR_HPUX_lf_send_pin_map       465
-#define __NR_HPUX_lf_free_buf           466
-#define __NR_HPUX_lf_wait_nq            467
-#define __NR_HPUX_lf_wakeup_conn_q      468
-#define __NR_HPUX_lf_unused             469
-#define __NR_HPUX_lwp_sema_init         470
-#define __NR_HPUX_lwp_sema_post         471
-#define __NR_HPUX_lwp_sema_wait         472
-#define __NR_HPUX_lwp_sema_trywait      473
-#define __NR_HPUX_lwp_sema_destroy      474
-#define __NR_HPUX_statvfs64             475
-#define __NR_HPUX_fstatvfs64            476
-#define __NR_HPUX_msh_register          477
-#define __NR_HPUX_ptrace64              478
-#define __NR_HPUX_sendfile              479
-#define __NR_HPUX_sendpath              480
-#define __NR_HPUX_sendfile64            481
-#define __NR_HPUX_sendpath64            482
-#define __NR_HPUX_modload               483
-#define __NR_HPUX_moduload              484
-#define __NR_HPUX_modpath               485
-#define __NR_HPUX_getksym               486
-#define __NR_HPUX_modadm                487
-#define __NR_HPUX_modstat               488
-#define __NR_HPUX_lwp_detached_exit     489
-#define __NR_HPUX_crashconf             490
-#define __NR_HPUX_siginhibit            491
-#define __NR_HPUX_sigenable             492
-#define __NR_HPUX_spuctl                493
-#define __NR_HPUX_zerokernelsum         494
-#define __NR_HPUX_nfs_kstat             495
-#define __NR_HPUX_aio_read64            496
-#define __NR_HPUX_aio_write64           497
-#define __NR_HPUX_aio_error64           498
-#define __NR_HPUX_aio_return64          499
-#define __NR_HPUX_aio_cancel64          500
-#define __NR_HPUX_aio_suspend64         501
-#define __NR_HPUX_aio_fsync64           502
-#define __NR_HPUX_lio_listio64          503
-#define __NR_HPUX_recv2                 504
-#define __NR_HPUX_recvfrom2             505
-#define __NR_HPUX_send2                 506
-#define __NR_HPUX_sendto2               507
-#define __NR_HPUX_acl                   508
-#define __NR_HPUX___cnx_p2p_ctl         509
-#define __NR_HPUX___cnx_gsched_ctl      510
-#define __NR_HPUX___cnx_pmon_ctl        511
-
-#define __NR_HPUX_syscalls             512
-
-/*
- * Linux system call numbers.
- *
- * Cary Coutant says that we should just use another syscall gateway
- * page to avoid clashing with the HPUX space, and I think he's right:
- * it will would keep a branch out of our syscall entry path, at the
- * very least.  If we decide to change it later, we can ``just'' tweak
- * the LINUX_GATEWAY_ADDR define at the bottom and make __NR_Linux be
- * 1024 or something.  Oh, and recompile libc. =)
- *
- * 64-bit HPUX binaries get the syscall gateway address passed in a register
- * from the kernel at startup, which seems a sane strategy.
- */
-
-#define __NR_Linux                0
-#define __NR_restart_syscall      (__NR_Linux + 0)
-#define __NR_exit                 (__NR_Linux + 1)
-#define __NR_fork                 (__NR_Linux + 2)
-#define __NR_read                 (__NR_Linux + 3)
-#define __NR_write                (__NR_Linux + 4)
-#define __NR_open                 (__NR_Linux + 5)
-#define __NR_close                (__NR_Linux + 6)
-#define __NR_waitpid              (__NR_Linux + 7)
-#define __NR_creat                (__NR_Linux + 8)
-#define __NR_link                 (__NR_Linux + 9)
-#define __NR_unlink              (__NR_Linux + 10)
-#define __NR_execve              (__NR_Linux + 11)
-#define __NR_chdir               (__NR_Linux + 12)
-#define __NR_time                (__NR_Linux + 13)
-#define __NR_mknod               (__NR_Linux + 14)
-#define __NR_chmod               (__NR_Linux + 15)
-#define __NR_lchown              (__NR_Linux + 16)
-#define __NR_socket              (__NR_Linux + 17)
-#define __NR_stat                (__NR_Linux + 18)
-#define __NR_lseek               (__NR_Linux + 19)
-#define __NR_getpid              (__NR_Linux + 20)
-#define __NR_mount               (__NR_Linux + 21)
-#define __NR_bind                (__NR_Linux + 22)
-#define __NR_setuid              (__NR_Linux + 23)
-#define __NR_getuid              (__NR_Linux + 24)
-#define __NR_stime               (__NR_Linux + 25)
-#define __NR_ptrace              (__NR_Linux + 26)
-#define __NR_alarm               (__NR_Linux + 27)
-#define __NR_fstat               (__NR_Linux + 28)
-#define __NR_pause               (__NR_Linux + 29)
-#define __NR_utime               (__NR_Linux + 30)
-#define __NR_connect             (__NR_Linux + 31)
-#define __NR_listen              (__NR_Linux + 32)
-#define __NR_access              (__NR_Linux + 33)
-#define __NR_nice                (__NR_Linux + 34)
-#define __NR_accept              (__NR_Linux + 35)
-#define __NR_sync                (__NR_Linux + 36)
-#define __NR_kill                (__NR_Linux + 37)
-#define __NR_rename              (__NR_Linux + 38)
-#define __NR_mkdir               (__NR_Linux + 39)
-#define __NR_rmdir               (__NR_Linux + 40)
-#define __NR_dup                 (__NR_Linux + 41)
-#define __NR_pipe                (__NR_Linux + 42)
-#define __NR_times               (__NR_Linux + 43)
-#define __NR_getsockname         (__NR_Linux + 44)
-#define __NR_brk                 (__NR_Linux + 45)
-#define __NR_setgid              (__NR_Linux + 46)
-#define __NR_getgid              (__NR_Linux + 47)
-#define __NR_signal              (__NR_Linux + 48)
-#define __NR_geteuid             (__NR_Linux + 49)
-#define __NR_getegid             (__NR_Linux + 50)
-#define __NR_acct                (__NR_Linux + 51)
-#define __NR_umount2             (__NR_Linux + 52)
-#define __NR_getpeername         (__NR_Linux + 53)
-#define __NR_ioctl               (__NR_Linux + 54)
-#define __NR_fcntl               (__NR_Linux + 55)
-#define __NR_socketpair          (__NR_Linux + 56)
-#define __NR_setpgid             (__NR_Linux + 57)
-#define __NR_send                (__NR_Linux + 58)
-#define __NR_uname               (__NR_Linux + 59)
-#define __NR_umask               (__NR_Linux + 60)
-#define __NR_chroot              (__NR_Linux + 61)
-#define __NR_ustat               (__NR_Linux + 62)
-#define __NR_dup2                (__NR_Linux + 63)
-#define __NR_getppid             (__NR_Linux + 64)
-#define __NR_getpgrp             (__NR_Linux + 65)
-#define __NR_setsid              (__NR_Linux + 66)
-#define __NR_pivot_root          (__NR_Linux + 67)
-#define __NR_sgetmask            (__NR_Linux + 68)
-#define __NR_ssetmask            (__NR_Linux + 69)
-#define __NR_setreuid            (__NR_Linux + 70)
-#define __NR_setregid            (__NR_Linux + 71)
-#define __NR_mincore             (__NR_Linux + 72)
-#define __NR_sigpending          (__NR_Linux + 73)
-#define __NR_sethostname         (__NR_Linux + 74)
-#define __NR_setrlimit           (__NR_Linux + 75)
-#define __NR_getrlimit           (__NR_Linux + 76)
-#define __NR_getrusage           (__NR_Linux + 77)
-#define __NR_gettimeofday        (__NR_Linux + 78)
-#define __NR_settimeofday        (__NR_Linux + 79)
-#define __NR_getgroups           (__NR_Linux + 80)
-#define __NR_setgroups           (__NR_Linux + 81)
-#define __NR_sendto              (__NR_Linux + 82)
-#define __NR_symlink             (__NR_Linux + 83)
-#define __NR_lstat               (__NR_Linux + 84)
-#define __NR_readlink            (__NR_Linux + 85)
-#define __NR_uselib              (__NR_Linux + 86)
-#define __NR_swapon              (__NR_Linux + 87)
-#define __NR_reboot              (__NR_Linux + 88)
-#define __NR_mmap2             (__NR_Linux + 89)
-#define __NR_mmap                (__NR_Linux + 90)
-#define __NR_munmap              (__NR_Linux + 91)
-#define __NR_truncate            (__NR_Linux + 92)
-#define __NR_ftruncate           (__NR_Linux + 93)
-#define __NR_fchmod              (__NR_Linux + 94)
-#define __NR_fchown              (__NR_Linux + 95)
-#define __NR_getpriority         (__NR_Linux + 96)
-#define __NR_setpriority         (__NR_Linux + 97)
-#define __NR_recv                (__NR_Linux + 98)
-#define __NR_statfs              (__NR_Linux + 99)
-#define __NR_fstatfs            (__NR_Linux + 100)
-#define __NR_stat64           (__NR_Linux + 101)
-/* #define __NR_socketcall         (__NR_Linux + 102) */
-#define __NR_syslog             (__NR_Linux + 103)
-#define __NR_setitimer          (__NR_Linux + 104)
-#define __NR_getitimer          (__NR_Linux + 105)
-#define __NR_capget             (__NR_Linux + 106)
-#define __NR_capset             (__NR_Linux + 107)
-#define __NR_pread64            (__NR_Linux + 108)
-#define __NR_pwrite64           (__NR_Linux + 109)
-#define __NR_getcwd             (__NR_Linux + 110)
-#define __NR_vhangup            (__NR_Linux + 111)
-#define __NR_fstat64            (__NR_Linux + 112)
-#define __NR_vfork              (__NR_Linux + 113)
-#define __NR_wait4              (__NR_Linux + 114)
-#define __NR_swapoff            (__NR_Linux + 115)
-#define __NR_sysinfo            (__NR_Linux + 116)
-#define __NR_shutdown           (__NR_Linux + 117)
-#define __NR_fsync              (__NR_Linux + 118)
-#define __NR_madvise            (__NR_Linux + 119)
-#define __NR_clone              (__NR_Linux + 120)
-#define __NR_setdomainname      (__NR_Linux + 121)
-#define __NR_sendfile           (__NR_Linux + 122)
-#define __NR_recvfrom           (__NR_Linux + 123)
-#define __NR_adjtimex           (__NR_Linux + 124)
-#define __NR_mprotect           (__NR_Linux + 125)
-#define __NR_sigprocmask        (__NR_Linux + 126)
-#define __NR_create_module      (__NR_Linux + 127)
-#define __NR_init_module        (__NR_Linux + 128)
-#define __NR_delete_module      (__NR_Linux + 129)
-#define __NR_get_kernel_syms    (__NR_Linux + 130)
-#define __NR_quotactl           (__NR_Linux + 131)
-#define __NR_getpgid            (__NR_Linux + 132)
-#define __NR_fchdir             (__NR_Linux + 133)
-#define __NR_bdflush            (__NR_Linux + 134)
-#define __NR_sysfs              (__NR_Linux + 135)
-#define __NR_personality        (__NR_Linux + 136)
-#define __NR_afs_syscall        (__NR_Linux + 137) /* Syscall for Andrew File System */
-#define __NR_setfsuid           (__NR_Linux + 138)
-#define __NR_setfsgid           (__NR_Linux + 139)
-#define __NR__llseek            (__NR_Linux + 140)
-#define __NR_getdents           (__NR_Linux + 141)
-#define __NR__newselect         (__NR_Linux + 142)
-#define __NR_flock              (__NR_Linux + 143)
-#define __NR_msync              (__NR_Linux + 144)
-#define __NR_readv              (__NR_Linux + 145)
-#define __NR_writev             (__NR_Linux + 146)
-#define __NR_getsid             (__NR_Linux + 147)
-#define __NR_fdatasync          (__NR_Linux + 148)
-#define __NR__sysctl            (__NR_Linux + 149)
-#define __NR_mlock              (__NR_Linux + 150)
-#define __NR_munlock            (__NR_Linux + 151)
-#define __NR_mlockall           (__NR_Linux + 152)
-#define __NR_munlockall         (__NR_Linux + 153)
-#define __NR_sched_setparam             (__NR_Linux + 154)
-#define __NR_sched_getparam             (__NR_Linux + 155)
-#define __NR_sched_setscheduler         (__NR_Linux + 156)
-#define __NR_sched_getscheduler         (__NR_Linux + 157)
-#define __NR_sched_yield                (__NR_Linux + 158)
-#define __NR_sched_get_priority_max     (__NR_Linux + 159)
-#define __NR_sched_get_priority_min     (__NR_Linux + 160)
-#define __NR_sched_rr_get_interval      (__NR_Linux + 161)
-#define __NR_nanosleep          (__NR_Linux + 162)
-#define __NR_mremap             (__NR_Linux + 163)
-#define __NR_setresuid          (__NR_Linux + 164)
-#define __NR_getresuid          (__NR_Linux + 165)
-#define __NR_sigaltstack        (__NR_Linux + 166)
-#define __NR_query_module       (__NR_Linux + 167)
-#define __NR_poll               (__NR_Linux + 168)
-#define __NR_nfsservctl         (__NR_Linux + 169)
-#define __NR_setresgid          (__NR_Linux + 170)
-#define __NR_getresgid          (__NR_Linux + 171)
-#define __NR_prctl              (__NR_Linux + 172)
-#define __NR_rt_sigreturn       (__NR_Linux + 173)
-#define __NR_rt_sigaction       (__NR_Linux + 174)
-#define __NR_rt_sigprocmask     (__NR_Linux + 175)
-#define __NR_rt_sigpending      (__NR_Linux + 176)
-#define __NR_rt_sigtimedwait    (__NR_Linux + 177)
-#define __NR_rt_sigqueueinfo    (__NR_Linux + 178)
-#define __NR_rt_sigsuspend      (__NR_Linux + 179)
-#define __NR_chown              (__NR_Linux + 180)
-#define __NR_setsockopt         (__NR_Linux + 181)
-#define __NR_getsockopt         (__NR_Linux + 182)
-#define __NR_sendmsg            (__NR_Linux + 183)
-#define __NR_recvmsg            (__NR_Linux + 184)
-#define __NR_semop              (__NR_Linux + 185)
-#define __NR_semget             (__NR_Linux + 186)
-#define __NR_semctl             (__NR_Linux + 187)
-#define __NR_msgsnd             (__NR_Linux + 188)
-#define __NR_msgrcv             (__NR_Linux + 189)
-#define __NR_msgget             (__NR_Linux + 190)
-#define __NR_msgctl             (__NR_Linux + 191)
-#define __NR_shmat              (__NR_Linux + 192)
-#define __NR_shmdt              (__NR_Linux + 193)
-#define __NR_shmget             (__NR_Linux + 194)
-#define __NR_shmctl             (__NR_Linux + 195)
-
-#define __NR_getpmsg           (__NR_Linux + 196) /* Somebody *wants* streams? */
-#define __NR_putpmsg           (__NR_Linux + 197)
-
-#define __NR_lstat64            (__NR_Linux + 198)
-#define __NR_truncate64         (__NR_Linux + 199)
-#define __NR_ftruncate64        (__NR_Linux + 200)
-#define __NR_getdents64         (__NR_Linux + 201)
-#define __NR_fcntl64            (__NR_Linux + 202)
-#define __NR_attrctl            (__NR_Linux + 203)
-#define __NR_acl_get            (__NR_Linux + 204)
-#define __NR_acl_set            (__NR_Linux + 205)
-#define __NR_gettid             (__NR_Linux + 206)
-#define __NR_readahead          (__NR_Linux + 207)
-#define __NR_tkill              (__NR_Linux + 208)
-#define __NR_sendfile64         (__NR_Linux + 209)
-#define __NR_futex              (__NR_Linux + 210)
-#define __NR_sched_setaffinity  (__NR_Linux + 211)
-#define __NR_sched_getaffinity  (__NR_Linux + 212)
-#define __NR_set_thread_area    (__NR_Linux + 213)
-#define __NR_get_thread_area    (__NR_Linux + 214)
-#define __NR_io_setup           (__NR_Linux + 215)
-#define __NR_io_destroy         (__NR_Linux + 216)
-#define __NR_io_getevents       (__NR_Linux + 217)
-#define __NR_io_submit          (__NR_Linux + 218)
-#define __NR_io_cancel          (__NR_Linux + 219)
-#define __NR_alloc_hugepages    (__NR_Linux + 220)
-#define __NR_free_hugepages     (__NR_Linux + 221)
-#define __NR_exit_group         (__NR_Linux + 222)
-#define __NR_lookup_dcookie     (__NR_Linux + 223)
-#define __NR_epoll_create       (__NR_Linux + 224)
-#define __NR_epoll_ctl          (__NR_Linux + 225)
-#define __NR_epoll_wait         (__NR_Linux + 226)
-#define __NR_remap_file_pages   (__NR_Linux + 227)
-#define __NR_semtimedop         (__NR_Linux + 228)
-#define __NR_mq_open            (__NR_Linux + 229)
-#define __NR_mq_unlink          (__NR_Linux + 230)
-#define __NR_mq_timedsend       (__NR_Linux + 231)
-#define __NR_mq_timedreceive    (__NR_Linux + 232)
-#define __NR_mq_notify          (__NR_Linux + 233)
-#define __NR_mq_getsetattr      (__NR_Linux + 234)
-#define __NR_waitid            (__NR_Linux + 235)
-#define __NR_fadvise64_64      (__NR_Linux + 236)
-#define __NR_set_tid_address   (__NR_Linux + 237)
-#define __NR_setxattr          (__NR_Linux + 238)
-#define __NR_lsetxattr         (__NR_Linux + 239)
-#define __NR_fsetxattr         (__NR_Linux + 240)
-#define __NR_getxattr          (__NR_Linux + 241)
-#define __NR_lgetxattr         (__NR_Linux + 242)
-#define __NR_fgetxattr         (__NR_Linux + 243)
-#define __NR_listxattr         (__NR_Linux + 244)
-#define __NR_llistxattr                (__NR_Linux + 245)
-#define __NR_flistxattr                (__NR_Linux + 246)
-#define __NR_removexattr       (__NR_Linux + 247)
-#define __NR_lremovexattr      (__NR_Linux + 248)
-#define __NR_fremovexattr      (__NR_Linux + 249)
-#define __NR_timer_create      (__NR_Linux + 250)
-#define __NR_timer_settime     (__NR_Linux + 251)
-#define __NR_timer_gettime     (__NR_Linux + 252)
-#define __NR_timer_getoverrun  (__NR_Linux + 253)
-#define __NR_timer_delete      (__NR_Linux + 254)
-#define __NR_clock_settime     (__NR_Linux + 255)
-#define __NR_clock_gettime     (__NR_Linux + 256)
-#define __NR_clock_getres      (__NR_Linux + 257)
-#define __NR_clock_nanosleep   (__NR_Linux + 258)
-#define __NR_tgkill            (__NR_Linux + 259)
-#define __NR_mbind             (__NR_Linux + 260)
-#define __NR_get_mempolicy     (__NR_Linux + 261)
-#define __NR_set_mempolicy     (__NR_Linux + 262)
-#define __NR_vserver           (__NR_Linux + 263)
-#define __NR_add_key           (__NR_Linux + 264)
-#define __NR_request_key       (__NR_Linux + 265)
-#define __NR_keyctl            (__NR_Linux + 266)
-#define __NR_ioprio_set                (__NR_Linux + 267)
-#define __NR_ioprio_get                (__NR_Linux + 268)
-#define __NR_inotify_init      (__NR_Linux + 269)
-#define __NR_inotify_add_watch (__NR_Linux + 270)
-#define __NR_inotify_rm_watch  (__NR_Linux + 271)
-#define __NR_migrate_pages     (__NR_Linux + 272)
-#define __NR_pselect6          (__NR_Linux + 273)
-#define __NR_ppoll             (__NR_Linux + 274)
-#define __NR_openat            (__NR_Linux + 275)
-#define __NR_mkdirat           (__NR_Linux + 276)
-#define __NR_mknodat           (__NR_Linux + 277)
-#define __NR_fchownat          (__NR_Linux + 278)
-#define __NR_futimesat         (__NR_Linux + 279)
-#define __NR_fstatat64         (__NR_Linux + 280)
-#define __NR_unlinkat          (__NR_Linux + 281)
-#define __NR_renameat          (__NR_Linux + 282)
-#define __NR_linkat            (__NR_Linux + 283)
-#define __NR_symlinkat         (__NR_Linux + 284)
-#define __NR_readlinkat                (__NR_Linux + 285)
-#define __NR_fchmodat          (__NR_Linux + 286)
-#define __NR_faccessat         (__NR_Linux + 287)
-#define __NR_unshare           (__NR_Linux + 288)
-#define __NR_set_robust_list   (__NR_Linux + 289)
-#define __NR_get_robust_list   (__NR_Linux + 290)
-#define __NR_splice            (__NR_Linux + 291)
-#define __NR_sync_file_range   (__NR_Linux + 292)
-#define __NR_tee               (__NR_Linux + 293)
-#define __NR_vmsplice          (__NR_Linux + 294)
-#define __NR_move_pages                (__NR_Linux + 295)
-#define __NR_getcpu            (__NR_Linux + 296)
-#define __NR_epoll_pwait       (__NR_Linux + 297)
-#define __NR_statfs64          (__NR_Linux + 298)
-#define __NR_fstatfs64         (__NR_Linux + 299)
-#define __NR_kexec_load                (__NR_Linux + 300)
-#define __NR_utimensat         (__NR_Linux + 301)
-#define __NR_signalfd          (__NR_Linux + 302)
-#define __NR_timerfd           (__NR_Linux + 303)
-#define __NR_eventfd           (__NR_Linux + 304)
-#define __NR_fallocate         (__NR_Linux + 305)
-#define __NR_timerfd_create    (__NR_Linux + 306)
-#define __NR_timerfd_settime   (__NR_Linux + 307)
-#define __NR_timerfd_gettime   (__NR_Linux + 308)
-#define __NR_signalfd4         (__NR_Linux + 309)
-#define __NR_eventfd2          (__NR_Linux + 310)
-#define __NR_epoll_create1     (__NR_Linux + 311)
-#define __NR_dup3              (__NR_Linux + 312)
-#define __NR_pipe2             (__NR_Linux + 313)
-#define __NR_inotify_init1     (__NR_Linux + 314)
-#define __NR_preadv            (__NR_Linux + 315)
-#define __NR_pwritev           (__NR_Linux + 316)
-#define __NR_rt_tgsigqueueinfo (__NR_Linux + 317)
-#define __NR_perf_event_open   (__NR_Linux + 318)
-#define __NR_recvmmsg          (__NR_Linux + 319)
-#define __NR_accept4           (__NR_Linux + 320)
-#define __NR_prlimit64         (__NR_Linux + 321)
-#define __NR_fanotify_init     (__NR_Linux + 322)
-#define __NR_fanotify_mark     (__NR_Linux + 323)
-#define __NR_clock_adjtime     (__NR_Linux + 324)
-#define __NR_name_to_handle_at (__NR_Linux + 325)
-#define __NR_open_by_handle_at (__NR_Linux + 326)
-#define __NR_syncfs            (__NR_Linux + 327)
-#define __NR_setns             (__NR_Linux + 328)
-#define __NR_sendmmsg          (__NR_Linux + 329)
-
-#define __NR_Linux_syscalls    (__NR_sendmmsg + 1)
-
-
-#define __IGNORE_select                /* newselect */
-#define __IGNORE_fadvise64     /* fadvise64_64 */
-#define __IGNORE_utimes                /* utime */
-
-
-#define HPUX_GATEWAY_ADDR       0xC0000004
-#define LINUX_GATEWAY_ADDR      0x100
+#include <uapi/asm/unistd.h>
 
-#ifdef __KERNEL__
 #ifndef __ASSEMBLY__
 
 #define SYS_ify(syscall_name)   __NR_##syscall_name
@@ -1009,5 +177,4 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5)      \
  */
 #define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
 
-#endif /* __KERNEL__ */
 #endif /* _ASM_PARISC_UNISTD_H_ */
diff --git a/arch/parisc/include/asm/user.h b/arch/parisc/include/asm/user.h
deleted file mode 100644 (file)
index 8022475..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-/* This file should not exist, but lots of generic code still includes
-   it. It's a hangover from old a.out days and the traditional core
-   dump format.  We are ELF-only, and so are our core dumps.  If we
-   need to support HP/UX core format then we'll do it here
-   eventually. */
diff --git a/arch/parisc/include/asm/vga.h b/arch/parisc/include/asm/vga.h
deleted file mode 100644 (file)
index 171399a..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __ASM_PARISC_VGA_H__
-#define __ASM_PARISC_VGA_H__
-
-/* nothing */
-
-#endif /* __ASM_PARISC_VGA_H__ */
diff --git a/arch/parisc/include/asm/xor.h b/arch/parisc/include/asm/xor.h
deleted file mode 100644 (file)
index c82eb12..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/xor.h>
index baebb3da1d44160fc6f6f259886656e6f494b167..a580642555b6f0e7f087ade117ce062cb303d429 100644 (file)
@@ -1,3 +1,31 @@
 # UAPI Header export list
 include include/uapi/asm-generic/Kbuild.asm
 
+header-y += bitsperlong.h
+header-y += byteorder.h
+header-y += errno.h
+header-y += fcntl.h
+header-y += ioctl.h
+header-y += ioctls.h
+header-y += ipcbuf.h
+header-y += mman.h
+header-y += msgbuf.h
+header-y += pdc.h
+header-y += posix_types.h
+header-y += ptrace.h
+header-y += resource.h
+header-y += sembuf.h
+header-y += setup.h
+header-y += shmbuf.h
+header-y += sigcontext.h
+header-y += siginfo.h
+header-y += signal.h
+header-y += socket.h
+header-y += sockios.h
+header-y += stat.h
+header-y += statfs.h
+header-y += swab.h
+header-y += termbits.h
+header-y += termios.h
+header-y += types.h
+header-y += unistd.h
diff --git a/arch/parisc/include/uapi/asm/pdc.h b/arch/parisc/include/uapi/asm/pdc.h
new file mode 100644 (file)
index 0000000..702498f
--- /dev/null
@@ -0,0 +1,427 @@
+#ifndef _UAPI_PARISC_PDC_H
+#define _UAPI_PARISC_PDC_H
+
+/*
+ *     PDC return values ...
+ *     All PDC calls return a subset of these errors. 
+ */
+
+#define PDC_WARN                 3     /* Call completed with a warning */
+#define PDC_REQ_ERR_1            2     /* See above                     */
+#define PDC_REQ_ERR_0            1     /* Call would generate a requestor error */
+#define PDC_OK                   0     /* Call completed successfully  */
+#define PDC_BAD_PROC            -1     /* Called non-existent procedure*/
+#define PDC_BAD_OPTION          -2     /* Called with non-existent option */
+#define PDC_ERROR               -3     /* Call could not complete without an error */
+#define PDC_NE_MOD              -5     /* Module not found             */
+#define PDC_NE_CELL_MOD                 -7     /* Cell module not found        */
+#define PDC_INVALID_ARG                -10     /* Called with an invalid argument */
+#define PDC_BUS_POW_WARN       -12     /* Call could not complete in allowed power budget */
+#define PDC_NOT_NARROW         -17     /* Narrow mode not supported    */
+
+/*
+ *     PDC entry points...
+ */
+
+#define PDC_POW_FAIL   1               /* perform a power-fail         */
+#define PDC_POW_FAIL_PREPARE   0       /* prepare for powerfail        */
+
+#define PDC_CHASSIS    2               /* PDC-chassis functions        */
+#define PDC_CHASSIS_DISP       0       /* update chassis display       */
+#define PDC_CHASSIS_WARN       1       /* return chassis warnings      */
+#define PDC_CHASSIS_DISPWARN   2       /* update&return chassis status */
+#define PDC_RETURN_CHASSIS_INFO 128    /* HVERSION dependent: return chassis LED/LCD info  */
+
+#define PDC_PIM         3               /* Get PIM data                 */
+#define PDC_PIM_HPMC            0       /* Transfer HPMC data           */
+#define PDC_PIM_RETURN_SIZE     1       /* Get Max buffer needed for PIM*/
+#define PDC_PIM_LPMC            2       /* Transfer HPMC data           */
+#define PDC_PIM_SOFT_BOOT       3       /* Transfer Soft Boot data      */
+#define PDC_PIM_TOC             4       /* Transfer TOC data            */
+
+#define PDC_MODEL      4               /* PDC model information call   */
+#define PDC_MODEL_INFO         0       /* returns information          */
+#define PDC_MODEL_BOOTID       1       /* set the BOOT_ID              */
+#define PDC_MODEL_VERSIONS     2       /* returns cpu-internal versions*/
+#define PDC_MODEL_SYSMODEL     3       /* return system model info     */
+#define PDC_MODEL_ENSPEC       4       /* enable specific option       */
+#define PDC_MODEL_DISPEC       5       /* disable specific option      */
+#define PDC_MODEL_CPU_ID       6       /* returns cpu-id (only newer machines!) */
+#define PDC_MODEL_CAPABILITIES 7       /* returns OS32/OS64-flags      */
+/* Values for PDC_MODEL_CAPABILITIES non-equivalent virtual aliasing support */
+#define  PDC_MODEL_OS64                        (1 << 0)
+#define  PDC_MODEL_OS32                        (1 << 1)
+#define  PDC_MODEL_IOPDIR_FDC          (1 << 2)
+#define  PDC_MODEL_NVA_MASK            (3 << 4)
+#define  PDC_MODEL_NVA_SUPPORTED       (0 << 4)
+#define  PDC_MODEL_NVA_SLOW            (1 << 4)
+#define  PDC_MODEL_NVA_UNSUPPORTED     (3 << 4)
+#define PDC_MODEL_GET_BOOT__OP 8       /* returns boot test options    */
+#define PDC_MODEL_SET_BOOT__OP 9       /* set boot test options        */
+
+#define PA89_INSTRUCTION_SET   0x4     /* capatibilies returned        */
+#define PA90_INSTRUCTION_SET   0x8
+
+#define PDC_CACHE      5               /* return/set cache (& TLB) info*/
+#define PDC_CACHE_INFO         0       /* returns information          */
+#define PDC_CACHE_SET_COH      1       /* set coherence state          */
+#define PDC_CACHE_RET_SPID     2       /* returns space-ID bits        */
+
+#define PDC_HPA                6               /* return HPA of processor      */
+#define PDC_HPA_PROCESSOR      0
+#define PDC_HPA_MODULES                1
+
+#define PDC_COPROC     7               /* Co-Processor (usually FP unit(s)) */
+#define PDC_COPROC_CFG         0       /* Co-Processor Cfg (FP unit(s) enabled?) */
+
+#define PDC_IODC       8               /* talk to IODC                 */
+#define PDC_IODC_READ          0       /* read IODC entry point        */
+/*      PDC_IODC_RI_                    * INDEX parameter of PDC_IODC_READ */
+#define PDC_IODC_RI_DATA_BYTES 0       /* IODC Data Bytes              */
+/*                             1, 2       obsolete - HVERSION dependent*/
+#define PDC_IODC_RI_INIT       3       /* Initialize module            */
+#define PDC_IODC_RI_IO         4       /* Module input/output          */
+#define PDC_IODC_RI_SPA                5       /* Module input/output          */
+#define PDC_IODC_RI_CONFIG     6       /* Module input/output          */
+/*                             7         obsolete - HVERSION dependent */
+#define PDC_IODC_RI_TEST       8       /* Module input/output          */
+#define PDC_IODC_RI_TLB                9       /* Module input/output          */
+#define PDC_IODC_NINIT         2       /* non-destructive init         */
+#define PDC_IODC_DINIT         3       /* destructive init             */
+#define PDC_IODC_MEMERR                4       /* check for memory errors      */
+#define PDC_IODC_INDEX_DATA    0       /* get first 16 bytes from mod IODC */
+#define PDC_IODC_BUS_ERROR     -4      /* bus error return value       */
+#define PDC_IODC_INVALID_INDEX -5      /* invalid index return value   */
+#define PDC_IODC_COUNT         -6      /* count is too small           */
+
+#define PDC_TOD                9               /* time-of-day clock (TOD)      */
+#define PDC_TOD_READ           0       /* read TOD                     */
+#define PDC_TOD_WRITE          1       /* write TOD                    */
+
+
+#define PDC_STABLE     10              /* stable storage (sprockets)   */
+#define PDC_STABLE_READ                0
+#define PDC_STABLE_WRITE       1
+#define PDC_STABLE_RETURN_SIZE 2
+#define PDC_STABLE_VERIFY_CONTENTS 3
+#define PDC_STABLE_INITIALIZE  4
+
+#define PDC_NVOLATILE  11              /* often not implemented        */
+
+#define PDC_ADD_VALID  12              /* Memory validation PDC call   */
+#define PDC_ADD_VALID_VERIFY   0       /* Make PDC_ADD_VALID verify region */
+
+#define PDC_INSTR      15              /* get instr to invoke PDCE_CHECK() */
+
+#define PDC_PROC       16              /* (sprockets)                  */
+
+#define PDC_CONFIG     16              /* (sprockets)                  */
+#define PDC_CONFIG_DECONFIG    0
+#define PDC_CONFIG_DRECONFIG   1
+#define PDC_CONFIG_DRETURN_CONFIG 2
+
+#define PDC_BLOCK_TLB  18              /* manage hardware block-TLB    */
+#define PDC_BTLB_INFO          0       /* returns parameter            */
+#define PDC_BTLB_INSERT                1       /* insert BTLB entry            */
+#define PDC_BTLB_PURGE         2       /* purge BTLB entries           */
+#define PDC_BTLB_PURGE_ALL     3       /* purge all BTLB entries       */
+
+#define PDC_TLB                19              /* manage hardware TLB miss handling */
+#define PDC_TLB_INFO           0       /* returns parameter            */
+#define PDC_TLB_SETUP          1       /* set up miss handling         */
+
+#define PDC_MEM                20              /* Manage memory                */
+#define PDC_MEM_MEMINFO                0
+#define PDC_MEM_ADD_PAGE       1
+#define PDC_MEM_CLEAR_PDT      2
+#define PDC_MEM_READ_PDT       3
+#define PDC_MEM_RESET_CLEAR    4
+#define PDC_MEM_GOODMEM                5
+#define PDC_MEM_TABLE          128     /* Non contig mem map (sprockets) */
+#define PDC_MEM_RETURN_ADDRESS_TABLE   PDC_MEM_TABLE
+#define PDC_MEM_GET_MEMORY_SYSTEM_TABLES_SIZE  131
+#define PDC_MEM_GET_MEMORY_SYSTEM_TABLES       132
+#define PDC_MEM_GET_PHYSICAL_LOCATION_FROM_MEMORY_ADDRESS 133
+
+#define PDC_MEM_RET_SBE_REPLACED       5       /* PDC_MEM return values */
+#define PDC_MEM_RET_DUPLICATE_ENTRY    4
+#define PDC_MEM_RET_BUF_SIZE_SMALL     1
+#define PDC_MEM_RET_PDT_FULL           -11
+#define PDC_MEM_RET_INVALID_PHYSICAL_LOCATION ~0ULL
+
+#define PDC_PSW                21              /* Get/Set default System Mask  */
+#define PDC_PSW_MASK           0       /* Return mask                  */
+#define PDC_PSW_GET_DEFAULTS   1       /* Return defaults              */
+#define PDC_PSW_SET_DEFAULTS   2       /* Set default                  */
+#define PDC_PSW_ENDIAN_BIT     1       /* set for big endian           */
+#define PDC_PSW_WIDE_BIT       2       /* set for wide mode            */ 
+
+#define PDC_SYSTEM_MAP 22              /* find system modules          */
+#define PDC_FIND_MODULE        0
+#define PDC_FIND_ADDRESS       1
+#define PDC_TRANSLATE_PATH     2
+
+#define PDC_SOFT_POWER 23              /* soft power switch            */
+#define PDC_SOFT_POWER_INFO    0       /* return info about the soft power switch */
+#define PDC_SOFT_POWER_ENABLE  1       /* enable/disable soft power switch */
+
+
+/* HVERSION dependent */
+
+/* The PDC_MEM_MAP calls */
+#define PDC_MEM_MAP    128             /* on s700: return page info    */
+#define PDC_MEM_MAP_HPA                0       /* returns hpa of a module      */
+
+#define PDC_EEPROM     129             /* EEPROM access                */
+#define PDC_EEPROM_READ_WORD   0
+#define PDC_EEPROM_WRITE_WORD  1
+#define PDC_EEPROM_READ_BYTE   2
+#define PDC_EEPROM_WRITE_BYTE  3
+#define PDC_EEPROM_EEPROM_PASSWORD -1000
+
+#define PDC_NVM                130             /* NVM (non-volatile memory) access */
+#define PDC_NVM_READ_WORD      0
+#define PDC_NVM_WRITE_WORD     1
+#define PDC_NVM_READ_BYTE      2
+#define PDC_NVM_WRITE_BYTE     3
+
+#define PDC_SEED_ERROR 132             /* (sprockets)                  */
+
+#define PDC_IO         135             /* log error info, reset IO system */
+#define PDC_IO_READ_AND_CLEAR_ERRORS   0
+#define PDC_IO_RESET                   1
+#define PDC_IO_RESET_DEVICES           2
+/* sets bits 6&7 (little endian) of the HcControl Register */
+#define PDC_IO_USB_SUSPEND     0xC000000000000000
+#define PDC_IO_EEPROM_IO_ERR_TABLE_FULL        -5      /* return value */
+#define PDC_IO_NO_SUSPEND              -6      /* return value */
+
+#define PDC_BROADCAST_RESET 136                /* reset all processors         */
+#define PDC_DO_RESET           0       /* option: perform a broadcast reset */
+#define PDC_DO_FIRM_TEST_RESET 1       /* Do broadcast reset with bitmap */
+#define PDC_BR_RECONFIGURATION 2       /* reset w/reconfiguration      */
+#define PDC_FIRM_TEST_MAGIC    0xab9ec36fUL    /* for this reboot only */
+
+#define PDC_LAN_STATION_ID 138         /* Hversion dependent mechanism for */
+#define PDC_LAN_STATION_ID_READ        0       /* getting the lan station address  */
+
+#define        PDC_LAN_STATION_ID_SIZE 6
+
+#define PDC_CHECK_RANGES 139           /* (sprockets)                  */
+
+#define PDC_NV_SECTIONS        141             /* (sprockets)                  */
+
+#define PDC_PERFORMANCE        142             /* performance monitoring       */
+
+#define PDC_SYSTEM_INFO        143             /* system information           */
+#define PDC_SYSINFO_RETURN_INFO_SIZE   0
+#define PDC_SYSINFO_RRETURN_SYS_INFO   1
+#define PDC_SYSINFO_RRETURN_ERRORS     2
+#define PDC_SYSINFO_RRETURN_WARNINGS   3
+#define PDC_SYSINFO_RETURN_REVISIONS   4
+#define PDC_SYSINFO_RRETURN_DIAGNOSE   5
+#define PDC_SYSINFO_RRETURN_HV_DIAGNOSE        1005
+
+#define PDC_RDR                144             /* (sprockets)                  */
+#define PDC_RDR_READ_BUFFER    0
+#define PDC_RDR_READ_SINGLE    1
+#define PDC_RDR_WRITE_SINGLE   2
+
+#define PDC_INTRIGUE   145             /* (sprockets)                  */
+#define PDC_INTRIGUE_WRITE_BUFFER       0
+#define PDC_INTRIGUE_GET_SCRATCH_BUFSIZE 1
+#define PDC_INTRIGUE_START_CPU_COUNTERS         2
+#define PDC_INTRIGUE_STOP_CPU_COUNTERS  3
+
+#define PDC_STI                146             /* STI access                   */
+/* same as PDC_PCI_XXX values (see below) */
+
+/* Legacy PDC definitions for same stuff */
+#define PDC_PCI_INDEX  147
+#define PDC_PCI_INTERFACE_INFO         0
+#define PDC_PCI_SLOT_INFO              1
+#define PDC_PCI_INFLIGHT_BYTES         2
+#define PDC_PCI_READ_CONFIG            3
+#define PDC_PCI_WRITE_CONFIG           4
+#define PDC_PCI_READ_PCI_IO            5
+#define PDC_PCI_WRITE_PCI_IO           6
+#define PDC_PCI_READ_CONFIG_DELAY      7
+#define PDC_PCI_UPDATE_CONFIG_DELAY    8
+#define PDC_PCI_PCI_PATH_TO_PCI_HPA    9
+#define PDC_PCI_PCI_HPA_TO_PCI_PATH    10
+#define PDC_PCI_PCI_PATH_TO_PCI_BUS    11
+#define PDC_PCI_PCI_RESERVED           12
+#define PDC_PCI_PCI_INT_ROUTE_SIZE     13
+#define PDC_PCI_GET_INT_TBL_SIZE       PDC_PCI_PCI_INT_ROUTE_SIZE
+#define PDC_PCI_PCI_INT_ROUTE          14
+#define PDC_PCI_GET_INT_TBL            PDC_PCI_PCI_INT_ROUTE 
+#define PDC_PCI_READ_MON_TYPE          15
+#define PDC_PCI_WRITE_MON_TYPE         16
+
+
+/* Get SCSI Interface Card info:  SDTR, SCSI ID, mode (SE vs LVD) */
+#define PDC_INITIATOR  163
+#define PDC_GET_INITIATOR      0
+#define PDC_SET_INITIATOR      1
+#define PDC_DELETE_INITIATOR   2
+#define PDC_RETURN_TABLE_SIZE  3
+#define PDC_RETURN_TABLE       4
+
+#define PDC_LINK       165             /* (sprockets)                  */
+#define PDC_LINK_PCI_ENTRY_POINTS      0  /* list (Arg1) = 0 */
+#define PDC_LINK_USB_ENTRY_POINTS      1  /* list (Arg1) = 1 */
+
+/* cl_class
+ * page 3-33 of IO-Firmware ARS
+ * IODC ENTRY_INIT(Search first) RET[1]
+ */
+#define        CL_NULL         0       /* invalid */
+#define        CL_RANDOM       1       /* random access (as disk) */
+#define        CL_SEQU         2       /* sequential access (as tape) */
+#define        CL_DUPLEX       7       /* full-duplex point-to-point (RS-232, Net) */
+#define        CL_KEYBD        8       /* half-duplex console (HIL Keyboard) */
+#define        CL_DISPL        9       /* half-duplex console (display) */
+#define        CL_FC           10      /* FiberChannel access media */
+
+/* IODC ENTRY_INIT() */
+#define ENTRY_INIT_SRCH_FRST   2
+#define ENTRY_INIT_SRCH_NEXT   3
+#define ENTRY_INIT_MOD_DEV     4
+#define ENTRY_INIT_DEV         5
+#define ENTRY_INIT_MOD         6
+#define ENTRY_INIT_MSG         9
+
+/* IODC ENTRY_IO() */
+#define ENTRY_IO_BOOTIN                0
+#define ENTRY_IO_BOOTOUT       1
+#define ENTRY_IO_CIN           2
+#define ENTRY_IO_COUT          3
+#define ENTRY_IO_CLOSE         4
+#define ENTRY_IO_GETMSG                9
+#define ENTRY_IO_BBLOCK_IN     16
+#define ENTRY_IO_BBLOCK_OUT    17
+
+/* IODC ENTRY_SPA() */
+
+/* IODC ENTRY_CONFIG() */
+
+/* IODC ENTRY_TEST() */
+
+/* IODC ENTRY_TLB() */
+
+/* constants for OS (NVM...) */
+#define OS_ID_NONE             0       /* Undefined OS ID      */
+#define OS_ID_HPUX             1       /* HP-UX OS             */
+#define OS_ID_MPEXL            2       /* MPE XL OS            */
+#define OS_ID_OSF              3       /* OSF OS               */
+#define OS_ID_HPRT             4       /* HP-RT OS             */
+#define OS_ID_NOVEL            5       /* NOVELL OS            */
+#define OS_ID_LINUX            6       /* Linux                */
+
+
+/* constants for PDC_CHASSIS */
+#define OSTAT_OFF              0
+#define OSTAT_FLT              1 
+#define OSTAT_TEST             2
+#define OSTAT_INIT             3
+#define OSTAT_SHUT             4
+#define OSTAT_WARN             5
+#define OSTAT_RUN              6
+#define OSTAT_ON               7
+
+/* Page Zero constant offsets used by the HPMC handler */
+#define BOOT_CONSOLE_HPA_OFFSET  0x3c0
+#define BOOT_CONSOLE_SPA_OFFSET  0x3c4
+#define BOOT_CONSOLE_PATH_OFFSET 0x3a8
+
+/* size of the pdc_result buffer for firmware.c */
+#define NUM_PDC_RESULT 32
+
+#if !defined(__ASSEMBLY__)
+
+#include <linux/types.h>
+
+
+/* flags of the device_path */
+#define        PF_AUTOBOOT     0x80
+#define        PF_AUTOSEARCH   0x40
+#define        PF_TIMER        0x0F
+
+struct device_path {           /* page 1-69 */
+       unsigned char flags;    /* flags see above! */
+       unsigned char bc[6];    /* bus converter routing info */
+       unsigned char mod;
+       unsigned int  layers[6];/* device-specific layer-info */
+} __attribute__((aligned(8))) ;
+
+struct pz_device {
+       struct  device_path dp; /* see above */
+       /* struct       iomod *hpa; */
+       unsigned int hpa;       /* HPA base address */
+       /* char *spa; */
+       unsigned int spa;       /* SPA base address */
+       /* int  (*iodc_io)(struct iomod*, ...); */
+       unsigned int iodc_io;   /* device entry point */
+       short   pad;            /* reserved */
+       unsigned short cl_class;/* see below */
+} __attribute__((aligned(8))) ;
+
+struct zeropage {
+       /* [0x000] initialize vectors (VEC) */
+       unsigned int    vec_special;            /* must be zero */
+       /* int  (*vec_pow_fail)(void);*/
+       unsigned int    vec_pow_fail; /* power failure handler */
+       /* int  (*vec_toc)(void); */
+       unsigned int    vec_toc;
+       unsigned int    vec_toclen;
+       /* int  (*vec_rendz)(void); */
+       unsigned int vec_rendz;
+       int     vec_pow_fail_flen;
+       int     vec_pad[10];            
+       
+       /* [0x040] reserved processor dependent */
+       int     pad0[112];
+
+       /* [0x200] reserved */
+       int     pad1[84];
+
+       /* [0x350] memory configuration (MC) */
+       int     memc_cont;              /* contiguous mem size (bytes) */
+       int     memc_phsize;            /* physical memory size */
+       int     memc_adsize;            /* additional mem size, bytes of SPA space used by PDC */
+       unsigned int mem_pdc_hi;        /* used for 64-bit */
+
+       /* [0x360] various parameters for the boot-CPU */
+       /* unsigned int *mem_booterr[8]; */
+       unsigned int mem_booterr[8];    /* ptr to boot errors */
+       unsigned int mem_free;          /* first location, where OS can be loaded */
+       /* struct iomod *mem_hpa; */
+       unsigned int mem_hpa;           /* HPA of the boot-CPU */
+       /* int (*mem_pdc)(int, ...); */
+       unsigned int mem_pdc;           /* PDC entry point */
+       unsigned int mem_10msec;        /* number of clock ticks in 10msec */
+
+       /* [0x390] initial memory module (IMM) */
+       /* struct iomod *imm_hpa; */
+       unsigned int imm_hpa;           /* HPA of the IMM */
+       int     imm_soft_boot;          /* 0 = was hard boot, 1 = was soft boot */
+       unsigned int    imm_spa_size;           /* SPA size of the IMM in bytes */
+       unsigned int    imm_max_mem;            /* bytes of mem in IMM */
+
+       /* [0x3A0] boot console, display device and keyboard */
+       struct pz_device mem_cons;      /* description of console device */
+       struct pz_device mem_boot;      /* description of boot device */
+       struct pz_device mem_kbd;       /* description of keyboard device */
+
+       /* [0x430] reserved */
+       int     pad430[116];
+
+       /* [0x600] processor dependent */
+       __u32   pad600[1];
+       __u32   proc_sti;               /* pointer to STI ROM */
+       __u32   pad608[126];
+};
+
+#endif /* !defined(__ASSEMBLY__) */
+
+#endif /* _UAPI_PARISC_PDC_H */
diff --git a/arch/parisc/include/uapi/asm/ptrace.h b/arch/parisc/include/uapi/asm/ptrace.h
new file mode 100644 (file)
index 0000000..c4fa6c8
--- /dev/null
@@ -0,0 +1,47 @@
+/* written by Philipp Rumpf, Copyright (C) 1999 SuSE GmbH Nuernberg
+** Copyright (C) 2000 Grant Grundler, Hewlett-Packard
+*/
+#ifndef _UAPI_PARISC_PTRACE_H
+#define _UAPI_PARISC_PTRACE_H
+
+
+#include <linux/types.h>
+
+/* This struct defines the way the registers are stored on the 
+ * stack during a system call.
+ *
+ * N.B. gdb/strace care about the size and offsets within this
+ * structure. If you change things, you may break object compatibility
+ * for those applications.
+ */
+
+struct pt_regs {
+       unsigned long gr[32];   /* PSW is in gr[0] */
+       __u64 fr[32];
+       unsigned long sr[ 8];
+       unsigned long iasq[2];
+       unsigned long iaoq[2];
+       unsigned long cr27;
+       unsigned long pad0;     /* available for other uses */
+       unsigned long orig_r28;
+       unsigned long ksp;
+       unsigned long kpc;
+       unsigned long sar;      /* CR11 */
+       unsigned long iir;      /* CR19 */
+       unsigned long isr;      /* CR20 */
+       unsigned long ior;      /* CR21 */
+       unsigned long ipsw;     /* CR22 */
+};
+
+/*
+ * The numbers chosen here are somewhat arbitrary but absolutely MUST
+ * not overlap with any of the number assigned in <linux/ptrace.h>.
+ *
+ * These ones are taken from IA-64 on the assumption that theirs are
+ * the most correct (and we also want to support PTRACE_SINGLEBLOCK
+ * since we have taken branch traps too)
+ */
+#define PTRACE_SINGLEBLOCK     12      /* resume execution until next branch */
+
+
+#endif /* _UAPI_PARISC_PTRACE_H */
diff --git a/arch/parisc/include/uapi/asm/signal.h b/arch/parisc/include/uapi/asm/signal.h
new file mode 100644 (file)
index 0000000..b1ddaa2
--- /dev/null
@@ -0,0 +1,118 @@
+#ifndef _UAPI_ASM_PARISC_SIGNAL_H
+#define _UAPI_ASM_PARISC_SIGNAL_H
+
+#define SIGHUP          1
+#define SIGINT          2
+#define SIGQUIT                 3
+#define SIGILL          4
+#define SIGTRAP                 5
+#define SIGABRT                 6
+#define SIGIOT          6
+#define SIGEMT          7
+#define SIGFPE          8
+#define SIGKILL                 9
+#define SIGBUS         10
+#define SIGSEGV                11
+#define SIGSYS         12 /* Linux doesn't use this */
+#define SIGPIPE                13
+#define SIGALRM                14
+#define SIGTERM                15
+#define SIGUSR1                16
+#define SIGUSR2                17
+#define SIGCHLD                18
+#define SIGPWR         19
+#define SIGVTALRM      20
+#define SIGPROF                21
+#define SIGIO          22
+#define SIGPOLL                SIGIO
+#define SIGWINCH       23
+#define SIGSTOP                24
+#define SIGTSTP                25
+#define SIGCONT                26
+#define SIGTTIN                27
+#define SIGTTOU                28
+#define SIGURG         29
+#define SIGLOST                30 /* Linux doesn't use this either */
+#define        SIGUNUSED       31
+#define SIGRESERVE     SIGUNUSED
+
+#define SIGXCPU                33
+#define SIGXFSZ                34
+#define SIGSTKFLT      36
+
+/* These should not be considered constants from userland.  */
+#define SIGRTMIN       37
+#define SIGRTMAX       _NSIG /* it's 44 under HP/UX */
+
+/*
+ * SA_FLAGS values:
+ *
+ * SA_ONSTACK indicates that a registered stack_t will be used.
+ * SA_RESTART flag to get restarting signals (which were the default long ago)
+ * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
+ * SA_RESETHAND clears the handler when the signal is delivered.
+ * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
+ * SA_NODEFER prevents the current signal from being masked in the handler.
+ *
+ * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
+ * Unix names RESETHAND and NODEFER respectively.
+ */
+#define SA_ONSTACK     0x00000001
+#define SA_RESETHAND   0x00000004
+#define SA_NOCLDSTOP   0x00000008
+#define SA_SIGINFO     0x00000010
+#define SA_NODEFER     0x00000020
+#define SA_RESTART     0x00000040
+#define SA_NOCLDWAIT   0x00000080
+#define _SA_SIGGFAULT  0x00000100 /* HPUX */
+
+#define SA_NOMASK      SA_NODEFER
+#define SA_ONESHOT     SA_RESETHAND
+
+#define SA_RESTORER    0x04000000 /* obsolete -- ignored */
+
+/* 
+ * sigaltstack controls
+ */
+#define SS_ONSTACK     1
+#define SS_DISABLE     2
+
+#define MINSIGSTKSZ    2048
+#define SIGSTKSZ       8192
+
+
+#define SIG_BLOCK          0   /* for blocking signals */
+#define SIG_UNBLOCK        1   /* for unblocking signals */
+#define SIG_SETMASK        2   /* for setting the signal mask */
+
+#define SIG_DFL        ((__sighandler_t)0)     /* default signal handling */
+#define SIG_IGN        ((__sighandler_t)1)     /* ignore signal */
+#define SIG_ERR        ((__sighandler_t)-1)    /* error return from signal */
+
+# ifndef __ASSEMBLY__
+
+#  include <linux/types.h>
+
+/* Avoid too many header ordering problems.  */
+struct siginfo;
+
+/* Type of a signal handler.  */
+#ifdef CONFIG_64BIT
+/* function pointers on 64-bit parisc are pointers to little structs and the
+ * compiler doesn't support code which changes or tests the address of
+ * the function in the little struct.  This is really ugly -PB
+ */
+typedef char __user *__sighandler_t;
+#else
+typedef void __signalfn_t(int);
+typedef __signalfn_t __user *__sighandler_t;
+#endif
+
+typedef struct sigaltstack {
+       void __user *ss_sp;
+       int ss_flags;
+       size_t ss_size;
+} stack_t;
+
+#endif /* !__ASSEMBLY */
+#endif /* _UAPI_ASM_PARISC_SIGNAL_H */
diff --git a/arch/parisc/include/uapi/asm/termios.h b/arch/parisc/include/uapi/asm/termios.h
new file mode 100644 (file)
index 0000000..f337739
--- /dev/null
@@ -0,0 +1,43 @@
+#ifndef _UAPI_PARISC_TERMIOS_H
+#define _UAPI_PARISC_TERMIOS_H
+
+#include <asm/termbits.h>
+#include <asm/ioctls.h>
+
+struct winsize {
+       unsigned short ws_row;
+       unsigned short ws_col;
+       unsigned short ws_xpixel;
+       unsigned short ws_ypixel;
+};
+
+#define NCC 8
+struct termio {
+       unsigned short c_iflag;         /* input mode flags */
+       unsigned short c_oflag;         /* output mode flags */
+       unsigned short c_cflag;         /* control mode flags */
+       unsigned short c_lflag;         /* local mode flags */
+       unsigned char c_line;           /* line discipline */
+       unsigned char c_cc[NCC];        /* control characters */
+};
+
+/* modem lines */
+#define TIOCM_LE       0x001
+#define TIOCM_DTR      0x002
+#define TIOCM_RTS      0x004
+#define TIOCM_ST       0x008
+#define TIOCM_SR       0x010
+#define TIOCM_CTS      0x020
+#define TIOCM_CAR      0x040
+#define TIOCM_RNG      0x080
+#define TIOCM_DSR      0x100
+#define TIOCM_CD       TIOCM_CAR
+#define TIOCM_RI       TIOCM_RNG
+#define TIOCM_OUT1     0x2000
+#define TIOCM_OUT2     0x4000
+#define TIOCM_LOOP     0x8000
+
+/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
+
+
+#endif /* _UAPI_PARISC_TERMIOS_H */
diff --git a/arch/parisc/include/uapi/asm/unistd.h b/arch/parisc/include/uapi/asm/unistd.h
new file mode 100644 (file)
index 0000000..e178f30
--- /dev/null
@@ -0,0 +1,837 @@
+#ifndef _UAPI_ASM_PARISC_UNISTD_H_
+#define _UAPI_ASM_PARISC_UNISTD_H_
+
+/*
+ * This file contains the system call numbers.
+ */
+
+/*
+ *   HP-UX system calls get their native numbers for binary compatibility.
+ */
+
+#define __NR_HPUX_exit                    1
+#define __NR_HPUX_fork                    2
+#define __NR_HPUX_read                    3
+#define __NR_HPUX_write                   4
+#define __NR_HPUX_open                    5
+#define __NR_HPUX_close                   6
+#define __NR_HPUX_wait                    7
+#define __NR_HPUX_creat                   8
+#define __NR_HPUX_link                    9
+#define __NR_HPUX_unlink                 10
+#define __NR_HPUX_execv                  11
+#define __NR_HPUX_chdir                  12
+#define __NR_HPUX_time                   13
+#define __NR_HPUX_mknod                  14
+#define __NR_HPUX_chmod                  15
+#define __NR_HPUX_chown                  16
+#define __NR_HPUX_break                  17
+#define __NR_HPUX_lchmod                 18
+#define __NR_HPUX_lseek                  19
+#define __NR_HPUX_getpid                 20
+#define __NR_HPUX_mount                  21
+#define __NR_HPUX_umount                 22
+#define __NR_HPUX_setuid                 23
+#define __NR_HPUX_getuid                 24
+#define __NR_HPUX_stime                  25
+#define __NR_HPUX_ptrace                 26
+#define __NR_HPUX_alarm                  27
+#define __NR_HPUX_oldfstat               28
+#define __NR_HPUX_pause                  29
+#define __NR_HPUX_utime                  30
+#define __NR_HPUX_stty                   31
+#define __NR_HPUX_gtty                   32
+#define __NR_HPUX_access                 33
+#define __NR_HPUX_nice                   34
+#define __NR_HPUX_ftime                  35
+#define __NR_HPUX_sync                   36
+#define __NR_HPUX_kill                   37
+#define __NR_HPUX_stat                   38
+#define __NR_HPUX_setpgrp3               39
+#define __NR_HPUX_lstat                  40
+#define __NR_HPUX_dup                    41
+#define __NR_HPUX_pipe                   42
+#define __NR_HPUX_times                  43
+#define __NR_HPUX_profil                 44
+#define __NR_HPUX_ki_call                45
+#define __NR_HPUX_setgid                 46
+#define __NR_HPUX_getgid                 47
+#define __NR_HPUX_sigsys                 48
+#define __NR_HPUX_reserved1              49
+#define __NR_HPUX_reserved2              50
+#define __NR_HPUX_acct                   51
+#define __NR_HPUX_set_userthreadid       52
+#define __NR_HPUX_oldlock                53
+#define __NR_HPUX_ioctl                  54
+#define __NR_HPUX_reboot                 55
+#define __NR_HPUX_symlink                56
+#define __NR_HPUX_utssys                 57
+#define __NR_HPUX_readlink               58
+#define __NR_HPUX_execve                 59
+#define __NR_HPUX_umask                  60
+#define __NR_HPUX_chroot                 61
+#define __NR_HPUX_fcntl                  62
+#define __NR_HPUX_ulimit                 63
+#define __NR_HPUX_getpagesize            64
+#define __NR_HPUX_mremap                 65
+#define __NR_HPUX_vfork                  66
+#define __NR_HPUX_vread                  67
+#define __NR_HPUX_vwrite                 68
+#define __NR_HPUX_sbrk                   69
+#define __NR_HPUX_sstk                   70
+#define __NR_HPUX_mmap                   71
+#define __NR_HPUX_vadvise                72
+#define __NR_HPUX_munmap                 73
+#define __NR_HPUX_mprotect               74
+#define __NR_HPUX_madvise                75
+#define __NR_HPUX_vhangup                76
+#define __NR_HPUX_swapoff                77
+#define __NR_HPUX_mincore                78
+#define __NR_HPUX_getgroups              79
+#define __NR_HPUX_setgroups              80
+#define __NR_HPUX_getpgrp2               81
+#define __NR_HPUX_setpgrp2               82
+#define __NR_HPUX_setitimer              83
+#define __NR_HPUX_wait3                  84
+#define __NR_HPUX_swapon                 85
+#define __NR_HPUX_getitimer              86
+#define __NR_HPUX_gethostname42          87
+#define __NR_HPUX_sethostname42          88
+#define __NR_HPUX_getdtablesize          89
+#define __NR_HPUX_dup2                   90
+#define __NR_HPUX_getdopt                91
+#define __NR_HPUX_fstat                  92
+#define __NR_HPUX_select                 93
+#define __NR_HPUX_setdopt                94
+#define __NR_HPUX_fsync                  95
+#define __NR_HPUX_setpriority            96
+#define __NR_HPUX_socket_old             97
+#define __NR_HPUX_connect_old            98
+#define __NR_HPUX_accept_old             99
+#define __NR_HPUX_getpriority           100
+#define __NR_HPUX_send_old              101
+#define __NR_HPUX_recv_old              102
+#define __NR_HPUX_socketaddr_old        103
+#define __NR_HPUX_bind_old              104
+#define __NR_HPUX_setsockopt_old        105
+#define __NR_HPUX_listen_old            106
+#define __NR_HPUX_vtimes_old            107
+#define __NR_HPUX_sigvector             108
+#define __NR_HPUX_sigblock              109
+#define __NR_HPUX_siggetmask            110
+#define __NR_HPUX_sigpause              111
+#define __NR_HPUX_sigstack              112
+#define __NR_HPUX_recvmsg_old           113
+#define __NR_HPUX_sendmsg_old           114
+#define __NR_HPUX_vtrace_old            115
+#define __NR_HPUX_gettimeofday          116
+#define __NR_HPUX_getrusage             117
+#define __NR_HPUX_getsockopt_old        118
+#define __NR_HPUX_resuba_old            119
+#define __NR_HPUX_readv                 120
+#define __NR_HPUX_writev                121
+#define __NR_HPUX_settimeofday          122
+#define __NR_HPUX_fchown                123
+#define __NR_HPUX_fchmod                124
+#define __NR_HPUX_recvfrom_old          125
+#define __NR_HPUX_setresuid             126
+#define __NR_HPUX_setresgid             127
+#define __NR_HPUX_rename                128
+#define __NR_HPUX_truncate              129
+#define __NR_HPUX_ftruncate             130
+#define __NR_HPUX_flock_old             131
+#define __NR_HPUX_sysconf               132
+#define __NR_HPUX_sendto_old            133
+#define __NR_HPUX_shutdown_old          134
+#define __NR_HPUX_socketpair_old        135
+#define __NR_HPUX_mkdir                 136
+#define __NR_HPUX_rmdir                 137
+#define __NR_HPUX_utimes_old            138
+#define __NR_HPUX_sigcleanup_old        139
+#define __NR_HPUX_setcore               140
+#define __NR_HPUX_getpeername_old       141
+#define __NR_HPUX_gethostid             142
+#define __NR_HPUX_sethostid             143
+#define __NR_HPUX_getrlimit             144
+#define __NR_HPUX_setrlimit             145
+#define __NR_HPUX_killpg_old            146
+#define __NR_HPUX_cachectl              147
+#define __NR_HPUX_quotactl              148
+#define __NR_HPUX_get_sysinfo           149
+#define __NR_HPUX_getsockname_old       150
+#define __NR_HPUX_privgrp               151
+#define __NR_HPUX_rtprio                152
+#define __NR_HPUX_plock                 153
+#define __NR_HPUX_reserved3             154
+#define __NR_HPUX_lockf                 155
+#define __NR_HPUX_semget                156
+#define __NR_HPUX_osemctl               157
+#define __NR_HPUX_semop                 158
+#define __NR_HPUX_msgget                159
+#define __NR_HPUX_omsgctl               160
+#define __NR_HPUX_msgsnd                161
+#define __NR_HPUX_msgrecv               162
+#define __NR_HPUX_shmget                163
+#define __NR_HPUX_oshmctl               164
+#define __NR_HPUX_shmat                 165
+#define __NR_HPUX_shmdt                 166
+#define __NR_HPUX_m68020_advise         167
+/* [168,189] are for Discless/DUX */
+#define __NR_HPUX_csp                   168
+#define __NR_HPUX_cluster               169
+#define __NR_HPUX_mkrnod                170
+#define __NR_HPUX_test                  171
+#define __NR_HPUX_unsp_open             172
+#define __NR_HPUX_reserved4             173
+#define __NR_HPUX_getcontext_old        174
+#define __NR_HPUX_osetcontext           175
+#define __NR_HPUX_bigio                 176
+#define __NR_HPUX_pipenode              177
+#define __NR_HPUX_lsync                 178
+#define __NR_HPUX_getmachineid          179
+#define __NR_HPUX_cnodeid               180
+#define __NR_HPUX_cnodes                181
+#define __NR_HPUX_swapclients           182
+#define __NR_HPUX_rmt_process           183
+#define __NR_HPUX_dskless_stats         184
+#define __NR_HPUX_sigprocmask           185
+#define __NR_HPUX_sigpending            186
+#define __NR_HPUX_sigsuspend            187
+#define __NR_HPUX_sigaction             188
+#define __NR_HPUX_reserved5             189
+#define __NR_HPUX_nfssvc                190
+#define __NR_HPUX_getfh                 191
+#define __NR_HPUX_getdomainname         192
+#define __NR_HPUX_setdomainname         193
+#define __NR_HPUX_async_daemon          194
+#define __NR_HPUX_getdirentries         195
+#define __NR_HPUX_statfs                196
+#define __NR_HPUX_fstatfs               197
+#define __NR_HPUX_vfsmount              198
+#define __NR_HPUX_reserved6             199
+#define __NR_HPUX_waitpid               200
+/* 201 - 223 missing */
+#define __NR_HPUX_sigsetreturn          224
+#define __NR_HPUX_sigsetstatemask       225
+/* 226 missing */
+#define __NR_HPUX_cs                    227
+#define __NR_HPUX_cds                   228
+#define __NR_HPUX_set_no_trunc          229
+#define __NR_HPUX_pathconf              230
+#define __NR_HPUX_fpathconf             231
+/* 232, 233 missing */
+#define __NR_HPUX_nfs_fcntl             234
+#define __NR_HPUX_ogetacl               235
+#define __NR_HPUX_ofgetacl              236
+#define __NR_HPUX_osetacl               237
+#define __NR_HPUX_ofsetacl              238
+#define __NR_HPUX_pstat                 239
+#define __NR_HPUX_getaudid              240
+#define __NR_HPUX_setaudid              241
+#define __NR_HPUX_getaudproc            242
+#define __NR_HPUX_setaudproc            243
+#define __NR_HPUX_getevent              244
+#define __NR_HPUX_setevent              245
+#define __NR_HPUX_audwrite              246
+#define __NR_HPUX_audswitch             247
+#define __NR_HPUX_audctl                248
+#define __NR_HPUX_ogetaccess            249
+#define __NR_HPUX_fsctl                 250
+/* 251 - 258 missing */
+#define __NR_HPUX_swapfs                259
+#define __NR_HPUX_fss                   260
+/* 261 - 266 missing */
+#define __NR_HPUX_tsync                 267
+#define __NR_HPUX_getnumfds             268
+#define __NR_HPUX_poll                  269
+#define __NR_HPUX_getmsg                270
+#define __NR_HPUX_putmsg                271
+#define __NR_HPUX_fchdir                272
+#define __NR_HPUX_getmount_cnt          273
+#define __NR_HPUX_getmount_entry        274
+#define __NR_HPUX_accept                275
+#define __NR_HPUX_bind                  276
+#define __NR_HPUX_connect               277
+#define __NR_HPUX_getpeername           278
+#define __NR_HPUX_getsockname           279
+#define __NR_HPUX_getsockopt            280
+#define __NR_HPUX_listen                281
+#define __NR_HPUX_recv                  282
+#define __NR_HPUX_recvfrom              283
+#define __NR_HPUX_recvmsg               284
+#define __NR_HPUX_send                  285
+#define __NR_HPUX_sendmsg               286
+#define __NR_HPUX_sendto                287
+#define __NR_HPUX_setsockopt            288
+#define __NR_HPUX_shutdown              289
+#define __NR_HPUX_socket                290
+#define __NR_HPUX_socketpair            291
+#define __NR_HPUX_proc_open             292
+#define __NR_HPUX_proc_close            293
+#define __NR_HPUX_proc_send             294
+#define __NR_HPUX_proc_recv             295
+#define __NR_HPUX_proc_sendrecv         296
+#define __NR_HPUX_proc_syscall          297
+/* 298 - 311 missing */
+#define __NR_HPUX_semctl                312
+#define __NR_HPUX_msgctl                313
+#define __NR_HPUX_shmctl                314
+#define __NR_HPUX_mpctl                 315
+#define __NR_HPUX_exportfs              316
+#define __NR_HPUX_getpmsg               317
+#define __NR_HPUX_putpmsg               318
+/* 319 missing */
+#define __NR_HPUX_msync                 320
+#define __NR_HPUX_msleep                321
+#define __NR_HPUX_mwakeup               322
+#define __NR_HPUX_msem_init             323
+#define __NR_HPUX_msem_remove           324
+#define __NR_HPUX_adjtime               325
+#define __NR_HPUX_kload                 326
+#define __NR_HPUX_fattach               327
+#define __NR_HPUX_fdetach               328
+#define __NR_HPUX_serialize             329
+#define __NR_HPUX_statvfs               330
+#define __NR_HPUX_fstatvfs              331
+#define __NR_HPUX_lchown                332
+#define __NR_HPUX_getsid                333
+#define __NR_HPUX_sysfs                 334
+/* 335, 336 missing */
+#define __NR_HPUX_sched_setparam        337
+#define __NR_HPUX_sched_getparam        338
+#define __NR_HPUX_sched_setscheduler    339
+#define __NR_HPUX_sched_getscheduler    340
+#define __NR_HPUX_sched_yield           341
+#define __NR_HPUX_sched_get_priority_max 342
+#define __NR_HPUX_sched_get_priority_min 343
+#define __NR_HPUX_sched_rr_get_interval 344
+#define __NR_HPUX_clock_settime         345
+#define __NR_HPUX_clock_gettime         346
+#define __NR_HPUX_clock_getres          347
+#define __NR_HPUX_timer_create          348
+#define __NR_HPUX_timer_delete          349
+#define __NR_HPUX_timer_settime         350
+#define __NR_HPUX_timer_gettime         351
+#define __NR_HPUX_timer_getoverrun      352
+#define __NR_HPUX_nanosleep             353
+#define __NR_HPUX_toolbox               354
+/* 355 missing */
+#define __NR_HPUX_getdents              356
+#define __NR_HPUX_getcontext            357
+#define __NR_HPUX_sysinfo               358
+#define __NR_HPUX_fcntl64               359
+#define __NR_HPUX_ftruncate64           360
+#define __NR_HPUX_fstat64               361
+#define __NR_HPUX_getdirentries64       362
+#define __NR_HPUX_getrlimit64           363
+#define __NR_HPUX_lockf64               364
+#define __NR_HPUX_lseek64               365
+#define __NR_HPUX_lstat64               366
+#define __NR_HPUX_mmap64                367
+#define __NR_HPUX_setrlimit64           368
+#define __NR_HPUX_stat64                369
+#define __NR_HPUX_truncate64            370
+#define __NR_HPUX_ulimit64              371
+#define __NR_HPUX_pread                 372
+#define __NR_HPUX_preadv                373
+#define __NR_HPUX_pwrite                374
+#define __NR_HPUX_pwritev               375
+#define __NR_HPUX_pread64               376
+#define __NR_HPUX_preadv64              377
+#define __NR_HPUX_pwrite64              378
+#define __NR_HPUX_pwritev64             379
+#define __NR_HPUX_setcontext            380
+#define __NR_HPUX_sigaltstack           381
+#define __NR_HPUX_waitid                382
+#define __NR_HPUX_setpgrp               383
+#define __NR_HPUX_recvmsg2              384
+#define __NR_HPUX_sendmsg2              385
+#define __NR_HPUX_socket2               386
+#define __NR_HPUX_socketpair2           387
+#define __NR_HPUX_setregid              388
+#define __NR_HPUX_lwp_create            389
+#define __NR_HPUX_lwp_terminate         390
+#define __NR_HPUX_lwp_wait              391
+#define __NR_HPUX_lwp_suspend           392
+#define __NR_HPUX_lwp_resume            393
+/* 394 missing */
+#define __NR_HPUX_lwp_abort_syscall     395
+#define __NR_HPUX_lwp_info              396
+#define __NR_HPUX_lwp_kill              397
+#define __NR_HPUX_ksleep                398
+#define __NR_HPUX_kwakeup               399
+/* 400 missing */
+#define __NR_HPUX_pstat_getlwp          401
+#define __NR_HPUX_lwp_exit              402
+#define __NR_HPUX_lwp_continue          403
+#define __NR_HPUX_getacl                404
+#define __NR_HPUX_fgetacl               405
+#define __NR_HPUX_setacl                406
+#define __NR_HPUX_fsetacl               407
+#define __NR_HPUX_getaccess             408
+#define __NR_HPUX_lwp_mutex_init        409
+#define __NR_HPUX_lwp_mutex_lock_sys    410
+#define __NR_HPUX_lwp_mutex_unlock      411
+#define __NR_HPUX_lwp_cond_init         412
+#define __NR_HPUX_lwp_cond_signal       413
+#define __NR_HPUX_lwp_cond_broadcast    414
+#define __NR_HPUX_lwp_cond_wait_sys     415
+#define __NR_HPUX_lwp_getscheduler      416
+#define __NR_HPUX_lwp_setscheduler      417
+#define __NR_HPUX_lwp_getstate          418
+#define __NR_HPUX_lwp_setstate          419
+#define __NR_HPUX_lwp_detach            420
+#define __NR_HPUX_mlock                 421
+#define __NR_HPUX_munlock               422
+#define __NR_HPUX_mlockall              423
+#define __NR_HPUX_munlockall            424
+#define __NR_HPUX_shm_open              425
+#define __NR_HPUX_shm_unlink            426
+#define __NR_HPUX_sigqueue              427
+#define __NR_HPUX_sigwaitinfo           428
+#define __NR_HPUX_sigtimedwait          429
+#define __NR_HPUX_sigwait               430
+#define __NR_HPUX_aio_read              431
+#define __NR_HPUX_aio_write             432
+#define __NR_HPUX_lio_listio            433
+#define __NR_HPUX_aio_error             434
+#define __NR_HPUX_aio_return            435
+#define __NR_HPUX_aio_cancel            436
+#define __NR_HPUX_aio_suspend           437
+#define __NR_HPUX_aio_fsync             438
+#define __NR_HPUX_mq_open               439
+#define __NR_HPUX_mq_close              440
+#define __NR_HPUX_mq_unlink             441
+#define __NR_HPUX_mq_send               442
+#define __NR_HPUX_mq_receive            443
+#define __NR_HPUX_mq_notify             444
+#define __NR_HPUX_mq_setattr            445
+#define __NR_HPUX_mq_getattr            446
+#define __NR_HPUX_ksem_open             447
+#define __NR_HPUX_ksem_unlink           448
+#define __NR_HPUX_ksem_close            449
+#define __NR_HPUX_ksem_post             450
+#define __NR_HPUX_ksem_wait             451
+#define __NR_HPUX_ksem_read             452
+#define __NR_HPUX_ksem_trywait          453
+#define __NR_HPUX_lwp_rwlock_init       454
+#define __NR_HPUX_lwp_rwlock_destroy    455
+#define __NR_HPUX_lwp_rwlock_rdlock_sys 456
+#define __NR_HPUX_lwp_rwlock_wrlock_sys 457
+#define __NR_HPUX_lwp_rwlock_tryrdlock  458
+#define __NR_HPUX_lwp_rwlock_trywrlock  459
+#define __NR_HPUX_lwp_rwlock_unlock     460
+#define __NR_HPUX_ttrace                461
+#define __NR_HPUX_ttrace_wait           462
+#define __NR_HPUX_lf_wire_mem           463
+#define __NR_HPUX_lf_unwire_mem         464
+#define __NR_HPUX_lf_send_pin_map       465
+#define __NR_HPUX_lf_free_buf           466
+#define __NR_HPUX_lf_wait_nq            467
+#define __NR_HPUX_lf_wakeup_conn_q      468
+#define __NR_HPUX_lf_unused             469
+#define __NR_HPUX_lwp_sema_init         470
+#define __NR_HPUX_lwp_sema_post         471
+#define __NR_HPUX_lwp_sema_wait         472
+#define __NR_HPUX_lwp_sema_trywait      473
+#define __NR_HPUX_lwp_sema_destroy      474
+#define __NR_HPUX_statvfs64             475
+#define __NR_HPUX_fstatvfs64            476
+#define __NR_HPUX_msh_register          477
+#define __NR_HPUX_ptrace64              478
+#define __NR_HPUX_sendfile              479
+#define __NR_HPUX_sendpath              480
+#define __NR_HPUX_sendfile64            481
+#define __NR_HPUX_sendpath64            482
+#define __NR_HPUX_modload               483
+#define __NR_HPUX_moduload              484
+#define __NR_HPUX_modpath               485
+#define __NR_HPUX_getksym               486
+#define __NR_HPUX_modadm                487
+#define __NR_HPUX_modstat               488
+#define __NR_HPUX_lwp_detached_exit     489
+#define __NR_HPUX_crashconf             490
+#define __NR_HPUX_siginhibit            491
+#define __NR_HPUX_sigenable             492
+#define __NR_HPUX_spuctl                493
+#define __NR_HPUX_zerokernelsum         494
+#define __NR_HPUX_nfs_kstat             495
+#define __NR_HPUX_aio_read64            496
+#define __NR_HPUX_aio_write64           497
+#define __NR_HPUX_aio_error64           498
+#define __NR_HPUX_aio_return64          499
+#define __NR_HPUX_aio_cancel64          500
+#define __NR_HPUX_aio_suspend64         501
+#define __NR_HPUX_aio_fsync64           502
+#define __NR_HPUX_lio_listio64          503
+#define __NR_HPUX_recv2                 504
+#define __NR_HPUX_recvfrom2             505
+#define __NR_HPUX_send2                 506
+#define __NR_HPUX_sendto2               507
+#define __NR_HPUX_acl                   508
+#define __NR_HPUX___cnx_p2p_ctl         509
+#define __NR_HPUX___cnx_gsched_ctl      510
+#define __NR_HPUX___cnx_pmon_ctl        511
+
+#define __NR_HPUX_syscalls             512
+
+/*
+ * Linux system call numbers.
+ *
+ * Cary Coutant says that we should just use another syscall gateway
+ * page to avoid clashing with the HPUX space, and I think he's right:
+ * it will would keep a branch out of our syscall entry path, at the
+ * very least.  If we decide to change it later, we can ``just'' tweak
+ * the LINUX_GATEWAY_ADDR define at the bottom and make __NR_Linux be
+ * 1024 or something.  Oh, and recompile libc. =)
+ *
+ * 64-bit HPUX binaries get the syscall gateway address passed in a register
+ * from the kernel at startup, which seems a sane strategy.
+ */
+
+#define __NR_Linux                0
+#define __NR_restart_syscall      (__NR_Linux + 0)
+#define __NR_exit                 (__NR_Linux + 1)
+#define __NR_fork                 (__NR_Linux + 2)
+#define __NR_read                 (__NR_Linux + 3)
+#define __NR_write                (__NR_Linux + 4)
+#define __NR_open                 (__NR_Linux + 5)
+#define __NR_close                (__NR_Linux + 6)
+#define __NR_waitpid              (__NR_Linux + 7)
+#define __NR_creat                (__NR_Linux + 8)
+#define __NR_link                 (__NR_Linux + 9)
+#define __NR_unlink              (__NR_Linux + 10)
+#define __NR_execve              (__NR_Linux + 11)
+#define __NR_chdir               (__NR_Linux + 12)
+#define __NR_time                (__NR_Linux + 13)
+#define __NR_mknod               (__NR_Linux + 14)
+#define __NR_chmod               (__NR_Linux + 15)
+#define __NR_lchown              (__NR_Linux + 16)
+#define __NR_socket              (__NR_Linux + 17)
+#define __NR_stat                (__NR_Linux + 18)
+#define __NR_lseek               (__NR_Linux + 19)
+#define __NR_getpid              (__NR_Linux + 20)
+#define __NR_mount               (__NR_Linux + 21)
+#define __NR_bind                (__NR_Linux + 22)
+#define __NR_setuid              (__NR_Linux + 23)
+#define __NR_getuid              (__NR_Linux + 24)
+#define __NR_stime               (__NR_Linux + 25)
+#define __NR_ptrace              (__NR_Linux + 26)
+#define __NR_alarm               (__NR_Linux + 27)
+#define __NR_fstat               (__NR_Linux + 28)
+#define __NR_pause               (__NR_Linux + 29)
+#define __NR_utime               (__NR_Linux + 30)
+#define __NR_connect             (__NR_Linux + 31)
+#define __NR_listen              (__NR_Linux + 32)
+#define __NR_access              (__NR_Linux + 33)
+#define __NR_nice                (__NR_Linux + 34)
+#define __NR_accept              (__NR_Linux + 35)
+#define __NR_sync                (__NR_Linux + 36)
+#define __NR_kill                (__NR_Linux + 37)
+#define __NR_rename              (__NR_Linux + 38)
+#define __NR_mkdir               (__NR_Linux + 39)
+#define __NR_rmdir               (__NR_Linux + 40)
+#define __NR_dup                 (__NR_Linux + 41)
+#define __NR_pipe                (__NR_Linux + 42)
+#define __NR_times               (__NR_Linux + 43)
+#define __NR_getsockname         (__NR_Linux + 44)
+#define __NR_brk                 (__NR_Linux + 45)
+#define __NR_setgid              (__NR_Linux + 46)
+#define __NR_getgid              (__NR_Linux + 47)
+#define __NR_signal              (__NR_Linux + 48)
+#define __NR_geteuid             (__NR_Linux + 49)
+#define __NR_getegid             (__NR_Linux + 50)
+#define __NR_acct                (__NR_Linux + 51)
+#define __NR_umount2             (__NR_Linux + 52)
+#define __NR_getpeername         (__NR_Linux + 53)
+#define __NR_ioctl               (__NR_Linux + 54)
+#define __NR_fcntl               (__NR_Linux + 55)
+#define __NR_socketpair          (__NR_Linux + 56)
+#define __NR_setpgid             (__NR_Linux + 57)
+#define __NR_send                (__NR_Linux + 58)
+#define __NR_uname               (__NR_Linux + 59)
+#define __NR_umask               (__NR_Linux + 60)
+#define __NR_chroot              (__NR_Linux + 61)
+#define __NR_ustat               (__NR_Linux + 62)
+#define __NR_dup2                (__NR_Linux + 63)
+#define __NR_getppid             (__NR_Linux + 64)
+#define __NR_getpgrp             (__NR_Linux + 65)
+#define __NR_setsid              (__NR_Linux + 66)
+#define __NR_pivot_root          (__NR_Linux + 67)
+#define __NR_sgetmask            (__NR_Linux + 68)
+#define __NR_ssetmask            (__NR_Linux + 69)
+#define __NR_setreuid            (__NR_Linux + 70)
+#define __NR_setregid            (__NR_Linux + 71)
+#define __NR_mincore             (__NR_Linux + 72)
+#define __NR_sigpending          (__NR_Linux + 73)
+#define __NR_sethostname         (__NR_Linux + 74)
+#define __NR_setrlimit           (__NR_Linux + 75)
+#define __NR_getrlimit           (__NR_Linux + 76)
+#define __NR_getrusage           (__NR_Linux + 77)
+#define __NR_gettimeofday        (__NR_Linux + 78)
+#define __NR_settimeofday        (__NR_Linux + 79)
+#define __NR_getgroups           (__NR_Linux + 80)
+#define __NR_setgroups           (__NR_Linux + 81)
+#define __NR_sendto              (__NR_Linux + 82)
+#define __NR_symlink             (__NR_Linux + 83)
+#define __NR_lstat               (__NR_Linux + 84)
+#define __NR_readlink            (__NR_Linux + 85)
+#define __NR_uselib              (__NR_Linux + 86)
+#define __NR_swapon              (__NR_Linux + 87)
+#define __NR_reboot              (__NR_Linux + 88)
+#define __NR_mmap2             (__NR_Linux + 89)
+#define __NR_mmap                (__NR_Linux + 90)
+#define __NR_munmap              (__NR_Linux + 91)
+#define __NR_truncate            (__NR_Linux + 92)
+#define __NR_ftruncate           (__NR_Linux + 93)
+#define __NR_fchmod              (__NR_Linux + 94)
+#define __NR_fchown              (__NR_Linux + 95)
+#define __NR_getpriority         (__NR_Linux + 96)
+#define __NR_setpriority         (__NR_Linux + 97)
+#define __NR_recv                (__NR_Linux + 98)
+#define __NR_statfs              (__NR_Linux + 99)
+#define __NR_fstatfs            (__NR_Linux + 100)
+#define __NR_stat64           (__NR_Linux + 101)
+/* #define __NR_socketcall         (__NR_Linux + 102) */
+#define __NR_syslog             (__NR_Linux + 103)
+#define __NR_setitimer          (__NR_Linux + 104)
+#define __NR_getitimer          (__NR_Linux + 105)
+#define __NR_capget             (__NR_Linux + 106)
+#define __NR_capset             (__NR_Linux + 107)
+#define __NR_pread64            (__NR_Linux + 108)
+#define __NR_pwrite64           (__NR_Linux + 109)
+#define __NR_getcwd             (__NR_Linux + 110)
+#define __NR_vhangup            (__NR_Linux + 111)
+#define __NR_fstat64            (__NR_Linux + 112)
+#define __NR_vfork              (__NR_Linux + 113)
+#define __NR_wait4              (__NR_Linux + 114)
+#define __NR_swapoff            (__NR_Linux + 115)
+#define __NR_sysinfo            (__NR_Linux + 116)
+#define __NR_shutdown           (__NR_Linux + 117)
+#define __NR_fsync              (__NR_Linux + 118)
+#define __NR_madvise            (__NR_Linux + 119)
+#define __NR_clone              (__NR_Linux + 120)
+#define __NR_setdomainname      (__NR_Linux + 121)
+#define __NR_sendfile           (__NR_Linux + 122)
+#define __NR_recvfrom           (__NR_Linux + 123)
+#define __NR_adjtimex           (__NR_Linux + 124)
+#define __NR_mprotect           (__NR_Linux + 125)
+#define __NR_sigprocmask        (__NR_Linux + 126)
+#define __NR_create_module      (__NR_Linux + 127)
+#define __NR_init_module        (__NR_Linux + 128)
+#define __NR_delete_module      (__NR_Linux + 129)
+#define __NR_get_kernel_syms    (__NR_Linux + 130)
+#define __NR_quotactl           (__NR_Linux + 131)
+#define __NR_getpgid            (__NR_Linux + 132)
+#define __NR_fchdir             (__NR_Linux + 133)
+#define __NR_bdflush            (__NR_Linux + 134)
+#define __NR_sysfs              (__NR_Linux + 135)
+#define __NR_personality        (__NR_Linux + 136)
+#define __NR_afs_syscall        (__NR_Linux + 137) /* Syscall for Andrew File System */
+#define __NR_setfsuid           (__NR_Linux + 138)
+#define __NR_setfsgid           (__NR_Linux + 139)
+#define __NR__llseek            (__NR_Linux + 140)
+#define __NR_getdents           (__NR_Linux + 141)
+#define __NR__newselect         (__NR_Linux + 142)
+#define __NR_flock              (__NR_Linux + 143)
+#define __NR_msync              (__NR_Linux + 144)
+#define __NR_readv              (__NR_Linux + 145)
+#define __NR_writev             (__NR_Linux + 146)
+#define __NR_getsid             (__NR_Linux + 147)
+#define __NR_fdatasync          (__NR_Linux + 148)
+#define __NR__sysctl            (__NR_Linux + 149)
+#define __NR_mlock              (__NR_Linux + 150)
+#define __NR_munlock            (__NR_Linux + 151)
+#define __NR_mlockall           (__NR_Linux + 152)
+#define __NR_munlockall         (__NR_Linux + 153)
+#define __NR_sched_setparam             (__NR_Linux + 154)
+#define __NR_sched_getparam             (__NR_Linux + 155)
+#define __NR_sched_setscheduler         (__NR_Linux + 156)
+#define __NR_sched_getscheduler         (__NR_Linux + 157)
+#define __NR_sched_yield                (__NR_Linux + 158)
+#define __NR_sched_get_priority_max     (__NR_Linux + 159)
+#define __NR_sched_get_priority_min     (__NR_Linux + 160)
+#define __NR_sched_rr_get_interval      (__NR_Linux + 161)
+#define __NR_nanosleep          (__NR_Linux + 162)
+#define __NR_mremap             (__NR_Linux + 163)
+#define __NR_setresuid          (__NR_Linux + 164)
+#define __NR_getresuid          (__NR_Linux + 165)
+#define __NR_sigaltstack        (__NR_Linux + 166)
+#define __NR_query_module       (__NR_Linux + 167)
+#define __NR_poll               (__NR_Linux + 168)
+#define __NR_nfsservctl         (__NR_Linux + 169)
+#define __NR_setresgid          (__NR_Linux + 170)
+#define __NR_getresgid          (__NR_Linux + 171)
+#define __NR_prctl              (__NR_Linux + 172)
+#define __NR_rt_sigreturn       (__NR_Linux + 173)
+#define __NR_rt_sigaction       (__NR_Linux + 174)
+#define __NR_rt_sigprocmask     (__NR_Linux + 175)
+#define __NR_rt_sigpending      (__NR_Linux + 176)
+#define __NR_rt_sigtimedwait    (__NR_Linux + 177)
+#define __NR_rt_sigqueueinfo    (__NR_Linux + 178)
+#define __NR_rt_sigsuspend      (__NR_Linux + 179)
+#define __NR_chown              (__NR_Linux + 180)
+#define __NR_setsockopt         (__NR_Linux + 181)
+#define __NR_getsockopt         (__NR_Linux + 182)
+#define __NR_sendmsg            (__NR_Linux + 183)
+#define __NR_recvmsg            (__NR_Linux + 184)
+#define __NR_semop              (__NR_Linux + 185)
+#define __NR_semget             (__NR_Linux + 186)
+#define __NR_semctl             (__NR_Linux + 187)
+#define __NR_msgsnd             (__NR_Linux + 188)
+#define __NR_msgrcv             (__NR_Linux + 189)
+#define __NR_msgget             (__NR_Linux + 190)
+#define __NR_msgctl             (__NR_Linux + 191)
+#define __NR_shmat              (__NR_Linux + 192)
+#define __NR_shmdt              (__NR_Linux + 193)
+#define __NR_shmget             (__NR_Linux + 194)
+#define __NR_shmctl             (__NR_Linux + 195)
+
+#define __NR_getpmsg           (__NR_Linux + 196) /* Somebody *wants* streams? */
+#define __NR_putpmsg           (__NR_Linux + 197)
+
+#define __NR_lstat64            (__NR_Linux + 198)
+#define __NR_truncate64         (__NR_Linux + 199)
+#define __NR_ftruncate64        (__NR_Linux + 200)
+#define __NR_getdents64         (__NR_Linux + 201)
+#define __NR_fcntl64            (__NR_Linux + 202)
+#define __NR_attrctl            (__NR_Linux + 203)
+#define __NR_acl_get            (__NR_Linux + 204)
+#define __NR_acl_set            (__NR_Linux + 205)
+#define __NR_gettid             (__NR_Linux + 206)
+#define __NR_readahead          (__NR_Linux + 207)
+#define __NR_tkill              (__NR_Linux + 208)
+#define __NR_sendfile64         (__NR_Linux + 209)
+#define __NR_futex              (__NR_Linux + 210)
+#define __NR_sched_setaffinity  (__NR_Linux + 211)
+#define __NR_sched_getaffinity  (__NR_Linux + 212)
+#define __NR_set_thread_area    (__NR_Linux + 213)
+#define __NR_get_thread_area    (__NR_Linux + 214)
+#define __NR_io_setup           (__NR_Linux + 215)
+#define __NR_io_destroy         (__NR_Linux + 216)
+#define __NR_io_getevents       (__NR_Linux + 217)
+#define __NR_io_submit          (__NR_Linux + 218)
+#define __NR_io_cancel          (__NR_Linux + 219)
+#define __NR_alloc_hugepages    (__NR_Linux + 220)
+#define __NR_free_hugepages     (__NR_Linux + 221)
+#define __NR_exit_group         (__NR_Linux + 222)
+#define __NR_lookup_dcookie     (__NR_Linux + 223)
+#define __NR_epoll_create       (__NR_Linux + 224)
+#define __NR_epoll_ctl          (__NR_Linux + 225)
+#define __NR_epoll_wait         (__NR_Linux + 226)
+#define __NR_remap_file_pages   (__NR_Linux + 227)
+#define __NR_semtimedop         (__NR_Linux + 228)
+#define __NR_mq_open            (__NR_Linux + 229)
+#define __NR_mq_unlink          (__NR_Linux + 230)
+#define __NR_mq_timedsend       (__NR_Linux + 231)
+#define __NR_mq_timedreceive    (__NR_Linux + 232)
+#define __NR_mq_notify          (__NR_Linux + 233)
+#define __NR_mq_getsetattr      (__NR_Linux + 234)
+#define __NR_waitid            (__NR_Linux + 235)
+#define __NR_fadvise64_64      (__NR_Linux + 236)
+#define __NR_set_tid_address   (__NR_Linux + 237)
+#define __NR_setxattr          (__NR_Linux + 238)
+#define __NR_lsetxattr         (__NR_Linux + 239)
+#define __NR_fsetxattr         (__NR_Linux + 240)
+#define __NR_getxattr          (__NR_Linux + 241)
+#define __NR_lgetxattr         (__NR_Linux + 242)
+#define __NR_fgetxattr         (__NR_Linux + 243)
+#define __NR_listxattr         (__NR_Linux + 244)
+#define __NR_llistxattr                (__NR_Linux + 245)
+#define __NR_flistxattr                (__NR_Linux + 246)
+#define __NR_removexattr       (__NR_Linux + 247)
+#define __NR_lremovexattr      (__NR_Linux + 248)
+#define __NR_fremovexattr      (__NR_Linux + 249)
+#define __NR_timer_create      (__NR_Linux + 250)
+#define __NR_timer_settime     (__NR_Linux + 251)
+#define __NR_timer_gettime     (__NR_Linux + 252)
+#define __NR_timer_getoverrun  (__NR_Linux + 253)
+#define __NR_timer_delete      (__NR_Linux + 254)
+#define __NR_clock_settime     (__NR_Linux + 255)
+#define __NR_clock_gettime     (__NR_Linux + 256)
+#define __NR_clock_getres      (__NR_Linux + 257)
+#define __NR_clock_nanosleep   (__NR_Linux + 258)
+#define __NR_tgkill            (__NR_Linux + 259)
+#define __NR_mbind             (__NR_Linux + 260)
+#define __NR_get_mempolicy     (__NR_Linux + 261)
+#define __NR_set_mempolicy     (__NR_Linux + 262)
+#define __NR_vserver           (__NR_Linux + 263)
+#define __NR_add_key           (__NR_Linux + 264)
+#define __NR_request_key       (__NR_Linux + 265)
+#define __NR_keyctl            (__NR_Linux + 266)
+#define __NR_ioprio_set                (__NR_Linux + 267)
+#define __NR_ioprio_get                (__NR_Linux + 268)
+#define __NR_inotify_init      (__NR_Linux + 269)
+#define __NR_inotify_add_watch (__NR_Linux + 270)
+#define __NR_inotify_rm_watch  (__NR_Linux + 271)
+#define __NR_migrate_pages     (__NR_Linux + 272)
+#define __NR_pselect6          (__NR_Linux + 273)
+#define __NR_ppoll             (__NR_Linux + 274)
+#define __NR_openat            (__NR_Linux + 275)
+#define __NR_mkdirat           (__NR_Linux + 276)
+#define __NR_mknodat           (__NR_Linux + 277)
+#define __NR_fchownat          (__NR_Linux + 278)
+#define __NR_futimesat         (__NR_Linux + 279)
+#define __NR_fstatat64         (__NR_Linux + 280)
+#define __NR_unlinkat          (__NR_Linux + 281)
+#define __NR_renameat          (__NR_Linux + 282)
+#define __NR_linkat            (__NR_Linux + 283)
+#define __NR_symlinkat         (__NR_Linux + 284)
+#define __NR_readlinkat                (__NR_Linux + 285)
+#define __NR_fchmodat          (__NR_Linux + 286)
+#define __NR_faccessat         (__NR_Linux + 287)
+#define __NR_unshare           (__NR_Linux + 288)
+#define __NR_set_robust_list   (__NR_Linux + 289)
+#define __NR_get_robust_list   (__NR_Linux + 290)
+#define __NR_splice            (__NR_Linux + 291)
+#define __NR_sync_file_range   (__NR_Linux + 292)
+#define __NR_tee               (__NR_Linux + 293)
+#define __NR_vmsplice          (__NR_Linux + 294)
+#define __NR_move_pages                (__NR_Linux + 295)
+#define __NR_getcpu            (__NR_Linux + 296)
+#define __NR_epoll_pwait       (__NR_Linux + 297)
+#define __NR_statfs64          (__NR_Linux + 298)
+#define __NR_fstatfs64         (__NR_Linux + 299)
+#define __NR_kexec_load                (__NR_Linux + 300)
+#define __NR_utimensat         (__NR_Linux + 301)
+#define __NR_signalfd          (__NR_Linux + 302)
+#define __NR_timerfd           (__NR_Linux + 303)
+#define __NR_eventfd           (__NR_Linux + 304)
+#define __NR_fallocate         (__NR_Linux + 305)
+#define __NR_timerfd_create    (__NR_Linux + 306)
+#define __NR_timerfd_settime   (__NR_Linux + 307)
+#define __NR_timerfd_gettime   (__NR_Linux + 308)
+#define __NR_signalfd4         (__NR_Linux + 309)
+#define __NR_eventfd2          (__NR_Linux + 310)
+#define __NR_epoll_create1     (__NR_Linux + 311)
+#define __NR_dup3              (__NR_Linux + 312)
+#define __NR_pipe2             (__NR_Linux + 313)
+#define __NR_inotify_init1     (__NR_Linux + 314)
+#define __NR_preadv            (__NR_Linux + 315)
+#define __NR_pwritev           (__NR_Linux + 316)
+#define __NR_rt_tgsigqueueinfo (__NR_Linux + 317)
+#define __NR_perf_event_open   (__NR_Linux + 318)
+#define __NR_recvmmsg          (__NR_Linux + 319)
+#define __NR_accept4           (__NR_Linux + 320)
+#define __NR_prlimit64         (__NR_Linux + 321)
+#define __NR_fanotify_init     (__NR_Linux + 322)
+#define __NR_fanotify_mark     (__NR_Linux + 323)
+#define __NR_clock_adjtime     (__NR_Linux + 324)
+#define __NR_name_to_handle_at (__NR_Linux + 325)
+#define __NR_open_by_handle_at (__NR_Linux + 326)
+#define __NR_syncfs            (__NR_Linux + 327)
+#define __NR_setns             (__NR_Linux + 328)
+#define __NR_sendmmsg          (__NR_Linux + 329)
+
+#define __NR_Linux_syscalls    (__NR_sendmmsg + 1)
+
+
+#define __IGNORE_select                /* newselect */
+#define __IGNORE_fadvise64     /* fadvise64_64 */
+#define __IGNORE_utimes                /* utime */
+
+
+#define HPUX_GATEWAY_ADDR       0xC0000004
+#define LINUX_GATEWAY_ADDR      0x100
+
+#endif /* _UAPI_ASM_PARISC_UNISTD_H_ */
index 7ab286ab5300accb706fb72a2e343153cae85d18..39ed65a44c5fac5fc996b2d5ec25effbbf9853fa 100644 (file)
                        interrupts = <2 7 0>;
                };
 
+               sclpc@3c00 {
+                       compatible = "fsl,mpc5200-lpbfifo";
+                       reg = <0x3c00 0x60>;
+                       interrupts = <2 23 0>;
+               };
+
                i2c@3d00 {
                        #address-cells = <1>;
                        #size-cells = <0>;
index 3444eb8f0ade62305d0a935ca50a02d1fca16933..24f668039295b1b95ff279ff91974a7ad65582ff 100644 (file)
                                reg = <0>;
                        };
                };
-
-               sclpc@3c00 {
-                       compatible = "fsl,mpc5200-lpbfifo";
-                       reg = <0x3c00 0x60>;
-                       interrupts = <3 23 0>;
-               };
        };
 
        localbus {
index 9e354997eb7e3ccc29ac70ee5e7a31c3ce319b01..96512c05803336d937cabcf5b06aa86e43bc538b 100644 (file)
@@ -59,7 +59,7 @@
                        #gpio-cells = <2>;
                };
 
-               psc@2000 { /* PSC1 in ac97 mode */
+               audioplatform: psc@2000 { /* PSC1 in ac97 mode */
                        compatible = "mpc5200b-psc-ac97","fsl,mpc5200b-psc-ac97";
                        cell-index = <0>;
                };
        localbus {
                status = "disabled";
        };
+
+       sound {
+               compatible = "phytec,pcm030-audio-fabric";
+               asoc-platform = <&audioplatform>;
+       };
 };
index 922d9b5fe3d5c9b9863691ffff89c3122f103b21..3abb58394da4830d9d2b61ff6397e5f3090f1c69 100644 (file)
@@ -96,7 +96,7 @@ static inline unsigned int fh_send_nmi(unsigned int vcpu_mask)
        r11 = FH_HCALL_TOKEN(FH_SEND_NMI);
        r3 = vcpu_mask;
 
-       __asm__ __volatile__ ("sc 1"
+       asm volatile("bl        epapr_hypercall_start"
                : "+r" (r11), "+r" (r3)
                : : EV_HCALL_CLOBBERS1
        );
@@ -151,7 +151,7 @@ static inline unsigned int fh_partition_get_dtprop(int handle,
        r9 = (uint32_t)propvalue_addr;
        r10 = *propvalue_len;
 
-       __asm__ __volatile__ ("sc 1"
+       asm volatile("bl        epapr_hypercall_start"
                : "+r" (r11),
                  "+r" (r3), "+r" (r4), "+r" (r5), "+r" (r6), "+r" (r7),
                  "+r" (r8), "+r" (r9), "+r" (r10)
@@ -205,7 +205,7 @@ static inline unsigned int fh_partition_set_dtprop(int handle,
        r9 = (uint32_t)propvalue_addr;
        r10 = propvalue_len;
 
-       __asm__ __volatile__ ("sc 1"
+       asm volatile("bl        epapr_hypercall_start"
                : "+r" (r11),
                  "+r" (r3), "+r" (r4), "+r" (r5), "+r" (r6), "+r" (r7),
                  "+r" (r8), "+r" (r9), "+r" (r10)
@@ -229,7 +229,7 @@ static inline unsigned int fh_partition_restart(unsigned int partition)
        r11 = FH_HCALL_TOKEN(FH_PARTITION_RESTART);
        r3 = partition;
 
-       __asm__ __volatile__ ("sc 1"
+       asm volatile("bl        epapr_hypercall_start"
                : "+r" (r11), "+r" (r3)
                : : EV_HCALL_CLOBBERS1
        );
@@ -262,7 +262,7 @@ static inline unsigned int fh_partition_get_status(unsigned int partition,
        r11 = FH_HCALL_TOKEN(FH_PARTITION_GET_STATUS);
        r3 = partition;
 
-       __asm__ __volatile__ ("sc 1"
+       asm volatile("bl        epapr_hypercall_start"
                : "+r" (r11), "+r" (r3), "=r" (r4)
                : : EV_HCALL_CLOBBERS2
        );
@@ -295,7 +295,7 @@ static inline unsigned int fh_partition_start(unsigned int partition,
        r4 = entry_point;
        r5 = load;
 
-       __asm__ __volatile__ ("sc 1"
+       asm volatile("bl        epapr_hypercall_start"
                : "+r" (r11), "+r" (r3), "+r" (r4), "+r" (r5)
                : : EV_HCALL_CLOBBERS3
        );
@@ -317,7 +317,7 @@ static inline unsigned int fh_partition_stop(unsigned int partition)
        r11 = FH_HCALL_TOKEN(FH_PARTITION_STOP);
        r3 = partition;
 
-       __asm__ __volatile__ ("sc 1"
+       asm volatile("bl        epapr_hypercall_start"
                : "+r" (r11), "+r" (r3)
                : : EV_HCALL_CLOBBERS1
        );
@@ -376,7 +376,7 @@ static inline unsigned int fh_partition_memcpy(unsigned int source,
 #endif
        r7 = count;
 
-       __asm__ __volatile__ ("sc 1"
+       asm volatile("bl        epapr_hypercall_start"
                : "+r" (r11),
                  "+r" (r3), "+r" (r4), "+r" (r5), "+r" (r6), "+r" (r7)
                : : EV_HCALL_CLOBBERS5
@@ -399,7 +399,7 @@ static inline unsigned int fh_dma_enable(unsigned int liodn)
        r11 = FH_HCALL_TOKEN(FH_DMA_ENABLE);
        r3 = liodn;
 
-       __asm__ __volatile__ ("sc 1"
+       asm volatile("bl        epapr_hypercall_start"
                : "+r" (r11), "+r" (r3)
                : : EV_HCALL_CLOBBERS1
        );
@@ -421,7 +421,7 @@ static inline unsigned int fh_dma_disable(unsigned int liodn)
        r11 = FH_HCALL_TOKEN(FH_DMA_DISABLE);
        r3 = liodn;
 
-       __asm__ __volatile__ ("sc 1"
+       asm volatile("bl        epapr_hypercall_start"
                : "+r" (r11), "+r" (r3)
                : : EV_HCALL_CLOBBERS1
        );
@@ -447,7 +447,7 @@ static inline unsigned int fh_vmpic_get_msir(unsigned int interrupt,
        r11 = FH_HCALL_TOKEN(FH_VMPIC_GET_MSIR);
        r3 = interrupt;
 
-       __asm__ __volatile__ ("sc 1"
+       asm volatile("bl        epapr_hypercall_start"
                : "+r" (r11), "+r" (r3), "=r" (r4)
                : : EV_HCALL_CLOBBERS2
        );
@@ -469,7 +469,7 @@ static inline unsigned int fh_system_reset(void)
 
        r11 = FH_HCALL_TOKEN(FH_SYSTEM_RESET);
 
-       __asm__ __volatile__ ("sc 1"
+       asm volatile("bl        epapr_hypercall_start"
                : "+r" (r11), "=r" (r3)
                : : EV_HCALL_CLOBBERS1
        );
@@ -506,7 +506,7 @@ static inline unsigned int fh_err_get_info(int queue, uint32_t *bufsize,
        r6 = addr_lo;
        r7 = peek;
 
-       __asm__ __volatile__ ("sc 1"
+       asm volatile("bl        epapr_hypercall_start"
                : "+r" (r11), "+r" (r3), "+r" (r4), "+r" (r5), "+r" (r6),
                  "+r" (r7)
                : : EV_HCALL_CLOBBERS5
@@ -542,7 +542,7 @@ static inline unsigned int fh_get_core_state(unsigned int handle,
        r3 = handle;
        r4 = vcpu;
 
-       __asm__ __volatile__ ("sc 1"
+       asm volatile("bl        epapr_hypercall_start"
                : "+r" (r11), "+r" (r3), "+r" (r4)
                : : EV_HCALL_CLOBBERS2
        );
@@ -572,7 +572,7 @@ static inline unsigned int fh_enter_nap(unsigned int handle, unsigned int vcpu)
        r3 = handle;
        r4 = vcpu;
 
-       __asm__ __volatile__ ("sc 1"
+       asm volatile("bl        epapr_hypercall_start"
                : "+r" (r11), "+r" (r3), "+r" (r4)
                : : EV_HCALL_CLOBBERS2
        );
@@ -597,7 +597,7 @@ static inline unsigned int fh_exit_nap(unsigned int handle, unsigned int vcpu)
        r3 = handle;
        r4 = vcpu;
 
-       __asm__ __volatile__ ("sc 1"
+       asm volatile("bl        epapr_hypercall_start"
                : "+r" (r11), "+r" (r3), "+r" (r4)
                : : EV_HCALL_CLOBBERS2
        );
@@ -618,7 +618,7 @@ static inline unsigned int fh_claim_device(unsigned int handle)
        r11 = FH_HCALL_TOKEN(FH_CLAIM_DEVICE);
        r3 = handle;
 
-       __asm__ __volatile__ ("sc 1"
+       asm volatile("bl        epapr_hypercall_start"
                : "+r" (r11), "+r" (r3)
                : : EV_HCALL_CLOBBERS1
        );
@@ -645,7 +645,7 @@ static inline unsigned int fh_partition_stop_dma(unsigned int handle)
        r11 = FH_HCALL_TOKEN(FH_PARTITION_STOP_DMA);
        r3 = handle;
 
-       __asm__ __volatile__ ("sc 1"
+       asm volatile("bl        epapr_hypercall_start"
                : "+r" (r11), "+r" (r3)
                : : EV_HCALL_CLOBBERS1
        );
index 7aefdb3e1ce405865beb991934dadfac22036724..36fcf41904613cf442bd07338887bb492735213a 100644 (file)
@@ -160,7 +160,7 @@ extern long kvmppc_virtmode_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
 extern long kvmppc_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
                        long pte_index, unsigned long pteh, unsigned long ptel);
 extern long kvmppc_hv_get_dirty_log(struct kvm *kvm,
-                       struct kvm_memory_slot *memslot);
+                       struct kvm_memory_slot *memslot, unsigned long *map);
 
 extern void kvmppc_entry_trampoline(void);
 extern void kvmppc_hv_entry_trampoline(void);
index 30a600fa1b6a9977a2edc380f763eda4b1ccf5c9..a37a12a9a7d720374304b8460f59b690f24c2556 100644 (file)
@@ -38,9 +38,9 @@
 #ifdef CONFIG_KVM_BOOKE_HV
 BEGIN_FTR_SECTION
        mtocrf  0x80, r11       /* check MSR[GS] without clobbering reg */
-       bf      3, kvmppc_resume_\intno\()_\srr1
+       bf      3, 1975f
        b       kvmppc_handler_\intno\()_\srr1
-kvmppc_resume_\intno\()_\srr1:
+1975:
 END_FTR_SECTION_IFSET(CPU_FTR_EMB_HV)
 #endif
 .endm
index 28e8f5e5c63e7e1ac87247edaf2a0052e6c128a8..68f5a308737a125865b8a78db52b54acae85b0c4 100644 (file)
@@ -46,7 +46,7 @@
 #define KVM_COALESCED_MMIO_PAGE_OFFSET 1
 #endif
 
-#ifdef CONFIG_KVM_BOOK3S_64_HV
+#if !defined(CONFIG_KVM_440)
 #include <linux/mmu_notifier.h>
 
 #define KVM_ARCH_WANT_MMU_NOTIFIER
@@ -204,7 +204,7 @@ struct revmap_entry {
 };
 
 /*
- * We use the top bit of each memslot->rmap entry as a lock bit,
+ * We use the top bit of each memslot->arch.rmap entry as a lock bit,
  * and bit 32 as a present flag.  The bottom 32 bits are the
  * index in the guest HPT of a HPTE that points to the page.
  */
@@ -215,14 +215,17 @@ struct revmap_entry {
 #define KVMPPC_RMAP_PRESENT    0x100000000ul
 #define KVMPPC_RMAP_INDEX      0xfffffffful
 
-/* Low-order bits in kvm->arch.slot_phys[][] */
+/* Low-order bits in memslot->arch.slot_phys[] */
 #define KVMPPC_PAGE_ORDER_MASK 0x1f
 #define KVMPPC_PAGE_NO_CACHE   HPTE_R_I        /* 0x20 */
 #define KVMPPC_PAGE_WRITETHRU  HPTE_R_W        /* 0x40 */
 #define KVMPPC_GOT_PAGE                0x80
 
 struct kvm_arch_memory_slot {
+#ifdef CONFIG_KVM_BOOK3S_64_HV
        unsigned long *rmap;
+       unsigned long *slot_phys;
+#endif /* CONFIG_KVM_BOOK3S_64_HV */
 };
 
 struct kvm_arch {
@@ -246,8 +249,6 @@ struct kvm_arch {
        unsigned long hpt_npte;
        unsigned long hpt_mask;
        spinlock_t slot_phys_lock;
-       unsigned long *slot_phys[KVM_MEM_SLOTS_NUM];
-       int slot_npages[KVM_MEM_SLOTS_NUM];
        unsigned short last_vcpu[NR_CPUS];
        struct kvmppc_vcore *vcores[KVM_MAX_VCORES];
        struct kvmppc_linear_info *hpt_li;
@@ -346,6 +347,27 @@ struct kvmppc_slb {
        bool class      : 1;
 };
 
+# ifdef CONFIG_PPC_FSL_BOOK3E
+#define KVMPPC_BOOKE_IAC_NUM   2
+#define KVMPPC_BOOKE_DAC_NUM   2
+# else
+#define KVMPPC_BOOKE_IAC_NUM   4
+#define KVMPPC_BOOKE_DAC_NUM   2
+# endif
+#define KVMPPC_BOOKE_MAX_IAC   4
+#define KVMPPC_BOOKE_MAX_DAC   2
+
+struct kvmppc_booke_debug_reg {
+       u32 dbcr0;
+       u32 dbcr1;
+       u32 dbcr2;
+#ifdef CONFIG_KVM_E500MC
+       u32 dbcr4;
+#endif
+       u64 iac[KVMPPC_BOOKE_MAX_IAC];
+       u64 dac[KVMPPC_BOOKE_MAX_DAC];
+};
+
 struct kvm_vcpu_arch {
        ulong host_stack;
        u32 host_pid;
@@ -440,8 +462,6 @@ struct kvm_vcpu_arch {
 
        u32 ccr0;
        u32 ccr1;
-       u32 dbcr0;
-       u32 dbcr1;
        u32 dbsr;
 
        u64 mmcr[3];
@@ -471,9 +491,12 @@ struct kvm_vcpu_arch {
        ulong fault_esr;
        ulong queued_dear;
        ulong queued_esr;
+       spinlock_t wdt_lock;
+       struct timer_list wdt_timer;
        u32 tlbcfg[4];
        u32 mmucfg;
        u32 epr;
+       struct kvmppc_booke_debug_reg dbg_reg;
 #endif
        gpa_t paddr_accessed;
        gva_t vaddr_accessed;
@@ -486,6 +509,7 @@ struct kvm_vcpu_arch {
        u8 osi_needed;
        u8 osi_enabled;
        u8 papr_enabled;
+       u8 watchdog_enabled;
        u8 sane;
        u8 cpu_type;
        u8 hcall_needed;
index 9365860fb7f61676a57233eb14de66db0cc0c65b..2b119654b4c1a5fcd2ce568fd83ad3a64bccdd03 100644 (file)
@@ -21,7 +21,6 @@
 
 #include <uapi/asm/kvm_para.h>
 
-
 #ifdef CONFIG_KVM_GUEST
 
 #include <linux/of.h>
@@ -55,7 +54,7 @@ static unsigned long kvm_hypercall(unsigned long *in,
                                   unsigned long *out,
                                   unsigned long nr)
 {
-       return HC_EV_UNIMPLEMENTED;
+       return EV_UNIMPLEMENTED;
 }
 
 #endif
@@ -66,7 +65,7 @@ static inline long kvm_hypercall0_1(unsigned int nr, unsigned long *r2)
        unsigned long out[8];
        unsigned long r;
 
-       r = kvm_hypercall(in, out, nr | HC_VENDOR_KVM);
+       r = kvm_hypercall(in, out, KVM_HCALL_TOKEN(nr));
        *r2 = out[0];
 
        return r;
@@ -77,7 +76,7 @@ static inline long kvm_hypercall0(unsigned int nr)
        unsigned long in[8];
        unsigned long out[8];
 
-       return kvm_hypercall(in, out, nr | HC_VENDOR_KVM);
+       return kvm_hypercall(in, out, KVM_HCALL_TOKEN(nr));
 }
 
 static inline long kvm_hypercall1(unsigned int nr, unsigned long p1)
@@ -86,7 +85,7 @@ static inline long kvm_hypercall1(unsigned int nr, unsigned long p1)
        unsigned long out[8];
 
        in[0] = p1;
-       return kvm_hypercall(in, out, nr | HC_VENDOR_KVM);
+       return kvm_hypercall(in, out, KVM_HCALL_TOKEN(nr));
 }
 
 static inline long kvm_hypercall2(unsigned int nr, unsigned long p1,
@@ -97,7 +96,7 @@ static inline long kvm_hypercall2(unsigned int nr, unsigned long p1,
 
        in[0] = p1;
        in[1] = p2;
-       return kvm_hypercall(in, out, nr | HC_VENDOR_KVM);
+       return kvm_hypercall(in, out, KVM_HCALL_TOKEN(nr));
 }
 
 static inline long kvm_hypercall3(unsigned int nr, unsigned long p1,
@@ -109,7 +108,7 @@ static inline long kvm_hypercall3(unsigned int nr, unsigned long p1,
        in[0] = p1;
        in[1] = p2;
        in[2] = p3;
-       return kvm_hypercall(in, out, nr | HC_VENDOR_KVM);
+       return kvm_hypercall(in, out, KVM_HCALL_TOKEN(nr));
 }
 
 static inline long kvm_hypercall4(unsigned int nr, unsigned long p1,
@@ -123,7 +122,7 @@ static inline long kvm_hypercall4(unsigned int nr, unsigned long p1,
        in[1] = p2;
        in[2] = p3;
        in[3] = p4;
-       return kvm_hypercall(in, out, nr | HC_VENDOR_KVM);
+       return kvm_hypercall(in, out, KVM_HCALL_TOKEN(nr));
 }
 
 
index e006f0bdea95f1a9464c688928dc7206690f5c14..609cca3e942621a7380c79724cd6e72d2e6d9b5c 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/types.h>
 #include <linux/kvm_types.h>
 #include <linux/kvm_host.h>
+#include <linux/bug.h>
 #ifdef CONFIG_PPC_BOOK3S
 #include <asm/kvm_book3s.h>
 #else
@@ -68,6 +69,8 @@ extern void kvmppc_emulate_dec(struct kvm_vcpu *vcpu);
 extern u32 kvmppc_get_dec(struct kvm_vcpu *vcpu, u64 tb);
 extern void kvmppc_decrementer_func(unsigned long data);
 extern int kvmppc_sanity_check(struct kvm_vcpu *vcpu);
+extern int kvmppc_subarch_vcpu_init(struct kvm_vcpu *vcpu);
+extern void kvmppc_subarch_vcpu_uninit(struct kvm_vcpu *vcpu);
 
 /* Core-specific hooks */
 
@@ -104,6 +107,7 @@ extern void kvmppc_core_queue_external(struct kvm_vcpu *vcpu,
                                        struct kvm_interrupt *irq);
 extern void kvmppc_core_dequeue_external(struct kvm_vcpu *vcpu,
                                          struct kvm_interrupt *irq);
+extern void kvmppc_core_flush_tlb(struct kvm_vcpu *vcpu);
 
 extern int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
                                   unsigned int op, int *advance);
@@ -111,6 +115,7 @@ extern int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn,
                                     ulong val);
 extern int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn,
                                     ulong *val);
+extern int kvmppc_core_check_requests(struct kvm_vcpu *vcpu);
 
 extern int kvmppc_booke_init(void);
 extern void kvmppc_booke_exit(void);
@@ -139,16 +144,26 @@ extern struct kvmppc_linear_info *kvm_alloc_hpt(void);
 extern void kvm_release_hpt(struct kvmppc_linear_info *li);
 extern int kvmppc_core_init_vm(struct kvm *kvm);
 extern void kvmppc_core_destroy_vm(struct kvm *kvm);
+extern void kvmppc_core_free_memslot(struct kvm_memory_slot *free,
+                                    struct kvm_memory_slot *dont);
+extern int kvmppc_core_create_memslot(struct kvm_memory_slot *slot,
+                                     unsigned long npages);
 extern int kvmppc_core_prepare_memory_region(struct kvm *kvm,
+                               struct kvm_memory_slot *memslot,
                                struct kvm_userspace_memory_region *mem);
 extern void kvmppc_core_commit_memory_region(struct kvm *kvm,
-                               struct kvm_userspace_memory_region *mem);
+                               struct kvm_userspace_memory_region *mem,
+                               struct kvm_memory_slot old);
 extern int kvm_vm_ioctl_get_smmu_info(struct kvm *kvm,
                                      struct kvm_ppc_smmu_info *info);
+extern void kvmppc_core_flush_memslot(struct kvm *kvm,
+                                     struct kvm_memory_slot *memslot);
 
 extern int kvmppc_bookehv_init(void);
 extern void kvmppc_bookehv_exit(void);
 
+extern int kvmppc_prepare_to_enter(struct kvm_vcpu *vcpu);
+
 /*
  * Cuts out inst bits with ordering according to spec.
  * That means the leftmost bit is zero. All given bits are included.
@@ -182,6 +197,41 @@ static inline u32 kvmppc_set_field(u64 inst, int msb, int lsb, int value)
        return r;
 }
 
+union kvmppc_one_reg {
+       u32     wval;
+       u64     dval;
+       vector128 vval;
+       u64     vsxval[2];
+       struct {
+               u64     addr;
+               u64     length;
+       }       vpaval;
+};
+
+#define one_reg_size(id)       \
+       (1ul << (((id) & KVM_REG_SIZE_MASK) >> KVM_REG_SIZE_SHIFT))
+
+#define get_reg_val(id, reg)   ({              \
+       union kvmppc_one_reg __u;               \
+       switch (one_reg_size(id)) {             \
+       case 4: __u.wval = (reg); break;        \
+       case 8: __u.dval = (reg); break;        \
+       default: BUG();                         \
+       }                                       \
+       __u;                                    \
+})
+
+
+#define set_reg_val(id, val)   ({              \
+       u64 __v;                                \
+       switch (one_reg_size(id)) {             \
+       case 4: __v = (val).wval; break;        \
+       case 8: __v = (val).dval; break;        \
+       default: BUG();                         \
+       }                                       \
+       __v;                                    \
+})
+
 void kvmppc_core_get_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs);
 int kvmppc_core_set_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs);
 
@@ -190,6 +240,8 @@ int kvmppc_set_sregs_ivor(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs);
 
 int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg);
 int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg);
+int kvmppc_get_one_reg(struct kvm_vcpu *vcpu, u64 id, union kvmppc_one_reg *);
+int kvmppc_set_one_reg(struct kvm_vcpu *vcpu, u64 id, union kvmppc_one_reg *);
 
 void kvmppc_set_pid(struct kvm_vcpu *vcpu, u32 pid);
 
@@ -230,5 +282,15 @@ static inline void kvmppc_mmu_flush_icache(pfn_t pfn)
        }
 }
 
+/* Please call after prepare_to_enter. This function puts the lazy ee state
+   back to normal mode, without actually enabling interrupts. */
+static inline void kvmppc_lazy_ee_enable(void)
+{
+#ifdef CONFIG_PPC64
+       /* Only need to enable IRQs by hard enabling them after this */
+       local_paca->irq_happened = 0;
+       local_paca->soft_enabled = 1;
+#endif
+}
 
 #endif /* __POWERPC_KVM_PPC_H__ */
index 2d916c4982c5136a71b10f917606757aa743792f..e07e6af5e1ff9938a00468d49c46aaaee7be8ee9 100644 (file)
 #define TCR_FIE                0x00800000      /* FIT Interrupt Enable */
 #define TCR_ARE                0x00400000      /* Auto Reload Enable */
 
+#ifdef CONFIG_E500
+#define TCR_GET_WP(tcr)  ((((tcr) & 0xC0000000) >> 30) | \
+                             (((tcr) & 0x1E0000) >> 15))
+#else
+#define TCR_GET_WP(tcr)  (((tcr) & 0xC0000000) >> 30)
+#endif
+
 /* Bit definitions for the TSR. */
 #define TSR_ENW                0x80000000      /* Enable Next Watchdog */
 #define TSR_WIS                0x40000000      /* WDT Interrupt Status */
index 840838769853e653f1ee950d9fdb4ed619f54ede..d0b27f8b47fb2989f380c18716560169034ac2d9 100644 (file)
@@ -356,3 +356,4 @@ COMPAT_SYS_SPU(sendmmsg)
 SYSCALL_SPU(setns)
 COMPAT_SYS(process_vm_readv)
 COMPAT_SYS(process_vm_writev)
+SYSCALL(finit_module)
index 280068cfff2e8721e39e4582277de4670bd09793..ae2c891f2669bf64269bd51eee5c2b5ae379e59d 100644 (file)
@@ -12,7 +12,7 @@
 #include <uapi/asm/unistd.h>
 
 
-#define __NR_syscalls          353
+#define __NR_syscalls          354
 
 #define __NR__exit __NR_exit
 #define NR_syscalls    __NR_syscalls
index a33c3c03bb2e104693eab939e0ffc3e901508259..c62a732f417181b67465b33d581299fab745459e 100644 (file)
@@ -8,6 +8,7 @@ header-y += byteorder.h
 header-y += cputable.h
 header-y += elf.h
 header-y += errno.h
+header-y += epapr_hcalls.h
 header-y += fcntl.h
 header-y += ioctl.h
 header-y += ioctls.h
similarity index 96%
rename from arch/powerpc/include/asm/epapr_hcalls.h
rename to arch/powerpc/include/uapi/asm/epapr_hcalls.h
index bf2c06c338719e66c20db73bf8bc8d0bb8dabc5d..b8d94459a929d6d1c74203bd40d03b6ab8bea9ab 100644 (file)
 #ifndef _EPAPR_HCALLS_H
 #define _EPAPR_HCALLS_H
 
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <asm/byteorder.h>
-
 #define EV_BYTE_CHANNEL_SEND           1
 #define EV_BYTE_CHANNEL_RECEIVE                2
 #define EV_BYTE_CHANNEL_POLL           3
@@ -88,7 +84,8 @@
 #define _EV_HCALL_TOKEN(id, num) (((id) << 16) | (num))
 #define EV_HCALL_TOKEN(hcall_num) _EV_HCALL_TOKEN(EV_EPAPR_VENDOR_ID, hcall_num)
 
-/* epapr error codes */
+/* epapr return codes */
+#define EV_SUCCESS             0
 #define EV_EPERM               1       /* Operation not permitted */
 #define EV_ENOENT              2       /*  Entry Not Found */
 #define EV_EIO                 3       /* I/O error occured */
 #define EV_UNIMPLEMENTED       12      /* Unimplemented hypercall */
 #define EV_BUFFER_OVERFLOW     13      /* Caller-supplied buffer too small */
 
+#ifndef __ASSEMBLY__
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/byteorder.h>
+
 /*
  * Hypercall register clobber list
  *
@@ -193,7 +195,7 @@ static inline unsigned int ev_int_set_config(unsigned int interrupt,
        r5  = priority;
        r6  = destination;
 
-       __asm__ __volatile__ ("sc 1"
+       asm volatile("bl        epapr_hypercall_start"
                : "+r" (r11), "+r" (r3), "+r" (r4), "+r" (r5), "+r" (r6)
                : : EV_HCALL_CLOBBERS4
        );
@@ -222,7 +224,7 @@ static inline unsigned int ev_int_get_config(unsigned int interrupt,
        r11 = EV_HCALL_TOKEN(EV_INT_GET_CONFIG);
        r3 = interrupt;
 
-       __asm__ __volatile__ ("sc 1"
+       asm volatile("bl        epapr_hypercall_start"
                : "+r" (r11), "+r" (r3), "=r" (r4), "=r" (r5), "=r" (r6)
                : : EV_HCALL_CLOBBERS4
        );
@@ -252,7 +254,7 @@ static inline unsigned int ev_int_set_mask(unsigned int interrupt,
        r3 = interrupt;
        r4 = mask;
 
-       __asm__ __volatile__ ("sc 1"
+       asm volatile("bl        epapr_hypercall_start"
                : "+r" (r11), "+r" (r3), "+r" (r4)
                : : EV_HCALL_CLOBBERS2
        );
@@ -277,7 +279,7 @@ static inline unsigned int ev_int_get_mask(unsigned int interrupt,
        r11 = EV_HCALL_TOKEN(EV_INT_GET_MASK);
        r3 = interrupt;
 
-       __asm__ __volatile__ ("sc 1"
+       asm volatile("bl        epapr_hypercall_start"
                : "+r" (r11), "+r" (r3), "=r" (r4)
                : : EV_HCALL_CLOBBERS2
        );
@@ -305,7 +307,7 @@ static inline unsigned int ev_int_eoi(unsigned int interrupt)
        r11 = EV_HCALL_TOKEN(EV_INT_EOI);
        r3 = interrupt;
 
-       __asm__ __volatile__ ("sc 1"
+       asm volatile("bl        epapr_hypercall_start"
                : "+r" (r11), "+r" (r3)
                : : EV_HCALL_CLOBBERS1
        );
@@ -344,7 +346,7 @@ static inline unsigned int ev_byte_channel_send(unsigned int handle,
        r7 = be32_to_cpu(p[2]);
        r8 = be32_to_cpu(p[3]);
 
-       __asm__ __volatile__ ("sc 1"
+       asm volatile("bl        epapr_hypercall_start"
                : "+r" (r11), "+r" (r3),
                  "+r" (r4), "+r" (r5), "+r" (r6), "+r" (r7), "+r" (r8)
                : : EV_HCALL_CLOBBERS6
@@ -383,7 +385,7 @@ static inline unsigned int ev_byte_channel_receive(unsigned int handle,
        r3 = handle;
        r4 = *count;
 
-       __asm__ __volatile__ ("sc 1"
+       asm volatile("bl        epapr_hypercall_start"
                : "+r" (r11), "+r" (r3), "+r" (r4),
                  "=r" (r5), "=r" (r6), "=r" (r7), "=r" (r8)
                : : EV_HCALL_CLOBBERS6
@@ -421,7 +423,7 @@ static inline unsigned int ev_byte_channel_poll(unsigned int handle,
        r11 = EV_HCALL_TOKEN(EV_BYTE_CHANNEL_POLL);
        r3 = handle;
 
-       __asm__ __volatile__ ("sc 1"
+       asm volatile("bl        epapr_hypercall_start"
                : "+r" (r11), "+r" (r3), "=r" (r4), "=r" (r5)
                : : EV_HCALL_CLOBBERS3
        );
@@ -454,7 +456,7 @@ static inline unsigned int ev_int_iack(unsigned int handle,
        r11 = EV_HCALL_TOKEN(EV_INT_IACK);
        r3 = handle;
 
-       __asm__ __volatile__ ("sc 1"
+       asm volatile("bl        epapr_hypercall_start"
                : "+r" (r11), "+r" (r3), "=r" (r4)
                : : EV_HCALL_CLOBBERS2
        );
@@ -478,7 +480,7 @@ static inline unsigned int ev_doorbell_send(unsigned int handle)
        r11 = EV_HCALL_TOKEN(EV_DOORBELL_SEND);
        r3 = handle;
 
-       __asm__ __volatile__ ("sc 1"
+       asm volatile("bl        epapr_hypercall_start"
                : "+r" (r11), "+r" (r3)
                : : EV_HCALL_CLOBBERS1
        );
@@ -498,12 +500,12 @@ static inline unsigned int ev_idle(void)
 
        r11 = EV_HCALL_TOKEN(EV_IDLE);
 
-       __asm__ __volatile__ ("sc 1"
+       asm volatile("bl        epapr_hypercall_start"
                : "+r" (r11), "=r" (r3)
                : : EV_HCALL_CLOBBERS1
        );
 
        return r3;
 }
-
+#endif /* !__ASSEMBLY__ */
 #endif
index 1bea4d8ea6f432d3e3425752aafa156a8fe7710b..b89ae4db45ced4523e101c18a5477c62c928fd0a 100644 (file)
@@ -221,6 +221,12 @@ struct kvm_sregs {
 
                        __u32 dbsr;     /* KVM_SREGS_E_UPDATE_DBSR */
                        __u32 dbcr[3];
+                       /*
+                        * iac/dac registers are 64bit wide, while this API
+                        * interface provides only lower 32 bits on 64 bit
+                        * processors. ONE_REG interface is added for 64bit
+                        * iac/dac registers.
+                        */
                        __u32 iac[4];
                        __u32 dac[2];
                        __u32 dvc[2];
@@ -326,5 +332,58 @@ struct kvm_book3e_206_tlb_params {
 };
 
 #define KVM_REG_PPC_HIOR       (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x1)
+#define KVM_REG_PPC_IAC1       (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x2)
+#define KVM_REG_PPC_IAC2       (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x3)
+#define KVM_REG_PPC_IAC3       (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x4)
+#define KVM_REG_PPC_IAC4       (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x5)
+#define KVM_REG_PPC_DAC1       (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x6)
+#define KVM_REG_PPC_DAC2       (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x7)
+#define KVM_REG_PPC_DABR       (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x8)
+#define KVM_REG_PPC_DSCR       (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x9)
+#define KVM_REG_PPC_PURR       (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xa)
+#define KVM_REG_PPC_SPURR      (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb)
+#define KVM_REG_PPC_DAR                (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xc)
+#define KVM_REG_PPC_DSISR      (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xd)
+#define KVM_REG_PPC_AMR                (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xe)
+#define KVM_REG_PPC_UAMOR      (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xf)
+
+#define KVM_REG_PPC_MMCR0      (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x10)
+#define KVM_REG_PPC_MMCR1      (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x11)
+#define KVM_REG_PPC_MMCRA      (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x12)
+
+#define KVM_REG_PPC_PMC1       (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x18)
+#define KVM_REG_PPC_PMC2       (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x19)
+#define KVM_REG_PPC_PMC3       (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1a)
+#define KVM_REG_PPC_PMC4       (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1b)
+#define KVM_REG_PPC_PMC5       (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1c)
+#define KVM_REG_PPC_PMC6       (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1d)
+#define KVM_REG_PPC_PMC7       (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1e)
+#define KVM_REG_PPC_PMC8       (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1f)
+
+/* 32 floating-point registers */
+#define KVM_REG_PPC_FPR0       (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x20)
+#define KVM_REG_PPC_FPR(n)     (KVM_REG_PPC_FPR0 + (n))
+#define KVM_REG_PPC_FPR31      (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x3f)
+
+/* 32 VMX/Altivec vector registers */
+#define KVM_REG_PPC_VR0                (KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x40)
+#define KVM_REG_PPC_VR(n)      (KVM_REG_PPC_VR0 + (n))
+#define KVM_REG_PPC_VR31       (KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x5f)
+
+/* 32 double-width FP registers for VSX */
+/* High-order halves overlap with FP regs */
+#define KVM_REG_PPC_VSR0       (KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x60)
+#define KVM_REG_PPC_VSR(n)     (KVM_REG_PPC_VSR0 + (n))
+#define KVM_REG_PPC_VSR31      (KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x7f)
+
+/* FP and vector status/control registers */
+#define KVM_REG_PPC_FPSCR      (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x80)
+#define KVM_REG_PPC_VSCR       (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x81)
+
+/* Virtual processor areas */
+/* For SLB & DTL, address in high (first) half, length in low half */
+#define KVM_REG_PPC_VPA_ADDR   (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x82)
+#define KVM_REG_PPC_VPA_SLB    (KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x83)
+#define KVM_REG_PPC_VPA_DTL    (KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x84)
 
 #endif /* __LINUX_KVM_POWERPC_H */
index 5e04383a1db5867c9c678b8ad3c6cadf760cab58..34d8b1cfab2272121b2099529cf908c9a8898bf9 100644 (file)
@@ -75,9 +75,10 @@ struct kvm_vcpu_arch_shared {
 };
 
 #define KVM_SC_MAGIC_R0                0x4b564d21 /* "KVM!" */
-#define HC_VENDOR_KVM          (42 << 16)
-#define HC_EV_SUCCESS          0
-#define HC_EV_UNIMPLEMENTED    12
+
+#define KVM_HCALL_TOKEN(num)   _EV_HCALL_TOKEN(EV_KVM_VENDOR_ID, num)
+
+#include <asm/epapr_hcalls.h>
 
 #define KVM_FEATURE_MAGIC_PAGE 1
 
index 380b5d37a9049fd1c2cb60d852d46e5e648c293d..8c478c6c6b1e41c7090b06a8b52815f7d537ff89 100644 (file)
 #define __NR_setns             350
 #define __NR_process_vm_readv  351
 #define __NR_process_vm_writev 352
+#define __NR_finit_module      353
 
 
 #endif /* _UAPI_ASM_POWERPC_UNISTD_H_ */
index 697b390ebfd8af815075b1764699da52a7402da2..62c0dc2378266653cd97591f095261d2ed5c901a 100644 (file)
@@ -8,13 +8,41 @@
  */
 
 #include <linux/threads.h>
+#include <asm/epapr_hcalls.h>
 #include <asm/reg.h>
 #include <asm/page.h>
 #include <asm/cputable.h>
 #include <asm/thread_info.h>
 #include <asm/ppc_asm.h>
+#include <asm/asm-compat.h>
 #include <asm/asm-offsets.h>
 
+/* epapr_ev_idle() was derived from e500_idle() */
+_GLOBAL(epapr_ev_idle)
+       CURRENT_THREAD_INFO(r3, r1)
+       PPC_LL  r4, TI_LOCAL_FLAGS(r3)  /* set napping bit */
+       ori     r4, r4,_TLF_NAPPING     /* so when we take an exception */
+       PPC_STL r4, TI_LOCAL_FLAGS(r3)  /* it will return to our caller */
+
+       wrteei  1
+
+idle_loop:
+       LOAD_REG_IMMEDIATE(r11, EV_HCALL_TOKEN(EV_IDLE))
+
+.global epapr_ev_idle_start
+epapr_ev_idle_start:
+       li      r3, -1
+       nop
+       nop
+       nop
+
+       /*
+        * Guard against spurious wakeups from a hypervisor --
+        * only interrupt will cause us to return to LR due to
+        * _TLF_NAPPING.
+        */
+       b       idle_loop
+
 /* Hypercall entry point. Will be patched with device tree instructions. */
 .global epapr_hypercall_start
 epapr_hypercall_start:
index 028aeae370b657fb91096be96243efdf0e8bf61f..f3eab8594d9f873432deb94c770db354f20ffc76 100644 (file)
 #include <asm/epapr_hcalls.h>
 #include <asm/cacheflush.h>
 #include <asm/code-patching.h>
+#include <asm/machdep.h>
+
+extern void epapr_ev_idle(void);
+extern u32 epapr_ev_idle_start[];
 
 bool epapr_paravirt_enabled;
 
@@ -41,8 +45,13 @@ static int __init epapr_paravirt_init(void)
        if (len % 4 || len > (4 * 4))
                return -ENODEV;
 
-       for (i = 0; i < (len / 4); i++)
+       for (i = 0; i < (len / 4); i++) {
                patch_instruction(epapr_hypercall_start + i, insts[i]);
+               patch_instruction(epapr_ev_idle_start + i, insts[i]);
+       }
+
+       if (of_get_property(hyper_node, "has-idle", NULL))
+               ppc_md.power_save = epapr_ev_idle;
 
        epapr_paravirt_enabled = true;
 
index 867db1de8949571a152cd9559a5b36bb7c91e090..a61b133c4f99b2a380b274fa7c39c7a5d301761a 100644 (file)
@@ -419,7 +419,7 @@ static void kvm_map_magic_page(void *data)
        in[0] = KVM_MAGIC_PAGE;
        in[1] = KVM_MAGIC_PAGE;
 
-       kvm_hypercall(in, out, HC_VENDOR_KVM | KVM_HC_PPC_MAP_MAGIC_PAGE);
+       kvm_hypercall(in, out, KVM_HCALL_TOKEN(KVM_HC_PPC_MAP_MAGIC_PAGE));
 
        *features = out[0];
 }
index 19e4288d84865e7b97f1a22a6fe099037b46aeef..78b8766fd79e4605f96a103c6562ff62caa37c5e 100644 (file)
@@ -43,6 +43,7 @@
 #include <asm/dcr.h>
 #include <asm/ftrace.h>
 #include <asm/switch_to.h>
+#include <asm/epapr_hcalls.h>
 
 #ifdef CONFIG_PPC32
 extern void transfer_to_handler(void);
@@ -191,3 +192,7 @@ EXPORT_SYMBOL(__arch_hweight64);
 #ifdef CONFIG_PPC_BOOK3S_64
 EXPORT_SYMBOL_GPL(mmu_psize_defs);
 #endif
+
+#ifdef CONFIG_EPAPR_PARAVIRT
+EXPORT_SYMBOL(epapr_hypercall_start);
+#endif
index 50e7dbc7356cd0ed574f3ac9fa61ea509fb26439..3d7fd21c65f92eeeb26ce19fc9d7fe07d0cdb36c 100644 (file)
@@ -83,6 +83,7 @@ int kvmppc_core_vcpu_setup(struct kvm_vcpu *vcpu)
                vcpu_44x->shadow_refs[i].gtlb_index = -1;
 
        vcpu->arch.cpu_type = KVM_CPU_440;
+       vcpu->arch.pvr = mfspr(SPRN_PVR);
 
        return 0;
 }
index c8c61578fdfc6e8420497854971d8da7b6d74598..35ec0a8547dabb86977f0e24657f8ba710cd4f69 100644 (file)
 #include "booke.h"
 #include "44x_tlb.h"
 
+#define XOP_MFDCRX  259
 #define XOP_MFDCR   323
+#define XOP_MTDCRX  387
 #define XOP_MTDCR   451
 #define XOP_TLBSX   914
 #define XOP_ICCCI   966
 #define XOP_TLBWE   978
 
+static int emulate_mtdcr(struct kvm_vcpu *vcpu, int rs, int dcrn)
+{
+       /* emulate some access in kernel */
+       switch (dcrn) {
+       case DCRN_CPR0_CONFIG_ADDR:
+               vcpu->arch.cpr0_cfgaddr = kvmppc_get_gpr(vcpu, rs);
+               return EMULATE_DONE;
+       default:
+               vcpu->run->dcr.dcrn = dcrn;
+               vcpu->run->dcr.data = kvmppc_get_gpr(vcpu, rs);
+               vcpu->run->dcr.is_write = 1;
+               vcpu->arch.dcr_is_write = 1;
+               vcpu->arch.dcr_needed = 1;
+               kvmppc_account_exit(vcpu, DCR_EXITS);
+               return EMULATE_DO_DCR;
+       }
+}
+
+static int emulate_mfdcr(struct kvm_vcpu *vcpu, int rt, int dcrn)
+{
+       /* The guest may access CPR0 registers to determine the timebase
+        * frequency, and it must know the real host frequency because it
+        * can directly access the timebase registers.
+        *
+        * It would be possible to emulate those accesses in userspace,
+        * but userspace can really only figure out the end frequency.
+        * We could decompose that into the factors that compute it, but
+        * that's tricky math, and it's easier to just report the real
+        * CPR0 values.
+        */
+       switch (dcrn) {
+       case DCRN_CPR0_CONFIG_ADDR:
+               kvmppc_set_gpr(vcpu, rt, vcpu->arch.cpr0_cfgaddr);
+               break;
+       case DCRN_CPR0_CONFIG_DATA:
+               local_irq_disable();
+               mtdcr(DCRN_CPR0_CONFIG_ADDR,
+                         vcpu->arch.cpr0_cfgaddr);
+               kvmppc_set_gpr(vcpu, rt,
+                              mfdcr(DCRN_CPR0_CONFIG_DATA));
+               local_irq_enable();
+               break;
+       default:
+               vcpu->run->dcr.dcrn = dcrn;
+               vcpu->run->dcr.data =  0;
+               vcpu->run->dcr.is_write = 0;
+               vcpu->arch.dcr_is_write = 0;
+               vcpu->arch.io_gpr = rt;
+               vcpu->arch.dcr_needed = 1;
+               kvmppc_account_exit(vcpu, DCR_EXITS);
+               return EMULATE_DO_DCR;
+       }
+
+       return EMULATE_DONE;
+}
+
 int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
                            unsigned int inst, int *advance)
 {
@@ -50,55 +108,21 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
                switch (get_xop(inst)) {
 
                case XOP_MFDCR:
-                       /* The guest may access CPR0 registers to determine the timebase
-                        * frequency, and it must know the real host frequency because it
-                        * can directly access the timebase registers.
-                        *
-                        * It would be possible to emulate those accesses in userspace,
-                        * but userspace can really only figure out the end frequency.
-                        * We could decompose that into the factors that compute it, but
-                        * that's tricky math, and it's easier to just report the real
-                        * CPR0 values.
-                        */
-                       switch (dcrn) {
-                       case DCRN_CPR0_CONFIG_ADDR:
-                               kvmppc_set_gpr(vcpu, rt, vcpu->arch.cpr0_cfgaddr);
-                               break;
-                       case DCRN_CPR0_CONFIG_DATA:
-                               local_irq_disable();
-                               mtdcr(DCRN_CPR0_CONFIG_ADDR,
-                                         vcpu->arch.cpr0_cfgaddr);
-                               kvmppc_set_gpr(vcpu, rt,
-                                              mfdcr(DCRN_CPR0_CONFIG_DATA));
-                               local_irq_enable();
-                               break;
-                       default:
-                               run->dcr.dcrn = dcrn;
-                               run->dcr.data =  0;
-                               run->dcr.is_write = 0;
-                               vcpu->arch.io_gpr = rt;
-                               vcpu->arch.dcr_needed = 1;
-                               kvmppc_account_exit(vcpu, DCR_EXITS);
-                               emulated = EMULATE_DO_DCR;
-                       }
+                       emulated = emulate_mfdcr(vcpu, rt, dcrn);
+                       break;
 
+               case XOP_MFDCRX:
+                       emulated = emulate_mfdcr(vcpu, rt,
+                                       kvmppc_get_gpr(vcpu, ra));
                        break;
 
                case XOP_MTDCR:
-                       /* emulate some access in kernel */
-                       switch (dcrn) {
-                       case DCRN_CPR0_CONFIG_ADDR:
-                               vcpu->arch.cpr0_cfgaddr = kvmppc_get_gpr(vcpu, rs);
-                               break;
-                       default:
-                               run->dcr.dcrn = dcrn;
-                               run->dcr.data = kvmppc_get_gpr(vcpu, rs);
-                               run->dcr.is_write = 1;
-                               vcpu->arch.dcr_needed = 1;
-                               kvmppc_account_exit(vcpu, DCR_EXITS);
-                               emulated = EMULATE_DO_DCR;
-                       }
+                       emulated = emulate_mtdcr(vcpu, rs, dcrn);
+                       break;
 
+               case XOP_MTDCRX:
+                       emulated = emulate_mtdcr(vcpu, rs,
+                                       kvmppc_get_gpr(vcpu, ra));
                        break;
 
                case XOP_TLBWE:
index f4dacb9c57fac1a275291aedf1357c3070b6f750..71f0cd9edf335a4751895c16f6b3069e5f872950 100644 (file)
@@ -36,6 +36,7 @@ config KVM_BOOK3S_64_HANDLER
 config KVM_BOOK3S_PR
        bool
        select KVM_MMIO
+       select MMU_NOTIFIER
 
 config KVM_BOOK3S_32
        tristate "KVM support for PowerPC book3s_32 processors"
@@ -123,6 +124,7 @@ config KVM_E500V2
        depends on EXPERIMENTAL && E500 && !PPC_E500MC
        select KVM
        select KVM_MMIO
+       select MMU_NOTIFIER
        ---help---
          Support running unmodified E500 guest kernels in virtual machines on
          E500v2 host processors.
@@ -138,6 +140,7 @@ config KVM_E500MC
        select KVM
        select KVM_MMIO
        select KVM_BOOKE_HV
+       select MMU_NOTIFIER
        ---help---
          Support running unmodified E500MC/E5500 (32-bit) guest kernels in
          virtual machines on E500MC/E5500 host processors.
index 3f2a8360c857f1aae94a13631b2eb099a96795a0..a4b64528524098633bcec777404c2fcbf5ac2fe6 100644 (file)
@@ -411,6 +411,15 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
        return 0;
 }
 
+int kvmppc_subarch_vcpu_init(struct kvm_vcpu *vcpu)
+{
+       return 0;
+}
+
+void kvmppc_subarch_vcpu_uninit(struct kvm_vcpu *vcpu)
+{
+}
+
 int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
 {
        int i;
@@ -476,6 +485,122 @@ int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
        return -ENOTSUPP;
 }
 
+int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
+{
+       int r;
+       union kvmppc_one_reg val;
+       int size;
+       long int i;
+
+       size = one_reg_size(reg->id);
+       if (size > sizeof(val))
+               return -EINVAL;
+
+       r = kvmppc_get_one_reg(vcpu, reg->id, &val);
+
+       if (r == -EINVAL) {
+               r = 0;
+               switch (reg->id) {
+               case KVM_REG_PPC_DAR:
+                       val = get_reg_val(reg->id, vcpu->arch.shared->dar);
+                       break;
+               case KVM_REG_PPC_DSISR:
+                       val = get_reg_val(reg->id, vcpu->arch.shared->dsisr);
+                       break;
+               case KVM_REG_PPC_FPR0 ... KVM_REG_PPC_FPR31:
+                       i = reg->id - KVM_REG_PPC_FPR0;
+                       val = get_reg_val(reg->id, vcpu->arch.fpr[i]);
+                       break;
+               case KVM_REG_PPC_FPSCR:
+                       val = get_reg_val(reg->id, vcpu->arch.fpscr);
+                       break;
+#ifdef CONFIG_ALTIVEC
+               case KVM_REG_PPC_VR0 ... KVM_REG_PPC_VR31:
+                       if (!cpu_has_feature(CPU_FTR_ALTIVEC)) {
+                               r = -ENXIO;
+                               break;
+                       }
+                       val.vval = vcpu->arch.vr[reg->id - KVM_REG_PPC_VR0];
+                       break;
+               case KVM_REG_PPC_VSCR:
+                       if (!cpu_has_feature(CPU_FTR_ALTIVEC)) {
+                               r = -ENXIO;
+                               break;
+                       }
+                       val = get_reg_val(reg->id, vcpu->arch.vscr.u[3]);
+                       break;
+#endif /* CONFIG_ALTIVEC */
+               default:
+                       r = -EINVAL;
+                       break;
+               }
+       }
+       if (r)
+               return r;
+
+       if (copy_to_user((char __user *)(unsigned long)reg->addr, &val, size))
+               r = -EFAULT;
+
+       return r;
+}
+
+int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
+{
+       int r;
+       union kvmppc_one_reg val;
+       int size;
+       long int i;
+
+       size = one_reg_size(reg->id);
+       if (size > sizeof(val))
+               return -EINVAL;
+
+       if (copy_from_user(&val, (char __user *)(unsigned long)reg->addr, size))
+               return -EFAULT;
+
+       r = kvmppc_set_one_reg(vcpu, reg->id, &val);
+
+       if (r == -EINVAL) {
+               r = 0;
+               switch (reg->id) {
+               case KVM_REG_PPC_DAR:
+                       vcpu->arch.shared->dar = set_reg_val(reg->id, val);
+                       break;
+               case KVM_REG_PPC_DSISR:
+                       vcpu->arch.shared->dsisr = set_reg_val(reg->id, val);
+                       break;
+               case KVM_REG_PPC_FPR0 ... KVM_REG_PPC_FPR31:
+                       i = reg->id - KVM_REG_PPC_FPR0;
+                       vcpu->arch.fpr[i] = set_reg_val(reg->id, val);
+                       break;
+               case KVM_REG_PPC_FPSCR:
+                       vcpu->arch.fpscr = set_reg_val(reg->id, val);
+                       break;
+#ifdef CONFIG_ALTIVEC
+               case KVM_REG_PPC_VR0 ... KVM_REG_PPC_VR31:
+                       if (!cpu_has_feature(CPU_FTR_ALTIVEC)) {
+                               r = -ENXIO;
+                               break;
+                       }
+                       vcpu->arch.vr[reg->id - KVM_REG_PPC_VR0] = val.vval;
+                       break;
+               case KVM_REG_PPC_VSCR:
+                       if (!cpu_has_feature(CPU_FTR_ALTIVEC)) {
+                               r = -ENXIO;
+                               break;
+                       }
+                       vcpu->arch.vscr.u[3] = set_reg_val(reg->id, val);
+                       break;
+#endif /* CONFIG_ALTIVEC */
+               default:
+                       r = -EINVAL;
+                       break;
+               }
+       }
+
+       return r;
+}
+
 int kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu,
                                   struct kvm_translation *tr)
 {
index b0f625a33345a6e7cf690d21b041507adae5f61f..d1107a9b5d130d08dc8f4e20ec6e8f697a3c285e 100644 (file)
@@ -254,6 +254,7 @@ next_pteg:
 
        kvmppc_mmu_hpte_cache_map(vcpu, pte);
 
+       kvm_release_pfn_clean(hpaddr >> PAGE_SHIFT);
 out:
        return r;
 }
index 4d72f9ebc554bddf331ac9d9201b10cd0d3e484f..d0205a545a81913d1a0698884ee9d6a69ae75075 100644 (file)
@@ -171,6 +171,7 @@ map_again:
 
                kvmppc_mmu_hpte_cache_map(vcpu, pte);
        }
+       kvm_release_pfn_clean(hpaddr >> PAGE_SHIFT);
 
 out:
        return r;
index d95d11322a159912230832371eefbe74c61c8e62..7a4aae99ac5b11bce09aa03b8bd3d8562094e0bb 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/slab.h>
 #include <linux/hugetlb.h>
 #include <linux/vmalloc.h>
+#include <linux/srcu.h>
 
 #include <asm/tlbflush.h>
 #include <asm/kvm_ppc.h>
@@ -260,7 +261,7 @@ static void kvmppc_mmu_book3s_64_hv_reset_msr(struct kvm_vcpu *vcpu)
 
 /*
  * This is called to get a reference to a guest page if there isn't
- * one already in the kvm->arch.slot_phys[][] arrays.
+ * one already in the memslot->arch.slot_phys[] array.
  */
 static long kvmppc_get_guest_page(struct kvm *kvm, unsigned long gfn,
                                  struct kvm_memory_slot *memslot,
@@ -275,7 +276,7 @@ static long kvmppc_get_guest_page(struct kvm *kvm, unsigned long gfn,
        struct vm_area_struct *vma;
        unsigned long pfn, i, npages;
 
-       physp = kvm->arch.slot_phys[memslot->id];
+       physp = memslot->arch.slot_phys;
        if (!physp)
                return -EINVAL;
        if (physp[gfn - memslot->base_gfn])
@@ -570,7 +571,7 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
        struct kvm *kvm = vcpu->kvm;
        unsigned long *hptep, hpte[3], r;
        unsigned long mmu_seq, psize, pte_size;
-       unsigned long gfn, hva, pfn;
+       unsigned long gpa, gfn, hva, pfn;
        struct kvm_memory_slot *memslot;
        unsigned long *rmap;
        struct revmap_entry *rev;
@@ -608,15 +609,14 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
 
        /* Translate the logical address and get the page */
        psize = hpte_page_size(hpte[0], r);
-       gfn = hpte_rpn(r, psize);
+       gpa = (r & HPTE_R_RPN & ~(psize - 1)) | (ea & (psize - 1));
+       gfn = gpa >> PAGE_SHIFT;
        memslot = gfn_to_memslot(kvm, gfn);
 
        /* No memslot means it's an emulated MMIO region */
-       if (!memslot || (memslot->flags & KVM_MEMSLOT_INVALID)) {
-               unsigned long gpa = (gfn << PAGE_SHIFT) | (ea & (psize - 1));
+       if (!memslot || (memslot->flags & KVM_MEMSLOT_INVALID))
                return kvmppc_hv_emulate_mmio(run, vcpu, gpa, ea,
                                              dsisr & DSISR_ISSTORE);
-       }
 
        if (!kvm->arch.using_mmu_notifiers)
                return -EFAULT;         /* should never get here */
@@ -850,7 +850,8 @@ static int kvm_unmap_rmapp(struct kvm *kvm, unsigned long *rmapp,
                psize = hpte_page_size(hptep[0], ptel);
                if ((hptep[0] & HPTE_V_VALID) &&
                    hpte_rpn(ptel, psize) == gfn) {
-                       hptep[0] |= HPTE_V_ABSENT;
+                       if (kvm->arch.using_mmu_notifiers)
+                               hptep[0] |= HPTE_V_ABSENT;
                        kvmppc_invalidate_hpte(kvm, hptep, i);
                        /* Harvest R and C */
                        rcbits = hptep[1] & (HPTE_R_R | HPTE_R_C);
@@ -877,6 +878,28 @@ int kvm_unmap_hva_range(struct kvm *kvm, unsigned long start, unsigned long end)
        return 0;
 }
 
+void kvmppc_core_flush_memslot(struct kvm *kvm, struct kvm_memory_slot *memslot)
+{
+       unsigned long *rmapp;
+       unsigned long gfn;
+       unsigned long n;
+
+       rmapp = memslot->arch.rmap;
+       gfn = memslot->base_gfn;
+       for (n = memslot->npages; n; --n) {
+               /*
+                * Testing the present bit without locking is OK because
+                * the memslot has been marked invalid already, and hence
+                * no new HPTEs referencing this page can be created,
+                * thus the present bit can't go from 0 to 1.
+                */
+               if (*rmapp & KVMPPC_RMAP_PRESENT)
+                       kvm_unmap_rmapp(kvm, rmapp, gfn);
+               ++rmapp;
+               ++gfn;
+       }
+}
+
 static int kvm_age_rmapp(struct kvm *kvm, unsigned long *rmapp,
                         unsigned long gfn)
 {
@@ -1030,16 +1053,16 @@ static int kvm_test_clear_dirty(struct kvm *kvm, unsigned long *rmapp)
        return ret;
 }
 
-long kvmppc_hv_get_dirty_log(struct kvm *kvm, struct kvm_memory_slot *memslot)
+long kvmppc_hv_get_dirty_log(struct kvm *kvm, struct kvm_memory_slot *memslot,
+                            unsigned long *map)
 {
        unsigned long i;
-       unsigned long *rmapp, *map;
+       unsigned long *rmapp;
 
        preempt_disable();
        rmapp = memslot->arch.rmap;
-       map = memslot->dirty_bitmap;
        for (i = 0; i < memslot->npages; ++i) {
-               if (kvm_test_clear_dirty(kvm, rmapp))
+               if (kvm_test_clear_dirty(kvm, rmapp) && map)
                        __set_bit_le(i, map);
                ++rmapp;
        }
@@ -1057,20 +1080,22 @@ void *kvmppc_pin_guest_page(struct kvm *kvm, unsigned long gpa,
        unsigned long hva, psize, offset;
        unsigned long pa;
        unsigned long *physp;
+       int srcu_idx;
 
+       srcu_idx = srcu_read_lock(&kvm->srcu);
        memslot = gfn_to_memslot(kvm, gfn);
        if (!memslot || (memslot->flags & KVM_MEMSLOT_INVALID))
-               return NULL;
+               goto err;
        if (!kvm->arch.using_mmu_notifiers) {
-               physp = kvm->arch.slot_phys[memslot->id];
+               physp = memslot->arch.slot_phys;
                if (!physp)
-                       return NULL;
+                       goto err;
                physp += gfn - memslot->base_gfn;
                pa = *physp;
                if (!pa) {
                        if (kvmppc_get_guest_page(kvm, gfn, memslot,
                                                  PAGE_SIZE) < 0)
-                               return NULL;
+                               goto err;
                        pa = *physp;
                }
                page = pfn_to_page(pa >> PAGE_SHIFT);
@@ -1079,9 +1104,11 @@ void *kvmppc_pin_guest_page(struct kvm *kvm, unsigned long gpa,
                hva = gfn_to_hva_memslot(memslot, gfn);
                npages = get_user_pages_fast(hva, 1, 1, pages);
                if (npages < 1)
-                       return NULL;
+                       goto err;
                page = pages[0];
        }
+       srcu_read_unlock(&kvm->srcu, srcu_idx);
+
        psize = PAGE_SIZE;
        if (PageHuge(page)) {
                page = compound_head(page);
@@ -1091,6 +1118,10 @@ void *kvmppc_pin_guest_page(struct kvm *kvm, unsigned long gpa,
        if (nb_ret)
                *nb_ret = psize - offset;
        return page_address(page) + offset;
+
+ err:
+       srcu_read_unlock(&kvm->srcu, srcu_idx);
+       return NULL;
 }
 
 void kvmppc_unpin_guest_page(struct kvm *kvm, void *va)
index 721d4603a23587bf692c887a7c10c9aca73c2ccb..cd8025db3017ec52a95f61e6c6ef97f7df8ea4ce 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/cpumask.h>
 #include <linux/spinlock.h>
 #include <linux/page-flags.h>
+#include <linux/srcu.h>
 
 #include <asm/reg.h>
 #include <asm/cputable.h>
@@ -142,6 +143,22 @@ static void init_vpa(struct kvm_vcpu *vcpu, struct lppaca *vpa)
        vpa->yield_count = 1;
 }
 
+static int set_vpa(struct kvm_vcpu *vcpu, struct kvmppc_vpa *v,
+                  unsigned long addr, unsigned long len)
+{
+       /* check address is cacheline aligned */
+       if (addr & (L1_CACHE_BYTES - 1))
+               return -EINVAL;
+       spin_lock(&vcpu->arch.vpa_update_lock);
+       if (v->next_gpa != addr || v->len != len) {
+               v->next_gpa = addr;
+               v->len = addr ? len : 0;
+               v->update_pending = 1;
+       }
+       spin_unlock(&vcpu->arch.vpa_update_lock);
+       return 0;
+}
+
 /* Length for a per-processor buffer is passed in at offset 4 in the buffer */
 struct reg_vpa {
        u32 dummy;
@@ -320,7 +337,8 @@ static void kvmppc_update_vpas(struct kvm_vcpu *vcpu)
        spin_lock(&vcpu->arch.vpa_update_lock);
        if (vcpu->arch.vpa.update_pending) {
                kvmppc_update_vpa(vcpu, &vcpu->arch.vpa);
-               init_vpa(vcpu, vcpu->arch.vpa.pinned_addr);
+               if (vcpu->arch.vpa.pinned_addr)
+                       init_vpa(vcpu, vcpu->arch.vpa.pinned_addr);
        }
        if (vcpu->arch.dtl.update_pending) {
                kvmppc_update_vpa(vcpu, &vcpu->arch.dtl);
@@ -366,13 +384,16 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu)
        unsigned long req = kvmppc_get_gpr(vcpu, 3);
        unsigned long target, ret = H_SUCCESS;
        struct kvm_vcpu *tvcpu;
+       int idx;
 
        switch (req) {
        case H_ENTER:
+               idx = srcu_read_lock(&vcpu->kvm->srcu);
                ret = kvmppc_virtmode_h_enter(vcpu, kvmppc_get_gpr(vcpu, 4),
                                              kvmppc_get_gpr(vcpu, 5),
                                              kvmppc_get_gpr(vcpu, 6),
                                              kvmppc_get_gpr(vcpu, 7));
+               srcu_read_unlock(&vcpu->kvm->srcu, idx);
                break;
        case H_CEDE:
                break;
@@ -411,6 +432,7 @@ static int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
                              struct task_struct *tsk)
 {
        int r = RESUME_HOST;
+       int srcu_idx;
 
        vcpu->stat.sum_exits++;
 
@@ -470,12 +492,16 @@ static int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
         * have been handled already.
         */
        case BOOK3S_INTERRUPT_H_DATA_STORAGE:
+               srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
                r = kvmppc_book3s_hv_page_fault(run, vcpu,
                                vcpu->arch.fault_dar, vcpu->arch.fault_dsisr);
+               srcu_read_unlock(&vcpu->kvm->srcu, srcu_idx);
                break;
        case BOOK3S_INTERRUPT_H_INST_STORAGE:
+               srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
                r = kvmppc_book3s_hv_page_fault(run, vcpu,
                                kvmppc_get_pc(vcpu), 0);
+               srcu_read_unlock(&vcpu->kvm->srcu, srcu_idx);
                break;
        /*
         * This occurs if the guest executes an illegal instruction.
@@ -535,36 +561,175 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
        return 0;
 }
 
-int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
+int kvmppc_get_one_reg(struct kvm_vcpu *vcpu, u64 id, union kvmppc_one_reg *val)
 {
-       int r = -EINVAL;
+       int r = 0;
+       long int i;
 
-       switch (reg->id) {
+       switch (id) {
        case KVM_REG_PPC_HIOR:
-               r = put_user(0, (u64 __user *)reg->addr);
+               *val = get_reg_val(id, 0);
+               break;
+       case KVM_REG_PPC_DABR:
+               *val = get_reg_val(id, vcpu->arch.dabr);
+               break;
+       case KVM_REG_PPC_DSCR:
+               *val = get_reg_val(id, vcpu->arch.dscr);
+               break;
+       case KVM_REG_PPC_PURR:
+               *val = get_reg_val(id, vcpu->arch.purr);
+               break;
+       case KVM_REG_PPC_SPURR:
+               *val = get_reg_val(id, vcpu->arch.spurr);
+               break;
+       case KVM_REG_PPC_AMR:
+               *val = get_reg_val(id, vcpu->arch.amr);
+               break;
+       case KVM_REG_PPC_UAMOR:
+               *val = get_reg_val(id, vcpu->arch.uamor);
+               break;
+       case KVM_REG_PPC_MMCR0 ... KVM_REG_PPC_MMCRA:
+               i = id - KVM_REG_PPC_MMCR0;
+               *val = get_reg_val(id, vcpu->arch.mmcr[i]);
+               break;
+       case KVM_REG_PPC_PMC1 ... KVM_REG_PPC_PMC8:
+               i = id - KVM_REG_PPC_PMC1;
+               *val = get_reg_val(id, vcpu->arch.pmc[i]);
+               break;
+#ifdef CONFIG_VSX
+       case KVM_REG_PPC_FPR0 ... KVM_REG_PPC_FPR31:
+               if (cpu_has_feature(CPU_FTR_VSX)) {
+                       /* VSX => FP reg i is stored in arch.vsr[2*i] */
+                       long int i = id - KVM_REG_PPC_FPR0;
+                       *val = get_reg_val(id, vcpu->arch.vsr[2 * i]);
+               } else {
+                       /* let generic code handle it */
+                       r = -EINVAL;
+               }
+               break;
+       case KVM_REG_PPC_VSR0 ... KVM_REG_PPC_VSR31:
+               if (cpu_has_feature(CPU_FTR_VSX)) {
+                       long int i = id - KVM_REG_PPC_VSR0;
+                       val->vsxval[0] = vcpu->arch.vsr[2 * i];
+                       val->vsxval[1] = vcpu->arch.vsr[2 * i + 1];
+               } else {
+                       r = -ENXIO;
+               }
+               break;
+#endif /* CONFIG_VSX */
+       case KVM_REG_PPC_VPA_ADDR:
+               spin_lock(&vcpu->arch.vpa_update_lock);
+               *val = get_reg_val(id, vcpu->arch.vpa.next_gpa);
+               spin_unlock(&vcpu->arch.vpa_update_lock);
+               break;
+       case KVM_REG_PPC_VPA_SLB:
+               spin_lock(&vcpu->arch.vpa_update_lock);
+               val->vpaval.addr = vcpu->arch.slb_shadow.next_gpa;
+               val->vpaval.length = vcpu->arch.slb_shadow.len;
+               spin_unlock(&vcpu->arch.vpa_update_lock);
+               break;
+       case KVM_REG_PPC_VPA_DTL:
+               spin_lock(&vcpu->arch.vpa_update_lock);
+               val->vpaval.addr = vcpu->arch.dtl.next_gpa;
+               val->vpaval.length = vcpu->arch.dtl.len;
+               spin_unlock(&vcpu->arch.vpa_update_lock);
                break;
        default:
+               r = -EINVAL;
                break;
        }
 
        return r;
 }
 
-int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
+int kvmppc_set_one_reg(struct kvm_vcpu *vcpu, u64 id, union kvmppc_one_reg *val)
 {
-       int r = -EINVAL;
+       int r = 0;
+       long int i;
+       unsigned long addr, len;
 
-       switch (reg->id) {
+       switch (id) {
        case KVM_REG_PPC_HIOR:
-       {
-               u64 hior;
                /* Only allow this to be set to zero */
-               r = get_user(hior, (u64 __user *)reg->addr);
-               if (!r && (hior != 0))
+               if (set_reg_val(id, *val))
                        r = -EINVAL;
                break;
-       }
+       case KVM_REG_PPC_DABR:
+               vcpu->arch.dabr = set_reg_val(id, *val);
+               break;
+       case KVM_REG_PPC_DSCR:
+               vcpu->arch.dscr = set_reg_val(id, *val);
+               break;
+       case KVM_REG_PPC_PURR:
+               vcpu->arch.purr = set_reg_val(id, *val);
+               break;
+       case KVM_REG_PPC_SPURR:
+               vcpu->arch.spurr = set_reg_val(id, *val);
+               break;
+       case KVM_REG_PPC_AMR:
+               vcpu->arch.amr = set_reg_val(id, *val);
+               break;
+       case KVM_REG_PPC_UAMOR:
+               vcpu->arch.uamor = set_reg_val(id, *val);
+               break;
+       case KVM_REG_PPC_MMCR0 ... KVM_REG_PPC_MMCRA:
+               i = id - KVM_REG_PPC_MMCR0;
+               vcpu->arch.mmcr[i] = set_reg_val(id, *val);
+               break;
+       case KVM_REG_PPC_PMC1 ... KVM_REG_PPC_PMC8:
+               i = id - KVM_REG_PPC_PMC1;
+               vcpu->arch.pmc[i] = set_reg_val(id, *val);
+               break;
+#ifdef CONFIG_VSX
+       case KVM_REG_PPC_FPR0 ... KVM_REG_PPC_FPR31:
+               if (cpu_has_feature(CPU_FTR_VSX)) {
+                       /* VSX => FP reg i is stored in arch.vsr[2*i] */
+                       long int i = id - KVM_REG_PPC_FPR0;
+                       vcpu->arch.vsr[2 * i] = set_reg_val(id, *val);
+               } else {
+                       /* let generic code handle it */
+                       r = -EINVAL;
+               }
+               break;
+       case KVM_REG_PPC_VSR0 ... KVM_REG_PPC_VSR31:
+               if (cpu_has_feature(CPU_FTR_VSX)) {
+                       long int i = id - KVM_REG_PPC_VSR0;
+                       vcpu->arch.vsr[2 * i] = val->vsxval[0];
+                       vcpu->arch.vsr[2 * i + 1] = val->vsxval[1];
+               } else {
+                       r = -ENXIO;
+               }
+               break;
+#endif /* CONFIG_VSX */
+       case KVM_REG_PPC_VPA_ADDR:
+               addr = set_reg_val(id, *val);
+               r = -EINVAL;
+               if (!addr && (vcpu->arch.slb_shadow.next_gpa ||
+                             vcpu->arch.dtl.next_gpa))
+                       break;
+               r = set_vpa(vcpu, &vcpu->arch.vpa, addr, sizeof(struct lppaca));
+               break;
+       case KVM_REG_PPC_VPA_SLB:
+               addr = val->vpaval.addr;
+               len = val->vpaval.length;
+               r = -EINVAL;
+               if (addr && !vcpu->arch.vpa.next_gpa)
+                       break;
+               r = set_vpa(vcpu, &vcpu->arch.slb_shadow, addr, len);
+               break;
+       case KVM_REG_PPC_VPA_DTL:
+               addr = val->vpaval.addr;
+               len = val->vpaval.length;
+               r = -EINVAL;
+               if (len < sizeof(struct dtl_entry))
+                       break;
+               if (addr && !vcpu->arch.vpa.next_gpa)
+                       break;
+               len -= len % sizeof(struct dtl_entry);
+               r = set_vpa(vcpu, &vcpu->arch.dtl, addr, len);
+               break;
        default:
+               r = -EINVAL;
                break;
        }
 
@@ -697,17 +862,11 @@ extern void xics_wake_cpu(int cpu);
 static void kvmppc_remove_runnable(struct kvmppc_vcore *vc,
                                   struct kvm_vcpu *vcpu)
 {
-       struct kvm_vcpu *v;
-
        if (vcpu->arch.state != KVMPPC_VCPU_RUNNABLE)
                return;
        vcpu->arch.state = KVMPPC_VCPU_BUSY_IN_HOST;
        --vc->n_runnable;
        ++vc->n_busy;
-       /* decrement the physical thread id of each following vcpu */
-       v = vcpu;
-       list_for_each_entry_continue(v, &vc->runnable_threads, arch.run_list)
-               --v->arch.ptid;
        list_del(&vcpu->arch.run_list);
 }
 
@@ -820,6 +979,7 @@ static int kvmppc_run_core(struct kvmppc_vcore *vc)
        long ret;
        u64 now;
        int ptid, i, need_vpa_update;
+       int srcu_idx;
 
        /* don't start if any threads have a signal pending */
        need_vpa_update = 0;
@@ -898,6 +1058,9 @@ static int kvmppc_run_core(struct kvmppc_vcore *vc)
        spin_unlock(&vc->lock);
 
        kvm_guest_enter();
+
+       srcu_idx = srcu_read_lock(&vcpu0->kvm->srcu);
+
        __kvmppc_vcore_entry(NULL, vcpu0);
        for (i = 0; i < threads_per_core; ++i)
                kvmppc_release_hwthread(vc->pcpu + i);
@@ -913,6 +1076,8 @@ static int kvmppc_run_core(struct kvmppc_vcore *vc)
        vc->vcore_state = VCORE_EXITING;
        spin_unlock(&vc->lock);
 
+       srcu_read_unlock(&vcpu0->kvm->srcu, srcu_idx);
+
        /* make sure updates to secondary vcpu structs are visible now */
        smp_mb();
        kvm_guest_exit();
@@ -1273,7 +1438,7 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, struct kvm_dirty_log *log)
        n = kvm_dirty_bitmap_bytes(memslot);
        memset(memslot->dirty_bitmap, 0, n);
 
-       r = kvmppc_hv_get_dirty_log(kvm, memslot);
+       r = kvmppc_hv_get_dirty_log(kvm, memslot, memslot->dirty_bitmap);
        if (r)
                goto out;
 
@@ -1299,53 +1464,86 @@ static unsigned long slb_pgsize_encoding(unsigned long psize)
        return senc;
 }
 
-int kvmppc_core_prepare_memory_region(struct kvm *kvm,
-                               struct kvm_userspace_memory_region *mem)
+static void unpin_slot(struct kvm_memory_slot *memslot)
 {
-       unsigned long npages;
-       unsigned long *phys;
+       unsigned long *physp;
+       unsigned long j, npages, pfn;
+       struct page *page;
 
-       /* Allocate a slot_phys array */
-       phys = kvm->arch.slot_phys[mem->slot];
-       if (!kvm->arch.using_mmu_notifiers && !phys) {
-               npages = mem->memory_size >> PAGE_SHIFT;
-               phys = vzalloc(npages * sizeof(unsigned long));
-               if (!phys)
-                       return -ENOMEM;
-               kvm->arch.slot_phys[mem->slot] = phys;
-               kvm->arch.slot_npages[mem->slot] = npages;
+       physp = memslot->arch.slot_phys;
+       npages = memslot->npages;
+       if (!physp)
+               return;
+       for (j = 0; j < npages; j++) {
+               if (!(physp[j] & KVMPPC_GOT_PAGE))
+                       continue;
+               pfn = physp[j] >> PAGE_SHIFT;
+               page = pfn_to_page(pfn);
+               SetPageDirty(page);
+               put_page(page);
        }
+}
+
+void kvmppc_core_free_memslot(struct kvm_memory_slot *free,
+                             struct kvm_memory_slot *dont)
+{
+       if (!dont || free->arch.rmap != dont->arch.rmap) {
+               vfree(free->arch.rmap);
+               free->arch.rmap = NULL;
+       }
+       if (!dont || free->arch.slot_phys != dont->arch.slot_phys) {
+               unpin_slot(free);
+               vfree(free->arch.slot_phys);
+               free->arch.slot_phys = NULL;
+       }
+}
+
+int kvmppc_core_create_memslot(struct kvm_memory_slot *slot,
+                              unsigned long npages)
+{
+       slot->arch.rmap = vzalloc(npages * sizeof(*slot->arch.rmap));
+       if (!slot->arch.rmap)
+               return -ENOMEM;
+       slot->arch.slot_phys = NULL;
 
        return 0;
 }
 
-static void unpin_slot(struct kvm *kvm, int slot_id)
+int kvmppc_core_prepare_memory_region(struct kvm *kvm,
+                                     struct kvm_memory_slot *memslot,
+                                     struct kvm_userspace_memory_region *mem)
 {
-       unsigned long *physp;
-       unsigned long j, npages, pfn;
-       struct page *page;
+       unsigned long *phys;
 
-       physp = kvm->arch.slot_phys[slot_id];
-       npages = kvm->arch.slot_npages[slot_id];
-       if (physp) {
-               spin_lock(&kvm->arch.slot_phys_lock);
-               for (j = 0; j < npages; j++) {
-                       if (!(physp[j] & KVMPPC_GOT_PAGE))
-                               continue;
-                       pfn = physp[j] >> PAGE_SHIFT;
-                       page = pfn_to_page(pfn);
-                       SetPageDirty(page);
-                       put_page(page);
-               }
-               kvm->arch.slot_phys[slot_id] = NULL;
-               spin_unlock(&kvm->arch.slot_phys_lock);
-               vfree(physp);
+       /* Allocate a slot_phys array if needed */
+       phys = memslot->arch.slot_phys;
+       if (!kvm->arch.using_mmu_notifiers && !phys && memslot->npages) {
+               phys = vzalloc(memslot->npages * sizeof(unsigned long));
+               if (!phys)
+                       return -ENOMEM;
+               memslot->arch.slot_phys = phys;
        }
+
+       return 0;
 }
 
 void kvmppc_core_commit_memory_region(struct kvm *kvm,
-                               struct kvm_userspace_memory_region *mem)
+                                     struct kvm_userspace_memory_region *mem,
+                                     struct kvm_memory_slot old)
 {
+       unsigned long npages = mem->memory_size >> PAGE_SHIFT;
+       struct kvm_memory_slot *memslot;
+
+       if (npages && old.npages) {
+               /*
+                * If modifying a memslot, reset all the rmap dirty bits.
+                * If this is a new memslot, we don't need to do anything
+                * since the rmap array starts out as all zeroes,
+                * i.e. no pages are dirty.
+                */
+               memslot = id_to_memslot(kvm->memslots, mem->slot);
+               kvmppc_hv_get_dirty_log(kvm, memslot, NULL);
+       }
 }
 
 static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu)
@@ -1362,6 +1560,7 @@ static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu)
        unsigned long rmls;
        unsigned long *physp;
        unsigned long i, npages;
+       int srcu_idx;
 
        mutex_lock(&kvm->lock);
        if (kvm->arch.rma_setup_done)
@@ -1377,12 +1576,13 @@ static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu)
        }
 
        /* Look up the memslot for guest physical address 0 */
+       srcu_idx = srcu_read_lock(&kvm->srcu);
        memslot = gfn_to_memslot(kvm, 0);
 
        /* We must have some memory at 0 by now */
        err = -EINVAL;
        if (!memslot || (memslot->flags & KVM_MEMSLOT_INVALID))
-               goto out;
+               goto out_srcu;
 
        /* Look up the VMA for the start of this memory slot */
        hva = memslot->userspace_addr;
@@ -1406,14 +1606,14 @@ static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu)
                err = -EPERM;
                if (cpu_has_feature(CPU_FTR_ARCH_201)) {
                        pr_err("KVM: CPU requires an RMO\n");
-                       goto out;
+                       goto out_srcu;
                }
 
                /* We can handle 4k, 64k or 16M pages in the VRMA */
                err = -EINVAL;
                if (!(psize == 0x1000 || psize == 0x10000 ||
                      psize == 0x1000000))
-                       goto out;
+                       goto out_srcu;
 
                /* Update VRMASD field in the LPCR */
                senc = slb_pgsize_encoding(psize);
@@ -1436,7 +1636,7 @@ static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu)
                err = -EINVAL;
                if (rmls < 0) {
                        pr_err("KVM: Can't use RMA of 0x%lx bytes\n", rma_size);
-                       goto out;
+                       goto out_srcu;
                }
                atomic_inc(&ri->use_count);
                kvm->arch.rma = ri;
@@ -1465,17 +1665,24 @@ static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu)
                /* Initialize phys addrs of pages in RMO */
                npages = ri->npages;
                porder = __ilog2(npages);
-               physp = kvm->arch.slot_phys[memslot->id];
-               spin_lock(&kvm->arch.slot_phys_lock);
-               for (i = 0; i < npages; ++i)
-                       physp[i] = ((ri->base_pfn + i) << PAGE_SHIFT) + porder;
-               spin_unlock(&kvm->arch.slot_phys_lock);
+               physp = memslot->arch.slot_phys;
+               if (physp) {
+                       if (npages > memslot->npages)
+                               npages = memslot->npages;
+                       spin_lock(&kvm->arch.slot_phys_lock);
+                       for (i = 0; i < npages; ++i)
+                               physp[i] = ((ri->base_pfn + i) << PAGE_SHIFT) +
+                                       porder;
+                       spin_unlock(&kvm->arch.slot_phys_lock);
+               }
        }
 
        /* Order updates to kvm->arch.lpcr etc. vs. rma_setup_done */
        smp_wmb();
        kvm->arch.rma_setup_done = 1;
        err = 0;
+ out_srcu:
+       srcu_read_unlock(&kvm->srcu, srcu_idx);
  out:
        mutex_unlock(&kvm->lock);
        return err;
@@ -1528,12 +1735,6 @@ int kvmppc_core_init_vm(struct kvm *kvm)
 
 void kvmppc_core_destroy_vm(struct kvm *kvm)
 {
-       unsigned long i;
-
-       if (!kvm->arch.using_mmu_notifiers)
-               for (i = 0; i < KVM_MEM_SLOTS_NUM; i++)
-                       unpin_slot(kvm, i);
-
        if (kvm->arch.rma) {
                kvm_release_rma(kvm->arch.rma);
                kvm->arch.rma = NULL;
index fb4eac290fefc1c438b46a1cc5865c0b3200ce57..ec0a9e5de1005331e7372a5c76d3a153d2a4dfd5 100644 (file)
@@ -157,8 +157,8 @@ static void __init kvm_linear_init_one(ulong size, int count, int type)
        linear_info = alloc_bootmem(count * sizeof(struct kvmppc_linear_info));
        for (i = 0; i < count; ++i) {
                linear = alloc_bootmem_align(size, size);
-               pr_info("Allocated KVM %s at %p (%ld MB)\n", typestr, linear,
-                       size >> 20);
+               pr_debug("Allocated KVM %s at %p (%ld MB)\n", typestr, linear,
+                        size >> 20);
                linear_info[i].base_virt = linear;
                linear_info[i].base_pfn = __pa(linear) >> PAGE_SHIFT;
                linear_info[i].npages = npages;
index fb0e821622d4fc97465288cd57f6c12978bdc381..9955216477a4c7934284276b499184893e959251 100644 (file)
@@ -81,7 +81,7 @@ static void remove_revmap_chain(struct kvm *kvm, long pte_index,
        ptel = rev->guest_rpte |= rcbits;
        gfn = hpte_rpn(ptel, hpte_page_size(hpte_v, ptel));
        memslot = __gfn_to_memslot(kvm_memslots(kvm), gfn);
-       if (!memslot || (memslot->flags & KVM_MEMSLOT_INVALID))
+       if (!memslot)
                return;
 
        rmap = real_vmalloc_addr(&memslot->arch.rmap[gfn - memslot->base_gfn]);
@@ -183,7 +183,7 @@ long kvmppc_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
        rmap = &memslot->arch.rmap[slot_fn];
 
        if (!kvm->arch.using_mmu_notifiers) {
-               physp = kvm->arch.slot_phys[memslot->id];
+               physp = memslot->arch.slot_phys;
                if (!physp)
                        return H_PARAMETER;
                physp += slot_fn;
index 41cb0017e757a1d8ccd83360624d9f1a40189426..2c86b0d6371494d4417b3e7e8d796c25a4b21a48 100644 (file)
@@ -114,11 +114,6 @@ static void invalidate_pte(struct kvm_vcpu *vcpu, struct hpte_cache *pte)
        hlist_del_init_rcu(&pte->list_vpte);
        hlist_del_init_rcu(&pte->list_vpte_long);
 
-       if (pte->pte.may_write)
-               kvm_release_pfn_dirty(pte->pfn);
-       else
-               kvm_release_pfn_clean(pte->pfn);
-
        spin_unlock(&vcpu3s->mmu_lock);
 
        vcpu3s->hpte_cache_count--;
index 05c28f59f77f4a4bc46c196addf12747cbb97e4f..b853696b6d8e30ad63ce3ef2d3db1bc07c67c1af 100644 (file)
@@ -52,8 +52,6 @@ static int kvmppc_handle_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr,
 #define MSR_USER32 MSR_USER
 #define MSR_USER64 MSR_USER
 #define HW_PAGE_SIZE PAGE_SIZE
-#define __hard_irq_disable local_irq_disable
-#define __hard_irq_enable local_irq_enable
 #endif
 
 void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
@@ -66,7 +64,7 @@ void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
        svcpu->slb_max = to_book3s(vcpu)->slb_shadow_max;
        svcpu_put(svcpu);
 #endif
-
+       vcpu->cpu = smp_processor_id();
 #ifdef CONFIG_PPC_BOOK3S_32
        current->thread.kvm_shadow_vcpu = to_book3s(vcpu)->shadow_vcpu;
 #endif
@@ -86,8 +84,64 @@ void kvmppc_core_vcpu_put(struct kvm_vcpu *vcpu)
        kvmppc_giveup_ext(vcpu, MSR_FP);
        kvmppc_giveup_ext(vcpu, MSR_VEC);
        kvmppc_giveup_ext(vcpu, MSR_VSX);
+       vcpu->cpu = -1;
+}
+
+int kvmppc_core_check_requests(struct kvm_vcpu *vcpu)
+{
+       int r = 1; /* Indicate we want to get back into the guest */
+
+       /* We misuse TLB_FLUSH to indicate that we want to clear
+          all shadow cache entries */
+       if (kvm_check_request(KVM_REQ_TLB_FLUSH, vcpu))
+               kvmppc_mmu_pte_flush(vcpu, 0, 0);
+
+       return r;
+}
+
+/************* MMU Notifiers *************/
+
+int kvm_unmap_hva(struct kvm *kvm, unsigned long hva)
+{
+       trace_kvm_unmap_hva(hva);
+
+       /*
+        * Flush all shadow tlb entries everywhere. This is slow, but
+        * we are 100% sure that we catch the to be unmapped page
+        */
+       kvm_flush_remote_tlbs(kvm);
+
+       return 0;
+}
+
+int kvm_unmap_hva_range(struct kvm *kvm, unsigned long start, unsigned long end)
+{
+       /* kvm_unmap_hva flushes everything anyways */
+       kvm_unmap_hva(kvm, start);
+
+       return 0;
+}
+
+int kvm_age_hva(struct kvm *kvm, unsigned long hva)
+{
+       /* XXX could be more clever ;) */
+       return 0;
+}
+
+int kvm_test_age_hva(struct kvm *kvm, unsigned long hva)
+{
+       /* XXX could be more clever ;) */
+       return 0;
+}
+
+void kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte)
+{
+       /* The page will get remapped properly on its next fault */
+       kvm_unmap_hva(kvm, hva);
 }
 
+/*****************************************/
+
 static void kvmppc_recalc_shadow_msr(struct kvm_vcpu *vcpu)
 {
        ulong smsr = vcpu->arch.shared->msr;
@@ -540,18 +594,18 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
                        unsigned int exit_nr)
 {
        int r = RESUME_HOST;
+       int s;
 
        vcpu->stat.sum_exits++;
 
        run->exit_reason = KVM_EXIT_UNKNOWN;
        run->ready_for_interrupt_injection = 1;
 
-       /* We get here with MSR.EE=0, so enable it to be a nice citizen */
-       __hard_irq_enable();
+       /* We get here with MSR.EE=1 */
+
+       trace_kvm_exit(exit_nr, vcpu);
+       kvm_guest_exit();
 
-       trace_kvm_book3s_exit(exit_nr, vcpu);
-       preempt_enable();
-       kvm_resched(vcpu);
        switch (exit_nr) {
        case BOOK3S_INTERRUPT_INST_STORAGE:
        {
@@ -802,7 +856,6 @@ program_interrupt:
        }
        }
 
-       preempt_disable();
        if (!(r & RESUME_HOST)) {
                /* To avoid clobbering exit_reason, only check for signals if
                 * we aren't already exiting to userspace for some other
@@ -814,20 +867,13 @@ program_interrupt:
                 * and if we really did time things so badly, then we just exit
                 * again due to a host external interrupt.
                 */
-               __hard_irq_disable();
-               if (signal_pending(current)) {
-                       __hard_irq_enable();
-#ifdef EXIT_DEBUG
-                       printk(KERN_EMERG "KVM: Going back to host\n");
-#endif
-                       vcpu->stat.signal_exits++;
-                       run->exit_reason = KVM_EXIT_INTR;
-                       r = -EINTR;
+               local_irq_disable();
+               s = kvmppc_prepare_to_enter(vcpu);
+               if (s <= 0) {
+                       local_irq_enable();
+                       r = s;
                } else {
-                       /* In case an interrupt came in that was triggered
-                        * from userspace (like DEC), we need to check what
-                        * to inject now! */
-                       kvmppc_core_prepare_to_enter(vcpu);
+                       kvmppc_lazy_ee_enable();
                }
        }
 
@@ -899,34 +945,59 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
        return 0;
 }
 
-int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
+int kvmppc_get_one_reg(struct kvm_vcpu *vcpu, u64 id, union kvmppc_one_reg *val)
 {
-       int r = -EINVAL;
+       int r = 0;
 
-       switch (reg->id) {
+       switch (id) {
        case KVM_REG_PPC_HIOR:
-               r = copy_to_user((u64 __user *)(long)reg->addr,
-                               &to_book3s(vcpu)->hior, sizeof(u64));
+               *val = get_reg_val(id, to_book3s(vcpu)->hior);
+               break;
+#ifdef CONFIG_VSX
+       case KVM_REG_PPC_VSR0 ... KVM_REG_PPC_VSR31: {
+               long int i = id - KVM_REG_PPC_VSR0;
+
+               if (!cpu_has_feature(CPU_FTR_VSX)) {
+                       r = -ENXIO;
+                       break;
+               }
+               val->vsxval[0] = vcpu->arch.fpr[i];
+               val->vsxval[1] = vcpu->arch.vsr[i];
                break;
+       }
+#endif /* CONFIG_VSX */
        default:
+               r = -EINVAL;
                break;
        }
 
        return r;
 }
 
-int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
+int kvmppc_set_one_reg(struct kvm_vcpu *vcpu, u64 id, union kvmppc_one_reg *val)
 {
-       int r = -EINVAL;
+       int r = 0;
 
-       switch (reg->id) {
+       switch (id) {
        case KVM_REG_PPC_HIOR:
-               r = copy_from_user(&to_book3s(vcpu)->hior,
-                                  (u64 __user *)(long)reg->addr, sizeof(u64));
-               if (!r)
-                       to_book3s(vcpu)->hior_explicit = true;
+               to_book3s(vcpu)->hior = set_reg_val(id, *val);
+               to_book3s(vcpu)->hior_explicit = true;
+               break;
+#ifdef CONFIG_VSX
+       case KVM_REG_PPC_VSR0 ... KVM_REG_PPC_VSR31: {
+               long int i = id - KVM_REG_PPC_VSR0;
+
+               if (!cpu_has_feature(CPU_FTR_VSX)) {
+                       r = -ENXIO;
+                       break;
+               }
+               vcpu->arch.fpr[i] = val->vsxval[0];
+               vcpu->arch.vsr[i] = val->vsxval[1];
                break;
+       }
+#endif /* CONFIG_VSX */
        default:
+               r = -EINVAL;
                break;
        }
 
@@ -1020,8 +1091,6 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 #endif
        ulong ext_msr;
 
-       preempt_disable();
-
        /* Check if we can run the vcpu at all */
        if (!vcpu->arch.sane) {
                kvm_run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
@@ -1029,21 +1098,16 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
                goto out;
        }
 
-       kvmppc_core_prepare_to_enter(vcpu);
-
        /*
         * Interrupts could be timers for the guest which we have to inject
         * again, so let's postpone them until we're in the guest and if we
         * really did time things so badly, then we just exit again due to
         * a host external interrupt.
         */
-       __hard_irq_disable();
-
-       /* No need to go into the guest when all we do is going out */
-       if (signal_pending(current)) {
-               __hard_irq_enable();
-               kvm_run->exit_reason = KVM_EXIT_INTR;
-               ret = -EINTR;
+       local_irq_disable();
+       ret = kvmppc_prepare_to_enter(vcpu);
+       if (ret <= 0) {
+               local_irq_enable();
                goto out;
        }
 
@@ -1080,11 +1144,12 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
        if (vcpu->arch.shared->msr & MSR_FP)
                kvmppc_handle_ext(vcpu, BOOK3S_INTERRUPT_FP_UNAVAIL, MSR_FP);
 
-       kvm_guest_enter();
+       kvmppc_lazy_ee_enable();
 
        ret = __kvmppc_vcpu_run(kvm_run, vcpu);
 
-       kvm_guest_exit();
+       /* No need for kvm_guest_exit. It's done in handle_exit.
+          We also get here with interrupts enabled. */
 
        current->thread.regs->msr = ext_msr;
 
@@ -1113,7 +1178,7 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 #endif
 
 out:
-       preempt_enable();
+       vcpu->mode = OUTSIDE_GUEST_MODE;
        return ret;
 }
 
@@ -1181,14 +1246,31 @@ int kvm_vm_ioctl_get_smmu_info(struct kvm *kvm, struct kvm_ppc_smmu_info *info)
 }
 #endif /* CONFIG_PPC64 */
 
+void kvmppc_core_free_memslot(struct kvm_memory_slot *free,
+                             struct kvm_memory_slot *dont)
+{
+}
+
+int kvmppc_core_create_memslot(struct kvm_memory_slot *slot,
+                              unsigned long npages)
+{
+       return 0;
+}
+
 int kvmppc_core_prepare_memory_region(struct kvm *kvm,
+                                     struct kvm_memory_slot *memslot,
                                      struct kvm_userspace_memory_region *mem)
 {
        return 0;
 }
 
 void kvmppc_core_commit_memory_region(struct kvm *kvm,
-                               struct kvm_userspace_memory_region *mem)
+                               struct kvm_userspace_memory_region *mem,
+                               struct kvm_memory_slot old)
+{
+}
+
+void kvmppc_core_flush_memslot(struct kvm *kvm, struct kvm_memory_slot *memslot)
 {
 }
 
index 9ecf6e35cd8de0de4fe148a7527524a46256c900..b2f8258b545ae9e7a5530d2c73e204dc7b8d3db8 100644 (file)
@@ -170,20 +170,21 @@ kvmppc_handler_skip_ins:
  * Call kvmppc_handler_trampoline_enter in real mode
  *
  * On entry, r4 contains the guest shadow MSR
+ * MSR.EE has to be 0 when calling this function
  */
 _GLOBAL(kvmppc_entry_trampoline)
        mfmsr   r5
        LOAD_REG_ADDR(r7, kvmppc_handler_trampoline_enter)
        toreal(r7)
 
-       li      r9, MSR_RI
-       ori     r9, r9, MSR_EE
-       andc    r9, r5, r9      /* Clear EE and RI in MSR value */
        li      r6, MSR_IR | MSR_DR
-       ori     r6, r6, MSR_EE
-       andc    r6, r5, r6      /* Clear EE, DR and IR in MSR value */
-       MTMSR_EERI(r9)          /* Clear EE and RI in MSR */
-       mtsrr0  r7              /* before we set srr0/1 */
+       andc    r6, r5, r6      /* Clear DR and IR in MSR value */
+       /*
+        * Set EE in HOST_MSR so that it's enabled when we get into our
+        * C exit handler function
+        */
+       ori     r5, r5, MSR_EE
+       mtsrr0  r7
        mtsrr1  r6
        RFI
 
index d25a097c852b75469785578cde71daef2043c65b..3d1f35dc786281f5640ebf825a752f5ae19c2231 100644 (file)
@@ -39,6 +39,7 @@
 
 #include "timing.h"
 #include "booke.h"
+#include "trace.h"
 
 unsigned long kvmppc_booke_handlers;
 
@@ -62,6 +63,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
        { "halt_wakeup", VCPU_STAT(halt_wakeup) },
        { "doorbell", VCPU_STAT(dbell_exits) },
        { "guest doorbell", VCPU_STAT(gdbell_exits) },
+       { "remote_tlb_flush", VM_STAT(remote_tlb_flush) },
        { NULL }
 };
 
@@ -120,6 +122,16 @@ static void kvmppc_vcpu_sync_spe(struct kvm_vcpu *vcpu)
 }
 #endif
 
+static void kvmppc_vcpu_sync_fpu(struct kvm_vcpu *vcpu)
+{
+#if defined(CONFIG_PPC_FPU) && !defined(CONFIG_KVM_BOOKE_HV)
+       /* We always treat the FP bit as enabled from the host
+          perspective, so only need to adjust the shadow MSR */
+       vcpu->arch.shadow_msr &= ~MSR_FP;
+       vcpu->arch.shadow_msr |= vcpu->arch.shared->msr & MSR_FP;
+#endif
+}
+
 /*
  * Helper function for "full" MSR writes.  No need to call this if only
  * EE/CE/ME/DE/RI are changing.
@@ -136,11 +148,13 @@ void kvmppc_set_msr(struct kvm_vcpu *vcpu, u32 new_msr)
 
        kvmppc_mmu_msr_notify(vcpu, old_msr);
        kvmppc_vcpu_sync_spe(vcpu);
+       kvmppc_vcpu_sync_fpu(vcpu);
 }
 
 static void kvmppc_booke_queue_irqprio(struct kvm_vcpu *vcpu,
                                        unsigned int priority)
 {
+       trace_kvm_booke_queue_irqprio(vcpu, priority);
        set_bit(priority, &vcpu->arch.pending_exceptions);
 }
 
@@ -206,6 +220,16 @@ void kvmppc_core_dequeue_external(struct kvm_vcpu *vcpu,
        clear_bit(BOOKE_IRQPRIO_EXTERNAL_LEVEL, &vcpu->arch.pending_exceptions);
 }
 
+static void kvmppc_core_queue_watchdog(struct kvm_vcpu *vcpu)
+{
+       kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_WATCHDOG);
+}
+
+static void kvmppc_core_dequeue_watchdog(struct kvm_vcpu *vcpu)
+{
+       clear_bit(BOOKE_IRQPRIO_WATCHDOG, &vcpu->arch.pending_exceptions);
+}
+
 static void set_guest_srr(struct kvm_vcpu *vcpu, unsigned long srr0, u32 srr1)
 {
 #ifdef CONFIG_KVM_BOOKE_HV
@@ -325,6 +349,7 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,
                msr_mask = MSR_CE | MSR_ME | MSR_DE;
                int_class = INT_CLASS_NONCRIT;
                break;
+       case BOOKE_IRQPRIO_WATCHDOG:
        case BOOKE_IRQPRIO_CRITICAL:
        case BOOKE_IRQPRIO_DBELL_CRIT:
                allowed = vcpu->arch.shared->msr & MSR_CE;
@@ -404,12 +429,121 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,
        return allowed;
 }
 
+/*
+ * Return the number of jiffies until the next timeout.  If the timeout is
+ * longer than the NEXT_TIMER_MAX_DELTA, then return NEXT_TIMER_MAX_DELTA
+ * because the larger value can break the timer APIs.
+ */
+static unsigned long watchdog_next_timeout(struct kvm_vcpu *vcpu)
+{
+       u64 tb, wdt_tb, wdt_ticks = 0;
+       u64 nr_jiffies = 0;
+       u32 period = TCR_GET_WP(vcpu->arch.tcr);
+
+       wdt_tb = 1ULL << (63 - period);
+       tb = get_tb();
+       /*
+        * The watchdog timeout will hapeen when TB bit corresponding
+        * to watchdog will toggle from 0 to 1.
+        */
+       if (tb & wdt_tb)
+               wdt_ticks = wdt_tb;
+
+       wdt_ticks += wdt_tb - (tb & (wdt_tb - 1));
+
+       /* Convert timebase ticks to jiffies */
+       nr_jiffies = wdt_ticks;
+
+       if (do_div(nr_jiffies, tb_ticks_per_jiffy))
+               nr_jiffies++;
+
+       return min_t(unsigned long long, nr_jiffies, NEXT_TIMER_MAX_DELTA);
+}
+
+static void arm_next_watchdog(struct kvm_vcpu *vcpu)
+{
+       unsigned long nr_jiffies;
+       unsigned long flags;
+
+       /*
+        * If TSR_ENW and TSR_WIS are not set then no need to exit to
+        * userspace, so clear the KVM_REQ_WATCHDOG request.
+        */
+       if ((vcpu->arch.tsr & (TSR_ENW | TSR_WIS)) != (TSR_ENW | TSR_WIS))
+               clear_bit(KVM_REQ_WATCHDOG, &vcpu->requests);
+
+       spin_lock_irqsave(&vcpu->arch.wdt_lock, flags);
+       nr_jiffies = watchdog_next_timeout(vcpu);
+       /*
+        * If the number of jiffies of watchdog timer >= NEXT_TIMER_MAX_DELTA
+        * then do not run the watchdog timer as this can break timer APIs.
+        */
+       if (nr_jiffies < NEXT_TIMER_MAX_DELTA)
+               mod_timer(&vcpu->arch.wdt_timer, jiffies + nr_jiffies);
+       else
+               del_timer(&vcpu->arch.wdt_timer);
+       spin_unlock_irqrestore(&vcpu->arch.wdt_lock, flags);
+}
+
+void kvmppc_watchdog_func(unsigned long data)
+{
+       struct kvm_vcpu *vcpu = (struct kvm_vcpu *)data;
+       u32 tsr, new_tsr;
+       int final;
+
+       do {
+               new_tsr = tsr = vcpu->arch.tsr;
+               final = 0;
+
+               /* Time out event */
+               if (tsr & TSR_ENW) {
+                       if (tsr & TSR_WIS)
+                               final = 1;
+                       else
+                               new_tsr = tsr | TSR_WIS;
+               } else {
+                       new_tsr = tsr | TSR_ENW;
+               }
+       } while (cmpxchg(&vcpu->arch.tsr, tsr, new_tsr) != tsr);
+
+       if (new_tsr & TSR_WIS) {
+               smp_wmb();
+               kvm_make_request(KVM_REQ_PENDING_TIMER, vcpu);
+               kvm_vcpu_kick(vcpu);
+       }
+
+       /*
+        * If this is final watchdog expiry and some action is required
+        * then exit to userspace.
+        */
+       if (final && (vcpu->arch.tcr & TCR_WRC_MASK) &&
+           vcpu->arch.watchdog_enabled) {
+               smp_wmb();
+               kvm_make_request(KVM_REQ_WATCHDOG, vcpu);
+               kvm_vcpu_kick(vcpu);
+       }
+
+       /*
+        * Stop running the watchdog timer after final expiration to
+        * prevent the host from being flooded with timers if the
+        * guest sets a short period.
+        * Timers will resume when TSR/TCR is updated next time.
+        */
+       if (!final)
+               arm_next_watchdog(vcpu);
+}
+
 static void update_timer_ints(struct kvm_vcpu *vcpu)
 {
        if ((vcpu->arch.tcr & TCR_DIE) && (vcpu->arch.tsr & TSR_DIS))
                kvmppc_core_queue_dec(vcpu);
        else
                kvmppc_core_dequeue_dec(vcpu);
+
+       if ((vcpu->arch.tcr & TCR_WIE) && (vcpu->arch.tsr & TSR_WIS))
+               kvmppc_core_queue_watchdog(vcpu);
+       else
+               kvmppc_core_dequeue_watchdog(vcpu);
 }
 
 static void kvmppc_core_check_exceptions(struct kvm_vcpu *vcpu)
@@ -417,13 +551,6 @@ static void kvmppc_core_check_exceptions(struct kvm_vcpu *vcpu)
        unsigned long *pending = &vcpu->arch.pending_exceptions;
        unsigned int priority;
 
-       if (vcpu->requests) {
-               if (kvm_check_request(KVM_REQ_PENDING_TIMER, vcpu)) {
-                       smp_mb();
-                       update_timer_ints(vcpu);
-               }
-       }
-
        priority = __ffs(*pending);
        while (priority < BOOKE_IRQPRIO_MAX) {
                if (kvmppc_booke_irqprio_deliver(vcpu, priority))
@@ -459,37 +586,20 @@ int kvmppc_core_prepare_to_enter(struct kvm_vcpu *vcpu)
        return r;
 }
 
-/*
- * Common checks before entering the guest world.  Call with interrupts
- * disabled.
- *
- * returns !0 if a signal is pending and check_signal is true
- */
-static int kvmppc_prepare_to_enter(struct kvm_vcpu *vcpu)
+int kvmppc_core_check_requests(struct kvm_vcpu *vcpu)
 {
-       int r = 0;
-
-       WARN_ON_ONCE(!irqs_disabled());
-       while (true) {
-               if (need_resched()) {
-                       local_irq_enable();
-                       cond_resched();
-                       local_irq_disable();
-                       continue;
-               }
-
-               if (signal_pending(current)) {
-                       r = 1;
-                       break;
-               }
+       int r = 1; /* Indicate we want to get back into the guest */
 
-               if (kvmppc_core_prepare_to_enter(vcpu)) {
-                       /* interrupts got enabled in between, so we
-                          are back at square 1 */
-                       continue;
-               }
+       if (kvm_check_request(KVM_REQ_PENDING_TIMER, vcpu))
+               update_timer_ints(vcpu);
+#if defined(CONFIG_KVM_E500V2) || defined(CONFIG_KVM_E500MC)
+       if (kvm_check_request(KVM_REQ_TLB_FLUSH, vcpu))
+               kvmppc_core_flush_tlb(vcpu);
+#endif
 
-               break;
+       if (kvm_check_request(KVM_REQ_WATCHDOG, vcpu)) {
+               vcpu->run->exit_reason = KVM_EXIT_WATCHDOG;
+               r = 0;
        }
 
        return r;
@@ -497,7 +607,7 @@ static int kvmppc_prepare_to_enter(struct kvm_vcpu *vcpu)
 
 int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 {
-       int ret;
+       int ret, s;
 #ifdef CONFIG_PPC_FPU
        unsigned int fpscr;
        int fpexc_mode;
@@ -510,11 +620,13 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
        }
 
        local_irq_disable();
-       if (kvmppc_prepare_to_enter(vcpu)) {
-               kvm_run->exit_reason = KVM_EXIT_INTR;
-               ret = -EINTR;
+       s = kvmppc_prepare_to_enter(vcpu);
+       if (s <= 0) {
+               local_irq_enable();
+               ret = s;
                goto out;
        }
+       kvmppc_lazy_ee_enable();
 
        kvm_guest_enter();
 
@@ -542,6 +654,9 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 
        ret = __kvmppc_vcpu_run(kvm_run, vcpu);
 
+       /* No need for kvm_guest_exit. It's done in handle_exit.
+          We also get here with interrupts enabled. */
+
 #ifdef CONFIG_PPC_FPU
        kvmppc_save_guest_fp(vcpu);
 
@@ -557,10 +672,8 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
        current->thread.fpexc_mode = fpexc_mode;
 #endif
 
-       kvm_guest_exit();
-
 out:
-       local_irq_enable();
+       vcpu->mode = OUTSIDE_GUEST_MODE;
        return ret;
 }
 
@@ -668,6 +781,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
                        unsigned int exit_nr)
 {
        int r = RESUME_HOST;
+       int s;
 
        /* update before a new last_exit_type is rewritten */
        kvmppc_update_timing_stats(vcpu);
@@ -677,6 +791,9 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
 
        local_irq_enable();
 
+       trace_kvm_exit(exit_nr, vcpu);
+       kvm_guest_exit();
+
        run->exit_reason = KVM_EXIT_UNKNOWN;
        run->ready_for_interrupt_injection = 1;
 
@@ -971,10 +1088,12 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
         */
        if (!(r & RESUME_HOST)) {
                local_irq_disable();
-               if (kvmppc_prepare_to_enter(vcpu)) {
-                       run->exit_reason = KVM_EXIT_INTR;
-                       r = (-EINTR << 2) | RESUME_HOST | (r & RESUME_FLAG_NV);
-                       kvmppc_account_exit(vcpu, SIGNAL_EXITS);
+               s = kvmppc_prepare_to_enter(vcpu);
+               if (s <= 0) {
+                       local_irq_enable();
+                       r = (s << 2) | RESUME_HOST | (r & RESUME_FLAG_NV);
+               } else {
+                       kvmppc_lazy_ee_enable();
                }
        }
 
@@ -1011,6 +1130,21 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
        return r;
 }
 
+int kvmppc_subarch_vcpu_init(struct kvm_vcpu *vcpu)
+{
+       /* setup watchdog timer once */
+       spin_lock_init(&vcpu->arch.wdt_lock);
+       setup_timer(&vcpu->arch.wdt_timer, kvmppc_watchdog_func,
+                   (unsigned long)vcpu);
+
+       return 0;
+}
+
+void kvmppc_subarch_vcpu_uninit(struct kvm_vcpu *vcpu)
+{
+       del_timer_sync(&vcpu->arch.wdt_timer);
+}
+
 int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
 {
        int i;
@@ -1106,7 +1240,13 @@ static int set_sregs_base(struct kvm_vcpu *vcpu,
        }
 
        if (sregs->u.e.update_special & KVM_SREGS_E_UPDATE_TSR) {
+               u32 old_tsr = vcpu->arch.tsr;
+
                vcpu->arch.tsr = sregs->u.e.tsr;
+
+               if ((old_tsr ^ vcpu->arch.tsr) & (TSR_ENW | TSR_WIS))
+                       arm_next_watchdog(vcpu);
+
                update_timer_ints(vcpu);
        }
 
@@ -1221,12 +1361,56 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
 
 int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
 {
-       return -EINVAL;
+       int r = -EINVAL;
+
+       switch (reg->id) {
+       case KVM_REG_PPC_IAC1:
+       case KVM_REG_PPC_IAC2:
+       case KVM_REG_PPC_IAC3:
+       case KVM_REG_PPC_IAC4: {
+               int iac = reg->id - KVM_REG_PPC_IAC1;
+               r = copy_to_user((u64 __user *)(long)reg->addr,
+                                &vcpu->arch.dbg_reg.iac[iac], sizeof(u64));
+               break;
+       }
+       case KVM_REG_PPC_DAC1:
+       case KVM_REG_PPC_DAC2: {
+               int dac = reg->id - KVM_REG_PPC_DAC1;
+               r = copy_to_user((u64 __user *)(long)reg->addr,
+                                &vcpu->arch.dbg_reg.dac[dac], sizeof(u64));
+               break;
+       }
+       default:
+               break;
+       }
+       return r;
 }
 
 int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
 {
-       return -EINVAL;
+       int r = -EINVAL;
+
+       switch (reg->id) {
+       case KVM_REG_PPC_IAC1:
+       case KVM_REG_PPC_IAC2:
+       case KVM_REG_PPC_IAC3:
+       case KVM_REG_PPC_IAC4: {
+               int iac = reg->id - KVM_REG_PPC_IAC1;
+               r = copy_from_user(&vcpu->arch.dbg_reg.iac[iac],
+                            (u64 __user *)(long)reg->addr, sizeof(u64));
+               break;
+       }
+       case KVM_REG_PPC_DAC1:
+       case KVM_REG_PPC_DAC2: {
+               int dac = reg->id - KVM_REG_PPC_DAC1;
+               r = copy_from_user(&vcpu->arch.dbg_reg.dac[dac],
+                            (u64 __user *)(long)reg->addr, sizeof(u64));
+               break;
+       }
+       default:
+               break;
+       }
+       return r;
 }
 
 int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
@@ -1253,20 +1437,38 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, struct kvm_dirty_log *log)
        return -ENOTSUPP;
 }
 
+void kvmppc_core_free_memslot(struct kvm_memory_slot *free,
+                             struct kvm_memory_slot *dont)
+{
+}
+
+int kvmppc_core_create_memslot(struct kvm_memory_slot *slot,
+                              unsigned long npages)
+{
+       return 0;
+}
+
 int kvmppc_core_prepare_memory_region(struct kvm *kvm,
+                                     struct kvm_memory_slot *memslot,
                                      struct kvm_userspace_memory_region *mem)
 {
        return 0;
 }
 
 void kvmppc_core_commit_memory_region(struct kvm *kvm,
-                               struct kvm_userspace_memory_region *mem)
+                               struct kvm_userspace_memory_region *mem,
+                               struct kvm_memory_slot old)
+{
+}
+
+void kvmppc_core_flush_memslot(struct kvm *kvm, struct kvm_memory_slot *memslot)
 {
 }
 
 void kvmppc_set_tcr(struct kvm_vcpu *vcpu, u32 new_tcr)
 {
        vcpu->arch.tcr = new_tcr;
+       arm_next_watchdog(vcpu);
        update_timer_ints(vcpu);
 }
 
@@ -1281,6 +1483,14 @@ void kvmppc_set_tsr_bits(struct kvm_vcpu *vcpu, u32 tsr_bits)
 void kvmppc_clr_tsr_bits(struct kvm_vcpu *vcpu, u32 tsr_bits)
 {
        clear_bits(tsr_bits, &vcpu->arch.tsr);
+
+       /*
+        * We may have stopped the watchdog due to
+        * being stuck on final expiration.
+        */
+       if (tsr_bits & (TSR_ENW | TSR_WIS))
+               arm_next_watchdog(vcpu);
+
        update_timer_ints(vcpu);
 }
 
@@ -1298,12 +1508,14 @@ void kvmppc_decrementer_func(unsigned long data)
 
 void kvmppc_booke_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 {
+       vcpu->cpu = smp_processor_id();
        current->thread.kvm_vcpu = vcpu;
 }
 
 void kvmppc_booke_vcpu_put(struct kvm_vcpu *vcpu)
 {
        current->thread.kvm_vcpu = NULL;
+       vcpu->cpu = -1;
 }
 
 int __init kvmppc_booke_init(void)
index 12834bb608aba1e41653fa6aaa96f0735d587b80..514790f41abafa9c752ebdaa90bde9f1e961423f 100644 (file)
@@ -133,10 +133,10 @@ int kvmppc_booke_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, ulong spr_val)
                vcpu->arch.csrr1 = spr_val;
                break;
        case SPRN_DBCR0:
-               vcpu->arch.dbcr0 = spr_val;
+               vcpu->arch.dbg_reg.dbcr0 = spr_val;
                break;
        case SPRN_DBCR1:
-               vcpu->arch.dbcr1 = spr_val;
+               vcpu->arch.dbg_reg.dbcr1 = spr_val;
                break;
        case SPRN_DBSR:
                vcpu->arch.dbsr &= ~spr_val;
@@ -145,6 +145,14 @@ int kvmppc_booke_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, ulong spr_val)
                kvmppc_clr_tsr_bits(vcpu, spr_val);
                break;
        case SPRN_TCR:
+               /*
+                * WRC is a 2-bit field that is supposed to preserve its
+                * value once written to non-zero.
+                */
+               if (vcpu->arch.tcr & TCR_WRC_MASK) {
+                       spr_val &= ~TCR_WRC_MASK;
+                       spr_val |= vcpu->arch.tcr & TCR_WRC_MASK;
+               }
                kvmppc_set_tcr(vcpu, spr_val);
                break;
 
@@ -229,6 +237,9 @@ int kvmppc_booke_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, ulong spr_val)
        case SPRN_IVOR15:
                vcpu->arch.ivor[BOOKE_IRQPRIO_DEBUG] = spr_val;
                break;
+       case SPRN_MCSR:
+               vcpu->arch.mcsr &= ~spr_val;
+               break;
 
        default:
                emulated = EMULATE_FAIL;
@@ -258,10 +269,10 @@ int kvmppc_booke_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val)
                *spr_val = vcpu->arch.csrr1;
                break;
        case SPRN_DBCR0:
-               *spr_val = vcpu->arch.dbcr0;
+               *spr_val = vcpu->arch.dbg_reg.dbcr0;
                break;
        case SPRN_DBCR1:
-               *spr_val = vcpu->arch.dbcr1;
+               *spr_val = vcpu->arch.dbg_reg.dbcr1;
                break;
        case SPRN_DBSR:
                *spr_val = vcpu->arch.dbsr;
@@ -321,6 +332,9 @@ int kvmppc_booke_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val)
        case SPRN_IVOR15:
                *spr_val = vcpu->arch.ivor[BOOKE_IRQPRIO_DEBUG];
                break;
+       case SPRN_MCSR:
+               *spr_val = vcpu->arch.mcsr;
+               break;
 
        default:
                emulated = EMULATE_FAIL;
index aa8b81428bf4afd168a1a2e8fa40da83f180b860..d1622864549ecc6b03c26bb1bde194a9ce691237 100644 (file)
@@ -27,8 +27,7 @@
 #define E500_TLB_NUM   2
 
 #define E500_TLB_VALID 1
-#define E500_TLB_DIRTY 2
-#define E500_TLB_BITMAP 4
+#define E500_TLB_BITMAP 2
 
 struct tlbe_ref {
        pfn_t pfn;
index ff38b664195d6dcac44f1e24b6e15c6a431abd7b..c73389477d177226c5f6f3009868bb77b72cd50a 100644 (file)
@@ -304,17 +304,13 @@ static inline void kvmppc_e500_ref_setup(struct tlbe_ref *ref,
        ref->flags = E500_TLB_VALID;
 
        if (tlbe_is_writable(gtlbe))
-               ref->flags |= E500_TLB_DIRTY;
+               kvm_set_pfn_dirty(pfn);
 }
 
 static inline void kvmppc_e500_ref_release(struct tlbe_ref *ref)
 {
        if (ref->flags & E500_TLB_VALID) {
-               if (ref->flags & E500_TLB_DIRTY)
-                       kvm_release_pfn_dirty(ref->pfn);
-               else
-                       kvm_release_pfn_clean(ref->pfn);
-
+               trace_kvm_booke206_ref_release(ref->pfn, ref->flags);
                ref->flags = 0;
        }
 }
@@ -357,6 +353,13 @@ static void clear_tlb_refs(struct kvmppc_vcpu_e500 *vcpu_e500)
        clear_tlb_privs(vcpu_e500);
 }
 
+void kvmppc_core_flush_tlb(struct kvm_vcpu *vcpu)
+{
+       struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
+       clear_tlb_refs(vcpu_e500);
+       clear_tlb1_bitmap(vcpu_e500);
+}
+
 static inline void kvmppc_e500_deliver_tlb_miss(struct kvm_vcpu *vcpu,
                unsigned int eaddr, int as)
 {
@@ -541,6 +544,9 @@ static inline void kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,
 
        /* Clear i-cache for new pages */
        kvmppc_mmu_flush_icache(pfn);
+
+       /* Drop refcount on page, so that mmu notifiers can clear it */
+       kvm_release_pfn_clean(pfn);
 }
 
 /* XXX only map the one-one case, for now use TLB0 */
@@ -1039,8 +1045,12 @@ void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 eaddr, gpa_t gpaddr,
                sesel = 0; /* unused */
                priv = &vcpu_e500->gtlb_priv[tlbsel][esel];
 
-               kvmppc_e500_setup_stlbe(vcpu, gtlbe, BOOK3E_PAGESZ_4K,
-                                       &priv->ref, eaddr, &stlbe);
+               /* Only triggers after clear_tlb_refs */
+               if (unlikely(!(priv->ref.flags & E500_TLB_VALID)))
+                       kvmppc_e500_tlb0_map(vcpu_e500, esel, &stlbe);
+               else
+                       kvmppc_e500_setup_stlbe(vcpu, gtlbe, BOOK3E_PAGESZ_4K,
+                                               &priv->ref, eaddr, &stlbe);
                break;
 
        case 1: {
@@ -1060,6 +1070,49 @@ void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 eaddr, gpa_t gpaddr,
        write_stlbe(vcpu_e500, gtlbe, &stlbe, stlbsel, sesel);
 }
 
+/************* MMU Notifiers *************/
+
+int kvm_unmap_hva(struct kvm *kvm, unsigned long hva)
+{
+       trace_kvm_unmap_hva(hva);
+
+       /*
+        * Flush all shadow tlb entries everywhere. This is slow, but
+        * we are 100% sure that we catch the to be unmapped page
+        */
+       kvm_flush_remote_tlbs(kvm);
+
+       return 0;
+}
+
+int kvm_unmap_hva_range(struct kvm *kvm, unsigned long start, unsigned long end)
+{
+       /* kvm_unmap_hva flushes everything anyways */
+       kvm_unmap_hva(kvm, start);
+
+       return 0;
+}
+
+int kvm_age_hva(struct kvm *kvm, unsigned long hva)
+{
+       /* XXX could be more clever ;) */
+       return 0;
+}
+
+int kvm_test_age_hva(struct kvm *kvm, unsigned long hva)
+{
+       /* XXX could be more clever ;) */
+       return 0;
+}
+
+void kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte)
+{
+       /* The page will get remapped properly on its next fault */
+       kvm_unmap_hva(kvm, hva);
+}
+
+/*****************************************/
+
 static void free_gtlb(struct kvmppc_vcpu_e500 *vcpu_e500)
 {
        int i;
@@ -1081,6 +1134,8 @@ static void free_gtlb(struct kvmppc_vcpu_e500 *vcpu_e500)
                }
 
                vcpu_e500->num_shared_tlb_pages = 0;
+
+               kfree(vcpu_e500->shared_tlb_pages);
                vcpu_e500->shared_tlb_pages = NULL;
        } else {
                kfree(vcpu_e500->gtlb_arch);
@@ -1178,21 +1233,27 @@ int kvm_vcpu_ioctl_config_tlb(struct kvm_vcpu *vcpu,
        }
 
        virt = vmap(pages, num_pages, VM_MAP, PAGE_KERNEL);
-       if (!virt)
+       if (!virt) {
+               ret = -ENOMEM;
                goto err_put_page;
+       }
 
        privs[0] = kzalloc(sizeof(struct tlbe_priv) * params.tlb_sizes[0],
                           GFP_KERNEL);
        privs[1] = kzalloc(sizeof(struct tlbe_priv) * params.tlb_sizes[1],
                           GFP_KERNEL);
 
-       if (!privs[0] || !privs[1])
-               goto err_put_page;
+       if (!privs[0] || !privs[1]) {
+               ret = -ENOMEM;
+               goto err_privs;
+       }
 
        g2h_bitmap = kzalloc(sizeof(u64) * params.tlb_sizes[1],
                             GFP_KERNEL);
-       if (!g2h_bitmap)
-               goto err_put_page;
+       if (!g2h_bitmap) {
+               ret = -ENOMEM;
+               goto err_privs;
+       }
 
        free_gtlb(vcpu_e500);
 
@@ -1232,10 +1293,11 @@ int kvm_vcpu_ioctl_config_tlb(struct kvm_vcpu *vcpu,
        kvmppc_recalc_tlb1map_range(vcpu_e500);
        return 0;
 
-err_put_page:
+err_privs:
        kfree(privs[0]);
        kfree(privs[1]);
 
+err_put_page:
        for (i = 0; i < num_pages; i++)
                put_page(pages[i]);
 
@@ -1332,7 +1394,7 @@ int kvmppc_e500_tlb_init(struct kvmppc_vcpu_e500 *vcpu_e500)
        if (!vcpu_e500->gtlb_priv[1])
                goto err;
 
-       vcpu_e500->g2h_tlb1_map = kzalloc(sizeof(unsigned int) *
+       vcpu_e500->g2h_tlb1_map = kzalloc(sizeof(u64) *
                                          vcpu_e500->gtlb_params[1].entries,
                                          GFP_KERNEL);
        if (!vcpu_e500->g2h_tlb1_map)
index ee04abaefe233c89e692a9e1a84e4686d4da8030..b0855e5d8905ee50e6422ca9edfc37aa952f6b21 100644 (file)
@@ -131,6 +131,125 @@ u32 kvmppc_get_dec(struct kvm_vcpu *vcpu, u64 tb)
        return vcpu->arch.dec - jd;
 }
 
+static int kvmppc_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs)
+{
+       enum emulation_result emulated = EMULATE_DONE;
+       ulong spr_val = kvmppc_get_gpr(vcpu, rs);
+
+       switch (sprn) {
+       case SPRN_SRR0:
+               vcpu->arch.shared->srr0 = spr_val;
+               break;
+       case SPRN_SRR1:
+               vcpu->arch.shared->srr1 = spr_val;
+               break;
+
+       /* XXX We need to context-switch the timebase for
+        * watchdog and FIT. */
+       case SPRN_TBWL: break;
+       case SPRN_TBWU: break;
+
+       case SPRN_MSSSR0: break;
+
+       case SPRN_DEC:
+               vcpu->arch.dec = spr_val;
+               kvmppc_emulate_dec(vcpu);
+               break;
+
+       case SPRN_SPRG0:
+               vcpu->arch.shared->sprg0 = spr_val;
+               break;
+       case SPRN_SPRG1:
+               vcpu->arch.shared->sprg1 = spr_val;
+               break;
+       case SPRN_SPRG2:
+               vcpu->arch.shared->sprg2 = spr_val;
+               break;
+       case SPRN_SPRG3:
+               vcpu->arch.shared->sprg3 = spr_val;
+               break;
+
+       default:
+               emulated = kvmppc_core_emulate_mtspr(vcpu, sprn,
+                                                    spr_val);
+               if (emulated == EMULATE_FAIL)
+                       printk(KERN_INFO "mtspr: unknown spr "
+                               "0x%x\n", sprn);
+               break;
+       }
+
+       kvmppc_set_exit_type(vcpu, EMULATED_MTSPR_EXITS);
+
+       return emulated;
+}
+
+static int kvmppc_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt)
+{
+       enum emulation_result emulated = EMULATE_DONE;
+       ulong spr_val = 0;
+
+       switch (sprn) {
+       case SPRN_SRR0:
+               spr_val = vcpu->arch.shared->srr0;
+               break;
+       case SPRN_SRR1:
+               spr_val = vcpu->arch.shared->srr1;
+               break;
+       case SPRN_PVR:
+               spr_val = vcpu->arch.pvr;
+               break;
+       case SPRN_PIR:
+               spr_val = vcpu->vcpu_id;
+               break;
+       case SPRN_MSSSR0:
+               spr_val = 0;
+               break;
+
+       /* Note: mftb and TBRL/TBWL are user-accessible, so
+        * the guest can always access the real TB anyways.
+        * In fact, we probably will never see these traps. */
+       case SPRN_TBWL:
+               spr_val = get_tb() >> 32;
+               break;
+       case SPRN_TBWU:
+               spr_val = get_tb();
+               break;
+
+       case SPRN_SPRG0:
+               spr_val = vcpu->arch.shared->sprg0;
+               break;
+       case SPRN_SPRG1:
+               spr_val = vcpu->arch.shared->sprg1;
+               break;
+       case SPRN_SPRG2:
+               spr_val = vcpu->arch.shared->sprg2;
+               break;
+       case SPRN_SPRG3:
+               spr_val = vcpu->arch.shared->sprg3;
+               break;
+       /* Note: SPRG4-7 are user-readable, so we don't get
+        * a trap. */
+
+       case SPRN_DEC:
+               spr_val = kvmppc_get_dec(vcpu, get_tb());
+               break;
+       default:
+               emulated = kvmppc_core_emulate_mfspr(vcpu, sprn,
+                                                    &spr_val);
+               if (unlikely(emulated == EMULATE_FAIL)) {
+                       printk(KERN_INFO "mfspr: unknown spr "
+                               "0x%x\n", sprn);
+               }
+               break;
+       }
+
+       if (emulated == EMULATE_DONE)
+               kvmppc_set_gpr(vcpu, rt, spr_val);
+       kvmppc_set_exit_type(vcpu, EMULATED_MFSPR_EXITS);
+
+       return emulated;
+}
+
 /* XXX to do:
  * lhax
  * lhaux
@@ -156,7 +275,6 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
        int sprn = get_sprn(inst);
        enum emulation_result emulated = EMULATE_DONE;
        int advance = 1;
-       ulong spr_val = 0;
 
        /* this default type might be overwritten by subcategories */
        kvmppc_set_exit_type(vcpu, EMULATED_INST_EXITS);
@@ -236,62 +354,7 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
                        break;
 
                case OP_31_XOP_MFSPR:
-                       switch (sprn) {
-                       case SPRN_SRR0:
-                               spr_val = vcpu->arch.shared->srr0;
-                               break;
-                       case SPRN_SRR1:
-                               spr_val = vcpu->arch.shared->srr1;
-                               break;
-                       case SPRN_PVR:
-                               spr_val = vcpu->arch.pvr;
-                               break;
-                       case SPRN_PIR:
-                               spr_val = vcpu->vcpu_id;
-                               break;
-                       case SPRN_MSSSR0:
-                               spr_val = 0;
-                               break;
-
-                       /* Note: mftb and TBRL/TBWL are user-accessible, so
-                        * the guest can always access the real TB anyways.
-                        * In fact, we probably will never see these traps. */
-                       case SPRN_TBWL:
-                               spr_val = get_tb() >> 32;
-                               break;
-                       case SPRN_TBWU:
-                               spr_val = get_tb();
-                               break;
-
-                       case SPRN_SPRG0:
-                               spr_val = vcpu->arch.shared->sprg0;
-                               break;
-                       case SPRN_SPRG1:
-                               spr_val = vcpu->arch.shared->sprg1;
-                               break;
-                       case SPRN_SPRG2:
-                               spr_val = vcpu->arch.shared->sprg2;
-                               break;
-                       case SPRN_SPRG3:
-                               spr_val = vcpu->arch.shared->sprg3;
-                               break;
-                       /* Note: SPRG4-7 are user-readable, so we don't get
-                        * a trap. */
-
-                       case SPRN_DEC:
-                               spr_val = kvmppc_get_dec(vcpu, get_tb());
-                               break;
-                       default:
-                               emulated = kvmppc_core_emulate_mfspr(vcpu, sprn,
-                                                                    &spr_val);
-                               if (unlikely(emulated == EMULATE_FAIL)) {
-                                       printk(KERN_INFO "mfspr: unknown spr "
-                                               "0x%x\n", sprn);
-                               }
-                               break;
-                       }
-                       kvmppc_set_gpr(vcpu, rt, spr_val);
-                       kvmppc_set_exit_type(vcpu, EMULATED_MFSPR_EXITS);
+                       emulated = kvmppc_emulate_mfspr(vcpu, sprn, rt);
                        break;
 
                case OP_31_XOP_STHX:
@@ -308,49 +371,7 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
                        break;
 
                case OP_31_XOP_MTSPR:
-                       spr_val = kvmppc_get_gpr(vcpu, rs);
-                       switch (sprn) {
-                       case SPRN_SRR0:
-                               vcpu->arch.shared->srr0 = spr_val;
-                               break;
-                       case SPRN_SRR1:
-                               vcpu->arch.shared->srr1 = spr_val;
-                               break;
-
-                       /* XXX We need to context-switch the timebase for
-                        * watchdog and FIT. */
-                       case SPRN_TBWL: break;
-                       case SPRN_TBWU: break;
-
-                       case SPRN_MSSSR0: break;
-
-                       case SPRN_DEC:
-                               vcpu->arch.dec = spr_val;
-                               kvmppc_emulate_dec(vcpu);
-                               break;
-
-                       case SPRN_SPRG0:
-                               vcpu->arch.shared->sprg0 = spr_val;
-                               break;
-                       case SPRN_SPRG1:
-                               vcpu->arch.shared->sprg1 = spr_val;
-                               break;
-                       case SPRN_SPRG2:
-                               vcpu->arch.shared->sprg2 = spr_val;
-                               break;
-                       case SPRN_SPRG3:
-                               vcpu->arch.shared->sprg3 = spr_val;
-                               break;
-
-                       default:
-                               emulated = kvmppc_core_emulate_mtspr(vcpu, sprn,
-                                                                    spr_val);
-                               if (emulated == EMULATE_FAIL)
-                                       printk(KERN_INFO "mtspr: unknown spr "
-                                               "0x%x\n", sprn);
-                               break;
-                       }
-                       kvmppc_set_exit_type(vcpu, EMULATED_MTSPR_EXITS);
+                       emulated = kvmppc_emulate_mtspr(vcpu, sprn, rs);
                        break;
 
                case OP_31_XOP_DCBI:
index 4d213b8b0fb55eeb1eff3ae1ab591ab91d00dba9..deb0d596d815fca2457c415d774144702869f60e 100644 (file)
@@ -30,6 +30,7 @@
 #include <asm/kvm_ppc.h>
 #include <asm/tlbflush.h>
 #include <asm/cputhreads.h>
+#include <asm/irqflags.h>
 #include "timing.h"
 #include "../mm/mmu_decl.h"
 
@@ -38,8 +39,7 @@
 
 int kvm_arch_vcpu_runnable(struct kvm_vcpu *v)
 {
-       return !(v->arch.shared->msr & MSR_WE) ||
-              !!(v->arch.pending_exceptions) ||
+       return !!(v->arch.pending_exceptions) ||
               v->requests;
 }
 
@@ -48,6 +48,85 @@ int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu)
        return 1;
 }
 
+#ifndef CONFIG_KVM_BOOK3S_64_HV
+/*
+ * Common checks before entering the guest world.  Call with interrupts
+ * disabled.
+ *
+ * returns:
+ *
+ * == 1 if we're ready to go into guest state
+ * <= 0 if we need to go back to the host with return value
+ */
+int kvmppc_prepare_to_enter(struct kvm_vcpu *vcpu)
+{
+       int r = 1;
+
+       WARN_ON_ONCE(!irqs_disabled());
+       while (true) {
+               if (need_resched()) {
+                       local_irq_enable();
+                       cond_resched();
+                       local_irq_disable();
+                       continue;
+               }
+
+               if (signal_pending(current)) {
+                       kvmppc_account_exit(vcpu, SIGNAL_EXITS);
+                       vcpu->run->exit_reason = KVM_EXIT_INTR;
+                       r = -EINTR;
+                       break;
+               }
+
+               vcpu->mode = IN_GUEST_MODE;
+
+               /*
+                * Reading vcpu->requests must happen after setting vcpu->mode,
+                * so we don't miss a request because the requester sees
+                * OUTSIDE_GUEST_MODE and assumes we'll be checking requests
+                * before next entering the guest (and thus doesn't IPI).
+                */
+               smp_mb();
+
+               if (vcpu->requests) {
+                       /* Make sure we process requests preemptable */
+                       local_irq_enable();
+                       trace_kvm_check_requests(vcpu);
+                       r = kvmppc_core_check_requests(vcpu);
+                       local_irq_disable();
+                       if (r > 0)
+                               continue;
+                       break;
+               }
+
+               if (kvmppc_core_prepare_to_enter(vcpu)) {
+                       /* interrupts got enabled in between, so we
+                          are back at square 1 */
+                       continue;
+               }
+
+#ifdef CONFIG_PPC64
+               /* lazy EE magic */
+               hard_irq_disable();
+               if (lazy_irq_pending()) {
+                       /* Got an interrupt in between, try again */
+                       local_irq_enable();
+                       local_irq_disable();
+                       kvm_guest_exit();
+                       continue;
+               }
+
+               trace_hardirqs_on();
+#endif
+
+               kvm_guest_enter();
+               break;
+       }
+
+       return r;
+}
+#endif /* CONFIG_KVM_BOOK3S_64_HV */
+
 int kvmppc_kvm_pv(struct kvm_vcpu *vcpu)
 {
        int nr = kvmppc_get_gpr(vcpu, 11);
@@ -67,18 +146,18 @@ int kvmppc_kvm_pv(struct kvm_vcpu *vcpu)
        }
 
        switch (nr) {
-       case HC_VENDOR_KVM | KVM_HC_PPC_MAP_MAGIC_PAGE:
+       case KVM_HCALL_TOKEN(KVM_HC_PPC_MAP_MAGIC_PAGE):
        {
                vcpu->arch.magic_page_pa = param1;
                vcpu->arch.magic_page_ea = param2;
 
                r2 = KVM_MAGIC_FEAT_SR | KVM_MAGIC_FEAT_MAS0_TO_SPRG7;
 
-               r = HC_EV_SUCCESS;
+               r = EV_SUCCESS;
                break;
        }
-       case HC_VENDOR_KVM | KVM_HC_FEATURES:
-               r = HC_EV_SUCCESS;
+       case KVM_HCALL_TOKEN(KVM_HC_FEATURES):
+               r = EV_SUCCESS;
 #if defined(CONFIG_PPC_BOOK3S) || defined(CONFIG_KVM_E500V2)
                /* XXX Missing magic page on 44x */
                r2 |= (1 << KVM_FEATURE_MAGIC_PAGE);
@@ -86,8 +165,13 @@ int kvmppc_kvm_pv(struct kvm_vcpu *vcpu)
 
                /* Second return value is in r4 */
                break;
+       case EV_HCALL_TOKEN(EV_IDLE):
+               r = EV_SUCCESS;
+               kvm_vcpu_block(vcpu);
+               clear_bit(KVM_REQ_UNHALT, &vcpu->requests);
+               break;
        default:
-               r = HC_EV_UNIMPLEMENTED;
+               r = EV_UNIMPLEMENTED;
                break;
        }
 
@@ -220,6 +304,7 @@ int kvm_dev_ioctl_check_extension(long ext)
        switch (ext) {
 #ifdef CONFIG_BOOKE
        case KVM_CAP_PPC_BOOKE_SREGS:
+       case KVM_CAP_PPC_BOOKE_WATCHDOG:
 #else
        case KVM_CAP_PPC_SEGSTATE:
        case KVM_CAP_PPC_HIOR:
@@ -260,10 +345,16 @@ int kvm_dev_ioctl_check_extension(long ext)
                if (cpu_has_feature(CPU_FTR_ARCH_201))
                        r = 2;
                break;
+#endif
        case KVM_CAP_SYNC_MMU:
+#ifdef CONFIG_KVM_BOOK3S_64_HV
                r = cpu_has_feature(CPU_FTR_ARCH_206) ? 1 : 0;
-               break;
+#elif defined(KVM_ARCH_WANT_MMU_NOTIFIER)
+               r = 1;
+#else
+               r = 0;
 #endif
+               break;
        case KVM_CAP_NR_VCPUS:
                /*
                 * Recommending a number of CPUs is somewhat arbitrary; we
@@ -302,19 +393,12 @@ long kvm_arch_dev_ioctl(struct file *filp,
 void kvm_arch_free_memslot(struct kvm_memory_slot *free,
                           struct kvm_memory_slot *dont)
 {
-       if (!dont || free->arch.rmap != dont->arch.rmap) {
-               vfree(free->arch.rmap);
-               free->arch.rmap = NULL;
-       }
+       kvmppc_core_free_memslot(free, dont);
 }
 
 int kvm_arch_create_memslot(struct kvm_memory_slot *slot, unsigned long npages)
 {
-       slot->arch.rmap = vzalloc(npages * sizeof(*slot->arch.rmap));
-       if (!slot->arch.rmap)
-               return -ENOMEM;
-
-       return 0;
+       return kvmppc_core_create_memslot(slot, npages);
 }
 
 int kvm_arch_prepare_memory_region(struct kvm *kvm,
@@ -323,7 +407,7 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
                                    struct kvm_userspace_memory_region *mem,
                                    int user_alloc)
 {
-       return kvmppc_core_prepare_memory_region(kvm, mem);
+       return kvmppc_core_prepare_memory_region(kvm, memslot, mem);
 }
 
 void kvm_arch_commit_memory_region(struct kvm *kvm,
@@ -331,7 +415,7 @@ void kvm_arch_commit_memory_region(struct kvm *kvm,
                struct kvm_memory_slot old,
                int user_alloc)
 {
-       kvmppc_core_commit_memory_region(kvm, mem);
+       kvmppc_core_commit_memory_region(kvm, mem, old);
 }
 
 void kvm_arch_flush_shadow_all(struct kvm *kvm)
@@ -341,6 +425,7 @@ void kvm_arch_flush_shadow_all(struct kvm *kvm)
 void kvm_arch_flush_shadow_memslot(struct kvm *kvm,
                                   struct kvm_memory_slot *slot)
 {
+       kvmppc_core_flush_memslot(kvm, slot);
 }
 
 struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id)
@@ -390,6 +475,8 @@ enum hrtimer_restart kvmppc_decrementer_wakeup(struct hrtimer *timer)
 
 int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
 {
+       int ret;
+
        hrtimer_init(&vcpu->arch.dec_timer, CLOCK_REALTIME, HRTIMER_MODE_ABS);
        tasklet_init(&vcpu->arch.tasklet, kvmppc_decrementer_func, (ulong)vcpu);
        vcpu->arch.dec_timer.function = kvmppc_decrementer_wakeup;
@@ -398,13 +485,14 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
 #ifdef CONFIG_KVM_EXIT_TIMING
        mutex_init(&vcpu->arch.exit_timing_lock);
 #endif
-
-       return 0;
+       ret = kvmppc_subarch_vcpu_init(vcpu);
+       return ret;
 }
 
 void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu)
 {
        kvmppc_mmu_destroy(vcpu);
+       kvmppc_subarch_vcpu_uninit(vcpu);
 }
 
 void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
@@ -420,7 +508,6 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
        mtspr(SPRN_VRSAVE, vcpu->arch.vrsave);
 #endif
        kvmppc_core_vcpu_load(vcpu, cpu);
-       vcpu->cpu = smp_processor_id();
 }
 
 void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
@@ -429,7 +516,6 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
 #ifdef CONFIG_BOOKE
        vcpu->arch.vrsave = mfspr(SPRN_VRSAVE);
 #endif
-       vcpu->cpu = -1;
 }
 
 int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu,
@@ -649,6 +735,12 @@ static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu,
                r = 0;
                vcpu->arch.papr_enabled = true;
                break;
+#ifdef CONFIG_BOOKE
+       case KVM_CAP_PPC_BOOKE_WATCHDOG:
+               r = 0;
+               vcpu->arch.watchdog_enabled = true;
+               break;
+#endif
 #if defined(CONFIG_KVM_E500V2) || defined(CONFIG_KVM_E500MC)
        case KVM_CAP_SW_TLB: {
                struct kvm_config_tlb cfg;
@@ -751,9 +843,16 @@ int kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf)
 
 static int kvm_vm_ioctl_get_pvinfo(struct kvm_ppc_pvinfo *pvinfo)
 {
+       u32 inst_nop = 0x60000000;
+#ifdef CONFIG_KVM_BOOKE_HV
+       u32 inst_sc1 = 0x44000022;
+       pvinfo->hcall[0] = inst_sc1;
+       pvinfo->hcall[1] = inst_nop;
+       pvinfo->hcall[2] = inst_nop;
+       pvinfo->hcall[3] = inst_nop;
+#else
        u32 inst_lis = 0x3c000000;
        u32 inst_ori = 0x60000000;
-       u32 inst_nop = 0x60000000;
        u32 inst_sc = 0x44000002;
        u32 inst_imm_mask = 0xffff;
 
@@ -770,6 +869,9 @@ static int kvm_vm_ioctl_get_pvinfo(struct kvm_ppc_pvinfo *pvinfo)
        pvinfo->hcall[1] = inst_ori | (KVM_SC_MAGIC_R0 & inst_imm_mask);
        pvinfo->hcall[2] = inst_sc;
        pvinfo->hcall[3] = inst_nop;
+#endif
+
+       pvinfo->flags = KVM_PPC_PVINFO_FLAGS_EV_IDLE;
 
        return 0;
 }
index ddb6a2149d4460c067da161de4672f3cbaf4a97a..e326489a54205b30bc8c111c442ca19ab6d5c831 100644 (file)
@@ -31,6 +31,126 @@ TRACE_EVENT(kvm_ppc_instr,
                  __entry->inst, __entry->pc, __entry->emulate)
 );
 
+#ifdef CONFIG_PPC_BOOK3S
+#define kvm_trace_symbol_exit \
+       {0x100, "SYSTEM_RESET"}, \
+       {0x200, "MACHINE_CHECK"}, \
+       {0x300, "DATA_STORAGE"}, \
+       {0x380, "DATA_SEGMENT"}, \
+       {0x400, "INST_STORAGE"}, \
+       {0x480, "INST_SEGMENT"}, \
+       {0x500, "EXTERNAL"}, \
+       {0x501, "EXTERNAL_LEVEL"}, \
+       {0x502, "EXTERNAL_HV"}, \
+       {0x600, "ALIGNMENT"}, \
+       {0x700, "PROGRAM"}, \
+       {0x800, "FP_UNAVAIL"}, \
+       {0x900, "DECREMENTER"}, \
+       {0x980, "HV_DECREMENTER"}, \
+       {0xc00, "SYSCALL"}, \
+       {0xd00, "TRACE"}, \
+       {0xe00, "H_DATA_STORAGE"}, \
+       {0xe20, "H_INST_STORAGE"}, \
+       {0xe40, "H_EMUL_ASSIST"}, \
+       {0xf00, "PERFMON"}, \
+       {0xf20, "ALTIVEC"}, \
+       {0xf40, "VSX"}
+#else
+#define kvm_trace_symbol_exit \
+       {0, "CRITICAL"}, \
+       {1, "MACHINE_CHECK"}, \
+       {2, "DATA_STORAGE"}, \
+       {3, "INST_STORAGE"}, \
+       {4, "EXTERNAL"}, \
+       {5, "ALIGNMENT"}, \
+       {6, "PROGRAM"}, \
+       {7, "FP_UNAVAIL"}, \
+       {8, "SYSCALL"}, \
+       {9, "AP_UNAVAIL"}, \
+       {10, "DECREMENTER"}, \
+       {11, "FIT"}, \
+       {12, "WATCHDOG"}, \
+       {13, "DTLB_MISS"}, \
+       {14, "ITLB_MISS"}, \
+       {15, "DEBUG"}, \
+       {32, "SPE_UNAVAIL"}, \
+       {33, "SPE_FP_DATA"}, \
+       {34, "SPE_FP_ROUND"}, \
+       {35, "PERFORMANCE_MONITOR"}, \
+       {36, "DOORBELL"}, \
+       {37, "DOORBELL_CRITICAL"}, \
+       {38, "GUEST_DBELL"}, \
+       {39, "GUEST_DBELL_CRIT"}, \
+       {40, "HV_SYSCALL"}, \
+       {41, "HV_PRIV"}
+#endif
+
+TRACE_EVENT(kvm_exit,
+       TP_PROTO(unsigned int exit_nr, struct kvm_vcpu *vcpu),
+       TP_ARGS(exit_nr, vcpu),
+
+       TP_STRUCT__entry(
+               __field(        unsigned int,   exit_nr         )
+               __field(        unsigned long,  pc              )
+               __field(        unsigned long,  msr             )
+               __field(        unsigned long,  dar             )
+#ifdef CONFIG_KVM_BOOK3S_PR
+               __field(        unsigned long,  srr1            )
+#endif
+               __field(        unsigned long,  last_inst       )
+       ),
+
+       TP_fast_assign(
+#ifdef CONFIG_KVM_BOOK3S_PR
+               struct kvmppc_book3s_shadow_vcpu *svcpu;
+#endif
+               __entry->exit_nr        = exit_nr;
+               __entry->pc             = kvmppc_get_pc(vcpu);
+               __entry->dar            = kvmppc_get_fault_dar(vcpu);
+               __entry->msr            = vcpu->arch.shared->msr;
+#ifdef CONFIG_KVM_BOOK3S_PR
+               svcpu = svcpu_get(vcpu);
+               __entry->srr1           = svcpu->shadow_srr1;
+               svcpu_put(svcpu);
+#endif
+               __entry->last_inst      = vcpu->arch.last_inst;
+       ),
+
+       TP_printk("exit=%s"
+               " | pc=0x%lx"
+               " | msr=0x%lx"
+               " | dar=0x%lx"
+#ifdef CONFIG_KVM_BOOK3S_PR
+               " | srr1=0x%lx"
+#endif
+               " | last_inst=0x%lx"
+               ,
+               __print_symbolic(__entry->exit_nr, kvm_trace_symbol_exit),
+               __entry->pc,
+               __entry->msr,
+               __entry->dar,
+#ifdef CONFIG_KVM_BOOK3S_PR
+               __entry->srr1,
+#endif
+               __entry->last_inst
+               )
+);
+
+TRACE_EVENT(kvm_unmap_hva,
+       TP_PROTO(unsigned long hva),
+       TP_ARGS(hva),
+
+       TP_STRUCT__entry(
+               __field(        unsigned long,  hva             )
+       ),
+
+       TP_fast_assign(
+               __entry->hva            = hva;
+       ),
+
+       TP_printk("unmap hva 0x%lx\n", __entry->hva)
+);
+
 TRACE_EVENT(kvm_stlb_inval,
        TP_PROTO(unsigned int stlb_index),
        TP_ARGS(stlb_index),
@@ -98,41 +218,31 @@ TRACE_EVENT(kvm_gtlb_write,
                __entry->word1, __entry->word2)
 );
 
-
-/*************************************************************************
- *                         Book3S trace points                           *
- *************************************************************************/
-
-#ifdef CONFIG_KVM_BOOK3S_PR
-
-TRACE_EVENT(kvm_book3s_exit,
-       TP_PROTO(unsigned int exit_nr, struct kvm_vcpu *vcpu),
-       TP_ARGS(exit_nr, vcpu),
+TRACE_EVENT(kvm_check_requests,
+       TP_PROTO(struct kvm_vcpu *vcpu),
+       TP_ARGS(vcpu),
 
        TP_STRUCT__entry(
-               __field(        unsigned int,   exit_nr         )
-               __field(        unsigned long,  pc              )
-               __field(        unsigned long,  msr             )
-               __field(        unsigned long,  dar             )
-               __field(        unsigned long,  srr1            )
+               __field(        __u32,  cpu_nr          )
+               __field(        __u32,  requests        )
        ),
 
        TP_fast_assign(
-               struct kvmppc_book3s_shadow_vcpu *svcpu;
-               __entry->exit_nr        = exit_nr;
-               __entry->pc             = kvmppc_get_pc(vcpu);
-               __entry->dar            = kvmppc_get_fault_dar(vcpu);
-               __entry->msr            = vcpu->arch.shared->msr;
-               svcpu = svcpu_get(vcpu);
-               __entry->srr1           = svcpu->shadow_srr1;
-               svcpu_put(svcpu);
+               __entry->cpu_nr         = vcpu->vcpu_id;
+               __entry->requests       = vcpu->requests;
        ),
 
-       TP_printk("exit=0x%x | pc=0x%lx | msr=0x%lx | dar=0x%lx | srr1=0x%lx",
-                 __entry->exit_nr, __entry->pc, __entry->msr, __entry->dar,
-                 __entry->srr1)
+       TP_printk("vcpu=%x requests=%x",
+               __entry->cpu_nr, __entry->requests)
 );
 
+
+/*************************************************************************
+ *                         Book3S trace points                           *
+ *************************************************************************/
+
+#ifdef CONFIG_KVM_BOOK3S_PR
+
 TRACE_EVENT(kvm_book3s_reenter,
        TP_PROTO(int r, struct kvm_vcpu *vcpu),
        TP_ARGS(r, vcpu),
@@ -395,6 +505,44 @@ TRACE_EVENT(kvm_booke206_gtlb_write,
                __entry->mas2, __entry->mas7_3)
 );
 
+TRACE_EVENT(kvm_booke206_ref_release,
+       TP_PROTO(__u64 pfn, __u32 flags),
+       TP_ARGS(pfn, flags),
+
+       TP_STRUCT__entry(
+               __field(        __u64,  pfn             )
+               __field(        __u32,  flags           )
+       ),
+
+       TP_fast_assign(
+               __entry->pfn            = pfn;
+               __entry->flags          = flags;
+       ),
+
+       TP_printk("pfn=%llx flags=%x",
+               __entry->pfn, __entry->flags)
+);
+
+TRACE_EVENT(kvm_booke_queue_irqprio,
+       TP_PROTO(struct kvm_vcpu *vcpu, unsigned int priority),
+       TP_ARGS(vcpu, priority),
+
+       TP_STRUCT__entry(
+               __field(        __u32,  cpu_nr          )
+               __field(        __u32,  priority                )
+               __field(        unsigned long,  pending         )
+       ),
+
+       TP_fast_assign(
+               __entry->cpu_nr         = vcpu->vcpu_id;
+               __entry->priority       = priority;
+               __entry->pending        = vcpu->arch.pending_exceptions;
+       ),
+
+       TP_printk("vcpu=%x prio=%x pending=%lx",
+               __entry->cpu_nr, __entry->priority, __entry->pending)
+);
+
 #endif
 
 #endif /* _TRACE_KVM_H */
index 8520b58a5e9a0f0027a95f0df2662cbab898c5cc..b89ef65392dc229b4ec026e23ddd9c5228ed05f1 100644 (file)
@@ -372,10 +372,11 @@ static int mpc52xx_irqhost_map(struct irq_domain *h, unsigned int virq,
        case MPC52xx_IRQ_L1_MAIN: irqchip = &mpc52xx_main_irqchip; break;
        case MPC52xx_IRQ_L1_PERP: irqchip = &mpc52xx_periph_irqchip; break;
        case MPC52xx_IRQ_L1_SDMA: irqchip = &mpc52xx_sdma_irqchip; break;
-       default:
-               pr_err("%s: invalid irq: virq=%i, l1=%i, l2=%i\n",
-                      __func__, virq, l1irq, l2irq);
-               return -EINVAL;
+       case MPC52xx_IRQ_L1_CRIT:
+               pr_warn("%s: Critical IRQ #%d is unsupported! Nopping it.\n",
+                       __func__, l2irq);
+               irq_set_chip(virq, &no_irq_chip);
+               return 0;
        }
 
        irq_set_chip_and_handler(virq, irqchip, handle_level_irq);
index e7a896acd982798d20650bd9b0bd9df9aa202bff..48a920d514892b2e238a9bcfc60050cb25f95f00 100644 (file)
@@ -90,6 +90,7 @@ config MPIC
 config PPC_EPAPR_HV_PIC
        bool
        default n
+       select EPAPR_PARAVIRT
 
 config MPIC_WEIRD
        bool
index 51ffafae561ea5a4a12da1f401c76da164811fff..63c5f04ea580177649aba38d101cb3f86b40cb35 100644 (file)
@@ -236,7 +236,6 @@ static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc)
        u32 intr_index;
        u32 have_shift = 0;
        struct fsl_msi_cascade_data *cascade_data;
-       unsigned int ret;
 
        cascade_data = irq_get_handler_data(irq);
        msi_data = cascade_data->msi_data;
@@ -268,7 +267,9 @@ static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc)
        case FSL_PIC_IP_IPIC:
                msir_value = fsl_msi_read(msi_data->msi_regs, msir_index * 0x4);
                break;
-       case FSL_PIC_IP_VMPIC:
+#ifdef CONFIG_EPAPR_PARAVIRT
+       case FSL_PIC_IP_VMPIC: {
+               unsigned int ret;
                ret = fh_vmpic_get_msir(virq_to_hw(irq), &msir_value);
                if (ret) {
                        pr_err("fsl-msi: fh_vmpic_get_msir() failed for "
@@ -277,6 +278,8 @@ static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc)
                }
                break;
        }
+#endif
+       }
 
        while (msir_value) {
                intr_index = ffs(msir_value) - 1;
@@ -508,10 +511,12 @@ static const struct of_device_id fsl_of_msi_ids[] = {
                .compatible = "fsl,ipic-msi",
                .data = &ipic_msi_feature,
        },
+#ifdef CONFIG_EPAPR_PARAVIRT
        {
                .compatible = "fsl,vmpic-msi",
                .data = &vmpic_msi_feature,
        },
+#endif
        {}
 };
 
index c449dbd1c938f749447bf04944dde0e6ca1450e1..97118dc3d2851b7a33ce46a4aec162ff1cc4bba5 100644 (file)
@@ -253,6 +253,7 @@ struct platform_diu_data_ops diu_ops;
 EXPORT_SYMBOL(diu_ops);
 #endif
 
+#ifdef CONFIG_EPAPR_PARAVIRT
 /*
  * Restart the current partition
  *
@@ -278,3 +279,4 @@ void fsl_hv_halt(void)
        pr_info("hv exit\n");
        fh_partition_stop(-1);
 }
+#endif
index 3cdc0f1978ada13e1bef8042ae427af5166c8324..af431de6363c6e1d2afcfa030582c74e5b5dda9b 100644 (file)
@@ -130,6 +130,7 @@ config S390
        select ARCH_INLINE_WRITE_UNLOCK_IRQRESTORE
        select HAVE_UID16 if 32BIT
        select ARCH_WANT_IPC_PARSE_VERSION
+       select HAVE_ARCH_TRANSPARENT_HUGEPAGE if 64BIT
        select GENERIC_SMP_IDLE_THREAD
        select GENERIC_TIME_VSYSCALL_OLD
        select GENERIC_CLOCKEVENTS
index d80f79d8dd9cd03d237ee2e7af1531abba69f2b2..8e1fb82392873669ce34b03ed34f18b64cc5b2de 100644 (file)
@@ -5,7 +5,7 @@ OUTPUT_FORMAT("elf64-s390", "elf64-s390", "elf64-s390")
 OUTPUT_ARCH(s390:64-bit)
 #else
 OUTPUT_FORMAT("elf32-s390", "elf32-s390", "elf32-s390")
-OUTPUT_ARCH(s390)
+OUTPUT_ARCH(s390:31-bit)
 #endif
 
 ENTRY(startup)
index 7941968e12b48ced12b4122918f111485de1dc4e..5f0173a31693b19700b8afa92b60db199bfcb749 100644 (file)
@@ -9,7 +9,7 @@
 #include <asm/cpu_mf.h>
 
 /* CPU-measurement counter facility */
-#define PERF_CPUM_CF_MAX_CTR           160
+#define PERF_CPUM_CF_MAX_CTR           256
 
 /* Per-CPU flags for PMU states */
 #define PMU_F_RESERVED                 0x1000
index dd647c919a66c766a75a8114588f1cd51afdafd7..28469202eadbfbb33970b889ca4eff4f82b42f30 100644 (file)
@@ -345,6 +345,8 @@ extern unsigned long MODULES_END;
 #define _REGION3_ENTRY         (_REGION_ENTRY_TYPE_R3 | _REGION_ENTRY_LENGTH)
 #define _REGION3_ENTRY_EMPTY   (_REGION_ENTRY_TYPE_R3 | _REGION_ENTRY_INV)
 
+#define _REGION3_ENTRY_LARGE   0x400   /* RTTE-format control, large page  */
+
 /* Bits in the segment table entry */
 #define _SEGMENT_ENTRY_ORIGIN  ~0x7ffUL/* segment table origin             */
 #define _SEGMENT_ENTRY_RO      0x200   /* page protection bit              */
@@ -444,6 +446,7 @@ static inline int pgd_bad(pgd_t pgd)     { return 0; }
 
 static inline int pud_present(pud_t pud) { return 1; }
 static inline int pud_none(pud_t pud)   { return 0; }
+static inline int pud_large(pud_t pud)  { return 0; }
 static inline int pud_bad(pud_t pud)    { return 0; }
 
 #else /* CONFIG_64BIT */
@@ -489,6 +492,13 @@ static inline int pud_none(pud_t pud)
        return (pud_val(pud) & _REGION_ENTRY_INV) != 0UL;
 }
 
+static inline int pud_large(pud_t pud)
+{
+       if ((pud_val(pud) & _REGION_ENTRY_TYPE_MASK) != _REGION_ENTRY_TYPE_R3)
+               return 0;
+       return !!(pud_val(pud) & _REGION3_ENTRY_LARGE);
+}
+
 static inline int pud_bad(pud_t pud)
 {
        /*
@@ -1240,6 +1250,19 @@ static inline void set_pmd_at(struct mm_struct *mm, unsigned long addr,
        *pmdp = entry;
 }
 
+static inline pgprot_t pmd_pgprot(pmd_t pmd)
+{
+       pgprot_t prot = PAGE_RW;
+
+       if (pmd_val(pmd) & _SEGMENT_ENTRY_RO) {
+               if (pmd_val(pmd) & _SEGMENT_ENTRY_INV)
+                       prot = PAGE_NONE;
+               else
+                       prot = PAGE_RO;
+       }
+       return prot;
+}
+
 static inline unsigned long massage_pgprot_pmd(pgprot_t pgprot)
 {
        unsigned long pgprot_pmd = 0;
index 59b67ed423b422bb6ed353f516b796278f5bcb38..7bf68fff7c5d28cd2255d8d86189eb55368ddd71 100644 (file)
@@ -1,8 +1,6 @@
 # UAPI Header export list
 include include/uapi/asm-generic/Kbuild.asm
 
-generic-y += kvm_para.h
-
 header-y += auxvec.h
 header-y += bitsperlong.h
 header-y += byteorder.h
index 581992dfae27b605e49a8a6f5d2972cc0646fadc..6b4fb29cc197e5d9544fd124e61a742a41114464 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *    Copyright IBM Corp. 2007
+ *    Copyright IBM Corp. 2007, 2012
  *    Author(s): Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
  */
 
 #define __MAX_CHPID 255
 
 struct chp_id {
-       u8 reserved1;
-       u8 cssid;
-       u8 reserved2;
-       u8 id;
+       __u8 reserved1;
+       __u8 cssid;
+       __u8 reserved2;
+       __u8 id;
 } __attribute__((packed));
 
 
diff --git a/arch/s390/include/uapi/asm/kvm_para.h b/arch/s390/include/uapi/asm/kvm_para.h
new file mode 100644 (file)
index 0000000..ff1f4e7
--- /dev/null
@@ -0,0 +1,11 @@
+/*
+ * User API definitions for paravirtual devices on s390
+ *
+ * Copyright IBM Corp. 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License (version 2 only)
+ * as published by the Free Software Foundation.
+ *
+ *    Author(s): Christian Borntraeger <borntraeger@de.ibm.com>
+ */
index 4da52fe317437e312e509b05d28a5d92ed681d5d..2ac311ef5c9b11a3b37aa4f5586a240aa14679a6 100644 (file)
@@ -23,7 +23,7 @@ CFLAGS_sysinfo.o += -Iinclude/math-emu -Iarch/s390/math-emu -w
 obj-y  :=  bitmap.o traps.o time.o process.o base.o early.o setup.o vtime.o \
            processor.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o nmi.o \
            debug.o irq.o ipl.o dis.o diag.o mem_detect.o sclp.o vdso.o \
-           sysinfo.o jump_label.o lgr.o os_info.o machine_kexec.o
+           sysinfo.o jump_label.o lgr.o os_info.o machine_kexec.o pgm_check.o
 
 obj-y  += $(if $(CONFIG_64BIT),entry64.o,entry.o)
 obj-y  += $(if $(CONFIG_64BIT),reipl64.o,reipl.o)
index 8df8d8a19c986e1b2fea8db91cf59d329fc3b877..64b24650e4f8c1d43f5cf151b46478f5a602e277 100644 (file)
@@ -59,8 +59,8 @@ enum {
 
 enum {
        CACHE_TI_UNIFIED = 0,
-       CACHE_TI_INSTRUCTION = 0,
-       CACHE_TI_DATA,
+       CACHE_TI_DATA = 0,
+       CACHE_TI_INSTRUCTION,
 };
 
 struct cache_info {
@@ -121,7 +121,10 @@ static int __init cache_add(int level, int private, int type)
        cache = kzalloc(sizeof(*cache), GFP_KERNEL);
        if (!cache)
                return -ENOMEM;
-       ti = type == CACHE_TYPE_DATA ? CACHE_TI_DATA : CACHE_TI_UNIFIED;
+       if (type == CACHE_TYPE_INSTRUCTION)
+               ti = CACHE_TI_INSTRUCTION;
+       else
+               ti = CACHE_TI_UNIFIED;
        cache->size = ecag(EXTRACT_SIZE, level, ti);
        cache->line_size = ecag(EXTRACT_LINE_SIZE, level, ti);
        cache->associativity = ecag(EXTRACT_ASSOCIATIVITY, level, ti);
index d0d3f69a73463744edc3d3ec53fdd37dddd0adca..80ebb985f3b9b49335f58d7ca6609edca759b3e9 100644 (file)
@@ -6,7 +6,6 @@
 #include <asm/ptrace.h>
 #include <asm/cputime.h>
 
-extern void (*pgm_check_table[128])(struct pt_regs *);
 extern void *restart_stack;
 
 void system_call(void);
@@ -25,6 +24,26 @@ void do_protection_exception(struct pt_regs *regs);
 void do_dat_exception(struct pt_regs *regs);
 void do_asce_exception(struct pt_regs *regs);
 
+void addressing_exception(struct pt_regs *regs);
+void data_exception(struct pt_regs *regs);
+void default_trap_handler(struct pt_regs *regs);
+void divide_exception(struct pt_regs *regs);
+void execute_exception(struct pt_regs *regs);
+void hfp_divide_exception(struct pt_regs *regs);
+void hfp_overflow_exception(struct pt_regs *regs);
+void hfp_significance_exception(struct pt_regs *regs);
+void hfp_sqrt_exception(struct pt_regs *regs);
+void hfp_underflow_exception(struct pt_regs *regs);
+void illegal_op(struct pt_regs *regs);
+void operand_exception(struct pt_regs *regs);
+void overflow_exception(struct pt_regs *regs);
+void privileged_op(struct pt_regs *regs);
+void space_switch_exception(struct pt_regs *regs);
+void special_op_exception(struct pt_regs *regs);
+void specification_exception(struct pt_regs *regs);
+void transaction_exception(struct pt_regs *regs);
+void translation_exception(struct pt_regs *regs);
+
 void do_per_trap(struct pt_regs *regs);
 void syscall_trace(struct pt_regs *regs, int entryexit);
 void kernel_stack_overflow(struct pt_regs * regs);
index 499e95e90f38d9d785609a3c0ed2d1e41a5c8f15..e983ddb872477e2109df611972eaebb07eca5d4e 100644 (file)
@@ -413,9 +413,9 @@ ENTRY(pgm_check_handler)
        larl    %r1,pgm_check_table
        llgh    %r10,__PT_INT_CODE+2(%r11)
        nill    %r10,0x007f
-       sll     %r10,3
+       sll     %r10,2
        je      sysc_return
-       lg      %r1,0(%r10,%r1)         # load address of handler routine
+       lgf     %r1,0(%r10,%r1)         # load address of handler routine
        lgr     %r2,%r11                # pass pointer to pt_regs
        basr    %r14,%r1                # branch to interrupt-handler
        j       sysc_return
index acaaaf4b7055e2d50122f43e6f695771a6f781cd..085a95eb315f480dc2edb492fc58a80dde0ae7d5 100644 (file)
 .align 2
 startup_kdump_relocated:
        basr    %r13,0
-0:
-       mvc     0(8,%r0),.Lrestart_psw-0b(%r13) # Setup restart PSW
-       sam31                                   # Switch to 31 bit addr mode
-       sr      %r1,%r1                         # Erase register r1
-       sr      %r2,%r2                         # Erase register r2
-       sigp    %r1,%r2,SIGP_SET_ARCHITECTURE   # Switch to 31 bit arch mode
-       lpsw    0                               # Start new kernel...
+0:     lpswe   .Lrestart_psw-0b(%r13)          # Start new kernel...
 .align 8
 .Lrestart_psw:
-       .long   0x00080000,0x80000000 + startup
+       .quad   0x0000000080000000,0x0000000000000000 + startup
 #else
 .align 2
 .Lep_startup_kdump:
index 9871b1971ed7602a7efef88fc62d019dde3b98c4..c4e7269d4a0980d8736c5a9c32e916cb581b0a58 100644 (file)
@@ -94,7 +94,7 @@ static int get_counter_set(u64 event)
                set = CPUMF_CTR_SET_USER;
        else if (event < 128)
                set = CPUMF_CTR_SET_CRYPTO;
-       else if (event < 160)
+       else if (event < 256)
                set = CPUMF_CTR_SET_EXT;
 
        return set;
@@ -138,6 +138,10 @@ static int validate_ctr_version(const struct hw_perf_event *hwc)
        case CPUMF_CTR_SET_EXT:
                if (cpuhw->info.csvn < 1)
                        err = -EOPNOTSUPP;
+               if ((cpuhw->info.csvn == 1 && hwc->config > 159) ||
+                   (cpuhw->info.csvn == 2 && hwc->config > 175) ||
+                   (cpuhw->info.csvn  > 2 && hwc->config > 255))
+                       err = -EOPNOTSUPP;
                break;
        }
 
diff --git a/arch/s390/kernel/pgm_check.S b/arch/s390/kernel/pgm_check.S
new file mode 100644 (file)
index 0000000..14bdecb
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ *    Program check table.
+ *
+ *    Copyright IBM Corp. 2012
+ */
+
+#include <linux/linkage.h>
+
+#ifdef CONFIG_32BIT
+#define PGM_CHECK_64BIT(handler) .long default_trap_handler
+#else
+#define PGM_CHECK_64BIT(handler) .long handler
+#endif
+
+#define PGM_CHECK(handler)     .long handler
+#define PGM_CHECK_DEFAULT      PGM_CHECK(default_trap_handler)
+
+/*
+ * The program check table contains exactly 128 (0x00-0x7f) entries. Each
+ * line defines the 31 and/or 64 bit function to be called corresponding
+ * to the program check interruption code.
+ */
+.section .rodata, "a"
+ENTRY(pgm_check_table)
+PGM_CHECK_DEFAULT                      /* 00 */
+PGM_CHECK(illegal_op)                  /* 01 */
+PGM_CHECK(privileged_op)               /* 02 */
+PGM_CHECK(execute_exception)           /* 03 */
+PGM_CHECK(do_protection_exception)     /* 04 */
+PGM_CHECK(addressing_exception)                /* 05 */
+PGM_CHECK(specification_exception)     /* 06 */
+PGM_CHECK(data_exception)              /* 07 */
+PGM_CHECK(overflow_exception)          /* 08 */
+PGM_CHECK(divide_exception)            /* 09 */
+PGM_CHECK(overflow_exception)          /* 0a */
+PGM_CHECK(divide_exception)            /* 0b */
+PGM_CHECK(hfp_overflow_exception)      /* 0c */
+PGM_CHECK(hfp_underflow_exception)     /* 0d */
+PGM_CHECK(hfp_significance_exception)  /* 0e */
+PGM_CHECK(hfp_divide_exception)                /* 0f */
+PGM_CHECK(do_dat_exception)            /* 10 */
+PGM_CHECK(do_dat_exception)            /* 11 */
+PGM_CHECK(translation_exception)       /* 12 */
+PGM_CHECK(special_op_exception)                /* 13 */
+PGM_CHECK_DEFAULT                      /* 14 */
+PGM_CHECK(operand_exception)           /* 15 */
+PGM_CHECK_DEFAULT                      /* 16 */
+PGM_CHECK_DEFAULT                      /* 17 */
+PGM_CHECK_64BIT(transaction_exception) /* 18 */
+PGM_CHECK_DEFAULT                      /* 19 */
+PGM_CHECK_DEFAULT                      /* 1a */
+PGM_CHECK_DEFAULT                      /* 1b */
+PGM_CHECK(space_switch_exception)      /* 1c */
+PGM_CHECK(hfp_sqrt_exception)          /* 1d */
+PGM_CHECK_DEFAULT                      /* 1e */
+PGM_CHECK_DEFAULT                      /* 1f */
+PGM_CHECK_DEFAULT                      /* 20 */
+PGM_CHECK_DEFAULT                      /* 21 */
+PGM_CHECK_DEFAULT                      /* 22 */
+PGM_CHECK_DEFAULT                      /* 23 */
+PGM_CHECK_DEFAULT                      /* 24 */
+PGM_CHECK_DEFAULT                      /* 25 */
+PGM_CHECK_DEFAULT                      /* 26 */
+PGM_CHECK_DEFAULT                      /* 27 */
+PGM_CHECK_DEFAULT                      /* 28 */
+PGM_CHECK_DEFAULT                      /* 29 */
+PGM_CHECK_DEFAULT                      /* 2a */
+PGM_CHECK_DEFAULT                      /* 2b */
+PGM_CHECK_DEFAULT                      /* 2c */
+PGM_CHECK_DEFAULT                      /* 2d */
+PGM_CHECK_DEFAULT                      /* 2e */
+PGM_CHECK_DEFAULT                      /* 2f */
+PGM_CHECK_DEFAULT                      /* 30 */
+PGM_CHECK_DEFAULT                      /* 31 */
+PGM_CHECK_DEFAULT                      /* 32 */
+PGM_CHECK_DEFAULT                      /* 33 */
+PGM_CHECK_DEFAULT                      /* 34 */
+PGM_CHECK_DEFAULT                      /* 35 */
+PGM_CHECK_DEFAULT                      /* 36 */
+PGM_CHECK_DEFAULT                      /* 37 */
+PGM_CHECK_64BIT(do_asce_exception)     /* 38 */
+PGM_CHECK_64BIT(do_dat_exception)      /* 39 */
+PGM_CHECK_64BIT(do_dat_exception)      /* 3a */
+PGM_CHECK_64BIT(do_dat_exception)      /* 3b */
+PGM_CHECK_DEFAULT                      /* 3c */
+PGM_CHECK_DEFAULT                      /* 3d */
+PGM_CHECK_DEFAULT                      /* 3e */
+PGM_CHECK_DEFAULT                      /* 3f */
+PGM_CHECK_DEFAULT                      /* 40 */
+PGM_CHECK_DEFAULT                      /* 41 */
+PGM_CHECK_DEFAULT                      /* 42 */
+PGM_CHECK_DEFAULT                      /* 43 */
+PGM_CHECK_DEFAULT                      /* 44 */
+PGM_CHECK_DEFAULT                      /* 45 */
+PGM_CHECK_DEFAULT                      /* 46 */
+PGM_CHECK_DEFAULT                      /* 47 */
+PGM_CHECK_DEFAULT                      /* 48 */
+PGM_CHECK_DEFAULT                      /* 49 */
+PGM_CHECK_DEFAULT                      /* 4a */
+PGM_CHECK_DEFAULT                      /* 4b */
+PGM_CHECK_DEFAULT                      /* 4c */
+PGM_CHECK_DEFAULT                      /* 4d */
+PGM_CHECK_DEFAULT                      /* 4e */
+PGM_CHECK_DEFAULT                      /* 4f */
+PGM_CHECK_DEFAULT                      /* 50 */
+PGM_CHECK_DEFAULT                      /* 51 */
+PGM_CHECK_DEFAULT                      /* 52 */
+PGM_CHECK_DEFAULT                      /* 53 */
+PGM_CHECK_DEFAULT                      /* 54 */
+PGM_CHECK_DEFAULT                      /* 55 */
+PGM_CHECK_DEFAULT                      /* 56 */
+PGM_CHECK_DEFAULT                      /* 57 */
+PGM_CHECK_DEFAULT                      /* 58 */
+PGM_CHECK_DEFAULT                      /* 59 */
+PGM_CHECK_DEFAULT                      /* 5a */
+PGM_CHECK_DEFAULT                      /* 5b */
+PGM_CHECK_DEFAULT                      /* 5c */
+PGM_CHECK_DEFAULT                      /* 5d */
+PGM_CHECK_DEFAULT                      /* 5e */
+PGM_CHECK_DEFAULT                      /* 5f */
+PGM_CHECK_DEFAULT                      /* 60 */
+PGM_CHECK_DEFAULT                      /* 61 */
+PGM_CHECK_DEFAULT                      /* 62 */
+PGM_CHECK_DEFAULT                      /* 63 */
+PGM_CHECK_DEFAULT                      /* 64 */
+PGM_CHECK_DEFAULT                      /* 65 */
+PGM_CHECK_DEFAULT                      /* 66 */
+PGM_CHECK_DEFAULT                      /* 67 */
+PGM_CHECK_DEFAULT                      /* 68 */
+PGM_CHECK_DEFAULT                      /* 69 */
+PGM_CHECK_DEFAULT                      /* 6a */
+PGM_CHECK_DEFAULT                      /* 6b */
+PGM_CHECK_DEFAULT                      /* 6c */
+PGM_CHECK_DEFAULT                      /* 6d */
+PGM_CHECK_DEFAULT                      /* 6e */
+PGM_CHECK_DEFAULT                      /* 6f */
+PGM_CHECK_DEFAULT                      /* 70 */
+PGM_CHECK_DEFAULT                      /* 71 */
+PGM_CHECK_DEFAULT                      /* 72 */
+PGM_CHECK_DEFAULT                      /* 73 */
+PGM_CHECK_DEFAULT                      /* 74 */
+PGM_CHECK_DEFAULT                      /* 75 */
+PGM_CHECK_DEFAULT                      /* 76 */
+PGM_CHECK_DEFAULT                      /* 77 */
+PGM_CHECK_DEFAULT                      /* 78 */
+PGM_CHECK_DEFAULT                      /* 79 */
+PGM_CHECK_DEFAULT                      /* 7a */
+PGM_CHECK_DEFAULT                      /* 7b */
+PGM_CHECK_DEFAULT                      /* 7c */
+PGM_CHECK_DEFAULT                      /* 7d */
+PGM_CHECK_DEFAULT                      /* 7e */
+PGM_CHECK_DEFAULT                      /* 7f */
index 3d2b0fa37db09649f6bcf0861de452144c22b0da..70ecfc5fe8f0acc87b7fe0036df511f283b22dbe 100644 (file)
@@ -41,8 +41,6 @@
 #include <asm/ipl.h>
 #include "entry.h"
 
-void (*pgm_check_table[128])(struct pt_regs *regs);
-
 int show_unhandled_signals = 1;
 
 #define stack_pointer ({ void **sp; asm("la %0,0(15)" : "=&d" (sp)); sp; })
@@ -350,7 +348,7 @@ void __kprobes do_per_trap(struct pt_regs *regs)
        force_sig_info(SIGTRAP, &info, current);
 }
 
-static void default_trap_handler(struct pt_regs *regs)
+void default_trap_handler(struct pt_regs *regs)
 {
        if (user_mode(regs)) {
                report_user_fault(regs, SIGSEGV);
@@ -360,9 +358,9 @@ static void default_trap_handler(struct pt_regs *regs)
 }
 
 #define DO_ERROR_INFO(name, signr, sicode, str) \
-static void name(struct pt_regs *regs) \
-{ \
-       do_trap(regs, signr, sicode, str); \
+void name(struct pt_regs *regs)                        \
+{                                              \
+       do_trap(regs, signr, sicode, str);      \
 }
 
 DO_ERROR_INFO(addressing_exception, SIGILL, ILL_ILLADR,
@@ -417,7 +415,7 @@ static inline void do_fp_trap(struct pt_regs *regs, int fpc)
        do_trap(regs, SIGFPE, si_code, "floating point exception");
 }
 
-static void __kprobes illegal_op(struct pt_regs *regs)
+void __kprobes illegal_op(struct pt_regs *regs)
 {
        siginfo_t info;
         __u8 opcode[6];
@@ -536,7 +534,7 @@ DO_ERROR_INFO(specification_exception, SIGILL, ILL_ILLOPN,
              "specification exception");
 #endif
 
-static void data_exception(struct pt_regs *regs)
+void data_exception(struct pt_regs *regs)
 {
        __u16 __user *location;
        int signal = 0;
@@ -611,7 +609,7 @@ static void data_exception(struct pt_regs *regs)
                do_trap(regs, signal, ILL_ILLOPN, "data exception");
 }
 
-static void space_switch_exception(struct pt_regs *regs)
+void space_switch_exception(struct pt_regs *regs)
 {
        /* Set user psw back to home space mode. */
        if (user_mode(regs))
@@ -629,43 +627,7 @@ void __kprobes kernel_stack_overflow(struct pt_regs * regs)
        panic("Corrupt kernel stack, can't continue.");
 }
 
-/* init is done in lowcore.S and head.S */
-
 void __init trap_init(void)
 {
-        int i;
-
-        for (i = 0; i < 128; i++)
-          pgm_check_table[i] = &default_trap_handler;
-        pgm_check_table[1] = &illegal_op;
-        pgm_check_table[2] = &privileged_op;
-        pgm_check_table[3] = &execute_exception;
-        pgm_check_table[4] = &do_protection_exception;
-        pgm_check_table[5] = &addressing_exception;
-        pgm_check_table[6] = &specification_exception;
-        pgm_check_table[7] = &data_exception;
-        pgm_check_table[8] = &overflow_exception;
-        pgm_check_table[9] = &divide_exception;
-        pgm_check_table[0x0A] = &overflow_exception;
-        pgm_check_table[0x0B] = &divide_exception;
-        pgm_check_table[0x0C] = &hfp_overflow_exception;
-        pgm_check_table[0x0D] = &hfp_underflow_exception;
-        pgm_check_table[0x0E] = &hfp_significance_exception;
-        pgm_check_table[0x0F] = &hfp_divide_exception;
-        pgm_check_table[0x10] = &do_dat_exception;
-        pgm_check_table[0x11] = &do_dat_exception;
-        pgm_check_table[0x12] = &translation_exception;
-        pgm_check_table[0x13] = &special_op_exception;
-#ifdef CONFIG_64BIT
-       pgm_check_table[0x18] = &transaction_exception;
-       pgm_check_table[0x38] = &do_asce_exception;
-       pgm_check_table[0x39] = &do_dat_exception;
-       pgm_check_table[0x3A] = &do_dat_exception;
-        pgm_check_table[0x3B] = &do_dat_exception;
-#endif /* CONFIG_64BIT */
-        pgm_check_table[0x15] = &operand_exception;
-        pgm_check_table[0x1C] = &space_switch_exception;
-        pgm_check_table[0x1D] = &hfp_sqrt_exception;
-       /* Enable machine checks early. */
        local_mcck_enable();
 }
index de8fa9bbd35ee9787537e93c18b561b75cacf72f..79cb51adc7419b52245d444c74e2c9378eaf99ab 100644 (file)
@@ -8,7 +8,7 @@
 
 #ifndef CONFIG_64BIT
 OUTPUT_FORMAT("elf32-s390", "elf32-s390", "elf32-s390")
-OUTPUT_ARCH(s390)
+OUTPUT_ARCH(s390:31-bit)
 ENTRY(startup)
 jiffies = jiffies_64 + 4;
 #else
index ff1e2f8ef94a02146e9b90e56c7105f9e9b140f3..c30615e605ac6716a1f93ee8dc377f9691ee99e0 100644 (file)
@@ -629,10 +629,27 @@ int kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu,
                break;
        case KVM_S390_SIGP_STOP:
        case KVM_S390_RESTART:
+               VCPU_EVENT(vcpu, 3, "inject: type %x", s390int->type);
+               inti->type = s390int->type;
+               break;
        case KVM_S390_INT_EXTERNAL_CALL:
+               if (s390int->parm & 0xffff0000) {
+                       kfree(inti);
+                       return -EINVAL;
+               }
+               VCPU_EVENT(vcpu, 3, "inject: external call source-cpu:%u",
+                          s390int->parm);
+               inti->type = s390int->type;
+               inti->extcall.code = s390int->parm;
+               break;
        case KVM_S390_INT_EMERGENCY:
-               VCPU_EVENT(vcpu, 3, "inject: type %x", s390int->type);
+               if (s390int->parm & 0xffff0000) {
+                       kfree(inti);
+                       return -EINVAL;
+               }
+               VCPU_EVENT(vcpu, 3, "inject: emergency %u\n", s390int->parm);
                inti->type = s390int->type;
+               inti->emerg.code = s390int->parm;
                break;
        case KVM_S390_INT_VIRTIO:
        case KVM_S390_INT_SERVICE:
index ecced9d18986895fc8af13680a876d5f0cf532db..38883f0bf27e0e8ec9c864133bc5bd6939770888 100644 (file)
@@ -997,7 +997,7 @@ static int __init kvm_s390_init(void)
        }
        memcpy(facilities, S390_lowcore.stfle_fac_list, 16);
        facilities[0] &= 0xff00fff3f47c0000ULL;
-       facilities[1] &= 0x201c000000000000ULL;
+       facilities[1] &= 0x001c000000000000ULL;
        return 0;
 }
 
index cbc6668acb85e8dd5b6100410a1fcd887e97df1d..04e4892247d2081f1087897613d0028149133a72 100644 (file)
@@ -150,6 +150,7 @@ static void walk_pmd_level(struct seq_file *m, struct pg_state *st,
 static void walk_pud_level(struct seq_file *m, struct pg_state *st,
                           pgd_t *pgd, unsigned long addr)
 {
+       unsigned int prot;
        pud_t *pud;
        int i;
 
@@ -157,7 +158,11 @@ static void walk_pud_level(struct seq_file *m, struct pg_state *st,
                st->current_address = addr;
                pud = pud_offset(pgd, addr);
                if (!pud_none(*pud))
-                       walk_pmd_level(m, st, pud, addr);
+                       if (pud_large(*pud)) {
+                               prot = pud_val(*pud) & _PAGE_RO;
+                               note_page(m, st, prot, 2);
+                       } else
+                               walk_pmd_level(m, st, pud, addr);
                else
                        note_page(m, st, _PAGE_INVALID, 2);
                addr += PUD_SIZE;
index 00be01c4b4f3fc3ee8242ea1e7b6921bfc6afc2a..c7ec7c2e46b0864d7010bce697c2df0f0691cf26 100644 (file)
@@ -19,7 +19,7 @@ static pte_t *walk_page_table(unsigned long addr)
        if (pgd_none(*pgdp))
                return NULL;
        pudp = pud_offset(pgdp, addr);
-       if (pud_none(*pudp))
+       if (pud_none(*pudp) || pud_large(*pudp))
                return NULL;
        pmdp = pmd_offset(pudp, addr);
        if (pmd_none(*pmdp) || pmd_large(*pmdp))
index 387c7c60b5b8d65a50bec087a54288a1cc913519..6ed1426d27c55ff893b22a9ae2d2876c8bccb3c5 100644 (file)
@@ -89,6 +89,7 @@ static int vmem_add_mem(unsigned long start, unsigned long size, int ro)
        int ret = -ENOMEM;
 
        while (address < end) {
+               pte = mk_pte_phys(address, __pgprot(ro ? _PAGE_RO : 0));
                pg_dir = pgd_offset_k(address);
                if (pgd_none(*pg_dir)) {
                        pu_dir = vmem_pud_alloc();
@@ -96,18 +97,24 @@ static int vmem_add_mem(unsigned long start, unsigned long size, int ro)
                                goto out;
                        pgd_populate(&init_mm, pg_dir, pu_dir);
                }
-
                pu_dir = pud_offset(pg_dir, address);
+#if defined(CONFIG_64BIT) && !defined(CONFIG_DEBUG_PAGEALLOC)
+               if (MACHINE_HAS_EDAT2 && pud_none(*pu_dir) && address &&
+                   !(address & ~PUD_MASK) && (address + PUD_SIZE <= end)) {
+                       pte_val(pte) |= _REGION3_ENTRY_LARGE;
+                       pte_val(pte) |= _REGION_ENTRY_TYPE_R3;
+                       pud_val(*pu_dir) = pte_val(pte);
+                       address += PUD_SIZE;
+                       continue;
+               }
+#endif
                if (pud_none(*pu_dir)) {
                        pm_dir = vmem_pmd_alloc();
                        if (!pm_dir)
                                goto out;
                        pud_populate(&init_mm, pu_dir, pm_dir);
                }
-
-               pte = mk_pte_phys(address, __pgprot(ro ? _PAGE_RO : 0));
                pm_dir = pmd_offset(pu_dir, address);
-
 #if defined(CONFIG_64BIT) && !defined(CONFIG_DEBUG_PAGEALLOC)
                if (MACHINE_HAS_EDAT1 && pmd_none(*pm_dir) && address &&
                    !(address & ~PMD_MASK) && (address + PMD_SIZE <= end)) {
@@ -160,6 +167,11 @@ static void vmem_remove_range(unsigned long start, unsigned long size)
                        address += PUD_SIZE;
                        continue;
                }
+               if (pud_large(*pu_dir)) {
+                       pud_clear(pu_dir);
+                       address += PUD_SIZE;
+                       continue;
+               }
                pm_dir = pmd_offset(pu_dir, address);
                if (pmd_none(*pm_dir)) {
                        address += PMD_SIZE;
@@ -193,7 +205,7 @@ int __meminit vmemmap_populate(struct page *start, unsigned long nr, int node)
        start_addr = (unsigned long) start;
        end_addr = (unsigned long) (start + nr);
 
-       for (address = start_addr; address < end_addr; address += PAGE_SIZE) {
+       for (address = start_addr; address < end_addr;) {
                pg_dir = pgd_offset_k(address);
                if (pgd_none(*pg_dir)) {
                        pu_dir = vmem_pud_alloc();
@@ -212,10 +224,33 @@ int __meminit vmemmap_populate(struct page *start, unsigned long nr, int node)
 
                pm_dir = pmd_offset(pu_dir, address);
                if (pmd_none(*pm_dir)) {
+#ifdef CONFIG_64BIT
+                       /* Use 1MB frames for vmemmap if available. We always
+                        * use large frames even if they are only partially
+                        * used.
+                        * Otherwise we would have also page tables since
+                        * vmemmap_populate gets called for each section
+                        * separately. */
+                       if (MACHINE_HAS_EDAT1) {
+                               void *new_page;
+
+                               new_page = vmemmap_alloc_block(PMD_SIZE, node);
+                               if (!new_page)
+                                       goto out;
+                               pte = mk_pte_phys(__pa(new_page), PAGE_RW);
+                               pte_val(pte) |= _SEGMENT_ENTRY_LARGE;
+                               pmd_val(*pm_dir) = pte_val(pte);
+                               address = (address + PMD_SIZE) & PMD_MASK;
+                               continue;
+                       }
+#endif
                        pt_dir = vmem_pte_alloc(address);
                        if (!pt_dir)
                                goto out;
                        pmd_populate(&init_mm, pm_dir, pt_dir);
+               } else if (pmd_large(*pm_dir)) {
+                       address = (address + PMD_SIZE) & PMD_MASK;
+                       continue;
                }
 
                pt_dir = pte_offset_kernel(pm_dir, address);
@@ -228,6 +263,7 @@ int __meminit vmemmap_populate(struct page *start, unsigned long nr, int node)
                        pte = pfn_pte(new_page >> PAGE_SHIFT, PAGE_KERNEL);
                        *pt_dir = pte;
                }
+               address += PAGE_SIZE;
        }
        memset(start, 0, nr * sizeof(struct page));
        ret = 0;
index 73a23f4617a37c5a5270d5bc50d9689af45d8f89..629db2ad79162173dec3e903fd4af568e16c8839 100644 (file)
@@ -382,7 +382,7 @@ static inline int iounmap_fixed(void __iomem *addr) { return -EINVAL; }
 #define xlate_dev_kmem_ptr(p)  p
 
 #define ARCH_HAS_VALID_PHYS_ADDR_RANGE
-int valid_phys_addr_range(unsigned long addr, size_t size);
+int valid_phys_addr_range(phys_addr_t addr, size_t size);
 int valid_mmap_phys_addr_range(unsigned long pfn, size_t size);
 
 #endif /* __KERNEL__ */
index 0c2f1b2c2e1973440465e679ec1dd674e2522836..42d991f632b1f4b013b55af71df2a81f143b6090 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/serial_sci.h>
 #include <linux/sh_timer.h>
 #include <linux/sh_intc.h>
+#include <linux/usb/ohci_pdriver.h>
 #include <asm/rtc.h>
 #include <cpu/serial.h>
 
@@ -103,12 +104,15 @@ static struct resource usb_ohci_resources[] = {
 
 static u64 usb_ohci_dma_mask = 0xffffffffUL;
 
+static struct usb_ohci_pdata usb_ohci_pdata;
+
 static struct platform_device usb_ohci_device = {
-       .name           = "sh_ohci",
+       .name           = "ohci-platform",
        .id             = -1,
        .dev = {
                .dma_mask               = &usb_ohci_dma_mask,
                .coherent_dma_mask      = 0xffffffff,
+               .platform_data          = &usb_ohci_pdata,
        },
        .num_resources  = ARRAY_SIZE(usb_ohci_resources),
        .resource       = usb_ohci_resources,
index 4a2f357f4df8a1b93fd285b0e0c461dbbc2897d5..9079a0f9ea9be7b48369ffd7bcc2e6e516916326 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/sh_timer.h>
 #include <linux/sh_dma.h>
 #include <linux/sh_intc.h>
+#include <linux/usb/ohci_pdriver.h>
 #include <cpu/dma-register.h>
 #include <cpu/sh7757.h>
 
@@ -750,12 +751,15 @@ static struct resource usb_ohci_resources[] = {
        },
 };
 
+static struct usb_ohci_pdata usb_ohci_pdata;
+
 static struct platform_device usb_ohci_device = {
-       .name           = "sh_ohci",
+       .name           = "ohci-platform",
        .id             = -1,
        .dev = {
                .dma_mask = &usb_ohci_device.dev.coherent_dma_mask,
                .coherent_dma_mask = DMA_BIT_MASK(32),
+               .platform_data  = &usb_ohci_pdata,
        },
        .num_resources  = ARRAY_SIZE(usb_ohci_resources),
        .resource       = usb_ohci_resources,
index bd0a8fbe610f678077cad20dc1b5af07f9b46b8b..1686acaaf45af226a8f6809f937896abee8000c5 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/sh_intc.h>
 #include <linux/io.h>
 #include <linux/serial_sci.h>
+#include <linux/usb/ohci_pdriver.h>
 
 static struct plat_sci_port scif0_platform_data = {
        .mapbase        = 0xffe00000,
@@ -106,12 +107,15 @@ static struct resource usb_ohci_resources[] = {
 
 static u64 usb_ohci_dma_mask = 0xffffffffUL;
 
+static struct usb_ohci_pdata usb_ohci_pdata;
+
 static struct platform_device usb_ohci_device = {
-       .name           = "sh_ohci",
+       .name           = "ohci-platform",
        .id             = -1,
        .dev = {
                .dma_mask               = &usb_ohci_dma_mask,
                .coherent_dma_mask      = 0xffffffff,
+               .platform_data          = &usb_ohci_pdata,
        },
        .num_resources  = ARRAY_SIZE(usb_ohci_resources),
        .resource       = usb_ohci_resources,
index 2e6952f87848e287a6ad042414fc8f3d9532ccc8..ab52d4d4484d460bffc3b66ec9be5a60287d92cd 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/sh_timer.h>
 #include <linux/sh_dma.h>
 #include <linux/sh_intc.h>
+#include <linux/usb/ohci_pdriver.h>
 #include <cpu/dma-register.h>
 #include <asm/mmzone.h>
 
@@ -583,12 +584,15 @@ static struct resource usb_ohci_resources[] = {
        },
 };
 
+static struct usb_ohci_pdata usb_ohci_pdata;
+
 static struct platform_device usb_ohci_device = {
-       .name           = "sh_ohci",
+       .name           = "ohci-platform",
        .id             = -1,
        .dev = {
                .dma_mask               = &usb_ohci_device.dev.coherent_dma_mask,
                .coherent_dma_mask      = DMA_BIT_MASK(32),
+               .platform_data          = &usb_ohci_pdata,
        },
        .num_resources  = ARRAY_SIZE(usb_ohci_resources),
        .resource       = usb_ohci_resources,
index cb8f9920f4dd873b69050e81c4a46fc7e40f5007..1210cc74f86292a6a3b79b025d0519335821226c 100644 (file)
@@ -111,6 +111,7 @@ config VSYSCALL
 config NUMA
        bool "Non Uniform Memory Access (NUMA) Support"
        depends on MMU && SYS_SUPPORTS_NUMA && EXPERIMENTAL
+       select EMBEDDED_NUMA
        default n
        help
          Some SH systems have many various memories scattered around
index afeb710ec5c35d06926717a7f666f373ea366887..80bf494ddbcb4c86c1852d82fadfb973de89b435 100644 (file)
@@ -238,7 +238,7 @@ bottomup:
  * You really shouldn't be using read() or write() on /dev/mem.  This
  * might go away in the future.
  */
-int valid_phys_addr_range(unsigned long addr, size_t count)
+int valid_phys_addr_range(phys_addr_t addr, size_t count)
 {
        if (addr < __MEMORY_START)
                return 0;
index 55640cf92597b11f943173928b4d7d7437d4be14..3d15364c60714bf661da140c8f6e67cde20001b3 100644 (file)
@@ -26,6 +26,10 @@ $(error Set TILERA_ROOT or CROSS_COMPILE when building $(ARCH) on $(HOST_ARCH))
   endif
 endif
 
+# The tile compiler may emit .eh_frame information for backtracing.
+# In kernel modules, this causes load failures due to unsupported relocations.
+KBUILD_CFLAGS   += -fno-asynchronous-unwind-tables
+
 ifneq ($(CONFIG_DEBUG_EXTRA_FLAGS),"")
 KBUILD_CFLAGS   += $(CONFIG_DEBUG_EXTRA_FLAGS)
 endif
index 001cbfa10ac6364a9136b9d4440bfe69730a08be..243ffebe38d69a510f16e53083c49b46f3e6531b 100644 (file)
 #include <asm/homecache.h>
 #include <arch/opcode.h>
 
-#ifdef __tilegx__
-# define Elf_Rela Elf64_Rela
-# define ELF_R_SYM ELF64_R_SYM
-# define ELF_R_TYPE ELF64_R_TYPE
-#else
-# define Elf_Rela Elf32_Rela
-# define ELF_R_SYM ELF32_R_SYM
-# define ELF_R_TYPE ELF32_R_TYPE
-#endif
-
 #ifdef MODULE_DEBUG
 #define DEBUGP printk
 #else
index 79ccfe6c70787054c61d1116cb42449d562dfca8..49e3b49e552f7f81dea63e708bbb0abf1e32a3f4 100644 (file)
@@ -648,7 +648,7 @@ static void stack_proc(void *arg)
        struct task_struct *from = current, *to = arg;
 
        to->thread.saved_task = from;
-       rcu_switch(from, to);
+       rcu_user_hooks_switch(from, to);
        switch_to(from, to, from);
 }
 
index 46c3bff3ced20e31c379bdde1c9a50c95206ff8e..af3d760203ce7a4b359312fe460649b3be305dcc 100644 (file)
@@ -570,6 +570,37 @@ config SCHED_OMIT_FRAME_POINTER
 
          If in doubt, say "Y".
 
+config KVMTOOL_TEST_ENABLE
+       bool "Enable options to create a bootable tools/kvm/ kernel"
+       select NET
+       select NETDEVICES
+       select PCI
+       select BLOCK
+       select BLK_DEV
+       select NETWORK_FILESYSTEMS
+       select INET
+       select EXPERIMENTAL
+       select SERIAL_8250
+       select SERIAL_8250_CONSOLE
+       select IP_PNP
+       select IP_PNP_DHCP
+       select BINFMT_ELF
+       select PCI_MSI
+       select HAVE_ARCH_KGDB
+       select DEBUG_KERNEL
+       select KGDB
+       select KGDB_SERIAL_CONSOLE
+       select VIRTUALIZATION
+       select VIRTIO
+       select VIRTIO_RING
+       select VIRTIO_PCI
+       select VIRTIO_BLK
+       select VIRTIO_CONSOLE
+       select VIRTIO_NET
+       select 9P_FS
+       select NET_9P
+       select NET_9P_VIRTIO
+
 menuconfig PARAVIRT_GUEST
        bool "Paravirtualized guest support"
        ---help---
index 5bacb4a226ac8e4ff88562b60e96f04f2e0cc8e4..84d7dbaba26e37d88489a6994ba36a2374788785 100644 (file)
@@ -47,3 +47,5 @@ serpent-avx-x86_64-y := serpent-avx-x86_64-asm_64.o serpent_avx_glue.o
 aesni-intel-y := aesni-intel_asm.o aesni-intel_glue.o fpu.o
 ghash-clmulni-intel-y := ghash-clmulni-intel_asm.o ghash-clmulni-intel_glue.o
 sha1-ssse3-y := sha1_ssse3_asm.o sha1_ssse3_glue.o
+crc32c-intel-y := crc32c-intel_glue.o
+crc32c-intel-$(CONFIG_CRYPTO_CRC32C_X86_64) += crc32c-pcl-intel-asm_64.o
index 42ffd2bbab5bb9e18de2695d1f5814e4c5b43958..021a0086186bb28a4cc0cd39ce3f11eda553a378 100644 (file)
@@ -1317,21 +1317,21 @@ static void camellia_decrypt_cbc_2way(void *ctx, u128 *dst, const u128 *src)
        u128_xor(&dst[1], &dst[1], &iv);
 }
 
-static void camellia_crypt_ctr(void *ctx, u128 *dst, const u128 *src, u128 *iv)
+static void camellia_crypt_ctr(void *ctx, u128 *dst, const u128 *src, le128 *iv)
 {
        be128 ctrblk;
 
        if (dst != src)
                *dst = *src;
 
-       u128_to_be128(&ctrblk, iv);
-       u128_inc(iv);
+       le128_to_be128(&ctrblk, iv);
+       le128_inc(iv);
 
        camellia_enc_blk_xor(ctx, (u8 *)dst, (u8 *)&ctrblk);
 }
 
 static void camellia_crypt_ctr_2way(void *ctx, u128 *dst, const u128 *src,
-                                   u128 *iv)
+                                   le128 *iv)
 {
        be128 ctrblks[2];
 
@@ -1340,10 +1340,10 @@ static void camellia_crypt_ctr_2way(void *ctx, u128 *dst, const u128 *src,
                dst[1] = src[1];
        }
 
-       u128_to_be128(&ctrblks[0], iv);
-       u128_inc(iv);
-       u128_to_be128(&ctrblks[1], iv);
-       u128_inc(iv);
+       le128_to_be128(&ctrblks[0], iv);
+       le128_inc(iv);
+       le128_to_be128(&ctrblks[1], iv);
+       le128_inc(iv);
 
        camellia_enc_blk_xor_2way(ctx, (u8 *)dst, (u8 *)ctrblks);
 }
index a41a3aaba220ded5fe44ae0e79c5cd3fe2b41228..12478e47236898251d05eba35850a9004e1bd95a 100644 (file)
        vpunpcklqdq             t1, t0, x0; \
        vpunpckhqdq             t1, t0, x1;
 
-#define inpack_blocks(in, x0, x1, t0, t1, rmask) \
-       vmovdqu (0*4*4)(in),    x0; \
-       vmovdqu (1*4*4)(in),    x1; \
+#define inpack_blocks(x0, x1, t0, t1, rmask) \
        vpshufb rmask,  x0,     x0; \
        vpshufb rmask,  x1,     x1; \
        \
        transpose_2x4(x0, x1, t0, t1)
 
-#define outunpack_blocks(out, x0, x1, t0, t1, rmask) \
+#define outunpack_blocks(x0, x1, t0, t1, rmask) \
        transpose_2x4(x0, x1, t0, t1) \
        \
        vpshufb rmask,  x0, x0;           \
-       vpshufb rmask,  x1, x1;           \
-       vmovdqu         x0, (0*4*4)(out); \
-       vmovdqu         x1, (1*4*4)(out);
-
-#define outunpack_xor_blocks(out, x0, x1, t0, t1, rmask) \
-       transpose_2x4(x0, x1, t0, t1) \
-       \
-       vpshufb rmask,  x0, x0;               \
-       vpshufb rmask,  x1, x1;               \
-       vpxor           (0*4*4)(out), x0, x0; \
-       vmovdqu         x0, (0*4*4)(out);     \
-       vpxor           (1*4*4)(out), x1, x1; \
-       vmovdqu         x1, (1*4*4)(out);
+       vpshufb rmask,  x1, x1;
 
 .data
 
        .byte 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12
 .Lbswap128_mask:
        .byte 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
+.Lbswap_iv_mask:
+       .byte 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0
 .L16_mask:
        .byte 16, 16, 16, 16
 .L32_mask:
 .text
 
 .align 16
-.global __cast5_enc_blk_16way
-.type   __cast5_enc_blk_16way,@function;
+.type   __cast5_enc_blk16,@function;
 
-__cast5_enc_blk_16way:
+__cast5_enc_blk16:
        /* input:
         *      %rdi: ctx, CTX
-        *      %rsi: dst
-        *      %rdx: src
-        *      %rcx: bool, if true: xor output
+        *      RL1: blocks 1 and 2
+        *      RR1: blocks 3 and 4
+        *      RL2: blocks 5 and 6
+        *      RR2: blocks 7 and 8
+        *      RL3: blocks 9 and 10
+        *      RR3: blocks 11 and 12
+        *      RL4: blocks 13 and 14
+        *      RR4: blocks 15 and 16
+        * output:
+        *      RL1: encrypted blocks 1 and 2
+        *      RR1: encrypted blocks 3 and 4
+        *      RL2: encrypted blocks 5 and 6
+        *      RR2: encrypted blocks 7 and 8
+        *      RL3: encrypted blocks 9 and 10
+        *      RR3: encrypted blocks 11 and 12
+        *      RL4: encrypted blocks 13 and 14
+        *      RR4: encrypted blocks 15 and 16
         */
 
        pushq %rbp;
        pushq %rbx;
-       pushq %rcx;
 
        vmovdqa .Lbswap_mask, RKM;
        vmovd .Lfirst_mask, R1ST;
        vmovd .L32_mask, R32;
        enc_preload_rkr();
 
-       leaq 1*(2*4*4)(%rdx), %rax;
-       inpack_blocks(%rdx, RL1, RR1, RTMP, RX, RKM);
-       inpack_blocks(%rax, RL2, RR2, RTMP, RX, RKM);
-       leaq 2*(2*4*4)(%rdx), %rax;
-       inpack_blocks(%rax, RL3, RR3, RTMP, RX, RKM);
-       leaq 3*(2*4*4)(%rdx), %rax;
-       inpack_blocks(%rax, RL4, RR4, RTMP, RX, RKM);
-
-       movq %rsi, %r11;
+       inpack_blocks(RL1, RR1, RTMP, RX, RKM);
+       inpack_blocks(RL2, RR2, RTMP, RX, RKM);
+       inpack_blocks(RL3, RR3, RTMP, RX, RKM);
+       inpack_blocks(RL4, RR4, RTMP, RX, RKM);
 
        round(RL, RR, 0, 1);
        round(RR, RL, 1, 2);
@@ -276,44 +271,41 @@ __cast5_enc_blk_16way:
        round(RR, RL, 15, 1);
 
 __skip_enc:
-       popq %rcx;
        popq %rbx;
        popq %rbp;
 
        vmovdqa .Lbswap_mask, RKM;
-       leaq 1*(2*4*4)(%r11), %rax;
 
-       testb %cl, %cl;
-       jnz __enc_xor16;
-
-       outunpack_blocks(%r11, RR1, RL1, RTMP, RX, RKM);
-       outunpack_blocks(%rax, RR2, RL2, RTMP, RX, RKM);
-       leaq 2*(2*4*4)(%r11), %rax;
-       outunpack_blocks(%rax, RR3, RL3, RTMP, RX, RKM);
-       leaq 3*(2*4*4)(%r11), %rax;
-       outunpack_blocks(%rax, RR4, RL4, RTMP, RX, RKM);
-
-       ret;
-
-__enc_xor16:
-       outunpack_xor_blocks(%r11, RR1, RL1, RTMP, RX, RKM);
-       outunpack_xor_blocks(%rax, RR2, RL2, RTMP, RX, RKM);
-       leaq 2*(2*4*4)(%r11), %rax;
-       outunpack_xor_blocks(%rax, RR3, RL3, RTMP, RX, RKM);
-       leaq 3*(2*4*4)(%r11), %rax;
-       outunpack_xor_blocks(%rax, RR4, RL4, RTMP, RX, RKM);
+       outunpack_blocks(RR1, RL1, RTMP, RX, RKM);
+       outunpack_blocks(RR2, RL2, RTMP, RX, RKM);
+       outunpack_blocks(RR3, RL3, RTMP, RX, RKM);
+       outunpack_blocks(RR4, RL4, RTMP, RX, RKM);
 
        ret;
 
 .align 16
-.global cast5_dec_blk_16way
-.type   cast5_dec_blk_16way,@function;
+.type   __cast5_dec_blk16,@function;
 
-cast5_dec_blk_16way:
+__cast5_dec_blk16:
        /* input:
         *      %rdi: ctx, CTX
-        *      %rsi: dst
-        *      %rdx: src
+        *      RL1: encrypted blocks 1 and 2
+        *      RR1: encrypted blocks 3 and 4
+        *      RL2: encrypted blocks 5 and 6
+        *      RR2: encrypted blocks 7 and 8
+        *      RL3: encrypted blocks 9 and 10
+        *      RR3: encrypted blocks 11 and 12
+        *      RL4: encrypted blocks 13 and 14
+        *      RR4: encrypted blocks 15 and 16
+        * output:
+        *      RL1: decrypted blocks 1 and 2
+        *      RR1: decrypted blocks 3 and 4
+        *      RL2: decrypted blocks 5 and 6
+        *      RR2: decrypted blocks 7 and 8
+        *      RL3: decrypted blocks 9 and 10
+        *      RR3: decrypted blocks 11 and 12
+        *      RL4: decrypted blocks 13 and 14
+        *      RR4: decrypted blocks 15 and 16
         */
 
        pushq %rbp;
@@ -324,15 +316,10 @@ cast5_dec_blk_16way:
        vmovd .L32_mask, R32;
        dec_preload_rkr();
 
-       leaq 1*(2*4*4)(%rdx), %rax;
-       inpack_blocks(%rdx, RL1, RR1, RTMP, RX, RKM);
-       inpack_blocks(%rax, RL2, RR2, RTMP, RX, RKM);
-       leaq 2*(2*4*4)(%rdx), %rax;
-       inpack_blocks(%rax, RL3, RR3, RTMP, RX, RKM);
-       leaq 3*(2*4*4)(%rdx), %rax;
-       inpack_blocks(%rax, RL4, RR4, RTMP, RX, RKM);
-
-       movq %rsi, %r11;
+       inpack_blocks(RL1, RR1, RTMP, RX, RKM);
+       inpack_blocks(RL2, RR2, RTMP, RX, RKM);
+       inpack_blocks(RL3, RR3, RTMP, RX, RKM);
+       inpack_blocks(RL4, RR4, RTMP, RX, RKM);
 
        movzbl rr(CTX), %eax;
        testl %eax, %eax;
@@ -361,16 +348,211 @@ __dec_tail:
        popq %rbx;
        popq %rbp;
 
-       leaq 1*(2*4*4)(%r11), %rax;
-       outunpack_blocks(%r11, RR1, RL1, RTMP, RX, RKM);
-       outunpack_blocks(%rax, RR2, RL2, RTMP, RX, RKM);
-       leaq 2*(2*4*4)(%r11), %rax;
-       outunpack_blocks(%rax, RR3, RL3, RTMP, RX, RKM);
-       leaq 3*(2*4*4)(%r11), %rax;
-       outunpack_blocks(%rax, RR4, RL4, RTMP, RX, RKM);
+       outunpack_blocks(RR1, RL1, RTMP, RX, RKM);
+       outunpack_blocks(RR2, RL2, RTMP, RX, RKM);
+       outunpack_blocks(RR3, RL3, RTMP, RX, RKM);
+       outunpack_blocks(RR4, RL4, RTMP, RX, RKM);
 
        ret;
 
 __skip_dec:
        vpsrldq $4, RKR, RKR;
        jmp __dec_tail;
+
+.align 16
+.global cast5_ecb_enc_16way
+.type   cast5_ecb_enc_16way,@function;
+
+cast5_ecb_enc_16way:
+       /* input:
+        *      %rdi: ctx, CTX
+        *      %rsi: dst
+        *      %rdx: src
+        */
+
+       movq %rsi, %r11;
+
+       vmovdqu (0*4*4)(%rdx), RL1;
+       vmovdqu (1*4*4)(%rdx), RR1;
+       vmovdqu (2*4*4)(%rdx), RL2;
+       vmovdqu (3*4*4)(%rdx), RR2;
+       vmovdqu (4*4*4)(%rdx), RL3;
+       vmovdqu (5*4*4)(%rdx), RR3;
+       vmovdqu (6*4*4)(%rdx), RL4;
+       vmovdqu (7*4*4)(%rdx), RR4;
+
+       call __cast5_enc_blk16;
+
+       vmovdqu RR1, (0*4*4)(%r11);
+       vmovdqu RL1, (1*4*4)(%r11);
+       vmovdqu RR2, (2*4*4)(%r11);
+       vmovdqu RL2, (3*4*4)(%r11);
+       vmovdqu RR3, (4*4*4)(%r11);
+       vmovdqu RL3, (5*4*4)(%r11);
+       vmovdqu RR4, (6*4*4)(%r11);
+       vmovdqu RL4, (7*4*4)(%r11);
+
+       ret;
+
+.align 16
+.global cast5_ecb_dec_16way
+.type   cast5_ecb_dec_16way,@function;
+
+cast5_ecb_dec_16way:
+       /* input:
+        *      %rdi: ctx, CTX
+        *      %rsi: dst
+        *      %rdx: src
+        */
+
+       movq %rsi, %r11;
+
+       vmovdqu (0*4*4)(%rdx), RL1;
+       vmovdqu (1*4*4)(%rdx), RR1;
+       vmovdqu (2*4*4)(%rdx), RL2;
+       vmovdqu (3*4*4)(%rdx), RR2;
+       vmovdqu (4*4*4)(%rdx), RL3;
+       vmovdqu (5*4*4)(%rdx), RR3;
+       vmovdqu (6*4*4)(%rdx), RL4;
+       vmovdqu (7*4*4)(%rdx), RR4;
+
+       call __cast5_dec_blk16;
+
+       vmovdqu RR1, (0*4*4)(%r11);
+       vmovdqu RL1, (1*4*4)(%r11);
+       vmovdqu RR2, (2*4*4)(%r11);
+       vmovdqu RL2, (3*4*4)(%r11);
+       vmovdqu RR3, (4*4*4)(%r11);
+       vmovdqu RL3, (5*4*4)(%r11);
+       vmovdqu RR4, (6*4*4)(%r11);
+       vmovdqu RL4, (7*4*4)(%r11);
+
+       ret;
+
+.align 16
+.global cast5_cbc_dec_16way
+.type   cast5_cbc_dec_16way,@function;
+
+cast5_cbc_dec_16way:
+       /* input:
+        *      %rdi: ctx, CTX
+        *      %rsi: dst
+        *      %rdx: src
+        */
+
+       pushq %r12;
+
+       movq %rsi, %r11;
+       movq %rdx, %r12;
+
+       vmovdqu (0*16)(%rdx), RL1;
+       vmovdqu (1*16)(%rdx), RR1;
+       vmovdqu (2*16)(%rdx), RL2;
+       vmovdqu (3*16)(%rdx), RR2;
+       vmovdqu (4*16)(%rdx), RL3;
+       vmovdqu (5*16)(%rdx), RR3;
+       vmovdqu (6*16)(%rdx), RL4;
+       vmovdqu (7*16)(%rdx), RR4;
+
+       call __cast5_dec_blk16;
+
+       /* xor with src */
+       vmovq (%r12), RX;
+       vpshufd $0x4f, RX, RX;
+       vpxor RX, RR1, RR1;
+       vpxor 0*16+8(%r12), RL1, RL1;
+       vpxor 1*16+8(%r12), RR2, RR2;
+       vpxor 2*16+8(%r12), RL2, RL2;
+       vpxor 3*16+8(%r12), RR3, RR3;
+       vpxor 4*16+8(%r12), RL3, RL3;
+       vpxor 5*16+8(%r12), RR4, RR4;
+       vpxor 6*16+8(%r12), RL4, RL4;
+
+       vmovdqu RR1, (0*16)(%r11);
+       vmovdqu RL1, (1*16)(%r11);
+       vmovdqu RR2, (2*16)(%r11);
+       vmovdqu RL2, (3*16)(%r11);
+       vmovdqu RR3, (4*16)(%r11);
+       vmovdqu RL3, (5*16)(%r11);
+       vmovdqu RR4, (6*16)(%r11);
+       vmovdqu RL4, (7*16)(%r11);
+
+       popq %r12;
+
+       ret;
+
+.align 16
+.global cast5_ctr_16way
+.type   cast5_ctr_16way,@function;
+
+cast5_ctr_16way:
+       /* input:
+        *      %rdi: ctx, CTX
+        *      %rsi: dst
+        *      %rdx: src
+        *      %rcx: iv (big endian, 64bit)
+        */
+
+       pushq %r12;
+
+       movq %rsi, %r11;
+       movq %rdx, %r12;
+
+       vpcmpeqd RTMP, RTMP, RTMP;
+       vpsrldq $8, RTMP, RTMP; /* low: -1, high: 0 */
+
+       vpcmpeqd RKR, RKR, RKR;
+       vpaddq RKR, RKR, RKR; /* low: -2, high: -2 */
+       vmovdqa .Lbswap_iv_mask, R1ST;
+       vmovdqa .Lbswap128_mask, RKM;
+
+       /* load IV and byteswap */
+       vmovq (%rcx), RX;
+       vpshufb R1ST, RX, RX;
+
+       /* construct IVs */
+       vpsubq RTMP, RX, RX;  /* le: IV1, IV0 */
+       vpshufb RKM, RX, RL1; /* be: IV0, IV1 */
+       vpsubq RKR, RX, RX;
+       vpshufb RKM, RX, RR1; /* be: IV2, IV3 */
+       vpsubq RKR, RX, RX;
+       vpshufb RKM, RX, RL2; /* be: IV4, IV5 */
+       vpsubq RKR, RX, RX;
+       vpshufb RKM, RX, RR2; /* be: IV6, IV7 */
+       vpsubq RKR, RX, RX;
+       vpshufb RKM, RX, RL3; /* be: IV8, IV9 */
+       vpsubq RKR, RX, RX;
+       vpshufb RKM, RX, RR3; /* be: IV10, IV11 */
+       vpsubq RKR, RX, RX;
+       vpshufb RKM, RX, RL4; /* be: IV12, IV13 */
+       vpsubq RKR, RX, RX;
+       vpshufb RKM, RX, RR4; /* be: IV14, IV15 */
+
+       /* store last IV */
+       vpsubq RTMP, RX, RX; /* le: IV16, IV14 */
+       vpshufb R1ST, RX, RX; /* be: IV16, IV16 */
+       vmovq RX, (%rcx);
+
+       call __cast5_enc_blk16;
+
+       /* dst = src ^ iv */
+       vpxor (0*16)(%r12), RR1, RR1;
+       vpxor (1*16)(%r12), RL1, RL1;
+       vpxor (2*16)(%r12), RR2, RR2;
+       vpxor (3*16)(%r12), RL2, RL2;
+       vpxor (4*16)(%r12), RR3, RR3;
+       vpxor (5*16)(%r12), RL3, RL3;
+       vpxor (6*16)(%r12), RR4, RR4;
+       vpxor (7*16)(%r12), RL4, RL4;
+       vmovdqu RR1, (0*16)(%r11);
+       vmovdqu RL1, (1*16)(%r11);
+       vmovdqu RR2, (2*16)(%r11);
+       vmovdqu RL2, (3*16)(%r11);
+       vmovdqu RR3, (4*16)(%r11);
+       vmovdqu RL3, (5*16)(%r11);
+       vmovdqu RR4, (6*16)(%r11);
+       vmovdqu RL4, (7*16)(%r11);
+
+       popq %r12;
+
+       ret;
index e0ea14f9547f269cb667868f137f5d3fc704d288..c6631813dc115c609e186044790aa5461cb6f0c7 100644 (file)
 
 #define CAST5_PARALLEL_BLOCKS 16
 
-asmlinkage void __cast5_enc_blk_16way(struct cast5_ctx *ctx, u8 *dst,
-                                     const u8 *src, bool xor);
-asmlinkage void cast5_dec_blk_16way(struct cast5_ctx *ctx, u8 *dst,
+asmlinkage void cast5_ecb_enc_16way(struct cast5_ctx *ctx, u8 *dst,
                                    const u8 *src);
-
-static inline void cast5_enc_blk_xway(struct cast5_ctx *ctx, u8 *dst,
-                                     const u8 *src)
-{
-       __cast5_enc_blk_16way(ctx, dst, src, false);
-}
-
-static inline void cast5_enc_blk_xway_xor(struct cast5_ctx *ctx, u8 *dst,
-                                         const u8 *src)
-{
-       __cast5_enc_blk_16way(ctx, dst, src, true);
-}
-
-static inline void cast5_dec_blk_xway(struct cast5_ctx *ctx, u8 *dst,
-                                     const u8 *src)
-{
-       cast5_dec_blk_16way(ctx, dst, src);
-}
-
+asmlinkage void cast5_ecb_dec_16way(struct cast5_ctx *ctx, u8 *dst,
+                                   const u8 *src);
+asmlinkage void cast5_cbc_dec_16way(struct cast5_ctx *ctx, u8 *dst,
+                                   const u8 *src);
+asmlinkage void cast5_ctr_16way(struct cast5_ctx *ctx, u8 *dst, const u8 *src,
+                               __be64 *iv);
 
 static inline bool cast5_fpu_begin(bool fpu_enabled, unsigned int nbytes)
 {
@@ -79,8 +64,11 @@ static int ecb_crypt(struct blkcipher_desc *desc, struct blkcipher_walk *walk,
        struct cast5_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
        const unsigned int bsize = CAST5_BLOCK_SIZE;
        unsigned int nbytes;
+       void (*fn)(struct cast5_ctx *ctx, u8 *dst, const u8 *src);
        int err;
 
+       fn = (enc) ? cast5_ecb_enc_16way : cast5_ecb_dec_16way;
+
        err = blkcipher_walk_virt(desc, walk);
        desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
 
@@ -93,10 +81,7 @@ static int ecb_crypt(struct blkcipher_desc *desc, struct blkcipher_walk *walk,
                /* Process multi-block batch */
                if (nbytes >= bsize * CAST5_PARALLEL_BLOCKS) {
                        do {
-                               if (enc)
-                                       cast5_enc_blk_xway(ctx, wdst, wsrc);
-                               else
-                                       cast5_dec_blk_xway(ctx, wdst, wsrc);
+                               fn(ctx, wdst, wsrc);
 
                                wsrc += bsize * CAST5_PARALLEL_BLOCKS;
                                wdst += bsize * CAST5_PARALLEL_BLOCKS;
@@ -107,12 +92,11 @@ static int ecb_crypt(struct blkcipher_desc *desc, struct blkcipher_walk *walk,
                                goto done;
                }
 
+               fn = (enc) ? __cast5_encrypt : __cast5_decrypt;
+
                /* Handle leftovers */
                do {
-                       if (enc)
-                               __cast5_encrypt(ctx, wdst, wsrc);
-                       else
-                               __cast5_decrypt(ctx, wdst, wsrc);
+                       fn(ctx, wdst, wsrc);
 
                        wsrc += bsize;
                        wdst += bsize;
@@ -194,9 +178,7 @@ static unsigned int __cbc_decrypt(struct blkcipher_desc *desc,
        unsigned int nbytes = walk->nbytes;
        u64 *src = (u64 *)walk->src.virt.addr;
        u64 *dst = (u64 *)walk->dst.virt.addr;
-       u64 ivs[CAST5_PARALLEL_BLOCKS - 1];
        u64 last_iv;
-       int i;
 
        /* Start of the last block. */
        src += nbytes / bsize - 1;
@@ -211,13 +193,7 @@ static unsigned int __cbc_decrypt(struct blkcipher_desc *desc,
                        src -= CAST5_PARALLEL_BLOCKS - 1;
                        dst -= CAST5_PARALLEL_BLOCKS - 1;
 
-                       for (i = 0; i < CAST5_PARALLEL_BLOCKS - 1; i++)
-                               ivs[i] = src[i];
-
-                       cast5_dec_blk_xway(ctx, (u8 *)dst, (u8 *)src);
-
-                       for (i = 0; i < CAST5_PARALLEL_BLOCKS - 1; i++)
-                               *(dst + (i + 1)) ^= *(ivs + i);
+                       cast5_cbc_dec_16way(ctx, (u8 *)dst, (u8 *)src);
 
                        nbytes -= bsize;
                        if (nbytes < bsize)
@@ -298,23 +274,12 @@ static unsigned int __ctr_crypt(struct blkcipher_desc *desc,
        unsigned int nbytes = walk->nbytes;
        u64 *src = (u64 *)walk->src.virt.addr;
        u64 *dst = (u64 *)walk->dst.virt.addr;
-       u64 ctrblk = be64_to_cpu(*(__be64 *)walk->iv);
-       __be64 ctrblocks[CAST5_PARALLEL_BLOCKS];
-       int i;
 
        /* Process multi-block batch */
        if (nbytes >= bsize * CAST5_PARALLEL_BLOCKS) {
                do {
-                       /* create ctrblks for parallel encrypt */
-                       for (i = 0; i < CAST5_PARALLEL_BLOCKS; i++) {
-                               if (dst != src)
-                                       dst[i] = src[i];
-
-                               ctrblocks[i] = cpu_to_be64(ctrblk++);
-                       }
-
-                       cast5_enc_blk_xway_xor(ctx, (u8 *)dst,
-                                              (u8 *)ctrblocks);
+                       cast5_ctr_16way(ctx, (u8 *)dst, (u8 *)src,
+                                       (__be64 *)walk->iv);
 
                        src += CAST5_PARALLEL_BLOCKS;
                        dst += CAST5_PARALLEL_BLOCKS;
@@ -327,13 +292,16 @@ static unsigned int __ctr_crypt(struct blkcipher_desc *desc,
 
        /* Handle leftovers */
        do {
+               u64 ctrblk;
+
                if (dst != src)
                        *dst = *src;
 
-               ctrblocks[0] = cpu_to_be64(ctrblk++);
+               ctrblk = *(u64 *)walk->iv;
+               be64_add_cpu((__be64 *)walk->iv, 1);
 
-               __cast5_encrypt(ctx, (u8 *)ctrblocks, (u8 *)ctrblocks);
-               *dst ^= ctrblocks[0];
+               __cast5_encrypt(ctx, (u8 *)&ctrblk, (u8 *)&ctrblk);
+               *dst ^= ctrblk;
 
                src += 1;
                dst += 1;
@@ -341,7 +309,6 @@ static unsigned int __ctr_crypt(struct blkcipher_desc *desc,
        } while (nbytes >= bsize);
 
 done:
-       *(__be64 *)walk->iv = cpu_to_be64(ctrblk);
        return nbytes;
 }
 
index 218d283772f420339e8ef7be42adb184e829753d..83a53818f0a5e3cb89a02bce1d83a9174fc0b0a6 100644 (file)
@@ -23,6 +23,8 @@
  *
  */
 
+#include "glue_helper-asm-avx.S"
+
 .file "cast6-avx-x86_64-asm_64.S"
 
 .extern cast6_s1
        vpunpcklqdq             x3, t2, x2; \
        vpunpckhqdq             x3, t2, x3;
 
-#define inpack_blocks(in, x0, x1, x2, x3, t0, t1, t2, rmask) \
-       vmovdqu (0*4*4)(in),    x0; \
-       vmovdqu (1*4*4)(in),    x1; \
-       vmovdqu (2*4*4)(in),    x2; \
-       vmovdqu (3*4*4)(in),    x3; \
+#define inpack_blocks(x0, x1, x2, x3, t0, t1, t2, rmask) \
        vpshufb rmask, x0,      x0; \
        vpshufb rmask, x1,      x1; \
        vpshufb rmask, x2,      x2; \
        \
        transpose_4x4(x0, x1, x2, x3, t0, t1, t2)
 
-#define outunpack_blocks(out, x0, x1, x2, x3, t0, t1, t2, rmask) \
+#define outunpack_blocks(x0, x1, x2, x3, t0, t1, t2, rmask) \
        transpose_4x4(x0, x1, x2, x3, t0, t1, t2) \
        \
        vpshufb rmask,          x0, x0;       \
        vpshufb rmask,          x1, x1;       \
        vpshufb rmask,          x2, x2;       \
-       vpshufb rmask,          x3, x3;       \
-       vmovdqu x0,             (0*4*4)(out); \
-       vmovdqu x1,             (1*4*4)(out); \
-       vmovdqu x2,             (2*4*4)(out); \
-       vmovdqu x3,             (3*4*4)(out);
-
-#define outunpack_xor_blocks(out, x0, x1, x2, x3, t0, t1, t2, rmask) \
-       transpose_4x4(x0, x1, x2, x3, t0, t1, t2) \
-       \
-       vpshufb rmask,          x0, x0;       \
-       vpshufb rmask,          x1, x1;       \
-       vpshufb rmask,          x2, x2;       \
-       vpshufb rmask,          x3, x3;       \
-       vpxor (0*4*4)(out),     x0, x0;       \
-       vmovdqu x0,             (0*4*4)(out); \
-       vpxor (1*4*4)(out),     x1, x1;       \
-       vmovdqu x1,             (1*4*4)(out); \
-       vpxor (2*4*4)(out),     x2, x2;       \
-       vmovdqu x2,             (2*4*4)(out); \
-       vpxor (3*4*4)(out),     x3, x3;       \
-       vmovdqu x3,             (3*4*4)(out);
+       vpshufb rmask,          x3, x3;
 
 .data
 
 .align 16
 .Lbswap_mask:
        .byte 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12
+.Lbswap128_mask:
+       .byte 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
 .Lrkr_enc_Q_Q_QBAR_QBAR:
        .byte 0, 1, 2, 3, 4, 5, 6, 7, 11, 10, 9, 8, 15, 14, 13, 12
 .Lrkr_enc_QBAR_QBAR_QBAR_QBAR:
 
 .text
 
-.align 16
-.global __cast6_enc_blk_8way
-.type   __cast6_enc_blk_8way,@function;
+.align 8
+.type   __cast6_enc_blk8,@function;
 
-__cast6_enc_blk_8way:
+__cast6_enc_blk8:
        /* input:
         *      %rdi: ctx, CTX
-        *      %rsi: dst
-        *      %rdx: src
-        *      %rcx: bool, if true: xor output
+        *      RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2: blocks
+        * output:
+        *      RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2: encrypted blocks
         */
 
        pushq %rbp;
        pushq %rbx;
-       pushq %rcx;
 
        vmovdqa .Lbswap_mask, RKM;
        vmovd .Lfirst_mask, R1ST;
        vmovd .L32_mask, R32;
 
-       leaq (4*4*4)(%rdx), %rax;
-       inpack_blocks(%rdx, RA1, RB1, RC1, RD1, RTMP, RX, RKRF, RKM);
-       inpack_blocks(%rax, RA2, RB2, RC2, RD2, RTMP, RX, RKRF, RKM);
-
-       movq %rsi, %r11;
+       inpack_blocks(RA1, RB1, RC1, RD1, RTMP, RX, RKRF, RKM);
+       inpack_blocks(RA2, RB2, RC2, RD2, RTMP, RX, RKRF, RKM);
 
        preload_rkr(0, dummy, none);
        Q(0);
@@ -311,36 +286,25 @@ __cast6_enc_blk_8way:
        QBAR(10);
        QBAR(11);
 
-       popq %rcx;
        popq %rbx;
        popq %rbp;
 
        vmovdqa .Lbswap_mask, RKM;
-       leaq (4*4*4)(%r11), %rax;
-
-       testb %cl, %cl;
-       jnz __enc_xor8;
-
-       outunpack_blocks(%r11, RA1, RB1, RC1, RD1, RTMP, RX, RKRF, RKM);
-       outunpack_blocks(%rax, RA2, RB2, RC2, RD2, RTMP, RX, RKRF, RKM);
-
-       ret;
 
-__enc_xor8:
-       outunpack_xor_blocks(%r11, RA1, RB1, RC1, RD1, RTMP, RX, RKRF, RKM);
-       outunpack_xor_blocks(%rax, RA2, RB2, RC2, RD2, RTMP, RX, RKRF, RKM);
+       outunpack_blocks(RA1, RB1, RC1, RD1, RTMP, RX, RKRF, RKM);
+       outunpack_blocks(RA2, RB2, RC2, RD2, RTMP, RX, RKRF, RKM);
 
        ret;
 
-.align 16
-.global cast6_dec_blk_8way
-.type   cast6_dec_blk_8way,@function;
+.align 8
+.type   __cast6_dec_blk8,@function;
 
-cast6_dec_blk_8way:
+__cast6_dec_blk8:
        /* input:
         *      %rdi: ctx, CTX
-        *      %rsi: dst
-        *      %rdx: src
+        *      RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2: encrypted blocks
+        * output:
+        *      RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2: decrypted blocks
         */
 
        pushq %rbp;
@@ -350,11 +314,8 @@ cast6_dec_blk_8way:
        vmovd .Lfirst_mask, R1ST;
        vmovd .L32_mask, R32;
 
-       leaq (4*4*4)(%rdx), %rax;
-       inpack_blocks(%rdx, RA1, RB1, RC1, RD1, RTMP, RX, RKRF, RKM);
-       inpack_blocks(%rax, RA2, RB2, RC2, RD2, RTMP, RX, RKRF, RKM);
-
-       movq %rsi, %r11;
+       inpack_blocks(RA1, RB1, RC1, RD1, RTMP, RX, RKRF, RKM);
+       inpack_blocks(RA2, RB2, RC2, RD2, RTMP, RX, RKRF, RKM);
 
        preload_rkr(2, shuffle, .Lrkr_dec_Q_Q_Q_Q);
        Q(11);
@@ -376,8 +337,103 @@ cast6_dec_blk_8way:
        popq %rbp;
 
        vmovdqa .Lbswap_mask, RKM;
-       leaq (4*4*4)(%r11), %rax;
-       outunpack_blocks(%r11, RA1, RB1, RC1, RD1, RTMP, RX, RKRF, RKM);
-       outunpack_blocks(%rax, RA2, RB2, RC2, RD2, RTMP, RX, RKRF, RKM);
+       outunpack_blocks(RA1, RB1, RC1, RD1, RTMP, RX, RKRF, RKM);
+       outunpack_blocks(RA2, RB2, RC2, RD2, RTMP, RX, RKRF, RKM);
+
+       ret;
+
+.align 8
+.global cast6_ecb_enc_8way
+.type   cast6_ecb_enc_8way,@function;
+
+cast6_ecb_enc_8way:
+       /* input:
+        *      %rdi: ctx, CTX
+        *      %rsi: dst
+        *      %rdx: src
+        */
+
+       movq %rsi, %r11;
+
+       load_8way(%rdx, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
+
+       call __cast6_enc_blk8;
+
+       store_8way(%r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
+
+       ret;
+
+.align 8
+.global cast6_ecb_dec_8way
+.type   cast6_ecb_dec_8way,@function;
+
+cast6_ecb_dec_8way:
+       /* input:
+        *      %rdi: ctx, CTX
+        *      %rsi: dst
+        *      %rdx: src
+        */
+
+       movq %rsi, %r11;
+
+       load_8way(%rdx, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
+
+       call __cast6_dec_blk8;
+
+       store_8way(%r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
+
+       ret;
+
+.align 8
+.global cast6_cbc_dec_8way
+.type   cast6_cbc_dec_8way,@function;
+
+cast6_cbc_dec_8way:
+       /* input:
+        *      %rdi: ctx, CTX
+        *      %rsi: dst
+        *      %rdx: src
+        */
+
+       pushq %r12;
+
+       movq %rsi, %r11;
+       movq %rdx, %r12;
+
+       load_8way(%rdx, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
+
+       call __cast6_dec_blk8;
+
+       store_cbc_8way(%r12, %r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
+
+       popq %r12;
+
+       ret;
+
+.align 8
+.global cast6_ctr_8way
+.type   cast6_ctr_8way,@function;
+
+cast6_ctr_8way:
+       /* input:
+        *      %rdi: ctx, CTX
+        *      %rsi: dst
+        *      %rdx: src
+        *      %rcx: iv (little endian, 128bit)
+        */
+
+       pushq %r12;
+
+       movq %rsi, %r11;
+       movq %rdx, %r12;
+
+       load_ctr_8way(%rcx, .Lbswap128_mask, RA1, RB1, RC1, RD1, RA2, RB2, RC2,
+                     RD2, RX, RKR, RKM);
+
+       call __cast6_enc_blk8;
+
+       store_ctr_8way(%r12, %r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
+
+       popq %r12;
 
        ret;
index 15e5f85a50115a6eba3659011e35d5b95ff97558..92f7ca24790a60658c84ddae7a4741ec651b88b1 100644 (file)
 
 #define CAST6_PARALLEL_BLOCKS 8
 
-asmlinkage void __cast6_enc_blk_8way(struct cast6_ctx *ctx, u8 *dst,
-                                    const u8 *src, bool xor);
-asmlinkage void cast6_dec_blk_8way(struct cast6_ctx *ctx, u8 *dst,
+asmlinkage void cast6_ecb_enc_8way(struct cast6_ctx *ctx, u8 *dst,
+                                  const u8 *src);
+asmlinkage void cast6_ecb_dec_8way(struct cast6_ctx *ctx, u8 *dst,
                                   const u8 *src);
 
-static inline void cast6_enc_blk_xway(struct cast6_ctx *ctx, u8 *dst,
-                                     const u8 *src)
-{
-       __cast6_enc_blk_8way(ctx, dst, src, false);
-}
-
-static inline void cast6_enc_blk_xway_xor(struct cast6_ctx *ctx, u8 *dst,
-                                         const u8 *src)
-{
-       __cast6_enc_blk_8way(ctx, dst, src, true);
-}
-
-static inline void cast6_dec_blk_xway(struct cast6_ctx *ctx, u8 *dst,
-                                     const u8 *src)
-{
-       cast6_dec_blk_8way(ctx, dst, src);
-}
-
-
-static void cast6_decrypt_cbc_xway(void *ctx, u128 *dst, const u128 *src)
-{
-       u128 ivs[CAST6_PARALLEL_BLOCKS - 1];
-       unsigned int j;
-
-       for (j = 0; j < CAST6_PARALLEL_BLOCKS - 1; j++)
-               ivs[j] = src[j];
-
-       cast6_dec_blk_xway(ctx, (u8 *)dst, (u8 *)src);
-
-       for (j = 0; j < CAST6_PARALLEL_BLOCKS - 1; j++)
-               u128_xor(dst + (j + 1), dst + (j + 1), ivs + j);
-}
+asmlinkage void cast6_cbc_dec_8way(struct cast6_ctx *ctx, u8 *dst,
+                                  const u8 *src);
+asmlinkage void cast6_ctr_8way(struct cast6_ctx *ctx, u8 *dst, const u8 *src,
+                              le128 *iv);
 
-static void cast6_crypt_ctr(void *ctx, u128 *dst, const u128 *src, u128 *iv)
+static void cast6_crypt_ctr(void *ctx, u128 *dst, const u128 *src, le128 *iv)
 {
        be128 ctrblk;
 
-       u128_to_be128(&ctrblk, iv);
-       u128_inc(iv);
+       le128_to_be128(&ctrblk, iv);
+       le128_inc(iv);
 
        __cast6_encrypt(ctx, (u8 *)&ctrblk, (u8 *)&ctrblk);
        u128_xor(dst, src, (u128 *)&ctrblk);
 }
 
-static void cast6_crypt_ctr_xway(void *ctx, u128 *dst, const u128 *src,
-                                  u128 *iv)
-{
-       be128 ctrblks[CAST6_PARALLEL_BLOCKS];
-       unsigned int i;
-
-       for (i = 0; i < CAST6_PARALLEL_BLOCKS; i++) {
-               if (dst != src)
-                       dst[i] = src[i];
-
-               u128_to_be128(&ctrblks[i], iv);
-               u128_inc(iv);
-       }
-
-       cast6_enc_blk_xway_xor(ctx, (u8 *)dst, (u8 *)ctrblks);
-}
-
 static const struct common_glue_ctx cast6_enc = {
        .num_funcs = 2,
        .fpu_blocks_limit = CAST6_PARALLEL_BLOCKS,
 
        .funcs = { {
                .num_blocks = CAST6_PARALLEL_BLOCKS,
-               .fn_u = { .ecb = GLUE_FUNC_CAST(cast6_enc_blk_xway) }
+               .fn_u = { .ecb = GLUE_FUNC_CAST(cast6_ecb_enc_8way) }
        }, {
                .num_blocks = 1,
                .fn_u = { .ecb = GLUE_FUNC_CAST(__cast6_encrypt) }
@@ -125,7 +80,7 @@ static const struct common_glue_ctx cast6_ctr = {
 
        .funcs = { {
                .num_blocks = CAST6_PARALLEL_BLOCKS,
-               .fn_u = { .ctr = GLUE_CTR_FUNC_CAST(cast6_crypt_ctr_xway) }
+               .fn_u = { .ctr = GLUE_CTR_FUNC_CAST(cast6_ctr_8way) }
        }, {
                .num_blocks = 1,
                .fn_u = { .ctr = GLUE_CTR_FUNC_CAST(cast6_crypt_ctr) }
@@ -138,7 +93,7 @@ static const struct common_glue_ctx cast6_dec = {
 
        .funcs = { {
                .num_blocks = CAST6_PARALLEL_BLOCKS,
-               .fn_u = { .ecb = GLUE_FUNC_CAST(cast6_dec_blk_xway) }
+               .fn_u = { .ecb = GLUE_FUNC_CAST(cast6_ecb_dec_8way) }
        }, {
                .num_blocks = 1,
                .fn_u = { .ecb = GLUE_FUNC_CAST(__cast6_decrypt) }
@@ -151,7 +106,7 @@ static const struct common_glue_ctx cast6_dec_cbc = {
 
        .funcs = { {
                .num_blocks = CAST6_PARALLEL_BLOCKS,
-               .fn_u = { .cbc = GLUE_CBC_FUNC_CAST(cast6_decrypt_cbc_xway) }
+               .fn_u = { .cbc = GLUE_CBC_FUNC_CAST(cast6_cbc_dec_8way) }
        }, {
                .num_blocks = 1,
                .fn_u = { .cbc = GLUE_CBC_FUNC_CAST(__cast6_decrypt) }
@@ -215,7 +170,7 @@ static void encrypt_callback(void *priv, u8 *srcdst, unsigned int nbytes)
        ctx->fpu_enabled = cast6_fpu_begin(ctx->fpu_enabled, nbytes);
 
        if (nbytes == bsize * CAST6_PARALLEL_BLOCKS) {
-               cast6_enc_blk_xway(ctx->ctx, srcdst, srcdst);
+               cast6_ecb_enc_8way(ctx->ctx, srcdst, srcdst);
                return;
        }
 
@@ -232,7 +187,7 @@ static void decrypt_callback(void *priv, u8 *srcdst, unsigned int nbytes)
        ctx->fpu_enabled = cast6_fpu_begin(ctx->fpu_enabled, nbytes);
 
        if (nbytes == bsize * CAST6_PARALLEL_BLOCKS) {
-               cast6_dec_blk_xway(ctx->ctx, srcdst, srcdst);
+               cast6_ecb_dec_8way(ctx->ctx, srcdst, srcdst);
                return;
        }
 
similarity index 69%
rename from arch/x86/crypto/crc32c-intel.c
rename to arch/x86/crypto/crc32c-intel_glue.c
index 493f959261f7274eaf69729a7add9a2664d475fd..6812ad98355c3d0e93be5e07c47e5e3956ebc8a4 100644 (file)
@@ -32,6 +32,8 @@
 
 #include <asm/cpufeature.h>
 #include <asm/cpu_device_id.h>
+#include <asm/i387.h>
+#include <asm/fpu-internal.h>
 
 #define CHKSUM_BLOCK_SIZE      1
 #define CHKSUM_DIGEST_SIZE     4
 #define REX_PRE
 #endif
 
+#ifdef CONFIG_X86_64
+/*
+ * use carryless multiply version of crc32c when buffer
+ * size is >= 512 (when eager fpu is enabled) or
+ * >= 1024 (when eager fpu is disabled) to account
+ * for fpu state save/restore overhead.
+ */
+#define CRC32C_PCL_BREAKEVEN_EAGERFPU  512
+#define CRC32C_PCL_BREAKEVEN_NOEAGERFPU        1024
+
+asmlinkage unsigned int crc_pcl(const u8 *buffer, int len,
+                               unsigned int crc_init);
+static int crc32c_pcl_breakeven = CRC32C_PCL_BREAKEVEN_EAGERFPU;
+#if defined(X86_FEATURE_EAGER_FPU)
+#define set_pcl_breakeven_point()                                      \
+do {                                                                   \
+       if (!use_eager_fpu())                                           \
+               crc32c_pcl_breakeven = CRC32C_PCL_BREAKEVEN_NOEAGERFPU; \
+} while (0)
+#else
+#define set_pcl_breakeven_point()                                      \
+       (crc32c_pcl_breakeven = CRC32C_PCL_BREAKEVEN_NOEAGERFPU)
+#endif
+#endif /* CONFIG_X86_64 */
+
 static u32 crc32c_intel_le_hw_byte(u32 crc, unsigned char const *data, size_t length)
 {
        while (length--) {
@@ -154,6 +181,52 @@ static int crc32c_intel_cra_init(struct crypto_tfm *tfm)
        return 0;
 }
 
+#ifdef CONFIG_X86_64
+static int crc32c_pcl_intel_update(struct shash_desc *desc, const u8 *data,
+                              unsigned int len)
+{
+       u32 *crcp = shash_desc_ctx(desc);
+
+       /*
+        * use faster PCL version if datasize is large enough to
+        * overcome kernel fpu state save/restore overhead
+        */
+       if (len >= crc32c_pcl_breakeven && irq_fpu_usable()) {
+               kernel_fpu_begin();
+               *crcp = crc_pcl(data, len, *crcp);
+               kernel_fpu_end();
+       } else
+               *crcp = crc32c_intel_le_hw(*crcp, data, len);
+       return 0;
+}
+
+static int __crc32c_pcl_intel_finup(u32 *crcp, const u8 *data, unsigned int len,
+                               u8 *out)
+{
+       if (len >= crc32c_pcl_breakeven && irq_fpu_usable()) {
+               kernel_fpu_begin();
+               *(__le32 *)out = ~cpu_to_le32(crc_pcl(data, len, *crcp));
+               kernel_fpu_end();
+       } else
+               *(__le32 *)out =
+                       ~cpu_to_le32(crc32c_intel_le_hw(*crcp, data, len));
+       return 0;
+}
+
+static int crc32c_pcl_intel_finup(struct shash_desc *desc, const u8 *data,
+                             unsigned int len, u8 *out)
+{
+       return __crc32c_pcl_intel_finup(shash_desc_ctx(desc), data, len, out);
+}
+
+static int crc32c_pcl_intel_digest(struct shash_desc *desc, const u8 *data,
+                              unsigned int len, u8 *out)
+{
+       return __crc32c_pcl_intel_finup(crypto_shash_ctx(desc->tfm), data, len,
+                                   out);
+}
+#endif /* CONFIG_X86_64 */
+
 static struct shash_alg alg = {
        .setkey                 =       crc32c_intel_setkey,
        .init                   =       crc32c_intel_init,
@@ -184,6 +257,14 @@ static int __init crc32c_intel_mod_init(void)
 {
        if (!x86_match_cpu(crc32c_cpu_id))
                return -ENODEV;
+#ifdef CONFIG_X86_64
+       if (cpu_has_pclmulqdq) {
+               alg.update = crc32c_pcl_intel_update;
+               alg.finup = crc32c_pcl_intel_finup;
+               alg.digest = crc32c_pcl_intel_digest;
+               set_pcl_breakeven_point();
+       }
+#endif
        return crypto_register_shash(&alg);
 }
 
diff --git a/arch/x86/crypto/crc32c-pcl-intel-asm_64.S b/arch/x86/crypto/crc32c-pcl-intel-asm_64.S
new file mode 100644 (file)
index 0000000..93c6d39
--- /dev/null
@@ -0,0 +1,460 @@
+/*
+ * Implement fast CRC32C with PCLMULQDQ instructions. (x86_64)
+ *
+ * The white paper on CRC32C calculations with PCLMULQDQ instruction can be
+ * downloaded from:
+ * http://download.intel.com/design/intarch/papers/323405.pdf
+ *
+ * Copyright (C) 2012 Intel Corporation.
+ *
+ * Authors:
+ *     Wajdi Feghali <wajdi.k.feghali@intel.com>
+ *     James Guilford <james.guilford@intel.com>
+ *     David Cote <david.m.cote@intel.com>
+ *     Tim Chen <tim.c.chen@linux.intel.com>
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+## ISCSI CRC 32 Implementation with crc32 and pclmulqdq Instruction
+
+.macro LABEL prefix n
+\prefix\n\():
+.endm
+
+.macro JMPTBL_ENTRY i
+.word crc_\i - crc_array
+.endm
+
+.macro JNC_LESS_THAN j
+       jnc less_than_\j
+.endm
+
+# Define threshold where buffers are considered "small" and routed to more
+# efficient "by-1" code. This "by-1" code only handles up to 255 bytes, so
+# SMALL_SIZE can be no larger than 255.
+
+#define SMALL_SIZE 200
+
+.if (SMALL_SIZE > 255)
+.error "SMALL_ SIZE must be < 256"
+.endif
+
+# unsigned int crc_pcl(u8 *buffer, int len, unsigned int crc_init);
+
+.global crc_pcl
+crc_pcl:
+#define    bufp                %rdi
+#define    bufp_dw     %edi
+#define    bufp_w      %di
+#define    bufp_b      %dil
+#define    bufptmp     %rcx
+#define    block_0     %rcx
+#define    block_1     %rdx
+#define    block_2     %r11
+#define    len         %rsi
+#define    len_dw      %esi
+#define    len_w       %si
+#define    len_b       %sil
+#define    crc_init_arg %rdx
+#define    tmp         %rbx
+#define    crc_init    %r8
+#define    crc_init_dw %r8d
+#define    crc1                %r9
+#define    crc2                %r10
+
+       pushq   %rbx
+       pushq   %rdi
+       pushq   %rsi
+
+       ## Move crc_init for Linux to a different
+       mov     crc_init_arg, crc_init
+
+       ################################################################
+       ## 1) ALIGN:
+       ################################################################
+
+       mov     bufp, bufptmp           # rdi = *buf
+       neg     bufp
+       and     $7, bufp                # calculate the unalignment amount of
+                                       # the address
+       je      proc_block              # Skip if aligned
+
+       ## If len is less than 8 and we're unaligned, we need to jump
+       ## to special code to avoid reading beyond the end of the buffer
+       cmp     $8, len
+       jae     do_align
+       # less_than_8 expects length in upper 3 bits of len_dw
+       # less_than_8_post_shl1 expects length = carryflag * 8 + len_dw[31:30]
+       shl     $32-3+1, len_dw
+       jmp     less_than_8_post_shl1
+
+do_align:
+       #### Calculate CRC of unaligned bytes of the buffer (if any)
+       movq    (bufptmp), tmp          # load a quadward from the buffer
+       add     bufp, bufptmp           # align buffer pointer for quadword
+                                       # processing
+       sub     bufp, len               # update buffer length
+align_loop:
+       crc32b  %bl, crc_init_dw        # compute crc32 of 1-byte
+       shr     $8, tmp                 # get next byte
+       dec     bufp
+       jne     align_loop
+
+proc_block:
+
+       ################################################################
+       ## 2) PROCESS  BLOCKS:
+       ################################################################
+
+       ## compute num of bytes to be processed
+       movq    len, tmp                # save num bytes in tmp
+
+       cmpq    $128*24, len
+       jae     full_block
+
+continue_block:
+       cmpq    $SMALL_SIZE, len
+       jb      small
+
+       ## len < 128*24
+       movq    $2731, %rax             # 2731 = ceil(2^16 / 24)
+       mul     len_dw
+       shrq    $16, %rax
+
+       ## eax contains floor(bytes / 24) = num 24-byte chunks to do
+
+       ## process rax 24-byte chunks (128 >= rax >= 0)
+
+       ## compute end address of each block
+       ## block 0 (base addr + RAX * 8)
+       ## block 1 (base addr + RAX * 16)
+       ## block 2 (base addr + RAX * 24)
+       lea     (bufptmp, %rax, 8), block_0
+       lea     (block_0, %rax, 8), block_1
+       lea     (block_1, %rax, 8), block_2
+
+       xor     crc1, crc1
+       xor     crc2, crc2
+
+       ## branch into array
+       lea     jump_table(%rip), bufp
+       movzxw  (bufp, %rax, 2), len
+       offset=crc_array-jump_table
+       lea     offset(bufp, len, 1), bufp
+       jmp     *bufp
+
+       ################################################################
+       ## 2a) PROCESS FULL BLOCKS:
+       ################################################################
+full_block:
+       movq    $128,%rax
+       lea     128*8*2(block_0), block_1
+       lea     128*8*3(block_0), block_2
+       add     $128*8*1, block_0
+
+       xor     crc1,crc1
+       xor     crc2,crc2
+
+       # Fall thruogh into top of crc array (crc_128)
+
+       ################################################################
+       ## 3) CRC Array:
+       ################################################################
+
+crc_array:
+       i=128
+.rept 128-1
+.altmacro
+LABEL crc_ %i
+.noaltmacro
+       crc32q   -i*8(block_0), crc_init
+       crc32q   -i*8(block_1), crc1
+       crc32q   -i*8(block_2), crc2
+       i=(i-1)
+.endr
+
+.altmacro
+LABEL crc_ %i
+.noaltmacro
+       crc32q   -i*8(block_0), crc_init
+       crc32q   -i*8(block_1), crc1
+# SKIP  crc32  -i*8(block_2), crc2 ; Don't do this one yet
+
+       mov     block_2, block_0
+
+       ################################################################
+       ## 4) Combine three results:
+       ################################################################
+
+       lea     (K_table-16)(%rip), bufp        # first entry is for idx 1
+       shlq    $3, %rax                        # rax *= 8
+       subq    %rax, tmp                       # tmp -= rax*8
+       shlq    $1, %rax
+       subq    %rax, tmp                       # tmp -= rax*16
+                                               # (total tmp -= rax*24)
+       addq    %rax, bufp
+
+       movdqa  (bufp), %xmm0                   # 2 consts: K1:K2
+
+       movq    crc_init, %xmm1                 # CRC for block 1
+       pclmulqdq $0x00,%xmm0,%xmm1             # Multiply by K2
+
+       movq    crc1, %xmm2                     # CRC for block 2
+       pclmulqdq $0x10, %xmm0, %xmm2           # Multiply by K1
+
+       pxor    %xmm2,%xmm1
+       movq    %xmm1, %rax
+       xor     -i*8(block_2), %rax
+       mov     crc2, crc_init
+       crc32   %rax, crc_init
+
+################################################################
+## 5) Check for end:
+################################################################
+
+LABEL crc_ 0
+       mov     tmp, len
+       cmp     $128*24, tmp
+       jae     full_block
+       cmp     $24, tmp
+       jae     continue_block
+
+less_than_24:
+       shl     $32-4, len_dw                   # less_than_16 expects length
+                                               # in upper 4 bits of len_dw
+       jnc     less_than_16
+       crc32q  (bufptmp), crc_init
+       crc32q  8(bufptmp), crc_init
+       jz      do_return
+       add     $16, bufptmp
+       # len is less than 8 if we got here
+       # less_than_8 expects length in upper 3 bits of len_dw
+       # less_than_8_post_shl1 expects length = carryflag * 8 + len_dw[31:30]
+       shl     $2, len_dw
+       jmp     less_than_8_post_shl1
+
+       #######################################################################
+       ## 6) LESS THAN 256-bytes REMAIN AT THIS POINT (8-bits of len are full)
+       #######################################################################
+small:
+       shl $32-8, len_dw               # Prepare len_dw for less_than_256
+       j=256
+.rept 5                                        # j = {256, 128, 64, 32, 16}
+.altmacro
+LABEL less_than_ %j                    # less_than_j: Length should be in
+                                       # upper lg(j) bits of len_dw
+       j=(j/2)
+       shl     $1, len_dw              # Get next MSB
+       JNC_LESS_THAN %j
+.noaltmacro
+       i=0
+.rept (j/8)
+       crc32q  i(bufptmp), crc_init    # Compute crc32 of 8-byte data
+       i=i+8
+.endr
+       jz      do_return               # Return if remaining length is zero
+       add     $j, bufptmp             # Advance buf
+.endr
+
+less_than_8:                           # Length should be stored in
+                                       # upper 3 bits of len_dw
+       shl     $1, len_dw
+less_than_8_post_shl1:
+       jnc     less_than_4
+       crc32l  (bufptmp), crc_init_dw  # CRC of 4 bytes
+       jz      do_return               # return if remaining data is zero
+       add     $4, bufptmp
+less_than_4:                           # Length should be stored in
+                                       # upper 2 bits of len_dw
+       shl     $1, len_dw
+       jnc     less_than_2
+       crc32w  (bufptmp), crc_init_dw  # CRC of 2 bytes
+       jz      do_return               # return if remaining data is zero
+       add     $2, bufptmp
+less_than_2:                           # Length should be stored in the MSB
+                                       # of len_dw
+       shl     $1, len_dw
+       jnc     less_than_1
+       crc32b  (bufptmp), crc_init_dw  # CRC of 1 byte
+less_than_1:                           # Length should be zero
+do_return:
+       movq    crc_init, %rax
+       popq    %rsi
+       popq    %rdi
+       popq    %rbx
+        ret
+
+        ################################################################
+        ## jump table        Table is 129 entries x 2 bytes each
+        ################################################################
+.align 4
+jump_table:
+       i=0
+.rept 129
+.altmacro
+JMPTBL_ENTRY %i
+.noaltmacro
+       i=i+1
+.endr
+       ################################################################
+       ## PCLMULQDQ tables
+       ## Table is 128 entries x 2 quad words each
+       ################################################################
+.data
+.align 64
+K_table:
+        .quad 0x14cd00bd6,0x105ec76f0
+        .quad 0x0ba4fc28e,0x14cd00bd6
+        .quad 0x1d82c63da,0x0f20c0dfe
+        .quad 0x09e4addf8,0x0ba4fc28e
+        .quad 0x039d3b296,0x1384aa63a
+        .quad 0x102f9b8a2,0x1d82c63da
+        .quad 0x14237f5e6,0x01c291d04
+        .quad 0x00d3b6092,0x09e4addf8
+        .quad 0x0c96cfdc0,0x0740eef02
+        .quad 0x18266e456,0x039d3b296
+        .quad 0x0daece73e,0x0083a6eec
+        .quad 0x0ab7aff2a,0x102f9b8a2
+        .quad 0x1248ea574,0x1c1733996
+        .quad 0x083348832,0x14237f5e6
+        .quad 0x12c743124,0x02ad91c30
+        .quad 0x0b9e02b86,0x00d3b6092
+        .quad 0x018b33a4e,0x06992cea2
+        .quad 0x1b331e26a,0x0c96cfdc0
+        .quad 0x17d35ba46,0x07e908048
+        .quad 0x1bf2e8b8a,0x18266e456
+        .quad 0x1a3e0968a,0x11ed1f9d8
+        .quad 0x0ce7f39f4,0x0daece73e
+        .quad 0x061d82e56,0x0f1d0f55e
+        .quad 0x0d270f1a2,0x0ab7aff2a
+        .quad 0x1c3f5f66c,0x0a87ab8a8
+        .quad 0x12ed0daac,0x1248ea574
+        .quad 0x065863b64,0x08462d800
+        .quad 0x11eef4f8e,0x083348832
+        .quad 0x1ee54f54c,0x071d111a8
+        .quad 0x0b3e32c28,0x12c743124
+        .quad 0x0064f7f26,0x0ffd852c6
+        .quad 0x0dd7e3b0c,0x0b9e02b86
+        .quad 0x0f285651c,0x0dcb17aa4
+        .quad 0x010746f3c,0x018b33a4e
+        .quad 0x1c24afea4,0x0f37c5aee
+        .quad 0x0271d9844,0x1b331e26a
+        .quad 0x08e766a0c,0x06051d5a2
+        .quad 0x093a5f730,0x17d35ba46
+        .quad 0x06cb08e5c,0x11d5ca20e
+        .quad 0x06b749fb2,0x1bf2e8b8a
+        .quad 0x1167f94f2,0x021f3d99c
+        .quad 0x0cec3662e,0x1a3e0968a
+        .quad 0x19329634a,0x08f158014
+        .quad 0x0e6fc4e6a,0x0ce7f39f4
+        .quad 0x08227bb8a,0x1a5e82106
+        .quad 0x0b0cd4768,0x061d82e56
+        .quad 0x13c2b89c4,0x188815ab2
+        .quad 0x0d7a4825c,0x0d270f1a2
+        .quad 0x10f5ff2ba,0x105405f3e
+        .quad 0x00167d312,0x1c3f5f66c
+        .quad 0x0f6076544,0x0e9adf796
+        .quad 0x026f6a60a,0x12ed0daac
+        .quad 0x1a2adb74e,0x096638b34
+        .quad 0x19d34af3a,0x065863b64
+        .quad 0x049c3cc9c,0x1e50585a0
+        .quad 0x068bce87a,0x11eef4f8e
+        .quad 0x1524fa6c6,0x19f1c69dc
+        .quad 0x16cba8aca,0x1ee54f54c
+        .quad 0x042d98888,0x12913343e
+        .quad 0x1329d9f7e,0x0b3e32c28
+        .quad 0x1b1c69528,0x088f25a3a
+        .quad 0x02178513a,0x0064f7f26
+        .quad 0x0e0ac139e,0x04e36f0b0
+        .quad 0x0170076fa,0x0dd7e3b0c
+        .quad 0x141a1a2e2,0x0bd6f81f8
+        .quad 0x16ad828b4,0x0f285651c
+        .quad 0x041d17b64,0x19425cbba
+        .quad 0x1fae1cc66,0x010746f3c
+        .quad 0x1a75b4b00,0x18db37e8a
+        .quad 0x0f872e54c,0x1c24afea4
+        .quad 0x01e41e9fc,0x04c144932
+        .quad 0x086d8e4d2,0x0271d9844
+        .quad 0x160f7af7a,0x052148f02
+        .quad 0x05bb8f1bc,0x08e766a0c
+        .quad 0x0a90fd27a,0x0a3c6f37a
+        .quad 0x0b3af077a,0x093a5f730
+        .quad 0x04984d782,0x1d22c238e
+        .quad 0x0ca6ef3ac,0x06cb08e5c
+        .quad 0x0234e0b26,0x063ded06a
+        .quad 0x1d88abd4a,0x06b749fb2
+        .quad 0x04597456a,0x04d56973c
+        .quad 0x0e9e28eb4,0x1167f94f2
+        .quad 0x07b3ff57a,0x19385bf2e
+        .quad 0x0c9c8b782,0x0cec3662e
+        .quad 0x13a9cba9e,0x0e417f38a
+        .quad 0x093e106a4,0x19329634a
+        .quad 0x167001a9c,0x14e727980
+        .quad 0x1ddffc5d4,0x0e6fc4e6a
+        .quad 0x00df04680,0x0d104b8fc
+        .quad 0x02342001e,0x08227bb8a
+        .quad 0x00a2a8d7e,0x05b397730
+        .quad 0x168763fa6,0x0b0cd4768
+        .quad 0x1ed5a407a,0x0e78eb416
+        .quad 0x0d2c3ed1a,0x13c2b89c4
+        .quad 0x0995a5724,0x1641378f0
+        .quad 0x19b1afbc4,0x0d7a4825c
+        .quad 0x109ffedc0,0x08d96551c
+        .quad 0x0f2271e60,0x10f5ff2ba
+        .quad 0x00b0bf8ca,0x00bf80dd2
+        .quad 0x123888b7a,0x00167d312
+        .quad 0x1e888f7dc,0x18dcddd1c
+        .quad 0x002ee03b2,0x0f6076544
+        .quad 0x183e8d8fe,0x06a45d2b2
+        .quad 0x133d7a042,0x026f6a60a
+        .quad 0x116b0f50c,0x1dd3e10e8
+        .quad 0x05fabe670,0x1a2adb74e
+        .quad 0x130004488,0x0de87806c
+        .quad 0x000bcf5f6,0x19d34af3a
+        .quad 0x18f0c7078,0x014338754
+        .quad 0x017f27698,0x049c3cc9c
+        .quad 0x058ca5f00,0x15e3e77ee
+        .quad 0x1af900c24,0x068bce87a
+        .quad 0x0b5cfca28,0x0dd07448e
+        .quad 0x0ded288f8,0x1524fa6c6
+        .quad 0x059f229bc,0x1d8048348
+        .quad 0x06d390dec,0x16cba8aca
+        .quad 0x037170390,0x0a3e3e02c
+        .quad 0x06353c1cc,0x042d98888
+        .quad 0x0c4584f5c,0x0d73c7bea
+        .quad 0x1f16a3418,0x1329d9f7e
+        .quad 0x0531377e2,0x185137662
+        .quad 0x1d8d9ca7c,0x1b1c69528
+        .quad 0x0b25b29f2,0x18a08b5bc
+        .quad 0x19fb2a8b0,0x02178513a
+        .quad 0x1a08fe6ac,0x1da758ae0
+        .quad 0x045cddf4e,0x0e0ac139e
+        .quad 0x1a91647f2,0x169cf9eb0
+        .quad 0x1a0f717c4,0x0170076fa
diff --git a/arch/x86/crypto/glue_helper-asm-avx.S b/arch/x86/crypto/glue_helper-asm-avx.S
new file mode 100644 (file)
index 0000000..f7b6ea2
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Shared glue code for 128bit block ciphers, AVX assembler macros
+ *
+ * Copyright (c) 2012 Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#define load_8way(src, x0, x1, x2, x3, x4, x5, x6, x7) \
+       vmovdqu (0*16)(src), x0; \
+       vmovdqu (1*16)(src), x1; \
+       vmovdqu (2*16)(src), x2; \
+       vmovdqu (3*16)(src), x3; \
+       vmovdqu (4*16)(src), x4; \
+       vmovdqu (5*16)(src), x5; \
+       vmovdqu (6*16)(src), x6; \
+       vmovdqu (7*16)(src), x7;
+
+#define store_8way(dst, x0, x1, x2, x3, x4, x5, x6, x7) \
+       vmovdqu x0, (0*16)(dst); \
+       vmovdqu x1, (1*16)(dst); \
+       vmovdqu x2, (2*16)(dst); \
+       vmovdqu x3, (3*16)(dst); \
+       vmovdqu x4, (4*16)(dst); \
+       vmovdqu x5, (5*16)(dst); \
+       vmovdqu x6, (6*16)(dst); \
+       vmovdqu x7, (7*16)(dst);
+
+#define store_cbc_8way(src, dst, x0, x1, x2, x3, x4, x5, x6, x7) \
+       vpxor (0*16)(src), x1, x1; \
+       vpxor (1*16)(src), x2, x2; \
+       vpxor (2*16)(src), x3, x3; \
+       vpxor (3*16)(src), x4, x4; \
+       vpxor (4*16)(src), x5, x5; \
+       vpxor (5*16)(src), x6, x6; \
+       vpxor (6*16)(src), x7, x7; \
+       store_8way(dst, x0, x1, x2, x3, x4, x5, x6, x7);
+
+#define inc_le128(x, minus_one, tmp) \
+       vpcmpeqq minus_one, x, tmp; \
+       vpsubq minus_one, x, x; \
+       vpslldq $8, tmp, tmp; \
+       vpsubq tmp, x, x;
+
+#define load_ctr_8way(iv, bswap, x0, x1, x2, x3, x4, x5, x6, x7, t0, t1, t2) \
+       vpcmpeqd t0, t0, t0; \
+       vpsrldq $8, t0, t0; /* low: -1, high: 0 */ \
+       vmovdqa bswap, t1; \
+       \
+       /* load IV and byteswap */ \
+       vmovdqu (iv), x7; \
+       vpshufb t1, x7, x0; \
+       \
+       /* construct IVs */ \
+       inc_le128(x7, t0, t2); \
+       vpshufb t1, x7, x1; \
+       inc_le128(x7, t0, t2); \
+       vpshufb t1, x7, x2; \
+       inc_le128(x7, t0, t2); \
+       vpshufb t1, x7, x3; \
+       inc_le128(x7, t0, t2); \
+       vpshufb t1, x7, x4; \
+       inc_le128(x7, t0, t2); \
+       vpshufb t1, x7, x5; \
+       inc_le128(x7, t0, t2); \
+       vpshufb t1, x7, x6; \
+       inc_le128(x7, t0, t2); \
+       vmovdqa x7, t2; \
+       vpshufb t1, x7, x7; \
+       inc_le128(t2, t0, t1); \
+       vmovdqu t2, (iv);
+
+#define store_ctr_8way(src, dst, x0, x1, x2, x3, x4, x5, x6, x7) \
+       vpxor (0*16)(src), x0, x0; \
+       vpxor (1*16)(src), x1, x1; \
+       vpxor (2*16)(src), x2, x2; \
+       vpxor (3*16)(src), x3, x3; \
+       vpxor (4*16)(src), x4, x4; \
+       vpxor (5*16)(src), x5, x5; \
+       vpxor (6*16)(src), x6, x6; \
+       vpxor (7*16)(src), x7, x7; \
+       store_8way(dst, x0, x1, x2, x3, x4, x5, x6, x7);
index 30b3927bd733b6f0c17c0d492621ee1666de2b5a..22ce4f683e550da4b464c99d8fedfce6414ea885 100644 (file)
@@ -221,16 +221,16 @@ static void glue_ctr_crypt_final_128bit(const common_glue_ctr_func_t fn_ctr,
        u8 *src = (u8 *)walk->src.virt.addr;
        u8 *dst = (u8 *)walk->dst.virt.addr;
        unsigned int nbytes = walk->nbytes;
-       u128 ctrblk;
+       le128 ctrblk;
        u128 tmp;
 
-       be128_to_u128(&ctrblk, (be128 *)walk->iv);
+       be128_to_le128(&ctrblk, (be128 *)walk->iv);
 
        memcpy(&tmp, src, nbytes);
        fn_ctr(ctx, &tmp, &tmp, &ctrblk);
        memcpy(dst, &tmp, nbytes);
 
-       u128_to_be128((be128 *)walk->iv, &ctrblk);
+       le128_to_be128((be128 *)walk->iv, &ctrblk);
 }
 EXPORT_SYMBOL_GPL(glue_ctr_crypt_final_128bit);
 
@@ -243,11 +243,11 @@ static unsigned int __glue_ctr_crypt_128bit(const struct common_glue_ctx *gctx,
        unsigned int nbytes = walk->nbytes;
        u128 *src = (u128 *)walk->src.virt.addr;
        u128 *dst = (u128 *)walk->dst.virt.addr;
-       u128 ctrblk;
+       le128 ctrblk;
        unsigned int num_blocks, func_bytes;
        unsigned int i;
 
-       be128_to_u128(&ctrblk, (be128 *)walk->iv);
+       be128_to_le128(&ctrblk, (be128 *)walk->iv);
 
        /* Process multi-block batch */
        for (i = 0; i < gctx->num_funcs; i++) {
@@ -269,7 +269,7 @@ static unsigned int __glue_ctr_crypt_128bit(const struct common_glue_ctx *gctx,
        }
 
 done:
-       u128_to_be128((be128 *)walk->iv, &ctrblk);
+       le128_to_be128((be128 *)walk->iv, &ctrblk);
        return nbytes;
 }
 
index 504106bf04a289c2e1d2d1c7de6bf970062e1279..02b0e9fe997c9208e09da9e31bb798302f3be0f5 100644 (file)
  *
  */
 
+#include "glue_helper-asm-avx.S"
+
 .file "serpent-avx-x86_64-asm_64.S"
+
+.data
+.align 16
+
+.Lbswap128_mask:
+       .byte 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
+
 .text
 
 #define CTX %rdi
        vpunpcklqdq             x3, t2, x2; \
        vpunpckhqdq             x3, t2, x3;
 
-#define read_blocks(in, x0, x1, x2, x3, t0, t1, t2) \
-       vmovdqu (0*4*4)(in),    x0; \
-       vmovdqu (1*4*4)(in),    x1; \
-       vmovdqu (2*4*4)(in),    x2; \
-       vmovdqu (3*4*4)(in),    x3; \
-       \
+#define read_blocks(x0, x1, x2, x3, t0, t1, t2) \
        transpose_4x4(x0, x1, x2, x3, t0, t1, t2)
 
-#define write_blocks(out, x0, x1, x2, x3, t0, t1, t2) \
-       transpose_4x4(x0, x1, x2, x3, t0, t1, t2) \
-       \
-       vmovdqu x0,             (0*4*4)(out); \
-       vmovdqu x1,             (1*4*4)(out); \
-       vmovdqu x2,             (2*4*4)(out); \
-       vmovdqu x3,             (3*4*4)(out);
-
-#define xor_blocks(out, x0, x1, x2, x3, t0, t1, t2) \
-       transpose_4x4(x0, x1, x2, x3, t0, t1, t2) \
-       \
-       vpxor (0*4*4)(out),     x0, x0;       \
-       vmovdqu x0,             (0*4*4)(out); \
-       vpxor (1*4*4)(out),     x1, x1;       \
-       vmovdqu x1,             (1*4*4)(out); \
-       vpxor (2*4*4)(out),     x2, x2;       \
-       vmovdqu x2,             (2*4*4)(out); \
-       vpxor (3*4*4)(out),     x3, x3;       \
-       vmovdqu x3,             (3*4*4)(out);
+#define write_blocks(x0, x1, x2, x3, t0, t1, t2) \
+       transpose_4x4(x0, x1, x2, x3, t0, t1, t2)
 
 .align 8
-.global __serpent_enc_blk_8way_avx
-.type   __serpent_enc_blk_8way_avx,@function;
+.type   __serpent_enc_blk8_avx,@function;
 
-__serpent_enc_blk_8way_avx:
+__serpent_enc_blk8_avx:
        /* input:
         *      %rdi: ctx, CTX
-        *      %rsi: dst
-        *      %rdx: src
-        *      %rcx: bool, if true: xor output
+        *      RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2: blocks
+        * output:
+        *      RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2: encrypted blocks
         */
 
        vpcmpeqd RNOT, RNOT, RNOT;
 
-       leaq (4*4*4)(%rdx), %rax;
-       read_blocks(%rdx, RA1, RB1, RC1, RD1, RK0, RK1, RK2);
-       read_blocks(%rax, RA2, RB2, RC2, RD2, RK0, RK1, RK2);
+       read_blocks(RA1, RB1, RC1, RD1, RK0, RK1, RK2);
+       read_blocks(RA2, RB2, RC2, RD2, RK0, RK1, RK2);
 
                                                 K2(RA, RB, RC, RD, RE, 0);
        S(S0, RA, RB, RC, RD, RE);              LK2(RC, RB, RD, RA, RE, 1);
@@ -630,38 +615,26 @@ __serpent_enc_blk_8way_avx:
        S(S6, RA, RB, RD, RC, RE);              LK2(RD, RE, RB, RC, RA, 31);
        S(S7, RD, RE, RB, RC, RA);               K2(RA, RB, RC, RD, RE, 32);
 
-       leaq (4*4*4)(%rsi), %rax;
-
-       testb %cl, %cl;
-       jnz __enc_xor8;
-
-       write_blocks(%rsi, RA1, RB1, RC1, RD1, RK0, RK1, RK2);
-       write_blocks(%rax, RA2, RB2, RC2, RD2, RK0, RK1, RK2);
-
-       ret;
-
-__enc_xor8:
-       xor_blocks(%rsi, RA1, RB1, RC1, RD1, RK0, RK1, RK2);
-       xor_blocks(%rax, RA2, RB2, RC2, RD2, RK0, RK1, RK2);
+       write_blocks(RA1, RB1, RC1, RD1, RK0, RK1, RK2);
+       write_blocks(RA2, RB2, RC2, RD2, RK0, RK1, RK2);
 
        ret;
 
 .align 8
-.global serpent_dec_blk_8way_avx
-.type   serpent_dec_blk_8way_avx,@function;
+.type   __serpent_dec_blk8_avx,@function;
 
-serpent_dec_blk_8way_avx:
+__serpent_dec_blk8_avx:
        /* input:
         *      %rdi: ctx, CTX
-        *      %rsi: dst
-        *      %rdx: src
+        *      RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2: encrypted blocks
+        * output:
+        *      RC1, RD1, RB1, RE1, RC2, RD2, RB2, RE2: decrypted blocks
         */
 
        vpcmpeqd RNOT, RNOT, RNOT;
 
-       leaq (4*4*4)(%rdx), %rax;
-       read_blocks(%rdx, RA1, RB1, RC1, RD1, RK0, RK1, RK2);
-       read_blocks(%rax, RA2, RB2, RC2, RD2, RK0, RK1, RK2);
+       read_blocks(RA1, RB1, RC1, RD1, RK0, RK1, RK2);
+       read_blocks(RA2, RB2, RC2, RD2, RK0, RK1, RK2);
 
                                                 K2(RA, RB, RC, RD, RE, 32);
        SP(SI7, RA, RB, RC, RD, RE, 31);        KL2(RB, RD, RA, RE, RC, 31);
@@ -697,8 +670,85 @@ serpent_dec_blk_8way_avx:
        SP(SI1, RD, RB, RC, RA, RE, 1);         KL2(RE, RB, RC, RA, RD, 1);
        S(SI0, RE, RB, RC, RA, RD);              K2(RC, RD, RB, RE, RA, 0);
 
-       leaq (4*4*4)(%rsi), %rax;
-       write_blocks(%rsi, RC1, RD1, RB1, RE1, RK0, RK1, RK2);
-       write_blocks(%rax, RC2, RD2, RB2, RE2, RK0, RK1, RK2);
+       write_blocks(RC1, RD1, RB1, RE1, RK0, RK1, RK2);
+       write_blocks(RC2, RD2, RB2, RE2, RK0, RK1, RK2);
+
+       ret;
+
+.align 8
+.global serpent_ecb_enc_8way_avx
+.type   serpent_ecb_enc_8way_avx,@function;
+
+serpent_ecb_enc_8way_avx:
+       /* input:
+        *      %rdi: ctx, CTX
+        *      %rsi: dst
+        *      %rdx: src
+        */
+
+       load_8way(%rdx, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
+
+       call __serpent_enc_blk8_avx;
+
+       store_8way(%rsi, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
+
+       ret;
+
+.align 8
+.global serpent_ecb_dec_8way_avx
+.type   serpent_ecb_dec_8way_avx,@function;
+
+serpent_ecb_dec_8way_avx:
+       /* input:
+        *      %rdi: ctx, CTX
+        *      %rsi: dst
+        *      %rdx: src
+        */
+
+       load_8way(%rdx, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
+
+       call __serpent_dec_blk8_avx;
+
+       store_8way(%rsi, RC1, RD1, RB1, RE1, RC2, RD2, RB2, RE2);
+
+       ret;
+
+.align 8
+.global serpent_cbc_dec_8way_avx
+.type   serpent_cbc_dec_8way_avx,@function;
+
+serpent_cbc_dec_8way_avx:
+       /* input:
+        *      %rdi: ctx, CTX
+        *      %rsi: dst
+        *      %rdx: src
+        */
+
+       load_8way(%rdx, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
+
+       call __serpent_dec_blk8_avx;
+
+       store_cbc_8way(%rdx, %rsi, RC1, RD1, RB1, RE1, RC2, RD2, RB2, RE2);
+
+       ret;
+
+.align 8
+.global serpent_ctr_8way_avx
+.type   serpent_ctr_8way_avx,@function;
+
+serpent_ctr_8way_avx:
+       /* input:
+        *      %rdi: ctx, CTX
+        *      %rsi: dst
+        *      %rdx: src
+        *      %rcx: iv (little endian, 128bit)
+        */
+
+       load_ctr_8way(%rcx, .Lbswap128_mask, RA1, RB1, RC1, RD1, RA2, RB2, RC2,
+                     RD2, RK0, RK1, RK2);
+
+       call __serpent_enc_blk8_avx;
+
+       store_ctr_8way(%rdx, %rsi, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
 
        ret;
index 3f543a04cf1ee2c697e2b2ea1b427ea7f8631386..52abaaf28e7fe798807950a38bfeb0ec6c7361ba 100644 (file)
 #include <asm/crypto/ablk_helper.h>
 #include <asm/crypto/glue_helper.h>
 
-static void serpent_decrypt_cbc_xway(void *ctx, u128 *dst, const u128 *src)
-{
-       u128 ivs[SERPENT_PARALLEL_BLOCKS - 1];
-       unsigned int j;
-
-       for (j = 0; j < SERPENT_PARALLEL_BLOCKS - 1; j++)
-               ivs[j] = src[j];
-
-       serpent_dec_blk_xway(ctx, (u8 *)dst, (u8 *)src);
-
-       for (j = 0; j < SERPENT_PARALLEL_BLOCKS - 1; j++)
-               u128_xor(dst + (j + 1), dst + (j + 1), ivs + j);
-}
-
-static void serpent_crypt_ctr(void *ctx, u128 *dst, const u128 *src, u128 *iv)
+static void serpent_crypt_ctr(void *ctx, u128 *dst, const u128 *src, le128 *iv)
 {
        be128 ctrblk;
 
-       u128_to_be128(&ctrblk, iv);
-       u128_inc(iv);
+       le128_to_be128(&ctrblk, iv);
+       le128_inc(iv);
 
        __serpent_encrypt(ctx, (u8 *)&ctrblk, (u8 *)&ctrblk);
        u128_xor(dst, src, (u128 *)&ctrblk);
 }
 
-static void serpent_crypt_ctr_xway(void *ctx, u128 *dst, const u128 *src,
-                                  u128 *iv)
-{
-       be128 ctrblks[SERPENT_PARALLEL_BLOCKS];
-       unsigned int i;
-
-       for (i = 0; i < SERPENT_PARALLEL_BLOCKS; i++) {
-               if (dst != src)
-                       dst[i] = src[i];
-
-               u128_to_be128(&ctrblks[i], iv);
-               u128_inc(iv);
-       }
-
-       serpent_enc_blk_xway_xor(ctx, (u8 *)dst, (u8 *)ctrblks);
-}
-
 static const struct common_glue_ctx serpent_enc = {
        .num_funcs = 2,
        .fpu_blocks_limit = SERPENT_PARALLEL_BLOCKS,
 
        .funcs = { {
                .num_blocks = SERPENT_PARALLEL_BLOCKS,
-               .fn_u = { .ecb = GLUE_FUNC_CAST(serpent_enc_blk_xway) }
+               .fn_u = { .ecb = GLUE_FUNC_CAST(serpent_ecb_enc_8way_avx) }
        }, {
                .num_blocks = 1,
                .fn_u = { .ecb = GLUE_FUNC_CAST(__serpent_encrypt) }
@@ -103,7 +72,7 @@ static const struct common_glue_ctx serpent_ctr = {
 
        .funcs = { {
                .num_blocks = SERPENT_PARALLEL_BLOCKS,
-               .fn_u = { .ctr = GLUE_CTR_FUNC_CAST(serpent_crypt_ctr_xway) }
+               .fn_u = { .ctr = GLUE_CTR_FUNC_CAST(serpent_ctr_8way_avx) }
        }, {
                .num_blocks = 1,
                .fn_u = { .ctr = GLUE_CTR_FUNC_CAST(serpent_crypt_ctr) }
@@ -116,7 +85,7 @@ static const struct common_glue_ctx serpent_dec = {
 
        .funcs = { {
                .num_blocks = SERPENT_PARALLEL_BLOCKS,
-               .fn_u = { .ecb = GLUE_FUNC_CAST(serpent_dec_blk_xway) }
+               .fn_u = { .ecb = GLUE_FUNC_CAST(serpent_ecb_dec_8way_avx) }
        }, {
                .num_blocks = 1,
                .fn_u = { .ecb = GLUE_FUNC_CAST(__serpent_decrypt) }
@@ -129,7 +98,7 @@ static const struct common_glue_ctx serpent_dec_cbc = {
 
        .funcs = { {
                .num_blocks = SERPENT_PARALLEL_BLOCKS,
-               .fn_u = { .cbc = GLUE_CBC_FUNC_CAST(serpent_decrypt_cbc_xway) }
+               .fn_u = { .cbc = GLUE_CBC_FUNC_CAST(serpent_cbc_dec_8way_avx) }
        }, {
                .num_blocks = 1,
                .fn_u = { .cbc = GLUE_CBC_FUNC_CAST(__serpent_decrypt) }
@@ -193,7 +162,7 @@ static void encrypt_callback(void *priv, u8 *srcdst, unsigned int nbytes)
        ctx->fpu_enabled = serpent_fpu_begin(ctx->fpu_enabled, nbytes);
 
        if (nbytes == bsize * SERPENT_PARALLEL_BLOCKS) {
-               serpent_enc_blk_xway(ctx->ctx, srcdst, srcdst);
+               serpent_ecb_enc_8way_avx(ctx->ctx, srcdst, srcdst);
                return;
        }
 
@@ -210,7 +179,7 @@ static void decrypt_callback(void *priv, u8 *srcdst, unsigned int nbytes)
        ctx->fpu_enabled = serpent_fpu_begin(ctx->fpu_enabled, nbytes);
 
        if (nbytes == bsize * SERPENT_PARALLEL_BLOCKS) {
-               serpent_dec_blk_xway(ctx->ctx, srcdst, srcdst);
+               serpent_ecb_dec_8way_avx(ctx->ctx, srcdst, srcdst);
                return;
        }
 
index 9107a9908c41ecb4a3e591f0c10380487d5c5b47..97a356ece24d2b74d18090760e988c45d2bc914a 100644 (file)
@@ -59,19 +59,19 @@ static void serpent_decrypt_cbc_xway(void *ctx, u128 *dst, const u128 *src)
                u128_xor(dst + (j + 1), dst + (j + 1), ivs + j);
 }
 
-static void serpent_crypt_ctr(void *ctx, u128 *dst, const u128 *src, u128 *iv)
+static void serpent_crypt_ctr(void *ctx, u128 *dst, const u128 *src, le128 *iv)
 {
        be128 ctrblk;
 
-       u128_to_be128(&ctrblk, iv);
-       u128_inc(iv);
+       le128_to_be128(&ctrblk, iv);
+       le128_inc(iv);
 
        __serpent_encrypt(ctx, (u8 *)&ctrblk, (u8 *)&ctrblk);
        u128_xor(dst, src, (u128 *)&ctrblk);
 }
 
 static void serpent_crypt_ctr_xway(void *ctx, u128 *dst, const u128 *src,
-                                  u128 *iv)
+                                  le128 *iv)
 {
        be128 ctrblks[SERPENT_PARALLEL_BLOCKS];
        unsigned int i;
@@ -80,8 +80,8 @@ static void serpent_crypt_ctr_xway(void *ctx, u128 *dst, const u128 *src,
                if (dst != src)
                        dst[i] = src[i];
 
-               u128_to_be128(&ctrblks[i], iv);
-               u128_inc(iv);
+               le128_to_be128(&ctrblks[i], iv);
+               le128_inc(iv);
        }
 
        serpent_enc_blk_xway_xor(ctx, (u8 *)dst, (u8 *)ctrblks);
index 1585abb13ddec3482c07bcd8fa09d470513814a7..ebac16bfa8302331d50bca8dc760965845a4428f 100644 (file)
  *
  */
 
+#include "glue_helper-asm-avx.S"
+
 .file "twofish-avx-x86_64-asm_64.S"
+
+.data
+.align 16
+
+.Lbswap128_mask:
+       .byte 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
+
 .text
 
 /* structure of crypto context */
        vpunpcklqdq             x3, t2, x2; \
        vpunpckhqdq             x3, t2, x3;
 
-#define inpack_blocks(in, x0, x1, x2, x3, wkey, t0, t1, t2) \
-       vpxor (0*4*4)(in),      wkey, x0; \
-       vpxor (1*4*4)(in),      wkey, x1; \
-       vpxor (2*4*4)(in),      wkey, x2; \
-       vpxor (3*4*4)(in),      wkey, x3; \
+#define inpack_blocks(x0, x1, x2, x3, wkey, t0, t1, t2) \
+       vpxor           x0, wkey, x0; \
+       vpxor           x1, wkey, x1; \
+       vpxor           x2, wkey, x2; \
+       vpxor           x3, wkey, x3; \
        \
        transpose_4x4(x0, x1, x2, x3, t0, t1, t2)
 
-#define outunpack_blocks(out, x0, x1, x2, x3, wkey, t0, t1, t2) \
-       transpose_4x4(x0, x1, x2, x3, t0, t1, t2) \
-       \
-       vpxor           x0, wkey, x0;     \
-       vmovdqu         x0, (0*4*4)(out); \
-       vpxor           x1, wkey, x1;     \
-       vmovdqu         x1, (1*4*4)(out); \
-       vpxor           x2, wkey, x2;     \
-       vmovdqu         x2, (2*4*4)(out); \
-       vpxor           x3, wkey, x3;     \
-       vmovdqu         x3, (3*4*4)(out);
-
-#define outunpack_xor_blocks(out, x0, x1, x2, x3, wkey, t0, t1, t2) \
+#define outunpack_blocks(x0, x1, x2, x3, wkey, t0, t1, t2) \
        transpose_4x4(x0, x1, x2, x3, t0, t1, t2) \
        \
-       vpxor           x0, wkey, x0;         \
-       vpxor           (0*4*4)(out), x0, x0; \
-       vmovdqu         x0, (0*4*4)(out);     \
-       vpxor           x1, wkey, x1;         \
-       vpxor           (1*4*4)(out), x1, x1; \
-       vmovdqu         x1, (1*4*4)(out);     \
-       vpxor           x2, wkey, x2;         \
-       vpxor           (2*4*4)(out), x2, x2; \
-       vmovdqu         x2, (2*4*4)(out);     \
-       vpxor           x3, wkey, x3;         \
-       vpxor           (3*4*4)(out), x3, x3; \
-       vmovdqu         x3, (3*4*4)(out);
+       vpxor           x0, wkey, x0; \
+       vpxor           x1, wkey, x1; \
+       vpxor           x2, wkey, x2; \
+       vpxor           x3, wkey, x3;
 
 .align 8
-.global __twofish_enc_blk_8way
-.type   __twofish_enc_blk_8way,@function;
+.type  __twofish_enc_blk8,@function;
 
-__twofish_enc_blk_8way:
+__twofish_enc_blk8:
        /* input:
         *      %rdi: ctx, CTX
-        *      %rsi: dst
-        *      %rdx: src
-        *      %rcx: bool, if true: xor output
+        *      RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2: blocks
+        * output:
+        *      RC1, RD1, RA1, RB1, RC2, RD2, RA2, RB2: encrypted blocks
         */
 
+       vmovdqu w(CTX), RK1;
+
        pushq %rbp;
        pushq %rbx;
        pushq %rcx;
 
-       vmovdqu w(CTX), RK1;
-
-       leaq (4*4*4)(%rdx), %rax;
-       inpack_blocks(%rdx, RA1, RB1, RC1, RD1, RK1, RX0, RY0, RK2);
+       inpack_blocks(RA1, RB1, RC1, RD1, RK1, RX0, RY0, RK2);
        preload_rgi(RA1);
        rotate_1l(RD1);
-       inpack_blocks(%rax, RA2, RB2, RC2, RD2, RK1, RX0, RY0, RK2);
+       inpack_blocks(RA2, RB2, RC2, RD2, RK1, RX0, RY0, RK2);
        rotate_1l(RD2);
 
-       movq %rsi, %r11;
-
        encrypt_cycle(0);
        encrypt_cycle(1);
        encrypt_cycle(2);
@@ -295,47 +280,33 @@ __twofish_enc_blk_8way:
        popq %rbx;
        popq %rbp;
 
-       leaq (4*4*4)(%r11), %rax;
-
-       testb %cl, %cl;
-       jnz __enc_xor8;
-
-       outunpack_blocks(%r11, RC1, RD1, RA1, RB1, RK1, RX0, RY0, RK2);
-       outunpack_blocks(%rax, RC2, RD2, RA2, RB2, RK1, RX0, RY0, RK2);
-
-       ret;
-
-__enc_xor8:
-       outunpack_xor_blocks(%r11, RC1, RD1, RA1, RB1, RK1, RX0, RY0, RK2);
-       outunpack_xor_blocks(%rax, RC2, RD2, RA2, RB2, RK1, RX0, RY0, RK2);
+       outunpack_blocks(RC1, RD1, RA1, RB1, RK1, RX0, RY0, RK2);
+       outunpack_blocks(RC2, RD2, RA2, RB2, RK1, RX0, RY0, RK2);
 
        ret;
 
 .align 8
-.global twofish_dec_blk_8way
-.type   twofish_dec_blk_8way,@function;
+.type  __twofish_dec_blk8,@function;
 
-twofish_dec_blk_8way:
+__twofish_dec_blk8:
        /* input:
         *      %rdi: ctx, CTX
-        *      %rsi: dst
-        *      %rdx: src
+        *      RC1, RD1, RA1, RB1, RC2, RD2, RA2, RB2: encrypted blocks
+        * output:
+        *      RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2: decrypted blocks
         */
 
+       vmovdqu (w+4*4)(CTX), RK1;
+
        pushq %rbp;
        pushq %rbx;
 
-       vmovdqu (w+4*4)(CTX), RK1;
-
-       leaq (4*4*4)(%rdx), %rax;
-       inpack_blocks(%rdx, RC1, RD1, RA1, RB1, RK1, RX0, RY0, RK2);
+       inpack_blocks(RC1, RD1, RA1, RB1, RK1, RX0, RY0, RK2);
        preload_rgi(RC1);
        rotate_1l(RA1);
-       inpack_blocks(%rax, RC2, RD2, RA2, RB2, RK1, RX0, RY0, RK2);
+       inpack_blocks(RC2, RD2, RA2, RB2, RK1, RX0, RY0, RK2);
        rotate_1l(RA2);
 
-       movq %rsi, %r11;
-
        decrypt_cycle(7);
        decrypt_cycle(6);
        decrypt_cycle(5);
@@ -350,8 +321,103 @@ twofish_dec_blk_8way:
        popq %rbx;
        popq %rbp;
 
-       leaq (4*4*4)(%r11), %rax;
-       outunpack_blocks(%r11, RA1, RB1, RC1, RD1, RK1, RX0, RY0, RK2);
-       outunpack_blocks(%rax, RA2, RB2, RC2, RD2, RK1, RX0, RY0, RK2);
+       outunpack_blocks(RA1, RB1, RC1, RD1, RK1, RX0, RY0, RK2);
+       outunpack_blocks(RA2, RB2, RC2, RD2, RK1, RX0, RY0, RK2);
+
+       ret;
+
+.align 8
+.global twofish_ecb_enc_8way
+.type   twofish_ecb_enc_8way,@function;
+
+twofish_ecb_enc_8way:
+       /* input:
+        *      %rdi: ctx, CTX
+        *      %rsi: dst
+        *      %rdx: src
+        */
+
+       movq %rsi, %r11;
+
+       load_8way(%rdx, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
+
+       call __twofish_enc_blk8;
+
+       store_8way(%r11, RC1, RD1, RA1, RB1, RC2, RD2, RA2, RB2);
+
+       ret;
+
+.align 8
+.global twofish_ecb_dec_8way
+.type   twofish_ecb_dec_8way,@function;
+
+twofish_ecb_dec_8way:
+       /* input:
+        *      %rdi: ctx, CTX
+        *      %rsi: dst
+        *      %rdx: src
+        */
+
+       movq %rsi, %r11;
+
+       load_8way(%rdx, RC1, RD1, RA1, RB1, RC2, RD2, RA2, RB2);
+
+       call __twofish_dec_blk8;
+
+       store_8way(%r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
+
+       ret;
+
+.align 8
+.global twofish_cbc_dec_8way
+.type   twofish_cbc_dec_8way,@function;
+
+twofish_cbc_dec_8way:
+       /* input:
+        *      %rdi: ctx, CTX
+        *      %rsi: dst
+        *      %rdx: src
+        */
+
+       pushq %r12;
+
+       movq %rsi, %r11;
+       movq %rdx, %r12;
+
+       load_8way(%rdx, RC1, RD1, RA1, RB1, RC2, RD2, RA2, RB2);
+
+       call __twofish_dec_blk8;
+
+       store_cbc_8way(%r12, %r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
+
+       popq %r12;
+
+       ret;
+
+.align 8
+.global twofish_ctr_8way
+.type   twofish_ctr_8way,@function;
+
+twofish_ctr_8way:
+       /* input:
+        *      %rdi: ctx, CTX
+        *      %rsi: dst
+        *      %rdx: src
+        *      %rcx: iv (little endian, 128bit)
+        */
+
+       pushq %r12;
+
+       movq %rsi, %r11;
+       movq %rdx, %r12;
+
+       load_ctr_8way(%rcx, .Lbswap128_mask, RA1, RB1, RC1, RD1, RA2, RB2, RC2,
+                     RD2, RX0, RX1, RY0);
+
+       call __twofish_enc_blk8;
+
+       store_ctr_8way(%r12, %r11, RC1, RD1, RA1, RB1, RC2, RD2, RA2, RB2);
+
+       popq %r12;
 
        ret;
index e7708b5442e0b59ab7478306124c8c84493a551c..94ac91d26e47e3b4ef415df06115d1c490b9f6a9 100644 (file)
 
 #define TWOFISH_PARALLEL_BLOCKS 8
 
-static inline void twofish_enc_blk_3way(struct twofish_ctx *ctx, u8 *dst,
-                                       const u8 *src)
-{
-       __twofish_enc_blk_3way(ctx, dst, src, false);
-}
-
 /* 8-way parallel cipher functions */
-asmlinkage void __twofish_enc_blk_8way(struct twofish_ctx *ctx, u8 *dst,
-                                      const u8 *src, bool xor);
-asmlinkage void twofish_dec_blk_8way(struct twofish_ctx *ctx, u8 *dst,
+asmlinkage void twofish_ecb_enc_8way(struct twofish_ctx *ctx, u8 *dst,
+                                    const u8 *src);
+asmlinkage void twofish_ecb_dec_8way(struct twofish_ctx *ctx, u8 *dst,
                                     const u8 *src);
 
-static inline void twofish_enc_blk_xway(struct twofish_ctx *ctx, u8 *dst,
-                                       const u8 *src)
-{
-       __twofish_enc_blk_8way(ctx, dst, src, false);
-}
-
-static inline void twofish_enc_blk_xway_xor(struct twofish_ctx *ctx, u8 *dst,
-                                           const u8 *src)
-{
-       __twofish_enc_blk_8way(ctx, dst, src, true);
-}
+asmlinkage void twofish_cbc_dec_8way(struct twofish_ctx *ctx, u8 *dst,
+                                    const u8 *src);
+asmlinkage void twofish_ctr_8way(struct twofish_ctx *ctx, u8 *dst,
+                                const u8 *src, le128 *iv);
 
-static inline void twofish_dec_blk_xway(struct twofish_ctx *ctx, u8 *dst,
+static inline void twofish_enc_blk_3way(struct twofish_ctx *ctx, u8 *dst,
                                        const u8 *src)
 {
-       twofish_dec_blk_8way(ctx, dst, src);
-}
-
-static void twofish_dec_blk_cbc_xway(void *ctx, u128 *dst, const u128 *src)
-{
-       u128 ivs[TWOFISH_PARALLEL_BLOCKS - 1];
-       unsigned int j;
-
-       for (j = 0; j < TWOFISH_PARALLEL_BLOCKS - 1; j++)
-               ivs[j] = src[j];
-
-       twofish_dec_blk_xway(ctx, (u8 *)dst, (u8 *)src);
-
-       for (j = 0; j < TWOFISH_PARALLEL_BLOCKS - 1; j++)
-               u128_xor(dst + (j + 1), dst + (j + 1), ivs + j);
+       __twofish_enc_blk_3way(ctx, dst, src, false);
 }
 
-static void twofish_enc_blk_ctr_xway(void *ctx, u128 *dst, const u128 *src,
-                                    u128 *iv)
-{
-       be128 ctrblks[TWOFISH_PARALLEL_BLOCKS];
-       unsigned int i;
-
-       for (i = 0; i < TWOFISH_PARALLEL_BLOCKS; i++) {
-               if (dst != src)
-                       dst[i] = src[i];
-
-               u128_to_be128(&ctrblks[i], iv);
-               u128_inc(iv);
-       }
-
-       twofish_enc_blk_xway_xor(ctx, (u8 *)dst, (u8 *)ctrblks);
-}
 
 static const struct common_glue_ctx twofish_enc = {
        .num_funcs = 3,
@@ -112,7 +69,7 @@ static const struct common_glue_ctx twofish_enc = {
 
        .funcs = { {
                .num_blocks = TWOFISH_PARALLEL_BLOCKS,
-               .fn_u = { .ecb = GLUE_FUNC_CAST(twofish_enc_blk_xway) }
+               .fn_u = { .ecb = GLUE_FUNC_CAST(twofish_ecb_enc_8way) }
        }, {
                .num_blocks = 3,
                .fn_u = { .ecb = GLUE_FUNC_CAST(twofish_enc_blk_3way) }
@@ -128,7 +85,7 @@ static const struct common_glue_ctx twofish_ctr = {
 
        .funcs = { {
                .num_blocks = TWOFISH_PARALLEL_BLOCKS,
-               .fn_u = { .ctr = GLUE_CTR_FUNC_CAST(twofish_enc_blk_ctr_xway) }
+               .fn_u = { .ctr = GLUE_CTR_FUNC_CAST(twofish_ctr_8way) }
        }, {
                .num_blocks = 3,
                .fn_u = { .ctr = GLUE_CTR_FUNC_CAST(twofish_enc_blk_ctr_3way) }
@@ -144,7 +101,7 @@ static const struct common_glue_ctx twofish_dec = {
 
        .funcs = { {
                .num_blocks = TWOFISH_PARALLEL_BLOCKS,
-               .fn_u = { .ecb = GLUE_FUNC_CAST(twofish_dec_blk_xway) }
+               .fn_u = { .ecb = GLUE_FUNC_CAST(twofish_ecb_dec_8way) }
        }, {
                .num_blocks = 3,
                .fn_u = { .ecb = GLUE_FUNC_CAST(twofish_dec_blk_3way) }
@@ -160,7 +117,7 @@ static const struct common_glue_ctx twofish_dec_cbc = {
 
        .funcs = { {
                .num_blocks = TWOFISH_PARALLEL_BLOCKS,
-               .fn_u = { .cbc = GLUE_CBC_FUNC_CAST(twofish_dec_blk_cbc_xway) }
+               .fn_u = { .cbc = GLUE_CBC_FUNC_CAST(twofish_cbc_dec_8way) }
        }, {
                .num_blocks = 3,
                .fn_u = { .cbc = GLUE_CBC_FUNC_CAST(twofish_dec_blk_cbc_3way) }
@@ -227,7 +184,7 @@ static void encrypt_callback(void *priv, u8 *srcdst, unsigned int nbytes)
        ctx->fpu_enabled = twofish_fpu_begin(ctx->fpu_enabled, nbytes);
 
        if (nbytes == bsize * TWOFISH_PARALLEL_BLOCKS) {
-               twofish_enc_blk_xway(ctx->ctx, srcdst, srcdst);
+               twofish_ecb_enc_8way(ctx->ctx, srcdst, srcdst);
                return;
        }
 
@@ -249,7 +206,7 @@ static void decrypt_callback(void *priv, u8 *srcdst, unsigned int nbytes)
        ctx->fpu_enabled = twofish_fpu_begin(ctx->fpu_enabled, nbytes);
 
        if (nbytes == bsize * TWOFISH_PARALLEL_BLOCKS) {
-               twofish_dec_blk_xway(ctx->ctx, srcdst, srcdst);
+               twofish_ecb_dec_8way(ctx->ctx, srcdst, srcdst);
                return;
        }
 
index aa3eb358b7e81b82d1816cbafbc58a04349d3428..13e63b3e1dfb44593ea2274a63adebfbdce7e6ce 100644 (file)
@@ -62,15 +62,15 @@ void twofish_dec_blk_cbc_3way(void *ctx, u128 *dst, const u128 *src)
 }
 EXPORT_SYMBOL_GPL(twofish_dec_blk_cbc_3way);
 
-void twofish_enc_blk_ctr(void *ctx, u128 *dst, const u128 *src, u128 *iv)
+void twofish_enc_blk_ctr(void *ctx, u128 *dst, const u128 *src, le128 *iv)
 {
        be128 ctrblk;
 
        if (dst != src)
                *dst = *src;
 
-       u128_to_be128(&ctrblk, iv);
-       u128_inc(iv);
+       le128_to_be128(&ctrblk, iv);
+       le128_inc(iv);
 
        twofish_enc_blk(ctx, (u8 *)&ctrblk, (u8 *)&ctrblk);
        u128_xor(dst, dst, (u128 *)&ctrblk);
@@ -78,7 +78,7 @@ void twofish_enc_blk_ctr(void *ctx, u128 *dst, const u128 *src, u128 *iv)
 EXPORT_SYMBOL_GPL(twofish_enc_blk_ctr);
 
 void twofish_enc_blk_ctr_3way(void *ctx, u128 *dst, const u128 *src,
-                                    u128 *iv)
+                             le128 *iv)
 {
        be128 ctrblks[3];
 
@@ -88,12 +88,12 @@ void twofish_enc_blk_ctr_3way(void *ctx, u128 *dst, const u128 *src,
                dst[2] = src[2];
        }
 
-       u128_to_be128(&ctrblks[0], iv);
-       u128_inc(iv);
-       u128_to_be128(&ctrblks[1], iv);
-       u128_inc(iv);
-       u128_to_be128(&ctrblks[2], iv);
-       u128_inc(iv);
+       le128_to_be128(&ctrblks[0], iv);
+       le128_inc(iv);
+       le128_to_be128(&ctrblks[1], iv);
+       le128_inc(iv);
+       le128_to_be128(&ctrblks[2], iv);
+       le128_inc(iv);
 
        twofish_enc_blk_xor_3way(ctx, (u8 *)dst, (u8 *)ctrblks);
 }
index 3e408bddc96f1f80ae66c60152c14533fdd12012..e2d65b061d27801c0c515dda3d1bc956ada4b563 100644 (file)
@@ -13,7 +13,7 @@
 typedef void (*common_glue_func_t)(void *ctx, u8 *dst, const u8 *src);
 typedef void (*common_glue_cbc_func_t)(void *ctx, u128 *dst, const u128 *src);
 typedef void (*common_glue_ctr_func_t)(void *ctx, u128 *dst, const u128 *src,
-                                      u128 *iv);
+                                      le128 *iv);
 
 #define GLUE_FUNC_CAST(fn) ((common_glue_func_t)(fn))
 #define GLUE_CBC_FUNC_CAST(fn) ((common_glue_cbc_func_t)(fn))
@@ -71,23 +71,29 @@ static inline void glue_fpu_end(bool fpu_enabled)
                kernel_fpu_end();
 }
 
-static inline void u128_to_be128(be128 *dst, const u128 *src)
+static inline void le128_to_be128(be128 *dst, const le128 *src)
 {
-       dst->a = cpu_to_be64(src->a);
-       dst->b = cpu_to_be64(src->b);
+       dst->a = cpu_to_be64(le64_to_cpu(src->a));
+       dst->b = cpu_to_be64(le64_to_cpu(src->b));
 }
 
-static inline void be128_to_u128(u128 *dst, const be128 *src)
+static inline void be128_to_le128(le128 *dst, const be128 *src)
 {
-       dst->a = be64_to_cpu(src->a);
-       dst->b = be64_to_cpu(src->b);
+       dst->a = cpu_to_le64(be64_to_cpu(src->a));
+       dst->b = cpu_to_le64(be64_to_cpu(src->b));
 }
 
-static inline void u128_inc(u128 *i)
+static inline void le128_inc(le128 *i)
 {
-       i->b++;
-       if (!i->b)
-               i->a++;
+       u64 a = le64_to_cpu(i->a);
+       u64 b = le64_to_cpu(i->b);
+
+       b++;
+       if (!b)
+               a++;
+
+       i->a = cpu_to_le64(a);
+       i->b = cpu_to_le64(b);
 }
 
 extern int glue_ecb_crypt_128bit(const struct common_glue_ctx *gctx,
index 432deedd294570bd1b0807491fca242027d70ab7..0da1d3e2a55ce3710509d0f3051af046b081a5e4 100644 (file)
@@ -6,27 +6,14 @@
 
 #define SERPENT_PARALLEL_BLOCKS 8
 
-asmlinkage void __serpent_enc_blk_8way_avx(struct serpent_ctx *ctx, u8 *dst,
-                                          const u8 *src, bool xor);
-asmlinkage void serpent_dec_blk_8way_avx(struct serpent_ctx *ctx, u8 *dst,
+asmlinkage void serpent_ecb_enc_8way_avx(struct serpent_ctx *ctx, u8 *dst,
+                                        const u8 *src);
+asmlinkage void serpent_ecb_dec_8way_avx(struct serpent_ctx *ctx, u8 *dst,
                                         const u8 *src);
 
-static inline void serpent_enc_blk_xway(struct serpent_ctx *ctx, u8 *dst,
-                                  const u8 *src)
-{
-       __serpent_enc_blk_8way_avx(ctx, dst, src, false);
-}
-
-static inline void serpent_enc_blk_xway_xor(struct serpent_ctx *ctx, u8 *dst,
-                                      const u8 *src)
-{
-       __serpent_enc_blk_8way_avx(ctx, dst, src, true);
-}
-
-static inline void serpent_dec_blk_xway(struct serpent_ctx *ctx, u8 *dst,
-                                  const u8 *src)
-{
-       serpent_dec_blk_8way_avx(ctx, dst, src);
-}
+asmlinkage void serpent_cbc_dec_8way_avx(struct serpent_ctx *ctx, u8 *dst,
+                                        const u8 *src);
+asmlinkage void serpent_ctr_8way_avx(struct serpent_ctx *ctx, u8 *dst,
+                                    const u8 *src, le128 *iv);
 
 #endif
index 9d2c514bd5f90020b3d22036a73ab816735b3416..878c51ceebb57f408d78eb94abb13d16d0c2801d 100644 (file)
@@ -31,9 +31,9 @@ asmlinkage void twofish_dec_blk_3way(struct twofish_ctx *ctx, u8 *dst,
 /* helpers from twofish_x86_64-3way module */
 extern void twofish_dec_blk_cbc_3way(void *ctx, u128 *dst, const u128 *src);
 extern void twofish_enc_blk_ctr(void *ctx, u128 *dst, const u128 *src,
-                               u128 *iv);
+                               le128 *iv);
 extern void twofish_enc_blk_ctr_3way(void *ctx, u128 *dst, const u128 *src,
-                                    u128 *iv);
+                                    le128 *iv);
 
 extern int lrw_twofish_setkey(struct crypto_tfm *tfm, const u8 *key,
                              unsigned int keylen);
index f7b4c7903e7e51eb317ecfcd6fa9be05a3336f65..808dae63eeea6f73eb312d4f5b7f77cf4e869e6c 100644 (file)
@@ -47,6 +47,7 @@ static inline struct dma_map_ops *get_dma_ops(struct device *dev)
 static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
 {
        struct dma_map_ops *ops = get_dma_ops(dev);
+       debug_dma_mapping_error(dev, dma_addr);
        if (ops->mapping_error)
                return ops->mapping_error(dev, dma_addr);
 
index c9dcc181d4d1a814c10d6822d0801c7a1b2d7196..36ff332da130a32766867074ff4c17bfd039b59e 100644 (file)
@@ -35,7 +35,7 @@ extern unsigned long asmlinkage efi_call_phys(void *, ...);
 #define efi_call_virt6(f, a1, a2, a3, a4, a5, a6)      \
        efi_call_virt(f, a1, a2, a3, a4, a5, a6)
 
-#define efi_ioremap(addr, size, type)          ioremap_cache(addr, size)
+#define efi_ioremap(addr, size, type, attr)    ioremap_cache(addr, size)
 
 #else /* !CONFIG_X86_32 */
 
@@ -89,7 +89,7 @@ extern u64 efi_call6(void *fp, u64 arg1, u64 arg2, u64 arg3,
                  (u64)(a3), (u64)(a4), (u64)(a5), (u64)(a6))
 
 extern void __iomem *efi_ioremap(unsigned long addr, unsigned long size,
-                                u32 type);
+                                u32 type, u64 attribute);
 
 #endif /* CONFIG_X86_32 */
 
@@ -98,6 +98,7 @@ extern void efi_set_executable(efi_memory_desc_t *md, bool executable);
 extern int efi_memblock_x86_reserve_range(void);
 extern void efi_call_phys_prelog(void);
 extern void efi_call_phys_epilog(void);
+extern void efi_memory_uc(u64 addr, unsigned long size);
 
 #ifndef CONFIG_EFI
 /*
index a1f780d45f7628a741939ba65e0f711d0fce468b..ecf64b4ed752fee91fe616bfc888695df9ed9ad4 100644 (file)
@@ -349,6 +349,7 @@ static inline pgprot_t pgprot_modify(pgprot_t oldprot, pgprot_t newprot)
 }
 
 #define pte_pgprot(x) __pgprot(pte_flags(x) & PTE_FLAGS_MASK)
+#define pmd_pgprot(x) __pgprot(pmd_val(x) & ~_HPAGE_CHG_MASK)
 
 #define canon_pgprot(p) __pgprot(massage_pgprot(p))
 
@@ -407,6 +408,12 @@ static inline int pte_present(pte_t a)
        return pte_flags(a) & (_PAGE_PRESENT | _PAGE_PROTNONE);
 }
 
+#define __HAVE_ARCH_PTE_ACCESSIBLE
+static inline int pte_accessible(pte_t a)
+{
+       return pte_flags(a) & _PAGE_PRESENT;
+}
+
 static inline int pte_hidden(pte_t pte)
 {
        return pte_flags(pte) & _PAGE_HIDDEN;
index 6d2f75a82a14bca62162f38cde9fff8e6404bec9..5dc619819f311555b124c9a2da0c19cda39f2d24 100644 (file)
  * with Xen so that on ARM we can have one ABI that works for 32 and 64
  * bit guests. */
 typedef unsigned long xen_pfn_t;
+#define PRI_xen_pfn "lx"
 typedef unsigned long xen_ulong_t;
+#define PRI_xen_ulong "lx"
 /* Guest handles for primitive C types. */
 __DEFINE_GUEST_HANDLE(uchar, unsigned char);
 __DEFINE_GUEST_HANDLE(uint,  unsigned int);
-__DEFINE_GUEST_HANDLE(ulong, unsigned long);
 DEFINE_GUEST_HANDLE(char);
 DEFINE_GUEST_HANDLE(int);
-DEFINE_GUEST_HANDLE(long);
 DEFINE_GUEST_HANDLE(void);
 DEFINE_GUEST_HANDLE(uint64_t);
 DEFINE_GUEST_HANDLE(uint32_t);
@@ -144,7 +144,8 @@ struct vcpu_guest_context {
     struct cpu_user_regs user_regs;         /* User-level CPU registers     */
     struct trap_info trap_ctxt[256];        /* Virtual IDT                  */
     unsigned long ldt_base, ldt_ents;       /* LDT (linear address, # ents) */
-    unsigned long gdt_frames[16], gdt_ents; /* GDT (machine frames, # ents) */
+    unsigned long gdt_frames[16], gdt_ents; /* GDT (machine frames, # ents).*
+                                            * PV in HVM: it's GDTR addr/sz */
     unsigned long kernel_ss, kernel_sp;     /* Virtual TSS (only SS1/SP1)   */
     /* NB. User pagetable on x86/64 is placed in ctrlreg[1]. */
     unsigned long ctrlreg[8];               /* CR0-CR7 (control registers)  */
index 472b9b783019a2e2f7c7b273ab7b13b96ec257b9..6af440d5a53315f5ebc5e54e211f5e22f705f96b 100644 (file)
@@ -159,6 +159,9 @@ static inline xpaddr_t machine_to_phys(xmaddr_t machine)
 static inline unsigned long mfn_to_local_pfn(unsigned long mfn)
 {
        unsigned long pfn = mfn_to_pfn(mfn);
+
+       if (xen_feature(XENFEAT_auto_translated_physmap))
+               return mfn;
        if (get_phys_to_machine(pfn) != mfn)
                return -1; /* force !pfn_valid() */
        return pfn;
index 91ce48f05f9f6d623beaa84029be5ff1cdf1cfc8..9fd5eed3f8f5d30bf9256cdc88719df06f4dee5d 100644 (file)
@@ -9,7 +9,6 @@ CPPFLAGS_vmlinux.lds += -U$(UTS_MACHINE)
 ifdef CONFIG_FUNCTION_TRACER
 # Do not profile debug and lowlevel utilities
 CFLAGS_REMOVE_tsc.o = -pg
-CFLAGS_REMOVE_rtc.o = -pg
 CFLAGS_REMOVE_paravirt-spinlocks.o = -pg
 CFLAGS_REMOVE_pvclock.o = -pg
 CFLAGS_REMOVE_kvmclock.o = -pg
index e651f7a589acaced6ea79f56aaccbf4a9fbece8d..46f2c0f31cda45e9302c77fae9ac9fd7cc5f8927 100644 (file)
@@ -1700,3 +1700,9 @@ int __acpi_release_global_lock(unsigned int *lock)
        } while (unlikely (val != old));
        return old & 0x1;
 }
+
+void __init arch_reserve_mem_area(acpi_physical_address addr, size_t size)
+{
+       e820_add_region(addr, size, E820_ACPI);
+       update_e820();
+}
index 11676cf65aee5ee51b64c8fadda0261c1f38599f..d5e0d717005abd1f9b610ff1ce39beaefaa080f0 100644 (file)
@@ -101,6 +101,8 @@ static int __init acpi_sleep_setup(char *str)
 #endif
                if (strncmp(str, "nonvs", 5) == 0)
                        acpi_nvs_nosave();
+               if (strncmp(str, "nonvs_s3", 8) == 0)
+                       acpi_nvs_nosave_s3();
                if (strncmp(str, "old_ordering", 12) == 0)
                        acpi_old_suspend_ordering();
                str = strchr(str, ',');
index c265593ec2cdc3df35fda1586aaf91514fab62fa..1817fa911024f07151d3edf91bd350722c9f79f8 100644 (file)
@@ -2257,6 +2257,9 @@ asmlinkage void smp_irq_move_cleanup_interrupt(void)
                        continue;
 
                cfg = irq_cfg(irq);
+               if (!cfg)
+                       continue;
+
                raw_spin_lock(&desc->lock);
 
                /*
index 9a7c90d80bc4c87bafd96cb73efb46ced84b5276..93c5451bdd527ca9436a98b661e9f3165e484570 100644 (file)
@@ -991,7 +991,7 @@ static struct attribute ** __cpuinit amd_l3_attrs(void)
        if (attrs)
                return attrs;
 
-       n = sizeof (default_attrs) / sizeof (struct attribute *);
+       n = ARRAY_SIZE(default_attrs);
 
        if (amd_nb_has_feature(AMD_NB_L3_INDEX_DISABLE))
                n += 2;
index 29e87d3b2843610207ebd875071a4291bec02cfe..46cbf8689692fdbd3d0517d6e20d20a9e192f5e0 100644 (file)
@@ -2209,11 +2209,6 @@ static struct dev_ext_attribute dev_attr_cmci_disabled = {
        &mce_cmci_disabled
 };
 
-static struct dev_ext_attribute dev_attr_bios_cmci_threshold = {
-       __ATTR(bios_cmci_threshold, 0444, device_show_int, NULL),
-       &mce_bios_cmci_threshold
-};
-
 static struct device_attribute *mce_device_attrs[] = {
        &dev_attr_tolerant.attr,
        &dev_attr_check_interval.attr,
@@ -2222,7 +2217,6 @@ static struct device_attribute *mce_device_attrs[] = {
        &dev_attr_dont_log_ce.attr,
        &dev_attr_ignore_ce.attr,
        &dev_attr_cmci_disabled.attr,
-       &dev_attr_bios_cmci_threshold.attr,
        NULL
 };
 
index c4e916d773780f4239ac831478c15aa2325c7382..698b6ec12e0f40f9c292b9f84206b38214d9fe7e 100644 (file)
@@ -576,12 +576,10 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank)
        int err = 0;
 
        if (shared_bank[bank]) {
-
                nb = node_to_amd_nb(amd_get_nb_id(cpu));
-               WARN_ON(!nb);
 
                /* threshold descriptor already initialized on this node? */
-               if (nb->bank4) {
+               if (nb && nb->bank4) {
                        /* yes, use it */
                        b = nb->bank4;
                        err = kobject_add(b->kobj, &dev->kobj, name);
@@ -615,8 +613,10 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank)
                atomic_set(&b->cpus, 1);
 
                /* nb is already initialized, see above */
-               WARN_ON(nb->bank4);
-               nb->bank4 = b;
+               if (nb) {
+                       WARN_ON(nb->bank4);
+                       nb->bank4 = b;
+               }
        }
 
        err = allocate_threshold_blocks(cpu, bank, 0,
index 915b876edd1e2b8a509786446642302648989a73..0a55ab2ff849925ddc47d8db04cb8e14e4a2e7b1 100644 (file)
@@ -208,12 +208,14 @@ static bool check_hw_exists(void)
        }
 
        /*
-        * Now write a value and read it back to see if it matches,
-        * this is needed to detect certain hardware emulators (qemu/kvm)
-        * that don't trap on the MSR access and always return 0s.
+        * Read the current value, change it and read it back to see if it
+        * matches, this is needed to detect certain hardware emulators
+        * (qemu/kvm) that don't trap on the MSR access and always return 0s.
         */
-       val = 0xabcdUL;
        reg = x86_pmu_event_addr(0);
+       if (rdmsrl_safe(reg, &val))
+               goto msr_fail;
+       val ^= 0xffffUL;
        ret = wrmsrl_safe(reg, val);
        ret |= rdmsrl_safe(reg, &val_new);
        if (ret || val != val_new)
@@ -338,6 +340,9 @@ int x86_setup_perfctr(struct perf_event *event)
                /* BTS is currently only allowed for user-mode. */
                if (!attr->exclude_kernel)
                        return -EOPNOTSUPP;
+
+               if (!attr->exclude_guest)
+                       return -EOPNOTSUPP;
        }
 
        hwc->config |= config;
@@ -380,6 +385,9 @@ int x86_pmu_hw_config(struct perf_event *event)
        if (event->attr.precise_ip) {
                int precise = 0;
 
+               if (!event->attr.exclude_guest)
+                       return -EOPNOTSUPP;
+
                /* Support for constant skid */
                if (x86_pmu.pebs_active && !x86_pmu.pebs_broken) {
                        precise++;
@@ -1308,6 +1316,121 @@ static struct attribute_group x86_pmu_format_group = {
        .attrs = NULL,
 };
 
+struct perf_pmu_events_attr {
+       struct device_attribute attr;
+       u64 id;
+};
+
+/*
+ * Remove all undefined events (x86_pmu.event_map(id) == 0)
+ * out of events_attr attributes.
+ */
+static void __init filter_events(struct attribute **attrs)
+{
+       int i, j;
+
+       for (i = 0; attrs[i]; i++) {
+               if (x86_pmu.event_map(i))
+                       continue;
+
+               for (j = i; attrs[j]; j++)
+                       attrs[j] = attrs[j + 1];
+
+               /* Check the shifted attr. */
+               i--;
+       }
+}
+
+ssize_t events_sysfs_show(struct device *dev, struct device_attribute *attr,
+                         char *page)
+{
+       struct perf_pmu_events_attr *pmu_attr = \
+               container_of(attr, struct perf_pmu_events_attr, attr);
+
+       u64 config = x86_pmu.event_map(pmu_attr->id);
+       return x86_pmu.events_sysfs_show(page, config);
+}
+
+#define EVENT_VAR(_id)  event_attr_##_id
+#define EVENT_PTR(_id) &event_attr_##_id.attr.attr
+
+#define EVENT_ATTR(_name, _id)                                 \
+static struct perf_pmu_events_attr EVENT_VAR(_id) = {          \
+       .attr = __ATTR(_name, 0444, events_sysfs_show, NULL),   \
+       .id   =  PERF_COUNT_HW_##_id,                           \
+};
+
+EVENT_ATTR(cpu-cycles,                 CPU_CYCLES              );
+EVENT_ATTR(instructions,               INSTRUCTIONS            );
+EVENT_ATTR(cache-references,           CACHE_REFERENCES        );
+EVENT_ATTR(cache-misses,               CACHE_MISSES            );
+EVENT_ATTR(branch-instructions,                BRANCH_INSTRUCTIONS     );
+EVENT_ATTR(branch-misses,              BRANCH_MISSES           );
+EVENT_ATTR(bus-cycles,                 BUS_CYCLES              );
+EVENT_ATTR(stalled-cycles-frontend,    STALLED_CYCLES_FRONTEND );
+EVENT_ATTR(stalled-cycles-backend,     STALLED_CYCLES_BACKEND  );
+EVENT_ATTR(ref-cycles,                 REF_CPU_CYCLES          );
+
+static struct attribute *empty_attrs;
+
+struct attribute *events_attr[] = {
+       EVENT_PTR(CPU_CYCLES),
+       EVENT_PTR(INSTRUCTIONS),
+       EVENT_PTR(CACHE_REFERENCES),
+       EVENT_PTR(CACHE_MISSES),
+       EVENT_PTR(BRANCH_INSTRUCTIONS),
+       EVENT_PTR(BRANCH_MISSES),
+       EVENT_PTR(BUS_CYCLES),
+       EVENT_PTR(STALLED_CYCLES_FRONTEND),
+       EVENT_PTR(STALLED_CYCLES_BACKEND),
+       EVENT_PTR(REF_CPU_CYCLES),
+       NULL,
+};
+
+static struct attribute_group x86_pmu_events_group = {
+       .name = "events",
+       .attrs = events_attr,
+};
+
+ssize_t x86_event_sysfs_show(char *page, u64 config, u64 event)
+{
+       u64 umask  = (config & ARCH_PERFMON_EVENTSEL_UMASK) >> 8;
+       u64 cmask  = (config & ARCH_PERFMON_EVENTSEL_CMASK) >> 24;
+       bool edge  = (config & ARCH_PERFMON_EVENTSEL_EDGE);
+       bool pc    = (config & ARCH_PERFMON_EVENTSEL_PIN_CONTROL);
+       bool any   = (config & ARCH_PERFMON_EVENTSEL_ANY);
+       bool inv   = (config & ARCH_PERFMON_EVENTSEL_INV);
+       ssize_t ret;
+
+       /*
+       * We have whole page size to spend and just little data
+       * to write, so we can safely use sprintf.
+       */
+       ret = sprintf(page, "event=0x%02llx", event);
+
+       if (umask)
+               ret += sprintf(page + ret, ",umask=0x%02llx", umask);
+
+       if (edge)
+               ret += sprintf(page + ret, ",edge");
+
+       if (pc)
+               ret += sprintf(page + ret, ",pc");
+
+       if (any)
+               ret += sprintf(page + ret, ",any");
+
+       if (inv)
+               ret += sprintf(page + ret, ",inv");
+
+       if (cmask)
+               ret += sprintf(page + ret, ",cmask=0x%02llx", cmask);
+
+       ret += sprintf(page + ret, "\n");
+
+       return ret;
+}
+
 static int __init init_hw_perf_events(void)
 {
        struct x86_pmu_quirk *quirk;
@@ -1354,6 +1477,11 @@ static int __init init_hw_perf_events(void)
        x86_pmu.attr_rdpmc = 1; /* enable userspace RDPMC usage by default */
        x86_pmu_format_group.attrs = x86_pmu.format_attrs;
 
+       if (!x86_pmu.events_sysfs_show)
+               x86_pmu_events_group.attrs = &empty_attrs;
+       else
+               filter_events(x86_pmu_events_group.attrs);
+
        pr_info("... version:                %d\n",     x86_pmu.version);
        pr_info("... bit width:              %d\n",     x86_pmu.cntval_bits);
        pr_info("... generic registers:      %d\n",     x86_pmu.num_counters);
@@ -1643,6 +1771,7 @@ static struct attribute_group x86_pmu_attr_group = {
 static const struct attribute_group *x86_pmu_attr_groups[] = {
        &x86_pmu_attr_group,
        &x86_pmu_format_group,
+       &x86_pmu_events_group,
        NULL,
 };
 
index 271d25700297402c2d47403ecc9f350d00dab8ad..115c1ea977469b0fda5b43f76e8595575effb24b 100644 (file)
@@ -354,6 +354,8 @@ struct x86_pmu {
        int             attr_rdpmc;
        struct attribute **format_attrs;
 
+       ssize_t         (*events_sysfs_show)(char *page, u64 config);
+
        /*
         * CPU Hotplug hooks
         */
@@ -536,6 +538,9 @@ static inline void set_linear_ip(struct pt_regs *regs, unsigned long ip)
        regs->ip = ip;
 }
 
+ssize_t x86_event_sysfs_show(char *page, u64 config, u64 event);
+ssize_t intel_event_sysfs_show(char *page, u64 config);
+
 #ifdef CONFIG_CPU_SUP_AMD
 
 int amd_pmu_init(void);
index 4528ae7b6ec4c96aaeb9822b3ea82bad59c4fc7a..c93bc4e813a0c10303984db79cafc1d6ee5a6caf 100644 (file)
@@ -568,6 +568,14 @@ amd_get_event_constraints_f15h(struct cpu_hw_events *cpuc, struct perf_event *ev
        }
 }
 
+static ssize_t amd_event_sysfs_show(char *page, u64 config)
+{
+       u64 event = (config & ARCH_PERFMON_EVENTSEL_EVENT) |
+                   (config & AMD64_EVENTSEL_EVENT) >> 24;
+
+       return x86_event_sysfs_show(page, config, event);
+}
+
 static __initconst const struct x86_pmu amd_pmu = {
        .name                   = "AMD",
        .handle_irq             = x86_pmu_handle_irq,
@@ -591,6 +599,7 @@ static __initconst const struct x86_pmu amd_pmu = {
        .put_event_constraints  = amd_put_event_constraints,
 
        .format_attrs           = amd_format_attr,
+       .events_sysfs_show      = amd_event_sysfs_show,
 
        .cpu_prepare            = amd_pmu_cpu_prepare,
        .cpu_starting           = amd_pmu_cpu_starting,
index 324bb523d9d9b402dbc6ac36706b6a8b90d577e7..93b9e1181f830ff91b9ad432e0d148a38b0e93c3 100644 (file)
@@ -1603,6 +1603,13 @@ static struct attribute *intel_arch_formats_attr[] = {
        NULL,
 };
 
+ssize_t intel_event_sysfs_show(char *page, u64 config)
+{
+       u64 event = (config & ARCH_PERFMON_EVENTSEL_EVENT);
+
+       return x86_event_sysfs_show(page, config, event);
+}
+
 static __initconst const struct x86_pmu core_pmu = {
        .name                   = "core",
        .handle_irq             = x86_pmu_handle_irq,
@@ -1628,6 +1635,7 @@ static __initconst const struct x86_pmu core_pmu = {
        .event_constraints      = intel_core_event_constraints,
        .guest_get_msrs         = core_guest_get_msrs,
        .format_attrs           = intel_arch_formats_attr,
+       .events_sysfs_show      = intel_event_sysfs_show,
 };
 
 struct intel_shared_regs *allocate_shared_regs(int cpu)
@@ -1766,6 +1774,7 @@ static __initconst const struct x86_pmu intel_pmu = {
        .pebs_aliases           = intel_pebs_aliases_core2,
 
        .format_attrs           = intel_arch3_formats_attr,
+       .events_sysfs_show      = intel_event_sysfs_show,
 
        .cpu_prepare            = intel_pmu_cpu_prepare,
        .cpu_starting           = intel_pmu_cpu_starting,
index 99d96a4978b56630115c2de5b465ca5eca0ffee0..3cf3d97cce3a7ab0b02c678f2535dc5ec03d09bb 100644 (file)
@@ -118,22 +118,24 @@ static void snbep_uncore_pci_disable_box(struct intel_uncore_box *box)
 {
        struct pci_dev *pdev = box->pci_dev;
        int box_ctl = uncore_pci_box_ctl(box);
-       u32 config;
+       u32 config = 0;
 
-       pci_read_config_dword(pdev, box_ctl, &config);
-       config |= SNBEP_PMON_BOX_CTL_FRZ;
-       pci_write_config_dword(pdev, box_ctl, config);
+       if (!pci_read_config_dword(pdev, box_ctl, &config)) {
+               config |= SNBEP_PMON_BOX_CTL_FRZ;
+               pci_write_config_dword(pdev, box_ctl, config);
+       }
 }
 
 static void snbep_uncore_pci_enable_box(struct intel_uncore_box *box)
 {
        struct pci_dev *pdev = box->pci_dev;
        int box_ctl = uncore_pci_box_ctl(box);
-       u32 config;
+       u32 config = 0;
 
-       pci_read_config_dword(pdev, box_ctl, &config);
-       config &= ~SNBEP_PMON_BOX_CTL_FRZ;
-       pci_write_config_dword(pdev, box_ctl, config);
+       if (!pci_read_config_dword(pdev, box_ctl, &config)) {
+               config &= ~SNBEP_PMON_BOX_CTL_FRZ;
+               pci_write_config_dword(pdev, box_ctl, config);
+       }
 }
 
 static void snbep_uncore_pci_enable_event(struct intel_uncore_box *box, struct perf_event *event)
@@ -156,7 +158,7 @@ static u64 snbep_uncore_pci_read_counter(struct intel_uncore_box *box, struct pe
 {
        struct pci_dev *pdev = box->pci_dev;
        struct hw_perf_event *hwc = &event->hw;
-       u64 count;
+       u64 count = 0;
 
        pci_read_config_dword(pdev, hwc->event_base, (u32 *)&count);
        pci_read_config_dword(pdev, hwc->event_base + 4, (u32 *)&count + 1);
@@ -603,11 +605,12 @@ static struct pci_driver snbep_uncore_pci_driver = {
 /*
  * build pci bus to socket mapping
  */
-static void snbep_pci2phy_map_init(void)
+static int snbep_pci2phy_map_init(void)
 {
        struct pci_dev *ubox_dev = NULL;
        int i, bus, nodeid;
-       u32 config;
+       int err = 0;
+       u32 config = 0;
 
        while (1) {
                /* find the UBOX device */
@@ -618,10 +621,14 @@ static void snbep_pci2phy_map_init(void)
                        break;
                bus = ubox_dev->bus->number;
                /* get the Node ID of the local register */
-               pci_read_config_dword(ubox_dev, 0x40, &config);
+               err = pci_read_config_dword(ubox_dev, 0x40, &config);
+               if (err)
+                       break;
                nodeid = config;
                /* get the Node ID mapping */
-               pci_read_config_dword(ubox_dev, 0x54, &config);
+               err = pci_read_config_dword(ubox_dev, 0x54, &config);
+               if (err)
+                       break;
                /*
                 * every three bits in the Node ID mapping register maps
                 * to a particular node.
@@ -633,7 +640,11 @@ static void snbep_pci2phy_map_init(void)
                        }
                }
        };
-       return;
+
+       if (ubox_dev)
+               pci_dev_put(ubox_dev);
+
+       return err ? pcibios_err_to_errno(err) : 0;
 }
 /* end of Sandy Bridge-EP uncore support */
 
@@ -1547,7 +1558,6 @@ void nhmex_rbox_alter_er(struct intel_uncore_box *box, struct perf_event *event)
 {
        struct hw_perf_event *hwc = &event->hw;
        struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
-       int port;
 
        /* adjust the main event selector and extra register index */
        if (reg1->idx % 2) {
@@ -1559,7 +1569,6 @@ void nhmex_rbox_alter_er(struct intel_uncore_box *box, struct perf_event *event)
        }
 
        /* adjust extra register config */
-       port = reg1->idx / 6 + box->pmu->pmu_idx * 4;
        switch (reg1->idx % 6) {
        case 2:
                /* shift the 8~15 bits to the 0~7 bits */
@@ -2578,9 +2587,11 @@ static int __init uncore_pci_init(void)
 
        switch (boot_cpu_data.x86_model) {
        case 45: /* Sandy Bridge-EP */
+               ret = snbep_pci2phy_map_init();
+               if (ret)
+                       return ret;
                pci_uncores = snbep_pci_uncores;
                uncore_pci_driver = &snbep_uncore_pci_driver;
-               snbep_pci2phy_map_init();
                break;
        default:
                return 0;
@@ -2926,6 +2937,9 @@ static int __init intel_uncore_init(void)
        if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
                return -ENODEV;
 
+       if (cpu_has_hypervisor)
+               return -ENODEV;
+
        ret = uncore_pci_init();
        if (ret)
                goto fail;
index 7c46bfdbc3732f87b005ecb7196a635eba5db546..4b7731bf23a812a4631aa7c53196068924b52ee7 100644 (file)
@@ -3,6 +3,8 @@
 #include <linux/perf_event.h>
 #include <linux/types.h>
 
+#include <asm/hardirq.h>
+
 #include "perf_event.h"
 
 static const u64 knc_perfmon_event_map[] =
@@ -173,30 +175,100 @@ static void knc_pmu_enable_all(int added)
 static inline void
 knc_pmu_disable_event(struct perf_event *event)
 {
-       struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
        struct hw_perf_event *hwc = &event->hw;
        u64 val;
 
        val = hwc->config;
-       if (cpuc->enabled)
-               val &= ~ARCH_PERFMON_EVENTSEL_ENABLE;
+       val &= ~ARCH_PERFMON_EVENTSEL_ENABLE;
 
        (void)wrmsrl_safe(hwc->config_base + hwc->idx, val);
 }
 
 static void knc_pmu_enable_event(struct perf_event *event)
 {
-       struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
        struct hw_perf_event *hwc = &event->hw;
        u64 val;
 
        val = hwc->config;
-       if (cpuc->enabled)
-               val |= ARCH_PERFMON_EVENTSEL_ENABLE;
+       val |= ARCH_PERFMON_EVENTSEL_ENABLE;
 
        (void)wrmsrl_safe(hwc->config_base + hwc->idx, val);
 }
 
+static inline u64 knc_pmu_get_status(void)
+{
+       u64 status;
+
+       rdmsrl(MSR_KNC_IA32_PERF_GLOBAL_STATUS, status);
+
+       return status;
+}
+
+static inline void knc_pmu_ack_status(u64 ack)
+{
+       wrmsrl(MSR_KNC_IA32_PERF_GLOBAL_OVF_CONTROL, ack);
+}
+
+static int knc_pmu_handle_irq(struct pt_regs *regs)
+{
+       struct perf_sample_data data;
+       struct cpu_hw_events *cpuc;
+       int handled = 0;
+       int bit, loops;
+       u64 status;
+
+       cpuc = &__get_cpu_var(cpu_hw_events);
+
+       knc_pmu_disable_all();
+
+       status = knc_pmu_get_status();
+       if (!status) {
+               knc_pmu_enable_all(0);
+               return handled;
+       }
+
+       loops = 0;
+again:
+       knc_pmu_ack_status(status);
+       if (++loops > 100) {
+               WARN_ONCE(1, "perf: irq loop stuck!\n");
+               perf_event_print_debug();
+               goto done;
+       }
+
+       inc_irq_stat(apic_perf_irqs);
+
+       for_each_set_bit(bit, (unsigned long *)&status, X86_PMC_IDX_MAX) {
+               struct perf_event *event = cpuc->events[bit];
+
+               handled++;
+
+               if (!test_bit(bit, cpuc->active_mask))
+                       continue;
+
+               if (!intel_pmu_save_and_restart(event))
+                       continue;
+
+               perf_sample_data_init(&data, 0, event->hw.last_period);
+
+               if (perf_event_overflow(event, &data, regs))
+                       x86_pmu_stop(event, 0);
+       }
+
+       /*
+        * Repeat if there is more work to be done:
+        */
+       status = knc_pmu_get_status();
+       if (status)
+               goto again;
+
+done:
+       knc_pmu_enable_all(0);
+
+       return handled;
+}
+
+
 PMU_FORMAT_ATTR(event, "config:0-7"    );
 PMU_FORMAT_ATTR(umask, "config:8-15"   );
 PMU_FORMAT_ATTR(edge,  "config:18"     );
@@ -214,7 +286,7 @@ static struct attribute *intel_knc_formats_attr[] = {
 
 static __initconst struct x86_pmu knc_pmu = {
        .name                   = "knc",
-       .handle_irq             = x86_pmu_handle_irq,
+       .handle_irq             = knc_pmu_handle_irq,
        .disable_all            = knc_pmu_disable_all,
        .enable_all             = knc_pmu_enable_all,
        .enable                 = knc_pmu_enable_event,
@@ -226,12 +298,11 @@ static __initconst struct x86_pmu knc_pmu = {
        .event_map              = knc_pmu_event_map,
        .max_events             = ARRAY_SIZE(knc_perfmon_event_map),
        .apic                   = 1,
-       .max_period             = (1ULL << 31) - 1,
+       .max_period             = (1ULL << 39) - 1,
        .version                = 0,
        .num_counters           = 2,
-       /* in theory 40 bits, early silicon is buggy though */
-       .cntval_bits            = 32,
-       .cntval_mask            = (1ULL << 32) - 1,
+       .cntval_bits            = 40,
+       .cntval_mask            = (1ULL << 40) - 1,
        .get_event_constraints  = x86_get_event_constraints,
        .event_constraints      = knc_event_constraints,
        .format_attrs           = intel_knc_formats_attr,
index e4dd0f7a04535f09b83d47d95868bcc1c152dff3..f2af39f5dc3d96916f8665350445a3e8155f290b 100644 (file)
  */
 static const u64 p6_perfmon_event_map[] =
 {
-  [PERF_COUNT_HW_CPU_CYCLES]           = 0x0079,
-  [PERF_COUNT_HW_INSTRUCTIONS]         = 0x00c0,
-  [PERF_COUNT_HW_CACHE_REFERENCES]     = 0x0f2e,
-  [PERF_COUNT_HW_CACHE_MISSES]         = 0x012e,
-  [PERF_COUNT_HW_BRANCH_INSTRUCTIONS]  = 0x00c4,
-  [PERF_COUNT_HW_BRANCH_MISSES]                = 0x00c5,
-  [PERF_COUNT_HW_BUS_CYCLES]           = 0x0062,
+  [PERF_COUNT_HW_CPU_CYCLES]           = 0x0079,       /* CPU_CLK_UNHALTED */
+  [PERF_COUNT_HW_INSTRUCTIONS]         = 0x00c0,       /* INST_RETIRED     */
+  [PERF_COUNT_HW_CACHE_REFERENCES]     = 0x0f2e,       /* L2_RQSTS:M:E:S:I */
+  [PERF_COUNT_HW_CACHE_MISSES]         = 0x012e,       /* L2_RQSTS:I       */
+  [PERF_COUNT_HW_BRANCH_INSTRUCTIONS]  = 0x00c4,       /* BR_INST_RETIRED  */
+  [PERF_COUNT_HW_BRANCH_MISSES]                = 0x00c5,       /* BR_MISS_PRED_RETIRED */
+  [PERF_COUNT_HW_BUS_CYCLES]           = 0x0062,       /* BUS_DRDY_CLOCKS  */
+  [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = 0x00a2,    /* RESOURCE_STALLS  */
+
+};
+
+static __initconst u64 p6_hw_cache_event_ids
+                               [PERF_COUNT_HW_CACHE_MAX]
+                               [PERF_COUNT_HW_CACHE_OP_MAX]
+                               [PERF_COUNT_HW_CACHE_RESULT_MAX] =
+{
+ [ C(L1D) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0043,  /* DATA_MEM_REFS       */
+                [ C(RESULT_MISS)   ] = 0x0045, /* DCU_LINES_IN        */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = 0,
+               [ C(RESULT_MISS)   ] = 0x0f29,  /* L2_LD:M:E:S:I       */
+       },
+        [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0,
+               [ C(RESULT_MISS)   ] = 0,
+        },
+ },
+ [ C(L1I ) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0080,  /* IFU_IFETCH         */
+               [ C(RESULT_MISS)   ] = 0x0f28,  /* L2_IFETCH:M:E:S:I  */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0,
+               [ C(RESULT_MISS)   ] = 0,
+       },
+ },
+ [ C(LL  ) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0,
+               [ C(RESULT_MISS)   ] = 0,
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = 0,
+               [ C(RESULT_MISS)   ] = 0x0025,  /* L2_M_LINES_INM     */
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0,
+               [ C(RESULT_MISS)   ] = 0,
+       },
+ },
+ [ C(DTLB) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0043,  /* DATA_MEM_REFS      */
+               [ C(RESULT_MISS)   ] = 0,
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = 0,
+               [ C(RESULT_MISS)   ] = 0,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0,
+               [ C(RESULT_MISS)   ] = 0,
+       },
+ },
+ [ C(ITLB) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0080,  /* IFU_IFETCH         */
+               [ C(RESULT_MISS)   ] = 0x0085,  /* ITLB_MISS          */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+ },
+ [ C(BPU ) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x00c4,  /* BR_INST_RETIRED      */
+               [ C(RESULT_MISS)   ] = 0x00c5,  /* BR_MISS_PRED_RETIRED */
+        },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+ },
 };
 
 static u64 p6_pmu_event_map(int hw_event)
@@ -34,7 +127,7 @@ static struct event_constraint p6_event_constraints[] =
 {
        INTEL_EVENT_CONSTRAINT(0xc1, 0x1),      /* FLOPS */
        INTEL_EVENT_CONSTRAINT(0x10, 0x1),      /* FP_COMP_OPS_EXE */
-       INTEL_EVENT_CONSTRAINT(0x11, 0x1),      /* FP_ASSIST */
+       INTEL_EVENT_CONSTRAINT(0x11, 0x2),      /* FP_ASSIST */
        INTEL_EVENT_CONSTRAINT(0x12, 0x2),      /* MUL */
        INTEL_EVENT_CONSTRAINT(0x13, 0x2),      /* DIV */
        INTEL_EVENT_CONSTRAINT(0x14, 0x1),      /* CYCLES_DIV_BUSY */
@@ -64,25 +157,25 @@ static void p6_pmu_enable_all(int added)
 static inline void
 p6_pmu_disable_event(struct perf_event *event)
 {
-       struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
        struct hw_perf_event *hwc = &event->hw;
        u64 val = P6_NOP_EVENT;
 
-       if (cpuc->enabled)
-               val |= ARCH_PERFMON_EVENTSEL_ENABLE;
-
        (void)wrmsrl_safe(hwc->config_base, val);
 }
 
 static void p6_pmu_enable_event(struct perf_event *event)
 {
-       struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
        struct hw_perf_event *hwc = &event->hw;
        u64 val;
 
        val = hwc->config;
-       if (cpuc->enabled)
-               val |= ARCH_PERFMON_EVENTSEL_ENABLE;
+
+       /*
+        * p6 only has a global event enable, set on PerfEvtSel0
+        * We "disable" events by programming P6_NOP_EVENT
+        * and we rely on p6_pmu_enable_all() being called
+        * to actually enable the events.
+        */
 
        (void)wrmsrl_safe(hwc->config_base, val);
 }
@@ -134,6 +227,8 @@ static __initconst const struct x86_pmu p6_pmu = {
        .event_constraints      = p6_event_constraints,
 
        .format_attrs           = intel_p6_formats_attr,
+       .events_sysfs_show      = intel_event_sysfs_show,
+
 };
 
 __init int p6_pmu_init(void)
@@ -158,5 +253,9 @@ __init int p6_pmu_init(void)
 
        x86_pmu = p6_pmu;
 
+       memcpy(hw_cache_event_ids, p6_hw_cache_event_ids,
+               sizeof(hw_cache_event_ids));
+
+
        return 0;
 }
index a1193aef6d7d2ef1af31a4b257ed0e161876ad19..88b725aa1d52463d7534882a187da4c392bf3947 100644 (file)
@@ -1035,7 +1035,7 @@ ENTRY(xen_sysenter_target)
 
 ENTRY(xen_hypervisor_callback)
        CFI_STARTPROC
-       pushl_cfi $0
+       pushl_cfi $-1 /* orig_ax = -1 => not a system call */
        SAVE_ALL
        TRACE_IRQS_OFF
 
@@ -1077,14 +1077,16 @@ ENTRY(xen_failsafe_callback)
 2:     mov 8(%esp),%es
 3:     mov 12(%esp),%fs
 4:     mov 16(%esp),%gs
+       /* EAX == 0 => Category 1 (Bad segment)
+          EAX != 0 => Category 2 (Bad IRET) */
        testl %eax,%eax
        popl_cfi %eax
        lea 16(%esp),%esp
        CFI_ADJUST_CFA_OFFSET -16
        jz 5f
        addl $16,%esp
-       jmp iret_exc            # EAX != 0 => Category 2 (Bad IRET)
-5:     pushl_cfi $0            # EAX == 0 => Category 1 (Bad segment)
+       jmp iret_exc
+5:     pushl_cfi $-1 /* orig_ax = -1 => not a system call */
        SAVE_ALL
        jmp ret_from_exception
        CFI_ENDPROC
index 0c58952d64e8723b4486ce620c8b11bcfe8d01f5..b51b2c7ee51fcbc3738ed8bd05fb4fd67d9fe1ab 100644 (file)
@@ -1435,7 +1435,7 @@ ENTRY(xen_failsafe_callback)
        CFI_RESTORE r11
        addq $0x30,%rsp
        CFI_ADJUST_CFA_OFFSET -0x30
-       pushq_cfi $0
+       pushq_cfi $-1 /* orig_ax = -1 => not a system call */
        SAVE_ALL
        jmp error_exit
        CFI_ENDPROC
index b3e5e51bc907ef4da71549ff7e2214467721af0a..4180a874c764d4df9d514648082eee5ac6907930 100644 (file)
@@ -247,7 +247,10 @@ do_async_page_fault(struct pt_regs *regs, unsigned long error_code)
                break;
        case KVM_PV_REASON_PAGE_NOT_PRESENT:
                /* page is swapped out by the host. */
+               rcu_irq_enter();
+               exit_idle();
                kvm_async_pf_task_wait((u32)read_cr2());
+               rcu_irq_exit();
                break;
        case KVM_PV_REASON_PAGE_READY:
                rcu_irq_enter();
index 52190a938b4ac0d26a85704e6db4c131dd938aca..4e8ba39eaf0fd93cbca557eaecf3efcd954ee05b 100644 (file)
@@ -358,14 +358,6 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "VGN-Z540N"),
                },
        },
-       {       /* Handle problems with rebooting on CompuLab SBC-FITPC2 */
-               .callback = set_bios_reboot,
-               .ident = "CompuLab SBC-FITPC2",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "CompuLab"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "SBC-FITPC2"),
-               },
-       },
        {       /* Handle problems with rebooting on ASUS P4S800 */
                .callback = set_bios_reboot,
                .ident = "ASUS P4S800",
index 4929c1be0ac0077f7c279fe296ece8e425684c9a..801602b5d745adeb1eb892294588bbcb8de1a88d 100644 (file)
@@ -195,12 +195,6 @@ void read_persistent_clock(struct timespec *ts)
        ts->tv_nsec = 0;
 }
 
-unsigned long long native_read_tsc(void)
-{
-       return __native_read_tsc();
-}
-EXPORT_SYMBOL(native_read_tsc);
-
 
 static struct resource rtc_resources[] = {
        [0] = {
index a2bb18e02839489dcbf9dbc1e3d348f5fb176c34..128d1256d29c2533527d1f6740ab9e5d0e0d5936 100644 (file)
@@ -920,8 +920,21 @@ void __init setup_arch(char **cmdline_p)
 
 #ifdef CONFIG_X86_64
        if (max_pfn > max_low_pfn) {
-               max_pfn_mapped = init_memory_mapping(1UL<<32,
-                                                    max_pfn<<PAGE_SHIFT);
+               int i;
+               for (i = 0; i < e820.nr_map; i++) {
+                       struct e820entry *ei = &e820.map[i];
+
+                       if (ei->addr + ei->size <= 1UL << 32)
+                               continue;
+
+                       if (ei->type == E820_RESERVED)
+                               continue;
+
+                       max_pfn_mapped = init_memory_mapping(
+                               ei->addr < 1UL << 32 ? 1UL << 32 : ei->addr,
+                               ei->addr + ei->size);
+               }
+
                /* can we preseve max_low_pfn ?*/
                max_low_pfn = max_pfn;
        }
@@ -942,6 +955,10 @@ void __init setup_arch(char **cmdline_p)
 
        reserve_initrd();
 
+#if defined(CONFIG_ACPI) && defined(CONFIG_BLK_DEV_INITRD)
+       acpi_initrd_override((void *)initrd_start, initrd_end - initrd_start);
+#endif
+
        reserve_crashkernel();
 
        vsmp_init();
index 29ad351804e9324d3aaf59c07c86d274958516b3..70b27ee6118e12c8411c7903e2254aeff44cd90e 100644 (file)
@@ -824,10 +824,8 @@ do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags)
                mce_notify_process();
 #endif /* CONFIG_X86_64 && CONFIG_X86_MCE */
 
-       if (thread_info_flags & _TIF_UPROBE) {
-               clear_thread_flag(TIF_UPROBE);
+       if (thread_info_flags & _TIF_UPROBE)
                uprobe_notify_resume(regs);
-       }
 
        /* deal with pending signal delivery */
        if (thread_info_flags & _TIF_SIGPENDING)
index cfa5d4f7ca56c06934c8b8bfa6e9815fe8e606b4..06ccb5073a3f7280f1f71b20cbf7edc68d7d278c 100644 (file)
@@ -77,6 +77,12 @@ unsigned long long
 sched_clock(void) __attribute__((alias("native_sched_clock")));
 #endif
 
+unsigned long long native_read_tsc(void)
+{
+       return __native_read_tsc();
+}
+EXPORT_SYMBOL(native_read_tsc);
+
 int check_tsc_unstable(void)
 {
        return tsc_unstable;
index 9538f00827a9b25257debf63aaa438ef6e40d68b..aafa5557b3964a57bf0abbdd9c849786688f1ce9 100644 (file)
@@ -651,31 +651,19 @@ void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
 
 /*
  * Skip these instructions as per the currently known x86 ISA.
- * 0x66* { 0x90 | 0x0f 0x1f | 0x0f 0x19 | 0x87 0xc0 }
+ * rep=0x66*; nop=0x90
  */
 static bool __skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
 {
        int i;
 
        for (i = 0; i < MAX_UINSN_BYTES; i++) {
-               if ((auprobe->insn[i] == 0x66))
+               if (auprobe->insn[i] == 0x66)
                        continue;
 
                if (auprobe->insn[i] == 0x90)
                        return true;
 
-               if (i == (MAX_UINSN_BYTES - 1))
-                       break;
-
-               if ((auprobe->insn[i] == 0x0f) && (auprobe->insn[i+1] == 0x1f))
-                       return true;
-
-               if ((auprobe->insn[i] == 0x0f) && (auprobe->insn[i+1] == 0x19))
-                       return true;
-
-               if ((auprobe->insn[i] == 0x87) && (auprobe->insn[i+1] == 0xc0))
-                       return true;
-
                break;
        }
        return false;
index 3a3e8c9e280dcac9ba655491b4300c1d698bfb5a..9a907a67be8f48abc0399017865a4697968ae2c3 100644 (file)
@@ -145,19 +145,6 @@ static int addr_to_vsyscall_nr(unsigned long addr)
        return nr;
 }
 
-#ifdef CONFIG_SECCOMP
-static int vsyscall_seccomp(struct task_struct *tsk, int syscall_nr)
-{
-       if (!seccomp_mode(&tsk->seccomp))
-               return 0;
-       task_pt_regs(tsk)->orig_ax = syscall_nr;
-       task_pt_regs(tsk)->ax = syscall_nr;
-       return __secure_computing(syscall_nr);
-}
-#else
-#define vsyscall_seccomp(_tsk, _nr) 0
-#endif
-
 static bool write_ok_or_segv(unsigned long ptr, size_t size)
 {
        /*
@@ -190,10 +177,9 @@ bool emulate_vsyscall(struct pt_regs *regs, unsigned long address)
 {
        struct task_struct *tsk;
        unsigned long caller;
-       int vsyscall_nr;
+       int vsyscall_nr, syscall_nr, tmp;
        int prev_sig_on_uaccess_error;
        long ret;
-       int skip;
 
        /*
         * No point in checking CS -- the only way to get here is a user mode
@@ -225,56 +211,84 @@ bool emulate_vsyscall(struct pt_regs *regs, unsigned long address)
        }
 
        tsk = current;
-       /*
-        * With a real vsyscall, page faults cause SIGSEGV.  We want to
-        * preserve that behavior to make writing exploits harder.
-        */
-       prev_sig_on_uaccess_error = current_thread_info()->sig_on_uaccess_error;
-       current_thread_info()->sig_on_uaccess_error = 1;
 
        /*
+        * Check for access_ok violations and find the syscall nr.
+        *
         * NULL is a valid user pointer (in the access_ok sense) on 32-bit and
         * 64-bit, so we don't need to special-case it here.  For all the
         * vsyscalls, NULL means "don't write anything" not "write it at
         * address 0".
         */
-       ret = -EFAULT;
-       skip = 0;
        switch (vsyscall_nr) {
        case 0:
-               skip = vsyscall_seccomp(tsk, __NR_gettimeofday);
-               if (skip)
-                       break;
-
                if (!write_ok_or_segv(regs->di, sizeof(struct timeval)) ||
-                   !write_ok_or_segv(regs->si, sizeof(struct timezone)))
-                       break;
+                   !write_ok_or_segv(regs->si, sizeof(struct timezone))) {
+                       ret = -EFAULT;
+                       goto check_fault;
+               }
+
+               syscall_nr = __NR_gettimeofday;
+               break;
+
+       case 1:
+               if (!write_ok_or_segv(regs->di, sizeof(time_t))) {
+                       ret = -EFAULT;
+                       goto check_fault;
+               }
+
+               syscall_nr = __NR_time;
+               break;
+
+       case 2:
+               if (!write_ok_or_segv(regs->di, sizeof(unsigned)) ||
+                   !write_ok_or_segv(regs->si, sizeof(unsigned))) {
+                       ret = -EFAULT;
+                       goto check_fault;
+               }
+
+               syscall_nr = __NR_getcpu;
+               break;
+       }
+
+       /*
+        * Handle seccomp.  regs->ip must be the original value.
+        * See seccomp_send_sigsys and Documentation/prctl/seccomp_filter.txt.
+        *
+        * We could optimize the seccomp disabled case, but performance
+        * here doesn't matter.
+        */
+       regs->orig_ax = syscall_nr;
+       regs->ax = -ENOSYS;
+       tmp = secure_computing(syscall_nr);
+       if ((!tmp && regs->orig_ax != syscall_nr) || regs->ip != address) {
+               warn_bad_vsyscall(KERN_DEBUG, regs,
+                                 "seccomp tried to change syscall nr or ip");
+               do_exit(SIGSYS);
+       }
+       if (tmp)
+               goto do_ret;  /* skip requested */
 
+       /*
+        * With a real vsyscall, page faults cause SIGSEGV.  We want to
+        * preserve that behavior to make writing exploits harder.
+        */
+       prev_sig_on_uaccess_error = current_thread_info()->sig_on_uaccess_error;
+       current_thread_info()->sig_on_uaccess_error = 1;
+
+       ret = -EFAULT;
+       switch (vsyscall_nr) {
+       case 0:
                ret = sys_gettimeofday(
                        (struct timeval __user *)regs->di,
                        (struct timezone __user *)regs->si);
                break;
 
        case 1:
-               skip = vsyscall_seccomp(tsk, __NR_time);
-               if (skip)
-                       break;
-
-               if (!write_ok_or_segv(regs->di, sizeof(time_t)))
-                       break;
-
                ret = sys_time((time_t __user *)regs->di);
                break;
 
        case 2:
-               skip = vsyscall_seccomp(tsk, __NR_getcpu);
-               if (skip)
-                       break;
-
-               if (!write_ok_or_segv(regs->di, sizeof(unsigned)) ||
-                   !write_ok_or_segv(regs->si, sizeof(unsigned)))
-                       break;
-
                ret = sys_getcpu((unsigned __user *)regs->di,
                                 (unsigned __user *)regs->si,
                                 NULL);
@@ -283,12 +297,7 @@ bool emulate_vsyscall(struct pt_regs *regs, unsigned long address)
 
        current_thread_info()->sig_on_uaccess_error = prev_sig_on_uaccess_error;
 
-       if (skip) {
-               if ((long)regs->ax <= 0L) /* seccomp errno emulation */
-                       goto do_ret;
-               goto done; /* seccomp trace/trap */
-       }
-
+check_fault:
        if (ret == -EFAULT) {
                /* Bad news -- userspace fed a bad pointer to a vsyscall. */
                warn_bad_vsyscall(KERN_INFO, regs,
@@ -311,7 +320,6 @@ do_ret:
        /* Emulate a ret instruction. */
        regs->ip = caller;
        regs->sp += 8;
-done:
        return true;
 
 sigsegv:
index c6e6b721b6ee3a38d6267ee8867bd029fbdc6d6a..43e9fadca5d080a4e98a65735cbe071102742911 100644 (file)
@@ -1311,7 +1311,7 @@ void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value)
        vcpu->arch.apic_base = value;
        if (apic_x2apic_mode(apic)) {
                u32 id = kvm_apic_id(apic);
-               u32 ldr = ((id & ~0xf) << 16) | (1 << (id & 0xf));
+               u32 ldr = ((id >> 4) << 16) | (1 << (id & 0xf));
                kvm_apic_set_ldr(apic, ldr);
        }
        apic->base_address = apic->vcpu->arch.apic_base &
index d289fee1ffb8631c0b93f663104965fe7def7b11..6f85fe0bf958987f0275f1fa25e2b9e5240aad02 100644 (file)
@@ -2497,8 +2497,7 @@ static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *sptep,
                }
        }
 
-       if (!is_error_pfn(pfn))
-               kvm_release_pfn_clean(pfn);
+       kvm_release_pfn_clean(pfn);
 }
 
 static void nonpaging_new_cr3(struct kvm_vcpu *vcpu)
index 1eefebe5d72758873df0d13e4ae8c686a7d016ee..841d09b123dbca1b6e2fe0efcfdd1ea805636fd1 100644 (file)
@@ -158,7 +158,9 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
 
 u64 __read_mostly host_xcr0;
 
-int emulator_fix_hypercall(struct x86_emulate_ctxt *ctxt);
+static int emulator_fix_hypercall(struct x86_emulate_ctxt *ctxt);
+
+static int kvm_vcpu_reset(struct kvm_vcpu *vcpu);
 
 static inline void kvm_async_pf_hash_reset(struct kvm_vcpu *vcpu)
 {
@@ -5066,7 +5068,7 @@ out:
 }
 EXPORT_SYMBOL_GPL(kvm_emulate_hypercall);
 
-int emulator_fix_hypercall(struct x86_emulate_ctxt *ctxt)
+static int emulator_fix_hypercall(struct x86_emulate_ctxt *ctxt)
 {
        struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt);
        char instruction[3];
@@ -5426,7 +5428,7 @@ static int __vcpu_run(struct kvm_vcpu *vcpu)
                pr_debug("vcpu %d received sipi with vector # %x\n",
                         vcpu->vcpu_id, vcpu->arch.sipi_vector);
                kvm_lapic_reset(vcpu);
-               r = kvm_arch_vcpu_reset(vcpu);
+               r = kvm_vcpu_reset(vcpu);
                if (r)
                        return r;
                vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
@@ -6036,7 +6038,7 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
        r = vcpu_load(vcpu);
        if (r)
                return r;
-       r = kvm_arch_vcpu_reset(vcpu);
+       r = kvm_vcpu_reset(vcpu);
        if (r == 0)
                r = kvm_mmu_setup(vcpu);
        vcpu_put(vcpu);
@@ -6058,7 +6060,7 @@ void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
        kvm_x86_ops->vcpu_free(vcpu);
 }
 
-int kvm_arch_vcpu_reset(struct kvm_vcpu *vcpu)
+static int kvm_vcpu_reset(struct kvm_vcpu *vcpu)
 {
        atomic_set(&vcpu->arch.nmi_queued, 0);
        vcpu->arch.nmi_pending = 0;
index 6b34d04d096aaa40f4b1c1e3fea61ceaa9911075..176cca67212b7072687f42450ef56018c03ebaaa 100644 (file)
@@ -5,91 +5,89 @@
 #include <asm/alternative-asm.h>
 
        ALIGN
-copy_page_c:
+copy_page_rep:
        CFI_STARTPROC
-       movl $4096/8,%ecx
-       rep movsq
+       movl    $4096/8, %ecx
+       rep     movsq
        ret
        CFI_ENDPROC
-ENDPROC(copy_page_c)
+ENDPROC(copy_page_rep)
 
-/* Don't use streaming store because it's better when the target
-   ends up in cache. */
-           
-/* Could vary the prefetch distance based on SMP/UP */
+/*
+ *  Don't use streaming copy unless the CPU indicates X86_FEATURE_REP_GOOD.
+ *  Could vary the prefetch distance based on SMP/UP.
+*/
 
 ENTRY(copy_page)
        CFI_STARTPROC
-       subq    $2*8,%rsp
+       subq    $2*8,   %rsp
        CFI_ADJUST_CFA_OFFSET 2*8
-       movq    %rbx,(%rsp)
+       movq    %rbx,   (%rsp)
        CFI_REL_OFFSET rbx, 0
-       movq    %r12,1*8(%rsp)
+       movq    %r12,   1*8(%rsp)
        CFI_REL_OFFSET r12, 1*8
 
-       movl    $(4096/64)-5,%ecx
+       movl    $(4096/64)-5,   %ecx
        .p2align 4
 .Loop64:
-       dec     %rcx
-
-       movq        (%rsi), %rax
-       movq      8 (%rsi), %rbx
-       movq     16 (%rsi), %rdx
-       movq     24 (%rsi), %r8
-       movq     32 (%rsi), %r9
-       movq     40 (%rsi), %r10
-       movq     48 (%rsi), %r11
-       movq     56 (%rsi), %r12
+       dec     %rcx
+       movq    0x8*0(%rsi), %rax
+       movq    0x8*1(%rsi), %rbx
+       movq    0x8*2(%rsi), %rdx
+       movq    0x8*3(%rsi), %r8
+       movq    0x8*4(%rsi), %r9
+       movq    0x8*5(%rsi), %r10
+       movq    0x8*6(%rsi), %r11
+       movq    0x8*7(%rsi), %r12
 
        prefetcht0 5*64(%rsi)
 
-       movq     %rax,    (%rdi)
-       movq     %rbx,  8 (%rdi)
-       movq     %rdx, 16 (%rdi)
-       movq     %r8,  24 (%rdi)
-       movq     %r9,  32 (%rdi)
-       movq     %r10, 40 (%rdi)
-       movq     %r11, 48 (%rdi)
-       movq     %r12, 56 (%rdi)
+       movq    %rax, 0x8*0(%rdi)
+       movq    %rbx, 0x8*1(%rdi)
+       movq    %rdx, 0x8*2(%rdi)
+       movq    %r8,  0x8*3(%rdi)
+       movq    %r9,  0x8*4(%rdi)
+       movq    %r10, 0x8*5(%rdi)
+       movq    %r11, 0x8*6(%rdi)
+       movq    %r12, 0x8*7(%rdi)
 
-       leaq    64 (%rsi), %rsi
-       leaq    64 (%rdi), %rdi
+       leaq    64 (%rsi), %rsi
+       leaq    64 (%rdi), %rdi
 
-       jnz     .Loop64
+       jnz     .Loop64
 
-       movl    $5,%ecx
+       movl    $5, %ecx
        .p2align 4
 .Loop2:
-       decl   %ecx
-
-       movq        (%rsi), %rax
-       movq      8 (%rsi), %rbx
-       movq     16 (%rsi), %rdx
-       movq     24 (%rsi), %r8
-       movq     32 (%rsi), %r9
-       movq     40 (%rsi), %r10
-       movq     48 (%rsi), %r11
-       movq     56 (%rsi), %r12
-
-       movq     %rax,    (%rdi)
-       movq     %rbx,  8 (%rdi)
-       movq     %rdx, 16 (%rdi)
-       movq     %r8,  24 (%rdi)
-       movq     %r9,  32 (%rdi)
-       movq     %r10, 40 (%rdi)
-       movq     %r11, 48 (%rdi)
-       movq     %r12, 56 (%rdi)
-
-       leaq    64(%rdi),%rdi
-       leaq    64(%rsi),%rsi
-
+       decl    %ecx
+
+       movq    0x8*0(%rsi), %rax
+       movq    0x8*1(%rsi), %rbx
+       movq    0x8*2(%rsi), %rdx
+       movq    0x8*3(%rsi), %r8
+       movq    0x8*4(%rsi), %r9
+       movq    0x8*5(%rsi), %r10
+       movq    0x8*6(%rsi), %r11
+       movq    0x8*7(%rsi), %r12
+
+       movq    %rax, 0x8*0(%rdi)
+       movq    %rbx, 0x8*1(%rdi)
+       movq    %rdx, 0x8*2(%rdi)
+       movq    %r8,  0x8*3(%rdi)
+       movq    %r9,  0x8*4(%rdi)
+       movq    %r10, 0x8*5(%rdi)
+       movq    %r11, 0x8*6(%rdi)
+       movq    %r12, 0x8*7(%rdi)
+
+       leaq    64(%rdi), %rdi
+       leaq    64(%rsi), %rsi
        jnz     .Loop2
 
-       movq    (%rsp),%rbx
+       movq    (%rsp), %rbx
        CFI_RESTORE rbx
-       movq    1*8(%rsp),%r12
+       movq    1*8(%rsp), %r12
        CFI_RESTORE r12
-       addq    $2*8,%rsp
+       addq    $2*8, %rsp
        CFI_ADJUST_CFA_OFFSET -2*8
        ret
 .Lcopy_page_end:
@@ -103,7 +101,7 @@ ENDPROC(copy_page)
 
        .section .altinstr_replacement,"ax"
 1:     .byte 0xeb                                      /* jmp <disp8> */
-       .byte (copy_page_c - copy_page) - (2f - 1b)     /* offset */
+       .byte (copy_page_rep - copy_page) - (2f - 1b)   /* offset */
 2:
        .previous
        .section .altinstructions,"a"
index dd74e46828c0fc243740b61a18c2dea654fafb5e..6dc992125a8414ebc9b0fe0dbd54a0432c8eaf98 100644 (file)
@@ -150,7 +150,13 @@ static int gup_pmd_range(pud_t pud, unsigned long addr, unsigned long end,
 
        pmdp = pmd_offset(&pud, addr);
        do {
-               pmd_t pmd = *pmdp;
+               /*
+                * With THP and hugetlbfs the pmd can change from
+                * under us and it can be cleared as well by the TLB
+                * shootdown, so read it with ACCESS_ONCE to do all
+                * computations on the same sampling.
+                */
+               pmd_t pmd = ACCESS_ONCE(*pmdp);
 
                next = pmd_addr_end(addr, end);
                /*
@@ -220,7 +226,13 @@ static int gup_pud_range(pgd_t pgd, unsigned long addr, unsigned long end,
 
        pudp = pud_offset(&pgd, addr);
        do {
-               pud_t pud = *pudp;
+               /*
+                * With hugetlbfs giga pages the pud can change from
+                * under us and it can be cleared as well by the TLB
+                * shootdown, so read it with ACCESS_ONCE to do all
+                * computations on the same sampling.
+                */
+               pud_t pud = ACCESS_ONCE(*pudp);
 
                next = pud_addr_end(addr, end);
                if (pud_none(pud))
@@ -280,7 +292,12 @@ int __get_user_pages_fast(unsigned long start, int nr_pages, int write,
        local_irq_save(flags);
        pgdp = pgd_offset(mm, addr);
        do {
-               pgd_t pgd = *pgdp;
+               /*
+                * The pgd could be cleared by the TLB shootdown from
+                * under us so read it with ACCESS_ONCE to do all
+                * computations on the same sampling.
+                */
+               pgd_t pgd = ACCESS_ONCE(*pgdp);
 
                next = pgd_addr_end(addr, end);
                if (pgd_none(pgd))
index ab1f6a93b527c9bd50acc12a52e9ce157f2cc48b..8653b3a722be2d533074ca9c1ccca488f8e7e811 100644 (file)
@@ -29,14 +29,8 @@ int direct_gbpages
 #endif
 ;
 
-struct map_range {
-       unsigned long start;
-       unsigned long end;
-       unsigned page_size_mask;
-};
-
-static void __init find_early_table_space(struct map_range *mr, unsigned long end,
-                                         int use_pse, int use_gbpages)
+static void __init find_early_table_space(unsigned long end, int use_pse,
+                                         int use_gbpages)
 {
        unsigned long puds, pmds, ptes, tables, start = 0, good_end = end;
        phys_addr_t base;
@@ -61,10 +55,6 @@ static void __init find_early_table_space(struct map_range *mr, unsigned long en
 #ifdef CONFIG_X86_32
                extra += PMD_SIZE;
 #endif
-               /* The first 2/4M doesn't use large pages. */
-               if (mr->start < PMD_SIZE)
-                       extra += mr->end - mr->start;
-
                ptes = (extra + PAGE_SIZE - 1) >> PAGE_SHIFT;
        } else
                ptes = (end + PAGE_SIZE - 1) >> PAGE_SHIFT;
@@ -95,6 +85,12 @@ void __init native_pagetable_reserve(u64 start, u64 end)
        memblock_reserve(start, end - start);
 }
 
+struct map_range {
+       unsigned long start;
+       unsigned long end;
+       unsigned page_size_mask;
+};
+
 #ifdef CONFIG_X86_32
 #define NR_RANGE_MR 3
 #else /* CONFIG_X86_64 */
@@ -267,7 +263,7 @@ unsigned long __init_refok init_memory_mapping(unsigned long start,
         * nodes are discovered.
         */
        if (!after_bootmem)
-               find_early_table_space(&mr[0], end, use_pse, use_gbpages);
+               find_early_table_space(end, use_pse, use_gbpages);
 
        for (i = 0; i < nr_range; i++)
                ret = kernel_physical_mapping_init(mr[i].start, mr[i].end,
index 2b6b4a3c8beb8727d27b1cdba22411fe0d271efb..3baff255adac6472570298d7e9ee60df75e93dfc 100644 (file)
@@ -386,7 +386,8 @@ phys_pte_init(pte_t *pte_page, unsigned long addr, unsigned long end,
                 * these mappings are more intelligent.
                 */
                if (pte_val(*pte)) {
-                       pages++;
+                       if (!after_bootmem)
+                               pages++;
                        continue;
                }
 
@@ -451,6 +452,8 @@ phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end,
                         * attributes.
                         */
                        if (page_size_mask & (1 << PG_LEVEL_2M)) {
+                               if (!after_bootmem)
+                                       pages++;
                                last_map_addr = next;
                                continue;
                        }
@@ -526,6 +529,8 @@ phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end,
                         * attributes.
                         */
                        if (page_size_mask & (1 << PG_LEVEL_1G)) {
+                               if (!after_bootmem)
+                                       pages++;
                                last_map_addr = next;
                                continue;
                        }
index 8573b83a63d037bf2f7eb09c8922b94c2b535c45..fc82cf1fd03d89f3ff7a34367711dd9581ce3065 100644 (file)
@@ -306,11 +306,26 @@ int ptep_set_access_flags(struct vm_area_struct *vma,
                          pte_t entry, int dirty)
 {
        int changed = !pte_same(*ptep, entry);
+       /*
+        * If the page used to be inaccessible (_PAGE_PROTNONE), or
+        * this call upgrades the access permissions on the same page,
+        * it is safe to skip the remote TLB flush.
+        */
+       bool flush_remote = false;
+       if (!pte_accessible(*ptep))
+               flush_remote = false;
+       else if (pte_pfn(*ptep) != pte_pfn(entry) ||
+                       (pte_write(*ptep) && !pte_write(entry)) ||
+                       (pte_exec(*ptep) && !pte_exec(entry)))
+               flush_remote = true;
 
        if (changed && dirty) {
                *ptep = entry;
                pte_update_defer(vma->vm_mm, address, ptep);
-               flush_tlb_page(vma, address);
+               if (flush_remote)
+                       flush_tlb_page(vma, address);
+               else
+                       __flush_tlb_one(address);
        }
 
        return changed;
index 26b8a8514ee566e8a7d235a06de1037c2641adec..48768df2471af2bc9e4059fad6eb8c583f93f4d0 100644 (file)
@@ -55,7 +55,7 @@ u64 op_x86_get_ctrl(struct op_x86_model_spec const *model,
        val |= counter_config->extra;
        event &= model->event_mask ? model->event_mask : 0xFF;
        val |= event & 0xFF;
-       val |= (event & 0x0F00) << 24;
+       val |= (u64)(event & 0x0F00) << 24;
 
        return val;
 }
index 192397c98606690f34d1d510052738f04bbdd931..7010c199b4f0ee68db45a54e85bd0cd08bac6229 100644 (file)
@@ -98,6 +98,16 @@ static const struct dmi_system_id pci_use_crs_table[] __initconst = {
                        DMI_MATCH(DMI_BIOS_VERSION, "6JET85WW (1.43 )"),
                },
        },
+       /* https://bugzilla.kernel.org/show_bug.cgi?id=47981 */
+       {
+               .callback = set_nouse_crs,
+               .ident = "CheckPoint P-20-00",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "CheckPoint"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "P-20-00"),
+                       DMI_MATCH(DMI_BOARD_NAME, "Bridgeport"),
+               },
+       },
        {}
 };
 
index 4c61b52191eb293bcaef2cac2380c6114cdaefcf..0dcc30e9df8cde01308f81e3bf343871a47e16ff 100644 (file)
@@ -92,8 +92,11 @@ static void ce4100_serial_fixup(int port, struct uart_port *up,
                up->membase =
                        (void __iomem *)__fix_to_virt(FIX_EARLYCON_MEM_BASE);
                up->membase += up->mapbase & ~PAGE_MASK;
+               up->mapbase += port * 0x100;
+               up->membase += port * 0x100;
                up->iotype   = UPIO_MEM32;
                up->regshift = 2;
+               up->irq = 4;
        }
 #endif
        up->iobase = 0;
index aded2a91162a8af12ad104d047544afce91ff4c4..cb34839c97c5ba350840ae61690e468713d43a0a 100644 (file)
@@ -810,6 +810,16 @@ void __iomem *efi_lookup_mapped_addr(u64 phys_addr)
        return NULL;
 }
 
+void efi_memory_uc(u64 addr, unsigned long size)
+{
+       unsigned long page_shift = 1UL << EFI_PAGE_SHIFT;
+       u64 npages;
+
+       npages = round_up(size, page_shift) / page_shift;
+       memrange_efi_to_native(&addr, &npages);
+       set_memory_uc(addr, npages);
+}
+
 /*
  * This function will switch the EFI runtime services to virtual mode.
  * Essentially, look through the EFI memmap and map every region that
@@ -823,7 +833,7 @@ void __init efi_enter_virtual_mode(void)
        efi_memory_desc_t *md, *prev_md = NULL;
        efi_status_t status;
        unsigned long size;
-       u64 end, systab, addr, npages, end_pfn;
+       u64 end, systab, end_pfn;
        void *p, *va, *new_memmap = NULL;
        int count = 0;
 
@@ -879,10 +889,14 @@ void __init efi_enter_virtual_mode(void)
                end_pfn = PFN_UP(end);
                if (end_pfn <= max_low_pfn_mapped
                    || (end_pfn > (1UL << (32 - PAGE_SHIFT))
-                       && end_pfn <= max_pfn_mapped))
+                       && end_pfn <= max_pfn_mapped)) {
                        va = __va(md->phys_addr);
-               else
-                       va = efi_ioremap(md->phys_addr, size, md->type);
+
+                       if (!(md->attribute & EFI_MEMORY_WB))
+                               efi_memory_uc((u64)(unsigned long)va, size);
+               } else
+                       va = efi_ioremap(md->phys_addr, size,
+                                        md->type, md->attribute);
 
                md->virt_addr = (u64) (unsigned long) va;
 
@@ -892,13 +906,6 @@ void __init efi_enter_virtual_mode(void)
                        continue;
                }
 
-               if (!(md->attribute & EFI_MEMORY_WB)) {
-                       addr = md->virt_addr;
-                       npages = md->num_pages;
-                       memrange_efi_to_native(&addr, &npages);
-                       set_memory_uc(addr, npages);
-               }
-
                systab = (u64) (unsigned long) efi_phys.systab;
                if (md->phys_addr <= systab && systab < end) {
                        systab += md->virt_addr - md->phys_addr;
index ac3aa54e26546ba5cb4121eba0c58ca00f06ea82..95fd505dfeb6e43dd37b0c41954f0b0db6535d1c 100644 (file)
@@ -82,7 +82,7 @@ void __init efi_call_phys_epilog(void)
 }
 
 void __iomem *__init efi_ioremap(unsigned long phys_addr, unsigned long size,
-                                u32 type)
+                                u32 type, u64 attribute)
 {
        unsigned long last_map_pfn;
 
@@ -92,8 +92,11 @@ void __iomem *__init efi_ioremap(unsigned long phys_addr, unsigned long size,
        last_map_pfn = init_memory_mapping(phys_addr, phys_addr + size);
        if ((last_map_pfn << PAGE_SHIFT) < phys_addr + size) {
                unsigned long top = last_map_pfn << PAGE_SHIFT;
-               efi_ioremap(top, size - (top - phys_addr), type);
+               efi_ioremap(top, size - (top - phys_addr), type, attribute);
        }
 
+       if (!(attribute & EFI_MEMORY_WB))
+               efi_memory_uc((u64)(unsigned long)__va(phys_addr), size);
+
        return (void __iomem *)__va(phys_addr);
 }
index e56479e580534ffd0cd5b3eb70531d4dd716869f..9e7e14797a72dda0b85d4c70afca61fdb2fdf92e 100644 (file)
@@ -74,18 +74,9 @@ ENTRY(wakeup_start)
 
        lidtl   wakeup_idt
 
-       /* Clear the EFLAGS but remember if we have EFLAGS.ID */
-       movl $X86_EFLAGS_ID, %ecx
-       pushl %ecx
-       popfl
-       pushfl
-       popl %edi
+       /* Clear the EFLAGS */
        pushl $0
        popfl
-       pushfl
-       popl %edx
-       xorl %edx, %edi
-       andl %ecx, %edi         /* %edi is zero iff CPUID & %cr4 are missing */
 
        /* Check header signature... */
        movl    signature, %eax
@@ -120,12 +111,12 @@ ENTRY(wakeup_start)
        movl    %eax, %cr3
 
        btl     $WAKEUP_BEHAVIOR_RESTORE_CR4, %edi
-       j     1f
+       jnc     1f
        movl    pmode_cr4, %eax
        movl    %eax, %cr4
 1:
        btl     $WAKEUP_BEHAVIOR_RESTORE_EFER, %edi
-       j     1f
+       jnc     1f
        movl    pmode_efer, %eax
        movl    pmode_efer + 4, %edx
        movl    $MSR_EFER, %ecx
index a47103fbc6925ac7c717ef1ed2d1f9eccaa35fa4..83b3838417edc09532110e83b43aaa48ae659974 100644 (file)
 347    i386    process_vm_readv        sys_process_vm_readv            compat_sys_process_vm_readv
 348    i386    process_vm_writev       sys_process_vm_writev           compat_sys_process_vm_writev
 349    i386    kcmp                    sys_kcmp
+350    i386    finit_module            sys_finit_module
index a582bfed95bb05fd1ae4f62060f719856d49a405..7c58c84b7bc8dae578f7cee7dc2433ad46e69f03 100644 (file)
 310    64      process_vm_readv        sys_process_vm_readv
 311    64      process_vm_writev       sys_process_vm_writev
 312    common  kcmp                    sys_kcmp
+313    common  finit_module            sys_finit_module
 
 #
 # x32-specific system call numbers start at 512 to avoid cache impact
index e3497f240eabb869e6cda863036689e6b093899d..586d83812b67b64f96594f1eebdc859bdcb12adc 100644 (file)
@@ -81,8 +81,6 @@
 #include "smp.h"
 #include "multicalls.h"
 
-#include <xen/events.h>
-
 EXPORT_SYMBOL_GPL(hypercall_page);
 
 DEFINE_PER_CPU(struct vcpu_info *, xen_vcpu);
index 8971a26d21abb943d5c9e23b5c6630a207f43536..d12f7d30babd8dd7658122f6282cab61f2dbba70 100644 (file)
@@ -526,10 +526,9 @@ void __cpuinit xen_enable_syscall(void)
 #endif /* CONFIG_X86_64 */
 }
 
-void __init xen_arch_setup(void)
+/* Normal PV domain not running in HVM container */
+static __init void inline xen_non_pvh_arch_setup(void)
 {
-       xen_panic_handler_init();
-
        HYPERVISOR_vm_assist(VMASST_CMD_enable, VMASST_TYPE_4gb_segments);
        HYPERVISOR_vm_assist(VMASST_CMD_enable, VMASST_TYPE_writable_pagetables);
 
@@ -543,6 +542,14 @@ void __init xen_arch_setup(void)
 
        xen_enable_sysenter();
        xen_enable_syscall();
+}
+
+void __init xen_arch_setup(void)
+{
+       xen_panic_handler_init();
+
+       if (!xen_pvh_domain())
+               xen_non_pvh_arch_setup();
 
 #ifdef CONFIG_ACPI
        if (!(xen_start_info->flags & SIF_INITDOMAIN)) {
index 353c50f18702cfc2ff93118ce3a18b50c6dfdd5c..620e5a2f3e2d4f51897cc4951da7101f172d8350 100644 (file)
@@ -300,8 +300,6 @@ cpu_initialize_context(unsigned int cpu, struct task_struct *idle)
        gdt = get_cpu_gdt_table(cpu);
 
        ctxt->flags = VGCF_IN_KERNEL;
-       ctxt->user_regs.ds = __USER_DS;
-       ctxt->user_regs.es = __USER_DS;
        ctxt->user_regs.ss = __KERNEL_DS;
 #ifdef CONFIG_X86_32
        ctxt->user_regs.fs = __KERNEL_PERCPU;
@@ -314,31 +312,36 @@ cpu_initialize_context(unsigned int cpu, struct task_struct *idle)
 
        memset(&ctxt->fpu_ctxt, 0, sizeof(ctxt->fpu_ctxt));
 
-       xen_copy_trap_info(ctxt->trap_ctxt);
+               ctxt->user_regs.ds = __USER_DS;
+               ctxt->user_regs.es = __USER_DS;
 
-       ctxt->ldt_ents = 0;
+               xen_copy_trap_info(ctxt->trap_ctxt);
 
-       BUG_ON((unsigned long)gdt & ~PAGE_MASK);
+               ctxt->ldt_ents = 0;
 
-       gdt_mfn = arbitrary_virt_to_mfn(gdt);
-       make_lowmem_page_readonly(gdt);
-       make_lowmem_page_readonly(mfn_to_virt(gdt_mfn));
+               BUG_ON((unsigned long)gdt & ~PAGE_MASK);
 
-       ctxt->gdt_frames[0] = gdt_mfn;
-       ctxt->gdt_ents      = GDT_ENTRIES;
+               gdt_mfn = arbitrary_virt_to_mfn(gdt);
+               make_lowmem_page_readonly(gdt);
+               make_lowmem_page_readonly(mfn_to_virt(gdt_mfn));
 
-       ctxt->user_regs.cs = __KERNEL_CS;
-       ctxt->user_regs.esp = idle->thread.sp0 - sizeof(struct pt_regs);
+               ctxt->gdt_frames[0] = gdt_mfn;
+               ctxt->gdt_ents      = GDT_ENTRIES;
 
-       ctxt->kernel_ss = __KERNEL_DS;
-       ctxt->kernel_sp = idle->thread.sp0;
+               ctxt->kernel_ss = __KERNEL_DS;
+               ctxt->kernel_sp = idle->thread.sp0;
 
 #ifdef CONFIG_X86_32
-       ctxt->event_callback_cs     = __KERNEL_CS;
-       ctxt->failsafe_callback_cs  = __KERNEL_CS;
+               ctxt->event_callback_cs     = __KERNEL_CS;
+               ctxt->failsafe_callback_cs  = __KERNEL_CS;
 #endif
-       ctxt->event_callback_eip    = (unsigned long)xen_hypervisor_callback;
-       ctxt->failsafe_callback_eip = (unsigned long)xen_failsafe_callback;
+               ctxt->event_callback_eip    =
+                                       (unsigned long)xen_hypervisor_callback;
+               ctxt->failsafe_callback_eip =
+                                       (unsigned long)xen_failsafe_callback;
+
+       ctxt->user_regs.cs = __KERNEL_CS;
+       ctxt->user_regs.esp = idle->thread.sp0 - sizeof(struct pt_regs);
 
        per_cpu(xen_cr3, cpu) = __pa(swapper_pg_dir);
        ctxt->ctrlreg[3] = xen_pfn_to_cr3(virt_to_mfn(swapper_pg_dir));
index 4c316cd28a542b2f06685179eb0e37b7819b539a..86c34dbc9cd0abdf1b5b055f6d9a7b46e082aae2 100644 (file)
@@ -51,17 +51,17 @@ _start:
        /* 'reset' window registers */
 
        movi    a4, 1
-       wsr     a4, PS
+       wsr     a4, ps
        rsync
 
-       rsr     a5, WINDOWBASE
+       rsr     a5, windowbase
        ssl     a5
        sll     a4, a4
-       wsr     a4, WINDOWSTART
+       wsr     a4, windowstart
        rsync
 
        movi    a4, 0x00040000
-       wsr     a4, PS
+       wsr     a4, ps
        rsync
 
        /* copy the loader to its address
index fccd81eddff1f6de89b07cc13c362809364c9507..6d13027899957d528a142964db0b299d36b74a13 100644 (file)
@@ -1,4 +1,28 @@
-include include/asm-generic/Kbuild.asm
-
+generic-y += bitsperlong.h
+generic-y += bug.h
 generic-y += clkdev.h
+generic-y += cputime.h
+generic-y += device.h
+generic-y += div64.h
+generic-y += emergency-restart.h
+generic-y += errno.h
 generic-y += exec.h
+generic-y += fcntl.h
+generic-y += futex.h
+generic-y += hardirq.h
+generic-y += ioctl.h
+generic-y += irq_regs.h
+generic-y += kdebug.h
+generic-y += kmap_types.h
+generic-y += kvm_para.h
+generic-y += local.h
+generic-y += local64.h
+generic-y += percpu.h
+generic-y += resource.h
+generic-y += scatterlist.h
+generic-y += sections.h
+generic-y += siginfo.h
+generic-y += statfs.h
+generic-y += termios.h
+generic-y += topology.h
+generic-y += xor.h
index b4098930877587d7dec309bbc702a5ed674c94f6..24f50cada70c27ae041356f960b728dc285e4e5b 100644 (file)
@@ -73,7 +73,7 @@ static inline void atomic_add(int i, atomic_t * v)
        "l32i    %0, %2, 0              \n\t"
        "add     %0, %0, %1             \n\t"
        "s32i    %0, %2, 0              \n\t"
-       "wsr     a15, "__stringify(PS)"       \n\t"
+       "wsr     a15, ps                \n\t"
        "rsync                          \n"
        : "=&a" (vval)
        : "a" (i), "a" (v)
@@ -97,7 +97,7 @@ static inline void atomic_sub(int i, atomic_t *v)
        "l32i    %0, %2, 0              \n\t"
        "sub     %0, %0, %1             \n\t"
        "s32i    %0, %2, 0              \n\t"
-       "wsr     a15, "__stringify(PS)"       \n\t"
+       "wsr     a15, ps                \n\t"
        "rsync                          \n"
        : "=&a" (vval)
        : "a" (i), "a" (v)
@@ -118,7 +118,7 @@ static inline int atomic_add_return(int i, atomic_t * v)
        "l32i    %0, %2, 0             \n\t"
        "add     %0, %0, %1            \n\t"
        "s32i    %0, %2, 0             \n\t"
-       "wsr     a15, "__stringify(PS)"      \n\t"
+       "wsr     a15, ps               \n\t"
        "rsync                         \n"
        : "=&a" (vval)
        : "a" (i), "a" (v)
@@ -137,7 +137,7 @@ static inline int atomic_sub_return(int i, atomic_t * v)
        "l32i    %0, %2, 0             \n\t"
        "sub     %0, %0, %1            \n\t"
        "s32i    %0, %2, 0             \n\t"
-       "wsr     a15, "__stringify(PS)"       \n\t"
+       "wsr     a15, ps               \n\t"
        "rsync                         \n"
        : "=&a" (vval)
        : "a" (i), "a" (v)
@@ -260,7 +260,7 @@ static inline void atomic_clear_mask(unsigned int mask, atomic_t *v)
        "xor     %1, %4, %3            \n\t"
        "and     %0, %0, %4            \n\t"
        "s32i    %0, %2, 0             \n\t"
-       "wsr     a15, "__stringify(PS)"      \n\t"
+       "wsr     a15, ps               \n\t"
        "rsync                         \n"
        : "=&a" (vval), "=a" (mask)
        : "a" (v), "a" (all_f), "1" (mask)
@@ -277,7 +277,7 @@ static inline void atomic_set_mask(unsigned int mask, atomic_t *v)
        "l32i    %0, %2, 0             \n\t"
        "or      %0, %0, %1            \n\t"
        "s32i    %0, %2, 0             \n\t"
-       "wsr     a15, "__stringify(PS)"       \n\t"
+       "wsr     a15, ps               \n\t"
        "rsync                         \n"
        : "=&a" (vval)
        : "a" (mask), "a" (v)
diff --git a/arch/xtensa/include/asm/bitsperlong.h b/arch/xtensa/include/asm/bitsperlong.h
deleted file mode 100644 (file)
index 6dc0bb0..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/bitsperlong.h>
diff --git a/arch/xtensa/include/asm/bug.h b/arch/xtensa/include/asm/bug.h
deleted file mode 100644 (file)
index 3e52d72..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * include/asm-xtensa/bug.h
- *
- * Macros to cause a 'bug' message.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2001 - 2005 Tensilica Inc.
- */
-
-#ifndef _XTENSA_BUG_H
-#define _XTENSA_BUG_H
-
-#include <asm-generic/bug.h>
-
-#endif /* _XTENSA_BUG_H */
index 376cd9d5f45529c48078b7a84e9c7618ad865060..569fec4f9a20db0899e8ee92085ba4faea2fa4d2 100644 (file)
@@ -165,7 +165,7 @@ extern void copy_from_user_page(struct vm_area_struct*, struct page*,
 static inline u32 xtensa_get_cacheattr(void)
 {
        u32 r;
-       asm volatile("  rsr %0, CACHEATTR" : "=a"(r));
+       asm volatile("  rsr %0, cacheattr" : "=a"(r));
        return r;
 }
 
index e32149063d83163cdb3ac68132f5c10e981f0ce4..64dad04a9d276453cfca46df63eabcad816a07e2 100644 (file)
@@ -27,7 +27,7 @@ __cmpxchg_u32(volatile int *p, int old, int new)
                       "bne     %0, %2, 1f             \n\t"
                       "s32i    %3, %1, 0              \n\t"
                       "1:                             \n\t"
-                      "wsr     a15, "__stringify(PS)" \n\t"
+                      "wsr     a15, ps                \n\t"
                       "rsync                          \n\t"
                       : "=&a" (old)
                       : "a" (p), "a" (old), "r" (new)
@@ -97,7 +97,7 @@ static inline unsigned long xchg_u32(volatile int * m, unsigned long val)
   __asm__ __volatile__("rsil    a15, "__stringify(LOCKLEVEL)"\n\t"
                       "l32i    %0, %1, 0              \n\t"
                       "s32i    %2, %1, 0              \n\t"
-                      "wsr     a15, "__stringify(PS)" \n\t"
+                      "wsr     a15, ps                \n\t"
                       "rsync                          \n\t"
                       : "=&a" (tmp)
                       : "a" (m), "a" (val)
index 75c94a1658b02b81b14ec3759c5f29cb8db97a4d..677501b32dfcfa0b5a8471c73cc118b3d4415855 100644 (file)
 #if XCHAL_HAVE_CP
 
 #define RSR_CPENABLE(x)        do {                                              \
-       __asm__ __volatile__("rsr %0," __stringify(CPENABLE) : "=a" (x)); \
+       __asm__ __volatile__("rsr %0, cpenable" : "=a" (x));              \
        } while(0);
 #define WSR_CPENABLE(x)        do {                                              \
-       __asm__ __volatile__("wsr %0," __stringify(CPENABLE) "; rsync"    \
-                            :: "a" (x));                                 \
+       __asm__ __volatile__("wsr %0, cpenable; rsync" :: "a" (x));       \
        } while(0);
 
 #endif /* XCHAL_HAVE_CP */
diff --git a/arch/xtensa/include/asm/cputime.h b/arch/xtensa/include/asm/cputime.h
deleted file mode 100644 (file)
index a7fb864..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _XTENSA_CPUTIME_H
-#define _XTENSA_CPUTIME_H
-
-#include <asm-generic/cputime.h>
-
-#endif /* _XTENSA_CPUTIME_H */
index e1d8c9e010c1df976624ce71ea0449d6c8f47ae4..58c0a4fd4003891f18cd1c9a4f8babe4f1923be3 100644 (file)
@@ -27,7 +27,7 @@ static inline void __delay(unsigned long loops)
 static __inline__ u32 xtensa_get_ccount(void)
 {
        u32 ccount;
-       asm volatile ("rsr %0, 234; # CCOUNT\n" : "=r" (ccount));
+       asm volatile ("rsr %0, ccount\n" : "=r" (ccount));
        return ccount;
 }
 
diff --git a/arch/xtensa/include/asm/device.h b/arch/xtensa/include/asm/device.h
deleted file mode 100644 (file)
index d8f9872..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-/*
- * Arch specific extensions to struct device
- *
- * This file is released under the GPLv2
- */
-#include <asm-generic/device.h>
-
diff --git a/arch/xtensa/include/asm/div64.h b/arch/xtensa/include/asm/div64.h
deleted file mode 100644 (file)
index f35678c..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * include/asm-xtensa/div64.h
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2001 - 2007 Tensilica Inc.
- */
-
-#ifndef _XTENSA_DIV64_H
-#define _XTENSA_DIV64_H
-
-#include <asm-generic/div64.h>
-
-#endif /* _XTENSA_DIV64_H */
diff --git a/arch/xtensa/include/asm/emergency-restart.h b/arch/xtensa/include/asm/emergency-restart.h
deleted file mode 100644 (file)
index 108d8c4..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASM_EMERGENCY_RESTART_H
-#define _ASM_EMERGENCY_RESTART_H
-
-#include <asm-generic/emergency-restart.h>
-
-#endif /* _ASM_EMERGENCY_RESTART_H */
diff --git a/arch/xtensa/include/asm/errno.h b/arch/xtensa/include/asm/errno.h
deleted file mode 100644 (file)
index a0f3b96..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * include/asm-xtensa/errno.h
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file "COPYING" in the main directory of
- * this archive for more details.
- *
- * Copyright (C) 2002 - 2005 Tensilica Inc.
- */
-
-#ifndef _XTENSA_ERRNO_H
-#define _XTENSA_ERRNO_H
-
-#include <asm-generic/errno.h>
-
-#endif /* _XTENSA_ERRNO_H */
diff --git a/arch/xtensa/include/asm/fcntl.h b/arch/xtensa/include/asm/fcntl.h
deleted file mode 100644 (file)
index 46ab12d..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/fcntl.h>
diff --git a/arch/xtensa/include/asm/futex.h b/arch/xtensa/include/asm/futex.h
deleted file mode 100644 (file)
index 0b74582..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/futex.h>
diff --git a/arch/xtensa/include/asm/hardirq.h b/arch/xtensa/include/asm/hardirq.h
deleted file mode 100644 (file)
index 91695a1..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * include/asm-xtensa/hardirq.h
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file "COPYING" in the main directory of
- * this archive for more details.
- *
- * Copyright (C) 2002 - 2005 Tensilica Inc.
- */
-
-#ifndef _XTENSA_HARDIRQ_H
-#define _XTENSA_HARDIRQ_H
-
-#include <asm-generic/hardirq.h>
-
-#endif /* _XTENSA_HARDIRQ_H */
diff --git a/arch/xtensa/include/asm/ioctl.h b/arch/xtensa/include/asm/ioctl.h
deleted file mode 100644 (file)
index b279fe0..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/ioctl.h>
diff --git a/arch/xtensa/include/asm/irq_regs.h b/arch/xtensa/include/asm/irq_regs.h
deleted file mode 100644 (file)
index 3dd9c0b..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/irq_regs.h>
index dae9a8bdcb1725ce6a38db642fdc777403d354e1..f865b1c1eae497fefdba3cccf90ac07d218e9d06 100644 (file)
@@ -16,7 +16,7 @@
 static inline unsigned long arch_local_save_flags(void)
 {
        unsigned long flags;
-       asm volatile("rsr %0,"__stringify(PS) : "=a" (flags));
+       asm volatile("rsr %0, ps" : "=a" (flags));
        return flags;
 }
 
@@ -41,7 +41,7 @@ static inline void arch_local_irq_enable(void)
 
 static inline void arch_local_irq_restore(unsigned long flags)
 {
-       asm volatile("wsr %0, "__stringify(PS)" ; rsync"
+       asm volatile("wsr %0, ps; rsync"
                     :: "a" (flags) : "memory");
 }
 
diff --git a/arch/xtensa/include/asm/kdebug.h b/arch/xtensa/include/asm/kdebug.h
deleted file mode 100644 (file)
index 6ece1b0..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/kdebug.h>
diff --git a/arch/xtensa/include/asm/kmap_types.h b/arch/xtensa/include/asm/kmap_types.h
deleted file mode 100644 (file)
index 11c687e..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _XTENSA_KMAP_TYPES_H
-#define _XTENSA_KMAP_TYPES_H
-
-#include <asm-generic/kmap_types.h>
-
-#endif /* _XTENSA_KMAP_TYPES_H */
diff --git a/arch/xtensa/include/asm/kvm_para.h b/arch/xtensa/include/asm/kvm_para.h
deleted file mode 100644 (file)
index 14fab8f..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/kvm_para.h>
diff --git a/arch/xtensa/include/asm/local.h b/arch/xtensa/include/asm/local.h
deleted file mode 100644 (file)
index 48723e5..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * include/asm-xtensa/local.h
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2001 - 2005 Tensilica Inc.
- */
-
-#ifndef _XTENSA_LOCAL_H
-#define _XTENSA_LOCAL_H
-
-#include <asm-generic/local.h>
-
-#endif /* _XTENSA_LOCAL_H */
diff --git a/arch/xtensa/include/asm/local64.h b/arch/xtensa/include/asm/local64.h
deleted file mode 100644 (file)
index 36c93b5..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/local64.h>
index dbd8731a876aec90c2765df2dd1a1c6d5e2310d0..feb10af96519900e3cf64341b6c425b5e017e924 100644 (file)
@@ -51,14 +51,14 @@ extern unsigned long asid_cache;
 
 static inline void set_rasid_register (unsigned long val)
 {
-       __asm__ __volatile__ (" wsr %0, "__stringify(RASID)"\n\t"
+       __asm__ __volatile__ (" wsr %0, rasid\n\t"
                              " isync\n" : : "a" (val));
 }
 
 static inline unsigned long get_rasid_register (void)
 {
        unsigned long tmp;
-       __asm__ __volatile__ (" rsr %0,"__stringify(RASID)"\n\t" : "=a" (tmp));
+       __asm__ __volatile__ (" rsr %0, rasid\n\t" : "=a" (tmp));
        return tmp;
 }
 
index ba03d5aeab6b085d21bd0b14db47163552f04be7..0a70e780ef2a33f3466fe9201897578d2771ba70 100644 (file)
@@ -7,28 +7,12 @@
  *
  * Copyright (C) 2001 - 2005 Tensilica Inc.
  */
-
 #ifndef _XTENSA_PARAM_H
 #define _XTENSA_PARAM_H
 
-#ifdef __KERNEL__
+#include <uapi/asm/param.h>
+
 # define HZ            CONFIG_HZ       /* internal timer frequency */
 # define USER_HZ       100             /* for user interfaces in "ticks" */
 # define CLOCKS_PER_SEC (USER_HZ)      /* frequnzy at which times() counts */
-#else
-# define HZ            100
-#endif
-
-#define EXEC_PAGESIZE  4096
-
-#ifndef NGROUPS
-#define NGROUPS                32
-#endif
-
-#ifndef NOGROUP
-#define NOGROUP                (-1)
-#endif
-
-#define MAXHOSTNAMELEN 64      /* max length of hostname */
-
 #endif /* _XTENSA_PARAM_H */
diff --git a/arch/xtensa/include/asm/percpu.h b/arch/xtensa/include/asm/percpu.h
deleted file mode 100644 (file)
index 6d2bc2a..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * linux/include/asm-xtensa/percpu.h
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2001 - 2005 Tensilica Inc.
- */
-
-#ifndef _XTENSA_PERCPU__
-#define _XTENSA_PERCPU__
-
-#include <asm-generic/percpu.h>
-
-#endif /* _XTENSA_PERCPU__ */
index d85d38da8eecc28df1be5c318e08e550b4b7e4eb..da21c17f23aad235c313c02683e87ccbfb9e23bf 100644 (file)
@@ -7,73 +7,11 @@
  *
  * Copyright (C) 2001 - 2005 Tensilica Inc.
  */
-
 #ifndef _XTENSA_PTRACE_H
 #define _XTENSA_PTRACE_H
 
-/*
- * Kernel stack
- *
- *             +-----------------------+  -------- STACK_SIZE
- *             |     register file     |  |
- *             +-----------------------+  |
- *             |    struct pt_regs     |  |
- *             +-----------------------+  | ------ PT_REGS_OFFSET
- * double      :  16 bytes spill area  :  |  ^
- * excetion    :- - - - - - - - - - - -:  |  |
- * frame       :    struct pt_regs     :  |  |
- *             :- - - - - - - - - - - -:  |  |
- *             |                       |  |  |
- *             |     memory stack      |  |  |
- *             |                       |  |  |
- *             ~                       ~  ~  ~
- *             ~                       ~  ~  ~
- *             |                       |  |  |
- *             |                       |  |  |
- *             +-----------------------+  |  | --- STACK_BIAS
- *             |  struct task_struct   |  |  |  ^
- *  current --> +-----------------------+  |  |  |
- *             |  struct thread_info   |  |  |  |
- *             +-----------------------+ --------
- */
-
-#define KERNEL_STACK_SIZE (2 * PAGE_SIZE)
-
-/*  Offsets for exception_handlers[] (3 x 64-entries x 4-byte tables). */
-
-#define EXC_TABLE_KSTK         0x004   /* Kernel Stack */
-#define EXC_TABLE_DOUBLE_SAVE  0x008   /* Double exception save area for a0 */
-#define EXC_TABLE_FIXUP                0x00c   /* Fixup handler */
-#define EXC_TABLE_PARAM                0x010   /* For passing a parameter to fixup */
-#define EXC_TABLE_SYSCALL_SAVE 0x014   /* For fast syscall handler */
-#define EXC_TABLE_FAST_USER    0x100   /* Fast user exception handler */
-#define EXC_TABLE_FAST_KERNEL  0x200   /* Fast kernel exception handler */
-#define EXC_TABLE_DEFAULT      0x300   /* Default C-Handler */
-#define EXC_TABLE_SIZE         0x400
+#include <uapi/asm/ptrace.h>
 
-/* Registers used by strace */
-
-#define REG_A_BASE     0x0000
-#define REG_AR_BASE    0x0100
-#define REG_PC         0x0020
-#define REG_PS         0x02e6
-#define REG_WB         0x0248
-#define REG_WS         0x0249
-#define REG_LBEG       0x0200
-#define REG_LEND       0x0201
-#define REG_LCOUNT     0x0202
-#define REG_SAR                0x0203
-
-#define SYSCALL_NR     0x00ff
-
-/* Other PTRACE_ values defined in <linux/ptrace.h> using values 0-9,16,17,24 */
-
-#define PTRACE_GETREGS         12
-#define PTRACE_SETREGS         13
-#define PTRACE_GETXTREGS       18
-#define PTRACE_SETXTREGS       19
-
-#ifdef __KERNEL__
 
 #ifndef __ASSEMBLY__
 
@@ -132,6 +70,4 @@ struct pt_regs {
 
 #endif /* !__ASSEMBLY__ */
 
-#endif  /* __KERNEL__ */
-
 #endif /* _XTENSA_PTRACE_H */
index a3075b12aff112c4f3ed7176fccb8125b9336db8..8a8aa61ccc8df27075e4f2671715e9884571cc26 100644 (file)
 
 /*  Special registers.  */
 
-#define LBEG           0
-#define LEND           1
-#define LCOUNT         2
-#define SAR            3
-#define BR             4
-#define SCOMPARE1      12
-#define ACCHI          16
-#define ACCLO          17
-#define MR             32
-#define WINDOWBASE     72
-#define WINDOWSTART    73
-#define PTEVADDR       83
-#define RASID          90
-#define ITLBCFG                91
-#define DTLBCFG                92
-#define IBREAKENABLE   96
-#define DDR            104
-#define IBREAKA                128
-#define DBREAKA                144
-#define DBREAKC                160
-#define EPC            176
-#define EPC_1          177
-#define DEPC           192
-#define EPS            192
-#define EPS_1          193
-#define EXCSAVE                208
-#define EXCSAVE_1      209
-#define INTERRUPT      226
-#define INTENABLE      228
-#define PS             230
-#define THREADPTR      231
-#define EXCCAUSE       232
-#define DEBUGCAUSE     233
-#define CCOUNT         234
-#define PRID           235
-#define ICOUNT         236
-#define ICOUNTLEVEL    237
-#define EXCVADDR       238
-#define CCOMPARE       240
-#define MISC_SR                244
-
-/*  Special names for read-only and write-only interrupt registers.  */
-
-#define INTREAD                226
-#define INTSET         226
-#define INTCLEAR       227
+#define SREG_MR                        32
+#define SREG_IBREAKA           128
+#define SREG_DBREAKA           144
+#define SREG_DBREAKC           160
+#define SREG_EPC               176
+#define SREG_EPS               192
+#define SREG_EXCSAVE           208
+#define SREG_CCOMPARE          240
+#define SREG_MISC              244
 
 /*  EXCCAUSE register fields  */
 
diff --git a/arch/xtensa/include/asm/resource.h b/arch/xtensa/include/asm/resource.h
deleted file mode 100644 (file)
index 17b5ab3..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * include/asm-xtensa/resource.h
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2005 Tensilica Inc.
- */
-
-#ifndef _XTENSA_RESOURCE_H
-#define _XTENSA_RESOURCE_H
-
-#include <asm-generic/resource.h>
-
-#endif /* _XTENSA_RESOURCE_H */
diff --git a/arch/xtensa/include/asm/scatterlist.h b/arch/xtensa/include/asm/scatterlist.h
deleted file mode 100644 (file)
index a0421a6..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * include/asm-xtensa/scatterlist.h
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2001 - 2005 Tensilica Inc.
- */
-
-#ifndef _XTENSA_SCATTERLIST_H
-#define _XTENSA_SCATTERLIST_H
-
-#include <asm-generic/scatterlist.h>
-
-#endif /* _XTENSA_SCATTERLIST_H */
diff --git a/arch/xtensa/include/asm/sections.h b/arch/xtensa/include/asm/sections.h
deleted file mode 100644 (file)
index 40b5191..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * include/asm-xtensa/sections.h
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2001 - 2005 Tensilica Inc.
- */
-
-#ifndef _XTENSA_SECTIONS_H
-#define _XTENSA_SECTIONS_H
-
-#include <asm-generic/sections.h>
-
-#endif /* _XTENSA_SECTIONS_H */
diff --git a/arch/xtensa/include/asm/siginfo.h b/arch/xtensa/include/asm/siginfo.h
deleted file mode 100644 (file)
index 6916248..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * include/asm-xtensa/siginfo.h
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2001 - 2005 Tensilica Inc.
- */
-
-#ifndef _XTENSA_SIGINFO_H
-#define _XTENSA_SIGINFO_H
-
-#include <asm-generic/siginfo.h>
-
-#endif /* _XTENSA_SIGINFO_H */
index 7f201b9d4195747f153c13f4e2f495fd53343bf5..72fd44c85b702ad3c2c78da2e6cf64bc74545d46 100644 (file)
  *
  * Copyright (C) 2001 - 2005 Tensilica Inc.
  */
-
 #ifndef _XTENSA_SIGNAL_H
 #define _XTENSA_SIGNAL_H
 
-
-#define _NSIG          64
-#define _NSIG_BPW      32
-#define _NSIG_WORDS    (_NSIG / _NSIG_BPW)
-
-#ifndef __ASSEMBLY__
-
-#include <linux/types.h>
-
-/* Avoid too many header ordering problems.  */
-struct siginfo;
-typedef unsigned long old_sigset_t;            /* at least 32 bits */
-typedef struct {
-       unsigned long sig[_NSIG_WORDS];
-} sigset_t;
-
-#endif
-
-#define SIGHUP          1
-#define SIGINT          2
-#define SIGQUIT                 3
-#define SIGILL          4
-#define SIGTRAP                 5
-#define SIGABRT                 6
-#define SIGIOT          6
-#define SIGBUS          7
-#define SIGFPE          8
-#define SIGKILL                 9
-#define SIGUSR1                10
-#define SIGSEGV                11
-#define SIGUSR2                12
-#define SIGPIPE                13
-#define SIGALRM                14
-#define SIGTERM                15
-#define SIGSTKFLT      16
-#define SIGCHLD                17
-#define SIGCONT                18
-#define SIGSTOP                19
-#define SIGTSTP                20
-#define SIGTTIN                21
-#define SIGTTOU                22
-#define SIGURG         23
-#define SIGXCPU                24
-#define SIGXFSZ                25
-#define SIGVTALRM      26
-#define SIGPROF                27
-#define SIGWINCH       28
-#define SIGIO          29
-#define SIGPOLL                SIGIO
-/* #define SIGLOST             29 */
-#define SIGPWR         30
-#define SIGSYS         31
-#define        SIGUNUSED       31
-
-/* These should not be considered constants from userland.  */
-#define SIGRTMIN       32
-#define SIGRTMAX       (_NSIG-1)
-
-/*
- * SA_FLAGS values:
- *
- * SA_ONSTACK indicates that a registered stack_t will be used.
- * SA_RESTART flag to get restarting signals (which were the default long ago)
- * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
- * SA_RESETHAND clears the handler when the signal is delivered.
- * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
- * SA_NODEFER prevents the current signal from being masked in the handler.
- *
- * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
- * Unix names RESETHAND and NODEFER respectively.
- */
-#define SA_NOCLDSTOP   0x00000001
-#define SA_NOCLDWAIT   0x00000002 /* not supported yet */
-#define SA_SIGINFO     0x00000004
-#define SA_ONSTACK     0x08000000
-#define SA_RESTART     0x10000000
-#define SA_NODEFER     0x40000000
-#define SA_RESETHAND   0x80000000
-
-#define SA_NOMASK      SA_NODEFER
-#define SA_ONESHOT     SA_RESETHAND
-
-#define SA_RESTORER    0x04000000
-
-/*
- * sigaltstack controls
- */
-#define SS_ONSTACK     1
-#define SS_DISABLE     2
-
-#define MINSIGSTKSZ    2048
-#define SIGSTKSZ       8192
+#include <uapi/asm/signal.h>
 
 #ifndef __ASSEMBLY__
-
-#define SIG_BLOCK          0   /* for blocking signals */
-#define SIG_UNBLOCK        1   /* for unblocking signals */
-#define SIG_SETMASK        2   /* for setting the signal mask */
-
-/* Type of a signal handler.  */
-typedef void (*__sighandler_t)(int);
-
-#define SIG_DFL        ((__sighandler_t)0)     /* default signal handling */
-#define SIG_IGN        ((__sighandler_t)1)     /* ignore signal */
-#define SIG_ERR        ((__sighandler_t)-1)    /* error return from signal */
-
-#ifdef __KERNEL__
 struct sigaction {
        __sighandler_t sa_handler;
        unsigned long sa_flags;
@@ -131,35 +26,8 @@ struct k_sigaction {
        struct sigaction sa;
 };
 
-#else
-
-/* Here we must cater to libcs that poke about in kernel headers.  */
-
-struct sigaction {
-       union {
-         __sighandler_t _sa_handler;
-         void (*_sa_sigaction)(int, struct siginfo *, void *);
-       } _u;
-       sigset_t sa_mask;
-       unsigned long sa_flags;
-       void (*sa_restorer)(void);
-};
-
-#define sa_handler     _u._sa_handler
-#define sa_sigaction   _u._sa_sigaction
-
-#endif /* __KERNEL__ */
-
-typedef struct sigaltstack {
-       void *ss_sp;
-       int ss_flags;
-       size_t ss_size;
-} stack_t;
-
-#ifdef __KERNEL__
 #include <asm/sigcontext.h>
 #define ptrace_signal_deliver(regs, cookie) do { } while (0)
 
-#endif /* __KERNEL__ */
 #endif /* __ASSEMBLY__ */
 #endif /* _XTENSA_SIGNAL_H */
diff --git a/arch/xtensa/include/asm/statfs.h b/arch/xtensa/include/asm/statfs.h
deleted file mode 100644 (file)
index 9c3d1a2..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * include/asm-xtensa/statfs.h
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2005 Tensilica Inc.
- */
-
-#ifndef _XTENSA_STATFS_H
-#define _XTENSA_STATFS_H
-
-#include <asm-generic/statfs.h>
-
-#endif /* _XTENSA_STATFS_H */
-
diff --git a/arch/xtensa/include/asm/termios.h b/arch/xtensa/include/asm/termios.h
deleted file mode 100644 (file)
index 4673f42..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * include/asm-xtensa/termios.h
- *
- * Copied from SH.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2001 - 2005 Tensilica Inc.
- */
-
-#ifndef _XTENSA_TERMIOS_H
-#define _XTENSA_TERMIOS_H
-
-#include <asm/termbits.h>
-#include <asm/ioctls.h>
-
-struct winsize {
-       unsigned short ws_row;
-       unsigned short ws_col;
-       unsigned short ws_xpixel;
-       unsigned short ws_ypixel;
-};
-
-#define NCC 8
-struct termio {
-       unsigned short c_iflag;         /* input mode flags */
-       unsigned short c_oflag;         /* output mode flags */
-       unsigned short c_cflag;         /* control mode flags */
-       unsigned short c_lflag;         /* local mode flags */
-       unsigned char c_line;           /* line discipline */
-       unsigned char c_cc[NCC];        /* control characters */
-};
-
-/* Modem lines */
-
-#define TIOCM_LE       0x001
-#define TIOCM_DTR      0x002
-#define TIOCM_RTS      0x004
-#define TIOCM_ST       0x008
-#define TIOCM_SR       0x010
-#define TIOCM_CTS      0x020
-#define TIOCM_CAR      0x040
-#define TIOCM_RNG      0x080
-#define TIOCM_DSR      0x100
-#define TIOCM_CD       TIOCM_CAR
-#define TIOCM_RI       TIOCM_RNG
-#define TIOCM_OUT1     0x2000
-#define TIOCM_OUT2     0x4000
-#define TIOCM_LOOP     0x8000
-
-/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
-
-#ifdef __KERNEL__
-
-/*     intr=^C         quit=^\         erase=del       kill=^U
-       eof=^D          vtime=\0        vmin=\1         sxtc=\0
-       start=^Q        stop=^S         susp=^Z         eol=\0
-       reprint=^R      discard=^U      werase=^W       lnext=^V
-       eol2=\0
-*/
-#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0"
-
-/*
- * Translate a "termio" structure into a "termios". Ugh.
- */
-
-#define SET_LOW_TERMIOS_BITS(termios, termio, x) { \
-       unsigned short __tmp; \
-       get_user(__tmp,&(termio)->x); \
-       *(unsigned short *) &(termios)->x = __tmp; \
-}
-
-#define user_termio_to_kernel_termios(termios, termio) \
-({ \
-       SET_LOW_TERMIOS_BITS(termios, termio, c_iflag); \
-       SET_LOW_TERMIOS_BITS(termios, termio, c_oflag); \
-       SET_LOW_TERMIOS_BITS(termios, termio, c_cflag); \
-       SET_LOW_TERMIOS_BITS(termios, termio, c_lflag); \
-       copy_from_user((termios)->c_cc, (termio)->c_cc, NCC); \
-})
-
-/*
- * Translate a "termios" structure into a "termio". Ugh.
- */
-
-#define kernel_termios_to_user_termio(termio, termios) \
-({ \
-       put_user((termios)->c_iflag, &(termio)->c_iflag); \
-       put_user((termios)->c_oflag, &(termio)->c_oflag); \
-       put_user((termios)->c_cflag, &(termio)->c_cflag); \
-       put_user((termios)->c_lflag, &(termio)->c_lflag); \
-       put_user((termios)->c_line,  &(termio)->c_line); \
-       copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
-})
-
-#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios2))
-#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios2))
-#define user_termios_to_kernel_termios_1(k, u) copy_from_user(k, u, sizeof(struct termios))
-#define kernel_termios_to_user_termios_1(u, k) copy_to_user(u, k, sizeof(struct termios))
-
-#endif /* __KERNEL__ */
-
-#endif /* _XTENSA_TERMIOS_H */
index 053bc42721067de7dbdf51fd50ab2b3c75b6dc27..175b3d5e1b01cd29f8c849f37db3496cc0005531 100644 (file)
@@ -63,10 +63,10 @@ extern cycles_t cacheflush_time;
  * Register access.
  */
 
-#define WSR_CCOUNT(r)    asm volatile ("wsr %0,"__stringify(CCOUNT) :: "a" (r))
-#define RSR_CCOUNT(r)    asm volatile ("rsr %0,"__stringify(CCOUNT) : "=a" (r))
-#define WSR_CCOMPARE(x,r) asm volatile ("wsr %0,"__stringify(CCOMPARE)"+"__stringify(x) :: "a"(r))
-#define RSR_CCOMPARE(x,r) asm volatile ("rsr %0,"__stringify(CCOMPARE)"+"__stringify(x) : "=a"(r))
+#define WSR_CCOUNT(r)    asm volatile ("wsr %0, ccount" :: "a" (r))
+#define RSR_CCOUNT(r)    asm volatile ("rsr %0, ccount" : "=a" (r))
+#define WSR_CCOMPARE(x,r) asm volatile ("wsr %0,"__stringify(SREG_CCOMPARE)"+"__stringify(x) :: "a"(r))
+#define RSR_CCOMPARE(x,r) asm volatile ("rsr %0,"__stringify(SREG_CCOMPARE)"+"__stringify(x) : "=a"(r))
 
 static inline unsigned long get_ccount (void)
 {
index 46d240074f747aa622711b35d0b130cedba6b812..43dd348a5a478d27daa70f2e8b019b8cfa0fcd22 100644 (file)
@@ -86,26 +86,26 @@ static inline void invalidate_dtlb_entry_no_isync (unsigned entry)
 
 static inline void set_itlbcfg_register (unsigned long val)
 {
-       __asm__ __volatile__("wsr  %0, "__stringify(ITLBCFG)"\n\t" "isync\n\t"
+       __asm__ __volatile__("wsr  %0, itlbcfg\n\t" "isync\n\t"
                             : : "a" (val));
 }
 
 static inline void set_dtlbcfg_register (unsigned long val)
 {
-       __asm__ __volatile__("wsr  %0, "__stringify(DTLBCFG)"; dsync\n\t"
+       __asm__ __volatile__("wsr  %0, dtlbcfg; dsync\n\t"
                             : : "a" (val));
 }
 
 static inline void set_ptevaddr_register (unsigned long val)
 {
-       __asm__ __volatile__(" wsr  %0, "__stringify(PTEVADDR)"; isync\n"
+       __asm__ __volatile__(" wsr  %0, ptevaddr; isync\n"
                             : : "a" (val));
 }
 
 static inline unsigned long read_ptevaddr_register (void)
 {
        unsigned long tmp;
-       __asm__ __volatile__("rsr  %0, "__stringify(PTEVADDR)"\n\t" : "=a" (tmp));
+       __asm__ __volatile__("rsr  %0, ptevaddr\n\t" : "=a" (tmp));
        return tmp;
 }
 
diff --git a/arch/xtensa/include/asm/topology.h b/arch/xtensa/include/asm/topology.h
deleted file mode 100644 (file)
index 7309e38..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * include/asm-xtensa/topology.h
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2001 - 2005 Tensilica Inc.
- */
-
-#ifndef _XTENSA_TOPOLOGY_H
-#define _XTENSA_TOPOLOGY_H
-
-#include <asm-generic/topology.h>
-
-#endif /* _XTENSA_TOPOLOGY_H */
index 6d4db7e8ffac608520d9985a3680fddcfcfc9a1b..2b410b8c7f79fcbe4e9e29fb1901dc8ad73395cb 100644 (file)
@@ -7,30 +7,17 @@
  *
  * Copyright (C) 2001 - 2005 Tensilica Inc.
  */
-
 #ifndef _XTENSA_TYPES_H
 #define _XTENSA_TYPES_H
 
-#include <asm-generic/int-ll64.h>
-
-#ifdef __ASSEMBLY__
-# define __XTENSA_UL(x)                (x)
-# define __XTENSA_UL_CONST(x)  x
-#else
-# define __XTENSA_UL(x)                ((unsigned long)(x))
-# define __XTENSA_UL_CONST(x)  x##UL
-#endif
+#include <uapi/asm/types.h>
 
 #ifndef __ASSEMBLY__
-
 /*
  * These aren't exported outside the kernel to avoid name space clashes
  */
-#ifdef __KERNEL__
 
 #define BITS_PER_LONG 32
 
-#endif /* __KERNEL__ */
 #endif
-
 #endif /* _XTENSA_TYPES_H */
index bc7e005faa602f5eb61beaf886f5a83c1ea1d209..9ef1c31d2c8363fdae934f157abce35d1ef21e89 100644 (file)
@@ -8,705 +8,8 @@
  * Copyright (C) 2001 - 2005 Tensilica Inc.
  */
 
-#ifndef _XTENSA_UNISTD_H
-#define _XTENSA_UNISTD_H
+#include <uapi/asm/unistd.h>
 
-#ifndef __SYSCALL
-# define __SYSCALL(nr,func,nargs)
-#endif
-
-#define __NR_spill                               0
-__SYSCALL(  0, sys_ni_syscall, 0)
-#define __NR_xtensa                              1
-__SYSCALL(  1, sys_ni_syscall, 0)
-#define __NR_available4                                  2
-__SYSCALL(  2, sys_ni_syscall, 0)
-#define __NR_available5                                  3
-__SYSCALL(  3, sys_ni_syscall, 0)
-#define __NR_available6                                  4
-__SYSCALL(  4, sys_ni_syscall, 0)
-#define __NR_available7                                  5
-__SYSCALL(  5, sys_ni_syscall, 0)
-#define __NR_available8                                  6
-__SYSCALL(  6, sys_ni_syscall, 0)
-#define __NR_available9                                  7
-__SYSCALL(  7, sys_ni_syscall, 0)
-
-/* File Operations */
-
-#define __NR_open                                8
-__SYSCALL(  8, sys_open, 3)
-#define __NR_close                               9
-__SYSCALL(  9, sys_close, 1)
-#define __NR_dup                                10
-__SYSCALL( 10, sys_dup, 1)
-#define __NR_dup2                               11
-__SYSCALL( 11, sys_dup2, 2)
-#define __NR_read                               12
-__SYSCALL( 12, sys_read, 3)
-#define __NR_write                              13
-__SYSCALL( 13, sys_write, 3)
-#define __NR_select                             14
-__SYSCALL( 14, sys_select, 5)
-#define __NR_lseek                              15
-__SYSCALL( 15, sys_lseek, 3)
-#define __NR_poll                               16
-__SYSCALL( 16, sys_poll, 3)
-#define __NR__llseek                            17
-__SYSCALL( 17, sys_llseek, 5)
-#define __NR_epoll_wait                         18
-__SYSCALL( 18, sys_epoll_wait, 4)
-#define __NR_epoll_ctl                                  19
-__SYSCALL( 19, sys_epoll_ctl, 4)
-#define __NR_epoll_create                       20
-__SYSCALL( 20, sys_epoll_create, 1)
-#define __NR_creat                              21
-__SYSCALL( 21, sys_creat, 2)
-#define __NR_truncate                           22
-__SYSCALL( 22, sys_truncate, 2)
-#define __NR_ftruncate                                  23
-__SYSCALL( 23, sys_ftruncate, 2)
-#define __NR_readv                              24
-__SYSCALL( 24, sys_readv, 3)
-#define __NR_writev                             25
-__SYSCALL( 25, sys_writev, 3)
-#define __NR_fsync                              26
-__SYSCALL( 26, sys_fsync, 1)
-#define __NR_fdatasync                                  27
-__SYSCALL( 27, sys_fdatasync, 1)
-#define __NR_truncate64                         28
-__SYSCALL( 28, sys_truncate64, 2)
-#define __NR_ftruncate64                        29
-__SYSCALL( 29, sys_ftruncate64, 2)
-#define __NR_pread64                            30
-__SYSCALL( 30, sys_pread64, 6)
-#define __NR_pwrite64                           31
-__SYSCALL( 31, sys_pwrite64, 6)
-
-#define __NR_link                               32
-__SYSCALL( 32, sys_link, 2)
-#define __NR_rename                             33
-__SYSCALL( 33, sys_rename, 2)
-#define __NR_symlink                            34
-__SYSCALL( 34, sys_symlink, 2)
-#define __NR_readlink                           35
-__SYSCALL( 35, sys_readlink, 3)
-#define __NR_mknod                              36
-__SYSCALL( 36, sys_mknod, 3)
-#define __NR_pipe                               37
-__SYSCALL( 37, sys_pipe, 1)
-#define __NR_unlink                             38
-__SYSCALL( 38, sys_unlink, 1)
-#define __NR_rmdir                              39
-__SYSCALL( 39, sys_rmdir, 1)
-
-#define __NR_mkdir                              40
-__SYSCALL( 40, sys_mkdir, 2)
-#define __NR_chdir                              41
-__SYSCALL( 41, sys_chdir, 1)
-#define __NR_fchdir                             42
-__SYSCALL( 42, sys_fchdir, 1)
-#define __NR_getcwd                             43
-__SYSCALL( 43, sys_getcwd, 2)
-
-#define __NR_chmod                              44
-__SYSCALL( 44, sys_chmod, 2)
-#define __NR_chown                              45
-__SYSCALL( 45, sys_chown, 3)
-#define __NR_stat                               46
-__SYSCALL( 46, sys_newstat, 2)
-#define __NR_stat64                             47
-__SYSCALL( 47, sys_stat64, 2)
-
-#define __NR_lchown                             48
-__SYSCALL( 48, sys_lchown, 3)
-#define __NR_lstat                              49
-__SYSCALL( 49, sys_newlstat, 2)
-#define __NR_lstat64                            50
-__SYSCALL( 50, sys_lstat64, 2)
-#define __NR_available51                        51
-__SYSCALL( 51, sys_ni_syscall, 0)
-
-#define __NR_fchmod                             52
-__SYSCALL( 52, sys_fchmod, 2)
-#define __NR_fchown                             53
-__SYSCALL( 53, sys_fchown, 3)
-#define __NR_fstat                              54
-__SYSCALL( 54, sys_newfstat, 2)
-#define __NR_fstat64                            55
-__SYSCALL( 55, sys_fstat64, 2)
-
-#define __NR_flock                              56
-__SYSCALL( 56, sys_flock, 2)
-#define __NR_access                             57
-__SYSCALL( 57, sys_access, 2)
-#define __NR_umask                              58
-__SYSCALL( 58, sys_umask, 1)
-#define __NR_getdents                           59
-__SYSCALL( 59, sys_getdents, 3)
-#define __NR_getdents64                         60
-__SYSCALL( 60, sys_getdents64, 3)
-#define __NR_fcntl64                            61
-__SYSCALL( 61, sys_fcntl64, 3)
-#define __NR_available62                        62
-__SYSCALL( 62, sys_ni_syscall, 0)
-#define __NR_fadvise64_64                       63
-__SYSCALL( 63, xtensa_fadvise64_64, 6)
-#define __NR_utime                              64     /* glibc 2.3.3 ?? */
-__SYSCALL( 64, sys_utime, 2)
-#define __NR_utimes                             65
-__SYSCALL( 65, sys_utimes, 2)
-#define __NR_ioctl                              66
-__SYSCALL( 66, sys_ioctl, 3)
-#define __NR_fcntl                              67
-__SYSCALL( 67, sys_fcntl, 3)
-
-#define __NR_setxattr                           68
-__SYSCALL( 68, sys_setxattr, 5)
-#define __NR_getxattr                           69
-__SYSCALL( 69, sys_getxattr, 4)
-#define __NR_listxattr                                  70
-__SYSCALL( 70, sys_listxattr, 3)
-#define __NR_removexattr                        71
-__SYSCALL( 71, sys_removexattr, 2)
-#define __NR_lsetxattr                                  72
-__SYSCALL( 72, sys_lsetxattr, 5)
-#define __NR_lgetxattr                                  73
-__SYSCALL( 73, sys_lgetxattr, 4)
-#define __NR_llistxattr                         74
-__SYSCALL( 74, sys_llistxattr, 3)
-#define __NR_lremovexattr                       75
-__SYSCALL( 75, sys_lremovexattr, 2)
-#define __NR_fsetxattr                                  76
-__SYSCALL( 76, sys_fsetxattr, 5)
-#define __NR_fgetxattr                                  77
-__SYSCALL( 77, sys_fgetxattr, 4)
-#define __NR_flistxattr                         78
-__SYSCALL( 78, sys_flistxattr, 3)
-#define __NR_fremovexattr                       79
-__SYSCALL( 79, sys_fremovexattr, 2)
-
-/* File Map / Shared Memory Operations */
-
-#define __NR_mmap2                              80
-__SYSCALL( 80, sys_mmap_pgoff, 6)
-#define __NR_munmap                             81
-__SYSCALL( 81, sys_munmap, 2)
-#define __NR_mprotect                           82
-__SYSCALL( 82, sys_mprotect, 3)
-#define __NR_brk                                83
-__SYSCALL( 83, sys_brk, 1)
-#define __NR_mlock                              84
-__SYSCALL( 84, sys_mlock, 2)
-#define __NR_munlock                            85
-__SYSCALL( 85, sys_munlock, 2)
-#define __NR_mlockall                           86
-__SYSCALL( 86, sys_mlockall, 1)
-#define __NR_munlockall                         87
-__SYSCALL( 87, sys_munlockall, 0)
-#define __NR_mremap                             88
-__SYSCALL( 88, sys_mremap, 4)
-#define __NR_msync                              89
-__SYSCALL( 89, sys_msync, 3)
-#define __NR_mincore                            90
-__SYSCALL( 90, sys_mincore, 3)
-#define __NR_madvise                            91
-__SYSCALL( 91, sys_madvise, 3)
-#define __NR_shmget                             92
-__SYSCALL( 92, sys_shmget, 4)
-#define __NR_shmat                              93
-__SYSCALL( 93, xtensa_shmat, 4)
-#define __NR_shmctl                             94
-__SYSCALL( 94, sys_shmctl, 4)
-#define __NR_shmdt                              95
-__SYSCALL( 95, sys_shmdt, 4)
-
-/* Socket Operations */
-
-#define __NR_socket                             96
-__SYSCALL( 96, sys_socket, 3)
-#define __NR_setsockopt                         97
-__SYSCALL( 97, sys_setsockopt, 5)
-#define __NR_getsockopt                         98
-__SYSCALL( 98, sys_getsockopt, 5)
-#define __NR_shutdown                           99
-__SYSCALL( 99, sys_shutdown, 2)
-
-#define __NR_bind                              100
-__SYSCALL(100, sys_bind, 3)
-#define __NR_connect                           101
-__SYSCALL(101, sys_connect, 3)
-#define __NR_listen                            102
-__SYSCALL(102, sys_listen, 2)
-#define __NR_accept                            103
-__SYSCALL(103, sys_accept, 3)
-
-#define __NR_getsockname                       104
-__SYSCALL(104, sys_getsockname, 3)
-#define __NR_getpeername                       105
-__SYSCALL(105, sys_getpeername, 3)
-#define __NR_sendmsg                           106
-__SYSCALL(106, sys_sendmsg, 3)
-#define __NR_recvmsg                           107
-__SYSCALL(107, sys_recvmsg, 3)
-#define __NR_send                              108
-__SYSCALL(108, sys_send, 4)
-#define __NR_recv                              109
-__SYSCALL(109, sys_recv, 4)
-#define __NR_sendto                            110
-__SYSCALL(110, sys_sendto, 6)
-#define __NR_recvfrom                          111
-__SYSCALL(111, sys_recvfrom, 6)
-
-#define __NR_socketpair                        112
-__SYSCALL(112, sys_socketpair, 4)
-#define __NR_sendfile                          113
-__SYSCALL(113, sys_sendfile, 4)
-#define __NR_sendfile64                        114
-__SYSCALL(114, sys_sendfile64, 4)
-#define __NR_available115                      115
-__SYSCALL(115, sys_ni_syscall, 0)
-
-/* Process Operations */
-
-#define __NR_clone                             116
-__SYSCALL(116, xtensa_clone, 5)
-#define __NR_execve                            117
-__SYSCALL(117, xtensa_execve, 3)
-#define __NR_exit                              118
-__SYSCALL(118, sys_exit, 1)
-#define __NR_exit_group                        119
-__SYSCALL(119, sys_exit_group, 1)
-#define __NR_getpid                            120
-__SYSCALL(120, sys_getpid, 0)
-#define __NR_wait4                             121
-__SYSCALL(121, sys_wait4, 4)
-#define __NR_waitid                            122
-__SYSCALL(122, sys_waitid, 5)
-#define __NR_kill                              123
-__SYSCALL(123, sys_kill, 2)
-#define __NR_tkill                             124
-__SYSCALL(124, sys_tkill, 2)
-#define __NR_tgkill                            125
-__SYSCALL(125, sys_tgkill, 3)
-#define __NR_set_tid_address                   126
-__SYSCALL(126, sys_set_tid_address, 1)
-#define __NR_gettid                            127
-__SYSCALL(127, sys_gettid, 0)
-#define __NR_setsid                            128
-__SYSCALL(128, sys_setsid, 0)
-#define __NR_getsid                            129
-__SYSCALL(129, sys_getsid, 1)
-#define __NR_prctl                             130
-__SYSCALL(130, sys_prctl, 5)
-#define __NR_personality                       131
-__SYSCALL(131, sys_personality, 1)
-#define __NR_getpriority                       132
-__SYSCALL(132, sys_getpriority, 2)
-#define __NR_setpriority                       133
-__SYSCALL(133, sys_setpriority, 3)
-#define __NR_setitimer                                 134
-__SYSCALL(134, sys_setitimer, 3)
-#define __NR_getitimer                                 135
-__SYSCALL(135, sys_getitimer, 2)
-#define __NR_setuid                            136
-__SYSCALL(136, sys_setuid, 1)
-#define __NR_getuid                            137
-__SYSCALL(137, sys_getuid, 0)
-#define __NR_setgid                            138
-__SYSCALL(138, sys_setgid, 1)
-#define __NR_getgid                            139
-__SYSCALL(139, sys_getgid, 0)
-#define __NR_geteuid                           140
-__SYSCALL(140, sys_geteuid, 0)
-#define __NR_getegid                           141
-__SYSCALL(141, sys_getegid, 0)
-#define __NR_setreuid                          142
-__SYSCALL(142, sys_setreuid, 2)
-#define __NR_setregid                          143
-__SYSCALL(143, sys_setregid, 2)
-#define __NR_setresuid                                 144
-__SYSCALL(144, sys_setresuid, 3)
-#define __NR_getresuid                                 145
-__SYSCALL(145, sys_getresuid, 3)
-#define __NR_setresgid                                 146
-__SYSCALL(146, sys_setresgid, 3)
-#define __NR_getresgid                                 147
-__SYSCALL(147, sys_getresgid, 3)
-#define __NR_setpgid                           148
-__SYSCALL(148, sys_setpgid, 2)
-#define __NR_getpgid                           149
-__SYSCALL(149, sys_getpgid, 1)
-#define __NR_getppid                           150
-__SYSCALL(150, sys_getppid, 0)
-#define __NR_getpgrp                           151
-__SYSCALL(151, sys_getpgrp, 0)
-
-#define __NR_reserved152                       152     /* set_thread_area */
-__SYSCALL(152, sys_ni_syscall, 0)
-#define __NR_reserved153                       153     /* get_thread_area */
-__SYSCALL(153, sys_ni_syscall, 0)
-#define __NR_times                             154
-__SYSCALL(154, sys_times, 1)
-#define __NR_acct                              155
-__SYSCALL(155, sys_acct, 1)
-#define __NR_sched_setaffinity                         156
-__SYSCALL(156, sys_sched_setaffinity, 3)
-#define __NR_sched_getaffinity                         157
-__SYSCALL(157, sys_sched_getaffinity, 3)
-#define __NR_capget                            158
-__SYSCALL(158, sys_capget, 2)
-#define __NR_capset                            159
-__SYSCALL(159, sys_capset, 2)
-#define __NR_ptrace                            160
-__SYSCALL(160, sys_ptrace, 4)
-#define __NR_semtimedop                                161
-__SYSCALL(161, sys_semtimedop, 5)
-#define __NR_semget                            162
-__SYSCALL(162, sys_semget, 4)
-#define __NR_semop                             163
-__SYSCALL(163, sys_semop, 4)
-#define __NR_semctl                            164
-__SYSCALL(164, sys_semctl, 4)
-#define __NR_available165                      165
-__SYSCALL(165, sys_ni_syscall, 0)
-#define __NR_msgget                            166
-__SYSCALL(166, sys_msgget, 4)
-#define __NR_msgsnd                            167
-__SYSCALL(167, sys_msgsnd, 4)
-#define __NR_msgrcv                            168
-__SYSCALL(168, sys_msgrcv, 4)
-#define __NR_msgctl                            169
-__SYSCALL(169, sys_msgctl, 4)
-#define __NR_available170                      170
-__SYSCALL(170, sys_ni_syscall, 0)
-#define __NR_available171                      171
-__SYSCALL(171, sys_ni_syscall, 0)
-
-/* File System */
-
-#define __NR_mount                             172
-__SYSCALL(172, sys_mount, 5)
-#define __NR_swapon                            173
-__SYSCALL(173, sys_swapon, 2)
-#define __NR_chroot                            174
-__SYSCALL(174, sys_chroot, 1)
-#define __NR_pivot_root                        175
-__SYSCALL(175, sys_pivot_root, 2)
-#define __NR_umount                            176
-__SYSCALL(176, sys_umount, 2)
-#define __NR_swapoff                           177
-__SYSCALL(177, sys_swapoff, 1)
-#define __NR_sync                              178
-__SYSCALL(178, sys_sync, 0)
-#define __NR_available179                      179
-__SYSCALL(179, sys_ni_syscall, 0)
-#define __NR_setfsuid                          180
-__SYSCALL(180, sys_setfsuid, 1)
-#define __NR_setfsgid                          181
-__SYSCALL(181, sys_setfsgid, 1)
-#define __NR_sysfs                             182
-__SYSCALL(182, sys_sysfs, 3)
-#define __NR_ustat                             183
-__SYSCALL(183, sys_ustat, 2)
-#define __NR_statfs                            184
-__SYSCALL(184, sys_statfs, 2)
-#define __NR_fstatfs                           185
-__SYSCALL(185, sys_fstatfs, 2)
-#define __NR_statfs64                          186
-__SYSCALL(186, sys_statfs64, 3)
-#define __NR_fstatfs64                                 187
-__SYSCALL(187, sys_fstatfs64, 3)
-
-/* System */
-
-#define __NR_setrlimit                                 188
-__SYSCALL(188, sys_setrlimit, 2)
-#define __NR_getrlimit                                 189
-__SYSCALL(189, sys_getrlimit, 2)
-#define __NR_getrusage                                 190
-__SYSCALL(190, sys_getrusage, 2)
-#define __NR_futex                             191
-__SYSCALL(191, sys_futex, 5)
-#define __NR_gettimeofday                      192
-__SYSCALL(192, sys_gettimeofday, 2)
-#define __NR_settimeofday                      193
-__SYSCALL(193, sys_settimeofday, 2)
-#define __NR_adjtimex                          194
-__SYSCALL(194, sys_adjtimex, 1)
-#define __NR_nanosleep                         195
-__SYSCALL(195, sys_nanosleep, 2)
-#define __NR_getgroups                                 196
-__SYSCALL(196, sys_getgroups, 2)
-#define __NR_setgroups                                 197
-__SYSCALL(197, sys_setgroups, 2)
-#define __NR_sethostname                       198
-__SYSCALL(198, sys_sethostname, 2)
-#define __NR_setdomainname                     199
-__SYSCALL(199, sys_setdomainname, 2)
-#define __NR_syslog                            200
-__SYSCALL(200, sys_syslog, 3)
-#define __NR_vhangup                           201
-__SYSCALL(201, sys_vhangup, 0)
-#define __NR_uselib                            202
-__SYSCALL(202, sys_uselib, 1)
-#define __NR_reboot                            203
-__SYSCALL(203, sys_reboot, 3)
-#define __NR_quotactl                          204
-__SYSCALL(204, sys_quotactl, 4)
-#define __NR_nfsservctl                        205
-__SYSCALL(205, sys_ni_syscall, 0)
-#define __NR__sysctl                           206
-__SYSCALL(206, sys_sysctl, 1)
-#define __NR_bdflush                           207
-__SYSCALL(207, sys_bdflush, 2)
-#define __NR_uname                             208
-__SYSCALL(208, sys_newuname, 1)
-#define __NR_sysinfo                           209
-__SYSCALL(209, sys_sysinfo, 1)
-#define __NR_init_module                       210
-__SYSCALL(210, sys_init_module, 2)
-#define __NR_delete_module                     211
-__SYSCALL(211, sys_delete_module, 1)
-
-#define __NR_sched_setparam                    212
-__SYSCALL(212, sys_sched_setparam, 2)
-#define __NR_sched_getparam                    213
-__SYSCALL(213, sys_sched_getparam, 2)
-#define __NR_sched_setscheduler                214
-__SYSCALL(214, sys_sched_setscheduler, 3)
-#define __NR_sched_getscheduler                215
-__SYSCALL(215, sys_sched_getscheduler, 1)
-#define __NR_sched_get_priority_max            216
-__SYSCALL(216, sys_sched_get_priority_max, 1)
-#define __NR_sched_get_priority_min            217
-__SYSCALL(217, sys_sched_get_priority_min, 1)
-#define __NR_sched_rr_get_interval             218
-__SYSCALL(218, sys_sched_rr_get_interval, 2)
-#define __NR_sched_yield                       219
-__SYSCALL(219, sys_sched_yield, 0)
-#define __NR_available222                      222
-__SYSCALL(222, sys_ni_syscall, 0)
-
-/* Signal Handling */
-
-#define __NR_restart_syscall                   223
-__SYSCALL(223, sys_restart_syscall, 0)
-#define __NR_sigaltstack                       224
-__SYSCALL(224, xtensa_sigaltstack, 2)
-#define __NR_rt_sigreturn                      225
-__SYSCALL(225, xtensa_rt_sigreturn, 1)
-#define __NR_rt_sigaction                      226
-__SYSCALL(226, sys_rt_sigaction, 4)
-#define __NR_rt_sigprocmask                    227
-__SYSCALL(227, sys_rt_sigprocmask, 4)
-#define __NR_rt_sigpending                     228
-__SYSCALL(228, sys_rt_sigpending, 2)
-#define __NR_rt_sigtimedwait                   229
-__SYSCALL(229, sys_rt_sigtimedwait, 4)
-#define __NR_rt_sigqueueinfo                   230
-__SYSCALL(230, sys_rt_sigqueueinfo, 3)
-#define __NR_rt_sigsuspend                     231
-__SYSCALL(231, sys_rt_sigsuspend, 2)
-
-/* Message */
-
-#define __NR_mq_open                           232
-__SYSCALL(232, sys_mq_open, 4)
-#define __NR_mq_unlink                                 233
-__SYSCALL(233, sys_mq_unlink, 1)
-#define __NR_mq_timedsend                      234
-__SYSCALL(234, sys_mq_timedsend, 5)
-#define __NR_mq_timedreceive                   235
-__SYSCALL(235, sys_mq_timedreceive, 5)
-#define __NR_mq_notify                                 236
-__SYSCALL(236, sys_mq_notify, 2)
-#define __NR_mq_getsetattr                     237
-__SYSCALL(237, sys_mq_getsetattr, 3)
-#define __NR_available238                      238
-__SYSCALL(238, sys_ni_syscall, 0)
-
-/* IO */
-
-#define __NR_io_setup                          239
-__SYSCALL(239, sys_io_setup, 2)
-#define __NR_io_destroy                        240
-__SYSCALL(240, sys_io_destroy, 1)
-#define __NR_io_submit                                 241
-__SYSCALL(241, sys_io_submit, 3)
-#define __NR_io_getevents                      242
-__SYSCALL(242, sys_io_getevents, 5)
-#define __NR_io_cancel                                 243
-__SYSCALL(243, sys_io_cancel, 3)
-#define __NR_clock_settime                     244
-__SYSCALL(244, sys_clock_settime, 2)
-#define __NR_clock_gettime                     245
-__SYSCALL(245, sys_clock_gettime, 2)
-#define __NR_clock_getres                      246
-__SYSCALL(246, sys_clock_getres, 2)
-#define __NR_clock_nanosleep                   247
-__SYSCALL(247, sys_clock_nanosleep, 4)
-
-/* Timer */
-
-#define __NR_timer_create                      248
-__SYSCALL(248, sys_timer_create, 3)
-#define __NR_timer_delete                      249
-__SYSCALL(249, sys_timer_delete, 1)
-#define __NR_timer_settime                     250
-__SYSCALL(250, sys_timer_settime, 4)
-#define __NR_timer_gettime                     251
-__SYSCALL(251, sys_timer_gettime, 2)
-#define __NR_timer_getoverrun                  252
-__SYSCALL(252, sys_timer_getoverrun, 1)
-
-/* System */
-
-#define __NR_reserved244                       253
-__SYSCALL(253, sys_ni_syscall, 0)
-#define __NR_lookup_dcookie                    254
-__SYSCALL(254, sys_lookup_dcookie, 4)
-#define __NR_available255                      255
-__SYSCALL(255, sys_ni_syscall, 0)
-#define __NR_add_key                           256
-__SYSCALL(256, sys_add_key, 5)
-#define __NR_request_key                       257
-__SYSCALL(257, sys_request_key, 5)
-#define __NR_keyctl                            258
-__SYSCALL(258, sys_keyctl, 5)
-#define __NR_available259                      259
-__SYSCALL(259, sys_ni_syscall, 0)
-
-
-#define __NR_readahead                         260
-__SYSCALL(260, sys_readahead, 5)
-#define __NR_remap_file_pages                  261
-__SYSCALL(261, sys_remap_file_pages, 5)
-#define __NR_migrate_pages                     262
-__SYSCALL(262, sys_migrate_pages, 0)
-#define __NR_mbind                             263
-__SYSCALL(263, sys_mbind, 6)
-#define __NR_get_mempolicy                     264
-__SYSCALL(264, sys_get_mempolicy, 5)
-#define __NR_set_mempolicy                     265
-__SYSCALL(265, sys_set_mempolicy, 3)
-#define __NR_unshare                           266
-__SYSCALL(266, sys_unshare, 1)
-#define __NR_move_pages                                267
-__SYSCALL(267, sys_move_pages, 0)
-#define __NR_splice                            268
-__SYSCALL(268, sys_splice, 0)
-#define __NR_tee                               269
-__SYSCALL(269, sys_tee, 0)
-#define __NR_vmsplice                          270
-__SYSCALL(270, sys_vmsplice, 0)
-#define __NR_available271                      271
-__SYSCALL(271, sys_ni_syscall, 0)
-
-#define __NR_pselect6                          272
-__SYSCALL(272, sys_pselect6, 0)
-#define __NR_ppoll                             273
-__SYSCALL(273, sys_ppoll, 0)
-#define __NR_epoll_pwait                       274
-__SYSCALL(274, sys_epoll_pwait, 0)
-#define __NR_available275                      275
-__SYSCALL(275, sys_ni_syscall, 0)
-
-#define __NR_inotify_init                      276
-__SYSCALL(276, sys_inotify_init, 0)
-#define __NR_inotify_add_watch                 277
-__SYSCALL(277, sys_inotify_add_watch, 3)
-#define __NR_inotify_rm_watch                  278
-__SYSCALL(278, sys_inotify_rm_watch, 2)
-#define __NR_available279                      279
-__SYSCALL(279, sys_ni_syscall, 0)
-
-#define __NR_getcpu                            280
-__SYSCALL(280, sys_getcpu, 0)
-#define __NR_kexec_load                                281
-__SYSCALL(281, sys_ni_syscall, 0)
-
-#define __NR_ioprio_set                                282
-__SYSCALL(282, sys_ioprio_set, 2)
-#define __NR_ioprio_get                                283
-__SYSCALL(283, sys_ioprio_get, 3)
-
-#define __NR_set_robust_list                   284
-__SYSCALL(284, sys_set_robust_list, 3)
-#define __NR_get_robust_list                   285
-__SYSCALL(285, sys_get_robust_list, 3)
-#define __NR_reserved286                       286     /* sync_file_rangeX */
-__SYSCALL(286, sys_ni_syscall, 3)
-#define __NR_available287                      287
-__SYSCALL(287, sys_faccessat, 0)
-
-/* Relative File Operations */
-
-#define __NR_openat                            288
-__SYSCALL(288, sys_openat, 4)
-#define __NR_mkdirat                           289
-__SYSCALL(289, sys_mkdirat, 3)
-#define __NR_mknodat                           290
-__SYSCALL(290, sys_mknodat, 4)
-#define __NR_unlinkat                          291
-__SYSCALL(291, sys_unlinkat, 3)
-#define __NR_renameat                          292
-__SYSCALL(292, sys_renameat, 4)
-#define __NR_linkat                            293
-__SYSCALL(293, sys_linkat, 5)
-#define __NR_symlinkat                         294
-__SYSCALL(294, sys_symlinkat, 3)
-#define __NR_readlinkat                                295
-__SYSCALL(295, sys_readlinkat, 4)
-#define __NR_utimensat                         296
-__SYSCALL(296, sys_utimensat, 0)
-#define __NR_fchownat                          297
-__SYSCALL(297, sys_fchownat, 5)
-#define __NR_futimesat                         298
-__SYSCALL(298, sys_futimesat, 4)
-#define __NR_fstatat64                         299
-__SYSCALL(299, sys_fstatat64, 0)
-#define __NR_fchmodat                          300
-__SYSCALL(300, sys_fchmodat, 4)
-#define __NR_faccessat                         301
-__SYSCALL(301, sys_faccessat, 4)
-#define __NR_available302                      302
-__SYSCALL(302, sys_ni_syscall, 0)
-#define __NR_available303                      303
-__SYSCALL(303, sys_ni_syscall, 0)
-
-#define __NR_signalfd                          304
-__SYSCALL(304, sys_signalfd, 3)
-/*  305 was __NR_timerfd  */
-__SYSCALL(305, sys_ni_syscall, 0)
-#define __NR_eventfd                           306
-__SYSCALL(306, sys_eventfd, 1)
-#define __NR_recvmmsg                          307
-__SYSCALL(307, sys_recvmmsg, 5)
-#define __NR_setns                             308
-__SYSCALL(308, sys_setns, 2)
-
-#define __NR_syscall_count                     309
-
-/*
- * sysxtensa syscall handler
- *
- * int sysxtensa (SYS_XTENSA_ATOMIC_SET,     ptr, val,    unused);
- * int sysxtensa (SYS_XTENSA_ATOMIC_ADD,     ptr, val,    unused);
- * int sysxtensa (SYS_XTENSA_ATOMIC_EXG_ADD, ptr, val,    unused);
- * int sysxtensa (SYS_XTENSA_ATOMIC_CMP_SWP, ptr, oldval, newval);
- *        a2            a6                   a3    a4      a5
- */
-
-#define SYS_XTENSA_RESERVED               0     /* don't use this */
-#define SYS_XTENSA_ATOMIC_SET             1     /* set variable */
-#define SYS_XTENSA_ATOMIC_EXG_ADD         2     /* exchange memory and add */
-#define SYS_XTENSA_ATOMIC_ADD             3     /* add to memory */
-#define SYS_XTENSA_ATOMIC_CMP_SWP         4     /* compare and swap */
-
-#define SYS_XTENSA_COUNT                  5     /* count */
-
-#ifdef __KERNEL__
 
 /*
  * "Conditional" syscalls
@@ -734,6 +37,3 @@ __SYSCALL(308, sys_setns, 2)
 #define __IGNORE_mmap                          /* use mmap2 */
 #define __IGNORE_vfork                         /* use clone */
 #define __IGNORE_fadvise64                     /* use fadvise64_64 */
-
-#endif /* __KERNEL__ */
-#endif /* _XTENSA_UNISTD_H */
diff --git a/arch/xtensa/include/asm/xor.h b/arch/xtensa/include/asm/xor.h
deleted file mode 100644 (file)
index e7b1f08..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * include/asm-xtensa/xor.h
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2001 - 2005 Tensilica Inc.
- */
-
-#ifndef _XTENSA_XOR_H
-#define _XTENSA_XOR_H
-
-#include <asm-generic/xor.h>
-
-#endif
index baebb3da1d44160fc6f6f259886656e6f494b167..56aad54e7fb7b7fd62c5a55e13589705d194ebb7 100644 (file)
@@ -1,3 +1,25 @@
 # UAPI Header export list
 include include/uapi/asm-generic/Kbuild.asm
 
+header-y += auxvec.h
+header-y += byteorder.h
+header-y += ioctls.h
+header-y += ipcbuf.h
+header-y += mman.h
+header-y += msgbuf.h
+header-y += param.h
+header-y += poll.h
+header-y += posix_types.h
+header-y += ptrace.h
+header-y += sembuf.h
+header-y += setup.h
+header-y += shmbuf.h
+header-y += sigcontext.h
+header-y += signal.h
+header-y += socket.h
+header-y += sockios.h
+header-y += stat.h
+header-y += swab.h
+header-y += termbits.h
+header-y += types.h
+header-y += unistd.h
diff --git a/arch/xtensa/include/uapi/asm/param.h b/arch/xtensa/include/uapi/asm/param.h
new file mode 100644 (file)
index 0000000..87bc2ea
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * include/asm-xtensa/param.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _UAPI_XTENSA_PARAM_H
+#define _UAPI_XTENSA_PARAM_H
+
+#ifndef __KERNEL__
+# define HZ            100
+#endif
+
+#define EXEC_PAGESIZE  4096
+
+#ifndef NGROUPS
+#define NGROUPS                32
+#endif
+
+#ifndef NOGROUP
+#define NOGROUP                (-1)
+#endif
+
+#define MAXHOSTNAMELEN 64      /* max length of hostname */
+
+#endif /* _UAPI_XTENSA_PARAM_H */
diff --git a/arch/xtensa/include/uapi/asm/ptrace.h b/arch/xtensa/include/uapi/asm/ptrace.h
new file mode 100644 (file)
index 0000000..ee17aa8
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * include/asm-xtensa/ptrace.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _UAPI_XTENSA_PTRACE_H
+#define _UAPI_XTENSA_PTRACE_H
+
+/*
+ * Kernel stack
+ *
+ *             +-----------------------+  -------- STACK_SIZE
+ *             |     register file     |  |
+ *             +-----------------------+  |
+ *             |    struct pt_regs     |  |
+ *             +-----------------------+  | ------ PT_REGS_OFFSET
+ * double      :  16 bytes spill area  :  |  ^
+ * excetion    :- - - - - - - - - - - -:  |  |
+ * frame       :    struct pt_regs     :  |  |
+ *             :- - - - - - - - - - - -:  |  |
+ *             |                       |  |  |
+ *             |     memory stack      |  |  |
+ *             |                       |  |  |
+ *             ~                       ~  ~  ~
+ *             ~                       ~  ~  ~
+ *             |                       |  |  |
+ *             |                       |  |  |
+ *             +-----------------------+  |  | --- STACK_BIAS
+ *             |  struct task_struct   |  |  |  ^
+ *  current --> +-----------------------+  |  |  |
+ *             |  struct thread_info   |  |  |  |
+ *             +-----------------------+ --------
+ */
+
+#define KERNEL_STACK_SIZE (2 * PAGE_SIZE)
+
+/*  Offsets for exception_handlers[] (3 x 64-entries x 4-byte tables). */
+
+#define EXC_TABLE_KSTK         0x004   /* Kernel Stack */
+#define EXC_TABLE_DOUBLE_SAVE  0x008   /* Double exception save area for a0 */
+#define EXC_TABLE_FIXUP                0x00c   /* Fixup handler */
+#define EXC_TABLE_PARAM                0x010   /* For passing a parameter to fixup */
+#define EXC_TABLE_SYSCALL_SAVE 0x014   /* For fast syscall handler */
+#define EXC_TABLE_FAST_USER    0x100   /* Fast user exception handler */
+#define EXC_TABLE_FAST_KERNEL  0x200   /* Fast kernel exception handler */
+#define EXC_TABLE_DEFAULT      0x300   /* Default C-Handler */
+#define EXC_TABLE_SIZE         0x400
+
+/* Registers used by strace */
+
+#define REG_A_BASE     0x0000
+#define REG_AR_BASE    0x0100
+#define REG_PC         0x0020
+#define REG_PS         0x02e6
+#define REG_WB         0x0248
+#define REG_WS         0x0249
+#define REG_LBEG       0x0200
+#define REG_LEND       0x0201
+#define REG_LCOUNT     0x0202
+#define REG_SAR                0x0203
+
+#define SYSCALL_NR     0x00ff
+
+/* Other PTRACE_ values defined in <linux/ptrace.h> using values 0-9,16,17,24 */
+
+#define PTRACE_GETREGS         12
+#define PTRACE_SETREGS         13
+#define PTRACE_GETXTREGS       18
+#define PTRACE_SETXTREGS       19
+
+
+#endif /* _UAPI_XTENSA_PTRACE_H */
diff --git a/arch/xtensa/include/uapi/asm/signal.h b/arch/xtensa/include/uapi/asm/signal.h
new file mode 100644 (file)
index 0000000..b88ce96
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * include/asm-xtensa/signal.h
+ *
+ * Swiped from SH.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _UAPI_XTENSA_SIGNAL_H
+#define _UAPI_XTENSA_SIGNAL_H
+
+
+#define _NSIG          64
+#define _NSIG_BPW      32
+#define _NSIG_WORDS    (_NSIG / _NSIG_BPW)
+
+#ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+
+/* Avoid too many header ordering problems.  */
+struct siginfo;
+typedef unsigned long old_sigset_t;            /* at least 32 bits */
+typedef struct {
+       unsigned long sig[_NSIG_WORDS];
+} sigset_t;
+
+#endif
+
+#define SIGHUP          1
+#define SIGINT          2
+#define SIGQUIT                 3
+#define SIGILL          4
+#define SIGTRAP                 5
+#define SIGABRT                 6
+#define SIGIOT          6
+#define SIGBUS          7
+#define SIGFPE          8
+#define SIGKILL                 9
+#define SIGUSR1                10
+#define SIGSEGV                11
+#define SIGUSR2                12
+#define SIGPIPE                13
+#define SIGALRM                14
+#define SIGTERM                15
+#define SIGSTKFLT      16
+#define SIGCHLD                17
+#define SIGCONT                18
+#define SIGSTOP                19
+#define SIGTSTP                20
+#define SIGTTIN                21
+#define SIGTTOU                22
+#define SIGURG         23
+#define SIGXCPU                24
+#define SIGXFSZ                25
+#define SIGVTALRM      26
+#define SIGPROF                27
+#define SIGWINCH       28
+#define SIGIO          29
+#define SIGPOLL                SIGIO
+/* #define SIGLOST             29 */
+#define SIGPWR         30
+#define SIGSYS         31
+#define        SIGUNUSED       31
+
+/* These should not be considered constants from userland.  */
+#define SIGRTMIN       32
+#define SIGRTMAX       (_NSIG-1)
+
+/*
+ * SA_FLAGS values:
+ *
+ * SA_ONSTACK indicates that a registered stack_t will be used.
+ * SA_RESTART flag to get restarting signals (which were the default long ago)
+ * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
+ * SA_RESETHAND clears the handler when the signal is delivered.
+ * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
+ * SA_NODEFER prevents the current signal from being masked in the handler.
+ *
+ * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
+ * Unix names RESETHAND and NODEFER respectively.
+ */
+#define SA_NOCLDSTOP   0x00000001
+#define SA_NOCLDWAIT   0x00000002 /* not supported yet */
+#define SA_SIGINFO     0x00000004
+#define SA_ONSTACK     0x08000000
+#define SA_RESTART     0x10000000
+#define SA_NODEFER     0x40000000
+#define SA_RESETHAND   0x80000000
+
+#define SA_NOMASK      SA_NODEFER
+#define SA_ONESHOT     SA_RESETHAND
+
+#define SA_RESTORER    0x04000000
+
+/*
+ * sigaltstack controls
+ */
+#define SS_ONSTACK     1
+#define SS_DISABLE     2
+
+#define MINSIGSTKSZ    2048
+#define SIGSTKSZ       8192
+
+#ifndef __ASSEMBLY__
+
+#define SIG_BLOCK          0   /* for blocking signals */
+#define SIG_UNBLOCK        1   /* for unblocking signals */
+#define SIG_SETMASK        2   /* for setting the signal mask */
+
+/* Type of a signal handler.  */
+typedef void (*__sighandler_t)(int);
+
+#define SIG_DFL        ((__sighandler_t)0)     /* default signal handling */
+#define SIG_IGN        ((__sighandler_t)1)     /* ignore signal */
+#define SIG_ERR        ((__sighandler_t)-1)    /* error return from signal */
+
+#ifndef __KERNEL__
+
+/* Here we must cater to libcs that poke about in kernel headers.  */
+
+struct sigaction {
+       union {
+         __sighandler_t _sa_handler;
+         void (*_sa_sigaction)(int, struct siginfo *, void *);
+       } _u;
+       sigset_t sa_mask;
+       unsigned long sa_flags;
+       void (*sa_restorer)(void);
+};
+
+#define sa_handler     _u._sa_handler
+#define sa_sigaction   _u._sa_sigaction
+
+#endif /* __KERNEL__ */
+
+typedef struct sigaltstack {
+       void *ss_sp;
+       int ss_flags;
+       size_t ss_size;
+} stack_t;
+
+#endif /* __ASSEMBLY__ */
+#endif /* _UAPI_XTENSA_SIGNAL_H */
diff --git a/arch/xtensa/include/uapi/asm/types.h b/arch/xtensa/include/uapi/asm/types.h
new file mode 100644 (file)
index 0000000..87ec7ae
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * include/asm-xtensa/types.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _UAPI_XTENSA_TYPES_H
+#define _UAPI_XTENSA_TYPES_H
+
+#include <asm-generic/int-ll64.h>
+
+#ifdef __ASSEMBLY__
+# define __XTENSA_UL(x)                (x)
+# define __XTENSA_UL_CONST(x)  x
+#else
+# define __XTENSA_UL(x)                ((unsigned long)(x))
+# define __XTENSA_UL_CONST(x)  x##UL
+#endif
+
+#ifndef __ASSEMBLY__
+
+#endif
+
+#endif /* _UAPI_XTENSA_TYPES_H */
diff --git a/arch/xtensa/include/uapi/asm/unistd.h b/arch/xtensa/include/uapi/asm/unistd.h
new file mode 100644 (file)
index 0000000..479abae
--- /dev/null
@@ -0,0 +1,762 @@
+/*
+ * include/asm-xtensa/unistd.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2012 Tensilica Inc.
+ */
+
+#ifndef _UAPI_XTENSA_UNISTD_H
+#define _UAPI_XTENSA_UNISTD_H
+
+#ifndef __SYSCALL
+# define __SYSCALL(nr,func,nargs)
+#endif
+
+#define __NR_spill                               0
+__SYSCALL(  0, sys_ni_syscall, 0)
+#define __NR_xtensa                              1
+__SYSCALL(  1, sys_ni_syscall, 0)
+#define __NR_available4                                  2
+__SYSCALL(  2, sys_ni_syscall, 0)
+#define __NR_available5                                  3
+__SYSCALL(  3, sys_ni_syscall, 0)
+#define __NR_available6                                  4
+__SYSCALL(  4, sys_ni_syscall, 0)
+#define __NR_available7                                  5
+__SYSCALL(  5, sys_ni_syscall, 0)
+#define __NR_available8                                  6
+__SYSCALL(  6, sys_ni_syscall, 0)
+#define __NR_available9                                  7
+__SYSCALL(  7, sys_ni_syscall, 0)
+
+/* File Operations */
+
+#define __NR_open                                8
+__SYSCALL(  8, sys_open, 3)
+#define __NR_close                               9
+__SYSCALL(  9, sys_close, 1)
+#define __NR_dup                                10
+__SYSCALL( 10, sys_dup, 1)
+#define __NR_dup2                               11
+__SYSCALL( 11, sys_dup2, 2)
+#define __NR_read                               12
+__SYSCALL( 12, sys_read, 3)
+#define __NR_write                              13
+__SYSCALL( 13, sys_write, 3)
+#define __NR_select                             14
+__SYSCALL( 14, sys_select, 5)
+#define __NR_lseek                              15
+__SYSCALL( 15, sys_lseek, 3)
+#define __NR_poll                               16
+__SYSCALL( 16, sys_poll, 3)
+#define __NR__llseek                            17
+__SYSCALL( 17, sys_llseek, 5)
+#define __NR_epoll_wait                         18
+__SYSCALL( 18, sys_epoll_wait, 4)
+#define __NR_epoll_ctl                                  19
+__SYSCALL( 19, sys_epoll_ctl, 4)
+#define __NR_epoll_create                       20
+__SYSCALL( 20, sys_epoll_create, 1)
+#define __NR_creat                              21
+__SYSCALL( 21, sys_creat, 2)
+#define __NR_truncate                           22
+__SYSCALL( 22, sys_truncate, 2)
+#define __NR_ftruncate                                  23
+__SYSCALL( 23, sys_ftruncate, 2)
+#define __NR_readv                              24
+__SYSCALL( 24, sys_readv, 3)
+#define __NR_writev                             25
+__SYSCALL( 25, sys_writev, 3)
+#define __NR_fsync                              26
+__SYSCALL( 26, sys_fsync, 1)
+#define __NR_fdatasync                                  27
+__SYSCALL( 27, sys_fdatasync, 1)
+#define __NR_truncate64                         28
+__SYSCALL( 28, sys_truncate64, 2)
+#define __NR_ftruncate64                        29
+__SYSCALL( 29, sys_ftruncate64, 2)
+#define __NR_pread64                            30
+__SYSCALL( 30, sys_pread64, 6)
+#define __NR_pwrite64                           31
+__SYSCALL( 31, sys_pwrite64, 6)
+
+#define __NR_link                               32
+__SYSCALL( 32, sys_link, 2)
+#define __NR_rename                             33
+__SYSCALL( 33, sys_rename, 2)
+#define __NR_symlink                            34
+__SYSCALL( 34, sys_symlink, 2)
+#define __NR_readlink                           35
+__SYSCALL( 35, sys_readlink, 3)
+#define __NR_mknod                              36
+__SYSCALL( 36, sys_mknod, 3)
+#define __NR_pipe                               37
+__SYSCALL( 37, sys_pipe, 1)
+#define __NR_unlink                             38
+__SYSCALL( 38, sys_unlink, 1)
+#define __NR_rmdir                              39
+__SYSCALL( 39, sys_rmdir, 1)
+
+#define __NR_mkdir                              40
+__SYSCALL( 40, sys_mkdir, 2)
+#define __NR_chdir                              41
+__SYSCALL( 41, sys_chdir, 1)
+#define __NR_fchdir                             42
+__SYSCALL( 42, sys_fchdir, 1)
+#define __NR_getcwd                             43
+__SYSCALL( 43, sys_getcwd, 2)
+
+#define __NR_chmod                              44
+__SYSCALL( 44, sys_chmod, 2)
+#define __NR_chown                              45
+__SYSCALL( 45, sys_chown, 3)
+#define __NR_stat                               46
+__SYSCALL( 46, sys_newstat, 2)
+#define __NR_stat64                             47
+__SYSCALL( 47, sys_stat64, 2)
+
+#define __NR_lchown                             48
+__SYSCALL( 48, sys_lchown, 3)
+#define __NR_lstat                              49
+__SYSCALL( 49, sys_newlstat, 2)
+#define __NR_lstat64                            50
+__SYSCALL( 50, sys_lstat64, 2)
+#define __NR_available51                        51
+__SYSCALL( 51, sys_ni_syscall, 0)
+
+#define __NR_fchmod                             52
+__SYSCALL( 52, sys_fchmod, 2)
+#define __NR_fchown                             53
+__SYSCALL( 53, sys_fchown, 3)
+#define __NR_fstat                              54
+__SYSCALL( 54, sys_newfstat, 2)
+#define __NR_fstat64                            55
+__SYSCALL( 55, sys_fstat64, 2)
+
+#define __NR_flock                              56
+__SYSCALL( 56, sys_flock, 2)
+#define __NR_access                             57
+__SYSCALL( 57, sys_access, 2)
+#define __NR_umask                              58
+__SYSCALL( 58, sys_umask, 1)
+#define __NR_getdents                           59
+__SYSCALL( 59, sys_getdents, 3)
+#define __NR_getdents64                         60
+__SYSCALL( 60, sys_getdents64, 3)
+#define __NR_fcntl64                            61
+__SYSCALL( 61, sys_fcntl64, 3)
+#define __NR_fallocate                          62
+__SYSCALL( 62, sys_fallocate, 6)
+#define __NR_fadvise64_64                       63
+__SYSCALL( 63, xtensa_fadvise64_64, 6)
+#define __NR_utime                              64     /* glibc 2.3.3 ?? */
+__SYSCALL( 64, sys_utime, 2)
+#define __NR_utimes                             65
+__SYSCALL( 65, sys_utimes, 2)
+#define __NR_ioctl                              66
+__SYSCALL( 66, sys_ioctl, 3)
+#define __NR_fcntl                              67
+__SYSCALL( 67, sys_fcntl, 3)
+
+#define __NR_setxattr                           68
+__SYSCALL( 68, sys_setxattr, 5)
+#define __NR_getxattr                           69
+__SYSCALL( 69, sys_getxattr, 4)
+#define __NR_listxattr                                  70
+__SYSCALL( 70, sys_listxattr, 3)
+#define __NR_removexattr                        71
+__SYSCALL( 71, sys_removexattr, 2)
+#define __NR_lsetxattr                                  72
+__SYSCALL( 72, sys_lsetxattr, 5)
+#define __NR_lgetxattr                                  73
+__SYSCALL( 73, sys_lgetxattr, 4)
+#define __NR_llistxattr                         74
+__SYSCALL( 74, sys_llistxattr, 3)
+#define __NR_lremovexattr                       75
+__SYSCALL( 75, sys_lremovexattr, 2)
+#define __NR_fsetxattr                                  76
+__SYSCALL( 76, sys_fsetxattr, 5)
+#define __NR_fgetxattr                                  77
+__SYSCALL( 77, sys_fgetxattr, 4)
+#define __NR_flistxattr                         78
+__SYSCALL( 78, sys_flistxattr, 3)
+#define __NR_fremovexattr                       79
+__SYSCALL( 79, sys_fremovexattr, 2)
+
+/* File Map / Shared Memory Operations */
+
+#define __NR_mmap2                              80
+__SYSCALL( 80, sys_mmap_pgoff, 6)
+#define __NR_munmap                             81
+__SYSCALL( 81, sys_munmap, 2)
+#define __NR_mprotect                           82
+__SYSCALL( 82, sys_mprotect, 3)
+#define __NR_brk                                83
+__SYSCALL( 83, sys_brk, 1)
+#define __NR_mlock                              84
+__SYSCALL( 84, sys_mlock, 2)
+#define __NR_munlock                            85
+__SYSCALL( 85, sys_munlock, 2)
+#define __NR_mlockall                           86
+__SYSCALL( 86, sys_mlockall, 1)
+#define __NR_munlockall                         87
+__SYSCALL( 87, sys_munlockall, 0)
+#define __NR_mremap                             88
+__SYSCALL( 88, sys_mremap, 4)
+#define __NR_msync                              89
+__SYSCALL( 89, sys_msync, 3)
+#define __NR_mincore                            90
+__SYSCALL( 90, sys_mincore, 3)
+#define __NR_madvise                            91
+__SYSCALL( 91, sys_madvise, 3)
+#define __NR_shmget                             92
+__SYSCALL( 92, sys_shmget, 4)
+#define __NR_shmat                              93
+__SYSCALL( 93, xtensa_shmat, 4)
+#define __NR_shmctl                             94
+__SYSCALL( 94, sys_shmctl, 4)
+#define __NR_shmdt                              95
+__SYSCALL( 95, sys_shmdt, 4)
+
+/* Socket Operations */
+
+#define __NR_socket                             96
+__SYSCALL( 96, sys_socket, 3)
+#define __NR_setsockopt                         97
+__SYSCALL( 97, sys_setsockopt, 5)
+#define __NR_getsockopt                         98
+__SYSCALL( 98, sys_getsockopt, 5)
+#define __NR_shutdown                           99
+__SYSCALL( 99, sys_shutdown, 2)
+
+#define __NR_bind                              100
+__SYSCALL(100, sys_bind, 3)
+#define __NR_connect                           101
+__SYSCALL(101, sys_connect, 3)
+#define __NR_listen                            102
+__SYSCALL(102, sys_listen, 2)
+#define __NR_accept                            103
+__SYSCALL(103, sys_accept, 3)
+
+#define __NR_getsockname                       104
+__SYSCALL(104, sys_getsockname, 3)
+#define __NR_getpeername                       105
+__SYSCALL(105, sys_getpeername, 3)
+#define __NR_sendmsg                           106
+__SYSCALL(106, sys_sendmsg, 3)
+#define __NR_recvmsg                           107
+__SYSCALL(107, sys_recvmsg, 3)
+#define __NR_send                              108
+__SYSCALL(108, sys_send, 4)
+#define __NR_recv                              109
+__SYSCALL(109, sys_recv, 4)
+#define __NR_sendto                            110
+__SYSCALL(110, sys_sendto, 6)
+#define __NR_recvfrom                          111
+__SYSCALL(111, sys_recvfrom, 6)
+
+#define __NR_socketpair                        112
+__SYSCALL(112, sys_socketpair, 4)
+#define __NR_sendfile                          113
+__SYSCALL(113, sys_sendfile, 4)
+#define __NR_sendfile64                        114
+__SYSCALL(114, sys_sendfile64, 4)
+#define __NR_sendmmsg                          115
+__SYSCALL(115, sys_sendmmsg, 4)
+
+/* Process Operations */
+
+#define __NR_clone                             116
+__SYSCALL(116, xtensa_clone, 5)
+#define __NR_execve                            117
+__SYSCALL(117, xtensa_execve, 3)
+#define __NR_exit                              118
+__SYSCALL(118, sys_exit, 1)
+#define __NR_exit_group                        119
+__SYSCALL(119, sys_exit_group, 1)
+#define __NR_getpid                            120
+__SYSCALL(120, sys_getpid, 0)
+#define __NR_wait4                             121
+__SYSCALL(121, sys_wait4, 4)
+#define __NR_waitid                            122
+__SYSCALL(122, sys_waitid, 5)
+#define __NR_kill                              123
+__SYSCALL(123, sys_kill, 2)
+#define __NR_tkill                             124
+__SYSCALL(124, sys_tkill, 2)
+#define __NR_tgkill                            125
+__SYSCALL(125, sys_tgkill, 3)
+#define __NR_set_tid_address                   126
+__SYSCALL(126, sys_set_tid_address, 1)
+#define __NR_gettid                            127
+__SYSCALL(127, sys_gettid, 0)
+#define __NR_setsid                            128
+__SYSCALL(128, sys_setsid, 0)
+#define __NR_getsid                            129
+__SYSCALL(129, sys_getsid, 1)
+#define __NR_prctl                             130
+__SYSCALL(130, sys_prctl, 5)
+#define __NR_personality                       131
+__SYSCALL(131, sys_personality, 1)
+#define __NR_getpriority                       132
+__SYSCALL(132, sys_getpriority, 2)
+#define __NR_setpriority                       133
+__SYSCALL(133, sys_setpriority, 3)
+#define __NR_setitimer                                 134
+__SYSCALL(134, sys_setitimer, 3)
+#define __NR_getitimer                                 135
+__SYSCALL(135, sys_getitimer, 2)
+#define __NR_setuid                            136
+__SYSCALL(136, sys_setuid, 1)
+#define __NR_getuid                            137
+__SYSCALL(137, sys_getuid, 0)
+#define __NR_setgid                            138
+__SYSCALL(138, sys_setgid, 1)
+#define __NR_getgid                            139
+__SYSCALL(139, sys_getgid, 0)
+#define __NR_geteuid                           140
+__SYSCALL(140, sys_geteuid, 0)
+#define __NR_getegid                           141
+__SYSCALL(141, sys_getegid, 0)
+#define __NR_setreuid                          142
+__SYSCALL(142, sys_setreuid, 2)
+#define __NR_setregid                          143
+__SYSCALL(143, sys_setregid, 2)
+#define __NR_setresuid                                 144
+__SYSCALL(144, sys_setresuid, 3)
+#define __NR_getresuid                                 145
+__SYSCALL(145, sys_getresuid, 3)
+#define __NR_setresgid                                 146
+__SYSCALL(146, sys_setresgid, 3)
+#define __NR_getresgid                                 147
+__SYSCALL(147, sys_getresgid, 3)
+#define __NR_setpgid                           148
+__SYSCALL(148, sys_setpgid, 2)
+#define __NR_getpgid                           149
+__SYSCALL(149, sys_getpgid, 1)
+#define __NR_getppid                           150
+__SYSCALL(150, sys_getppid, 0)
+#define __NR_getpgrp                           151
+__SYSCALL(151, sys_getpgrp, 0)
+
+#define __NR_reserved152                       152     /* set_thread_area */
+__SYSCALL(152, sys_ni_syscall, 0)
+#define __NR_reserved153                       153     /* get_thread_area */
+__SYSCALL(153, sys_ni_syscall, 0)
+#define __NR_times                             154
+__SYSCALL(154, sys_times, 1)
+#define __NR_acct                              155
+__SYSCALL(155, sys_acct, 1)
+#define __NR_sched_setaffinity                         156
+__SYSCALL(156, sys_sched_setaffinity, 3)
+#define __NR_sched_getaffinity                         157
+__SYSCALL(157, sys_sched_getaffinity, 3)
+#define __NR_capget                            158
+__SYSCALL(158, sys_capget, 2)
+#define __NR_capset                            159
+__SYSCALL(159, sys_capset, 2)
+#define __NR_ptrace                            160
+__SYSCALL(160, sys_ptrace, 4)
+#define __NR_semtimedop                                161
+__SYSCALL(161, sys_semtimedop, 5)
+#define __NR_semget                            162
+__SYSCALL(162, sys_semget, 4)
+#define __NR_semop                             163
+__SYSCALL(163, sys_semop, 4)
+#define __NR_semctl                            164
+__SYSCALL(164, sys_semctl, 4)
+#define __NR_available165                      165
+__SYSCALL(165, sys_ni_syscall, 0)
+#define __NR_msgget                            166
+__SYSCALL(166, sys_msgget, 4)
+#define __NR_msgsnd                            167
+__SYSCALL(167, sys_msgsnd, 4)
+#define __NR_msgrcv                            168
+__SYSCALL(168, sys_msgrcv, 4)
+#define __NR_msgctl                            169
+__SYSCALL(169, sys_msgctl, 4)
+#define __NR_available170                      170
+__SYSCALL(170, sys_ni_syscall, 0)
+
+/* File System */
+
+#define __NR_umount2                           171
+__SYSCALL(171, sys_umount, 2)
+#define __NR_mount                             172
+__SYSCALL(172, sys_mount, 5)
+#define __NR_swapon                            173
+__SYSCALL(173, sys_swapon, 2)
+#define __NR_chroot                            174
+__SYSCALL(174, sys_chroot, 1)
+#define __NR_pivot_root                        175
+__SYSCALL(175, sys_pivot_root, 2)
+#define __NR_umount                            176
+__SYSCALL(176, sys_umount, 2)
+#define __NR_swapoff                           177
+__SYSCALL(177, sys_swapoff, 1)
+#define __NR_sync                              178
+__SYSCALL(178, sys_sync, 0)
+#define __NR_syncfs                            179
+__SYSCALL(179, sys_syncfs, 1)
+#define __NR_setfsuid                          180
+__SYSCALL(180, sys_setfsuid, 1)
+#define __NR_setfsgid                          181
+__SYSCALL(181, sys_setfsgid, 1)
+#define __NR_sysfs                             182
+__SYSCALL(182, sys_sysfs, 3)
+#define __NR_ustat                             183
+__SYSCALL(183, sys_ustat, 2)
+#define __NR_statfs                            184
+__SYSCALL(184, sys_statfs, 2)
+#define __NR_fstatfs                           185
+__SYSCALL(185, sys_fstatfs, 2)
+#define __NR_statfs64                          186
+__SYSCALL(186, sys_statfs64, 3)
+#define __NR_fstatfs64                                 187
+__SYSCALL(187, sys_fstatfs64, 3)
+
+/* System */
+
+#define __NR_setrlimit                                 188
+__SYSCALL(188, sys_setrlimit, 2)
+#define __NR_getrlimit                                 189
+__SYSCALL(189, sys_getrlimit, 2)
+#define __NR_getrusage                                 190
+__SYSCALL(190, sys_getrusage, 2)
+#define __NR_futex                             191
+__SYSCALL(191, sys_futex, 5)
+#define __NR_gettimeofday                      192
+__SYSCALL(192, sys_gettimeofday, 2)
+#define __NR_settimeofday                      193
+__SYSCALL(193, sys_settimeofday, 2)
+#define __NR_adjtimex                          194
+__SYSCALL(194, sys_adjtimex, 1)
+#define __NR_nanosleep                         195
+__SYSCALL(195, sys_nanosleep, 2)
+#define __NR_getgroups                                 196
+__SYSCALL(196, sys_getgroups, 2)
+#define __NR_setgroups                                 197
+__SYSCALL(197, sys_setgroups, 2)
+#define __NR_sethostname                       198
+__SYSCALL(198, sys_sethostname, 2)
+#define __NR_setdomainname                     199
+__SYSCALL(199, sys_setdomainname, 2)
+#define __NR_syslog                            200
+__SYSCALL(200, sys_syslog, 3)
+#define __NR_vhangup                           201
+__SYSCALL(201, sys_vhangup, 0)
+#define __NR_uselib                            202
+__SYSCALL(202, sys_uselib, 1)
+#define __NR_reboot                            203
+__SYSCALL(203, sys_reboot, 3)
+#define __NR_quotactl                          204
+__SYSCALL(204, sys_quotactl, 4)
+#define __NR_nfsservctl                        205
+__SYSCALL(205, sys_ni_syscall, 0)                      /* old nfsservctl */
+#define __NR__sysctl                           206
+__SYSCALL(206, sys_sysctl, 1)
+#define __NR_bdflush                           207
+__SYSCALL(207, sys_bdflush, 2)
+#define __NR_uname                             208
+__SYSCALL(208, sys_newuname, 1)
+#define __NR_sysinfo                           209
+__SYSCALL(209, sys_sysinfo, 1)
+#define __NR_init_module                       210
+__SYSCALL(210, sys_init_module, 2)
+#define __NR_delete_module                     211
+__SYSCALL(211, sys_delete_module, 1)
+
+#define __NR_sched_setparam                    212
+__SYSCALL(212, sys_sched_setparam, 2)
+#define __NR_sched_getparam                    213
+__SYSCALL(213, sys_sched_getparam, 2)
+#define __NR_sched_setscheduler                214
+__SYSCALL(214, sys_sched_setscheduler, 3)
+#define __NR_sched_getscheduler                215
+__SYSCALL(215, sys_sched_getscheduler, 1)
+#define __NR_sched_get_priority_max            216
+__SYSCALL(216, sys_sched_get_priority_max, 1)
+#define __NR_sched_get_priority_min            217
+__SYSCALL(217, sys_sched_get_priority_min, 1)
+#define __NR_sched_rr_get_interval             218
+__SYSCALL(218, sys_sched_rr_get_interval, 2)
+#define __NR_sched_yield                       219
+__SYSCALL(219, sys_sched_yield, 0)
+#define __NR_available222                      222
+__SYSCALL(222, sys_ni_syscall, 0)
+
+/* Signal Handling */
+
+#define __NR_restart_syscall                   223
+__SYSCALL(223, sys_restart_syscall, 0)
+#define __NR_sigaltstack                       224
+__SYSCALL(224, xtensa_sigaltstack, 2)
+#define __NR_rt_sigreturn                      225
+__SYSCALL(225, xtensa_rt_sigreturn, 1)
+#define __NR_rt_sigaction                      226
+__SYSCALL(226, sys_rt_sigaction, 4)
+#define __NR_rt_sigprocmask                    227
+__SYSCALL(227, sys_rt_sigprocmask, 4)
+#define __NR_rt_sigpending                     228
+__SYSCALL(228, sys_rt_sigpending, 2)
+#define __NR_rt_sigtimedwait                   229
+__SYSCALL(229, sys_rt_sigtimedwait, 4)
+#define __NR_rt_sigqueueinfo                   230
+__SYSCALL(230, sys_rt_sigqueueinfo, 3)
+#define __NR_rt_sigsuspend                     231
+__SYSCALL(231, sys_rt_sigsuspend, 2)
+
+/* Message */
+
+#define __NR_mq_open                           232
+__SYSCALL(232, sys_mq_open, 4)
+#define __NR_mq_unlink                                 233
+__SYSCALL(233, sys_mq_unlink, 1)
+#define __NR_mq_timedsend                      234
+__SYSCALL(234, sys_mq_timedsend, 5)
+#define __NR_mq_timedreceive                   235
+__SYSCALL(235, sys_mq_timedreceive, 5)
+#define __NR_mq_notify                                 236
+__SYSCALL(236, sys_mq_notify, 2)
+#define __NR_mq_getsetattr                     237
+__SYSCALL(237, sys_mq_getsetattr, 3)
+#define __NR_available238                      238
+__SYSCALL(238, sys_ni_syscall, 0)
+
+/* IO */
+
+#define __NR_io_setup                          239
+__SYSCALL(239, sys_io_setup, 2)
+#define __NR_io_destroy                        240
+__SYSCALL(240, sys_io_destroy, 1)
+#define __NR_io_submit                                 241
+__SYSCALL(241, sys_io_submit, 3)
+#define __NR_io_getevents                      242
+__SYSCALL(242, sys_io_getevents, 5)
+#define __NR_io_cancel                                 243
+__SYSCALL(243, sys_io_cancel, 3)
+#define __NR_clock_settime                     244
+__SYSCALL(244, sys_clock_settime, 2)
+#define __NR_clock_gettime                     245
+__SYSCALL(245, sys_clock_gettime, 2)
+#define __NR_clock_getres                      246
+__SYSCALL(246, sys_clock_getres, 2)
+#define __NR_clock_nanosleep                   247
+__SYSCALL(247, sys_clock_nanosleep, 4)
+
+/* Timer */
+
+#define __NR_timer_create                      248
+__SYSCALL(248, sys_timer_create, 3)
+#define __NR_timer_delete                      249
+__SYSCALL(249, sys_timer_delete, 1)
+#define __NR_timer_settime                     250
+__SYSCALL(250, sys_timer_settime, 4)
+#define __NR_timer_gettime                     251
+__SYSCALL(251, sys_timer_gettime, 2)
+#define __NR_timer_getoverrun                  252
+__SYSCALL(252, sys_timer_getoverrun, 1)
+
+/* System */
+
+#define __NR_reserved253                       253
+__SYSCALL(253, sys_ni_syscall, 0)
+#define __NR_lookup_dcookie                    254
+__SYSCALL(254, sys_lookup_dcookie, 4)
+#define __NR_available255                      255
+__SYSCALL(255, sys_ni_syscall, 0)
+#define __NR_add_key                           256
+__SYSCALL(256, sys_add_key, 5)
+#define __NR_request_key                       257
+__SYSCALL(257, sys_request_key, 5)
+#define __NR_keyctl                            258
+__SYSCALL(258, sys_keyctl, 5)
+#define __NR_available259                      259
+__SYSCALL(259, sys_ni_syscall, 0)
+
+
+#define __NR_readahead                         260
+__SYSCALL(260, sys_readahead, 5)
+#define __NR_remap_file_pages                  261
+__SYSCALL(261, sys_remap_file_pages, 5)
+#define __NR_migrate_pages                     262
+__SYSCALL(262, sys_migrate_pages, 0)
+#define __NR_mbind                             263
+__SYSCALL(263, sys_mbind, 6)
+#define __NR_get_mempolicy                     264
+__SYSCALL(264, sys_get_mempolicy, 5)
+#define __NR_set_mempolicy                     265
+__SYSCALL(265, sys_set_mempolicy, 3)
+#define __NR_unshare                           266
+__SYSCALL(266, sys_unshare, 1)
+#define __NR_move_pages                                267
+__SYSCALL(267, sys_move_pages, 0)
+#define __NR_splice                            268
+__SYSCALL(268, sys_splice, 0)
+#define __NR_tee                               269
+__SYSCALL(269, sys_tee, 0)
+#define __NR_vmsplice                          270
+__SYSCALL(270, sys_vmsplice, 0)
+#define __NR_available271                      271
+__SYSCALL(271, sys_ni_syscall, 0)
+
+#define __NR_pselect6                          272
+__SYSCALL(272, sys_pselect6, 0)
+#define __NR_ppoll                             273
+__SYSCALL(273, sys_ppoll, 0)
+#define __NR_epoll_pwait                       274
+__SYSCALL(274, sys_epoll_pwait, 0)
+#define __NR_epoll_create1             275
+__SYSCALL(275, sys_epoll_create1, 1)
+
+#define __NR_inotify_init                      276
+__SYSCALL(276, sys_inotify_init, 0)
+#define __NR_inotify_add_watch                 277
+__SYSCALL(277, sys_inotify_add_watch, 3)
+#define __NR_inotify_rm_watch                  278
+__SYSCALL(278, sys_inotify_rm_watch, 2)
+#define __NR_inotify_init1                     279
+__SYSCALL(279, sys_inotify_init1, 1)
+
+#define __NR_getcpu                            280
+__SYSCALL(280, sys_getcpu, 0)
+#define __NR_kexec_load                                281
+__SYSCALL(281, sys_ni_syscall, 0)
+
+#define __NR_ioprio_set                                282
+__SYSCALL(282, sys_ioprio_set, 2)
+#define __NR_ioprio_get                                283
+__SYSCALL(283, sys_ioprio_get, 3)
+
+#define __NR_set_robust_list                   284
+__SYSCALL(284, sys_set_robust_list, 3)
+#define __NR_get_robust_list                   285
+__SYSCALL(285, sys_get_robust_list, 3)
+#define __NR_available286                      286
+__SYSCALL(286, sys_ni_syscall, 0)
+#define __NR_available287                      287
+__SYSCALL(287, sys_ni_syscall, 0)
+
+/* Relative File Operations */
+
+#define __NR_openat                            288
+__SYSCALL(288, sys_openat, 4)
+#define __NR_mkdirat                           289
+__SYSCALL(289, sys_mkdirat, 3)
+#define __NR_mknodat                           290
+__SYSCALL(290, sys_mknodat, 4)
+#define __NR_unlinkat                          291
+__SYSCALL(291, sys_unlinkat, 3)
+#define __NR_renameat                          292
+__SYSCALL(292, sys_renameat, 4)
+#define __NR_linkat                            293
+__SYSCALL(293, sys_linkat, 5)
+#define __NR_symlinkat                         294
+__SYSCALL(294, sys_symlinkat, 3)
+#define __NR_readlinkat                                295
+__SYSCALL(295, sys_readlinkat, 4)
+#define __NR_utimensat                         296
+__SYSCALL(296, sys_utimensat, 0)
+#define __NR_fchownat                          297
+__SYSCALL(297, sys_fchownat, 5)
+#define __NR_futimesat                         298
+__SYSCALL(298, sys_futimesat, 4)
+#define __NR_fstatat64                         299
+__SYSCALL(299, sys_fstatat64, 0)
+#define __NR_fchmodat                          300
+__SYSCALL(300, sys_fchmodat, 4)
+#define __NR_faccessat                         301
+__SYSCALL(301, sys_faccessat, 4)
+#define __NR_available302                      302
+__SYSCALL(302, sys_ni_syscall, 0)
+#define __NR_available303                      303
+__SYSCALL(303, sys_ni_syscall, 0)
+
+#define __NR_signalfd                          304
+__SYSCALL(304, sys_signalfd, 3)
+/*  305 was __NR_timerfd  */
+__SYSCALL(305, sys_ni_syscall, 0)
+#define __NR_eventfd                           306
+__SYSCALL(306, sys_eventfd, 1)
+#define __NR_recvmmsg                          307
+__SYSCALL(307, sys_recvmmsg, 5)
+
+#define __NR_setns                             308
+__SYSCALL(308, sys_setns, 2)
+#define __NR_signalfd4                         309
+__SYSCALL(309, sys_signalfd4, 4)
+#define __NR_dup3                              310
+__SYSCALL(310, sys_dup3, 3)
+#define __NR_pipe2                             311
+__SYSCALL(311, sys_pipe2, 2)
+
+#define __NR_timerfd_create                    312
+__SYSCALL(312, sys_timerfd_create, 2)
+#define __NR_timerfd_settime                   313
+__SYSCALL(313, sys_timerfd_settime, 4)
+#define __NR_timerfd_gettime                   314
+__SYSCALL(314, sys_timerfd_gettime, 2)
+#define __NR_available315                      315
+__SYSCALL(315, sys_ni_syscall, 0)
+
+#define __NR_eventfd2                          316
+__SYSCALL(316, sys_eventfd2, 2)
+#define __NR_preadv                            317
+__SYSCALL(317, sys_preadv, 5)
+#define __NR_pwritev                           318
+__SYSCALL(318, sys_pwritev, 5)
+#define __NR_available319                      319
+__SYSCALL(319, sys_ni_syscall, 0)
+
+#define __NR_fanotify_init                     320
+__SYSCALL(320, sys_fanotify_init, 2)
+#define __NR_fanotify_mark                     321
+__SYSCALL(321, sys_fanotify_mark, 6)
+#define __NR_process_vm_readv                  322
+__SYSCALL(322, sys_process_vm_readv, 6)
+#define __NR_process_vm_writev                 323
+__SYSCALL(323, sys_process_vm_writev, 6)
+
+#define __NR_name_to_handle_at                 324
+__SYSCALL(324, sys_name_to_handle_at, 5)
+#define __NR_open_by_handle_at                 325
+__SYSCALL(325, sys_open_by_handle_at, 3)
+#define __NR_sync_file_range                   326
+__SYSCALL(326, sys_sync_file_range2, 6)
+#define __NR_perf_event_open                   327
+__SYSCALL(327, sys_perf_event_open, 5)
+
+#define __NR_rt_tgsigqueueinfo                 328
+__SYSCALL(328, sys_rt_tgsigqueueinfo, 4)
+#define __NR_clock_adjtime                     329
+__SYSCALL(329, sys_clock_adjtime, 2)
+#define __NR_prlimit64                         330
+__SYSCALL(330, sys_prlimit64, 4)
+#define __NR_kcmp                              331
+__SYSCALL(331, sys_kcmp, 5)
+
+
+#define __NR_syscall_count                     332
+
+/*
+ * sysxtensa syscall handler
+ *
+ * int sysxtensa (SYS_XTENSA_ATOMIC_SET,     ptr, val,    unused);
+ * int sysxtensa (SYS_XTENSA_ATOMIC_ADD,     ptr, val,    unused);
+ * int sysxtensa (SYS_XTENSA_ATOMIC_EXG_ADD, ptr, val,    unused);
+ * int sysxtensa (SYS_XTENSA_ATOMIC_CMP_SWP, ptr, oldval, newval);
+ *        a2            a6                   a3    a4      a5
+ */
+
+#define SYS_XTENSA_RESERVED               0     /* don't use this */
+#define SYS_XTENSA_ATOMIC_SET             1     /* set variable */
+#define SYS_XTENSA_ATOMIC_EXG_ADD         2     /* exchange memory and add */
+#define SYS_XTENSA_ATOMIC_ADD             3     /* add to memory */
+#define SYS_XTENSA_ATOMIC_CMP_SWP         4     /* compare and swap */
+
+#define SYS_XTENSA_COUNT                  5     /* count */
+
+#endif /* _UAPI_XTENSA_UNISTD_H */
index 33d6e9d2e83ca10ec0301689457727c27fb58ec7..934ae58e2c79766f46cba80ac12ed63649faae9b 100644 (file)
@@ -170,15 +170,15 @@ ENTRY(fast_unaligned)
        s32i    a7, a2, PT_AREG7
        s32i    a8, a2, PT_AREG8
 
-       rsr     a0, DEPC
-       xsr     a3, EXCSAVE_1
+       rsr     a0, depc
+       xsr     a3, excsave1
        s32i    a0, a2, PT_AREG2
        s32i    a3, a2, PT_AREG3
 
        /* Keep value of SAR in a0 */
 
-       rsr     a0, SAR
-       rsr     a8, EXCVADDR            # load unaligned memory address
+       rsr     a0, sar
+       rsr     a8, excvaddr            # load unaligned memory address
 
        /* Now, identify one of the following load/store instructions.
         *
@@ -197,7 +197,7 @@ ENTRY(fast_unaligned)
 
        /* Extract the instruction that caused the unaligned access. */
 
-       rsr     a7, EPC_1       # load exception address
+       rsr     a7, epc1        # load exception address
        movi    a3, ~3
        and     a3, a3, a7      # mask lower bits
 
@@ -275,16 +275,16 @@ ENTRY(fast_unaligned)
 1:
 
 #if XCHAL_HAVE_LOOPS
-       rsr     a5, LEND                # check if we reached LEND
+       rsr     a5, lend                # check if we reached LEND
        bne     a7, a5, 1f
-       rsr     a5, LCOUNT              # and LCOUNT != 0
+       rsr     a5, lcount              # and LCOUNT != 0
        beqz    a5, 1f
        addi    a5, a5, -1              # decrement LCOUNT and set
-       rsr     a7, LBEG                # set PC to LBEGIN
-       wsr     a5, LCOUNT
+       rsr     a7, lbeg                # set PC to LBEGIN
+       wsr     a5, lcount
 #endif
 
-1:     wsr     a7, EPC_1               # skip load instruction
+1:     wsr     a7, epc1                # skip load instruction
        extui   a4, a4, INSN_T, 4       # extract target register
        movi    a5, .Lload_table
        addx8   a4, a4, a5
@@ -355,16 +355,16 @@ ENTRY(fast_unaligned)
 
 1:
 #if XCHAL_HAVE_LOOPS
-       rsr     a4, LEND                # check if we reached LEND
+       rsr     a4, lend                # check if we reached LEND
        bne     a7, a4, 1f
-       rsr     a4, LCOUNT              # and LCOUNT != 0
+       rsr     a4, lcount              # and LCOUNT != 0
        beqz    a4, 1f
        addi    a4, a4, -1              # decrement LCOUNT and set
-       rsr     a7, LBEG                # set PC to LBEGIN
-       wsr     a4, LCOUNT
+       rsr     a7, lbeg                # set PC to LBEGIN
+       wsr     a4, lcount
 #endif
 
-1:     wsr     a7, EPC_1               # skip store instruction
+1:     wsr     a7, epc1                # skip store instruction
        movi    a4, ~3
        and     a4, a4, a8              # align memory address
 
@@ -406,7 +406,7 @@ ENTRY(fast_unaligned)
 
 .Lexit:
        movi    a4, 0
-       rsr     a3, EXCSAVE_1
+       rsr     a3, excsave1
        s32i    a4, a3, EXC_TABLE_FIXUP
 
        /* Restore working register */
@@ -420,7 +420,7 @@ ENTRY(fast_unaligned)
 
        /* restore SAR and return */
 
-       wsr     a0, SAR
+       wsr     a0, sar
        l32i    a0, a2, PT_AREG0
        l32i    a2, a2, PT_AREG2
        rfe
@@ -438,10 +438,10 @@ ENTRY(fast_unaligned)
        l32i    a6, a2, PT_AREG6
        l32i    a5, a2, PT_AREG5
        l32i    a4, a2, PT_AREG4
-       wsr     a0, SAR
+       wsr     a0, sar
        mov     a1, a2
 
-       rsr     a0, PS
+       rsr     a0, ps
         bbsi.l  a2, PS_UM_BIT, 1f     # jump if user mode
 
        movi    a0, _kernel_exception
index 2bc1e145c0a46d66512826db3bcf41aa65d92491..54c3be313bfa8141e79f84606f8f3d6093d6946f 100644 (file)
@@ -43,7 +43,7 @@
 /* IO protection is currently unsupported. */
 
 ENTRY(fast_io_protect)
-       wsr     a0, EXCSAVE_1
+       wsr     a0, excsave1
        movi    a0, unrecoverable_exception
        callx0  a0
 
@@ -220,7 +220,7 @@ ENTRY(coprocessor_restore)
  */
 
 ENTRY(fast_coprocessor_double)
-       wsr     a0, EXCSAVE_1
+       wsr     a0, excsave1
        movi    a0, unrecoverable_exception
        callx0  a0
 
@@ -229,13 +229,13 @@ ENTRY(fast_coprocessor)
 
        /* Save remaining registers a1-a3 and SAR */
 
-       xsr     a3, EXCSAVE_1
+       xsr     a3, excsave1
        s32i    a3, a2, PT_AREG3
-       rsr     a3, SAR
+       rsr     a3, sar
        s32i    a1, a2, PT_AREG1
        s32i    a3, a2, PT_SAR
        mov     a1, a2
-       rsr     a2, DEPC
+       rsr     a2, depc
        s32i    a2, a1, PT_AREG2
 
        /*
@@ -248,17 +248,17 @@ ENTRY(fast_coprocessor)
 
        /* Find coprocessor number. Subtract first CP EXCCAUSE from EXCCAUSE */
 
-       rsr     a3, EXCCAUSE
+       rsr     a3, exccause
        addi    a3, a3, -EXCCAUSE_COPROCESSOR0_DISABLED
 
        /* Set corresponding CPENABLE bit -> (sar:cp-index, a3: 1<<cp-index)*/
 
        ssl     a3                      # SAR: 32 - coprocessor_number
        movi    a2, 1
-       rsr     a0, CPENABLE
+       rsr     a0, cpenable
        sll     a2, a2
        or      a0, a0, a2
-       wsr     a0, CPENABLE
+       wsr     a0, cpenable
        rsync
 
        /* Retrieve previous owner. (a3 still holds CP number) */
@@ -291,7 +291,7 @@ ENTRY(fast_coprocessor)
 
        /* Note that only a0 and a1 were preserved. */
 
-2:     rsr     a3, EXCCAUSE
+2:     rsr     a3, exccause
        addi    a3, a3, -EXCCAUSE_COPROCESSOR0_DISABLED
        movi    a0, coprocessor_owner
        addx4   a0, a3, a0
@@ -321,7 +321,7 @@ ENTRY(fast_coprocessor)
        l32i    a0, a1, PT_SAR
        l32i    a3, a1, PT_AREG3
        l32i    a2, a1, PT_AREG2
-       wsr     a0, SAR
+       wsr     a0, sar
        l32i    a0, a1, PT_AREG0
        l32i    a1, a1, PT_AREG1
 
index 7e62360733971886161bfc80bd318a41cc21feb4..18453067c2582034e896adee07c0d474912a98d2 100644 (file)
@@ -112,8 +112,8 @@ ENTRY(user_exception)
 
        /* Save a2, a3, and depc, restore excsave_1 and set SP. */
 
-       xsr     a3, EXCSAVE_1
-       rsr     a0, DEPC
+       xsr     a3, excsave1
+       rsr     a0, depc
        s32i    a1, a2, PT_AREG1
        s32i    a0, a2, PT_AREG2
        s32i    a3, a2, PT_AREG3
@@ -125,16 +125,16 @@ _user_exception:
        /* Save SAR and turn off single stepping */
 
        movi    a2, 0
-       rsr     a3, SAR
-       xsr     a2, ICOUNTLEVEL
+       rsr     a3, sar
+       xsr     a2, icountlevel
        s32i    a3, a1, PT_SAR
        s32i    a2, a1, PT_ICOUNTLEVEL
 
        /* Rotate ws so that the current windowbase is at bit0. */
        /* Assume ws = xxwww1yyyy. Rotate ws right, so that a2 = yyyyxxwww1 */
 
-       rsr     a2, WINDOWBASE
-       rsr     a3, WINDOWSTART
+       rsr     a2, windowbase
+       rsr     a3, windowstart
        ssr     a2
        s32i    a2, a1, PT_WINDOWBASE
        s32i    a3, a1, PT_WINDOWSTART
@@ -205,12 +205,12 @@ _user_exception:
 
        /* WINDOWBASE still in SAR! */
 
-       rsr     a2, SAR                 # original WINDOWBASE
+       rsr     a2, sar                 # original WINDOWBASE
        movi    a3, 1
        ssl     a2
        sll     a3, a3
-       wsr     a3, WINDOWSTART         # set corresponding WINDOWSTART bit
-       wsr     a2, WINDOWBASE          # and WINDOWSTART
+       wsr     a3, windowstart         # set corresponding WINDOWSTART bit
+       wsr     a2, windowbase          # and WINDOWSTART
        rsync
 
        /* We are back to the original stack pointer (a1) */
@@ -252,8 +252,8 @@ ENTRY(kernel_exception)
 
        /* Save a0, a2, a3, DEPC and set SP. */
 
-       xsr     a3, EXCSAVE_1           # restore a3, excsave_1
-       rsr     a0, DEPC                # get a2
+       xsr     a3, excsave1            # restore a3, excsave_1
+       rsr     a0, depc                # get a2
        s32i    a1, a2, PT_AREG1
        s32i    a0, a2, PT_AREG2
        s32i    a3, a2, PT_AREG3
@@ -265,16 +265,16 @@ _kernel_exception:
        /* Save SAR and turn off single stepping */
 
        movi    a2, 0
-       rsr     a3, SAR
-       xsr     a2, ICOUNTLEVEL
+       rsr     a3, sar
+       xsr     a2, icountlevel
        s32i    a3, a1, PT_SAR
        s32i    a2, a1, PT_ICOUNTLEVEL
 
        /* Rotate ws so that the current windowbase is at bit0. */
        /* Assume ws = xxwww1yyyy. Rotate ws right, so that a2 = yyyyxxwww1 */
 
-       rsr     a2, WINDOWBASE          # don't need to save these, we only
-       rsr     a3, WINDOWSTART         # need shifted windowstart: windowmask
+       rsr     a2, windowbase          # don't need to save these, we only
+       rsr     a3, windowstart         # need shifted windowstart: windowmask
        ssr     a2
        slli    a2, a3, 32-WSBITS
        src     a2, a3, a2
@@ -323,24 +323,24 @@ common_exception:
 
        /* Save some registers, disable loops and clear the syscall flag. */
 
-       rsr     a2, DEBUGCAUSE
-       rsr     a3, EPC_1
+       rsr     a2, debugcause
+       rsr     a3, epc1
        s32i    a2, a1, PT_DEBUGCAUSE
        s32i    a3, a1, PT_PC
 
        movi    a2, -1
-       rsr     a3, EXCVADDR
+       rsr     a3, excvaddr
        s32i    a2, a1, PT_SYSCALL
        movi    a2, 0
        s32i    a3, a1, PT_EXCVADDR
-       xsr     a2, LCOUNT
+       xsr     a2, lcount
        s32i    a2, a1, PT_LCOUNT
 
        /* It is now save to restore the EXC_TABLE_FIXUP variable. */
 
-       rsr     a0, EXCCAUSE
+       rsr     a0, exccause
        movi    a3, 0
-       rsr     a2, EXCSAVE_1
+       rsr     a2, excsave1
        s32i    a0, a1, PT_EXCCAUSE
        s32i    a3, a2, EXC_TABLE_FIXUP
 
@@ -352,22 +352,22 @@ common_exception:
         *     (interrupts disabled) and if this exception is not an interrupt.
         */
 
-       rsr     a3, PS
+       rsr     a3, ps
        addi    a0, a0, -4
        movi    a2, 1
        extui   a3, a3, 0, 1            # a3 = PS.INTLEVEL[0]
        moveqz  a3, a2, a0              # a3 = 1 iff interrupt exception
        movi    a2, 1 << PS_WOE_BIT
        or      a3, a3, a2
-       rsr     a0, EXCCAUSE
-       xsr     a3, PS
+       rsr     a0, exccause
+       xsr     a3, ps
 
        s32i    a3, a1, PT_PS           # save ps
 
-       /* Save LBEG, LEND */
+       /* Save lbeg, lend */
 
-       rsr     a2, LBEG
-       rsr     a3, LEND
+       rsr     a2, lbeg
+       rsr     a3, lend
        s32i    a2, a1, PT_LBEG
        s32i    a3, a1, PT_LEND
 
@@ -432,7 +432,7 @@ common_exception_return:
 
        load_xtregs_opt a1 a2 a4 a5 a6 a7 PT_XTREGS_OPT
 
-       wsr     a3, PS          /* disable interrupts */
+       wsr     a3, ps          /* disable interrupts */
 
        _bbci.l a3, PS_UM_BIT, kernel_exception_exit
 
@@ -444,12 +444,12 @@ user_exception_exit:
 
        l32i    a2, a1, PT_WINDOWBASE
        l32i    a3, a1, PT_WINDOWSTART
-       wsr     a1, DEPC                # use DEPC as temp storage
-       wsr     a3, WINDOWSTART         # restore WINDOWSTART
+       wsr     a1, depc                # use DEPC as temp storage
+       wsr     a3, windowstart         # restore WINDOWSTART
        ssr     a2                      # preserve user's WB in the SAR
-       wsr     a2, WINDOWBASE          # switch to user's saved WB
+       wsr     a2, windowbase          # switch to user's saved WB
        rsync
-       rsr     a1, DEPC                # restore stack pointer
+       rsr     a1, depc                # restore stack pointer
        l32i    a2, a1, PT_WMASK        # register frames saved (in bits 4...9)
        rotw    -1                      # we restore a4..a7
        _bltui  a6, 16, 1f              # only have to restore current window?
@@ -475,8 +475,8 @@ user_exception_exit:
 
        /* Clear unrestored registers (don't leak anything to user-land */
 
-1:     rsr     a0, WINDOWBASE
-       rsr     a3, SAR
+1:     rsr     a0, windowbase
+       rsr     a3, sar
        sub     a3, a0, a3
        beqz    a3, 2f
        extui   a3, a3, 0, WBBITS
@@ -556,7 +556,7 @@ kernel_exception_exit:
 
        /* Test WINDOWSTART now. If spilled, do the movsp */
 
-       rsr     a3, WINDOWSTART
+       rsr     a3, windowstart
        addi    a0, a3, -1
        and     a3, a3, a0
        _bnez   a3, common_exception_exit
@@ -604,24 +604,24 @@ common_exception_exit:
 
 1:     l32i    a2, a1, PT_PC
        l32i    a3, a1, PT_SAR
-       wsr     a2, EPC_1
-       wsr     a3, SAR
+       wsr     a2, epc1
+       wsr     a3, sar
 
        /* Restore LBEG, LEND, LCOUNT */
 
        l32i    a2, a1, PT_LBEG
        l32i    a3, a1, PT_LEND
-       wsr     a2, LBEG
+       wsr     a2, lbeg
        l32i    a2, a1, PT_LCOUNT
-       wsr     a3, LEND
-       wsr     a2, LCOUNT
+       wsr     a3, lend
+       wsr     a2, lcount
 
        /* We control single stepping through the ICOUNTLEVEL register. */
 
        l32i    a2, a1, PT_ICOUNTLEVEL
        movi    a3, -2
-       wsr     a2, ICOUNTLEVEL
-       wsr     a3, ICOUNT
+       wsr     a2, icountlevel
+       wsr     a3, icount
 
        /* Check if it was double exception. */
 
@@ -636,7 +636,7 @@ common_exception_exit:
        l32i    a1, a1, PT_AREG1
        rfe
 
-1:     wsr     a0, DEPC
+1:     wsr     a0, depc
        l32i    a0, a1, PT_AREG0
        l32i    a1, a1, PT_AREG1
        rfde
@@ -651,25 +651,25 @@ common_exception_exit:
 
 ENTRY(debug_exception)
 
-       rsr     a0, EPS + XCHAL_DEBUGLEVEL
+       rsr     a0, SREG_EPS + XCHAL_DEBUGLEVEL
        bbsi.l  a0, PS_EXCM_BIT, 1f     # exception mode
 
-       /* Set EPC_1 and EXCCAUSE */
+       /* Set EPC1 and EXCCAUSE */
 
-       wsr     a2, DEPC                # save a2 temporarily
-       rsr     a2, EPC + XCHAL_DEBUGLEVEL
-       wsr     a2, EPC_1
+       wsr     a2, depc                # save a2 temporarily
+       rsr     a2, SREG_EPC + XCHAL_DEBUGLEVEL
+       wsr     a2, epc1
 
        movi    a2, EXCCAUSE_MAPPED_DEBUG
-       wsr     a2, EXCCAUSE
+       wsr     a2, exccause
 
        /* Restore PS to the value before the debug exc but with PS.EXCM set.*/
 
        movi    a2, 1 << PS_EXCM_BIT
        or      a2, a0, a2
        movi    a0, debug_exception     # restore a3, debug jump vector
-       wsr     a2, PS
-       xsr     a0, EXCSAVE + XCHAL_DEBUGLEVEL
+       wsr     a2, ps
+       xsr     a0, SREG_EXCSAVE + XCHAL_DEBUGLEVEL
 
        /* Switch to kernel/user stack, restore jump vector, and save a0 */
 
@@ -680,19 +680,19 @@ ENTRY(debug_exception)
        movi    a0, 0
        s32i    a1, a2, PT_AREG1
        s32i    a0, a2, PT_DEPC         # mark it as a regular exception
-       xsr     a0, DEPC
+       xsr     a0, depc
        s32i    a3, a2, PT_AREG3
        s32i    a0, a2, PT_AREG2
        mov     a1, a2
        j       _kernel_exception
 
-2:     rsr     a2, EXCSAVE_1
+2:     rsr     a2, excsave1
        l32i    a2, a2, EXC_TABLE_KSTK  # load kernel stack pointer
        s32i    a0, a2, PT_AREG0
        movi    a0, 0
        s32i    a1, a2, PT_AREG1
        s32i    a0, a2, PT_DEPC
-       xsr     a0, DEPC
+       xsr     a0, depc
        s32i    a3, a2, PT_AREG3
        s32i    a0, a2, PT_AREG2
        mov     a1, a2
@@ -732,12 +732,12 @@ ENTRY(unrecoverable_exception)
        movi    a0, 1
        movi    a1, 0
 
-       wsr     a0, WINDOWSTART
-       wsr     a1, WINDOWBASE
+       wsr     a0, windowstart
+       wsr     a1, windowbase
        rsync
 
        movi    a1, (1 << PS_WOE_BIT) | 1
-       wsr     a1, PS
+       wsr     a1, ps
        rsync
 
        movi    a1, init_task
@@ -793,7 +793,7 @@ ENTRY(fast_alloca)
        l32i    a0, a2, PT_DEPC
        _bgeui  a0, VALID_DOUBLE_EXCEPTION_ADDRESS, .Lunhandled_double
 
-       rsr     a0, DEPC                # get a2
+       rsr     a0, depc                # get a2
        s32i    a4, a2, PT_AREG4        # save a4 and
        s32i    a0, a2, PT_AREG2        # a2 to stack
 
@@ -804,8 +804,8 @@ ENTRY(fast_alloca)
 
        /* Restore a3, excsave_1 */
 
-       xsr     a3, EXCSAVE_1           # make sure excsave_1 is valid for dbl.
-       rsr     a4, EPC_1               # get exception address
+       xsr     a3, excsave1            # make sure excsave_1 is valid for dbl.
+       rsr     a4, epc1                # get exception address
        s32i    a3, a2, PT_AREG3        # save a3 to stack
 
 #ifdef ALLOCA_EXCEPTION_IN_IRAM
@@ -820,7 +820,7 @@ ENTRY(fast_alloca)
        jx      a3
 
 .Lunhandled_double:
-       wsr     a0, EXCSAVE_1
+       wsr     a0, excsave1
        movi    a0, unrecoverable_exception
        callx0  a0
 
@@ -852,7 +852,7 @@ ENTRY(fast_alloca)
 #endif
        addi    a4, a4, 3               # step over movsp
        _EXTUI_MOVSP_DST(a0)            # extract destination register
-       wsr     a4, EPC_1               # save new epc_1
+       wsr     a4, epc1                # save new epc_1
 
        _bnei   a0, 1, 1f               # no 'movsp a1, ax': jump
 
@@ -953,14 +953,14 @@ ENTRY(fast_syscall_kernel)
 
        /* Skip syscall. */
 
-       rsr     a0, EPC_1
+       rsr     a0, epc1
        addi    a0, a0, 3
-       wsr     a0, EPC_1
+       wsr     a0, epc1
 
        l32i    a0, a2, PT_DEPC
        bgeui   a0, VALID_DOUBLE_EXCEPTION_ADDRESS, fast_syscall_unrecoverable
 
-       rsr     a0, DEPC                        # get syscall-nr
+       rsr     a0, depc                        # get syscall-nr
        _beqz   a0, fast_syscall_spill_registers
        _beqi   a0, __NR_xtensa, fast_syscall_xtensa
 
@@ -970,14 +970,14 @@ ENTRY(fast_syscall_user)
 
        /* Skip syscall. */
 
-       rsr     a0, EPC_1
+       rsr     a0, epc1
        addi    a0, a0, 3
-       wsr     a0, EPC_1
+       wsr     a0, epc1
 
        l32i    a0, a2, PT_DEPC
        bgeui   a0, VALID_DOUBLE_EXCEPTION_ADDRESS, fast_syscall_unrecoverable
 
-       rsr     a0, DEPC                        # get syscall-nr
+       rsr     a0, depc                        # get syscall-nr
        _beqz   a0, fast_syscall_spill_registers
        _beqi   a0, __NR_xtensa, fast_syscall_xtensa
 
@@ -988,10 +988,10 @@ ENTRY(fast_syscall_unrecoverable)
         /* Restore all states. */
 
         l32i    a0, a2, PT_AREG0        # restore a0
-        xsr     a2, DEPC                # restore a2, depc
-        rsr     a3, EXCSAVE_1
+        xsr     a2, depc                # restore a2, depc
+        rsr     a3, excsave1
 
-        wsr     a0, EXCSAVE_1
+        wsr     a0, excsave1
         movi    a0, unrecoverable_exception
         callx0  a0
 
@@ -1047,7 +1047,7 @@ ENTRY(fast_syscall_unrecoverable)
 
 ENTRY(fast_syscall_xtensa)
 
-       xsr     a3, EXCSAVE_1           # restore a3, excsave1
+       xsr     a3, excsave1            # restore a3, excsave1
 
        s32i    a7, a2, PT_AREG7        # we need an additional register
        movi    a7, 4                   # sizeof(unsigned int)
@@ -1124,13 +1124,13 @@ ENTRY(fast_syscall_spill_registers)
 
        movi    a0, fast_syscall_spill_registers_fixup
        s32i    a0, a3, EXC_TABLE_FIXUP
-       rsr     a0, WINDOWBASE
+       rsr     a0, windowbase
        s32i    a0, a3, EXC_TABLE_PARAM
 
        /* Save a3 and SAR on stack. */
 
-       rsr     a0, SAR
-       xsr     a3, EXCSAVE_1           # restore a3 and excsave_1
+       rsr     a0, sar
+       xsr     a3, excsave1            # restore a3 and excsave_1
        s32i    a3, a2, PT_AREG3
        s32i    a4, a2, PT_AREG4
        s32i    a0, a2, PT_AREG5        # store SAR to PT_AREG5
@@ -1148,7 +1148,7 @@ ENTRY(fast_syscall_spill_registers)
        l32i    a3, a2, PT_AREG5
        l32i    a4, a2, PT_AREG4
        l32i    a0, a2, PT_AREG0
-       wsr     a3, SAR
+       wsr     a3, sar
        l32i    a3, a2, PT_AREG3
 
        /* Restore clobbered registers. */
@@ -1173,8 +1173,8 @@ ENTRY(fast_syscall_spill_registers)
 
 fast_syscall_spill_registers_fixup:
 
-       rsr     a2, WINDOWBASE  # get current windowbase (a2 is saved)
-       xsr     a0, DEPC        # restore depc and a0
+       rsr     a2, windowbase  # get current windowbase (a2 is saved)
+       xsr     a0, depc        # restore depc and a0
        ssl     a2              # set shift (32 - WB)
 
        /* We need to make sure the current registers (a0-a3) are preserved.
@@ -1182,12 +1182,12 @@ fast_syscall_spill_registers_fixup:
         * in WS, so that the exception handlers save them to the task stack.
         */
 
-       rsr     a3, EXCSAVE_1   # get spill-mask
+       rsr     a3, excsave1    # get spill-mask
        slli    a2, a3, 1       # shift left by one
 
        slli    a3, a2, 32-WSBITS
        src     a2, a2, a3      # a1 = xxwww1yyxxxwww1yy......
-       wsr     a2, WINDOWSTART # set corrected windowstart
+       wsr     a2, windowstart # set corrected windowstart
 
        movi    a3, exc_table
        l32i    a2, a3, EXC_TABLE_DOUBLE_SAVE   # restore a2
@@ -1201,7 +1201,7 @@ fast_syscall_spill_registers_fixup:
         * excsave_1:   a3
         */
 
-       wsr     a3, WINDOWBASE
+       wsr     a3, windowbase
        rsync
 
        /* We are now in the original frame when we entered _spill_registers:
@@ -1227,7 +1227,7 @@ fast_syscall_spill_registers_fixup:
        /* Jump to the exception handler. */
 
        movi    a3, exc_table
-       rsr     a0, EXCCAUSE
+       rsr     a0, exccause
         addx4  a0, a0, a3                      # find entry in table
         l32i   a0, a0, EXC_TABLE_FAST_USER     # load handler
         jx     a0
@@ -1236,28 +1236,28 @@ fast_syscall_spill_registers_fixup_return:
 
        /* When we return here, all registers have been restored (a2: DEPC) */
 
-       wsr     a2, DEPC                # exception address
+       wsr     a2, depc                # exception address
 
        /* Restore fixup handler. */
 
-       xsr     a3, EXCSAVE_1
+       xsr     a3, excsave1
        movi    a2, fast_syscall_spill_registers_fixup
        s32i    a2, a3, EXC_TABLE_FIXUP
-       rsr     a2, WINDOWBASE
+       rsr     a2, windowbase
        s32i    a2, a3, EXC_TABLE_PARAM
        l32i    a2, a3, EXC_TABLE_KSTK
 
        /* Load WB at the time the exception occurred. */
 
-       rsr     a3, SAR                 # WB is still in SAR
+       rsr     a3, sar                 # WB is still in SAR
        neg     a3, a3
-       wsr     a3, WINDOWBASE
+       wsr     a3, windowbase
        rsync
 
        /* Restore a3 and return. */
 
        movi    a3, exc_table
-       xsr     a3, EXCSAVE_1
+       xsr     a3, excsave1
 
        rfde
 
@@ -1283,8 +1283,8 @@ ENTRY(_spill_registers)
         * Rotate ws right so that a4 = yyxxxwww1.
         */
 
-       rsr     a4, WINDOWBASE
-       rsr     a3, WINDOWSTART         # a3 = xxxwww1yy
+       rsr     a4, windowbase
+       rsr     a3, windowstart         # a3 = xxxwww1yy
        ssr     a4                      # holds WB
        slli    a4, a3, WSBITS
        or      a3, a3, a4              # a3 = xxxwww1yyxxxwww1yy
@@ -1302,7 +1302,7 @@ ENTRY(_spill_registers)
 
        /* Skip empty frames - get 'oldest' WINDOWSTART-bit. */
 
-       wsr     a3, WINDOWSTART         # save shifted windowstart
+       wsr     a3, windowstart         # save shifted windowstart
        neg     a4, a3
        and     a3, a4, a3              # first bit set from right: 000010000
 
@@ -1311,12 +1311,12 @@ ENTRY(_spill_registers)
        sub     a4, a3, a4              # WSBITS-a4:number of 0-bits from right
        ssr     a4                      # save in SAR for later.
 
-       rsr     a3, WINDOWBASE
+       rsr     a3, windowbase
        add     a3, a3, a4
-       wsr     a3, WINDOWBASE
+       wsr     a3, windowbase
        rsync
 
-       rsr     a3, WINDOWSTART
+       rsr     a3, windowstart
        srl     a3, a3                  # shift windowstart
 
        /* WB is now just one frame below the oldest frame in the register
@@ -1364,11 +1364,11 @@ ENTRY(_spill_registers)
 .Lexit: /* Done. Do the final rotation, set WS, and return. */
 
        rotw    1
-       rsr     a3, WINDOWBASE
+       rsr     a3, windowbase
        ssl     a3
        movi    a3, 1
        sll     a3, a3
-       wsr     a3, WINDOWSTART
+       wsr     a3, windowstart
        ret
 
 .Lc4:  s32e    a4, a9, -16
@@ -1429,7 +1429,7 @@ ENTRY(_spill_registers)
         * however, this condition is unrecoverable in kernel space.
         */
 
-       rsr     a0, PS
+       rsr     a0, ps
        _bbci.l a0, PS_UM_BIT, 1f
 
        /* User space: Setup a dummy frame and kill application.
@@ -1439,18 +1439,18 @@ ENTRY(_spill_registers)
        movi    a0, 1
        movi    a1, 0
 
-       wsr     a0, WINDOWSTART
-       wsr     a1, WINDOWBASE
+       wsr     a0, windowstart
+       wsr     a1, windowbase
        rsync
 
        movi    a0, 0
 
        movi    a3, exc_table
        l32i    a1, a3, EXC_TABLE_KSTK
-       wsr     a3, EXCSAVE_1
+       wsr     a3, excsave1
 
        movi    a4, (1 << PS_WOE_BIT) | 1
-       wsr     a4, PS
+       wsr     a4, ps
        rsync
 
        movi    a6, SIGSEGV
@@ -1459,7 +1459,7 @@ ENTRY(_spill_registers)
 
 1:     /* Kernel space: PANIC! */
 
-       wsr     a0, EXCSAVE_1
+       wsr     a0, excsave1
        movi    a0, unrecoverable_exception
        callx0  a0              # should not return
 1:     j       1b
@@ -1524,7 +1524,7 @@ ENTRY(fast_second_level_miss)
 
        /* We deliberately destroy a3 that holds the exception table. */
 
-8:     rsr     a3, EXCVADDR            # fault address
+8:     rsr     a3, excvaddr            # fault address
        _PGD_OFFSET(a0, a3, a1)
        l32i    a0, a0, 0               # read pmdval
        beqz    a0, 2f
@@ -1542,7 +1542,7 @@ ENTRY(fast_second_level_miss)
         * pteval = ((pmdval - PAGE_OFFSET) & PAGE_MASK) | PAGE_DIRECTORY
         */
 
-       movi    a1, -PAGE_OFFSET
+       movi    a1, (-PAGE_OFFSET) & 0xffffffff
        add     a0, a0, a1              # pmdval - PAGE_OFFSET
        extui   a1, a0, 0, PAGE_SHIFT   # ... & PAGE_MASK
        xor     a0, a0, a1
@@ -1561,7 +1561,7 @@ ENTRY(fast_second_level_miss)
         */
 
        extui   a3, a3, 28, 2           # addr. bit 28 and 29   0,1,2,3
-       rsr     a1, PTEVADDR
+       rsr     a1, ptevaddr
        addx2   a3, a3, a3              # ->                    0,3,6,9
        srli    a1, a1, PAGE_SHIFT
        extui   a3, a3, 2, 2            # ->                    0,0,1,2
@@ -1583,18 +1583,18 @@ ENTRY(fast_second_level_miss)
        l32i    a0, a2, PT_AREG0
        l32i    a1, a2, PT_AREG1
        l32i    a2, a2, PT_DEPC
-       xsr     a3, EXCSAVE_1
+       xsr     a3, excsave1
 
        bgeui   a2, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f
 
        /* Restore excsave1 and return. */
 
-       rsr     a2, DEPC
+       rsr     a2, depc
        rfe
 
        /* Return from double exception. */
 
-1:     xsr     a2, DEPC
+1:     xsr     a2, depc
        esync
        rfde
 
@@ -1618,7 +1618,7 @@ ENTRY(fast_second_level_miss)
        /* Make sure the exception originated in the special functions */
 
        movi    a0, __tlbtemp_mapping_start
-       rsr     a3, EPC_1
+       rsr     a3, epc1
        bltu    a3, a0, 2f
        movi    a0, __tlbtemp_mapping_end
        bgeu    a3, a0, 2f
@@ -1626,7 +1626,7 @@ ENTRY(fast_second_level_miss)
        /* Check if excvaddr was in one of the TLBTEMP_BASE areas. */
 
        movi    a3, TLBTEMP_BASE_1
-       rsr     a0, EXCVADDR
+       rsr     a0, excvaddr
        bltu    a0, a3, 2f
 
        addi    a1, a0, -(2 << (DCACHE_ALIAS_ORDER + PAGE_SHIFT))
@@ -1635,7 +1635,7 @@ ENTRY(fast_second_level_miss)
        /* Check if we have to restore an ITLB mapping. */
 
        movi    a1, __tlbtemp_mapping_itlb
-       rsr     a3, EPC_1
+       rsr     a3, epc1
        sub     a3, a3, a1
 
        /* Calculate VPN */
@@ -1671,13 +1671,13 @@ ENTRY(fast_second_level_miss)
 2:     /* Invalid PGD, default exception handling */
 
        movi    a3, exc_table
-       rsr     a1, DEPC
-       xsr     a3, EXCSAVE_1
+       rsr     a1, depc
+       xsr     a3, excsave1
        s32i    a1, a2, PT_AREG2
        s32i    a3, a2, PT_AREG3
        mov     a1, a2
 
-       rsr     a2, PS
+       rsr     a2, ps
        bbsi.l  a2, PS_UM_BIT, 1f
        j       _kernel_exception
 1:     j       _user_exception
@@ -1712,7 +1712,7 @@ ENTRY(fast_store_prohibited)
        l32i    a0, a1, TASK_MM         # tsk->mm
        beqz    a0, 9f
 
-8:     rsr     a1, EXCVADDR            # fault address
+8:     rsr     a1, excvaddr            # fault address
        _PGD_OFFSET(a0, a1, a4)
        l32i    a0, a0, 0
        beqz    a0, 2f
@@ -1725,7 +1725,7 @@ ENTRY(fast_store_prohibited)
 
        movi    a1, _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_HW_WRITE
        or      a4, a4, a1
-       rsr     a1, EXCVADDR
+       rsr     a1, excvaddr
        s32i    a4, a0, 0
 
        /* We need to flush the cache if we have page coloring. */
@@ -1749,15 +1749,15 @@ ENTRY(fast_store_prohibited)
 
        /* Restore excsave1 and a3. */
 
-       xsr     a3, EXCSAVE_1
+       xsr     a3, excsave1
        bgeui   a2, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f
 
-       rsr     a2, DEPC
+       rsr     a2, depc
        rfe
 
        /* Double exception. Restore FIXUP handler and return. */
 
-1:     xsr     a2, DEPC
+1:     xsr     a2, depc
        esync
        rfde
 
@@ -1766,14 +1766,14 @@ ENTRY(fast_store_prohibited)
 
 2:     /* If there was a problem, handle fault in C */
 
-       rsr     a4, DEPC        # still holds a2
-       xsr     a3, EXCSAVE_1
+       rsr     a4, depc        # still holds a2
+       xsr     a3, excsave1
        s32i    a4, a2, PT_AREG2
        s32i    a3, a2, PT_AREG3
        l32i    a4, a2, PT_AREG4
        mov     a1, a2
 
-       rsr     a2, PS
+       rsr     a2, ps
        bbsi.l  a2, PS_UM_BIT, 1f
        j       _kernel_exception
 1:     j       _user_exception
@@ -1901,8 +1901,8 @@ ENTRY(_switch_to)
        /* Disable ints while we manipulate the stack pointer. */
 
        movi    a14, (1 << PS_EXCM_BIT) | LOCKLEVEL
-       xsr     a14, PS
-       rsr     a3, EXCSAVE_1
+       xsr     a14, ps
+       rsr     a3, excsave1
        rsync
        s32i    a3, a3, EXC_TABLE_FIXUP /* enter critical section */
 
@@ -1910,7 +1910,7 @@ ENTRY(_switch_to)
 
 #if (XTENSA_HAVE_COPROCESSORS || XTENSA_HAVE_IO_PORTS)
        l32i    a3, a5, THREAD_CPENABLE
-       xsr     a3, CPENABLE
+       xsr     a3, cpenable
        s32i    a3, a4, THREAD_CPENABLE
 #endif
 
@@ -1924,7 +1924,7 @@ ENTRY(_switch_to)
         *       we return from kernel space.
         */
 
-       rsr     a3, EXCSAVE_1           # exc_table
+       rsr     a3, excsave1            # exc_table
        movi    a6, 0
        addi    a7, a5, PT_REGS_OFFSET
        s32i    a6, a3, EXC_TABLE_FIXUP
@@ -1937,7 +1937,7 @@ ENTRY(_switch_to)
 
        load_xtregs_user a5 a6 a8 a9 a10 a11 THREAD_XTREGS_USER
 
-       wsr     a14, PS
+       wsr     a14, ps
        mov     a2, a12                 # return 'prev'
        rsync
 
index 3ef91a73652d31bb943c4ca00949d05e270a8390..bdc50788f35e13e9e4d89b54e65af887f1a26610 100644 (file)
@@ -61,18 +61,18 @@ _startup:
        /* Disable interrupts and exceptions. */
 
        movi    a0, LOCKLEVEL
-       wsr     a0, PS
+       wsr     a0, ps
 
        /* Preserve the pointer to the boot parameter list in EXCSAVE_1 */
 
-       wsr     a2, EXCSAVE_1
+       wsr     a2, excsave1
 
        /* Start with a fresh windowbase and windowstart.  */
 
        movi    a1, 1
        movi    a0, 0
-       wsr     a1, WINDOWSTART
-       wsr     a0, WINDOWBASE
+       wsr     a1, windowstart
+       wsr     a0, windowbase
        rsync
 
        /* Set a0 to 0 for the remaining initialization. */
@@ -82,46 +82,46 @@ _startup:
        /* Clear debugging registers. */
 
 #if XCHAL_HAVE_DEBUG
-       wsr     a0, IBREAKENABLE
-       wsr     a0, ICOUNT
+       wsr     a0, ibreakenable
+       wsr     a0, icount
        movi    a1, 15
-       wsr     a0, ICOUNTLEVEL
+       wsr     a0, icountlevel
 
        .set    _index, 0
        .rept   XCHAL_NUM_DBREAK - 1
-       wsr     a0, DBREAKC + _index
+       wsr     a0, SREG_DBREAKC + _index
        .set    _index, _index + 1
        .endr
 #endif
 
        /* Clear CCOUNT (not really necessary, but nice) */
 
-       wsr     a0, CCOUNT      # not really necessary, but nice
+       wsr     a0, ccount      # not really necessary, but nice
 
        /* Disable zero-loops. */
 
 #if XCHAL_HAVE_LOOPS
-       wsr     a0, LCOUNT
+       wsr     a0, lcount
 #endif
 
        /* Disable all timers. */
 
        .set    _index, 0
        .rept   XCHAL_NUM_TIMERS - 1
-       wsr     a0, CCOMPARE + _index
+       wsr     a0, SREG_CCOMPARE + _index
        .set    _index, _index + 1
        .endr
 
        /* Interrupt initialization. */
 
        movi    a2, XCHAL_INTTYPE_MASK_SOFTWARE | XCHAL_INTTYPE_MASK_EXTERN_EDGE
-       wsr     a0, INTENABLE
-       wsr     a2, INTCLEAR
+       wsr     a0, intenable
+       wsr     a2, intclear
 
        /* Disable coprocessors. */
 
 #if XCHAL_CP_NUM > 0
-       wsr     a0, CPENABLE
+       wsr     a0, cpenable
 #endif
 
        /* Set PS.INTLEVEL=1, PS.WOE=0, kernel stack, PS.EXCM=0
@@ -132,7 +132,7 @@ _startup:
         */
 
        movi    a1, 1
-       wsr     a1, PS
+       wsr     a1, ps
        rsync
 
        /*  Initialize the caches.
@@ -206,18 +206,18 @@ _startup:
        addi    a1, a1, KERNEL_STACK_SIZE
 
        movi    a2, 0x00040001          # WOE=1, INTLEVEL=1, UM=0
-       wsr     a2, PS                  # (enable reg-windows; progmode stack)
+       wsr     a2, ps                  # (enable reg-windows; progmode stack)
        rsync
 
        /* Set up EXCSAVE[DEBUGLEVEL] to point to the Debug Exception Handler.*/
 
        movi    a2, debug_exception
-       wsr     a2, EXCSAVE + XCHAL_DEBUGLEVEL
+       wsr     a2, SREG_EXCSAVE + XCHAL_DEBUGLEVEL
 
        /* Set up EXCSAVE[1] to point to the exc_table. */
 
        movi    a6, exc_table
-       xsr     a6, EXCSAVE_1
+       xsr     a6, excsave1
 
        /* init_arch kick-starts the linux kernel */
 
index 98e77c3ef1c38d9e1401b7238a7a4a4c51cea460..a6ce3e563739f1b56d34eea2a0c2f770159c9f46 100644 (file)
@@ -72,13 +72,13 @@ int arch_show_interrupts(struct seq_file *p, int prec)
 static void xtensa_irq_mask(struct irq_data *d)
 {
        cached_irq_mask &= ~(1 << d->irq);
-       set_sr (cached_irq_mask, INTENABLE);
+       set_sr (cached_irq_mask, intenable);
 }
 
 static void xtensa_irq_unmask(struct irq_data *d)
 {
        cached_irq_mask |= 1 << d->irq;
-       set_sr (cached_irq_mask, INTENABLE);
+       set_sr (cached_irq_mask, intenable);
 }
 
 static void xtensa_irq_enable(struct irq_data *d)
@@ -95,7 +95,7 @@ static void xtensa_irq_disable(struct irq_data *d)
 
 static void xtensa_irq_ack(struct irq_data *d)
 {
-       set_sr(1 << d->irq, INTCLEAR);
+       set_sr(1 << d->irq, intclear);
 }
 
 static int xtensa_irq_retrigger(struct irq_data *d)
index bc020825cce55197e6aaf7dfc127203a143e3553..1908f6642d31e0073c5884b0f90445641452cb75 100644 (file)
@@ -173,6 +173,16 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
  *
  * Note: This is a pristine frame, so we don't need any spill region on top of
  *       childregs.
+ *
+ * The fun part:  if we're keeping the same VM (i.e. cloning a thread,
+ * not an entire process), we're normally given a new usp, and we CANNOT share
+ * any live address register windows.  If we just copy those live frames over,
+ * the two threads (parent and child) will overflow the same frames onto the
+ * parent stack at different times, likely corrupting the parent stack (esp.
+ * if the parent returns from functions that called clone() and calls new
+ * ones, before the child overflows its now old copies of its parent windows).
+ * One solution is to spill windows to the parent stack, but that's fairly
+ * involved.  Much simpler to just not copy those live frames across.
  */
 
 int copy_thread(unsigned long clone_flags, unsigned long usp,
@@ -180,10 +190,13 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
                 struct task_struct * p, struct pt_regs * regs)
 {
        struct pt_regs *childregs;
-       struct thread_info *ti;
        unsigned long tos;
        int user_mode = user_mode(regs);
 
+#if (XTENSA_HAVE_COPROCESSORS || XTENSA_HAVE_IO_PORTS)
+       struct thread_info *ti;
+#endif
+
        /* Set up new TSS. */
        tos = (unsigned long)task_stack_page(p) + THREAD_SIZE;
        if (user_mode)
@@ -191,13 +204,14 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
        else
                childregs = (struct pt_regs*)tos - 1;
 
+       /* This does not copy all the regs.  In a bout of brilliance or madness,
+          ARs beyond a0-a15 exist past the end of the struct. */
        *childregs = *regs;
 
        /* Create a call4 dummy-frame: a0 = 0, a1 = childregs. */
        *((int*)childregs - 3) = (unsigned long)childregs;
        *((int*)childregs - 4) = 0;
 
-       childregs->areg[1] = tos;
        childregs->areg[2] = 0;
        p->set_child_tid = p->clear_child_tid = NULL;
        p->thread.ra = MAKE_RA_FOR_CALL((unsigned long)ret_from_fork, 0x1);
@@ -205,10 +219,14 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
 
        if (user_mode(regs)) {
 
-               int len = childregs->wmask & ~0xf;
                childregs->areg[1] = usp;
-               memcpy(&childregs->areg[XCHAL_NUM_AREGS - len/4],
-                      &regs->areg[XCHAL_NUM_AREGS - len/4], len);
+               if (clone_flags & CLONE_VM) {
+                       childregs->wmask = 1;   /* can't share live windows */
+               } else {
+                       int len = childregs->wmask & ~0xf;
+                       memcpy(&childregs->areg[XCHAL_NUM_AREGS - len/4],
+                              &regs->areg[XCHAL_NUM_AREGS - len/4], len);
+               }
 // FIXME: we need to set THREADPTR in thread_info...
                if (clone_flags & CLONE_SETTLS)
                        childregs->areg[2] = childregs->areg[6];
@@ -216,6 +234,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
        } else {
                /* In kernel space, we start a new thread with a new stack. */
                childregs->wmask = 1;
+               childregs->areg[1] = tos;
        }
 
 #if (XTENSA_HAVE_COPROCESSORS || XTENSA_HAVE_IO_PORTS)
index 270360d9806ca6832d0ff7d4aeeff62dfad910c7..b237988ba6d77b789ca2766509e66fd50985c840 100644 (file)
@@ -100,7 +100,7 @@ typedef struct tagtable {
 } tagtable_t;
 
 #define __tagtable(tag, fn) static tagtable_t __tagtable_##fn          \
-       __attribute__((unused, __section__(".taglist"))) = { tag, fn }
+       __attribute__((used, section(".taglist"))) = { tag, fn }
 
 /* parse current tag */
 
@@ -120,7 +120,7 @@ static int __init parse_tag_mem(const bp_tag_t *tag)
        }
        sysmem.bank[sysmem.nr_banks].type  = mi->type;
        sysmem.bank[sysmem.nr_banks].start = PAGE_ALIGN(mi->start);
-       sysmem.bank[sysmem.nr_banks].end   = mi->end & PAGE_SIZE;
+       sysmem.bank[sysmem.nr_banks].end   = mi->end & PAGE_MASK;
        sysmem.nr_banks++;
 
        return 0;
index 05b3f093d5d7cd09435c0395cf5a20e0a07e26ec..a5c01e74d5d5590f3c5287dace8f23c10c527cd9 100644 (file)
@@ -34,7 +34,6 @@ syscall_t sys_call_table[__NR_syscall_count] /* FIXME __cacheline_aligned */= {
 
 #undef __SYSCALL
 #define __SYSCALL(nr,symbol,nargs) [ nr ] = (syscall_t)symbol,
-#undef _XTENSA_UNISTD_H
 #undef  __KERNEL_SYSCALLS__
 #include <asm/unistd.h>
 };
index bc1e14cf93692b811c09c7440c83d9309cc00834..5caf2b64d43ac846c7a0c148166c54877dec8178 100644 (file)
@@ -97,7 +97,7 @@ static dispatch_init_table_t __initdata dispatch_init_table[] = {
 /* EXCCAUSE_INTEGER_DIVIDE_BY_ZERO unhandled */
 /* EXCCAUSE_PRIVILEGED unhandled */
 #if XCHAL_UNALIGNED_LOAD_EXCEPTION || XCHAL_UNALIGNED_STORE_EXCEPTION
-#ifdef CONFIG_UNALIGNED_USER
+#ifdef CONFIG_XTENSA_UNALIGNED_USER
 { EXCCAUSE_UNALIGNED,          USER,      fast_unaligned },
 #else
 { EXCCAUSE_UNALIGNED,          0,         do_unaligned_user },
@@ -202,8 +202,8 @@ extern void do_IRQ(int, struct pt_regs *);
 
 void do_interrupt (struct pt_regs *regs)
 {
-       unsigned long intread = get_sr (INTREAD);
-       unsigned long intenable = get_sr (INTENABLE);
+       unsigned long intread = get_sr (interrupt);
+       unsigned long intenable = get_sr (intenable);
        int i, mask;
 
        /* Handle all interrupts (no priorities).
@@ -213,7 +213,7 @@ void do_interrupt (struct pt_regs *regs)
 
        for (i=0, mask = 1; i < XCHAL_NUM_INTERRUPTS; i++, mask <<= 1) {
                if (mask & (intread & intenable)) {
-                       set_sr (mask, INTCLEAR);
+                       set_sr (mask, intclear);
                        do_IRQ (i,regs);
                }
        }
@@ -244,7 +244,7 @@ do_illegal_instruction(struct pt_regs *regs)
  */
 
 #if XCHAL_UNALIGNED_LOAD_EXCEPTION || XCHAL_UNALIGNED_STORE_EXCEPTION
-#ifndef CONFIG_UNALIGNED_USER
+#ifndef CONFIG_XTENSA_UNALIGNED_USER
 void
 do_unaligned_user (struct pt_regs *regs)
 {
@@ -339,7 +339,7 @@ void __init trap_init(void)
        /* Initialize EXCSAVE_1 to hold the address of the exception table. */
 
        i = (unsigned long)exc_table;
-       __asm__ __volatile__("wsr  %0, "__stringify(EXCSAVE_1)"\n" : : "a" (i));
+       __asm__ __volatile__("wsr  %0, excsave1\n" : : "a" (i));
 }
 
 /*
@@ -386,16 +386,16 @@ static inline void spill_registers(void)
        unsigned int a0, ps;
 
        __asm__ __volatile__ (
-               "movi   a14," __stringify (PS_EXCM_BIT) " | 1\n\t"
+               "movi   a14, " __stringify(PS_EXCM_BIT | 1) "\n\t"
                "mov    a12, a0\n\t"
-               "rsr    a13," __stringify(SAR) "\n\t"
-               "xsr    a14," __stringify(PS) "\n\t"
+               "rsr    a13, sar\n\t"
+               "xsr    a14, ps\n\t"
                "movi   a0, _spill_registers\n\t"
                "rsync\n\t"
                "callx0 a0\n\t"
                "mov    a0, a12\n\t"
-               "wsr    a13," __stringify(SAR) "\n\t"
-               "wsr    a14," __stringify(PS) "\n\t"
+               "wsr    a13, sar\n\t"
+               "wsr    a14, ps\n\t"
                :: "a" (&a0), "a" (&ps)
                : "a2", "a3", "a4", "a7", "a11", "a12", "a13", "a14", "a15", "memory");
 }
index 70066e3582d0b878f427832f56d5f983fc5e11bb..4462c1e595c2b1ed87f772e11335561ed1885d6d 100644 (file)
 
 ENTRY(_UserExceptionVector)
 
-       xsr     a3, EXCSAVE_1           # save a3 and get dispatch table
-       wsr     a2, DEPC                # save a2
+       xsr     a3, excsave1            # save a3 and get dispatch table
+       wsr     a2, depc                # save a2
        l32i    a2, a3, EXC_TABLE_KSTK  # load kernel stack to a2
        s32i    a0, a2, PT_AREG0        # save a0 to ESF
-       rsr     a0, EXCCAUSE            # retrieve exception cause
+       rsr     a0, exccause            # retrieve exception cause
        s32i    a0, a2, PT_DEPC         # mark it as a regular exception
        addx4   a0, a0, a3              # find entry in table
        l32i    a0, a0, EXC_TABLE_FAST_USER     # load handler
@@ -93,11 +93,11 @@ ENTRY(_UserExceptionVector)
 
 ENTRY(_KernelExceptionVector)
 
-       xsr     a3, EXCSAVE_1           # save a3, and get dispatch table
-       wsr     a2, DEPC                # save a2
+       xsr     a3, excsave1            # save a3, and get dispatch table
+       wsr     a2, depc                # save a2
        addi    a2, a1, -16-PT_SIZE     # adjust stack pointer
        s32i    a0, a2, PT_AREG0        # save a0 to ESF
-       rsr     a0, EXCCAUSE            # retrieve exception cause
+       rsr     a0, exccause            # retrieve exception cause
        s32i    a0, a2, PT_DEPC         # mark it as a regular exception
        addx4   a0, a0, a3              # find entry in table
        l32i    a0, a0, EXC_TABLE_FAST_KERNEL   # load handler address
@@ -205,17 +205,17 @@ ENTRY(_DoubleExceptionVector)
 
        /* Deliberately destroy excsave (don't assume it's value was valid). */
 
-       wsr     a3, EXCSAVE_1           # save a3
+       wsr     a3, excsave1            # save a3
 
        /* Check for kernel double exception (usually fatal). */
 
-       rsr     a3, PS
+       rsr     a3, ps
        _bbci.l a3, PS_UM_BIT, .Lksp
 
        /* Check if we are currently handling a window exception. */
        /* Note: We don't need to indicate that we enter a critical section. */
 
-       xsr     a0, DEPC                # get DEPC, save a0
+       xsr     a0, depc                # get DEPC, save a0
 
        movi    a3, XCHAL_WINDOW_VECTORS_VADDR
        _bltu   a0, a3, .Lfixup
@@ -243,21 +243,21 @@ ENTRY(_DoubleExceptionVector)
         * Note: We can trash the current window frame (a0...a3) and depc!
         */
 
-       wsr     a2, DEPC                # save stack pointer temporarily
-       rsr     a0, PS
+       wsr     a2, depc                # save stack pointer temporarily
+       rsr     a0, ps
        extui   a0, a0, PS_OWB_SHIFT, 4
-       wsr     a0, WINDOWBASE
+       wsr     a0, windowbase
        rsync
 
        /* We are now in the previous window frame. Save registers again. */
 
-       xsr     a2, DEPC                # save a2 and get stack pointer
+       xsr     a2, depc                # save a2 and get stack pointer
        s32i    a0, a2, PT_AREG0
 
-       wsr     a3, EXCSAVE_1           # save a3
+       wsr     a3, excsave1            # save a3
        movi    a3, exc_table
 
-       rsr     a0, EXCCAUSE
+       rsr     a0, exccause
        s32i    a0, a2, PT_DEPC         # mark it as a regular exception
        addx4   a0, a0, a3
        l32i    a0, a0, EXC_TABLE_FAST_USER
@@ -290,14 +290,14 @@ ENTRY(_DoubleExceptionVector)
 
        /* a0: depc, a1: a1, a2: kstk, a3: a2, depc: a0, excsave: a3 */
 
-       xsr     a3, DEPC
+       xsr     a3, depc
        s32i    a0, a2, PT_DEPC
        s32i    a3, a2, PT_AREG0
 
        /* a0: avail, a1: a1, a2: kstk, a3: avail, depc: a2, excsave: a3 */
 
        movi    a3, exc_table
-       rsr     a0, EXCCAUSE
+       rsr     a0, exccause
        addx4   a0, a0, a3
        l32i    a0, a0, EXC_TABLE_FAST_USER
        jx      a0
@@ -312,7 +312,7 @@ ENTRY(_DoubleExceptionVector)
 
 .Lksp: /* a0: a0, a1: a1, a2: a2, a3: trashed, depc: depc, excsave: a3 */
 
-       rsr     a3, EXCCAUSE
+       rsr     a3, exccause
        beqi    a3, EXCCAUSE_ITLB_MISS, 1f
        addi    a3, a3, -EXCCAUSE_DTLB_MISS
        bnez    a3, .Lunrecoverable
@@ -328,11 +328,11 @@ ENTRY(_DoubleExceptionVector)
 
 .Lunrecoverable_fixup:
        l32i    a2, a3, EXC_TABLE_DOUBLE_SAVE
-       xsr     a0, DEPC
+       xsr     a0, depc
 
 .Lunrecoverable:
-       rsr     a3, EXCSAVE_1
-       wsr     a0, EXCSAVE_1
+       rsr     a3, excsave1
+       wsr     a0, excsave1
        movi    a0, unrecoverable_exception
        callx0  a0
 
@@ -349,7 +349,7 @@ ENTRY(_DoubleExceptionVector)
        .section .DebugInterruptVector.text, "ax"
 
 ENTRY(_DebugInterruptVector)
-       xsr     a0, EXCSAVE + XCHAL_DEBUGLEVEL
+       xsr     a0, SREG_EXCSAVE + XCHAL_DEBUGLEVEL
        jx      a0
 
 
index ea59dcd038666da7af3004c68da1eb7d9964d9dd..c48b80acb5f014813c9d509f425e95e4f3b872e0 100644 (file)
@@ -6,7 +6,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 2002 - 2005 Tensilica Inc.
+ * Copyright (C) 2002 - 2012 Tensilica Inc.
  */
 
 #include <variant/core.h>
 #endif
        .endm
 
-
 /*
  * void *memcpy(void *dst, const void *src, size_t len);
- * void *memmove(void *dst, const void *src, size_t len);
- * void *bcopy(const void *src, void *dst, size_t len);
  *
  * This function is intended to do the same thing as the standard
- * library function memcpy() (or bcopy()) for most cases.
+ * library function memcpy() for most cases.
  * However, where the source and/or destination references
  * an instruction RAM or ROM or a data RAM or ROM, that
  * source and/or destination will always be accessed with
@@ -45,9 +42,6 @@
  * !!!!!!!  Handling of IRAM/IROM has not yet
  * !!!!!!!  been implemented.
  *
- * The bcopy version is provided here to avoid the overhead
- * of an extra call, for callers that require this convention.
- *
  * The (general case) algorithm is as follows:
  *   If destination is unaligned, align it by conditionally
  *     copying 1 and 2 bytes.
  */
 
        .text
-       .align  4
-       .global bcopy
-       .type   bcopy,@function
-bcopy:
-       entry   sp, 16          # minimal stack frame
-       # a2=src, a3=dst, a4=len
-       mov     a5, a3          # copy dst so that a2 is return value
-       mov     a3, a2
-       mov     a2, a5
-       j       .Lcommon        # go to common code for memcpy+bcopy
-
 
 /*
  * Byte by byte copy
@@ -107,7 +90,7 @@ bcopy:
        s8i     a6, a5, 0
        addi    a5, a5, 1
 #if !XCHAL_HAVE_LOOPS
-       blt     a3, a7, .Lnextbyte
+       bne     a3, a7, .Lnextbyte # continue loop if $a3:src != $a7:src_end
 #endif /* !XCHAL_HAVE_LOOPS */
 .Lbytecopydone:
        retw
@@ -144,9 +127,6 @@ bcopy:
        .global memcpy
        .type   memcpy,@function
 memcpy:
-       .global memmove
-       .type   memmove,@function
-memmove:
 
        entry   sp, 16          # minimal stack frame
        # a2/ dst, a3/ src, a4/ len
@@ -182,7 +162,7 @@ memmove:
        s32i    a7, a5, 12
        addi    a5, a5, 16
 #if !XCHAL_HAVE_LOOPS
-       blt     a3, a8, .Loop1
+       bne     a3, a8, .Loop1  # continue loop if a3:src != a8:src_end
 #endif /* !XCHAL_HAVE_LOOPS */
 .Loop1done:
        bbci.l  a4, 3, .L2
@@ -260,7 +240,7 @@ memmove:
        s32i    a9, a5, 12
        addi    a5, a5, 16
 #if !XCHAL_HAVE_LOOPS
-       blt     a3, a10, .Loop2
+       bne     a3, a10, .Loop2 # continue loop if a3:src != a10:src_end
 #endif /* !XCHAL_HAVE_LOOPS */
 .Loop2done:
        bbci.l  a4, 3, .L12
@@ -305,6 +285,285 @@ memmove:
        l8ui    a6, a3,  0
        s8i     a6, a5,  0
        retw
+
+
+/*
+ * void bcopy(const void *src, void *dest, size_t n);
+ */
+       .align  4
+       .global bcopy
+       .type   bcopy,@function
+bcopy:
+       entry   sp, 16          # minimal stack frame
+       # a2=src, a3=dst, a4=len
+       mov     a5, a3
+       mov     a3, a2
+       mov     a2, a5
+       j       .Lmovecommon    # go to common code for memmove+bcopy
+
+/*
+ * void *memmove(void *dst, const void *src, size_t len);
+ *
+ * This function is intended to do the same thing as the standard
+ * library function memmove() for most cases.
+ * However, where the source and/or destination references
+ * an instruction RAM or ROM or a data RAM or ROM, that
+ * source and/or destination will always be accessed with
+ * 32-bit load and store instructions (as required for these
+ * types of devices).
+ *
+ * !!!!!!!  XTFIXME:
+ * !!!!!!!  Handling of IRAM/IROM has not yet
+ * !!!!!!!  been implemented.
+ *
+ * The (general case) algorithm is as follows:
+ *   If end of source doesn't overlap destination then use memcpy.
+ *   Otherwise do memcpy backwards.
+ *
+ * Register use:
+ *     a0/ return address
+ *     a1/ stack pointer
+ *     a2/ return value
+ *     a3/ src
+ *     a4/ length
+ *     a5/ dst
+ *     a6/ tmp
+ *     a7/ tmp
+ *     a8/ tmp
+ *     a9/ tmp
+ *     a10/ tmp
+ *     a11/ tmp
+ */
+
+/*
+ * Byte by byte copy
+ */
+       .align  4
+       .byte   0               # 1 mod 4 alignment for LOOPNEZ
+                               # (0 mod 4 alignment for LBEG)
+.Lbackbytecopy:
+#if XCHAL_HAVE_LOOPS
+       loopnez a4, .Lbackbytecopydone
+#else /* !XCHAL_HAVE_LOOPS */
+       beqz    a4, .Lbackbytecopydone
+       sub     a7, a3, a4      # a7 = start address for source
+#endif /* !XCHAL_HAVE_LOOPS */
+.Lbacknextbyte:
+       addi    a3, a3, -1
+       l8ui    a6, a3, 0
+       addi    a5, a5, -1
+       s8i     a6, a5, 0
+#if !XCHAL_HAVE_LOOPS
+       bne     a3, a7, .Lbacknextbyte # continue loop if
+                                      # $a3:src != $a7:src_start
+#endif /* !XCHAL_HAVE_LOOPS */
+.Lbackbytecopydone:
+       retw
+
+/*
+ * Destination is unaligned
+ */
+
+       .align  4
+.Lbackdst1mod2:        # dst is only byte aligned
+       _bltui  a4, 7, .Lbackbytecopy   # do short copies byte by byte
+
+       # copy 1 byte
+       addi    a3, a3, -1
+       l8ui    a6, a3,  0
+       addi    a5, a5, -1
+       s8i     a6, a5,  0
+       addi    a4, a4, -1
+       _bbci.l a5, 1, .Lbackdstaligned # if dst is now aligned, then
+                                       # return to main algorithm
+.Lbackdst2mod4:        # dst 16-bit aligned
+       # copy 2 bytes
+       _bltui  a4, 6, .Lbackbytecopy   # do short copies byte by byte
+       addi    a3, a3, -2
+       l8ui    a6, a3,  0
+       l8ui    a7, a3,  1
+       addi    a5, a5, -2
+       s8i     a6, a5,  0
+       s8i     a7, a5,  1
+       addi    a4, a4, -2
+       j       .Lbackdstaligned        # dst is now aligned,
+                                       # return to main algorithm
+
+       .align  4
+       .global memmove
+       .type   memmove,@function
+memmove:
+
+       entry   sp, 16          # minimal stack frame
+       # a2/ dst, a3/ src, a4/ len
+       mov     a5, a2          # copy dst so that a2 is return value
+.Lmovecommon:
+       sub     a6, a5, a3
+       bgeu    a6, a4, .Lcommon
+
+       add     a5, a5, a4
+       add     a3, a3, a4
+
+       _bbsi.l a5, 0, .Lbackdst1mod2   # if dst is 1 mod 2
+       _bbsi.l a5, 1, .Lbackdst2mod4   # if dst is 2 mod 4
+.Lbackdstaligned:      # return here from .Lbackdst?mod? once dst is aligned
+       srli    a7, a4, 4       # number of loop iterations with 16B
+                               # per iteration
+       movi    a8, 3           # if source is not aligned,
+       _bany   a3, a8, .Lbacksrcunaligned      # then use shifting copy
+       /*
+        * Destination and source are word-aligned, use word copy.
+        */
+       # copy 16 bytes per iteration for word-aligned dst and word-aligned src
+#if XCHAL_HAVE_LOOPS
+       loopnez a7, .backLoop1done
+#else /* !XCHAL_HAVE_LOOPS */
+       beqz    a7, .backLoop1done
+       slli    a8, a7, 4
+       sub     a8, a3, a8      # a8 = start of first 16B source chunk
+#endif /* !XCHAL_HAVE_LOOPS */
+.backLoop1:
+       addi    a3, a3, -16
+       l32i    a7, a3, 12
+       l32i    a6, a3,  8
+       addi    a5, a5, -16
+       s32i    a7, a5, 12
+       l32i    a7, a3,  4
+       s32i    a6, a5,  8
+       l32i    a6, a3,  0
+       s32i    a7, a5,  4
+       s32i    a6, a5,  0
+#if !XCHAL_HAVE_LOOPS
+       bne     a3, a8, .backLoop1  # continue loop if a3:src != a8:src_start
+#endif /* !XCHAL_HAVE_LOOPS */
+.backLoop1done:
+       bbci.l  a4, 3, .Lback2
+       # copy 8 bytes
+       addi    a3, a3, -8
+       l32i    a6, a3,  0
+       l32i    a7, a3,  4
+       addi    a5, a5, -8
+       s32i    a6, a5,  0
+       s32i    a7, a5,  4
+.Lback2:
+       bbsi.l  a4, 2, .Lback3
+       bbsi.l  a4, 1, .Lback4
+       bbsi.l  a4, 0, .Lback5
+       retw
+.Lback3:
+       # copy 4 bytes
+       addi    a3, a3, -4
+       l32i    a6, a3,  0
+       addi    a5, a5, -4
+       s32i    a6, a5,  0
+       bbsi.l  a4, 1, .Lback4
+       bbsi.l  a4, 0, .Lback5
+       retw
+.Lback4:
+       # copy 2 bytes
+       addi    a3, a3, -2
+       l16ui   a6, a3,  0
+       addi    a5, a5, -2
+       s16i    a6, a5,  0
+       bbsi.l  a4, 0, .Lback5
+       retw
+.Lback5:
+       # copy 1 byte
+       addi    a3, a3, -1
+       l8ui    a6, a3,  0
+       addi    a5, a5, -1
+       s8i     a6, a5,  0
+       retw
+
+/*
+ * Destination is aligned, Source is unaligned
+ */
+
+       .align  4
+.Lbacksrcunaligned:
+       _beqz   a4, .Lbackdone  # avoid loading anything for zero-length copies
+       # copy 16 bytes per iteration for word-aligned dst and unaligned src
+       ssa8    a3              # set shift amount from byte offset
+#define SIM_CHECKS_ALIGNMENT   1       /* set to 1 when running on ISS with
+                                        * the lint or ferret client, or 0
+                                        * to save a few cycles */
+#if XCHAL_UNALIGNED_LOAD_EXCEPTION || SIM_CHECKS_ALIGNMENT
+       and     a11, a3, a8     # save unalignment offset for below
+       sub     a3, a3, a11     # align a3
+#endif
+       l32i    a6, a3, 0       # load first word
+#if XCHAL_HAVE_LOOPS
+       loopnez a7, .backLoop2done
+#else /* !XCHAL_HAVE_LOOPS */
+       beqz    a7, .backLoop2done
+       slli    a10, a7, 4
+       sub     a10, a3, a10    # a10 = start of first 16B source chunk
+#endif /* !XCHAL_HAVE_LOOPS */
+.backLoop2:
+       addi    a3, a3, -16
+       l32i    a7, a3, 12
+       l32i    a8, a3,  8
+       addi    a5, a5, -16
+       src_b   a6, a7, a6
+       s32i    a6, a5, 12
+       l32i    a9, a3,  4
+       src_b   a7, a8, a7
+       s32i    a7, a5,  8
+       l32i    a6, a3,  0
+       src_b   a8, a9, a8
+       s32i    a8, a5,  4
+       src_b   a9, a6, a9
+       s32i    a9, a5,  0
+#if !XCHAL_HAVE_LOOPS
+       bne     a3, a10, .backLoop2 # continue loop if a3:src != a10:src_start
+#endif /* !XCHAL_HAVE_LOOPS */
+.backLoop2done:
+       bbci.l  a4, 3, .Lback12
+       # copy 8 bytes
+       addi    a3, a3, -8
+       l32i    a7, a3,  4
+       l32i    a8, a3,  0
+       addi    a5, a5, -8
+       src_b   a6, a7, a6
+       s32i    a6, a5,  4
+       src_b   a7, a8, a7
+       s32i    a7, a5,  0
+       mov     a6, a8
+.Lback12:
+       bbci.l  a4, 2, .Lback13
+       # copy 4 bytes
+       addi    a3, a3, -4
+       l32i    a7, a3,  0
+       addi    a5, a5, -4
+       src_b   a6, a7, a6
+       s32i    a6, a5,  0
+       mov     a6, a7
+.Lback13:
+#if XCHAL_UNALIGNED_LOAD_EXCEPTION || SIM_CHECKS_ALIGNMENT
+       add     a3, a3, a11     # readjust a3 with correct misalignment
+#endif
+       bbsi.l  a4, 1, .Lback14
+       bbsi.l  a4, 0, .Lback15
+.Lbackdone:
+       retw
+.Lback14:
+       # copy 2 bytes
+       addi    a3, a3, -2
+       l8ui    a6, a3,  0
+       l8ui    a7, a3,  1
+       addi    a5, a5, -2
+       s8i     a6, a5,  0
+       s8i     a7, a5,  1
+       bbsi.l  a4, 0, .Lback15
+       retw
+.Lback15:
+       # copy 1 byte
+       addi    a3, a3, -1
+       addi    a5, a5, -1
+       l8ui    a6, a3,  0
+       s8i     a6, a5,  0
+       retw
+
 \f
 /*
  * Local Variables:
index 2c2f710ed1dc905a8c9e0509d36cd76ed073e0ce..245b08f7eaf4bb98fd3a731c7f6d329214a5b55a 100644 (file)
@@ -6,7 +6,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 2001 - 2005 Tensilica Inc.
+ * Copyright (C) 2001 - 2010 Tensilica Inc.
  *
  * Chris Zankel <chris@zankel.net>
  * Joe Taylor  <joe@tensilica.com, joetylr@yahoo.com>
@@ -186,6 +186,7 @@ do_sigbus:
        /* Kernel mode? Handle exceptions or die */
        if (!user_mode(regs))
                bad_page_fault(regs, address, SIGBUS);
+       return;
 
 vmalloc_fault:
        {
index 8ab47edd7c82b677a5d893391d4f340454c1cb48..7e74895eee04c8e17333d159998ce0cc0b10cccb 100644 (file)
@@ -91,7 +91,7 @@ static int rs_write(struct tty_struct * tty,
 {
        /* see drivers/char/serialX.c to reference original version */
 
-       __simc (SYS_write, 1, (unsigned long)buf, count, 0, 0);
+       simc_write(1, buf, count);
        return count;
 }
 
@@ -122,12 +122,7 @@ static void rs_poll(unsigned long priv)
 
 static int rs_put_char(struct tty_struct *tty, unsigned char ch)
 {
-       char buf[2];
-
-       buf[0] = ch;
-       buf[1] = '\0';          /* Is this NULL necessary? */
-       __simc (SYS_write, 1, (unsigned long) buf, 1, 0, 0);
-       return 1;
+       return rs_write(tty, &ch, 1);
 }
 
 static void rs_flush_chars(struct tty_struct *tty)
index 8c43bfea05e1e6257ad37f53f6eb12c4aaf45b85..bd78192e2fc9e61e72dbd8c38eda423598c6e2bb 100644 (file)
@@ -78,8 +78,9 @@ static inline int __simc(int a, int b, int c, int d, int e, int f)
        return ret;
 }
 
-static inline int simc_open(char *file, int flags, int mode)
+static inline int simc_open(const char *file, int flags, int mode)
 {
+       wmb();
        return __simc(SYS_open, (int) file, flags, mode, 0, 0);
 }
 
@@ -90,16 +91,19 @@ static inline int simc_close(int fd)
 
 static inline int simc_ioctl(int fd, int request, void *arg)
 {
+       wmb();
        return __simc(SYS_ioctl, fd, request, (int) arg, 0, 0);
 }
 
 static inline int simc_read(int fd, void *buf, size_t count)
 {
+       rmb();
        return __simc(SYS_read, fd, (int) buf, count, 0, 0);
 }
 
-static inline int simc_write(int fd, void *buf, size_t count)
+static inline int simc_write(int fd, const void *buf, size_t count)
 {
+       wmb();
        return __simc(SYS_write, fd, (int) buf, count, 0, 0);
 }
 
@@ -107,6 +111,7 @@ static inline int simc_poll(int fd)
 {
        struct timeval tv = { .tv_sec = 0, .tv_usec = 0 };
 
+       wmb();
        return __simc(SYS_select_one, fd, XTISS_SELECT_ONE_READ, (int)&tv,
                        0, 0);
 }
index 927acf378ea35e3bb6364bfb78cfc1347f829ecb..e1700102f35ee8039d66661250f1a41ca26fc5d0 100644 (file)
@@ -61,13 +61,13 @@ void platform_restart(void)
         * jump to the reset vector. */
 
        __asm__ __volatile__("movi      a2, 15\n\t"
-                            "wsr       a2, " __stringify(ICOUNTLEVEL) "\n\t"
+                            "wsr       a2, icountlevel\n\t"
                             "movi      a2, 0\n\t"
-                            "wsr       a2, " __stringify(ICOUNT) "\n\t"
-                            "wsr       a2, " __stringify(IBREAKENABLE) "\n\t"
-                            "wsr       a2, " __stringify(LCOUNT) "\n\t"
+                            "wsr       a2, icount\n\t"
+                            "wsr       a2, ibreakenable\n\t"
+                            "wsr       a2, lcount\n\t"
                             "movi      a2, 0x1f\n\t"
-                            "wsr       a2, " __stringify(PS) "\n\t"
+                            "wsr       a2, ps\n\t"
                             "isync\n\t"
                             "jx        %0\n\t"
                             :
index 9e83940ac26577f3f60c92784b6bb482f98f736e..c7d90f17886e1fd86a1fc17df51bab8cbd2c939d 100644 (file)
@@ -66,13 +66,13 @@ void platform_restart(void)
         * jump to the reset vector. */
 
        __asm__ __volatile__ ("movi     a2, 15\n\t"
-                             "wsr      a2, " __stringify(ICOUNTLEVEL) "\n\t"
+                             "wsr      a2, icountlevel\n\t"
                              "movi     a2, 0\n\t"
-                             "wsr      a2, " __stringify(ICOUNT) "\n\t"
-                             "wsr      a2, " __stringify(IBREAKENABLE) "\n\t"
-                             "wsr      a2, " __stringify(LCOUNT) "\n\t"
+                             "wsr      a2, icount\n\t"
+                             "wsr      a2, ibreakenable\n\t"
+                             "wsr      a2, lcount\n\t"
                              "movi     a2, 0x1f\n\t"
-                             "wsr      a2, " __stringify(PS) "\n\t"
+                             "wsr      a2, ps\n\t"
                              "isync\n\t"
                              "jx       %0\n\t"
                              :
index a33870b1847bb70c6ef1937f7bef4e93bdf9c980..b421289928edcb80a655e36dc0c394f4a11e9957 100644 (file)
@@ -40,6 +40,7 @@
 EXPORT_TRACEPOINT_SYMBOL_GPL(block_bio_remap);
 EXPORT_TRACEPOINT_SYMBOL_GPL(block_rq_remap);
 EXPORT_TRACEPOINT_SYMBOL_GPL(block_bio_complete);
+EXPORT_TRACEPOINT_SYMBOL_GPL(block_unplug);
 
 DEFINE_IDA(blk_queue_ida);
 
index 6cace663a80e4a89492f8b656f580a944b134f9d..8f29a0b9032e37eb83d61cbd4f4c9585591ab2b6 100644 (file)
@@ -587,8 +587,6 @@ void add_disk(struct gendisk *disk)
        WARN_ON(disk->minors && !(disk->major || disk->first_minor));
        WARN_ON(!disk->minors && !(disk->flags & GENHD_FL_EXT_DEVT));
 
-       disk->flags |= GENHD_FL_UP;
-
        retval = blk_alloc_devt(&disk->part0, &devt);
        if (retval) {
                WARN_ON(1);
@@ -596,6 +594,8 @@ void add_disk(struct gendisk *disk)
        }
        disk_to_dev(disk)->devt = devt;
 
+       disk->flags |= GENHD_FL_UP;
+
        /* ->major and ->first_minor aren't supposed to be
         * dereferenced from here on, but set them just in case.
         */
@@ -1105,7 +1105,7 @@ static void disk_release(struct device *dev)
        disk_replace_part_tbl(disk, NULL);
        free_part_stats(&disk->part0);
        free_part_info(&disk->part0);
-       if (disk->queue)
+       if (disk->queue && disk->flags & GENHD_FL_UP)
                blk_put_queue(disk->queue);
        kfree(disk);
 }
index 6563366bae809f8e5b052e003ad42c6c2f2adb33..b901b590635f1b5ca7f44b1270db837cfee746ca 100644 (file)
@@ -324,9 +324,19 @@ config CRYPTO_CRC32C
          by iSCSI for header and data digests and by others.
          See Castagnoli93.  Module will be crc32c.
 
+config CRYPTO_CRC32C_X86_64
+       bool
+       depends on X86 && 64BIT
+       select CRYPTO_HASH
+       help
+         In Intel processor with SSE4.2 supported, the processor will
+         support CRC32C calculation using hardware accelerated CRC32
+         instruction optimized with PCLMULQDQ instruction when available.
+
 config CRYPTO_CRC32C_INTEL
        tristate "CRC32c INTEL hardware acceleration"
        depends on X86
+       select CRYPTO_CRC32C_X86_64 if 64BIT
        select CRYPTO_HASH
        help
          In Intel processor with SSE4.2 supported, the processor will
index 671d4d6d14df106b3b0278364340ef3290d7a185..7bdd61b867c899901ed846ed5a229bc6ab31653b 100644 (file)
@@ -137,13 +137,18 @@ static void cryptd_queue_worker(struct work_struct *work)
        struct crypto_async_request *req, *backlog;
 
        cpu_queue = container_of(work, struct cryptd_cpu_queue, work);
-       /* Only handle one request at a time to avoid hogging crypto
-        * workqueue. preempt_disable/enable is used to prevent
-        * being preempted by cryptd_enqueue_request() */
+       /*
+        * Only handle one request at a time to avoid hogging crypto workqueue.
+        * preempt_disable/enable is used to prevent being preempted by
+        * cryptd_enqueue_request(). local_bh_disable/enable is used to prevent
+        * cryptd_enqueue_request() being accessed from software interrupts.
+        */
+       local_bh_disable();
        preempt_disable();
        backlog = crypto_get_backlog(&cpu_queue->queue);
        req = crypto_dequeue_request(&cpu_queue->queue);
        preempt_enable();
+       local_bh_enable();
 
        if (!req)
                return;
index e87fa60f58311f4d471686009f500087afae9ce5..71b58c6e5c18eb3836e8d66af463b75978478d06 100644 (file)
@@ -971,11 +971,13 @@ static int do_test(int m)
        case 3:
                ret += tcrypt_test("ecb(des)");
                ret += tcrypt_test("cbc(des)");
+               ret += tcrypt_test("ctr(des)");
                break;
 
        case 4:
                ret += tcrypt_test("ecb(des3_ede)");
                ret += tcrypt_test("cbc(des3_ede)");
+               ret += tcrypt_test("ctr(des3_ede)");
                break;
 
        case 5:
@@ -1479,6 +1481,10 @@ static int do_test(int m)
                test_hash_speed("ghash-generic", sec, hash_speed_template_16);
                if (mode > 300 && mode < 400) break;
 
+       case 319:
+               test_hash_speed("crc32c", sec, generic_hash_speed_template);
+               if (mode > 300 && mode < 400) break;
+
        case 399:
                break;
 
index 941d75cd1f7cd918ef2ef1b436854cd9ec7abb03..879b61d436e9753b4ac30b28e0158922fc111fde 100644 (file)
@@ -2335,6 +2335,36 @@ static const struct alg_test_desc alg_test_descs[] = {
                                }
                        }
                }
+       }, {
+               .alg = "ctr(des)",
+               .test = alg_test_skcipher,
+               .suite = {
+                       .cipher = {
+                               .enc = {
+                                       .vecs = des_ctr_enc_tv_template,
+                                       .count = DES_CTR_ENC_TEST_VECTORS
+                               },
+                               .dec = {
+                                       .vecs = des_ctr_dec_tv_template,
+                                       .count = DES_CTR_DEC_TEST_VECTORS
+                               }
+                       }
+               }
+       }, {
+               .alg = "ctr(des3_ede)",
+               .test = alg_test_skcipher,
+               .suite = {
+                       .cipher = {
+                               .enc = {
+                                       .vecs = des3_ede_ctr_enc_tv_template,
+                                       .count = DES3_EDE_CTR_ENC_TEST_VECTORS
+                               },
+                               .dec = {
+                                       .vecs = des3_ede_ctr_dec_tv_template,
+                                       .count = DES3_EDE_CTR_DEC_TEST_VECTORS
+                               }
+                       }
+               }
        }, {
                .alg = "ctr(serpent)",
                .test = alg_test_skcipher,
index 76d7f6cc82f554f8be2846b393846218f5c9a587..17db4a9c7265a3092bbf6b04c187248f28c94796 100644 (file)
@@ -1707,7 +1707,7 @@ static struct hash_testvec aes_xcbc128_tv_template[] = {
        }
 };
 
-#define VMAC_AES_TEST_VECTORS  8
+#define VMAC_AES_TEST_VECTORS  11
 static char vmac_string1[128] = {'\x01', '\x01', '\x01', '\x01',
                                '\x02', '\x03', '\x02', '\x02',
                                '\x02', '\x04', '\x01', '\x07',
@@ -1723,6 +1723,19 @@ static char vmac_string3[128] = {'a', 'b', 'c', 'a', 'b', 'c',
                                'a', 'b', 'c', 'a', 'b', 'c',
                                };
 
+static char vmac_string4[17] = {'b', 'c', 'e', 'f',
+                               'i', 'j', 'l', 'm',
+                               'o', 'p', 'r', 's',
+                               't', 'u', 'w', 'x', 'z'};
+
+static char vmac_string5[127] = {'r', 'm', 'b', 't', 'c',
+                                'o', 'l', 'k', ']', '%',
+                                '9', '2', '7', '!', 'A'};
+
+static char vmac_string6[129] = {'p', 't', '*', '7', 'l',
+                                'i', '!', '#', 'w', '0',
+                                'z', '/', '4', 'A', 'n'};
+
 static struct hash_testvec aes_vmac128_tv_template[] = {
        {
                .key    = "\x00\x01\x02\x03\x04\x05\x06\x07"
@@ -1776,6 +1789,24 @@ static struct hash_testvec aes_vmac128_tv_template[] = {
                .digest = "\x8b\x32\x8f\xe1\xed\x8f\xfa\xd4",
                .psize  = 128,
                .ksize  = 16,
+       }, {
+               .key = "a09b5cd!f#07K\x00\x00\x00",
+               .plaintext = vmac_string4,
+               .digest = "\xab\xa5\x0f\xea\x42\x4e\xa1\x5f",
+               .psize = sizeof(vmac_string4),
+               .ksize = 16,
+       }, {
+               .key = "a09b5cd!f#07K\x00\x00\x00",
+               .plaintext = vmac_string5,
+               .digest = "\x25\x31\x98\xbc\x1d\xe8\x67\x60",
+               .psize = sizeof(vmac_string5),
+               .ksize = 16,
+       }, {
+               .key = "a09b5cd!f#07K\x00\x00\x00",
+               .plaintext = vmac_string6,
+               .digest = "\xc4\xae\x9b\x47\x95\x65\xeb\x41",
+               .psize = sizeof(vmac_string6),
+               .ksize = 16,
        },
 };
 
@@ -1993,14 +2024,18 @@ static struct hash_testvec hmac_sha512_tv_template[] = {
 /*
  * DES test vectors.
  */
-#define DES_ENC_TEST_VECTORS           10
-#define DES_DEC_TEST_VECTORS           4
-#define DES_CBC_ENC_TEST_VECTORS       5
-#define DES_CBC_DEC_TEST_VECTORS       4
-#define DES3_EDE_ENC_TEST_VECTORS      3
-#define DES3_EDE_DEC_TEST_VECTORS      3
-#define DES3_EDE_CBC_ENC_TEST_VECTORS  1
-#define DES3_EDE_CBC_DEC_TEST_VECTORS  1
+#define DES_ENC_TEST_VECTORS           11
+#define DES_DEC_TEST_VECTORS           5
+#define DES_CBC_ENC_TEST_VECTORS       6
+#define DES_CBC_DEC_TEST_VECTORS       5
+#define DES_CTR_ENC_TEST_VECTORS       2
+#define DES_CTR_DEC_TEST_VECTORS       2
+#define DES3_EDE_ENC_TEST_VECTORS      4
+#define DES3_EDE_DEC_TEST_VECTORS      4
+#define DES3_EDE_CBC_ENC_TEST_VECTORS  2
+#define DES3_EDE_CBC_DEC_TEST_VECTORS  2
+#define DES3_EDE_CTR_ENC_TEST_VECTORS  2
+#define DES3_EDE_CTR_DEC_TEST_VECTORS  2
 
 static struct cipher_testvec des_enc_tv_template[] = {
        { /* From Applied Cryptography */
@@ -2103,6 +2138,76 @@ static struct cipher_testvec des_enc_tv_template[] = {
                .rlen   = 8,
                .np     = 8,
                .tap    = { 1, 1, 1, 1, 1, 1, 1, 1 }
+       }, { /* Generated with Crypto++ */
+               .key    = "\xC9\x83\xA6\xC9\xEC\x0F\x32\x55",
+               .klen   = 8,
+               .input  = "\x50\xB9\x22\xAE\x17\x80\x0C\x75"
+                         "\xDE\x47\xD3\x3C\xA5\x0E\x9A\x03"
+                         "\x6C\xF8\x61\xCA\x33\xBF\x28\x91"
+                         "\x1D\x86\xEF\x58\xE4\x4D\xB6\x1F"
+                         "\xAB\x14\x7D\x09\x72\xDB\x44\xD0"
+                         "\x39\xA2\x0B\x97\x00\x69\xF5\x5E"
+                         "\xC7\x30\xBC\x25\x8E\x1A\x83\xEC"
+                         "\x55\xE1\x4A\xB3\x1C\xA8\x11\x7A"
+                         "\x06\x6F\xD8\x41\xCD\x36\x9F\x08"
+                         "\x94\xFD\x66\xF2\x5B\xC4\x2D\xB9"
+                         "\x22\x8B\x17\x80\xE9\x52\xDE\x47"
+                         "\xB0\x19\xA5\x0E\x77\x03\x6C\xD5"
+                         "\x3E\xCA\x33\x9C\x05\x91\xFA\x63"
+                         "\xEF\x58\xC1\x2A\xB6\x1F\x88\x14"
+                         "\x7D\xE6\x4F\xDB\x44\xAD\x16\xA2"
+                         "\x0B\x74\x00\x69\xD2\x3B\xC7\x30"
+                         "\x99\x02\x8E\xF7\x60\xEC\x55\xBE"
+                         "\x27\xB3\x1C\x85\x11\x7A\xE3\x4C"
+                         "\xD8\x41\xAA\x13\x9F\x08\x71\xFD"
+                         "\x66\xCF\x38\xC4\x2D\x96\x22\x8B"
+                         "\xF4\x5D\xE9\x52\xBB\x24\xB0\x19"
+                         "\x82\x0E\x77\xE0\x49\xD5\x3E\xA7"
+                         "\x10\x9C\x05\x6E\xFA\x63\xCC\x35"
+                         "\xC1\x2A\x93\x1F\x88\xF1\x5A\xE6"
+                         "\x4F\xB8\x21\xAD\x16\x7F\x0B\x74"
+                         "\xDD\x46\xD2\x3B\xA4\x0D\x99\x02"
+                         "\x6B\xF7\x60\xC9\x32\xBE\x27\x90"
+                         "\x1C\x85\xEE\x57\xE3\x4C\xB5\x1E"
+                         "\xAA\x13\x7C\x08\x71\xDA\x43\xCF"
+                         "\x38\xA1\x0A\x96\xFF\x68\xF4\x5D"
+                         "\xC6\x2F\xBB\x24\x8D\x19\x82\xEB",
+               .ilen   = 248,
+               .result = "\x88\xCB\x1F\xAB\x2F\x2A\x49\x57"
+                         "\x92\xB9\x77\xFF\x2F\x47\x58\xDD"
+                         "\xD7\x8A\x91\x95\x26\x33\x78\xB2"
+                         "\x33\xBA\xB2\x3E\x02\xF5\x1F\xEF"
+                         "\x98\xC5\xA6\xD2\x7D\x79\xEC\xB3"
+                         "\x45\xF3\x4C\x61\xAC\x6C\xC2\x55"
+                         "\xE5\xD3\x06\x58\x8A\x42\x3E\xDD"
+                         "\x3D\x20\x45\xE9\x6F\x0D\x25\xA8"
+                         "\xA5\xC7\x69\xCE\xD5\x3B\x7B\xC9"
+                         "\x9E\x65\xE7\xA3\xF2\xE4\x18\x94"
+                         "\xD2\x81\xE9\x33\x2B\x2D\x49\xC4"
+                         "\xFE\xDA\x7F\xE2\xF2\x8C\x9C\xDC"
+                         "\x73\x58\x11\x1F\x81\xD7\x21\x1A"
+                         "\x80\xD0\x0D\xE8\x45\xD6\xD8\xD5"
+                         "\x2E\x51\x16\xCA\x09\x89\x54\x62"
+                         "\xF7\x04\x3D\x75\xB9\xA3\x84\xF4"
+                         "\x62\xF0\x02\x58\x83\xAF\x30\x87"
+                         "\x85\x3F\x01\xCD\x8E\x58\x42\xC4"
+                         "\x41\x73\xE0\x15\x0A\xE6\x2E\x80"
+                         "\x94\xF8\x5B\x3A\x4E\xDF\x51\xB2"
+                         "\x9D\xE4\xC4\x9D\xF7\x3F\xF8\x8E"
+                         "\x37\x22\x4D\x00\x2A\xEF\xC1\x0F"
+                         "\x14\xA0\x66\xAB\x79\x39\xD0\x8E"
+                         "\xE9\x95\x61\x74\x12\xED\x07\xD7"
+                         "\xDD\x95\xDC\x7B\x57\x25\x27\x9C"
+                         "\x51\x96\x16\xF7\x94\x61\xB8\x87"
+                         "\xF0\x21\x1B\x32\xFB\x07\x0F\x29"
+                         "\x56\xBD\x9D\x22\xA2\x9F\xA2\xB9"
+                         "\x46\x31\x4C\x5E\x2E\x95\x61\xEF"
+                         "\xE1\x58\x39\x09\xB4\x8B\x40\xAC"
+                         "\x5F\x62\xC7\x72\xD9\xFC\xCB\x9A",
+               .rlen   = 248,
+               .also_non_np = 1,
+               .np     = 2,
+               .tap    = { 248 - 8, 8 },
        },
 };
 
@@ -2143,6 +2248,76 @@ static struct cipher_testvec des_dec_tv_template[] = {
                .rlen   = 16,
                .np     = 3,
                .tap    = { 3, 12, 1 }
+       }, { /* Generated with Crypto++ */
+               .key    = "\xC9\x83\xA6\xC9\xEC\x0F\x32\x55",
+               .klen   = 8,
+               .input  = "\x88\xCB\x1F\xAB\x2F\x2A\x49\x57"
+                         "\x92\xB9\x77\xFF\x2F\x47\x58\xDD"
+                         "\xD7\x8A\x91\x95\x26\x33\x78\xB2"
+                         "\x33\xBA\xB2\x3E\x02\xF5\x1F\xEF"
+                         "\x98\xC5\xA6\xD2\x7D\x79\xEC\xB3"
+                         "\x45\xF3\x4C\x61\xAC\x6C\xC2\x55"
+                         "\xE5\xD3\x06\x58\x8A\x42\x3E\xDD"
+                         "\x3D\x20\x45\xE9\x6F\x0D\x25\xA8"
+                         "\xA5\xC7\x69\xCE\xD5\x3B\x7B\xC9"
+                         "\x9E\x65\xE7\xA3\xF2\xE4\x18\x94"
+                         "\xD2\x81\xE9\x33\x2B\x2D\x49\xC4"
+                         "\xFE\xDA\x7F\xE2\xF2\x8C\x9C\xDC"
+                         "\x73\x58\x11\x1F\x81\xD7\x21\x1A"
+                         "\x80\xD0\x0D\xE8\x45\xD6\xD8\xD5"
+                         "\x2E\x51\x16\xCA\x09\x89\x54\x62"
+                         "\xF7\x04\x3D\x75\xB9\xA3\x84\xF4"
+                         "\x62\xF0\x02\x58\x83\xAF\x30\x87"
+                         "\x85\x3F\x01\xCD\x8E\x58\x42\xC4"
+                         "\x41\x73\xE0\x15\x0A\xE6\x2E\x80"
+                         "\x94\xF8\x5B\x3A\x4E\xDF\x51\xB2"
+                         "\x9D\xE4\xC4\x9D\xF7\x3F\xF8\x8E"
+                         "\x37\x22\x4D\x00\x2A\xEF\xC1\x0F"
+                         "\x14\xA0\x66\xAB\x79\x39\xD0\x8E"
+                         "\xE9\x95\x61\x74\x12\xED\x07\xD7"
+                         "\xDD\x95\xDC\x7B\x57\x25\x27\x9C"
+                         "\x51\x96\x16\xF7\x94\x61\xB8\x87"
+                         "\xF0\x21\x1B\x32\xFB\x07\x0F\x29"
+                         "\x56\xBD\x9D\x22\xA2\x9F\xA2\xB9"
+                         "\x46\x31\x4C\x5E\x2E\x95\x61\xEF"
+                         "\xE1\x58\x39\x09\xB4\x8B\x40\xAC"
+                         "\x5F\x62\xC7\x72\xD9\xFC\xCB\x9A",
+               .ilen   = 248,
+               .result = "\x50\xB9\x22\xAE\x17\x80\x0C\x75"
+                         "\xDE\x47\xD3\x3C\xA5\x0E\x9A\x03"
+                         "\x6C\xF8\x61\xCA\x33\xBF\x28\x91"
+                         "\x1D\x86\xEF\x58\xE4\x4D\xB6\x1F"
+                         "\xAB\x14\x7D\x09\x72\xDB\x44\xD0"
+                         "\x39\xA2\x0B\x97\x00\x69\xF5\x5E"
+                         "\xC7\x30\xBC\x25\x8E\x1A\x83\xEC"
+                         "\x55\xE1\x4A\xB3\x1C\xA8\x11\x7A"
+                         "\x06\x6F\xD8\x41\xCD\x36\x9F\x08"
+                         "\x94\xFD\x66\xF2\x5B\xC4\x2D\xB9"
+                         "\x22\x8B\x17\x80\xE9\x52\xDE\x47"
+                         "\xB0\x19\xA5\x0E\x77\x03\x6C\xD5"
+                         "\x3E\xCA\x33\x9C\x05\x91\xFA\x63"
+                         "\xEF\x58\xC1\x2A\xB6\x1F\x88\x14"
+                         "\x7D\xE6\x4F\xDB\x44\xAD\x16\xA2"
+                         "\x0B\x74\x00\x69\xD2\x3B\xC7\x30"
+                         "\x99\x02\x8E\xF7\x60\xEC\x55\xBE"
+                         "\x27\xB3\x1C\x85\x11\x7A\xE3\x4C"
+                         "\xD8\x41\xAA\x13\x9F\x08\x71\xFD"
+                         "\x66\xCF\x38\xC4\x2D\x96\x22\x8B"
+                         "\xF4\x5D\xE9\x52\xBB\x24\xB0\x19"
+                         "\x82\x0E\x77\xE0\x49\xD5\x3E\xA7"
+                         "\x10\x9C\x05\x6E\xFA\x63\xCC\x35"
+                         "\xC1\x2A\x93\x1F\x88\xF1\x5A\xE6"
+                         "\x4F\xB8\x21\xAD\x16\x7F\x0B\x74"
+                         "\xDD\x46\xD2\x3B\xA4\x0D\x99\x02"
+                         "\x6B\xF7\x60\xC9\x32\xBE\x27\x90"
+                         "\x1C\x85\xEE\x57\xE3\x4C\xB5\x1E"
+                         "\xAA\x13\x7C\x08\x71\xDA\x43\xCF"
+                         "\x38\xA1\x0A\x96\xFF\x68\xF4\x5D"
+                         "\xC6\x2F\xBB\x24\x8D\x19\x82\xEB",
+               .rlen   = 248,
+               .also_non_np = 1,
+               .np     = 2,
+               .tap    = { 248 - 8, 8 },
        },
 };
 
@@ -2198,6 +2373,77 @@ static struct cipher_testvec des_cbc_enc_tv_template[] = {
                .rlen   = 24,
                .np     = 2,
                .tap    = { 13, 11 }
+       }, { /* Generated with Crypto++ */
+               .key    = "\xC9\x83\xA6\xC9\xEC\x0F\x32\x55",
+               .klen   = 8,
+               .iv     = "\xE7\x82\x1D\xB8\x53\x11\xAC\x47",
+               .input  = "\x50\xB9\x22\xAE\x17\x80\x0C\x75"
+                         "\xDE\x47\xD3\x3C\xA5\x0E\x9A\x03"
+                         "\x6C\xF8\x61\xCA\x33\xBF\x28\x91"
+                         "\x1D\x86\xEF\x58\xE4\x4D\xB6\x1F"
+                         "\xAB\x14\x7D\x09\x72\xDB\x44\xD0"
+                         "\x39\xA2\x0B\x97\x00\x69\xF5\x5E"
+                         "\xC7\x30\xBC\x25\x8E\x1A\x83\xEC"
+                         "\x55\xE1\x4A\xB3\x1C\xA8\x11\x7A"
+                         "\x06\x6F\xD8\x41\xCD\x36\x9F\x08"
+                         "\x94\xFD\x66\xF2\x5B\xC4\x2D\xB9"
+                         "\x22\x8B\x17\x80\xE9\x52\xDE\x47"
+                         "\xB0\x19\xA5\x0E\x77\x03\x6C\xD5"
+                         "\x3E\xCA\x33\x9C\x05\x91\xFA\x63"
+                         "\xEF\x58\xC1\x2A\xB6\x1F\x88\x14"
+                         "\x7D\xE6\x4F\xDB\x44\xAD\x16\xA2"
+                         "\x0B\x74\x00\x69\xD2\x3B\xC7\x30"
+                         "\x99\x02\x8E\xF7\x60\xEC\x55\xBE"
+                         "\x27\xB3\x1C\x85\x11\x7A\xE3\x4C"
+                         "\xD8\x41\xAA\x13\x9F\x08\x71\xFD"
+                         "\x66\xCF\x38\xC4\x2D\x96\x22\x8B"
+                         "\xF4\x5D\xE9\x52\xBB\x24\xB0\x19"
+                         "\x82\x0E\x77\xE0\x49\xD5\x3E\xA7"
+                         "\x10\x9C\x05\x6E\xFA\x63\xCC\x35"
+                         "\xC1\x2A\x93\x1F\x88\xF1\x5A\xE6"
+                         "\x4F\xB8\x21\xAD\x16\x7F\x0B\x74"
+                         "\xDD\x46\xD2\x3B\xA4\x0D\x99\x02"
+                         "\x6B\xF7\x60\xC9\x32\xBE\x27\x90"
+                         "\x1C\x85\xEE\x57\xE3\x4C\xB5\x1E"
+                         "\xAA\x13\x7C\x08\x71\xDA\x43\xCF"
+                         "\x38\xA1\x0A\x96\xFF\x68\xF4\x5D"
+                         "\xC6\x2F\xBB\x24\x8D\x19\x82\xEB",
+               .ilen   = 248,
+               .result = "\x71\xCC\x56\x1C\x87\x2C\x43\x20"
+                         "\x1C\x20\x13\x09\xF9\x2B\x40\x47"
+                         "\x99\x10\xD1\x1B\x65\x33\x33\xBA"
+                         "\x88\x0D\xA2\xD1\x86\xFF\x4D\xF4"
+                         "\x5A\x0C\x12\x96\x32\x57\xAA\x26"
+                         "\xA7\xF4\x32\x8D\xBC\x10\x31\x9E"
+                         "\x81\x72\x74\xDE\x30\x19\x69\x49"
+                         "\x54\x9C\xC3\xEB\x0B\x97\xDD\xD1"
+                         "\xE8\x6D\x0D\x05\x83\xA5\x12\x08"
+                         "\x47\xF8\x88\x03\x86\x51\x3C\xEF"
+                         "\xE7\x11\x73\x4D\x44\x2B\xE2\x16"
+                         "\xE8\xA5\x06\x50\x66\x70\x0E\x14"
+                         "\xBA\x21\x3B\xD5\x23\x5B\xA7\x8F"
+                         "\x56\xB6\xA7\x44\xDB\x86\xAB\x69"
+                         "\x33\x3C\xBE\x64\xC4\x22\xD3\xFE"
+                         "\x49\x90\x88\x6A\x09\x8F\x76\x59"
+                         "\xCB\xB7\xA0\x2D\x79\x75\x92\x8A"
+                         "\x82\x1D\xC2\xFE\x09\x1F\x78\x6B"
+                         "\x2F\xD6\xA4\x87\x1E\xC4\x53\x63"
+                         "\x80\x02\x61\x2F\xE3\x46\xB6\xB5"
+                         "\xAA\x95\xF4\xEE\xA7\x64\x2B\x4F"
+                         "\x20\xCF\xD2\x47\x4E\x39\x65\xB3"
+                         "\x11\x87\xA2\x6C\x49\x7E\x36\xC7"
+                         "\x62\x8B\x48\x0D\x6A\x64\x00\xBD"
+                         "\x71\x91\x8C\xE9\x70\x19\x01\x4F"
+                         "\x4E\x68\x23\xBA\xDA\x24\x2E\x45"
+                         "\x02\x14\x33\x21\xAE\x58\x4B\xCF"
+                         "\x3B\x4B\xE8\xF8\xF6\x4F\x34\x93"
+                         "\xD7\x07\x8A\xD7\x18\x92\x36\x8C"
+                         "\x82\xA9\xBD\x6A\x31\x91\x39\x11"
+                         "\xC6\x4A\xF3\x55\xC7\x29\x2E\x63",
+               .rlen   = 248,
+               .also_non_np = 1,
+               .np     = 2,
+               .tap    = { 248 - 8, 8 },
        },
 };
 
@@ -2236,6 +2482,369 @@ static struct cipher_testvec des_cbc_dec_tv_template[] = {
                .rlen   = 8,
                .np     = 2,
                .tap    = { 4, 4 }
+       }, { /* Generated with Crypto++ */
+               .key    = "\xC9\x83\xA6\xC9\xEC\x0F\x32\x55",
+               .klen   = 8,
+               .iv     = "\xE7\x82\x1D\xB8\x53\x11\xAC\x47",
+               .input  = "\x71\xCC\x56\x1C\x87\x2C\x43\x20"
+                         "\x1C\x20\x13\x09\xF9\x2B\x40\x47"
+                         "\x99\x10\xD1\x1B\x65\x33\x33\xBA"
+                         "\x88\x0D\xA2\xD1\x86\xFF\x4D\xF4"
+                         "\x5A\x0C\x12\x96\x32\x57\xAA\x26"
+                         "\xA7\xF4\x32\x8D\xBC\x10\x31\x9E"
+                         "\x81\x72\x74\xDE\x30\x19\x69\x49"
+                         "\x54\x9C\xC3\xEB\x0B\x97\xDD\xD1"
+                         "\xE8\x6D\x0D\x05\x83\xA5\x12\x08"
+                         "\x47\xF8\x88\x03\x86\x51\x3C\xEF"
+                         "\xE7\x11\x73\x4D\x44\x2B\xE2\x16"
+                         "\xE8\xA5\x06\x50\x66\x70\x0E\x14"
+                         "\xBA\x21\x3B\xD5\x23\x5B\xA7\x8F"
+                         "\x56\xB6\xA7\x44\xDB\x86\xAB\x69"
+                         "\x33\x3C\xBE\x64\xC4\x22\xD3\xFE"
+                         "\x49\x90\x88\x6A\x09\x8F\x76\x59"
+                         "\xCB\xB7\xA0\x2D\x79\x75\x92\x8A"
+                         "\x82\x1D\xC2\xFE\x09\x1F\x78\x6B"
+                         "\x2F\xD6\xA4\x87\x1E\xC4\x53\x63"
+                         "\x80\x02\x61\x2F\xE3\x46\xB6\xB5"
+                         "\xAA\x95\xF4\xEE\xA7\x64\x2B\x4F"
+                         "\x20\xCF\xD2\x47\x4E\x39\x65\xB3"
+                         "\x11\x87\xA2\x6C\x49\x7E\x36\xC7"
+                         "\x62\x8B\x48\x0D\x6A\x64\x00\xBD"
+                         "\x71\x91\x8C\xE9\x70\x19\x01\x4F"
+                         "\x4E\x68\x23\xBA\xDA\x24\x2E\x45"
+                         "\x02\x14\x33\x21\xAE\x58\x4B\xCF"
+                         "\x3B\x4B\xE8\xF8\xF6\x4F\x34\x93"
+                         "\xD7\x07\x8A\xD7\x18\x92\x36\x8C"
+                         "\x82\xA9\xBD\x6A\x31\x91\x39\x11"
+                         "\xC6\x4A\xF3\x55\xC7\x29\x2E\x63",
+               .ilen   = 248,
+               .result = "\x50\xB9\x22\xAE\x17\x80\x0C\x75"
+                         "\xDE\x47\xD3\x3C\xA5\x0E\x9A\x03"
+                         "\x6C\xF8\x61\xCA\x33\xBF\x28\x91"
+                         "\x1D\x86\xEF\x58\xE4\x4D\xB6\x1F"
+                         "\xAB\x14\x7D\x09\x72\xDB\x44\xD0"
+                         "\x39\xA2\x0B\x97\x00\x69\xF5\x5E"
+                         "\xC7\x30\xBC\x25\x8E\x1A\x83\xEC"
+                         "\x55\xE1\x4A\xB3\x1C\xA8\x11\x7A"
+                         "\x06\x6F\xD8\x41\xCD\x36\x9F\x08"
+                         "\x94\xFD\x66\xF2\x5B\xC4\x2D\xB9"
+                         "\x22\x8B\x17\x80\xE9\x52\xDE\x47"
+                         "\xB0\x19\xA5\x0E\x77\x03\x6C\xD5"
+                         "\x3E\xCA\x33\x9C\x05\x91\xFA\x63"
+                         "\xEF\x58\xC1\x2A\xB6\x1F\x88\x14"
+                         "\x7D\xE6\x4F\xDB\x44\xAD\x16\xA2"
+                         "\x0B\x74\x00\x69\xD2\x3B\xC7\x30"
+                         "\x99\x02\x8E\xF7\x60\xEC\x55\xBE"
+                         "\x27\xB3\x1C\x85\x11\x7A\xE3\x4C"
+                         "\xD8\x41\xAA\x13\x9F\x08\x71\xFD"
+                         "\x66\xCF\x38\xC4\x2D\x96\x22\x8B"
+                         "\xF4\x5D\xE9\x52\xBB\x24\xB0\x19"
+                         "\x82\x0E\x77\xE0\x49\xD5\x3E\xA7"
+                         "\x10\x9C\x05\x6E\xFA\x63\xCC\x35"
+                         "\xC1\x2A\x93\x1F\x88\xF1\x5A\xE6"
+                         "\x4F\xB8\x21\xAD\x16\x7F\x0B\x74"
+                         "\xDD\x46\xD2\x3B\xA4\x0D\x99\x02"
+                         "\x6B\xF7\x60\xC9\x32\xBE\x27\x90"
+                         "\x1C\x85\xEE\x57\xE3\x4C\xB5\x1E"
+                         "\xAA\x13\x7C\x08\x71\xDA\x43\xCF"
+                         "\x38\xA1\x0A\x96\xFF\x68\xF4\x5D"
+                         "\xC6\x2F\xBB\x24\x8D\x19\x82\xEB",
+               .rlen   = 248,
+               .also_non_np = 1,
+               .np     = 2,
+               .tap    = { 248 - 8, 8 },
+       },
+};
+
+static struct cipher_testvec des_ctr_enc_tv_template[] = {
+       { /* Generated with Crypto++ */
+               .key    = "\xC9\x83\xA6\xC9\xEC\x0F\x32\x55",
+               .klen   = 8,
+               .iv     = "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFD",
+               .input  = "\x50\xB9\x22\xAE\x17\x80\x0C\x75"
+                         "\xDE\x47\xD3\x3C\xA5\x0E\x9A\x03"
+                         "\x6C\xF8\x61\xCA\x33\xBF\x28\x91"
+                         "\x1D\x86\xEF\x58\xE4\x4D\xB6\x1F"
+                         "\xAB\x14\x7D\x09\x72\xDB\x44\xD0"
+                         "\x39\xA2\x0B\x97\x00\x69\xF5\x5E"
+                         "\xC7\x30\xBC\x25\x8E\x1A\x83\xEC"
+                         "\x55\xE1\x4A\xB3\x1C\xA8\x11\x7A"
+                         "\x06\x6F\xD8\x41\xCD\x36\x9F\x08"
+                         "\x94\xFD\x66\xF2\x5B\xC4\x2D\xB9"
+                         "\x22\x8B\x17\x80\xE9\x52\xDE\x47"
+                         "\xB0\x19\xA5\x0E\x77\x03\x6C\xD5"
+                         "\x3E\xCA\x33\x9C\x05\x91\xFA\x63"
+                         "\xEF\x58\xC1\x2A\xB6\x1F\x88\x14"
+                         "\x7D\xE6\x4F\xDB\x44\xAD\x16\xA2"
+                         "\x0B\x74\x00\x69\xD2\x3B\xC7\x30"
+                         "\x99\x02\x8E\xF7\x60\xEC\x55\xBE"
+                         "\x27\xB3\x1C\x85\x11\x7A\xE3\x4C"
+                         "\xD8\x41\xAA\x13\x9F\x08\x71\xFD"
+                         "\x66\xCF\x38\xC4\x2D\x96\x22\x8B"
+                         "\xF4\x5D\xE9\x52\xBB\x24\xB0\x19"
+                         "\x82\x0E\x77\xE0\x49\xD5\x3E\xA7"
+                         "\x10\x9C\x05\x6E\xFA\x63\xCC\x35"
+                         "\xC1\x2A\x93\x1F\x88\xF1\x5A\xE6"
+                         "\x4F\xB8\x21\xAD\x16\x7F\x0B\x74"
+                         "\xDD\x46\xD2\x3B\xA4\x0D\x99\x02"
+                         "\x6B\xF7\x60\xC9\x32\xBE\x27\x90"
+                         "\x1C\x85\xEE\x57\xE3\x4C\xB5\x1E"
+                         "\xAA\x13\x7C\x08\x71\xDA\x43\xCF"
+                         "\x38\xA1\x0A\x96\xFF\x68\xF4\x5D"
+                         "\xC6\x2F\xBB\x24\x8D\x19\x82\xEB",
+               .ilen   = 248,
+               .result = "\x2F\x96\x06\x0F\x50\xC9\x68\x03"
+                         "\x0F\x31\xD4\x64\xA5\x29\x77\x35"
+                         "\xBC\x7A\x9F\x19\xE7\x0D\x33\x3E"
+                         "\x12\x0B\x8C\xAE\x48\xAE\xD9\x02"
+                         "\x0A\xD4\xB0\xD6\x37\xB2\x65\x1C"
+                         "\x4B\x65\xEB\x24\xB5\x8E\xAD\x47"
+                         "\x0D\xDA\x79\x77\xA0\x29\xA0\x2B"
+                         "\xC8\x0F\x85\xDC\x03\x13\xA9\x04"
+                         "\x19\x40\xBE\xBE\x5C\x49\x4A\x69"
+                         "\xED\xE8\xE1\x9E\x14\x43\x74\xDE"
+                         "\xEC\x6E\x11\x3F\x36\xEF\x7B\xFB"
+                         "\xBE\x4C\x91\x43\x22\x65\x72\x48"
+                         "\xE2\x12\xED\x88\xAC\xA7\xC9\x91"
+                         "\x14\xA2\x36\x1C\x29\xFF\xC8\x4F"
+                         "\x72\x5C\x4B\xB0\x1E\x93\xC2\xFA"
+                         "\x9D\x53\x86\xA0\xAE\xC6\xB7\x3C"
+                         "\x59\x0C\xD0\x8F\xA6\xD8\xA4\x31"
+                         "\xB7\x30\x1C\x21\x38\xFB\x68\x8C"
+                         "\x2E\xF5\x6E\x73\xC3\x16\x5F\x12"
+                         "\x0C\x33\xB9\x1E\x7B\x70\xDE\x86"
+                         "\x32\xB3\xC1\x16\xAB\xD9\x49\x0B"
+                         "\x96\x28\x72\x6B\xF3\x30\xA9\xEB"
+                         "\x69\xE2\x1E\x58\x46\xA2\x8E\xC7"
+                         "\xC0\xEF\x07\xB7\x77\x2C\x00\x05"
+                         "\x46\xBD\xFE\x53\x81\x8B\xA4\x03"
+                         "\x20\x0F\xDB\x78\x0B\x1F\x53\x04"
+                         "\x4C\x60\x4C\xC3\x2A\x86\x86\x7E"
+                         "\x13\xD2\x26\xED\x5D\x3E\x9C\xF2"
+                         "\x5C\xC4\x15\xC9\x9A\x21\xC5\xCD"
+                         "\x19\x7F\x99\x19\x53\xCE\x1D\x14"
+                         "\x69\x74\xA1\x06\x46\x0F\x4E\x75",
+               .rlen   = 248,
+               .also_non_np = 1,
+               .np     = 2,
+               .tap    = { 248 - 8, 8 },
+       }, { /* Generated with Crypto++ */
+               .key    = "\xC9\x83\xA6\xC9\xEC\x0F\x32\x55",
+               .klen   = 8,
+               .iv     = "\xE7\x82\x1D\xB8\x53\x11\xAC\x47",
+               .input  = "\x50\xB9\x22\xAE\x17\x80\x0C\x75"
+                         "\xDE\x47\xD3\x3C\xA5\x0E\x9A\x03"
+                         "\x6C\xF8\x61\xCA\x33\xBF\x28\x91"
+                         "\x1D\x86\xEF\x58\xE4\x4D\xB6\x1F"
+                         "\xAB\x14\x7D\x09\x72\xDB\x44\xD0"
+                         "\x39\xA2\x0B\x97\x00\x69\xF5\x5E"
+                         "\xC7\x30\xBC\x25\x8E\x1A\x83\xEC"
+                         "\x55\xE1\x4A\xB3\x1C\xA8\x11\x7A"
+                         "\x06\x6F\xD8\x41\xCD\x36\x9F\x08"
+                         "\x94\xFD\x66\xF2\x5B\xC4\x2D\xB9"
+                         "\x22\x8B\x17\x80\xE9\x52\xDE\x47"
+                         "\xB0\x19\xA5\x0E\x77\x03\x6C\xD5"
+                         "\x3E\xCA\x33\x9C\x05\x91\xFA\x63"
+                         "\xEF\x58\xC1\x2A\xB6\x1F\x88\x14"
+                         "\x7D\xE6\x4F\xDB\x44\xAD\x16\xA2"
+                         "\x0B\x74\x00\x69\xD2\x3B\xC7\x30"
+                         "\x99\x02\x8E\xF7\x60\xEC\x55\xBE"
+                         "\x27\xB3\x1C\x85\x11\x7A\xE3\x4C"
+                         "\xD8\x41\xAA\x13\x9F\x08\x71\xFD"
+                         "\x66\xCF\x38\xC4\x2D\x96\x22\x8B"
+                         "\xF4\x5D\xE9\x52\xBB\x24\xB0\x19"
+                         "\x82\x0E\x77\xE0\x49\xD5\x3E\xA7"
+                         "\x10\x9C\x05\x6E\xFA\x63\xCC\x35"
+                         "\xC1\x2A\x93\x1F\x88\xF1\x5A\xE6"
+                         "\x4F\xB8\x21\xAD\x16\x7F\x0B\x74"
+                         "\xDD\x46\xD2\x3B\xA4\x0D\x99\x02"
+                         "\x6B\xF7\x60\xC9\x32\xBE\x27\x90"
+                         "\x1C\x85\xEE\x57\xE3\x4C\xB5\x1E"
+                         "\xAA\x13\x7C\x08\x71\xDA\x43\xCF"
+                         "\x38\xA1\x0A\x96\xFF\x68\xF4\x5D"
+                         "\xC6\x2F\xBB\x24\x8D\x19\x82",
+               .ilen   = 247,
+               .result = "\x62\xE5\xF4\xDC\x99\xE7\x89\xE3"
+                         "\xF4\x10\xCC\x21\x99\xEB\xDC\x15"
+                         "\x19\x13\x93\x27\x9D\xB6\x6F\x45"
+                         "\x17\x55\x61\x72\xC8\xD3\x7F\xA5"
+                         "\x32\xD0\xD3\x02\x15\xA4\x05\x23"
+                         "\x9C\x23\x61\x60\x77\x7B\x6C\x95"
+                         "\x26\x49\x42\x2E\xF3\xC1\x8C\x6D"
+                         "\xC8\x47\xD5\x94\xE7\x53\xC8\x23"
+                         "\x1B\xA5\x0B\xCB\x12\xD3\x7A\x12"
+                         "\xA4\x42\x15\x34\xF7\x5F\xDC\x58"
+                         "\x5B\x58\x4C\xAD\xD1\x33\x8E\xE6"
+                         "\xE5\xA0\xDA\x4D\x94\x3D\x63\xA8"
+                         "\x02\x82\xBB\x16\xB8\xDC\xB5\x58"
+                         "\xC3\x2D\x79\xE4\x25\x79\x43\xF9"
+                         "\x6D\xD3\xCA\xC0\xE8\x12\xD4\x7E"
+                         "\x04\x25\x79\xFD\x27\xFB\xC4\xEA"
+                         "\x32\x94\x48\x92\xF3\x68\x1A\x7F"
+                         "\x36\x33\x43\x79\xF7\xCA\xC2\x38"
+                         "\xC0\x68\xD4\x53\xA9\xCC\x43\x0C"
+                         "\x40\x57\x3E\xED\x00\x9F\x22\x6E"
+                         "\x80\x99\x0B\xCC\x40\x63\x46\x8A"
+                         "\xE8\xC4\x9B\x6D\x7A\x08\x6E\xA9"
+                         "\x6F\x84\xBC\xB3\xF4\x95\x0B\x2D"
+                         "\x6A\xBA\x37\x50\xC3\xCF\x9F\x7C"
+                         "\x59\x5E\xDE\x0B\x30\xFA\x34\x8A"
+                         "\xF8\xD1\xA2\xF8\x4E\xBD\x5D\x5E"
+                         "\x7D\x71\x99\xE0\xF6\xE5\x7C\xE0"
+                         "\x6D\xEE\x82\x89\x92\xD4\xF5\xD7"
+                         "\xDF\x85\x2D\xE1\xB2\xD6\xAB\x94"
+                         "\xA5\xA6\xE7\xB0\x51\x36\x52\x37"
+                         "\x91\x45\x05\x3E\x58\xBF\x32",
+               .rlen   = 247,
+               .also_non_np = 1,
+               .np     = 2,
+               .tap    = { 247 - 8, 8 },
+       },
+};
+
+static struct cipher_testvec des_ctr_dec_tv_template[] = {
+       { /* Generated with Crypto++ */
+               .key    = "\xC9\x83\xA6\xC9\xEC\x0F\x32\x55",
+               .klen   = 8,
+               .iv     = "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFD",
+               .input  = "\x2F\x96\x06\x0F\x50\xC9\x68\x03"
+                         "\x0F\x31\xD4\x64\xA5\x29\x77\x35"
+                         "\xBC\x7A\x9F\x19\xE7\x0D\x33\x3E"
+                         "\x12\x0B\x8C\xAE\x48\xAE\xD9\x02"
+                         "\x0A\xD4\xB0\xD6\x37\xB2\x65\x1C"
+                         "\x4B\x65\xEB\x24\xB5\x8E\xAD\x47"
+                         "\x0D\xDA\x79\x77\xA0\x29\xA0\x2B"
+                         "\xC8\x0F\x85\xDC\x03\x13\xA9\x04"
+                         "\x19\x40\xBE\xBE\x5C\x49\x4A\x69"
+                         "\xED\xE8\xE1\x9E\x14\x43\x74\xDE"
+                         "\xEC\x6E\x11\x3F\x36\xEF\x7B\xFB"
+                         "\xBE\x4C\x91\x43\x22\x65\x72\x48"
+                         "\xE2\x12\xED\x88\xAC\xA7\xC9\x91"
+                         "\x14\xA2\x36\x1C\x29\xFF\xC8\x4F"
+                         "\x72\x5C\x4B\xB0\x1E\x93\xC2\xFA"
+                         "\x9D\x53\x86\xA0\xAE\xC6\xB7\x3C"
+                         "\x59\x0C\xD0\x8F\xA6\xD8\xA4\x31"
+                         "\xB7\x30\x1C\x21\x38\xFB\x68\x8C"
+                         "\x2E\xF5\x6E\x73\xC3\x16\x5F\x12"
+                         "\x0C\x33\xB9\x1E\x7B\x70\xDE\x86"
+                         "\x32\xB3\xC1\x16\xAB\xD9\x49\x0B"
+                         "\x96\x28\x72\x6B\xF3\x30\xA9\xEB"
+                         "\x69\xE2\x1E\x58\x46\xA2\x8E\xC7"
+                         "\xC0\xEF\x07\xB7\x77\x2C\x00\x05"
+                         "\x46\xBD\xFE\x53\x81\x8B\xA4\x03"
+                         "\x20\x0F\xDB\x78\x0B\x1F\x53\x04"
+                         "\x4C\x60\x4C\xC3\x2A\x86\x86\x7E"
+                         "\x13\xD2\x26\xED\x5D\x3E\x9C\xF2"
+                         "\x5C\xC4\x15\xC9\x9A\x21\xC5\xCD"
+                         "\x19\x7F\x99\x19\x53\xCE\x1D\x14"
+                         "\x69\x74\xA1\x06\x46\x0F\x4E\x75",
+               .ilen   = 248,
+               .result = "\x50\xB9\x22\xAE\x17\x80\x0C\x75"
+                         "\xDE\x47\xD3\x3C\xA5\x0E\x9A\x03"
+                         "\x6C\xF8\x61\xCA\x33\xBF\x28\x91"
+                         "\x1D\x86\xEF\x58\xE4\x4D\xB6\x1F"
+                         "\xAB\x14\x7D\x09\x72\xDB\x44\xD0"
+                         "\x39\xA2\x0B\x97\x00\x69\xF5\x5E"
+                         "\xC7\x30\xBC\x25\x8E\x1A\x83\xEC"
+                         "\x55\xE1\x4A\xB3\x1C\xA8\x11\x7A"
+                         "\x06\x6F\xD8\x41\xCD\x36\x9F\x08"
+                         "\x94\xFD\x66\xF2\x5B\xC4\x2D\xB9"
+                         "\x22\x8B\x17\x80\xE9\x52\xDE\x47"
+                         "\xB0\x19\xA5\x0E\x77\x03\x6C\xD5"
+                         "\x3E\xCA\x33\x9C\x05\x91\xFA\x63"
+                         "\xEF\x58\xC1\x2A\xB6\x1F\x88\x14"
+                         "\x7D\xE6\x4F\xDB\x44\xAD\x16\xA2"
+                         "\x0B\x74\x00\x69\xD2\x3B\xC7\x30"
+                         "\x99\x02\x8E\xF7\x60\xEC\x55\xBE"
+                         "\x27\xB3\x1C\x85\x11\x7A\xE3\x4C"
+                         "\xD8\x41\xAA\x13\x9F\x08\x71\xFD"
+                         "\x66\xCF\x38\xC4\x2D\x96\x22\x8B"
+                         "\xF4\x5D\xE9\x52\xBB\x24\xB0\x19"
+                         "\x82\x0E\x77\xE0\x49\xD5\x3E\xA7"
+                         "\x10\x9C\x05\x6E\xFA\x63\xCC\x35"
+                         "\xC1\x2A\x93\x1F\x88\xF1\x5A\xE6"
+                         "\x4F\xB8\x21\xAD\x16\x7F\x0B\x74"
+                         "\xDD\x46\xD2\x3B\xA4\x0D\x99\x02"
+                         "\x6B\xF7\x60\xC9\x32\xBE\x27\x90"
+                         "\x1C\x85\xEE\x57\xE3\x4C\xB5\x1E"
+                         "\xAA\x13\x7C\x08\x71\xDA\x43\xCF"
+                         "\x38\xA1\x0A\x96\xFF\x68\xF4\x5D"
+                         "\xC6\x2F\xBB\x24\x8D\x19\x82\xEB",
+               .rlen   = 248,
+               .also_non_np = 1,
+               .np     = 2,
+               .tap    = { 248 - 8, 8 },
+       }, { /* Generated with Crypto++ */
+               .key    = "\xC9\x83\xA6\xC9\xEC\x0F\x32\x55",
+               .klen   = 8,
+               .iv     = "\xE7\x82\x1D\xB8\x53\x11\xAC\x47",
+               .input  = "\x62\xE5\xF4\xDC\x99\xE7\x89\xE3"
+                         "\xF4\x10\xCC\x21\x99\xEB\xDC\x15"
+                         "\x19\x13\x93\x27\x9D\xB6\x6F\x45"
+                         "\x17\x55\x61\x72\xC8\xD3\x7F\xA5"
+                         "\x32\xD0\xD3\x02\x15\xA4\x05\x23"
+                         "\x9C\x23\x61\x60\x77\x7B\x6C\x95"
+                         "\x26\x49\x42\x2E\xF3\xC1\x8C\x6D"
+                         "\xC8\x47\xD5\x94\xE7\x53\xC8\x23"
+                         "\x1B\xA5\x0B\xCB\x12\xD3\x7A\x12"
+                         "\xA4\x42\x15\x34\xF7\x5F\xDC\x58"
+                         "\x5B\x58\x4C\xAD\xD1\x33\x8E\xE6"
+                         "\xE5\xA0\xDA\x4D\x94\x3D\x63\xA8"
+                         "\x02\x82\xBB\x16\xB8\xDC\xB5\x58"
+                         "\xC3\x2D\x79\xE4\x25\x79\x43\xF9"
+                         "\x6D\xD3\xCA\xC0\xE8\x12\xD4\x7E"
+                         "\x04\x25\x79\xFD\x27\xFB\xC4\xEA"
+                         "\x32\x94\x48\x92\xF3\x68\x1A\x7F"
+                         "\x36\x33\x43\x79\xF7\xCA\xC2\x38"
+                         "\xC0\x68\xD4\x53\xA9\xCC\x43\x0C"
+                         "\x40\x57\x3E\xED\x00\x9F\x22\x6E"
+                         "\x80\x99\x0B\xCC\x40\x63\x46\x8A"
+                         "\xE8\xC4\x9B\x6D\x7A\x08\x6E\xA9"
+                         "\x6F\x84\xBC\xB3\xF4\x95\x0B\x2D"
+                         "\x6A\xBA\x37\x50\xC3\xCF\x9F\x7C"
+                         "\x59\x5E\xDE\x0B\x30\xFA\x34\x8A"
+                         "\xF8\xD1\xA2\xF8\x4E\xBD\x5D\x5E"
+                         "\x7D\x71\x99\xE0\xF6\xE5\x7C\xE0"
+                         "\x6D\xEE\x82\x89\x92\xD4\xF5\xD7"
+                         "\xDF\x85\x2D\xE1\xB2\xD6\xAB\x94"
+                         "\xA5\xA6\xE7\xB0\x51\x36\x52\x37"
+                         "\x91\x45\x05\x3E\x58\xBF\x32",
+               .ilen   = 247,
+               .result = "\x50\xB9\x22\xAE\x17\x80\x0C\x75"
+                         "\xDE\x47\xD3\x3C\xA5\x0E\x9A\x03"
+                         "\x6C\xF8\x61\xCA\x33\xBF\x28\x91"
+                         "\x1D\x86\xEF\x58\xE4\x4D\xB6\x1F"
+                         "\xAB\x14\x7D\x09\x72\xDB\x44\xD0"
+                         "\x39\xA2\x0B\x97\x00\x69\xF5\x5E"
+                         "\xC7\x30\xBC\x25\x8E\x1A\x83\xEC"
+                         "\x55\xE1\x4A\xB3\x1C\xA8\x11\x7A"
+                         "\x06\x6F\xD8\x41\xCD\x36\x9F\x08"
+                         "\x94\xFD\x66\xF2\x5B\xC4\x2D\xB9"
+                         "\x22\x8B\x17\x80\xE9\x52\xDE\x47"
+                         "\xB0\x19\xA5\x0E\x77\x03\x6C\xD5"
+                         "\x3E\xCA\x33\x9C\x05\x91\xFA\x63"
+                         "\xEF\x58\xC1\x2A\xB6\x1F\x88\x14"
+                         "\x7D\xE6\x4F\xDB\x44\xAD\x16\xA2"
+                         "\x0B\x74\x00\x69\xD2\x3B\xC7\x30"
+                         "\x99\x02\x8E\xF7\x60\xEC\x55\xBE"
+                         "\x27\xB3\x1C\x85\x11\x7A\xE3\x4C"
+                         "\xD8\x41\xAA\x13\x9F\x08\x71\xFD"
+                         "\x66\xCF\x38\xC4\x2D\x96\x22\x8B"
+                         "\xF4\x5D\xE9\x52\xBB\x24\xB0\x19"
+                         "\x82\x0E\x77\xE0\x49\xD5\x3E\xA7"
+                         "\x10\x9C\x05\x6E\xFA\x63\xCC\x35"
+                         "\xC1\x2A\x93\x1F\x88\xF1\x5A\xE6"
+                         "\x4F\xB8\x21\xAD\x16\x7F\x0B\x74"
+                         "\xDD\x46\xD2\x3B\xA4\x0D\x99\x02"
+                         "\x6B\xF7\x60\xC9\x32\xBE\x27\x90"
+                         "\x1C\x85\xEE\x57\xE3\x4C\xB5\x1E"
+                         "\xAA\x13\x7C\x08\x71\xDA\x43\xCF"
+                         "\x38\xA1\x0A\x96\xFF\x68\xF4\x5D"
+                         "\xC6\x2F\xBB\x24\x8D\x19\x82",
+               .rlen   = 247,
+               .also_non_np = 1,
+               .np     = 2,
+               .tap    = { 247 - 8, 8 },
        },
 };
 
@@ -2267,6 +2876,140 @@ static struct cipher_testvec des3_ede_enc_tv_template[] = {
                .ilen   = 8,
                .result = "\xe1\xef\x62\xc3\x32\xfe\x82\x5b",
                .rlen   = 8,
+       }, { /* Generated with Crypto++ */
+               .key    = "\xF3\x9C\xD6\xF3\x9C\xB9\x5A\x67"
+                         "\x00\x5A\x67\x00\x2D\xCE\xEB\x2D"
+                         "\xCE\xEB\xB4\x51\x72\xB4\x51\x72",
+               .klen   = 24,
+               .input  = "\x05\xEC\x77\xFB\x42\xD5\x59\x20"
+                         "\x8B\x12\x86\x69\xF0\x5B\xCF\x56"
+                         "\x39\xAD\x34\x9F\x66\xEA\x7D\xC4"
+                         "\x48\xD3\xBA\x0D\xB1\x18\xE3\x4A"
+                         "\xFE\x41\x28\x5C\x27\x8E\x11\x85"
+                         "\x6C\xF7\x5E\xC2\x55\x3C\xA0\x0B"
+                         "\x92\x65\xE9\x70\xDB\x4F\xD6\xB9"
+                         "\x00\xB4\x1F\xE6\x49\xFD\x44\x2F"
+                         "\x53\x3A\x8D\x14\x98\x63\xCA\x5D"
+                         "\xC1\xA8\x33\xA7\x0E\x91\x78\xEC"
+                         "\x77\xDE\x42\xD5\xBC\x07\x8B\x12"
+                         "\xE5\x4C\xF0\x5B\x22\x56\x39\x80"
+                         "\x6B\x9F\x66\xC9\x50\xC4\xAF\x36"
+                         "\xBA\x0D\x94\x7F\xE3\x4A\xDD\x41"
+                         "\x28\xB3\x1A\x8E\x11\xF8\x43\xF7"
+                         "\x5E\x21\x55\x3C\x87\x6E\x92\x65"
+                         "\xCC\x57\xDB\xA2\x35\xB9\x00\xEB"
+                         "\x72\xE6\x49\xD0\x44\x2F\xB6\x19"
+                         "\x8D\x14\xFF\x46\xCA\x5D\x24\xA8"
+                         "\x33\x9A\x6D\x91\x78\xC3\x77\xDE"
+                         "\xA1\x08\xBC\x07\xEE\x71\xE5\x4C"
+                         "\xD7\x5B\x22\xB5\x1C\x80\x6B\xF2"
+                         "\x45\xC9\x50\x3B\xAF\x36\x99\x60"
+                         "\x94\x7F\xC6\x4A\xDD\xA4\x0F\xB3"
+                         "\x1A\xED\x74\xF8\x43\x2A\x5E\x21"
+                         "\x88\x13\x87\x6E\xF1\x58\xCC\x57"
+                         "\x3E\xA2\x35\x9C\x67\xEB\x72\xC5"
+                         "\x49\xD0\xBB\x02\xB6\x19\xE0\x4B"
+                         "\xFF\x46\x29\x5D\x24\x8F\x16\x9A"
+                         "\x6D\xF4\x5F\xC3\xAA\x3D\xA1\x08"
+                         "\x93\x7A\xEE\x71\xD8\x4C\xD7\xBE"
+                         "\x01\xB5\x1C\xE7\x4E\xF2\x45\x2C"
+                         "\x50\x3B\x82\x15\x99\x60\xCB\x52"
+                         "\xC6\xA9\x30\xA4\x0F\x96\x79\xED"
+                         "\x74\xDF\x43\x2A\xBD\x04\x88\x13"
+                         "\xFA\x4D\xF1\x58\x23\x57\x3E\x81"
+                         "\x68\x9C\x67\xCE\x51\xC5\xAC\x37"
+                         "\xBB\x02\x95\x7C\xE0\x4B\xD2\x46"
+                         "\x29\xB0\x1B\x8F\x16\xF9\x40\xF4"
+                         "\x5F\x26\xAA\x3D\x84\x6F\x93\x7A"
+                         "\xCD\x54\xD8\xA3\x0A\xBE\x01\xE8"
+                         "\x73\xE7\x4E\xD1\x45\x2C\xB7\x1E"
+                         "\x82\x15\xFC\x47\xCB\x52\x25\xA9"
+                         "\x30\x9B\x62\x96\x79\xC0\x74\xDF"
+                         "\xA6\x09\xBD\x04\xEF\x76\xFA\x4D"
+                         "\xD4\x58\x23\x8A\x1D\x81\x68\xF3"
+                         "\x5A\xCE\x51\x38\xAC\x37\x9E\x61"
+                         "\x95\x7C\xC7\x4B\xD2\xA5\x0C\xB0"
+                         "\x1B\xE2\x75\xF9\x40\x2B\x5F\x26"
+                         "\x89\x10\x84\x6F\xF6\x59\xCD\x54"
+                         "\x3F\xA3\x0A\x9D\x64\xE8\x73\xDA"
+                         "\x4E\xD1\xB8\x03\xB7\x1E\xE1\x48"
+                         "\xFC\x47\x2E\x52\x25\x8C\x17\x9B"
+                         "\x62\xF5\x5C\xC0\xAB\x32\xA6\x09"
+                         "\x90\x7B\xEF\x76\xD9\x4D\xD4\xBF"
+                         "\x06\x8A\x1D\xE4\x4F\xF3\x5A\x2D"
+                         "\x51\x38\x83\x6A\x9E\x61\xC8\x53"
+                         "\xC7\xAE\x31\xA5\x0C\x97\x7E\xE2"
+                         "\x75\xDC\x40\x2B\xB2\x05\x89\x10"
+                         "\xFB\x42\xF6\x59\x20\x54\x3F\x86"
+                         "\x69\x9D\x64\xCF\x56\xDA\xAD\x34"
+                         "\xB8\x03\xEA\x7D\xE1\x48\xD3\x47",
+               .ilen   = 496,
+               .result = "\x4E\x9A\x40\x3D\x61\x7D\x17\xFA"
+                         "\x16\x86\x88\x0B\xD8\xAE\xF8\xE4"
+                         "\x81\x01\x04\x00\x76\xFA\xED\xD3"
+                         "\x44\x7E\x21\x9D\xF0\xFB\x2B\x64"
+                         "\xCA\x4E\x90\xE0\xC0\x63\x28\x92"
+                         "\xF3\x1F\xA4\x53\x2C\x77\xCC\x77"
+                         "\x69\x56\xD0\x19\xAD\x00\x2D\x97"
+                         "\xBC\xDE\x49\x6A\x82\xBC\x16\xE2"
+                         "\x2F\x3E\x72\xEE\xD1\xCE\xFC\x1B"
+                         "\xEA\x32\x56\xE4\x0B\xAF\x27\x36"
+                         "\xAF\x08\xB9\x61\xB7\x48\x23\x27"
+                         "\xEE\x4D\xC8\x79\x56\x06\xEB\xC7"
+                         "\x5B\xCA\x0A\xC6\x5E\x5C\xCB\xB6"
+                         "\x9D\xDA\x04\x59\xE2\x09\x48\x7E"
+                         "\x6B\x37\xC6\xFE\x92\xA9\x1E\x6E"
+                         "\x0D\x19\xFA\x33\x0F\xEE\x36\x68"
+                         "\x11\xBB\xF9\x5A\x73\xAB\x3A\xEA"
+                         "\xAC\x28\xD8\xD5\x27\xE8\x6B\x16"
+                         "\x45\x86\x50\x01\x70\x35\x99\x92"
+                         "\xDF\x0C\x07\x88\x8B\x7F\x9E\x4B"
+                         "\xD2\x04\x84\x90\xC4\x27\xDF\x0A"
+                         "\x49\xA8\xA7\x1A\x6D\x78\x16\xCA"
+                         "\xB3\x18\x5C\xC3\x93\x63\x5A\x68"
+                         "\x77\x02\xBA\xED\x62\x71\xB1\xD9"
+                         "\x5E\xE5\x6F\x1A\xCC\x1D\xBE\x2E"
+                         "\x11\xF3\xA6\x97\xCA\x8E\xBF\xB4"
+                         "\x56\xA1\x36\x6B\xB1\x0A\x3E\x70"
+                         "\xEA\xD7\xCD\x72\x7B\x79\xC8\xAD"
+                         "\x6B\xFE\xFB\xBA\x64\xAE\x19\xC1"
+                         "\x82\xCF\x8A\xA1\x50\x17\x7F\xB2"
+                         "\x6F\x7B\x0F\x52\xC5\x3E\x4A\x52"
+                         "\x3F\xD9\x3F\x01\xA6\x41\x1A\xB3"
+                         "\xB3\x7A\x0E\x8E\x75\xB2\xB1\x5F"
+                         "\xDB\xEA\x84\x13\x26\x6C\x85\x4E"
+                         "\xAE\x6B\xDC\xE7\xE7\xAD\xB0\x06"
+                         "\x5C\xBA\x92\xD0\x30\xBB\x8D\xD2"
+                         "\xAE\x4C\x70\x85\xA0\x07\xE3\x2C"
+                         "\xD1\x27\x9C\xCF\xDB\x13\xB7\xE5"
+                         "\xF9\x6A\x02\xD0\x39\x9D\xB6\xE7"
+                         "\xD1\x17\x25\x08\xF9\xA9\xA6\x67"
+                         "\x38\x80\xD1\x22\xAB\x1A\xD7\x26"
+                         "\xAD\xCA\x19\x1B\xFA\x18\xA7\x57"
+                         "\x31\xEC\xC9\xED\xDB\x79\xC0\x48"
+                         "\xAC\x31\x9F\x03\x8B\x62\x5B\x7E"
+                         "\x0E\xA6\xD0\x64\xEE\xEA\x00\xFC"
+                         "\x58\xC8\xDE\x51\x4E\x17\x15\x11"
+                         "\x66\x58\xB6\x90\xDC\xDF\xA1\x49"
+                         "\xCA\x79\xE9\x31\x31\x42\xDC\x56"
+                         "\x0B\xCD\xB6\x0D\xC7\x64\xF7\x19"
+                         "\xD9\x42\x05\x7F\xBC\x2F\xFC\x90"
+                         "\xAE\x29\x86\xAA\x43\x7A\x4F\x6B"
+                         "\xCE\xEA\xBC\x31\x8D\x65\x9D\x46"
+                         "\xEA\x77\xB4\xF9\x58\xEA\x5D\x84"
+                         "\xE4\xDC\x14\xBB\xBD\x15\x0E\xDA"
+                         "\xD8\xE4\xA4\x5D\x61\xF9\x58\x0F"
+                         "\xE4\x82\x77\xCE\x87\xC0\x09\xF0"
+                         "\xD6\x10\x9E\x34\xE1\x0C\x67\x55"
+                         "\x7B\x6D\xD5\x51\x4B\x00\xEE\xBA"
+                         "\xF2\x7B\xBE\x75\x07\x42\x9D\x99"
+                         "\x12\xE1\x71\x4A\xF9\x2A\xF5\xF6"
+                         "\x93\x03\xD7\x51\x09\xFA\xBE\x68"
+                         "\xD8\x45\xFF\x33\xBA\xBB\x2B\x63",
+               .rlen   = 496,
+               .also_non_np = 1,
+               .np     = 2,
+               .tap    = { 496 - 16, 16 },
        },
 };
 
@@ -2298,6 +3041,140 @@ static struct cipher_testvec des3_ede_dec_tv_template[] = {
                .ilen   = 8,
                .result = "\x00\x00\x00\x00\x00\x00\x00\x00",
                .rlen   = 8,
+       }, { /* Generated with Crypto++ */
+               .key    = "\xF3\x9C\xD6\xF3\x9C\xB9\x5A\x67"
+                         "\x00\x5A\x67\x00\x2D\xCE\xEB\x2D"
+                         "\xCE\xEB\xB4\x51\x72\xB4\x51\x72",
+               .klen   = 24,
+               .input  = "\x4E\x9A\x40\x3D\x61\x7D\x17\xFA"
+                         "\x16\x86\x88\x0B\xD8\xAE\xF8\xE4"
+                         "\x81\x01\x04\x00\x76\xFA\xED\xD3"
+                         "\x44\x7E\x21\x9D\xF0\xFB\x2B\x64"
+                         "\xCA\x4E\x90\xE0\xC0\x63\x28\x92"
+                         "\xF3\x1F\xA4\x53\x2C\x77\xCC\x77"
+                         "\x69\x56\xD0\x19\xAD\x00\x2D\x97"
+                         "\xBC\xDE\x49\x6A\x82\xBC\x16\xE2"
+                         "\x2F\x3E\x72\xEE\xD1\xCE\xFC\x1B"
+                         "\xEA\x32\x56\xE4\x0B\xAF\x27\x36"
+                         "\xAF\x08\xB9\x61\xB7\x48\x23\x27"
+                         "\xEE\x4D\xC8\x79\x56\x06\xEB\xC7"
+                         "\x5B\xCA\x0A\xC6\x5E\x5C\xCB\xB6"
+                         "\x9D\xDA\x04\x59\xE2\x09\x48\x7E"
+                         "\x6B\x37\xC6\xFE\x92\xA9\x1E\x6E"
+                         "\x0D\x19\xFA\x33\x0F\xEE\x36\x68"
+                         "\x11\xBB\xF9\x5A\x73\xAB\x3A\xEA"
+                         "\xAC\x28\xD8\xD5\x27\xE8\x6B\x16"
+                         "\x45\x86\x50\x01\x70\x35\x99\x92"
+                         "\xDF\x0C\x07\x88\x8B\x7F\x9E\x4B"
+                         "\xD2\x04\x84\x90\xC4\x27\xDF\x0A"
+                         "\x49\xA8\xA7\x1A\x6D\x78\x16\xCA"
+                         "\xB3\x18\x5C\xC3\x93\x63\x5A\x68"
+                         "\x77\x02\xBA\xED\x62\x71\xB1\xD9"
+                         "\x5E\xE5\x6F\x1A\xCC\x1D\xBE\x2E"
+                         "\x11\xF3\xA6\x97\xCA\x8E\xBF\xB4"
+                         "\x56\xA1\x36\x6B\xB1\x0A\x3E\x70"
+                         "\xEA\xD7\xCD\x72\x7B\x79\xC8\xAD"
+                         "\x6B\xFE\xFB\xBA\x64\xAE\x19\xC1"
+                         "\x82\xCF\x8A\xA1\x50\x17\x7F\xB2"
+                         "\x6F\x7B\x0F\x52\xC5\x3E\x4A\x52"
+                         "\x3F\xD9\x3F\x01\xA6\x41\x1A\xB3"
+                         "\xB3\x7A\x0E\x8E\x75\xB2\xB1\x5F"
+                         "\xDB\xEA\x84\x13\x26\x6C\x85\x4E"
+                         "\xAE\x6B\xDC\xE7\xE7\xAD\xB0\x06"
+                         "\x5C\xBA\x92\xD0\x30\xBB\x8D\xD2"
+                         "\xAE\x4C\x70\x85\xA0\x07\xE3\x2C"
+                         "\xD1\x27\x9C\xCF\xDB\x13\xB7\xE5"
+                         "\xF9\x6A\x02\xD0\x39\x9D\xB6\xE7"
+                         "\xD1\x17\x25\x08\xF9\xA9\xA6\x67"
+                         "\x38\x80\xD1\x22\xAB\x1A\xD7\x26"
+                         "\xAD\xCA\x19\x1B\xFA\x18\xA7\x57"
+                         "\x31\xEC\xC9\xED\xDB\x79\xC0\x48"
+                         "\xAC\x31\x9F\x03\x8B\x62\x5B\x7E"
+                         "\x0E\xA6\xD0\x64\xEE\xEA\x00\xFC"
+                         "\x58\xC8\xDE\x51\x4E\x17\x15\x11"
+                         "\x66\x58\xB6\x90\xDC\xDF\xA1\x49"
+                         "\xCA\x79\xE9\x31\x31\x42\xDC\x56"
+                         "\x0B\xCD\xB6\x0D\xC7\x64\xF7\x19"
+                         "\xD9\x42\x05\x7F\xBC\x2F\xFC\x90"
+                         "\xAE\x29\x86\xAA\x43\x7A\x4F\x6B"
+                         "\xCE\xEA\xBC\x31\x8D\x65\x9D\x46"
+                         "\xEA\x77\xB4\xF9\x58\xEA\x5D\x84"
+                         "\xE4\xDC\x14\xBB\xBD\x15\x0E\xDA"
+                         "\xD8\xE4\xA4\x5D\x61\xF9\x58\x0F"
+                         "\xE4\x82\x77\xCE\x87\xC0\x09\xF0"
+                         "\xD6\x10\x9E\x34\xE1\x0C\x67\x55"
+                         "\x7B\x6D\xD5\x51\x4B\x00\xEE\xBA"
+                         "\xF2\x7B\xBE\x75\x07\x42\x9D\x99"
+                         "\x12\xE1\x71\x4A\xF9\x2A\xF5\xF6"
+                         "\x93\x03\xD7\x51\x09\xFA\xBE\x68"
+                         "\xD8\x45\xFF\x33\xBA\xBB\x2B\x63",
+               .ilen   = 496,
+               .result = "\x05\xEC\x77\xFB\x42\xD5\x59\x20"
+                         "\x8B\x12\x86\x69\xF0\x5B\xCF\x56"
+                         "\x39\xAD\x34\x9F\x66\xEA\x7D\xC4"
+                         "\x48\xD3\xBA\x0D\xB1\x18\xE3\x4A"
+                         "\xFE\x41\x28\x5C\x27\x8E\x11\x85"
+                         "\x6C\xF7\x5E\xC2\x55\x3C\xA0\x0B"
+                         "\x92\x65\xE9\x70\xDB\x4F\xD6\xB9"
+                         "\x00\xB4\x1F\xE6\x49\xFD\x44\x2F"
+                         "\x53\x3A\x8D\x14\x98\x63\xCA\x5D"
+                         "\xC1\xA8\x33\xA7\x0E\x91\x78\xEC"
+                         "\x77\xDE\x42\xD5\xBC\x07\x8B\x12"
+                         "\xE5\x4C\xF0\x5B\x22\x56\x39\x80"
+                         "\x6B\x9F\x66\xC9\x50\xC4\xAF\x36"
+                         "\xBA\x0D\x94\x7F\xE3\x4A\xDD\x41"
+                         "\x28\xB3\x1A\x8E\x11\xF8\x43\xF7"
+                         "\x5E\x21\x55\x3C\x87\x6E\x92\x65"
+                         "\xCC\x57\xDB\xA2\x35\xB9\x00\xEB"
+                         "\x72\xE6\x49\xD0\x44\x2F\xB6\x19"
+                         "\x8D\x14\xFF\x46\xCA\x5D\x24\xA8"
+                         "\x33\x9A\x6D\x91\x78\xC3\x77\xDE"
+                         "\xA1\x08\xBC\x07\xEE\x71\xE5\x4C"
+                         "\xD7\x5B\x22\xB5\x1C\x80\x6B\xF2"
+                         "\x45\xC9\x50\x3B\xAF\x36\x99\x60"
+                         "\x94\x7F\xC6\x4A\xDD\xA4\x0F\xB3"
+                         "\x1A\xED\x74\xF8\x43\x2A\x5E\x21"
+                         "\x88\x13\x87\x6E\xF1\x58\xCC\x57"
+                         "\x3E\xA2\x35\x9C\x67\xEB\x72\xC5"
+                         "\x49\xD0\xBB\x02\xB6\x19\xE0\x4B"
+                         "\xFF\x46\x29\x5D\x24\x8F\x16\x9A"
+                         "\x6D\xF4\x5F\xC3\xAA\x3D\xA1\x08"
+                         "\x93\x7A\xEE\x71\xD8\x4C\xD7\xBE"
+                         "\x01\xB5\x1C\xE7\x4E\xF2\x45\x2C"
+                         "\x50\x3B\x82\x15\x99\x60\xCB\x52"
+                         "\xC6\xA9\x30\xA4\x0F\x96\x79\xED"
+                         "\x74\xDF\x43\x2A\xBD\x04\x88\x13"
+                         "\xFA\x4D\xF1\x58\x23\x57\x3E\x81"
+                         "\x68\x9C\x67\xCE\x51\xC5\xAC\x37"
+                         "\xBB\x02\x95\x7C\xE0\x4B\xD2\x46"
+                         "\x29\xB0\x1B\x8F\x16\xF9\x40\xF4"
+                         "\x5F\x26\xAA\x3D\x84\x6F\x93\x7A"
+                         "\xCD\x54\xD8\xA3\x0A\xBE\x01\xE8"
+                         "\x73\xE7\x4E\xD1\x45\x2C\xB7\x1E"
+                         "\x82\x15\xFC\x47\xCB\x52\x25\xA9"
+                         "\x30\x9B\x62\x96\x79\xC0\x74\xDF"
+                         "\xA6\x09\xBD\x04\xEF\x76\xFA\x4D"
+                         "\xD4\x58\x23\x8A\x1D\x81\x68\xF3"
+                         "\x5A\xCE\x51\x38\xAC\x37\x9E\x61"
+                         "\x95\x7C\xC7\x4B\xD2\xA5\x0C\xB0"
+                         "\x1B\xE2\x75\xF9\x40\x2B\x5F\x26"
+                         "\x89\x10\x84\x6F\xF6\x59\xCD\x54"
+                         "\x3F\xA3\x0A\x9D\x64\xE8\x73\xDA"
+                         "\x4E\xD1\xB8\x03\xB7\x1E\xE1\x48"
+                         "\xFC\x47\x2E\x52\x25\x8C\x17\x9B"
+                         "\x62\xF5\x5C\xC0\xAB\x32\xA6\x09"
+                         "\x90\x7B\xEF\x76\xD9\x4D\xD4\xBF"
+                         "\x06\x8A\x1D\xE4\x4F\xF3\x5A\x2D"
+                         "\x51\x38\x83\x6A\x9E\x61\xC8\x53"
+                         "\xC7\xAE\x31\xA5\x0C\x97\x7E\xE2"
+                         "\x75\xDC\x40\x2B\xB2\x05\x89\x10"
+                         "\xFB\x42\xF6\x59\x20\x54\x3F\x86"
+                         "\x69\x9D\x64\xCF\x56\xDA\xAD\x34"
+                         "\xB8\x03\xEA\x7D\xE1\x48\xD3\x47",
+               .rlen   = 496,
+               .also_non_np = 1,
+               .np     = 2,
+               .tap    = { 496 - 16, 16 },
        },
 };
 
@@ -2342,6 +3219,142 @@ static struct cipher_testvec des3_ede_cbc_enc_tv_template[] = {
                          "\x9d\xde\xa5\x70\xe9\x42\x45\x8a"
                          "\x6b\xfa\xb1\x91\x13\xb0\xd9\x19",
                .rlen   = 128,
+       }, { /* Generated with Crypto++ */
+               .key    = "\x9C\xD6\xF3\x9C\xB9\x5A\x67\x00"
+                         "\x5A\x67\x00\x2D\xCE\xEB\x2D\xCE"
+                         "\xEB\xB4\x51\x72\xB4\x51\x72\x1F",
+               .klen   = 24,
+               .iv     = "\xB2\xD7\x48\xED\x06\x44\xF9\x12"
+                         "\xB7\x28\x4D\x83\x24\x59\xF2\x17",
+               .input  = "\x05\xEC\x77\xFB\x42\xD5\x59\x20"
+                         "\x8B\x12\x86\x69\xF0\x5B\xCF\x56"
+                         "\x39\xAD\x34\x9F\x66\xEA\x7D\xC4"
+                         "\x48\xD3\xBA\x0D\xB1\x18\xE3\x4A"
+                         "\xFE\x41\x28\x5C\x27\x8E\x11\x85"
+                         "\x6C\xF7\x5E\xC2\x55\x3C\xA0\x0B"
+                         "\x92\x65\xE9\x70\xDB\x4F\xD6\xB9"
+                         "\x00\xB4\x1F\xE6\x49\xFD\x44\x2F"
+                         "\x53\x3A\x8D\x14\x98\x63\xCA\x5D"
+                         "\xC1\xA8\x33\xA7\x0E\x91\x78\xEC"
+                         "\x77\xDE\x42\xD5\xBC\x07\x8B\x12"
+                         "\xE5\x4C\xF0\x5B\x22\x56\x39\x80"
+                         "\x6B\x9F\x66\xC9\x50\xC4\xAF\x36"
+                         "\xBA\x0D\x94\x7F\xE3\x4A\xDD\x41"
+                         "\x28\xB3\x1A\x8E\x11\xF8\x43\xF7"
+                         "\x5E\x21\x55\x3C\x87\x6E\x92\x65"
+                         "\xCC\x57\xDB\xA2\x35\xB9\x00\xEB"
+                         "\x72\xE6\x49\xD0\x44\x2F\xB6\x19"
+                         "\x8D\x14\xFF\x46\xCA\x5D\x24\xA8"
+                         "\x33\x9A\x6D\x91\x78\xC3\x77\xDE"
+                         "\xA1\x08\xBC\x07\xEE\x71\xE5\x4C"
+                         "\xD7\x5B\x22\xB5\x1C\x80\x6B\xF2"
+                         "\x45\xC9\x50\x3B\xAF\x36\x99\x60"
+                         "\x94\x7F\xC6\x4A\xDD\xA4\x0F\xB3"
+                         "\x1A\xED\x74\xF8\x43\x2A\x5E\x21"
+                         "\x88\x13\x87\x6E\xF1\x58\xCC\x57"
+                         "\x3E\xA2\x35\x9C\x67\xEB\x72\xC5"
+                         "\x49\xD0\xBB\x02\xB6\x19\xE0\x4B"
+                         "\xFF\x46\x29\x5D\x24\x8F\x16\x9A"
+                         "\x6D\xF4\x5F\xC3\xAA\x3D\xA1\x08"
+                         "\x93\x7A\xEE\x71\xD8\x4C\xD7\xBE"
+                         "\x01\xB5\x1C\xE7\x4E\xF2\x45\x2C"
+                         "\x50\x3B\x82\x15\x99\x60\xCB\x52"
+                         "\xC6\xA9\x30\xA4\x0F\x96\x79\xED"
+                         "\x74\xDF\x43\x2A\xBD\x04\x88\x13"
+                         "\xFA\x4D\xF1\x58\x23\x57\x3E\x81"
+                         "\x68\x9C\x67\xCE\x51\xC5\xAC\x37"
+                         "\xBB\x02\x95\x7C\xE0\x4B\xD2\x46"
+                         "\x29\xB0\x1B\x8F\x16\xF9\x40\xF4"
+                         "\x5F\x26\xAA\x3D\x84\x6F\x93\x7A"
+                         "\xCD\x54\xD8\xA3\x0A\xBE\x01\xE8"
+                         "\x73\xE7\x4E\xD1\x45\x2C\xB7\x1E"
+                         "\x82\x15\xFC\x47\xCB\x52\x25\xA9"
+                         "\x30\x9B\x62\x96\x79\xC0\x74\xDF"
+                         "\xA6\x09\xBD\x04\xEF\x76\xFA\x4D"
+                         "\xD4\x58\x23\x8A\x1D\x81\x68\xF3"
+                         "\x5A\xCE\x51\x38\xAC\x37\x9E\x61"
+                         "\x95\x7C\xC7\x4B\xD2\xA5\x0C\xB0"
+                         "\x1B\xE2\x75\xF9\x40\x2B\x5F\x26"
+                         "\x89\x10\x84\x6F\xF6\x59\xCD\x54"
+                         "\x3F\xA3\x0A\x9D\x64\xE8\x73\xDA"
+                         "\x4E\xD1\xB8\x03\xB7\x1E\xE1\x48"
+                         "\xFC\x47\x2E\x52\x25\x8C\x17\x9B"
+                         "\x62\xF5\x5C\xC0\xAB\x32\xA6\x09"
+                         "\x90\x7B\xEF\x76\xD9\x4D\xD4\xBF"
+                         "\x06\x8A\x1D\xE4\x4F\xF3\x5A\x2D"
+                         "\x51\x38\x83\x6A\x9E\x61\xC8\x53"
+                         "\xC7\xAE\x31\xA5\x0C\x97\x7E\xE2"
+                         "\x75\xDC\x40\x2B\xB2\x05\x89\x10"
+                         "\xFB\x42\xF6\x59\x20\x54\x3F\x86"
+                         "\x69\x9D\x64\xCF\x56\xDA\xAD\x34"
+                         "\xB8\x03\xEA\x7D\xE1\x48\xD3\x47",
+               .ilen   = 496,
+               .result = "\xF8\xF6\xB5\x60\x5C\x5A\x75\x84"
+                         "\x87\x81\x53\xBA\xC9\x6F\xEC\xD5"
+                         "\x1E\x68\x8E\x85\x12\x86\x1D\x38"
+                         "\x1C\x91\x40\xCC\x69\x6A\xD5\x35"
+                         "\x0D\x7C\xB5\x07\x7C\x7B\x2A\xAF"
+                         "\x32\xBC\xA1\xB3\x84\x31\x1B\x3C"
+                         "\x0A\x2B\xFA\xD3\x9F\xB0\x8C\x37"
+                         "\x8F\x9D\xA7\x6D\x6C\xFA\xD7\x90"
+                         "\xE3\x69\x54\xED\x3A\xC4\xF1\x6B"
+                         "\xB1\xCC\xFB\x7D\xD8\x8E\x17\x0B"
+                         "\x9C\xF6\x4C\xD6\xFF\x03\x4E\xD9"
+                         "\xE6\xA5\xAD\x25\xE6\x17\x69\x63"
+                         "\x11\x35\x61\x94\x88\x7B\x1C\x48"
+                         "\xF1\x24\x20\x29\x6B\x93\x1A\x8E"
+                         "\x43\x03\x89\xD8\xB1\xDA\x47\x7B"
+                         "\x79\x3A\x83\x76\xDA\xAE\xC6\xBB"
+                         "\x22\xF8\xE8\x3D\x9A\x65\x54\xD8"
+                         "\x4C\xE9\xE7\xE4\x63\x2F\x5C\x73"
+                         "\x5A\xC3\xAE\x46\xA8\xCD\x57\xE6"
+                         "\x67\x88\xA5\x20\x6F\x5F\x97\xC7"
+                         "\xCC\x15\xA2\x0A\x93\xEA\x33\xE7"
+                         "\x03\x5F\xEC\x64\x30\x6F\xEE\xD7"
+                         "\x7E\xDF\xD6\xE9\x6F\x3F\xD6\x1E"
+                         "\xBE\x67\x6C\x5B\x97\xA0\x09\xE6"
+                         "\xEE\xFE\x55\xA3\x29\x65\xE0\x12"
+                         "\xA1\x6A\x8A\x6F\xF2\xE6\xF1\x96"
+                         "\x87\xFB\x9C\x05\xDD\x80\xEC\xFF"
+                         "\xC5\xED\x50\xFE\xFC\x91\xCD\xCE"
+                         "\x25\x2C\x5F\xD9\xAD\x95\x7D\x99"
+                         "\xF0\x05\xC4\x71\x46\x5F\xF9\x0D"
+                         "\xD2\x63\xDF\x9B\x96\x2E\x2B\xA6"
+                         "\x2B\x1C\xD5\xFB\x96\x24\x60\x60"
+                         "\x54\x40\xB8\x62\xA4\xF8\x46\x95"
+                         "\x73\x28\xA3\xA6\x16\x2B\x17\xE7"
+                         "\x7A\xF8\x62\x54\x3B\x64\x69\xE1"
+                         "\x71\x34\x29\x5B\x4E\x05\x9B\xFA"
+                         "\x5E\xF1\x96\xB7\xCE\x16\x9B\x59"
+                         "\xF1\x1A\x4C\x51\x26\xFD\x79\xE2"
+                         "\x3B\x8E\x71\x69\x6A\x91\xB6\x65"
+                         "\x32\x09\xB8\xE4\x09\x1F\xEA\x39"
+                         "\xCE\x20\x65\x9F\xD6\xD1\xC7\xF0"
+                         "\x73\x50\x08\x56\x20\x9B\x94\x23"
+                         "\x14\x39\xB7\x2B\xB1\x2D\x6D\x6F"
+                         "\x41\x5B\xCC\xE2\x18\xAE\x62\x89"
+                         "\x78\x8E\x67\x23\xD0\xFB\x2B\xE5"
+                         "\x25\xC9\x48\x97\xB5\xD3\x17\xD5"
+                         "\x6A\x9F\xA7\x48\x0C\x2B\x73\x3B"
+                         "\x57\x08\xAE\x91\xF2\xB7\x57\x89"
+                         "\xF4\xD0\xB0\x07\xB0\x42\x6C\xAF"
+                         "\x98\x1A\xE7\xD1\xAC\x1E\xB5\x02"
+                         "\xD4\x56\x42\x79\x79\x7F\x2A\x77"
+                         "\x25\xE9\x7D\xC1\x88\x19\x2B\x49"
+                         "\x6F\x46\x59\xAB\x56\x1F\x61\xE0"
+                         "\x0C\x24\x9C\xC9\x5B\x63\xA9\x12"
+                         "\xCF\x88\x96\xB6\xA8\x24\xC6\xA8"
+                         "\x21\x85\x1A\x62\x7E\x34\xBB\xEB"
+                         "\xBD\x02\x2A\xC7\xD8\x89\x80\xC5"
+                         "\xB1\xBB\x60\xA5\x22\xFC\x6F\x38"
+                         "\x02\x80\xA3\x28\x22\x75\xE1\xE9"
+                         "\x90\xE9\xFA\x4B\x00\x10\xAC\x58"
+                         "\x83\x70\xFF\x86\xE6\xAA\x0F\x1F"
+                         "\x95\x63\x73\xA2\x44\xAC\xF8\xA5",
+               .rlen   = 496,
+               .also_non_np = 1,
+               .np     = 2,
+               .tap    = { 496 - 16, 16 },
        },
 };
 
@@ -2386,6 +3399,698 @@ static struct cipher_testvec des3_ede_cbc_dec_tv_template[] = {
                          "\x63\x65\x65\x72\x73\x74\x54\x20"
                          "\x6f\x6f\x4d\x20\x6e\x61\x0a\x79",
                .rlen   = 128,
+       }, { /* Generated with Crypto++ */
+               .key    = "\x9C\xD6\xF3\x9C\xB9\x5A\x67\x00"
+                         "\x5A\x67\x00\x2D\xCE\xEB\x2D\xCE"
+                         "\xEB\xB4\x51\x72\xB4\x51\x72\x1F",
+               .klen   = 24,
+               .iv     = "\xB2\xD7\x48\xED\x06\x44\xF9\x12"
+                         "\xB7\x28\x4D\x83\x24\x59\xF2\x17",
+               .input  = "\xF8\xF6\xB5\x60\x5C\x5A\x75\x84"
+                         "\x87\x81\x53\xBA\xC9\x6F\xEC\xD5"
+                         "\x1E\x68\x8E\x85\x12\x86\x1D\x38"
+                         "\x1C\x91\x40\xCC\x69\x6A\xD5\x35"
+                         "\x0D\x7C\xB5\x07\x7C\x7B\x2A\xAF"
+                         "\x32\xBC\xA1\xB3\x84\x31\x1B\x3C"
+                         "\x0A\x2B\xFA\xD3\x9F\xB0\x8C\x37"
+                         "\x8F\x9D\xA7\x6D\x6C\xFA\xD7\x90"
+                         "\xE3\x69\x54\xED\x3A\xC4\xF1\x6B"
+                         "\xB1\xCC\xFB\x7D\xD8\x8E\x17\x0B"
+                         "\x9C\xF6\x4C\xD6\xFF\x03\x4E\xD9"
+                         "\xE6\xA5\xAD\x25\xE6\x17\x69\x63"
+                         "\x11\x35\x61\x94\x88\x7B\x1C\x48"
+                         "\xF1\x24\x20\x29\x6B\x93\x1A\x8E"
+                         "\x43\x03\x89\xD8\xB1\xDA\x47\x7B"
+                         "\x79\x3A\x83\x76\xDA\xAE\xC6\xBB"
+                         "\x22\xF8\xE8\x3D\x9A\x65\x54\xD8"
+                         "\x4C\xE9\xE7\xE4\x63\x2F\x5C\x73"
+                         "\x5A\xC3\xAE\x46\xA8\xCD\x57\xE6"
+                         "\x67\x88\xA5\x20\x6F\x5F\x97\xC7"
+                         "\xCC\x15\xA2\x0A\x93\xEA\x33\xE7"
+                         "\x03\x5F\xEC\x64\x30\x6F\xEE\xD7"
+                         "\x7E\xDF\xD6\xE9\x6F\x3F\xD6\x1E"
+                         "\xBE\x67\x6C\x5B\x97\xA0\x09\xE6"
+                         "\xEE\xFE\x55\xA3\x29\x65\xE0\x12"
+                         "\xA1\x6A\x8A\x6F\xF2\xE6\xF1\x96"
+                         "\x87\xFB\x9C\x05\xDD\x80\xEC\xFF"
+                         "\xC5\xED\x50\xFE\xFC\x91\xCD\xCE"
+                         "\x25\x2C\x5F\xD9\xAD\x95\x7D\x99"
+                         "\xF0\x05\xC4\x71\x46\x5F\xF9\x0D"
+                         "\xD2\x63\xDF\x9B\x96\x2E\x2B\xA6"
+                         "\x2B\x1C\xD5\xFB\x96\x24\x60\x60"
+                         "\x54\x40\xB8\x62\xA4\xF8\x46\x95"
+                         "\x73\x28\xA3\xA6\x16\x2B\x17\xE7"
+                         "\x7A\xF8\x62\x54\x3B\x64\x69\xE1"
+                         "\x71\x34\x29\x5B\x4E\x05\x9B\xFA"
+                         "\x5E\xF1\x96\xB7\xCE\x16\x9B\x59"
+                         "\xF1\x1A\x4C\x51\x26\xFD\x79\xE2"
+                         "\x3B\x8E\x71\x69\x6A\x91\xB6\x65"
+                         "\x32\x09\xB8\xE4\x09\x1F\xEA\x39"
+                         "\xCE\x20\x65\x9F\xD6\xD1\xC7\xF0"
+                         "\x73\x50\x08\x56\x20\x9B\x94\x23"
+                         "\x14\x39\xB7\x2B\xB1\x2D\x6D\x6F"
+                         "\x41\x5B\xCC\xE2\x18\xAE\x62\x89"
+                         "\x78\x8E\x67\x23\xD0\xFB\x2B\xE5"
+                         "\x25\xC9\x48\x97\xB5\xD3\x17\xD5"
+                         "\x6A\x9F\xA7\x48\x0C\x2B\x73\x3B"
+                         "\x57\x08\xAE\x91\xF2\xB7\x57\x89"
+                         "\xF4\xD0\xB0\x07\xB0\x42\x6C\xAF"
+                         "\x98\x1A\xE7\xD1\xAC\x1E\xB5\x02"
+                         "\xD4\x56\x42\x79\x79\x7F\x2A\x77"
+                         "\x25\xE9\x7D\xC1\x88\x19\x2B\x49"
+                         "\x6F\x46\x59\xAB\x56\x1F\x61\xE0"
+                         "\x0C\x24\x9C\xC9\x5B\x63\xA9\x12"
+                         "\xCF\x88\x96\xB6\xA8\x24\xC6\xA8"
+                         "\x21\x85\x1A\x62\x7E\x34\xBB\xEB"
+                         "\xBD\x02\x2A\xC7\xD8\x89\x80\xC5"
+                         "\xB1\xBB\x60\xA5\x22\xFC\x6F\x38"
+                         "\x02\x80\xA3\x28\x22\x75\xE1\xE9"
+                         "\x90\xE9\xFA\x4B\x00\x10\xAC\x58"
+                         "\x83\x70\xFF\x86\xE6\xAA\x0F\x1F"
+                         "\x95\x63\x73\xA2\x44\xAC\xF8\xA5",
+               .ilen   = 496,
+               .result = "\x05\xEC\x77\xFB\x42\xD5\x59\x20"
+                         "\x8B\x12\x86\x69\xF0\x5B\xCF\x56"
+                         "\x39\xAD\x34\x9F\x66\xEA\x7D\xC4"
+                         "\x48\xD3\xBA\x0D\xB1\x18\xE3\x4A"
+                         "\xFE\x41\x28\x5C\x27\x8E\x11\x85"
+                         "\x6C\xF7\x5E\xC2\x55\x3C\xA0\x0B"
+                         "\x92\x65\xE9\x70\xDB\x4F\xD6\xB9"
+                         "\x00\xB4\x1F\xE6\x49\xFD\x44\x2F"
+                         "\x53\x3A\x8D\x14\x98\x63\xCA\x5D"
+                         "\xC1\xA8\x33\xA7\x0E\x91\x78\xEC"
+                         "\x77\xDE\x42\xD5\xBC\x07\x8B\x12"
+                         "\xE5\x4C\xF0\x5B\x22\x56\x39\x80"
+                         "\x6B\x9F\x66\xC9\x50\xC4\xAF\x36"
+                         "\xBA\x0D\x94\x7F\xE3\x4A\xDD\x41"
+                         "\x28\xB3\x1A\x8E\x11\xF8\x43\xF7"
+                         "\x5E\x21\x55\x3C\x87\x6E\x92\x65"
+                         "\xCC\x57\xDB\xA2\x35\xB9\x00\xEB"
+                         "\x72\xE6\x49\xD0\x44\x2F\xB6\x19"
+                         "\x8D\x14\xFF\x46\xCA\x5D\x24\xA8"
+                         "\x33\x9A\x6D\x91\x78\xC3\x77\xDE"
+                         "\xA1\x08\xBC\x07\xEE\x71\xE5\x4C"
+                         "\xD7\x5B\x22\xB5\x1C\x80\x6B\xF2"
+                         "\x45\xC9\x50\x3B\xAF\x36\x99\x60"
+                         "\x94\x7F\xC6\x4A\xDD\xA4\x0F\xB3"
+                         "\x1A\xED\x74\xF8\x43\x2A\x5E\x21"
+                         "\x88\x13\x87\x6E\xF1\x58\xCC\x57"
+                         "\x3E\xA2\x35\x9C\x67\xEB\x72\xC5"
+                         "\x49\xD0\xBB\x02\xB6\x19\xE0\x4B"
+                         "\xFF\x46\x29\x5D\x24\x8F\x16\x9A"
+                         "\x6D\xF4\x5F\xC3\xAA\x3D\xA1\x08"
+                         "\x93\x7A\xEE\x71\xD8\x4C\xD7\xBE"
+                         "\x01\xB5\x1C\xE7\x4E\xF2\x45\x2C"
+                         "\x50\x3B\x82\x15\x99\x60\xCB\x52"
+                         "\xC6\xA9\x30\xA4\x0F\x96\x79\xED"
+                         "\x74\xDF\x43\x2A\xBD\x04\x88\x13"
+                         "\xFA\x4D\xF1\x58\x23\x57\x3E\x81"
+                         "\x68\x9C\x67\xCE\x51\xC5\xAC\x37"
+                         "\xBB\x02\x95\x7C\xE0\x4B\xD2\x46"
+                         "\x29\xB0\x1B\x8F\x16\xF9\x40\xF4"
+                         "\x5F\x26\xAA\x3D\x84\x6F\x93\x7A"
+                         "\xCD\x54\xD8\xA3\x0A\xBE\x01\xE8"
+                         "\x73\xE7\x4E\xD1\x45\x2C\xB7\x1E"
+                         "\x82\x15\xFC\x47\xCB\x52\x25\xA9"
+                         "\x30\x9B\x62\x96\x79\xC0\x74\xDF"
+                         "\xA6\x09\xBD\x04\xEF\x76\xFA\x4D"
+                         "\xD4\x58\x23\x8A\x1D\x81\x68\xF3"
+                         "\x5A\xCE\x51\x38\xAC\x37\x9E\x61"
+                         "\x95\x7C\xC7\x4B\xD2\xA5\x0C\xB0"
+                         "\x1B\xE2\x75\xF9\x40\x2B\x5F\x26"
+                         "\x89\x10\x84\x6F\xF6\x59\xCD\x54"
+                         "\x3F\xA3\x0A\x9D\x64\xE8\x73\xDA"
+                         "\x4E\xD1\xB8\x03\xB7\x1E\xE1\x48"
+                         "\xFC\x47\x2E\x52\x25\x8C\x17\x9B"
+                         "\x62\xF5\x5C\xC0\xAB\x32\xA6\x09"
+                         "\x90\x7B\xEF\x76\xD9\x4D\xD4\xBF"
+                         "\x06\x8A\x1D\xE4\x4F\xF3\x5A\x2D"
+                         "\x51\x38\x83\x6A\x9E\x61\xC8\x53"
+                         "\xC7\xAE\x31\xA5\x0C\x97\x7E\xE2"
+                         "\x75\xDC\x40\x2B\xB2\x05\x89\x10"
+                         "\xFB\x42\xF6\x59\x20\x54\x3F\x86"
+                         "\x69\x9D\x64\xCF\x56\xDA\xAD\x34"
+                         "\xB8\x03\xEA\x7D\xE1\x48\xD3\x47",
+               .rlen   = 496,
+               .also_non_np = 1,
+               .np     = 2,
+               .tap    = { 496 - 16, 16 },
+       },
+};
+
+static struct cipher_testvec des3_ede_ctr_enc_tv_template[] = {
+       { /* Generated with Crypto++ */
+               .key    = "\x9C\xD6\xF3\x9C\xB9\x5A\x67\x00"
+                         "\x5A\x67\x00\x2D\xCE\xEB\x2D\xCE"
+                         "\xEB\xB4\x51\x72\xB4\x51\x72\x1F",
+               .klen   = 24,
+               .iv     = "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
+                         "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFD",
+               .input  = "\x05\xEC\x77\xFB\x42\xD5\x59\x20"
+                         "\x8B\x12\x86\x69\xF0\x5B\xCF\x56"
+                         "\x39\xAD\x34\x9F\x66\xEA\x7D\xC4"
+                         "\x48\xD3\xBA\x0D\xB1\x18\xE3\x4A"
+                         "\xFE\x41\x28\x5C\x27\x8E\x11\x85"
+                         "\x6C\xF7\x5E\xC2\x55\x3C\xA0\x0B"
+                         "\x92\x65\xE9\x70\xDB\x4F\xD6\xB9"
+                         "\x00\xB4\x1F\xE6\x49\xFD\x44\x2F"
+                         "\x53\x3A\x8D\x14\x98\x63\xCA\x5D"
+                         "\xC1\xA8\x33\xA7\x0E\x91\x78\xEC"
+                         "\x77\xDE\x42\xD5\xBC\x07\x8B\x12"
+                         "\xE5\x4C\xF0\x5B\x22\x56\x39\x80"
+                         "\x6B\x9F\x66\xC9\x50\xC4\xAF\x36"
+                         "\xBA\x0D\x94\x7F\xE3\x4A\xDD\x41"
+                         "\x28\xB3\x1A\x8E\x11\xF8\x43\xF7"
+                         "\x5E\x21\x55\x3C\x87\x6E\x92\x65"
+                         "\xCC\x57\xDB\xA2\x35\xB9\x00\xEB"
+                         "\x72\xE6\x49\xD0\x44\x2F\xB6\x19"
+                         "\x8D\x14\xFF\x46\xCA\x5D\x24\xA8"
+                         "\x33\x9A\x6D\x91\x78\xC3\x77\xDE"
+                         "\xA1\x08\xBC\x07\xEE\x71\xE5\x4C"
+                         "\xD7\x5B\x22\xB5\x1C\x80\x6B\xF2"
+                         "\x45\xC9\x50\x3B\xAF\x36\x99\x60"
+                         "\x94\x7F\xC6\x4A\xDD\xA4\x0F\xB3"
+                         "\x1A\xED\x74\xF8\x43\x2A\x5E\x21"
+                         "\x88\x13\x87\x6E\xF1\x58\xCC\x57"
+                         "\x3E\xA2\x35\x9C\x67\xEB\x72\xC5"
+                         "\x49\xD0\xBB\x02\xB6\x19\xE0\x4B"
+                         "\xFF\x46\x29\x5D\x24\x8F\x16\x9A"
+                         "\x6D\xF4\x5F\xC3\xAA\x3D\xA1\x08"
+                         "\x93\x7A\xEE\x71\xD8\x4C\xD7\xBE"
+                         "\x01\xB5\x1C\xE7\x4E\xF2\x45\x2C"
+                         "\x50\x3B\x82\x15\x99\x60\xCB\x52"
+                         "\xC6\xA9\x30\xA4\x0F\x96\x79\xED"
+                         "\x74\xDF\x43\x2A\xBD\x04\x88\x13"
+                         "\xFA\x4D\xF1\x58\x23\x57\x3E\x81"
+                         "\x68\x9C\x67\xCE\x51\xC5\xAC\x37"
+                         "\xBB\x02\x95\x7C\xE0\x4B\xD2\x46"
+                         "\x29\xB0\x1B\x8F\x16\xF9\x40\xF4"
+                         "\x5F\x26\xAA\x3D\x84\x6F\x93\x7A"
+                         "\xCD\x54\xD8\xA3\x0A\xBE\x01\xE8"
+                         "\x73\xE7\x4E\xD1\x45\x2C\xB7\x1E"
+                         "\x82\x15\xFC\x47\xCB\x52\x25\xA9"
+                         "\x30\x9B\x62\x96\x79\xC0\x74\xDF"
+                         "\xA6\x09\xBD\x04\xEF\x76\xFA\x4D"
+                         "\xD4\x58\x23\x8A\x1D\x81\x68\xF3"
+                         "\x5A\xCE\x51\x38\xAC\x37\x9E\x61"
+                         "\x95\x7C\xC7\x4B\xD2\xA5\x0C\xB0"
+                         "\x1B\xE2\x75\xF9\x40\x2B\x5F\x26"
+                         "\x89\x10\x84\x6F\xF6\x59\xCD\x54"
+                         "\x3F\xA3\x0A\x9D\x64\xE8\x73\xDA"
+                         "\x4E\xD1\xB8\x03\xB7\x1E\xE1\x48"
+                         "\xFC\x47\x2E\x52\x25\x8C\x17\x9B"
+                         "\x62\xF5\x5C\xC0\xAB\x32\xA6\x09"
+                         "\x90\x7B\xEF\x76\xD9\x4D\xD4\xBF"
+                         "\x06\x8A\x1D\xE4\x4F\xF3\x5A\x2D"
+                         "\x51\x38\x83\x6A\x9E\x61\xC8\x53"
+                         "\xC7\xAE\x31\xA5\x0C\x97\x7E\xE2"
+                         "\x75\xDC\x40\x2B\xB2\x05\x89\x10"
+                         "\xFB\x42\xF6\x59\x20\x54\x3F\x86"
+                         "\x69\x9D\x64\xCF\x56\xDA\xAD\x34"
+                         "\xB8\x03\xEA\x7D\xE1\x48\xD3\x47",
+               .ilen   = 496,
+               .result = "\x07\xC2\x08\x20\x72\x1F\x49\xEF"
+                         "\x19\xCD\x6F\x32\x53\x05\x22\x15"
+                         "\xA2\x85\x2B\xDB\x85\xD2\xD8\xB9"
+                         "\xDD\x0D\x1B\x45\xCB\x69\x11\xD4"
+                         "\xEA\xBE\xB2\x45\x5D\x0C\xAE\xBE"
+                         "\xA0\xC1\x27\xAC\x65\x9F\x53\x7E"
+                         "\xAF\xC2\x1B\xB5\xB8\x6D\x36\x0C"
+                         "\x25\xC0\xF8\x6D\x0B\x29\x01\xDA"
+                         "\x13\x78\xDC\x89\x12\x12\x43\xFA"
+                         "\xF6\x12\xEF\x8D\x87\x62\x78\x83"
+                         "\xE2\xBE\x41\x20\x4C\x6D\x35\x1B"
+                         "\xD1\x0C\x30\xCF\xE2\xDE\x2B\x03"
+                         "\xBF\x45\x73\xD4\xE5\x59\x95\xD1"
+                         "\xB3\x9B\x27\x62\x97\xBD\xDE\x7F"
+                         "\xA4\xD2\x39\x80\xAA\x50\x23\xF0"
+                         "\x74\x88\x3D\xA8\x6A\x18\x79\x3B"
+                         "\xC4\x96\x6C\x8D\x22\x40\x92\x6E"
+                         "\xD6\xAD\x2A\x1F\xDE\x63\xC0\xE7"
+                         "\x07\xF7\x2D\xF7\xB5\xF3\xF0\xCC"
+                         "\x01\x7C\x2A\x9B\xC2\x10\xCA\xAA"
+                         "\xFD\x2B\x3F\xC5\xF3\xF6\xFC\x9B"
+                         "\x45\xDB\x53\xE4\x5B\xF3\xC9\x7B"
+                         "\x8E\x52\xFF\xC8\x02\xB8\xAC\x9D"
+                         "\xA1\x00\x39\xDA\x3D\x2D\x0E\x01"
+                         "\x09\x7D\x8D\x5E\xBE\x53\xB9\xB0"
+                         "\x8E\xE7\xE2\x96\x6A\xB2\x78\xEA"
+                         "\xDE\x23\x8B\xA5\xFA\x5C\xE3\xDA"
+                         "\xBF\x8E\x31\x6A\x55\xD1\x6A\xB2"
+                         "\xB5\x46\x6F\xA5\xF0\xEE\xBA\x1F"
+                         "\x9F\x98\xB0\x66\x4F\xD0\x3F\xA9"
+                         "\xDF\x5F\x58\xC4\xF4\xFF\x75\x5C"
+                         "\x40\x3A\x09\x7E\x6E\x1C\x97\xD4"
+                         "\xCC\xE7\xE7\x71\xCF\x0B\x15\x08"
+                         "\x71\xFA\x07\x97\xCD\xE6\xCA\x1D"
+                         "\x14\x28\x0C\xCF\x99\x13\x7A\xF1"
+                         "\xEB\xFA\xFA\x92\x07\xDE\x1D\xA1"
+                         "\xD3\x36\x69\xFE\x51\x4D\x9F\x2E"
+                         "\x83\x37\x4F\x1F\x48\x30\xED\x04"
+                         "\x4D\xA4\xEF\x3A\xCA\x76\xF4\x1C"
+                         "\x41\x8F\x63\x37\x78\x2F\x86\xA6"
+                         "\xEF\x41\x7E\xD2\xAF\x88\xAB\x67"
+                         "\x52\x71\xC3\x8E\xF8\x26\x93\x72"
+                         "\xAA\xD6\x0E\xE7\x0B\x46\xB1\x3A"
+                         "\xB4\x08\xA9\xA8\xA0\xCF\x20\x0C"
+                         "\x52\xBC\x8B\x05\x56\xB2\xBC\x31"
+                         "\x9B\x74\xB9\x29\x29\x96\x9A\x50"
+                         "\xDC\x45\xDC\x1A\xEB\x0C\x64\xD4"
+                         "\xD3\x05\x7E\x59\x55\xC3\xF4\x90"
+                         "\xC2\xAB\xF8\x9B\x8A\xDA\xCE\xA1"
+                         "\xC3\xF4\xAD\x77\xDD\x44\xC8\xAC"
+                         "\xA3\xF1\xC9\xD2\x19\x5C\xB0\xCA"
+                         "\xA2\x34\xC1\xF7\x6C\xFD\xAC\x65"
+                         "\x32\xDC\x48\xC4\xF2\x00\x6B\x77"
+                         "\xF1\x7D\x76\xAC\xC0\x31\x63\x2A"
+                         "\xA5\x3A\x62\xC8\x91\xB1\x03\x65"
+                         "\xCB\x43\xD1\x06\xDF\xC3\x67\xBC"
+                         "\xDC\xE0\xCD\x35\xCE\x49\x65\xA0"
+                         "\x52\x7B\xA7\x0D\x07\xA9\x1B\xB0"
+                         "\x40\x77\x72\xC2\xEA\x0E\x3A\x78"
+                         "\x46\xB9\x91\xB6\xE7\x3D\x51\x42"
+                         "\xFD\x51\xB0\xC6\x2C\x63\x13\x78"
+                         "\x5C\xEE\xFC\xCF\xC4\x70\x00\x34",
+               .rlen   = 496,
+               .also_non_np = 1,
+               .np     = 2,
+               .tap    = { 496 - 16, 16 },
+       }, { /* Generated with Crypto++ */
+               .key    = "\x9C\xD6\xF3\x9C\xB9\x5A\x67\x00"
+                         "\x5A\x67\x00\x2D\xCE\xEB\x2D\xCE"
+                         "\xEB\xB4\x51\x72\xB4\x51\x72\x1F",
+               .klen   = 24,
+               .iv     = "\xB2\xD7\x48\xED\x06\x44\xF9\x12"
+                         "\xB7\x28\x4D\x83\x24\x59\xF2\x17",
+               .input  = "\x05\xEC\x77\xFB\x42\xD5\x59\x20"
+                         "\x8B\x12\x86\x69\xF0\x5B\xCF\x56"
+                         "\x39\xAD\x34\x9F\x66\xEA\x7D\xC4"
+                         "\x48\xD3\xBA\x0D\xB1\x18\xE3\x4A"
+                         "\xFE\x41\x28\x5C\x27\x8E\x11\x85"
+                         "\x6C\xF7\x5E\xC2\x55\x3C\xA0\x0B"
+                         "\x92\x65\xE9\x70\xDB\x4F\xD6\xB9"
+                         "\x00\xB4\x1F\xE6\x49\xFD\x44\x2F"
+                         "\x53\x3A\x8D\x14\x98\x63\xCA\x5D"
+                         "\xC1\xA8\x33\xA7\x0E\x91\x78\xEC"
+                         "\x77\xDE\x42\xD5\xBC\x07\x8B\x12"
+                         "\xE5\x4C\xF0\x5B\x22\x56\x39\x80"
+                         "\x6B\x9F\x66\xC9\x50\xC4\xAF\x36"
+                         "\xBA\x0D\x94\x7F\xE3\x4A\xDD\x41"
+                         "\x28\xB3\x1A\x8E\x11\xF8\x43\xF7"
+                         "\x5E\x21\x55\x3C\x87\x6E\x92\x65"
+                         "\xCC\x57\xDB\xA2\x35\xB9\x00\xEB"
+                         "\x72\xE6\x49\xD0\x44\x2F\xB6\x19"
+                         "\x8D\x14\xFF\x46\xCA\x5D\x24\xA8"
+                         "\x33\x9A\x6D\x91\x78\xC3\x77\xDE"
+                         "\xA1\x08\xBC\x07\xEE\x71\xE5\x4C"
+                         "\xD7\x5B\x22\xB5\x1C\x80\x6B\xF2"
+                         "\x45\xC9\x50\x3B\xAF\x36\x99\x60"
+                         "\x94\x7F\xC6\x4A\xDD\xA4\x0F\xB3"
+                         "\x1A\xED\x74\xF8\x43\x2A\x5E\x21"
+                         "\x88\x13\x87\x6E\xF1\x58\xCC\x57"
+                         "\x3E\xA2\x35\x9C\x67\xEB\x72\xC5"
+                         "\x49\xD0\xBB\x02\xB6\x19\xE0\x4B"
+                         "\xFF\x46\x29\x5D\x24\x8F\x16\x9A"
+                         "\x6D\xF4\x5F\xC3\xAA\x3D\xA1\x08"
+                         "\x93\x7A\xEE\x71\xD8\x4C\xD7\xBE"
+                         "\x01\xB5\x1C\xE7\x4E\xF2\x45\x2C"
+                         "\x50\x3B\x82\x15\x99\x60\xCB\x52"
+                         "\xC6\xA9\x30\xA4\x0F\x96\x79\xED"
+                         "\x74\xDF\x43\x2A\xBD\x04\x88\x13"
+                         "\xFA\x4D\xF1\x58\x23\x57\x3E\x81"
+                         "\x68\x9C\x67\xCE\x51\xC5\xAC\x37"
+                         "\xBB\x02\x95\x7C\xE0\x4B\xD2\x46"
+                         "\x29\xB0\x1B\x8F\x16\xF9\x40\xF4"
+                         "\x5F\x26\xAA\x3D\x84\x6F\x93\x7A"
+                         "\xCD\x54\xD8\xA3\x0A\xBE\x01\xE8"
+                         "\x73\xE7\x4E\xD1\x45\x2C\xB7\x1E"
+                         "\x82\x15\xFC\x47\xCB\x52\x25\xA9"
+                         "\x30\x9B\x62\x96\x79\xC0\x74\xDF"
+                         "\xA6\x09\xBD\x04\xEF\x76\xFA\x4D"
+                         "\xD4\x58\x23\x8A\x1D\x81\x68\xF3"
+                         "\x5A\xCE\x51\x38\xAC\x37\x9E\x61"
+                         "\x95\x7C\xC7\x4B\xD2\xA5\x0C\xB0"
+                         "\x1B\xE2\x75\xF9\x40\x2B\x5F\x26"
+                         "\x89\x10\x84\x6F\xF6\x59\xCD\x54"
+                         "\x3F\xA3\x0A\x9D\x64\xE8\x73\xDA"
+                         "\x4E\xD1\xB8\x03\xB7\x1E\xE1\x48"
+                         "\xFC\x47\x2E\x52\x25\x8C\x17\x9B"
+                         "\x62\xF5\x5C\xC0\xAB\x32\xA6\x09"
+                         "\x90\x7B\xEF\x76\xD9\x4D\xD4\xBF"
+                         "\x06\x8A\x1D\xE4\x4F\xF3\x5A\x2D"
+                         "\x51\x38\x83\x6A\x9E\x61\xC8\x53"
+                         "\xC7\xAE\x31\xA5\x0C\x97\x7E\xE2"
+                         "\x75\xDC\x40\x2B\xB2\x05\x89\x10"
+                         "\xFB\x42\xF6\x59\x20\x54\x3F\x86"
+                         "\x69\x9D\x64\xCF\x56\xDA\xAD\x34"
+                         "\xB8\x03\xEA\x7D\xE1\x48\xD3\x47"
+                         "\x2E\xB1\x18",
+               .ilen   = 499,
+               .result = "\x23\xFF\x5C\x99\x75\xBB\x1F\xD4"
+                         "\xBC\x27\x9D\x36\x60\xA9\xC9\xF7"
+                         "\x94\x9D\x1B\xFF\x8E\x95\x57\x89"
+                         "\x8C\x2E\x33\x70\x43\x61\xE6\xD2"
+                         "\x82\x33\x63\xB6\xC4\x34\x5E\xF8"
+                         "\x96\x07\xA7\xD2\x3B\x8E\xC9\xAA"
+                         "\x7C\xA0\x55\x89\x2E\xE1\x85\x25"
+                         "\x14\x04\xDA\x6B\xE0\xEE\x56\xCF"
+                         "\x08\x2E\x69\xD4\x54\xDE\x22\x84"
+                         "\x69\xA6\xA7\xD3\x3A\x9A\xE8\x05"
+                         "\x63\xDB\xBF\x46\x3A\x26\x2E\x0F"
+                         "\x58\x5C\x46\xEA\x07\x40\xDA\xE1"
+                         "\x14\x1D\xCD\x4F\x06\xC0\xCA\x54"
+                         "\x1E\xC9\x45\x85\x67\x7C\xC2\xB5"
+                         "\x97\x5D\x61\x78\x2E\x46\xEC\x6A"
+                         "\x53\xF4\xD0\xAE\xFA\xB4\x86\x29"
+                         "\x9F\x17\x33\x24\xD8\xB9\xB2\x05"
+                         "\x93\x88\xEA\xF7\xA0\x70\x69\x49"
+                         "\x88\x6B\x73\x40\x41\x8D\xD9\xD9"
+                         "\x7E\x78\xE9\xBE\x6C\x14\x22\x7A"
+                         "\x66\xE1\xDA\xED\x10\xFF\x69\x1D"
+                         "\xB9\xAA\xF2\x56\x72\x1B\x23\xE2"
+                         "\x45\x54\x8B\xA3\x70\x23\xB4\x5E"
+                         "\x8E\x96\xC9\x05\x00\xB3\xB6\xC2"
+                         "\x2A\x02\x43\x7A\x62\xD5\xC8\xD2"
+                         "\xC2\xD0\xE4\x78\xA1\x7B\x3E\xE8"
+                         "\x9F\x7F\x7D\x40\x54\x30\x3B\xC0"
+                         "\xA5\x54\xFD\xCA\x25\xEC\x44\x3E"
+                         "\x1A\x54\x7F\x88\xD0\xE1\xFE\x71"
+                         "\xCE\x05\x49\x89\xBA\xD6\x72\xE7"
+                         "\xD6\x5D\x3F\xA2\xD9\xAB\xC5\x02"
+                         "\xD6\x43\x22\xAF\xA2\xE4\x80\x85"
+                         "\xD7\x87\xB9\xEA\x43\xDB\xC8\xEF"
+                         "\x5C\x82\x2E\x98\x0D\x30\x41\x6B"
+                         "\x08\x48\x8D\xF0\xF8\x60\xD7\x9D"
+                         "\xE9\xDE\x40\xAD\x0D\xAD\x0D\x58"
+                         "\x2A\x98\x35\xFE\xF7\xDD\x4B\x40"
+                         "\xDE\xB0\x05\xD9\x7B\x09\x4D\xBC"
+                         "\x42\xC0\xF1\x15\x0B\xFA\x26\x6B"
+                         "\xC6\x12\x13\x4F\xCB\x35\xBA\x35"
+                         "\xDD\x7A\x36\x9C\x12\x57\x55\x83"
+                         "\x78\x58\x09\xD0\xB0\xCF\x7C\x5C"
+                         "\x38\xCF\xBD\x79\x5B\x13\x4D\x97"
+                         "\xC1\x85\x6F\x97\xC9\xE8\xC2\xA4"
+                         "\x98\xE2\xBD\x77\x6B\x53\x39\x1A"
+                         "\x28\x10\xE7\xE0\xE7\xDE\x9D\x69"
+                         "\x78\x6F\x8E\xD2\xD9\x5D\xD2\x15"
+                         "\x9E\xB5\x4D\x8C\xC0\x78\x22\x2F"
+                         "\x17\x11\x2E\x99\xD7\xE3\xA4\x4F"
+                         "\x65\xA5\x6B\x03\x2C\x35\x6F\xDA"
+                         "\x8A\x19\x08\xE1\x08\x48\x59\x51"
+                         "\x53\x4B\xD1\xDF\xDA\x14\x50\x5F"
+                         "\xDF\xB5\x8C\xDF\xC6\xFD\x85\xFA"
+                         "\xD4\xF9\x64\x45\x65\x0D\x7D\xF4"
+                         "\xC8\xCD\x3F\x32\xAF\xDD\x30\xED"
+                         "\x7B\xAA\xAC\xF0\xDA\x7F\xDF\x75"
+                         "\x1C\xA4\xF1\xCB\x5E\x4F\x0B\xB4"
+                         "\x97\x73\x28\xDE\xCF\xAF\x82\xBD"
+                         "\xC4\xBA\xB4\x9C\x0D\x16\x77\x42"
+                         "\x42\x39\x7C\x53\xA4\xD4\xDD\x40"
+                         "\x5C\x60\x1F\x6E\xA7\xE2\xDC\xE7"
+                         "\x32\x0F\x05\x2F\xF2\x4C\x95\x3B"
+                         "\xF2\x79\xD9",
+               .rlen   = 499,
+               .also_non_np = 1,
+               .np     = 2,
+               .tap    = { 499 - 16, 16 },
+       },
+};
+
+static struct cipher_testvec des3_ede_ctr_dec_tv_template[] = {
+       { /* Generated with Crypto++ */
+               .key    = "\x9C\xD6\xF3\x9C\xB9\x5A\x67\x00"
+                         "\x5A\x67\x00\x2D\xCE\xEB\x2D\xCE"
+                         "\xEB\xB4\x51\x72\xB4\x51\x72\x1F",
+               .klen   = 24,
+               .iv     = "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
+                         "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFD",
+               .input  = "\x07\xC2\x08\x20\x72\x1F\x49\xEF"
+                         "\x19\xCD\x6F\x32\x53\x05\x22\x15"
+                         "\xA2\x85\x2B\xDB\x85\xD2\xD8\xB9"
+                         "\xDD\x0D\x1B\x45\xCB\x69\x11\xD4"
+                         "\xEA\xBE\xB2\x45\x5D\x0C\xAE\xBE"
+                         "\xA0\xC1\x27\xAC\x65\x9F\x53\x7E"
+                         "\xAF\xC2\x1B\xB5\xB8\x6D\x36\x0C"
+                         "\x25\xC0\xF8\x6D\x0B\x29\x01\xDA"
+                         "\x13\x78\xDC\x89\x12\x12\x43\xFA"
+                         "\xF6\x12\xEF\x8D\x87\x62\x78\x83"
+                         "\xE2\xBE\x41\x20\x4C\x6D\x35\x1B"
+                         "\xD1\x0C\x30\xCF\xE2\xDE\x2B\x03"
+                         "\xBF\x45\x73\xD4\xE5\x59\x95\xD1"
+                         "\xB3\x9B\x27\x62\x97\xBD\xDE\x7F"
+                         "\xA4\xD2\x39\x80\xAA\x50\x23\xF0"
+                         "\x74\x88\x3D\xA8\x6A\x18\x79\x3B"
+                         "\xC4\x96\x6C\x8D\x22\x40\x92\x6E"
+                         "\xD6\xAD\x2A\x1F\xDE\x63\xC0\xE7"
+                         "\x07\xF7\x2D\xF7\xB5\xF3\xF0\xCC"
+                         "\x01\x7C\x2A\x9B\xC2\x10\xCA\xAA"
+                         "\xFD\x2B\x3F\xC5\xF3\xF6\xFC\x9B"
+                         "\x45\xDB\x53\xE4\x5B\xF3\xC9\x7B"
+                         "\x8E\x52\xFF\xC8\x02\xB8\xAC\x9D"
+                         "\xA1\x00\x39\xDA\x3D\x2D\x0E\x01"
+                         "\x09\x7D\x8D\x5E\xBE\x53\xB9\xB0"
+                         "\x8E\xE7\xE2\x96\x6A\xB2\x78\xEA"
+                         "\xDE\x23\x8B\xA5\xFA\x5C\xE3\xDA"
+                         "\xBF\x8E\x31\x6A\x55\xD1\x6A\xB2"
+                         "\xB5\x46\x6F\xA5\xF0\xEE\xBA\x1F"
+                         "\x9F\x98\xB0\x66\x4F\xD0\x3F\xA9"
+                         "\xDF\x5F\x58\xC4\xF4\xFF\x75\x5C"
+                         "\x40\x3A\x09\x7E\x6E\x1C\x97\xD4"
+                         "\xCC\xE7\xE7\x71\xCF\x0B\x15\x08"
+                         "\x71\xFA\x07\x97\xCD\xE6\xCA\x1D"
+                         "\x14\x28\x0C\xCF\x99\x13\x7A\xF1"
+                         "\xEB\xFA\xFA\x92\x07\xDE\x1D\xA1"
+                         "\xD3\x36\x69\xFE\x51\x4D\x9F\x2E"
+                         "\x83\x37\x4F\x1F\x48\x30\xED\x04"
+                         "\x4D\xA4\xEF\x3A\xCA\x76\xF4\x1C"
+                         "\x41\x8F\x63\x37\x78\x2F\x86\xA6"
+                         "\xEF\x41\x7E\xD2\xAF\x88\xAB\x67"
+                         "\x52\x71\xC3\x8E\xF8\x26\x93\x72"
+                         "\xAA\xD6\x0E\xE7\x0B\x46\xB1\x3A"
+                         "\xB4\x08\xA9\xA8\xA0\xCF\x20\x0C"
+                         "\x52\xBC\x8B\x05\x56\xB2\xBC\x31"
+                         "\x9B\x74\xB9\x29\x29\x96\x9A\x50"
+                         "\xDC\x45\xDC\x1A\xEB\x0C\x64\xD4"
+                         "\xD3\x05\x7E\x59\x55\xC3\xF4\x90"
+                         "\xC2\xAB\xF8\x9B\x8A\xDA\xCE\xA1"
+                         "\xC3\xF4\xAD\x77\xDD\x44\xC8\xAC"
+                         "\xA3\xF1\xC9\xD2\x19\x5C\xB0\xCA"
+                         "\xA2\x34\xC1\xF7\x6C\xFD\xAC\x65"
+                         "\x32\xDC\x48\xC4\xF2\x00\x6B\x77"
+                         "\xF1\x7D\x76\xAC\xC0\x31\x63\x2A"
+                         "\xA5\x3A\x62\xC8\x91\xB1\x03\x65"
+                         "\xCB\x43\xD1\x06\xDF\xC3\x67\xBC"
+                         "\xDC\xE0\xCD\x35\xCE\x49\x65\xA0"
+                         "\x52\x7B\xA7\x0D\x07\xA9\x1B\xB0"
+                         "\x40\x77\x72\xC2\xEA\x0E\x3A\x78"
+                         "\x46\xB9\x91\xB6\xE7\x3D\x51\x42"
+                         "\xFD\x51\xB0\xC6\x2C\x63\x13\x78"
+                         "\x5C\xEE\xFC\xCF\xC4\x70\x00\x34",
+               .ilen   = 496,
+               .result = "\x05\xEC\x77\xFB\x42\xD5\x59\x20"
+                         "\x8B\x12\x86\x69\xF0\x5B\xCF\x56"
+                         "\x39\xAD\x34\x9F\x66\xEA\x7D\xC4"
+                         "\x48\xD3\xBA\x0D\xB1\x18\xE3\x4A"
+                         "\xFE\x41\x28\x5C\x27\x8E\x11\x85"
+                         "\x6C\xF7\x5E\xC2\x55\x3C\xA0\x0B"
+                         "\x92\x65\xE9\x70\xDB\x4F\xD6\xB9"
+                         "\x00\xB4\x1F\xE6\x49\xFD\x44\x2F"
+                         "\x53\x3A\x8D\x14\x98\x63\xCA\x5D"
+                         "\xC1\xA8\x33\xA7\x0E\x91\x78\xEC"
+                         "\x77\xDE\x42\xD5\xBC\x07\x8B\x12"
+                         "\xE5\x4C\xF0\x5B\x22\x56\x39\x80"
+                         "\x6B\x9F\x66\xC9\x50\xC4\xAF\x36"
+                         "\xBA\x0D\x94\x7F\xE3\x4A\xDD\x41"
+                         "\x28\xB3\x1A\x8E\x11\xF8\x43\xF7"
+                         "\x5E\x21\x55\x3C\x87\x6E\x92\x65"
+                         "\xCC\x57\xDB\xA2\x35\xB9\x00\xEB"
+                         "\x72\xE6\x49\xD0\x44\x2F\xB6\x19"
+                         "\x8D\x14\xFF\x46\xCA\x5D\x24\xA8"
+                         "\x33\x9A\x6D\x91\x78\xC3\x77\xDE"
+                         "\xA1\x08\xBC\x07\xEE\x71\xE5\x4C"
+                         "\xD7\x5B\x22\xB5\x1C\x80\x6B\xF2"
+                         "\x45\xC9\x50\x3B\xAF\x36\x99\x60"
+                         "\x94\x7F\xC6\x4A\xDD\xA4\x0F\xB3"
+                         "\x1A\xED\x74\xF8\x43\x2A\x5E\x21"
+                         "\x88\x13\x87\x6E\xF1\x58\xCC\x57"
+                         "\x3E\xA2\x35\x9C\x67\xEB\x72\xC5"
+                         "\x49\xD0\xBB\x02\xB6\x19\xE0\x4B"
+                         "\xFF\x46\x29\x5D\x24\x8F\x16\x9A"
+                         "\x6D\xF4\x5F\xC3\xAA\x3D\xA1\x08"
+                         "\x93\x7A\xEE\x71\xD8\x4C\xD7\xBE"
+                         "\x01\xB5\x1C\xE7\x4E\xF2\x45\x2C"
+                         "\x50\x3B\x82\x15\x99\x60\xCB\x52"
+                         "\xC6\xA9\x30\xA4\x0F\x96\x79\xED"
+                         "\x74\xDF\x43\x2A\xBD\x04\x88\x13"
+                         "\xFA\x4D\xF1\x58\x23\x57\x3E\x81"
+                         "\x68\x9C\x67\xCE\x51\xC5\xAC\x37"
+                         "\xBB\x02\x95\x7C\xE0\x4B\xD2\x46"
+                         "\x29\xB0\x1B\x8F\x16\xF9\x40\xF4"
+                         "\x5F\x26\xAA\x3D\x84\x6F\x93\x7A"
+                         "\xCD\x54\xD8\xA3\x0A\xBE\x01\xE8"
+                         "\x73\xE7\x4E\xD1\x45\x2C\xB7\x1E"
+                         "\x82\x15\xFC\x47\xCB\x52\x25\xA9"
+                         "\x30\x9B\x62\x96\x79\xC0\x74\xDF"
+                         "\xA6\x09\xBD\x04\xEF\x76\xFA\x4D"
+                         "\xD4\x58\x23\x8A\x1D\x81\x68\xF3"
+                         "\x5A\xCE\x51\x38\xAC\x37\x9E\x61"
+                         "\x95\x7C\xC7\x4B\xD2\xA5\x0C\xB0"
+                         "\x1B\xE2\x75\xF9\x40\x2B\x5F\x26"
+                         "\x89\x10\x84\x6F\xF6\x59\xCD\x54"
+                         "\x3F\xA3\x0A\x9D\x64\xE8\x73\xDA"
+                         "\x4E\xD1\xB8\x03\xB7\x1E\xE1\x48"
+                         "\xFC\x47\x2E\x52\x25\x8C\x17\x9B"
+                         "\x62\xF5\x5C\xC0\xAB\x32\xA6\x09"
+                         "\x90\x7B\xEF\x76\xD9\x4D\xD4\xBF"
+                         "\x06\x8A\x1D\xE4\x4F\xF3\x5A\x2D"
+                         "\x51\x38\x83\x6A\x9E\x61\xC8\x53"
+                         "\xC7\xAE\x31\xA5\x0C\x97\x7E\xE2"
+                         "\x75\xDC\x40\x2B\xB2\x05\x89\x10"
+                         "\xFB\x42\xF6\x59\x20\x54\x3F\x86"
+                         "\x69\x9D\x64\xCF\x56\xDA\xAD\x34"
+                         "\xB8\x03\xEA\x7D\xE1\x48\xD3\x47",
+               .rlen   = 496,
+               .also_non_np = 1,
+               .np     = 2,
+               .tap    = { 496 - 16, 16 },
+       }, { /* Generated with Crypto++ */
+               .key    = "\x9C\xD6\xF3\x9C\xB9\x5A\x67\x00"
+                         "\x5A\x67\x00\x2D\xCE\xEB\x2D\xCE"
+                         "\xEB\xB4\x51\x72\xB4\x51\x72\x1F",
+               .klen   = 24,
+               .iv     = "\xB2\xD7\x48\xED\x06\x44\xF9\x12"
+                         "\xB7\x28\x4D\x83\x24\x59\xF2\x17",
+               .input  = "\x23\xFF\x5C\x99\x75\xBB\x1F\xD4"
+                         "\xBC\x27\x9D\x36\x60\xA9\xC9\xF7"
+                         "\x94\x9D\x1B\xFF\x8E\x95\x57\x89"
+                         "\x8C\x2E\x33\x70\x43\x61\xE6\xD2"
+                         "\x82\x33\x63\xB6\xC4\x34\x5E\xF8"
+                         "\x96\x07\xA7\xD2\x3B\x8E\xC9\xAA"
+                         "\x7C\xA0\x55\x89\x2E\xE1\x85\x25"
+                         "\x14\x04\xDA\x6B\xE0\xEE\x56\xCF"
+                         "\x08\x2E\x69\xD4\x54\xDE\x22\x84"
+                         "\x69\xA6\xA7\xD3\x3A\x9A\xE8\x05"
+                         "\x63\xDB\xBF\x46\x3A\x26\x2E\x0F"
+                         "\x58\x5C\x46\xEA\x07\x40\xDA\xE1"
+                         "\x14\x1D\xCD\x4F\x06\xC0\xCA\x54"
+                         "\x1E\xC9\x45\x85\x67\x7C\xC2\xB5"
+                         "\x97\x5D\x61\x78\x2E\x46\xEC\x6A"
+                         "\x53\xF4\xD0\xAE\xFA\xB4\x86\x29"
+                         "\x9F\x17\x33\x24\xD8\xB9\xB2\x05"
+                         "\x93\x88\xEA\xF7\xA0\x70\x69\x49"
+                         "\x88\x6B\x73\x40\x41\x8D\xD9\xD9"
+                         "\x7E\x78\xE9\xBE\x6C\x14\x22\x7A"
+                         "\x66\xE1\xDA\xED\x10\xFF\x69\x1D"
+                         "\xB9\xAA\xF2\x56\x72\x1B\x23\xE2"
+                         "\x45\x54\x8B\xA3\x70\x23\xB4\x5E"
+                         "\x8E\x96\xC9\x05\x00\xB3\xB6\xC2"
+                         "\x2A\x02\x43\x7A\x62\xD5\xC8\xD2"
+                         "\xC2\xD0\xE4\x78\xA1\x7B\x3E\xE8"
+                         "\x9F\x7F\x7D\x40\x54\x30\x3B\xC0"
+                         "\xA5\x54\xFD\xCA\x25\xEC\x44\x3E"
+                         "\x1A\x54\x7F\x88\xD0\xE1\xFE\x71"
+                         "\xCE\x05\x49\x89\xBA\xD6\x72\xE7"
+                         "\xD6\x5D\x3F\xA2\xD9\xAB\xC5\x02"
+                         "\xD6\x43\x22\xAF\xA2\xE4\x80\x85"
+                         "\xD7\x87\xB9\xEA\x43\xDB\xC8\xEF"
+                         "\x5C\x82\x2E\x98\x0D\x30\x41\x6B"
+                         "\x08\x48\x8D\xF0\xF8\x60\xD7\x9D"
+                         "\xE9\xDE\x40\xAD\x0D\xAD\x0D\x58"
+                         "\x2A\x98\x35\xFE\xF7\xDD\x4B\x40"
+                         "\xDE\xB0\x05\xD9\x7B\x09\x4D\xBC"
+                         "\x42\xC0\xF1\x15\x0B\xFA\x26\x6B"
+                         "\xC6\x12\x13\x4F\xCB\x35\xBA\x35"
+                         "\xDD\x7A\x36\x9C\x12\x57\x55\x83"
+                         "\x78\x58\x09\xD0\xB0\xCF\x7C\x5C"
+                         "\x38\xCF\xBD\x79\x5B\x13\x4D\x97"
+                         "\xC1\x85\x6F\x97\xC9\xE8\xC2\xA4"
+                         "\x98\xE2\xBD\x77\x6B\x53\x39\x1A"
+                         "\x28\x10\xE7\xE0\xE7\xDE\x9D\x69"
+                         "\x78\x6F\x8E\xD2\xD9\x5D\xD2\x15"
+                         "\x9E\xB5\x4D\x8C\xC0\x78\x22\x2F"
+                         "\x17\x11\x2E\x99\xD7\xE3\xA4\x4F"
+                         "\x65\xA5\x6B\x03\x2C\x35\x6F\xDA"
+                         "\x8A\x19\x08\xE1\x08\x48\x59\x51"
+                         "\x53\x4B\xD1\xDF\xDA\x14\x50\x5F"
+                         "\xDF\xB5\x8C\xDF\xC6\xFD\x85\xFA"
+                         "\xD4\xF9\x64\x45\x65\x0D\x7D\xF4"
+                         "\xC8\xCD\x3F\x32\xAF\xDD\x30\xED"
+                         "\x7B\xAA\xAC\xF0\xDA\x7F\xDF\x75"
+                         "\x1C\xA4\xF1\xCB\x5E\x4F\x0B\xB4"
+                         "\x97\x73\x28\xDE\xCF\xAF\x82\xBD"
+                         "\xC4\xBA\xB4\x9C\x0D\x16\x77\x42"
+                         "\x42\x39\x7C\x53\xA4\xD4\xDD\x40"
+                         "\x5C\x60\x1F\x6E\xA7\xE2\xDC\xE7"
+                         "\x32\x0F\x05\x2F\xF2\x4C\x95\x3B"
+                         "\xF2\x79\xD9",
+               .ilen   = 499,
+               .result = "\x05\xEC\x77\xFB\x42\xD5\x59\x20"
+                         "\x8B\x12\x86\x69\xF0\x5B\xCF\x56"
+                         "\x39\xAD\x34\x9F\x66\xEA\x7D\xC4"
+                         "\x48\xD3\xBA\x0D\xB1\x18\xE3\x4A"
+                         "\xFE\x41\x28\x5C\x27\x8E\x11\x85"
+                         "\x6C\xF7\x5E\xC2\x55\x3C\xA0\x0B"
+                         "\x92\x65\xE9\x70\xDB\x4F\xD6\xB9"
+                         "\x00\xB4\x1F\xE6\x49\xFD\x44\x2F"
+                         "\x53\x3A\x8D\x14\x98\x63\xCA\x5D"
+                         "\xC1\xA8\x33\xA7\x0E\x91\x78\xEC"
+                         "\x77\xDE\x42\xD5\xBC\x07\x8B\x12"
+                         "\xE5\x4C\xF0\x5B\x22\x56\x39\x80"
+                         "\x6B\x9F\x66\xC9\x50\xC4\xAF\x36"
+                         "\xBA\x0D\x94\x7F\xE3\x4A\xDD\x41"
+                         "\x28\xB3\x1A\x8E\x11\xF8\x43\xF7"
+                         "\x5E\x21\x55\x3C\x87\x6E\x92\x65"
+                         "\xCC\x57\xDB\xA2\x35\xB9\x00\xEB"
+                         "\x72\xE6\x49\xD0\x44\x2F\xB6\x19"
+                         "\x8D\x14\xFF\x46\xCA\x5D\x24\xA8"
+                         "\x33\x9A\x6D\x91\x78\xC3\x77\xDE"
+                         "\xA1\x08\xBC\x07\xEE\x71\xE5\x4C"
+                         "\xD7\x5B\x22\xB5\x1C\x80\x6B\xF2"
+                         "\x45\xC9\x50\x3B\xAF\x36\x99\x60"
+                         "\x94\x7F\xC6\x4A\xDD\xA4\x0F\xB3"
+                         "\x1A\xED\x74\xF8\x43\x2A\x5E\x21"
+                         "\x88\x13\x87\x6E\xF1\x58\xCC\x57"
+                         "\x3E\xA2\x35\x9C\x67\xEB\x72\xC5"
+                         "\x49\xD0\xBB\x02\xB6\x19\xE0\x4B"
+                         "\xFF\x46\x29\x5D\x24\x8F\x16\x9A"
+                         "\x6D\xF4\x5F\xC3\xAA\x3D\xA1\x08"
+                         "\x93\x7A\xEE\x71\xD8\x4C\xD7\xBE"
+                         "\x01\xB5\x1C\xE7\x4E\xF2\x45\x2C"
+                         "\x50\x3B\x82\x15\x99\x60\xCB\x52"
+                         "\xC6\xA9\x30\xA4\x0F\x96\x79\xED"
+                         "\x74\xDF\x43\x2A\xBD\x04\x88\x13"
+                         "\xFA\x4D\xF1\x58\x23\x57\x3E\x81"
+                         "\x68\x9C\x67\xCE\x51\xC5\xAC\x37"
+                         "\xBB\x02\x95\x7C\xE0\x4B\xD2\x46"
+                         "\x29\xB0\x1B\x8F\x16\xF9\x40\xF4"
+                         "\x5F\x26\xAA\x3D\x84\x6F\x93\x7A"
+                         "\xCD\x54\xD8\xA3\x0A\xBE\x01\xE8"
+                         "\x73\xE7\x4E\xD1\x45\x2C\xB7\x1E"
+                         "\x82\x15\xFC\x47\xCB\x52\x25\xA9"
+                         "\x30\x9B\x62\x96\x79\xC0\x74\xDF"
+                         "\xA6\x09\xBD\x04\xEF\x76\xFA\x4D"
+                         "\xD4\x58\x23\x8A\x1D\x81\x68\xF3"
+                         "\x5A\xCE\x51\x38\xAC\x37\x9E\x61"
+                         "\x95\x7C\xC7\x4B\xD2\xA5\x0C\xB0"
+                         "\x1B\xE2\x75\xF9\x40\x2B\x5F\x26"
+                         "\x89\x10\x84\x6F\xF6\x59\xCD\x54"
+                         "\x3F\xA3\x0A\x9D\x64\xE8\x73\xDA"
+                         "\x4E\xD1\xB8\x03\xB7\x1E\xE1\x48"
+                         "\xFC\x47\x2E\x52\x25\x8C\x17\x9B"
+                         "\x62\xF5\x5C\xC0\xAB\x32\xA6\x09"
+                         "\x90\x7B\xEF\x76\xD9\x4D\xD4\xBF"
+                         "\x06\x8A\x1D\xE4\x4F\xF3\x5A\x2D"
+                         "\x51\x38\x83\x6A\x9E\x61\xC8\x53"
+                         "\xC7\xAE\x31\xA5\x0C\x97\x7E\xE2"
+                         "\x75\xDC\x40\x2B\xB2\x05\x89\x10"
+                         "\xFB\x42\xF6\x59\x20\x54\x3F\x86"
+                         "\x69\x9D\x64\xCF\x56\xDA\xAD\x34"
+                         "\xB8\x03\xEA\x7D\xE1\x48\xD3\x47"
+                         "\x2E\xB1\x18",
+               .rlen   = 499,
+               .also_non_np = 1,
+               .np     = 2,
+               .tap    = { 499 - 16, 16 },
        },
 };
 
@@ -2461,17 +4166,133 @@ static struct cipher_testvec bf_enc_tv_template[] = {
                          "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
                          "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
                          "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
-                         "\x1E\x92\x29\xC0\x34\xCB\x62\xF9",
-               .ilen   = 40,
+                         "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+                         "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+                         "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+                         "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+                         "\xC3\x37\xCE\x65\xFC\x70\x07\x9E"
+                         "\x12\xA9\x40\xD7\x4B\xE2\x79\x10"
+                         "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F"
+                         "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1"
+                         "\x68\xFF\x73\x0A\xA1\x15\xAC\x43"
+                         "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5"
+                         "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
+                         "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
+                         "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
+                         "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+                         "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+                         "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+                         "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+                         "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+                         "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+                         "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+                         "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+                         "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+                         "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+                         "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+                         "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+                         "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+                         "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+                         "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+                         "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+                         "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+                         "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+                         "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+                         "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+                         "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+                         "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+                         "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+                         "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+                         "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+                         "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+                         "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+                         "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+                         "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+                         "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+                         "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+                         "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+                         "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+                         "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+                         "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+                         "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+                         "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+                         "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+                         "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+                         "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+                         "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+                         "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+                         "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+                         "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+                         "\xDC\x50\xE7\x7E\x15\x89\x20\xB7"
+                         "\x2B\xC2\x59\xF0\x64\xFB\x92\x06",
+               .ilen   = 504,
                .result = "\x96\x87\x3D\x0C\x7B\xFB\xBD\x1F"
                          "\xE3\xC1\x99\x6D\x39\xD4\xC2\x7D"
                          "\xD7\x87\xA1\xF2\xDF\x51\x71\x26"
                          "\xC2\xF4\x6D\xFF\xF6\xCD\x6B\x40"
-                         "\xE1\xB3\xBF\xD4\x38\x2B\xC8\x3B",
-               .rlen   = 40,
+                         "\xE1\xB3\xBF\xD4\x38\x2B\xC8\x3B"
+                         "\xD3\xB2\xD4\x61\xC7\x9F\x06\xE9"
+                         "\xCD\xF3\x88\x39\x39\x7A\xDF\x19"
+                         "\xE8\x03\x2A\x0B\x9E\xA0\x2B\x86"
+                         "\x31\xF8\x9D\xB1\xEE\x78\x9D\xB5"
+                         "\xCD\x8B\x7C\x2E\xF5\xA2\x2D\x5D"
+                         "\x6E\x66\xAF\x38\x6C\xD3\x13\xED"
+                         "\x14\xEA\x5D\xD0\x17\x77\x0F\x4A"
+                         "\x50\xF2\xD0\x0F\xC8\xF7\x1E\x7B"
+                         "\x9D\x5B\x54\x65\x4F\x16\x8A\x97"
+                         "\xF3\xF6\xD4\xAA\x87\x36\x77\x72"
+                         "\x99\x4A\xB5\x5E\x88\xC3\xCD\x7D"
+                         "\x1D\x97\xF9\x11\xBD\xE0\x1F\x1F"
+                         "\x96\x3E\x4B\x22\xF4\xC0\xE6\xB8"
+                         "\x47\x82\x98\x23\x33\x36\xBC\x1B"
+                         "\x36\xE7\xF6\xCF\x97\x37\x16\xC0"
+                         "\x87\x31\x8B\xB0\xDB\x19\x42\xA5"
+                         "\x1F\x90\x7E\x66\x34\xDD\x5E\xE9"
+                         "\x4F\xB2\x2B\x9A\xDE\xB3\x5D\x71"
+                         "\x4D\x68\xF0\xDC\xA6\xEA\xE3\x9B"
+                         "\x60\x00\x55\x57\x06\x8B\xD5\xB3"
+                         "\x86\x30\x78\xDA\x33\x9A\x9D\xCC"
+                         "\xBA\x0B\x81\x06\x77\x43\xC7\xC9"
+                         "\xDB\x37\x60\x11\x45\x59\x6D\x2D"
+                         "\x90\x3D\x65\x3E\xD0\x13\xC6\x3C"
+                         "\x0E\x78\x7D\x9A\x00\xD6\x2F\x0B"
+                         "\x3B\x53\x19\x1E\xA8\x9B\x11\xD9"
+                         "\x98\xE4\x7F\xC3\x6E\x51\x24\x70"
+                         "\x9F\x04\x9C\xC2\x9E\x44\x84\xE3"
+                         "\xE0\x8A\x44\xA2\x5C\x94\x74\x34"
+                         "\x37\x52\x7C\x03\xE8\x8E\x97\xE1"
+                         "\x5B\x5C\x0E\xB0\x70\xFE\x54\x3F"
+                         "\xD8\x65\xA9\xC5\xCD\xEC\xF4\x45"
+                         "\x55\xC5\xA7\xA3\x19\x80\x28\x51"
+                         "\xBE\x64\x4A\xC1\xD4\xE1\xBE\xEB"
+                         "\x73\x4C\xB6\xF9\x5F\x6D\x82\xBC"
+                         "\x3E\x42\x14\x49\x88\x51\xBF\x68"
+                         "\x45\x75\x27\x1B\x0A\x72\xED\xAF"
+                         "\xDA\xC4\x4D\x67\x0D\xEE\x75\xE3"
+                         "\x34\xDD\x91\x19\x42\x3A\xCB\xDA"
+                         "\x38\xFA\x3C\x93\x62\xF2\xE3\x81"
+                         "\xB3\xE4\xBB\xF6\x0D\x0B\x1D\x09"
+                         "\x9C\x52\x0D\x50\x63\xA4\xB2\xD2"
+                         "\x82\xA0\x23\x3F\x1F\xB6\xED\x6E"
+                         "\xC2\x9C\x1C\xD0\x9A\x40\xB6\xFC"
+                         "\x36\x56\x6E\x85\x73\xD7\x52\xBA"
+                         "\x35\x5E\x32\x89\x5D\x42\xF5\x36"
+                         "\x52\x8D\x46\x7D\xC8\x71\xAD\x33"
+                         "\xE1\xAF\x6A\xA8\xEC\xBA\x1C\xDC"
+                         "\xFE\x88\xE6\x16\xE4\xC8\x13\x00"
+                         "\x3C\xDA\x59\x32\x38\x19\xD5\xEB"
+                         "\xB6\x7F\x78\x45\x1B\x8E\x07\x8C"
+                         "\x66\x52\x75\xFF\xAF\xCE\x2D\x2B"
+                         "\x22\x29\xCA\xB3\x5F\x7F\xE3\x29"
+                         "\xB2\xB8\x9D\xEB\x16\xC8\xC5\x1D"
+                         "\xC9\x0D\x59\x82\x27\x57\x9D\x42"
+                         "\x54\x59\x09\xA5\x3D\xC5\x84\x68"
+                         "\x56\xEB\x36\x77\x3D\xAA\xB8\xF5"
+                         "\xC9\x1A\xFB\x5D\xDE\xBB\x43\xF4",
+               .rlen   = 504,
                .also_non_np = 1,
                .np     = 2,
-               .tap    = { 40 - 8, 8 },
+               .tap    = { 504 - 8, 8 },
        },
 };
 
@@ -2537,17 +4358,133 @@ static struct cipher_testvec bf_dec_tv_template[] = {
                          "\xE3\xC1\x99\x6D\x39\xD4\xC2\x7D"
                          "\xD7\x87\xA1\xF2\xDF\x51\x71\x26"
                          "\xC2\xF4\x6D\xFF\xF6\xCD\x6B\x40"
-                         "\xE1\xB3\xBF\xD4\x38\x2B\xC8\x3B",
-               .ilen   = 40,
+                         "\xE1\xB3\xBF\xD4\x38\x2B\xC8\x3B"
+                         "\xD3\xB2\xD4\x61\xC7\x9F\x06\xE9"
+                         "\xCD\xF3\x88\x39\x39\x7A\xDF\x19"
+                         "\xE8\x03\x2A\x0B\x9E\xA0\x2B\x86"
+                         "\x31\xF8\x9D\xB1\xEE\x78\x9D\xB5"
+                         "\xCD\x8B\x7C\x2E\xF5\xA2\x2D\x5D"
+                         "\x6E\x66\xAF\x38\x6C\xD3\x13\xED"
+                         "\x14\xEA\x5D\xD0\x17\x77\x0F\x4A"
+                         "\x50\xF2\xD0\x0F\xC8\xF7\x1E\x7B"
+                         "\x9D\x5B\x54\x65\x4F\x16\x8A\x97"
+                         "\xF3\xF6\xD4\xAA\x87\x36\x77\x72"
+                         "\x99\x4A\xB5\x5E\x88\xC3\xCD\x7D"
+                         "\x1D\x97\xF9\x11\xBD\xE0\x1F\x1F"
+                         "\x96\x3E\x4B\x22\xF4\xC0\xE6\xB8"
+                         "\x47\x82\x98\x23\x33\x36\xBC\x1B"
+                         "\x36\xE7\xF6\xCF\x97\x37\x16\xC0"
+                         "\x87\x31\x8B\xB0\xDB\x19\x42\xA5"
+                         "\x1F\x90\x7E\x66\x34\xDD\x5E\xE9"
+                         "\x4F\xB2\x2B\x9A\xDE\xB3\x5D\x71"
+                         "\x4D\x68\xF0\xDC\xA6\xEA\xE3\x9B"
+                         "\x60\x00\x55\x57\x06\x8B\xD5\xB3"
+                         "\x86\x30\x78\xDA\x33\x9A\x9D\xCC"
+                         "\xBA\x0B\x81\x06\x77\x43\xC7\xC9"
+                         "\xDB\x37\x60\x11\x45\x59\x6D\x2D"
+                         "\x90\x3D\x65\x3E\xD0\x13\xC6\x3C"
+                         "\x0E\x78\x7D\x9A\x00\xD6\x2F\x0B"
+                         "\x3B\x53\x19\x1E\xA8\x9B\x11\xD9"
+                         "\x98\xE4\x7F\xC3\x6E\x51\x24\x70"
+                         "\x9F\x04\x9C\xC2\x9E\x44\x84\xE3"
+                         "\xE0\x8A\x44\xA2\x5C\x94\x74\x34"
+                         "\x37\x52\x7C\x03\xE8\x8E\x97\xE1"
+                         "\x5B\x5C\x0E\xB0\x70\xFE\x54\x3F"
+                         "\xD8\x65\xA9\xC5\xCD\xEC\xF4\x45"
+                         "\x55\xC5\xA7\xA3\x19\x80\x28\x51"
+                         "\xBE\x64\x4A\xC1\xD4\xE1\xBE\xEB"
+                         "\x73\x4C\xB6\xF9\x5F\x6D\x82\xBC"
+                         "\x3E\x42\x14\x49\x88\x51\xBF\x68"
+                         "\x45\x75\x27\x1B\x0A\x72\xED\xAF"
+                         "\xDA\xC4\x4D\x67\x0D\xEE\x75\xE3"
+                         "\x34\xDD\x91\x19\x42\x3A\xCB\xDA"
+                         "\x38\xFA\x3C\x93\x62\xF2\xE3\x81"
+                         "\xB3\xE4\xBB\xF6\x0D\x0B\x1D\x09"
+                         "\x9C\x52\x0D\x50\x63\xA4\xB2\xD2"
+                         "\x82\xA0\x23\x3F\x1F\xB6\xED\x6E"
+                         "\xC2\x9C\x1C\xD0\x9A\x40\xB6\xFC"
+                         "\x36\x56\x6E\x85\x73\xD7\x52\xBA"
+                         "\x35\x5E\x32\x89\x5D\x42\xF5\x36"
+                         "\x52\x8D\x46\x7D\xC8\x71\xAD\x33"
+                         "\xE1\xAF\x6A\xA8\xEC\xBA\x1C\xDC"
+                         "\xFE\x88\xE6\x16\xE4\xC8\x13\x00"
+                         "\x3C\xDA\x59\x32\x38\x19\xD5\xEB"
+                         "\xB6\x7F\x78\x45\x1B\x8E\x07\x8C"
+                         "\x66\x52\x75\xFF\xAF\xCE\x2D\x2B"
+                         "\x22\x29\xCA\xB3\x5F\x7F\xE3\x29"
+                         "\xB2\xB8\x9D\xEB\x16\xC8\xC5\x1D"
+                         "\xC9\x0D\x59\x82\x27\x57\x9D\x42"
+                         "\x54\x59\x09\xA5\x3D\xC5\x84\x68"
+                         "\x56\xEB\x36\x77\x3D\xAA\xB8\xF5"
+                         "\xC9\x1A\xFB\x5D\xDE\xBB\x43\xF4",
+               .ilen   = 504,
                .result = "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
                          "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
                          "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
                          "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
-                         "\x1E\x92\x29\xC0\x34\xCB\x62\xF9",
-               .rlen   = 40,
+                         "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+                         "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+                         "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+                         "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+                         "\xC3\x37\xCE\x65\xFC\x70\x07\x9E"
+                         "\x12\xA9\x40\xD7\x4B\xE2\x79\x10"
+                         "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F"
+                         "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1"
+                         "\x68\xFF\x73\x0A\xA1\x15\xAC\x43"
+                         "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5"
+                         "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
+                         "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
+                         "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
+                         "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+                         "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+                         "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+                         "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+                         "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+                         "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+                         "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+                         "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+                         "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+                         "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+                         "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+                         "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+                         "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+                         "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+                         "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+                         "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+                         "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+                         "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+                         "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+                         "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+                         "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+                         "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+                         "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+                         "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+                         "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+                         "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+                         "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+                         "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+                         "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+                         "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+                         "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+                         "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+                         "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+                         "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+                         "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+                         "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+                         "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+                         "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+                         "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+                         "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+                         "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+                         "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+                         "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+                         "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+                         "\xDC\x50\xE7\x7E\x15\x89\x20\xB7"
+                         "\x2B\xC2\x59\xF0\x64\xFB\x92\x06",
+               .rlen   = 504,
                .also_non_np = 1,
                .np     = 2,
-               .tap    = { 40 - 8, 8 },
+               .tap    = { 504 - 8, 8 },
        },
 };
 
@@ -2578,29 +4515,145 @@ static struct cipher_testvec bf_cbc_enc_tv_template[] = {
                          "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
                          "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
                          "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
-                         "\x1E\x92\x29\xC0\x34\xCB\x62\xF9",
-               .ilen   = 40,
-               .result = "\xB4\xFE\xA5\xBB\x3D\x2C\x27\x06"
-                         "\x06\x2B\x3A\x92\xB2\xF5\x5E\x62"
-                         "\x84\xCD\xF7\x66\x7E\x41\x6C\x8E"
-                         "\x1B\xD9\x02\xB6\x48\xB0\x87\x25"
-                         "\x01\x9C\x93\x63\x51\x60\x82\xD2",
-               .rlen   = 40,
-               .also_non_np = 1,
-               .np     = 2,
-               .tap    = { 40 - 8, 8 },
-       },
-};
-
-static struct cipher_testvec bf_cbc_dec_tv_template[] = {
-       { /* From OpenSSL */
-               .key    = "\x01\x23\x45\x67\x89\xab\xcd\xef"
-                         "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87",
-               .klen   = 16,
-               .iv     = "\xfe\xdc\xba\x98\x76\x54\x32\x10",
-               .input  = "\x6b\x77\xb4\xd6\x30\x06\xde\xe6"
-                         "\x05\xb1\x56\xe2\x74\x03\x97\x93"
-                         "\x58\xde\xb9\xe7\x15\x46\x16\xd9"
+                         "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+                         "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+                         "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+                         "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+                         "\xC3\x37\xCE\x65\xFC\x70\x07\x9E"
+                         "\x12\xA9\x40\xD7\x4B\xE2\x79\x10"
+                         "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F"
+                         "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1"
+                         "\x68\xFF\x73\x0A\xA1\x15\xAC\x43"
+                         "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5"
+                         "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
+                         "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
+                         "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
+                         "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+                         "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+                         "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+                         "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+                         "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+                         "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+                         "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+                         "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+                         "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+                         "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+                         "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+                         "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+                         "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+                         "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+                         "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+                         "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+                         "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+                         "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+                         "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+                         "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+                         "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+                         "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+                         "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+                         "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+                         "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+                         "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+                         "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+                         "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+                         "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+                         "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+                         "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+                         "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+                         "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+                         "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+                         "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+                         "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+                         "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+                         "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+                         "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+                         "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+                         "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+                         "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+                         "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+                         "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+                         "\xDC\x50\xE7\x7E\x15\x89\x20\xB7"
+                         "\x2B\xC2\x59\xF0\x64\xFB\x92\x06",
+               .ilen   = 504,
+               .result = "\xB4\xFE\xA5\xBB\x3D\x2C\x27\x06"
+                         "\x06\x2B\x3A\x92\xB2\xF5\x5E\x62"
+                         "\x84\xCD\xF7\x66\x7E\x41\x6C\x8E"
+                         "\x1B\xD9\x02\xB6\x48\xB0\x87\x25"
+                         "\x01\x9C\x93\x63\x51\x60\x82\xD2"
+                         "\x4D\xE5\xC2\xB7\xAE\x60\xD8\xAD"
+                         "\x9F\xAB\x6C\xFA\x20\x05\xDA\x6F"
+                         "\x1F\xD1\xD8\x36\x0F\xB5\x16\x69"
+                         "\x3C\xAF\xB3\x30\x18\x33\xE6\xB5"
+                         "\x43\x29\x9D\x94\xF4\x2F\x0A\x65"
+                         "\x40\xB2\xB2\xB2\x42\x89\xEE\x8A"
+                         "\x60\xD3\x52\xA8\xED\x91\xDF\xE1"
+                         "\x91\x73\x7C\x28\xA1\x14\xC3\x4C"
+                         "\x82\x72\x4B\x7D\x7D\x32\xD5\x19"
+                         "\xE8\xB8\x6B\x30\x21\x09\x0E\x27"
+                         "\x10\x9D\x2D\x3A\x6A\x4B\x7B\xE6"
+                         "\x8D\x4E\x02\x32\xFF\x7F\x8E\x13"
+                         "\xB0\x96\xF4\xC2\xA1\x60\x8A\x69"
+                         "\xEF\x0F\x86\xD0\x25\x13\x1A\x7C"
+                         "\x6E\xF0\x41\xA3\xFB\xB3\xAB\x40"
+                         "\x7D\x19\xA0\x11\x4F\x3E\x1D\x43"
+                         "\x65\xFE\x15\x40\xD0\x62\x41\x02"
+                         "\xEA\x0C\x7A\xC3\x84\xEE\xB0\xBE"
+                         "\xBE\xC8\x57\x51\xCD\x4F\xAD\x5C"
+                         "\xCC\x79\xBA\x0D\x85\x3A\xED\x6B"
+                         "\xAC\x6B\xA3\x4D\xBC\xE8\x02\x6A"
+                         "\xC2\x6D\xBD\x5E\x89\x95\x86\x43"
+                         "\x2C\x17\x4B\xC6\x40\xA2\xBD\x24"
+                         "\x04\xF0\x86\x08\x78\x18\x42\xE0"
+                         "\x39\x1B\x22\x9E\x89\x4C\x04\x6B"
+                         "\x65\xC5\xB6\x0E\xF6\x63\xFC\xD7"
+                         "\xAE\x9E\x87\x13\xCC\xD3\x1A\xEC"
+                         "\xF0\x51\xCC\x93\x68\xFC\xE9\x19"
+                         "\x7C\x4E\x9B\xCC\x17\xAD\xD2\xFC"
+                         "\x97\x18\x92\xFF\x15\x11\xCE\xED"
+                         "\x04\x41\x05\xA3\x92\xFF\x3B\xE6"
+                         "\xB6\x8C\x90\xC6\xCD\x15\xA0\x04"
+                         "\x25\x8B\x5D\x5B\x5F\xDB\xAE\x68"
+                         "\xEF\xB3\x61\x18\xDB\x83\x9B\x39"
+                         "\xCA\x82\xD1\x88\xF0\xA2\x5C\x02"
+                         "\x87\xBD\x8D\x8F\xBB\x62\xF0\x35"
+                         "\x75\x6F\x06\x81\x0A\x97\x4D\xF0"
+                         "\x43\x12\x73\x77\xDB\x91\x83\x5B"
+                         "\xE7\x3A\xA6\x07\x7B\xBF\x2C\x50"
+                         "\x94\xDE\x7B\x65\xDA\x1C\xF1\x9F"
+                         "\x7E\x12\x40\xB2\x3E\x19\x23\xF1"
+                         "\x7C\x1B\x5F\xA8\xF3\xAC\x63\x87"
+                         "\xEB\x3E\x0C\xBE\xA3\x63\x97\x88"
+                         "\x8D\x27\xC6\x2A\xF8\xF2\x67\x9A"
+                         "\x0D\x14\x16\x2B\x6F\xCB\xD4\x76"
+                         "\x14\x48\x2E\xDE\x2A\x44\x5E\x45"
+                         "\xF1\x97\x82\xEF\xB7\xAE\xED\x3A"
+                         "\xED\x73\xD3\x79\xF7\x38\x1D\xD0"
+                         "\xC5\xF8\x69\x83\x28\x84\x87\x56"
+                         "\x3F\xAE\x81\x04\x79\x1F\xD1\x09"
+                         "\xC5\xE5\x05\x0D\x64\x16\xCE\x42"
+                         "\xC5\xF8\xDB\x57\x89\x33\x22\xFC"
+                         "\xB4\xD7\x94\xB9\xF3\xCC\x02\x90"
+                         "\x02\xBA\x55\x1E\x24\x3E\x02\x1D"
+                         "\xC6\xCD\x8F\xD9\xBD\xED\xB0\x51"
+                         "\xCD\xE9\xD5\x0C\xFE\x12\x39\xA9"
+                         "\x93\x9B\xEE\xB5\x97\x41\xD2\xA0"
+                         "\xB4\x98\xD8\x6B\x74\xE7\x65\xF4",
+               .rlen   = 504,
+               .also_non_np = 1,
+               .np     = 2,
+               .tap    = { 504 - 8, 8 },
+       },
+};
+
+static struct cipher_testvec bf_cbc_dec_tv_template[] = {
+       { /* From OpenSSL */
+               .key    = "\x01\x23\x45\x67\x89\xab\xcd\xef"
+                         "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87",
+               .klen   = 16,
+               .iv     = "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+               .input  = "\x6b\x77\xb4\xd6\x30\x06\xde\xe6"
+                         "\x05\xb1\x56\xe2\x74\x03\x97\x93"
+                         "\x58\xde\xb9\xe7\x15\x46\x16\xd9"
                          "\x59\xf1\x65\x2b\xd5\xff\x92\xcc",
                .ilen   = 32,
                .result = "\x37\x36\x35\x34\x33\x32\x31\x20"
@@ -2619,17 +4672,133 @@ static struct cipher_testvec bf_cbc_dec_tv_template[] = {
                          "\x06\x2B\x3A\x92\xB2\xF5\x5E\x62"
                          "\x84\xCD\xF7\x66\x7E\x41\x6C\x8E"
                          "\x1B\xD9\x02\xB6\x48\xB0\x87\x25"
-                         "\x01\x9C\x93\x63\x51\x60\x82\xD2",
-               .ilen   = 40,
+                         "\x01\x9C\x93\x63\x51\x60\x82\xD2"
+                         "\x4D\xE5\xC2\xB7\xAE\x60\xD8\xAD"
+                         "\x9F\xAB\x6C\xFA\x20\x05\xDA\x6F"
+                         "\x1F\xD1\xD8\x36\x0F\xB5\x16\x69"
+                         "\x3C\xAF\xB3\x30\x18\x33\xE6\xB5"
+                         "\x43\x29\x9D\x94\xF4\x2F\x0A\x65"
+                         "\x40\xB2\xB2\xB2\x42\x89\xEE\x8A"
+                         "\x60\xD3\x52\xA8\xED\x91\xDF\xE1"
+                         "\x91\x73\x7C\x28\xA1\x14\xC3\x4C"
+                         "\x82\x72\x4B\x7D\x7D\x32\xD5\x19"
+                         "\xE8\xB8\x6B\x30\x21\x09\x0E\x27"
+                         "\x10\x9D\x2D\x3A\x6A\x4B\x7B\xE6"
+                         "\x8D\x4E\x02\x32\xFF\x7F\x8E\x13"
+                         "\xB0\x96\xF4\xC2\xA1\x60\x8A\x69"
+                         "\xEF\x0F\x86\xD0\x25\x13\x1A\x7C"
+                         "\x6E\xF0\x41\xA3\xFB\xB3\xAB\x40"
+                         "\x7D\x19\xA0\x11\x4F\x3E\x1D\x43"
+                         "\x65\xFE\x15\x40\xD0\x62\x41\x02"
+                         "\xEA\x0C\x7A\xC3\x84\xEE\xB0\xBE"
+                         "\xBE\xC8\x57\x51\xCD\x4F\xAD\x5C"
+                         "\xCC\x79\xBA\x0D\x85\x3A\xED\x6B"
+                         "\xAC\x6B\xA3\x4D\xBC\xE8\x02\x6A"
+                         "\xC2\x6D\xBD\x5E\x89\x95\x86\x43"
+                         "\x2C\x17\x4B\xC6\x40\xA2\xBD\x24"
+                         "\x04\xF0\x86\x08\x78\x18\x42\xE0"
+                         "\x39\x1B\x22\x9E\x89\x4C\x04\x6B"
+                         "\x65\xC5\xB6\x0E\xF6\x63\xFC\xD7"
+                         "\xAE\x9E\x87\x13\xCC\xD3\x1A\xEC"
+                         "\xF0\x51\xCC\x93\x68\xFC\xE9\x19"
+                         "\x7C\x4E\x9B\xCC\x17\xAD\xD2\xFC"
+                         "\x97\x18\x92\xFF\x15\x11\xCE\xED"
+                         "\x04\x41\x05\xA3\x92\xFF\x3B\xE6"
+                         "\xB6\x8C\x90\xC6\xCD\x15\xA0\x04"
+                         "\x25\x8B\x5D\x5B\x5F\xDB\xAE\x68"
+                         "\xEF\xB3\x61\x18\xDB\x83\x9B\x39"
+                         "\xCA\x82\xD1\x88\xF0\xA2\x5C\x02"
+                         "\x87\xBD\x8D\x8F\xBB\x62\xF0\x35"
+                         "\x75\x6F\x06\x81\x0A\x97\x4D\xF0"
+                         "\x43\x12\x73\x77\xDB\x91\x83\x5B"
+                         "\xE7\x3A\xA6\x07\x7B\xBF\x2C\x50"
+                         "\x94\xDE\x7B\x65\xDA\x1C\xF1\x9F"
+                         "\x7E\x12\x40\xB2\x3E\x19\x23\xF1"
+                         "\x7C\x1B\x5F\xA8\xF3\xAC\x63\x87"
+                         "\xEB\x3E\x0C\xBE\xA3\x63\x97\x88"
+                         "\x8D\x27\xC6\x2A\xF8\xF2\x67\x9A"
+                         "\x0D\x14\x16\x2B\x6F\xCB\xD4\x76"
+                         "\x14\x48\x2E\xDE\x2A\x44\x5E\x45"
+                         "\xF1\x97\x82\xEF\xB7\xAE\xED\x3A"
+                         "\xED\x73\xD3\x79\xF7\x38\x1D\xD0"
+                         "\xC5\xF8\x69\x83\x28\x84\x87\x56"
+                         "\x3F\xAE\x81\x04\x79\x1F\xD1\x09"
+                         "\xC5\xE5\x05\x0D\x64\x16\xCE\x42"
+                         "\xC5\xF8\xDB\x57\x89\x33\x22\xFC"
+                         "\xB4\xD7\x94\xB9\xF3\xCC\x02\x90"
+                         "\x02\xBA\x55\x1E\x24\x3E\x02\x1D"
+                         "\xC6\xCD\x8F\xD9\xBD\xED\xB0\x51"
+                         "\xCD\xE9\xD5\x0C\xFE\x12\x39\xA9"
+                         "\x93\x9B\xEE\xB5\x97\x41\xD2\xA0"
+                         "\xB4\x98\xD8\x6B\x74\xE7\x65\xF4",
+               .ilen   = 504,
                .result = "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
                          "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
                          "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
                          "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
-                         "\x1E\x92\x29\xC0\x34\xCB\x62\xF9",
-               .rlen   = 40,
+                         "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+                         "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+                         "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+                         "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+                         "\xC3\x37\xCE\x65\xFC\x70\x07\x9E"
+                         "\x12\xA9\x40\xD7\x4B\xE2\x79\x10"
+                         "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F"
+                         "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1"
+                         "\x68\xFF\x73\x0A\xA1\x15\xAC\x43"
+                         "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5"
+                         "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
+                         "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
+                         "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
+                         "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+                         "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+                         "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+                         "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+                         "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+                         "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+                         "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+                         "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+                         "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+                         "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+                         "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+                         "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+                         "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+                         "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+                         "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+                         "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+                         "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+                         "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+                         "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+                         "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+                         "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+                         "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+                         "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+                         "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+                         "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+                         "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+                         "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+                         "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+                         "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+                         "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+                         "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+                         "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+                         "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+                         "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+                         "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+                         "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+                         "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+                         "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+                         "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+                         "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+                         "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+                         "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+                         "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+                         "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+                         "\xDC\x50\xE7\x7E\x15\x89\x20\xB7"
+                         "\x2B\xC2\x59\xF0\x64\xFB\x92\x06",
+               .rlen   = 504,
                .also_non_np = 1,
                .np     = 2,
-               .tap    = { 40 - 8, 8 },
+               .tap    = { 504 - 8, 8 },
        },
 };
 
@@ -2645,14 +4814,130 @@ static struct cipher_testvec bf_ctr_enc_tv_template[] = {
                          "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
                          "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
                          "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
-                         "\x1E\x92\x29\xC0\x34\xCB\x62\xF9",
-               .ilen   = 40,
+                         "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+                         "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+                         "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+                         "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+                         "\xC3\x37\xCE\x65\xFC\x70\x07\x9E"
+                         "\x12\xA9\x40\xD7\x4B\xE2\x79\x10"
+                         "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F"
+                         "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1"
+                         "\x68\xFF\x73\x0A\xA1\x15\xAC\x43"
+                         "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5"
+                         "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
+                         "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
+                         "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
+                         "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+                         "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+                         "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+                         "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+                         "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+                         "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+                         "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+                         "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+                         "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+                         "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+                         "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+                         "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+                         "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+                         "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+                         "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+                         "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+                         "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+                         "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+                         "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+                         "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+                         "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+                         "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+                         "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+                         "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+                         "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+                         "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+                         "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+                         "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+                         "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+                         "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+                         "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+                         "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+                         "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+                         "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+                         "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+                         "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+                         "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+                         "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+                         "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+                         "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+                         "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+                         "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+                         "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+                         "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+                         "\xDC\x50\xE7\x7E\x15\x89\x20\xB7"
+                         "\x2B\xC2\x59\xF0\x64\xFB\x92\x06",
+               .ilen   = 504,
                .result = "\xC7\xA3\xDF\xB9\x05\xF4\x9E\x8D"
                          "\x9E\xDF\x38\x18\x83\x07\xEF\xC1"
                          "\x93\x3C\xAA\xAA\xFE\x06\x42\xCC"
                          "\x0D\x70\x86\x5A\x44\xAD\x85\x17"
-                         "\xE4\x1F\x5E\xA5\x89\xAC\x32\xBC",
-               .rlen   = 40,
+                         "\xE4\x1F\x5E\xA5\x89\xAC\x32\xBC"
+                         "\x3D\xA7\xE9\x0A\x5C\x70\x4D\xDE"
+                         "\x99\x38\x07\xCA\x1D\x21\xC1\x11"
+                         "\x97\xEB\x98\x75\xC4\x73\x45\x83"
+                         "\x46\x1C\x9C\x91\x87\xC1\xA0\x56"
+                         "\x98\xA1\x8B\xDB\x22\x76\xBD\x62"
+                         "\xA4\xBC\xE8\x86\xDA\xD2\x51\x13"
+                         "\x13\xD2\x96\x68\x69\x10\x67\x0C"
+                         "\xD0\x17\x25\x7C\xB2\xAE\x4F\x93"
+                         "\xA6\x82\x20\xCF\x0F\xA6\x47\x79"
+                         "\x88\x09\x40\x59\xBD\x12\x64\xB5"
+                         "\x19\x38\x0D\xFF\x86\xD9\x42\x20"
+                         "\x81\x0D\x96\x99\xAF\x22\x1F\x94"
+                         "\x5C\x6E\xEC\xEA\xA3\x39\xCB\x09"
+                         "\x43\x19\x7F\xD0\xBB\x10\xC2\x49"
+                         "\xF7\xE9\xF2\xEE\xBF\xF7\xF8\xB3"
+                         "\x0E\x1A\xF1\x8D\x70\x82\x0C\x04"
+                         "\xFD\x29\x1A\xAC\xC0\x92\x48\x34"
+                         "\x6A\xE3\x1D\x4F\xFC\x1C\x72\x6A"
+                         "\x57\xCB\xAD\xD0\x98\xAB\xB1\x01"
+                         "\x03\x6A\x45\xDD\x07\x71\x5F\x5B"
+                         "\xB5\x4A\xE4\xE5\xB9\xB9\xBC\xAC"
+                         "\x44\xF7\x41\xA4\x5F\x2E\xE9\x28"
+                         "\xE3\x05\xD2\x94\x78\x4C\x33\x1B"
+                         "\xBD\xC1\x6E\x51\xD9\xAD\xD9\x86"
+                         "\x15\x4A\x78\xAE\x7B\xAD\x3B\xBC"
+                         "\x2F\xE0\x0E\xC5\x7B\x54\x97\x5F"
+                         "\x60\x51\x14\x65\xF9\x91\xE9\xDA"
+                         "\x9A\xBC\xFC\x19\x29\x67\xAA\x63"
+                         "\x5E\xF2\x48\x88\xEB\x79\xE1\xE4"
+                         "\xF7\xF6\x4C\xA9\xE2\x8C\x3B\xE0"
+                         "\xED\x52\xAE\x90\x8F\x5B\x98\x34"
+                         "\x29\x94\x34\x7F\xF9\x6C\x1E\xB6"
+                         "\xA4\xE7\x2D\x06\x54\x9D\xC3\x02"
+                         "\xC1\x90\xA4\x72\x31\x6B\x24\x51"
+                         "\x0B\xB3\x7C\x63\x15\xBA\xAF\x5D"
+                         "\x41\xE0\x37\x6D\xBE\x41\x58\xDE"
+                         "\xF2\x07\x62\x99\xBE\xC1\x8C\x0F"
+                         "\x0F\x28\xFB\x8F\x0E\x1D\x91\xE2"
+                         "\xDA\x99\x5C\x49\xBA\x9C\xA8\x86"
+                         "\x82\x63\x11\xB3\x54\x49\x00\x08"
+                         "\x07\xF2\xE8\x1F\x34\x49\x61\xF4"
+                         "\x81\xE9\xF6\xA9\x5A\x28\x60\x1F"
+                         "\x66\x99\x08\x06\xF2\xE8\x2D\xD1"
+                         "\xD0\x67\xBA\x32\x1F\x02\x86\x7B"
+                         "\xFB\x79\x3D\xC5\xB1\x7F\x15\xAF"
+                         "\xD7\xBF\x31\x46\x22\x7F\xAE\x5B"
+                         "\x8B\x95\x47\xC2\xB1\x62\xA1\xCE"
+                         "\x52\xAC\x9C\x8B\xC2\x49\x7F\xBC"
+                         "\x9C\x89\xB8\xB6\xCA\xE3\x8F\xEA"
+                         "\xAC\xB4\x5D\xE4\x50\xDC\x3A\xB5"
+                         "\x91\x04\x94\x99\x03\x3B\x42\x6D"
+                         "\x9C\x4A\x02\xF5\xB5\x38\x98\xA8"
+                         "\x5C\x97\x2E\x4D\x79\x67\x71\xAF"
+                         "\xF0\x70\x77\xFF\x2D\xDA\xA0\x9E"
+                         "\x23\x8D\xD6\xA6\x68\x10\x78\x9A"
+                         "\x64\xBB\x15\xB8\x56\xCF\xEE\xE5"
+                         "\x32\x44\x96\x1C\xD8\xEB\x95\xD2"
+                         "\xF3\x71\xEF\xEB\x4E\xBB\x4D\x29",
+               .rlen   = 504,
        }, { /* Generated with Crypto++ */
                .key    = "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
                          "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
@@ -2665,18 +4950,132 @@ static struct cipher_testvec bf_ctr_enc_tv_template[] = {
                          "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
                          "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
                          "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
-                         "\x6D\x04\x9B",
-               .ilen   = 43,
+                         "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+                         "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+                         "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+                         "\xC3\x37\xCE\x65\xFC\x70\x07\x9E"
+                         "\x12\xA9\x40\xD7\x4B\xE2\x79\x10"
+                         "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F"
+                         "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1"
+                         "\x68\xFF\x73\x0A\xA1\x15\xAC\x43"
+                         "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5"
+                         "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
+                         "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
+                         "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
+                         "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+                         "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+                         "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+                         "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+                         "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+                         "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+                         "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+                         "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+                         "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+                         "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+                         "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+                         "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+                         "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+                         "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+                         "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+                         "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+                         "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+                         "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+                         "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+                         "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+                         "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+                         "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+                         "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+                         "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+                         "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+                         "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+                         "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+                         "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+                         "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+                         "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+                         "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+                         "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+                         "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+                         "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+                         "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+                         "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+                         "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+                         "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+                         "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+                         "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+                         "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+                         "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+                         "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+                         "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+                         "\xDC\x50\xE7\x7E\x15\x89\x20\xB7"
+                         "\x2B\xC2\x59\xF0\x64\xFB\x92",
+               .ilen   = 503,
                .result = "\xC7\xA3\xDF\xB9\x05\xF4\x9E\x8D"
                          "\x9E\xDF\x38\x18\x83\x07\xEF\xC1"
                          "\x93\x3C\xAA\xAA\xFE\x06\x42\xCC"
                          "\x0D\x70\x86\x5A\x44\xAD\x85\x17"
                          "\xE4\x1F\x5E\xA5\x89\xAC\x32\xBC"
-                         "\x3D\xA7\xE9",
-               .rlen   = 43,
+                         "\x3D\xA7\xE9\x0A\x5C\x70\x4D\xDE"
+                         "\x99\x38\x07\xCA\x1D\x21\xC1\x11"
+                         "\x97\xEB\x98\x75\xC4\x73\x45\x83"
+                         "\x46\x1C\x9C\x91\x87\xC1\xA0\x56"
+                         "\x98\xA1\x8B\xDB\x22\x76\xBD\x62"
+                         "\xA4\xBC\xE8\x86\xDA\xD2\x51\x13"
+                         "\x13\xD2\x96\x68\x69\x10\x67\x0C"
+                         "\xD0\x17\x25\x7C\xB2\xAE\x4F\x93"
+                         "\xA6\x82\x20\xCF\x0F\xA6\x47\x79"
+                         "\x88\x09\x40\x59\xBD\x12\x64\xB5"
+                         "\x19\x38\x0D\xFF\x86\xD9\x42\x20"
+                         "\x81\x0D\x96\x99\xAF\x22\x1F\x94"
+                         "\x5C\x6E\xEC\xEA\xA3\x39\xCB\x09"
+                         "\x43\x19\x7F\xD0\xBB\x10\xC2\x49"
+                         "\xF7\xE9\xF2\xEE\xBF\xF7\xF8\xB3"
+                         "\x0E\x1A\xF1\x8D\x70\x82\x0C\x04"
+                         "\xFD\x29\x1A\xAC\xC0\x92\x48\x34"
+                         "\x6A\xE3\x1D\x4F\xFC\x1C\x72\x6A"
+                         "\x57\xCB\xAD\xD0\x98\xAB\xB1\x01"
+                         "\x03\x6A\x45\xDD\x07\x71\x5F\x5B"
+                         "\xB5\x4A\xE4\xE5\xB9\xB9\xBC\xAC"
+                         "\x44\xF7\x41\xA4\x5F\x2E\xE9\x28"
+                         "\xE3\x05\xD2\x94\x78\x4C\x33\x1B"
+                         "\xBD\xC1\x6E\x51\xD9\xAD\xD9\x86"
+                         "\x15\x4A\x78\xAE\x7B\xAD\x3B\xBC"
+                         "\x2F\xE0\x0E\xC5\x7B\x54\x97\x5F"
+                         "\x60\x51\x14\x65\xF9\x91\xE9\xDA"
+                         "\x9A\xBC\xFC\x19\x29\x67\xAA\x63"
+                         "\x5E\xF2\x48\x88\xEB\x79\xE1\xE4"
+                         "\xF7\xF6\x4C\xA9\xE2\x8C\x3B\xE0"
+                         "\xED\x52\xAE\x90\x8F\x5B\x98\x34"
+                         "\x29\x94\x34\x7F\xF9\x6C\x1E\xB6"
+                         "\xA4\xE7\x2D\x06\x54\x9D\xC3\x02"
+                         "\xC1\x90\xA4\x72\x31\x6B\x24\x51"
+                         "\x0B\xB3\x7C\x63\x15\xBA\xAF\x5D"
+                         "\x41\xE0\x37\x6D\xBE\x41\x58\xDE"
+                         "\xF2\x07\x62\x99\xBE\xC1\x8C\x0F"
+                         "\x0F\x28\xFB\x8F\x0E\x1D\x91\xE2"
+                         "\xDA\x99\x5C\x49\xBA\x9C\xA8\x86"
+                         "\x82\x63\x11\xB3\x54\x49\x00\x08"
+                         "\x07\xF2\xE8\x1F\x34\x49\x61\xF4"
+                         "\x81\xE9\xF6\xA9\x5A\x28\x60\x1F"
+                         "\x66\x99\x08\x06\xF2\xE8\x2D\xD1"
+                         "\xD0\x67\xBA\x32\x1F\x02\x86\x7B"
+                         "\xFB\x79\x3D\xC5\xB1\x7F\x15\xAF"
+                         "\xD7\xBF\x31\x46\x22\x7F\xAE\x5B"
+                         "\x8B\x95\x47\xC2\xB1\x62\xA1\xCE"
+                         "\x52\xAC\x9C\x8B\xC2\x49\x7F\xBC"
+                         "\x9C\x89\xB8\xB6\xCA\xE3\x8F\xEA"
+                         "\xAC\xB4\x5D\xE4\x50\xDC\x3A\xB5"
+                         "\x91\x04\x94\x99\x03\x3B\x42\x6D"
+                         "\x9C\x4A\x02\xF5\xB5\x38\x98\xA8"
+                         "\x5C\x97\x2E\x4D\x79\x67\x71\xAF"
+                         "\xF0\x70\x77\xFF\x2D\xDA\xA0\x9E"
+                         "\x23\x8D\xD6\xA6\x68\x10\x78\x9A"
+                         "\x64\xBB\x15\xB8\x56\xCF\xEE\xE5"
+                         "\x32\x44\x96\x1C\xD8\xEB\x95\xD2"
+                         "\xF3\x71\xEF\xEB\x4E\xBB\x4D",
+               .rlen   = 503,
                .also_non_np = 1,
                .np     = 2,
-               .tap    = { 43 - 8, 8 },
+               .tap    = { 503 - 8, 8 },
        }, { /* Generated with Crypto++ */
                .key    = "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
                          "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
@@ -2827,14 +5226,130 @@ static struct cipher_testvec bf_ctr_dec_tv_template[] = {
                          "\x9E\xDF\x38\x18\x83\x07\xEF\xC1"
                          "\x93\x3C\xAA\xAA\xFE\x06\x42\xCC"
                          "\x0D\x70\x86\x5A\x44\xAD\x85\x17"
-                         "\xE4\x1F\x5E\xA5\x89\xAC\x32\xBC",
-               .ilen   = 40,
+                         "\xE4\x1F\x5E\xA5\x89\xAC\x32\xBC"
+                         "\x3D\xA7\xE9\x0A\x5C\x70\x4D\xDE"
+                         "\x99\x38\x07\xCA\x1D\x21\xC1\x11"
+                         "\x97\xEB\x98\x75\xC4\x73\x45\x83"
+                         "\x46\x1C\x9C\x91\x87\xC1\xA0\x56"
+                         "\x98\xA1\x8B\xDB\x22\x76\xBD\x62"
+                         "\xA4\xBC\xE8\x86\xDA\xD2\x51\x13"
+                         "\x13\xD2\x96\x68\x69\x10\x67\x0C"
+                         "\xD0\x17\x25\x7C\xB2\xAE\x4F\x93"
+                         "\xA6\x82\x20\xCF\x0F\xA6\x47\x79"
+                         "\x88\x09\x40\x59\xBD\x12\x64\xB5"
+                         "\x19\x38\x0D\xFF\x86\xD9\x42\x20"
+                         "\x81\x0D\x96\x99\xAF\x22\x1F\x94"
+                         "\x5C\x6E\xEC\xEA\xA3\x39\xCB\x09"
+                         "\x43\x19\x7F\xD0\xBB\x10\xC2\x49"
+                         "\xF7\xE9\xF2\xEE\xBF\xF7\xF8\xB3"
+                         "\x0E\x1A\xF1\x8D\x70\x82\x0C\x04"
+                         "\xFD\x29\x1A\xAC\xC0\x92\x48\x34"
+                         "\x6A\xE3\x1D\x4F\xFC\x1C\x72\x6A"
+                         "\x57\xCB\xAD\xD0\x98\xAB\xB1\x01"
+                         "\x03\x6A\x45\xDD\x07\x71\x5F\x5B"
+                         "\xB5\x4A\xE4\xE5\xB9\xB9\xBC\xAC"
+                         "\x44\xF7\x41\xA4\x5F\x2E\xE9\x28"
+                         "\xE3\x05\xD2\x94\x78\x4C\x33\x1B"
+                         "\xBD\xC1\x6E\x51\xD9\xAD\xD9\x86"
+                         "\x15\x4A\x78\xAE\x7B\xAD\x3B\xBC"
+                         "\x2F\xE0\x0E\xC5\x7B\x54\x97\x5F"
+                         "\x60\x51\x14\x65\xF9\x91\xE9\xDA"
+                         "\x9A\xBC\xFC\x19\x29\x67\xAA\x63"
+                         "\x5E\xF2\x48\x88\xEB\x79\xE1\xE4"
+                         "\xF7\xF6\x4C\xA9\xE2\x8C\x3B\xE0"
+                         "\xED\x52\xAE\x90\x8F\x5B\x98\x34"
+                         "\x29\x94\x34\x7F\xF9\x6C\x1E\xB6"
+                         "\xA4\xE7\x2D\x06\x54\x9D\xC3\x02"
+                         "\xC1\x90\xA4\x72\x31\x6B\x24\x51"
+                         "\x0B\xB3\x7C\x63\x15\xBA\xAF\x5D"
+                         "\x41\xE0\x37\x6D\xBE\x41\x58\xDE"
+                         "\xF2\x07\x62\x99\xBE\xC1\x8C\x0F"
+                         "\x0F\x28\xFB\x8F\x0E\x1D\x91\xE2"
+                         "\xDA\x99\x5C\x49\xBA\x9C\xA8\x86"
+                         "\x82\x63\x11\xB3\x54\x49\x00\x08"
+                         "\x07\xF2\xE8\x1F\x34\x49\x61\xF4"
+                         "\x81\xE9\xF6\xA9\x5A\x28\x60\x1F"
+                         "\x66\x99\x08\x06\xF2\xE8\x2D\xD1"
+                         "\xD0\x67\xBA\x32\x1F\x02\x86\x7B"
+                         "\xFB\x79\x3D\xC5\xB1\x7F\x15\xAF"
+                         "\xD7\xBF\x31\x46\x22\x7F\xAE\x5B"
+                         "\x8B\x95\x47\xC2\xB1\x62\xA1\xCE"
+                         "\x52\xAC\x9C\x8B\xC2\x49\x7F\xBC"
+                         "\x9C\x89\xB8\xB6\xCA\xE3\x8F\xEA"
+                         "\xAC\xB4\x5D\xE4\x50\xDC\x3A\xB5"
+                         "\x91\x04\x94\x99\x03\x3B\x42\x6D"
+                         "\x9C\x4A\x02\xF5\xB5\x38\x98\xA8"
+                         "\x5C\x97\x2E\x4D\x79\x67\x71\xAF"
+                         "\xF0\x70\x77\xFF\x2D\xDA\xA0\x9E"
+                         "\x23\x8D\xD6\xA6\x68\x10\x78\x9A"
+                         "\x64\xBB\x15\xB8\x56\xCF\xEE\xE5"
+                         "\x32\x44\x96\x1C\xD8\xEB\x95\xD2"
+                         "\xF3\x71\xEF\xEB\x4E\xBB\x4D\x29",
+               .ilen   = 504,
                .result = "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
                          "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
                          "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
                          "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
-                         "\x1E\x92\x29\xC0\x34\xCB\x62\xF9",
-               .rlen   = 40,
+                         "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+                         "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+                         "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+                         "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+                         "\xC3\x37\xCE\x65\xFC\x70\x07\x9E"
+                         "\x12\xA9\x40\xD7\x4B\xE2\x79\x10"
+                         "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F"
+                         "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1"
+                         "\x68\xFF\x73\x0A\xA1\x15\xAC\x43"
+                         "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5"
+                         "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
+                         "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
+                         "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
+                         "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+                         "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+                         "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+                         "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+                         "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+                         "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+                         "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+                         "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+                         "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+                         "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+                         "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+                         "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+                         "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+                         "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+                         "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+                         "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+                         "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+                         "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+                         "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+                         "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+                         "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+                         "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+                         "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+                         "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+                         "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+                         "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+                         "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+                         "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+                         "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+                         "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+                         "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+                         "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+                         "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+                         "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+                         "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+                         "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+                         "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+                         "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+                         "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+                         "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+                         "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+                         "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+                         "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+                         "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+                         "\xDC\x50\xE7\x7E\x15\x89\x20\xB7"
+                         "\x2B\xC2\x59\xF0\x64\xFB\x92\x06",
+               .rlen   = 504,
        }, { /* Generated with Crypto++ */
                .key    = "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
                          "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
@@ -2847,18 +5362,132 @@ static struct cipher_testvec bf_ctr_dec_tv_template[] = {
                          "\x93\x3C\xAA\xAA\xFE\x06\x42\xCC"
                          "\x0D\x70\x86\x5A\x44\xAD\x85\x17"
                          "\xE4\x1F\x5E\xA5\x89\xAC\x32\xBC"
-                         "\x3D\xA7\xE9",
-               .ilen   = 43,
+                         "\x3D\xA7\xE9\x0A\x5C\x70\x4D\xDE"
+                         "\x99\x38\x07\xCA\x1D\x21\xC1\x11"
+                         "\x97\xEB\x98\x75\xC4\x73\x45\x83"
+                         "\x46\x1C\x9C\x91\x87\xC1\xA0\x56"
+                         "\x98\xA1\x8B\xDB\x22\x76\xBD\x62"
+                         "\xA4\xBC\xE8\x86\xDA\xD2\x51\x13"
+                         "\x13\xD2\x96\x68\x69\x10\x67\x0C"
+                         "\xD0\x17\x25\x7C\xB2\xAE\x4F\x93"
+                         "\xA6\x82\x20\xCF\x0F\xA6\x47\x79"
+                         "\x88\x09\x40\x59\xBD\x12\x64\xB5"
+                         "\x19\x38\x0D\xFF\x86\xD9\x42\x20"
+                         "\x81\x0D\x96\x99\xAF\x22\x1F\x94"
+                         "\x5C\x6E\xEC\xEA\xA3\x39\xCB\x09"
+                         "\x43\x19\x7F\xD0\xBB\x10\xC2\x49"
+                         "\xF7\xE9\xF2\xEE\xBF\xF7\xF8\xB3"
+                         "\x0E\x1A\xF1\x8D\x70\x82\x0C\x04"
+                         "\xFD\x29\x1A\xAC\xC0\x92\x48\x34"
+                         "\x6A\xE3\x1D\x4F\xFC\x1C\x72\x6A"
+                         "\x57\xCB\xAD\xD0\x98\xAB\xB1\x01"
+                         "\x03\x6A\x45\xDD\x07\x71\x5F\x5B"
+                         "\xB5\x4A\xE4\xE5\xB9\xB9\xBC\xAC"
+                         "\x44\xF7\x41\xA4\x5F\x2E\xE9\x28"
+                         "\xE3\x05\xD2\x94\x78\x4C\x33\x1B"
+                         "\xBD\xC1\x6E\x51\xD9\xAD\xD9\x86"
+                         "\x15\x4A\x78\xAE\x7B\xAD\x3B\xBC"
+                         "\x2F\xE0\x0E\xC5\x7B\x54\x97\x5F"
+                         "\x60\x51\x14\x65\xF9\x91\xE9\xDA"
+                         "\x9A\xBC\xFC\x19\x29\x67\xAA\x63"
+                         "\x5E\xF2\x48\x88\xEB\x79\xE1\xE4"
+                         "\xF7\xF6\x4C\xA9\xE2\x8C\x3B\xE0"
+                         "\xED\x52\xAE\x90\x8F\x5B\x98\x34"
+                         "\x29\x94\x34\x7F\xF9\x6C\x1E\xB6"
+                         "\xA4\xE7\x2D\x06\x54\x9D\xC3\x02"
+                         "\xC1\x90\xA4\x72\x31\x6B\x24\x51"
+                         "\x0B\xB3\x7C\x63\x15\xBA\xAF\x5D"
+                         "\x41\xE0\x37\x6D\xBE\x41\x58\xDE"
+                         "\xF2\x07\x62\x99\xBE\xC1\x8C\x0F"
+                         "\x0F\x28\xFB\x8F\x0E\x1D\x91\xE2"
+                         "\xDA\x99\x5C\x49\xBA\x9C\xA8\x86"
+                         "\x82\x63\x11\xB3\x54\x49\x00\x08"
+                         "\x07\xF2\xE8\x1F\x34\x49\x61\xF4"
+                         "\x81\xE9\xF6\xA9\x5A\x28\x60\x1F"
+                         "\x66\x99\x08\x06\xF2\xE8\x2D\xD1"
+                         "\xD0\x67\xBA\x32\x1F\x02\x86\x7B"
+                         "\xFB\x79\x3D\xC5\xB1\x7F\x15\xAF"
+                         "\xD7\xBF\x31\x46\x22\x7F\xAE\x5B"
+                         "\x8B\x95\x47\xC2\xB1\x62\xA1\xCE"
+                         "\x52\xAC\x9C\x8B\xC2\x49\x7F\xBC"
+                         "\x9C\x89\xB8\xB6\xCA\xE3\x8F\xEA"
+                         "\xAC\xB4\x5D\xE4\x50\xDC\x3A\xB5"
+                         "\x91\x04\x94\x99\x03\x3B\x42\x6D"
+                         "\x9C\x4A\x02\xF5\xB5\x38\x98\xA8"
+                         "\x5C\x97\x2E\x4D\x79\x67\x71\xAF"
+                         "\xF0\x70\x77\xFF\x2D\xDA\xA0\x9E"
+                         "\x23\x8D\xD6\xA6\x68\x10\x78\x9A"
+                         "\x64\xBB\x15\xB8\x56\xCF\xEE\xE5"
+                         "\x32\x44\x96\x1C\xD8\xEB\x95\xD2"
+                         "\xF3\x71\xEF\xEB\x4E\xBB\x4D",
+               .ilen   = 503,
                .result = "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
                          "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
                          "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
                          "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
                          "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
-                         "\x6D\x04\x9B",
-               .rlen   = 43,
+                         "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+                         "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+                         "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+                         "\xC3\x37\xCE\x65\xFC\x70\x07\x9E"
+                         "\x12\xA9\x40\xD7\x4B\xE2\x79\x10"
+                         "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F"
+                         "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1"
+                         "\x68\xFF\x73\x0A\xA1\x15\xAC\x43"
+                         "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5"
+                         "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
+                         "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
+                         "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
+                         "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+                         "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+                         "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+                         "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+                         "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+                         "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+                         "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+                         "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+                         "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+                         "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+                         "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+                         "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+                         "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+                         "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+                         "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+                         "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+                         "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+                         "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+                         "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+                         "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+                         "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+                         "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+                         "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+                         "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+                         "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+                         "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+                         "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+                         "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+                         "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+                         "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+                         "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+                         "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+                         "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+                         "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+                         "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+                         "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+                         "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+                         "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+                         "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+                         "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+                         "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+                         "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+                         "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+                         "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+                         "\xDC\x50\xE7\x7E\x15\x89\x20\xB7"
+                         "\x2B\xC2\x59\xF0\x64\xFB\x92",
+               .rlen   = 503,
                .also_non_np = 1,
                .np     = 2,
-               .tap    = { 43 - 8, 8 },
+               .tap    = { 503 - 8, 8 },
        }, { /* Generated with Crypto++ */
                .key    = "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
                          "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
@@ -5808,8 +8437,52 @@ static struct cipher_testvec serpent_enc_tv_template[] = {
                          "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
                          "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
                          "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
-                         "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A",
-               .ilen   = 144,
+                         "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+                         "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+                         "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+                         "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+                         "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+                         "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+                         "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+                         "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+                         "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+                         "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+                         "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+                         "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+                         "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+                         "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+                         "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+                         "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+                         "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+                         "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+                         "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+                         "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+                         "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+                         "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+                         "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+                         "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+                         "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+                         "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+                         "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+                         "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+                         "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+                         "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+                         "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+                         "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+                         "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+                         "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+                         "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+                         "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+                         "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+                         "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+                         "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+                         "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+                         "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+                         "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+                         "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+                         "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+                         "\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
+               .ilen   = 496,
                .result = "\xFB\xB0\x5D\xDE\xC0\xFE\xFC\xEB"
                          "\xB1\x80\x10\x43\xDE\x62\x70\xBD"
                          "\xFA\x8A\x93\xEA\x6B\xF7\xC5\xD7"
@@ -5827,11 +8500,55 @@ static struct cipher_testvec serpent_enc_tv_template[] = {
                          "\x9D\x74\x2B\x77\x53\x2D\xE5\xBD"
                          "\x69\xDA\x7A\x01\xF5\x6A\x70\x39"
                          "\x30\xD4\x2C\xF2\x8E\x06\x4B\x39"
-                         "\xB3\x12\x1D\xB3\x17\x46\xE6\xD6",
-               .rlen   = 144,
+                         "\xB3\x12\x1D\xB3\x17\x46\xE6\xD6"
+                         "\xB6\x31\x36\x34\x38\x3C\x1D\x69"
+                         "\x9F\x47\x28\x9A\x1D\x96\x70\x54"
+                         "\x8E\x88\xCB\xE0\xF5\x6A\xAE\x0A"
+                         "\x3C\xD5\x93\x1C\x21\xC9\x14\x3A"
+                         "\x23\x9C\x9B\x79\xC7\x75\xC8\x39"
+                         "\xA6\xAC\x65\x9A\x99\x37\xAF\x6D"
+                         "\xBD\xB5\x32\xFD\xD8\x9C\x95\x7B"
+                         "\xC6\x6A\x80\x64\xEA\xEF\x6D\x3F"
+                         "\xA9\xFE\x5B\x16\xA3\xCF\x32\xC8"
+                         "\xEF\x50\x22\x20\x93\x30\xBE\xE2"
+                         "\x38\x05\x65\xAF\xBA\xB6\xE4\x72"
+                         "\xA9\xEE\x05\x42\x88\xBD\x9D\x49"
+                         "\xAD\x93\xCA\x4D\x45\x11\x43\x4D"
+                         "\xB8\xF5\x74\x2B\x48\xE7\x21\xE4"
+                         "\x4E\x3A\x4C\xDE\x65\x7A\x5A\xAD"
+                         "\x86\xE6\x23\xEC\x6B\xA7\x17\xE6"
+                         "\xF6\xA1\xAC\x29\xAE\xF9\x9B\x69"
+                         "\x73\x65\x65\x51\xD6\x0B\x4E\x8C"
+                         "\x17\x15\x9D\xB0\xCF\xB2\x42\x2B"
+                         "\x51\xC3\x03\xE8\xB7\x7D\x2D\x39"
+                         "\xE8\x10\x93\x16\xC8\x68\x4C\x60"
+                         "\x87\x70\x14\xD0\x01\x57\xCB\x42"
+                         "\x13\x59\xB1\x7F\x12\x4F\xBB\xC7"
+                         "\xBD\x2B\xD4\xA9\x12\x26\x4F\xDE"
+                         "\xFD\x72\xEC\xD7\x6F\x97\x14\x90"
+                         "\x0E\x37\x13\xE6\x67\x1D\xE5\xFE"
+                         "\x9E\x18\x3C\x8F\x3A\x3F\x59\x9B"
+                         "\x71\x80\x05\x35\x3F\x40\x0B\x21"
+                         "\x76\xE5\xEF\x42\x6C\xDB\x31\x05"
+                         "\x5F\x05\xCF\x14\xE3\xF0\x61\xA2"
+                         "\x49\x03\x5E\x77\x2E\x20\xBA\xA1"
+                         "\xAF\x46\x51\xC0\x2B\xC4\x64\x1E"
+                         "\x65\xCC\x51\x58\x0A\xDF\xF0\x5F"
+                         "\x75\x9F\x48\xCD\x81\xEC\xC3\xF6"
+                         "\xED\xC9\x4B\x7B\x4E\x26\x23\xE1"
+                         "\xBB\xE9\x83\x0B\xCF\xE4\xDE\x00"
+                         "\x48\xFF\xBF\x6C\xB4\x72\x16\xEF"
+                         "\xC7\x46\xEE\x48\x8C\xB8\xAF\x45"
+                         "\x91\x76\xE7\x6E\x65\x3D\x15\x86"
+                         "\x10\xF8\xDB\x66\x97\x7C\x43\x4D"
+                         "\x79\x12\x4E\xCE\x06\xD1\xD1\x6A"
+                         "\x34\xC1\xC9\xF2\x28\x4A\xCD\x02"
+                         "\x75\x55\x9B\xFF\x36\x73\xAB\x7C"
+                         "\xF4\x46\x2E\xEB\xAC\xF3\xD2\xB7",
+               .rlen   = 496,
                .also_non_np = 1,
                .np     = 2,
-               .tap    = { 144 - 16, 16 },
+               .tap    = { 496 - 16, 16 },
        },
 };
 
@@ -5946,8 +8663,52 @@ static struct cipher_testvec serpent_dec_tv_template[] = {
                          "\x9D\x74\x2B\x77\x53\x2D\xE5\xBD"
                          "\x69\xDA\x7A\x01\xF5\x6A\x70\x39"
                          "\x30\xD4\x2C\xF2\x8E\x06\x4B\x39"
-                         "\xB3\x12\x1D\xB3\x17\x46\xE6\xD6",
-               .ilen   = 144,
+                         "\xB3\x12\x1D\xB3\x17\x46\xE6\xD6"
+                         "\xB6\x31\x36\x34\x38\x3C\x1D\x69"
+                         "\x9F\x47\x28\x9A\x1D\x96\x70\x54"
+                         "\x8E\x88\xCB\xE0\xF5\x6A\xAE\x0A"
+                         "\x3C\xD5\x93\x1C\x21\xC9\x14\x3A"
+                         "\x23\x9C\x9B\x79\xC7\x75\xC8\x39"
+                         "\xA6\xAC\x65\x9A\x99\x37\xAF\x6D"
+                         "\xBD\xB5\x32\xFD\xD8\x9C\x95\x7B"
+                         "\xC6\x6A\x80\x64\xEA\xEF\x6D\x3F"
+                         "\xA9\xFE\x5B\x16\xA3\xCF\x32\xC8"
+                         "\xEF\x50\x22\x20\x93\x30\xBE\xE2"
+                         "\x38\x05\x65\xAF\xBA\xB6\xE4\x72"
+                         "\xA9\xEE\x05\x42\x88\xBD\x9D\x49"
+                         "\xAD\x93\xCA\x4D\x45\x11\x43\x4D"
+                         "\xB8\xF5\x74\x2B\x48\xE7\x21\xE4"
+                         "\x4E\x3A\x4C\xDE\x65\x7A\x5A\xAD"
+                         "\x86\xE6\x23\xEC\x6B\xA7\x17\xE6"
+                         "\xF6\xA1\xAC\x29\xAE\xF9\x9B\x69"
+                         "\x73\x65\x65\x51\xD6\x0B\x4E\x8C"
+                         "\x17\x15\x9D\xB0\xCF\xB2\x42\x2B"
+                         "\x51\xC3\x03\xE8\xB7\x7D\x2D\x39"
+                         "\xE8\x10\x93\x16\xC8\x68\x4C\x60"
+                         "\x87\x70\x14\xD0\x01\x57\xCB\x42"
+                         "\x13\x59\xB1\x7F\x12\x4F\xBB\xC7"
+                         "\xBD\x2B\xD4\xA9\x12\x26\x4F\xDE"
+                         "\xFD\x72\xEC\xD7\x6F\x97\x14\x90"
+                         "\x0E\x37\x13\xE6\x67\x1D\xE5\xFE"
+                         "\x9E\x18\x3C\x8F\x3A\x3F\x59\x9B"
+                         "\x71\x80\x05\x35\x3F\x40\x0B\x21"
+                         "\x76\xE5\xEF\x42\x6C\xDB\x31\x05"
+                         "\x5F\x05\xCF\x14\xE3\xF0\x61\xA2"
+                         "\x49\x03\x5E\x77\x2E\x20\xBA\xA1"
+                         "\xAF\x46\x51\xC0\x2B\xC4\x64\x1E"
+                         "\x65\xCC\x51\x58\x0A\xDF\xF0\x5F"
+                         "\x75\x9F\x48\xCD\x81\xEC\xC3\xF6"
+                         "\xED\xC9\x4B\x7B\x4E\x26\x23\xE1"
+                         "\xBB\xE9\x83\x0B\xCF\xE4\xDE\x00"
+                         "\x48\xFF\xBF\x6C\xB4\x72\x16\xEF"
+                         "\xC7\x46\xEE\x48\x8C\xB8\xAF\x45"
+                         "\x91\x76\xE7\x6E\x65\x3D\x15\x86"
+                         "\x10\xF8\xDB\x66\x97\x7C\x43\x4D"
+                         "\x79\x12\x4E\xCE\x06\xD1\xD1\x6A"
+                         "\x34\xC1\xC9\xF2\x28\x4A\xCD\x02"
+                         "\x75\x55\x9B\xFF\x36\x73\xAB\x7C"
+                         "\xF4\x46\x2E\xEB\xAC\xF3\xD2\xB7",
+               .ilen   = 496,
                .result = "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
                          "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
                          "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
@@ -5965,11 +8726,55 @@ static struct cipher_testvec serpent_dec_tv_template[] = {
                          "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
                          "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
                          "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
-                         "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A",
-               .rlen   = 144,
+                         "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+                         "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+                         "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+                         "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+                         "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+                         "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+                         "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+                         "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+                         "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+                         "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+                         "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+                         "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+                         "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+                         "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+                         "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+                         "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+                         "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+                         "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+                         "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+                         "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+                         "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+                         "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+                         "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+                         "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+                         "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+                         "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+                         "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+                         "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+                         "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+                         "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+                         "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+                         "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+                         "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+                         "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+                         "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+                         "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+                         "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+                         "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+                         "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+                         "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+                         "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+                         "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+                         "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+                         "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+                         "\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
+               .rlen   = 496,
                .also_non_np = 1,
                .np     = 2,
-               .tap    = { 144 - 16, 16 },
+               .tap    = { 496 - 16, 16 },
        },
 };
 
@@ -6040,8 +8845,52 @@ static struct cipher_testvec serpent_cbc_enc_tv_template[] = {
                          "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
                          "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
                          "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
-                         "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A",
-               .ilen   = 144,
+                         "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+                         "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+                         "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+                         "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+                         "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+                         "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+                         "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+                         "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+                         "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+                         "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+                         "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+                         "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+                         "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+                         "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+                         "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+                         "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+                         "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+                         "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+                         "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+                         "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+                         "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+                         "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+                         "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+                         "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+                         "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+                         "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+                         "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+                         "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+                         "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+                         "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+                         "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+                         "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+                         "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+                         "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+                         "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+                         "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+                         "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+                         "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+                         "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+                         "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+                         "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+                         "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+                         "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+                         "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+                         "\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
+               .ilen   = 496,
                .result = "\x80\xCF\x11\x41\x1A\xB9\x4B\x9C"
                          "\xFF\xB7\x6C\xEA\xF0\xAF\x77\x6E"
                          "\x71\x75\x95\x9D\x4E\x1C\xCF\xAD"
@@ -6059,11 +8908,55 @@ static struct cipher_testvec serpent_cbc_enc_tv_template[] = {
                          "\x15\x26\xE1\xDB\xA4\x3D\x74\xD2"
                          "\x41\x1E\x3F\xA9\xC6\x7D\x2A\xAB"
                          "\x27\xDF\x89\x1D\x86\x3E\xF7\x5A"
-                         "\xF6\xE3\x0F\xC7\x6B\x4C\x96\x7C",
-               .rlen   = 144,
+                         "\xF6\xE3\x0F\xC7\x6B\x4C\x96\x7C"
+                         "\x2D\x12\xA5\x05\x92\xCB\xD7\x4A"
+                         "\x4D\x1E\x88\x21\xE1\x63\xB4\xFC"
+                         "\x4A\xF2\xCD\x35\xB9\xD7\x70\x97"
+                         "\x5A\x5E\x7E\x96\x52\x20\xDC\x25"
+                         "\xE9\x6B\x36\xB4\xE0\x98\x85\x2C"
+                         "\x3C\xD2\xF7\x78\x8A\x73\x26\x9B"
+                         "\xAF\x0B\x11\xE8\x4D\x67\x23\xE9"
+                         "\x77\xDF\x58\xF6\x6F\x9E\xA4\xC5"
+                         "\x10\xA1\x82\x0E\x80\xA0\x8F\x4B"
+                         "\xA1\xC0\x12\x54\x4E\xC9\x20\x92"
+                         "\x11\x00\x10\x4E\xB3\x7C\xCA\x63"
+                         "\xE5\x3F\xD3\x41\x37\xCD\x74\xB7"
+                         "\xA5\x7C\x61\xB8\x0B\x7A\x7F\x4D"
+                         "\xFE\x96\x7D\x1B\xBE\x60\x37\xB7"
+                         "\x81\x92\x66\x67\x15\x1E\x39\x98"
+                         "\x52\xC0\xF4\x69\xC0\x99\x4F\x5A"
+                         "\x2E\x32\xAD\x7C\x8B\xE9\xAD\x05"
+                         "\x55\xF9\x0A\x1F\x97\x5C\xFA\x2B"
+                         "\xF4\x99\x76\x3A\x6E\x4D\xE1\x4C"
+                         "\x14\x4E\x6F\x87\xEE\x1A\x85\xA3"
+                         "\x96\xC6\x66\x49\xDA\x0D\x71\xAC"
+                         "\x04\x05\x46\xD3\x90\x0F\x64\x64"
+                         "\x01\x66\x2C\x62\x5D\x34\xD1\xCB"
+                         "\x3A\x24\xCE\x95\xEF\xAE\x2C\x97"
+                         "\x0E\x0C\x1D\x36\x49\xEB\xE9\x3D"
+                         "\x62\xA6\x19\x28\x9E\x26\xB4\x3F"
+                         "\xD7\x55\x42\x3C\xCD\x72\x0A\xF0"
+                         "\x7D\xE9\x95\x45\x86\xED\xB1\xE0"
+                         "\x8D\xE9\xC5\x86\x13\x24\x28\x7D"
+                         "\x74\xEF\xCA\x50\x12\x7E\x64\x8F"
+                         "\x1B\xF5\x5B\xFE\xE2\xAC\xFA\xE7"
+                         "\xBD\x38\x8C\x11\x20\xEF\xB1\xAA"
+                         "\x7B\xE5\xE5\x78\xAD\x9D\x2D\xA2"
+                         "\x8E\xDD\x48\xB3\xEF\x18\x92\x7E"
+                         "\xE6\x75\x0D\x54\x64\x11\xA3\x3A"
+                         "\xDB\x97\x0F\xD3\xDF\x07\xD3\x7E"
+                         "\x1E\xD1\x87\xE4\x74\xBB\x46\xF4"
+                         "\xBA\x23\x2D\x8D\x29\x07\x12\xCF"
+                         "\x34\xCD\x72\x7F\x01\x30\xE7\xA0"
+                         "\xF8\xDD\xA8\x08\xF0\xBC\xB1\xA2"
+                         "\xCC\xE1\x6B\x5F\xBE\xEA\xF1\xE4"
+                         "\x02\xC4\xAF\xFA\xAD\x31\xF4\xBF"
+                         "\xFC\x66\xAA\x37\xF2\x37\x39\x6B"
+                         "\xBC\x08\x3A\xA2\x29\xB3\xDF\xD1",
+               .rlen   = 496,
                .also_non_np = 1,
                .np     = 2,
-               .tap    = { 144 - 16, 16 },
+               .tap    = { 496 - 16, 16 },
        },
 };
 
@@ -6093,8 +8986,52 @@ static struct cipher_testvec serpent_cbc_dec_tv_template[] = {
                          "\x15\x26\xE1\xDB\xA4\x3D\x74\xD2"
                          "\x41\x1E\x3F\xA9\xC6\x7D\x2A\xAB"
                          "\x27\xDF\x89\x1D\x86\x3E\xF7\x5A"
-                         "\xF6\xE3\x0F\xC7\x6B\x4C\x96\x7C",
-               .ilen   = 144,
+                         "\xF6\xE3\x0F\xC7\x6B\x4C\x96\x7C"
+                         "\x2D\x12\xA5\x05\x92\xCB\xD7\x4A"
+                         "\x4D\x1E\x88\x21\xE1\x63\xB4\xFC"
+                         "\x4A\xF2\xCD\x35\xB9\xD7\x70\x97"
+                         "\x5A\x5E\x7E\x96\x52\x20\xDC\x25"
+                         "\xE9\x6B\x36\xB4\xE0\x98\x85\x2C"
+                         "\x3C\xD2\xF7\x78\x8A\x73\x26\x9B"
+                         "\xAF\x0B\x11\xE8\x4D\x67\x23\xE9"
+                         "\x77\xDF\x58\xF6\x6F\x9E\xA4\xC5"
+                         "\x10\xA1\x82\x0E\x80\xA0\x8F\x4B"
+                         "\xA1\xC0\x12\x54\x4E\xC9\x20\x92"
+                         "\x11\x00\x10\x4E\xB3\x7C\xCA\x63"
+                         "\xE5\x3F\xD3\x41\x37\xCD\x74\xB7"
+                         "\xA5\x7C\x61\xB8\x0B\x7A\x7F\x4D"
+                         "\xFE\x96\x7D\x1B\xBE\x60\x37\xB7"
+                         "\x81\x92\x66\x67\x15\x1E\x39\x98"
+                         "\x52\xC0\xF4\x69\xC0\x99\x4F\x5A"
+                         "\x2E\x32\xAD\x7C\x8B\xE9\xAD\x05"
+                         "\x55\xF9\x0A\x1F\x97\x5C\xFA\x2B"
+                         "\xF4\x99\x76\x3A\x6E\x4D\xE1\x4C"
+                         "\x14\x4E\x6F\x87\xEE\x1A\x85\xA3"
+                         "\x96\xC6\x66\x49\xDA\x0D\x71\xAC"
+                         "\x04\x05\x46\xD3\x90\x0F\x64\x64"
+                         "\x01\x66\x2C\x62\x5D\x34\xD1\xCB"
+                         "\x3A\x24\xCE\x95\xEF\xAE\x2C\x97"
+                         "\x0E\x0C\x1D\x36\x49\xEB\xE9\x3D"
+                         "\x62\xA6\x19\x28\x9E\x26\xB4\x3F"
+                         "\xD7\x55\x42\x3C\xCD\x72\x0A\xF0"
+                         "\x7D\xE9\x95\x45\x86\xED\xB1\xE0"
+                         "\x8D\xE9\xC5\x86\x13\x24\x28\x7D"
+                         "\x74\xEF\xCA\x50\x12\x7E\x64\x8F"
+                         "\x1B\xF5\x5B\xFE\xE2\xAC\xFA\xE7"
+                         "\xBD\x38\x8C\x11\x20\xEF\xB1\xAA"
+                         "\x7B\xE5\xE5\x78\xAD\x9D\x2D\xA2"
+                         "\x8E\xDD\x48\xB3\xEF\x18\x92\x7E"
+                         "\xE6\x75\x0D\x54\x64\x11\xA3\x3A"
+                         "\xDB\x97\x0F\xD3\xDF\x07\xD3\x7E"
+                         "\x1E\xD1\x87\xE4\x74\xBB\x46\xF4"
+                         "\xBA\x23\x2D\x8D\x29\x07\x12\xCF"
+                         "\x34\xCD\x72\x7F\x01\x30\xE7\xA0"
+                         "\xF8\xDD\xA8\x08\xF0\xBC\xB1\xA2"
+                         "\xCC\xE1\x6B\x5F\xBE\xEA\xF1\xE4"
+                         "\x02\xC4\xAF\xFA\xAD\x31\xF4\xBF"
+                         "\xFC\x66\xAA\x37\xF2\x37\x39\x6B"
+                         "\xBC\x08\x3A\xA2\x29\xB3\xDF\xD1",
+               .ilen   = 496,
                .result = "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
                          "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
                          "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
@@ -6112,11 +9049,55 @@ static struct cipher_testvec serpent_cbc_dec_tv_template[] = {
                          "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
                          "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
                          "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
-                         "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A",
-               .rlen   = 144,
+                         "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+                         "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+                         "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+                         "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+                         "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+                         "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+                         "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+                         "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+                         "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+                         "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+                         "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+                         "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+                         "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+                         "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+                         "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+                         "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+                         "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+                         "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+                         "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+                         "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+                         "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+                         "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+                         "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+                         "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+                         "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+                         "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+                         "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+                         "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+                         "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+                         "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+                         "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+                         "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+                         "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+                         "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+                         "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+                         "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+                         "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+                         "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+                         "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+                         "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+                         "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+                         "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+                         "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+                         "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+                         "\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
+               .rlen   = 496,
                .also_non_np = 1,
                .np     = 2,
-               .tap    = { 144 - 16, 16 },
+               .tap    = { 496 - 16, 16 },
        },
 };
 
@@ -6146,8 +9127,52 @@ static struct cipher_testvec serpent_ctr_enc_tv_template[] = {
                          "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
                          "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
                          "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
-                         "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A",
-               .ilen   = 144,
+                         "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+                         "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+                         "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+                         "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+                         "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+                         "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+                         "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+                         "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+                         "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+                         "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+                         "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+                         "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+                         "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+                         "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+                         "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+                         "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+                         "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+                         "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+                         "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+                         "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+                         "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+                         "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+                         "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+                         "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+                         "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+                         "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+                         "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+                         "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+                         "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+                         "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+                         "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+                         "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+                         "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+                         "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+                         "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+                         "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+                         "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+                         "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+                         "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+                         "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+                         "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+                         "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+                         "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+                         "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+                         "\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
+               .ilen   = 496,
                .result = "\x84\x68\xEC\xF2\x1C\x88\x20\xCA"
                          "\x37\x69\xE3\x3A\x22\x85\x48\x46"
                          "\x70\xAA\x25\xB4\xCD\x8B\x04\x4E"
@@ -6165,8 +9190,52 @@ static struct cipher_testvec serpent_ctr_enc_tv_template[] = {
                          "\xBA\x58\x2A\x1C\xDF\xC2\x3A\xA5"
                          "\x7C\xB5\x12\x89\xED\xBF\xB6\x09"
                          "\x13\x4F\x7D\x61\x3C\x5C\x27\xFC"
-                         "\x5D\xE1\x4F\xA1\xEA\xB3\xCA\xB9",
-               .rlen   = 144,
+                         "\x5D\xE1\x4F\xA1\xEA\xB3\xCA\xB9"
+                         "\xE6\xD0\x97\x81\xDE\xD1\xFB\x8A"
+                         "\x30\xDB\xA3\x5D\xEC\x25\x0B\x86"
+                         "\x71\xC8\xA7\x67\xE8\xBC\x7D\x4C"
+                         "\xAE\x82\xD3\x73\x31\x09\xCB\xB3"
+                         "\x4D\xD4\xC0\x8A\x2B\xFA\xA6\x55"
+                         "\x39\x0A\xBC\x6E\x75\xAB\xC2\xE2"
+                         "\x8A\xF2\x26\xCD\x63\x38\x35\xF7"
+                         "\xAE\x12\x83\xCD\x8A\x9E\x7E\x4C"
+                         "\xFE\x4D\xD7\xCE\x5C\x6E\x4C\xAF"
+                         "\xE3\xCD\x76\xA7\x87\xA1\x54\x7C"
+                         "\xEC\x32\xC7\x83\x2A\xFF\xF8\xEA"
+                         "\x87\xB2\x47\xA3\x9D\xC2\x9C\xA2"
+                         "\xB7\x2C\x7C\x1A\x24\xCB\x88\x61"
+                         "\xFF\xA7\x1A\x16\x01\xDD\x4B\xFC"
+                         "\x2E\xE0\x48\x67\x09\x42\xCC\x91"
+                         "\xBE\x20\x38\xC0\x5E\x3B\x95\x00"
+                         "\xA1\x96\x66\x0B\x8A\xE9\x9E\xF7"
+                         "\x6B\x34\x0A\x51\xC0\x3B\xEB\x71"
+                         "\x07\x97\x38\x4B\x5C\x56\x98\x67"
+                         "\x78\x9C\xD0\x0E\x2B\xB5\x67\x90"
+                         "\x75\xF8\xFE\x6D\x4E\x85\xCC\x0D"
+                         "\x18\x06\x15\x9D\x5A\x10\x13\x37"
+                         "\xA3\xD6\x68\xA2\xDF\x7E\xC7\x12"
+                         "\xC9\x0D\x4D\x91\xB0\x2A\x55\xFF"
+                         "\x6F\x73\x13\xDF\x28\xB5\x2A\x2C"
+                         "\xE4\xFC\x20\xD9\xF1\x7A\x82\xB1"
+                         "\xCB\x57\xB6\x3D\x8C\xF4\x8E\x27"
+                         "\x37\xDC\x35\xF3\x79\x01\x53\xA4"
+                         "\x7B\x37\xDE\x7C\x04\xAE\x50\xDB"
+                         "\x9B\x1E\x8C\x07\xA7\x52\x49\x50"
+                         "\x34\x25\x65\xDD\xA9\x8F\x7E\xBD"
+                         "\x7A\xC9\x36\xAE\xDE\x21\x48\x64"
+                         "\xC2\x02\xBA\xBE\x11\x1E\x3D\x9C"
+                         "\x98\x52\xCC\x04\xBD\x5E\x61\x26"
+                         "\x10\xD3\x21\xD9\x6E\x25\x98\x77"
+                         "\x8E\x98\x63\xF6\xF6\x52\xFB\x13"
+                         "\xAA\x30\xF2\xB9\xA4\x43\x53\x39"
+                         "\x1C\x97\x07\x7E\x6B\xFF\x3D\x43"
+                         "\xA6\x71\x6B\x66\x8F\x58\x3F\x71"
+                         "\x90\x47\x40\x92\xE6\x69\xD1\x96"
+                         "\x34\xB3\x3B\xE5\x43\xE4\xD5\x56"
+                         "\xB2\xE6\x7E\x86\x7A\x12\x17\x5B"
+                         "\x30\xF3\x9B\x0D\xFA\x57\xE4\x50"
+                         "\x40\x53\x77\x8C\x15\xF8\x8D\x13",
+               .rlen   = 496,
        }, { /* Generated with Crypto++ */
                .key    = "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
                          "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
@@ -6193,8 +9262,52 @@ static struct cipher_testvec serpent_ctr_enc_tv_template[] = {
                          "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
                          "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
                          "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
-                         "\xF1\x65\xFC",
-               .ilen   = 147,
+                         "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+                         "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+                         "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+                         "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+                         "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+                         "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+                         "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+                         "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+                         "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+                         "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+                         "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+                         "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+                         "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+                         "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+                         "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+                         "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+                         "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+                         "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+                         "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+                         "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+                         "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+                         "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+                         "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+                         "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+                         "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+                         "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+                         "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+                         "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+                         "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+                         "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+                         "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+                         "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+                         "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+                         "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+                         "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+                         "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+                         "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+                         "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+                         "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+                         "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+                         "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+                         "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+                         "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+                         "\xDC\x50\xE7\x7E\x15\x89\x20\xB7"
+                         "\x2B\xC2\x59",
+               .ilen   = 499,
                .result = "\x84\x68\xEC\xF2\x1C\x88\x20\xCA"
                          "\x37\x69\xE3\x3A\x22\x85\x48\x46"
                          "\x70\xAA\x25\xB4\xCD\x8B\x04\x4E"
@@ -6213,11 +9326,55 @@ static struct cipher_testvec serpent_ctr_enc_tv_template[] = {
                          "\x7C\xB5\x12\x89\xED\xBF\xB6\x09"
                          "\x13\x4F\x7D\x61\x3C\x5C\x27\xFC"
                          "\x5D\xE1\x4F\xA1\xEA\xB3\xCA\xB9"
-                         "\xE6\xD0\x97",
-               .rlen   = 147,
+                         "\xE6\xD0\x97\x81\xDE\xD1\xFB\x8A"
+                         "\x30\xDB\xA3\x5D\xEC\x25\x0B\x86"
+                         "\x71\xC8\xA7\x67\xE8\xBC\x7D\x4C"
+                         "\xAE\x82\xD3\x73\x31\x09\xCB\xB3"
+                         "\x4D\xD4\xC0\x8A\x2B\xFA\xA6\x55"
+                         "\x39\x0A\xBC\x6E\x75\xAB\xC2\xE2"
+                         "\x8A\xF2\x26\xCD\x63\x38\x35\xF7"
+                         "\xAE\x12\x83\xCD\x8A\x9E\x7E\x4C"
+                         "\xFE\x4D\xD7\xCE\x5C\x6E\x4C\xAF"
+                         "\xE3\xCD\x76\xA7\x87\xA1\x54\x7C"
+                         "\xEC\x32\xC7\x83\x2A\xFF\xF8\xEA"
+                         "\x87\xB2\x47\xA3\x9D\xC2\x9C\xA2"
+                         "\xB7\x2C\x7C\x1A\x24\xCB\x88\x61"
+                         "\xFF\xA7\x1A\x16\x01\xDD\x4B\xFC"
+                         "\x2E\xE0\x48\x67\x09\x42\xCC\x91"
+                         "\xBE\x20\x38\xC0\x5E\x3B\x95\x00"
+                         "\xA1\x96\x66\x0B\x8A\xE9\x9E\xF7"
+                         "\x6B\x34\x0A\x51\xC0\x3B\xEB\x71"
+                         "\x07\x97\x38\x4B\x5C\x56\x98\x67"
+                         "\x78\x9C\xD0\x0E\x2B\xB5\x67\x90"
+                         "\x75\xF8\xFE\x6D\x4E\x85\xCC\x0D"
+                         "\x18\x06\x15\x9D\x5A\x10\x13\x37"
+                         "\xA3\xD6\x68\xA2\xDF\x7E\xC7\x12"
+                         "\xC9\x0D\x4D\x91\xB0\x2A\x55\xFF"
+                         "\x6F\x73\x13\xDF\x28\xB5\x2A\x2C"
+                         "\xE4\xFC\x20\xD9\xF1\x7A\x82\xB1"
+                         "\xCB\x57\xB6\x3D\x8C\xF4\x8E\x27"
+                         "\x37\xDC\x35\xF3\x79\x01\x53\xA4"
+                         "\x7B\x37\xDE\x7C\x04\xAE\x50\xDB"
+                         "\x9B\x1E\x8C\x07\xA7\x52\x49\x50"
+                         "\x34\x25\x65\xDD\xA9\x8F\x7E\xBD"
+                         "\x7A\xC9\x36\xAE\xDE\x21\x48\x64"
+                         "\xC2\x02\xBA\xBE\x11\x1E\x3D\x9C"
+                         "\x98\x52\xCC\x04\xBD\x5E\x61\x26"
+                         "\x10\xD3\x21\xD9\x6E\x25\x98\x77"
+                         "\x8E\x98\x63\xF6\xF6\x52\xFB\x13"
+                         "\xAA\x30\xF2\xB9\xA4\x43\x53\x39"
+                         "\x1C\x97\x07\x7E\x6B\xFF\x3D\x43"
+                         "\xA6\x71\x6B\x66\x8F\x58\x3F\x71"
+                         "\x90\x47\x40\x92\xE6\x69\xD1\x96"
+                         "\x34\xB3\x3B\xE5\x43\xE4\xD5\x56"
+                         "\xB2\xE6\x7E\x86\x7A\x12\x17\x5B"
+                         "\x30\xF3\x9B\x0D\xFA\x57\xE4\x50"
+                         "\x40\x53\x77\x8C\x15\xF8\x8D\x13"
+                         "\x38\xE2\xE5",
+               .rlen   = 499,
                .also_non_np = 1,
                .np     = 2,
-               .tap    = { 147 - 16, 16 },
+               .tap    = { 499 - 16, 16 },
        }, { /* Generated with Crypto++ */
                .key    = "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
                          "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
@@ -6381,8 +9538,52 @@ static struct cipher_testvec serpent_ctr_dec_tv_template[] = {
                          "\xBA\x58\x2A\x1C\xDF\xC2\x3A\xA5"
                          "\x7C\xB5\x12\x89\xED\xBF\xB6\x09"
                          "\x13\x4F\x7D\x61\x3C\x5C\x27\xFC"
-                         "\x5D\xE1\x4F\xA1\xEA\xB3\xCA\xB9",
-               .ilen   = 144,
+                         "\x5D\xE1\x4F\xA1\xEA\xB3\xCA\xB9"
+                         "\xE6\xD0\x97\x81\xDE\xD1\xFB\x8A"
+                         "\x30\xDB\xA3\x5D\xEC\x25\x0B\x86"
+                         "\x71\xC8\xA7\x67\xE8\xBC\x7D\x4C"
+                         "\xAE\x82\xD3\x73\x31\x09\xCB\xB3"
+                         "\x4D\xD4\xC0\x8A\x2B\xFA\xA6\x55"
+                         "\x39\x0A\xBC\x6E\x75\xAB\xC2\xE2"
+                         "\x8A\xF2\x26\xCD\x63\x38\x35\xF7"
+                         "\xAE\x12\x83\xCD\x8A\x9E\x7E\x4C"
+                         "\xFE\x4D\xD7\xCE\x5C\x6E\x4C\xAF"
+                         "\xE3\xCD\x76\xA7\x87\xA1\x54\x7C"
+                         "\xEC\x32\xC7\x83\x2A\xFF\xF8\xEA"
+                         "\x87\xB2\x47\xA3\x9D\xC2\x9C\xA2"
+                         "\xB7\x2C\x7C\x1A\x24\xCB\x88\x61"
+                         "\xFF\xA7\x1A\x16\x01\xDD\x4B\xFC"
+                         "\x2E\xE0\x48\x67\x09\x42\xCC\x91"
+                         "\xBE\x20\x38\xC0\x5E\x3B\x95\x00"
+                         "\xA1\x96\x66\x0B\x8A\xE9\x9E\xF7"
+                         "\x6B\x34\x0A\x51\xC0\x3B\xEB\x71"
+                         "\x07\x97\x38\x4B\x5C\x56\x98\x67"
+                         "\x78\x9C\xD0\x0E\x2B\xB5\x67\x90"
+                         "\x75\xF8\xFE\x6D\x4E\x85\xCC\x0D"
+                         "\x18\x06\x15\x9D\x5A\x10\x13\x37"
+                         "\xA3\xD6\x68\xA2\xDF\x7E\xC7\x12"
+                         "\xC9\x0D\x4D\x91\xB0\x2A\x55\xFF"
+                         "\x6F\x73\x13\xDF\x28\xB5\x2A\x2C"
+                         "\xE4\xFC\x20\xD9\xF1\x7A\x82\xB1"
+                         "\xCB\x57\xB6\x3D\x8C\xF4\x8E\x27"
+                         "\x37\xDC\x35\xF3\x79\x01\x53\xA4"
+                         "\x7B\x37\xDE\x7C\x04\xAE\x50\xDB"
+                         "\x9B\x1E\x8C\x07\xA7\x52\x49\x50"
+                         "\x34\x25\x65\xDD\xA9\x8F\x7E\xBD"
+                         "\x7A\xC9\x36\xAE\xDE\x21\x48\x64"
+                         "\xC2\x02\xBA\xBE\x11\x1E\x3D\x9C"
+                         "\x98\x52\xCC\x04\xBD\x5E\x61\x26"
+                         "\x10\xD3\x21\xD9\x6E\x25\x98\x77"
+                         "\x8E\x98\x63\xF6\xF6\x52\xFB\x13"
+                         "\xAA\x30\xF2\xB9\xA4\x43\x53\x39"
+                         "\x1C\x97\x07\x7E\x6B\xFF\x3D\x43"
+                         "\xA6\x71\x6B\x66\x8F\x58\x3F\x71"
+                         "\x90\x47\x40\x92\xE6\x69\xD1\x96"
+                         "\x34\xB3\x3B\xE5\x43\xE4\xD5\x56"
+                         "\xB2\xE6\x7E\x86\x7A\x12\x17\x5B"
+                         "\x30\xF3\x9B\x0D\xFA\x57\xE4\x50"
+                         "\x40\x53\x77\x8C\x15\xF8\x8D\x13",
+               .ilen   = 496,
                .result = "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
                          "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
                          "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
@@ -6400,8 +9601,52 @@ static struct cipher_testvec serpent_ctr_dec_tv_template[] = {
                          "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
                          "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
                          "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
-                         "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A",
-               .rlen   = 144,
+                         "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+                         "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+                         "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+                         "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+                         "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+                         "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+                         "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+                         "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+                         "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+                         "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+                         "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+                         "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+                         "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+                         "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+                         "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+                         "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+                         "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+                         "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+                         "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+                         "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+                         "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+                         "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+                         "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+                         "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+                         "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+                         "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+                         "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+                         "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+                         "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+                         "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+                         "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+                         "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+                         "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+                         "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+                         "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+                         "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+                         "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+                         "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+                         "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+                         "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+                         "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+                         "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+                         "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+                         "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+                         "\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
+               .rlen   = 496,
        }, { /* Generated with Crypto++ */
                .key    = "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
                          "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
@@ -6428,8 +9673,52 @@ static struct cipher_testvec serpent_ctr_dec_tv_template[] = {
                          "\x7C\xB5\x12\x89\xED\xBF\xB6\x09"
                          "\x13\x4F\x7D\x61\x3C\x5C\x27\xFC"
                          "\x5D\xE1\x4F\xA1\xEA\xB3\xCA\xB9"
-                         "\xE6\xD0\x97",
-               .ilen   = 147,
+                         "\xE6\xD0\x97\x81\xDE\xD1\xFB\x8A"
+                         "\x30\xDB\xA3\x5D\xEC\x25\x0B\x86"
+                         "\x71\xC8\xA7\x67\xE8\xBC\x7D\x4C"
+                         "\xAE\x82\xD3\x73\x31\x09\xCB\xB3"
+                         "\x4D\xD4\xC0\x8A\x2B\xFA\xA6\x55"
+                         "\x39\x0A\xBC\x6E\x75\xAB\xC2\xE2"
+                         "\x8A\xF2\x26\xCD\x63\x38\x35\xF7"
+                         "\xAE\x12\x83\xCD\x8A\x9E\x7E\x4C"
+                         "\xFE\x4D\xD7\xCE\x5C\x6E\x4C\xAF"
+                         "\xE3\xCD\x76\xA7\x87\xA1\x54\x7C"
+                         "\xEC\x32\xC7\x83\x2A\xFF\xF8\xEA"
+                         "\x87\xB2\x47\xA3\x9D\xC2\x9C\xA2"
+                         "\xB7\x2C\x7C\x1A\x24\xCB\x88\x61"
+                         "\xFF\xA7\x1A\x16\x01\xDD\x4B\xFC"
+                         "\x2E\xE0\x48\x67\x09\x42\xCC\x91"
+                         "\xBE\x20\x38\xC0\x5E\x3B\x95\x00"
+                         "\xA1\x96\x66\x0B\x8A\xE9\x9E\xF7"
+                         "\x6B\x34\x0A\x51\xC0\x3B\xEB\x71"
+                         "\x07\x97\x38\x4B\x5C\x56\x98\x67"
+                         "\x78\x9C\xD0\x0E\x2B\xB5\x67\x90"
+                         "\x75\xF8\xFE\x6D\x4E\x85\xCC\x0D"
+                         "\x18\x06\x15\x9D\x5A\x10\x13\x37"
+                         "\xA3\xD6\x68\xA2\xDF\x7E\xC7\x12"
+                         "\xC9\x0D\x4D\x91\xB0\x2A\x55\xFF"
+                         "\x6F\x73\x13\xDF\x28\xB5\x2A\x2C"
+                         "\xE4\xFC\x20\xD9\xF1\x7A\x82\xB1"
+                         "\xCB\x57\xB6\x3D\x8C\xF4\x8E\x27"
+                         "\x37\xDC\x35\xF3\x79\x01\x53\xA4"
+                         "\x7B\x37\xDE\x7C\x04\xAE\x50\xDB"
+                         "\x9B\x1E\x8C\x07\xA7\x52\x49\x50"
+                         "\x34\x25\x65\xDD\xA9\x8F\x7E\xBD"
+                         "\x7A\xC9\x36\xAE\xDE\x21\x48\x64"
+                         "\xC2\x02\xBA\xBE\x11\x1E\x3D\x9C"
+                         "\x98\x52\xCC\x04\xBD\x5E\x61\x26"
+                         "\x10\xD3\x21\xD9\x6E\x25\x98\x77"
+                         "\x8E\x98\x63\xF6\xF6\x52\xFB\x13"
+                         "\xAA\x30\xF2\xB9\xA4\x43\x53\x39"
+                         "\x1C\x97\x07\x7E\x6B\xFF\x3D\x43"
+                         "\xA6\x71\x6B\x66\x8F\x58\x3F\x71"
+                         "\x90\x47\x40\x92\xE6\x69\xD1\x96"
+                         "\x34\xB3\x3B\xE5\x43\xE4\xD5\x56"
+                         "\xB2\xE6\x7E\x86\x7A\x12\x17\x5B"
+                         "\x30\xF3\x9B\x0D\xFA\x57\xE4\x50"
+                         "\x40\x53\x77\x8C\x15\xF8\x8D\x13"
+                         "\x38\xE2\xE5",
+               .ilen   = 499,
                .result = "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
                          "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
                          "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
@@ -6448,11 +9737,55 @@ static struct cipher_testvec serpent_ctr_dec_tv_template[] = {
                          "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
                          "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
                          "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
-                         "\xF1\x65\xFC",
-               .rlen   = 147,
+                         "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+                         "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+                         "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+                         "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+                         "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+                         "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+                         "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+                         "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+                         "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+                         "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+                         "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+                         "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+                         "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+                         "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+                         "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+                         "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+                         "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+                         "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+                         "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+                         "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+                         "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+                         "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+                         "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+                         "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+                         "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+                         "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+                         "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+                         "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+                         "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+                         "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+                         "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+                         "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+                         "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+                         "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+                         "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+                         "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+                         "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+                         "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+                         "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+                         "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+                         "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+                         "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+                         "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+                         "\xDC\x50\xE7\x7E\x15\x89\x20\xB7"
+                         "\x2B\xC2\x59",
+               .rlen   = 499,
                .also_non_np = 1,
                .np     = 2,
-               .tap    = { 147 - 16, 16 },
+               .tap    = { 499 - 16, 16 },
        }, { /* Generated with Crypto++ */
                .key    = "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
                          "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
@@ -9326,10 +12659,10 @@ static struct cipher_testvec cast6_xts_dec_tv_template[] = {
 /*
  * AES test vectors.
  */
-#define AES_ENC_TEST_VECTORS 3
-#define AES_DEC_TEST_VECTORS 3
-#define AES_CBC_ENC_TEST_VECTORS 4
-#define AES_CBC_DEC_TEST_VECTORS 4
+#define AES_ENC_TEST_VECTORS 4
+#define AES_DEC_TEST_VECTORS 4
+#define AES_CBC_ENC_TEST_VECTORS 5
+#define AES_CBC_DEC_TEST_VECTORS 5
 #define HMAC_SHA1_AES_CBC_ENC_TEST_VECTORS 7
 #define HMAC_SHA256_AES_CBC_ENC_TEST_VECTORS 7
 #define HMAC_SHA512_AES_CBC_ENC_TEST_VECTORS 7
@@ -9337,8 +12670,8 @@ static struct cipher_testvec cast6_xts_dec_tv_template[] = {
 #define AES_LRW_DEC_TEST_VECTORS 8
 #define AES_XTS_ENC_TEST_VECTORS 5
 #define AES_XTS_DEC_TEST_VECTORS 5
-#define AES_CTR_ENC_TEST_VECTORS 3
-#define AES_CTR_DEC_TEST_VECTORS 3
+#define AES_CTR_ENC_TEST_VECTORS 5
+#define AES_CTR_DEC_TEST_VECTORS 5
 #define AES_OFB_ENC_TEST_VECTORS 1
 #define AES_OFB_DEC_TEST_VECTORS 1
 #define AES_CTR_3686_ENC_TEST_VECTORS 7
@@ -9386,6 +12719,141 @@ static struct cipher_testvec aes_enc_tv_template[] = {
                .result = "\x8e\xa2\xb7\xca\x51\x67\x45\xbf"
                          "\xea\xfc\x49\x90\x4b\x49\x60\x89",
                .rlen   = 16,
+       }, { /* Generated with Crypto++ */
+               .key    = "\xA6\xC9\x83\xA6\xC9\xEC\x0F\x32"
+                         "\x55\x0F\x32\x55\x78\x9B\xBE\x78"
+                         "\x9B\xBE\xE1\x04\x27\xE1\x04\x27"
+                         "\x4A\x6D\x90\x4A\x6D\x90\xB3\xD6",
+               .klen   = 32,
+               .input  = "\x50\xB9\x22\xAE\x17\x80\x0C\x75"
+                         "\xDE\x47\xD3\x3C\xA5\x0E\x9A\x03"
+                         "\x6C\xF8\x61\xCA\x33\xBF\x28\x91"
+                         "\x1D\x86\xEF\x58\xE4\x4D\xB6\x1F"
+                         "\xAB\x14\x7D\x09\x72\xDB\x44\xD0"
+                         "\x39\xA2\x0B\x97\x00\x69\xF5\x5E"
+                         "\xC7\x30\xBC\x25\x8E\x1A\x83\xEC"
+                         "\x55\xE1\x4A\xB3\x1C\xA8\x11\x7A"
+                         "\x06\x6F\xD8\x41\xCD\x36\x9F\x08"
+                         "\x94\xFD\x66\xF2\x5B\xC4\x2D\xB9"
+                         "\x22\x8B\x17\x80\xE9\x52\xDE\x47"
+                         "\xB0\x19\xA5\x0E\x77\x03\x6C\xD5"
+                         "\x3E\xCA\x33\x9C\x05\x91\xFA\x63"
+                         "\xEF\x58\xC1\x2A\xB6\x1F\x88\x14"
+                         "\x7D\xE6\x4F\xDB\x44\xAD\x16\xA2"
+                         "\x0B\x74\x00\x69\xD2\x3B\xC7\x30"
+                         "\x99\x02\x8E\xF7\x60\xEC\x55\xBE"
+                         "\x27\xB3\x1C\x85\x11\x7A\xE3\x4C"
+                         "\xD8\x41\xAA\x13\x9F\x08\x71\xFD"
+                         "\x66\xCF\x38\xC4\x2D\x96\x22\x8B"
+                         "\xF4\x5D\xE9\x52\xBB\x24\xB0\x19"
+                         "\x82\x0E\x77\xE0\x49\xD5\x3E\xA7"
+                         "\x10\x9C\x05\x6E\xFA\x63\xCC\x35"
+                         "\xC1\x2A\x93\x1F\x88\xF1\x5A\xE6"
+                         "\x4F\xB8\x21\xAD\x16\x7F\x0B\x74"
+                         "\xDD\x46\xD2\x3B\xA4\x0D\x99\x02"
+                         "\x6B\xF7\x60\xC9\x32\xBE\x27\x90"
+                         "\x1C\x85\xEE\x57\xE3\x4C\xB5\x1E"
+                         "\xAA\x13\x7C\x08\x71\xDA\x43\xCF"
+                         "\x38\xA1\x0A\x96\xFF\x68\xF4\x5D"
+                         "\xC6\x2F\xBB\x24\x8D\x19\x82\xEB"
+                         "\x54\xE0\x49\xB2\x1B\xA7\x10\x79"
+                         "\x05\x6E\xD7\x40\xCC\x35\x9E\x07"
+                         "\x93\xFC\x65\xF1\x5A\xC3\x2C\xB8"
+                         "\x21\x8A\x16\x7F\xE8\x51\xDD\x46"
+                         "\xAF\x18\xA4\x0D\x76\x02\x6B\xD4"
+                         "\x3D\xC9\x32\x9B\x04\x90\xF9\x62"
+                         "\xEE\x57\xC0\x29\xB5\x1E\x87\x13"
+                         "\x7C\xE5\x4E\xDA\x43\xAC\x15\xA1"
+                         "\x0A\x73\xFF\x68\xD1\x3A\xC6\x2F"
+                         "\x98\x01\x8D\xF6\x5F\xEB\x54\xBD"
+                         "\x26\xB2\x1B\x84\x10\x79\xE2\x4B"
+                         "\xD7\x40\xA9\x12\x9E\x07\x70\xFC"
+                         "\x65\xCE\x37\xC3\x2C\x95\x21\x8A"
+                         "\xF3\x5C\xE8\x51\xBA\x23\xAF\x18"
+                         "\x81\x0D\x76\xDF\x48\xD4\x3D\xA6"
+                         "\x0F\x9B\x04\x6D\xF9\x62\xCB\x34"
+                         "\xC0\x29\x92\x1E\x87\xF0\x59\xE5"
+                         "\x4E\xB7\x20\xAC\x15\x7E\x0A\x73"
+                         "\xDC\x45\xD1\x3A\xA3\x0C\x98\x01"
+                         "\x6A\xF6\x5F\xC8\x31\xBD\x26\x8F"
+                         "\x1B\x84\xED\x56\xE2\x4B\xB4\x1D"
+                         "\xA9\x12\x7B\x07\x70\xD9\x42\xCE"
+                         "\x37\xA0\x09\x95\xFE\x67\xF3\x5C"
+                         "\xC5\x2E\xBA\x23\x8C\x18\x81\xEA"
+                         "\x53\xDF\x48\xB1\x1A\xA6\x0F\x78"
+                         "\x04\x6D\xD6\x3F\xCB\x34\x9D\x06"
+                         "\x92\xFB\x64\xF0\x59\xC2\x2B\xB7"
+                         "\x20\x89\x15\x7E\xE7\x50\xDC\x45"
+                         "\xAE\x17\xA3\x0C\x75\x01\x6A\xD3"
+                         "\x3C\xC8\x31\x9A\x03\x8F\xF8\x61"
+                         "\xED\x56\xBF\x28\xB4\x1D\x86\x12",
+               .ilen   = 496,
+               .result = "\x71\x73\xF7\xDB\x24\x93\x21\x6D"
+                         "\x61\x1E\xBB\x63\x42\x79\xDB\x64"
+                         "\x6F\x82\xC0\xCA\xA3\x9B\xFA\x0B"
+                         "\xD9\x08\xC7\x4A\x90\xAE\x8F\x5F"
+                         "\x5E\x06\xF0\x5F\x31\x51\x18\x37"
+                         "\x45\xD7\xCA\x3A\xFD\x6C\x3F\xE1"
+                         "\xDD\x8D\x22\x65\x2B\x00\x50\xCE"
+                         "\xBA\x28\x67\xD7\xCE\x0E\x0D\xEA"
+                         "\x78\x69\x7F\xAE\x8F\x8B\x69\x37"
+                         "\x75\xE0\xDC\x96\xE0\xB7\xF4\x09"
+                         "\xCB\x6D\xA2\xFB\xDA\xAF\x09\xF8"
+                         "\x81\x82\x27\xFA\x45\x9C\x29\xA4"
+                         "\x22\x8B\x78\x69\x5B\x46\xF9\x39"
+                         "\x1B\xCC\xF9\x1D\x09\xEB\xBC\x5C"
+                         "\x41\x72\x51\x97\x1D\x07\x49\xA0"
+                         "\x1B\x8E\x65\x4B\xB2\x6A\x12\x03"
+                         "\x6A\x60\x95\xAC\xBD\xAC\x1A\x64"
+                         "\xDE\x5A\xA5\xF0\x83\x2F\xCB\xCA"
+                         "\x22\x74\xA6\x6C\x9B\x73\xCE\x3F"
+                         "\xE1\x8B\x22\x17\x59\x0C\x47\x89"
+                         "\x33\xA1\xD6\x47\x03\x19\x4F\xA8"
+                         "\x67\x69\xF0\x5B\xF0\x20\xAD\x06"
+                         "\x27\x81\x92\xD8\xC5\xBA\x98\x12"
+                         "\xBE\x24\xB5\x2F\x75\x02\xC2\xAD"
+                         "\x12\x2F\x07\x32\xEE\x39\xAF\x64"
+                         "\x05\x8F\xB3\xD4\xEB\x1B\x46\x6E"
+                         "\xD9\x21\xF9\xC4\xB7\xC9\x45\x68"
+                         "\xB4\xA1\x74\x9F\x82\x47\xEB\xCC"
+                         "\xBD\x0A\x14\x95\x0F\x8B\xA8\x2F"
+                         "\x4B\x1B\xA7\xBF\x82\xA6\x43\x0C"
+                         "\xB9\x39\x4A\xA8\x10\x6F\x50\x7B"
+                         "\x25\xFB\x26\x81\xE0\x2F\xF0\x96"
+                         "\x8D\x8B\xAC\x92\x0F\xF6\xED\x64"
+                         "\x63\x29\x4C\x8E\x18\x13\xC5\xBF"
+                         "\xFC\xA0\xD9\xBF\x7C\x3A\x0E\x29"
+                         "\x6F\xD1\x6C\x6F\xA5\xDA\xBF\xB1"
+                         "\x30\xEA\x44\x2D\xC3\x8F\x16\xE1"
+                         "\x66\xFA\xA3\x21\x3E\xFC\x13\xCA"
+                         "\xF0\xF6\xF0\x59\xBD\x8F\x38\x50"
+                         "\x31\xCB\x69\x3F\x96\x15\xD6\xF5"
+                         "\xAE\xFF\xF6\xAA\x41\x85\x4C\x10"
+                         "\x58\xE3\xF9\x44\xE6\x28\xDA\x9A"
+                         "\xDC\x6A\x80\x34\x73\x97\x1B\xC5"
+                         "\xCA\x26\x16\x77\x0E\x60\xAB\x89"
+                         "\x0F\x04\x27\xBD\xCE\x3E\x71\xB4"
+                         "\xA0\xD7\x22\x7E\xDB\xEB\x24\x70"
+                         "\x42\x71\x51\x78\x70\xB3\xE0\x3D"
+                         "\x84\x8E\x8D\x7B\xD0\x6D\xEA\x92"
+                         "\x11\x08\x42\x4F\xE5\xAD\x26\x92"
+                         "\xD2\x00\xAE\xA8\xE3\x4B\x37\x47"
+                         "\x22\xC1\x95\xC1\x63\x7F\xCB\x03"
+                         "\xF3\xE3\xD7\x9D\x60\xC7\xBC\xEA"
+                         "\x35\xA2\xFD\x45\x52\x39\x13\x6F"
+                         "\xC1\x53\xF3\x53\xDF\x33\x84\xD7"
+                         "\xD2\xC8\x37\xB0\x75\xE3\x41\x46"
+                         "\xB3\xC7\x83\x2E\x8A\xBB\xA4\xE5"
+                         "\x7F\x3C\xFD\x8B\xEB\xEA\x63\xBD"
+                         "\xB7\x46\xE7\xBF\x09\x9C\x0D\x0F"
+                         "\x40\x86\x7F\x51\xE1\x11\x9C\xCB"
+                         "\x88\xE6\x68\x47\xE3\x2B\xC5\xFF"
+                         "\x09\x79\xA0\x43\x5C\x0D\x08\x58"
+                         "\x17\xBB\xC0\x6B\x62\x3F\x56\xE9",
+               .rlen   = 496,
+               .also_non_np = 1,
+               .np     = 2,
+               .tap    = { 496 - 16, 16 },
        },
 };
 
@@ -9423,6 +12891,141 @@ static struct cipher_testvec aes_dec_tv_template[] = {
                .result = "\x00\x11\x22\x33\x44\x55\x66\x77"
                          "\x88\x99\xaa\xbb\xcc\xdd\xee\xff",
                .rlen   = 16,
+       }, { /* Generated with Crypto++ */
+               .key    = "\xA6\xC9\x83\xA6\xC9\xEC\x0F\x32"
+                         "\x55\x0F\x32\x55\x78\x9B\xBE\x78"
+                         "\x9B\xBE\xE1\x04\x27\xE1\x04\x27"
+                         "\x4A\x6D\x90\x4A\x6D\x90\xB3\xD6",
+               .klen   = 32,
+               .input  = "\x71\x73\xF7\xDB\x24\x93\x21\x6D"
+                         "\x61\x1E\xBB\x63\x42\x79\xDB\x64"
+                         "\x6F\x82\xC0\xCA\xA3\x9B\xFA\x0B"
+                         "\xD9\x08\xC7\x4A\x90\xAE\x8F\x5F"
+                         "\x5E\x06\xF0\x5F\x31\x51\x18\x37"
+                         "\x45\xD7\xCA\x3A\xFD\x6C\x3F\xE1"
+                         "\xDD\x8D\x22\x65\x2B\x00\x50\xCE"
+                         "\xBA\x28\x67\xD7\xCE\x0E\x0D\xEA"
+                         "\x78\x69\x7F\xAE\x8F\x8B\x69\x37"
+                         "\x75\xE0\xDC\x96\xE0\xB7\xF4\x09"
+                         "\xCB\x6D\xA2\xFB\xDA\xAF\x09\xF8"
+                         "\x81\x82\x27\xFA\x45\x9C\x29\xA4"
+                         "\x22\x8B\x78\x69\x5B\x46\xF9\x39"
+                         "\x1B\xCC\xF9\x1D\x09\xEB\xBC\x5C"
+                         "\x41\x72\x51\x97\x1D\x07\x49\xA0"
+                         "\x1B\x8E\x65\x4B\xB2\x6A\x12\x03"
+                         "\x6A\x60\x95\xAC\xBD\xAC\x1A\x64"
+                         "\xDE\x5A\xA5\xF0\x83\x2F\xCB\xCA"
+                         "\x22\x74\xA6\x6C\x9B\x73\xCE\x3F"
+                         "\xE1\x8B\x22\x17\x59\x0C\x47\x89"
+                         "\x33\xA1\xD6\x47\x03\x19\x4F\xA8"
+                         "\x67\x69\xF0\x5B\xF0\x20\xAD\x06"
+                         "\x27\x81\x92\xD8\xC5\xBA\x98\x12"
+                         "\xBE\x24\xB5\x2F\x75\x02\xC2\xAD"
+                         "\x12\x2F\x07\x32\xEE\x39\xAF\x64"
+                         "\x05\x8F\xB3\xD4\xEB\x1B\x46\x6E"
+                         "\xD9\x21\xF9\xC4\xB7\xC9\x45\x68"
+                         "\xB4\xA1\x74\x9F\x82\x47\xEB\xCC"
+                         "\xBD\x0A\x14\x95\x0F\x8B\xA8\x2F"
+                         "\x4B\x1B\xA7\xBF\x82\xA6\x43\x0C"
+                         "\xB9\x39\x4A\xA8\x10\x6F\x50\x7B"
+                         "\x25\xFB\x26\x81\xE0\x2F\xF0\x96"
+                         "\x8D\x8B\xAC\x92\x0F\xF6\xED\x64"
+                         "\x63\x29\x4C\x8E\x18\x13\xC5\xBF"
+                         "\xFC\xA0\xD9\xBF\x7C\x3A\x0E\x29"
+                         "\x6F\xD1\x6C\x6F\xA5\xDA\xBF\xB1"
+                         "\x30\xEA\x44\x2D\xC3\x8F\x16\xE1"
+                         "\x66\xFA\xA3\x21\x3E\xFC\x13\xCA"
+                         "\xF0\xF6\xF0\x59\xBD\x8F\x38\x50"
+                         "\x31\xCB\x69\x3F\x96\x15\xD6\xF5"
+                         "\xAE\xFF\xF6\xAA\x41\x85\x4C\x10"
+                         "\x58\xE3\xF9\x44\xE6\x28\xDA\x9A"
+                         "\xDC\x6A\x80\x34\x73\x97\x1B\xC5"
+                         "\xCA\x26\x16\x77\x0E\x60\xAB\x89"
+                         "\x0F\x04\x27\xBD\xCE\x3E\x71\xB4"
+                         "\xA0\xD7\x22\x7E\xDB\xEB\x24\x70"
+                         "\x42\x71\x51\x78\x70\xB3\xE0\x3D"
+                         "\x84\x8E\x8D\x7B\xD0\x6D\xEA\x92"
+                         "\x11\x08\x42\x4F\xE5\xAD\x26\x92"
+                         "\xD2\x00\xAE\xA8\xE3\x4B\x37\x47"
+                         "\x22\xC1\x95\xC1\x63\x7F\xCB\x03"
+                         "\xF3\xE3\xD7\x9D\x60\xC7\xBC\xEA"
+                         "\x35\xA2\xFD\x45\x52\x39\x13\x6F"
+                         "\xC1\x53\xF3\x53\xDF\x33\x84\xD7"
+                         "\xD2\xC8\x37\xB0\x75\xE3\x41\x46"
+                         "\xB3\xC7\x83\x2E\x8A\xBB\xA4\xE5"
+                         "\x7F\x3C\xFD\x8B\xEB\xEA\x63\xBD"
+                         "\xB7\x46\xE7\xBF\x09\x9C\x0D\x0F"
+                         "\x40\x86\x7F\x51\xE1\x11\x9C\xCB"
+                         "\x88\xE6\x68\x47\xE3\x2B\xC5\xFF"
+                         "\x09\x79\xA0\x43\x5C\x0D\x08\x58"
+                         "\x17\xBB\xC0\x6B\x62\x3F\x56\xE9",
+               .ilen   = 496,
+               .result = "\x50\xB9\x22\xAE\x17\x80\x0C\x75"
+                         "\xDE\x47\xD3\x3C\xA5\x0E\x9A\x03"
+                         "\x6C\xF8\x61\xCA\x33\xBF\x28\x91"
+                         "\x1D\x86\xEF\x58\xE4\x4D\xB6\x1F"
+                         "\xAB\x14\x7D\x09\x72\xDB\x44\xD0"
+                         "\x39\xA2\x0B\x97\x00\x69\xF5\x5E"
+                         "\xC7\x30\xBC\x25\x8E\x1A\x83\xEC"
+                         "\x55\xE1\x4A\xB3\x1C\xA8\x11\x7A"
+                         "\x06\x6F\xD8\x41\xCD\x36\x9F\x08"
+                         "\x94\xFD\x66\xF2\x5B\xC4\x2D\xB9"
+                         "\x22\x8B\x17\x80\xE9\x52\xDE\x47"
+                         "\xB0\x19\xA5\x0E\x77\x03\x6C\xD5"
+                         "\x3E\xCA\x33\x9C\x05\x91\xFA\x63"
+                         "\xEF\x58\xC1\x2A\xB6\x1F\x88\x14"
+                         "\x7D\xE6\x4F\xDB\x44\xAD\x16\xA2"
+                         "\x0B\x74\x00\x69\xD2\x3B\xC7\x30"
+                         "\x99\x02\x8E\xF7\x60\xEC\x55\xBE"
+                         "\x27\xB3\x1C\x85\x11\x7A\xE3\x4C"
+                         "\xD8\x41\xAA\x13\x9F\x08\x71\xFD"
+                         "\x66\xCF\x38\xC4\x2D\x96\x22\x8B"
+                         "\xF4\x5D\xE9\x52\xBB\x24\xB0\x19"
+                         "\x82\x0E\x77\xE0\x49\xD5\x3E\xA7"
+                         "\x10\x9C\x05\x6E\xFA\x63\xCC\x35"
+                         "\xC1\x2A\x93\x1F\x88\xF1\x5A\xE6"
+                         "\x4F\xB8\x21\xAD\x16\x7F\x0B\x74"
+                         "\xDD\x46\xD2\x3B\xA4\x0D\x99\x02"
+                         "\x6B\xF7\x60\xC9\x32\xBE\x27\x90"
+                         "\x1C\x85\xEE\x57\xE3\x4C\xB5\x1E"
+                         "\xAA\x13\x7C\x08\x71\xDA\x43\xCF"
+                         "\x38\xA1\x0A\x96\xFF\x68\xF4\x5D"
+                         "\xC6\x2F\xBB\x24\x8D\x19\x82\xEB"
+                         "\x54\xE0\x49\xB2\x1B\xA7\x10\x79"
+                         "\x05\x6E\xD7\x40\xCC\x35\x9E\x07"
+                         "\x93\xFC\x65\xF1\x5A\xC3\x2C\xB8"
+                         "\x21\x8A\x16\x7F\xE8\x51\xDD\x46"
+                         "\xAF\x18\xA4\x0D\x76\x02\x6B\xD4"
+                         "\x3D\xC9\x32\x9B\x04\x90\xF9\x62"
+                         "\xEE\x57\xC0\x29\xB5\x1E\x87\x13"
+                         "\x7C\xE5\x4E\xDA\x43\xAC\x15\xA1"
+                         "\x0A\x73\xFF\x68\xD1\x3A\xC6\x2F"
+                         "\x98\x01\x8D\xF6\x5F\xEB\x54\xBD"
+                         "\x26\xB2\x1B\x84\x10\x79\xE2\x4B"
+                         "\xD7\x40\xA9\x12\x9E\x07\x70\xFC"
+                         "\x65\xCE\x37\xC3\x2C\x95\x21\x8A"
+                         "\xF3\x5C\xE8\x51\xBA\x23\xAF\x18"
+                         "\x81\x0D\x76\xDF\x48\xD4\x3D\xA6"
+                         "\x0F\x9B\x04\x6D\xF9\x62\xCB\x34"
+                         "\xC0\x29\x92\x1E\x87\xF0\x59\xE5"
+                         "\x4E\xB7\x20\xAC\x15\x7E\x0A\x73"
+                         "\xDC\x45\xD1\x3A\xA3\x0C\x98\x01"
+                         "\x6A\xF6\x5F\xC8\x31\xBD\x26\x8F"
+                         "\x1B\x84\xED\x56\xE2\x4B\xB4\x1D"
+                         "\xA9\x12\x7B\x07\x70\xD9\x42\xCE"
+                         "\x37\xA0\x09\x95\xFE\x67\xF3\x5C"
+                         "\xC5\x2E\xBA\x23\x8C\x18\x81\xEA"
+                         "\x53\xDF\x48\xB1\x1A\xA6\x0F\x78"
+                         "\x04\x6D\xD6\x3F\xCB\x34\x9D\x06"
+                         "\x92\xFB\x64\xF0\x59\xC2\x2B\xB7"
+                         "\x20\x89\x15\x7E\xE7\x50\xDC\x45"
+                         "\xAE\x17\xA3\x0C\x75\x01\x6A\xD3"
+                         "\x3C\xC8\x31\x9A\x03\x8F\xF8\x61"
+                         "\xED\x56\xBF\x28\xB4\x1D\x86\x12",
+               .rlen   = 496,
+               .also_non_np = 1,
+               .np     = 2,
+               .tap    = { 496 - 16, 16 },
        },
 };
 
@@ -9505,6 +13108,143 @@ static struct cipher_testvec aes_cbc_enc_tv_template[] = {
                          "\xb2\xeb\x05\xe2\xc3\x9b\xe9\xfc"
                          "\xda\x6c\x19\x07\x8c\x6a\x9d\x1b",
                .rlen   = 64,
+       }, { /* Generated with Crypto++ */
+               .key    = "\xC9\x83\xA6\xC9\xEC\x0F\x32\x55"
+                         "\x0F\x32\x55\x78\x9B\xBE\x78\x9B"
+                         "\xBE\xE1\x04\x27\xE1\x04\x27\x4A"
+                         "\x6D\x90\x4A\x6D\x90\xB3\xD6\xF9",
+               .klen   = 32,
+               .iv     = "\xE7\x82\x1D\xB8\x53\x11\xAC\x47"
+                         "\xE2\x7D\x18\xD6\x71\x0C\xA7\x42",
+               .input  = "\x50\xB9\x22\xAE\x17\x80\x0C\x75"
+                         "\xDE\x47\xD3\x3C\xA5\x0E\x9A\x03"
+                         "\x6C\xF8\x61\xCA\x33\xBF\x28\x91"
+                         "\x1D\x86\xEF\x58\xE4\x4D\xB6\x1F"
+                         "\xAB\x14\x7D\x09\x72\xDB\x44\xD0"
+                         "\x39\xA2\x0B\x97\x00\x69\xF5\x5E"
+                         "\xC7\x30\xBC\x25\x8E\x1A\x83\xEC"
+                         "\x55\xE1\x4A\xB3\x1C\xA8\x11\x7A"
+                         "\x06\x6F\xD8\x41\xCD\x36\x9F\x08"
+                         "\x94\xFD\x66\xF2\x5B\xC4\x2D\xB9"
+                         "\x22\x8B\x17\x80\xE9\x52\xDE\x47"
+                         "\xB0\x19\xA5\x0E\x77\x03\x6C\xD5"
+                         "\x3E\xCA\x33\x9C\x05\x91\xFA\x63"
+                         "\xEF\x58\xC1\x2A\xB6\x1F\x88\x14"
+                         "\x7D\xE6\x4F\xDB\x44\xAD\x16\xA2"
+                         "\x0B\x74\x00\x69\xD2\x3B\xC7\x30"
+                         "\x99\x02\x8E\xF7\x60\xEC\x55\xBE"
+                         "\x27\xB3\x1C\x85\x11\x7A\xE3\x4C"
+                         "\xD8\x41\xAA\x13\x9F\x08\x71\xFD"
+                         "\x66\xCF\x38\xC4\x2D\x96\x22\x8B"
+                         "\xF4\x5D\xE9\x52\xBB\x24\xB0\x19"
+                         "\x82\x0E\x77\xE0\x49\xD5\x3E\xA7"
+                         "\x10\x9C\x05\x6E\xFA\x63\xCC\x35"
+                         "\xC1\x2A\x93\x1F\x88\xF1\x5A\xE6"
+                         "\x4F\xB8\x21\xAD\x16\x7F\x0B\x74"
+                         "\xDD\x46\xD2\x3B\xA4\x0D\x99\x02"
+                         "\x6B\xF7\x60\xC9\x32\xBE\x27\x90"
+                         "\x1C\x85\xEE\x57\xE3\x4C\xB5\x1E"
+                         "\xAA\x13\x7C\x08\x71\xDA\x43\xCF"
+                         "\x38\xA1\x0A\x96\xFF\x68\xF4\x5D"
+                         "\xC6\x2F\xBB\x24\x8D\x19\x82\xEB"
+                         "\x54\xE0\x49\xB2\x1B\xA7\x10\x79"
+                         "\x05\x6E\xD7\x40\xCC\x35\x9E\x07"
+                         "\x93\xFC\x65\xF1\x5A\xC3\x2C\xB8"
+                         "\x21\x8A\x16\x7F\xE8\x51\xDD\x46"
+                         "\xAF\x18\xA4\x0D\x76\x02\x6B\xD4"
+                         "\x3D\xC9\x32\x9B\x04\x90\xF9\x62"
+                         "\xEE\x57\xC0\x29\xB5\x1E\x87\x13"
+                         "\x7C\xE5\x4E\xDA\x43\xAC\x15\xA1"
+                         "\x0A\x73\xFF\x68\xD1\x3A\xC6\x2F"
+                         "\x98\x01\x8D\xF6\x5F\xEB\x54\xBD"
+                         "\x26\xB2\x1B\x84\x10\x79\xE2\x4B"
+                         "\xD7\x40\xA9\x12\x9E\x07\x70\xFC"
+                         "\x65\xCE\x37\xC3\x2C\x95\x21\x8A"
+                         "\xF3\x5C\xE8\x51\xBA\x23\xAF\x18"
+                         "\x81\x0D\x76\xDF\x48\xD4\x3D\xA6"
+                         "\x0F\x9B\x04\x6D\xF9\x62\xCB\x34"
+                         "\xC0\x29\x92\x1E\x87\xF0\x59\xE5"
+                         "\x4E\xB7\x20\xAC\x15\x7E\x0A\x73"
+                         "\xDC\x45\xD1\x3A\xA3\x0C\x98\x01"
+                         "\x6A\xF6\x5F\xC8\x31\xBD\x26\x8F"
+                         "\x1B\x84\xED\x56\xE2\x4B\xB4\x1D"
+                         "\xA9\x12\x7B\x07\x70\xD9\x42\xCE"
+                         "\x37\xA0\x09\x95\xFE\x67\xF3\x5C"
+                         "\xC5\x2E\xBA\x23\x8C\x18\x81\xEA"
+                         "\x53\xDF\x48\xB1\x1A\xA6\x0F\x78"
+                         "\x04\x6D\xD6\x3F\xCB\x34\x9D\x06"
+                         "\x92\xFB\x64\xF0\x59\xC2\x2B\xB7"
+                         "\x20\x89\x15\x7E\xE7\x50\xDC\x45"
+                         "\xAE\x17\xA3\x0C\x75\x01\x6A\xD3"
+                         "\x3C\xC8\x31\x9A\x03\x8F\xF8\x61"
+                         "\xED\x56\xBF\x28\xB4\x1D\x86\x12",
+               .ilen   = 496,
+               .result = "\xEA\x65\x8A\x19\xB0\x66\xC1\x3F"
+                         "\xCE\xF1\x97\x75\xC1\xFD\xB5\xAF"
+                         "\x52\x65\xF7\xFF\xBC\xD8\x2D\x9F"
+                         "\x2F\xB9\x26\x9B\x6F\x10\xB7\xB8"
+                         "\x26\xA1\x02\x46\xA2\xAD\xC6\xC0"
+                         "\x11\x15\xFF\x6D\x1E\x82\x04\xA6"
+                         "\xB1\x74\xD1\x08\x13\xFD\x90\x7C"
+                         "\xF5\xED\xD3\xDB\x5A\x0A\x0C\x2F"
+                         "\x0A\x70\xF1\x88\x07\xCF\x21\x26"
+                         "\x40\x40\x8A\xF5\x53\xF7\x24\x4F"
+                         "\x83\x38\x43\x5F\x08\x99\xEB\xE3"
+                         "\xDC\x02\x64\x67\x50\x6E\x15\xC3"
+                         "\x01\x1A\xA0\x81\x13\x65\xA6\x73"
+                         "\x71\xA6\x3B\x91\x83\x77\xBE\xFA"
+                         "\xDB\x71\x73\xA6\xC1\xAE\x43\xC3"
+                         "\x36\xCE\xD6\xEB\xF9\x30\x1C\x4F"
+                         "\x80\x38\x5E\x9C\x6E\xAB\x98\x2F"
+                         "\x53\xAF\xCF\xC8\x9A\xB8\x86\x43"
+                         "\x3E\x86\xE7\xA1\xF4\x2F\x30\x40"
+                         "\x03\xA8\x6C\x50\x42\x9F\x77\x59"
+                         "\x89\xA0\xC5\xEC\x9A\xB8\xDD\x99"
+                         "\x16\x24\x02\x07\x48\xAE\xF2\x31"
+                         "\x34\x0E\xC3\x85\xFE\x1C\x95\x99"
+                         "\x87\x58\x98\x8B\xE7\xC6\xC5\x70"
+                         "\x73\x81\x07\x7C\x56\x2F\xD8\x1B"
+                         "\xB7\xB9\x2B\xAB\xE3\x01\x87\x0F"
+                         "\xD8\xBB\xC0\x0D\xAC\x2C\x2F\x98"
+                         "\x3C\x0B\xA2\x99\x4A\x8C\xF7\x04"
+                         "\xE0\xE0\xCF\xD1\x81\x5B\xFE\xF5"
+                         "\x24\x04\xFD\xB8\xDF\x13\xD8\xCD"
+                         "\xF1\xE3\x3D\x98\x50\x02\x77\x9E"
+                         "\xBC\x22\xAB\xFA\xC2\x43\x1F\x66"
+                         "\x20\x02\x23\xDA\xDF\xA0\x89\xF6"
+                         "\xD8\xF3\x45\x24\x53\x6F\x16\x77"
+                         "\x02\x3E\x7B\x36\x5F\xA0\x3B\x78"
+                         "\x63\xA2\xBD\xB5\xA4\xCA\x1E\xD3"
+                         "\x57\xBC\x0B\x9F\x43\x51\x28\x4F"
+                         "\x07\x50\x6C\x68\x12\x07\xCF\xFA"
+                         "\x6B\x72\x0B\xEB\xF8\x88\x90\x2C"
+                         "\x7E\xF5\x91\xD1\x03\xD8\xD5\xBD"
+                         "\x22\x39\x7B\x16\x03\x01\x69\xAF"
+                         "\x3D\x38\x66\x28\x0C\xBE\x5B\xC5"
+                         "\x03\xB4\x2F\x51\x8A\x56\x17\x2B"
+                         "\x88\x42\x6D\x40\x68\x8F\xD0\x11"
+                         "\x19\xF9\x1F\x43\x79\x95\x31\xFA"
+                         "\x28\x7A\x3D\xF7\x66\xEB\xEF\xAC"
+                         "\x06\xB2\x01\xAD\xDB\x68\xDB\xEC"
+                         "\x8D\x53\x6E\x72\x68\xA3\xC7\x63"
+                         "\x43\x2B\x78\xE0\x04\x29\x8F\x72"
+                         "\xB2\x2C\xE6\x84\x03\x30\x6D\xCD"
+                         "\x26\x92\x37\xE1\x2F\xBB\x8B\x9D"
+                         "\xE4\x4C\xF6\x93\xBC\xD9\xAD\x44"
+                         "\x52\x65\xC7\xB0\x0E\x3F\x0E\x61"
+                         "\x56\x5D\x1C\x6D\xA7\x05\x2E\xBC"
+                         "\x58\x08\x15\xAB\x12\xAB\x17\x4A"
+                         "\x5E\x1C\xF2\xCD\xB8\xA2\xAE\xFB"
+                         "\x9B\x2E\x0E\x85\x34\x80\x0E\x3F"
+                         "\x4C\xB8\xDB\xCE\x1C\x90\xA1\x61"
+                         "\x6C\x69\x09\x35\x9E\xD4\xF4\xAD"
+                         "\xBC\x06\x41\xE3\x01\xB4\x4E\x0A"
+                         "\xE0\x1F\x91\xF8\x82\x96\x2D\x65"
+                         "\xA3\xAA\x13\xCC\x50\xFF\x7B\x02",
+               .rlen   = 496,
+               .also_non_np = 1,
+               .np     = 2,
+               .tap    = { 496 - 16, 16 },
        },
 };
 
@@ -9587,6 +13327,143 @@ static struct cipher_testvec aes_cbc_dec_tv_template[] = {
                          "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17"
                          "\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
                .rlen   = 64,
+       }, { /* Generated with Crypto++ */
+               .key    = "\xC9\x83\xA6\xC9\xEC\x0F\x32\x55"
+                         "\x0F\x32\x55\x78\x9B\xBE\x78\x9B"
+                         "\xBE\xE1\x04\x27\xE1\x04\x27\x4A"
+                         "\x6D\x90\x4A\x6D\x90\xB3\xD6\xF9",
+               .klen   = 32,
+               .iv     = "\xE7\x82\x1D\xB8\x53\x11\xAC\x47"
+                         "\xE2\x7D\x18\xD6\x71\x0C\xA7\x42",
+               .input  = "\xEA\x65\x8A\x19\xB0\x66\xC1\x3F"
+                         "\xCE\xF1\x97\x75\xC1\xFD\xB5\xAF"
+                         "\x52\x65\xF7\xFF\xBC\xD8\x2D\x9F"
+                         "\x2F\xB9\x26\x9B\x6F\x10\xB7\xB8"
+                         "\x26\xA1\x02\x46\xA2\xAD\xC6\xC0"
+                         "\x11\x15\xFF\x6D\x1E\x82\x04\xA6"
+                         "\xB1\x74\xD1\x08\x13\xFD\x90\x7C"
+                         "\xF5\xED\xD3\xDB\x5A\x0A\x0C\x2F"
+                         "\x0A\x70\xF1\x88\x07\xCF\x21\x26"
+                         "\x40\x40\x8A\xF5\x53\xF7\x24\x4F"
+                         "\x83\x38\x43\x5F\x08\x99\xEB\xE3"
+                         "\xDC\x02\x64\x67\x50\x6E\x15\xC3"
+                         "\x01\x1A\xA0\x81\x13\x65\xA6\x73"
+                         "\x71\xA6\x3B\x91\x83\x77\xBE\xFA"
+                         "\xDB\x71\x73\xA6\xC1\xAE\x43\xC3"
+                         "\x36\xCE\xD6\xEB\xF9\x30\x1C\x4F"
+                         "\x80\x38\x5E\x9C\x6E\xAB\x98\x2F"
+                         "\x53\xAF\xCF\xC8\x9A\xB8\x86\x43"
+                         "\x3E\x86\xE7\xA1\xF4\x2F\x30\x40"
+                         "\x03\xA8\x6C\x50\x42\x9F\x77\x59"
+                         "\x89\xA0\xC5\xEC\x9A\xB8\xDD\x99"
+                         "\x16\x24\x02\x07\x48\xAE\xF2\x31"
+                         "\x34\x0E\xC3\x85\xFE\x1C\x95\x99"
+                         "\x87\x58\x98\x8B\xE7\xC6\xC5\x70"
+                         "\x73\x81\x07\x7C\x56\x2F\xD8\x1B"
+                         "\xB7\xB9\x2B\xAB\xE3\x01\x87\x0F"
+                         "\xD8\xBB\xC0\x0D\xAC\x2C\x2F\x98"
+                         "\x3C\x0B\xA2\x99\x4A\x8C\xF7\x04"
+                         "\xE0\xE0\xCF\xD1\x81\x5B\xFE\xF5"
+                         "\x24\x04\xFD\xB8\xDF\x13\xD8\xCD"
+                         "\xF1\xE3\x3D\x98\x50\x02\x77\x9E"
+                         "\xBC\x22\xAB\xFA\xC2\x43\x1F\x66"
+                         "\x20\x02\x23\xDA\xDF\xA0\x89\xF6"
+                         "\xD8\xF3\x45\x24\x53\x6F\x16\x77"
+                         "\x02\x3E\x7B\x36\x5F\xA0\x3B\x78"
+                         "\x63\xA2\xBD\xB5\xA4\xCA\x1E\xD3"
+                         "\x57\xBC\x0B\x9F\x43\x51\x28\x4F"
+                         "\x07\x50\x6C\x68\x12\x07\xCF\xFA"
+                         "\x6B\x72\x0B\xEB\xF8\x88\x90\x2C"
+                         "\x7E\xF5\x91\xD1\x03\xD8\xD5\xBD"
+                         "\x22\x39\x7B\x16\x03\x01\x69\xAF"
+                         "\x3D\x38\x66\x28\x0C\xBE\x5B\xC5"
+                         "\x03\xB4\x2F\x51\x8A\x56\x17\x2B"
+                         "\x88\x42\x6D\x40\x68\x8F\xD0\x11"
+                         "\x19\xF9\x1F\x43\x79\x95\x31\xFA"
+                         "\x28\x7A\x3D\xF7\x66\xEB\xEF\xAC"
+                         "\x06\xB2\x01\xAD\xDB\x68\xDB\xEC"
+                         "\x8D\x53\x6E\x72\x68\xA3\xC7\x63"
+                         "\x43\x2B\x78\xE0\x04\x29\x8F\x72"
+                         "\xB2\x2C\xE6\x84\x03\x30\x6D\xCD"
+                         "\x26\x92\x37\xE1\x2F\xBB\x8B\x9D"
+                         "\xE4\x4C\xF6\x93\xBC\xD9\xAD\x44"
+                         "\x52\x65\xC7\xB0\x0E\x3F\x0E\x61"
+                         "\x56\x5D\x1C\x6D\xA7\x05\x2E\xBC"
+                         "\x58\x08\x15\xAB\x12\xAB\x17\x4A"
+                         "\x5E\x1C\xF2\xCD\xB8\xA2\xAE\xFB"
+                         "\x9B\x2E\x0E\x85\x34\x80\x0E\x3F"
+                         "\x4C\xB8\xDB\xCE\x1C\x90\xA1\x61"
+                         "\x6C\x69\x09\x35\x9E\xD4\xF4\xAD"
+                         "\xBC\x06\x41\xE3\x01\xB4\x4E\x0A"
+                         "\xE0\x1F\x91\xF8\x82\x96\x2D\x65"
+                         "\xA3\xAA\x13\xCC\x50\xFF\x7B\x02",
+               .ilen   = 496,
+               .result = "\x50\xB9\x22\xAE\x17\x80\x0C\x75"
+                         "\xDE\x47\xD3\x3C\xA5\x0E\x9A\x03"
+                         "\x6C\xF8\x61\xCA\x33\xBF\x28\x91"
+                         "\x1D\x86\xEF\x58\xE4\x4D\xB6\x1F"
+                         "\xAB\x14\x7D\x09\x72\xDB\x44\xD0"
+                         "\x39\xA2\x0B\x97\x00\x69\xF5\x5E"
+                         "\xC7\x30\xBC\x25\x8E\x1A\x83\xEC"
+                         "\x55\xE1\x4A\xB3\x1C\xA8\x11\x7A"
+                         "\x06\x6F\xD8\x41\xCD\x36\x9F\x08"
+                         "\x94\xFD\x66\xF2\x5B\xC4\x2D\xB9"
+                         "\x22\x8B\x17\x80\xE9\x52\xDE\x47"
+                         "\xB0\x19\xA5\x0E\x77\x03\x6C\xD5"
+                         "\x3E\xCA\x33\x9C\x05\x91\xFA\x63"
+                         "\xEF\x58\xC1\x2A\xB6\x1F\x88\x14"
+                         "\x7D\xE6\x4F\xDB\x44\xAD\x16\xA2"
+                         "\x0B\x74\x00\x69\xD2\x3B\xC7\x30"
+                         "\x99\x02\x8E\xF7\x60\xEC\x55\xBE"
+                         "\x27\xB3\x1C\x85\x11\x7A\xE3\x4C"
+                         "\xD8\x41\xAA\x13\x9F\x08\x71\xFD"
+                         "\x66\xCF\x38\xC4\x2D\x96\x22\x8B"
+                         "\xF4\x5D\xE9\x52\xBB\x24\xB0\x19"
+                         "\x82\x0E\x77\xE0\x49\xD5\x3E\xA7"
+                         "\x10\x9C\x05\x6E\xFA\x63\xCC\x35"
+                         "\xC1\x2A\x93\x1F\x88\xF1\x5A\xE6"
+                         "\x4F\xB8\x21\xAD\x16\x7F\x0B\x74"
+                         "\xDD\x46\xD2\x3B\xA4\x0D\x99\x02"
+                         "\x6B\xF7\x60\xC9\x32\xBE\x27\x90"
+                         "\x1C\x85\xEE\x57\xE3\x4C\xB5\x1E"
+                         "\xAA\x13\x7C\x08\x71\xDA\x43\xCF"
+                         "\x38\xA1\x0A\x96\xFF\x68\xF4\x5D"
+                         "\xC6\x2F\xBB\x24\x8D\x19\x82\xEB"
+                         "\x54\xE0\x49\xB2\x1B\xA7\x10\x79"
+                         "\x05\x6E\xD7\x40\xCC\x35\x9E\x07"
+                         "\x93\xFC\x65\xF1\x5A\xC3\x2C\xB8"
+                         "\x21\x8A\x16\x7F\xE8\x51\xDD\x46"
+                         "\xAF\x18\xA4\x0D\x76\x02\x6B\xD4"
+                         "\x3D\xC9\x32\x9B\x04\x90\xF9\x62"
+                         "\xEE\x57\xC0\x29\xB5\x1E\x87\x13"
+                         "\x7C\xE5\x4E\xDA\x43\xAC\x15\xA1"
+                         "\x0A\x73\xFF\x68\xD1\x3A\xC6\x2F"
+                         "\x98\x01\x8D\xF6\x5F\xEB\x54\xBD"
+                         "\x26\xB2\x1B\x84\x10\x79\xE2\x4B"
+                         "\xD7\x40\xA9\x12\x9E\x07\x70\xFC"
+                         "\x65\xCE\x37\xC3\x2C\x95\x21\x8A"
+                         "\xF3\x5C\xE8\x51\xBA\x23\xAF\x18"
+                         "\x81\x0D\x76\xDF\x48\xD4\x3D\xA6"
+                         "\x0F\x9B\x04\x6D\xF9\x62\xCB\x34"
+                         "\xC0\x29\x92\x1E\x87\xF0\x59\xE5"
+                         "\x4E\xB7\x20\xAC\x15\x7E\x0A\x73"
+                         "\xDC\x45\xD1\x3A\xA3\x0C\x98\x01"
+                         "\x6A\xF6\x5F\xC8\x31\xBD\x26\x8F"
+                         "\x1B\x84\xED\x56\xE2\x4B\xB4\x1D"
+                         "\xA9\x12\x7B\x07\x70\xD9\x42\xCE"
+                         "\x37\xA0\x09\x95\xFE\x67\xF3\x5C"
+                         "\xC5\x2E\xBA\x23\x8C\x18\x81\xEA"
+                         "\x53\xDF\x48\xB1\x1A\xA6\x0F\x78"
+                         "\x04\x6D\xD6\x3F\xCB\x34\x9D\x06"
+                         "\x92\xFB\x64\xF0\x59\xC2\x2B\xB7"
+                         "\x20\x89\x15\x7E\xE7\x50\xDC\x45"
+                         "\xAE\x17\xA3\x0C\x75\x01\x6A\xD3"
+                         "\x3C\xC8\x31\x9A\x03\x8F\xF8\x61"
+                         "\xED\x56\xBF\x28\xB4\x1D\x86\x12",
+               .rlen   = 496,
+               .also_non_np = 1,
+               .np     = 2,
+               .tap    = { 496 - 16, 16 },
        },
 };
 
@@ -11693,7 +15570,283 @@ static struct cipher_testvec aes_ctr_enc_tv_template[] = {
                          "\xdf\xc9\xc5\x8d\xb6\x7a\xad\xa6"
                          "\x13\xc2\xdd\x08\x45\x79\x41\xa6",
                .rlen   = 64,
-       }
+       }, { /* Generated with Crypto++ */
+               .key    = "\xC9\x83\xA6\xC9\xEC\x0F\x32\x55"
+                         "\x0F\x32\x55\x78\x9B\xBE\x78\x9B"
+                         "\xBE\xE1\x04\x27\xE1\x04\x27\x4A"
+                         "\x6D\x90\x4A\x6D\x90\xB3\xD6\xF9",
+               .klen   = 32,
+               .iv     = "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
+                         "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFD",
+               .input  = "\x50\xB9\x22\xAE\x17\x80\x0C\x75"
+                         "\xDE\x47\xD3\x3C\xA5\x0E\x9A\x03"
+                         "\x6C\xF8\x61\xCA\x33\xBF\x28\x91"
+                         "\x1D\x86\xEF\x58\xE4\x4D\xB6\x1F"
+                         "\xAB\x14\x7D\x09\x72\xDB\x44\xD0"
+                         "\x39\xA2\x0B\x97\x00\x69\xF5\x5E"
+                         "\xC7\x30\xBC\x25\x8E\x1A\x83\xEC"
+                         "\x55\xE1\x4A\xB3\x1C\xA8\x11\x7A"
+                         "\x06\x6F\xD8\x41\xCD\x36\x9F\x08"
+                         "\x94\xFD\x66\xF2\x5B\xC4\x2D\xB9"
+                         "\x22\x8B\x17\x80\xE9\x52\xDE\x47"
+                         "\xB0\x19\xA5\x0E\x77\x03\x6C\xD5"
+                         "\x3E\xCA\x33\x9C\x05\x91\xFA\x63"
+                         "\xEF\x58\xC1\x2A\xB6\x1F\x88\x14"
+                         "\x7D\xE6\x4F\xDB\x44\xAD\x16\xA2"
+                         "\x0B\x74\x00\x69\xD2\x3B\xC7\x30"
+                         "\x99\x02\x8E\xF7\x60\xEC\x55\xBE"
+                         "\x27\xB3\x1C\x85\x11\x7A\xE3\x4C"
+                         "\xD8\x41\xAA\x13\x9F\x08\x71\xFD"
+                         "\x66\xCF\x38\xC4\x2D\x96\x22\x8B"
+                         "\xF4\x5D\xE9\x52\xBB\x24\xB0\x19"
+                         "\x82\x0E\x77\xE0\x49\xD5\x3E\xA7"
+                         "\x10\x9C\x05\x6E\xFA\x63\xCC\x35"
+                         "\xC1\x2A\x93\x1F\x88\xF1\x5A\xE6"
+                         "\x4F\xB8\x21\xAD\x16\x7F\x0B\x74"
+                         "\xDD\x46\xD2\x3B\xA4\x0D\x99\x02"
+                         "\x6B\xF7\x60\xC9\x32\xBE\x27\x90"
+                         "\x1C\x85\xEE\x57\xE3\x4C\xB5\x1E"
+                         "\xAA\x13\x7C\x08\x71\xDA\x43\xCF"
+                         "\x38\xA1\x0A\x96\xFF\x68\xF4\x5D"
+                         "\xC6\x2F\xBB\x24\x8D\x19\x82\xEB"
+                         "\x54\xE0\x49\xB2\x1B\xA7\x10\x79"
+                         "\x05\x6E\xD7\x40\xCC\x35\x9E\x07"
+                         "\x93\xFC\x65\xF1\x5A\xC3\x2C\xB8"
+                         "\x21\x8A\x16\x7F\xE8\x51\xDD\x46"
+                         "\xAF\x18\xA4\x0D\x76\x02\x6B\xD4"
+                         "\x3D\xC9\x32\x9B\x04\x90\xF9\x62"
+                         "\xEE\x57\xC0\x29\xB5\x1E\x87\x13"
+                         "\x7C\xE5\x4E\xDA\x43\xAC\x15\xA1"
+                         "\x0A\x73\xFF\x68\xD1\x3A\xC6\x2F"
+                         "\x98\x01\x8D\xF6\x5F\xEB\x54\xBD"
+                         "\x26\xB2\x1B\x84\x10\x79\xE2\x4B"
+                         "\xD7\x40\xA9\x12\x9E\x07\x70\xFC"
+                         "\x65\xCE\x37\xC3\x2C\x95\x21\x8A"
+                         "\xF3\x5C\xE8\x51\xBA\x23\xAF\x18"
+                         "\x81\x0D\x76\xDF\x48\xD4\x3D\xA6"
+                         "\x0F\x9B\x04\x6D\xF9\x62\xCB\x34"
+                         "\xC0\x29\x92\x1E\x87\xF0\x59\xE5"
+                         "\x4E\xB7\x20\xAC\x15\x7E\x0A\x73"
+                         "\xDC\x45\xD1\x3A\xA3\x0C\x98\x01"
+                         "\x6A\xF6\x5F\xC8\x31\xBD\x26\x8F"
+                         "\x1B\x84\xED\x56\xE2\x4B\xB4\x1D"
+                         "\xA9\x12\x7B\x07\x70\xD9\x42\xCE"
+                         "\x37\xA0\x09\x95\xFE\x67\xF3\x5C"
+                         "\xC5\x2E\xBA\x23\x8C\x18\x81\xEA"
+                         "\x53\xDF\x48\xB1\x1A\xA6\x0F\x78"
+                         "\x04\x6D\xD6\x3F\xCB\x34\x9D\x06"
+                         "\x92\xFB\x64\xF0\x59\xC2\x2B\xB7"
+                         "\x20\x89\x15\x7E\xE7\x50\xDC\x45"
+                         "\xAE\x17\xA3\x0C\x75\x01\x6A\xD3"
+                         "\x3C\xC8\x31\x9A\x03\x8F\xF8\x61"
+                         "\xED\x56\xBF\x28\xB4\x1D\x86\x12",
+               .ilen   = 496,
+               .result = "\x04\xF3\xD3\x88\x17\xEF\xDC\xEF"
+                         "\x8B\x04\xF8\x3A\x66\x8D\x1A\x53"
+                         "\x57\x1F\x4B\x23\xE4\xA0\xAF\xF9"
+                         "\x69\x95\x35\x98\x8D\x4D\x8C\xC1"
+                         "\xF0\xB2\x7F\x80\xBB\x54\x28\xA2"
+                         "\x7A\x1B\x9F\x77\xEC\x0E\x6E\xDE"
+                         "\xF0\xEC\xB8\xE4\x20\x62\xEE\xDB"
+                         "\x5D\xF5\xDD\xE3\x54\xFC\xDD\xEB"
+                         "\x6A\xEE\x65\xA1\x21\xD6\xD7\x81"
+                         "\x47\x61\x12\x4D\xC2\x8C\xFA\x78"
+                         "\x1F\x28\x02\x01\xC3\xFC\x1F\xEC"
+                         "\x0F\x10\x4F\xB3\x12\x45\xC6\x3B"
+                         "\x7E\x08\xF9\x5A\xD0\x5D\x73\x2D"
+                         "\x58\xA4\xE5\xCB\x1C\xB4\xCE\x74"
+                         "\x32\x41\x1F\x31\x9C\x08\xA2\x5D"
+                         "\x67\xEB\x72\x1D\xF8\xE7\x70\x54"
+                         "\x34\x4B\x31\x69\x84\x66\x96\x44"
+                         "\x56\xCC\x1E\xD9\xE6\x13\x6A\xB9"
+                         "\x2D\x0A\x05\x45\x2D\x90\xCC\xDF"
+                         "\x16\x5C\x5F\x79\x34\x52\x54\xFE"
+                         "\xFE\xCD\xAD\x04\x2E\xAD\x86\x06"
+                         "\x1F\x37\xE8\x28\xBC\xD3\x8F\x5B"
+                         "\x92\x66\x87\x3B\x8A\x0A\x1A\xCC"
+                         "\x6E\xAB\x9F\x0B\xFA\x5C\xE6\xFD"
+                         "\x3C\x98\x08\x12\xEC\xAA\x9E\x11"
+                         "\xCA\xB2\x1F\xCE\x5E\x5B\xB2\x72"
+                         "\x9C\xCC\x5D\xC5\xE0\x32\xC0\x56"
+                         "\xD5\x45\x16\xD2\xAF\x13\x66\xF7"
+                         "\x8C\x67\xAC\x79\xB2\xAF\x56\x27"
+                         "\x3F\xCC\xFE\xCB\x1E\xC0\x75\xF1"
+                         "\xA7\xC9\xC3\x1D\x8E\xDD\xF9\xD4"
+                         "\x42\xC8\x21\x08\x16\xF7\x01\xD7"
+                         "\xAC\x8E\x3F\x1D\x56\xC1\x06\xE4"
+                         "\x9C\x62\xD6\xA5\x6A\x50\x44\xB3"
+                         "\x35\x1C\x82\xB9\x10\xF9\x42\xA1"
+                         "\xFC\x74\x9B\x44\x4F\x25\x02\xE3"
+                         "\x08\xF5\xD4\x32\x39\x08\x11\xE8"
+                         "\xD2\x6B\x50\x53\xD4\x08\xD1\x6B"
+                         "\x3A\x4A\x68\x7B\x7C\xCD\x46\x5E"
+                         "\x0D\x07\x19\xDB\x67\xD7\x98\x91"
+                         "\xD7\x17\x10\x9B\x7B\x8A\x9B\x33"
+                         "\xAE\xF3\x00\xA6\xD4\x15\xD9\xEA"
+                         "\x85\x99\x22\xE8\x91\x38\x70\x83"
+                         "\x93\x01\x24\x6C\xFA\x9A\xB9\x07"
+                         "\xEA\x8D\x3B\xD9\x2A\x43\x59\x16"
+                         "\x2F\x69\xEE\x84\x36\x44\x76\x98"
+                         "\xF3\x04\x2A\x7C\x74\x3D\x29\x2B"
+                         "\x0D\xAD\x8F\x44\x82\x9E\x57\x8D"
+                         "\xAC\xED\x18\x1F\x50\xA4\xF5\x98"
+                         "\x1F\xBD\x92\x91\x1B\x2D\xA6\xD6"
+                         "\xD2\xE3\x02\xAA\x92\x3B\xC6\xB3"
+                         "\x1B\x39\x72\xD5\x26\xCA\x04\xE0"
+                         "\xFC\x58\x78\xBB\xB1\x3F\xA1\x9C"
+                         "\x42\x24\x3E\x2E\x22\xBB\x4B\xBA"
+                         "\xF4\x52\x0A\xE6\xAE\x47\xB4\x7D"
+                         "\x1D\xA8\xBE\x81\x1A\x75\xDA\xAC"
+                         "\xA6\x25\x1E\xEF\x3A\xC0\x6C\x63"
+                         "\xEF\xDC\xC9\x79\x10\x26\xE8\x61"
+                         "\x29\xFC\xA4\x05\xDF\x7D\x5C\x63"
+                         "\x10\x09\x9B\x46\x9B\xF2\x2C\x2B"
+                         "\xFA\x3A\x05\x4C\xFA\xD1\xFF\xFE"
+                         "\xF1\x4C\xE5\xB2\x91\x64\x0C\x51",
+               .rlen   = 496,
+               .also_non_np = 1,
+               .np     = 2,
+               .tap    = { 496 - 16, 16 },
+       }, { /* Generated with Crypto++ */
+               .key    = "\xC9\x83\xA6\xC9\xEC\x0F\x32\x55"
+                         "\x0F\x32\x55\x78\x9B\xBE\x78\x9B"
+                         "\xBE\xE1\x04\x27\xE1\x04\x27\x4A"
+                         "\x6D\x90\x4A\x6D\x90\xB3\xD6\xF9",
+               .klen   = 32,
+               .iv     = "\xE7\x82\x1D\xB8\x53\x11\xAC\x47"
+                         "\xE2\x7D\x18\xD6\x71\x0C\xA7\x42",
+               .input  = "\x50\xB9\x22\xAE\x17\x80\x0C\x75"
+                         "\xDE\x47\xD3\x3C\xA5\x0E\x9A\x03"
+                         "\x6C\xF8\x61\xCA\x33\xBF\x28\x91"
+                         "\x1D\x86\xEF\x58\xE4\x4D\xB6\x1F"
+                         "\xAB\x14\x7D\x09\x72\xDB\x44\xD0"
+                         "\x39\xA2\x0B\x97\x00\x69\xF5\x5E"
+                         "\xC7\x30\xBC\x25\x8E\x1A\x83\xEC"
+                         "\x55\xE1\x4A\xB3\x1C\xA8\x11\x7A"
+                         "\x06\x6F\xD8\x41\xCD\x36\x9F\x08"
+                         "\x94\xFD\x66\xF2\x5B\xC4\x2D\xB9"
+                         "\x22\x8B\x17\x80\xE9\x52\xDE\x47"
+                         "\xB0\x19\xA5\x0E\x77\x03\x6C\xD5"
+                         "\x3E\xCA\x33\x9C\x05\x91\xFA\x63"
+                         "\xEF\x58\xC1\x2A\xB6\x1F\x88\x14"
+                         "\x7D\xE6\x4F\xDB\x44\xAD\x16\xA2"
+                         "\x0B\x74\x00\x69\xD2\x3B\xC7\x30"
+                         "\x99\x02\x8E\xF7\x60\xEC\x55\xBE"
+                         "\x27\xB3\x1C\x85\x11\x7A\xE3\x4C"
+                         "\xD8\x41\xAA\x13\x9F\x08\x71\xFD"
+                         "\x66\xCF\x38\xC4\x2D\x96\x22\x8B"
+                         "\xF4\x5D\xE9\x52\xBB\x24\xB0\x19"
+                         "\x82\x0E\x77\xE0\x49\xD5\x3E\xA7"
+                         "\x10\x9C\x05\x6E\xFA\x63\xCC\x35"
+                         "\xC1\x2A\x93\x1F\x88\xF1\x5A\xE6"
+                         "\x4F\xB8\x21\xAD\x16\x7F\x0B\x74"
+                         "\xDD\x46\xD2\x3B\xA4\x0D\x99\x02"
+                         "\x6B\xF7\x60\xC9\x32\xBE\x27\x90"
+                         "\x1C\x85\xEE\x57\xE3\x4C\xB5\x1E"
+                         "\xAA\x13\x7C\x08\x71\xDA\x43\xCF"
+                         "\x38\xA1\x0A\x96\xFF\x68\xF4\x5D"
+                         "\xC6\x2F\xBB\x24\x8D\x19\x82\xEB"
+                         "\x54\xE0\x49\xB2\x1B\xA7\x10\x79"
+                         "\x05\x6E\xD7\x40\xCC\x35\x9E\x07"
+                         "\x93\xFC\x65\xF1\x5A\xC3\x2C\xB8"
+                         "\x21\x8A\x16\x7F\xE8\x51\xDD\x46"
+                         "\xAF\x18\xA4\x0D\x76\x02\x6B\xD4"
+                         "\x3D\xC9\x32\x9B\x04\x90\xF9\x62"
+                         "\xEE\x57\xC0\x29\xB5\x1E\x87\x13"
+                         "\x7C\xE5\x4E\xDA\x43\xAC\x15\xA1"
+                         "\x0A\x73\xFF\x68\xD1\x3A\xC6\x2F"
+                         "\x98\x01\x8D\xF6\x5F\xEB\x54\xBD"
+                         "\x26\xB2\x1B\x84\x10\x79\xE2\x4B"
+                         "\xD7\x40\xA9\x12\x9E\x07\x70\xFC"
+                         "\x65\xCE\x37\xC3\x2C\x95\x21\x8A"
+                         "\xF3\x5C\xE8\x51\xBA\x23\xAF\x18"
+                         "\x81\x0D\x76\xDF\x48\xD4\x3D\xA6"
+                         "\x0F\x9B\x04\x6D\xF9\x62\xCB\x34"
+                         "\xC0\x29\x92\x1E\x87\xF0\x59\xE5"
+                         "\x4E\xB7\x20\xAC\x15\x7E\x0A\x73"
+                         "\xDC\x45\xD1\x3A\xA3\x0C\x98\x01"
+                         "\x6A\xF6\x5F\xC8\x31\xBD\x26\x8F"
+                         "\x1B\x84\xED\x56\xE2\x4B\xB4\x1D"
+                         "\xA9\x12\x7B\x07\x70\xD9\x42\xCE"
+                         "\x37\xA0\x09\x95\xFE\x67\xF3\x5C"
+                         "\xC5\x2E\xBA\x23\x8C\x18\x81\xEA"
+                         "\x53\xDF\x48\xB1\x1A\xA6\x0F\x78"
+                         "\x04\x6D\xD6\x3F\xCB\x34\x9D\x06"
+                         "\x92\xFB\x64\xF0\x59\xC2\x2B\xB7"
+                         "\x20\x89\x15\x7E\xE7\x50\xDC\x45"
+                         "\xAE\x17\xA3\x0C\x75\x01\x6A\xD3"
+                         "\x3C\xC8\x31\x9A\x03\x8F\xF8\x61"
+                         "\xED\x56\xBF\x28\xB4\x1D\x86\x12"
+                         "\x7B\xE4\x4D",
+               .ilen   = 499,
+               .result = "\xDA\x4E\x3F\xBC\xE8\xB6\x3A\xA2"
+                         "\xD5\x4D\x84\x4A\xA9\x0C\xE1\xA5"
+                         "\xB8\x73\xBC\xF9\xBB\x59\x2F\x44"
+                         "\x8B\xAB\x82\x6C\xB4\x32\x9A\xDE"
+                         "\x5A\x0B\xDB\x7A\x6B\xF2\x38\x9F"
+                         "\x06\xF7\xF7\xFF\xFF\xC0\x8A\x2E"
+                         "\x76\xEA\x06\x32\x23\xF3\x59\x2E"
+                         "\x75\xDE\x71\x86\x3C\x98\x23\x44"
+                         "\x5B\xF2\xFA\x6A\x00\xBB\xC1\xAD"
+                         "\x58\xBD\x3E\x6F\x2E\xB4\x19\x04"
+                         "\x70\x8B\x92\x55\x23\xE9\x6A\x3A"
+                         "\x78\x7A\x1B\x10\x85\x52\x9C\x12"
+                         "\xE4\x55\x81\x21\xCE\x53\xD0\x3B"
+                         "\x63\x77\x2C\x74\xD1\xF5\x60\xF3"
+                         "\xA1\xDE\x44\x3C\x8F\x4D\x2F\xDD"
+                         "\x8A\xFE\x3C\x42\x8E\xD3\xF2\x8E"
+                         "\xA8\x28\x69\x65\x31\xE1\x45\x83"
+                         "\xE4\x49\xC4\x9C\xA7\x28\xAA\x21"
+                         "\xCD\x5D\x0F\x15\xB7\x93\x07\x26"
+                         "\xB0\x65\x6D\x91\x90\x23\x7A\xC6"
+                         "\xDB\x68\xB0\xA1\x8E\xA4\x76\x4E"
+                         "\xC6\x91\x83\x20\x92\x4D\x63\x7A"
+                         "\x45\x18\x18\x74\x19\xAD\x71\x01"
+                         "\x6B\x23\xAD\x9D\x4E\xE4\x6E\x46"
+                         "\xC9\x73\x7A\xF9\x02\x95\xF4\x07"
+                         "\x0E\x7A\xA6\xC5\xAE\xFA\x15\x2C"
+                         "\x51\x71\xF1\xDC\x22\xB6\xAC\xD8"
+                         "\x19\x24\x44\xBC\x0C\xFB\x3C\x2D"
+                         "\xB1\x50\x47\x15\x0E\xDB\xB6\xD7"
+                         "\xE8\x61\xE5\x95\x52\x1E\x3E\x49"
+                         "\x70\xE9\x66\x04\x4C\xE1\xAF\xBD"
+                         "\xDD\x15\x3B\x20\x59\x24\xFF\xB0"
+                         "\x39\xAA\xE7\xBF\x23\xA3\x6E\xD5"
+                         "\x15\xF0\x61\x4F\xAE\x89\x10\x58"
+                         "\x5A\x33\x95\x52\x2A\xB5\x77\x9C"
+                         "\xA5\x43\x80\x40\x27\x2D\xAE\xD9"
+                         "\x3F\xE0\x80\x94\x78\x79\xCB\x7E"
+                         "\xAD\x12\x44\x4C\xEC\x27\xB0\xEE"
+                         "\x0B\x05\x2A\x82\x99\x58\xBB\x7A"
+                         "\x8D\x6D\x9D\x8E\xE2\x8E\xE7\x93"
+                         "\x2F\xB3\x09\x8D\x06\xD5\xEE\x70"
+                         "\x16\xAE\x35\xC5\x52\x0F\x46\x1F"
+                         "\x71\xF9\x5E\xF2\x67\xDC\x98\x2F"
+                         "\xA3\x23\xAA\xD5\xD0\x49\xF4\xA6"
+                         "\xF6\xB8\x32\xCD\xD6\x85\x73\x60"
+                         "\x59\x20\xE7\x55\x0E\x91\xE2\x0C"
+                         "\x3F\x1C\xEB\x3D\xDF\x52\x64\xF2"
+                         "\x7D\x8B\x5D\x63\x16\xB9\xB2\x5D"
+                         "\x5E\xAB\xB2\x97\xAB\x78\x44\xE7"
+                         "\xC6\x72\x20\xC5\x90\x9B\xDC\x5D"
+                         "\xB0\xEF\x44\xEF\x87\x31\x8D\xF4"
+                         "\xFB\x81\x5D\xF7\x96\x96\xD4\x50"
+                         "\x89\xA7\xF6\xB9\x67\x76\x40\x9E"
+                         "\x9D\x40\xD5\x2C\x30\xB8\x01\x8F"
+                         "\xE4\x7B\x71\x48\xA9\xA0\xA0\x1D"
+                         "\x87\x52\xA4\x91\xA9\xD7\xA9\x51"
+                         "\xD9\x59\xF7\xCC\x63\x22\xC1\x8D"
+                         "\x84\x7B\xD8\x22\x32\x5C\x6F\x1D"
+                         "\x6E\x9F\xFA\xDD\x49\x40\xDC\x37"
+                         "\x14\x8C\xE1\x80\x1B\xDD\x36\x2A"
+                         "\xD0\xE9\x54\x99\x5D\xBA\x3B\x11"
+                         "\xD8\xFE\xC9\x5B\x5C\x25\xE5\x76"
+                         "\xFB\xF2\x3F",
+               .rlen   = 499,
+               .also_non_np = 1,
+               .np     = 2,
+               .tap    = { 499 - 16, 16 },
+       },
 };
 
 static struct cipher_testvec aes_ctr_dec_tv_template[] = {
@@ -11772,7 +15925,283 @@ static struct cipher_testvec aes_ctr_dec_tv_template[] = {
                          "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17"
                          "\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
                .rlen   = 64,
-       }
+       }, { /* Generated with Crypto++ */
+               .key    = "\xC9\x83\xA6\xC9\xEC\x0F\x32\x55"
+                         "\x0F\x32\x55\x78\x9B\xBE\x78\x9B"
+                         "\xBE\xE1\x04\x27\xE1\x04\x27\x4A"
+                         "\x6D\x90\x4A\x6D\x90\xB3\xD6\xF9",
+               .klen   = 32,
+               .iv     = "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
+                         "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFD",
+               .input  = "\x04\xF3\xD3\x88\x17\xEF\xDC\xEF"
+                         "\x8B\x04\xF8\x3A\x66\x8D\x1A\x53"
+                         "\x57\x1F\x4B\x23\xE4\xA0\xAF\xF9"
+                         "\x69\x95\x35\x98\x8D\x4D\x8C\xC1"
+                         "\xF0\xB2\x7F\x80\xBB\x54\x28\xA2"
+                         "\x7A\x1B\x9F\x77\xEC\x0E\x6E\xDE"
+                         "\xF0\xEC\xB8\xE4\x20\x62\xEE\xDB"
+                         "\x5D\xF5\xDD\xE3\x54\xFC\xDD\xEB"
+                         "\x6A\xEE\x65\xA1\x21\xD6\xD7\x81"
+                         "\x47\x61\x12\x4D\xC2\x8C\xFA\x78"
+                         "\x1F\x28\x02\x01\xC3\xFC\x1F\xEC"
+                         "\x0F\x10\x4F\xB3\x12\x45\xC6\x3B"
+                         "\x7E\x08\xF9\x5A\xD0\x5D\x73\x2D"
+                         "\x58\xA4\xE5\xCB\x1C\xB4\xCE\x74"
+                         "\x32\x41\x1F\x31\x9C\x08\xA2\x5D"
+                         "\x67\xEB\x72\x1D\xF8\xE7\x70\x54"
+                         "\x34\x4B\x31\x69\x84\x66\x96\x44"
+                         "\x56\xCC\x1E\xD9\xE6\x13\x6A\xB9"
+                         "\x2D\x0A\x05\x45\x2D\x90\xCC\xDF"
+                         "\x16\x5C\x5F\x79\x34\x52\x54\xFE"
+                         "\xFE\xCD\xAD\x04\x2E\xAD\x86\x06"
+                         "\x1F\x37\xE8\x28\xBC\xD3\x8F\x5B"
+                         "\x92\x66\x87\x3B\x8A\x0A\x1A\xCC"
+                         "\x6E\xAB\x9F\x0B\xFA\x5C\xE6\xFD"
+                         "\x3C\x98\x08\x12\xEC\xAA\x9E\x11"
+                         "\xCA\xB2\x1F\xCE\x5E\x5B\xB2\x72"
+                         "\x9C\xCC\x5D\xC5\xE0\x32\xC0\x56"
+                         "\xD5\x45\x16\xD2\xAF\x13\x66\xF7"
+                         "\x8C\x67\xAC\x79\xB2\xAF\x56\x27"
+                         "\x3F\xCC\xFE\xCB\x1E\xC0\x75\xF1"
+                         "\xA7\xC9\xC3\x1D\x8E\xDD\xF9\xD4"
+                         "\x42\xC8\x21\x08\x16\xF7\x01\xD7"
+                         "\xAC\x8E\x3F\x1D\x56\xC1\x06\xE4"
+                         "\x9C\x62\xD6\xA5\x6A\x50\x44\xB3"
+                         "\x35\x1C\x82\xB9\x10\xF9\x42\xA1"
+                         "\xFC\x74\x9B\x44\x4F\x25\x02\xE3"
+                         "\x08\xF5\xD4\x32\x39\x08\x11\xE8"
+                         "\xD2\x6B\x50\x53\xD4\x08\xD1\x6B"
+                         "\x3A\x4A\x68\x7B\x7C\xCD\x46\x5E"
+                         "\x0D\x07\x19\xDB\x67\xD7\x98\x91"
+                         "\xD7\x17\x10\x9B\x7B\x8A\x9B\x33"
+                         "\xAE\xF3\x00\xA6\xD4\x15\xD9\xEA"
+                         "\x85\x99\x22\xE8\x91\x38\x70\x83"
+                         "\x93\x01\x24\x6C\xFA\x9A\xB9\x07"
+                         "\xEA\x8D\x3B\xD9\x2A\x43\x59\x16"
+                         "\x2F\x69\xEE\x84\x36\x44\x76\x98"
+                         "\xF3\x04\x2A\x7C\x74\x3D\x29\x2B"
+                         "\x0D\xAD\x8F\x44\x82\x9E\x57\x8D"
+                         "\xAC\xED\x18\x1F\x50\xA4\xF5\x98"
+                         "\x1F\xBD\x92\x91\x1B\x2D\xA6\xD6"
+                         "\xD2\xE3\x02\xAA\x92\x3B\xC6\xB3"
+                         "\x1B\x39\x72\xD5\x26\xCA\x04\xE0"
+                         "\xFC\x58\x78\xBB\xB1\x3F\xA1\x9C"
+                         "\x42\x24\x3E\x2E\x22\xBB\x4B\xBA"
+                         "\xF4\x52\x0A\xE6\xAE\x47\xB4\x7D"
+                         "\x1D\xA8\xBE\x81\x1A\x75\xDA\xAC"
+                         "\xA6\x25\x1E\xEF\x3A\xC0\x6C\x63"
+                         "\xEF\xDC\xC9\x79\x10\x26\xE8\x61"
+                         "\x29\xFC\xA4\x05\xDF\x7D\x5C\x63"
+                         "\x10\x09\x9B\x46\x9B\xF2\x2C\x2B"
+                         "\xFA\x3A\x05\x4C\xFA\xD1\xFF\xFE"
+                         "\xF1\x4C\xE5\xB2\x91\x64\x0C\x51",
+               .ilen   = 496,
+               .result = "\x50\xB9\x22\xAE\x17\x80\x0C\x75"
+                         "\xDE\x47\xD3\x3C\xA5\x0E\x9A\x03"
+                         "\x6C\xF8\x61\xCA\x33\xBF\x28\x91"
+                         "\x1D\x86\xEF\x58\xE4\x4D\xB6\x1F"
+                         "\xAB\x14\x7D\x09\x72\xDB\x44\xD0"
+                         "\x39\xA2\x0B\x97\x00\x69\xF5\x5E"
+                         "\xC7\x30\xBC\x25\x8E\x1A\x83\xEC"
+                         "\x55\xE1\x4A\xB3\x1C\xA8\x11\x7A"
+                         "\x06\x6F\xD8\x41\xCD\x36\x9F\x08"
+                         "\x94\xFD\x66\xF2\x5B\xC4\x2D\xB9"
+                         "\x22\x8B\x17\x80\xE9\x52\xDE\x47"
+                         "\xB0\x19\xA5\x0E\x77\x03\x6C\xD5"
+                         "\x3E\xCA\x33\x9C\x05\x91\xFA\x63"
+                         "\xEF\x58\xC1\x2A\xB6\x1F\x88\x14"
+                         "\x7D\xE6\x4F\xDB\x44\xAD\x16\xA2"
+                         "\x0B\x74\x00\x69\xD2\x3B\xC7\x30"
+                         "\x99\x02\x8E\xF7\x60\xEC\x55\xBE"
+                         "\x27\xB3\x1C\x85\x11\x7A\xE3\x4C"
+                         "\xD8\x41\xAA\x13\x9F\x08\x71\xFD"
+                         "\x66\xCF\x38\xC4\x2D\x96\x22\x8B"
+                         "\xF4\x5D\xE9\x52\xBB\x24\xB0\x19"
+                         "\x82\x0E\x77\xE0\x49\xD5\x3E\xA7"
+                         "\x10\x9C\x05\x6E\xFA\x63\xCC\x35"
+                         "\xC1\x2A\x93\x1F\x88\xF1\x5A\xE6"
+                         "\x4F\xB8\x21\xAD\x16\x7F\x0B\x74"
+                         "\xDD\x46\xD2\x3B\xA4\x0D\x99\x02"
+                         "\x6B\xF7\x60\xC9\x32\xBE\x27\x90"
+                         "\x1C\x85\xEE\x57\xE3\x4C\xB5\x1E"
+                         "\xAA\x13\x7C\x08\x71\xDA\x43\xCF"
+                         "\x38\xA1\x0A\x96\xFF\x68\xF4\x5D"
+                         "\xC6\x2F\xBB\x24\x8D\x19\x82\xEB"
+                         "\x54\xE0\x49\xB2\x1B\xA7\x10\x79"
+                         "\x05\x6E\xD7\x40\xCC\x35\x9E\x07"
+                         "\x93\xFC\x65\xF1\x5A\xC3\x2C\xB8"
+                         "\x21\x8A\x16\x7F\xE8\x51\xDD\x46"
+                         "\xAF\x18\xA4\x0D\x76\x02\x6B\xD4"
+                         "\x3D\xC9\x32\x9B\x04\x90\xF9\x62"
+                         "\xEE\x57\xC0\x29\xB5\x1E\x87\x13"
+                         "\x7C\xE5\x4E\xDA\x43\xAC\x15\xA1"
+                         "\x0A\x73\xFF\x68\xD1\x3A\xC6\x2F"
+                         "\x98\x01\x8D\xF6\x5F\xEB\x54\xBD"
+                         "\x26\xB2\x1B\x84\x10\x79\xE2\x4B"
+                         "\xD7\x40\xA9\x12\x9E\x07\x70\xFC"
+                         "\x65\xCE\x37\xC3\x2C\x95\x21\x8A"
+                         "\xF3\x5C\xE8\x51\xBA\x23\xAF\x18"
+                         "\x81\x0D\x76\xDF\x48\xD4\x3D\xA6"
+                         "\x0F\x9B\x04\x6D\xF9\x62\xCB\x34"
+                         "\xC0\x29\x92\x1E\x87\xF0\x59\xE5"
+                         "\x4E\xB7\x20\xAC\x15\x7E\x0A\x73"
+                         "\xDC\x45\xD1\x3A\xA3\x0C\x98\x01"
+                         "\x6A\xF6\x5F\xC8\x31\xBD\x26\x8F"
+                         "\x1B\x84\xED\x56\xE2\x4B\xB4\x1D"
+                         "\xA9\x12\x7B\x07\x70\xD9\x42\xCE"
+                         "\x37\xA0\x09\x95\xFE\x67\xF3\x5C"
+                         "\xC5\x2E\xBA\x23\x8C\x18\x81\xEA"
+                         "\x53\xDF\x48\xB1\x1A\xA6\x0F\x78"
+                         "\x04\x6D\xD6\x3F\xCB\x34\x9D\x06"
+                         "\x92\xFB\x64\xF0\x59\xC2\x2B\xB7"
+                         "\x20\x89\x15\x7E\xE7\x50\xDC\x45"
+                         "\xAE\x17\xA3\x0C\x75\x01\x6A\xD3"
+                         "\x3C\xC8\x31\x9A\x03\x8F\xF8\x61"
+                         "\xED\x56\xBF\x28\xB4\x1D\x86\x12",
+               .rlen   = 496,
+               .also_non_np = 1,
+               .np     = 2,
+               .tap    = { 496 - 16, 16 },
+       }, { /* Generated with Crypto++ */
+               .key    = "\xC9\x83\xA6\xC9\xEC\x0F\x32\x55"
+                         "\x0F\x32\x55\x78\x9B\xBE\x78\x9B"
+                         "\xBE\xE1\x04\x27\xE1\x04\x27\x4A"
+                         "\x6D\x90\x4A\x6D\x90\xB3\xD6\xF9",
+               .klen   = 32,
+               .iv     = "\xE7\x82\x1D\xB8\x53\x11\xAC\x47"
+                         "\xE2\x7D\x18\xD6\x71\x0C\xA7\x42",
+               .input  = "\xDA\x4E\x3F\xBC\xE8\xB6\x3A\xA2"
+                         "\xD5\x4D\x84\x4A\xA9\x0C\xE1\xA5"
+                         "\xB8\x73\xBC\xF9\xBB\x59\x2F\x44"
+                         "\x8B\xAB\x82\x6C\xB4\x32\x9A\xDE"
+                         "\x5A\x0B\xDB\x7A\x6B\xF2\x38\x9F"
+                         "\x06\xF7\xF7\xFF\xFF\xC0\x8A\x2E"
+                         "\x76\xEA\x06\x32\x23\xF3\x59\x2E"
+                         "\x75\xDE\x71\x86\x3C\x98\x23\x44"
+                         "\x5B\xF2\xFA\x6A\x00\xBB\xC1\xAD"
+                         "\x58\xBD\x3E\x6F\x2E\xB4\x19\x04"
+                         "\x70\x8B\x92\x55\x23\xE9\x6A\x3A"
+                         "\x78\x7A\x1B\x10\x85\x52\x9C\x12"
+                         "\xE4\x55\x81\x21\xCE\x53\xD0\x3B"
+                         "\x63\x77\x2C\x74\xD1\xF5\x60\xF3"
+                         "\xA1\xDE\x44\x3C\x8F\x4D\x2F\xDD"
+                         "\x8A\xFE\x3C\x42\x8E\xD3\xF2\x8E"
+                         "\xA8\x28\x69\x65\x31\xE1\x45\x83"
+                         "\xE4\x49\xC4\x9C\xA7\x28\xAA\x21"
+                         "\xCD\x5D\x0F\x15\xB7\x93\x07\x26"
+                         "\xB0\x65\x6D\x91\x90\x23\x7A\xC6"
+                         "\xDB\x68\xB0\xA1\x8E\xA4\x76\x4E"
+                         "\xC6\x91\x83\x20\x92\x4D\x63\x7A"
+                         "\x45\x18\x18\x74\x19\xAD\x71\x01"
+                         "\x6B\x23\xAD\x9D\x4E\xE4\x6E\x46"
+                         "\xC9\x73\x7A\xF9\x02\x95\xF4\x07"
+                         "\x0E\x7A\xA6\xC5\xAE\xFA\x15\x2C"
+                         "\x51\x71\xF1\xDC\x22\xB6\xAC\xD8"
+                         "\x19\x24\x44\xBC\x0C\xFB\x3C\x2D"
+                         "\xB1\x50\x47\x15\x0E\xDB\xB6\xD7"
+                         "\xE8\x61\xE5\x95\x52\x1E\x3E\x49"
+                         "\x70\xE9\x66\x04\x4C\xE1\xAF\xBD"
+                         "\xDD\x15\x3B\x20\x59\x24\xFF\xB0"
+                         "\x39\xAA\xE7\xBF\x23\xA3\x6E\xD5"
+                         "\x15\xF0\x61\x4F\xAE\x89\x10\x58"
+                         "\x5A\x33\x95\x52\x2A\xB5\x77\x9C"
+                         "\xA5\x43\x80\x40\x27\x2D\xAE\xD9"
+                         "\x3F\xE0\x80\x94\x78\x79\xCB\x7E"
+                         "\xAD\x12\x44\x4C\xEC\x27\xB0\xEE"
+                         "\x0B\x05\x2A\x82\x99\x58\xBB\x7A"
+                         "\x8D\x6D\x9D\x8E\xE2\x8E\xE7\x93"
+                         "\x2F\xB3\x09\x8D\x06\xD5\xEE\x70"
+                         "\x16\xAE\x35\xC5\x52\x0F\x46\x1F"
+                         "\x71\xF9\x5E\xF2\x67\xDC\x98\x2F"
+                         "\xA3\x23\xAA\xD5\xD0\x49\xF4\xA6"
+                         "\xF6\xB8\x32\xCD\xD6\x85\x73\x60"
+                         "\x59\x20\xE7\x55\x0E\x91\xE2\x0C"
+                         "\x3F\x1C\xEB\x3D\xDF\x52\x64\xF2"
+                         "\x7D\x8B\x5D\x63\x16\xB9\xB2\x5D"
+                         "\x5E\xAB\xB2\x97\xAB\x78\x44\xE7"
+                         "\xC6\x72\x20\xC5\x90\x9B\xDC\x5D"
+                         "\xB0\xEF\x44\xEF\x87\x31\x8D\xF4"
+                         "\xFB\x81\x5D\xF7\x96\x96\xD4\x50"
+                         "\x89\xA7\xF6\xB9\x67\x76\x40\x9E"
+                         "\x9D\x40\xD5\x2C\x30\xB8\x01\x8F"
+                         "\xE4\x7B\x71\x48\xA9\xA0\xA0\x1D"
+                         "\x87\x52\xA4\x91\xA9\xD7\xA9\x51"
+                         "\xD9\x59\xF7\xCC\x63\x22\xC1\x8D"
+                         "\x84\x7B\xD8\x22\x32\x5C\x6F\x1D"
+                         "\x6E\x9F\xFA\xDD\x49\x40\xDC\x37"
+                         "\x14\x8C\xE1\x80\x1B\xDD\x36\x2A"
+                         "\xD0\xE9\x54\x99\x5D\xBA\x3B\x11"
+                         "\xD8\xFE\xC9\x5B\x5C\x25\xE5\x76"
+                         "\xFB\xF2\x3F",
+               .ilen   = 499,
+               .result = "\x50\xB9\x22\xAE\x17\x80\x0C\x75"
+                         "\xDE\x47\xD3\x3C\xA5\x0E\x9A\x03"
+                         "\x6C\xF8\x61\xCA\x33\xBF\x28\x91"
+                         "\x1D\x86\xEF\x58\xE4\x4D\xB6\x1F"
+                         "\xAB\x14\x7D\x09\x72\xDB\x44\xD0"
+                         "\x39\xA2\x0B\x97\x00\x69\xF5\x5E"
+                         "\xC7\x30\xBC\x25\x8E\x1A\x83\xEC"
+                         "\x55\xE1\x4A\xB3\x1C\xA8\x11\x7A"
+                         "\x06\x6F\xD8\x41\xCD\x36\x9F\x08"
+                         "\x94\xFD\x66\xF2\x5B\xC4\x2D\xB9"
+                         "\x22\x8B\x17\x80\xE9\x52\xDE\x47"
+                         "\xB0\x19\xA5\x0E\x77\x03\x6C\xD5"
+                         "\x3E\xCA\x33\x9C\x05\x91\xFA\x63"
+                         "\xEF\x58\xC1\x2A\xB6\x1F\x88\x14"
+                         "\x7D\xE6\x4F\xDB\x44\xAD\x16\xA2"
+                         "\x0B\x74\x00\x69\xD2\x3B\xC7\x30"
+                         "\x99\x02\x8E\xF7\x60\xEC\x55\xBE"
+                         "\x27\xB3\x1C\x85\x11\x7A\xE3\x4C"
+                         "\xD8\x41\xAA\x13\x9F\x08\x71\xFD"
+                         "\x66\xCF\x38\xC4\x2D\x96\x22\x8B"
+                         "\xF4\x5D\xE9\x52\xBB\x24\xB0\x19"
+                         "\x82\x0E\x77\xE0\x49\xD5\x3E\xA7"
+                         "\x10\x9C\x05\x6E\xFA\x63\xCC\x35"
+                         "\xC1\x2A\x93\x1F\x88\xF1\x5A\xE6"
+                         "\x4F\xB8\x21\xAD\x16\x7F\x0B\x74"
+                         "\xDD\x46\xD2\x3B\xA4\x0D\x99\x02"
+                         "\x6B\xF7\x60\xC9\x32\xBE\x27\x90"
+                         "\x1C\x85\xEE\x57\xE3\x4C\xB5\x1E"
+                         "\xAA\x13\x7C\x08\x71\xDA\x43\xCF"
+                         "\x38\xA1\x0A\x96\xFF\x68\xF4\x5D"
+                         "\xC6\x2F\xBB\x24\x8D\x19\x82\xEB"
+                         "\x54\xE0\x49\xB2\x1B\xA7\x10\x79"
+                         "\x05\x6E\xD7\x40\xCC\x35\x9E\x07"
+                         "\x93\xFC\x65\xF1\x5A\xC3\x2C\xB8"
+                         "\x21\x8A\x16\x7F\xE8\x51\xDD\x46"
+                         "\xAF\x18\xA4\x0D\x76\x02\x6B\xD4"
+                         "\x3D\xC9\x32\x9B\x04\x90\xF9\x62"
+                         "\xEE\x57\xC0\x29\xB5\x1E\x87\x13"
+                         "\x7C\xE5\x4E\xDA\x43\xAC\x15\xA1"
+                         "\x0A\x73\xFF\x68\xD1\x3A\xC6\x2F"
+                         "\x98\x01\x8D\xF6\x5F\xEB\x54\xBD"
+                         "\x26\xB2\x1B\x84\x10\x79\xE2\x4B"
+                         "\xD7\x40\xA9\x12\x9E\x07\x70\xFC"
+                         "\x65\xCE\x37\xC3\x2C\x95\x21\x8A"
+                         "\xF3\x5C\xE8\x51\xBA\x23\xAF\x18"
+                         "\x81\x0D\x76\xDF\x48\xD4\x3D\xA6"
+                         "\x0F\x9B\x04\x6D\xF9\x62\xCB\x34"
+                         "\xC0\x29\x92\x1E\x87\xF0\x59\xE5"
+                         "\x4E\xB7\x20\xAC\x15\x7E\x0A\x73"
+                         "\xDC\x45\xD1\x3A\xA3\x0C\x98\x01"
+                         "\x6A\xF6\x5F\xC8\x31\xBD\x26\x8F"
+                         "\x1B\x84\xED\x56\xE2\x4B\xB4\x1D"
+                         "\xA9\x12\x7B\x07\x70\xD9\x42\xCE"
+                         "\x37\xA0\x09\x95\xFE\x67\xF3\x5C"
+                         "\xC5\x2E\xBA\x23\x8C\x18\x81\xEA"
+                         "\x53\xDF\x48\xB1\x1A\xA6\x0F\x78"
+                         "\x04\x6D\xD6\x3F\xCB\x34\x9D\x06"
+                         "\x92\xFB\x64\xF0\x59\xC2\x2B\xB7"
+                         "\x20\x89\x15\x7E\xE7\x50\xDC\x45"
+                         "\xAE\x17\xA3\x0C\x75\x01\x6A\xD3"
+                         "\x3C\xC8\x31\x9A\x03\x8F\xF8\x61"
+                         "\xED\x56\xBF\x28\xB4\x1D\x86\x12"
+                         "\x7B\xE4\x4D",
+               .rlen   = 499,
+               .also_non_np = 1,
+               .np     = 2,
+               .tap    = { 499 - 16, 16 },
+       },
 };
 
 static struct cipher_testvec aes_ctr_rfc3686_enc_tv_template[] = {
@@ -16291,8 +20720,7 @@ static struct cipher_testvec camellia_enc_tv_template[] = {
                .result = "\x9a\xcc\x23\x7d\xff\x16\xd7\x6c"
                          "\x20\xef\x7c\x91\x9e\x3a\x75\x09",
                .rlen   = 16,
-       },
-       { /* Generated with Crypto++ */
+       }, { /* Generated with Crypto++ */
                .key    = "\x3F\x85\x62\x3F\x1C\xF9\xD6\x1C"
                          "\xF9\xD6\xB3\x90\x6D\x4A\x90\x6D"
                          "\x4A\x27\x04\xE1\x27\x04\xE1\xBE"
@@ -16303,18 +20731,130 @@ static struct cipher_testvec camellia_enc_tv_template[] = {
                          "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
                          "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
                          "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
-                         "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48",
-               .ilen   = 48,
+                         "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+                         "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+                         "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+                         "\xC3\x37\xCE\x65\xFC\x70\x07\x9E"
+                         "\x12\xA9\x40\xD7\x4B\xE2\x79\x10"
+                         "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F"
+                         "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1"
+                         "\x68\xFF\x73\x0A\xA1\x15\xAC\x43"
+                         "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5"
+                         "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
+                         "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
+                         "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
+                         "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+                         "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+                         "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+                         "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+                         "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+                         "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+                         "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+                         "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+                         "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+                         "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+                         "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+                         "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+                         "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+                         "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+                         "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+                         "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+                         "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+                         "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+                         "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+                         "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+                         "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+                         "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+                         "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+                         "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+                         "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+                         "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+                         "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+                         "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+                         "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+                         "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+                         "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+                         "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+                         "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+                         "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+                         "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+                         "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+                         "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+                         "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+                         "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+                         "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+                         "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+                         "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+                         "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+                         "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+                         "\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
+               .ilen   = 496,
                .result = "\xED\xCD\xDB\xB8\x68\xCE\xBD\xEA"
                          "\x9D\x9D\xCD\x9F\x4F\xFC\x4D\xB7"
                          "\xA5\xFF\x6F\x43\x0F\xBA\x32\x04"
                          "\xB3\xC2\xB9\x03\xAA\x91\x56\x29"
                          "\x0D\xD0\xFD\xC4\x65\xA5\x69\xB9"
-                         "\xF1\xF6\xB1\xA5\xB2\x75\x4F\x8A",
-               .rlen   = 48,
+                         "\xF1\xF6\xB1\xA5\xB2\x75\x4F\x8A"
+                         "\x8D\x7D\x1B\x9B\xC7\x68\x72\xF8"
+                         "\x01\x9B\x17\x0A\x29\xE7\x61\x28"
+                         "\x7F\xA7\x50\xCA\x20\x2C\x96\x3B"
+                         "\x6E\x5C\x5D\x3F\xB5\x7F\xF3\x2B"
+                         "\x04\xEF\x9D\xD4\xCE\x41\x28\x8E"
+                         "\x83\x54\xAE\x7C\x82\x46\x10\xC9"
+                         "\xC4\x8A\x1E\x1F\x4C\xA9\xFC\xEC"
+                         "\x3C\x8C\x30\xFC\x59\xD2\x54\xC4"
+                         "\x6F\x50\xC6\xCA\x8C\x14\x5B\x9C"
+                         "\x18\x56\x5B\xF8\x33\x0E\x4A\xDB"
+                         "\xEC\xB5\x6E\x5B\x31\xC4\x0E\x98"
+                         "\x9F\x32\xBA\xA2\x18\xCF\x55\x43"
+                         "\xFE\x80\x8F\x60\xCF\x05\x30\x9B"
+                         "\x70\x50\x1E\x9C\x08\x87\xE6\x20"
+                         "\xD2\xF3\x27\xF8\x2A\x8D\x12\xB2"
+                         "\xBC\x5F\xFE\x52\x52\xF6\x7F\xB6"
+                         "\xB8\x30\x86\x3B\x0F\x94\x1E\x79"
+                         "\x13\x94\x35\xA2\xB1\x35\x5B\x05"
+                         "\x2A\x98\x6B\x96\x4C\xB1\x20\xBE"
+                         "\xB6\x14\xC2\x06\xBF\xFD\x5F\x2A"
+                         "\xF5\x33\xC8\x19\x45\x14\x44\x5D"
+                         "\xFE\x94\x7B\xBB\x63\x13\x57\xC3"
+                         "\x2A\x8F\x6C\x11\x2A\x07\xA7\x6A"
+                         "\xBF\x20\xD3\x99\xC6\x00\x0B\xBF"
+                         "\x83\x46\x25\x3A\xB0\xF6\xC5\xC8"
+                         "\x00\xCA\xE5\x28\x4A\x7C\x95\x9C"
+                         "\x7B\x43\xAB\xF9\xE4\xF8\x74\xAB"
+                         "\xA7\xB8\x9C\x0F\x53\x7B\xB6\x74"
+                         "\x60\x64\x0D\x1C\x80\xD1\x20\x9E"
+                         "\xDC\x14\x27\x9B\xFC\xBD\x5C\x96"
+                         "\xD2\x51\xDC\x96\xEE\xE5\xEA\x2B"
+                         "\x02\x7C\xAA\x3C\xDC\x9D\x7B\x01"
+                         "\x20\xC3\xE1\x0B\xDD\xAB\xF3\x1E"
+                         "\x19\xA8\x84\x29\x5F\xCC\xC3\x5B"
+                         "\xE4\x33\x59\xDC\x12\xEB\x2B\x4D"
+                         "\x5B\x55\x23\xB7\x40\x31\xDE\xEE"
+                         "\x18\xC9\x3C\x4D\xBC\xED\xE0\x42"
+                         "\xAD\xDE\xA0\xA3\xC3\xFE\x44\xD3"
+                         "\xE1\x9A\xDA\xAB\x32\xFC\x1A\xBF"
+                         "\x63\xA9\xF0\x6A\x08\x46\xBD\x48"
+                         "\x83\x06\xAB\x82\x99\x01\x16\x1A"
+                         "\x03\x36\xC5\x59\x6B\xB8\x8C\x9F"
+                         "\xC6\x51\x3D\xE5\x7F\xBF\xAB\xBC"
+                         "\xC9\xA1\x88\x34\x5F\xA9\x7C\x3B"
+                         "\x9F\x1B\x98\x2B\x4F\xFB\x9B\xF0"
+                         "\xCD\xB6\x45\xB2\x29\x2E\x34\x23"
+                         "\xA9\x97\xC0\x22\x8C\x42\x9B\x5F"
+                         "\x40\xC8\xD7\x3D\x82\x9A\x6F\xAA"
+                         "\x74\x83\x29\x05\xE8\xC4\x4D\x01"
+                         "\xB5\xE5\x84\x3F\x7F\xD3\xE0\x99"
+                         "\xDA\xE7\x6F\x30\xFD\xAA\x92\x30"
+                         "\xA5\x46\x8B\xA2\xE6\x58\x62\x7C"
+                         "\x2C\x35\x1B\x38\x85\x7D\xE8\xF3"
+                         "\x87\x4F\xDA\xD8\x5F\xFC\xB6\x44"
+                         "\xD0\xE3\x9B\x8B\xBF\xD6\xB8\xC4"
+                         "\x73\xAE\x1D\x8B\x5B\x74\x8B\xCB",
+               .rlen   = 496,
                .also_non_np = 1,
                .np     = 2,
-               .tap    = { 48 - 16, 16 },
+               .tap    = { 496 - 16, 16 },
        },
 };
 
@@ -16352,8 +20892,7 @@ static struct cipher_testvec camellia_dec_tv_template[] = {
                .result = "\x01\x23\x45\x67\x89\xab\xcd\xef"
                          "\xfe\xdc\xba\x98\x76\x54\x32\x10",
                .rlen   = 16,
-       },
-       { /* Generated with Crypto++ */
+       }, { /* Generated with Crypto++ */
                .key    = "\x3F\x85\x62\x3F\x1C\xF9\xD6\x1C"
                          "\xF9\xD6\xB3\x90\x6D\x4A\x90\x6D"
                          "\x4A\x27\x04\xE1\x27\x04\xE1\xBE"
@@ -16364,18 +20903,130 @@ static struct cipher_testvec camellia_dec_tv_template[] = {
                          "\xA5\xFF\x6F\x43\x0F\xBA\x32\x04"
                          "\xB3\xC2\xB9\x03\xAA\x91\x56\x29"
                          "\x0D\xD0\xFD\xC4\x65\xA5\x69\xB9"
-                         "\xF1\xF6\xB1\xA5\xB2\x75\x4F\x8A",
-               .ilen   = 48,
+                         "\xF1\xF6\xB1\xA5\xB2\x75\x4F\x8A"
+                         "\x8D\x7D\x1B\x9B\xC7\x68\x72\xF8"
+                         "\x01\x9B\x17\x0A\x29\xE7\x61\x28"
+                         "\x7F\xA7\x50\xCA\x20\x2C\x96\x3B"
+                         "\x6E\x5C\x5D\x3F\xB5\x7F\xF3\x2B"
+                         "\x04\xEF\x9D\xD4\xCE\x41\x28\x8E"
+                         "\x83\x54\xAE\x7C\x82\x46\x10\xC9"
+                         "\xC4\x8A\x1E\x1F\x4C\xA9\xFC\xEC"
+                         "\x3C\x8C\x30\xFC\x59\xD2\x54\xC4"
+                         "\x6F\x50\xC6\xCA\x8C\x14\x5B\x9C"
+                         "\x18\x56\x5B\xF8\x33\x0E\x4A\xDB"
+                         "\xEC\xB5\x6E\x5B\x31\xC4\x0E\x98"
+                         "\x9F\x32\xBA\xA2\x18\xCF\x55\x43"
+                         "\xFE\x80\x8F\x60\xCF\x05\x30\x9B"
+                         "\x70\x50\x1E\x9C\x08\x87\xE6\x20"
+                         "\xD2\xF3\x27\xF8\x2A\x8D\x12\xB2"
+                         "\xBC\x5F\xFE\x52\x52\xF6\x7F\xB6"
+                         "\xB8\x30\x86\x3B\x0F\x94\x1E\x79"
+                         "\x13\x94\x35\xA2\xB1\x35\x5B\x05"
+                         "\x2A\x98\x6B\x96\x4C\xB1\x20\xBE"
+                         "\xB6\x14\xC2\x06\xBF\xFD\x5F\x2A"
+                         "\xF5\x33\xC8\x19\x45\x14\x44\x5D"
+                         "\xFE\x94\x7B\xBB\x63\x13\x57\xC3"
+                         "\x2A\x8F\x6C\x11\x2A\x07\xA7\x6A"
+                         "\xBF\x20\xD3\x99\xC6\x00\x0B\xBF"
+                         "\x83\x46\x25\x3A\xB0\xF6\xC5\xC8"
+                         "\x00\xCA\xE5\x28\x4A\x7C\x95\x9C"
+                         "\x7B\x43\xAB\xF9\xE4\xF8\x74\xAB"
+                         "\xA7\xB8\x9C\x0F\x53\x7B\xB6\x74"
+                         "\x60\x64\x0D\x1C\x80\xD1\x20\x9E"
+                         "\xDC\x14\x27\x9B\xFC\xBD\x5C\x96"
+                         "\xD2\x51\xDC\x96\xEE\xE5\xEA\x2B"
+                         "\x02\x7C\xAA\x3C\xDC\x9D\x7B\x01"
+                         "\x20\xC3\xE1\x0B\xDD\xAB\xF3\x1E"
+                         "\x19\xA8\x84\x29\x5F\xCC\xC3\x5B"
+                         "\xE4\x33\x59\xDC\x12\xEB\x2B\x4D"
+                         "\x5B\x55\x23\xB7\x40\x31\xDE\xEE"
+                         "\x18\xC9\x3C\x4D\xBC\xED\xE0\x42"
+                         "\xAD\xDE\xA0\xA3\xC3\xFE\x44\xD3"
+                         "\xE1\x9A\xDA\xAB\x32\xFC\x1A\xBF"
+                         "\x63\xA9\xF0\x6A\x08\x46\xBD\x48"
+                         "\x83\x06\xAB\x82\x99\x01\x16\x1A"
+                         "\x03\x36\xC5\x59\x6B\xB8\x8C\x9F"
+                         "\xC6\x51\x3D\xE5\x7F\xBF\xAB\xBC"
+                         "\xC9\xA1\x88\x34\x5F\xA9\x7C\x3B"
+                         "\x9F\x1B\x98\x2B\x4F\xFB\x9B\xF0"
+                         "\xCD\xB6\x45\xB2\x29\x2E\x34\x23"
+                         "\xA9\x97\xC0\x22\x8C\x42\x9B\x5F"
+                         "\x40\xC8\xD7\x3D\x82\x9A\x6F\xAA"
+                         "\x74\x83\x29\x05\xE8\xC4\x4D\x01"
+                         "\xB5\xE5\x84\x3F\x7F\xD3\xE0\x99"
+                         "\xDA\xE7\x6F\x30\xFD\xAA\x92\x30"
+                         "\xA5\x46\x8B\xA2\xE6\x58\x62\x7C"
+                         "\x2C\x35\x1B\x38\x85\x7D\xE8\xF3"
+                         "\x87\x4F\xDA\xD8\x5F\xFC\xB6\x44"
+                         "\xD0\xE3\x9B\x8B\xBF\xD6\xB8\xC4"
+                         "\x73\xAE\x1D\x8B\x5B\x74\x8B\xCB",
+               .ilen   = 496,
                .result = "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
                          "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
                          "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
                          "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
                          "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
-                         "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48",
-               .rlen   = 48,
+                         "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+                         "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+                         "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+                         "\xC3\x37\xCE\x65\xFC\x70\x07\x9E"
+                         "\x12\xA9\x40\xD7\x4B\xE2\x79\x10"
+                         "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F"
+                         "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1"
+                         "\x68\xFF\x73\x0A\xA1\x15\xAC\x43"
+                         "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5"
+                         "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
+                         "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
+                         "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
+                         "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+                         "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+                         "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+                         "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+                         "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+                         "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+                         "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+                         "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+                         "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+                         "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+                         "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+                         "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+                         "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+                         "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+                         "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+                         "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+                         "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+                         "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+                         "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+                         "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+                         "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+                         "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+                         "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+                         "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+                         "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+                         "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+                         "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+                         "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+                         "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+                         "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+                         "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+                         "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+                         "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+                         "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+                         "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+                         "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+                         "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+                         "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+                         "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+                         "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+                         "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+                         "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+                         "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+                         "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+                         "\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
+               .rlen   = 496,
                .also_non_np = 1,
                .np     = 2,
-               .tap    = { 48 - 16, 16 },
+               .tap    = { 496 - 16, 16 },
        },
 };
 
@@ -16407,8 +21058,7 @@ static struct cipher_testvec camellia_cbc_enc_tv_template[] = {
                          "\x19\xb4\x3e\x57\x1c\x02\x5e\xa0"
                          "\x15\x78\xe0\x5e\xf2\xcb\x87\x16",
                .rlen   = 32,
-       },
-       { /* Generated with Crypto++ */
+       }, { /* Generated with Crypto++ */
                .key    = "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
                          "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
                          "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
@@ -16421,18 +21071,130 @@ static struct cipher_testvec camellia_cbc_enc_tv_template[] = {
                          "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
                          "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
                          "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
-                         "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48",
-               .ilen   = 48,
+                         "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+                         "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+                         "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+                         "\xC3\x37\xCE\x65\xFC\x70\x07\x9E"
+                         "\x12\xA9\x40\xD7\x4B\xE2\x79\x10"
+                         "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F"
+                         "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1"
+                         "\x68\xFF\x73\x0A\xA1\x15\xAC\x43"
+                         "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5"
+                         "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
+                         "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
+                         "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
+                         "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+                         "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+                         "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+                         "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+                         "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+                         "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+                         "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+                         "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+                         "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+                         "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+                         "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+                         "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+                         "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+                         "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+                         "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+                         "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+                         "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+                         "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+                         "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+                         "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+                         "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+                         "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+                         "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+                         "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+                         "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+                         "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+                         "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+                         "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+                         "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+                         "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+                         "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+                         "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+                         "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+                         "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+                         "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+                         "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+                         "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+                         "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+                         "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+                         "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+                         "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+                         "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+                         "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+                         "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+                         "\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
+               .ilen   = 496,
                .result = "\xCD\x3E\x2A\x3B\x3E\x94\xC5\x77"
                          "\xBA\xBB\x5B\xB1\xDE\x7B\xA4\x40"
                          "\x88\x39\xE3\xFD\x94\x4B\x25\x58"
                          "\xE1\x4B\xC4\x18\x7A\xFD\x17\x2B"
                          "\xB9\xF9\xC2\x27\x6A\xB6\x31\x27"
-                         "\xA6\xAD\xEF\xE5\x5D\xE4\x02\x01",
-               .rlen   = 48,
+                         "\xA6\xAD\xEF\xE5\x5D\xE4\x02\x01"
+                         "\x56\x2E\x10\xC2\x2C\xFF\xC6\x83"
+                         "\xB5\xDC\x4F\x63\xAD\x0E\x63\x5E"
+                         "\x56\xC8\x18\x3D\x79\x86\x97\xEF"
+                         "\x57\x0E\x63\xA1\xC1\x41\x48\xB8"
+                         "\x98\xB7\x51\x6D\x18\xF6\x19\x82"
+                         "\x37\x49\x88\xA4\xEF\x91\x21\x47"
+                         "\x03\x28\xEA\x42\xF4\xFB\x7A\x58"
+                         "\x28\x90\x77\x46\xD8\xD2\x35\x16"
+                         "\x44\xA9\x9E\x49\x52\x2A\xE4\x16"
+                         "\x5D\xF7\x65\xEB\x0F\xC9\x29\xE6"
+                         "\xCF\x76\x91\x89\x8A\x94\x39\xFA"
+                         "\x6B\x5F\x63\x53\x74\x43\x91\xF5"
+                         "\x3F\xBC\x88\x53\xB2\x1A\x02\x3F"
+                         "\x9D\x32\x84\xEB\x56\x28\xD6\x06"
+                         "\xD5\xB2\x20\xA9\xFC\xC3\x76\x62"
+                         "\x32\xCC\x86\xC8\x36\x67\x5E\x7E"
+                         "\xA4\xAA\x15\x63\x6B\xA9\x86\xAF"
+                         "\x1A\x52\x82\x36\x5F\xF4\x3F\x7A"
+                         "\x9B\x78\x62\x3B\x02\x28\x60\xB3"
+                         "\xBA\x82\xB1\xDD\xC9\x60\x8F\x47"
+                         "\xF1\x6B\xFE\xE5\x39\x34\xA0\x28"
+                         "\xA4\xB3\xC9\x7E\xED\x28\x8D\x70"
+                         "\xB2\x1D\xFD\xC6\x00\xCF\x1A\x94"
+                         "\x28\xF8\xC1\x34\xB7\x58\xA5\x6C"
+                         "\x1A\x9D\xE4\xE4\xF6\xB9\xB4\xB0"
+                         "\x5D\x51\x54\x9A\x53\xA0\xF9\x32"
+                         "\xBD\x31\x54\x14\x7B\x33\xEE\x17"
+                         "\xD3\xC7\x1F\x48\xBF\x0B\x22\xA2"
+                         "\x7D\x0C\xDF\xD0\x2E\x98\xFA\xD2"
+                         "\xFA\xCF\x24\x1D\x99\x9B\xD0\x7E"
+                         "\xF4\x4F\x88\xFF\x45\x99\x4A\xF4"
+                         "\xF2\x0A\x5B\x3B\x21\xAB\x92\xAE"
+                         "\x40\x78\x91\x95\xC4\x2F\xA3\xE8"
+                         "\x18\xC7\x07\xA6\xC8\xC0\x66\x33"
+                         "\x35\xC0\xB4\xA0\xF8\xEE\x1E\xF3"
+                         "\x40\xF5\x40\x54\xF1\x84\x8C\xEA"
+                         "\x27\x38\x1F\xF8\x77\xC7\xDF\xD8"
+                         "\x1D\xE2\xD9\x59\x40\x4F\x59\xD4"
+                         "\xF8\x17\x99\x8D\x58\x2D\x72\x44"
+                         "\x9D\x1D\x91\x64\xD6\x3F\x0A\x82"
+                         "\xC7\x57\x3D\xEF\xD3\x41\xFA\xA7"
+                         "\x68\xA3\xB8\xA5\x93\x74\x2E\x85"
+                         "\x4C\x9D\x69\x59\xCE\x15\xAE\xBF"
+                         "\x9C\x8F\x14\x64\x5D\x7F\xCF\x0B"
+                         "\xCE\x43\x5D\x28\xC0\x2F\xFB\x18"
+                         "\x79\x9A\xFC\x43\x16\x7C\x6B\x7B"
+                         "\x38\xB8\x48\x36\x66\x4E\x20\x43"
+                         "\xBA\x76\x13\x9A\xC3\xF2\xEB\x52"
+                         "\xD7\xDC\xB2\x67\x63\x14\x25\xCD"
+                         "\xB1\x13\x4B\xDE\x8C\x59\x21\x84"
+                         "\x81\x8D\x97\x23\x45\x33\x7C\xF3"
+                         "\xC5\xBC\x79\x95\xAA\x84\x68\x31"
+                         "\x2D\x1A\x68\xFE\xEC\x92\x94\xDA"
+                         "\x94\x2A\x6F\xD6\xFE\xE5\x76\x97"
+                         "\xF4\x6E\xEE\xCB\x2B\x95\x4E\x36"
+                         "\x5F\x74\x8C\x86\x5B\x71\xD0\x20",
+               .rlen   = 496,
                .also_non_np = 1,
                .np     = 2,
-               .tap    = { 48 - 16, 16 },
+               .tap    = { 496 - 16, 16 },
        },
 };
 
@@ -16464,8 +21226,7 @@ static struct cipher_testvec camellia_cbc_dec_tv_template[] = {
                          "\x10\x11\x12\x13\x14\x15\x16\x17"
                          "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
                .rlen   = 32,
-       },
-       { /* Generated with Crypto++ */
+       }, { /* Generated with Crypto++ */
                .key    = "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
                          "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
                          "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
@@ -16478,18 +21239,130 @@ static struct cipher_testvec camellia_cbc_dec_tv_template[] = {
                          "\x88\x39\xE3\xFD\x94\x4B\x25\x58"
                          "\xE1\x4B\xC4\x18\x7A\xFD\x17\x2B"
                          "\xB9\xF9\xC2\x27\x6A\xB6\x31\x27"
-                         "\xA6\xAD\xEF\xE5\x5D\xE4\x02\x01",
-               .ilen   = 48,
+                         "\xA6\xAD\xEF\xE5\x5D\xE4\x02\x01"
+                         "\x56\x2E\x10\xC2\x2C\xFF\xC6\x83"
+                         "\xB5\xDC\x4F\x63\xAD\x0E\x63\x5E"
+                         "\x56\xC8\x18\x3D\x79\x86\x97\xEF"
+                         "\x57\x0E\x63\xA1\xC1\x41\x48\xB8"
+                         "\x98\xB7\x51\x6D\x18\xF6\x19\x82"
+                         "\x37\x49\x88\xA4\xEF\x91\x21\x47"
+                         "\x03\x28\xEA\x42\xF4\xFB\x7A\x58"
+                         "\x28\x90\x77\x46\xD8\xD2\x35\x16"
+                         "\x44\xA9\x9E\x49\x52\x2A\xE4\x16"
+                         "\x5D\xF7\x65\xEB\x0F\xC9\x29\xE6"
+                         "\xCF\x76\x91\x89\x8A\x94\x39\xFA"
+                         "\x6B\x5F\x63\x53\x74\x43\x91\xF5"
+                         "\x3F\xBC\x88\x53\xB2\x1A\x02\x3F"
+                         "\x9D\x32\x84\xEB\x56\x28\xD6\x06"
+                         "\xD5\xB2\x20\xA9\xFC\xC3\x76\x62"
+                         "\x32\xCC\x86\xC8\x36\x67\x5E\x7E"
+                         "\xA4\xAA\x15\x63\x6B\xA9\x86\xAF"
+                         "\x1A\x52\x82\x36\x5F\xF4\x3F\x7A"
+                         "\x9B\x78\x62\x3B\x02\x28\x60\xB3"
+                         "\xBA\x82\xB1\xDD\xC9\x60\x8F\x47"
+                         "\xF1\x6B\xFE\xE5\x39\x34\xA0\x28"
+                         "\xA4\xB3\xC9\x7E\xED\x28\x8D\x70"
+                         "\xB2\x1D\xFD\xC6\x00\xCF\x1A\x94"
+                         "\x28\xF8\xC1\x34\xB7\x58\xA5\x6C"
+                         "\x1A\x9D\xE4\xE4\xF6\xB9\xB4\xB0"
+                         "\x5D\x51\x54\x9A\x53\xA0\xF9\x32"
+                         "\xBD\x31\x54\x14\x7B\x33\xEE\x17"
+                         "\xD3\xC7\x1F\x48\xBF\x0B\x22\xA2"
+                         "\x7D\x0C\xDF\xD0\x2E\x98\xFA\xD2"
+                         "\xFA\xCF\x24\x1D\x99\x9B\xD0\x7E"
+                         "\xF4\x4F\x88\xFF\x45\x99\x4A\xF4"
+                         "\xF2\x0A\x5B\x3B\x21\xAB\x92\xAE"
+                         "\x40\x78\x91\x95\xC4\x2F\xA3\xE8"
+                         "\x18\xC7\x07\xA6\xC8\xC0\x66\x33"
+                         "\x35\xC0\xB4\xA0\xF8\xEE\x1E\xF3"
+                         "\x40\xF5\x40\x54\xF1\x84\x8C\xEA"
+                         "\x27\x38\x1F\xF8\x77\xC7\xDF\xD8"
+                         "\x1D\xE2\xD9\x59\x40\x4F\x59\xD4"
+                         "\xF8\x17\x99\x8D\x58\x2D\x72\x44"
+                         "\x9D\x1D\x91\x64\xD6\x3F\x0A\x82"
+                         "\xC7\x57\x3D\xEF\xD3\x41\xFA\xA7"
+                         "\x68\xA3\xB8\xA5\x93\x74\x2E\x85"
+                         "\x4C\x9D\x69\x59\xCE\x15\xAE\xBF"
+                         "\x9C\x8F\x14\x64\x5D\x7F\xCF\x0B"
+                         "\xCE\x43\x5D\x28\xC0\x2F\xFB\x18"
+                         "\x79\x9A\xFC\x43\x16\x7C\x6B\x7B"
+                         "\x38\xB8\x48\x36\x66\x4E\x20\x43"
+                         "\xBA\x76\x13\x9A\xC3\xF2\xEB\x52"
+                         "\xD7\xDC\xB2\x67\x63\x14\x25\xCD"
+                         "\xB1\x13\x4B\xDE\x8C\x59\x21\x84"
+                         "\x81\x8D\x97\x23\x45\x33\x7C\xF3"
+                         "\xC5\xBC\x79\x95\xAA\x84\x68\x31"
+                         "\x2D\x1A\x68\xFE\xEC\x92\x94\xDA"
+                         "\x94\x2A\x6F\xD6\xFE\xE5\x76\x97"
+                         "\xF4\x6E\xEE\xCB\x2B\x95\x4E\x36"
+                         "\x5F\x74\x8C\x86\x5B\x71\xD0\x20",
+               .ilen   = 496,
                .result = "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
                          "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
                          "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
                          "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
                          "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
-                         "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48",
-               .rlen   = 48,
+                         "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+                         "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+                         "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+                         "\xC3\x37\xCE\x65\xFC\x70\x07\x9E"
+                         "\x12\xA9\x40\xD7\x4B\xE2\x79\x10"
+                         "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F"
+                         "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1"
+                         "\x68\xFF\x73\x0A\xA1\x15\xAC\x43"
+                         "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5"
+                         "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
+                         "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
+                         "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
+                         "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+                         "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+                         "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+                         "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+                         "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+                         "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+                         "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+                         "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+                         "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+                         "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+                         "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+                         "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+                         "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+                         "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+                         "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+                         "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+                         "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+                         "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+                         "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+                         "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+                         "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+                         "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+                         "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+                         "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+                         "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+                         "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+                         "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+                         "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+                         "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+                         "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+                         "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+                         "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+                         "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+                         "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+                         "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+                         "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+                         "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+                         "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+                         "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+                         "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+                         "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+                         "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+                         "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+                         "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+                         "\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
+               .rlen   = 496,
                .also_non_np = 1,
                .np     = 2,
-               .tap    = { 48 - 16, 16 },
+               .tap    = { 496 - 16, 16 },
        },
 };
 
@@ -16507,17 +21380,128 @@ static struct cipher_testvec camellia_ctr_enc_tv_template[] = {
                          "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
                          "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
                          "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
-                         "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48",
-               .ilen   = 48,
+                         "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+                         "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+                         "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+                         "\xC3\x37\xCE\x65\xFC\x70\x07\x9E"
+                         "\x12\xA9\x40\xD7\x4B\xE2\x79\x10"
+                         "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F"
+                         "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1"
+                         "\x68\xFF\x73\x0A\xA1\x15\xAC\x43"
+                         "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5"
+                         "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
+                         "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
+                         "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
+                         "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+                         "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+                         "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+                         "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+                         "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+                         "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+                         "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+                         "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+                         "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+                         "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+                         "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+                         "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+                         "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+                         "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+                         "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+                         "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+                         "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+                         "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+                         "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+                         "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+                         "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+                         "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+                         "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+                         "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+                         "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+                         "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+                         "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+                         "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+                         "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+                         "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+                         "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+                         "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+                         "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+                         "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+                         "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+                         "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+                         "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+                         "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+                         "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+                         "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+                         "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+                         "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+                         "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+                         "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+                         "\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
+               .ilen   = 496,
                .result = "\xF3\x06\x3A\x84\xCD\xBA\x8E\x11"
                          "\xB7\x74\x6F\x5C\x97\xFB\x36\xFE"
                          "\xDE\x71\x58\xD4\x15\xD1\xC1\xA4"
                          "\xC9\x28\x74\xA6\x6B\xC7\x95\xA6"
                          "\x6C\x77\xF7\x2F\xDF\xC7\xBB\x85"
-                         "\x60\xFC\xE8\x94\xE8\xB5\x09\x2C",
-               .rlen   = 48,
-       },
-       { /* Generated with Crypto++ */
+                         "\x60\xFC\xE8\x94\xE8\xB5\x09\x2C"
+                         "\x1E\x43\xEF\x6C\xE9\x98\xC5\xA0"
+                         "\x7B\x13\xE5\x7F\xF8\x49\x9A\x8C"
+                         "\xE6\x7B\x08\xC3\x32\x66\x55\x4E"
+                         "\xA5\x44\x1D\x2C\x18\xC7\x29\x1F"
+                         "\x61\x28\x4A\xE3\xCD\xE5\x47\xB2"
+                         "\x82\x2F\x66\x83\x91\x51\xAE\xD7"
+                         "\x1C\x91\x3C\x57\xE3\x1D\x5A\xC9"
+                         "\xFD\xC5\x58\x58\xEF\xCC\x33\xC9"
+                         "\x0F\xEA\x26\x32\xD1\x15\x19\x2D"
+                         "\x25\xB4\x7F\xB0\xDF\xFB\x88\x60"
+                         "\x4E\x4D\x06\x7D\xCC\x1F\xED\x3B"
+                         "\x68\x84\xD5\xB3\x1B\xE7\xB9\xA1"
+                         "\x68\x8B\x2C\x1A\x44\xDA\x63\xD3"
+                         "\x29\xE9\x59\x32\x1F\x30\x1C\x43"
+                         "\xEA\x3A\xA3\x6B\x54\x3C\xAA\x11"
+                         "\xAD\x38\x20\xC9\xB9\x8A\x64\x66"
+                         "\x5A\x07\x49\xDF\xA1\x9C\xF9\x76"
+                         "\x36\x65\xB6\x81\x8F\x76\x09\xE5"
+                         "\xEB\xD1\x29\xA4\xE4\xF4\x4C\xCD"
+                         "\xAF\xFC\xB9\x16\xD9\xC3\x73\x6A"
+                         "\x33\x12\xF8\x7E\xBC\xCC\x7D\x80"
+                         "\xBF\x3C\x25\x06\x13\x84\xFA\x35"
+                         "\xF7\x40\xFA\xA1\x44\x13\x70\xD8"
+                         "\x01\xF9\x85\x15\x63\xEC\x7D\xB9"
+                         "\x02\xD8\xBA\x41\x6C\x92\x68\x66"
+                         "\x95\xDD\xD6\x42\xE7\xBB\xE1\xFD"
+                         "\x28\x3E\x94\xB6\xBD\xA7\xBF\x47"
+                         "\x58\x8D\xFF\x19\x30\x75\x0D\x48"
+                         "\x94\xE9\xA6\xCD\xB3\x8E\x1E\xCD"
+                         "\x59\xBC\x1A\xAC\x3C\x4F\xA9\xEB"
+                         "\xF4\xA7\xE4\x75\x4A\x18\x40\xC9"
+                         "\x1E\xEC\x06\x9C\x28\x4B\xF7\x2B"
+                         "\xE2\xEF\xD6\x42\x2E\xBB\xFC\x0A"
+                         "\x79\xA2\x99\x28\x93\x1B\x00\x57"
+                         "\x35\x1E\x1A\x93\x90\xA4\x68\x95"
+                         "\x5E\x57\x40\xD5\xA9\xAA\x19\x48"
+                         "\xEC\xFF\x76\x77\xDC\x78\x89\x76"
+                         "\xE5\x3B\x00\xEC\x58\x4D\xD1\xE3"
+                         "\xC8\x6C\x2C\x45\x5E\x5F\xD9\x4E"
+                         "\x71\xA5\x36\x6D\x03\xF1\xC7\xD5"
+                         "\xF3\x63\xC0\xD8\xCB\x2B\xF1\xA8"
+                         "\xB9\x2B\xE6\x0B\xB9\x65\x78\xA0"
+                         "\xC4\x46\xE6\x9B\x8B\x43\x2D\xAB"
+                         "\x70\xA6\xE0\x59\x1E\xAC\x9D\xE0"
+                         "\x76\x44\x45\xF3\x24\x11\x57\x98"
+                         "\x9A\x86\xB4\x12\x80\x28\x86\x20"
+                         "\x23\x9D\x2D\xE9\x38\x32\xB1\xE1"
+                         "\xCF\x0A\x23\x73\x7D\xC5\x80\x3D"
+                         "\x9F\x6D\xA0\xD0\xEE\x93\x8A\x79"
+                         "\x3A\xDD\x1D\xBB\x9E\x26\x5D\x01"
+                         "\x44\xD0\xD4\x4E\xC3\xF1\xE4\x38"
+                         "\x09\x62\x0A\x1A\x4E\xD2\x63\x0F"
+                         "\x6E\x3E\xD2\xA4\x3A\xF4\xF3\xFF"
+                         "\x7E\x42\xEC\xB6\x6F\x4D\x6B\x48"
+                         "\xE6\xA6\x50\x80\x78\x9E\xF1\xB0"
+                         "\x4D\xB2\x0D\x3D\xFC\x40\x25\x4D",
+               .rlen   = 496,
+       }, { /* Generated with Crypto++ */
                .key    = "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
                          "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
                          "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
@@ -16531,19 +21515,131 @@ static struct cipher_testvec camellia_ctr_enc_tv_template[] = {
                          "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
                          "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
                          "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
-                         "\xDF\x76\x0D",
-               .ilen   = 51,
+                         "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+                         "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+                         "\xC3\x37\xCE\x65\xFC\x70\x07\x9E"
+                         "\x12\xA9\x40\xD7\x4B\xE2\x79\x10"
+                         "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F"
+                         "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1"
+                         "\x68\xFF\x73\x0A\xA1\x15\xAC\x43"
+                         "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5"
+                         "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
+                         "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
+                         "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
+                         "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+                         "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+                         "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+                         "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+                         "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+                         "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+                         "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+                         "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+                         "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+                         "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+                         "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+                         "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+                         "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+                         "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+                         "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+                         "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+                         "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+                         "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+                         "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+                         "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+                         "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+                         "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+                         "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+                         "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+                         "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+                         "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+                         "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+                         "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+                         "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+                         "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+                         "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+                         "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+                         "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+                         "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+                         "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+                         "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+                         "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+                         "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+                         "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+                         "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+                         "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+                         "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+                         "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+                         "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+                         "\xDC\x50\xE7\x7E\x15\x89\x20\xB7"
+                         "\x2B\xC2\x59",
+               .ilen   = 499,
                .result = "\xF3\x06\x3A\x84\xCD\xBA\x8E\x11"
                          "\xB7\x74\x6F\x5C\x97\xFB\x36\xFE"
                          "\xDE\x71\x58\xD4\x15\xD1\xC1\xA4"
                          "\xC9\x28\x74\xA6\x6B\xC7\x95\xA6"
                          "\x6C\x77\xF7\x2F\xDF\xC7\xBB\x85"
                          "\x60\xFC\xE8\x94\xE8\xB5\x09\x2C"
-                         "\x1E\x43\xEF",
-               .rlen   = 51,
+                         "\x1E\x43\xEF\x6C\xE9\x98\xC5\xA0"
+                         "\x7B\x13\xE5\x7F\xF8\x49\x9A\x8C"
+                         "\xE6\x7B\x08\xC3\x32\x66\x55\x4E"
+                         "\xA5\x44\x1D\x2C\x18\xC7\x29\x1F"
+                         "\x61\x28\x4A\xE3\xCD\xE5\x47\xB2"
+                         "\x82\x2F\x66\x83\x91\x51\xAE\xD7"
+                         "\x1C\x91\x3C\x57\xE3\x1D\x5A\xC9"
+                         "\xFD\xC5\x58\x58\xEF\xCC\x33\xC9"
+                         "\x0F\xEA\x26\x32\xD1\x15\x19\x2D"
+                         "\x25\xB4\x7F\xB0\xDF\xFB\x88\x60"
+                         "\x4E\x4D\x06\x7D\xCC\x1F\xED\x3B"
+                         "\x68\x84\xD5\xB3\x1B\xE7\xB9\xA1"
+                         "\x68\x8B\x2C\x1A\x44\xDA\x63\xD3"
+                         "\x29\xE9\x59\x32\x1F\x30\x1C\x43"
+                         "\xEA\x3A\xA3\x6B\x54\x3C\xAA\x11"
+                         "\xAD\x38\x20\xC9\xB9\x8A\x64\x66"
+                         "\x5A\x07\x49\xDF\xA1\x9C\xF9\x76"
+                         "\x36\x65\xB6\x81\x8F\x76\x09\xE5"
+                         "\xEB\xD1\x29\xA4\xE4\xF4\x4C\xCD"
+                         "\xAF\xFC\xB9\x16\xD9\xC3\x73\x6A"
+                         "\x33\x12\xF8\x7E\xBC\xCC\x7D\x80"
+                         "\xBF\x3C\x25\x06\x13\x84\xFA\x35"
+                         "\xF7\x40\xFA\xA1\x44\x13\x70\xD8"
+                         "\x01\xF9\x85\x15\x63\xEC\x7D\xB9"
+                         "\x02\xD8\xBA\x41\x6C\x92\x68\x66"
+                         "\x95\xDD\xD6\x42\xE7\xBB\xE1\xFD"
+                         "\x28\x3E\x94\xB6\xBD\xA7\xBF\x47"
+                         "\x58\x8D\xFF\x19\x30\x75\x0D\x48"
+                         "\x94\xE9\xA6\xCD\xB3\x8E\x1E\xCD"
+                         "\x59\xBC\x1A\xAC\x3C\x4F\xA9\xEB"
+                         "\xF4\xA7\xE4\x75\x4A\x18\x40\xC9"
+                         "\x1E\xEC\x06\x9C\x28\x4B\xF7\x2B"
+                         "\xE2\xEF\xD6\x42\x2E\xBB\xFC\x0A"
+                         "\x79\xA2\x99\x28\x93\x1B\x00\x57"
+                         "\x35\x1E\x1A\x93\x90\xA4\x68\x95"
+                         "\x5E\x57\x40\xD5\xA9\xAA\x19\x48"
+                         "\xEC\xFF\x76\x77\xDC\x78\x89\x76"
+                         "\xE5\x3B\x00\xEC\x58\x4D\xD1\xE3"
+                         "\xC8\x6C\x2C\x45\x5E\x5F\xD9\x4E"
+                         "\x71\xA5\x36\x6D\x03\xF1\xC7\xD5"
+                         "\xF3\x63\xC0\xD8\xCB\x2B\xF1\xA8"
+                         "\xB9\x2B\xE6\x0B\xB9\x65\x78\xA0"
+                         "\xC4\x46\xE6\x9B\x8B\x43\x2D\xAB"
+                         "\x70\xA6\xE0\x59\x1E\xAC\x9D\xE0"
+                         "\x76\x44\x45\xF3\x24\x11\x57\x98"
+                         "\x9A\x86\xB4\x12\x80\x28\x86\x20"
+                         "\x23\x9D\x2D\xE9\x38\x32\xB1\xE1"
+                         "\xCF\x0A\x23\x73\x7D\xC5\x80\x3D"
+                         "\x9F\x6D\xA0\xD0\xEE\x93\x8A\x79"
+                         "\x3A\xDD\x1D\xBB\x9E\x26\x5D\x01"
+                         "\x44\xD0\xD4\x4E\xC3\xF1\xE4\x38"
+                         "\x09\x62\x0A\x1A\x4E\xD2\x63\x0F"
+                         "\x6E\x3E\xD2\xA4\x3A\xF4\xF3\xFF"
+                         "\x7E\x42\xEC\xB6\x6F\x4D\x6B\x48"
+                         "\xE6\xA6\x50\x80\x78\x9E\xF1\xB0"
+                         "\x4D\xB2\x0D\x3D\xFC\x40\x25\x4D"
+                         "\x93\x11\x1C",
+               .rlen   = 499,
                .also_non_np = 1,
                .np     = 2,
-               .tap    = { 51 - 16, 16 },
+               .tap    = { 499 - 16, 16 },
        }, { /* Generated with Crypto++ */
                .key    = "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
                          "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
@@ -16695,17 +21791,128 @@ static struct cipher_testvec camellia_ctr_dec_tv_template[] = {
                          "\xDE\x71\x58\xD4\x15\xD1\xC1\xA4"
                          "\xC9\x28\x74\xA6\x6B\xC7\x95\xA6"
                          "\x6C\x77\xF7\x2F\xDF\xC7\xBB\x85"
-                         "\x60\xFC\xE8\x94\xE8\xB5\x09\x2C",
-               .ilen   = 48,
+                         "\x60\xFC\xE8\x94\xE8\xB5\x09\x2C"
+                         "\x1E\x43\xEF\x6C\xE9\x98\xC5\xA0"
+                         "\x7B\x13\xE5\x7F\xF8\x49\x9A\x8C"
+                         "\xE6\x7B\x08\xC3\x32\x66\x55\x4E"
+                         "\xA5\x44\x1D\x2C\x18\xC7\x29\x1F"
+                         "\x61\x28\x4A\xE3\xCD\xE5\x47\xB2"
+                         "\x82\x2F\x66\x83\x91\x51\xAE\xD7"
+                         "\x1C\x91\x3C\x57\xE3\x1D\x5A\xC9"
+                         "\xFD\xC5\x58\x58\xEF\xCC\x33\xC9"
+                         "\x0F\xEA\x26\x32\xD1\x15\x19\x2D"
+                         "\x25\xB4\x7F\xB0\xDF\xFB\x88\x60"
+                         "\x4E\x4D\x06\x7D\xCC\x1F\xED\x3B"
+                         "\x68\x84\xD5\xB3\x1B\xE7\xB9\xA1"
+                         "\x68\x8B\x2C\x1A\x44\xDA\x63\xD3"
+                         "\x29\xE9\x59\x32\x1F\x30\x1C\x43"
+                         "\xEA\x3A\xA3\x6B\x54\x3C\xAA\x11"
+                         "\xAD\x38\x20\xC9\xB9\x8A\x64\x66"
+                         "\x5A\x07\x49\xDF\xA1\x9C\xF9\x76"
+                         "\x36\x65\xB6\x81\x8F\x76\x09\xE5"
+                         "\xEB\xD1\x29\xA4\xE4\xF4\x4C\xCD"
+                         "\xAF\xFC\xB9\x16\xD9\xC3\x73\x6A"
+                         "\x33\x12\xF8\x7E\xBC\xCC\x7D\x80"
+                         "\xBF\x3C\x25\x06\x13\x84\xFA\x35"
+                         "\xF7\x40\xFA\xA1\x44\x13\x70\xD8"
+                         "\x01\xF9\x85\x15\x63\xEC\x7D\xB9"
+                         "\x02\xD8\xBA\x41\x6C\x92\x68\x66"
+                         "\x95\xDD\xD6\x42\xE7\xBB\xE1\xFD"
+                         "\x28\x3E\x94\xB6\xBD\xA7\xBF\x47"
+                         "\x58\x8D\xFF\x19\x30\x75\x0D\x48"
+                         "\x94\xE9\xA6\xCD\xB3\x8E\x1E\xCD"
+                         "\x59\xBC\x1A\xAC\x3C\x4F\xA9\xEB"
+                         "\xF4\xA7\xE4\x75\x4A\x18\x40\xC9"
+                         "\x1E\xEC\x06\x9C\x28\x4B\xF7\x2B"
+                         "\xE2\xEF\xD6\x42\x2E\xBB\xFC\x0A"
+                         "\x79\xA2\x99\x28\x93\x1B\x00\x57"
+                         "\x35\x1E\x1A\x93\x90\xA4\x68\x95"
+                         "\x5E\x57\x40\xD5\xA9\xAA\x19\x48"
+                         "\xEC\xFF\x76\x77\xDC\x78\x89\x76"
+                         "\xE5\x3B\x00\xEC\x58\x4D\xD1\xE3"
+                         "\xC8\x6C\x2C\x45\x5E\x5F\xD9\x4E"
+                         "\x71\xA5\x36\x6D\x03\xF1\xC7\xD5"
+                         "\xF3\x63\xC0\xD8\xCB\x2B\xF1\xA8"
+                         "\xB9\x2B\xE6\x0B\xB9\x65\x78\xA0"
+                         "\xC4\x46\xE6\x9B\x8B\x43\x2D\xAB"
+                         "\x70\xA6\xE0\x59\x1E\xAC\x9D\xE0"
+                         "\x76\x44\x45\xF3\x24\x11\x57\x98"
+                         "\x9A\x86\xB4\x12\x80\x28\x86\x20"
+                         "\x23\x9D\x2D\xE9\x38\x32\xB1\xE1"
+                         "\xCF\x0A\x23\x73\x7D\xC5\x80\x3D"
+                         "\x9F\x6D\xA0\xD0\xEE\x93\x8A\x79"
+                         "\x3A\xDD\x1D\xBB\x9E\x26\x5D\x01"
+                         "\x44\xD0\xD4\x4E\xC3\xF1\xE4\x38"
+                         "\x09\x62\x0A\x1A\x4E\xD2\x63\x0F"
+                         "\x6E\x3E\xD2\xA4\x3A\xF4\xF3\xFF"
+                         "\x7E\x42\xEC\xB6\x6F\x4D\x6B\x48"
+                         "\xE6\xA6\x50\x80\x78\x9E\xF1\xB0"
+                         "\x4D\xB2\x0D\x3D\xFC\x40\x25\x4D",
+               .ilen   = 496,
                .result = "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
                          "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
                          "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
                          "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
                          "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
-                         "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48",
-               .rlen   = 48,
-       },
-       { /* Generated with Crypto++ */
+                         "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+                         "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+                         "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+                         "\xC3\x37\xCE\x65\xFC\x70\x07\x9E"
+                         "\x12\xA9\x40\xD7\x4B\xE2\x79\x10"
+                         "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F"
+                         "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1"
+                         "\x68\xFF\x73\x0A\xA1\x15\xAC\x43"
+                         "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5"
+                         "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
+                         "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
+                         "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
+                         "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+                         "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+                         "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+                         "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+                         "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+                         "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+                         "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+                         "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+                         "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+                         "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+                         "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+                         "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+                         "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+                         "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+                         "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+                         "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+                         "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+                         "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+                         "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+                         "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+                         "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+                         "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+                         "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+                         "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+                         "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+                         "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+                         "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+                         "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+                         "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+                         "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+                         "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+                         "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+                         "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+                         "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+                         "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+                         "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+                         "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+                         "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+                         "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+                         "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+                         "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+                         "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+                         "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+                         "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+                         "\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
+               .rlen   = 496,
+       }, { /* Generated with Crypto++ */
                .key    = "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
                          "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
                          "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
@@ -16719,19 +21926,131 @@ static struct cipher_testvec camellia_ctr_dec_tv_template[] = {
                          "\xC9\x28\x74\xA6\x6B\xC7\x95\xA6"
                          "\x6C\x77\xF7\x2F\xDF\xC7\xBB\x85"
                          "\x60\xFC\xE8\x94\xE8\xB5\x09\x2C"
-                         "\x1E\x43\xEF",
-               .ilen   = 51,
+                         "\x1E\x43\xEF\x6C\xE9\x98\xC5\xA0"
+                         "\x7B\x13\xE5\x7F\xF8\x49\x9A\x8C"
+                         "\xE6\x7B\x08\xC3\x32\x66\x55\x4E"
+                         "\xA5\x44\x1D\x2C\x18\xC7\x29\x1F"
+                         "\x61\x28\x4A\xE3\xCD\xE5\x47\xB2"
+                         "\x82\x2F\x66\x83\x91\x51\xAE\xD7"
+                         "\x1C\x91\x3C\x57\xE3\x1D\x5A\xC9"
+                         "\xFD\xC5\x58\x58\xEF\xCC\x33\xC9"
+                         "\x0F\xEA\x26\x32\xD1\x15\x19\x2D"
+                         "\x25\xB4\x7F\xB0\xDF\xFB\x88\x60"
+                         "\x4E\x4D\x06\x7D\xCC\x1F\xED\x3B"
+                         "\x68\x84\xD5\xB3\x1B\xE7\xB9\xA1"
+                         "\x68\x8B\x2C\x1A\x44\xDA\x63\xD3"
+                         "\x29\xE9\x59\x32\x1F\x30\x1C\x43"
+                         "\xEA\x3A\xA3\x6B\x54\x3C\xAA\x11"
+                         "\xAD\x38\x20\xC9\xB9\x8A\x64\x66"
+                         "\x5A\x07\x49\xDF\xA1\x9C\xF9\x76"
+                         "\x36\x65\xB6\x81\x8F\x76\x09\xE5"
+                         "\xEB\xD1\x29\xA4\xE4\xF4\x4C\xCD"
+                         "\xAF\xFC\xB9\x16\xD9\xC3\x73\x6A"
+                         "\x33\x12\xF8\x7E\xBC\xCC\x7D\x80"
+                         "\xBF\x3C\x25\x06\x13\x84\xFA\x35"
+                         "\xF7\x40\xFA\xA1\x44\x13\x70\xD8"
+                         "\x01\xF9\x85\x15\x63\xEC\x7D\xB9"
+                         "\x02\xD8\xBA\x41\x6C\x92\x68\x66"
+                         "\x95\xDD\xD6\x42\xE7\xBB\xE1\xFD"
+                         "\x28\x3E\x94\xB6\xBD\xA7\xBF\x47"
+                         "\x58\x8D\xFF\x19\x30\x75\x0D\x48"
+                         "\x94\xE9\xA6\xCD\xB3\x8E\x1E\xCD"
+                         "\x59\xBC\x1A\xAC\x3C\x4F\xA9\xEB"
+                         "\xF4\xA7\xE4\x75\x4A\x18\x40\xC9"
+                         "\x1E\xEC\x06\x9C\x28\x4B\xF7\x2B"
+                         "\xE2\xEF\xD6\x42\x2E\xBB\xFC\x0A"
+                         "\x79\xA2\x99\x28\x93\x1B\x00\x57"
+                         "\x35\x1E\x1A\x93\x90\xA4\x68\x95"
+                         "\x5E\x57\x40\xD5\xA9\xAA\x19\x48"
+                         "\xEC\xFF\x76\x77\xDC\x78\x89\x76"
+                         "\xE5\x3B\x00\xEC\x58\x4D\xD1\xE3"
+                         "\xC8\x6C\x2C\x45\x5E\x5F\xD9\x4E"
+                         "\x71\xA5\x36\x6D\x03\xF1\xC7\xD5"
+                         "\xF3\x63\xC0\xD8\xCB\x2B\xF1\xA8"
+                         "\xB9\x2B\xE6\x0B\xB9\x65\x78\xA0"
+                         "\xC4\x46\xE6\x9B\x8B\x43\x2D\xAB"
+                         "\x70\xA6\xE0\x59\x1E\xAC\x9D\xE0"
+                         "\x76\x44\x45\xF3\x24\x11\x57\x98"
+                         "\x9A\x86\xB4\x12\x80\x28\x86\x20"
+                         "\x23\x9D\x2D\xE9\x38\x32\xB1\xE1"
+                         "\xCF\x0A\x23\x73\x7D\xC5\x80\x3D"
+                         "\x9F\x6D\xA0\xD0\xEE\x93\x8A\x79"
+                         "\x3A\xDD\x1D\xBB\x9E\x26\x5D\x01"
+                         "\x44\xD0\xD4\x4E\xC3\xF1\xE4\x38"
+                         "\x09\x62\x0A\x1A\x4E\xD2\x63\x0F"
+                         "\x6E\x3E\xD2\xA4\x3A\xF4\xF3\xFF"
+                         "\x7E\x42\xEC\xB6\x6F\x4D\x6B\x48"
+                         "\xE6\xA6\x50\x80\x78\x9E\xF1\xB0"
+                         "\x4D\xB2\x0D\x3D\xFC\x40\x25\x4D"
+                         "\x93\x11\x1C",
+               .ilen   = 499,
                .result = "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
                          "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
                          "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
                          "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
                          "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
                          "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
-                         "\xDF\x76\x0D",
-               .rlen   = 51,
+                         "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+                         "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+                         "\xC3\x37\xCE\x65\xFC\x70\x07\x9E"
+                         "\x12\xA9\x40\xD7\x4B\xE2\x79\x10"
+                         "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F"
+                         "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1"
+                         "\x68\xFF\x73\x0A\xA1\x15\xAC\x43"
+                         "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5"
+                         "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
+                         "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
+                         "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
+                         "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+                         "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+                         "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+                         "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+                         "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+                         "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+                         "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+                         "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+                         "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+                         "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+                         "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+                         "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+                         "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+                         "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+                         "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+                         "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+                         "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+                         "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+                         "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+                         "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+                         "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+                         "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+                         "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+                         "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+                         "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+                         "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+                         "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+                         "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+                         "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+                         "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+                         "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+                         "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+                         "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+                         "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+                         "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+                         "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+                         "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+                         "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+                         "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+                         "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+                         "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+                         "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+                         "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+                         "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+                         "\xDC\x50\xE7\x7E\x15\x89\x20\xB7"
+                         "\x2B\xC2\x59",
+               .rlen   = 499,
                .also_non_np = 1,
                .np     = 2,
-               .tap    = { 51 - 16, 16 },
+               .tap    = { 499 - 16, 16 },
        }, { /* Generated with Crypto++ */
                .key    = "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
                          "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
index f2338ca983686c5aea9f57d1ad733097bd6a1455..2eb11a30c29cee93203a1b90a990cc4463368440 100644 (file)
@@ -375,6 +375,11 @@ static void vhash_update(const unsigned char *m,
        u64 pkh = ctx->polykey[0];
        u64 pkl = ctx->polykey[1];
 
+       if (!mbytes)
+               return;
+
+       BUG_ON(mbytes % VMAC_NHBYTES);
+
        mptr = (u64 *)m;
        i = mbytes / VMAC_NHBYTES;  /* Must be non-zero */
 
@@ -454,7 +459,7 @@ do_l3:
 }
 
 static u64 vmac(unsigned char m[], unsigned int mbytes,
-                       unsigned char n[16], u64 *tagl,
+                       const unsigned char n[16], u64 *tagl,
                        struct vmac_ctx_t *ctx)
 {
        u64 *in_n, *out_p;
@@ -559,8 +564,33 @@ static int vmac_update(struct shash_desc *pdesc, const u8 *p,
 {
        struct crypto_shash *parent = pdesc->tfm;
        struct vmac_ctx_t *ctx = crypto_shash_ctx(parent);
+       int expand;
+       int min;
+
+       expand = VMAC_NHBYTES - ctx->partial_size > 0 ?
+                       VMAC_NHBYTES - ctx->partial_size : 0;
+
+       min = len < expand ? len : expand;
+
+       memcpy(ctx->partial + ctx->partial_size, p, min);
+       ctx->partial_size += min;
+
+       if (len < expand)
+               return 0;
 
-       vhash_update(p, len, &ctx->__vmac_ctx);
+       vhash_update(ctx->partial, VMAC_NHBYTES, &ctx->__vmac_ctx);
+       ctx->partial_size = 0;
+
+       len -= expand;
+       p += expand;
+
+       if (len % VMAC_NHBYTES) {
+               memcpy(ctx->partial, p + len - (len % VMAC_NHBYTES),
+                       len % VMAC_NHBYTES);
+               ctx->partial_size = len % VMAC_NHBYTES;
+       }
+
+       vhash_update(p, len - len % VMAC_NHBYTES, &ctx->__vmac_ctx);
 
        return 0;
 }
@@ -572,10 +602,20 @@ static int vmac_final(struct shash_desc *pdesc, u8 *out)
        vmac_t mac;
        u8 nonce[16] = {};
 
-       mac = vmac(NULL, 0, nonce, NULL, ctx);
+       /* vmac() ends up accessing outside the array bounds that
+        * we specify.  In appears to access up to the next 2-word
+        * boundary.  We'll just be uber cautious and zero the
+        * unwritten bytes in the buffer.
+        */
+       if (ctx->partial_size) {
+               memset(ctx->partial + ctx->partial_size, 0,
+                       VMAC_NHBYTES - ctx->partial_size);
+       }
+       mac = vmac(ctx->partial, ctx->partial_size, nonce, NULL, ctx);
        memcpy(out, &mac, sizeof(vmac_t));
        memset(&mac, 0, sizeof(vmac_t));
        memset(&ctx->__vmac_ctx, 0, sizeof(struct vmac_ctx));
+       ctx->partial_size = 0;
        return 0;
 }
 
@@ -673,4 +713,3 @@ module_exit(vmac_module_exit);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("VMAC hash algorithm");
-
index 119d58db834298ff950251bf07ae0fc5436ab1ca..44cea5d4b04e1353f480b9051f89f64ca09e3129 100644 (file)
@@ -261,6 +261,15 @@ config ACPI_CUSTOM_DSDT
        bool
        default ACPI_CUSTOM_DSDT_FILE != ""
 
+config ACPI_INITRD_TABLE_OVERRIDE
+       bool "ACPI tables can be passed via uncompressed cpio in initrd"
+       default n
+       help
+         This option provides functionality to override arbitrary ACPI tables
+         via initrd. No functional change if no ACPI tables are passed via
+         initrd, therefore it's safe to say Y.
+         See Documentation/acpi/initrd_table_override.txt for details
+
 config ACPI_BLACKLIST_YEAR
        int "Disable ACPI for systems before Jan 1st this year" if X86_32
        default 0
index af4aad6ee2eb9eb8d40acfa6151c60c7911b51d1..16fa979f7180b935a52fbfa03c75ca173359031d 100644 (file)
@@ -286,7 +286,7 @@ static ssize_t acpi_pad_rrtime_store(struct device *dev,
        struct device_attribute *attr, const char *buf, size_t count)
 {
        unsigned long num;
-       if (strict_strtoul(buf, 0, &num))
+       if (kstrtoul(buf, 0, &num))
                return -EINVAL;
        if (num < 1 || num >= 100)
                return -EINVAL;
@@ -309,7 +309,7 @@ static ssize_t acpi_pad_idlepct_store(struct device *dev,
        struct device_attribute *attr, const char *buf, size_t count)
 {
        unsigned long num;
-       if (strict_strtoul(buf, 0, &num))
+       if (kstrtoul(buf, 0, &num))
                return -EINVAL;
        if (num < 1 || num >= 100)
                return -EINVAL;
@@ -332,7 +332,7 @@ static ssize_t acpi_pad_idlecpus_store(struct device *dev,
        struct device_attribute *attr, const char *buf, size_t count)
 {
        unsigned long num;
-       if (strict_strtoul(buf, 0, &num))
+       if (kstrtoul(buf, 0, &num))
                return -EINVAL;
        mutex_lock(&isolated_cpus_lock);
        acpi_pad_idle_cpus(num);
@@ -457,7 +457,7 @@ static void acpi_pad_notify(acpi_handle handle, u32 event,
                        dev_name(&device->dev), event, 0);
                break;
        default:
-               printk(KERN_WARNING "Unsupported event [0x%x]\n", event);
+               pr_warn("Unsupported event [0x%x]\n", event);
                break;
        }
 }
index 1f9f7d7d7bc534f27ec9d0d31b2f5d61246c65b2..ffd76ee2b8509b8ad36606abefc8d169c487d9c7 100644 (file)
@@ -92,6 +92,19 @@ static int is_device_present(acpi_handle handle)
        return ((sta & ACPI_STA_DEVICE_PRESENT) == ACPI_STA_DEVICE_PRESENT);
 }
 
+static int is_container_device(const char *hid)
+{
+       const struct acpi_device_id *container_id;
+
+       for (container_id = container_device_ids;
+            container_id->id[0]; container_id++) {
+               if (!strcmp((char *)container_id->id, hid))
+                       return 1;
+       }
+
+       return 0;
+}
+
 /*******************************************************************/
 static int acpi_container_add(struct acpi_device *device)
 {
@@ -232,10 +245,8 @@ container_walk_namespace_cb(acpi_handle handle,
                goto end;
        }
 
-       if (strcmp(hid, "ACPI0004") && strcmp(hid, "PNP0A05") &&
-           strcmp(hid, "PNP0A06")) {
+       if (!is_container_device(hid))
                goto end;
-       }
 
        switch (*action) {
        case INSTALL_NOTIFY_HANDLER:
index 88eb14304667bc6bef8726e06ee0ecd8f339cca5..ae4ebf2d4cd224321edb560470ec53a2ee3602e0 100644 (file)
@@ -1016,44 +1016,32 @@ static int dock_remove(struct dock_station *ds)
 }
 
 /**
- * find_dock - look for a dock station
+ * find_dock_and_bay - look for dock stations and bays
  * @handle: acpi handle of a device
  * @lvl: unused
- * @context: counter of dock stations found
+ * @context: unused
  * @rv: unused
  *
- * This is called by acpi_walk_namespace to look for dock stations.
+ * This is called by acpi_walk_namespace to look for dock stations and bays.
  */
 static __init acpi_status
-find_dock(acpi_handle handle, u32 lvl, void *context, void **rv)
+find_dock_and_bay(acpi_handle handle, u32 lvl, void *context, void **rv)
 {
-       if (is_dock(handle))
+       if (is_dock(handle) || is_ejectable_bay(handle))
                dock_add(handle);
 
        return AE_OK;
 }
 
-static __init acpi_status
-find_bay(acpi_handle handle, u32 lvl, void *context, void **rv)
-{
-       /* If bay is a dock, it's already handled */
-       if (is_ejectable_bay(handle) && !is_dock(handle))
-               dock_add(handle);
-       return AE_OK;
-}
-
 static int __init dock_init(void)
 {
        if (acpi_disabled)
                return 0;
 
-       /* look for a dock station */
+       /* look for dock stations and bays */
        acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
-                           ACPI_UINT32_MAX, find_dock, NULL, NULL, NULL);
+               ACPI_UINT32_MAX, find_dock_and_bay, NULL, NULL, NULL);
 
-       /* look for bay */
-       acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
-                       ACPI_UINT32_MAX, find_bay, NULL, NULL, NULL);
        if (!dock_station_count) {
                printk(KERN_INFO PREFIX "No dock devices found.\n");
                return 0;
index a51df968131989178111343bea86aa4d5403268f..354007d490d1268a6e97cee38ba48fd36c1922f7 100644 (file)
@@ -158,10 +158,10 @@ static int ec_transaction_done(struct acpi_ec *ec)
 {
        unsigned long flags;
        int ret = 0;
-       spin_lock_irqsave(&ec->curr_lock, flags);
+       spin_lock_irqsave(&ec->lock, flags);
        if (!ec->curr || ec->curr->done)
                ret = 1;
-       spin_unlock_irqrestore(&ec->curr_lock, flags);
+       spin_unlock_irqrestore(&ec->lock, flags);
        return ret;
 }
 
@@ -175,32 +175,38 @@ static void start_transaction(struct acpi_ec *ec)
 static void advance_transaction(struct acpi_ec *ec, u8 status)
 {
        unsigned long flags;
-       spin_lock_irqsave(&ec->curr_lock, flags);
-       if (!ec->curr)
+       struct transaction *t = ec->curr;
+
+       spin_lock_irqsave(&ec->lock, flags);
+       if (!t)
                goto unlock;
-       if (ec->curr->wlen > ec->curr->wi) {
+       if (t->wlen > t->wi) {
                if ((status & ACPI_EC_FLAG_IBF) == 0)
                        acpi_ec_write_data(ec,
-                               ec->curr->wdata[ec->curr->wi++]);
+                               t->wdata[t->wi++]);
                else
                        goto err;
-       } else if (ec->curr->rlen > ec->curr->ri) {
+       } else if (t->rlen > t->ri) {
                if ((status & ACPI_EC_FLAG_OBF) == 1) {
-                       ec->curr->rdata[ec->curr->ri++] = acpi_ec_read_data(ec);
-                       if (ec->curr->rlen == ec->curr->ri)
-                               ec->curr->done = true;
+                       t->rdata[t->ri++] = acpi_ec_read_data(ec);
+                       if (t->rlen == t->ri)
+                               t->done = true;
                } else
                        goto err;
-       } else if (ec->curr->wlen == ec->curr->wi &&
+       } else if (t->wlen == t->wi &&
                   (status & ACPI_EC_FLAG_IBF) == 0)
-               ec->curr->done = true;
+               t->done = true;
        goto unlock;
 err:
-       /* false interrupt, state didn't change */
-       if (in_interrupt())
-               ++ec->curr->irq_count;
+       /*
+        * If SCI bit is set, then don't think it's a false IRQ
+        * otherwise will take a not handled IRQ as a false one.
+        */
+       if (in_interrupt() && !(status & ACPI_EC_FLAG_SCI))
+               ++t->irq_count;
+
 unlock:
-       spin_unlock_irqrestore(&ec->curr_lock, flags);
+       spin_unlock_irqrestore(&ec->lock, flags);
 }
 
 static int acpi_ec_sync_query(struct acpi_ec *ec);
@@ -238,9 +244,9 @@ static int ec_poll(struct acpi_ec *ec)
                if (acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF)
                        break;
                pr_debug(PREFIX "controller reset, restart transaction\n");
-               spin_lock_irqsave(&ec->curr_lock, flags);
+               spin_lock_irqsave(&ec->lock, flags);
                start_transaction(ec);
-               spin_unlock_irqrestore(&ec->curr_lock, flags);
+               spin_unlock_irqrestore(&ec->lock, flags);
        }
        return -ETIME;
 }
@@ -253,17 +259,17 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec,
        if (EC_FLAGS_MSI)
                udelay(ACPI_EC_MSI_UDELAY);
        /* start transaction */
-       spin_lock_irqsave(&ec->curr_lock, tmp);
+       spin_lock_irqsave(&ec->lock, tmp);
        /* following two actions should be kept atomic */
        ec->curr = t;
        start_transaction(ec);
        if (ec->curr->command == ACPI_EC_COMMAND_QUERY)
                clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);
-       spin_unlock_irqrestore(&ec->curr_lock, tmp);
+       spin_unlock_irqrestore(&ec->lock, tmp);
        ret = ec_poll(ec);
-       spin_lock_irqsave(&ec->curr_lock, tmp);
+       spin_lock_irqsave(&ec->lock, tmp);
        ec->curr = NULL;
-       spin_unlock_irqrestore(&ec->curr_lock, tmp);
+       spin_unlock_irqrestore(&ec->lock, tmp);
        return ret;
 }
 
@@ -292,7 +298,7 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t)
                return -EINVAL;
        if (t->rdata)
                memset(t->rdata, 0, t->rlen);
-       mutex_lock(&ec->lock);
+       mutex_lock(&ec->mutex);
        if (test_bit(EC_FLAGS_BLOCKED, &ec->flags)) {
                status = -EINVAL;
                goto unlock;
@@ -310,7 +316,8 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t)
                status = -ETIME;
                goto end;
        }
-       pr_debug(PREFIX "transaction start\n");
+       pr_debug(PREFIX "transaction start (cmd=0x%02x, addr=0x%02x)\n",
+                       t->command, t->wdata ? t->wdata[0] : 0);
        /* disable GPE during transaction if storm is detected */
        if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) {
                /* It has to be disabled, so that it doesn't trigger. */
@@ -326,8 +333,9 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t)
                /* It is safe to enable the GPE outside of the transaction. */
                acpi_enable_gpe(NULL, ec->gpe);
        } else if (t->irq_count > ec_storm_threshold) {
-               pr_info(PREFIX "GPE storm detected, "
-                       "transactions will use polling mode\n");
+               pr_info(PREFIX "GPE storm detected(%d GPEs), "
+                       "transactions will use polling mode\n",
+                       t->irq_count);
                set_bit(EC_FLAGS_GPE_STORM, &ec->flags);
        }
        pr_debug(PREFIX "transaction end\n");
@@ -335,7 +343,7 @@ end:
        if (ec->global_lock)
                acpi_release_global_lock(glk);
 unlock:
-       mutex_unlock(&ec->lock);
+       mutex_unlock(&ec->mutex);
        return status;
 }
 
@@ -403,7 +411,7 @@ int ec_burst_disable(void)
 
 EXPORT_SYMBOL(ec_burst_disable);
 
-int ec_read(u8 addr, u8 * val)
+int ec_read(u8 addr, u8 *val)
 {
        int err;
        u8 temp_data;
@@ -468,10 +476,10 @@ void acpi_ec_block_transactions(void)
        if (!ec)
                return;
 
-       mutex_lock(&ec->lock);
+       mutex_lock(&ec->mutex);
        /* Prevent transactions from being carried out */
        set_bit(EC_FLAGS_BLOCKED, &ec->flags);
-       mutex_unlock(&ec->lock);
+       mutex_unlock(&ec->mutex);
 }
 
 void acpi_ec_unblock_transactions(void)
@@ -481,10 +489,10 @@ void acpi_ec_unblock_transactions(void)
        if (!ec)
                return;
 
-       mutex_lock(&ec->lock);
+       mutex_lock(&ec->mutex);
        /* Allow transactions to be carried out again */
        clear_bit(EC_FLAGS_BLOCKED, &ec->flags);
-       mutex_unlock(&ec->lock);
+       mutex_unlock(&ec->mutex);
 }
 
 void acpi_ec_unblock_transactions_early(void)
@@ -536,9 +544,9 @@ int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit,
        handler->handle = handle;
        handler->func = func;
        handler->data = data;
-       mutex_lock(&ec->lock);
+       mutex_lock(&ec->mutex);
        list_add(&handler->node, &ec->list);
-       mutex_unlock(&ec->lock);
+       mutex_unlock(&ec->mutex);
        return 0;
 }
 
@@ -547,14 +555,14 @@ EXPORT_SYMBOL_GPL(acpi_ec_add_query_handler);
 void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit)
 {
        struct acpi_ec_query_handler *handler, *tmp;
-       mutex_lock(&ec->lock);
+       mutex_lock(&ec->mutex);
        list_for_each_entry_safe(handler, tmp, &ec->list, node) {
                if (query_bit == handler->query_bit) {
                        list_del(&handler->node);
                        kfree(handler);
                }
        }
-       mutex_unlock(&ec->lock);
+       mutex_unlock(&ec->mutex);
 }
 
 EXPORT_SYMBOL_GPL(acpi_ec_remove_query_handler);
@@ -601,9 +609,9 @@ static void acpi_ec_gpe_query(void *ec_cxt)
        struct acpi_ec *ec = ec_cxt;
        if (!ec)
                return;
-       mutex_lock(&ec->lock);
+       mutex_lock(&ec->mutex);
        acpi_ec_sync_query(ec);
-       mutex_unlock(&ec->lock);
+       mutex_unlock(&ec->mutex);
 }
 
 static int ec_check_sci(struct acpi_ec *ec, u8 state)
@@ -622,10 +630,11 @@ static u32 acpi_ec_gpe_handler(acpi_handle gpe_device,
        u32 gpe_number, void *data)
 {
        struct acpi_ec *ec = data;
+       u8 status = acpi_ec_read_status(ec);
 
-       pr_debug(PREFIX "~~~> interrupt\n");
+       pr_debug(PREFIX "~~~> interrupt, status:0x%02x\n", status);
 
-       advance_transaction(ec, acpi_ec_read_status(ec));
+       advance_transaction(ec, status);
        if (ec_transaction_done(ec) &&
            (acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF) == 0) {
                wake_up(&ec->wait);
@@ -691,10 +700,10 @@ static struct acpi_ec *make_acpi_ec(void)
        if (!ec)
                return NULL;
        ec->flags = 1 << EC_FLAGS_QUERY_PENDING;
-       mutex_init(&ec->lock);
+       mutex_init(&ec->mutex);
        init_waitqueue_head(&ec->wait);
        INIT_LIST_HEAD(&ec->list);
-       spin_lock_init(&ec->curr_lock);
+       spin_lock_init(&ec->lock);
        return ec;
 }
 
@@ -853,12 +862,12 @@ static int acpi_ec_remove(struct acpi_device *device, int type)
 
        ec = acpi_driver_data(device);
        ec_remove_handlers(ec);
-       mutex_lock(&ec->lock);
+       mutex_lock(&ec->mutex);
        list_for_each_entry_safe(handler, tmp, &ec->list, node) {
                list_del(&handler->node);
                kfree(handler);
        }
-       mutex_unlock(&ec->lock);
+       mutex_unlock(&ec->mutex);
        release_region(ec->data_addr, 1);
        release_region(ec->command_addr, 1);
        device->driver_data = NULL;
index d1a2d74033e945237afdef3fac02aea87cdebbdd..08373086cd7e883edeec356acb102bcac46147cf 100644 (file)
@@ -159,6 +159,7 @@ static int acpi_bind_one(struct device *dev, acpi_handle handle)
        if (physical_node->node_id >= ACPI_MAX_PHYSICAL_NODE) {
                retval = -ENOSPC;
                mutex_unlock(&acpi_dev->physical_node_lock);
+               kfree(physical_node);
                goto err;
        }
 
index ca75b9ce0489f0fb1140d994ccf2476bf4935a60..509dcaa17555c38cc3d0c622c343a68e82472fd6 100644 (file)
@@ -58,11 +58,11 @@ struct acpi_ec {
        unsigned long data_addr;
        unsigned long global_lock;
        unsigned long flags;
-       struct mutex lock;
+       struct mutex mutex;
        wait_queue_head_t wait;
        struct list_head list;
        struct transaction *curr;
-       spinlock_t curr_lock;
+       spinlock_t lock;
 };
 
 extern struct acpi_ec *first_ec;
index 9eaf708f588553ee78b10bb6571e55859fb1db3c..b0a2b3174237bb999e32b9d3de26f86dc552b1c0 100644 (file)
@@ -534,6 +534,137 @@ acpi_os_predefined_override(const struct acpi_predefined_names *init_val,
        return AE_OK;
 }
 
+#ifdef CONFIG_ACPI_INITRD_TABLE_OVERRIDE
+#include <linux/earlycpio.h>
+#include <linux/memblock.h>
+
+static u64 acpi_tables_addr;
+static int all_tables_size;
+
+/* Copied from acpica/tbutils.c:acpi_tb_checksum() */
+u8 __init acpi_table_checksum(u8 *buffer, u32 length)
+{
+       u8 sum = 0;
+       u8 *end = buffer + length;
+
+       while (buffer < end)
+               sum = (u8) (sum + *(buffer++));
+       return sum;
+}
+
+/* All but ACPI_SIG_RSDP and ACPI_SIG_FACS: */
+static const char * const table_sigs[] = {
+       ACPI_SIG_BERT, ACPI_SIG_CPEP, ACPI_SIG_ECDT, ACPI_SIG_EINJ,
+       ACPI_SIG_ERST, ACPI_SIG_HEST, ACPI_SIG_MADT, ACPI_SIG_MSCT,
+       ACPI_SIG_SBST, ACPI_SIG_SLIT, ACPI_SIG_SRAT, ACPI_SIG_ASF,
+       ACPI_SIG_BOOT, ACPI_SIG_DBGP, ACPI_SIG_DMAR, ACPI_SIG_HPET,
+       ACPI_SIG_IBFT, ACPI_SIG_IVRS, ACPI_SIG_MCFG, ACPI_SIG_MCHI,
+       ACPI_SIG_SLIC, ACPI_SIG_SPCR, ACPI_SIG_SPMI, ACPI_SIG_TCPA,
+       ACPI_SIG_UEFI, ACPI_SIG_WAET, ACPI_SIG_WDAT, ACPI_SIG_WDDT,
+       ACPI_SIG_WDRT, ACPI_SIG_DSDT, ACPI_SIG_FADT, ACPI_SIG_PSDT,
+       ACPI_SIG_RSDT, ACPI_SIG_XSDT, ACPI_SIG_SSDT, NULL };
+
+/* Non-fatal errors: Affected tables/files are ignored */
+#define INVALID_TABLE(x, path, name)                                   \
+       { pr_err("ACPI OVERRIDE: " x " [%s%s]\n", path, name); continue; }
+
+#define ACPI_HEADER_SIZE sizeof(struct acpi_table_header)
+
+/* Must not increase 10 or needs code modification below */
+#define ACPI_OVERRIDE_TABLES 10
+
+void __init acpi_initrd_override(void *data, size_t size)
+{
+       int sig, no, table_nr = 0, total_offset = 0;
+       long offset = 0;
+       struct acpi_table_header *table;
+       char cpio_path[32] = "kernel/firmware/acpi/";
+       struct cpio_data file;
+       struct cpio_data early_initrd_files[ACPI_OVERRIDE_TABLES];
+       char *p;
+
+       if (data == NULL || size == 0)
+               return;
+
+       for (no = 0; no < ACPI_OVERRIDE_TABLES; no++) {
+               file = find_cpio_data(cpio_path, data, size, &offset);
+               if (!file.data)
+                       break;
+
+               data += offset;
+               size -= offset;
+
+               if (file.size < sizeof(struct acpi_table_header))
+                       INVALID_TABLE("Table smaller than ACPI header",
+                                     cpio_path, file.name);
+
+               table = file.data;
+
+               for (sig = 0; table_sigs[sig]; sig++)
+                       if (!memcmp(table->signature, table_sigs[sig], 4))
+                               break;
+
+               if (!table_sigs[sig])
+                       INVALID_TABLE("Unknown signature",
+                                     cpio_path, file.name);
+               if (file.size != table->length)
+                       INVALID_TABLE("File length does not match table length",
+                                     cpio_path, file.name);
+               if (acpi_table_checksum(file.data, table->length))
+                       INVALID_TABLE("Bad table checksum",
+                                     cpio_path, file.name);
+
+               pr_info("%4.4s ACPI table found in initrd [%s%s][0x%x]\n",
+                       table->signature, cpio_path, file.name, table->length);
+
+               all_tables_size += table->length;
+               early_initrd_files[table_nr].data = file.data;
+               early_initrd_files[table_nr].size = file.size;
+               table_nr++;
+       }
+       if (table_nr == 0)
+               return;
+
+       acpi_tables_addr =
+               memblock_find_in_range(0, max_low_pfn_mapped << PAGE_SHIFT,
+                                      all_tables_size, PAGE_SIZE);
+       if (!acpi_tables_addr) {
+               WARN_ON(1);
+               return;
+       }
+       /*
+        * Only calling e820_add_reserve does not work and the
+        * tables are invalid (memory got used) later.
+        * memblock_reserve works as expected and the tables won't get modified.
+        * But it's not enough on X86 because ioremap will
+        * complain later (used by acpi_os_map_memory) that the pages
+        * that should get mapped are not marked "reserved".
+        * Both memblock_reserve and e820_add_region (via arch_reserve_mem_area)
+        * works fine.
+        */
+       memblock_reserve(acpi_tables_addr, acpi_tables_addr + all_tables_size);
+       arch_reserve_mem_area(acpi_tables_addr, all_tables_size);
+
+       p = early_ioremap(acpi_tables_addr, all_tables_size);
+
+       for (no = 0; no < table_nr; no++) {
+               memcpy(p + total_offset, early_initrd_files[no].data,
+                      early_initrd_files[no].size);
+               total_offset += early_initrd_files[no].size;
+       }
+       early_iounmap(p, all_tables_size);
+}
+#endif /* CONFIG_ACPI_INITRD_TABLE_OVERRIDE */
+
+static void acpi_table_taint(struct acpi_table_header *table)
+{
+       pr_warn(PREFIX
+               "Override [%4.4s-%8.8s], this is unsafe: tainting kernel\n",
+               table->signature, table->oem_table_id);
+       add_taint(TAINT_OVERRIDDEN_ACPI_TABLE);
+}
+
+
 acpi_status
 acpi_os_table_override(struct acpi_table_header * existing_table,
                       struct acpi_table_header ** new_table)
@@ -547,24 +678,73 @@ acpi_os_table_override(struct acpi_table_header * existing_table,
        if (strncmp(existing_table->signature, "DSDT", 4) == 0)
                *new_table = (struct acpi_table_header *)AmlCode;
 #endif
-       if (*new_table != NULL) {
-               printk(KERN_WARNING PREFIX "Override [%4.4s-%8.8s], "
-                          "this is unsafe: tainting kernel\n",
-                      existing_table->signature,
-                      existing_table->oem_table_id);
-               add_taint(TAINT_OVERRIDDEN_ACPI_TABLE);
-       }
+       if (*new_table != NULL)
+               acpi_table_taint(existing_table);
        return AE_OK;
 }
 
 acpi_status
 acpi_os_physical_table_override(struct acpi_table_header *existing_table,
-                               acpi_physical_address * new_address,
-                               u32 *new_table_length)
+                               acpi_physical_address *address,
+                               u32 *table_length)
 {
-       return AE_SUPPORT;
-}
+#ifndef CONFIG_ACPI_INITRD_TABLE_OVERRIDE
+       *table_length = 0;
+       *address = 0;
+       return AE_OK;
+#else
+       int table_offset = 0;
+       struct acpi_table_header *table;
+
+       *table_length = 0;
+       *address = 0;
+
+       if (!acpi_tables_addr)
+               return AE_OK;
+
+       do {
+               if (table_offset + ACPI_HEADER_SIZE > all_tables_size) {
+                       WARN_ON(1);
+                       return AE_OK;
+               }
 
+               table = acpi_os_map_memory(acpi_tables_addr + table_offset,
+                                          ACPI_HEADER_SIZE);
+
+               if (table_offset + table->length > all_tables_size) {
+                       acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
+                       WARN_ON(1);
+                       return AE_OK;
+               }
+
+               table_offset += table->length;
+
+               if (memcmp(existing_table->signature, table->signature, 4)) {
+                       acpi_os_unmap_memory(table,
+                                    ACPI_HEADER_SIZE);
+                       continue;
+               }
+
+               /* Only override tables with matching oem id */
+               if (memcmp(table->oem_table_id, existing_table->oem_table_id,
+                          ACPI_OEM_TABLE_ID_SIZE)) {
+                       acpi_os_unmap_memory(table,
+                                    ACPI_HEADER_SIZE);
+                       continue;
+               }
+
+               table_offset -= table->length;
+               *table_length = table->length;
+               acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
+               *address = acpi_tables_addr + table_offset;
+               break;
+       } while (table_offset + ACPI_HEADER_SIZE < all_tables_size);
+
+       if (*address != 0)
+               acpi_table_taint(existing_table);
+       return AE_OK;
+#endif
+}
 
 static irqreturn_t acpi_irq(int irq, void *dev_id)
 {
@@ -949,12 +1129,7 @@ static acpi_status __acpi_os_execute(acpi_execute_type type,
                (type == OSL_NOTIFY_HANDLER ? kacpi_notify_wq : kacpid_wq);
        dpc->wait = hp ? 1 : 0;
 
-       if (queue == kacpi_hotplug_wq)
-               INIT_WORK(&dpc->work, acpi_os_execute_deferred);
-       else if (queue == kacpi_notify_wq)
-               INIT_WORK(&dpc->work, acpi_os_execute_deferred);
-       else
-               INIT_WORK(&dpc->work, acpi_os_execute_deferred);
+       INIT_WORK(&dpc->work, acpi_os_execute_deferred);
 
        /*
         * On some machines, a software-initiated SMI causes corruption unless
index e78c2a52ea46665fe3ea31a7e79ba7f5cc5c38b2..ae50bfca5b67b6a8e586a7ebcffcae6f12ba4743 100644 (file)
@@ -851,8 +851,22 @@ static int acpi_processor_handle_eject(struct acpi_processor *pr)
        if (cpu_online(pr->id))
                cpu_down(pr->id);
 
+       get_online_cpus();
+       /*
+        * The cpu might become online again at this point. So we check whether
+        * the cpu has been onlined or not. If the cpu became online, it means
+        * that someone wants to use the cpu. So acpi_processor_handle_eject()
+        * returns -EAGAIN.
+        */
+       if (unlikely(cpu_online(pr->id))) {
+               put_online_cpus();
+               pr_warn("Failed to remove CPU %d, because other task "
+                       "brought the CPU back online\n", pr->id);
+               return -EAGAIN;
+       }
        arch_unregister_cpu(pr->id);
        acpi_unmap_lsapic(pr->id);
+       put_online_cpus();
        return (0);
 }
 #else
index 1fcb8678665c0e89113da39e0f603db2d49eeccb..19d3d4a1274aec4abe8d7094234113d0eb830213 100644 (file)
@@ -97,6 +97,7 @@ void acpi_bus_hot_remove_device(void *context)
        struct acpi_eject_event *ej_event = (struct acpi_eject_event *) context;
        struct acpi_device *device;
        acpi_handle handle = ej_event->handle;
+       acpi_handle temp;
        struct acpi_object_list arg_list;
        union acpi_object arg;
        acpi_status status = AE_OK;
@@ -117,13 +118,16 @@ void acpi_bus_hot_remove_device(void *context)
                goto err_out;
        }
 
+       /* device has been freed */
+       device = NULL;
+
        /* power off device */
        status = acpi_evaluate_object(handle, "_PS3", NULL, NULL);
        if (ACPI_FAILURE(status) && status != AE_NOT_FOUND)
                printk(KERN_WARNING PREFIX
                                "Power-off device failed\n");
 
-       if (device->flags.lockable) {
+       if (ACPI_SUCCESS(acpi_get_handle(handle, "_LCK", &temp))) {
                arg_list.count = 1;
                arg_list.pointer = &arg;
                arg.type = ACPI_TYPE_INTEGER;
@@ -1013,11 +1017,6 @@ static int acpi_bus_get_flags(struct acpi_device *device)
                        device->flags.ejectable = 1;
        }
 
-       /* Presence of _LCK indicates 'lockable' */
-       status = acpi_get_handle(device->handle, "_LCK", &temp);
-       if (ACPI_SUCCESS(status))
-               device->flags.lockable = 1;
-
        /* Power resources cannot be power manageable. */
        if (device->device_type == ACPI_BUS_TYPE_POWER)
                return 0;
index fdcdbb652915a32340d91a7d6e6fcce15c3ee602..924e8412ee5f74e9b1cbdb7aae17c89d66ca2dc4 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/acpi.h>
 #include <linux/module.h>
 #include <linux/pm_runtime.h>
+#include <linux/pm_qos.h>
 
 #include <asm/io.h>
 
@@ -97,6 +98,21 @@ void __init acpi_nvs_nosave(void)
        nvs_nosave = true;
 }
 
+/*
+ * The ACPI specification wants us to save NVS memory regions during hibernation
+ * but says nothing about saving NVS during S3.  Not all versions of Windows
+ * save NVS on S3 suspend either, and it is clear that not all systems need
+ * NVS to be saved at S3 time.  To improve suspend/resume time, allow the
+ * user to disable saving NVS on S3 if their system does not require it, but
+ * continue to save/restore NVS for S4 as specified.
+ */
+static bool nvs_nosave_s3;
+
+void __init acpi_nvs_nosave_s3(void)
+{
+       nvs_nosave_s3 = true;
+}
+
 /*
  * ACPI 1.0 wants us to execute _PTS before suspending devices, so we allow the
  * user to request that behavior by using the 'acpi_old_suspend_ordering'
@@ -243,7 +259,7 @@ static int acpi_suspend_begin(suspend_state_t pm_state)
        u32 acpi_state = acpi_suspend_states[pm_state];
        int error = 0;
 
-       error = nvs_nosave ? 0 : suspend_nvs_alloc();
+       error = (nvs_nosave || nvs_nosave_s3) ? 0 : suspend_nvs_alloc();
        if (error)
                return error;
 
@@ -683,34 +699,28 @@ int acpi_suspend(u32 acpi_state)
 
 #ifdef CONFIG_PM
 /**
- *     acpi_pm_device_sleep_state - return preferred power state of ACPI device
- *             in the system sleep state given by %acpi_target_sleep_state
- *     @dev: device to examine; its driver model wakeup flags control
- *             whether it should be able to wake up the system
- *     @d_min_p: used to store the upper limit of allowed states range
- *     @d_max_in: specify the lowest allowed states
- *     Return value: preferred power state of the device on success, -ENODEV
- *     (ie. if there's no 'struct acpi_device' for @dev) or -EINVAL on failure
+ * acpi_pm_device_sleep_state - Get preferred power state of ACPI device.
+ * @dev: Device whose preferred target power state to return.
+ * @d_min_p: Location to store the upper limit of the allowed states range.
+ * @d_max_in: Deepest low-power state to take into consideration.
+ * Return value: Preferred power state of the device on success, -ENODEV
+ * (if there's no 'struct acpi_device' for @dev) or -EINVAL on failure
  *
- *     Find the lowest power (highest number) ACPI device power state that
- *     device @dev can be in while the system is in the sleep state represented
- *     by %acpi_target_sleep_state.  If @wake is nonzero, the device should be
- *     able to wake up the system from this sleep state.  If @d_min_p is set,
- *     the highest power (lowest number) device power state of @dev allowed
- *     in this system sleep state is stored at the location pointed to by it.
+ * Find the lowest power (highest number) ACPI device power state that the
+ * device can be in while the system is in the sleep state represented
+ * by %acpi_target_sleep_state.  If @d_min_p is set, the highest power (lowest
+ * number) device power state that @dev can be in for the given system sleep
+ * state is stored at the location pointed to by it.
  *
- *     The caller must ensure that @dev is valid before using this function.
- *     The caller is also responsible for figuring out if the device is
- *     supposed to be able to wake up the system and passing this information
- *     via @wake.
+ * The caller must ensure that @dev is valid before using this function.
  */
-
 int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p, int d_max_in)
 {
        acpi_handle handle = DEVICE_ACPI_HANDLE(dev);
        struct acpi_device *adev;
        char acpi_method[] = "_SxD";
        unsigned long long d_min, d_max;
+       bool wakeup = false;
 
        if (d_max_in < ACPI_STATE_D0 || d_max_in > ACPI_STATE_D3)
                return -EINVAL;
@@ -718,6 +728,13 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p, int d_max_in)
                printk(KERN_DEBUG "ACPI handle has no context!\n");
                return -ENODEV;
        }
+       if (d_max_in > ACPI_STATE_D3_HOT) {
+               enum pm_qos_flags_status stat;
+
+               stat = dev_pm_qos_flags(dev, PM_QOS_FLAG_NO_POWER_OFF);
+               if (stat == PM_QOS_FLAGS_ALL)
+                       d_max_in = ACPI_STATE_D3_HOT;
+       }
 
        acpi_method[2] = '0' + acpi_target_sleep_state;
        /*
@@ -737,8 +754,14 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p, int d_max_in)
         * NOTE: We rely on acpi_evaluate_integer() not clobbering the integer
         * provided -- that's our fault recovery, we ignore retval.
         */
-       if (acpi_target_sleep_state > ACPI_STATE_S0)
+       if (acpi_target_sleep_state > ACPI_STATE_S0) {
                acpi_evaluate_integer(handle, acpi_method, NULL, &d_min);
+               wakeup = device_may_wakeup(dev) && adev->wakeup.flags.valid
+                       && adev->wakeup.sleep_state >= acpi_target_sleep_state;
+       } else if (dev_pm_qos_flags(dev, PM_QOS_FLAG_REMOTE_WAKEUP) !=
+                       PM_QOS_FLAGS_NONE) {
+               wakeup = adev->wakeup.flags.valid;
+       }
 
        /*
         * If _PRW says we can wake up the system from the target sleep state,
@@ -747,9 +770,7 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p, int d_max_in)
         * (ACPI 3.x), it should return the maximum (lowest power) D-state that
         * can wake the system.  _S0W may be valid, too.
         */
-       if (acpi_target_sleep_state == ACPI_STATE_S0 ||
-           (device_may_wakeup(dev) && adev->wakeup.flags.valid &&
-            adev->wakeup.sleep_state >= acpi_target_sleep_state)) {
+       if (wakeup) {
                acpi_status status;
 
                acpi_method[3] = 'W';
@@ -784,14 +805,15 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p, int d_max_in)
 EXPORT_SYMBOL(acpi_pm_device_sleep_state);
 #endif /* CONFIG_PM */
 
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_PM_RUNTIME
 /**
- * acpi_pm_device_run_wake - Enable/disable wake-up for given device.
- * @phys_dev: Device to enable/disable the platform to wake-up the system for.
- * @enable: Whether enable or disable the wake-up functionality.
+ * acpi_pm_device_run_wake - Enable/disable remote wakeup for given device.
+ * @phys_dev: Device to enable/disable the platform to wake up.
+ * @enable: Whether to enable or disable the wakeup functionality.
  *
- * Find the ACPI device object corresponding to @pci_dev and try to
- * enable/disable the GPE associated with it.
+ * Find the ACPI device object corresponding to @phys_dev and try to
+ * enable/disable the GPE associated with it, so that it can generate
+ * wakeup signals for the device in response to external (remote) events.
  */
 int acpi_pm_device_run_wake(struct device *phys_dev, bool enable)
 {
@@ -819,12 +841,13 @@ int acpi_pm_device_run_wake(struct device *phys_dev, bool enable)
        return 0;
 }
 EXPORT_SYMBOL(acpi_pm_device_run_wake);
+#endif /* CONFIG_PM_RUNTIME */
 
+#ifdef CONFIG_PM_SLEEP
 /**
- *     acpi_pm_device_sleep_wake - enable or disable the system wake-up
- *                                  capability of given device
- *     @dev: device to handle
- *     @enable: 'true' - enable, 'false' - disable the wake-up capability
+ * acpi_pm_device_sleep_wake - Enable or disable device to wake up the system.
+ * @dev: Device to enable/desible to wake up the system from sleep states.
+ * @enable: Whether to enable or disable @dev to wake up the system.
  */
 int acpi_pm_device_sleep_wake(struct device *dev, bool enable)
 {
index 804204d41999d0af951086f25b37a2f7ee783a90..1794468223c4c0d52847fbdb917246cb1c5e6f09 100644 (file)
@@ -900,14 +900,14 @@ static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz)
        if (tz->trips.passive.flags.valid)
                tz->thermal_zone =
                        thermal_zone_device_register("acpitz", trips, 0, tz,
-                                                    &acpi_thermal_zone_ops,
+                                               &acpi_thermal_zone_ops, NULL,
                                                     tz->trips.passive.tsp*100,
                                                     tz->polling_frequency*100);
        else
                tz->thermal_zone =
                        thermal_zone_device_register("acpitz", trips, 0, tz,
-                                                    &acpi_thermal_zone_ops, 0,
-                                                    tz->polling_frequency*100);
+                                               &acpi_thermal_zone_ops, NULL,
+                                               0, tz->polling_frequency*100);
        if (IS_ERR(tz->thermal_zone))
                return -ENODEV;
 
index f94d4c818fc74dc9a076e8f67fe98d7bc6620a61..0230cb6cbb3a18eda2fd323763d6594205c0ed7f 100644 (file)
@@ -1345,12 +1345,15 @@ static int
 acpi_video_bus_get_devices(struct acpi_video_bus *video,
                           struct acpi_device *device)
 {
-       int status;
+       int status = 0;
        struct acpi_device *dev;
 
-       status = acpi_video_device_enumerate(video);
-       if (status)
-               return status;
+       /*
+        * There are systems where video module known to work fine regardless
+        * of broken _DOD and ignoring returned value here doesn't cause
+        * any issues later.
+        */
+       acpi_video_device_enumerate(video);
 
        list_for_each_entry(dev, &device->children, node) {
 
index 0b6f0b28a4872b2aa32fe6f1e656ff1ae4ca213d..bd5de08ad6fd7a40ad30baaf7fcf1d8b7203d4b3 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
+#include <linux/tegra-ahb.h>
 
 #define DRV_NAME "tegra-ahb"
 
index 08b4c520938463fd989bba879d791a3e418efd39..b34b5cda5ae110aeec980b6ec7c2ec608490a093 100644 (file)
@@ -236,7 +236,7 @@ config CMA_SIZE_PERCENTAGE
 
 choice
        prompt "Selected region size"
-       default CMA_SIZE_SEL_ABSOLUTE
+       default CMA_SIZE_SEL_MBYTES
 
 config CMA_SIZE_SEL_MBYTES
        bool "Use mega bytes value only"
index abea76c36a4b96a10201bb4eeef5c0650e6644ae..150a41580fad7bfded3ba9770f742df98c87315c 100644 (file)
@@ -1180,7 +1180,6 @@ void device_del(struct device *dev)
        if (dev->bus)
                blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
                                             BUS_NOTIFY_DEL_DEVICE, dev);
-       device_pm_remove(dev);
        dpm_sysfs_remove(dev);
        if (parent)
                klist_del(&dev->p->knode_parent);
@@ -1205,6 +1204,7 @@ void device_del(struct device *dev)
        device_remove_file(dev, &uevent_attr);
        device_remove_attrs(dev);
        bus_remove_device(dev);
+       device_pm_remove(dev);
        driver_deferred_probe_del(dev);
 
        /* Notify the platform of the removal, in case they
index 460e22dee36dbb2389524f7287eb103b936e2c58..a3f79c495a411ea85b87604ab473fcef6b962558 100644 (file)
@@ -298,6 +298,8 @@ void dma_buf_unmap_attachment(struct dma_buf_attachment *attach,
                                struct sg_table *sg_table,
                                enum dma_data_direction direction)
 {
+       might_sleep();
+
        if (WARN_ON(!attach || !attach->dmabuf || !sg_table))
                return;
 
index 560a7173f810015a9532d25395a8ad1a57366e6c..bc256b64102710039e208ec82c513e97b223a290 100644 (file)
@@ -191,9 +191,8 @@ EXPORT_SYMBOL(dma_release_from_coherent);
  * This checks whether the memory was allocated from the per-device
  * coherent memory pool and if so, maps that memory to the provided vma.
  *
- * Returns 1 if we correctly mapped the memory, or 0 if
- * dma_release_coherent() should proceed with mapping memory from
- * generic pools.
+ * Returns 1 if we correctly mapped the memory, or 0 if the caller should
+ * proceed with mapping memory from generic pools.
  */
 int dma_mmap_from_coherent(struct device *dev, struct vm_area_struct *vma,
                           void *vaddr, size_t size, int *ret)
index 9a1469474f55addaea1ae5be1f4499187297db06..612afcc5a938f45549ed877ebd6c8ac697315fe3 100644 (file)
 #include <linux/mm.h>
 #include <linux/mutex.h>
 #include <linux/page-isolation.h>
+#include <linux/sizes.h>
 #include <linux/slab.h>
 #include <linux/swap.h>
 #include <linux/mm_types.h>
 #include <linux/dma-contiguous.h>
 
-#ifndef SZ_1M
-#define SZ_1M (1 << 20)
-#endif
-
 struct cma {
        unsigned long   base_pfn;
        unsigned long   count;
index 81541452887bd3ce5d868909e3fb753fb3d6b124..8945f4e489ed70a03cb272f57064a69330409a60 100644 (file)
@@ -36,68 +36,6 @@ MODULE_AUTHOR("Manuel Estrada Sainz");
 MODULE_DESCRIPTION("Multi purpose firmware loading support");
 MODULE_LICENSE("GPL");
 
-static const char *fw_path[] = {
-       "/lib/firmware/updates/" UTS_RELEASE,
-       "/lib/firmware/updates",
-       "/lib/firmware/" UTS_RELEASE,
-       "/lib/firmware"
-};
-
-/* Don't inline this: 'struct kstat' is biggish */
-static noinline long fw_file_size(struct file *file)
-{
-       struct kstat st;
-       if (vfs_getattr(file->f_path.mnt, file->f_path.dentry, &st))
-               return -1;
-       if (!S_ISREG(st.mode))
-               return -1;
-       if (st.size != (long)st.size)
-               return -1;
-       return st.size;
-}
-
-static bool fw_read_file_contents(struct file *file, struct firmware *fw)
-{
-       long size;
-       char *buf;
-
-       size = fw_file_size(file);
-       if (size < 0)
-               return false;
-       buf = vmalloc(size);
-       if (!buf)
-               return false;
-       if (kernel_read(file, 0, buf, size) != size) {
-               vfree(buf);
-               return false;
-       }
-       fw->data = buf;
-       fw->size = size;
-       return true;
-}
-
-static bool fw_get_filesystem_firmware(struct firmware *fw, const char *name)
-{
-       int i;
-       bool success = false;
-       char *path = __getname();
-
-       for (i = 0; i < ARRAY_SIZE(fw_path); i++) {
-               struct file *file;
-               snprintf(path, PATH_MAX, "%s/%s", fw_path[i], name);
-
-               file = filp_open(path, O_RDONLY, 0);
-               if (IS_ERR(file))
-                       continue;
-               success = fw_read_file_contents(file, fw);
-               fput(file);
-               if (success)
-                       break;
-       }
-       __putname(path);
-       return success;
-}
-
 /* Builtin firmware support */
 
 #ifdef CONFIG_FW_LOADER
@@ -150,6 +88,11 @@ enum {
        FW_STATUS_ABORT,
 };
 
+enum fw_buf_fmt {
+       VMALLOC_BUF,    /* used in direct loading */
+       PAGE_BUF,       /* used in loading via userspace */
+};
+
 static int loading_timeout = 60;       /* In seconds */
 
 static inline long firmware_loading_timeout(void)
@@ -173,8 +116,6 @@ struct firmware_cache {
        spinlock_t name_lock;
        struct list_head fw_names;
 
-       wait_queue_head_t wait_queue;
-       int cnt;
        struct delayed_work work;
 
        struct notifier_block   pm_notify;
@@ -187,6 +128,7 @@ struct firmware_buf {
        struct completion completion;
        struct firmware_cache *fwc;
        unsigned long status;
+       enum fw_buf_fmt fmt;
        void *data;
        size_t size;
        struct page **pages;
@@ -240,6 +182,7 @@ static struct firmware_buf *__allocate_fw_buf(const char *fw_name,
        strcpy(buf->fw_id, fw_name);
        buf->fwc = fwc;
        init_completion(&buf->completion);
+       buf->fmt = VMALLOC_BUF;
 
        pr_debug("%s: fw-%s buf=%p\n", __func__, fw_name, buf);
 
@@ -307,10 +250,14 @@ static void __fw_free_buf(struct kref *ref)
        list_del(&buf->list);
        spin_unlock(&fwc->lock);
 
-       vunmap(buf->data);
-       for (i = 0; i < buf->nr_pages; i++)
-               __free_page(buf->pages[i]);
-       kfree(buf->pages);
+
+       if (buf->fmt == PAGE_BUF) {
+               vunmap(buf->data);
+               for (i = 0; i < buf->nr_pages; i++)
+                       __free_page(buf->pages[i]);
+               kfree(buf->pages);
+       } else
+               vfree(buf->data);
        kfree(buf);
 }
 
@@ -319,6 +266,69 @@ static void fw_free_buf(struct firmware_buf *buf)
        kref_put(&buf->ref, __fw_free_buf);
 }
 
+/* direct firmware loading support */
+static const char *fw_path[] = {
+       "/lib/firmware/updates/" UTS_RELEASE,
+       "/lib/firmware/updates",
+       "/lib/firmware/" UTS_RELEASE,
+       "/lib/firmware"
+};
+
+/* Don't inline this: 'struct kstat' is biggish */
+static noinline long fw_file_size(struct file *file)
+{
+       struct kstat st;
+       if (vfs_getattr(file->f_path.mnt, file->f_path.dentry, &st))
+               return -1;
+       if (!S_ISREG(st.mode))
+               return -1;
+       if (st.size != (long)st.size)
+               return -1;
+       return st.size;
+}
+
+static bool fw_read_file_contents(struct file *file, struct firmware_buf *fw_buf)
+{
+       long size;
+       char *buf;
+
+       size = fw_file_size(file);
+       if (size < 0)
+               return false;
+       buf = vmalloc(size);
+       if (!buf)
+               return false;
+       if (kernel_read(file, 0, buf, size) != size) {
+               vfree(buf);
+               return false;
+       }
+       fw_buf->data = buf;
+       fw_buf->size = size;
+       return true;
+}
+
+static bool fw_get_filesystem_firmware(struct firmware_buf *buf)
+{
+       int i;
+       bool success = false;
+       char *path = __getname();
+
+       for (i = 0; i < ARRAY_SIZE(fw_path); i++) {
+               struct file *file;
+               snprintf(path, PATH_MAX, "%s/%s", fw_path[i], buf->fw_id);
+
+               file = filp_open(path, O_RDONLY, 0);
+               if (IS_ERR(file))
+                       continue;
+               success = fw_read_file_contents(file, buf);
+               fput(file);
+               if (success)
+                       break;
+       }
+       __putname(path);
+       return success;
+}
+
 static struct firmware_priv *to_firmware_priv(struct device *dev)
 {
        return container_of(dev, struct firmware_priv, dev);
@@ -423,6 +433,21 @@ static void firmware_free_data(const struct firmware *fw)
 #ifndef PAGE_KERNEL_RO
 #define PAGE_KERNEL_RO PAGE_KERNEL
 #endif
+
+/* one pages buffer should be mapped/unmapped only once */
+static int fw_map_pages_buf(struct firmware_buf *buf)
+{
+       if (buf->fmt != PAGE_BUF)
+               return 0;
+
+       if (buf->data)
+               vunmap(buf->data);
+       buf->data = vmap(buf->pages, buf->nr_pages, 0, PAGE_KERNEL_RO);
+       if (!buf->data)
+               return -ENOMEM;
+       return 0;
+}
+
 /**
  * firmware_loading_store - set value in the 'loading' control file
  * @dev: device pointer
@@ -467,6 +492,14 @@ static ssize_t firmware_loading_store(struct device *dev,
                if (test_bit(FW_STATUS_LOADING, &fw_buf->status)) {
                        set_bit(FW_STATUS_DONE, &fw_buf->status);
                        clear_bit(FW_STATUS_LOADING, &fw_buf->status);
+
+                       /*
+                        * Several loading requests may be pending on
+                        * one same firmware buf, so let all requests
+                        * see the mapped 'buf->data' once the loading
+                        * is completed.
+                        * */
+                       fw_map_pages_buf(fw_buf);
                        complete_all(&fw_buf->completion);
                        break;
                }
@@ -670,15 +703,6 @@ exit:
        return fw_priv;
 }
 
-/* one pages buffer is mapped/unmapped only once */
-static int fw_map_pages_buf(struct firmware_buf *buf)
-{
-       buf->data = vmap(buf->pages, buf->nr_pages, 0, PAGE_KERNEL_RO);
-       if (!buf->data)
-               return -ENOMEM;
-       return 0;
-}
-
 /* store the pages buffer info firmware from buf */
 static void fw_set_page_data(struct firmware_buf *buf, struct firmware *fw)
 {
@@ -778,11 +802,6 @@ _request_firmware_prepare(const struct firmware **firmware_p, const char *name,
                return NULL;
        }
 
-       if (fw_get_filesystem_firmware(firmware, name)) {
-               dev_dbg(device, "firmware: direct-loading firmware %s\n", name);
-               return NULL;
-       }
-
        ret = fw_lookup_and_allocate_buf(name, &fw_cache, &buf);
        if (!ret)
                fw_priv = fw_create_instance(firmware, name, device,
@@ -832,6 +851,21 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent,
        struct device *f_dev = &fw_priv->dev;
        struct firmware_buf *buf = fw_priv->buf;
        struct firmware_cache *fwc = &fw_cache;
+       int direct_load = 0;
+
+       /* try direct loading from fs first */
+       if (fw_get_filesystem_firmware(buf)) {
+               dev_dbg(f_dev->parent, "firmware: direct-loading"
+                       " firmware %s\n", buf->fw_id);
+
+               set_bit(FW_STATUS_DONE, &buf->status);
+               complete_all(&buf->completion);
+               direct_load = 1;
+               goto handle_fw;
+       }
+
+       /* fall back on userspace loading */
+       buf->fmt = PAGE_BUF;
 
        dev_set_uevent_suppress(f_dev, true);
 
@@ -870,6 +904,7 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent,
 
        del_timer_sync(&fw_priv->timeout);
 
+handle_fw:
        mutex_lock(&fw_lock);
        if (!buf->size || test_bit(FW_STATUS_ABORT, &buf->status))
                retval = -ENOENT;
@@ -884,9 +919,6 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent,
        if (!retval && f_dev->parent)
                fw_add_devm_name(f_dev->parent, buf->fw_id);
 
-       if (!retval)
-               retval = fw_map_pages_buf(buf);
-
        /*
         * After caching firmware image is started, let it piggyback
         * on request firmware.
@@ -902,6 +934,9 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent,
        fw_priv->buf = NULL;
        mutex_unlock(&fw_lock);
 
+       if (direct_load)
+               goto err_put_dev;
+
        device_remove_file(f_dev, &dev_attr_loading);
 err_del_bin_attr:
        device_remove_bin_file(f_dev, &firmware_attr_data);
@@ -1129,6 +1164,8 @@ int uncache_firmware(const char *fw_name)
 }
 
 #ifdef CONFIG_PM_SLEEP
+static ASYNC_DOMAIN_EXCLUSIVE(fw_cache_domain);
+
 static struct fw_cache_entry *alloc_fw_cache_entry(const char *name)
 {
        struct fw_cache_entry *fce;
@@ -1142,17 +1179,27 @@ exit:
        return fce;
 }
 
-static int fw_cache_piggyback_on_request(const char *name)
+static int __fw_entry_found(const char *name)
 {
        struct firmware_cache *fwc = &fw_cache;
        struct fw_cache_entry *fce;
-       int ret = 0;
 
-       spin_lock(&fwc->name_lock);
        list_for_each_entry(fce, &fwc->fw_names, list) {
                if (!strcmp(fce->name, name))
-                       goto found;
+                       return 1;
        }
+       return 0;
+}
+
+static int fw_cache_piggyback_on_request(const char *name)
+{
+       struct firmware_cache *fwc = &fw_cache;
+       struct fw_cache_entry *fce;
+       int ret = 0;
+
+       spin_lock(&fwc->name_lock);
+       if (__fw_entry_found(name))
+               goto found;
 
        fce = alloc_fw_cache_entry(name);
        if (fce) {
@@ -1185,12 +1232,6 @@ static void __async_dev_cache_fw_image(void *fw_entry,
 
                free_fw_cache_entry(fce);
        }
-
-       spin_lock(&fwc->name_lock);
-       fwc->cnt--;
-       spin_unlock(&fwc->name_lock);
-
-       wake_up(&fwc->wait_queue);
 }
 
 /* called with dev->devres_lock held */
@@ -1229,11 +1270,19 @@ static void dev_cache_fw_image(struct device *dev, void *data)
                list_del(&fce->list);
 
                spin_lock(&fwc->name_lock);
-               fwc->cnt++;
-               list_add(&fce->list, &fwc->fw_names);
+               /* only one cache entry for one firmware */
+               if (!__fw_entry_found(fce->name)) {
+                       list_add(&fce->list, &fwc->fw_names);
+               } else {
+                       free_fw_cache_entry(fce);
+                       fce = NULL;
+               }
                spin_unlock(&fwc->name_lock);
 
-               async_schedule(__async_dev_cache_fw_image, (void *)fce);
+               if (fce)
+                       async_schedule_domain(__async_dev_cache_fw_image,
+                                             (void *)fce,
+                                             &fw_cache_domain);
        }
 }
 
@@ -1275,6 +1324,9 @@ static void device_cache_fw_images(void)
 
        pr_debug("%s\n", __func__);
 
+       /* cancel uncache work */
+       cancel_delayed_work_sync(&fwc->work);
+
        /*
         * use small loading timeout for caching devices' firmware
         * because all these firmware images have been loaded
@@ -1292,21 +1344,7 @@ static void device_cache_fw_images(void)
        mutex_unlock(&fw_lock);
 
        /* wait for completion of caching firmware for all devices */
-       spin_lock(&fwc->name_lock);
-       for (;;) {
-               prepare_to_wait(&fwc->wait_queue, &wait,
-                               TASK_UNINTERRUPTIBLE);
-               if (!fwc->cnt)
-                       break;
-
-               spin_unlock(&fwc->name_lock);
-
-               schedule();
-
-               spin_lock(&fwc->name_lock);
-       }
-       spin_unlock(&fwc->name_lock);
-       finish_wait(&fwc->wait_queue, &wait);
+       async_synchronize_full_domain(&fw_cache_domain);
 
        loading_timeout = old_timeout;
 }
@@ -1394,9 +1432,7 @@ static void __init fw_cache_init(void)
 #ifdef CONFIG_PM_SLEEP
        spin_lock_init(&fw_cache.name_lock);
        INIT_LIST_HEAD(&fw_cache.fw_names);
-       fw_cache.cnt = 0;
 
-       init_waitqueue_head(&fw_cache.wait_queue);
        INIT_DELAYED_WORK(&fw_cache.work,
                          device_uncache_fw_images_work);
 
index af1a177216f12573c7e481fea0a568c09b97ef12..ef5115708dc761a1f63e9cfaae59abefefd58f9d 100644 (file)
@@ -169,7 +169,7 @@ static ssize_t node_read_numastat(struct device *dev,
                       node_page_state(dev->id, NUMA_HIT),
                       node_page_state(dev->id, NUMA_MISS),
                       node_page_state(dev->id, NUMA_FOREIGN),
-                      node_page_state(dev->id, NUMA_INTERLEAVE_HIT),
+                      0UL,
                       node_page_state(dev->id, NUMA_LOCAL),
                       node_page_state(dev->id, NUMA_OTHER));
 }
index eb78e9640c4a86c0df9c0464e7dbd0b37f4ab75d..9d8fde709390e853909ba52aec823167882da2ae 100644 (file)
@@ -99,7 +99,7 @@ static void __pm_clk_remove(struct pm_clock_entry *ce)
 
        if (ce->status < PCE_STATUS_ERROR) {
                if (ce->status == PCE_STATUS_ENABLED)
-                       clk_disable(ce->clk);
+                       clk_disable_unprepare(ce->clk);
 
                if (ce->status >= PCE_STATUS_ACQUIRED)
                        clk_put(ce->clk);
@@ -396,7 +396,7 @@ static void enable_clock(struct device *dev, const char *con_id)
 
        clk = clk_get(dev, con_id);
        if (!IS_ERR(clk)) {
-               clk_enable(clk);
+               clk_prepare_enable(clk);
                clk_put(clk);
                dev_info(dev, "Runtime PM disabled, clock forced on.\n");
        }
@@ -413,7 +413,7 @@ static void disable_clock(struct device *dev, const char *con_id)
 
        clk = clk_get(dev, con_id);
        if (!IS_ERR(clk)) {
-               clk_disable(clk);
+               clk_disable_unprepare(clk);
                clk_put(clk);
                dev_info(dev, "Runtime PM disabled, clock forced off.\n");
        }
index c22b869245d9498e7052fdc42ceacf3aaa4e332e..acc3a8ded29d0e45d704f6f3ecef261e70e6a5c2 100644 (file)
@@ -470,10 +470,19 @@ static int pm_genpd_poweroff(struct generic_pm_domain *genpd)
                return -EBUSY;
 
        not_suspended = 0;
-       list_for_each_entry(pdd, &genpd->dev_list, list_node)
+       list_for_each_entry(pdd, &genpd->dev_list, list_node) {
+               enum pm_qos_flags_status stat;
+
+               stat = dev_pm_qos_flags(pdd->dev,
+                                       PM_QOS_FLAG_NO_POWER_OFF
+                                               | PM_QOS_FLAG_REMOTE_WAKEUP);
+               if (stat > PM_QOS_FLAGS_NONE)
+                       return -EBUSY;
+
                if (pdd->dev->driver && (!pm_runtime_suspended(pdd->dev)
                    || pdd->dev->power.irq_safe))
                        not_suspended++;
+       }
 
        if (not_suspended > genpd->in_progress)
                return -EBUSY;
@@ -1862,7 +1871,7 @@ int pm_genpd_attach_cpuidle(struct generic_pm_domain *genpd, int state)
        cpuidle_drv = cpuidle_driver_ref();
        if (!cpuidle_drv) {
                ret = -ENODEV;
-               goto out;
+               goto err_drv;
        }
        if (cpuidle_drv->state_count <= state) {
                ret = -EINVAL;
@@ -1884,6 +1893,9 @@ int pm_genpd_attach_cpuidle(struct generic_pm_domain *genpd, int state)
 
  err:
        cpuidle_driver_unref();
+
+ err_drv:
+       kfree(cpu_data);
        goto out;
 }
 
index d9468642fc414c22f8578c82e57e2cac9ba224e5..c8a908b099c0e1074e7a0342271a353c934d8d94 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/rcupdate.h>
 #include <linux/opp.h>
 #include <linux/of.h>
+#include <linux/export.h>
 
 /*
  * Internal data structure organization with the OPP layer library is as
@@ -65,6 +66,7 @@ struct opp {
        unsigned long u_volt;
 
        struct device_opp *dev_opp;
+       struct rcu_head head;
 };
 
 /**
@@ -160,6 +162,7 @@ unsigned long opp_get_voltage(struct opp *opp)
 
        return v;
 }
+EXPORT_SYMBOL(opp_get_voltage);
 
 /**
  * opp_get_freq() - Gets the frequency corresponding to an available opp
@@ -189,6 +192,7 @@ unsigned long opp_get_freq(struct opp *opp)
 
        return f;
 }
+EXPORT_SYMBOL(opp_get_freq);
 
 /**
  * opp_get_opp_count() - Get number of opps available in the opp list
@@ -221,6 +225,7 @@ int opp_get_opp_count(struct device *dev)
 
        return count;
 }
+EXPORT_SYMBOL(opp_get_opp_count);
 
 /**
  * opp_find_freq_exact() - search for an exact frequency
@@ -230,7 +235,10 @@ int opp_get_opp_count(struct device *dev)
  *
  * Searches for exact match in the opp list and returns pointer to the matching
  * opp if found, else returns ERR_PTR in case of error and should be handled
- * using IS_ERR.
+ * using IS_ERR. Error return values can be:
+ * EINVAL:     for bad pointer
+ * ERANGE:     no match found for search
+ * ENODEV:     if device not found in list of registered devices
  *
  * Note: available is a modifier for the search. if available=true, then the
  * match is for exact matching frequency and is available in the stored OPP
@@ -249,7 +257,7 @@ struct opp *opp_find_freq_exact(struct device *dev, unsigned long freq,
                                bool available)
 {
        struct device_opp *dev_opp;
-       struct opp *temp_opp, *opp = ERR_PTR(-ENODEV);
+       struct opp *temp_opp, *opp = ERR_PTR(-ERANGE);
 
        dev_opp = find_device_opp(dev);
        if (IS_ERR(dev_opp)) {
@@ -268,6 +276,7 @@ struct opp *opp_find_freq_exact(struct device *dev, unsigned long freq,
 
        return opp;
 }
+EXPORT_SYMBOL(opp_find_freq_exact);
 
 /**
  * opp_find_freq_ceil() - Search for an rounded ceil freq
@@ -278,7 +287,11 @@ struct opp *opp_find_freq_exact(struct device *dev, unsigned long freq,
  * for a device.
  *
  * Returns matching *opp and refreshes *freq accordingly, else returns
- * ERR_PTR in case of error and should be handled using IS_ERR.
+ * ERR_PTR in case of error and should be handled using IS_ERR. Error return
+ * values can be:
+ * EINVAL:     for bad pointer
+ * ERANGE:     no match found for search
+ * ENODEV:     if device not found in list of registered devices
  *
  * Locking: This function must be called under rcu_read_lock(). opp is a rcu
  * protected pointer. The reason for the same is that the opp pointer which is
@@ -289,7 +302,7 @@ struct opp *opp_find_freq_exact(struct device *dev, unsigned long freq,
 struct opp *opp_find_freq_ceil(struct device *dev, unsigned long *freq)
 {
        struct device_opp *dev_opp;
-       struct opp *temp_opp, *opp = ERR_PTR(-ENODEV);
+       struct opp *temp_opp, *opp = ERR_PTR(-ERANGE);
 
        if (!dev || !freq) {
                dev_err(dev, "%s: Invalid argument freq=%p\n", __func__, freq);
@@ -298,7 +311,7 @@ struct opp *opp_find_freq_ceil(struct device *dev, unsigned long *freq)
 
        dev_opp = find_device_opp(dev);
        if (IS_ERR(dev_opp))
-               return opp;
+               return ERR_CAST(dev_opp);
 
        list_for_each_entry_rcu(temp_opp, &dev_opp->opp_list, node) {
                if (temp_opp->available && temp_opp->rate >= *freq) {
@@ -310,6 +323,7 @@ struct opp *opp_find_freq_ceil(struct device *dev, unsigned long *freq)
 
        return opp;
 }
+EXPORT_SYMBOL(opp_find_freq_ceil);
 
 /**
  * opp_find_freq_floor() - Search for a rounded floor freq
@@ -320,7 +334,11 @@ struct opp *opp_find_freq_ceil(struct device *dev, unsigned long *freq)
  * for a device.
  *
  * Returns matching *opp and refreshes *freq accordingly, else returns
- * ERR_PTR in case of error and should be handled using IS_ERR.
+ * ERR_PTR in case of error and should be handled using IS_ERR. Error return
+ * values can be:
+ * EINVAL:     for bad pointer
+ * ERANGE:     no match found for search
+ * ENODEV:     if device not found in list of registered devices
  *
  * Locking: This function must be called under rcu_read_lock(). opp is a rcu
  * protected pointer. The reason for the same is that the opp pointer which is
@@ -331,7 +349,7 @@ struct opp *opp_find_freq_ceil(struct device *dev, unsigned long *freq)
 struct opp *opp_find_freq_floor(struct device *dev, unsigned long *freq)
 {
        struct device_opp *dev_opp;
-       struct opp *temp_opp, *opp = ERR_PTR(-ENODEV);
+       struct opp *temp_opp, *opp = ERR_PTR(-ERANGE);
 
        if (!dev || !freq) {
                dev_err(dev, "%s: Invalid argument freq=%p\n", __func__, freq);
@@ -340,7 +358,7 @@ struct opp *opp_find_freq_floor(struct device *dev, unsigned long *freq)
 
        dev_opp = find_device_opp(dev);
        if (IS_ERR(dev_opp))
-               return opp;
+               return ERR_CAST(dev_opp);
 
        list_for_each_entry_rcu(temp_opp, &dev_opp->opp_list, node) {
                if (temp_opp->available) {
@@ -356,6 +374,7 @@ struct opp *opp_find_freq_floor(struct device *dev, unsigned long *freq)
 
        return opp;
 }
+EXPORT_SYMBOL(opp_find_freq_floor);
 
 /**
  * opp_add()  - Add an OPP table from a table definitions
@@ -441,6 +460,17 @@ int opp_add(struct device *dev, unsigned long freq, unsigned long u_volt)
        return 0;
 }
 
+/**
+ * opp_free_rcu() - helper to clear the struct opp when grace period has
+ * elapsed without blocking the the caller of opp_set_availability
+ */
+static void opp_free_rcu(struct rcu_head *head)
+{
+       struct opp *opp = container_of(head, struct opp, head);
+
+       kfree(opp);
+}
+
 /**
  * opp_set_availability() - helper to set the availability of an opp
  * @dev:               device for which we do this operation
@@ -512,7 +542,7 @@ static int opp_set_availability(struct device *dev, unsigned long freq,
 
        list_replace_rcu(&opp->node, &new_opp->node);
        mutex_unlock(&dev_opp_list_lock);
-       synchronize_rcu();
+       call_rcu(&opp->head, opp_free_rcu);
 
        /* Notify the change of the OPP availability */
        if (availability_req)
@@ -522,13 +552,10 @@ static int opp_set_availability(struct device *dev, unsigned long freq,
                srcu_notifier_call_chain(&dev_opp->head, OPP_EVENT_DISABLE,
                                         new_opp);
 
-       /* clean up old opp */
-       new_opp = opp;
-       goto out;
+       return 0;
 
 unlock:
        mutex_unlock(&dev_opp_list_lock);
-out:
        kfree(new_opp);
        return r;
 }
@@ -552,6 +579,7 @@ int opp_enable(struct device *dev, unsigned long freq)
 {
        return opp_set_availability(dev, freq, true);
 }
+EXPORT_SYMBOL(opp_enable);
 
 /**
  * opp_disable() - Disable a specific OPP
@@ -573,6 +601,7 @@ int opp_disable(struct device *dev, unsigned long freq)
 {
        return opp_set_availability(dev, freq, false);
 }
+EXPORT_SYMBOL(opp_disable);
 
 #ifdef CONFIG_CPU_FREQ
 /**
index 0dbfdf4419af8914136060f0b9c88838e4f2db4a..b16686a0a5a29b0d56a253c406a1e54b8b826228 100644 (file)
@@ -93,8 +93,10 @@ extern void dpm_sysfs_remove(struct device *dev);
 extern void rpm_sysfs_remove(struct device *dev);
 extern int wakeup_sysfs_add(struct device *dev);
 extern void wakeup_sysfs_remove(struct device *dev);
-extern int pm_qos_sysfs_add(struct device *dev);
-extern void pm_qos_sysfs_remove(struct device *dev);
+extern int pm_qos_sysfs_add_latency(struct device *dev);
+extern void pm_qos_sysfs_remove_latency(struct device *dev);
+extern int pm_qos_sysfs_add_flags(struct device *dev);
+extern void pm_qos_sysfs_remove_flags(struct device *dev);
 
 #else /* CONFIG_PM */
 
index 74a67e0019a2d246820ccb2858399bca193ff789..167834dcc82a3fed5fb74bfcd7674bbad04aa724 100644 (file)
@@ -40,6 +40,7 @@
 #include <linux/device.h>
 #include <linux/mutex.h>
 #include <linux/export.h>
+#include <linux/pm_runtime.h>
 
 #include "power.h"
 
@@ -47,6 +48,50 @@ static DEFINE_MUTEX(dev_pm_qos_mtx);
 
 static BLOCKING_NOTIFIER_HEAD(dev_pm_notifiers);
 
+/**
+ * __dev_pm_qos_flags - Check PM QoS flags for a given device.
+ * @dev: Device to check the PM QoS flags for.
+ * @mask: Flags to check against.
+ *
+ * This routine must be called with dev->power.lock held.
+ */
+enum pm_qos_flags_status __dev_pm_qos_flags(struct device *dev, s32 mask)
+{
+       struct dev_pm_qos *qos = dev->power.qos;
+       struct pm_qos_flags *pqf;
+       s32 val;
+
+       if (!qos)
+               return PM_QOS_FLAGS_UNDEFINED;
+
+       pqf = &qos->flags;
+       if (list_empty(&pqf->list))
+               return PM_QOS_FLAGS_UNDEFINED;
+
+       val = pqf->effective_flags & mask;
+       if (val)
+               return (val == mask) ? PM_QOS_FLAGS_ALL : PM_QOS_FLAGS_SOME;
+
+       return PM_QOS_FLAGS_NONE;
+}
+
+/**
+ * dev_pm_qos_flags - Check PM QoS flags for a given device (locked).
+ * @dev: Device to check the PM QoS flags for.
+ * @mask: Flags to check against.
+ */
+enum pm_qos_flags_status dev_pm_qos_flags(struct device *dev, s32 mask)
+{
+       unsigned long irqflags;
+       enum pm_qos_flags_status ret;
+
+       spin_lock_irqsave(&dev->power.lock, irqflags);
+       ret = __dev_pm_qos_flags(dev, mask);
+       spin_unlock_irqrestore(&dev->power.lock, irqflags);
+
+       return ret;
+}
+
 /**
  * __dev_pm_qos_read_value - Get PM QoS constraint for a given device.
  * @dev: Device to get the PM QoS constraint value for.
@@ -55,9 +100,7 @@ static BLOCKING_NOTIFIER_HEAD(dev_pm_notifiers);
  */
 s32 __dev_pm_qos_read_value(struct device *dev)
 {
-       struct pm_qos_constraints *c = dev->power.constraints;
-
-       return c ? pm_qos_read_value(c) : 0;
+       return dev->power.qos ? pm_qos_read_value(&dev->power.qos->latency) : 0;
 }
 
 /**
@@ -76,30 +119,39 @@ s32 dev_pm_qos_read_value(struct device *dev)
        return ret;
 }
 
-/*
- * apply_constraint
- * @req: constraint request to apply
- * @action: action to perform add/update/remove, of type enum pm_qos_req_action
- * @value: defines the qos request
+/**
+ * apply_constraint - Add/modify/remove device PM QoS request.
+ * @req: Constraint request to apply
+ * @action: Action to perform (add/update/remove).
+ * @value: Value to assign to the QoS request.
  *
  * Internal function to update the constraints list using the PM QoS core
  * code and if needed call the per-device and the global notification
  * callbacks
  */
 static int apply_constraint(struct dev_pm_qos_request *req,
-                           enum pm_qos_req_action action, int value)
+                           enum pm_qos_req_action action, s32 value)
 {
-       int ret, curr_value;
-
-       ret = pm_qos_update_target(req->dev->power.constraints,
-                                  &req->node, action, value);
+       struct dev_pm_qos *qos = req->dev->power.qos;
+       int ret;
 
-       if (ret) {
-               /* Call the global callbacks if needed */
-               curr_value = pm_qos_read_value(req->dev->power.constraints);
-               blocking_notifier_call_chain(&dev_pm_notifiers,
-                                            (unsigned long)curr_value,
-                                            req);
+       switch(req->type) {
+       case DEV_PM_QOS_LATENCY:
+               ret = pm_qos_update_target(&qos->latency, &req->data.pnode,
+                                          action, value);
+               if (ret) {
+                       value = pm_qos_read_value(&qos->latency);
+                       blocking_notifier_call_chain(&dev_pm_notifiers,
+                                                    (unsigned long)value,
+                                                    req);
+               }
+               break;
+       case DEV_PM_QOS_FLAGS:
+               ret = pm_qos_update_flags(&qos->flags, &req->data.flr,
+                                         action, value);
+               break;
+       default:
+               ret = -EINVAL;
        }
 
        return ret;
@@ -114,28 +166,32 @@ static int apply_constraint(struct dev_pm_qos_request *req,
  */
 static int dev_pm_qos_constraints_allocate(struct device *dev)
 {
+       struct dev_pm_qos *qos;
        struct pm_qos_constraints *c;
        struct blocking_notifier_head *n;
 
-       c = kzalloc(sizeof(*c), GFP_KERNEL);
-       if (!c)
+       qos = kzalloc(sizeof(*qos), GFP_KERNEL);
+       if (!qos)
                return -ENOMEM;
 
        n = kzalloc(sizeof(*n), GFP_KERNEL);
        if (!n) {
-               kfree(c);
+               kfree(qos);
                return -ENOMEM;
        }
        BLOCKING_INIT_NOTIFIER_HEAD(n);
 
+       c = &qos->latency;
        plist_head_init(&c->list);
        c->target_value = PM_QOS_DEV_LAT_DEFAULT_VALUE;
        c->default_value = PM_QOS_DEV_LAT_DEFAULT_VALUE;
        c->type = PM_QOS_MIN;
        c->notifiers = n;
 
+       INIT_LIST_HEAD(&qos->flags.list);
+
        spin_lock_irq(&dev->power.lock);
-       dev->power.constraints = c;
+       dev->power.qos = qos;
        spin_unlock_irq(&dev->power.lock);
 
        return 0;
@@ -151,7 +207,7 @@ static int dev_pm_qos_constraints_allocate(struct device *dev)
 void dev_pm_qos_constraints_init(struct device *dev)
 {
        mutex_lock(&dev_pm_qos_mtx);
-       dev->power.constraints = NULL;
+       dev->power.qos = NULL;
        dev->power.power_state = PMSG_ON;
        mutex_unlock(&dev_pm_qos_mtx);
 }
@@ -164,6 +220,7 @@ void dev_pm_qos_constraints_init(struct device *dev)
  */
 void dev_pm_qos_constraints_destroy(struct device *dev)
 {
+       struct dev_pm_qos *qos;
        struct dev_pm_qos_request *req, *tmp;
        struct pm_qos_constraints *c;
 
@@ -176,12 +233,13 @@ void dev_pm_qos_constraints_destroy(struct device *dev)
        mutex_lock(&dev_pm_qos_mtx);
 
        dev->power.power_state = PMSG_INVALID;
-       c = dev->power.constraints;
-       if (!c)
+       qos = dev->power.qos;
+       if (!qos)
                goto out;
 
+       c = &qos->latency;
        /* Flush the constraints list for the device */
-       plist_for_each_entry_safe(req, tmp, &c->list, node) {
+       plist_for_each_entry_safe(req, tmp, &c->list, data.pnode) {
                /*
                 * Update constraints list and call the notification
                 * callbacks if needed
@@ -191,7 +249,7 @@ void dev_pm_qos_constraints_destroy(struct device *dev)
        }
 
        spin_lock_irq(&dev->power.lock);
-       dev->power.constraints = NULL;
+       dev->power.qos = NULL;
        spin_unlock_irq(&dev->power.lock);
 
        kfree(c->notifiers);
@@ -205,6 +263,7 @@ void dev_pm_qos_constraints_destroy(struct device *dev)
  * dev_pm_qos_add_request - inserts new qos request into the list
  * @dev: target device for the constraint
  * @req: pointer to a preallocated handle
+ * @type: type of the request
  * @value: defines the qos request
  *
  * This function inserts a new entry in the device constraints list of
@@ -220,7 +279,7 @@ void dev_pm_qos_constraints_destroy(struct device *dev)
  * from the system.
  */
 int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req,
-                          s32 value)
+                          enum dev_pm_qos_req_type type, s32 value)
 {
        int ret = 0;
 
@@ -235,7 +294,7 @@ int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req,
 
        mutex_lock(&dev_pm_qos_mtx);
 
-       if (!dev->power.constraints) {
+       if (!dev->power.qos) {
                if (dev->power.power_state.event == PM_EVENT_INVALID) {
                        /* The device has been removed from the system. */
                        req->dev = NULL;
@@ -251,8 +310,10 @@ int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req,
                }
        }
 
-       if (!ret)
+       if (!ret) {
+               req->type = type;
                ret = apply_constraint(req, PM_QOS_ADD_REQ, value);
+       }
 
  out:
        mutex_unlock(&dev_pm_qos_mtx);
@@ -261,6 +322,37 @@ int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req,
 }
 EXPORT_SYMBOL_GPL(dev_pm_qos_add_request);
 
+/**
+ * __dev_pm_qos_update_request - Modify an existing device PM QoS request.
+ * @req : PM QoS request to modify.
+ * @new_value: New value to request.
+ */
+static int __dev_pm_qos_update_request(struct dev_pm_qos_request *req,
+                                      s32 new_value)
+{
+       s32 curr_value;
+       int ret = 0;
+
+       if (!req->dev->power.qos)
+               return -ENODEV;
+
+       switch(req->type) {
+       case DEV_PM_QOS_LATENCY:
+               curr_value = req->data.pnode.prio;
+               break;
+       case DEV_PM_QOS_FLAGS:
+               curr_value = req->data.flr.flags;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if (curr_value != new_value)
+               ret = apply_constraint(req, PM_QOS_UPDATE_REQ, new_value);
+
+       return ret;
+}
+
 /**
  * dev_pm_qos_update_request - modifies an existing qos request
  * @req : handle to list element holding a dev_pm_qos request to use
@@ -276,10 +368,9 @@ EXPORT_SYMBOL_GPL(dev_pm_qos_add_request);
  * -EINVAL in case of wrong parameters, -ENODEV if the device has been
  * removed from the system
  */
-int dev_pm_qos_update_request(struct dev_pm_qos_request *req,
-                             s32 new_value)
+int dev_pm_qos_update_request(struct dev_pm_qos_request *req, s32 new_value)
 {
-       int ret = 0;
+       int ret;
 
        if (!req) /*guard against callers passing in null */
                return -EINVAL;
@@ -289,17 +380,9 @@ int dev_pm_qos_update_request(struct dev_pm_qos_request *req,
                return -EINVAL;
 
        mutex_lock(&dev_pm_qos_mtx);
-
-       if (req->dev->power.constraints) {
-               if (new_value != req->node.prio)
-                       ret = apply_constraint(req, PM_QOS_UPDATE_REQ,
-                                              new_value);
-       } else {
-               /* Return if the device has been removed */
-               ret = -ENODEV;
-       }
-
+       __dev_pm_qos_update_request(req, new_value);
        mutex_unlock(&dev_pm_qos_mtx);
+
        return ret;
 }
 EXPORT_SYMBOL_GPL(dev_pm_qos_update_request);
@@ -329,7 +412,7 @@ int dev_pm_qos_remove_request(struct dev_pm_qos_request *req)
 
        mutex_lock(&dev_pm_qos_mtx);
 
-       if (req->dev->power.constraints) {
+       if (req->dev->power.qos) {
                ret = apply_constraint(req, PM_QOS_REMOVE_REQ,
                                       PM_QOS_DEFAULT_VALUE);
                memset(req, 0, sizeof(*req));
@@ -362,13 +445,13 @@ int dev_pm_qos_add_notifier(struct device *dev, struct notifier_block *notifier)
 
        mutex_lock(&dev_pm_qos_mtx);
 
-       if (!dev->power.constraints)
+       if (!dev->power.qos)
                ret = dev->power.power_state.event != PM_EVENT_INVALID ?
                        dev_pm_qos_constraints_allocate(dev) : -ENODEV;
 
        if (!ret)
                ret = blocking_notifier_chain_register(
-                               dev->power.constraints->notifiers, notifier);
+                               dev->power.qos->latency.notifiers, notifier);
 
        mutex_unlock(&dev_pm_qos_mtx);
        return ret;
@@ -393,9 +476,9 @@ int dev_pm_qos_remove_notifier(struct device *dev,
        mutex_lock(&dev_pm_qos_mtx);
 
        /* Silently return if the constraints object is not present. */
-       if (dev->power.constraints)
+       if (dev->power.qos)
                retval = blocking_notifier_chain_unregister(
-                               dev->power.constraints->notifiers,
+                               dev->power.qos->latency.notifiers,
                                notifier);
 
        mutex_unlock(&dev_pm_qos_mtx);
@@ -449,7 +532,8 @@ int dev_pm_qos_add_ancestor_request(struct device *dev,
                ancestor = ancestor->parent;
 
        if (ancestor)
-               error = dev_pm_qos_add_request(ancestor, req, value);
+               error = dev_pm_qos_add_request(ancestor, req,
+                                              DEV_PM_QOS_LATENCY, value);
 
        if (error)
                req->dev = NULL;
@@ -459,10 +543,19 @@ int dev_pm_qos_add_ancestor_request(struct device *dev,
 EXPORT_SYMBOL_GPL(dev_pm_qos_add_ancestor_request);
 
 #ifdef CONFIG_PM_RUNTIME
-static void __dev_pm_qos_drop_user_request(struct device *dev)
+static void __dev_pm_qos_drop_user_request(struct device *dev,
+                                          enum dev_pm_qos_req_type type)
 {
-       dev_pm_qos_remove_request(dev->power.pq_req);
-       dev->power.pq_req = NULL;
+       switch(type) {
+       case DEV_PM_QOS_LATENCY:
+               dev_pm_qos_remove_request(dev->power.qos->latency_req);
+               dev->power.qos->latency_req = NULL;
+               break;
+       case DEV_PM_QOS_FLAGS:
+               dev_pm_qos_remove_request(dev->power.qos->flags_req);
+               dev->power.qos->flags_req = NULL;
+               break;
+       }
 }
 
 /**
@@ -478,21 +571,21 @@ int dev_pm_qos_expose_latency_limit(struct device *dev, s32 value)
        if (!device_is_registered(dev) || value < 0)
                return -EINVAL;
 
-       if (dev->power.pq_req)
+       if (dev->power.qos && dev->power.qos->latency_req)
                return -EEXIST;
 
        req = kzalloc(sizeof(*req), GFP_KERNEL);
        if (!req)
                return -ENOMEM;
 
-       ret = dev_pm_qos_add_request(dev, req, value);
+       ret = dev_pm_qos_add_request(dev, req, DEV_PM_QOS_LATENCY, value);
        if (ret < 0)
                return ret;
 
-       dev->power.pq_req = req;
-       ret = pm_qos_sysfs_add(dev);
+       dev->power.qos->latency_req = req;
+       ret = pm_qos_sysfs_add_latency(dev);
        if (ret)
-               __dev_pm_qos_drop_user_request(dev);
+               __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_LATENCY);
 
        return ret;
 }
@@ -504,10 +597,87 @@ EXPORT_SYMBOL_GPL(dev_pm_qos_expose_latency_limit);
  */
 void dev_pm_qos_hide_latency_limit(struct device *dev)
 {
-       if (dev->power.pq_req) {
-               pm_qos_sysfs_remove(dev);
-               __dev_pm_qos_drop_user_request(dev);
+       if (dev->power.qos && dev->power.qos->latency_req) {
+               pm_qos_sysfs_remove_latency(dev);
+               __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_LATENCY);
        }
 }
 EXPORT_SYMBOL_GPL(dev_pm_qos_hide_latency_limit);
+
+/**
+ * dev_pm_qos_expose_flags - Expose PM QoS flags of a device to user space.
+ * @dev: Device whose PM QoS flags are to be exposed to user space.
+ * @val: Initial values of the flags.
+ */
+int dev_pm_qos_expose_flags(struct device *dev, s32 val)
+{
+       struct dev_pm_qos_request *req;
+       int ret;
+
+       if (!device_is_registered(dev))
+               return -EINVAL;
+
+       if (dev->power.qos && dev->power.qos->flags_req)
+               return -EEXIST;
+
+       req = kzalloc(sizeof(*req), GFP_KERNEL);
+       if (!req)
+               return -ENOMEM;
+
+       ret = dev_pm_qos_add_request(dev, req, DEV_PM_QOS_FLAGS, val);
+       if (ret < 0)
+               return ret;
+
+       dev->power.qos->flags_req = req;
+       ret = pm_qos_sysfs_add_flags(dev);
+       if (ret)
+               __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_FLAGS);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(dev_pm_qos_expose_flags);
+
+/**
+ * dev_pm_qos_hide_flags - Hide PM QoS flags of a device from user space.
+ * @dev: Device whose PM QoS flags are to be hidden from user space.
+ */
+void dev_pm_qos_hide_flags(struct device *dev)
+{
+       if (dev->power.qos && dev->power.qos->flags_req) {
+               pm_qos_sysfs_remove_flags(dev);
+               __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_FLAGS);
+       }
+}
+EXPORT_SYMBOL_GPL(dev_pm_qos_hide_flags);
+
+/**
+ * dev_pm_qos_update_flags - Update PM QoS flags request owned by user space.
+ * @dev: Device to update the PM QoS flags request for.
+ * @mask: Flags to set/clear.
+ * @set: Whether to set or clear the flags (true means set).
+ */
+int dev_pm_qos_update_flags(struct device *dev, s32 mask, bool set)
+{
+       s32 value;
+       int ret;
+
+       if (!dev->power.qos || !dev->power.qos->flags_req)
+               return -EINVAL;
+
+       pm_runtime_get_sync(dev);
+       mutex_lock(&dev_pm_qos_mtx);
+
+       value = dev_pm_qos_requested_flags(dev);
+       if (set)
+               value |= mask;
+       else
+               value &= ~mask;
+
+       ret = __dev_pm_qos_update_request(dev->power.qos->flags_req, value);
+
+       mutex_unlock(&dev_pm_qos_mtx);
+       pm_runtime_put(dev);
+
+       return ret;
+}
 #endif /* CONFIG_PM_RUNTIME */
index b91dc6f1e91476484584b5eb08f9dbb4b8811030..50d16e3cb0a91ad637124472ac6b570403e86229 100644 (file)
@@ -221,7 +221,7 @@ static DEVICE_ATTR(autosuspend_delay_ms, 0644, autosuspend_delay_ms_show,
 static ssize_t pm_qos_latency_show(struct device *dev,
                                   struct device_attribute *attr, char *buf)
 {
-       return sprintf(buf, "%d\n", dev->power.pq_req->node.prio);
+       return sprintf(buf, "%d\n", dev_pm_qos_requested_latency(dev));
 }
 
 static ssize_t pm_qos_latency_store(struct device *dev,
@@ -237,12 +237,66 @@ static ssize_t pm_qos_latency_store(struct device *dev,
        if (value < 0)
                return -EINVAL;
 
-       ret = dev_pm_qos_update_request(dev->power.pq_req, value);
+       ret = dev_pm_qos_update_request(dev->power.qos->latency_req, value);
        return ret < 0 ? ret : n;
 }
 
 static DEVICE_ATTR(pm_qos_resume_latency_us, 0644,
                   pm_qos_latency_show, pm_qos_latency_store);
+
+static ssize_t pm_qos_no_power_off_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       return sprintf(buf, "%d\n", !!(dev_pm_qos_requested_flags(dev)
+                                       & PM_QOS_FLAG_NO_POWER_OFF));
+}
+
+static ssize_t pm_qos_no_power_off_store(struct device *dev,
+                                        struct device_attribute *attr,
+                                        const char *buf, size_t n)
+{
+       int ret;
+
+       if (kstrtoint(buf, 0, &ret))
+               return -EINVAL;
+
+       if (ret != 0 && ret != 1)
+               return -EINVAL;
+
+       ret = dev_pm_qos_update_flags(dev, PM_QOS_FLAG_NO_POWER_OFF, ret);
+       return ret < 0 ? ret : n;
+}
+
+static DEVICE_ATTR(pm_qos_no_power_off, 0644,
+                  pm_qos_no_power_off_show, pm_qos_no_power_off_store);
+
+static ssize_t pm_qos_remote_wakeup_show(struct device *dev,
+                                        struct device_attribute *attr,
+                                        char *buf)
+{
+       return sprintf(buf, "%d\n", !!(dev_pm_qos_requested_flags(dev)
+                                       & PM_QOS_FLAG_REMOTE_WAKEUP));
+}
+
+static ssize_t pm_qos_remote_wakeup_store(struct device *dev,
+                                         struct device_attribute *attr,
+                                         const char *buf, size_t n)
+{
+       int ret;
+
+       if (kstrtoint(buf, 0, &ret))
+               return -EINVAL;
+
+       if (ret != 0 && ret != 1)
+               return -EINVAL;
+
+       ret = dev_pm_qos_update_flags(dev, PM_QOS_FLAG_REMOTE_WAKEUP, ret);
+       return ret < 0 ? ret : n;
+}
+
+static DEVICE_ATTR(pm_qos_remote_wakeup, 0644,
+                  pm_qos_remote_wakeup_show, pm_qos_remote_wakeup_store);
 #endif /* CONFIG_PM_RUNTIME */
 
 #ifdef CONFIG_PM_SLEEP
@@ -564,15 +618,27 @@ static struct attribute_group pm_runtime_attr_group = {
        .attrs  = runtime_attrs,
 };
 
-static struct attribute *pm_qos_attrs[] = {
+static struct attribute *pm_qos_latency_attrs[] = {
 #ifdef CONFIG_PM_RUNTIME
        &dev_attr_pm_qos_resume_latency_us.attr,
 #endif /* CONFIG_PM_RUNTIME */
        NULL,
 };
-static struct attribute_group pm_qos_attr_group = {
+static struct attribute_group pm_qos_latency_attr_group = {
        .name   = power_group_name,
-       .attrs  = pm_qos_attrs,
+       .attrs  = pm_qos_latency_attrs,
+};
+
+static struct attribute *pm_qos_flags_attrs[] = {
+#ifdef CONFIG_PM_RUNTIME
+       &dev_attr_pm_qos_no_power_off.attr,
+       &dev_attr_pm_qos_remote_wakeup.attr,
+#endif /* CONFIG_PM_RUNTIME */
+       NULL,
+};
+static struct attribute_group pm_qos_flags_attr_group = {
+       .name   = power_group_name,
+       .attrs  = pm_qos_flags_attrs,
 };
 
 int dpm_sysfs_add(struct device *dev)
@@ -615,14 +681,24 @@ void wakeup_sysfs_remove(struct device *dev)
        sysfs_unmerge_group(&dev->kobj, &pm_wakeup_attr_group);
 }
 
-int pm_qos_sysfs_add(struct device *dev)
+int pm_qos_sysfs_add_latency(struct device *dev)
+{
+       return sysfs_merge_group(&dev->kobj, &pm_qos_latency_attr_group);
+}
+
+void pm_qos_sysfs_remove_latency(struct device *dev)
+{
+       sysfs_unmerge_group(&dev->kobj, &pm_qos_latency_attr_group);
+}
+
+int pm_qos_sysfs_add_flags(struct device *dev)
 {
-       return sysfs_merge_group(&dev->kobj, &pm_qos_attr_group);
+       return sysfs_merge_group(&dev->kobj, &pm_qos_flags_attr_group);
 }
 
-void pm_qos_sysfs_remove(struct device *dev)
+void pm_qos_sysfs_remove_flags(struct device *dev)
 {
-       sysfs_unmerge_group(&dev->kobj, &pm_qos_attr_group);
+       sysfs_unmerge_group(&dev->kobj, &pm_qos_flags_attr_group);
 }
 
 void rpm_sysfs_remove(struct device *dev)
index 6be390bd8bd1bc3f0fa1e3bfc38cd56f36bfa6be..f0d30543fcce0944d3e619031ea0a828a179e852 100644 (file)
@@ -3,7 +3,7 @@
 # subsystems should select the appropriate symbols.
 
 config REGMAP
-       default y if (REGMAP_I2C || REGMAP_SPI)
+       default y if (REGMAP_I2C || REGMAP_SPI || REGMAP_MMIO || REGMAP_IRQ)
        select LZO_COMPRESS
        select LZO_DECOMPRESS
        select IRQ_DOMAIN if REGMAP_IRQ
index 80f9ab9c3aa4b7eba89b436d0dcd6a96b3623558..2cd01b57b1c40ac7fd154bbe1210ada67cf460ba 100644 (file)
@@ -31,14 +31,12 @@ struct regmap_format {
        unsigned int (*parse_val)(void *buf);
 };
 
-typedef void (*regmap_lock)(struct regmap *map);
-typedef void (*regmap_unlock)(struct regmap *map);
-
 struct regmap {
        struct mutex mutex;
        spinlock_t spinlock;
        regmap_lock lock;
        regmap_unlock unlock;
+       void *lock_arg; /* This is passed to lock/unlock functions */
 
        struct device *dev; /* Device we do I/O on */
        void *work_buf;     /* Scratch buffer used to format I/O */
@@ -120,6 +118,8 @@ int _regmap_write(struct regmap *map, unsigned int reg,
 
 struct regmap_range_node {
        struct rb_node node;
+       const char *name;
+       struct regmap *map;
 
        unsigned int range_min;
        unsigned int range_max;
index bb1ff175b9629083a4d5d6e4e0e6811de3b2f808..f4b9dd01c9819ad4e1bc789593876a1f449eb8e3 100644 (file)
@@ -56,15 +56,15 @@ static const struct file_operations regmap_name_fops = {
        .llseek = default_llseek,
 };
 
-static ssize_t regmap_map_read_file(struct file *file, char __user *user_buf,
-                                   size_t count, loff_t *ppos)
+static ssize_t regmap_read_debugfs(struct regmap *map, unsigned int from,
+                                  unsigned int to, char __user *user_buf,
+                                  size_t count, loff_t *ppos)
 {
        int reg_len, val_len, tot_len;
        size_t buf_pos = 0;
        loff_t p = 0;
        ssize_t ret;
        int i;
-       struct regmap *map = file->private_data;
        char *buf;
        unsigned int val;
 
@@ -80,7 +80,7 @@ static ssize_t regmap_map_read_file(struct file *file, char __user *user_buf,
        val_len = 2 * map->format.val_bytes;
        tot_len = reg_len + val_len + 3;      /* : \n */
 
-       for (i = 0; i <= map->max_register; i += map->reg_stride) {
+       for (i = from; i <= to; i += map->reg_stride) {
                if (!regmap_readable(map, i))
                        continue;
 
@@ -95,7 +95,7 @@ static ssize_t regmap_map_read_file(struct file *file, char __user *user_buf,
 
                        /* Format the register */
                        snprintf(buf + buf_pos, count - buf_pos, "%.*x: ",
-                                reg_len, i);
+                                reg_len, i - from);
                        buf_pos += reg_len + 2;
 
                        /* Format the value, write all X if we can't read */
@@ -126,6 +126,15 @@ out:
        return ret;
 }
 
+static ssize_t regmap_map_read_file(struct file *file, char __user *user_buf,
+                                   size_t count, loff_t *ppos)
+{
+       struct regmap *map = file->private_data;
+
+       return regmap_read_debugfs(map, 0, map->max_register, user_buf,
+                                  count, ppos);
+}
+
 #undef REGMAP_ALLOW_WRITE_DEBUGFS
 #ifdef REGMAP_ALLOW_WRITE_DEBUGFS
 /*
@@ -174,6 +183,22 @@ static const struct file_operations regmap_map_fops = {
        .llseek = default_llseek,
 };
 
+static ssize_t regmap_range_read_file(struct file *file, char __user *user_buf,
+                                     size_t count, loff_t *ppos)
+{
+       struct regmap_range_node *range = file->private_data;
+       struct regmap *map = range->map;
+
+       return regmap_read_debugfs(map, range->range_min, range->range_max,
+                                  user_buf, count, ppos);
+}
+
+static const struct file_operations regmap_range_fops = {
+       .open = simple_open,
+       .read = regmap_range_read_file,
+       .llseek = default_llseek,
+};
+
 static ssize_t regmap_access_read_file(struct file *file,
                                       char __user *user_buf, size_t count,
                                       loff_t *ppos)
@@ -244,6 +269,9 @@ static const struct file_operations regmap_access_fops = {
 
 void regmap_debugfs_init(struct regmap *map, const char *name)
 {
+       struct rb_node *next;
+       struct regmap_range_node *range_node;
+
        if (name) {
                map->debugfs_name = kasprintf(GFP_KERNEL, "%s-%s",
                                              dev_name(map->dev), name);
@@ -276,6 +304,18 @@ void regmap_debugfs_init(struct regmap *map, const char *name)
                debugfs_create_bool("cache_bypass", 0400, map->debugfs,
                                    &map->cache_bypass);
        }
+
+       next = rb_first(&map->range_tree);
+       while (next) {
+               range_node = rb_entry(next, struct regmap_range_node, node);
+
+               if (range_node->name)
+                       debugfs_create_file(range_node->name, 0400,
+                                           map->debugfs, range_node,
+                                           &regmap_range_fops);
+
+               next = rb_next(&range_node->node);
+       }
 }
 
 void regmap_debugfs_exit(struct regmap *map)
index 5b6b1d8e6cc028f7bf5233741e4f396ce00a03c5..5972ad958544e3c875a2196294d83c74d7e44cc9 100644 (file)
@@ -458,3 +458,22 @@ int regmap_irq_get_virq(struct regmap_irq_chip_data *data, int irq)
        return irq_create_mapping(data->domain, irq);
 }
 EXPORT_SYMBOL_GPL(regmap_irq_get_virq);
+
+/**
+ * regmap_irq_get_domain(): Retrieve the irq_domain for the chip
+ *
+ * Useful for drivers to request their own IRQs and for integration
+ * with subsystems.  For ease of integration NULL is accepted as a
+ * domain, allowing devices to just call this even if no domain is
+ * allocated.
+ *
+ * @data: regmap_irq controller to operate on.
+ */
+struct irq_domain *regmap_irq_get_domain(struct regmap_irq_chip_data *data)
+{
+       if (data)
+               return data->domain;
+       else
+               return NULL;
+}
+EXPORT_SYMBOL_GPL(regmap_irq_get_domain);
index 52069d29ff12ef197c7d8a447ab27ffb7096d85e..058572601431bacf44f8d3b8ef6bf42abfa516a2 100644 (file)
@@ -82,7 +82,7 @@ bool regmap_precious(struct regmap *map, unsigned int reg)
 }
 
 static bool regmap_volatile_range(struct regmap *map, unsigned int reg,
-       unsigned int num)
+       size_t num)
 {
        unsigned int i;
 
@@ -214,23 +214,27 @@ static unsigned int regmap_parse_32_native(void *buf)
        return *(u32 *)buf;
 }
 
-static void regmap_lock_mutex(struct regmap *map)
+static void regmap_lock_mutex(void *__map)
 {
+       struct regmap *map = __map;
        mutex_lock(&map->mutex);
 }
 
-static void regmap_unlock_mutex(struct regmap *map)
+static void regmap_unlock_mutex(void *__map)
 {
+       struct regmap *map = __map;
        mutex_unlock(&map->mutex);
 }
 
-static void regmap_lock_spinlock(struct regmap *map)
+static void regmap_lock_spinlock(void *__map)
 {
+       struct regmap *map = __map;
        spin_lock(&map->spinlock);
 }
 
-static void regmap_unlock_spinlock(struct regmap *map)
+static void regmap_unlock_spinlock(void *__map)
 {
+       struct regmap *map = __map;
        spin_unlock(&map->spinlock);
 }
 
@@ -335,14 +339,21 @@ struct regmap *regmap_init(struct device *dev,
                goto err;
        }
 
-       if (bus->fast_io) {
-               spin_lock_init(&map->spinlock);
-               map->lock = regmap_lock_spinlock;
-               map->unlock = regmap_unlock_spinlock;
+       if (config->lock && config->unlock) {
+               map->lock = config->lock;
+               map->unlock = config->unlock;
+               map->lock_arg = config->lock_arg;
        } else {
-               mutex_init(&map->mutex);
-               map->lock = regmap_lock_mutex;
-               map->unlock = regmap_unlock_mutex;
+               if (bus->fast_io) {
+                       spin_lock_init(&map->spinlock);
+                       map->lock = regmap_lock_spinlock;
+                       map->unlock = regmap_unlock_spinlock;
+               } else {
+                       mutex_init(&map->mutex);
+                       map->lock = regmap_lock_mutex;
+                       map->unlock = regmap_unlock_mutex;
+               }
+               map->lock_arg = map;
        }
        map->format.reg_bytes = DIV_ROUND_UP(config->reg_bits, 8);
        map->format.pad_bytes = config->pad_bits / 8;
@@ -519,20 +530,38 @@ struct regmap *regmap_init(struct device *dev,
        }
 
        map->range_tree = RB_ROOT;
-       for (i = 0; i < config->n_ranges; i++) {
+       for (i = 0; i < config->num_ranges; i++) {
                const struct regmap_range_cfg *range_cfg = &config->ranges[i];
                struct regmap_range_node *new;
 
                /* Sanity check */
-               if (range_cfg->range_max < range_cfg->range_min ||
-                   range_cfg->range_max > map->max_register ||
-                   range_cfg->selector_reg > map->max_register ||
-                   range_cfg->window_len == 0)
+               if (range_cfg->range_max < range_cfg->range_min) {
+                       dev_err(map->dev, "Invalid range %d: %d < %d\n", i,
+                               range_cfg->range_max, range_cfg->range_min);
                        goto err_range;
+               }
+
+               if (range_cfg->range_max > map->max_register) {
+                       dev_err(map->dev, "Invalid range %d: %d > %d\n", i,
+                               range_cfg->range_max, map->max_register);
+                       goto err_range;
+               }
+
+               if (range_cfg->selector_reg > map->max_register) {
+                       dev_err(map->dev,
+                               "Invalid range %d: selector out of map\n", i);
+                       goto err_range;
+               }
+
+               if (range_cfg->window_len == 0) {
+                       dev_err(map->dev, "Invalid range %d: window_len 0\n",
+                               i);
+                       goto err_range;
+               }
 
                /* Make sure, that this register range has no selector
                   or data window within its boundary */
-               for (j = 0; j < config->n_ranges; j++) {
+               for (j = 0; j < config->num_ranges; j++) {
                        unsigned sel_reg = config->ranges[j].selector_reg;
                        unsigned win_min = config->ranges[j].window_start;
                        unsigned win_max = win_min +
@@ -540,11 +569,17 @@ struct regmap *regmap_init(struct device *dev,
 
                        if (range_cfg->range_min <= sel_reg &&
                            sel_reg <= range_cfg->range_max) {
+                               dev_err(map->dev,
+                                       "Range %d: selector for %d in window\n",
+                                       i, j);
                                goto err_range;
                        }
 
                        if (!(win_max < range_cfg->range_min ||
                              win_min > range_cfg->range_max)) {
+                               dev_err(map->dev,
+                                       "Range %d: window for %d in window\n",
+                                       i, j);
                                goto err_range;
                        }
                }
@@ -555,6 +590,8 @@ struct regmap *regmap_init(struct device *dev,
                        goto err_range;
                }
 
+               new->map = map;
+               new->name = range_cfg->name;
                new->range_min = range_cfg->range_min;
                new->range_max = range_cfg->range_max;
                new->selector_reg = range_cfg->selector_reg;
@@ -564,6 +601,7 @@ struct regmap *regmap_init(struct device *dev,
                new->window_len = range_cfg->window_len;
 
                if (_regmap_range_add(map, new) == false) {
+                       dev_err(map->dev, "Failed to add range %d\n", i);
                        kfree(new);
                        goto err_range;
                }
@@ -579,7 +617,7 @@ struct regmap *regmap_init(struct device *dev,
        }
 
        ret = regcache_init(map, config);
-       if (ret < 0)
+       if (ret != 0)
                goto err_range;
 
        regmap_debugfs_init(map, config->name);
@@ -738,59 +776,57 @@ struct regmap *dev_get_regmap(struct device *dev, const char *name)
 EXPORT_SYMBOL_GPL(dev_get_regmap);
 
 static int _regmap_select_page(struct regmap *map, unsigned int *reg,
+                              struct regmap_range_node *range,
                               unsigned int val_num)
 {
-       struct regmap_range_node *range;
        void *orig_work_buf;
        unsigned int win_offset;
        unsigned int win_page;
        bool page_chg;
        int ret;
 
-       range = _regmap_range_lookup(map, *reg);
-       if (range) {
-               win_offset = (*reg - range->range_min) % range->window_len;
-               win_page = (*reg - range->range_min) / range->window_len;
-
-               if (val_num > 1) {
-                       /* Bulk write shouldn't cross range boundary */
-                       if (*reg + val_num - 1 > range->range_max)
-                               return -EINVAL;
+       win_offset = (*reg - range->range_min) % range->window_len;
+       win_page = (*reg - range->range_min) / range->window_len;
 
-                       /* ... or single page boundary */
-                       if (val_num > range->window_len - win_offset)
-                               return -EINVAL;
-               }
+       if (val_num > 1) {
+               /* Bulk write shouldn't cross range boundary */
+               if (*reg + val_num - 1 > range->range_max)
+                       return -EINVAL;
 
-               /* It is possible to have selector register inside data window.
-                  In that case, selector register is located on every page and
-                  it needs no page switching, when accessed alone. */
-               if (val_num > 1 ||
-                   range->window_start + win_offset != range->selector_reg) {
-                       /* Use separate work_buf during page switching */
-                       orig_work_buf = map->work_buf;
-                       map->work_buf = map->selector_work_buf;
+               /* ... or single page boundary */
+               if (val_num > range->window_len - win_offset)
+                       return -EINVAL;
+       }
 
-                       ret = _regmap_update_bits(map, range->selector_reg,
-                                       range->selector_mask,
-                                       win_page << range->selector_shift,
-                                       &page_chg);
+       /* It is possible to have selector register inside data window.
+          In that case, selector register is located on every page and
+          it needs no page switching, when accessed alone. */
+       if (val_num > 1 ||
+           range->window_start + win_offset != range->selector_reg) {
+               /* Use separate work_buf during page switching */
+               orig_work_buf = map->work_buf;
+               map->work_buf = map->selector_work_buf;
 
-                       map->work_buf = orig_work_buf;
+               ret = _regmap_update_bits(map, range->selector_reg,
+                                         range->selector_mask,
+                                         win_page << range->selector_shift,
+                                         &page_chg);
 
-                       if (ret < 0)
-                               return ret;
-               }
+               map->work_buf = orig_work_buf;
 
-               *reg = range->window_start + win_offset;
+               if (ret != 0)
+                       return ret;
        }
 
+       *reg = range->window_start + win_offset;
+
        return 0;
 }
 
 static int _regmap_raw_write(struct regmap *map, unsigned int reg,
                             const void *val, size_t val_len)
 {
+       struct regmap_range_node *range;
        u8 *u8 = map->work_buf;
        void *buf;
        int ret = -ENOTSUPP;
@@ -825,9 +861,35 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg,
                }
        }
 
-       ret = _regmap_select_page(map, &reg, val_len / map->format.val_bytes);
-       if (ret < 0)
-               return ret;
+       range = _regmap_range_lookup(map, reg);
+       if (range) {
+               int val_num = val_len / map->format.val_bytes;
+               int win_offset = (reg - range->range_min) % range->window_len;
+               int win_residue = range->window_len - win_offset;
+
+               /* If the write goes beyond the end of the window split it */
+               while (val_num > win_residue) {
+                       dev_dbg(map->dev, "Writing window %d/%d\n",
+                               win_residue, val_len / map->format.val_bytes);
+                       ret = _regmap_raw_write(map, reg, val, win_residue *
+                                               map->format.val_bytes);
+                       if (ret != 0)
+                               return ret;
+
+                       reg += win_residue;
+                       val_num -= win_residue;
+                       val += win_residue * map->format.val_bytes;
+                       val_len -= win_residue * map->format.val_bytes;
+
+                       win_offset = (reg - range->range_min) %
+                               range->window_len;
+                       win_residue = range->window_len - win_offset;
+               }
+
+               ret = _regmap_select_page(map, &reg, range, val_num);
+               if (ret != 0)
+                       return ret;
+       }
 
        map->format.format_reg(map->work_buf, reg, map->reg_shift);
 
@@ -876,6 +938,7 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg,
 int _regmap_write(struct regmap *map, unsigned int reg,
                  unsigned int val)
 {
+       struct regmap_range_node *range;
        int ret;
        BUG_ON(!map->format.format_write && !map->format.format_val);
 
@@ -897,9 +960,12 @@ int _regmap_write(struct regmap *map, unsigned int reg,
        trace_regmap_reg_write(map->dev, reg, val);
 
        if (map->format.format_write) {
-               ret = _regmap_select_page(map, &reg, 1);
-               if (ret < 0)
-                       return ret;
+               range = _regmap_range_lookup(map, reg);
+               if (range) {
+                       ret = _regmap_select_page(map, &reg, range, 1);
+                       if (ret != 0)
+                               return ret;
+               }
 
                map->format.format_write(map, reg, val);
 
@@ -939,11 +1005,11 @@ int regmap_write(struct regmap *map, unsigned int reg, unsigned int val)
        if (reg % map->reg_stride)
                return -EINVAL;
 
-       map->lock(map);
+       map->lock(map->lock_arg);
 
        ret = _regmap_write(map, reg, val);
 
-       map->unlock(map);
+       map->unlock(map->lock_arg);
 
        return ret;
 }
@@ -975,11 +1041,11 @@ int regmap_raw_write(struct regmap *map, unsigned int reg,
        if (reg % map->reg_stride)
                return -EINVAL;
 
-       map->lock(map);
+       map->lock(map->lock_arg);
 
        ret = _regmap_raw_write(map, reg, val, val_len);
 
-       map->unlock(map);
+       map->unlock(map->lock_arg);
 
        return ret;
 }
@@ -1011,7 +1077,7 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val,
        if (reg % map->reg_stride)
                return -EINVAL;
 
-       map->lock(map);
+       map->lock(map->lock_arg);
 
        /* No formatting is require if val_byte is 1 */
        if (val_bytes == 1) {
@@ -1047,7 +1113,7 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val,
                kfree(wval);
 
 out:
-       map->unlock(map);
+       map->unlock(map->lock_arg);
        return ret;
 }
 EXPORT_SYMBOL_GPL(regmap_bulk_write);
@@ -1055,12 +1121,17 @@ EXPORT_SYMBOL_GPL(regmap_bulk_write);
 static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
                            unsigned int val_len)
 {
+       struct regmap_range_node *range;
        u8 *u8 = map->work_buf;
        int ret;
 
-       ret = _regmap_select_page(map, &reg, val_len / map->format.val_bytes);
-       if (ret < 0)
-               return ret;
+       range = _regmap_range_lookup(map, reg);
+       if (range) {
+               ret = _regmap_select_page(map, &reg, range,
+                                         val_len / map->format.val_bytes);
+               if (ret != 0)
+                       return ret;
+       }
 
        map->format.format_reg(map->work_buf, reg, map->reg_shift);
 
@@ -1137,11 +1208,11 @@ int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val)
        if (reg % map->reg_stride)
                return -EINVAL;
 
-       map->lock(map);
+       map->lock(map->lock_arg);
 
        ret = _regmap_read(map, reg, val);
 
-       map->unlock(map);
+       map->unlock(map->lock_arg);
 
        return ret;
 }
@@ -1171,7 +1242,7 @@ int regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
        if (reg % map->reg_stride)
                return -EINVAL;
 
-       map->lock(map);
+       map->lock(map->lock_arg);
 
        if (regmap_volatile_range(map, reg, val_count) || map->cache_bypass ||
            map->cache_type == REGCACHE_NONE) {
@@ -1193,7 +1264,7 @@ int regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
        }
 
  out:
-       map->unlock(map);
+       map->unlock(map->lock_arg);
 
        return ret;
 }
@@ -1300,9 +1371,9 @@ int regmap_update_bits(struct regmap *map, unsigned int reg,
        bool change;
        int ret;
 
-       map->lock(map);
+       map->lock(map->lock_arg);
        ret = _regmap_update_bits(map, reg, mask, val, &change);
-       map->unlock(map);
+       map->unlock(map->lock_arg);
 
        return ret;
 }
@@ -1326,9 +1397,9 @@ int regmap_update_bits_check(struct regmap *map, unsigned int reg,
 {
        int ret;
 
-       map->lock(map);
+       map->lock(map->lock_arg);
        ret = _regmap_update_bits(map, reg, mask, val, change);
-       map->unlock(map);
+       map->unlock(map->lock_arg);
        return ret;
 }
 EXPORT_SYMBOL_GPL(regmap_update_bits_check);
@@ -1357,7 +1428,7 @@ int regmap_register_patch(struct regmap *map, const struct reg_default *regs,
        if (map->patch)
                return -EBUSY;
 
-       map->lock(map);
+       map->lock(map->lock_arg);
 
        bypass = map->cache_bypass;
 
@@ -1385,7 +1456,7 @@ int regmap_register_patch(struct regmap *map, const struct reg_default *regs,
 out:
        map->cache_bypass = bypass;
 
-       map->unlock(map);
+       map->unlock(map->lock_arg);
 
        return ret;
 }
index a4c3ebcc4c8609de39d7331d23b24bd830ac77cf..ffd74e51f02def4dedac4404fec82b436b7ddcdd 100644 (file)
@@ -22,12 +22,9 @@ static inline u32 bcma_cc_write32_masked(struct bcma_drv_cc *cc, u16 offset,
        return value;
 }
 
-void bcma_core_chipcommon_init(struct bcma_drv_cc *cc)
+void bcma_core_chipcommon_early_init(struct bcma_drv_cc *cc)
 {
-       u32 leddc_on = 10;
-       u32 leddc_off = 90;
-
-       if (cc->setup_done)
+       if (cc->early_setup_done)
                return;
 
        if (cc->core->id.rev >= 11)
@@ -36,6 +33,22 @@ void bcma_core_chipcommon_init(struct bcma_drv_cc *cc)
        if (cc->core->id.rev >= 35)
                cc->capabilities_ext = bcma_cc_read32(cc, BCMA_CC_CAP_EXT);
 
+       if (cc->capabilities & BCMA_CC_CAP_PMU)
+               bcma_pmu_early_init(cc);
+
+       cc->early_setup_done = true;
+}
+
+void bcma_core_chipcommon_init(struct bcma_drv_cc *cc)
+{
+       u32 leddc_on = 10;
+       u32 leddc_off = 90;
+
+       if (cc->setup_done)
+               return;
+
+       bcma_core_chipcommon_early_init(cc);
+
        if (cc->core->id.rev >= 20) {
                bcma_cc_write32(cc, BCMA_CC_GPIOPULLUP, 0);
                bcma_cc_write32(cc, BCMA_CC_GPIOPULLDOWN, 0);
index 9042781edec340e932e39d2b75c7dba495764e42..dbda91e4dff5189ccabbb710b7a2a11f0e099651 100644 (file)
@@ -32,6 +32,9 @@ int bcma_nflash_init(struct bcma_drv_cc *cc)
        }
 
        cc->nflash.present = true;
+       if (cc->core->id.rev == 38 &&
+           (cc->status & BCMA_CC_CHIPST_5357_NAND_BOOT))
+               cc->nflash.boot = true;
 
        /* Prepare platform device, but don't register it yet. It's too early,
         * malloc (required by device_private_init) is not available yet. */
index 201faf106b3f4e342337e2219213a72c670ef447..a63ddd9c70ebf8d72a81c28bfdb98328889d414b 100644 (file)
@@ -144,7 +144,7 @@ static void bcma_pmu_workarounds(struct bcma_drv_cc *cc)
        }
 }
 
-void bcma_pmu_init(struct bcma_drv_cc *cc)
+void bcma_pmu_early_init(struct bcma_drv_cc *cc)
 {
        u32 pmucap;
 
@@ -153,7 +153,10 @@ void bcma_pmu_init(struct bcma_drv_cc *cc)
 
        bcma_debug(cc->core->bus, "Found rev %u PMU (capabilities 0x%08X)\n",
                   cc->pmu.rev, pmucap);
+}
 
+void bcma_pmu_init(struct bcma_drv_cc *cc)
+{
        if (cc->pmu.rev == 1)
                bcma_cc_mask32(cc, BCMA_CC_PMU_CTL,
                              ~BCMA_CC_PMU_CTL_NOILPONW);
index 2c4eec2ca5a0784bd50d392a84edc74911a58916..63e688393825539b5f2c64537cbefb1659c579c3 100644 (file)
@@ -12,7 +12,7 @@
 
 static struct resource bcma_sflash_resource = {
        .name   = "bcma_sflash",
-       .start  = BCMA_SFLASH,
+       .start  = BCMA_SOC_FLASH2,
        .end    = 0,
        .flags  = IORESOURCE_MEM | IORESOURCE_READONLY,
 };
@@ -31,15 +31,42 @@ struct bcma_sflash_tbl_e {
 };
 
 static struct bcma_sflash_tbl_e bcma_sflash_st_tbl[] = {
-       { "", 0x14, 0x10000, 32, },
+       { "M25P20", 0x11, 0x10000, 4, },
+       { "M25P40", 0x12, 0x10000, 8, },
+
+       { "M25P16", 0x14, 0x10000, 32, },
+       { "M25P32", 0x14, 0x10000, 64, },
+       { "M25P64", 0x16, 0x10000, 128, },
+       { "M25FL128", 0x17, 0x10000, 256, },
        { 0 },
 };
 
 static struct bcma_sflash_tbl_e bcma_sflash_sst_tbl[] = {
+       { "SST25WF512", 1, 0x1000, 16, },
+       { "SST25VF512", 0x48, 0x1000, 16, },
+       { "SST25WF010", 2, 0x1000, 32, },
+       { "SST25VF010", 0x49, 0x1000, 32, },
+       { "SST25WF020", 3, 0x1000, 64, },
+       { "SST25VF020", 0x43, 0x1000, 64, },
+       { "SST25WF040", 4, 0x1000, 128, },
+       { "SST25VF040", 0x44, 0x1000, 128, },
+       { "SST25VF040B", 0x8d, 0x1000, 128, },
+       { "SST25WF080", 5, 0x1000, 256, },
+       { "SST25VF080B", 0x8e, 0x1000, 256, },
+       { "SST25VF016", 0x41, 0x1000, 512, },
+       { "SST25VF032", 0x4a, 0x1000, 1024, },
+       { "SST25VF064", 0x4b, 0x1000, 2048, },
        { 0 },
 };
 
 static struct bcma_sflash_tbl_e bcma_sflash_at_tbl[] = {
+       { "AT45DB011", 0xc, 256, 512, },
+       { "AT45DB021", 0x14, 256, 1024, },
+       { "AT45DB041", 0x1c, 256, 2048, },
+       { "AT45DB081", 0x24, 256, 4096, },
+       { "AT45DB161", 0x2c, 512, 4096, },
+       { "AT45DB321", 0x34, 512, 8192, },
+       { "AT45DB642", 0x3c, 1024, 8192, },
        { 0 },
 };
 
@@ -84,6 +111,8 @@ int bcma_sflash_init(struct bcma_drv_cc *cc)
                                        break;
                        }
                        break;
+               case 0x13:
+                       return -ENOTSUPP;
                default:
                        for (e = bcma_sflash_st_tbl; e->name; e++) {
                                if (e->id == id)
@@ -116,7 +145,7 @@ int bcma_sflash_init(struct bcma_drv_cc *cc)
                return -ENOTSUPP;
        }
 
-       sflash->window = BCMA_SFLASH;
+       sflash->window = BCMA_SOC_FLASH2;
        sflash->blocksize = e->blocksize;
        sflash->numblocks = e->numblocks;
        sflash->size = sflash->blocksize * sflash->numblocks;
index cc65b45b4368aabd6d0af17897cd5e0b2b857c31..170822ea51c71ef852d758f44f71d3ea9f16db8a 100644 (file)
@@ -181,47 +181,66 @@ EXPORT_SYMBOL(bcma_cpu_clock);
 static void bcma_core_mips_flash_detect(struct bcma_drv_mips *mcore)
 {
        struct bcma_bus *bus = mcore->core->bus;
+       struct bcma_drv_cc *cc = &bus->drv_cc;
 
-       switch (bus->drv_cc.capabilities & BCMA_CC_CAP_FLASHT) {
+       switch (cc->capabilities & BCMA_CC_CAP_FLASHT) {
        case BCMA_CC_FLASHT_STSER:
        case BCMA_CC_FLASHT_ATSER:
                bcma_debug(bus, "Found serial flash\n");
-               bcma_sflash_init(&bus->drv_cc);
+               bcma_sflash_init(cc);
                break;
        case BCMA_CC_FLASHT_PARA:
                bcma_debug(bus, "Found parallel flash\n");
-               bus->drv_cc.pflash.window = 0x1c000000;
-               bus->drv_cc.pflash.window_size = 0x02000000;
+               cc->pflash.present = true;
+               cc->pflash.window = BCMA_SOC_FLASH2;
+               cc->pflash.window_size = BCMA_SOC_FLASH2_SZ;
 
-               if ((bcma_read32(bus->drv_cc.core, BCMA_CC_FLASH_CFG) &
+               if ((bcma_read32(cc->core, BCMA_CC_FLASH_CFG) &
                     BCMA_CC_FLASH_CFG_DS) == 0)
-                       bus->drv_cc.pflash.buswidth = 1;
+                       cc->pflash.buswidth = 1;
                else
-                       bus->drv_cc.pflash.buswidth = 2;
+                       cc->pflash.buswidth = 2;
                break;
        default:
                bcma_err(bus, "Flash type not supported\n");
        }
 
-       if (bus->drv_cc.core->id.rev == 38 ||
+       if (cc->core->id.rev == 38 ||
            bus->chipinfo.id == BCMA_CHIP_ID_BCM4706) {
-               if (bus->drv_cc.capabilities & BCMA_CC_CAP_NFLASH) {
+               if (cc->capabilities & BCMA_CC_CAP_NFLASH) {
                        bcma_debug(bus, "Found NAND flash\n");
-                       bcma_nflash_init(&bus->drv_cc);
+                       bcma_nflash_init(cc);
                }
        }
 }
 
+void bcma_core_mips_early_init(struct bcma_drv_mips *mcore)
+{
+       struct bcma_bus *bus = mcore->core->bus;
+
+       if (mcore->early_setup_done)
+               return;
+
+       bcma_chipco_serial_init(&bus->drv_cc);
+       bcma_core_mips_flash_detect(mcore);
+
+       mcore->early_setup_done = true;
+}
+
 void bcma_core_mips_init(struct bcma_drv_mips *mcore)
 {
        struct bcma_bus *bus;
        struct bcma_device *core;
        bus = mcore->core->bus;
 
+       if (mcore->setup_done)
+               return;
+
        bcma_info(bus, "Initializing MIPS core...\n");
 
-       if (!mcore->setup_done)
-               mcore->assigned_irqs = 1;
+       bcma_core_mips_early_init(mcore);
+
+       mcore->assigned_irqs = 1;
 
        /* Assign IRQs to all cores on the bus */
        list_for_each_entry(core, &bus->cores, list) {
@@ -256,10 +275,5 @@ void bcma_core_mips_init(struct bcma_drv_mips *mcore)
        bcma_info(bus, "IRQ reconfiguration done\n");
        bcma_core_mips_dump_irq(bus);
 
-       if (mcore->setup_done)
-               return;
-
-       bcma_chipco_serial_init(&bus->drv_cc);
-       bcma_core_mips_flash_detect(mcore);
        mcore->setup_done = true;
 }
index 9baf886e82df39f710b897a0b864824fbedfebad..e564495066956a46e0ab71554e356dd446fe8e84 100644 (file)
@@ -35,11 +35,6 @@ bool __devinit bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc)
            chipid_top != 0x5300)
                return false;
 
-       if (bus->sprom.boardflags_lo & BCMA_CORE_PCI_BFL_NOPCI) {
-               bcma_info(bus, "This PCI core is disabled and not working\n");
-               return false;
-       }
-
        bcma_core_enable(pc->core, 0);
 
        return !mips_busprobe32(tmp, pc->core->io_addr);
@@ -396,6 +391,11 @@ void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc)
 
        bcma_info(bus, "PCIEcore in host mode found\n");
 
+       if (bus->sprom.boardflags_lo & BCMA_CORE_PCI_BFL_NOPCI) {
+               bcma_info(bus, "This PCIE core is disabled and not working\n");
+               return;
+       }
+
        pc_host = kzalloc(sizeof(*pc_host), GFP_KERNEL);
        if (!pc_host)  {
                bcma_err(bus, "can not allocate memory");
@@ -452,6 +452,8 @@ void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc)
                        pc_host->mem_resource.start = BCMA_SOC_PCI_MEM;
                        pc_host->mem_resource.end = BCMA_SOC_PCI_MEM +
                                                    BCMA_SOC_PCI_MEM_SZ - 1;
+                       pc_host->io_resource.start = 0x100;
+                       pc_host->io_resource.end = 0x47F;
                        pci_membase_1G = BCMA_SOC_PCIE_DMA_H32;
                        pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0,
                                        tmp | BCMA_SOC_PCI_MEM);
@@ -459,6 +461,8 @@ void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc)
                        pc_host->mem_resource.start = BCMA_SOC_PCI1_MEM;
                        pc_host->mem_resource.end = BCMA_SOC_PCI1_MEM +
                                                    BCMA_SOC_PCI_MEM_SZ - 1;
+                       pc_host->io_resource.start = 0x480;
+                       pc_host->io_resource.end = 0x7FF;
                        pci_membase_1G = BCMA_SOC_PCIE1_DMA_H32;
                        pc_host->host_cfg_addr = BCMA_SOC_PCI1_CFG;
                        pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0,
index 432aeeedfd5e6992c28ea081e4185bf88ffeed8e..a9718893000b907b7b990a673d956f37f05ce17e 100644 (file)
@@ -81,6 +81,18 @@ struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid)
 }
 EXPORT_SYMBOL_GPL(bcma_find_core);
 
+static struct bcma_device *bcma_find_core_unit(struct bcma_bus *bus, u16 coreid,
+                                              u8 unit)
+{
+       struct bcma_device *core;
+
+       list_for_each_entry(core, &bus->cores, list) {
+               if (core->id.id == coreid && core->core_unit == unit)
+                       return core;
+       }
+       return NULL;
+}
+
 static void bcma_release_core_dev(struct device *dev)
 {
        struct bcma_device *core = container_of(dev, struct bcma_device, dev);
@@ -158,9 +170,10 @@ static int bcma_register_cores(struct bcma_bus *bus)
 
 static void bcma_unregister_cores(struct bcma_bus *bus)
 {
-       struct bcma_device *core;
+       struct bcma_device *core, *tmp;
 
-       list_for_each_entry(core, &bus->cores, list) {
+       list_for_each_entry_safe(core, tmp, &bus->cores, list) {
+               list_del(&core->list);
                if (core->dev_registered)
                        device_unregister(&core->dev);
        }
@@ -182,6 +195,20 @@ int __devinit bcma_bus_register(struct bcma_bus *bus)
                return -1;
        }
 
+       /* Early init CC core */
+       core = bcma_find_core(bus, bcma_cc_core_id(bus));
+       if (core) {
+               bus->drv_cc.core = core;
+               bcma_core_chipcommon_early_init(&bus->drv_cc);
+       }
+
+       /* Try to get SPROM */
+       err = bcma_sprom_get(bus);
+       if (err == -ENOENT) {
+               bcma_err(bus, "No SPROM available\n");
+       } else if (err)
+               bcma_err(bus, "Failed to get SPROM: %d\n", err);
+
        /* Init CC core */
        core = bcma_find_core(bus, bcma_cc_core_id(bus));
        if (core) {
@@ -197,10 +224,17 @@ int __devinit bcma_bus_register(struct bcma_bus *bus)
        }
 
        /* Init PCIE core */
-       core = bcma_find_core(bus, BCMA_CORE_PCIE);
+       core = bcma_find_core_unit(bus, BCMA_CORE_PCIE, 0);
+       if (core) {
+               bus->drv_pci[0].core = core;
+               bcma_core_pci_init(&bus->drv_pci[0]);
+       }
+
+       /* Init PCIE core */
+       core = bcma_find_core_unit(bus, BCMA_CORE_PCIE, 1);
        if (core) {
-               bus->drv_pci.core = core;
-               bcma_core_pci_init(&bus->drv_pci);
+               bus->drv_pci[1].core = core;
+               bcma_core_pci_init(&bus->drv_pci[1]);
        }
 
        /* Init GBIT MAC COMMON core */
@@ -210,13 +244,6 @@ int __devinit bcma_bus_register(struct bcma_bus *bus)
                bcma_core_gmac_cmn_init(&bus->drv_gmac_cmn);
        }
 
-       /* Try to get SPROM */
-       err = bcma_sprom_get(bus);
-       if (err == -ENOENT) {
-               bcma_err(bus, "No SPROM available\n");
-       } else if (err)
-               bcma_err(bus, "Failed to get SPROM: %d\n", err);
-
        /* Register found cores */
        bcma_register_cores(bus);
 
@@ -274,18 +301,18 @@ int __init bcma_bus_early_register(struct bcma_bus *bus,
                return -1;
        }
 
-       /* Init CC core */
+       /* Early init CC core */
        core = bcma_find_core(bus, bcma_cc_core_id(bus));
        if (core) {
                bus->drv_cc.core = core;
-               bcma_core_chipcommon_init(&bus->drv_cc);
+               bcma_core_chipcommon_early_init(&bus->drv_cc);
        }
 
-       /* Init MIPS core */
+       /* Early init MIPS core */
        core = bcma_find_core(bus, BCMA_CORE_MIPS_74K);
        if (core) {
                bus->drv_mips.core = core;
-               bcma_core_mips_init(&bus->drv_mips);
+               bcma_core_mips_early_init(&bus->drv_mips);
        }
 
        bcma_info(bus, "Early bus registered\n");
index 0d546b64be341239a5ee405970f166be47f83081..4adf9ef9a113010e2b8f51cabd27e07c57898c83 100644 (file)
@@ -595,8 +595,11 @@ int bcma_sprom_get(struct bcma_bus *bus)
                bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, true);
 
        err = bcma_sprom_valid(sprom);
-       if (err)
+       if (err) {
+               bcma_warn(bus, "invalid sprom read from the PCIe card, try to use fallback sprom\n");
+               err = bcma_fill_sprom_with_fallback(bus, &bus->sprom);
                goto out;
+       }
 
        bcma_sprom_extract_r8(bus, sprom);
 
index f529407db93ff74dbfa8b9dad13324815467fad2..f7de3228f626a0d849c503f059944f575a05f831 100644 (file)
@@ -131,6 +131,7 @@ config BLK_CPQ_DA
 config BLK_CPQ_CISS_DA
        tristate "Compaq Smart Array 5xxx support"
        depends on PCI
+       select CHECK_SIGNATURE
        help
          This is the driver for Compaq Smart Array 5xxx controllers.
          Everyone using these boards should say Y here.
index b0f553b26d0f8d00f86f768f93aad27ebcb0529e..ca83f96756ad86b2a339971050b7378f9a9752d9 100644 (file)
@@ -5205,7 +5205,6 @@ static void cciss_shutdown(struct pci_dev *pdev)
                return;
        }
        /* write all data in the battery backed cache to disk */
-       memset(flush_buf, 0, 4);
        return_code = sendcmd_withirq(h, CCISS_CACHE_FLUSH, flush_buf,
                4, 0, CTLR_LUNID, TYPE_CMD);
        kfree(flush_buf);
index 17c675c522954cc39a210e431603aac2a3a2d946..a6eebab17a39da37a945de4de7eb8df94172bd58 100644 (file)
@@ -4109,12 +4109,19 @@ static struct platform_driver floppy_driver = {
 
 static struct platform_device floppy_device[N_DRIVE];
 
+static bool floppy_available(int drive)
+{
+       if (!(allowed_drive_mask & (1 << drive)))
+               return false;
+       if (fdc_state[FDC(drive)].version == FDC_NONE)
+               return false;
+       return true;
+}
+
 static struct kobject *floppy_find(dev_t dev, int *part, void *data)
 {
        int drive = (*part & 3) | ((*part & 0x80) >> 5);
-       if (drive >= N_DRIVE ||
-           !(allowed_drive_mask & (1 << drive)) ||
-           fdc_state[FDC(drive)].version == FDC_NONE)
+       if (drive >= N_DRIVE || !floppy_available(drive))
                return NULL;
        if (((*part >> 2) & 0x1f) >= ARRAY_SIZE(floppy_type))
                return NULL;
@@ -4124,8 +4131,7 @@ static struct kobject *floppy_find(dev_t dev, int *part, void *data)
 
 static int __init do_floppy_init(void)
 {
-       int i, unit, drive;
-       int err, dr;
+       int i, unit, drive, err;
 
        set_debugt();
        interruptjiffies = resultjiffies = jiffies;
@@ -4137,34 +4143,32 @@ static int __init do_floppy_init(void)
 
        raw_cmd = NULL;
 
-       for (dr = 0; dr < N_DRIVE; dr++) {
-               disks[dr] = alloc_disk(1);
-               if (!disks[dr]) {
-                       err = -ENOMEM;
-                       goto out_put_disk;
-               }
+       floppy_wq = alloc_ordered_workqueue("floppy", 0);
+       if (!floppy_wq)
+               return -ENOMEM;
 
-               floppy_wq = alloc_ordered_workqueue("floppy", 0);
-               if (!floppy_wq) {
+       for (drive = 0; drive < N_DRIVE; drive++) {
+               disks[drive] = alloc_disk(1);
+               if (!disks[drive]) {
                        err = -ENOMEM;
                        goto out_put_disk;
                }
 
-               disks[dr]->queue = blk_init_queue(do_fd_request, &floppy_lock);
-               if (!disks[dr]->queue) {
+               disks[drive]->queue = blk_init_queue(do_fd_request, &floppy_lock);
+               if (!disks[drive]->queue) {
                        err = -ENOMEM;
-                       goto out_destroy_workq;
+                       goto out_put_disk;
                }
 
-               blk_queue_max_hw_sectors(disks[dr]->queue, 64);
-               disks[dr]->major = FLOPPY_MAJOR;
-               disks[dr]->first_minor = TOMINOR(dr);
-               disks[dr]->fops = &floppy_fops;
-               sprintf(disks[dr]->disk_name, "fd%d", dr);
+               blk_queue_max_hw_sectors(disks[drive]->queue, 64);
+               disks[drive]->major = FLOPPY_MAJOR;
+               disks[drive]->first_minor = TOMINOR(drive);
+               disks[drive]->fops = &floppy_fops;
+               sprintf(disks[drive]->disk_name, "fd%d", drive);
 
-               init_timer(&motor_off_timer[dr]);
-               motor_off_timer[dr].data = dr;
-               motor_off_timer[dr].function = motor_off_callback;
+               init_timer(&motor_off_timer[drive]);
+               motor_off_timer[drive].data = drive;
+               motor_off_timer[drive].function = motor_off_callback;
        }
 
        err = register_blkdev(FLOPPY_MAJOR, "fd");
@@ -4282,9 +4286,7 @@ static int __init do_floppy_init(void)
        }
 
        for (drive = 0; drive < N_DRIVE; drive++) {
-               if (!(allowed_drive_mask & (1 << drive)))
-                       continue;
-               if (fdc_state[FDC(drive)].version == FDC_NONE)
+               if (!floppy_available(drive))
                        continue;
 
                floppy_device[drive].name = floppy_device_name;
@@ -4293,7 +4295,7 @@ static int __init do_floppy_init(void)
 
                err = platform_device_register(&floppy_device[drive]);
                if (err)
-                       goto out_release_dma;
+                       goto out_remove_drives;
 
                err = device_create_file(&floppy_device[drive].dev,
                                         &dev_attr_cmos);
@@ -4311,29 +4313,33 @@ static int __init do_floppy_init(void)
 
 out_unreg_platform_dev:
        platform_device_unregister(&floppy_device[drive]);
+out_remove_drives:
+       while (drive--) {
+               if (floppy_available(drive)) {
+                       del_gendisk(disks[drive]);
+                       device_remove_file(&floppy_device[drive].dev, &dev_attr_cmos);
+                       platform_device_unregister(&floppy_device[drive]);
+               }
+       }
 out_release_dma:
        if (atomic_read(&usage_count))
                floppy_release_irq_and_dma();
 out_unreg_region:
        blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256);
        platform_driver_unregister(&floppy_driver);
-out_destroy_workq:
-       destroy_workqueue(floppy_wq);
 out_unreg_blkdev:
        unregister_blkdev(FLOPPY_MAJOR, "fd");
 out_put_disk:
-       while (dr--) {
-               del_timer_sync(&motor_off_timer[dr]);
-               if (disks[dr]->queue) {
-                       blk_cleanup_queue(disks[dr]->queue);
-                       /*
-                        * put_disk() is not paired with add_disk() and
-                        * will put queue reference one extra time. fix it.
-                        */
-                       disks[dr]->queue = NULL;
+       for (drive = 0; drive < N_DRIVE; drive++) {
+               if (!disks[drive])
+                       break;
+               if (disks[drive]->queue) {
+                       del_timer_sync(&motor_off_timer[drive]);
+                       blk_cleanup_queue(disks[drive]->queue);
                }
-               put_disk(disks[dr]);
+               put_disk(disks[drive]);
        }
+       destroy_workqueue(floppy_wq);
        return err;
 }
 
@@ -4551,22 +4557,13 @@ static void __exit floppy_module_exit(void)
        for (drive = 0; drive < N_DRIVE; drive++) {
                del_timer_sync(&motor_off_timer[drive]);
 
-               if ((allowed_drive_mask & (1 << drive)) &&
-                   fdc_state[FDC(drive)].version != FDC_NONE) {
+               if (floppy_available(drive)) {
                        del_gendisk(disks[drive]);
                        device_remove_file(&floppy_device[drive].dev, &dev_attr_cmos);
                        platform_device_unregister(&floppy_device[drive]);
                }
                blk_cleanup_queue(disks[drive]->queue);
 
-               /*
-                * These disks have not called add_disk().  Don't put down
-                * queue reference in put_disk().
-                */
-               if (!(allowed_drive_mask & (1 << drive)) ||
-                   fdc_state[FDC(drive)].version == FDC_NONE)
-                       disks[drive]->queue = NULL;
-
                put_disk(disks[drive]);
        }
 
index e9d594fd12cbee408251c4ead03d1b71183ff7ae..54046e51160aef28e3ee733797fa453a0403a02a 100644 (file)
@@ -976,8 +976,21 @@ static int loop_clr_fd(struct loop_device *lo)
        if (lo->lo_state != Lo_bound)
                return -ENXIO;
 
-       if (lo->lo_refcnt > 1)  /* we needed one fd for the ioctl */
-               return -EBUSY;
+       /*
+        * If we've explicitly asked to tear down the loop device,
+        * and it has an elevated reference count, set it for auto-teardown when
+        * the last reference goes away. This stops $!~#$@ udev from
+        * preventing teardown because it decided that it needs to run blkid on
+        * the loopback device whenever they appear. xfstests is notorious for
+        * failing tests because blkid via udev races with a losetup
+        * <dev>/do something like mkfs/losetup -d <dev> causing the losetup -d
+        * command to fail with EBUSY.
+        */
+       if (lo->lo_refcnt > 1) {
+               lo->lo_flags |= LO_FLAGS_AUTOCLEAR;
+               mutex_unlock(&lo->lo_ctl_mutex);
+               return 0;
+       }
 
        if (filp == NULL)
                return -EINVAL;
index f946d31d6917e00aa0637df5d21cef35ebf82845..adc6f36564cf3c9f214ca37c9b3cf8faffbe6cf8 100644 (file)
@@ -2035,8 +2035,9 @@ static unsigned int implicit_sector(unsigned char command,
        }
        return rv;
 }
-
-static void mtip_set_timeout(struct host_to_dev_fis *fis, unsigned int *timeout)
+static void mtip_set_timeout(struct driver_data *dd,
+                                       struct host_to_dev_fis *fis,
+                                       unsigned int *timeout, u8 erasemode)
 {
        switch (fis->command) {
        case ATA_CMD_DOWNLOAD_MICRO:
@@ -2044,7 +2045,10 @@ static void mtip_set_timeout(struct host_to_dev_fis *fis, unsigned int *timeout)
                break;
        case ATA_CMD_SEC_ERASE_UNIT:
        case 0xFC:
-               *timeout = 240000; /* 4 minutes */
+               if (erasemode)
+                       *timeout = ((*(dd->port->identify + 90) * 2) * 60000);
+               else
+                       *timeout = ((*(dd->port->identify + 89) * 2) * 60000);
                break;
        case ATA_CMD_STANDBYNOW1:
                *timeout = 120000;  /* 2 minutes */
@@ -2087,6 +2091,7 @@ static int exec_drive_taskfile(struct driver_data *dd,
        unsigned int transfer_size;
        unsigned long task_file_data;
        int intotal = outtotal + req_task->out_size;
+       int erasemode = 0;
 
        taskout = req_task->out_size;
        taskin = req_task->in_size;
@@ -2212,7 +2217,13 @@ static int exec_drive_taskfile(struct driver_data *dd,
                fis.lba_hi,
                fis.device);
 
-       mtip_set_timeout(&fis, &timeout);
+       /* check for erase mode support during secure erase.*/
+       if ((fis.command == ATA_CMD_SEC_ERASE_UNIT)
+                                       && (outbuf[0] & MTIP_SEC_ERASE_MODE)) {
+               erasemode = 1;
+       }
+
+       mtip_set_timeout(dd, &fis, &timeout, erasemode);
 
        /* Determine the correct transfer size.*/
        if (force_single_sector)
index 18627a1d04c59eff34f7cdd2313555b10a75b283..5f4a917bd8bbcfe88283b3509e365a0faefbb3b5 100644 (file)
@@ -33,6 +33,9 @@
 /* offset of Device Control register in PCIe extended capabilites space */
 #define PCIE_CONFIG_EXT_DEVICE_CONTROL_OFFSET  0x48
 
+/* check for erase mode support during secure erase */
+#define MTIP_SEC_ERASE_MODE     0x3
+
 /* # of times to retry timed out/failed IOs */
 #define MTIP_MAX_RETRIES       2
 
index bb3d9be3b1b4eecb82ba82f8bc1045e825ff7a75..8f56d37637a7a402158c664f6f88aab31a1820ae 100644 (file)
 #define RBD_IMAGE_ID_LEN_MAX   64
 #define RBD_OBJ_PREFIX_LEN_MAX 64
 
+/* Feature bits */
+
+#define RBD_FEATURE_LAYERING      1
+
+/* Features supported by this (client software) implementation. */
+
+#define RBD_FEATURES_ALL          (0)
+
 /*
  * An RBD device name will be "rbd#", where the "rbd" comes from
  * RBD_DRV_NAME above, and # is a unique integer identifier.
@@ -268,7 +276,8 @@ static void rbd_put_dev(struct rbd_device *rbd_dev)
        put_device(&rbd_dev->dev);
 }
 
-static int rbd_refresh_header(struct rbd_device *rbd_dev, u64 *hver);
+static int rbd_dev_refresh(struct rbd_device *rbd_dev, u64 *hver);
+static int rbd_dev_v2_refresh(struct rbd_device *rbd_dev, u64 *hver);
 
 static int rbd_open(struct block_device *bdev, fmode_t mode)
 {
@@ -1304,7 +1313,7 @@ static void rbd_watch_cb(u64 ver, u64 notify_id, u8 opcode, void *data)
        dout("rbd_watch_cb %s notify_id=%llu opcode=%u\n",
                rbd_dev->header_name, (unsigned long long) notify_id,
                (unsigned int) opcode);
-       rc = rbd_refresh_header(rbd_dev, &hver);
+       rc = rbd_dev_refresh(rbd_dev, &hver);
        if (rc)
                pr_warning(RBD_DRV_NAME "%d got notification but failed to "
                           " update snaps: %d\n", rbd_dev->major, rc);
@@ -1716,10 +1725,23 @@ static void __rbd_remove_all_snaps(struct rbd_device *rbd_dev)
                __rbd_remove_snap_dev(snap);
 }
 
+static void rbd_update_mapping_size(struct rbd_device *rbd_dev)
+{
+       sector_t size;
+
+       if (rbd_dev->mapping.snap_id != CEPH_NOSNAP)
+               return;
+
+       size = (sector_t) rbd_dev->header.image_size / SECTOR_SIZE;
+       dout("setting size to %llu sectors", (unsigned long long) size);
+       rbd_dev->mapping.size = (u64) size;
+       set_capacity(rbd_dev->disk, size);
+}
+
 /*
  * only read the first part of the ondisk header, without the snaps info
  */
-static int __rbd_refresh_header(struct rbd_device *rbd_dev, u64 *hver)
+static int rbd_dev_v1_refresh(struct rbd_device *rbd_dev, u64 *hver)
 {
        int ret;
        struct rbd_image_header h;
@@ -1730,17 +1752,9 @@ static int __rbd_refresh_header(struct rbd_device *rbd_dev, u64 *hver)
 
        down_write(&rbd_dev->header_rwsem);
 
-       /* resized? */
-       if (rbd_dev->mapping.snap_id == CEPH_NOSNAP) {
-               sector_t size = (sector_t) h.image_size / SECTOR_SIZE;
-
-               if (size != (sector_t) rbd_dev->mapping.size) {
-                       dout("setting size to %llu sectors",
-                               (unsigned long long) size);
-                       rbd_dev->mapping.size = (u64) size;
-                       set_capacity(rbd_dev->disk, size);
-               }
-       }
+       /* Update image size, and check for resize of mapped image */
+       rbd_dev->header.image_size = h.image_size;
+       rbd_update_mapping_size(rbd_dev);
 
        /* rbd_dev->header.object_prefix shouldn't change */
        kfree(rbd_dev->header.snap_sizes);
@@ -1768,12 +1782,16 @@ static int __rbd_refresh_header(struct rbd_device *rbd_dev, u64 *hver)
        return ret;
 }
 
-static int rbd_refresh_header(struct rbd_device *rbd_dev, u64 *hver)
+static int rbd_dev_refresh(struct rbd_device *rbd_dev, u64 *hver)
 {
        int ret;
 
+       rbd_assert(rbd_image_format_valid(rbd_dev->image_format));
        mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
-       ret = __rbd_refresh_header(rbd_dev, hver);
+       if (rbd_dev->image_format == 1)
+               ret = rbd_dev_v1_refresh(rbd_dev, hver);
+       else
+               ret = rbd_dev_v2_refresh(rbd_dev, hver);
        mutex_unlock(&ctl_mutex);
 
        return ret;
@@ -1933,7 +1951,7 @@ static ssize_t rbd_image_refresh(struct device *dev,
        struct rbd_device *rbd_dev = dev_to_rbd_dev(dev);
        int ret;
 
-       ret = rbd_refresh_header(rbd_dev, NULL);
+       ret = rbd_dev_refresh(rbd_dev, NULL);
 
        return ret < 0 ? ret : size;
 }
@@ -2216,6 +2234,7 @@ static int _rbd_dev_v2_snap_features(struct rbd_device *rbd_dev, u64 snap_id,
                __le64 features;
                __le64 incompat;
        } features_buf = { 0 };
+       u64 incompat;
        int ret;
 
        ret = rbd_req_sync_exec(rbd_dev, rbd_dev->header_name,
@@ -2226,6 +2245,11 @@ static int _rbd_dev_v2_snap_features(struct rbd_device *rbd_dev, u64 snap_id,
        dout("%s: rbd_req_sync_exec returned %d\n", __func__, ret);
        if (ret < 0)
                return ret;
+
+       incompat = le64_to_cpu(features_buf.incompat);
+       if (incompat & ~RBD_FEATURES_ALL)
+               return -ENOTSUPP;
+
        *snap_features = le64_to_cpu(features_buf.features);
 
        dout("  snap_id 0x%016llx features = 0x%016llx incompat = 0x%016llx\n",
@@ -2397,6 +2421,41 @@ static char *rbd_dev_snap_info(struct rbd_device *rbd_dev, u32 which,
        return ERR_PTR(-EINVAL);
 }
 
+static int rbd_dev_v2_refresh(struct rbd_device *rbd_dev, u64 *hver)
+{
+       int ret;
+       __u8 obj_order;
+
+       down_write(&rbd_dev->header_rwsem);
+
+       /* Grab old order first, to see if it changes */
+
+       obj_order = rbd_dev->header.obj_order,
+       ret = rbd_dev_v2_image_size(rbd_dev);
+       if (ret)
+               goto out;
+       if (rbd_dev->header.obj_order != obj_order) {
+               ret = -EIO;
+               goto out;
+       }
+       rbd_update_mapping_size(rbd_dev);
+
+       ret = rbd_dev_v2_snap_context(rbd_dev, hver);
+       dout("rbd_dev_v2_snap_context returned %d\n", ret);
+       if (ret)
+               goto out;
+       ret = rbd_dev_snaps_update(rbd_dev);
+       dout("rbd_dev_snaps_update returned %d\n", ret);
+       if (ret)
+               goto out;
+       ret = rbd_dev_snaps_register(rbd_dev);
+       dout("rbd_dev_snaps_register returned %d\n", ret);
+out:
+       up_write(&rbd_dev->header_rwsem);
+
+       return ret;
+}
+
 /*
  * Scan the rbd device's current snapshot list and compare it to the
  * newly-received snapshot context.  Remove any existing snapshots
@@ -2559,7 +2618,7 @@ static int rbd_init_watch_dev(struct rbd_device *rbd_dev)
        do {
                ret = rbd_req_sync_watch(rbd_dev);
                if (ret == -ERANGE) {
-                       rc = rbd_refresh_header(rbd_dev, NULL);
+                       rc = rbd_dev_refresh(rbd_dev, NULL);
                        if (rc < 0)
                                return rc;
                }
@@ -2932,7 +2991,7 @@ static int rbd_dev_v2_probe(struct rbd_device *rbd_dev)
        if (ret < 0)
                goto out_err;
 
-       /* Get the features for the image */
+       /* Get the and check features for the image */
 
        ret = rbd_dev_v2_features(rbd_dev);
        if (ret < 0)
@@ -2955,7 +3014,7 @@ static int rbd_dev_v2_probe(struct rbd_device *rbd_dev)
        dout("discovered version 2 image, header name is %s\n",
                rbd_dev->header_name);
 
-       return -ENOTSUPP;
+       return 0;
 out_err:
        kfree(rbd_dev->header_name);
        rbd_dev->header_name = NULL;
@@ -3040,7 +3099,6 @@ static ssize_t rbd_add(struct bus_type *bus,
        rc = rbd_dev_probe(rbd_dev);
        if (rc < 0)
                goto err_out_client;
-       rbd_assert(rbd_image_format_valid(rbd_dev->image_format));
 
        /* no need to lock here, as rbd_dev is not registered yet */
        rc = rbd_dev_snaps_update(rbd_dev);
index 9ad3b5ec1dc1c521085db47a7928cc8cf1179701..9a54623e52d74ecc77953937bd923a9ecdb68d09 100644 (file)
@@ -158,8 +158,8 @@ struct xen_vbd {
        struct block_device     *bdev;
        /* Cached size parameter. */
        sector_t                size;
-       bool                    flush_support;
-       bool                    discard_secure;
+       unsigned int            flush_support:1;
+       unsigned int            discard_secure:1;
 };
 
 struct backend_info;
index 4f66171c668354b490f1284aec48278b8676bd84..f58434c2617cab4185b8c049804f1031f4226a6e 100644 (file)
@@ -105,11 +105,10 @@ static struct xen_blkif *xen_blkif_alloc(domid_t domid)
 {
        struct xen_blkif *blkif;
 
-       blkif = kmem_cache_alloc(xen_blkif_cachep, GFP_KERNEL);
+       blkif = kmem_cache_zalloc(xen_blkif_cachep, GFP_KERNEL);
        if (!blkif)
                return ERR_PTR(-ENOMEM);
 
-       memset(blkif, 0, sizeof(*blkif));
        blkif->domid = domid;
        spin_lock_init(&blkif->blk_ring_lock);
        atomic_set(&blkif->refcnt, 1);
@@ -196,7 +195,7 @@ static void xen_blkif_disconnect(struct xen_blkif *blkif)
        }
 }
 
-void xen_blkif_free(struct xen_blkif *blkif)
+static void xen_blkif_free(struct xen_blkif *blkif)
 {
        if (!atomic_dec_and_test(&blkif->refcnt))
                BUG();
@@ -257,7 +256,7 @@ static struct attribute_group xen_vbdstat_group = {
 VBD_SHOW(physical_device, "%x:%x\n", be->major, be->minor);
 VBD_SHOW(mode, "%s\n", be->mode);
 
-int xenvbd_sysfs_addif(struct xenbus_device *dev)
+static int xenvbd_sysfs_addif(struct xenbus_device *dev)
 {
        int error;
 
@@ -281,7 +280,7 @@ fail1:      device_remove_file(&dev->dev, &dev_attr_physical_device);
        return error;
 }
 
-void xenvbd_sysfs_delif(struct xenbus_device *dev)
+static void xenvbd_sysfs_delif(struct xenbus_device *dev)
 {
        sysfs_remove_group(&dev->dev.kobj, &xen_vbdstat_group);
        device_remove_file(&dev->dev, &dev_attr_mode);
index 3f4bfc814dc7d5a0382635dbe16a41af413e59fe..9959d4cb23dcc2ddad7deefa008def72ac513925 100644 (file)
@@ -492,7 +492,7 @@ done:
 static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
 {
        u16 buf_len = 0;
-       int ret, buf_block_len, blksz;
+       int ret, num_blocks, blksz;
        struct sk_buff *skb = NULL;
        u32 type;
        u8 *payload = NULL;
@@ -514,18 +514,17 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
        }
 
        blksz = SDIO_BLOCK_SIZE;
-       buf_block_len = (buf_len + blksz - 1) / blksz;
+       num_blocks = DIV_ROUND_UP(buf_len, blksz);
 
        if (buf_len <= SDIO_HEADER_LEN
-                       || (buf_block_len * blksz) > ALLOC_BUF_SIZE) {
+           || (num_blocks * blksz) > ALLOC_BUF_SIZE) {
                BT_ERR("invalid packet length: %d", buf_len);
                ret = -EINVAL;
                goto exit;
        }
 
        /* Allocate buffer */
-       skb = bt_skb_alloc(buf_block_len * blksz + BTSDIO_DMA_ALIGN,
-                                                               GFP_ATOMIC);
+       skb = bt_skb_alloc(num_blocks * blksz + BTSDIO_DMA_ALIGN, GFP_ATOMIC);
        if (skb == NULL) {
                BT_ERR("No free skb");
                goto exit;
@@ -541,7 +540,7 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
        payload = skb->data;
 
        ret = sdio_readsb(card->func, payload, card->ioport,
-                         buf_block_len * blksz);
+                         num_blocks * blksz);
        if (ret < 0) {
                BT_ERR("readsb failed: %d", ret);
                ret = -EIO;
@@ -553,7 +552,16 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
         */
 
        buf_len = payload[0];
-       buf_len |= (u16) payload[1] << 8;
+       buf_len |= payload[1] << 8;
+       buf_len |= payload[2] << 16;
+
+       if (buf_len > blksz * num_blocks) {
+               BT_ERR("Skip incorrect packet: hdrlen %d buffer %d",
+                      buf_len, blksz * num_blocks);
+               ret = -EIO;
+               goto exit;
+       }
+
        type = payload[3];
 
        switch (type) {
@@ -589,8 +597,7 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
 
        default:
                BT_ERR("Unknown packet type:%d", type);
-               print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, payload,
-                                               blksz * buf_block_len);
+               BT_ERR("hex: %*ph", blksz * num_blocks, payload);
 
                kfree_skb(skb);
                skb = NULL;
@@ -849,8 +856,7 @@ static int btmrvl_sdio_host_to_card(struct btmrvl_private *priv,
                if (ret < 0) {
                        i++;
                        BT_ERR("i=%d writesb failed: %d", i, ret);
-                       print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
-                                               payload, nb);
+                       BT_ERR("hex: %*ph", nb, payload);
                        ret = -EIO;
                        if (i > MAX_WRITE_IOMEM_RETRY)
                                goto exit;
index c8abce3d2d9c0618f2092c94398e3197d0396b27..ed0fade46aed279097f105d3b9c6208eb2b0fe46 100644 (file)
@@ -270,15 +270,10 @@ static int hci_uart_send_frame(struct sk_buff *skb)
  */
 static int hci_uart_tty_open(struct tty_struct *tty)
 {
-       struct hci_uart *hu = (void *) tty->disc_data;
+       struct hci_uart *hu;
 
        BT_DBG("tty %p", tty);
 
-       /* FIXME: This btw is bogus, nothing requires the old ldisc to clear
-          the pointer */
-       if (hu)
-               return -EEXIST;
-
        /* Error if the tty has no write op instead of leaving an exploitable
           hole */
        if (tty->ops->write == NULL)
index fbd9b2b850ef1de0a84a57182ff79bdd38064896..c58ea9b80b1a3b63e65a52236d71c8db4cfa02c4 100644 (file)
@@ -127,12 +127,12 @@ config HW_RANDOM_VIA
          If unsure, say Y.
 
 config HW_RANDOM_IXP4XX
-       tristate "Intel IXP4xx NPU HW Random Number Generator support"
+       tristate "Intel IXP4xx NPU HW Pseudo-Random Number Generator support"
        depends on HW_RANDOM && ARCH_IXP4XX
        default HW_RANDOM
        ---help---
-         This driver provides kernel-side support for the Random
-         Number Generator hardware found on the Intel IXP4xx NPU.
+         This driver provides kernel-side support for the Pseudo-Random
+         Number Generator hardware found on the Intel IXP45x/46x NPU.
 
          To compile this driver as a module, choose M here: the
          module will be called ixp4xx-rng.
index 263567f5f3923fb12ae13d6401aa84f1b636aa07..beec1627db3c1b147fb4be577c61697ef2e1005f 100644 (file)
@@ -45,6 +45,9 @@ static int __init ixp4xx_rng_init(void)
        void __iomem * rng_base;
        int err;
 
+       if (!cpu_is_ixp46x()) /* includes IXP455 */
+               return -ENOSYS;
+
        rng_base = ioremap(0x70002100, 4);
        if (!rng_base)
                return -ENOMEM;
@@ -68,5 +71,5 @@ module_init(ixp4xx_rng_init);
 module_exit(ixp4xx_rng_exit);
 
 MODULE_AUTHOR("Deepak Saxena <dsaxena@plexity.net>");
-MODULE_DESCRIPTION("H/W Random Number Generator (RNG) driver for IXP4xx");
+MODULE_DESCRIPTION("H/W Pseudo-Random Number Generator (RNG) driver for IXP45x/46x");
 MODULE_LICENSE("GPL");
index 0537903c985b653bfd78d3005133267f43bdf538..c6fa3bc2baa89cfec662945dcc9818dadfe0d44c 100644 (file)
@@ -48,7 +48,7 @@ static inline unsigned long size_inside_page(unsigned long start,
 }
 
 #ifndef ARCH_HAS_VALID_PHYS_ADDR_RANGE
-static inline int valid_phys_addr_range(unsigned long addr, size_t count)
+static inline int valid_phys_addr_range(phys_addr_t addr, size_t count)
 {
        return addr + count <= __pa(high_memory);
 }
@@ -96,7 +96,7 @@ void __weak unxlate_dev_mem_ptr(unsigned long phys, void *addr)
 static ssize_t read_mem(struct file *file, char __user *buf,
                        size_t count, loff_t *ppos)
 {
-       unsigned long p = *ppos;
+       phys_addr_t p = *ppos;
        ssize_t read, sz;
        char *ptr;
 
@@ -153,7 +153,7 @@ static ssize_t read_mem(struct file *file, char __user *buf,
 static ssize_t write_mem(struct file *file, const char __user *buf,
                         size_t count, loff_t *ppos)
 {
-       unsigned long p = *ppos;
+       phys_addr_t p = *ppos;
        ssize_t written, sz;
        unsigned long copied;
        void *ptr;
@@ -226,7 +226,7 @@ int __weak phys_mem_access_prot_allowed(struct file *file,
  *
  */
 #ifdef pgprot_noncached
-static int uncached_access(struct file *file, unsigned long addr)
+static int uncached_access(struct file *file, phys_addr_t addr)
 {
 #if defined(CONFIG_IA64)
        /*
@@ -258,7 +258,7 @@ static pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
                                     unsigned long size, pgprot_t vma_prot)
 {
 #ifdef pgprot_noncached
-       unsigned long offset = pfn << PAGE_SHIFT;
+       phys_addr_t offset = pfn << PAGE_SHIFT;
 
        if (uncached_access(file, offset))
                return pgprot_noncached(vma_prot);
index d0d824ebf2c187d492f29daef8bbf1043f56d7f1..1cd49241e60eb5024ac2941a5b0787fa46f7c13e 100644 (file)
@@ -251,12 +251,8 @@ static ssize_t pp_write (struct file * file, const char __user * buf,
                        break;
                }
 
-               if (signal_pending (current)) {
-                       if (!bytes_written) {
-                               bytes_written = -EINTR;
-                       }
+               if (signal_pending (current))
                        break;
-               }
 
                cond_resched();
        }
index 8ab9c3d4bf134c23bda43adafc688485a1c9e764..82ebe027166059a8100d2250128ad32db6eaec1d 100644 (file)
@@ -459,7 +459,7 @@ static ssize_t __send_control_msg(struct ports_device *portdev, u32 port_id,
        vq = portdev->c_ovq;
 
        sg_init_one(sg, &cpkt, sizeof(cpkt));
-       if (virtqueue_add_buf(vq, sg, 1, 0, &cpkt, GFP_ATOMIC) >= 0) {
+       if (virtqueue_add_buf(vq, sg, 1, 0, &cpkt, GFP_ATOMIC) == 0) {
                virtqueue_kick(vq);
                while (!virtqueue_get_buf(vq, &len))
                        cpu_relax();
@@ -524,7 +524,7 @@ static ssize_t __send_to_port(struct port *port, struct scatterlist *sg,
                              struct buffer_token *tok, bool nonblock)
 {
        struct virtqueue *out_vq;
-       ssize_t ret;
+       int err;
        unsigned long flags;
        unsigned int len;
 
@@ -534,17 +534,17 @@ static ssize_t __send_to_port(struct port *port, struct scatterlist *sg,
 
        reclaim_consumed_buffers(port);
 
-       ret = virtqueue_add_buf(out_vq, sg, nents, 0, tok, GFP_ATOMIC);
+       err = virtqueue_add_buf(out_vq, sg, nents, 0, tok, GFP_ATOMIC);
 
        /* Tell Host to go! */
        virtqueue_kick(out_vq);
 
-       if (ret < 0) {
+       if (err) {
                in_count = 0;
                goto done;
        }
 
-       if (ret == 0)
+       if (out_vq->num_free == 0)
                port->outvq_full = true;
 
        if (nonblock)
index 517a8ff7121e16da20aecc001ceb0db09fe7245e..6b4c70f7d23d4dfa99b5e566185e9e20b17397bf 100644 (file)
@@ -20,6 +20,7 @@ void __init nomadik_clk_init(void)
        clk_register_clkdev(clk, NULL, "gpio.2");
        clk_register_clkdev(clk, NULL, "gpio.3");
        clk_register_clkdev(clk, NULL, "rng");
+       clk_register_clkdev(clk, NULL, "fsmc-nand");
 
        /*
         * The 2.4 MHz TIMCLK reference clock is active at boot time, this is
index 1bc90e1306d88e0582b76c83abf6bfe98983ea35..5b1413e4721674f0eb8666cbf915ffbf09741917 100644 (file)
@@ -7,8 +7,8 @@ obj-$(CONFIG_CPU_FREQ_STAT)             += cpufreq_stats.o
 obj-$(CONFIG_CPU_FREQ_GOV_PERFORMANCE) += cpufreq_performance.o
 obj-$(CONFIG_CPU_FREQ_GOV_POWERSAVE)   += cpufreq_powersave.o
 obj-$(CONFIG_CPU_FREQ_GOV_USERSPACE)   += cpufreq_userspace.o
-obj-$(CONFIG_CPU_FREQ_GOV_ONDEMAND)    += cpufreq_ondemand.o
-obj-$(CONFIG_CPU_FREQ_GOV_CONSERVATIVE)        += cpufreq_conservative.o
+obj-$(CONFIG_CPU_FREQ_GOV_ONDEMAND)    += cpufreq_ondemand.o cpufreq_governor.o
+obj-$(CONFIG_CPU_FREQ_GOV_CONSERVATIVE)        += cpufreq_conservative.o cpufreq_governor.o
 
 # CPUfreq cross-arch helpers
 obj-$(CONFIG_CPU_FREQ_TABLE)           += freq_table.o
index fb8a5279c5d829898d37336c8b4e023ee55f36a5..f552d5fe0f8fa2c68daa9c78ef6780baf3834a32 100644 (file)
@@ -15,6 +15,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -445,7 +447,7 @@ static ssize_t show_scaling_governor(struct cpufreq_policy *policy, char *buf)
        else if (policy->policy == CPUFREQ_POLICY_PERFORMANCE)
                return sprintf(buf, "performance\n");
        else if (policy->governor)
-               return scnprintf(buf, CPUFREQ_NAME_LEN, "%s\n",
+               return scnprintf(buf, CPUFREQ_NAME_PLEN, "%s\n",
                                policy->governor->name);
        return -EINVAL;
 }
@@ -491,7 +493,7 @@ static ssize_t store_scaling_governor(struct cpufreq_policy *policy,
  */
 static ssize_t show_scaling_driver(struct cpufreq_policy *policy, char *buf)
 {
-       return scnprintf(buf, CPUFREQ_NAME_LEN, "%s\n", cpufreq_driver->name);
+       return scnprintf(buf, CPUFREQ_NAME_PLEN, "%s\n", cpufreq_driver->name);
 }
 
 /**
@@ -512,7 +514,7 @@ static ssize_t show_scaling_available_governors(struct cpufreq_policy *policy,
                if (i >= (ssize_t) ((PAGE_SIZE / sizeof(char))
                    - (CPUFREQ_NAME_LEN + 2)))
                        goto out;
-               i += scnprintf(&buf[i], CPUFREQ_NAME_LEN, "%s ", t->name);
+               i += scnprintf(&buf[i], CPUFREQ_NAME_PLEN, "%s ", t->name);
        }
 out:
        i += sprintf(&buf[i], "\n");
@@ -581,7 +583,7 @@ static ssize_t show_scaling_setspeed(struct cpufreq_policy *policy, char *buf)
 }
 
 /**
- * show_scaling_driver - show the current cpufreq HW/BIOS limitation
+ * show_bios_limit - show the current cpufreq HW/BIOS limitation
  */
 static ssize_t show_bios_limit(struct cpufreq_policy *policy, char *buf)
 {
@@ -1509,12 +1511,14 @@ int __cpufreq_driver_getavg(struct cpufreq_policy *policy, unsigned int cpu)
 {
        int ret = 0;
 
+       if (!(cpu_online(cpu) && cpufreq_driver->getavg))
+               return 0;
+
        policy = cpufreq_cpu_get(policy->cpu);
        if (!policy)
                return -EINVAL;
 
-       if (cpu_online(cpu) && cpufreq_driver->getavg)
-               ret = cpufreq_driver->getavg(policy, cpu);
+       ret = cpufreq_driver->getavg(policy, cpu);
 
        cpufreq_cpu_put(policy);
        return ret;
index a152af7e1991eff7db4dcd97c3d0d777b8812f37..181abad072667f0de1057c4eb4dd5d269c1322d8 100644 (file)
@@ -95,40 +95,6 @@ static struct dbs_tuners {
        .freq_step = 5,
 };
 
-static inline u64 get_cpu_idle_time_jiffy(unsigned int cpu, u64 *wall)
-{
-       u64 idle_time;
-       u64 cur_wall_time;
-       u64 busy_time;
-
-       cur_wall_time = jiffies64_to_cputime64(get_jiffies_64());
-
-       busy_time  = kcpustat_cpu(cpu).cpustat[CPUTIME_USER];
-       busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_SYSTEM];
-       busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_IRQ];
-       busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_SOFTIRQ];
-       busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_STEAL];
-       busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_NICE];
-
-       idle_time = cur_wall_time - busy_time;
-       if (wall)
-               *wall = jiffies_to_usecs(cur_wall_time);
-
-       return jiffies_to_usecs(idle_time);
-}
-
-static inline cputime64_t get_cpu_idle_time(unsigned int cpu, cputime64_t *wall)
-{
-       u64 idle_time = get_cpu_idle_time_us(cpu, NULL);
-
-       if (idle_time == -1ULL)
-               return get_cpu_idle_time_jiffy(cpu, wall);
-       else
-               idle_time += get_cpu_iowait_time_us(cpu, wall);
-
-       return idle_time;
-}
-
 /* keep track of frequency transitions */
 static int
 dbs_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c
new file mode 100644 (file)
index 0000000..679842a
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * drivers/cpufreq/cpufreq_governor.c
+ *
+ * CPUFREQ governors common code
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <asm/cputime.h>
+#include <linux/export.h>
+#include <linux/kernel_stat.h>
+#include <linux/tick.h>
+#include <linux/types.h>
+/*
+ * Code picked from earlier governer implementations
+ */
+static inline u64 get_cpu_idle_time_jiffy(unsigned int cpu, u64 *wall)
+{
+       u64 idle_time;
+       u64 cur_wall_time;
+       u64 busy_time;
+
+       cur_wall_time = jiffies64_to_cputime64(get_jiffies_64());
+
+       busy_time = kcpustat_cpu(cpu).cpustat[CPUTIME_USER];
+       busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_SYSTEM];
+       busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_IRQ];
+       busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_SOFTIRQ];
+       busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_STEAL];
+       busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_NICE];
+
+       idle_time = cur_wall_time - busy_time;
+       if (wall)
+               *wall = cputime_to_usecs(cur_wall_time);
+
+       return cputime_to_usecs(idle_time);
+}
+
+cputime64_t get_cpu_idle_time(unsigned int cpu, cputime64_t *wall)
+{
+       u64 idle_time = get_cpu_idle_time_us(cpu, NULL);
+
+       if (idle_time == -1ULL)
+               return get_cpu_idle_time_jiffy(cpu, wall);
+       else
+               idle_time += get_cpu_iowait_time_us(cpu, wall);
+
+       return idle_time;
+}
+EXPORT_SYMBOL_GPL(get_cpu_idle_time);
index 396322f2a83ffc22fd6249a3133c588b195cf25b..d7f774bb49dd3f9aa699e5b328c46b5da2e828f5 100644 (file)
@@ -119,40 +119,6 @@ static struct dbs_tuners {
        .powersave_bias = 0,
 };
 
-static inline u64 get_cpu_idle_time_jiffy(unsigned int cpu, u64 *wall)
-{
-       u64 idle_time;
-       u64 cur_wall_time;
-       u64 busy_time;
-
-       cur_wall_time = jiffies64_to_cputime64(get_jiffies_64());
-
-       busy_time  = kcpustat_cpu(cpu).cpustat[CPUTIME_USER];
-       busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_SYSTEM];
-       busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_IRQ];
-       busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_SOFTIRQ];
-       busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_STEAL];
-       busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_NICE];
-
-       idle_time = cur_wall_time - busy_time;
-       if (wall)
-               *wall = jiffies_to_usecs(cur_wall_time);
-
-       return jiffies_to_usecs(idle_time);
-}
-
-static inline cputime64_t get_cpu_idle_time(unsigned int cpu, cputime64_t *wall)
-{
-       u64 idle_time = get_cpu_idle_time_us(cpu, NULL);
-
-       if (idle_time == -1ULL)
-               return get_cpu_idle_time_jiffy(cpu, wall);
-       else
-               idle_time += get_cpu_iowait_time_us(cpu, wall);
-
-       return idle_time;
-}
-
 static inline cputime64_t get_cpu_iowait_time(unsigned int cpu, cputime64_t *wall)
 {
        u64 iowait_time = get_cpu_iowait_time_us(cpu, wall);
index f13a8a9af6a130d999a3794588218ee652d5f076..ceee06849b9167bb63e423f2aee29ecba3751f57 100644 (file)
@@ -10,6 +10,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/cpufreq.h>
index 4c2eb512f2bc3a3da1921ffc4c3ebca61908cd19..2d948a1711551de4b1ad95b6fd5bbc455bccab36 100644 (file)
@@ -10,6 +10,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/cpufreq.h>
index b40ee1403be9b657ffcabd5142650ddb926fb367..399831690fedc18a263636a89725ec7b9af7dadb 100644 (file)
@@ -328,6 +328,7 @@ static int __cpuinit cpufreq_stat_cpu_callback(struct notifier_block *nfb,
                cpufreq_update_policy(cpu);
                break;
        case CPU_DOWN_PREPARE:
+       case CPU_DOWN_PREPARE_FROZEN:
                cpufreq_stats_free_sysfs(cpu);
                break;
        case CPU_DEAD:
index bedac1aa9be31919f74ea6e3788d47e64f1e3342..c8c3d293cc57239c1f7d1965000a64c183204de1 100644 (file)
@@ -11,6 +11,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/smp.h>
index 90431cb92804b5cb166c231acd709093cfcf6ff6..49cda256efb2149c2311e588d9cdb151f87dc103 100644 (file)
@@ -9,6 +9,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
index 129e80bfff22e1d399fbe5320012f5721de1bcaf..c16a3a593ba48801e188aff6196e38cc02702621 100644 (file)
@@ -1052,14 +1052,7 @@ static int powernowk8_target(struct cpufreq_policy *pol,
        struct powernowk8_target_arg pta = { .pol = pol, .targfreq = targfreq,
                                             .relation = relation };
 
-       /*
-        * Must run on @pol->cpu.  cpufreq core is responsible for ensuring
-        * that we're bound to the current CPU and pol->cpu stays online.
-        */
-       if (smp_processor_id() == pol->cpu)
-               return powernowk8_target_fn(&pta);
-       else
-               return work_on_cpu(pol->cpu, powernowk8_target_fn, &pta);
+       return work_on_cpu(pol->cpu, powernowk8_target_fn, &pta);
 }
 
 /* Driver entry point to verify the policy and range of frequencies */
index 7f15b8514a1899460e16c2fcf7505d038eafe2d7..ce4cac706dd163f3ff4fda3c8bcca4e2c24a983f 100644 (file)
@@ -144,6 +144,10 @@ int cpuidle_idle_call(void)
        /* ask the governor for the next state */
        next_state = cpuidle_curr_governor->select(drv, dev);
        if (need_resched()) {
+               dev->last_residency = 0;
+               /* give the governor an opportunity to reflect on the outcome */
+               if (cpuidle_curr_governor->reflect)
+                       cpuidle_curr_governor->reflect(dev, next_state);
                local_irq_enable();
                return 0;
        }
@@ -394,17 +398,14 @@ EXPORT_SYMBOL_GPL(cpuidle_disable_device);
 static int __cpuidle_register_device(struct cpuidle_device *dev)
 {
        int ret;
-       struct device *cpu_dev = get_cpu_device((unsigned long)dev->cpu);
        struct cpuidle_driver *cpuidle_driver = cpuidle_get_driver();
 
        if (!try_module_get(cpuidle_driver->owner))
                return -EINVAL;
 
-       init_completion(&dev->kobj_unregister);
-
        per_cpu(cpuidle_devices, dev->cpu) = dev;
        list_add(&dev->device_list, &cpuidle_detected_devices);
-       ret = cpuidle_add_sysfs(cpu_dev);
+       ret = cpuidle_add_sysfs(dev);
        if (ret)
                goto err_sysfs;
 
@@ -416,8 +417,7 @@ static int __cpuidle_register_device(struct cpuidle_device *dev)
        return 0;
 
 err_coupled:
-       cpuidle_remove_sysfs(cpu_dev);
-       wait_for_completion(&dev->kobj_unregister);
+       cpuidle_remove_sysfs(dev);
 err_sysfs:
        list_del(&dev->device_list);
        per_cpu(cpuidle_devices, dev->cpu) = NULL;
@@ -460,7 +460,6 @@ EXPORT_SYMBOL_GPL(cpuidle_register_device);
  */
 void cpuidle_unregister_device(struct cpuidle_device *dev)
 {
-       struct device *cpu_dev = get_cpu_device((unsigned long)dev->cpu);
        struct cpuidle_driver *cpuidle_driver = cpuidle_get_driver();
 
        if (dev->registered == 0)
@@ -470,9 +469,8 @@ void cpuidle_unregister_device(struct cpuidle_device *dev)
 
        cpuidle_disable_device(dev);
 
-       cpuidle_remove_sysfs(cpu_dev);
+       cpuidle_remove_sysfs(dev);
        list_del(&dev->device_list);
-       wait_for_completion(&dev->kobj_unregister);
        per_cpu(cpuidle_devices, dev->cpu) = NULL;
 
        cpuidle_coupled_unregister_device(dev);
index 76e7f696ad8c62862e5ae1ca555955f755f5c33e..a5bbd1cc40f774186a3be55370e5c465c862d694 100644 (file)
@@ -5,8 +5,6 @@
 #ifndef __DRIVER_CPUIDLE_H
 #define __DRIVER_CPUIDLE_H
 
-#include <linux/device.h>
-
 /* For internal use only */
 extern struct cpuidle_governor *cpuidle_curr_governor;
 extern struct list_head cpuidle_governors;
@@ -29,8 +27,8 @@ extern int cpuidle_add_interface(struct device *dev);
 extern void cpuidle_remove_interface(struct device *dev);
 extern int cpuidle_add_state_sysfs(struct cpuidle_device *device);
 extern void cpuidle_remove_state_sysfs(struct cpuidle_device *device);
-extern int cpuidle_add_sysfs(struct device *dev);
-extern void cpuidle_remove_sysfs(struct device *dev);
+extern int cpuidle_add_sysfs(struct cpuidle_device *dev);
+extern void cpuidle_remove_sysfs(struct cpuidle_device *dev);
 
 #ifdef CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED
 bool cpuidle_state_is_coupled(struct cpuidle_device *dev,
index 5b1f2c372c1f1956c73f3548a25f25a82997e9f2..2efee27714a047ae999f579263e7b4cd3571534b 100644 (file)
 #define MAX_INTERESTING 50000
 #define STDDEV_THRESH 400
 
+/* 60 * 60 > STDDEV_THRESH * INTERVALS = 400 * 8 */
+#define MAX_DEVIATION 60
+
+static DEFINE_PER_CPU(struct hrtimer, menu_hrtimer);
+static DEFINE_PER_CPU(int, hrtimer_status);
+/* menu hrtimer mode */
+enum {MENU_HRTIMER_STOP, MENU_HRTIMER_REPEAT, MENU_HRTIMER_GENERAL};
 
 /*
  * Concepts and ideas behind the menu governor
  *
  */
 
+/*
+ * The C-state residency is so long that is is worthwhile to exit
+ * from the shallow C-state and re-enter into a deeper C-state.
+ */
+static unsigned int perfect_cstate_ms __read_mostly = 30;
+module_param(perfect_cstate_ms, uint, 0000);
+
 struct menu_device {
        int             last_state_idx;
        int             needs_update;
@@ -191,40 +205,102 @@ static u64 div_round64(u64 dividend, u32 divisor)
        return div_u64(dividend + (divisor / 2), divisor);
 }
 
+/* Cancel the hrtimer if it is not triggered yet */
+void menu_hrtimer_cancel(void)
+{
+       int cpu = smp_processor_id();
+       struct hrtimer *hrtmr = &per_cpu(menu_hrtimer, cpu);
+
+       /* The timer is still not time out*/
+       if (per_cpu(hrtimer_status, cpu)) {
+               hrtimer_cancel(hrtmr);
+               per_cpu(hrtimer_status, cpu) = MENU_HRTIMER_STOP;
+       }
+}
+EXPORT_SYMBOL_GPL(menu_hrtimer_cancel);
+
+/* Call back for hrtimer is triggered */
+static enum hrtimer_restart menu_hrtimer_notify(struct hrtimer *hrtimer)
+{
+       int cpu = smp_processor_id();
+       struct menu_device *data = &per_cpu(menu_devices, cpu);
+
+       /* In general case, the expected residency is much larger than
+        *  deepest C-state target residency, but prediction logic still
+        *  predicts a small predicted residency, so the prediction
+        *  history is totally broken if the timer is triggered.
+        *  So reset the correction factor.
+        */
+       if (per_cpu(hrtimer_status, cpu) == MENU_HRTIMER_GENERAL)
+               data->correction_factor[data->bucket] = RESOLUTION * DECAY;
+
+       per_cpu(hrtimer_status, cpu) = MENU_HRTIMER_STOP;
+
+       return HRTIMER_NORESTART;
+}
+
 /*
  * Try detecting repeating patterns by keeping track of the last 8
  * intervals, and checking if the standard deviation of that set
  * of points is below a threshold. If it is... then use the
  * average of these 8 points as the estimated value.
  */
-static void detect_repeating_patterns(struct menu_device *data)
+static u32 get_typical_interval(struct menu_device *data)
 {
-       int i;
-       uint64_t avg = 0;
-       uint64_t stddev = 0; /* contains the square of the std deviation */
-
-       /* first calculate average and standard deviation of the past */
-       for (i = 0; i < INTERVALS; i++)
-               avg += data->intervals[i];
-       avg = avg / INTERVALS;
+       int i = 0, divisor = 0;
+       uint64_t max = 0, avg = 0, stddev = 0;
+       int64_t thresh = LLONG_MAX; /* Discard outliers above this value. */
+       unsigned int ret = 0;
 
-       /* if the avg is beyond the known next tick, it's worthless */
-       if (avg > data->expected_us)
-               return;
+again:
 
-       for (i = 0; i < INTERVALS; i++)
-               stddev += (data->intervals[i] - avg) *
-                         (data->intervals[i] - avg);
-
-       stddev = stddev / INTERVALS;
+       /* first calculate average and standard deviation of the past */
+       max = avg = divisor = stddev = 0;
+       for (i = 0; i < INTERVALS; i++) {
+               int64_t value = data->intervals[i];
+               if (value <= thresh) {
+                       avg += value;
+                       divisor++;
+                       if (value > max)
+                               max = value;
+               }
+       }
+       do_div(avg, divisor);
 
+       for (i = 0; i < INTERVALS; i++) {
+               int64_t value = data->intervals[i];
+               if (value <= thresh) {
+                       int64_t diff = value - avg;
+                       stddev += diff * diff;
+               }
+       }
+       do_div(stddev, divisor);
+       stddev = int_sqrt(stddev);
        /*
-        * now.. if stddev is small.. then assume we have a
-        * repeating pattern and predict we keep doing this.
+        * If we have outliers to the upside in our distribution, discard
+        * those by setting the threshold to exclude these outliers, then
+        * calculate the average and standard deviation again. Once we get
+        * down to the bottom 3/4 of our samples, stop excluding samples.
+        *
+        * This can deal with workloads that have long pauses interspersed
+        * with sporadic activity with a bunch of short pauses.
+        *
+        * The typical interval is obtained when standard deviation is small
+        * or standard deviation is small compared to the average interval.
         */
-
-       if (avg && stddev < STDDEV_THRESH)
+       if (((avg > stddev * 6) && (divisor * 4 >= INTERVALS * 3))
+                                                       || stddev <= 20) {
                data->predicted_us = avg;
+               ret = 1;
+               return ret;
+
+       } else if ((divisor * 4) > INTERVALS * 3) {
+               /* Exclude the max interval */
+               thresh = max - 1;
+               goto again;
+       }
+
+       return ret;
 }
 
 /**
@@ -240,6 +316,9 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev)
        int i;
        int multiplier;
        struct timespec t;
+       int repeat = 0, low_predicted = 0;
+       int cpu = smp_processor_id();
+       struct hrtimer *hrtmr = &per_cpu(menu_hrtimer, cpu);
 
        if (data->needs_update) {
                menu_update(drv, dev);
@@ -274,7 +353,7 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev)
        data->predicted_us = div_round64(data->expected_us * data->correction_factor[data->bucket],
                                         RESOLUTION * DECAY);
 
-       detect_repeating_patterns(data);
+       repeat = get_typical_interval(data);
 
        /*
         * We want to default to C1 (hlt), not to busy polling
@@ -295,8 +374,10 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev)
 
                if (s->disabled || su->disable)
                        continue;
-               if (s->target_residency > data->predicted_us)
+               if (s->target_residency > data->predicted_us) {
+                       low_predicted = 1;
                        continue;
+               }
                if (s->exit_latency > latency_req)
                        continue;
                if (s->exit_latency * multiplier > data->predicted_us)
@@ -309,6 +390,42 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev)
                }
        }
 
+       /* not deepest C-state chosen for low predicted residency */
+       if (low_predicted) {
+               unsigned int timer_us = 0;
+               unsigned int perfect_us = 0;
+
+               /*
+                * Set a timer to detect whether this sleep is much
+                * longer than repeat mode predicted.  If the timer
+                * triggers, the code will evaluate whether to put
+                * the CPU into a deeper C-state.
+                * The timer is cancelled on CPU wakeup.
+                */
+               timer_us = 2 * (data->predicted_us + MAX_DEVIATION);
+
+               perfect_us = perfect_cstate_ms * 1000;
+
+               if (repeat && (4 * timer_us < data->expected_us)) {
+                       hrtimer_start(hrtmr, ns_to_ktime(1000 * timer_us),
+                               HRTIMER_MODE_REL_PINNED);
+                       /* In repeat case, menu hrtimer is started */
+                       per_cpu(hrtimer_status, cpu) = MENU_HRTIMER_REPEAT;
+               } else if (perfect_us < data->expected_us) {
+                       /*
+                        * The next timer is long. This could be because
+                        * we did not make a useful prediction.
+                        * In that case, it makes sense to re-enter
+                        * into a deeper C-state after some time.
+                        */
+                       hrtimer_start(hrtmr, ns_to_ktime(1000 * timer_us),
+                               HRTIMER_MODE_REL_PINNED);
+                       /* In general case, menu hrtimer is started */
+                       per_cpu(hrtimer_status, cpu) = MENU_HRTIMER_GENERAL;
+               }
+
+       }
+
        return data->last_state_idx;
 }
 
@@ -399,6 +516,9 @@ static int menu_enable_device(struct cpuidle_driver *drv,
                                struct cpuidle_device *dev)
 {
        struct menu_device *data = &per_cpu(menu_devices, dev->cpu);
+       struct hrtimer *t = &per_cpu(menu_hrtimer, dev->cpu);
+       hrtimer_init(t, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+       t->function = menu_hrtimer_notify;
 
        memset(data, 0, sizeof(struct menu_device));
 
index 5f809e337b89d04dde3d2cb3ffee098e6dff6e86..ed87399bb02b0101b32cd1d9ae5cf2c34282f189 100644 (file)
@@ -374,8 +374,8 @@ int cpuidle_add_state_sysfs(struct cpuidle_device *device)
                kobj->state_usage = &device->states_usage[i];
                init_completion(&kobj->kobj_unregister);
 
-               ret = kobject_init_and_add(&kobj->kobj, &ktype_state_cpuidle, &device->kobj,
-                                          "state%d", i);
+               ret = kobject_init_and_add(&kobj->kobj, &ktype_state_cpuidle,
+                                          &device->kobj, "state%d", i);
                if (ret) {
                        kfree(kobj);
                        goto error_state;
@@ -408,13 +408,13 @@ void cpuidle_remove_state_sysfs(struct cpuidle_device *device)
  * cpuidle_add_sysfs - creates a sysfs instance for the target device
  * @dev: the target device
  */
-int cpuidle_add_sysfs(struct device *cpu_dev)
+int cpuidle_add_sysfs(struct cpuidle_device *dev)
 {
-       int cpu = cpu_dev->id;
-       struct cpuidle_device *dev;
+       struct device *cpu_dev = get_cpu_device((unsigned long)dev->cpu);
        int error;
 
-       dev = per_cpu(cpuidle_devices, cpu);
+       init_completion(&dev->kobj_unregister);
+
        error = kobject_init_and_add(&dev->kobj, &ktype_cpuidle, &cpu_dev->kobj,
                                     "cpuidle");
        if (!error)
@@ -426,11 +426,8 @@ int cpuidle_add_sysfs(struct device *cpu_dev)
  * cpuidle_remove_sysfs - deletes a sysfs instance on the target device
  * @dev: the target device
  */
-void cpuidle_remove_sysfs(struct device *cpu_dev)
+void cpuidle_remove_sysfs(struct cpuidle_device *dev)
 {
-       int cpu = cpu_dev->id;
-       struct cpuidle_device *dev;
-
-       dev = per_cpu(cpuidle_devices, cpu);
        kobject_put(&dev->kobj);
+       wait_for_completion(&dev->kobj_unregister);
 }
index 308c7fb92a60b25a27d92ef11a9acbe80f23b921..f6644f59fd9da1042cec58487791f689d7ed127a 100644 (file)
@@ -224,7 +224,7 @@ config CRYPTO_DEV_TALITOS
 
 config CRYPTO_DEV_IXP4XX
        tristate "Driver for IXP4xx crypto hardware acceleration"
-       depends on ARCH_IXP4XX
+       depends on ARCH_IXP4XX && IXP4XX_QMGR && IXP4XX_NPE
        select CRYPTO_DES
        select CRYPTO_ALGAPI
        select CRYPTO_AUTHENC
index 8f3f74ce8c7fd7ac95e241c2c4504f06a52da38c..21180d6cad6e27f2f316a04b1e98fb2e61ac90d3 100644 (file)
@@ -750,12 +750,12 @@ static int setup_cipher(struct crypto_tfm *tfm, int encrypt,
        }
        if (cipher_cfg & MOD_AES) {
                switch (key_len) {
-                       case 16: keylen_cfg = MOD_AES128 | KEYLEN_128; break;
-                       case 24: keylen_cfg = MOD_AES192 | KEYLEN_192; break;
-                       case 32: keylen_cfg = MOD_AES256 | KEYLEN_256; break;
-                       default:
-                               *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
-                               return -EINVAL;
+               case 16: keylen_cfg = MOD_AES128; break;
+               case 24: keylen_cfg = MOD_AES192; break;
+               case 32: keylen_cfg = MOD_AES256; break;
+               default:
+                       *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+                       return -EINVAL;
                }
                cipher_cfg |= keylen_cfg;
        } else if (cipher_cfg & MOD_3DES) {
index da1112765a4465066ecff9bba2ad52900d19944d..09b184adf31b73902a98651843805e0c129c15b9 100644 (file)
@@ -936,8 +936,7 @@ static int sg_to_link_tbl(struct scatterlist *sg, int sg_count,
                sg_count--;
                link_tbl_ptr--;
        }
-       link_tbl_ptr->len = cpu_to_be16(be16_to_cpu(link_tbl_ptr->len)
-                                       + cryptlen);
+       be16_add_cpu(&link_tbl_ptr->len, cryptlen);
 
        /* tag end of link table */
        link_tbl_ptr->j_extent = DESC_PTR_LNKTBL_RETURN;
index 37185e6630cd77617f176d7387bad1c92ee396b9..2a91145bf9f34067ae4cdd1f4faacea31d367683 100644 (file)
@@ -41,8 +41,6 @@
 #include <linux/completion.h>
 #include <linux/workqueue.h>
 
-#include <mach/clk.h>
-
 #include <crypto/scatterwalk.h>
 #include <crypto/aes.h>
 #include <crypto/internal/rng.h>
@@ -674,8 +672,10 @@ static int tegra_aes_get_random(struct crypto_rng *tfm, u8 *rdata,
        mutex_lock(&aes_lock);
 
        ret = clk_prepare_enable(dd->aes_clk);
-       if (ret)
+       if (ret) {
+               mutex_unlock(&aes_lock);
                return ret;
+       }
 
        ctx->dd = dd;
        dd->ctx = ctx;
@@ -759,8 +759,10 @@ static int tegra_aes_rng_reset(struct crypto_rng *tfm, u8 *seed,
        dd->flags = FLAGS_ENCRYPT | FLAGS_RNG;
 
        ret = clk_prepare_enable(dd->aes_clk);
-       if (ret)
+       if (ret) {
+               mutex_unlock(&aes_lock);
                return ret;
+       }
 
        aes_set_key(dd);
 
index b146d76f04cfaf9361f3e9ebd767d5c99e8e45d6..49afbae43a9a103fdaec9c9f1b8c8b240d7973ca 100644 (file)
 #include <linux/hrtimer.h>
 #include "governor.h"
 
-struct class *devfreq_class;
+static struct class *devfreq_class;
 
 /*
- * devfreq_work periodically monitors every registered device.
- * The minimum polling interval is one jiffy. The polling interval is
- * determined by the minimum polling period among all polling devfreq
- * devices. The resolution of polling interval is one jiffy.
+ * devfreq core provides delayed work based load monitoring helper
+ * functions. Governors can use these or can implement their own
+ * monitoring mechanism.
  */
-static bool polling;
 static struct workqueue_struct *devfreq_wq;
-static struct delayed_work devfreq_work;
-
-/* wait removing if this is to be removed */
-static struct devfreq *wait_remove_device;
 
 /* The list of all device-devfreq */
 static LIST_HEAD(devfreq_list);
@@ -72,6 +66,8 @@ static struct devfreq *find_device_devfreq(struct device *dev)
        return ERR_PTR(-ENODEV);
 }
 
+/* Load monitoring helper functions for governors use */
+
 /**
  * update_devfreq() - Reevaluate the device and configure frequency.
  * @devfreq:   the devfreq instance.
@@ -120,12 +116,158 @@ int update_devfreq(struct devfreq *devfreq)
        return err;
 }
 
+/**
+ * devfreq_monitor() - Periodically poll devfreq objects.
+ * @work:      the work struct used to run devfreq_monitor periodically.
+ *
+ */
+static void devfreq_monitor(struct work_struct *work)
+{
+       int err;
+       struct devfreq *devfreq = container_of(work,
+                                       struct devfreq, work.work);
+
+       mutex_lock(&devfreq->lock);
+       err = update_devfreq(devfreq);
+       if (err)
+               dev_err(&devfreq->dev, "dvfs failed with (%d) error\n", err);
+
+       queue_delayed_work(devfreq_wq, &devfreq->work,
+                               msecs_to_jiffies(devfreq->profile->polling_ms));
+       mutex_unlock(&devfreq->lock);
+}
+
+/**
+ * devfreq_monitor_start() - Start load monitoring of devfreq instance
+ * @devfreq:   the devfreq instance.
+ *
+ * Helper function for starting devfreq device load monitoing. By
+ * default delayed work based monitoring is supported. Function
+ * to be called from governor in response to DEVFREQ_GOV_START
+ * event when device is added to devfreq framework.
+ */
+void devfreq_monitor_start(struct devfreq *devfreq)
+{
+       INIT_DEFERRABLE_WORK(&devfreq->work, devfreq_monitor);
+       if (devfreq->profile->polling_ms)
+               queue_delayed_work(devfreq_wq, &devfreq->work,
+                       msecs_to_jiffies(devfreq->profile->polling_ms));
+}
+
+/**
+ * devfreq_monitor_stop() - Stop load monitoring of a devfreq instance
+ * @devfreq:   the devfreq instance.
+ *
+ * Helper function to stop devfreq device load monitoing. Function
+ * to be called from governor in response to DEVFREQ_GOV_STOP
+ * event when device is removed from devfreq framework.
+ */
+void devfreq_monitor_stop(struct devfreq *devfreq)
+{
+       cancel_delayed_work_sync(&devfreq->work);
+}
+
+/**
+ * devfreq_monitor_suspend() - Suspend load monitoring of a devfreq instance
+ * @devfreq:   the devfreq instance.
+ *
+ * Helper function to suspend devfreq device load monitoing. Function
+ * to be called from governor in response to DEVFREQ_GOV_SUSPEND
+ * event or when polling interval is set to zero.
+ *
+ * Note: Though this function is same as devfreq_monitor_stop(),
+ * intentionally kept separate to provide hooks for collecting
+ * transition statistics.
+ */
+void devfreq_monitor_suspend(struct devfreq *devfreq)
+{
+       mutex_lock(&devfreq->lock);
+       if (devfreq->stop_polling) {
+               mutex_unlock(&devfreq->lock);
+               return;
+       }
+
+       devfreq->stop_polling = true;
+       mutex_unlock(&devfreq->lock);
+       cancel_delayed_work_sync(&devfreq->work);
+}
+
+/**
+ * devfreq_monitor_resume() - Resume load monitoring of a devfreq instance
+ * @devfreq:    the devfreq instance.
+ *
+ * Helper function to resume devfreq device load monitoing. Function
+ * to be called from governor in response to DEVFREQ_GOV_RESUME
+ * event or when polling interval is set to non-zero.
+ */
+void devfreq_monitor_resume(struct devfreq *devfreq)
+{
+       mutex_lock(&devfreq->lock);
+       if (!devfreq->stop_polling)
+               goto out;
+
+       if (!delayed_work_pending(&devfreq->work) &&
+                       devfreq->profile->polling_ms)
+               queue_delayed_work(devfreq_wq, &devfreq->work,
+                       msecs_to_jiffies(devfreq->profile->polling_ms));
+       devfreq->stop_polling = false;
+
+out:
+       mutex_unlock(&devfreq->lock);
+}
+
+/**
+ * devfreq_interval_update() - Update device devfreq monitoring interval
+ * @devfreq:    the devfreq instance.
+ * @delay:      new polling interval to be set.
+ *
+ * Helper function to set new load monitoring polling interval. Function
+ * to be called from governor in response to DEVFREQ_GOV_INTERVAL event.
+ */
+void devfreq_interval_update(struct devfreq *devfreq, unsigned int *delay)
+{
+       unsigned int cur_delay = devfreq->profile->polling_ms;
+       unsigned int new_delay = *delay;
+
+       mutex_lock(&devfreq->lock);
+       devfreq->profile->polling_ms = new_delay;
+
+       if (devfreq->stop_polling)
+               goto out;
+
+       /* if new delay is zero, stop polling */
+       if (!new_delay) {
+               mutex_unlock(&devfreq->lock);
+               cancel_delayed_work_sync(&devfreq->work);
+               return;
+       }
+
+       /* if current delay is zero, start polling with new delay */
+       if (!cur_delay) {
+               queue_delayed_work(devfreq_wq, &devfreq->work,
+                       msecs_to_jiffies(devfreq->profile->polling_ms));
+               goto out;
+       }
+
+       /* if current delay is greater than new delay, restart polling */
+       if (cur_delay > new_delay) {
+               mutex_unlock(&devfreq->lock);
+               cancel_delayed_work_sync(&devfreq->work);
+               mutex_lock(&devfreq->lock);
+               if (!devfreq->stop_polling)
+                       queue_delayed_work(devfreq_wq, &devfreq->work,
+                             msecs_to_jiffies(devfreq->profile->polling_ms));
+       }
+out:
+       mutex_unlock(&devfreq->lock);
+}
+
 /**
  * devfreq_notifier_call() - Notify that the device frequency requirements
  *                        has been changed out of devfreq framework.
- * @nb         the notifier_block (supposed to be devfreq->nb)
- * @type       not used
- * @devp       not used
+ * @nb:                the notifier_block (supposed to be devfreq->nb)
+ * @type:      not used
+ * @devp:      not used
  *
  * Called by a notifier that uses devfreq->nb.
  */
@@ -143,59 +285,33 @@ static int devfreq_notifier_call(struct notifier_block *nb, unsigned long type,
 }
 
 /**
- * _remove_devfreq() - Remove devfreq from the device.
+ * _remove_devfreq() - Remove devfreq from the devfreq list and
+               release its resources.
  * @devfreq:   the devfreq struct
  * @skip:      skip calling device_unregister().
- *
- * Note that the caller should lock devfreq->lock before calling
- * this. _remove_devfreq() will unlock it and free devfreq
- * internally. devfreq_list_lock should be locked by the caller
- * as well (not relased at return)
- *
- * Lock usage:
- * devfreq->lock: locked before call.
- *               unlocked at return (and freed)
- * devfreq_list_lock: locked before call.
- *                   kept locked at return.
- *                   if devfreq is centrally polled.
- *
- * Freed memory:
- * devfreq
  */
 static void _remove_devfreq(struct devfreq *devfreq, bool skip)
 {
-       if (!mutex_is_locked(&devfreq->lock)) {
-               WARN(true, "devfreq->lock must be locked by the caller.\n");
-               return;
-       }
-       if (!devfreq->governor->no_central_polling &&
-           !mutex_is_locked(&devfreq_list_lock)) {
-               WARN(true, "devfreq_list_lock must be locked by the caller.\n");
+       mutex_lock(&devfreq_list_lock);
+       if (IS_ERR(find_device_devfreq(devfreq->dev.parent))) {
+               mutex_unlock(&devfreq_list_lock);
+               dev_warn(&devfreq->dev, "releasing devfreq which doesn't exist\n");
                return;
        }
+       list_del(&devfreq->node);
+       mutex_unlock(&devfreq_list_lock);
 
-       if (devfreq->being_removed)
-               return;
-
-       devfreq->being_removed = true;
+       devfreq->governor->event_handler(devfreq, DEVFREQ_GOV_STOP, NULL);
 
        if (devfreq->profile->exit)
                devfreq->profile->exit(devfreq->dev.parent);
 
-       if (devfreq->governor->exit)
-               devfreq->governor->exit(devfreq);
-
        if (!skip && get_device(&devfreq->dev)) {
                device_unregister(&devfreq->dev);
                put_device(&devfreq->dev);
        }
 
-       if (!devfreq->governor->no_central_polling)
-               list_del(&devfreq->node);
-
-       mutex_unlock(&devfreq->lock);
        mutex_destroy(&devfreq->lock);
-
        kfree(devfreq);
 }
 
@@ -210,130 +326,8 @@ static void _remove_devfreq(struct devfreq *devfreq, bool skip)
 static void devfreq_dev_release(struct device *dev)
 {
        struct devfreq *devfreq = to_devfreq(dev);
-       bool central_polling = !devfreq->governor->no_central_polling;
 
-       /*
-        * If devfreq_dev_release() was called by device_unregister() of
-        * _remove_devfreq(), we cannot mutex_lock(&devfreq->lock) and
-        * being_removed is already set. This also partially checks the case
-        * where devfreq_dev_release() is called from a thread other than
-        * the one called _remove_devfreq(); however, this case is
-        * dealt completely with another following being_removed check.
-        *
-        * Because being_removed is never being
-        * unset, we do not need to worry about race conditions on
-        * being_removed.
-        */
-       if (devfreq->being_removed)
-               return;
-
-       if (central_polling)
-               mutex_lock(&devfreq_list_lock);
-
-       mutex_lock(&devfreq->lock);
-
-       /*
-        * Check being_removed flag again for the case where
-        * devfreq_dev_release() was called in a thread other than the one
-        * possibly called _remove_devfreq().
-        */
-       if (devfreq->being_removed) {
-               mutex_unlock(&devfreq->lock);
-               goto out;
-       }
-
-       /* devfreq->lock is unlocked and removed in _removed_devfreq() */
        _remove_devfreq(devfreq, true);
-
-out:
-       if (central_polling)
-               mutex_unlock(&devfreq_list_lock);
-}
-
-/**
- * devfreq_monitor() - Periodically poll devfreq objects.
- * @work: the work struct used to run devfreq_monitor periodically.
- *
- */
-static void devfreq_monitor(struct work_struct *work)
-{
-       static unsigned long last_polled_at;
-       struct devfreq *devfreq, *tmp;
-       int error;
-       unsigned long jiffies_passed;
-       unsigned long next_jiffies = ULONG_MAX, now = jiffies;
-       struct device *dev;
-
-       /* Initially last_polled_at = 0, polling every device at bootup */
-       jiffies_passed = now - last_polled_at;
-       last_polled_at = now;
-       if (jiffies_passed == 0)
-               jiffies_passed = 1;
-
-       mutex_lock(&devfreq_list_lock);
-       list_for_each_entry_safe(devfreq, tmp, &devfreq_list, node) {
-               mutex_lock(&devfreq->lock);
-               dev = devfreq->dev.parent;
-
-               /* Do not remove tmp for a while */
-               wait_remove_device = tmp;
-
-               if (devfreq->governor->no_central_polling ||
-                   devfreq->next_polling == 0) {
-                       mutex_unlock(&devfreq->lock);
-                       continue;
-               }
-               mutex_unlock(&devfreq_list_lock);
-
-               /*
-                * Reduce more next_polling if devfreq_wq took an extra
-                * delay. (i.e., CPU has been idled.)
-                */
-               if (devfreq->next_polling <= jiffies_passed) {
-                       error = update_devfreq(devfreq);
-
-                       /* Remove a devfreq with an error. */
-                       if (error && error != -EAGAIN) {
-
-                               dev_err(dev, "Due to update_devfreq error(%d), devfreq(%s) is removed from the device\n",
-                                       error, devfreq->governor->name);
-
-                               /*
-                                * Unlock devfreq before locking the list
-                                * in order to avoid deadlock with
-                                * find_device_devfreq or others
-                                */
-                               mutex_unlock(&devfreq->lock);
-                               mutex_lock(&devfreq_list_lock);
-                               /* Check if devfreq is already removed */
-                               if (IS_ERR(find_device_devfreq(dev)))
-                                       continue;
-                               mutex_lock(&devfreq->lock);
-                               /* This unlocks devfreq->lock and free it */
-                               _remove_devfreq(devfreq, false);
-                               continue;
-                       }
-                       devfreq->next_polling = devfreq->polling_jiffies;
-               } else {
-                       devfreq->next_polling -= jiffies_passed;
-               }
-
-               if (devfreq->next_polling)
-                       next_jiffies = (next_jiffies > devfreq->next_polling) ?
-                                       devfreq->next_polling : next_jiffies;
-
-               mutex_unlock(&devfreq->lock);
-               mutex_lock(&devfreq_list_lock);
-       }
-       wait_remove_device = NULL;
-       mutex_unlock(&devfreq_list_lock);
-
-       if (next_jiffies > 0 && next_jiffies < ULONG_MAX) {
-               polling = true;
-               queue_delayed_work(devfreq_wq, &devfreq_work, next_jiffies);
-       } else {
-               polling = false;
-       }
 }
 
 /**
@@ -357,16 +351,13 @@ struct devfreq *devfreq_add_device(struct device *dev,
                return ERR_PTR(-EINVAL);
        }
 
-
-       if (!governor->no_central_polling) {
-               mutex_lock(&devfreq_list_lock);
-               devfreq = find_device_devfreq(dev);
-               mutex_unlock(&devfreq_list_lock);
-               if (!IS_ERR(devfreq)) {
-                       dev_err(dev, "%s: Unable to create devfreq for the device. It already has one.\n", __func__);
-                       err = -EINVAL;
-                       goto err_out;
-               }
+       mutex_lock(&devfreq_list_lock);
+       devfreq = find_device_devfreq(dev);
+       mutex_unlock(&devfreq_list_lock);
+       if (!IS_ERR(devfreq)) {
+               dev_err(dev, "%s: Unable to create devfreq for the device. It already has one.\n", __func__);
+               err = -EINVAL;
+               goto err_out;
        }
 
        devfreq = kzalloc(sizeof(struct devfreq), GFP_KERNEL);
@@ -386,79 +377,84 @@ struct devfreq *devfreq_add_device(struct device *dev,
        devfreq->governor = governor;
        devfreq->previous_freq = profile->initial_freq;
        devfreq->data = data;
-       devfreq->next_polling = devfreq->polling_jiffies
-                             = msecs_to_jiffies(devfreq->profile->polling_ms);
        devfreq->nb.notifier_call = devfreq_notifier_call;
 
        dev_set_name(&devfreq->dev, dev_name(dev));
        err = device_register(&devfreq->dev);
        if (err) {
                put_device(&devfreq->dev);
+               mutex_unlock(&devfreq->lock);
                goto err_dev;
        }
 
-       if (governor->init)
-               err = governor->init(devfreq);
-       if (err)
-               goto err_init;
-
        mutex_unlock(&devfreq->lock);
 
-       if (governor->no_central_polling)
-               goto out;
-
        mutex_lock(&devfreq_list_lock);
-
        list_add(&devfreq->node, &devfreq_list);
+       mutex_unlock(&devfreq_list_lock);
 
-       if (devfreq_wq && devfreq->next_polling && !polling) {
-               polling = true;
-               queue_delayed_work(devfreq_wq, &devfreq_work,
-                                  devfreq->next_polling);
+       err = devfreq->governor->event_handler(devfreq,
+                               DEVFREQ_GOV_START, NULL);
+       if (err) {
+               dev_err(dev, "%s: Unable to start governor for the device\n",
+                       __func__);
+               goto err_init;
        }
-       mutex_unlock(&devfreq_list_lock);
-out:
+
        return devfreq;
 
 err_init:
+       list_del(&devfreq->node);
        device_unregister(&devfreq->dev);
 err_dev:
-       mutex_unlock(&devfreq->lock);
        kfree(devfreq);
 err_out:
        return ERR_PTR(err);
 }
+EXPORT_SYMBOL(devfreq_add_device);
 
 /**
  * devfreq_remove_device() - Remove devfreq feature from a device.
- * @devfreq    the devfreq instance to be removed
+ * @devfreq:   the devfreq instance to be removed
  */
 int devfreq_remove_device(struct devfreq *devfreq)
 {
-       bool central_polling;
-
        if (!devfreq)
                return -EINVAL;
 
-       central_polling = !devfreq->governor->no_central_polling;
+       _remove_devfreq(devfreq, false);
 
-       if (central_polling) {
-               mutex_lock(&devfreq_list_lock);
-               while (wait_remove_device == devfreq) {
-                       mutex_unlock(&devfreq_list_lock);
-                       schedule();
-                       mutex_lock(&devfreq_list_lock);
-               }
-       }
+       return 0;
+}
+EXPORT_SYMBOL(devfreq_remove_device);
 
-       mutex_lock(&devfreq->lock);
-       _remove_devfreq(devfreq, false); /* it unlocks devfreq->lock */
+/**
+ * devfreq_suspend_device() - Suspend devfreq of a device.
+ * @devfreq    the devfreq instance to be suspended
+ */
+int devfreq_suspend_device(struct devfreq *devfreq)
+{
+       if (!devfreq)
+               return -EINVAL;
 
-       if (central_polling)
-               mutex_unlock(&devfreq_list_lock);
+       return devfreq->governor->event_handler(devfreq,
+                               DEVFREQ_GOV_SUSPEND, NULL);
+}
+EXPORT_SYMBOL(devfreq_suspend_device);
 
-       return 0;
+/**
+ * devfreq_resume_device() - Resume devfreq of a device.
+ * @devfreq    the devfreq instance to be resumed
+ */
+int devfreq_resume_device(struct devfreq *devfreq)
+{
+       if (!devfreq)
+               return -EINVAL;
+
+       return devfreq->governor->event_handler(devfreq,
+                               DEVFREQ_GOV_RESUME, NULL);
 }
+EXPORT_SYMBOL(devfreq_resume_device);
 
 static ssize_t show_governor(struct device *dev,
                             struct device_attribute *attr, char *buf)
@@ -468,6 +464,19 @@ static ssize_t show_governor(struct device *dev,
 
 static ssize_t show_freq(struct device *dev,
                         struct device_attribute *attr, char *buf)
+{
+       unsigned long freq;
+       struct devfreq *devfreq = to_devfreq(dev);
+
+       if (devfreq->profile->get_cur_freq &&
+               !devfreq->profile->get_cur_freq(devfreq->dev.parent, &freq))
+                       return sprintf(buf, "%lu\n", freq);
+
+       return sprintf(buf, "%lu\n", devfreq->previous_freq);
+}
+
+static ssize_t show_target_freq(struct device *dev,
+                       struct device_attribute *attr, char *buf)
 {
        return sprintf(buf, "%lu\n", to_devfreq(dev)->previous_freq);
 }
@@ -488,37 +497,14 @@ static ssize_t store_polling_interval(struct device *dev,
 
        ret = sscanf(buf, "%u", &value);
        if (ret != 1)
-               goto out;
-
-       mutex_lock(&df->lock);
-       df->profile->polling_ms = value;
-       df->next_polling = df->polling_jiffies
-                        = msecs_to_jiffies(value);
-       mutex_unlock(&df->lock);
+               return -EINVAL;
 
+       df->governor->event_handler(df, DEVFREQ_GOV_INTERVAL, &value);
        ret = count;
 
-       if (df->governor->no_central_polling)
-               goto out;
-
-       mutex_lock(&devfreq_list_lock);
-       if (df->next_polling > 0 && !polling) {
-               polling = true;
-               queue_delayed_work(devfreq_wq, &devfreq_work,
-                                  df->next_polling);
-       }
-       mutex_unlock(&devfreq_list_lock);
-out:
        return ret;
 }
 
-static ssize_t show_central_polling(struct device *dev,
-                                   struct device_attribute *attr, char *buf)
-{
-       return sprintf(buf, "%d\n",
-                      !to_devfreq(dev)->governor->no_central_polling);
-}
-
 static ssize_t store_min_freq(struct device *dev, struct device_attribute *attr,
                              const char *buf, size_t count)
 {
@@ -529,7 +515,7 @@ static ssize_t store_min_freq(struct device *dev, struct device_attribute *attr,
 
        ret = sscanf(buf, "%lu", &value);
        if (ret != 1)
-               goto out;
+               return -EINVAL;
 
        mutex_lock(&df->lock);
        max = df->max_freq;
@@ -543,7 +529,6 @@ static ssize_t store_min_freq(struct device *dev, struct device_attribute *attr,
        ret = count;
 unlock:
        mutex_unlock(&df->lock);
-out:
        return ret;
 }
 
@@ -563,7 +548,7 @@ static ssize_t store_max_freq(struct device *dev, struct device_attribute *attr,
 
        ret = sscanf(buf, "%lu", &value);
        if (ret != 1)
-               goto out;
+               return -EINVAL;
 
        mutex_lock(&df->lock);
        min = df->min_freq;
@@ -577,7 +562,6 @@ static ssize_t store_max_freq(struct device *dev, struct device_attribute *attr,
        ret = count;
 unlock:
        mutex_unlock(&df->lock);
-out:
        return ret;
 }
 
@@ -590,7 +574,7 @@ static ssize_t show_max_freq(struct device *dev, struct device_attribute *attr,
 static struct device_attribute devfreq_attrs[] = {
        __ATTR(governor, S_IRUGO, show_governor, NULL),
        __ATTR(cur_freq, S_IRUGO, show_freq, NULL),
-       __ATTR(central_polling, S_IRUGO, show_central_polling, NULL),
+       __ATTR(target_freq, S_IRUGO, show_target_freq, NULL),
        __ATTR(polling_interval, S_IRUGO | S_IWUSR, show_polling_interval,
               store_polling_interval),
        __ATTR(min_freq, S_IRUGO | S_IWUSR, show_min_freq, store_min_freq),
@@ -598,23 +582,6 @@ static struct device_attribute devfreq_attrs[] = {
        { },
 };
 
-/**
- * devfreq_start_polling() - Initialize data structure for devfreq framework and
- *                        start polling registered devfreq devices.
- */
-static int __init devfreq_start_polling(void)
-{
-       mutex_lock(&devfreq_list_lock);
-       polling = false;
-       devfreq_wq = create_freezable_workqueue("devfreq_wq");
-       INIT_DEFERRABLE_WORK(&devfreq_work, devfreq_monitor);
-       mutex_unlock(&devfreq_list_lock);
-
-       devfreq_monitor(&devfreq_work.work);
-       return 0;
-}
-late_initcall(devfreq_start_polling);
-
 static int __init devfreq_init(void)
 {
        devfreq_class = class_create(THIS_MODULE, "devfreq");
@@ -622,7 +589,15 @@ static int __init devfreq_init(void)
                pr_err("%s: couldn't create class\n", __FILE__);
                return PTR_ERR(devfreq_class);
        }
+
+       devfreq_wq = create_freezable_workqueue("devfreq_wq");
+       if (IS_ERR(devfreq_wq)) {
+               class_destroy(devfreq_class);
+               pr_err("%s: couldn't create workqueue\n", __FILE__);
+               return PTR_ERR(devfreq_wq);
+       }
        devfreq_class->dev_attrs = devfreq_attrs;
+
        return 0;
 }
 subsys_initcall(devfreq_init);
@@ -630,6 +605,7 @@ subsys_initcall(devfreq_init);
 static void __exit devfreq_exit(void)
 {
        class_destroy(devfreq_class);
+       destroy_workqueue(devfreq_wq);
 }
 module_exit(devfreq_exit);
 
@@ -641,9 +617,9 @@ module_exit(devfreq_exit);
 /**
  * devfreq_recommended_opp() - Helper function to get proper OPP for the
  *                          freq value given to target callback.
- * @dev                The devfreq user device. (parent of devfreq)
- * @freq       The frequency given to target function
- * @flags      Flags handed from devfreq framework.
+ * @dev:       The devfreq user device. (parent of devfreq)
+ * @freq:      The frequency given to target function
+ * @flags:     Flags handed from devfreq framework.
  *
  */
 struct opp *devfreq_recommended_opp(struct device *dev, unsigned long *freq,
@@ -656,14 +632,14 @@ struct opp *devfreq_recommended_opp(struct device *dev, unsigned long *freq,
                opp = opp_find_freq_floor(dev, freq);
 
                /* If not available, use the closest opp */
-               if (opp == ERR_PTR(-ENODEV))
+               if (opp == ERR_PTR(-ERANGE))
                        opp = opp_find_freq_ceil(dev, freq);
        } else {
                /* The freq is an lower bound. opp should be higher */
                opp = opp_find_freq_ceil(dev, freq);
 
                /* If not available, use the closest opp */
-               if (opp == ERR_PTR(-ENODEV))
+               if (opp == ERR_PTR(-ERANGE))
                        opp = opp_find_freq_floor(dev, freq);
        }
 
@@ -674,8 +650,8 @@ struct opp *devfreq_recommended_opp(struct device *dev, unsigned long *freq,
  * devfreq_register_opp_notifier() - Helper function to get devfreq notified
  *                                for any changes in the OPP availability
  *                                changes
- * @dev                The devfreq user device. (parent of devfreq)
- * @devfreq    The devfreq object.
+ * @dev:       The devfreq user device. (parent of devfreq)
+ * @devfreq:   The devfreq object.
  */
 int devfreq_register_opp_notifier(struct device *dev, struct devfreq *devfreq)
 {
@@ -690,8 +666,8 @@ int devfreq_register_opp_notifier(struct device *dev, struct devfreq *devfreq)
  * devfreq_unregister_opp_notifier() - Helper function to stop getting devfreq
  *                                  notified for any changes in the OPP
  *                                  availability changes anymore.
- * @dev                The devfreq user device. (parent of devfreq)
- * @devfreq    The devfreq object.
+ * @dev:       The devfreq user device. (parent of devfreq)
+ * @devfreq:   The devfreq object.
  *
  * At exit() callback of devfreq_dev_profile, this must be included if
  * devfreq_recommended_opp is used.
index ea7f13c58dedf332c809dcc53351a196d1baa5fa..26432ac0a398f069c747a16cda78e6241ac7cfc3 100644 (file)
 
 #define to_devfreq(DEV)        container_of((DEV), struct devfreq, dev)
 
+/* Devfreq events */
+#define DEVFREQ_GOV_START                      0x1
+#define DEVFREQ_GOV_STOP                       0x2
+#define DEVFREQ_GOV_INTERVAL                   0x3
+#define DEVFREQ_GOV_SUSPEND                    0x4
+#define DEVFREQ_GOV_RESUME                     0x5
+
 /* Caution: devfreq->lock must be locked before calling update_devfreq */
 extern int update_devfreq(struct devfreq *devfreq);
 
+extern void devfreq_monitor_start(struct devfreq *devfreq);
+extern void devfreq_monitor_stop(struct devfreq *devfreq);
+extern void devfreq_monitor_suspend(struct devfreq *devfreq);
+extern void devfreq_monitor_resume(struct devfreq *devfreq);
+extern void devfreq_interval_update(struct devfreq *devfreq,
+                                       unsigned int *delay);
 #endif /* _GOVERNOR_H */
index af75ddd4f158b5de78f9d5bc44ec2f9c579e78a5..eea3f9bd78947331fe5b5ce8d9e8b6e6fac7de18 100644 (file)
@@ -26,14 +26,22 @@ static int devfreq_performance_func(struct devfreq *df,
        return 0;
 }
 
-static int performance_init(struct devfreq *devfreq)
+static int devfreq_performance_handler(struct devfreq *devfreq,
+                               unsigned int event, void *data)
 {
-       return update_devfreq(devfreq);
+       int ret = 0;
+
+       if (event == DEVFREQ_GOV_START) {
+               mutex_lock(&devfreq->lock);
+               ret = update_devfreq(devfreq);
+               mutex_unlock(&devfreq->lock);
+       }
+
+       return ret;
 }
 
 const struct devfreq_governor devfreq_performance = {
        .name = "performance",
-       .init = performance_init,
        .get_target_freq = devfreq_performance_func,
-       .no_central_polling = true,
+       .event_handler = devfreq_performance_handler,
 };
index fec0cdbd24773fd531b5c300bfb4afb5111d9545..2868d98ed3e23bd3075b046e25a9b120f77c223e 100644 (file)
@@ -23,14 +23,22 @@ static int devfreq_powersave_func(struct devfreq *df,
        return 0;
 }
 
-static int powersave_init(struct devfreq *devfreq)
+static int devfreq_powersave_handler(struct devfreq *devfreq,
+                               unsigned int event, void *data)
 {
-       return update_devfreq(devfreq);
+       int ret = 0;
+
+       if (event == DEVFREQ_GOV_START) {
+               mutex_lock(&devfreq->lock);
+               ret = update_devfreq(devfreq);
+               mutex_unlock(&devfreq->lock);
+       }
+
+       return ret;
 }
 
 const struct devfreq_governor devfreq_powersave = {
        .name = "powersave",
-       .init = powersave_init,
        .get_target_freq = devfreq_powersave_func,
-       .no_central_polling = true,
+       .event_handler = devfreq_powersave_handler,
 };
index a2e3eae790119ef7e01527a94b4bf44b20589a07..b5cf0fb24efeb4d15ed762bf6df5a28a49bfc73b 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/errno.h>
 #include <linux/devfreq.h>
 #include <linux/math64.h>
+#include "governor.h"
 
 /* Default constants for DevFreq-Simple-Ondemand (DFSO) */
 #define DFSO_UPTHRESHOLD       (90)
@@ -88,7 +89,39 @@ static int devfreq_simple_ondemand_func(struct devfreq *df,
        return 0;
 }
 
+static int devfreq_simple_ondemand_handler(struct devfreq *devfreq,
+                               unsigned int event, void *data)
+{
+       switch (event) {
+       case DEVFREQ_GOV_START:
+               devfreq_monitor_start(devfreq);
+               break;
+
+       case DEVFREQ_GOV_STOP:
+               devfreq_monitor_stop(devfreq);
+               break;
+
+       case DEVFREQ_GOV_INTERVAL:
+               devfreq_interval_update(devfreq, (unsigned int *)data);
+               break;
+
+       case DEVFREQ_GOV_SUSPEND:
+               devfreq_monitor_suspend(devfreq);
+               break;
+
+       case DEVFREQ_GOV_RESUME:
+               devfreq_monitor_resume(devfreq);
+               break;
+
+       default:
+               break;
+       }
+
+       return 0;
+}
+
 const struct devfreq_governor devfreq_simple_ondemand = {
        .name = "simple_ondemand",
        .get_target_freq = devfreq_simple_ondemand_func,
+       .event_handler = devfreq_simple_ondemand_handler,
 };
index 0681246fc89dc32e53900929abd2c2df4329e0ab..7067555bd4441060528bd8e1395c80de8df27b9f 100644 (file)
@@ -116,10 +116,27 @@ static void userspace_exit(struct devfreq *devfreq)
        devfreq->data = NULL;
 }
 
+static int devfreq_userspace_handler(struct devfreq *devfreq,
+                       unsigned int event, void *data)
+{
+       int ret = 0;
+
+       switch (event) {
+       case DEVFREQ_GOV_START:
+               ret = userspace_init(devfreq);
+               break;
+       case DEVFREQ_GOV_STOP:
+               userspace_exit(devfreq);
+               break;
+       default:
+               break;
+       }
+
+       return ret;
+}
+
 const struct devfreq_governor devfreq_userspace = {
        .name = "userspace",
        .get_target_freq = devfreq_userspace_func,
-       .init = userspace_init,
-       .exit = userspace_exit,
-       .no_central_polling = true,
+       .event_handler = devfreq_userspace_handler,
 };
index 677cd6e4e1a1c1afb387217fdc9f0f363c3149cf..dc8f4d1fd838c30aa23b44eafd2dee5b8f6e382b 100644 (file)
@@ -51,7 +51,7 @@ config ASYNC_TX_ENABLE_CHANNEL_SWITCH
 
 config AMBA_PL08X
        bool "ARM PrimeCell PL080 or PL081 support"
-       depends on ARM_AMBA && EXPERIMENTAL
+       depends on ARM_AMBA
        select DMA_ENGINE
        select DMA_VIRTUAL_CHANNELS
        help
index f11b5b2b1a1c1e41274ed7578ba197971e209f5a..a3a8270e76fb88c81cbe7ff249a8623fcd848d8a 100644 (file)
@@ -29,7 +29,6 @@
 
 #include <asm/irq.h>
 #include <linux/platform_data/dma-imx.h>
-#include <mach/hardware.h>
 
 #include "dmaengine.h"
 #define IMXDMA_MAX_CHAN_DESCRIPTORS    16
@@ -167,6 +166,12 @@ struct imxdma_channel {
        int                             slot_2d;
 };
 
+enum imx_dma_type {
+       IMX1_DMA,
+       IMX21_DMA,
+       IMX27_DMA,
+};
+
 struct imxdma_engine {
        struct device                   *dev;
        struct device_dma_parameters    dma_parms;
@@ -177,7 +182,39 @@ struct imxdma_engine {
        spinlock_t                      lock;
        struct imx_dma_2d_config        slots_2d[IMX_DMA_2D_SLOTS];
        struct imxdma_channel           channel[IMX_DMA_CHANNELS];
+       enum imx_dma_type               devtype;
+};
+
+static struct platform_device_id imx_dma_devtype[] = {
+       {
+               .name = "imx1-dma",
+               .driver_data = IMX1_DMA,
+       }, {
+               .name = "imx21-dma",
+               .driver_data = IMX21_DMA,
+       }, {
+               .name = "imx27-dma",
+               .driver_data = IMX27_DMA,
+       }, {
+               /* sentinel */
+       }
 };
+MODULE_DEVICE_TABLE(platform, imx_dma_devtype);
+
+static inline int is_imx1_dma(struct imxdma_engine *imxdma)
+{
+       return imxdma->devtype == IMX1_DMA;
+}
+
+static inline int is_imx21_dma(struct imxdma_engine *imxdma)
+{
+       return imxdma->devtype == IMX21_DMA;
+}
+
+static inline int is_imx27_dma(struct imxdma_engine *imxdma)
+{
+       return imxdma->devtype == IMX27_DMA;
+}
 
 static struct imxdma_channel *to_imxdma_chan(struct dma_chan *chan)
 {
@@ -212,7 +249,9 @@ static unsigned imx_dmav1_readl(struct imxdma_engine *imxdma, unsigned offset)
 
 static int imxdma_hw_chain(struct imxdma_channel *imxdmac)
 {
-       if (cpu_is_mx27())
+       struct imxdma_engine *imxdma = imxdmac->imxdma;
+
+       if (is_imx27_dma(imxdma))
                return imxdmac->hw_chaining;
        else
                return 0;
@@ -267,7 +306,7 @@ static void imxdma_enable_hw(struct imxdma_desc *d)
        imx_dmav1_writel(imxdma, imx_dmav1_readl(imxdma, DMA_CCR(channel)) |
                         CCR_CEN | CCR_ACRPT, DMA_CCR(channel));
 
-       if ((cpu_is_mx21() || cpu_is_mx27()) &&
+       if (!is_imx1_dma(imxdma) &&
                        d->sg && imxdma_hw_chain(imxdmac)) {
                d->sg = sg_next(d->sg);
                if (d->sg) {
@@ -436,7 +475,7 @@ static irqreturn_t dma_irq_handler(int irq, void *dev_id)
        struct imxdma_engine *imxdma = dev_id;
        int i, disr;
 
-       if (cpu_is_mx21() || cpu_is_mx27())
+       if (!is_imx1_dma(imxdma))
                imxdma_err_handler(irq, dev_id);
 
        disr = imx_dmav1_readl(imxdma, DMA_DISR);
@@ -959,35 +998,32 @@ static void imxdma_issue_pending(struct dma_chan *chan)
 static int __init imxdma_probe(struct platform_device *pdev)
        {
        struct imxdma_engine *imxdma;
+       struct resource *res;
        int ret, i;
+       int irq, irq_err;
 
-
-       imxdma = kzalloc(sizeof(*imxdma), GFP_KERNEL);
+       imxdma = devm_kzalloc(&pdev->dev, sizeof(*imxdma), GFP_KERNEL);
        if (!imxdma)
                return -ENOMEM;
 
-       if (cpu_is_mx1()) {
-               imxdma->base = MX1_IO_ADDRESS(MX1_DMA_BASE_ADDR);
-       } else if (cpu_is_mx21()) {
-               imxdma->base = MX21_IO_ADDRESS(MX21_DMA_BASE_ADDR);
-       } else if (cpu_is_mx27()) {
-               imxdma->base = MX27_IO_ADDRESS(MX27_DMA_BASE_ADDR);
-       } else {
-               kfree(imxdma);
-               return 0;
-       }
+       imxdma->devtype = pdev->id_entry->driver_data;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       imxdma->base = devm_request_and_ioremap(&pdev->dev, res);
+       if (!imxdma->base)
+               return -EADDRNOTAVAIL;
+
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0)
+               return irq;
 
        imxdma->dma_ipg = devm_clk_get(&pdev->dev, "ipg");
-       if (IS_ERR(imxdma->dma_ipg)) {
-               ret = PTR_ERR(imxdma->dma_ipg);
-               goto err_clk;
-       }
+       if (IS_ERR(imxdma->dma_ipg))
+               return PTR_ERR(imxdma->dma_ipg);
 
        imxdma->dma_ahb = devm_clk_get(&pdev->dev, "ahb");
-       if (IS_ERR(imxdma->dma_ahb)) {
-               ret = PTR_ERR(imxdma->dma_ahb);
-               goto err_clk;
-       }
+       if (IS_ERR(imxdma->dma_ahb))
+               return PTR_ERR(imxdma->dma_ahb);
 
        clk_prepare_enable(imxdma->dma_ipg);
        clk_prepare_enable(imxdma->dma_ahb);
@@ -995,18 +1031,25 @@ static int __init imxdma_probe(struct platform_device *pdev)
        /* reset DMA module */
        imx_dmav1_writel(imxdma, DCR_DRST, DMA_DCR);
 
-       if (cpu_is_mx1()) {
-               ret = request_irq(MX1_DMA_INT, dma_irq_handler, 0, "DMA", imxdma);
+       if (is_imx1_dma(imxdma)) {
+               ret = devm_request_irq(&pdev->dev, irq,
+                                      dma_irq_handler, 0, "DMA", imxdma);
                if (ret) {
                        dev_warn(imxdma->dev, "Can't register IRQ for DMA\n");
-                       goto err_enable;
+                       goto err;
+               }
+
+               irq_err = platform_get_irq(pdev, 1);
+               if (irq_err < 0) {
+                       ret = irq_err;
+                       goto err;
                }
 
-               ret = request_irq(MX1_DMA_ERR, imxdma_err_handler, 0, "DMA", imxdma);
+               ret = devm_request_irq(&pdev->dev, irq_err,
+                                      imxdma_err_handler, 0, "DMA", imxdma);
                if (ret) {
                        dev_warn(imxdma->dev, "Can't register ERRIRQ for DMA\n");
-                       free_irq(MX1_DMA_INT, NULL);
-                       goto err_enable;
+                       goto err;
                }
        }
 
@@ -1036,14 +1079,14 @@ static int __init imxdma_probe(struct platform_device *pdev)
        for (i = 0; i < IMX_DMA_CHANNELS; i++) {
                struct imxdma_channel *imxdmac = &imxdma->channel[i];
 
-               if (cpu_is_mx21() || cpu_is_mx27()) {
-                       ret = request_irq(MX2x_INT_DMACH0 + i,
+               if (!is_imx1_dma(imxdma)) {
+                       ret = devm_request_irq(&pdev->dev, irq + i,
                                        dma_irq_handler, 0, "DMA", imxdma);
                        if (ret) {
                                dev_warn(imxdma->dev, "Can't register IRQ %d "
                                         "for DMA channel %d\n",
-                                        MX2x_INT_DMACH0 + i, i);
-                               goto err_init;
+                                        irq + i, i);
+                               goto err;
                        }
                        init_timer(&imxdmac->watchdog);
                        imxdmac->watchdog.function = &imxdma_watchdog;
@@ -1089,46 +1132,25 @@ static int __init imxdma_probe(struct platform_device *pdev)
        ret = dma_async_device_register(&imxdma->dma_device);
        if (ret) {
                dev_err(&pdev->dev, "unable to register\n");
-               goto err_init;
+               goto err;
        }
 
        return 0;
 
-err_init:
-
-       if (cpu_is_mx21() || cpu_is_mx27()) {
-               while (--i >= 0)
-                       free_irq(MX2x_INT_DMACH0 + i, NULL);
-       } else if cpu_is_mx1() {
-               free_irq(MX1_DMA_INT, NULL);
-               free_irq(MX1_DMA_ERR, NULL);
-       }
-err_enable:
+err:
        clk_disable_unprepare(imxdma->dma_ipg);
        clk_disable_unprepare(imxdma->dma_ahb);
-err_clk:
-       kfree(imxdma);
        return ret;
 }
 
 static int __exit imxdma_remove(struct platform_device *pdev)
 {
        struct imxdma_engine *imxdma = platform_get_drvdata(pdev);
-       int i;
 
         dma_async_device_unregister(&imxdma->dma_device);
 
-       if (cpu_is_mx21() || cpu_is_mx27()) {
-               for (i = 0; i < IMX_DMA_CHANNELS; i++)
-                       free_irq(MX2x_INT_DMACH0 + i, NULL);
-       } else if cpu_is_mx1() {
-               free_irq(MX1_DMA_INT, NULL);
-               free_irq(MX1_DMA_ERR, NULL);
-       }
-
        clk_disable_unprepare(imxdma->dma_ipg);
        clk_disable_unprepare(imxdma->dma_ahb);
-       kfree(imxdma);
 
         return 0;
 }
@@ -1137,6 +1159,7 @@ static struct platform_driver imxdma_driver = {
        .driver         = {
                .name   = "imx-dma",
        },
+       .id_table       = imx_dma_devtype,
        .remove         = __exit_p(imxdma_remove),
 };
 
index c099ca0846f49dc76dcc29342940b29498ba68f9..f082aa3a918c9afa82fa459849c96d63f81242b6 100644 (file)
@@ -40,7 +40,6 @@
 #include <asm/irq.h>
 #include <linux/platform_data/dma-imx-sdma.h>
 #include <linux/platform_data/dma-imx.h>
-#include <mach/hardware.h>
 
 #include "dmaengine.h"
 
index c7573e50aa14110118426c9d56c49cdb890cd651..65855373cee656888cc68739e622abd8ce10e59f 100644 (file)
@@ -22,8 +22,7 @@
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/module.h>
-
-#include <mach/ipu.h>
+#include <linux/dma/ipu-dma.h>
 
 #include "../dmaengine.h"
 #include "ipu_intern.h"
index fa95bcc3de1f66b107a4cddf38e97d5fa68286b2..a5ee37d5320f9e94e4cdbf73a144a86216045078 100644 (file)
@@ -15,8 +15,7 @@
 #include <linux/irq.h>
 #include <linux/io.h>
 #include <linux/module.h>
-
-#include <mach/ipu.h>
+#include <linux/dma/ipu-dma.h>
 
 #include "ipu_intern.h"
 
index 409b92b8d346087b4ec292bda8790d03cc764224..4c6c876d9dc3f0fa949352c89039a00b3c0bc79a 100644 (file)
@@ -7,7 +7,7 @@
 menuconfig EDAC
        bool "EDAC (Error Detection And Correction) reporting"
        depends on HAS_IOMEM
-       depends on X86 || PPC || TILE || ARM
+       depends on X86 || PPC || TILE || ARM || EDAC_SUPPORT
        help
          EDAC is designed to report errors in the core system.
          These are low-level errors that are reported in the CPU or
@@ -27,6 +27,9 @@ menuconfig EDAC
          There is also a mailing list for the EDAC project, which can
          be found via the sourceforge page.
 
+config EDAC_SUPPORT
+       bool
+
 if EDAC
 
 comment "Reporting subsystems"
@@ -42,10 +45,10 @@ config EDAC_LEGACY_SYSFS
 config EDAC_DEBUG
        bool "Debugging"
        help
-         This turns on debugging information for the entire EDAC
-         sub-system. You can insert module with "debug_level=x", current
-         there're four debug levels (x=0,1,2,3 from low to high).
-         Usually you should select 'N'.
+         This turns on debugging information for the entire EDAC subsystem.
+         You do so by inserting edac_module with "edac_debug_level=x." Valid
+         levels are 0-4 (from low to high) and by default it is set to 2.
+         Usually you should select 'N' here.
 
 config EDAC_DECODE_MCE
        tristate "Decode MCEs in human-readable form (only on AMD for now)"
@@ -316,4 +319,32 @@ config EDAC_HIGHBANK_L2
          Support for error detection and correction on the
          Calxeda Highbank memory controller.
 
+config EDAC_OCTEON_PC
+       tristate "Cavium Octeon Primary Caches"
+       depends on EDAC_MM_EDAC && CPU_CAVIUM_OCTEON
+       help
+         Support for error detection and correction on the primary caches of
+         the cnMIPS cores of Cavium Octeon family SOCs.
+
+config EDAC_OCTEON_L2C
+       tristate "Cavium Octeon Secondary Caches (L2C)"
+       depends on EDAC_MM_EDAC && CPU_CAVIUM_OCTEON
+       help
+         Support for error detection and correction on the
+         Cavium Octeon family of SOCs.
+
+config EDAC_OCTEON_LMC
+       tristate "Cavium Octeon DRAM Memory Controller (LMC)"
+       depends on EDAC_MM_EDAC && CPU_CAVIUM_OCTEON
+       help
+         Support for error detection and correction on the
+         Cavium Octeon family of SOCs.
+
+config EDAC_OCTEON_PCI
+       tristate "Cavium Octeon PCI Controller"
+       depends on EDAC_MM_EDAC && PCI && CPU_CAVIUM_OCTEON
+       help
+         Support for error detection and correction on the
+         Cavium Octeon family of SOCs.
+
 endif # EDAC
index 7e5129a733f8cc6b8afdc7dac91228167949512d..5608a9ba61b7aaf442564feac6e586c6a26588cf 100644 (file)
@@ -58,3 +58,8 @@ obj-$(CONFIG_EDAC_TILE)                       += tile_edac.o
 
 obj-$(CONFIG_EDAC_HIGHBANK_MC) += highbank_mc_edac.o
 obj-$(CONFIG_EDAC_HIGHBANK_L2) += highbank_l2_edac.o
+
+obj-$(CONFIG_EDAC_OCTEON_PC)           += octeon_edac-pc.o
+obj-$(CONFIG_EDAC_OCTEON_L2C)          += octeon_edac-l2c.o
+obj-$(CONFIG_EDAC_OCTEON_LMC)          += octeon_edac-lmc.o
+obj-$(CONFIG_EDAC_OCTEON_PCI)          += octeon_edac-pci.o
index 5a297a26211d622b0f0ceedb0389fcbeb4223baf..f74a684269ff6c8ceb25241d82816ddbab035888 100644 (file)
@@ -60,8 +60,8 @@ struct scrubrate {
        { 0x00, 0UL},        /* scrubbing off */
 };
 
-static int __amd64_read_pci_cfg_dword(struct pci_dev *pdev, int offset,
-                                     u32 *val, const char *func)
+int __amd64_read_pci_cfg_dword(struct pci_dev *pdev, int offset,
+                              u32 *val, const char *func)
 {
        int err = 0;
 
@@ -170,8 +170,11 @@ static int __amd64_set_scrub_rate(struct pci_dev *ctl, u32 new_bw, u32 min_rate)
         * memory controller and apply to register. Search for the first
         * bandwidth entry that is greater or equal than the setting requested
         * and program that. If at last entry, turn off DRAM scrubbing.
+        *
+        * If no suitable bandwidth is found, turn off DRAM scrubbing entirely
+        * by falling back to the last element in scrubrates[].
         */
-       for (i = 0; i < ARRAY_SIZE(scrubrates); i++) {
+       for (i = 0; i < ARRAY_SIZE(scrubrates) - 1; i++) {
                /*
                 * skip scrub rates which aren't recommended
                 * (see F10 BKDG, F3x58)
@@ -181,12 +184,6 @@ static int __amd64_set_scrub_rate(struct pci_dev *ctl, u32 new_bw, u32 min_rate)
 
                if (scrubrates[i].bandwidth <= new_bw)
                        break;
-
-               /*
-                * if no suitable bandwidth found, turn off DRAM scrubbing
-                * entirely by falling back to the last element in the
-                * scrubrates array.
-                */
        }
 
        scrubval = scrubrates[i].scrubval;
@@ -426,7 +423,6 @@ int amd64_get_dram_hole_info(struct mem_ctl_info *mci, u64 *hole_base,
                             u64 *hole_offset, u64 *hole_size)
 {
        struct amd64_pvt *pvt = mci->pvt_info;
-       u64 base;
 
        /* only revE and later have the DRAM Hole Address Register */
        if (boot_cpu_data.x86 == 0xf && pvt->ext_model < K8_REV_E) {
@@ -465,10 +461,8 @@ int amd64_get_dram_hole_info(struct mem_ctl_info *mci, u64 *hole_base,
         * addresses in the hole so that they start at 0x100000000.
         */
 
-       base = dhar_base(pvt);
-
-       *hole_base = base;
-       *hole_size = (0x1ull << 32) - base;
+       *hole_base = dhar_base(pvt);
+       *hole_size = (1ULL << 32) - *hole_base;
 
        if (boot_cpu_data.x86 > 0xf)
                *hole_offset = f10_dhar_offset(pvt);
@@ -516,15 +510,15 @@ static u64 sys_addr_to_dram_addr(struct mem_ctl_info *mci, u64 sys_addr)
 {
        struct amd64_pvt *pvt = mci->pvt_info;
        u64 dram_base, hole_base, hole_offset, hole_size, dram_addr;
-       int ret = 0;
+       int ret;
 
        dram_base = get_dram_base(pvt, pvt->mc_node_id);
 
        ret = amd64_get_dram_hole_info(mci, &hole_base, &hole_offset,
                                      &hole_size);
        if (!ret) {
-               if ((sys_addr >= (1ull << 32)) &&
-                   (sys_addr < ((1ull << 32) + hole_size))) {
+               if ((sys_addr >= (1ULL << 32)) &&
+                   (sys_addr < ((1ULL << 32) + hole_size))) {
                        /* use DHAR to translate SysAddr to DramAddr */
                        dram_addr = sys_addr - hole_offset;
 
@@ -715,10 +709,10 @@ static inline u64 input_addr_to_sys_addr(struct mem_ctl_info *mci,
 
 /* Map the Error address to a PAGE and PAGE OFFSET. */
 static inline void error_address_to_page_and_offset(u64 error_address,
-                                                   u32 *page, u32 *offset)
+                                                   struct err_info *err)
 {
-       *page = (u32) (error_address >> PAGE_SHIFT);
-       *offset = ((u32) error_address) & ~PAGE_MASK;
+       err->page = (u32) (error_address >> PAGE_SHIFT);
+       err->offset = ((u32) error_address) & ~PAGE_MASK;
 }
 
 /*
@@ -1029,59 +1023,44 @@ static void read_dram_base_limit_regs(struct amd64_pvt *pvt, unsigned range)
 }
 
 static void k8_map_sysaddr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr,
-                                   u16 syndrome)
+                                   struct err_info *err)
 {
-       struct mem_ctl_info *src_mci;
        struct amd64_pvt *pvt = mci->pvt_info;
-       int channel, csrow;
-       u32 page, offset;
 
-       error_address_to_page_and_offset(sys_addr, &page, &offset);
+       error_address_to_page_and_offset(sys_addr, err);
 
        /*
         * Find out which node the error address belongs to. This may be
         * different from the node that detected the error.
         */
-       src_mci = find_mc_by_sys_addr(mci, sys_addr);
-       if (!src_mci) {
+       err->src_mci = find_mc_by_sys_addr(mci, sys_addr);
+       if (!err->src_mci) {
                amd64_mc_err(mci, "failed to map error addr 0x%lx to a node\n",
                             (unsigned long)sys_addr);
-               edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1,
-                                    page, offset, syndrome,
-                                    -1, -1, -1,
-                                    "failed to map error addr to a node",
-                                    "");
+               err->err_code = ERR_NODE;
                return;
        }
 
        /* Now map the sys_addr to a CSROW */
-       csrow = sys_addr_to_csrow(src_mci, sys_addr);
-       if (csrow < 0) {
-               edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1,
-                                    page, offset, syndrome,
-                                    -1, -1, -1,
-                                    "failed to map error addr to a csrow",
-                                    "");
+       err->csrow = sys_addr_to_csrow(err->src_mci, sys_addr);
+       if (err->csrow < 0) {
+               err->err_code = ERR_CSROW;
                return;
        }
 
        /* CHIPKILL enabled */
        if (pvt->nbcfg & NBCFG_CHIPKILL) {
-               channel = get_channel_from_ecc_syndrome(mci, syndrome);
-               if (channel < 0) {
+               err->channel = get_channel_from_ecc_syndrome(mci, err->syndrome);
+               if (err->channel < 0) {
                        /*
                         * Syndrome didn't map, so we don't know which of the
                         * 2 DIMMs is in error. So we need to ID 'both' of them
                         * as suspect.
                         */
-                       amd64_mc_warn(src_mci, "unknown syndrome 0x%04x - "
+                       amd64_mc_warn(err->src_mci, "unknown syndrome 0x%04x - "
                                      "possible error reporting race\n",
-                                     syndrome);
-                       edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1,
-                                            page, offset, syndrome,
-                                            csrow, -1, -1,
-                                            "unknown syndrome - possible error reporting race",
-                                            "");
+                                     err->syndrome);
+                       err->err_code = ERR_CHANNEL;
                        return;
                }
        } else {
@@ -1093,13 +1072,8 @@ static void k8_map_sysaddr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr,
                 * was obtained from email communication with someone at AMD.
                 * (Wish the email was placed in this comment - norsk)
                 */
-               channel = ((sys_addr & BIT(3)) != 0);
+               err->channel = ((sys_addr & BIT(3)) != 0);
        }
-
-       edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, src_mci, 1,
-                            page, offset, syndrome,
-                            csrow, channel, -1,
-                            "", "");
 }
 
 static int ddr2_cs_size(unsigned i, bool dct_width)
@@ -1485,7 +1459,7 @@ static u64 f1x_swap_interleaved_region(struct amd64_pvt *pvt, u64 sys_addr)
 
 /* For a given @dram_range, check if @sys_addr falls within it. */
 static int f1x_match_to_this_node(struct amd64_pvt *pvt, unsigned range,
-                                 u64 sys_addr, int *nid, int *chan_sel)
+                                 u64 sys_addr, int *chan_sel)
 {
        int cs_found = -EINVAL;
        u64 chan_addr;
@@ -1558,15 +1532,14 @@ static int f1x_match_to_this_node(struct amd64_pvt *pvt, unsigned range,
 
        cs_found = f1x_lookup_addr_in_dct(chan_addr, node_id, channel);
 
-       if (cs_found >= 0) {
-               *nid = node_id;
+       if (cs_found >= 0)
                *chan_sel = channel;
-       }
+
        return cs_found;
 }
 
 static int f1x_translate_sysaddr_to_cs(struct amd64_pvt *pvt, u64 sys_addr,
-                                      int *node, int *chan_sel)
+                                      int *chan_sel)
 {
        int cs_found = -EINVAL;
        unsigned range;
@@ -1580,8 +1553,7 @@ static int f1x_translate_sysaddr_to_cs(struct amd64_pvt *pvt, u64 sys_addr,
                    (get_dram_limit(pvt, range) >= sys_addr)) {
 
                        cs_found = f1x_match_to_this_node(pvt, range,
-                                                         sys_addr, node,
-                                                         chan_sel);
+                                                         sys_addr, chan_sel);
                        if (cs_found >= 0)
                                break;
                }
@@ -1597,22 +1569,15 @@ static int f1x_translate_sysaddr_to_cs(struct amd64_pvt *pvt, u64 sys_addr,
  * (MCX_ADDR).
  */
 static void f1x_map_sysaddr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr,
-                                    u16 syndrome)
+                                    struct err_info *err)
 {
        struct amd64_pvt *pvt = mci->pvt_info;
-       u32 page, offset;
-       int nid, csrow, chan = 0;
 
-       error_address_to_page_and_offset(sys_addr, &page, &offset);
+       error_address_to_page_and_offset(sys_addr, err);
 
-       csrow = f1x_translate_sysaddr_to_cs(pvt, sys_addr, &nid, &chan);
-
-       if (csrow < 0) {
-               edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1,
-                                    page, offset, syndrome,
-                                    -1, -1, -1,
-                                    "failed to map error addr to a csrow",
-                                    "");
+       err->csrow = f1x_translate_sysaddr_to_cs(pvt, sys_addr, &err->channel);
+       if (err->csrow < 0) {
+               err->err_code = ERR_CSROW;
                return;
        }
 
@@ -1622,12 +1587,7 @@ static void f1x_map_sysaddr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr,
         * this point.
         */
        if (dct_ganging_enabled(pvt))
-               chan = get_channel_from_ecc_syndrome(mci, syndrome);
-
-       edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1,
-                            page, offset, syndrome,
-                            csrow, chan, -1,
-                            "", "");
+               err->channel = get_channel_from_ecc_syndrome(mci, err->syndrome);
 }
 
 /*
@@ -1636,14 +1596,11 @@ static void f1x_map_sysaddr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr,
  */
 static void amd64_debug_display_dimm_sizes(struct amd64_pvt *pvt, u8 ctrl)
 {
-       int dimm, size0, size1, factor = 0;
+       int dimm, size0, size1;
        u32 *dcsb = ctrl ? pvt->csels[1].csbases : pvt->csels[0].csbases;
        u32 dbam  = ctrl ? pvt->dbam1 : pvt->dbam0;
 
        if (boot_cpu_data.x86 == 0xf) {
-               if (pvt->dclr0 & WIDTH_128)
-                       factor = 1;
-
                /* K8 families < revF not supported yet */
               if (pvt->ext_model < K8_REV_F)
                        return;
@@ -1674,8 +1631,8 @@ static void amd64_debug_display_dimm_sizes(struct amd64_pvt *pvt, u8 ctrl)
                                                     DBAM_DIMM(dimm, dbam));
 
                amd64_info(EDAC_MC ": %d: %5dMB %d: %5dMB\n",
-                               dimm * 2,     size0 << factor,
-                               dimm * 2 + 1, size1 << factor);
+                               dimm * 2,     size0,
+                               dimm * 2 + 1, size1);
        }
 }
 
@@ -1896,101 +1853,56 @@ static int get_channel_from_ecc_syndrome(struct mem_ctl_info *mci, u16 syndrome)
        return map_err_sym_to_channel(err_sym, pvt->ecc_sym_sz);
 }
 
-/*
- * Handle any Correctable Errors (CEs) that have occurred. Check for valid ERROR
- * ADDRESS and process.
- */
-static void amd64_handle_ce(struct mem_ctl_info *mci, struct mce *m)
-{
-       struct amd64_pvt *pvt = mci->pvt_info;
-       u64 sys_addr;
-       u16 syndrome;
-
-       /* Ensure that the Error Address is VALID */
-       if (!(m->status & MCI_STATUS_ADDRV)) {
-               amd64_mc_err(mci, "HW has no ERROR_ADDRESS available\n");
-               edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1,
-                                    0, 0, 0,
-                                    -1, -1, -1,
-                                    "HW has no ERROR_ADDRESS available",
-                                    "");
-               return;
-       }
-
-       sys_addr = get_error_address(m);
-       syndrome = extract_syndrome(m->status);
-
-       amd64_mc_err(mci, "CE ERROR_ADDRESS= 0x%llx\n", sys_addr);
-
-       pvt->ops->map_sysaddr_to_csrow(mci, sys_addr, syndrome);
-}
-
-/* Handle any Un-correctable Errors (UEs) */
-static void amd64_handle_ue(struct mem_ctl_info *mci, struct mce *m)
+static void __log_bus_error(struct mem_ctl_info *mci, struct err_info *err,
+                           u8 ecc_type)
 {
-       struct mem_ctl_info *log_mci, *src_mci = NULL;
-       int csrow;
-       u64 sys_addr;
-       u32 page, offset;
+       enum hw_event_mc_err_type err_type;
+       const char *string;
 
-       log_mci = mci;
-
-       if (!(m->status & MCI_STATUS_ADDRV)) {
-               amd64_mc_err(mci, "HW has no ERROR_ADDRESS available\n");
-               edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1,
-                                    0, 0, 0,
-                                    -1, -1, -1,
-                                    "HW has no ERROR_ADDRESS available",
-                                    "");
+       if (ecc_type == 2)
+               err_type = HW_EVENT_ERR_CORRECTED;
+       else if (ecc_type == 1)
+               err_type = HW_EVENT_ERR_UNCORRECTED;
+       else {
+               WARN(1, "Something is rotten in the state of Denmark.\n");
                return;
        }
 
-       sys_addr = get_error_address(m);
-       error_address_to_page_and_offset(sys_addr, &page, &offset);
-
-       /*
-        * Find out which node the error address belongs to. This may be
-        * different from the node that detected the error.
-        */
-       src_mci = find_mc_by_sys_addr(mci, sys_addr);
-       if (!src_mci) {
-               amd64_mc_err(mci, "ERROR ADDRESS (0x%lx) NOT mapped to a MC\n",
-                                 (unsigned long)sys_addr);
-               edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1,
-                                    page, offset, 0,
-                                    -1, -1, -1,
-                                    "ERROR ADDRESS NOT mapped to a MC",
-                                    "");
-               return;
+       switch (err->err_code) {
+       case DECODE_OK:
+               string = "";
+               break;
+       case ERR_NODE:
+               string = "Failed to map error addr to a node";
+               break;
+       case ERR_CSROW:
+               string = "Failed to map error addr to a csrow";
+               break;
+       case ERR_CHANNEL:
+               string = "unknown syndrome - possible error reporting race";
+               break;
+       default:
+               string = "WTF error";
+               break;
        }
 
-       log_mci = src_mci;
-
-       csrow = sys_addr_to_csrow(log_mci, sys_addr);
-       if (csrow < 0) {
-               amd64_mc_err(mci, "ERROR_ADDRESS (0x%lx) NOT mapped to CS\n",
-                                 (unsigned long)sys_addr);
-               edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1,
-                                    page, offset, 0,
-                                    -1, -1, -1,
-                                    "ERROR ADDRESS NOT mapped to CS",
-                                    "");
-       } else {
-               edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1,
-                                    page, offset, 0,
-                                    csrow, -1, -1,
-                                    "", "");
-       }
+       edac_mc_handle_error(err_type, mci, 1,
+                            err->page, err->offset, err->syndrome,
+                            err->csrow, err->channel, -1,
+                            string, "");
 }
 
 static inline void __amd64_decode_bus_error(struct mem_ctl_info *mci,
                                            struct mce *m)
 {
-       u16 ec = EC(m->status);
-       u8 xec = XEC(m->status, 0x1f);
+       struct amd64_pvt *pvt = mci->pvt_info;
        u8 ecc_type = (m->status >> 45) & 0x3;
+       u8 xec = XEC(m->status, 0x1f);
+       u16 ec = EC(m->status);
+       u64 sys_addr;
+       struct err_info err;
 
-       /* Bail early out if this was an 'observed' error */
+       /* Bail out early if this was an 'observed' error */
        if (PP(ec) == NBSL_PP_OBS)
                return;
 
@@ -1998,10 +1910,16 @@ static inline void __amd64_decode_bus_error(struct mem_ctl_info *mci,
        if (xec && xec != F10_NBSL_EXT_ERR_ECC)
                return;
 
+       memset(&err, 0, sizeof(err));
+
+       sys_addr = get_error_address(m);
+
        if (ecc_type == 2)
-               amd64_handle_ce(mci, m);
-       else if (ecc_type == 1)
-               amd64_handle_ue(mci, m);
+               err.syndrome = extract_syndrome(m->status);
+
+       pvt->ops->map_sysaddr_to_csrow(mci, sys_addr, &err);
+
+       __log_bus_error(mci, &err, ecc_type);
 }
 
 void amd64_decode_bus_error(int node_id, struct mce *m)
@@ -2169,6 +2087,7 @@ static u32 amd64_csrow_nr_pages(struct amd64_pvt *pvt, u8 dct, int csrow_nr)
        u32 cs_mode, nr_pages;
        u32 dbam = dct ? pvt->dbam1 : pvt->dbam0;
 
+
        /*
         * The math on this doesn't look right on the surface because x/2*4 can
         * be simplified to x*2 but this expression makes use of the fact that
@@ -2176,13 +2095,13 @@ static u32 amd64_csrow_nr_pages(struct amd64_pvt *pvt, u8 dct, int csrow_nr)
         * number of bits to shift the DBAM register to extract the proper CSROW
         * field.
         */
-       cs_mode =  (dbam >> ((csrow_nr / 2) * 4)) & 0xF;
+       cs_mode = DBAM_DIMM(csrow_nr / 2, dbam);
 
        nr_pages = pvt->ops->dbam_to_cs(pvt, dct, cs_mode) << (20 - PAGE_SHIFT);
 
-       edac_dbg(0, "  (csrow=%d) DBAM map index= %d\n", csrow_nr, cs_mode);
-       edac_dbg(0, "    nr_pages/channel= %u  channel-count = %d\n",
-                nr_pages, pvt->channel_count);
+       edac_dbg(0, "csrow: %d, channel: %d, DBAM idx: %d\n",
+                   csrow_nr, dct,  cs_mode);
+       edac_dbg(0, "nr_pages/channel: %u\n", nr_pages);
 
        return nr_pages;
 }
@@ -2193,15 +2112,14 @@ static u32 amd64_csrow_nr_pages(struct amd64_pvt *pvt, u8 dct, int csrow_nr)
  */
 static int init_csrows(struct mem_ctl_info *mci)
 {
+       struct amd64_pvt *pvt = mci->pvt_info;
        struct csrow_info *csrow;
        struct dimm_info *dimm;
-       struct amd64_pvt *pvt = mci->pvt_info;
-       u64 base, mask;
-       u32 val;
-       int i, j, empty = 1;
-       enum mem_type mtype;
        enum edac_type edac_mode;
+       enum mem_type mtype;
+       int i, j, empty = 1;
        int nr_pages = 0;
+       u32 val;
 
        amd64_read_pci_cfg(pvt->F3, NBCFG, &val);
 
@@ -2211,29 +2129,35 @@ static int init_csrows(struct mem_ctl_info *mci)
                 pvt->mc_node_id, val,
                 !!(val & NBCFG_CHIPKILL), !!(val & NBCFG_ECC_ENABLE));
 
+       /*
+        * We iterate over DCT0 here but we look at DCT1 in parallel, if needed.
+        */
        for_each_chip_select(i, 0, pvt) {
-               csrow = mci->csrows[i];
+               bool row_dct0 = !!csrow_enabled(i, 0, pvt);
+               bool row_dct1 = false;
 
-               if (!csrow_enabled(i, 0, pvt) && !csrow_enabled(i, 1, pvt)) {
-                       edac_dbg(1, "----CSROW %d VALID for MC node %d\n",
-                                i, pvt->mc_node_id);
+               if (boot_cpu_data.x86 != 0xf)
+                       row_dct1 = !!csrow_enabled(i, 1, pvt);
+
+               if (!row_dct0 && !row_dct1)
                        continue;
-               }
 
+               csrow = mci->csrows[i];
                empty = 0;
-               if (csrow_enabled(i, 0, pvt))
+
+               edac_dbg(1, "MC node: %d, csrow: %d\n",
+                           pvt->mc_node_id, i);
+
+               if (row_dct0)
                        nr_pages = amd64_csrow_nr_pages(pvt, 0, i);
-               if (csrow_enabled(i, 1, pvt))
-                       nr_pages += amd64_csrow_nr_pages(pvt, 1, i);
 
-               get_cs_base_and_mask(pvt, i, 0, &base, &mask);
-               /* 8 bytes of resolution */
+               /* K8 has only one DCT */
+               if (boot_cpu_data.x86 != 0xf && row_dct1)
+                       nr_pages += amd64_csrow_nr_pages(pvt, 1, i);
 
                mtype = amd64_determine_memory_type(pvt, i);
 
-               edac_dbg(1, "  for MC node %d csrow %d:\n", pvt->mc_node_id, i);
-               edac_dbg(1, "    nr_pages: %u\n",
-                        nr_pages * pvt->channel_count);
+               edac_dbg(1, "Total csrow%d pages: %u\n", i, nr_pages);
 
                /*
                 * determine whether CHIPKILL or JUST ECC or NO ECC is operating
@@ -2250,6 +2174,7 @@ static int init_csrows(struct mem_ctl_info *mci)
                        dimm->edac_mode = edac_mode;
                        dimm->nr_pages = nr_pages;
                }
+               csrow->nr_pages = nr_pages;
        }
 
        return empty;
@@ -2594,6 +2519,7 @@ static int amd64_init_one_instance(struct pci_dev *F2)
 
        mci->pvt_info = pvt;
        mci->pdev = &pvt->F2->dev;
+       mci->csbased = 1;
 
        setup_mci_misc_attrs(mci, fam_type);
 
index 8d4804732bacb77be17f07465e48f24ea513ab0c..cd95f182ea32cbd61f3d97b26a7b34eb19095663 100644 (file)
 #define DBAM1                          0x180
 
 /* Extract the DIMM 'type' on the i'th DIMM from the DBAM reg value passed */
-#define DBAM_DIMM(i, reg)              ((((reg) >> (4*i))) & 0xF)
+#define DBAM_DIMM(i, reg)              ((((reg) >> (4*(i)))) & 0xF)
 
 #define DBAM_MAX_VALUE                 11
 
 #define online_spare_bad_dramcs(pvt, c)        (((pvt)->online_spare >> (4 + 4 * (c))) & 0x7)
 
 #define F10_NB_ARRAY_ADDR              0xB8
-#define F10_NB_ARRAY_DRAM_ECC          BIT(31)
+#define F10_NB_ARRAY_DRAM              BIT(31)
 
 /* Bits [2:1] are used to select 16-byte section within a 64-byte cacheline  */
-#define SET_NB_ARRAY_ADDRESS(section)  (((section) & 0x3) << 1)
+#define SET_NB_ARRAY_ADDR(section)     (((section) & 0x3) << 1)
 
 #define F10_NB_ARRAY_DATA              0xBC
-#define SET_NB_DRAM_INJECTION_WRITE(word, bits)  \
-                                       (BIT(((word) & 0xF) + 20) | \
-                                       BIT(17) | bits)
-#define SET_NB_DRAM_INJECTION_READ(word, bits)  \
-                                       (BIT(((word) & 0xF) + 20) | \
-                                       BIT(16) |  bits)
+#define F10_NB_ARR_ECC_WR_REQ          BIT(17)
+#define SET_NB_DRAM_INJECTION_WRITE(inj)  \
+                                       (BIT(((inj.word) & 0xF) + 20) | \
+                                       F10_NB_ARR_ECC_WR_REQ | inj.bit_map)
+#define SET_NB_DRAM_INJECTION_READ(inj)  \
+                                       (BIT(((inj.word) & 0xF) + 20) | \
+                                       BIT(16) |  inj.bit_map)
+
 
 #define NBCAP                          0xE8
 #define NBCAP_CHIPKILL                 BIT(4)
@@ -305,9 +307,9 @@ enum amd_families {
 
 /* Error injection control structure */
 struct error_injection {
-       u32     section;
-       u32     word;
-       u32     bit_map;
+       u32      section;
+       u32      word;
+       u32      bit_map;
 };
 
 /* low and high part of PCI config space regs */
@@ -374,6 +376,23 @@ struct amd64_pvt {
        struct error_injection injection;
 };
 
+enum err_codes {
+       DECODE_OK       =  0,
+       ERR_NODE        = -1,
+       ERR_CSROW       = -2,
+       ERR_CHANNEL     = -3,
+};
+
+struct err_info {
+       int err_code;
+       struct mem_ctl_info *src_mci;
+       int csrow;
+       int channel;
+       u16 syndrome;
+       u32 page;
+       u32 offset;
+};
+
 static inline u64 get_dram_base(struct amd64_pvt *pvt, unsigned i)
 {
        u64 addr = ((u64)pvt->ranges[i].base.lo & 0xffff0000) << 8;
@@ -447,7 +466,7 @@ static inline void amd64_remove_sysfs_inject_files(struct mem_ctl_info *mci)
 struct low_ops {
        int (*early_channel_count)      (struct amd64_pvt *pvt);
        void (*map_sysaddr_to_csrow)    (struct mem_ctl_info *mci, u64 sys_addr,
-                                        u16 syndrome);
+                                        struct err_info *);
        int (*dbam_to_cs)               (struct amd64_pvt *pvt, u8 dct, unsigned cs_mode);
        int (*read_dct_pci_cfg)         (struct amd64_pvt *pvt, int offset,
                                         u32 *val, const char *func);
@@ -459,6 +478,8 @@ struct amd64_family_type {
        struct low_ops ops;
 };
 
+int __amd64_read_pci_cfg_dword(struct pci_dev *pdev, int offset,
+                              u32 *val, const char *func);
 int __amd64_write_pci_cfg_dword(struct pci_dev *pdev, int offset,
                                u32 val, const char *func);
 
@@ -475,3 +496,15 @@ int amd64_get_dram_hole_info(struct mem_ctl_info *mci, u64 *hole_base,
                             u64 *hole_offset, u64 *hole_size);
 
 #define to_mci(k) container_of(k, struct mem_ctl_info, dev)
+
+/* Injection helpers */
+static inline void disable_caches(void *dummy)
+{
+       write_cr0(read_cr0() | X86_CR0_CD);
+       wbinvd();
+}
+
+static inline void enable_caches(void *dummy)
+{
+       write_cr0(read_cr0() & ~X86_CR0_CD);
+}
index 53d972e00dfb084d812419463b7a0984a9c1deda..8c171fa1cb9bc65f5531e178bd45cb9a0ef0c9ad 100644 (file)
@@ -22,20 +22,19 @@ static ssize_t amd64_inject_section_store(struct device *dev,
        struct mem_ctl_info *mci = to_mci(dev);
        struct amd64_pvt *pvt = mci->pvt_info;
        unsigned long value;
-       int ret = 0;
+       int ret;
 
        ret = strict_strtoul(data, 10, &value);
-       if (ret != -EINVAL) {
+       if (ret < 0)
+               return ret;
 
-               if (value > 3) {
-                       amd64_warn("%s: invalid section 0x%lx\n", __func__, value);
-                       return -EINVAL;
-               }
-
-               pvt->injection.section = (u32) value;
-               return count;
+       if (value > 3) {
+               amd64_warn("%s: invalid section 0x%lx\n", __func__, value);
+               return -EINVAL;
        }
-       return ret;
+
+       pvt->injection.section = (u32) value;
+       return count;
 }
 
 static ssize_t amd64_inject_word_show(struct device *dev,
@@ -60,20 +59,19 @@ static ssize_t amd64_inject_word_store(struct device *dev,
        struct mem_ctl_info *mci = to_mci(dev);
        struct amd64_pvt *pvt = mci->pvt_info;
        unsigned long value;
-       int ret = 0;
+       int ret;
 
        ret = strict_strtoul(data, 10, &value);
-       if (ret != -EINVAL) {
+       if (ret < 0)
+               return ret;
 
-               if (value > 8) {
-                       amd64_warn("%s: invalid word 0x%lx\n", __func__, value);
-                       return -EINVAL;
-               }
-
-               pvt->injection.word = (u32) value;
-               return count;
+       if (value > 8) {
+               amd64_warn("%s: invalid word 0x%lx\n", __func__, value);
+               return -EINVAL;
        }
-       return ret;
+
+       pvt->injection.word = (u32) value;
+       return count;
 }
 
 static ssize_t amd64_inject_ecc_vector_show(struct device *dev,
@@ -97,21 +95,19 @@ static ssize_t amd64_inject_ecc_vector_store(struct device *dev,
        struct mem_ctl_info *mci = to_mci(dev);
        struct amd64_pvt *pvt = mci->pvt_info;
        unsigned long value;
-       int ret = 0;
+       int ret;
 
        ret = strict_strtoul(data, 16, &value);
-       if (ret != -EINVAL) {
+       if (ret < 0)
+               return ret;
 
-               if (value & 0xFFFF0000) {
-                       amd64_warn("%s: invalid EccVector: 0x%lx\n",
-                                  __func__, value);
-                       return -EINVAL;
-               }
-
-               pvt->injection.bit_map = (u32) value;
-               return count;
+       if (value & 0xFFFF0000) {
+               amd64_warn("%s: invalid EccVector: 0x%lx\n", __func__, value);
+               return -EINVAL;
        }
-       return ret;
+
+       pvt->injection.bit_map = (u32) value;
+       return count;
 }
 
 /*
@@ -126,28 +122,25 @@ static ssize_t amd64_inject_read_store(struct device *dev,
        struct amd64_pvt *pvt = mci->pvt_info;
        unsigned long value;
        u32 section, word_bits;
-       int ret = 0;
+       int ret;
 
        ret = strict_strtoul(data, 10, &value);
-       if (ret != -EINVAL) {
+       if (ret < 0)
+               return ret;
 
-               /* Form value to choose 16-byte section of cacheline */
-               section = F10_NB_ARRAY_DRAM_ECC |
-                               SET_NB_ARRAY_ADDRESS(pvt->injection.section);
-               amd64_write_pci_cfg(pvt->F3, F10_NB_ARRAY_ADDR, section);
+       /* Form value to choose 16-byte section of cacheline */
+       section = F10_NB_ARRAY_DRAM | SET_NB_ARRAY_ADDR(pvt->injection.section);
 
-               word_bits = SET_NB_DRAM_INJECTION_READ(pvt->injection.word,
-                                               pvt->injection.bit_map);
+       amd64_write_pci_cfg(pvt->F3, F10_NB_ARRAY_ADDR, section);
 
-               /* Issue 'word' and 'bit' along with the READ request */
-               amd64_write_pci_cfg(pvt->F3, F10_NB_ARRAY_DATA, word_bits);
+       word_bits = SET_NB_DRAM_INJECTION_READ(pvt->injection);
 
-               edac_dbg(0, "section=0x%x word_bits=0x%x\n",
-                        section, word_bits);
+       /* Issue 'word' and 'bit' along with the READ request */
+       amd64_write_pci_cfg(pvt->F3, F10_NB_ARRAY_DATA, word_bits);
 
-               return count;
-       }
-       return ret;
+       edac_dbg(0, "section=0x%x word_bits=0x%x\n", section, word_bits);
+
+       return count;
 }
 
 /*
@@ -160,30 +153,43 @@ static ssize_t amd64_inject_write_store(struct device *dev,
 {
        struct mem_ctl_info *mci = to_mci(dev);
        struct amd64_pvt *pvt = mci->pvt_info;
+       u32 section, word_bits, tmp;
        unsigned long value;
-       u32 section, word_bits;
-       int ret = 0;
+       int ret;
 
        ret = strict_strtoul(data, 10, &value);
-       if (ret != -EINVAL) {
+       if (ret < 0)
+               return ret;
+
+       /* Form value to choose 16-byte section of cacheline */
+       section = F10_NB_ARRAY_DRAM | SET_NB_ARRAY_ADDR(pvt->injection.section);
+
+       amd64_write_pci_cfg(pvt->F3, F10_NB_ARRAY_ADDR, section);
 
-               /* Form value to choose 16-byte section of cacheline */
-               section = F10_NB_ARRAY_DRAM_ECC |
-                               SET_NB_ARRAY_ADDRESS(pvt->injection.section);
-               amd64_write_pci_cfg(pvt->F3, F10_NB_ARRAY_ADDR, section);
+       word_bits = SET_NB_DRAM_INJECTION_WRITE(pvt->injection);
 
-               word_bits = SET_NB_DRAM_INJECTION_WRITE(pvt->injection.word,
-                                               pvt->injection.bit_map);
+       pr_notice_once("Don't forget to decrease MCE polling interval in\n"
+                       "/sys/bus/machinecheck/devices/machinecheck<CPUNUM>/check_interval\n"
+                       "so that you can get the error report faster.\n");
 
-               /* Issue 'word' and 'bit' along with the READ request */
-               amd64_write_pci_cfg(pvt->F3, F10_NB_ARRAY_DATA, word_bits);
+       on_each_cpu(disable_caches, NULL, 1);
 
-               edac_dbg(0, "section=0x%x word_bits=0x%x\n",
-                        section, word_bits);
+       /* Issue 'word' and 'bit' along with the READ request */
+       amd64_write_pci_cfg(pvt->F3, F10_NB_ARRAY_DATA, word_bits);
 
-               return count;
+ retry:
+       /* wait until injection happens */
+       amd64_read_pci_cfg(pvt->F3, F10_NB_ARRAY_DATA, &tmp);
+       if (tmp & F10_NB_ARR_ECC_WR_REQ) {
+               cpu_relax();
+               goto retry;
        }
-       return ret;
+
+       on_each_cpu(enable_caches, NULL, 1);
+
+       edac_dbg(0, "section=0x%x word_bits=0x%x\n", section, word_bits);
+
+       return count;
 }
 
 /*
index 90f0b730e9bb1ee4a23a2941ea60021a12798d1f..f8440047f6d2f8934f16b5100bbdffec4d47d7d3 100644 (file)
@@ -433,13 +433,6 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num,
 
        mci->op_state = OP_ALLOC;
 
-       /* at this point, the root kobj is valid, and in order to
-        * 'free' the object, then the function:
-        *      edac_mc_unregister_sysfs_main_kobj() must be called
-        * which will perform kobj unregistration and the actual free
-        * will occur during the kobject callback operation
-        */
-
        return mci;
 
 error:
@@ -966,20 +959,22 @@ static void edac_ce_error(struct mem_ctl_info *mci,
                          long grain)
 {
        unsigned long remapped_page;
+       char *msg_aux = "";
+
+       if (*msg)
+               msg_aux = " ";
 
        if (edac_mc_get_log_ce()) {
                if (other_detail && *other_detail)
                        edac_mc_printk(mci, KERN_WARNING,
-                                      "%d CE %s on %s (%s %s - %s)\n",
-                                      error_count,
-                                      msg, label, location,
-                                      detail, other_detail);
+                                      "%d CE %s%son %s (%s %s - %s)\n",
+                                      error_count, msg, msg_aux, label,
+                                      location, detail, other_detail);
                else
                        edac_mc_printk(mci, KERN_WARNING,
-                                      "%d CE %s on %s (%s %s)\n",
-                                      error_count,
-                                      msg, label, location,
-                                      detail);
+                                      "%d CE %s%son %s (%s %s)\n",
+                                      error_count, msg, msg_aux, label,
+                                      location, detail);
        }
        edac_inc_ce_error(mci, enable_per_layer_report, pos, error_count);
 
@@ -1014,27 +1009,31 @@ static void edac_ue_error(struct mem_ctl_info *mci,
                          const char *other_detail,
                          const bool enable_per_layer_report)
 {
+       char *msg_aux = "";
+
+       if (*msg)
+               msg_aux = " ";
+
        if (edac_mc_get_log_ue()) {
                if (other_detail && *other_detail)
                        edac_mc_printk(mci, KERN_WARNING,
-                                      "%d UE %s on %s (%s %s - %s)\n",
-                                      error_count,
-                                      msg, label, location, detail,
-                                      other_detail);
+                                      "%d UE %s%son %s (%s %s - %s)\n",
+                                      error_count, msg, msg_aux, label,
+                                      location, detail, other_detail);
                else
                        edac_mc_printk(mci, KERN_WARNING,
-                                      "%d UE %s on %s (%s %s)\n",
-                                      error_count,
-                                      msg, label, location, detail);
+                                      "%d UE %s%son %s (%s %s)\n",
+                                      error_count, msg, msg_aux, label,
+                                      location, detail);
        }
 
        if (edac_mc_get_panic_on_ue()) {
                if (other_detail && *other_detail)
-                       panic("UE %s on %s (%s%s - %s)\n",
-                             msg, label, location, detail, other_detail);
+                       panic("UE %s%son %s (%s%s - %s)\n",
+                             msg, msg_aux, label, location, detail, other_detail);
                else
-                       panic("UE %s on %s (%s%s)\n",
-                             msg, label, location, detail);
+                       panic("UE %s%son %s (%s%s)\n",
+                             msg, msg_aux, label, location, detail);
        }
 
        edac_inc_ue_error(mci, enable_per_layer_report, pos, error_count);
@@ -1093,10 +1092,6 @@ void edac_mc_handle_error(const enum hw_event_mc_err_type type,
         */
        for (i = 0; i < mci->n_layers; i++) {
                if (pos[i] >= (int)mci->layers[i].size) {
-                       if (type == HW_EVENT_ERR_CORRECTED)
-                               p = "CE";
-                       else
-                               p = "UE";
 
                        edac_mc_printk(mci, KERN_ERR,
                                       "INTERNAL ERROR: %s value is out of range (%d >= %d)\n",
@@ -1128,6 +1123,7 @@ void edac_mc_handle_error(const enum hw_event_mc_err_type type,
        grain = 0;
        p = label;
        *p = '\0';
+
        for (i = 0; i < mci->tot_dimms; i++) {
                struct dimm_info *dimm = mci->dimms[i];
 
@@ -1179,6 +1175,12 @@ void edac_mc_handle_error(const enum hw_event_mc_err_type type,
        if (!enable_per_layer_report) {
                strcpy(label, "any memory");
        } else {
+
+               if (mci->csbased) {
+                       row  = top_layer;
+                       chan = mid_layer;
+               }
+
                edac_dbg(4, "csrow/channel to increment: (%d,%d)\n", row, chan);
                if (p == label)
                        strcpy(label, "unknown memory");
@@ -1195,6 +1197,7 @@ void edac_mc_handle_error(const enum hw_event_mc_err_type type,
 
        /* Fill the RAM location data */
        p = location;
+
        for (i = 0; i < mci->n_layers; i++) {
                if (pos[i] < 0)
                        continue;
@@ -1207,7 +1210,6 @@ void edac_mc_handle_error(const enum hw_event_mc_err_type type,
                *(p - 1) = '\0';
 
        /* Report the error via the trace interface */
-
        grain_bits = fls_long(grain) + 1;
        trace_mc_event(type, msg, label, error_count,
                       mci->mc_idx, top_layer, mid_layer, low_layer,
index ed0bc07b85039deb78c09812e461e0c41e3b3670..52813b8b0f5f7fabe372937a1d4ffe8c0e6f7b3e 100644 (file)
@@ -180,6 +180,9 @@ static ssize_t csrow_size_show(struct device *dev,
        int i;
        u32 nr_pages = 0;
 
+       if (csrow->mci->csbased)
+               return sprintf(data, "%u\n", PAGES_TO_MiB(csrow->nr_pages));
+
        for (i = 0; i < csrow->nr_channels; i++)
                nr_pages += csrow->channels[i]->dimm->nr_pages;
        return sprintf(data, "%u\n", PAGES_TO_MiB(nr_pages));
@@ -373,6 +376,7 @@ static int edac_create_csrow_object(struct mem_ctl_info *mci,
        csrow->dev.bus = &mci->bus;
        device_initialize(&csrow->dev);
        csrow->dev.parent = &mci->dev;
+       csrow->mci = mci;
        dev_set_name(&csrow->dev, "csrow%d", index);
        dev_set_drvdata(&csrow->dev, csrow);
 
@@ -777,10 +781,14 @@ static ssize_t mci_size_mb_show(struct device *dev,
        for (csrow_idx = 0; csrow_idx < mci->nr_csrows; csrow_idx++) {
                struct csrow_info *csrow = mci->csrows[csrow_idx];
 
-               for (j = 0; j < csrow->nr_channels; j++) {
-                       struct dimm_info *dimm = csrow->channels[j]->dimm;
+               if (csrow->mci->csbased) {
+                       total_pages += csrow->nr_pages;
+               } else {
+                       for (j = 0; j < csrow->nr_channels; j++) {
+                               struct dimm_info *dimm = csrow->channels[j]->dimm;
 
-                       total_pages += dimm->nr_pages;
+                               total_pages += dimm->nr_pages;
+                       }
                }
        }
 
@@ -838,14 +846,8 @@ static ssize_t edac_fake_inject_write(struct file *file,
        return count;
 }
 
-static int debugfs_open(struct inode *inode, struct file *file)
-{
-       file->private_data = inode->i_private;
-       return 0;
-}
-
 static const struct file_operations debug_fake_inject_fops = {
-       .open = debugfs_open,
+       .open = simple_open,
        .write = edac_fake_inject_write,
        .llseek = generic_file_llseek,
 };
index 58a28d838f37bfef26450bacdf11c8a338f6dcc7..12c951a2c33d5c8bac6d80bf6f0221467278940e 100644 (file)
 #define EDAC_VERSION "Ver: 3.0.0"
 
 #ifdef CONFIG_EDAC_DEBUG
+
+static int edac_set_debug_level(const char *buf, struct kernel_param *kp)
+{
+       unsigned long val;
+       int ret;
+
+       ret = kstrtoul(buf, 0, &val);
+       if (ret)
+               return ret;
+
+       if (val < 0 || val > 4)
+               return -EINVAL;
+
+       return param_set_int(buf, kp);
+}
+
 /* Values of 0 to 4 will generate output */
 int edac_debug_level = 2;
 EXPORT_SYMBOL_GPL(edac_debug_level);
+
+module_param_call(edac_debug_level, edac_set_debug_level, param_get_int,
+                 &edac_debug_level, 0644);
+MODULE_PARM_DESC(edac_debug_level, "EDAC debug level: [0-4], default: 2");
 #endif
 
 /* scope is to module level only */
@@ -132,10 +152,3 @@ module_exit(edac_exit);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Doug Thompson www.softwarebitmaker.com, et al");
 MODULE_DESCRIPTION("Core library routines for EDAC reporting");
-
-/* refer to *_sysfs.c files for parameters that are exported via sysfs */
-
-#ifdef CONFIG_EDAC_DEBUG
-module_param(edac_debug_level, int, 0644);
-MODULE_PARM_DESC(edac_debug_level, "Debug level");
-#endif
index ee87ef972ead7667a60a1359e9347e9ebaf60bda..dd370f92ace3402321bbc6f94cfd6814cbb3fb4f 100644 (file)
@@ -470,7 +470,8 @@ struct edac_pci_ctl_info *edac_pci_create_generic_ctl(struct device *dev,
 
        pci->mod_name = mod_name;
        pci->ctl_name = EDAC_PCI_GENCTL_NAME;
-       pci->edac_check = edac_pci_generic_check;
+       if (edac_op_state == EDAC_OPSTATE_POLL)
+               pci->edac_check = edac_pci_generic_check;
 
        pdata->edac_idx = edac_pci_idx++;
 
index c769f477fd2228916498a291b37c384b86bb3297..7ea4cc2e8bd2292ca8871b6d27493d94ab9cda80 100644 (file)
@@ -113,14 +113,8 @@ static ssize_t highbank_mc_err_inject_write(struct file *file,
        return count;
 }
 
-static int debugfs_open(struct inode *inode, struct file *file)
-{
-       file->private_data = inode->i_private;
-       return 0;
-}
-
 static const struct file_operations highbank_mc_debug_inject_fops = {
-       .open = debugfs_open,
+       .open = simple_open,
        .write = highbank_mc_err_inject_write,
        .llseek = generic_file_llseek,
 };
index d0c372e30de41766cac54568c12d2994738cbf38..ad637572d8c77420c6da8e213890adb4f077e2fe 100644 (file)
@@ -64,7 +64,7 @@ EXPORT_SYMBOL_GPL(to_msgs);
 const char * const ii_msgs[] = { "MEM", "RESV", "IO", "GEN" };
 EXPORT_SYMBOL_GPL(ii_msgs);
 
-static const char * const f15h_ic_mce_desc[] = {
+static const char * const f15h_mc1_mce_desc[] = {
        "UC during a demand linefill from L2",
        "Parity error during data load from IC",
        "Parity error for IC valid bit",
@@ -84,7 +84,7 @@ static const char * const f15h_ic_mce_desc[] = {
        "fetch address FIFO"
 };
 
-static const char * const f15h_cu_mce_desc[] = {
+static const char * const f15h_mc2_mce_desc[] = {
        "Fill ECC error on data fills",                 /* xec = 0x4 */
        "Fill parity error on insn fills",
        "Prefetcher request FIFO parity error",
@@ -101,7 +101,7 @@ static const char * const f15h_cu_mce_desc[] = {
        "PRB address parity error"
 };
 
-static const char * const nb_mce_desc[] = {
+static const char * const mc4_mce_desc[] = {
        "DRAM ECC error detected on the NB",
        "CRC error detected on HT link",
        "Link-defined sync error packets detected on HT link",
@@ -123,7 +123,7 @@ static const char * const nb_mce_desc[] = {
        "ECC Error in the Probe Filter directory"
 };
 
-static const char * const fr_ex_mce_desc[] = {
+static const char * const mc5_mce_desc[] = {
        "CPU Watchdog timer expire",
        "Wakeup array dest tag",
        "AG payload array",
@@ -139,7 +139,7 @@ static const char * const fr_ex_mce_desc[] = {
        "DE error occurred"
 };
 
-static bool f12h_dc_mce(u16 ec, u8 xec)
+static bool f12h_mc0_mce(u16 ec, u8 xec)
 {
        bool ret = false;
 
@@ -157,26 +157,26 @@ static bool f12h_dc_mce(u16 ec, u8 xec)
        return ret;
 }
 
-static bool f10h_dc_mce(u16 ec, u8 xec)
+static bool f10h_mc0_mce(u16 ec, u8 xec)
 {
        if (R4(ec) == R4_GEN && LL(ec) == LL_L1) {
                pr_cont("during data scrub.\n");
                return true;
        }
-       return f12h_dc_mce(ec, xec);
+       return f12h_mc0_mce(ec, xec);
 }
 
-static bool k8_dc_mce(u16 ec, u8 xec)
+static bool k8_mc0_mce(u16 ec, u8 xec)
 {
        if (BUS_ERROR(ec)) {
                pr_cont("during system linefill.\n");
                return true;
        }
 
-       return f10h_dc_mce(ec, xec);
+       return f10h_mc0_mce(ec, xec);
 }
 
-static bool f14h_dc_mce(u16 ec, u8 xec)
+static bool f14h_mc0_mce(u16 ec, u8 xec)
 {
        u8 r4    = R4(ec);
        bool ret = true;
@@ -228,7 +228,7 @@ static bool f14h_dc_mce(u16 ec, u8 xec)
        return ret;
 }
 
-static bool f15h_dc_mce(u16 ec, u8 xec)
+static bool f15h_mc0_mce(u16 ec, u8 xec)
 {
        bool ret = true;
 
@@ -275,12 +275,12 @@ static bool f15h_dc_mce(u16 ec, u8 xec)
        return ret;
 }
 
-static void amd_decode_dc_mce(struct mce *m)
+static void decode_mc0_mce(struct mce *m)
 {
        u16 ec = EC(m->status);
        u8 xec = XEC(m->status, xec_mask);
 
-       pr_emerg(HW_ERR "Data Cache Error: ");
+       pr_emerg(HW_ERR "MC0 Error: ");
 
        /* TLB error signatures are the same across families */
        if (TLB_ERROR(ec)) {
@@ -290,13 +290,13 @@ static void amd_decode_dc_mce(struct mce *m)
                                            : (xec ? "multimatch" : "parity")));
                        return;
                }
-       } else if (fam_ops->dc_mce(ec, xec))
+       } else if (fam_ops->mc0_mce(ec, xec))
                ;
        else
-               pr_emerg(HW_ERR "Corrupted DC MCE info?\n");
+               pr_emerg(HW_ERR "Corrupted MC0 MCE info?\n");
 }
 
-static bool k8_ic_mce(u16 ec, u8 xec)
+static bool k8_mc1_mce(u16 ec, u8 xec)
 {
        u8 ll    = LL(ec);
        bool ret = true;
@@ -330,7 +330,7 @@ static bool k8_ic_mce(u16 ec, u8 xec)
        return ret;
 }
 
-static bool f14h_ic_mce(u16 ec, u8 xec)
+static bool f14h_mc1_mce(u16 ec, u8 xec)
 {
        u8 r4    = R4(ec);
        bool ret = true;
@@ -349,7 +349,7 @@ static bool f14h_ic_mce(u16 ec, u8 xec)
        return ret;
 }
 
-static bool f15h_ic_mce(u16 ec, u8 xec)
+static bool f15h_mc1_mce(u16 ec, u8 xec)
 {
        bool ret = true;
 
@@ -358,19 +358,19 @@ static bool f15h_ic_mce(u16 ec, u8 xec)
 
        switch (xec) {
        case 0x0 ... 0xa:
-               pr_cont("%s.\n", f15h_ic_mce_desc[xec]);
+               pr_cont("%s.\n", f15h_mc1_mce_desc[xec]);
                break;
 
        case 0xd:
-               pr_cont("%s.\n", f15h_ic_mce_desc[xec-2]);
+               pr_cont("%s.\n", f15h_mc1_mce_desc[xec-2]);
                break;
 
        case 0x10:
-               pr_cont("%s.\n", f15h_ic_mce_desc[xec-4]);
+               pr_cont("%s.\n", f15h_mc1_mce_desc[xec-4]);
                break;
 
        case 0x11 ... 0x14:
-               pr_cont("Decoder %s parity error.\n", f15h_ic_mce_desc[xec-4]);
+               pr_cont("Decoder %s parity error.\n", f15h_mc1_mce_desc[xec-4]);
                break;
 
        default:
@@ -379,12 +379,12 @@ static bool f15h_ic_mce(u16 ec, u8 xec)
        return ret;
 }
 
-static void amd_decode_ic_mce(struct mce *m)
+static void decode_mc1_mce(struct mce *m)
 {
        u16 ec = EC(m->status);
        u8 xec = XEC(m->status, xec_mask);
 
-       pr_emerg(HW_ERR "Instruction Cache Error: ");
+       pr_emerg(HW_ERR "MC1 Error: ");
 
        if (TLB_ERROR(ec))
                pr_cont("%s TLB %s.\n", LL_MSG(ec),
@@ -393,18 +393,18 @@ static void amd_decode_ic_mce(struct mce *m)
                bool k8 = (boot_cpu_data.x86 == 0xf && (m->status & BIT_64(58)));
 
                pr_cont("during %s.\n", (k8 ? "system linefill" : "NB data read"));
-       } else if (fam_ops->ic_mce(ec, xec))
+       } else if (fam_ops->mc1_mce(ec, xec))
                ;
        else
-               pr_emerg(HW_ERR "Corrupted IC MCE info?\n");
+               pr_emerg(HW_ERR "Corrupted MC1 MCE info?\n");
 }
 
-static void amd_decode_bu_mce(struct mce *m)
+static void decode_mc2_mce(struct mce *m)
 {
        u16 ec = EC(m->status);
        u8 xec = XEC(m->status, xec_mask);
 
-       pr_emerg(HW_ERR "Bus Unit Error");
+       pr_emerg(HW_ERR "MC2 Error");
 
        if (xec == 0x1)
                pr_cont(" in the write data buffers.\n");
@@ -429,24 +429,24 @@ static void amd_decode_bu_mce(struct mce *m)
                                pr_cont(": %s parity/ECC error during data "
                                        "access from L2.\n", R4_MSG(ec));
                        else
-                               goto wrong_bu_mce;
+                               goto wrong_mc2_mce;
                } else
-                       goto wrong_bu_mce;
+                       goto wrong_mc2_mce;
        } else
-               goto wrong_bu_mce;
+               goto wrong_mc2_mce;
 
        return;
 
-wrong_bu_mce:
-       pr_emerg(HW_ERR "Corrupted BU MCE info?\n");
+ wrong_mc2_mce:
+       pr_emerg(HW_ERR "Corrupted MC2 MCE info?\n");
 }
 
-static void amd_decode_cu_mce(struct mce *m)
+static void decode_f15_mc2_mce(struct mce *m)
 {
        u16 ec = EC(m->status);
        u8 xec = XEC(m->status, xec_mask);
 
-       pr_emerg(HW_ERR "Combined Unit Error: ");
+       pr_emerg(HW_ERR "MC2 Error: ");
 
        if (TLB_ERROR(ec)) {
                if (xec == 0x0)
@@ -454,63 +454,63 @@ static void amd_decode_cu_mce(struct mce *m)
                else if (xec == 0x1)
                        pr_cont("Poison data provided for TLB fill.\n");
                else
-                       goto wrong_cu_mce;
+                       goto wrong_f15_mc2_mce;
        } else if (BUS_ERROR(ec)) {
                if (xec > 2)
-                       goto wrong_cu_mce;
+                       goto wrong_f15_mc2_mce;
 
                pr_cont("Error during attempted NB data read.\n");
        } else if (MEM_ERROR(ec)) {
                switch (xec) {
                case 0x4 ... 0xc:
-                       pr_cont("%s.\n", f15h_cu_mce_desc[xec - 0x4]);
+                       pr_cont("%s.\n", f15h_mc2_mce_desc[xec - 0x4]);
                        break;
 
                case 0x10 ... 0x14:
-                       pr_cont("%s.\n", f15h_cu_mce_desc[xec - 0x7]);
+                       pr_cont("%s.\n", f15h_mc2_mce_desc[xec - 0x7]);
                        break;
 
                default:
-                       goto wrong_cu_mce;
+                       goto wrong_f15_mc2_mce;
                }
        }
 
        return;
 
-wrong_cu_mce:
-       pr_emerg(HW_ERR "Corrupted CU MCE info?\n");
+ wrong_f15_mc2_mce:
+       pr_emerg(HW_ERR "Corrupted MC2 MCE info?\n");
 }
 
-static void amd_decode_ls_mce(struct mce *m)
+static void decode_mc3_mce(struct mce *m)
 {
        u16 ec = EC(m->status);
        u8 xec = XEC(m->status, xec_mask);
 
        if (boot_cpu_data.x86 >= 0x14) {
-               pr_emerg("You shouldn't be seeing an LS MCE on this cpu family,"
+               pr_emerg("You shouldn't be seeing MC3 MCE on this cpu family,"
                         " please report on LKML.\n");
                return;
        }
 
-       pr_emerg(HW_ERR "Load Store Error");
+       pr_emerg(HW_ERR "MC3 Error");
 
        if (xec == 0x0) {
                u8 r4 = R4(ec);
 
                if (!BUS_ERROR(ec) || (r4 != R4_DRD && r4 != R4_DWR))
-                       goto wrong_ls_mce;
+                       goto wrong_mc3_mce;
 
                pr_cont(" during %s.\n", R4_MSG(ec));
        } else
-               goto wrong_ls_mce;
+               goto wrong_mc3_mce;
 
        return;
 
-wrong_ls_mce:
-       pr_emerg(HW_ERR "Corrupted LS MCE info?\n");
+ wrong_mc3_mce:
+       pr_emerg(HW_ERR "Corrupted MC3 MCE info?\n");
 }
 
-void amd_decode_nb_mce(struct mce *m)
+static void decode_mc4_mce(struct mce *m)
 {
        struct cpuinfo_x86 *c = &boot_cpu_data;
        int node_id = amd_get_nb_id(m->extcpu);
@@ -518,7 +518,7 @@ void amd_decode_nb_mce(struct mce *m)
        u8 xec = XEC(m->status, 0x1f);
        u8 offset = 0;
 
-       pr_emerg(HW_ERR "Northbridge Error (node %d): ", node_id);
+       pr_emerg(HW_ERR "MC4 Error (node %d): ", node_id);
 
        switch (xec) {
        case 0x0 ... 0xe:
@@ -527,9 +527,9 @@ void amd_decode_nb_mce(struct mce *m)
                if (xec == 0x0 || xec == 0x8) {
                        /* no ECCs on F11h */
                        if (c->x86 == 0x11)
-                               goto wrong_nb_mce;
+                               goto wrong_mc4_mce;
 
-                       pr_cont("%s.\n", nb_mce_desc[xec]);
+                       pr_cont("%s.\n", mc4_mce_desc[xec]);
 
                        if (nb_bus_decoder)
                                nb_bus_decoder(node_id, m);
@@ -543,14 +543,14 @@ void amd_decode_nb_mce(struct mce *m)
                else if (BUS_ERROR(ec))
                        pr_cont("DMA Exclusion Vector Table Walk error.\n");
                else
-                       goto wrong_nb_mce;
+                       goto wrong_mc4_mce;
                return;
 
        case 0x19:
                if (boot_cpu_data.x86 == 0x15)
                        pr_cont("Compute Unit Data Error.\n");
                else
-                       goto wrong_nb_mce;
+                       goto wrong_mc4_mce;
                return;
 
        case 0x1c ... 0x1f:
@@ -558,46 +558,44 @@ void amd_decode_nb_mce(struct mce *m)
                break;
 
        default:
-               goto wrong_nb_mce;
+               goto wrong_mc4_mce;
        }
 
-       pr_cont("%s.\n", nb_mce_desc[xec - offset]);
+       pr_cont("%s.\n", mc4_mce_desc[xec - offset]);
        return;
 
-wrong_nb_mce:
-       pr_emerg(HW_ERR "Corrupted NB MCE info?\n");
+ wrong_mc4_mce:
+       pr_emerg(HW_ERR "Corrupted MC4 MCE info?\n");
 }
-EXPORT_SYMBOL_GPL(amd_decode_nb_mce);
 
-static void amd_decode_fr_mce(struct mce *m)
+static void decode_mc5_mce(struct mce *m)
 {
        struct cpuinfo_x86 *c = &boot_cpu_data;
        u8 xec = XEC(m->status, xec_mask);
 
        if (c->x86 == 0xf || c->x86 == 0x11)
-               goto wrong_fr_mce;
+               goto wrong_mc5_mce;
 
-       pr_emerg(HW_ERR "%s Error: ",
-                (c->x86 == 0x15 ? "Execution Unit" : "FIROB"));
+       pr_emerg(HW_ERR "MC5 Error: ");
 
        if (xec == 0x0 || xec == 0xc)
-               pr_cont("%s.\n", fr_ex_mce_desc[xec]);
+               pr_cont("%s.\n", mc5_mce_desc[xec]);
        else if (xec < 0xd)
-               pr_cont("%s parity error.\n", fr_ex_mce_desc[xec]);
+               pr_cont("%s parity error.\n", mc5_mce_desc[xec]);
        else
-               goto wrong_fr_mce;
+               goto wrong_mc5_mce;
 
        return;
 
-wrong_fr_mce:
-       pr_emerg(HW_ERR "Corrupted FR MCE info?\n");
+ wrong_mc5_mce:
+       pr_emerg(HW_ERR "Corrupted MC5 MCE info?\n");
 }
 
-static void amd_decode_fp_mce(struct mce *m)
+static void decode_mc6_mce(struct mce *m)
 {
        u8 xec = XEC(m->status, xec_mask);
 
-       pr_emerg(HW_ERR "Floating Point Unit Error: ");
+       pr_emerg(HW_ERR "MC6 Error: ");
 
        switch (xec) {
        case 0x1:
@@ -621,7 +619,7 @@ static void amd_decode_fp_mce(struct mce *m)
                break;
 
        default:
-               goto wrong_fp_mce;
+               goto wrong_mc6_mce;
                break;
        }
 
@@ -629,8 +627,8 @@ static void amd_decode_fp_mce(struct mce *m)
 
        return;
 
-wrong_fp_mce:
-       pr_emerg(HW_ERR "Corrupted FP MCE info?\n");
+ wrong_mc6_mce:
+       pr_emerg(HW_ERR "Corrupted MC6 MCE info?\n");
 }
 
 static inline void amd_decode_err_code(u16 ec)
@@ -669,74 +667,94 @@ static bool amd_filter_mce(struct mce *m)
        return false;
 }
 
+static const char *decode_error_status(struct mce *m)
+{
+       if (m->status & MCI_STATUS_UC) {
+               if (m->status & MCI_STATUS_PCC)
+                       return "System Fatal error.";
+               if (m->mcgstatus & MCG_STATUS_RIPV)
+                       return "Uncorrected, software restartable error.";
+               return "Uncorrected, software containable error.";
+       }
+
+       if (m->status & MCI_STATUS_DEFERRED)
+               return "Deferred error.";
+
+       return "Corrected error, no action required.";
+}
+
 int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data)
 {
        struct mce *m = (struct mce *)data;
-       struct cpuinfo_x86 *c = &boot_cpu_data;
+       struct cpuinfo_x86 *c = &cpu_data(m->extcpu);
        int ecc;
 
        if (amd_filter_mce(m))
                return NOTIFY_STOP;
 
-       pr_emerg(HW_ERR "CPU:%d\tMC%d_STATUS[%s|%s|%s|%s|%s",
-               m->extcpu, m->bank,
-               ((m->status & MCI_STATUS_OVER)  ? "Over"  : "-"),
-               ((m->status & MCI_STATUS_UC)    ? "UE"    : "CE"),
-               ((m->status & MCI_STATUS_MISCV) ? "MiscV" : "-"),
-               ((m->status & MCI_STATUS_PCC)   ? "PCC"   : "-"),
-               ((m->status & MCI_STATUS_ADDRV) ? "AddrV" : "-"));
-
-       if (c->x86 == 0x15)
-               pr_cont("|%s|%s",
-                       ((m->status & BIT_64(44)) ? "Deferred" : "-"),
-                       ((m->status & BIT_64(43)) ? "Poison"   : "-"));
-
-       /* do the two bits[14:13] together */
-       ecc = (m->status >> 45) & 0x3;
-       if (ecc)
-               pr_cont("|%sECC", ((ecc == 2) ? "C" : "U"));
-
-       pr_cont("]: 0x%016llx\n", m->status);
-
-       if (m->status & MCI_STATUS_ADDRV)
-               pr_emerg(HW_ERR "\tMC%d_ADDR: 0x%016llx\n", m->bank, m->addr);
-
        switch (m->bank) {
        case 0:
-               amd_decode_dc_mce(m);
+               decode_mc0_mce(m);
                break;
 
        case 1:
-               amd_decode_ic_mce(m);
+               decode_mc1_mce(m);
                break;
 
        case 2:
                if (c->x86 == 0x15)
-                       amd_decode_cu_mce(m);
+                       decode_f15_mc2_mce(m);
                else
-                       amd_decode_bu_mce(m);
+                       decode_mc2_mce(m);
                break;
 
        case 3:
-               amd_decode_ls_mce(m);
+               decode_mc3_mce(m);
                break;
 
        case 4:
-               amd_decode_nb_mce(m);
+               decode_mc4_mce(m);
                break;
 
        case 5:
-               amd_decode_fr_mce(m);
+               decode_mc5_mce(m);
                break;
 
        case 6:
-               amd_decode_fp_mce(m);
+               decode_mc6_mce(m);
                break;
 
        default:
                break;
        }
 
+       pr_emerg(HW_ERR "Error Status: %s\n", decode_error_status(m));
+
+       pr_emerg(HW_ERR "CPU:%d (%x:%x:%x) MC%d_STATUS[%s|%s|%s|%s|%s",
+               m->extcpu,
+               c->x86, c->x86_model, c->x86_mask,
+               m->bank,
+               ((m->status & MCI_STATUS_OVER)  ? "Over"  : "-"),
+               ((m->status & MCI_STATUS_UC)    ? "UE"    : "CE"),
+               ((m->status & MCI_STATUS_MISCV) ? "MiscV" : "-"),
+               ((m->status & MCI_STATUS_PCC)   ? "PCC"   : "-"),
+               ((m->status & MCI_STATUS_ADDRV) ? "AddrV" : "-"));
+
+       if (c->x86 == 0x15)
+               pr_cont("|%s|%s",
+                       ((m->status & MCI_STATUS_DEFERRED) ? "Deferred" : "-"),
+                       ((m->status & MCI_STATUS_POISON)   ? "Poison"   : "-"));
+
+       /* do the two bits[14:13] together */
+       ecc = (m->status >> 45) & 0x3;
+       if (ecc)
+               pr_cont("|%sECC", ((ecc == 2) ? "C" : "U"));
+
+       pr_cont("]: 0x%016llx\n", m->status);
+
+       if (m->status & MCI_STATUS_ADDRV)
+               pr_emerg(HW_ERR "MC%d_ADDR: 0x%016llx\n", m->bank, m->addr);
+
        amd_decode_err_code(m->status & 0xffff);
 
        return NOTIFY_STOP;
@@ -763,35 +781,35 @@ static int __init mce_amd_init(void)
 
        switch (c->x86) {
        case 0xf:
-               fam_ops->dc_mce = k8_dc_mce;
-               fam_ops->ic_mce = k8_ic_mce;
+               fam_ops->mc0_mce = k8_mc0_mce;
+               fam_ops->mc1_mce = k8_mc1_mce;
                break;
 
        case 0x10:
-               fam_ops->dc_mce = f10h_dc_mce;
-               fam_ops->ic_mce = k8_ic_mce;
+               fam_ops->mc0_mce = f10h_mc0_mce;
+               fam_ops->mc1_mce = k8_mc1_mce;
                break;
 
        case 0x11:
-               fam_ops->dc_mce = k8_dc_mce;
-               fam_ops->ic_mce = k8_ic_mce;
+               fam_ops->mc0_mce = k8_mc0_mce;
+               fam_ops->mc1_mce = k8_mc1_mce;
                break;
 
        case 0x12:
-               fam_ops->dc_mce = f12h_dc_mce;
-               fam_ops->ic_mce = k8_ic_mce;
+               fam_ops->mc0_mce = f12h_mc0_mce;
+               fam_ops->mc1_mce = k8_mc1_mce;
                break;
 
        case 0x14:
                nb_err_cpumask  = 0x3;
-               fam_ops->dc_mce = f14h_dc_mce;
-               fam_ops->ic_mce = f14h_ic_mce;
+               fam_ops->mc0_mce = f14h_mc0_mce;
+               fam_ops->mc1_mce = f14h_mc1_mce;
                break;
 
        case 0x15:
                xec_mask = 0x1f;
-               fam_ops->dc_mce = f15h_dc_mce;
-               fam_ops->ic_mce = f15h_ic_mce;
+               fam_ops->mc0_mce = f15h_mc0_mce;
+               fam_ops->mc1_mce = f15h_mc1_mce;
                break;
 
        default:
index 8c87a5e870577c06b0082ca7d3b19eb7a81a252b..679679951e23a46371fdceec7bc158953150e3af 100644 (file)
 #define R4(x)                          (((x) >> 4) & 0xf)
 #define R4_MSG(x)                      ((R4(x) < 9) ?  rrrr_msgs[R4(x)] : "Wrong R4!")
 
-/*
- * F3x4C bits (MCi_STATUS' high half)
- */
-#define NBSH_ERR_CPU_VAL               BIT(24)
+#define MCI_STATUS_DEFERRED            BIT_64(44)
+#define MCI_STATUS_POISON              BIT_64(43)
 
 enum tt_ids {
        TT_INSTR = 0,
@@ -78,14 +76,13 @@ extern const char * const ii_msgs[];
  * per-family decoder ops
  */
 struct amd_decoder_ops {
-       bool (*dc_mce)(u16, u8);
-       bool (*ic_mce)(u16, u8);
+       bool (*mc0_mce)(u16, u8);
+       bool (*mc1_mce)(u16, u8);
 };
 
 void amd_report_gart_errors(bool);
 void amd_register_ecc_decoder(void (*f)(int, struct mce *));
 void amd_unregister_ecc_decoder(void (*f)(int, struct mce *));
-void amd_decode_nb_mce(struct mce *);
 int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data);
 
 #endif /* _EDAC_MCE_AMD_H */
diff --git a/drivers/edac/octeon_edac-l2c.c b/drivers/edac/octeon_edac-l2c.c
new file mode 100644 (file)
index 0000000..5f459aa
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2009 Wind River Systems,
+ *   written by Ralf Baechle <ralf@linux-mips.org>
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/edac.h>
+
+#include <asm/octeon/cvmx.h>
+
+#include "edac_core.h"
+#include "edac_module.h"
+
+#define EDAC_MOD_STR "octeon-l2c"
+
+static void co_l2c_poll(struct edac_device_ctl_info *l2c)
+{
+       union cvmx_l2t_err l2t_err;
+
+       l2t_err.u64 = cvmx_read_csr(CVMX_L2T_ERR);
+       if (l2t_err.s.sec_err) {
+               edac_device_handle_ce(l2c, 0, 0,
+                                     "Single bit error (corrected)");
+               l2t_err.s.sec_err = 1;          /* Reset */
+               cvmx_write_csr(CVMX_L2T_ERR, l2t_err.u64);
+       }
+       if (l2t_err.s.ded_err) {
+               edac_device_handle_ue(l2c, 0, 0,
+                                     "Double bit error (corrected)");
+               l2t_err.s.ded_err = 1;          /* Reset */
+               cvmx_write_csr(CVMX_L2T_ERR, l2t_err.u64);
+       }
+}
+
+static int __devinit co_l2c_probe(struct platform_device *pdev)
+{
+       struct edac_device_ctl_info *l2c;
+       union cvmx_l2t_err l2t_err;
+       int res = 0;
+
+       l2c = edac_device_alloc_ctl_info(0, "l2c", 1, NULL, 0, 0,
+                                        NULL, 0, edac_device_alloc_index());
+       if (!l2c)
+               return -ENOMEM;
+
+       l2c->dev = &pdev->dev;
+       platform_set_drvdata(pdev, l2c);
+       l2c->dev_name = dev_name(&pdev->dev);
+
+       l2c->mod_name = "octeon-l2c";
+       l2c->ctl_name = "octeon_l2c_err";
+       l2c->edac_check = co_l2c_poll;
+
+       if (edac_device_add_device(l2c) > 0) {
+               pr_err("%s: edac_device_add_device() failed\n", __func__);
+               goto err;
+       }
+
+       l2t_err.u64 = cvmx_read_csr(CVMX_L2T_ERR);
+       l2t_err.s.sec_intena = 0;       /* We poll */
+       l2t_err.s.ded_intena = 0;
+       l2t_err.s.sec_err = 1;          /* Clear, just in case */
+       l2t_err.s.ded_err = 1;
+       cvmx_write_csr(CVMX_L2T_ERR, l2t_err.u64);
+
+       return 0;
+
+err:
+       edac_device_free_ctl_info(l2c);
+
+       return res;
+}
+
+static int co_l2c_remove(struct platform_device *pdev)
+{
+       struct edac_device_ctl_info *l2c = platform_get_drvdata(pdev);
+
+       edac_device_del_device(&pdev->dev);
+       edac_device_free_ctl_info(l2c);
+
+       return 0;
+}
+
+static struct platform_driver co_l2c_driver = {
+       .probe = co_l2c_probe,
+       .remove = co_l2c_remove,
+       .driver = {
+                  .name = "co_l2c_edac",
+       }
+};
+
+static int __init co_edac_init(void)
+{
+       int ret;
+
+       ret = platform_driver_register(&co_l2c_driver);
+       if (ret)
+               pr_warning(EDAC_MOD_STR " EDAC failed to register\n");
+
+       return ret;
+}
+
+static void __exit co_edac_exit(void)
+{
+       platform_driver_unregister(&co_l2c_driver);
+}
+
+module_init(co_edac_init);
+module_exit(co_edac_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>");
diff --git a/drivers/edac/octeon_edac-lmc.c b/drivers/edac/octeon_edac-lmc.c
new file mode 100644 (file)
index 0000000..e0c1e44
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2009 Wind River Systems,
+ *   written by Ralf Baechle <ralf@linux-mips.org>
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/edac.h>
+
+#include <asm/octeon/cvmx.h>
+
+#include "edac_core.h"
+#include "edac_module.h"
+#include "octeon_edac-lmc.h"
+
+#define EDAC_MOD_STR "octeon"
+
+static struct mem_ctl_info *mc_cavium;
+static void *lmc_base;
+
+static void co_lmc_poll(struct mem_ctl_info *mci)
+{
+       union lmc_mem_cfg0 cfg0;
+       union lmc_fadr fadr;
+       char msg[64];
+
+       fadr.u64 = readq(lmc_base + LMC_FADR);
+       cfg0.u64 = readq(lmc_base + LMC_MEM_CFG0);
+       snprintf(msg, sizeof(msg), "DIMM %d rank %d bank %d row %d col %d",
+               fadr.fdimm, fadr.fbunk, fadr.fbank, fadr.frow, fadr.fcol);
+
+       if (cfg0.sec_err) {
+               edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, 0, 0, 0, -1, -1, -1,
+                                    msg, "");
+
+               cfg0.intr_sec_ena = -1;         /* Done, re-arm */
+       }
+
+       if (cfg0.ded_err) {
+               edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, 0, 0, 0, -1, -1, -1,
+                                    msg, "");
+               cfg0.intr_ded_ena = -1;         /* Done, re-arm */
+       }
+
+       writeq(cfg0.u64, lmc_base + LMC_MEM_CFG0);
+}
+
+static int __devinit co_lmc_probe(struct platform_device *pdev)
+{
+       struct mem_ctl_info *mci;
+       union lmc_mem_cfg0 cfg0;
+       int res = 0;
+
+       mci = edac_mc_alloc(0, 0, 0, 0);
+       if (!mci)
+               return -ENOMEM;
+
+       mci->pdev = &pdev->dev;
+       platform_set_drvdata(pdev, mci);
+       mci->dev_name = dev_name(&pdev->dev);
+
+       mci->mod_name = "octeon-lmc";
+       mci->ctl_name = "co_lmc_err";
+       mci->edac_check = co_lmc_poll;
+
+       if (edac_mc_add_mc(mci) > 0) {
+               pr_err("%s: edac_mc_add_mc() failed\n", __func__);
+               goto err;
+       }
+
+       cfg0.u64 = readq(lmc_base + LMC_MEM_CFG0);      /* We poll */
+       cfg0.intr_ded_ena = 0;
+       cfg0.intr_sec_ena = 0;
+       writeq(cfg0.u64, lmc_base + LMC_MEM_CFG0);
+
+       mc_cavium = mci;
+
+       return 0;
+
+err:
+       edac_mc_free(mci);
+
+       return res;
+}
+
+static int co_lmc_remove(struct platform_device *pdev)
+{
+       struct mem_ctl_info *mci = platform_get_drvdata(pdev);
+
+       mc_cavium = NULL;
+       edac_mc_del_mc(&pdev->dev);
+       edac_mc_free(mci);
+
+       return 0;
+}
+
+static struct platform_driver co_lmc_driver = {
+       .probe = co_lmc_probe,
+       .remove = co_lmc_remove,
+       .driver = {
+                  .name = "co_lmc_edac",
+       }
+};
+
+static int __init co_edac_init(void)
+{
+       union lmc_mem_cfg0 cfg0;
+       int ret;
+
+       lmc_base = ioremap_nocache(LMC_BASE, LMC_SIZE);
+       if (!lmc_base)
+               return -ENOMEM;
+
+       cfg0.u64 = readq(lmc_base + LMC_MEM_CFG0);
+       if (!cfg0.ecc_ena) {
+               pr_info(EDAC_MOD_STR " LMC EDAC: ECC disabled, good bye\n");
+               ret = -ENODEV;
+               goto out;
+       }
+
+       ret = platform_driver_register(&co_lmc_driver);
+       if (ret) {
+               pr_warning(EDAC_MOD_STR " LMC EDAC failed to register\n");
+               goto out;
+       }
+
+       return ret;
+
+out:
+       iounmap(lmc_base);
+
+       return ret;
+}
+
+static void __exit co_edac_exit(void)
+{
+       platform_driver_unregister(&co_lmc_driver);
+       iounmap(lmc_base);
+}
+
+module_init(co_edac_init);
+module_exit(co_edac_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>");
diff --git a/drivers/edac/octeon_edac-lmc.h b/drivers/edac/octeon_edac-lmc.h
new file mode 100644 (file)
index 0000000..246dc52
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * LMC Registers, see chapter 2.5
+ *
+ * These are RSL Type registers and are accessed indirectly across the
+ * I/O bus, so accesses are slowish.  Not that it matters.  Any size load is
+ * ok but stores must be 64-bit.
+ */
+#define LMC_BASE               0x0001180088000000
+#define LMC_SIZE               0xb8
+
+#define LMC_MEM_CFG0           0x0000000000000000
+#define LMC_MEM_CFG1           0x0000000000000008
+#define LMC_CTL                        0x0000000000000010
+#define LMC_DDR2_CTL           0x0000000000000018
+#define LMC_FADR               0x0000000000000020
+#define   LMC_FADR_FDIMM
+#define   LMC_FADR_FBUNK
+#define   LMC_FADR_FBANK
+#define   LMC_FADR_FROW
+#define   LMC_FADR_FCOL
+#define LMC_COMP_CTL           0x0000000000000028
+#define LMC_WODT_CTL           0x0000000000000030
+#define LMC_ECC_SYND           0x0000000000000038
+#define LMC_IFB_CNT_LO         0x0000000000000048
+#define LMC_IFB_CNT_HI         0x0000000000000050
+#define LMC_OPS_CNT_LO         0x0000000000000058
+#define LMC_OPS_CNT_HI         0x0000000000000060
+#define LMC_DCLK_CNT_LO                0x0000000000000068
+#define LMC_DCLK_CNT_HI                0x0000000000000070
+#define LMC_DELAY_CFG          0x0000000000000088
+#define LMC_CTL1               0x0000000000000090
+#define LMC_DUAL_MEM_CONFIG    0x0000000000000098
+#define LMC_RODT_COMP_CTL      0x00000000000000A0
+#define LMC_PLL_CTL            0x00000000000000A8
+#define LMC_PLL_STATUS         0x00000000000000B0
+
+union lmc_mem_cfg0 {
+       uint64_t u64;
+       struct {
+               uint64_t reserved_32_63:32;
+               uint64_t reset:1;
+               uint64_t silo_qc:1;
+               uint64_t bunk_ena:1;
+               uint64_t ded_err:4;
+               uint64_t sec_err:4;
+               uint64_t intr_ded_ena:1;
+               uint64_t intr_sec_ena:1;
+               uint64_t reserved_15_18:4;
+               uint64_t ref_int:5;
+               uint64_t pbank_lsb:4;
+               uint64_t row_lsb:3;
+               uint64_t ecc_ena:1;
+               uint64_t init_start:1;
+       };
+};
+
+union lmc_fadr {
+       uint64_t u64;
+       struct {
+               uint64_t reserved_32_63:32;
+               uint64_t fdimm:2;
+               uint64_t fbunk:1;
+               uint64_t fbank:3;
+               uint64_t frow:14;
+               uint64_t fcol:12;
+       };
+};
+
+union lmc_ecc_synd {
+       uint64_t u64;
+       struct {
+               uint64_t reserved_32_63:32;
+               uint64_t mrdsyn3:8;
+               uint64_t mrdsyn2:8;
+               uint64_t mrdsyn1:8;
+               uint64_t mrdsyn0:8;
+       };
+};
diff --git a/drivers/edac/octeon_edac-pc.c b/drivers/edac/octeon_edac-pc.c
new file mode 100644 (file)
index 0000000..9d13061
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2009 Wind River Systems,
+ *   written by Ralf Baechle <ralf@linux-mips.org>
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/edac.h>
+
+#include "edac_core.h"
+#include "edac_module.h"
+
+#include <asm/octeon/cvmx.h>
+#include <asm/mipsregs.h>
+
+#define EDAC_MOD_STR "octeon"
+
+extern int register_co_cache_error_notifier(struct notifier_block *nb);
+extern int unregister_co_cache_error_notifier(struct notifier_block *nb);
+
+extern unsigned long long cache_err_dcache[NR_CPUS];
+
+static struct edac_device_ctl_info *ed_cavium;
+
+/*
+ * EDAC CPU cache error callback
+ *
+ */
+
+static int  co_cache_error_event(struct notifier_block *this,
+       unsigned long event, void *ptr)
+{
+       unsigned int core = cvmx_get_core_num();
+       unsigned int cpu = smp_processor_id();
+       uint64_t icache_err = read_octeon_c0_icacheerr();
+       struct edac_device_ctl_info *ed = ed_cavium;
+
+       edac_device_printk(ed, KERN_ERR,
+                          "Cache error exception on core %d / processor %d:\n",
+                          core, cpu);
+       edac_device_printk(ed, KERN_ERR,
+                          "cp0_errorepc == %lx\n", read_c0_errorepc());
+       if (icache_err & 1) {
+               edac_device_printk(ed, KERN_ERR, "CacheErr (Icache) == %llx\n",
+                                  (unsigned long long)icache_err);
+               write_octeon_c0_icacheerr(0);
+               edac_device_handle_ce(ed, 0, 0, ed->ctl_name);
+       }
+       if (cache_err_dcache[core] & 1) {
+               edac_device_printk(ed, KERN_ERR, "CacheErr (Dcache) == %llx\n",
+                                  (unsigned long long)cache_err_dcache[core]);
+               cache_err_dcache[core] = 0;
+               edac_device_handle_ue(ed, 0, 0, ed->ctl_name);
+       }
+
+       return NOTIFY_DONE;
+}
+
+static struct notifier_block co_cache_error_notifier = {
+       .notifier_call = co_cache_error_event,
+};
+
+static int __devinit co_cache_error_probe(struct platform_device *pdev)
+{
+       struct edac_device_ctl_info *ed;
+       int res = 0;
+
+       ed = edac_device_alloc_ctl_info(0, "cpu", 1, NULL, 0, 0, NULL, 0,
+                                       edac_device_alloc_index());
+
+       ed->dev = &pdev->dev;
+       platform_set_drvdata(pdev, ed);
+       ed->dev_name = dev_name(&pdev->dev);
+
+       ed->mod_name = "octeon-cpu";
+       ed->ctl_name = "co_cpu_err";
+
+       if (edac_device_add_device(ed) > 0) {
+               pr_err("%s: edac_device_add_device() failed\n", __func__);
+               goto err;
+       }
+
+       register_co_cache_error_notifier(&co_cache_error_notifier);
+       ed_cavium = ed;
+
+       return 0;
+
+err:
+       edac_device_free_ctl_info(ed);
+
+       return res;
+}
+
+static int co_cache_error_remove(struct platform_device *pdev)
+{
+       struct edac_device_ctl_info *ed = platform_get_drvdata(pdev);
+
+       unregister_co_cache_error_notifier(&co_cache_error_notifier);
+       ed_cavium = NULL;
+       edac_device_del_device(&pdev->dev);
+       edac_device_free_ctl_info(ed);
+
+       return 0;
+}
+
+static struct platform_driver co_cache_error_driver = {
+       .probe = co_cache_error_probe,
+       .remove = co_cache_error_remove,
+       .driver = {
+                  .name = "co_pc_edac",
+       }
+};
+
+static int __init co_edac_init(void)
+{
+       int ret;
+
+       ret = platform_driver_register(&co_cache_error_driver);
+       if (ret)
+               pr_warning(EDAC_MOD_STR "CPU err failed to register\n");
+
+       return ret;
+}
+
+static void __exit co_edac_exit(void)
+{
+       platform_driver_unregister(&co_cache_error_driver);
+}
+
+module_init(co_edac_init);
+module_exit(co_edac_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>");
diff --git a/drivers/edac/octeon_edac-pci.c b/drivers/edac/octeon_edac-pci.c
new file mode 100644 (file)
index 0000000..e72b96e
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2009 Wind River Systems,
+ *   written by Ralf Baechle <ralf@linux-mips.org>
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/edac.h>
+
+#include <asm/octeon/cvmx.h>
+#include <asm/octeon/cvmx-npi-defs.h>
+#include <asm/octeon/cvmx-pci-defs.h>
+#include <asm/octeon/octeon.h>
+
+#include "edac_core.h"
+#include "edac_module.h"
+
+#define EDAC_MOD_STR "octeon"
+
+static void co_pci_poll(struct edac_pci_ctl_info *pci)
+{
+       union cvmx_pci_cfg01 cfg01;
+
+       cfg01.u32 = octeon_npi_read32(CVMX_NPI_PCI_CFG01);
+       if (cfg01.s.dpe) {              /* Detected parity error */
+               edac_pci_handle_pe(pci, pci->ctl_name);
+               cfg01.s.dpe = 1;                /* Reset  */
+               octeon_npi_write32(CVMX_NPI_PCI_CFG01, cfg01.u32);
+       }
+       if (cfg01.s.sse) {
+               edac_pci_handle_npe(pci, "Signaled System Error");
+               cfg01.s.sse = 1;                /* Reset */
+               octeon_npi_write32(CVMX_NPI_PCI_CFG01, cfg01.u32);
+       }
+       if (cfg01.s.rma) {
+               edac_pci_handle_npe(pci, "Received Master Abort");
+               cfg01.s.rma = 1;                /* Reset */
+               octeon_npi_write32(CVMX_NPI_PCI_CFG01, cfg01.u32);
+       }
+       if (cfg01.s.rta) {
+               edac_pci_handle_npe(pci, "Received Target Abort");
+               cfg01.s.rta = 1;                /* Reset */
+               octeon_npi_write32(CVMX_NPI_PCI_CFG01, cfg01.u32);
+       }
+       if (cfg01.s.sta) {
+               edac_pci_handle_npe(pci, "Signaled Target Abort");
+               cfg01.s.sta = 1;                /* Reset */
+               octeon_npi_write32(CVMX_NPI_PCI_CFG01, cfg01.u32);
+       }
+       if (cfg01.s.mdpe) {
+               edac_pci_handle_npe(pci, "Master Data Parity Error");
+               cfg01.s.mdpe = 1;               /* Reset */
+               octeon_npi_write32(CVMX_NPI_PCI_CFG01, cfg01.u32);
+       }
+       if (cfg01.s.mdpe) {
+               edac_pci_handle_npe(pci, "Master Data Parity Error");
+               cfg01.s.mdpe = 1;               /* Reset */
+               octeon_npi_write32(CVMX_NPI_PCI_CFG01, cfg01.u32);
+       }
+}
+
+static int __devinit co_pci_probe(struct platform_device *pdev)
+{
+       struct edac_pci_ctl_info *pci;
+       int res = 0;
+
+       pci = edac_pci_alloc_ctl_info(0, "octeon_pci_err");
+       if (!pci)
+               return -ENOMEM;
+
+       pci->dev = &pdev->dev;
+       platform_set_drvdata(pdev, pci);
+       pci->dev_name = dev_name(&pdev->dev);
+
+       pci->mod_name = "octeon-pci";
+       pci->ctl_name = "octeon_pci_err";
+       pci->edac_check = co_pci_poll;
+
+       if (edac_pci_add_device(pci, 0) > 0) {
+               pr_err("%s: edac_pci_add_device() failed\n", __func__);
+               goto err;
+       }
+
+       return 0;
+
+err:
+       edac_pci_free_ctl_info(pci);
+
+       return res;
+}
+
+static int co_pci_remove(struct platform_device *pdev)
+{
+       struct edac_pci_ctl_info *pci = platform_get_drvdata(pdev);
+
+       edac_pci_del_device(&pdev->dev);
+       edac_pci_free_ctl_info(pci);
+
+       return 0;
+}
+
+static struct platform_driver co_pci_driver = {
+       .probe = co_pci_probe,
+       .remove = co_pci_remove,
+       .driver = {
+                  .name = "co_pci_edac",
+       }
+};
+
+static int __init co_edac_init(void)
+{
+       int ret;
+
+       ret = platform_driver_register(&co_pci_driver);
+       if (ret)
+               pr_warning(EDAC_MOD_STR " PCI EDAC failed to register\n");
+
+       return ret;
+}
+
+static void __exit co_edac_exit(void)
+{
+       platform_driver_unregister(&co_pci_driver);
+}
+
+module_init(co_edac_init);
+module_exit(co_edac_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>");
index 725eb5aa8d8cb670d0e104d48557fb866947a20a..e87196f6d2d2db43f945e6317b3d14fe09e680f4 100644 (file)
@@ -14,6 +14,7 @@
  *
  */
 
+#include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/device.h>
 #include <linux/platform_device.h>
@@ -161,13 +162,12 @@ static int __devinit adc_jack_probe(struct platform_device *pdev)
        err = request_any_context_irq(data->irq, adc_jack_irq_thread,
                        pdata->irq_flags, pdata->name, data);
 
-       if (err) {
+       if (err < 0) {
                dev_err(&pdev->dev, "error: irq %d\n", data->irq);
-               err = -EINVAL;
                goto err_irq;
        }
 
-       goto out;
+       return 0;
 
 err_irq:
        extcon_dev_unregister(&data->edev);
@@ -196,3 +196,7 @@ static struct platform_driver adc_jack_driver = {
 };
 
 module_platform_driver(adc_jack_driver);
+
+MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
+MODULE_DESCRIPTION("ADC Jack extcon driver");
+MODULE_LICENSE("GPL v2");
index 946a3188b2b78a4014f84e93588e8423c41501c0..d398821097f35f181c7ad554360a127de13496d5 100644 (file)
@@ -41,7 +41,7 @@
  * every single port-type of the following cable names. Please choose cable
  * names that are actually used in your extcon device.
  */
-const char *extcon_cable_name[] = {
+const char extcon_cable_name[][CABLE_NAME_MAX + 1] = {
        [EXTCON_USB]            = "USB",
        [EXTCON_USB_HOST]       = "USB-Host",
        [EXTCON_TA]             = "TA",
@@ -62,8 +62,6 @@ const char *extcon_cable_name[] = {
        [EXTCON_VIDEO_IN]       = "Video-in",
        [EXTCON_VIDEO_OUT]      = "Video-out",
        [EXTCON_MECHANICAL]     = "Mechanical",
-
-       NULL,
 };
 
 static struct class *extcon_class;
@@ -91,17 +89,13 @@ static int check_mutually_exclusive(struct extcon_dev *edev, u32 new_state)
                return 0;
 
        for (i = 0; edev->mutually_exclusive[i]; i++) {
-               int count = 0, j;
+               int weight;
                u32 correspondants = new_state & edev->mutually_exclusive[i];
-               u32 exp = 1;
-
-               for (j = 0; j < 32; j++) {
-                       if (exp & correspondants)
-                               count++;
-                       if (count > 1)
-                               return i + 1;
-                       exp <<= 1;
-               }
+
+               /* calculate the total number of bits set */
+               weight = hweight32(correspondants);
+               if (weight > 1)
+                       return i + 1;
        }
 
        return 0;
@@ -362,7 +356,7 @@ int extcon_get_cable_state(struct extcon_dev *edev, const char *cable_name)
 EXPORT_SYMBOL_GPL(extcon_get_cable_state);
 
 /**
- * extcon_get_cable_state_() - Set the status of a specific cable.
+ * extcon_set_cable_state_() - Set the status of a specific cable.
  * @edev:      the extcon device that has the cable.
  * @index:     cable index that can be retrieved by extcon_find_cable_index().
  * @cable_state:       the new cable status. The default semantics is
@@ -382,7 +376,7 @@ int extcon_set_cable_state_(struct extcon_dev *edev,
 EXPORT_SYMBOL_GPL(extcon_set_cable_state_);
 
 /**
- * extcon_get_cable_state() - Set the status of a specific cable.
+ * extcon_set_cable_state() - Set the status of a specific cable.
  * @edev:      the extcon device that has the cable.
  * @cable_name:        cable name.
  * @cable_state:       the new cable status. The default semantics is
@@ -447,6 +441,8 @@ static int _call_per_cable(struct notifier_block *nb, unsigned long val,
  *                           extcon device.
  * @obj:       an empty extcon_specific_cable_nb object to be returned.
  * @extcon_name:       the name of extcon device.
+ *                     if NULL, extcon_register_interest will register
+ *                     every cable with the target cable_name given.
  * @cable_name:                the target cable name.
  * @nb:                the notifier block to get notified.
  *
@@ -466,22 +462,44 @@ int extcon_register_interest(struct extcon_specific_cable_nb *obj,
                             const char *extcon_name, const char *cable_name,
                             struct notifier_block *nb)
 {
-       if (!obj || !extcon_name || !cable_name || !nb)
+       if (!obj || !cable_name || !nb)
                return -EINVAL;
 
-       obj->edev = extcon_get_extcon_dev(extcon_name);
-       if (!obj->edev)
-               return -ENODEV;
+       if (extcon_name) {
+               obj->edev = extcon_get_extcon_dev(extcon_name);
+               if (!obj->edev)
+                       return -ENODEV;
 
-       obj->cable_index = extcon_find_cable_index(obj->edev, cable_name);
-       if (obj->cable_index < 0)
-               return -ENODEV;
+               obj->cable_index = extcon_find_cable_index(obj->edev, cable_name);
+               if (obj->cable_index < 0)
+                       return -ENODEV;
+
+               obj->user_nb = nb;
 
-       obj->user_nb = nb;
+               obj->internal_nb.notifier_call = _call_per_cable;
 
-       obj->internal_nb.notifier_call = _call_per_cable;
+               return raw_notifier_chain_register(&obj->edev->nh, &obj->internal_nb);
+       } else {
+               struct class_dev_iter iter;
+               struct extcon_dev *extd;
+               struct device *dev;
+
+               if (!extcon_class)
+                       return -ENODEV;
+               class_dev_iter_init(&iter, extcon_class, NULL, NULL);
+               while ((dev = class_dev_iter_next(&iter))) {
+                       extd = (struct extcon_dev *)dev_get_drvdata(dev);
+
+                       if (extcon_find_cable_index(extd, cable_name) < 0)
+                               continue;
+
+                       class_dev_iter_exit(&iter);
+                       return extcon_register_interest(obj, extd->name,
+                                               cable_name, nb);
+               }
 
-       return raw_notifier_chain_register(&obj->edev->nh, &obj->internal_nb);
+               return -ENODEV;
+       }
 }
 
 /**
@@ -551,43 +569,9 @@ static int create_extcon_class(void)
        return 0;
 }
 
-static void extcon_cleanup(struct extcon_dev *edev, bool skip)
-{
-       mutex_lock(&extcon_dev_list_lock);
-       list_del(&edev->entry);
-       mutex_unlock(&extcon_dev_list_lock);
-
-       if (!skip && get_device(edev->dev)) {
-               int index;
-
-               if (edev->mutually_exclusive && edev->max_supported) {
-                       for (index = 0; edev->mutually_exclusive[index];
-                            index++)
-                               kfree(edev->d_attrs_muex[index].attr.name);
-                       kfree(edev->d_attrs_muex);
-                       kfree(edev->attrs_muex);
-               }
-
-               for (index = 0; index < edev->max_supported; index++)
-                       kfree(edev->cables[index].attr_g.name);
-
-               if (edev->max_supported) {
-                       kfree(edev->extcon_dev_type.groups);
-                       kfree(edev->cables);
-               }
-
-               device_unregister(edev->dev);
-               put_device(edev->dev);
-       }
-
-       kfree(edev->dev);
-}
-
 static void extcon_dev_release(struct device *dev)
 {
-       struct extcon_dev *edev = (struct extcon_dev *) dev_get_drvdata(dev);
-
-       extcon_cleanup(edev, true);
+       kfree(dev);
 }
 
 static const char *muex_name = "mutually_exclusive";
@@ -813,7 +797,40 @@ EXPORT_SYMBOL_GPL(extcon_dev_register);
  */
 void extcon_dev_unregister(struct extcon_dev *edev)
 {
-       extcon_cleanup(edev, false);
+       int index;
+
+       mutex_lock(&extcon_dev_list_lock);
+       list_del(&edev->entry);
+       mutex_unlock(&extcon_dev_list_lock);
+
+       if (IS_ERR_OR_NULL(get_device(edev->dev))) {
+               dev_err(edev->dev, "Failed to unregister extcon_dev (%s)\n",
+                               dev_name(edev->dev));
+               return;
+       }
+
+       if (edev->mutually_exclusive && edev->max_supported) {
+               for (index = 0; edev->mutually_exclusive[index];
+                               index++)
+                       kfree(edev->d_attrs_muex[index].attr.name);
+               kfree(edev->d_attrs_muex);
+               kfree(edev->attrs_muex);
+       }
+
+       for (index = 0; index < edev->max_supported; index++)
+               kfree(edev->cables[index].attr_g.name);
+
+       if (edev->max_supported) {
+               kfree(edev->extcon_dev_type.groups);
+               kfree(edev->cables);
+       }
+
+#if defined(CONFIG_ANDROID)
+       if (switch_class)
+               class_compat_remove_link(switch_class, edev->dev, NULL);
+#endif
+       device_unregister(edev->dev);
+       put_device(edev->dev);
 }
 EXPORT_SYMBOL_GPL(extcon_dev_unregister);
 
@@ -825,6 +842,9 @@ module_init(extcon_class_init);
 
 static void __exit extcon_class_exit(void)
 {
+#if defined(CONFIG_ANDROID)
+       class_compat_unregister(switch_class);
+#endif
        class_destroy(extcon_class);
 }
 module_exit(extcon_class_exit);
index 3cc152e690b06087c8374bf35cb72106f9bfde32..71d3ab7b3d8d72c8c477250e25b8ec93ce7842e8 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
-#include <linux/extcon.h>
 #include <linux/workqueue.h>
 #include <linux/gpio.h>
 #include <linux/extcon.h>
index e21387e2da5c25d2c9fdd19dae94108f9e9455da..a17d0d91ada26865d580768b293f2bbd936e4d10 100644 (file)
@@ -239,25 +239,19 @@ const char *max77693_extcon_cable[] = {
 static int max77693_muic_set_debounce_time(struct max77693_muic_info *info,
                enum max77693_muic_adc_debounce_time time)
 {
-       int ret = 0;
-       u8 ctrl3;
+       int ret;
 
        switch (time) {
        case ADC_DEBOUNCE_TIME_5MS:
        case ADC_DEBOUNCE_TIME_10MS:
        case ADC_DEBOUNCE_TIME_25MS:
        case ADC_DEBOUNCE_TIME_38_62MS:
-               ret = max77693_read_reg(info->max77693->regmap_muic,
-                               MAX77693_MUIC_REG_CTRL3, &ctrl3);
-               ctrl3 &= ~CONTROL3_ADCDBSET_MASK;
-               ctrl3 |= (time << CONTROL3_ADCDBSET_SHIFT);
-
-               ret = max77693_write_reg(info->max77693->regmap_muic,
-                               MAX77693_MUIC_REG_CTRL3, ctrl3);
-               if (ret) {
+               ret = max77693_update_reg(info->max77693->regmap_muic,
+                                         MAX77693_MUIC_REG_CTRL3,
+                                         time << CONTROL3_ADCDBSET_SHIFT,
+                                         CONTROL3_ADCDBSET_MASK);
+               if (ret)
                        dev_err(info->dev, "failed to set ADC debounce time\n");
-                       ret = -EINVAL;
-               }
                break;
        default:
                dev_err(info->dev, "invalid ADC debounce time\n");
@@ -657,6 +651,8 @@ out:
 static int __devinit max77693_muic_probe(struct platform_device *pdev)
 {
        struct max77693_dev *max77693 = dev_get_drvdata(pdev->dev.parent);
+       struct max77693_platform_data *pdata = dev_get_platdata(max77693->dev);
+       struct max77693_muic_platform_data *muic_pdata = pdata->muic_data;
        struct max77693_muic_info *info;
        int ret, i;
        u8 id;
@@ -727,6 +723,31 @@ static int __devinit max77693_muic_probe(struct platform_device *pdev)
                goto err_extcon;
        }
 
+       /* Initialize MUIC register by using platform data */
+       for (i = 0 ; i < muic_pdata->num_init_data ; i++) {
+               enum max77693_irq_source irq_src = MAX77693_IRQ_GROUP_NR;
+
+               max77693_write_reg(info->max77693->regmap_muic,
+                               muic_pdata->init_data[i].addr,
+                               muic_pdata->init_data[i].data);
+
+               switch (muic_pdata->init_data[i].addr) {
+               case MAX77693_MUIC_REG_INTMASK1:
+                       irq_src = MUIC_INT1;
+                       break;
+               case MAX77693_MUIC_REG_INTMASK2:
+                       irq_src = MUIC_INT2;
+                       break;
+               case MAX77693_MUIC_REG_INTMASK3:
+                       irq_src = MUIC_INT3;
+                       break;
+               }
+
+               if (irq_src < MAX77693_IRQ_GROUP_NR)
+                       info->max77693->irq_masks_cur[irq_src]
+                               = muic_pdata->init_data[i].data;
+       }
+
        /* Check revision number of MUIC device*/
        ret = max77693_read_reg(info->max77693->regmap_muic,
                        MAX77693_MUIC_REG_ID, &id);
@@ -762,6 +783,7 @@ static int __devexit max77693_muic_remove(struct platform_device *pdev)
                free_irq(muic_irqs[i].virq, info);
        cancel_work_sync(&info->irq_work);
        extcon_dev_unregister(info->edev);
+       kfree(info->edev);
        kfree(info);
 
        return 0;
index ef9090a4271ddc00ee6d735c2c4b48051e5c09f3..77b66b0cc8f54b117280e951daf81b17d6d31c3c 100644 (file)
@@ -271,8 +271,6 @@ out:
 static int max8997_muic_handle_charger_type_detach(
                                struct max8997_muic_info *info)
 {
-       int ret = 0;
-
        switch (info->pre_charger_type) {
        case MAX8997_CHARGER_TYPE_USB:
                extcon_set_cable_state(info->edev, "USB", false);
@@ -290,11 +288,11 @@ static int max8997_muic_handle_charger_type_detach(
                extcon_set_cable_state(info->edev, "Fast-charger", false);
                break;
        default:
-               ret = -EINVAL;
+               return -EINVAL;
                break;
        }
 
-       return ret;
+       return 0;
 }
 
 static int max8997_muic_handle_charger_type(struct max8997_muic_info *info,
index c1cdc9236666f60ee6891206f5a1f90bba2c4a0f..90723e65b08172ac49e67d01065aa79ca7f7ee54 100644 (file)
@@ -237,7 +237,7 @@ static ssize_t memmap_attr_show(struct kobject *kobj,
  * firmware_map_add() or firmware_map_add_early() afterwards, the entries
  * are not added to sysfs.
  */
-static int __init memmap_init(void)
+static int __init firmware_memmap_init(void)
 {
        struct firmware_map_entry *entry;
 
@@ -246,5 +246,5 @@ static int __init memmap_init(void)
 
        return 0;
 }
-late_initcall(memmap_init);
+late_initcall(firmware_memmap_init);
 
index d055cee36942d5e7aea8535b5f8d77b4ab34fe09..9e3fb3438718ee2ce49fbd14904d6e9ed3012e3f 100644 (file)
@@ -86,11 +86,26 @@ config GPIO_DA9052
        help
          Say yes here to enable the GPIO driver for the DA9052 chip.
 
+config GPIO_DA9055
+       tristate "Dialog Semiconductor DA9055 GPIO"
+       depends on MFD_DA9055
+       help
+         Say yes here to enable the GPIO driver for the DA9055 chip.
+
+         The Dialog DA9055 PMIC chip has 3 GPIO pins that can be
+         be controller by this driver.
+
+         If driver is built as a module it will be called gpio-da9055.
+
 config GPIO_MAX730X
        tristate
 
 comment "Memory mapped GPIO drivers:"
 
+config GPIO_CLPS711X
+       def_bool y
+       depends on ARCH_CLPS711X
+
 config GPIO_GENERIC_PLATFORM
        tristate "Generic memory-mapped GPIO controller support (MMIO platform device)"
        select GPIO_GENERIC
index 9aeed67073261f94702d8a873542bfff78ab2261..1c1b63fcaeb3e25317e401ccd50ef09325bd0f90 100644 (file)
@@ -16,8 +16,10 @@ obj-$(CONFIG_GPIO_ADP5588)   += gpio-adp5588.o
 obj-$(CONFIG_GPIO_AMD8111)     += gpio-amd8111.o
 obj-$(CONFIG_GPIO_ARIZONA)     += gpio-arizona.o
 obj-$(CONFIG_GPIO_BT8XX)       += gpio-bt8xx.o
+obj-$(CONFIG_GPIO_CLPS711X)    += gpio-clps711x.o
 obj-$(CONFIG_GPIO_CS5535)      += gpio-cs5535.o
 obj-$(CONFIG_GPIO_DA9052)      += gpio-da9052.o
+obj-$(CONFIG_GPIO_DA9055)      += gpio-da9055.o
 obj-$(CONFIG_ARCH_DAVINCI)     += gpio-davinci.o
 obj-$(CONFIG_GPIO_EM)          += gpio-em.o
 obj-$(CONFIG_GPIO_EP93XX)      += gpio-ep93xx.o
index ed3e55161bdc5bacbd0409a8a728f161872671c9..f05e54258ffb0a7c1b62eb54be11f2f8ed9486d8 100644 (file)
@@ -153,7 +153,7 @@ static int __devinit gen_74x164_probe(struct spi_device *spi)
        }
 
        chip->gpio_chip.ngpio = GEN_74X164_NUMBER_GPIOS * chip->registers;
-       chip->buffer = devm_kzalloc(&spi->dev, chip->gpio_chip.ngpio, GFP_KERNEL);
+       chip->buffer = devm_kzalloc(&spi->dev, chip->registers, GFP_KERNEL);
        if (!chip->buffer) {
                ret = -ENOMEM;
                goto exit_destroy;
diff --git a/drivers/gpio/gpio-clps711x.c b/drivers/gpio/gpio-clps711x.c
new file mode 100644 (file)
index 0000000..0753b3a
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+ *  CLPS711X GPIO driver
+ *
+ *  Copyright (C) 2012 Alexander Shiyan <shc_work@mail.ru>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/platform_device.h>
+
+#include <mach/hardware.h>
+
+#define CLPS711X_GPIO_PORTS    5
+#define CLPS711X_GPIO_NAME     "gpio-clps711x"
+
+struct clps711x_gpio {
+       struct gpio_chip        chip[CLPS711X_GPIO_PORTS];
+       spinlock_t              lock;
+};
+
+static void __iomem *clps711x_ports[] = {
+       CLPS711X_VIRT_BASE + PADR,
+       CLPS711X_VIRT_BASE + PBDR,
+       CLPS711X_VIRT_BASE + PCDR,
+       CLPS711X_VIRT_BASE + PDDR,
+       CLPS711X_VIRT_BASE + PEDR,
+};
+
+static void __iomem *clps711x_pdirs[] = {
+       CLPS711X_VIRT_BASE + PADDR,
+       CLPS711X_VIRT_BASE + PBDDR,
+       CLPS711X_VIRT_BASE + PCDDR,
+       CLPS711X_VIRT_BASE + PDDDR,
+       CLPS711X_VIRT_BASE + PEDDR,
+};
+
+#define clps711x_port(x)       clps711x_ports[x->base / 8]
+#define clps711x_pdir(x)       clps711x_pdirs[x->base / 8]
+
+static int gpio_clps711x_get(struct gpio_chip *chip, unsigned offset)
+{
+       return !!(readb(clps711x_port(chip)) & (1 << offset));
+}
+
+static void gpio_clps711x_set(struct gpio_chip *chip, unsigned offset,
+                             int value)
+{
+       int tmp;
+       unsigned long flags;
+       struct clps711x_gpio *gpio = dev_get_drvdata(chip->dev);
+
+       spin_lock_irqsave(&gpio->lock, flags);
+       tmp = readb(clps711x_port(chip)) & ~(1 << offset);
+       if (value)
+               tmp |= 1 << offset;
+       writeb(tmp, clps711x_port(chip));
+       spin_unlock_irqrestore(&gpio->lock, flags);
+}
+
+static int gpio_clps711x_direction_in(struct gpio_chip *chip, unsigned offset)
+{
+       int tmp;
+       unsigned long flags;
+       struct clps711x_gpio *gpio = dev_get_drvdata(chip->dev);
+
+       spin_lock_irqsave(&gpio->lock, flags);
+       tmp = readb(clps711x_pdir(chip)) & ~(1 << offset);
+       writeb(tmp, clps711x_pdir(chip));
+       spin_unlock_irqrestore(&gpio->lock, flags);
+
+       return 0;
+}
+
+static int gpio_clps711x_direction_out(struct gpio_chip *chip, unsigned offset,
+                                      int value)
+{
+       int tmp;
+       unsigned long flags;
+       struct clps711x_gpio *gpio = dev_get_drvdata(chip->dev);
+
+       spin_lock_irqsave(&gpio->lock, flags);
+       tmp = readb(clps711x_pdir(chip)) | (1 << offset);
+       writeb(tmp, clps711x_pdir(chip));
+       tmp = readb(clps711x_port(chip)) & ~(1 << offset);
+       if (value)
+               tmp |= 1 << offset;
+       writeb(tmp, clps711x_port(chip));
+       spin_unlock_irqrestore(&gpio->lock, flags);
+
+       return 0;
+}
+
+struct clps711x_gpio_port {
+       char    *name;
+       int     nr;
+};
+
+static const struct clps711x_gpio_port clps711x_gpio_ports[] __initconst = {
+       { "PORTA", 8, },
+       { "PORTB", 8, },
+       { "PORTC", 8, },
+       { "PORTD", 8, },
+       { "PORTE", 3, },
+};
+
+static int __init gpio_clps711x_init(void)
+{
+       int i;
+       struct platform_device *pdev;
+       struct clps711x_gpio *gpio;
+
+       pdev = platform_device_alloc(CLPS711X_GPIO_NAME, 0);
+       if (!pdev) {
+               pr_err("Cannot create platform device: %s\n",
+                      CLPS711X_GPIO_NAME);
+               return -ENOMEM;
+       }
+
+       platform_device_add(pdev);
+
+       gpio = devm_kzalloc(&pdev->dev, sizeof(struct clps711x_gpio),
+                           GFP_KERNEL);
+       if (!gpio) {
+               dev_err(&pdev->dev, "GPIO allocating memory error\n");
+               platform_device_del(pdev);
+               platform_device_put(pdev);
+               return -ENOMEM;
+       }
+
+       platform_set_drvdata(pdev, gpio);
+
+       spin_lock_init(&gpio->lock);
+
+       for (i = 0; i < CLPS711X_GPIO_PORTS; i++) {
+               gpio->chip[i].owner             = THIS_MODULE;
+               gpio->chip[i].dev               = &pdev->dev;
+               gpio->chip[i].label             = clps711x_gpio_ports[i].name;
+               gpio->chip[i].base              = i * 8;
+               gpio->chip[i].ngpio             = clps711x_gpio_ports[i].nr;
+               gpio->chip[i].direction_input   = gpio_clps711x_direction_in;
+               gpio->chip[i].get               = gpio_clps711x_get;
+               gpio->chip[i].direction_output  = gpio_clps711x_direction_out;
+               gpio->chip[i].set               = gpio_clps711x_set;
+               WARN_ON(gpiochip_add(&gpio->chip[i]));
+       }
+
+       dev_info(&pdev->dev, "GPIO driver initialized\n");
+
+       return 0;
+}
+arch_initcall(gpio_clps711x_init);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Alexander Shiyan <shc_work@mail.ru>");
+MODULE_DESCRIPTION("CLPS711X GPIO driver");
diff --git a/drivers/gpio/gpio-da9055.c b/drivers/gpio/gpio-da9055.c
new file mode 100644 (file)
index 0000000..55d83c7
--- /dev/null
@@ -0,0 +1,204 @@
+/*
+ * GPIO Driver for Dialog DA9055 PMICs.
+ *
+ * Copyright(c) 2012 Dialog Semiconductor Ltd.
+ *
+ * Author: David Dajun Chen <dchen@diasemi.com>
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ */
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+
+#include <linux/mfd/da9055/core.h>
+#include <linux/mfd/da9055/reg.h>
+#include <linux/mfd/da9055/pdata.h>
+
+#define DA9055_VDD_IO                  0x0
+#define DA9055_PUSH_PULL               0x3
+#define DA9055_ACT_LOW                 0x0
+#define DA9055_GPI                     0x1
+#define DA9055_PORT_MASK               0x3
+#define DA9055_PORT_SHIFT(offset)      (4 * (offset % 2))
+
+#define DA9055_INPUT                   DA9055_GPI
+#define DA9055_OUTPUT                  DA9055_PUSH_PULL
+#define DA9055_IRQ_GPI0                        3
+
+struct da9055_gpio {
+       struct da9055 *da9055;
+       struct gpio_chip gp;
+};
+
+static inline struct da9055_gpio *to_da9055_gpio(struct gpio_chip *chip)
+{
+       return container_of(chip, struct da9055_gpio, gp);
+}
+
+static int da9055_gpio_get(struct gpio_chip *gc, unsigned offset)
+{
+       struct da9055_gpio *gpio = to_da9055_gpio(gc);
+       int gpio_direction = 0;
+       int ret;
+
+       /* Get GPIO direction */
+       ret = da9055_reg_read(gpio->da9055, (offset >> 1) + DA9055_REG_GPIO0_1);
+       if (ret < 0)
+               return ret;
+
+       gpio_direction = ret & (DA9055_PORT_MASK) << DA9055_PORT_SHIFT(offset);
+       gpio_direction >>= DA9055_PORT_SHIFT(offset);
+       switch (gpio_direction) {
+       case DA9055_INPUT:
+               ret = da9055_reg_read(gpio->da9055, DA9055_REG_STATUS_B);
+               if (ret < 0)
+                       return ret;
+               break;
+       case DA9055_OUTPUT:
+               ret = da9055_reg_read(gpio->da9055, DA9055_REG_GPIO_MODE0_2);
+               if (ret < 0)
+                       return ret;
+       }
+
+       return ret & (1 << offset);
+
+}
+
+static void da9055_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
+{
+       struct da9055_gpio *gpio = to_da9055_gpio(gc);
+
+       da9055_reg_update(gpio->da9055,
+                       DA9055_REG_GPIO_MODE0_2,
+                       1 << offset,
+                       value << offset);
+}
+
+static int da9055_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
+{
+       struct da9055_gpio *gpio = to_da9055_gpio(gc);
+       unsigned char reg_byte;
+
+       reg_byte = (DA9055_ACT_LOW | DA9055_GPI)
+                               << DA9055_PORT_SHIFT(offset);
+
+       return da9055_reg_update(gpio->da9055, (offset >> 1) +
+                               DA9055_REG_GPIO0_1,
+                               DA9055_PORT_MASK <<
+                               DA9055_PORT_SHIFT(offset),
+                               reg_byte);
+}
+
+static int da9055_gpio_direction_output(struct gpio_chip *gc,
+                                       unsigned offset, int value)
+{
+       struct da9055_gpio *gpio = to_da9055_gpio(gc);
+       unsigned char reg_byte;
+       int ret;
+
+       reg_byte = (DA9055_VDD_IO | DA9055_PUSH_PULL)
+                                       << DA9055_PORT_SHIFT(offset);
+
+       ret = da9055_reg_update(gpio->da9055, (offset >> 1) +
+                               DA9055_REG_GPIO0_1,
+                               DA9055_PORT_MASK <<
+                               DA9055_PORT_SHIFT(offset),
+                               reg_byte);
+       if (ret < 0)
+               return ret;
+
+       da9055_gpio_set(gc, offset, value);
+
+       return 0;
+}
+
+static int da9055_gpio_to_irq(struct gpio_chip *gc, u32 offset)
+{
+       struct da9055_gpio *gpio = to_da9055_gpio(gc);
+       struct da9055 *da9055 = gpio->da9055;
+
+       return regmap_irq_get_virq(da9055->irq_data,
+                                 DA9055_IRQ_GPI0 + offset);
+}
+
+static struct gpio_chip reference_gp __devinitdata = {
+       .label = "da9055-gpio",
+       .owner = THIS_MODULE,
+       .get = da9055_gpio_get,
+       .set = da9055_gpio_set,
+       .direction_input = da9055_gpio_direction_input,
+       .direction_output = da9055_gpio_direction_output,
+       .to_irq = da9055_gpio_to_irq,
+       .can_sleep = 1,
+       .ngpio = 3,
+       .base = -1,
+};
+
+static int __devinit da9055_gpio_probe(struct platform_device *pdev)
+{
+       struct da9055_gpio *gpio;
+       struct da9055_pdata *pdata;
+       int ret;
+
+       gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
+       if (gpio == NULL)
+               return -ENOMEM;
+
+       gpio->da9055 = dev_get_drvdata(pdev->dev.parent);
+       pdata = gpio->da9055->dev->platform_data;
+
+       gpio->gp = reference_gp;
+       if (pdata && pdata->gpio_base)
+               gpio->gp.base = pdata->gpio_base;
+
+       ret = gpiochip_add(&gpio->gp);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret);
+               goto err_mem;
+       }
+
+       platform_set_drvdata(pdev, gpio);
+
+       return 0;
+
+err_mem:
+       return ret;
+}
+
+static int __devexit da9055_gpio_remove(struct platform_device *pdev)
+{
+       struct da9055_gpio *gpio = platform_get_drvdata(pdev);
+
+       return gpiochip_remove(&gpio->gp);
+}
+
+static struct platform_driver da9055_gpio_driver = {
+       .probe = da9055_gpio_probe,
+       .remove = __devexit_p(da9055_gpio_remove),
+       .driver = {
+               .name   = "da9055-gpio",
+               .owner  = THIS_MODULE,
+       },
+};
+
+static int __init da9055_gpio_init(void)
+{
+       return platform_driver_register(&da9055_gpio_driver);
+}
+subsys_initcall(da9055_gpio_init);
+
+static void __exit da9055_gpio_exit(void)
+{
+       platform_driver_unregister(&da9055_gpio_driver);
+}
+module_exit(da9055_gpio_exit);
+
+MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
+MODULE_DESCRIPTION("DA9055 GPIO Device Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:da9055-gpio");
index 902af437eaf26e9dc1b5c2cf3f1e902b70d5e237..eb42ab18160df87df78bf66f88b31a5f1de08fb2 100644 (file)
@@ -244,6 +244,8 @@ static int mvebu_gpio_direction_output(struct gpio_chip *chip, unsigned pin,
        if (ret)
                return ret;
 
+       mvebu_gpio_set(chip, pin, value);
+
        spin_lock_irqsave(&mvchip->lock, flags);
        u = readl_relaxed(mvebu_gpioreg_io_conf(mvchip));
        u &= ~(1 << pin);
@@ -381,11 +383,13 @@ static int mvebu_gpio_irq_set_type(struct irq_data *d, unsigned int type)
                u = readl_relaxed(mvebu_gpioreg_in_pol(mvchip));
                u &= ~(1 << pin);
                writel_relaxed(u, mvebu_gpioreg_in_pol(mvchip));
+               break;
        case IRQ_TYPE_EDGE_FALLING:
        case IRQ_TYPE_LEVEL_LOW:
                u = readl_relaxed(mvebu_gpioreg_in_pol(mvchip));
                u |= 1 << pin;
                writel_relaxed(u, mvebu_gpioreg_in_pol(mvchip));
+               break;
        case IRQ_TYPE_EDGE_BOTH: {
                u32 v;
 
@@ -401,6 +405,7 @@ static int mvebu_gpio_irq_set_type(struct irq_data *d, unsigned int type)
                else
                        u &= ~(1 << pin);       /* rising */
                writel_relaxed(u, mvebu_gpioreg_in_pol(mvchip));
+               break;
        }
        }
        return 0;
index 94cbc842fbc3a1363de61b8b7d08f2e4b56daeaf..df0e5e0474726b567f7e22b93420c9178bb1e8f8 100644 (file)
@@ -187,6 +187,7 @@ static inline void _gpio_dbck_disable(struct gpio_bank *bank)
                 * to detect events and generate interrupts at least on OMAP3.
                 */
                __raw_writel(0, bank->base + bank->regs->debounce_en);
+               bank->dbck_enable_mask = 0;
 
                clk_disable(bank->dbck);
                bank->dbck_enabled = false;
@@ -1070,7 +1071,7 @@ static int __devinit omap_gpio_probe(struct platform_device *pdev)
        if (!pdata)
                return -EINVAL;
 
-       bank = devm_kzalloc(&pdev->dev, sizeof(struct gpio_bank), GFP_KERNEL);
+       bank = devm_kzalloc(dev, sizeof(struct gpio_bank), GFP_KERNEL);
        if (!bank) {
                dev_err(dev, "Memory alloc failed\n");
                return -ENOMEM;
index b4b5da4fd2cc896f219859bc9849831c2c0527c4..31d9c9e79ea924b474b52ceda3d69f34a0414162 100644 (file)
@@ -216,39 +216,34 @@ static void __init pl061_init_gc(struct pl061_gpio *chip, int irq_base)
                               IRQ_GC_INIT_NESTED_LOCK, IRQ_NOREQUEST, 0);
 }
 
-static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
+static int pl061_probe(struct amba_device *adev, const struct amba_id *id)
 {
-       struct pl061_platform_data *pdata;
+       struct device *dev = &adev->dev;
+       struct pl061_platform_data *pdata = dev->platform_data;
        struct pl061_gpio *chip;
        int ret, irq, i;
 
-       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+       chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
        if (chip == NULL)
                return -ENOMEM;
 
-       pdata = dev->dev.platform_data;
        if (pdata) {
                chip->gc.base = pdata->gpio_base;
                chip->irq_base = pdata->irq_base;
-       } else if (dev->dev.of_node) {
+       } else if (adev->dev.of_node) {
                chip->gc.base = -1;
                chip->irq_base = 0;
-       } else {
-               ret = -ENODEV;
-               goto free_mem;
-       }
+       } else
+               return -ENODEV;
 
-       if (!request_mem_region(dev->res.start,
-                               resource_size(&dev->res), "pl061")) {
-               ret = -EBUSY;
-               goto free_mem;
-       }
+       if (!devm_request_mem_region(dev, adev->res.start,
+                               resource_size(&adev->res), "pl061"))
+               return -EBUSY;
 
-       chip->base = ioremap(dev->res.start, resource_size(&dev->res));
-       if (chip->base == NULL) {
-               ret = -ENOMEM;
-               goto release_region;
-       }
+       chip->base = devm_ioremap(dev, adev->res.start,
+                               resource_size(&adev->res));
+       if (chip->base == NULL)
+               return -ENOMEM;
 
        spin_lock_init(&chip->lock);
 
@@ -258,13 +253,13 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
        chip->gc.set = pl061_set_value;
        chip->gc.to_irq = pl061_to_irq;
        chip->gc.ngpio = PL061_GPIO_NR;
-       chip->gc.label = dev_name(&dev->dev);
-       chip->gc.dev = &dev->dev;
+       chip->gc.label = dev_name(dev);
+       chip->gc.dev = dev;
        chip->gc.owner = THIS_MODULE;
 
        ret = gpiochip_add(&chip->gc);
        if (ret)
-               goto iounmap;
+               return ret;
 
        /*
         * irq_chip support
@@ -276,11 +271,10 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
        pl061_init_gc(chip, chip->irq_base);
 
        writeb(0, chip->base + GPIOIE); /* disable irqs */
-       irq = dev->irq[0];
-       if (irq < 0) {
-               ret = -ENODEV;
-               goto iounmap;
-       }
+       irq = adev->irq[0];
+       if (irq < 0)
+               return -ENODEV;
+
        irq_set_chained_handler(irq, pl061_irq_handler);
        irq_set_handler_data(irq, chip);
 
@@ -294,18 +288,9 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
                }
        }
 
-       amba_set_drvdata(dev, chip);
+       amba_set_drvdata(adev, chip);
 
        return 0;
-
-iounmap:
-       iounmap(chip->base);
-release_region:
-       release_mem_region(dev->res.start, resource_size(&dev->res));
-free_mem:
-       kfree(chip);
-
-       return ret;
 }
 
 #ifdef CONFIG_PM
index a006f0db15af78a536837e76fad021c12c4fb8b2..43c4595b5cf072e3ad6158ead128c849684c8c99 100644 (file)
 #include <plat/gpio-fns.h>
 #include <plat/pm.h>
 
-#ifndef DEBUG_GPIO
-#define gpio_dbg(x...) do { } while (0)
-#else
-#define gpio_dbg(x...) printk(KERN_DEBUG x)
-#endif
-
 int samsung_gpio_setpull_updown(struct samsung_gpio_chip *chip,
                                unsigned int off, samsung_gpio_pull_t pull)
 {
@@ -596,10 +590,13 @@ static int samsung_gpiolib_4bit_input(struct gpio_chip *chip,
        unsigned long con;
 
        con = __raw_readl(base + GPIOCON_OFF);
-       con &= ~(0xf << con_4bit_shift(offset));
+       if (ourchip->bitmap_gpio_int & BIT(offset))
+               con |= 0xf << con_4bit_shift(offset);
+       else
+               con &= ~(0xf << con_4bit_shift(offset));
        __raw_writel(con, base + GPIOCON_OFF);
 
-       gpio_dbg("%s: %p: CON now %08lx\n", __func__, base, con);
+       pr_debug("%s: %p: CON now %08lx\n", __func__, base, con);
 
        return 0;
 }
@@ -627,7 +624,7 @@ static int samsung_gpiolib_4bit_output(struct gpio_chip *chip,
        __raw_writel(con, base + GPIOCON_OFF);
        __raw_writel(dat, base + GPIODAT_OFF);
 
-       gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
+       pr_debug("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
 
        return 0;
 }
@@ -671,7 +668,7 @@ static int samsung_gpiolib_4bit2_input(struct gpio_chip *chip,
        con &= ~(0xf << con_4bit_shift(offset));
        __raw_writel(con, regcon);
 
-       gpio_dbg("%s: %p: CON %08lx\n", __func__, base, con);
+       pr_debug("%s: %p: CON %08lx\n", __func__, base, con);
 
        return 0;
 }
@@ -706,7 +703,7 @@ static int samsung_gpiolib_4bit2_output(struct gpio_chip *chip,
        __raw_writel(con, regcon);
        __raw_writel(dat, base + GPIODAT_OFF);
 
-       gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
+       pr_debug("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
 
        return 0;
 }
@@ -926,10 +923,10 @@ static void __init samsung_gpiolib_add(struct samsung_gpio_chip *chip)
 #ifdef CONFIG_PM
        if (chip->pm != NULL) {
                if (!chip->pm->save || !chip->pm->resume)
-                       printk(KERN_ERR "gpio: %s has missing PM functions\n",
+                       pr_err("gpio: %s has missing PM functions\n",
                               gc->label);
        } else
-               printk(KERN_ERR "gpio: %s has no PM function\n", gc->label);
+               pr_err("gpio: %s has no PM function\n", gc->label);
 #endif
 
        /* gpiochip_add() prints own failure message on error. */
@@ -1081,6 +1078,8 @@ static void __init samsung_gpiolib_add_4bit_chips(struct samsung_gpio_chip *chip
                if ((base != NULL) && (chip->base == NULL))
                        chip->base = base + ((i) * 0x20);
 
+               chip->bitmap_gpio_int = 0;
+
                samsung_gpiolib_add(chip);
        }
 }
index 031c6adf5b651542420ee819ad0810d537707222..1a3e2b9b4772f7e710c16dee60a48049a3ff5c6d 100644 (file)
@@ -116,7 +116,7 @@ static void timbgpio_irq_disable(struct irq_data *d)
        unsigned long flags;
 
        spin_lock_irqsave(&tgpio->lock, flags);
-       tgpio->last_ier &= ~(1 << offset);
+       tgpio->last_ier &= ~(1UL << offset);
        iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER);
        spin_unlock_irqrestore(&tgpio->lock, flags);
 }
@@ -128,7 +128,7 @@ static void timbgpio_irq_enable(struct irq_data *d)
        unsigned long flags;
 
        spin_lock_irqsave(&tgpio->lock, flags);
-       tgpio->last_ier |= 1 << offset;
+       tgpio->last_ier |= 1UL << offset;
        iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER);
        spin_unlock_irqrestore(&tgpio->lock, flags);
 }
index bcd8e4aa7c7d043300748d1a1bcea4a27d9fb5b6..9ed2a2b347faa00c31055cbe3544efe8336eaf0a 100644 (file)
@@ -96,6 +96,7 @@ static struct vt8500_gpio_data wm8505_data = {
                VT8500_BANK(0x5C, 0x84, 0xAC, 0xD4, 12),
                VT8500_BANK(0x60, 0x88, 0xB0, 0xD8, 16),
                VT8500_BANK(0x64, 0x8C, 0xB4, 0xDC, 22),
+               VT8500_BANK(0x500, 0x504, 0x508, 0x50C, 6),
        },
 };
 
@@ -115,6 +116,7 @@ static struct vt8500_gpio_data wm8650_data = {
                VT8500_BANK(0x58, 0x98, 0xD8, 0x18, 32),
                VT8500_BANK(0x5C, 0x9C, 0xDC, 0x1C, 32),
                VT8500_BANK(0x7C, 0xBC, 0xFC, 0x3C, 32),
+               VT8500_BANK(0x500, 0x504, 0x508, 0x50C, 6),
        },
 };
 
index 5d6c71edc73911c7765a7530e65352fda2478845..d5f9742d9ac177c35e952bb4cf1b4f6a8745196a 100644 (file)
@@ -702,8 +702,9 @@ int gpio_export(unsigned gpio, bool direction_may_change)
 {
        unsigned long           flags;
        struct gpio_desc        *desc;
-       int                     status = -EINVAL;
+       int                     status;
        const char              *ioname = NULL;
+       struct device           *dev;
 
        /* can't export until sysfs is available ... */
        if (!gpio_class.p) {
@@ -711,59 +712,65 @@ int gpio_export(unsigned gpio, bool direction_may_change)
                return -ENOENT;
        }
 
-       if (!gpio_is_valid(gpio))
-               goto done;
+       if (!gpio_is_valid(gpio)) {
+               pr_debug("%s: gpio %d is not valid\n", __func__, gpio);
+               return -EINVAL;
+       }
 
        mutex_lock(&sysfs_lock);
 
        spin_lock_irqsave(&gpio_lock, flags);
        desc = &gpio_desc[gpio];
-       if (test_bit(FLAG_REQUESTED, &desc->flags)
-                       && !test_bit(FLAG_EXPORT, &desc->flags)) {
-               status = 0;
-               if (!desc->chip->direction_input
-                               || !desc->chip->direction_output)
-                       direction_may_change = false;
+       if (!test_bit(FLAG_REQUESTED, &desc->flags) ||
+            test_bit(FLAG_EXPORT, &desc->flags)) {
+               spin_unlock_irqrestore(&gpio_lock, flags);
+               pr_debug("%s: gpio %d unavailable (requested=%d, exported=%d)\n",
+                               __func__, gpio,
+                               test_bit(FLAG_REQUESTED, &desc->flags),
+                               test_bit(FLAG_EXPORT, &desc->flags));
+               return -EPERM;
        }
+
+       if (!desc->chip->direction_input || !desc->chip->direction_output)
+               direction_may_change = false;
        spin_unlock_irqrestore(&gpio_lock, flags);
 
        if (desc->chip->names && desc->chip->names[gpio - desc->chip->base])
                ioname = desc->chip->names[gpio - desc->chip->base];
 
-       if (status == 0) {
-               struct device   *dev;
-
-               dev = device_create(&gpio_class, desc->chip->dev, MKDEV(0, 0),
-                               desc, ioname ? ioname : "gpio%u", gpio);
-               if (!IS_ERR(dev)) {
-                       status = sysfs_create_group(&dev->kobj,
-                                               &gpio_attr_group);
-
-                       if (!status && direction_may_change)
-                               status = device_create_file(dev,
-                                               &dev_attr_direction);
-
-                       if (!status && gpio_to_irq(gpio) >= 0
-                                       && (direction_may_change
-                                               || !test_bit(FLAG_IS_OUT,
-                                                       &desc->flags)))
-                               status = device_create_file(dev,
-                                               &dev_attr_edge);
-
-                       if (status != 0)
-                               device_unregister(dev);
-               } else
-                       status = PTR_ERR(dev);
-               if (status == 0)
-                       set_bit(FLAG_EXPORT, &desc->flags);
+       dev = device_create(&gpio_class, desc->chip->dev, MKDEV(0, 0),
+                           desc, ioname ? ioname : "gpio%u", gpio);
+       if (IS_ERR(dev)) {
+               status = PTR_ERR(dev);
+               goto fail_unlock;
        }
 
-       mutex_unlock(&sysfs_lock);
-
-done:
+       status = sysfs_create_group(&dev->kobj, &gpio_attr_group);
        if (status)
-               pr_debug("%s: gpio%d status %d\n", __func__, gpio, status);
+               goto fail_unregister_device;
+
+       if (direction_may_change) {
+               status = device_create_file(dev, &dev_attr_direction);
+               if (status)
+                       goto fail_unregister_device;
+       }
 
+       if (gpio_to_irq(gpio) >= 0 && (direction_may_change ||
+                                      !test_bit(FLAG_IS_OUT, &desc->flags))) {
+               status = device_create_file(dev, &dev_attr_edge);
+               if (status)
+                       goto fail_unregister_device;
+       }
+
+       set_bit(FLAG_EXPORT, &desc->flags);
+       mutex_unlock(&sysfs_lock);
+       return 0;
+
+fail_unregister_device:
+       device_unregister(dev);
+fail_unlock:
+       mutex_unlock(&sysfs_lock);
+       pr_debug("%s: gpio%d status %d\n", __func__, gpio, status);
        return status;
 }
 EXPORT_SYMBOL_GPL(gpio_export);
index 09e11a5d921a4487b273bcdc2c479e4a26f90301..fd9d0af4d5369bb7ebac13662a3d612188c87921 100644 (file)
@@ -206,7 +206,7 @@ static int drm_fbdev_cma_create(struct drm_fb_helper *helper,
        size_t size;
        int ret;
 
-       DRM_DEBUG_KMS("surface width(%d), height(%d) and bpp(%d\n",
+       DRM_DEBUG_KMS("surface width(%d), height(%d) and bpp(%d)\n",
                        sizes->surface_width, sizes->surface_height,
                        sizes->surface_bpp);
 
@@ -220,7 +220,7 @@ static int drm_fbdev_cma_create(struct drm_fb_helper *helper,
 
        size = mode_cmd.pitches[0] * mode_cmd.height;
        obj = drm_gem_cma_create(dev, size);
-       if (!obj)
+       if (IS_ERR(obj))
                return -ENOMEM;
 
        fbi = framebuffer_alloc(0, dev->dev);
index 441ebc1bdbef5455c6a8cc7aa34103926dd963fa..d4b20ceda3fbd8d183dc7e628683732590200f51 100644 (file)
@@ -205,8 +205,6 @@ static int drm_gem_one_name_info(int id, void *ptr, void *data)
        struct drm_gem_object *obj = ptr;
        struct seq_file *m = data;
 
-       seq_printf(m, "name %d size %zd\n", obj->name, obj->size);
-
        seq_printf(m, "%6d %8zd %7d %8d\n",
                   obj->name, obj->size,
                   atomic_read(&obj->handle_count),
index aaeb6f8d69ce3502c569dda32d2d600117fb54c5..b8a282ea87515546695bc2965bce2b9f3e4f2f2d 100644 (file)
@@ -64,7 +64,6 @@ int drm_get_platform_dev(struct platform_device *platdev,
        }
 
        if (drm_core_check_feature(dev, DRIVER_MODESET)) {
-               dev_set_drvdata(&platdev->dev, dev);
                ret = drm_get_minor(dev, &dev->control, DRM_MINOR_CONTROL);
                if (ret)
                        goto err_g1;
index aac4e5e1a5b9b3533f36f801be7c553c2e60c8a1..6770ee6084b478475c3dde3a9bec72fff1e11a53 100644 (file)
@@ -118,6 +118,13 @@ module_param_named(i915_enable_ppgtt, i915_enable_ppgtt, int, 0600);
 MODULE_PARM_DESC(i915_enable_ppgtt,
                "Enable PPGTT (default: true)");
 
+unsigned int i915_preliminary_hw_support __read_mostly = 0;
+module_param_named(preliminary_hw_support, i915_preliminary_hw_support, int, 0600);
+MODULE_PARM_DESC(preliminary_hw_support,
+               "Enable preliminary hardware support. "
+               "Enable Haswell and ValleyView Support. "
+               "(default: false)");
+
 static struct drm_driver driver;
 extern int intel_agp_enabled;
 
@@ -826,6 +833,12 @@ i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        struct intel_device_info *intel_info =
                (struct intel_device_info *) ent->driver_data;
 
+       if (intel_info->is_haswell || intel_info->is_valleyview)
+               if(!i915_preliminary_hw_support) {
+                       DRM_ERROR("Preliminary hardware support disabled\n");
+                       return -ENODEV;
+               }
+
        /* Only bind to function 0 of the device. Early generations
         * used function 1 as a placeholder for multi-head. This causes
         * us confusion instead, especially on the systems where both
index b84f7861e4388cb3ccd8baa86ec3d994e4e52ceb..f511fa2f41687718494f2f1d9e2afb0c24f1fb70 100644 (file)
@@ -1217,6 +1217,7 @@ extern int i915_enable_rc6 __read_mostly;
 extern int i915_enable_fbc __read_mostly;
 extern bool i915_enable_hangcheck __read_mostly;
 extern int i915_enable_ppgtt __read_mostly;
+extern unsigned int i915_preliminary_hw_support __read_mostly;
 
 extern int i915_suspend(struct drm_device *dev, pm_message_t state);
 extern int i915_resume(struct drm_device *dev);
index d33d02d13c9678a7dd64b1fb4c9e9c5f9682d223..107f09befe929540e9ad801ff2bbdfe97a6b651d 100644 (file)
@@ -1407,8 +1407,10 @@ out:
                return VM_FAULT_NOPAGE;
        case -ENOMEM:
                return VM_FAULT_OOM;
+       case -ENOSPC:
+               return VM_FAULT_SIGBUS;
        default:
-               WARN_ON_ONCE(ret);
+               WARN_ONCE(ret, "unhandled error in i915_gem_fault: %i\n", ret);
                return VM_FAULT_SIGBUS;
        }
 }
@@ -1822,10 +1824,11 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)
                sg_set_page(sg, page, PAGE_SIZE, 0);
        }
 
+       obj->pages = st;
+
        if (i915_gem_object_needs_bit17_swizzle(obj))
                i915_gem_object_do_bit_17_swizzle(obj);
 
-       obj->pages = st;
        return 0;
 
 err_pages:
index 893f30164b7ec70a5cd2308db6db1e3e55222d6f..f78061af70459d6f4e39c25e79d8ff722ccb7aa2 100644 (file)
@@ -219,20 +219,7 @@ static void intel_crt_mode_set(struct drm_encoder *encoder,
                intel_encoder_to_crt(to_intel_encoder(encoder));
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        struct drm_i915_private *dev_priv = dev->dev_private;
-       int dpll_md_reg;
-       u32 adpa, dpll_md;
-
-       dpll_md_reg = DPLL_MD(intel_crtc->pipe);
-
-       /*
-        * Disable separate mode multiplier used when cloning SDVO to CRT
-        * XXX this needs to be adjusted when we really are cloning
-        */
-       if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) {
-               dpll_md = I915_READ(dpll_md_reg);
-               I915_WRITE(dpll_md_reg,
-                          dpll_md & ~DPLL_MD_UDI_MULTIPLIER_MASK);
-       }
+       u32 adpa;
 
        adpa = ADPA_HOTPLUG_BITS;
        if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
index 682bd3729baf62369fc66d23434f058a643ffc78..461a637f1ef7d96a21ced8cd31ffd1536a7257a2 100644 (file)
@@ -7892,6 +7892,34 @@ struct intel_quirk {
        void (*hook)(struct drm_device *dev);
 };
 
+/* For systems that don't have a meaningful PCI subdevice/subvendor ID */
+struct intel_dmi_quirk {
+       void (*hook)(struct drm_device *dev);
+       const struct dmi_system_id (*dmi_id_list)[];
+};
+
+static int intel_dmi_reverse_brightness(const struct dmi_system_id *id)
+{
+       DRM_INFO("Backlight polarity reversed on %s\n", id->ident);
+       return 1;
+}
+
+static const struct intel_dmi_quirk intel_dmi_quirks[] = {
+       {
+               .dmi_id_list = &(const struct dmi_system_id[]) {
+                       {
+                               .callback = intel_dmi_reverse_brightness,
+                               .ident = "NCR Corporation",
+                               .matches = {DMI_MATCH(DMI_SYS_VENDOR, "NCR Corporation"),
+                                           DMI_MATCH(DMI_PRODUCT_NAME, ""),
+                               },
+                       },
+                       { }  /* terminating entry */
+               },
+               .hook = quirk_invert_brightness,
+       },
+};
+
 static struct intel_quirk intel_quirks[] = {
        /* HP Mini needs pipe A force quirk (LP: #322104) */
        { 0x27ae, 0x103c, 0x361a, quirk_pipea_force },
@@ -7931,6 +7959,10 @@ static void intel_init_quirks(struct drm_device *dev)
                     q->subsystem_device == PCI_ANY_ID))
                        q->hook(dev);
        }
+       for (i = 0; i < ARRAY_SIZE(intel_dmi_quirks); i++) {
+               if (dmi_check_system(*intel_dmi_quirks[i].dmi_id_list) != 0)
+                       intel_dmi_quirks[i].hook(dev);
+       }
 }
 
 /* Disable the VGA plane that we never use */
index 1b727a5c9ee5680364343be93e15203df42e2369..368ed8ef1600233b6df90f32a591b46ea8fbdf88 100644 (file)
@@ -1797,7 +1797,8 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
                        if ((intel_dp->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0)
                                break;
                if (i == intel_dp->lane_count && voltage_tries == 5) {
-                       if (++loop_tries == 5) {
+                       ++loop_tries;
+                       if (loop_tries == 5) {
                                DRM_DEBUG_KMS("too many full retries, give up\n");
                                break;
                        }
@@ -1807,11 +1808,15 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
                }
 
                /* Check to see if we've tried the same voltage 5 times */
-               if ((intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) != voltage) {
-                       voltage = intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK;
-                       voltage_tries = 0;
-               } else
+               if ((intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) {
                        ++voltage_tries;
+                       if (voltage_tries == 5) {
+                               DRM_DEBUG_KMS("too many voltage retries, give up\n");
+                               break;
+                       }
+               } else
+                       voltage_tries = 0;
+               voltage = intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK;
 
                /* Compute new intel_dp->train_set as requested by target */
                intel_get_adjust_train(intel_dp, link_status);
index e3166df55daad03f4f5c144a5c0558aaa017fec6..edba93b3474b9540a5608f6acbd9eb75f7e53a33 100644 (file)
@@ -777,6 +777,14 @@ static const struct dmi_system_id intel_no_lvds[] = {
                        DMI_MATCH(DMI_BOARD_NAME, "D525TUD"),
                },
        },
+       {
+               .callback = intel_no_lvds_dmi_callback,
+               .ident = "Supermicro X7SPA-H",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Supermicro"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "X7SPA-H"),
+               },
+       },
 
        { }     /* terminating entry */
 };
index 0007a4d9bf6e5248effc509fd25f442b6d4e3164..c01d97db0061d19be180f6dbcf9cecffd505aeb0 100644 (file)
@@ -139,6 +139,11 @@ struct intel_sdvo {
 
        /* DDC bus used by this SDVO encoder */
        uint8_t ddc_bus;
+
+       /*
+        * the sdvo flag gets lost in round trip: dtd->adjusted_mode->dtd
+        */
+       uint8_t dtd_sdvo_flags;
 };
 
 struct intel_sdvo_connector {
@@ -984,6 +989,7 @@ intel_sdvo_get_preferred_input_mode(struct intel_sdvo *intel_sdvo,
                return false;
 
        intel_sdvo_get_mode_from_dtd(adjusted_mode, &input_dtd);
+       intel_sdvo->dtd_sdvo_flags = input_dtd.part2.sdvo_flags;
 
        return true;
 }
@@ -1092,6 +1098,8 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
         * adjusted_mode.
         */
        intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode);
+       if (intel_sdvo->is_tv || intel_sdvo->is_lvds)
+               input_dtd.part2.sdvo_flags = intel_sdvo->dtd_sdvo_flags;
        if (!intel_sdvo_set_input_timing(intel_sdvo, &input_dtd))
                DRM_INFO("Setting input timings on %s failed\n",
                         SDVO_NAME(intel_sdvo));
@@ -2277,10 +2285,8 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device)
                intel_sdvo_connector->output_flag = SDVO_OUTPUT_LVDS1;
        }
 
-       /* SDVO LVDS is cloneable because the SDVO encoder does the upscaling,
-        * as opposed to native LVDS, where we upscale with the panel-fitter
-        * (and hence only the native LVDS resolution could be cloned). */
-       intel_sdvo->base.cloneable = true;
+       /* SDVO LVDS is not cloneable because the input mode gets adjusted by the encoder */
+       intel_sdvo->base.cloneable = false;
 
        intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo);
        if (!intel_sdvo_create_enhance_property(intel_sdvo, intel_sdvo_connector))
index 1f34549aff18748758d4d72feed0eba5800734ab..70586fde69cf48018fd9786ccccacd4eef0900d4 100644 (file)
@@ -39,6 +39,11 @@ nouveau_gpuobj_destroy(struct nouveau_gpuobj *gpuobj)
                        nv_wo32(gpuobj, i, 0x00000000);
        }
 
+       if (gpuobj->node) {
+               nouveau_mm_free(&nv_gpuobj(gpuobj->parent)->heap,
+                               &gpuobj->node);
+       }
+
        if (gpuobj->heap.block_size)
                nouveau_mm_fini(&gpuobj->heap);
 
index bfddf87926dd8857a73df69cb26757836bd02f1f..4d6206448670154deaeed940e0eb44993024fea9 100644 (file)
@@ -236,7 +236,7 @@ nouveau_mm_fini(struct nouveau_mm *mm)
        int nodes = 0;
 
        list_for_each_entry(node, &mm->nodes, nl_entry) {
-               if (nodes++ == mm->heap_nodes)
+               if (WARN_ON(nodes++ == mm->heap_nodes))
                        return -EBUSY;
        }
 
index dcb5c2befc928a716425ace89149cec8a808c2e3..70ca7d5a1aa1aaa4e4302ab599ed5398d4f666eb 100644 (file)
@@ -72,7 +72,7 @@ nouveau_bios_shadow_of(struct nouveau_bios *bios)
        }
 
        data = of_get_property(dn, "NVDA,BMP", &size);
-       if (data) {
+       if (data && size) {
                bios->size = size;
                bios->data = kmalloc(bios->size, GFP_KERNEL);
                if (bios->data)
@@ -104,6 +104,9 @@ nouveau_bios_shadow_pramin(struct nouveau_bios *bios)
                goto out;
 
        bios->size = nv_rd08(bios, 0x700002) * 512;
+       if (!bios->size)
+               goto out;
+
        bios->data = kmalloc(bios->size, GFP_KERNEL);
        if (bios->data) {
                for (i = 0; i < bios->size; i++)
@@ -155,6 +158,9 @@ nouveau_bios_shadow_prom(struct nouveau_bios *bios)
 
        /* read entire bios image to system memory */
        bios->size = nv_rd08(bios, 0x300002) * 512;
+       if (!bios->size)
+               goto out;
+
        bios->data = kmalloc(bios->size, GFP_KERNEL);
        if (bios->data) {
                for (i = 0; i < bios->size; i++)
@@ -186,14 +192,22 @@ nouveau_bios_shadow_acpi(struct nouveau_bios *bios)
 {
        struct pci_dev *pdev = nv_device(bios)->pdev;
        int ret, cnt, i;
-       u8  data[3];
 
-       if (!nouveau_acpi_rom_supported(pdev))
+       if (!nouveau_acpi_rom_supported(pdev)) {
+               bios->data = NULL;
                return;
+       }
 
        bios->size = 0;
-       if (nouveau_acpi_get_bios_chunk(data, 0, 3) == 3)
-               bios->size = data[2] * 512;
+       bios->data = kmalloc(4096, GFP_KERNEL);
+       if (bios->data) {
+               if (nouveau_acpi_get_bios_chunk(bios->data, 0, 4096) == 4096)
+                       bios->size = bios->data[2] * 512;
+               kfree(bios->data);
+       }
+
+       if (!bios->size)
+               return;
 
        bios->data = kmalloc(bios->size, GFP_KERNEL);
        for (i = 0; bios->data && i < bios->size; i += cnt) {
@@ -229,12 +243,14 @@ nouveau_bios_shadow_pci(struct nouveau_bios *bios)
 static int
 nouveau_bios_score(struct nouveau_bios *bios, const bool writeable)
 {
-       if (!bios->data || bios->data[0] != 0x55 || bios->data[1] != 0xAA) {
+       if (bios->size < 3 || !bios->data || bios->data[0] != 0x55 ||
+                       bios->data[1] != 0xAA) {
                nv_info(bios, "... signature not found\n");
                return 0;
        }
 
-       if (nvbios_checksum(bios->data, bios->data[2] * 512)) {
+       if (nvbios_checksum(bios->data,
+                       min_t(u32, bios->data[2] * 512, bios->size))) {
                nv_info(bios, "... checksum invalid\n");
                /* if a ro image is somewhat bad, it's probably all rubbish */
                return writeable ? 2 : 1;
index 5e5f4cddae3cc7248ed527c07b94e8d0c15e97e4..f835501203e552abb29b68425cb5b0a9b37e6bec 100644 (file)
@@ -157,11 +157,10 @@ pll_map_reg(struct nouveau_bios *bios, u32 reg, u32 *type, u8 *ver, u8 *len)
        while (map->reg) {
                if (map->reg == reg && *ver >= 0x20) {
                        u16 addr = (data += hdr);
+                       *type = map->type;
                        while (cnt--) {
-                               if (nv_ro32(bios, data) == map->reg) {
-                                       *type = map->type;
+                               if (nv_ro32(bios, data) == map->reg)
                                        return data;
-                               }
                                data += *len;
                        }
                        return addr;
@@ -200,11 +199,10 @@ pll_map_type(struct nouveau_bios *bios, u8 type, u32 *reg, u8 *ver, u8 *len)
        while (map->reg) {
                if (map->type == type && *ver >= 0x20) {
                        u16 addr = (data += hdr);
+                       *reg = map->reg;
                        while (cnt--) {
-                               if (nv_ro32(bios, data) == map->reg) {
-                                       *reg = map->reg;
+                               if (nv_ro32(bios, data) == map->reg)
                                        return data;
-                               }
                                data += *len;
                        }
                        return addr;
index 42d7539e65250d239a9e7f8c65efd68855b76c90..27fb1af7a779b2a0add14ab0462cb060d6e4d8d7 100644 (file)
@@ -237,6 +237,7 @@ nv50_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
                        return ret;
 
                priv->base.ram.stolen = (u64)nv_rd32(priv, 0x100e10) << 12;
+               priv->base.ram.type = NV_MEM_TYPE_STOLEN;
                break;
        default:
                ret = nouveau_mm_init(&priv->base.vram, rsvd_head, size,
index 0203e1e12caaad34f4639ec3824a33d770a5d447..49050d991e75a5c3610dfd36982113ca85c0dae3 100644 (file)
@@ -92,7 +92,8 @@ nv41_vmmgr_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        struct nv04_vmmgr_priv *priv;
        int ret;
 
-       if (!nouveau_boolopt(device->cfgopt, "NvPCIE", true)) {
+       if (pci_find_capability(device->pdev, PCI_CAP_ID_AGP) ||
+           !nouveau_boolopt(device->cfgopt, "NvPCIE", true)) {
                return nouveau_object_ctor(parent, engine, &nv04_vmmgr_oclass,
                                           data, size, pobject);
        }
index 0ac18d05a146389b6d87e8c7898188fda5b5c5e3..aa8131436e3dced3d3d9ef894fec6d5ff21cee2d 100644 (file)
@@ -163,7 +163,8 @@ nv44_vmmgr_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        struct nv04_vmmgr_priv *priv;
        int ret;
 
-       if (!nouveau_boolopt(device->cfgopt, "NvPCIE", true)) {
+       if (pci_find_capability(device->pdev, PCI_CAP_ID_AGP) ||
+           !nouveau_boolopt(device->cfgopt, "NvPCIE", true)) {
                return nouveau_object_ctor(parent, engine, &nv04_vmmgr_oclass,
                                           data, size, pobject);
        }
index 8f98e5a8c488dba5c8e86d937aa26b5e65d78175..d2f8ffeed742c54ae5a3d85d2f806f41e66d3a9d 100644 (file)
@@ -530,9 +530,11 @@ nouveau_page_flip_reserve(struct nouveau_bo *old_bo,
        if (ret)
                goto fail;
 
-       ret = ttm_bo_reserve(&old_bo->bo, false, false, false, 0);
-       if (ret)
-               goto fail_unreserve;
+       if (likely(old_bo != new_bo)) {
+               ret = ttm_bo_reserve(&old_bo->bo, false, false, false, 0);
+               if (ret)
+                       goto fail_unreserve;
+       }
 
        return 0;
 
@@ -551,8 +553,10 @@ nouveau_page_flip_unreserve(struct nouveau_bo *old_bo,
        nouveau_bo_fence(new_bo, fence);
        ttm_bo_unreserve(&new_bo->bo);
 
-       nouveau_bo_fence(old_bo, fence);
-       ttm_bo_unreserve(&old_bo->bo);
+       if (likely(old_bo != new_bo)) {
+               nouveau_bo_fence(old_bo, fence);
+               ttm_bo_unreserve(&old_bo->bo);
+       }
 
        nouveau_bo_unpin(old_bo);
 }
index c71d493fd0c54fc184023428bdcbfb286d2d1109..1c350fc4e449715edd5ef997e6eb791722d0f604 100644 (file)
@@ -201,6 +201,8 @@ static int shmob_drm_load(struct drm_device *dev, unsigned long flags)
                goto done;
        }
 
+       platform_set_drvdata(pdev, sdev);
+
 done:
        if (ret)
                shmob_drm_unload(dev);
@@ -299,11 +301,9 @@ static struct drm_driver shmob_drm_driver = {
 #if CONFIG_PM_SLEEP
 static int shmob_drm_pm_suspend(struct device *dev)
 {
-       struct platform_device *pdev = to_platform_device(dev);
-       struct drm_device *ddev = platform_get_drvdata(pdev);
-       struct shmob_drm_device *sdev = ddev->dev_private;
+       struct shmob_drm_device *sdev = dev_get_drvdata(dev);
 
-       drm_kms_helper_poll_disable(ddev);
+       drm_kms_helper_poll_disable(sdev->ddev);
        shmob_drm_crtc_suspend(&sdev->crtc);
 
        return 0;
@@ -311,9 +311,7 @@ static int shmob_drm_pm_suspend(struct device *dev)
 
 static int shmob_drm_pm_resume(struct device *dev)
 {
-       struct platform_device *pdev = to_platform_device(dev);
-       struct drm_device *ddev = platform_get_drvdata(pdev);
-       struct shmob_drm_device *sdev = ddev->dev_private;
+       struct shmob_drm_device *sdev = dev_get_drvdata(dev);
 
        mutex_lock(&sdev->ddev->mode_config.mutex);
        shmob_drm_crtc_resume(&sdev->crtc);
index 402ab69f9f991c64d149841cc154d6ea86ae9a96..bf6e4b5a73b509a73d06873c213335158b5fff89 100644 (file)
@@ -580,6 +580,7 @@ retry:
        if (unlikely(ret != 0))
                return ret;
 
+retry_reserve:
        spin_lock(&glob->lru_lock);
 
        if (unlikely(list_empty(&bo->ddestroy))) {
@@ -587,14 +588,20 @@ retry:
                return 0;
        }
 
-       ret = ttm_bo_reserve_locked(bo, interruptible,
-                                   no_wait_reserve, false, 0);
+       ret = ttm_bo_reserve_locked(bo, false, true, false, 0);
 
-       if (unlikely(ret != 0)) {
+       if (unlikely(ret == -EBUSY)) {
                spin_unlock(&glob->lru_lock);
-               return ret;
+               if (likely(!no_wait_reserve))
+                       ret = ttm_bo_wait_unreserved(bo, interruptible);
+               if (unlikely(ret != 0))
+                       return ret;
+
+               goto retry_reserve;
        }
 
+       BUG_ON(ret != 0);
+
        /**
         * We can re-check for sync object without taking
         * the bo::lock since setting the sync object requires
@@ -811,17 +818,14 @@ retry:
                                          no_wait_reserve, no_wait_gpu);
                kref_put(&bo->list_kref, ttm_bo_release_list);
 
-               if (likely(ret == 0 || ret == -ERESTARTSYS))
-                       return ret;
-
-               goto retry;
+               return ret;
        }
 
-       ret = ttm_bo_reserve_locked(bo, false, no_wait_reserve, false, 0);
+       ret = ttm_bo_reserve_locked(bo, false, true, false, 0);
 
        if (unlikely(ret == -EBUSY)) {
                spin_unlock(&glob->lru_lock);
-               if (likely(!no_wait_gpu))
+               if (likely(!no_wait_reserve))
                        ret = ttm_bo_wait_unreserved(bo, interruptible);
 
                kref_put(&bo->list_kref, ttm_bo_release_list);
index cef68ca859d335e7a58853a7fd55dc898b9c825e..ffe848fd83a45cdc0247370bb65b98006439b713 100644 (file)
@@ -93,8 +93,8 @@ obj-$(CONFIG_HID_PRIMAX)      += hid-primax.o
 obj-$(CONFIG_HID_PS3REMOTE)    += hid-ps3remote.o
 obj-$(CONFIG_HID_ROCCAT)       += hid-roccat.o hid-roccat-common.o \
        hid-roccat-arvo.o hid-roccat-isku.o hid-roccat-kone.o \
-       hid-roccat-koneplus.o hid-roccat-kovaplus.o hid-roccat-pyra.o \
-       hid-roccat-savu.o
+       hid-roccat-koneplus.o hid-roccat-kovaplus.o hid-roccat-lua.o \
+       hid-roccat-pyra.o hid-roccat-savu.o
 obj-$(CONFIG_HID_SAITEK)       += hid-saitek.o
 obj-$(CONFIG_HID_SAMSUNG)      += hid-samsung.o
 obj-$(CONFIG_HID_SMARTJOYPLUS) += hid-sjoy.o
index bd3971bf31bf7bc4369911a648b02c8729a3004d..9904776a706593373bfd928e23d8e98e6e77e6e0 100644 (file)
@@ -1655,6 +1655,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ISKU) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPLUS) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KOVAPLUS) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_LUA) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRED) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRELESS) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_SAVU) },
index 269b50912a4ae9207d1d04f2e014b3c950f20324..52b27b12a4a7ae87896378df677609770183fe51 100644 (file)
 #define USB_DEVICE_ID_ROCCAT_KONE      0x2ced
 #define USB_DEVICE_ID_ROCCAT_KONEPLUS  0x2d51
 #define USB_DEVICE_ID_ROCCAT_KOVAPLUS  0x2d50
+#define USB_DEVICE_ID_ROCCAT_LUA       0x2c2e
 #define USB_DEVICE_ID_ROCCAT_PYRA_WIRED        0x2c24
 #define USB_DEVICE_ID_ROCCAT_PYRA_WIRELESS     0x2cf6
 #define USB_DEVICE_ID_ROCCAT_SAVU      0x2d5a
index f5602fec48655016ca0fabdad1b743f71c17ae52..c47540a5d4f32b4861241f91871ab4c4220795ff 100644 (file)
@@ -222,6 +222,14 @@ static ssize_t koneplus_sysfs_write_tcu(struct file *fp,
                        sizeof(struct koneplus_tcu), KONEPLUS_COMMAND_TCU);
 }
 
+static ssize_t koneplus_sysfs_read_tcu(struct file *fp,
+               struct kobject *kobj, struct bin_attribute *attr, char *buf,
+               loff_t off, size_t count)
+{
+       return koneplus_sysfs_read(fp, kobj, buf, off, count,
+                       sizeof(struct koneplus_tcu), KONEPLUS_COMMAND_TCU);
+}
+
 static ssize_t koneplus_sysfs_read_tcu_image(struct file *fp,
                struct kobject *kobj, struct bin_attribute *attr, char *buf,
                loff_t off, size_t count)
@@ -426,8 +434,9 @@ static struct bin_attribute koneplus_bin_attributes[] = {
                .write = koneplus_sysfs_write_sensor
        },
        {
-               .attr = { .name = "tcu", .mode = 0220 },
+               .attr = { .name = "tcu", .mode = 0660 },
                .size = sizeof(struct koneplus_tcu),
+               .read = koneplus_sysfs_read_tcu,
                .write = koneplus_sysfs_write_tcu
        },
        {
diff --git a/drivers/hid/hid-roccat-lua.c b/drivers/hid/hid-roccat-lua.c
new file mode 100644 (file)
index 0000000..5084fb4
--- /dev/null
@@ -0,0 +1,227 @@
+/*
+ * Roccat Lua driver for Linux
+ *
+ * Copyright (c) 2012 Stefan Achatz <erazor_de@users.sourceforge.net>
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+
+/*
+ * Roccat Lua is a gamer mouse which cpi, button and light settings can be
+ * configured.
+ */
+
+#include <linux/device.h>
+#include <linux/input.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/hid-roccat.h>
+#include "hid-ids.h"
+#include "hid-roccat-common.h"
+#include "hid-roccat-lua.h"
+
+static ssize_t lua_sysfs_read(struct file *fp, struct kobject *kobj,
+               char *buf, loff_t off, size_t count,
+               size_t real_size, uint command)
+{
+       struct device *dev = container_of(kobj, struct device, kobj);
+       struct lua_device *lua = hid_get_drvdata(dev_get_drvdata(dev));
+       struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
+       int retval;
+
+       if (off >= real_size)
+               return 0;
+
+       if (off != 0 || count != real_size)
+               return -EINVAL;
+
+       mutex_lock(&lua->lua_lock);
+       retval = roccat_common2_receive(usb_dev, command, buf, real_size);
+       mutex_unlock(&lua->lua_lock);
+
+       return retval ? retval : real_size;
+}
+
+static ssize_t lua_sysfs_write(struct file *fp, struct kobject *kobj,
+               void const *buf, loff_t off, size_t count,
+               size_t real_size, uint command)
+{
+       struct device *dev = container_of(kobj, struct device, kobj);
+       struct lua_device *lua = hid_get_drvdata(dev_get_drvdata(dev));
+       struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
+       int retval;
+
+       if (off != 0 || count != real_size)
+               return -EINVAL;
+
+       mutex_lock(&lua->lua_lock);
+       retval = roccat_common2_send(usb_dev, command, (void *)buf, real_size);
+       mutex_unlock(&lua->lua_lock);
+
+       return retval ? retval : real_size;
+}
+
+#define LUA_SYSFS_W(thingy, THINGY) \
+static ssize_t lua_sysfs_write_ ## thingy(struct file *fp, \
+               struct kobject *kobj, struct bin_attribute *attr, \
+               char *buf, loff_t off, size_t count) \
+{ \
+       return lua_sysfs_write(fp, kobj, buf, off, count, \
+                       LUA_SIZE_ ## THINGY, LUA_COMMAND_ ## THINGY); \
+}
+
+#define LUA_SYSFS_R(thingy, THINGY) \
+static ssize_t lua_sysfs_read_ ## thingy(struct file *fp, \
+               struct kobject *kobj, struct bin_attribute *attr, \
+               char *buf, loff_t off, size_t count) \
+{ \
+       return lua_sysfs_read(fp, kobj, buf, off, count, \
+                       LUA_SIZE_ ## THINGY, LUA_COMMAND_ ## THINGY); \
+}
+
+#define LUA_BIN_ATTRIBUTE_RW(thingy, THINGY) \
+LUA_SYSFS_W(thingy, THINGY) \
+LUA_SYSFS_R(thingy, THINGY) \
+static struct bin_attribute lua_ ## thingy ## _attr = { \
+       .attr = { .name = #thingy, .mode = 0660 }, \
+       .size = LUA_SIZE_ ## THINGY, \
+       .read = lua_sysfs_read_ ## thingy, \
+       .write = lua_sysfs_write_ ## thingy \
+};
+
+LUA_BIN_ATTRIBUTE_RW(control, CONTROL)
+
+static int lua_create_sysfs_attributes(struct usb_interface *intf)
+{
+       return sysfs_create_bin_file(&intf->dev.kobj, &lua_control_attr);
+}
+
+static void lua_remove_sysfs_attributes(struct usb_interface *intf)
+{
+       sysfs_remove_bin_file(&intf->dev.kobj, &lua_control_attr);
+}
+
+static int lua_init_lua_device_struct(struct usb_device *usb_dev,
+               struct lua_device *lua)
+{
+       mutex_init(&lua->lua_lock);
+
+       return 0;
+}
+
+static int lua_init_specials(struct hid_device *hdev)
+{
+       struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
+       struct usb_device *usb_dev = interface_to_usbdev(intf);
+       struct lua_device *lua;
+       int retval;
+
+       lua = kzalloc(sizeof(*lua), GFP_KERNEL);
+       if (!lua) {
+               hid_err(hdev, "can't alloc device descriptor\n");
+               return -ENOMEM;
+       }
+       hid_set_drvdata(hdev, lua);
+
+       retval = lua_init_lua_device_struct(usb_dev, lua);
+       if (retval) {
+               hid_err(hdev, "couldn't init struct lua_device\n");
+               goto exit;
+       }
+
+       retval = lua_create_sysfs_attributes(intf);
+       if (retval) {
+               hid_err(hdev, "cannot create sysfs files\n");
+               goto exit;
+       }
+
+       return 0;
+exit:
+       kfree(lua);
+       return retval;
+}
+
+static void lua_remove_specials(struct hid_device *hdev)
+{
+       struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
+       struct lua_device *lua;
+
+       lua_remove_sysfs_attributes(intf);
+
+       lua = hid_get_drvdata(hdev);
+       kfree(lua);
+}
+
+static int lua_probe(struct hid_device *hdev,
+               const struct hid_device_id *id)
+{
+       int retval;
+
+       retval = hid_parse(hdev);
+       if (retval) {
+               hid_err(hdev, "parse failed\n");
+               goto exit;
+       }
+
+       retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+       if (retval) {
+               hid_err(hdev, "hw start failed\n");
+               goto exit;
+       }
+
+       retval = lua_init_specials(hdev);
+       if (retval) {
+               hid_err(hdev, "couldn't install mouse\n");
+               goto exit_stop;
+       }
+
+       return 0;
+
+exit_stop:
+       hid_hw_stop(hdev);
+exit:
+       return retval;
+}
+
+static void lua_remove(struct hid_device *hdev)
+{
+       lua_remove_specials(hdev);
+       hid_hw_stop(hdev);
+}
+
+static const struct hid_device_id lua_devices[] = {
+       { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_LUA) },
+       { }
+};
+
+MODULE_DEVICE_TABLE(hid, lua_devices);
+
+static struct hid_driver lua_driver = {
+               .name = "lua",
+               .id_table = lua_devices,
+               .probe = lua_probe,
+               .remove = lua_remove
+};
+
+static int __init lua_init(void)
+{
+       return hid_register_driver(&lua_driver);
+}
+
+static void __exit lua_exit(void)
+{
+       hid_unregister_driver(&lua_driver);
+}
+
+module_init(lua_init);
+module_exit(lua_exit);
+
+MODULE_AUTHOR("Stefan Achatz");
+MODULE_DESCRIPTION("USB Roccat Lua driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/hid/hid-roccat-lua.h b/drivers/hid/hid-roccat-lua.h
new file mode 100644 (file)
index 0000000..547d77a
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef __HID_ROCCAT_LUA_H
+#define __HID_ROCCAT_LUA_H
+
+/*
+ * Copyright (c) 2012 Stefan Achatz <erazor_de@users.sourceforge.net>
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+
+#include <linux/types.h>
+
+enum {
+       LUA_SIZE_CONTROL = 8,
+};
+
+enum lua_commands {
+       LUA_COMMAND_CONTROL = 3,
+};
+
+struct lua_device {
+       struct mutex lua_lock;
+};
+
+#endif
index 406537420fffdc0b90c008dad53205bd19f2acfe..773a2f25a8f062e794a5ac6b3f4747fab61d0ffb 100644 (file)
 #define NUM_PAGES_SPANNED(addr, len) \
 ((PAGE_ALIGN(addr + len) >> PAGE_SHIFT) - (addr >> PAGE_SHIFT))
 
-/* Internal routines */
-static int create_gpadl_header(
-       void *kbuffer,  /* must be phys and virt contiguous */
-       u32 size,       /* page-size multiple */
-       struct vmbus_channel_msginfo **msginfo,
-       u32 *messagecount);
-static void vmbus_setevent(struct vmbus_channel *channel);
-
 /*
  * vmbus_setevent- Trigger an event notification on the specified
  * channel.
@@ -146,14 +138,14 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
 
        if (ret != 0) {
                err = ret;
-               goto errorout;
+               goto error0;
        }
 
        ret = hv_ringbuffer_init(
                &newchannel->inbound, in, recv_ringbuffer_size);
        if (ret != 0) {
                err = ret;
-               goto errorout;
+               goto error0;
        }
 
 
@@ -168,7 +160,7 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
 
        if (ret != 0) {
                err = ret;
-               goto errorout;
+               goto error0;
        }
 
        /* Create and init the channel open message */
@@ -177,7 +169,7 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
                           GFP_KERNEL);
        if (!open_info) {
                err = -ENOMEM;
-               goto errorout;
+               goto error0;
        }
 
        init_completion(&open_info->waitevent);
@@ -193,7 +185,7 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
 
        if (userdatalen > MAX_USER_DEFINED_BYTES) {
                err = -EINVAL;
-               goto errorout;
+               goto error0;
        }
 
        if (userdatalen)
@@ -208,19 +200,18 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
                               sizeof(struct vmbus_channel_open_channel));
 
        if (ret != 0)
-               goto cleanup;
+               goto error1;
 
        t = wait_for_completion_timeout(&open_info->waitevent, 5*HZ);
        if (t == 0) {
                err = -ETIMEDOUT;
-               goto errorout;
+               goto error1;
        }
 
 
        if (open_info->response.open_result.status)
                err = open_info->response.open_result.status;
 
-cleanup:
        spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
        list_del(&open_info->msglistentry);
        spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
@@ -228,9 +219,12 @@ cleanup:
        kfree(open_info);
        return err;
 
-errorout:
-       hv_ringbuffer_cleanup(&newchannel->outbound);
-       hv_ringbuffer_cleanup(&newchannel->inbound);
+error1:
+       spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
+       list_del(&open_info->msglistentry);
+       spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
+
+error0:
        free_pages((unsigned long)out,
                get_order(send_ringbuffer_size + recv_ringbuffer_size));
        kfree(open_info);
index 2b8b8d4558d247c808a0a8f7f6bfd51601aa31a2..2f84c5cff8d4f95a026a42034eb1fac960ec6e6a 100644 (file)
@@ -265,14 +265,9 @@ static void vmbus_onoffer(struct vmbus_channel_message_header *hdr)
 {
        struct vmbus_channel_offer_channel *offer;
        struct vmbus_channel *newchannel;
-       uuid_le *guidtype;
-       uuid_le *guidinstance;
 
        offer = (struct vmbus_channel_offer_channel *)hdr;
 
-       guidtype = &offer->offer.if_type;
-       guidinstance = &offer->offer.if_instance;
-
        /* Allocate the channel object and save this offer. */
        newchannel = alloc_channel();
        if (!newchannel) {
@@ -470,7 +465,6 @@ static void vmbus_onversion_response(
 {
        struct vmbus_channel_msginfo *msginfo;
        struct vmbus_channel_message_header *requestheader;
-       struct vmbus_channel_initiate_contact *initiate;
        struct vmbus_channel_version_response *version_response;
        unsigned long flags;
 
@@ -484,8 +478,6 @@ static void vmbus_onversion_response(
 
                if (requestheader->msgtype ==
                    CHANNELMSG_INITIATE_CONTACT) {
-                       initiate =
-                       (struct vmbus_channel_initiate_contact *)requestheader;
                        memcpy(&msginfo->response.version_response,
                              version_response,
                              sizeof(struct vmbus_channel_version_response));
index c4633de64465a2eccc5d0305238feee8a8c28375..4800d4c2a7b7fc8c7634039dfbd52ee5c4232ae5 100644 (file)
@@ -334,6 +334,16 @@ config SENSORS_DA9052_ADC
          This driver can also be built as module. If so, the module
          will be called da9052-hwmon.
 
+config SENSORS_DA9055
+       tristate "Dialog Semiconductor DA9055 ADC"
+       depends on MFD_DA9055
+       help
+         If you say yes here you get support for ADC on the Dialog
+         Semiconductor DA9055 PMIC.
+
+         This driver can also be built as a module.  If so, the module
+         will be called da9055-hwmon.
+
 config SENSORS_I5K_AMB
        tristate "FB-DIMM AMB temperature sensor on Intel 5000 series chipsets"
        depends on PCI
@@ -455,7 +465,7 @@ config SENSORS_HIH6130
 
 config SENSORS_CORETEMP
        tristate "Intel Core/Core2/Atom temperature sensor"
-       depends on X86 && PCI
+       depends on X86
        help
          If you say yes here you get support for the temperature
          sensor inside your CPU. Most of the family 6 CPUs
@@ -1106,11 +1116,12 @@ config SENSORS_ADS1015
          will be called ads1015.
 
 config SENSORS_ADS7828
-       tristate "Texas Instruments ADS7828"
+       tristate "Texas Instruments ADS7828 and compatibles"
        depends on I2C
        help
-         If you say yes here you get support for Texas Instruments ADS7828
-         12-bit 8-channel ADC device.
+         If you say yes here you get support for Texas Instruments ADS7828 and
+         ADS7830 8-channel A/D converters. ADS7828 resolution is 12-bit, while
+         it is 8-bit on ADS7830.
 
          This driver can also be built as a module.  If so, the module
          will be called ads7828.
index 8d5fcb5e8e9f479438cfb3e6927906e0abd214cf..a930f0997d25a7fe4c69ad5fa10bc1a9c42ca5cb 100644 (file)
@@ -44,6 +44,7 @@ obj-$(CONFIG_SENSORS_ASC7621) += asc7621.o
 obj-$(CONFIG_SENSORS_ATXP1)    += atxp1.o
 obj-$(CONFIG_SENSORS_CORETEMP) += coretemp.o
 obj-$(CONFIG_SENSORS_DA9052_ADC)+= da9052-hwmon.o
+obj-$(CONFIG_SENSORS_DA9055)+= da9055-hwmon.o
 obj-$(CONFIG_SENSORS_DME1737)  += dme1737.o
 obj-$(CONFIG_SENSORS_DS620)    += ds620.o
 obj-$(CONFIG_SENSORS_DS1621)   += ds1621.o
index 1f9e8af0f322a045ae09e4db7f877a4e3db4a8d8..409b5c16defb1c0169c3871695c3b7b7c3d08fc0 100644 (file)
@@ -1,12 +1,14 @@
 /*
- * ads7828.c - lm_sensors driver for ads7828 12-bit 8-channel ADC
+ * ads7828.c - driver for TI ADS7828 8-channel A/D converter and compatibles
  * (C) 2007 EADS Astrium
  *
  * This driver is based on the lm75 and other lm_sensors/hwmon drivers
  *
  * Written by Steve Hardy <shardy@redhat.com>
  *
- * Datasheet available at: http://focus.ti.com/lit/ds/symlink/ads7828.pdf
+ * ADS7830 support, by Guillaume Roguez <guillaume.roguez@savoirfairelinux.com>
+ *
+ * For further information, see the Documentation/hwmon/ads7828 file.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/jiffies.h>
-#include <linux/i2c.h>
+#include <linux/err.h>
 #include <linux/hwmon.h>
 #include <linux/hwmon-sysfs.h>
-#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/jiffies.h>
+#include <linux/module.h>
 #include <linux/mutex.h>
+#include <linux/platform_data/ads7828.h>
+#include <linux/slab.h>
 
 /* The ADS7828 registers */
-#define ADS7828_NCH 8 /* 8 channels of 12-bit A-D supported */
-#define ADS7828_CMD_SD_SE 0x80 /* Single ended inputs */
-#define ADS7828_CMD_SD_DIFF 0x00 /* Differential inputs */
-#define ADS7828_CMD_PD0 0x0 /* Power Down between A-D conversions */
-#define ADS7828_CMD_PD1 0x04 /* Internal ref OFF && A-D ON */
-#define ADS7828_CMD_PD2 0x08 /* Internal ref ON && A-D OFF */
-#define ADS7828_CMD_PD3 0x0C /* Internal ref ON && A-D ON */
-#define ADS7828_INT_VREF_MV 2500 /* Internal vref is 2.5V, 2500mV */
-
-/* Addresses to scan */
-static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b,
-       I2C_CLIENT_END };
-
-/* Module parameters */
-static bool se_input = 1; /* Default is SE, 0 == diff */
-static bool int_vref = 1; /* Default is internal ref ON */
-static int vref_mv = ADS7828_INT_VREF_MV; /* set if vref != 2.5V */
-module_param(se_input, bool, S_IRUGO);
-module_param(int_vref, bool, S_IRUGO);
-module_param(vref_mv, int, S_IRUGO);
-
-/* Global Variables */
-static u8 ads7828_cmd_byte; /* cmd byte without channel bits */
-static unsigned int ads7828_lsb_resol; /* resolution of the ADC sample lsb */
-
-/* Each client has this additional data */
+#define ADS7828_NCH            8       /* 8 channels supported */
+#define ADS7828_CMD_SD_SE      0x80    /* Single ended inputs */
+#define ADS7828_CMD_PD1                0x04    /* Internal vref OFF && A/D ON */
+#define ADS7828_CMD_PD3                0x0C    /* Internal vref ON && A/D ON */
+#define ADS7828_INT_VREF_MV    2500    /* Internal vref is 2.5V, 2500mV */
+#define ADS7828_EXT_VREF_MV_MIN        50      /* External vref min value 0.05V */
+#define ADS7828_EXT_VREF_MV_MAX        5250    /* External vref max value 5.25V */
+
+/* List of supported devices */
+enum ads7828_chips { ads7828, ads7830 };
+
+/* Client specific data */
 struct ads7828_data {
        struct device *hwmon_dev;
-       struct mutex update_lock; /* mutex protect updates */
-       char valid; /* !=0 if following fields are valid */
-       unsigned long last_updated; /* In jiffies */
-       u16 adc_input[ADS7828_NCH]; /* ADS7828_NCH 12-bit samples */
+       struct mutex update_lock;       /* Mutex protecting updates */
+       unsigned long last_updated;     /* Last updated time (in jiffies) */
+       u16 adc_input[ADS7828_NCH];     /* ADS7828_NCH samples */
+       bool valid;                     /* Validity flag */
+       bool diff_input;                /* Differential input */
+       bool ext_vref;                  /* External voltage reference */
+       unsigned int vref_mv;           /* voltage reference value */
+       u8 cmd_byte;                    /* Command byte without channel bits */
+       unsigned int lsb_resol;         /* Resolution of the ADC sample LSB */
+       s32 (*read_channel)(const struct i2c_client *client, u8 command);
 };
 
-/* Function declaration - necessary due to function dependencies */
-static int ads7828_detect(struct i2c_client *client,
-                         struct i2c_board_info *info);
-static int ads7828_probe(struct i2c_client *client,
-                        const struct i2c_device_id *id);
-
-static inline u8 channel_cmd_byte(int ch)
+/* Command byte C2,C1,C0 - see datasheet */
+static inline u8 ads7828_cmd_byte(u8 cmd, int ch)
 {
-       /* cmd byte C2,C1,C0 - see datasheet */
-       u8 cmd = (((ch>>1) | (ch&0x01)<<2)<<4);
-       cmd |= ads7828_cmd_byte;
-       return cmd;
+       return cmd | (((ch >> 1) | (ch & 0x01) << 2) << 4);
 }
 
 /* Update data for the device (all 8 channels) */
@@ -96,12 +83,11 @@ static struct ads7828_data *ads7828_update_device(struct device *dev)
                dev_dbg(&client->dev, "Starting ads7828 update\n");
 
                for (ch = 0; ch < ADS7828_NCH; ch++) {
-                       u8 cmd = channel_cmd_byte(ch);
-                       data->adc_input[ch] =
-                               i2c_smbus_read_word_swapped(client, cmd);
+                       u8 cmd = ads7828_cmd_byte(data->cmd_byte, ch);
+                       data->adc_input[ch] = data->read_channel(client, cmd);
                }
                data->last_updated = jiffies;
-               data->valid = 1;
+               data->valid = true;
        }
 
        mutex_unlock(&data->update_lock);
@@ -110,28 +96,25 @@ static struct ads7828_data *ads7828_update_device(struct device *dev)
 }
 
 /* sysfs callback function */
-static ssize_t show_in(struct device *dev, struct device_attribute *da,
-       char *buf)
+static ssize_t ads7828_show_in(struct device *dev, struct device_attribute *da,
+                              char *buf)
 {
        struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
        struct ads7828_data *data = ads7828_update_device(dev);
-       /* Print value (in mV as specified in sysfs-interface documentation) */
-       return sprintf(buf, "%d\n", (data->adc_input[attr->index] *
-               ads7828_lsb_resol)/1000);
-}
+       unsigned int value = DIV_ROUND_CLOSEST(data->adc_input[attr->index] *
+                                              data->lsb_resol, 1000);
 
-#define in_reg(offset)\
-static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in,\
-       NULL, offset)
+       return sprintf(buf, "%d\n", value);
+}
 
-in_reg(0);
-in_reg(1);
-in_reg(2);
-in_reg(3);
-in_reg(4);
-in_reg(5);
-in_reg(6);
-in_reg(7);
+static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, ads7828_show_in, NULL, 0);
+static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, ads7828_show_in, NULL, 1);
+static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, ads7828_show_in, NULL, 2);
+static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, ads7828_show_in, NULL, 3);
+static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, ads7828_show_in, NULL, 4);
+static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, ads7828_show_in, NULL, 5);
+static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, ads7828_show_in, NULL, 6);
+static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, ads7828_show_in, NULL, 7);
 
 static struct attribute *ads7828_attributes[] = {
        &sensor_dev_attr_in0_input.dev_attr.attr,
@@ -152,60 +135,9 @@ static const struct attribute_group ads7828_group = {
 static int ads7828_remove(struct i2c_client *client)
 {
        struct ads7828_data *data = i2c_get_clientdata(client);
+
        hwmon_device_unregister(data->hwmon_dev);
        sysfs_remove_group(&client->dev.kobj, &ads7828_group);
-       return 0;
-}
-
-static const struct i2c_device_id ads7828_id[] = {
-       { "ads7828", 0 },
-       { }
-};
-MODULE_DEVICE_TABLE(i2c, ads7828_id);
-
-/* This is the driver that will be inserted */
-static struct i2c_driver ads7828_driver = {
-       .class = I2C_CLASS_HWMON,
-       .driver = {
-               .name = "ads7828",
-       },
-       .probe = ads7828_probe,
-       .remove = ads7828_remove,
-       .id_table = ads7828_id,
-       .detect = ads7828_detect,
-       .address_list = normal_i2c,
-};
-
-/* Return 0 if detection is successful, -ENODEV otherwise */
-static int ads7828_detect(struct i2c_client *client,
-                         struct i2c_board_info *info)
-{
-       struct i2c_adapter *adapter = client->adapter;
-       int ch;
-
-       /* Check we have a valid client */
-       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_WORD_DATA))
-               return -ENODEV;
-
-       /*
-        * Now, we do the remaining detection. There is no identification
-        * dedicated register so attempt to sanity check using knowledge of
-        * the chip
-        * - Read from the 8 channel addresses
-        * - Check the top 4 bits of each result are not set (12 data bits)
-        */
-       for (ch = 0; ch < ADS7828_NCH; ch++) {
-               u16 in_data;
-               u8 cmd = channel_cmd_byte(ch);
-               in_data = i2c_smbus_read_word_swapped(client, cmd);
-               if (in_data & 0xF000) {
-                       pr_debug("%s : Doesn't look like an ads7828 device\n",
-                                __func__);
-                       return -ENODEV;
-               }
-       }
-
-       strlcpy(info->type, "ads7828", I2C_NAME_SIZE);
 
        return 0;
 }
@@ -213,6 +145,7 @@ static int ads7828_detect(struct i2c_client *client,
 static int ads7828_probe(struct i2c_client *client,
                         const struct i2c_device_id *id)
 {
+       struct ads7828_platform_data *pdata = client->dev.platform_data;
        struct ads7828_data *data;
        int err;
 
@@ -221,10 +154,37 @@ static int ads7828_probe(struct i2c_client *client,
        if (!data)
                return -ENOMEM;
 
+       if (pdata) {
+               data->diff_input = pdata->diff_input;
+               data->ext_vref = pdata->ext_vref;
+               if (data->ext_vref)
+                       data->vref_mv = pdata->vref_mv;
+       }
+
+       /* Bound Vref with min/max values if it was provided */
+       if (data->vref_mv)
+               data->vref_mv = SENSORS_LIMIT(data->vref_mv,
+                                             ADS7828_EXT_VREF_MV_MIN,
+                                             ADS7828_EXT_VREF_MV_MAX);
+       else
+               data->vref_mv = ADS7828_INT_VREF_MV;
+
+       /* ADS7828 uses 12-bit samples, while ADS7830 is 8-bit */
+       if (id->driver_data == ads7828) {
+               data->lsb_resol = DIV_ROUND_CLOSEST(data->vref_mv * 1000, 4096);
+               data->read_channel = i2c_smbus_read_word_swapped;
+       } else {
+               data->lsb_resol = DIV_ROUND_CLOSEST(data->vref_mv * 1000, 256);
+               data->read_channel = i2c_smbus_read_byte_data;
+       }
+
+       data->cmd_byte = data->ext_vref ? ADS7828_CMD_PD1 : ADS7828_CMD_PD3;
+       if (!data->diff_input)
+               data->cmd_byte |= ADS7828_CMD_SD_SE;
+
        i2c_set_clientdata(client, data);
        mutex_init(&data->update_lock);
 
-       /* Register sysfs hooks */
        err = sysfs_create_group(&client->dev.kobj, &ads7828_group);
        if (err)
                return err;
@@ -232,38 +192,35 @@ static int ads7828_probe(struct i2c_client *client,
        data->hwmon_dev = hwmon_device_register(&client->dev);
        if (IS_ERR(data->hwmon_dev)) {
                err = PTR_ERR(data->hwmon_dev);
-               goto exit_remove;
+               goto error;
        }
 
        return 0;
 
-exit_remove:
+error:
        sysfs_remove_group(&client->dev.kobj, &ads7828_group);
        return err;
 }
 
-static int __init sensors_ads7828_init(void)
-{
-       /* Initialize the command byte according to module parameters */
-       ads7828_cmd_byte = se_input ?
-               ADS7828_CMD_SD_SE : ADS7828_CMD_SD_DIFF;
-       ads7828_cmd_byte |= int_vref ?
-               ADS7828_CMD_PD3 : ADS7828_CMD_PD1;
+static const struct i2c_device_id ads7828_device_ids[] = {
+       { "ads7828", ads7828 },
+       { "ads7830", ads7830 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, ads7828_device_ids);
 
-       /* Calculate the LSB resolution */
-       ads7828_lsb_resol = (vref_mv*1000)/4096;
+static struct i2c_driver ads7828_driver = {
+       .driver = {
+               .name = "ads7828",
+       },
 
-       return i2c_add_driver(&ads7828_driver);
-}
+       .id_table = ads7828_device_ids,
+       .probe = ads7828_probe,
+       .remove = ads7828_remove,
+};
 
-static void __exit sensors_ads7828_exit(void)
-{
-       i2c_del_driver(&ads7828_driver);
-}
+module_i2c_driver(ads7828_driver);
 
-MODULE_AUTHOR("Steve Hardy <shardy@redhat.com>");
-MODULE_DESCRIPTION("ADS7828 driver");
 MODULE_LICENSE("GPL");
-
-module_init(sensors_ads7828_init);
-module_exit(sensors_ads7828_exit);
+MODULE_AUTHOR("Steve Hardy <shardy@redhat.com>");
+MODULE_DESCRIPTION("Driver for TI ADS7828 A/D converter and compatibles");
index a227be47149f473bfd6fc2d41a8de99f842056fd..520e5bf4f76d9f8cd1b16edf5610554fde103181 100644 (file)
@@ -32,7 +32,7 @@
  * ASB100-A supports pwm1, while plain ASB100 does not.  There is no known
  * way for the driver to tell which one is there.
  *
- * Chip        #vin    #fanin  #pwm    #temp   wchipid vendid  i2c     ISA
+ * Chip                #vin    #fanin  #pwm    #temp   wchipid vendid  i2c     ISA
  * asb100      7       3       1       4       0x31    0x0694  yes     no
  */
 
index 984a3f13923b615b7c6849cd59b396689680ed20..24426a785ad59552ebbc390b40672f209704e01d 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/list.h>
 #include <linux/platform_device.h>
 #include <linux/cpu.h>
-#include <linux/pci.h>
 #include <linux/smp.h>
 #include <linux/moduleparam.h>
 #include <asm/msr.h>
@@ -197,16 +196,33 @@ struct tjmax {
 };
 
 static const struct tjmax __cpuinitconst tjmax_table[] = {
-       { "CPU D410", 100000 },
-       { "CPU D425", 100000 },
-       { "CPU D510", 100000 },
-       { "CPU D525", 100000 },
-       { "CPU N450", 100000 },
-       { "CPU N455", 100000 },
-       { "CPU N470", 100000 },
-       { "CPU N475", 100000 },
-       { "CPU  230", 100000 },
-       { "CPU  330", 125000 },
+       { "CPU  230", 100000 },         /* Model 0x1c, stepping 2       */
+       { "CPU  330", 125000 },         /* Model 0x1c, stepping 2       */
+       { "CPU CE4110", 110000 },       /* Model 0x1c, stepping 10      */
+       { "CPU CE4150", 110000 },       /* Model 0x1c, stepping 10      */
+       { "CPU CE4170", 110000 },       /* Model 0x1c, stepping 10      */
+};
+
+struct tjmax_model {
+       u8 model;
+       u8 mask;
+       int tjmax;
+};
+
+#define ANY 0xff
+
+static const struct tjmax_model __cpuinitconst tjmax_model_table[] = {
+       { 0x1c, 10, 100000 },   /* D4xx, N4xx, D5xx, N5xx */
+       { 0x1c, ANY, 90000 },   /* Z5xx, N2xx, possibly others
+                                * Note: Also matches 230 and 330,
+                                * which are covered by tjmax_table
+                                */
+       { 0x26, ANY, 90000 },   /* Atom Tunnel Creek (Exx), Lincroft (Z6xx)
+                                * Note: TjMax for E6xxT is 110C, but CPU type
+                                * is undetectable by software
+                                */
+       { 0x27, ANY, 90000 },   /* Atom Medfield (Z2460) */
+       { 0x36, ANY, 100000 },  /* Atom Cedar Trail/Cedarview (N2xxx, D2xxx) */
 };
 
 static int __cpuinit adjust_tjmax(struct cpuinfo_x86 *c, u32 id,
@@ -219,7 +235,6 @@ static int __cpuinit adjust_tjmax(struct cpuinfo_x86 *c, u32 id,
        int usemsr_ee = 1;
        int err;
        u32 eax, edx;
-       struct pci_dev *host_bridge;
        int i;
 
        /* explicit tjmax table entries override heuristics */
@@ -228,32 +243,18 @@ static int __cpuinit adjust_tjmax(struct cpuinfo_x86 *c, u32 id,
                        return tjmax_table[i].tjmax;
        }
 
+       for (i = 0; i < ARRAY_SIZE(tjmax_model_table); i++) {
+               const struct tjmax_model *tm = &tjmax_model_table[i];
+               if (c->x86_model == tm->model &&
+                   (tm->mask == ANY || c->x86_mask == tm->mask))
+                       return tm->tjmax;
+       }
+
        /* Early chips have no MSR for TjMax */
 
        if (c->x86_model == 0xf && c->x86_mask < 4)
                usemsr_ee = 0;
 
-       /* Atom CPUs */
-
-       if (c->x86_model == 0x1c || c->x86_model == 0x26
-           || c->x86_model == 0x27) {
-               usemsr_ee = 0;
-
-               host_bridge = pci_get_bus_and_slot(0, PCI_DEVFN(0, 0));
-
-               if (host_bridge && host_bridge->vendor == PCI_VENDOR_ID_INTEL
-                   && (host_bridge->device == 0xa000   /* NM10 based nettop */
-                   || host_bridge->device == 0xa010))  /* NM10 based netbook */
-                       tjmax = 100000;
-               else
-                       tjmax = 90000;
-
-               pci_dev_put(host_bridge);
-       } else if (c->x86_model == 0x36) {
-               usemsr_ee = 0;
-               tjmax = 100000;
-       }
-
        if (c->x86_model > 0xe && usemsr_ee) {
                u8 platform_id;
 
index b8d01c5f57131f0489659c2bdf3e31346bc64f90..19704948801c4b93de48b89d7b24cf5a8493624f 100644 (file)
@@ -60,30 +60,17 @@ static inline int vbbat_reg_to_mV(int value)
        return DIV_ROUND_CLOSEST(value * 2500, 512);
 }
 
-static int da9052_enable_vddout_channel(struct da9052 *da9052)
+static inline int da9052_enable_vddout_channel(struct da9052 *da9052)
 {
-       int ret;
-
-       ret = da9052_reg_read(da9052, DA9052_ADC_CONT_REG);
-       if (ret < 0)
-               return ret;
-
-       ret |= DA9052_ADCCONT_AUTOVDDEN;
-
-       return da9052_reg_write(da9052, DA9052_ADC_CONT_REG, ret);
+       return da9052_reg_update(da9052, DA9052_ADC_CONT_REG,
+                                DA9052_ADCCONT_AUTOVDDEN,
+                                DA9052_ADCCONT_AUTOVDDEN);
 }
 
-static int da9052_disable_vddout_channel(struct da9052 *da9052)
+static inline int da9052_disable_vddout_channel(struct da9052 *da9052)
 {
-       int ret;
-
-       ret = da9052_reg_read(da9052, DA9052_ADC_CONT_REG);
-       if (ret < 0)
-               return ret;
-
-       ret &= ~DA9052_ADCCONT_AUTOVDDEN;
-
-       return da9052_reg_write(da9052, DA9052_ADC_CONT_REG, ret);
+       return da9052_reg_update(da9052, DA9052_ADC_CONT_REG,
+                                DA9052_ADCCONT_AUTOVDDEN, 0);
 }
 
 static ssize_t da9052_read_vddout(struct device *dev,
diff --git a/drivers/hwmon/da9055-hwmon.c b/drivers/hwmon/da9055-hwmon.c
new file mode 100644 (file)
index 0000000..0b41f2c
--- /dev/null
@@ -0,0 +1,336 @@
+/*
+ * HWMON Driver for Dialog DA9055
+ *
+ * Copyright(c) 2012 Dialog Semiconductor Ltd.
+ *
+ * Author: David Dajun Chen <dchen@diasemi.com>
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/completion.h>
+
+#include <linux/mfd/da9055/core.h>
+#include <linux/mfd/da9055/reg.h>
+
+#define DA9055_ADCIN_DIV       102
+#define DA9055_VSYS_DIV        85
+
+#define DA9055_ADC_VSYS        0
+#define DA9055_ADC_ADCIN1      1
+#define DA9055_ADC_ADCIN2      2
+#define DA9055_ADC_ADCIN3      3
+#define DA9055_ADC_TJUNC       4
+
+struct da9055_hwmon {
+       struct da9055   *da9055;
+       struct device   *class_device;
+       struct mutex    hwmon_lock;
+       struct mutex    irq_lock;
+       struct completion done;
+};
+
+static const char * const input_names[] = {
+       [DA9055_ADC_VSYS]       = "VSYS",
+       [DA9055_ADC_ADCIN1]     = "ADC IN1",
+       [DA9055_ADC_ADCIN2]     = "ADC IN2",
+       [DA9055_ADC_ADCIN3]     = "ADC IN3",
+       [DA9055_ADC_TJUNC]      = "CHIP TEMP",
+};
+
+static const u8 chan_mux[DA9055_ADC_TJUNC + 1] = {
+       [DA9055_ADC_VSYS]       = DA9055_ADC_MUX_VSYS,
+       [DA9055_ADC_ADCIN1]     = DA9055_ADC_MUX_ADCIN1,
+       [DA9055_ADC_ADCIN2]     = DA9055_ADC_MUX_ADCIN2,
+       [DA9055_ADC_ADCIN3]     = DA9055_ADC_MUX_ADCIN1,
+       [DA9055_ADC_TJUNC]      = DA9055_ADC_MUX_T_SENSE,
+};
+
+static int da9055_adc_manual_read(struct da9055_hwmon *hwmon,
+                                       unsigned char channel)
+{
+       int ret;
+       unsigned short calc_data;
+       unsigned short data;
+       unsigned char mux_sel;
+       struct da9055 *da9055 = hwmon->da9055;
+
+       if (channel > DA9055_ADC_TJUNC)
+               return -EINVAL;
+
+       mutex_lock(&hwmon->irq_lock);
+
+       /* Selects desired MUX for manual conversion */
+       mux_sel = chan_mux[channel] | DA9055_ADC_MAN_CONV;
+
+       ret = da9055_reg_write(da9055, DA9055_REG_ADC_MAN, mux_sel);
+       if (ret < 0)
+               goto err;
+
+       /* Wait for an interrupt */
+       if (!wait_for_completion_timeout(&hwmon->done,
+                                       msecs_to_jiffies(500))) {
+               dev_err(da9055->dev,
+                       "timeout waiting for ADC conversion interrupt\n");
+               ret = -ETIMEDOUT;
+               goto err;
+       }
+
+       ret = da9055_reg_read(da9055, DA9055_REG_ADC_RES_H);
+       if (ret < 0)
+               goto err;
+
+       calc_data = (unsigned short)ret;
+       data = calc_data << 2;
+
+       ret = da9055_reg_read(da9055, DA9055_REG_ADC_RES_L);
+       if (ret < 0)
+               goto err;
+
+       calc_data = (unsigned short)(ret & DA9055_ADC_LSB_MASK);
+       data |= calc_data;
+
+       ret = data;
+
+err:
+       mutex_unlock(&hwmon->irq_lock);
+       return ret;
+}
+
+static irqreturn_t da9055_auxadc_irq(int irq, void *irq_data)
+{
+       struct da9055_hwmon *hwmon = irq_data;
+
+       complete(&hwmon->done);
+
+       return IRQ_HANDLED;
+}
+
+/* Conversion function for VSYS and ADCINx */
+static inline int volt_reg_to_mV(int value, int channel)
+{
+       if (channel == DA9055_ADC_VSYS)
+               return DIV_ROUND_CLOSEST(value * 1000, DA9055_VSYS_DIV) + 2500;
+       else
+               return DIV_ROUND_CLOSEST(value * 1000, DA9055_ADCIN_DIV);
+}
+
+static int da9055_enable_auto_mode(struct da9055 *da9055, int channel)
+{
+
+       return da9055_reg_update(da9055, DA9055_REG_ADC_CONT, 1 << channel,
+                               1 << channel);
+
+}
+
+static int da9055_disable_auto_mode(struct da9055 *da9055, int channel)
+{
+
+       return da9055_reg_update(da9055, DA9055_REG_ADC_CONT, 1 << channel, 0);
+}
+
+static ssize_t da9055_read_auto_ch(struct device *dev,
+                               struct device_attribute *devattr, char *buf)
+{
+       struct da9055_hwmon *hwmon = dev_get_drvdata(dev);
+       int ret, adc;
+       int channel = to_sensor_dev_attr(devattr)->index;
+
+       mutex_lock(&hwmon->hwmon_lock);
+
+       ret = da9055_enable_auto_mode(hwmon->da9055, channel);
+       if (ret < 0)
+               goto hwmon_err;
+
+       usleep_range(10000, 10500);
+
+       adc = da9055_reg_read(hwmon->da9055, DA9055_REG_VSYS_RES + channel);
+       if (adc < 0) {
+               ret = adc;
+               goto hwmon_err_release;
+       }
+
+       ret = da9055_disable_auto_mode(hwmon->da9055, channel);
+       if (ret < 0)
+               goto hwmon_err;
+
+       mutex_unlock(&hwmon->hwmon_lock);
+
+       return sprintf(buf, "%d\n", volt_reg_to_mV(adc, channel));
+
+hwmon_err_release:
+       da9055_disable_auto_mode(hwmon->da9055, channel);
+hwmon_err:
+       mutex_unlock(&hwmon->hwmon_lock);
+       return ret;
+}
+
+static ssize_t da9055_read_tjunc(struct device *dev,
+                                struct device_attribute *devattr, char *buf)
+{
+       struct da9055_hwmon *hwmon = dev_get_drvdata(dev);
+       int tjunc;
+       int toffset;
+
+       tjunc = da9055_adc_manual_read(hwmon, DA9055_ADC_TJUNC);
+       if (tjunc < 0)
+               return tjunc;
+
+       toffset = da9055_reg_read(hwmon->da9055, DA9055_REG_T_OFFSET);
+       if (toffset < 0)
+               return toffset;
+
+       /*
+        * Degrees celsius = -0.4084 * (ADC_RES - T_OFFSET) + 307.6332
+        * T_OFFSET is a trim value used to improve accuracy of the result
+        */
+       return sprintf(buf, "%d\n", DIV_ROUND_CLOSEST(-4084 * (tjunc - toffset)
+                                                       + 3076332, 10000));
+}
+
+static ssize_t da9055_hwmon_show_name(struct device *dev,
+                                     struct device_attribute *devattr,
+                                     char *buf)
+{
+       return sprintf(buf, "da9055-hwmon\n");
+}
+
+static ssize_t show_label(struct device *dev,
+                         struct device_attribute *devattr, char *buf)
+{
+       return sprintf(buf, "%s\n",
+                      input_names[to_sensor_dev_attr(devattr)->index]);
+}
+
+static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, da9055_read_auto_ch, NULL,
+                         DA9055_ADC_VSYS);
+static SENSOR_DEVICE_ATTR(in0_label, S_IRUGO, show_label, NULL,
+                         DA9055_ADC_VSYS);
+static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, da9055_read_auto_ch, NULL,
+                         DA9055_ADC_ADCIN1);
+static SENSOR_DEVICE_ATTR(in1_label, S_IRUGO, show_label, NULL,
+                         DA9055_ADC_ADCIN1);
+static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, da9055_read_auto_ch, NULL,
+                         DA9055_ADC_ADCIN2);
+static SENSOR_DEVICE_ATTR(in2_label, S_IRUGO, show_label, NULL,
+                         DA9055_ADC_ADCIN2);
+static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, da9055_read_auto_ch, NULL,
+                         DA9055_ADC_ADCIN3);
+static SENSOR_DEVICE_ATTR(in3_label, S_IRUGO, show_label, NULL,
+                         DA9055_ADC_ADCIN3);
+
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, da9055_read_tjunc, NULL,
+                         DA9055_ADC_TJUNC);
+static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, show_label, NULL,
+                         DA9055_ADC_TJUNC);
+
+static DEVICE_ATTR(name, S_IRUGO, da9055_hwmon_show_name, NULL);
+
+static struct attribute *da9055_attr[] = {
+       &dev_attr_name.attr,
+       &sensor_dev_attr_in0_input.dev_attr.attr,
+       &sensor_dev_attr_in0_label.dev_attr.attr,
+       &sensor_dev_attr_in1_input.dev_attr.attr,
+       &sensor_dev_attr_in1_label.dev_attr.attr,
+       &sensor_dev_attr_in2_input.dev_attr.attr,
+       &sensor_dev_attr_in2_label.dev_attr.attr,
+       &sensor_dev_attr_in3_input.dev_attr.attr,
+       &sensor_dev_attr_in3_label.dev_attr.attr,
+
+       &sensor_dev_attr_temp1_input.dev_attr.attr,
+       &sensor_dev_attr_temp1_label.dev_attr.attr,
+       NULL
+};
+
+static const struct attribute_group da9055_attr_group = {.attrs = da9055_attr};
+
+static int __devinit da9055_hwmon_probe(struct platform_device *pdev)
+{
+       struct da9055_hwmon *hwmon;
+       int hwmon_irq, ret;
+
+       hwmon = devm_kzalloc(&pdev->dev, sizeof(struct da9055_hwmon),
+                            GFP_KERNEL);
+       if (!hwmon)
+               return -ENOMEM;
+
+       mutex_init(&hwmon->hwmon_lock);
+       mutex_init(&hwmon->irq_lock);
+
+       init_completion(&hwmon->done);
+       hwmon->da9055 = dev_get_drvdata(pdev->dev.parent);
+
+       platform_set_drvdata(pdev, hwmon);
+
+       hwmon_irq = platform_get_irq_byname(pdev, "HWMON");
+       if (hwmon_irq < 0)
+               return hwmon_irq;
+
+       hwmon_irq = regmap_irq_get_virq(hwmon->da9055->irq_data, hwmon_irq);
+       if (hwmon_irq < 0)
+               return hwmon_irq;
+
+       ret = devm_request_threaded_irq(&pdev->dev, hwmon_irq,
+                                       NULL, da9055_auxadc_irq,
+                                       IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+                                       "adc-irq", hwmon);
+       if (ret != 0) {
+               dev_err(hwmon->da9055->dev, "DA9055 ADC IRQ failed ret=%d\n",
+                       ret);
+               return ret;
+       }
+
+       ret = sysfs_create_group(&pdev->dev.kobj, &da9055_attr_group);
+       if (ret)
+               return ret;
+
+       hwmon->class_device = hwmon_device_register(&pdev->dev);
+       if (IS_ERR(hwmon->class_device)) {
+               ret = PTR_ERR(hwmon->class_device);
+               goto err;
+       }
+
+       return 0;
+
+err:
+       sysfs_remove_group(&pdev->dev.kobj, &da9055_attr_group);
+       return ret;
+}
+
+static int __devexit da9055_hwmon_remove(struct platform_device *pdev)
+{
+       struct da9055_hwmon *hwmon = platform_get_drvdata(pdev);
+
+       sysfs_remove_group(&pdev->dev.kobj, &da9055_attr_group);
+       hwmon_device_unregister(hwmon->class_device);
+
+       return 0;
+}
+
+static struct platform_driver da9055_hwmon_driver = {
+       .probe = da9055_hwmon_probe,
+       .remove = __devexit_p(da9055_hwmon_remove),
+       .driver = {
+               .name = "da9055-hwmon",
+               .owner = THIS_MODULE,
+       },
+};
+
+module_platform_driver(da9055_hwmon_driver);
+
+MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
+MODULE_DESCRIPTION("DA9055 HWMON driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:da9055-hwmon");
index 2b726346f8faa976ddca5b22332cc4a31013e84c..8e7158c3ad2fa37bb76bf6a484666a7c9cb7f0dd 100644 (file)
@@ -302,19 +302,8 @@ static struct i2c_driver ina2xx_driver = {
        .id_table       = ina2xx_id,
 };
 
-static int __init ina2xx_init(void)
-{
-       return i2c_add_driver(&ina2xx_driver);
-}
-
-static void __exit ina2xx_exit(void)
-{
-       i2c_del_driver(&ina2xx_driver);
-}
+module_i2c_driver(ina2xx_driver);
 
 MODULE_AUTHOR("Lothar Felten <l-felten@ti.com>");
 MODULE_DESCRIPTION("ina2xx driver");
 MODULE_LICENSE("GPL");
-
-module_init(ina2xx_init);
-module_exit(ina2xx_exit);
index 2ca6a5a4f5a795a23721467581ff9e02cc5baf5a..60745a535821d3b787af31a00cfcecd41743c7ec 100644 (file)
@@ -4,7 +4,7 @@
 
 menuconfig PMBUS
        tristate "PMBus support"
-       depends on I2C && EXPERIMENTAL
+       depends on I2C
        default n
        help
          Say yes here if you want to enable PMBus support.
index 1821b7423d5b77ae5a9e6cdd2794a7e1b9a2c173..fb624ae4da0da5e5ea08a03e3fb69051534dccd1 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  w83627ehf - Driver for the hardware monitoring functionality of
  *             the Winbond W83627EHF Super-I/O chip
- *  Copyright (C) 2005-2011  Jean Delvare <khali@linux-fr.org>
+ *  Copyright (C) 2005-2012  Jean Delvare <khali@linux-fr.org>
  *  Copyright (C) 2006  Yuan Mu (Winbond),
  *                     Rudolf Marek <r.marek@assembler.cz>
  *                     David Hubbard <david.c.hubbard@gmail.com>
@@ -502,6 +502,13 @@ struct w83627ehf_data {
        u16 have_temp_offset;
        u8 in6_skip:1;
        u8 temp3_val_only:1;
+
+#ifdef CONFIG_PM
+       /* Remember extra register values over suspend/resume */
+       u8 vbat;
+       u8 fandiv1;
+       u8 fandiv2;
+#endif
 };
 
 struct w83627ehf_sio_data {
@@ -2607,10 +2614,94 @@ static int __devexit w83627ehf_remove(struct platform_device *pdev)
        return 0;
 }
 
+#ifdef CONFIG_PM
+static int w83627ehf_suspend(struct device *dev)
+{
+       struct w83627ehf_data *data = w83627ehf_update_device(dev);
+       struct w83627ehf_sio_data *sio_data = dev->platform_data;
+
+       mutex_lock(&data->update_lock);
+       data->vbat = w83627ehf_read_value(data, W83627EHF_REG_VBAT);
+       if (sio_data->kind == nct6775) {
+               data->fandiv1 = w83627ehf_read_value(data, NCT6775_REG_FANDIV1);
+               data->fandiv2 = w83627ehf_read_value(data, NCT6775_REG_FANDIV2);
+       }
+       mutex_unlock(&data->update_lock);
+
+       return 0;
+}
+
+static int w83627ehf_resume(struct device *dev)
+{
+       struct w83627ehf_data *data = dev_get_drvdata(dev);
+       struct w83627ehf_sio_data *sio_data = dev->platform_data;
+       int i;
+
+       /* Restore limits */
+       mutex_lock(&data->update_lock);
+       for (i = 0; i < data->in_num; i++) {
+               if ((i == 6) && data->in6_skip)
+                       continue;
+
+               w83627ehf_write_value(data, W83627EHF_REG_IN_MIN(i),
+                                     data->in_min[i]);
+               w83627ehf_write_value(data, W83627EHF_REG_IN_MAX(i),
+                                     data->in_max[i]);
+       }
+
+       for (i = 0; i < 5; i++) {
+               if (!(data->has_fan_min & (1 << i)))
+                       continue;
+
+               w83627ehf_write_value(data, data->REG_FAN_MIN[i],
+                                     data->fan_min[i]);
+       }
+
+       for (i = 0; i < NUM_REG_TEMP; i++) {
+               if (!(data->have_temp & (1 << i)))
+                       continue;
+
+               if (data->reg_temp_over[i])
+                       w83627ehf_write_temp(data, data->reg_temp_over[i],
+                                            data->temp_max[i]);
+               if (data->reg_temp_hyst[i])
+                       w83627ehf_write_temp(data, data->reg_temp_hyst[i],
+                                            data->temp_max_hyst[i]);
+               if (data->have_temp_offset & (1 << i))
+                       w83627ehf_write_value(data,
+                                             W83627EHF_REG_TEMP_OFFSET[i],
+                                             data->temp_offset[i]);
+       }
+
+       /* Restore other settings */
+       w83627ehf_write_value(data, W83627EHF_REG_VBAT, data->vbat);
+       if (sio_data->kind == nct6775) {
+               w83627ehf_write_value(data, NCT6775_REG_FANDIV1, data->fandiv1);
+               w83627ehf_write_value(data, NCT6775_REG_FANDIV2, data->fandiv2);
+       }
+
+       /* Force re-reading all values */
+       data->valid = 0;
+       mutex_unlock(&data->update_lock);
+
+       return 0;
+}
+
+static const struct dev_pm_ops w83627ehf_dev_pm_ops = {
+       .suspend = w83627ehf_suspend,
+       .resume = w83627ehf_resume,
+};
+
+#define W83627EHF_DEV_PM_OPS   (&w83627ehf_dev_pm_ops)
+#else
+#define W83627EHF_DEV_PM_OPS   NULL
+#endif /* CONFIG_PM */
+
 static struct platform_driver w83627ehf_driver = {
        .driver = {
                .owner  = THIS_MODULE,
                .name   = DRVNAME,
+               .pm     = W83627EHF_DEV_PM_OPS,
        },
        .probe          = w83627ehf_probe,
        .remove         = __devexit_p(w83627ehf_remove),
index 5b1a6a666441f242ac63f21d9b9359464ced3f97..b8851f76265da433007c4ad14b754e19c41647db 100644 (file)
@@ -5,7 +5,7 @@
  *                           Philip Edelbrock <phil@netroedge.com>,
  *                           and Mark Studebaker <mdsxyz123@yahoo.com>
  * Ported to 2.6 by Bernhard C. Schrenk <clemy@clemy.org>
- * Copyright (c) 2007  Jean Delvare <khali@linux-fr.org>
+ * Copyright (c) 2007 - 1012  Jean Delvare <khali@linux-fr.org>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -25,7 +25,7 @@
 /*
  * Supports following chips:
  *
- * Chip        #vin    #fanin  #pwm    #temp   wchipid vendid  i2c     ISA
+ * Chip                #vin    #fanin  #pwm    #temp   wchipid vendid  i2c     ISA
  * w83627hf    9       3       2       3       0x20    0x5ca3  no      yes(LPC)
  * w83627thf   7       3       3       3       0x90    0x5ca3  no      yes(LPC)
  * w83637hf    7       3       3       3       0x80    0x5ca3  no      yes(LPC)
@@ -389,6 +389,12 @@ struct w83627hf_data {
                                 */
        u8 vrm;
        u8 vrm_ovt;             /* Register value, 627THF/637HF/687THF only */
+
+#ifdef CONFIG_PM
+       /* Remember extra register values over suspend/resume */
+       u8 scfg1;
+       u8 scfg2;
+#endif
 };
 
 
@@ -401,10 +407,77 @@ static void w83627hf_update_fan_div(struct w83627hf_data *data);
 static struct w83627hf_data *w83627hf_update_device(struct device *dev);
 static void w83627hf_init_device(struct platform_device *pdev);
 
+#ifdef CONFIG_PM
+static int w83627hf_suspend(struct device *dev)
+{
+       struct w83627hf_data *data = w83627hf_update_device(dev);
+
+       mutex_lock(&data->update_lock);
+       data->scfg1 = w83627hf_read_value(data, W83781D_REG_SCFG1);
+       data->scfg2 = w83627hf_read_value(data, W83781D_REG_SCFG2);
+       mutex_unlock(&data->update_lock);
+
+       return 0;
+}
+
+static int w83627hf_resume(struct device *dev)
+{
+       struct w83627hf_data *data = dev_get_drvdata(dev);
+       int i, num_temps = (data->type == w83697hf) ? 2 : 3;
+
+       /* Restore limits */
+       mutex_lock(&data->update_lock);
+       for (i = 0; i <= 8; i++) {
+               /* skip missing sensors */
+               if (((data->type == w83697hf) && (i == 1)) ||
+                   ((data->type != w83627hf && data->type != w83697hf)
+                   && (i == 5 || i == 6)))
+                       continue;
+               w83627hf_write_value(data, W83781D_REG_IN_MAX(i),
+                                    data->in_max[i]);
+               w83627hf_write_value(data, W83781D_REG_IN_MIN(i),
+                                    data->in_min[i]);
+       }
+       for (i = 0; i <= 2; i++)
+               w83627hf_write_value(data, W83627HF_REG_FAN_MIN(i),
+                                    data->fan_min[i]);
+       for (i = 0; i < num_temps; i++) {
+               w83627hf_write_value(data, w83627hf_reg_temp_over[i],
+                                    data->temp_max[i]);
+               w83627hf_write_value(data, w83627hf_reg_temp_hyst[i],
+                                    data->temp_max_hyst[i]);
+       }
+
+       /* Fixup BIOS bugs */
+       if (data->type == w83627thf || data->type == w83637hf ||
+           data->type == w83687thf)
+               w83627hf_write_value(data, W83627THF_REG_VRM_OVT_CFG,
+                                    data->vrm_ovt);
+       w83627hf_write_value(data, W83781D_REG_SCFG1, data->scfg1);
+       w83627hf_write_value(data, W83781D_REG_SCFG2, data->scfg2);
+
+       /* Force re-reading all values */
+       data->valid = 0;
+       mutex_unlock(&data->update_lock);
+
+       return 0;
+}
+
+static const struct dev_pm_ops w83627hf_dev_pm_ops = {
+       .suspend = w83627hf_suspend,
+       .resume = w83627hf_resume,
+};
+
+#define W83627HF_DEV_PM_OPS    (&w83627hf_dev_pm_ops)
+#else
+#define W83627HF_DEV_PM_OPS    NULL
+#endif /* CONFIG_PM */
+
 static struct platform_driver w83627hf_driver = {
        .driver = {
                .owner  = THIS_MODULE,
                .name   = DRVNAME,
+               .pm     = W83627HF_DEV_PM_OPS,
        },
        .probe          = w83627hf_probe,
        .remove         = __devexit_p(w83627hf_remove),
index 5a5046d94c3eee8288cf5871655fffa973d97977..20f11d31da407f5545af8b7082187c518721522a 100644 (file)
@@ -24,7 +24,7 @@
 /*
  * Supports following chips:
  *
- * Chip        #vin    #fanin  #pwm    #temp   wchipid vendid  i2c     ISA
+ * Chip                #vin    #fanin  #pwm    #temp   wchipid vendid  i2c     ISA
  * as99127f    7       3       0       3       0x31    0x12c3  yes     no
  * as99127f rev.2 (type_name = as99127f)       0x31    0x5ca3  yes     no
  * w83781d     7       3       0       3       0x10-1  0x5ca3  yes     yes
index 39ab7bcc616e7a9e8733ce9bbbcc7e3cf6b0b970..ed397c6451983473b9ca7d1dbac399194a746fb3 100644 (file)
@@ -22,7 +22,7 @@
 /*
  * Supports following chips:
  *
- * Chip        #vin    #fanin  #pwm    #temp   wchipid vendid  i2c     ISA
+ * Chip                #vin    #fanin  #pwm    #temp   wchipid vendid  i2c     ISA
  * w83791d     10      5       5       3       0x71    0x5ca3  yes     no
  *
  * The w83791d chip appears to be part way between the 83781d and the
index 053645279f381b453396053dfb71294346604717..301942d084534ef748f1917b1fa3dccde1b8beed 100644 (file)
@@ -31,7 +31,7 @@
 /*
  * Supports following chips:
  *
- * Chip        #vin    #fanin  #pwm    #temp   wchipid vendid  i2c     ISA
+ * Chip                #vin    #fanin  #pwm    #temp   wchipid vendid  i2c     ISA
  * w83792d     9       7       7       3       0x7a    0x5ca3  yes     no
  */
 
index f0e8286c3c70ed7c1c2a57a73b19cc06fec8a193..79710bcac2f724233746b9c416fd53384dd52e52 100644 (file)
@@ -20,7 +20,7 @@
 /*
  * Supports following chips:
  *
- * Chip        #vin    #fanin  #pwm    #temp   wchipid vendid  i2c     ISA
+ * Chip                #vin    #fanin  #pwm    #temp   wchipid vendid  i2c     ISA
  * w83l786ng   3       2       2       2       0x7b    0x5ca3  yes     no
  */
 
index beee6b2d361db458a1336a48bd13b5166d6d013c..1722f50f247385e0247c98e5dee91c97f18203ee 100644 (file)
@@ -8,6 +8,7 @@ obj-$(CONFIG_I2C_SMBUS)         += i2c-smbus.o
 obj-$(CONFIG_I2C_CHARDEV)      += i2c-dev.o
 obj-$(CONFIG_I2C_MUX)          += i2c-mux.o
 obj-y                          += algos/ busses/ muxes/
+obj-$(CONFIG_I2C_STUB)         += i2c-stub.o
 
 ccflags-$(CONFIG_I2C_DEBUG_CORE) := -DDEBUG
 CFLAGS_i2c-core.o := -Wno-deprecated-declarations
index 65dd599a02620211b8db7a1ef6bfd1d8f9cdda30..e9df4612b7ebc9710db24290b159b4bd77d5d625 100644 (file)
@@ -81,7 +81,6 @@ config I2C_I801
        tristate "Intel 82801 (ICH/PCH)"
        depends on PCI
        select CHECK_SIGNATURE if X86 && DMI
-       select GPIOLIB if I2C_MUX
        help
          If you say yes to this option, support will be included for the Intel
          801 family of mainboard I2C interfaces.  Specifically, the following
index 2d33d62952c112adfb62bde5f08a342a37466c78..395b516ffa08cddbf5fdc2cbc5e2c34a558e356c 100644 (file)
@@ -85,7 +85,6 @@ obj-$(CONFIG_I2C_ACORN)               += i2c-acorn.o
 obj-$(CONFIG_I2C_ELEKTOR)      += i2c-elektor.o
 obj-$(CONFIG_I2C_PCA_ISA)      += i2c-pca-isa.o
 obj-$(CONFIG_I2C_SIBYTE)       += i2c-sibyte.o
-obj-$(CONFIG_I2C_STUB)         += i2c-stub.o
 obj-$(CONFIG_SCx200_ACB)       += scx200_acb.o
 obj-$(CONFIG_SCx200_I2C)       += scx200_i2c.o
 
index 37793156bd936202a10362e7910d88708c4a9248..e80eafc48e7838cced28eb2776854f31d0208bfa 100644 (file)
 #include <linux/slab.h>
 #include <linux/wait.h>
 #include <linux/err.h>
+#include <linux/of_i2c.h>
 
-#if defined CONFIG_I2C_MUX || defined CONFIG_I2C_MUX_MODULE
+#if (defined CONFIG_I2C_MUX_GPIO || defined CONFIG_I2C_MUX_GPIO_MODULE) && \
+               defined CONFIG_DMI
 #include <linux/gpio.h>
 #include <linux/i2c-mux-gpio.h>
 #include <linux/platform_device.h>
@@ -192,7 +194,8 @@ struct i801_priv {
        int len;
        u8 *data;
 
-#if defined CONFIG_I2C_MUX || defined CONFIG_I2C_MUX_MODULE
+#if (defined CONFIG_I2C_MUX_GPIO || defined CONFIG_I2C_MUX_GPIO_MODULE) && \
+               defined CONFIG_DMI
        const struct i801_mux_config *mux_drvdata;
        struct platform_device *mux_pdev;
 #endif
@@ -921,7 +924,8 @@ static void __init input_apanel_init(void) {}
 static void __devinit i801_probe_optional_slaves(struct i801_priv *priv) {}
 #endif /* CONFIG_X86 && CONFIG_DMI */
 
-#if defined CONFIG_I2C_MUX || defined CONFIG_I2C_MUX_MODULE
+#if (defined CONFIG_I2C_MUX_GPIO || defined CONFIG_I2C_MUX_GPIO_MODULE) && \
+               defined CONFIG_DMI
 static struct i801_mux_config i801_mux_config_asus_z8_d12 = {
        .gpio_chip = "gpio_ich",
        .values = { 0x02, 0x03 },
@@ -1059,7 +1063,7 @@ static unsigned int __devinit i801_get_adapter_class(struct i801_priv *priv)
 
        id = dmi_first_match(mux_dmi_table);
        if (id) {
-               /* Remove from branch classes from trunk */
+               /* Remove branch classes from trunk */
                mux_config = id->driver_data;
                for (i = 0; i < mux_config->n_values; i++)
                        class &= ~mux_config->classes[i];
@@ -1212,6 +1216,7 @@ static int __devinit i801_probe(struct pci_dev *dev,
                goto exit_free_irq;
        }
 
+       of_i2c_register_devices(&priv->adapter);
        i801_probe_optional_slaves(priv);
        /* We ignore errors - multiplexing is optional */
        i801_add_mux(priv);
index 2ef162d148cbacbc63269bf89774c81aba34983c..b9734747d61080ffa16be81eb7c996f5a163bece 100644 (file)
@@ -52,8 +52,6 @@
 #include <linux/of_device.h>
 #include <linux/of_i2c.h>
 #include <linux/pinctrl/consumer.h>
-
-#include <mach/hardware.h>
 #include <linux/platform_data/i2c-imx.h>
 
 /** Defines ********************************************************************
@@ -115,6 +113,11 @@ static u16 __initdata i2c_clk_div[50][2] = {
        { 3072, 0x1E }, { 3840, 0x1F }
 };
 
+enum imx_i2c_type {
+       IMX1_I2C,
+       IMX21_I2C,
+};
+
 struct imx_i2c_struct {
        struct i2c_adapter      adapter;
        struct clk              *clk;
@@ -124,13 +127,33 @@ struct imx_i2c_struct {
        unsigned int            disable_delay;
        int                     stopped;
        unsigned int            ifdr; /* IMX_I2C_IFDR */
+       enum imx_i2c_type       devtype;
+};
+
+static struct platform_device_id imx_i2c_devtype[] = {
+       {
+               .name = "imx1-i2c",
+               .driver_data = IMX1_I2C,
+       }, {
+               .name = "imx21-i2c",
+               .driver_data = IMX21_I2C,
+       }, {
+               /* sentinel */
+       }
 };
+MODULE_DEVICE_TABLE(platform, imx_i2c_devtype);
 
 static const struct of_device_id i2c_imx_dt_ids[] = {
-       { .compatible = "fsl,imx1-i2c", },
+       { .compatible = "fsl,imx1-i2c", .data = &imx_i2c_devtype[IMX1_I2C], },
+       { .compatible = "fsl,imx21-i2c", .data = &imx_i2c_devtype[IMX21_I2C], },
        { /* sentinel */ }
 };
 
+static inline int is_imx1_i2c(struct imx_i2c_struct *i2c_imx)
+{
+       return i2c_imx->devtype == IMX1_I2C;
+}
+
 /** Functions for IMX I2C adapter driver ***************************************
 *******************************************************************************/
 
@@ -223,7 +246,7 @@ static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx)
                temp &= ~(I2CR_MSTA | I2CR_MTX);
                writeb(temp, i2c_imx->base + IMX_I2C_I2CR);
        }
-       if (cpu_is_mx1()) {
+       if (is_imx1_i2c(i2c_imx)) {
                /*
                 * This delay caused by an i.MXL hardware bug.
                 * If no (or too short) delay, no "STOP" bit will be generated.
@@ -465,6 +488,8 @@ static struct i2c_algorithm i2c_imx_algo = {
 
 static int __init i2c_imx_probe(struct platform_device *pdev)
 {
+       const struct of_device_id *of_id = of_match_device(i2c_imx_dt_ids,
+                                                          &pdev->dev);
        struct imx_i2c_struct *i2c_imx;
        struct resource *res;
        struct imxi2c_platform_data *pdata = pdev->dev.platform_data;
@@ -497,6 +522,10 @@ static int __init i2c_imx_probe(struct platform_device *pdev)
                return -ENOMEM;
        }
 
+       if (of_id)
+               pdev->id_entry = of_id->data;
+       i2c_imx->devtype = pdev->id_entry->driver_data;
+
        /* Setup i2c_imx driver structure */
        strlcpy(i2c_imx->adapter.name, pdev->name, sizeof(i2c_imx->adapter.name));
        i2c_imx->adapter.owner          = THIS_MODULE;
@@ -593,7 +622,8 @@ static struct platform_driver i2c_imx_driver = {
                .name   = DRIVER_NAME,
                .owner  = THIS_MODULE,
                .of_match_table = i2c_imx_dt_ids,
-       }
+       },
+       .id_table       = imx_i2c_devtype,
 };
 
 static int __init i2c_adap_imx_init(void)
similarity index 75%
rename from drivers/i2c/busses/i2c-stub.c
rename to drivers/i2c/i2c-stub.c
index b1b3447942c9efd42c30ed7a9e271f00268db127..60e2c416c414e2d17eaca048684dca6cd2f1b716 100644 (file)
@@ -2,7 +2,7 @@
     i2c-stub.c - I2C/SMBus chip emulator
 
     Copyright (c) 2004 Mark M. Hoffman <mhoffman@lightlink.com>
-    Copyright (C) 2007 Jean Delvare <khali@linux-fr.org>
+    Copyright (C) 2007, 2012 Jean Delvare <khali@linux-fr.org>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -51,8 +51,8 @@ struct stub_chip {
 static struct stub_chip *stub_chips;
 
 /* Return negative errno on error. */
-static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags,
-       char read_write, u8 command, int size, union i2c_smbus_data * data)
+static s32 stub_xfer(struct i2c_adapter *adap, u16 addr, unsigned short flags,
+       char read_write, u8 command, int size, union i2c_smbus_data *data)
 {
        s32 ret;
        int i, len;
@@ -78,14 +78,14 @@ static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags,
        case I2C_SMBUS_BYTE:
                if (read_write == I2C_SMBUS_WRITE) {
                        chip->pointer = command;
-                       dev_dbg(&adap->dev, "smbus byte - addr 0x%02x, "
-                                       "wrote 0x%02x.\n",
-                                       addr, command);
+                       dev_dbg(&adap->dev,
+                               "smbus byte - addr 0x%02x, wrote 0x%02x.\n",
+                               addr, command);
                } else {
                        data->byte = chip->words[chip->pointer++] & 0xff;
-                       dev_dbg(&adap->dev, "smbus byte - addr 0x%02x, "
-                                       "read  0x%02x.\n",
-                                       addr, data->byte);
+                       dev_dbg(&adap->dev,
+                               "smbus byte - addr 0x%02x, read  0x%02x.\n",
+                               addr, data->byte);
                }
 
                ret = 0;
@@ -95,14 +95,14 @@ static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags,
                if (read_write == I2C_SMBUS_WRITE) {
                        chip->words[command] &= 0xff00;
                        chip->words[command] |= data->byte;
-                       dev_dbg(&adap->dev, "smbus byte data - addr 0x%02x, "
-                                       "wrote 0x%02x at 0x%02x.\n",
-                                       addr, data->byte, command);
+                       dev_dbg(&adap->dev,
+                               "smbus byte data - addr 0x%02x, wrote 0x%02x at 0x%02x.\n",
+                               addr, data->byte, command);
                } else {
                        data->byte = chip->words[command] & 0xff;
-                       dev_dbg(&adap->dev, "smbus byte data - addr 0x%02x, "
-                                       "read  0x%02x at 0x%02x.\n",
-                                       addr, data->byte, command);
+                       dev_dbg(&adap->dev,
+                               "smbus byte data - addr 0x%02x, read  0x%02x at 0x%02x.\n",
+                               addr, data->byte, command);
                }
                chip->pointer = command + 1;
 
@@ -112,14 +112,14 @@ static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags,
        case I2C_SMBUS_WORD_DATA:
                if (read_write == I2C_SMBUS_WRITE) {
                        chip->words[command] = data->word;
-                       dev_dbg(&adap->dev, "smbus word data - addr 0x%02x, "
-                                       "wrote 0x%04x at 0x%02x.\n",
-                                       addr, data->word, command);
+                       dev_dbg(&adap->dev,
+                               "smbus word data - addr 0x%02x, wrote 0x%04x at 0x%02x.\n",
+                               addr, data->word, command);
                } else {
                        data->word = chip->words[command];
-                       dev_dbg(&adap->dev, "smbus word data - addr 0x%02x, "
-                                       "read  0x%04x at 0x%02x.\n",
-                                       addr, data->word, command);
+                       dev_dbg(&adap->dev,
+                               "smbus word data - addr 0x%02x, read  0x%04x at 0x%02x.\n",
+                               addr, data->word, command);
                }
 
                ret = 0;
@@ -132,17 +132,17 @@ static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags,
                                chip->words[command + i] &= 0xff00;
                                chip->words[command + i] |= data->block[1 + i];
                        }
-                       dev_dbg(&adap->dev, "i2c block data - addr 0x%02x, "
-                                       "wrote %d bytes at 0x%02x.\n",
-                                       addr, len, command);
+                       dev_dbg(&adap->dev,
+                               "i2c block data - addr 0x%02x, wrote %d bytes at 0x%02x.\n",
+                               addr, len, command);
                } else {
                        for (i = 0; i < len; i++) {
                                data->block[1 + i] =
                                        chip->words[command + i] & 0xff;
                        }
-                       dev_dbg(&adap->dev, "i2c block data - addr 0x%02x, "
-                                       "read  %d bytes at 0x%02x.\n",
-                                       addr, len, command);
+                       dev_dbg(&adap->dev,
+                               "i2c block data - addr 0x%02x, read  %d bytes at 0x%02x.\n",
+                               addr, len, command);
                }
 
                ret = 0;
@@ -179,25 +179,24 @@ static int __init i2c_stub_init(void)
        int i, ret;
 
        if (!chip_addr[0]) {
-               printk(KERN_ERR "i2c-stub: Please specify a chip address\n");
+               pr_err("i2c-stub: Please specify a chip address\n");
                return -ENODEV;
        }
 
        for (i = 0; i < MAX_CHIPS && chip_addr[i]; i++) {
                if (chip_addr[i] < 0x03 || chip_addr[i] > 0x77) {
-                       printk(KERN_ERR "i2c-stub: Invalid chip address "
-                              "0x%02x\n", chip_addr[i]);
+                       pr_err("i2c-stub: Invalid chip address 0x%02x\n",
+                              chip_addr[i]);
                        return -EINVAL;
                }
 
-               printk(KERN_INFO "i2c-stub: Virtual chip at 0x%02x\n",
-                      chip_addr[i]);
+               pr_info("i2c-stub: Virtual chip at 0x%02x\n", chip_addr[i]);
        }
 
        /* Allocate memory for all chips at once */
        stub_chips = kzalloc(i * sizeof(struct stub_chip), GFP_KERNEL);
        if (!stub_chips) {
-               printk(KERN_ERR "i2c-stub: Out of memory\n");
+               pr_err("i2c-stub: Out of memory\n");
                return -ENOMEM;
        }
 
index 6e3f143fc71d146c786a550162216be2200d0f4f..fc937aca71fbb2f7bb8a53fac55e2ae9b0cec048 100644 (file)
@@ -62,7 +62,6 @@ source "drivers/iio/frequency/Kconfig"
 source "drivers/iio/dac/Kconfig"
 source "drivers/iio/common/Kconfig"
 source "drivers/iio/gyro/Kconfig"
-source "drivers/iio/light/Kconfig"
 source "drivers/iio/magnetometer/Kconfig"
 
 endif # IIO
index f7fa3c0867b4c29026b2821cf793c352972741ce..761f2b65ac52865f4d16a99db3a1f6e7e1b61fbb 100644 (file)
@@ -18,5 +18,4 @@ obj-y += frequency/
 obj-y += dac/
 obj-y += common/
 obj-y += gyro/
-obj-y += light/
 obj-y += magnetometer/
index b2510c4d9a5ac4d5e61868f60af33027243617eb..fe4bcd7c5b12ea9ef5e4f23b56c25169038ad570 100644 (file)
@@ -8,7 +8,7 @@ config HID_SENSOR_ACCEL_3D
        select IIO_BUFFER
        select IIO_TRIGGERED_BUFFER
        select HID_SENSOR_IIO_COMMON
-       tristate "HID Acelerometers 3D"
+       tristate "HID Accelerometers 3D"
        help
          Say yes here to build support for the HID SENSOR
          accelerometers 3D.
index 3ed94bf8059675f047bdaacc74916c1db42a7cdf..a9176722042f1fc751a4b92a3e74dabec0f20a1e 100644 (file)
@@ -46,7 +46,6 @@ struct at91_adc_state {
        struct clk              *clk;
        bool                    done;
        int                     irq;
-       bool                    irq_enabled;
        u16                     last_value;
        struct mutex            lock;
        u8                      num_channels;
@@ -82,10 +81,9 @@ static irqreturn_t at91_adc_trigger_handler(int irq, void *p)
                *timestamp = pf->timestamp;
        }
 
-       buffer->access->store_to(buffer, (u8 *)st->buffer);
+       iio_push_to_buffer(buffer, st->buffer);
 
        iio_trigger_notify_done(idev->trig);
-       st->irq_enabled = true;
 
        /* Needed to ACK the DRDY interruption */
        at91_adc_readl(st, AT91_ADC_LCDR);
@@ -106,7 +104,6 @@ static irqreturn_t at91_adc_eoc_trigger(int irq, void *private)
 
        if (iio_buffer_enabled(idev)) {
                disable_irq_nosync(irq);
-               st->irq_enabled = false;
                iio_trigger_poll(idev->trig, iio_get_time_ns());
        } else {
                st->last_value = at91_adc_readl(st, AT91_ADC_LCDR);
@@ -126,10 +123,8 @@ static int at91_adc_channel_init(struct iio_dev *idev)
        idev->num_channels = bitmap_weight(&st->channels_mask,
                                           st->num_channels) + 1;
 
-       chan_array = devm_kzalloc(&idev->dev,
-                                 ((idev->num_channels + 1) *
-                                       sizeof(struct iio_chan_spec)),
-                                 GFP_KERNEL);
+       chan_array = devm_kcalloc(&idev->dev, idev->num_channels + 1,
+                                       sizeof(*chan_array), GFP_KERNEL);
 
        if (!chan_array)
                return -ENOMEM;
@@ -273,9 +268,8 @@ static int at91_adc_trigger_init(struct iio_dev *idev)
        struct at91_adc_state *st = iio_priv(idev);
        int i, ret;
 
-       st->trig = devm_kzalloc(&idev->dev,
-                               st->trigger_number * sizeof(st->trig),
-                               GFP_KERNEL);
+       st->trig = devm_kcalloc(&idev->dev, st->trigger_number,
+                               sizeof(*st->trig), GFP_KERNEL);
 
        if (st->trig == NULL) {
                ret = -ENOMEM;
@@ -457,9 +451,8 @@ static int at91_adc_probe_dt(struct at91_adc_state *st,
        st->registers->trigger_register = prop;
 
        st->trigger_number = of_get_child_count(node);
-       st->trigger_list = devm_kzalloc(&idev->dev, st->trigger_number *
-                                       sizeof(struct at91_adc_trigger),
-                                       GFP_KERNEL);
+       st->trigger_list = devm_kcalloc(&idev->dev, st->trigger_number,
+                                       sizeof(*st->trigger_list), GFP_KERNEL);
        if (!st->trigger_list) {
                dev_err(&idev->dev, "Could not allocate trigger list memory.\n");
                ret = -ENOMEM;
index b1c0ee5294ca3af97b0b75d94e496d6ce0dee4a1..f68756e6dd628f83fb60672959e1954702b7107a 100644 (file)
@@ -67,6 +67,16 @@ config AD5446
          To compile this driver as a module, choose M here: the
          module will be called ad5446.
 
+config AD5449
+       tristate "Analog Device AD5449 and similar DACs driver"
+       depends on SPI_MASTER
+       help
+         Say yes here to build support for Analog Devices AD5415, AD5426, AD5429,
+         AD5432, AD5439, AD5443, AD5449 Digital to Analog Converters.
+
+         To compile this driver as a module, choose M here: the
+         module will be called ad5449.
+
 config AD5504
        tristate "Analog Devices AD5504/AD5501 DAC SPI driver"
        depends on SPI
index c0d333b23ba3bf5a95f7e841e9b0778e1677015a..5b528ebb3343c60d260506821510ea60316da26f 100644 (file)
@@ -9,6 +9,7 @@ obj-$(CONFIG_AD5624R_SPI) += ad5624r_spi.o
 obj-$(CONFIG_AD5064) += ad5064.o
 obj-$(CONFIG_AD5504) += ad5504.o
 obj-$(CONFIG_AD5446) += ad5446.o
+obj-$(CONFIG_AD5449) += ad5449.o
 obj-$(CONFIG_AD5755) += ad5755.o
 obj-$(CONFIG_AD5764) += ad5764.o
 obj-$(CONFIG_AD5791) += ad5791.o
diff --git a/drivers/iio/dac/ad5449.c b/drivers/iio/dac/ad5449.c
new file mode 100644 (file)
index 0000000..5b43030
--- /dev/null
@@ -0,0 +1,375 @@
+/*
+ * AD5415, AD5426, AD5429, AD5432, AD5439, AD5443, AD5449 Digital to Analog
+ * Converter driver.
+ *
+ * Copyright 2012 Analog Devices Inc.
+ *  Author: Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/spi/spi.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
+#include <linux/regulator/consumer.h>
+#include <asm/unaligned.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+
+#include <linux/platform_data/ad5449.h>
+
+#define AD5449_MAX_CHANNELS            2
+#define AD5449_MAX_VREFS               2
+
+#define AD5449_CMD_NOOP                        0x0
+#define AD5449_CMD_LOAD_AND_UPDATE(x)  (0x1 + (x) * 3)
+#define AD5449_CMD_READ(x)             (0x2 + (x) * 3)
+#define AD5449_CMD_LOAD(x)             (0x3 + (x) * 3)
+#define AD5449_CMD_CTRL                        13
+
+#define AD5449_CTRL_SDO_OFFSET         10
+#define AD5449_CTRL_DAISY_CHAIN                BIT(9)
+#define AD5449_CTRL_HCLR_TO_MIDSCALE   BIT(8)
+#define AD5449_CTRL_SAMPLE_RISING      BIT(7)
+
+/**
+ * struct ad5449_chip_info - chip specific information
+ * @channels:          Channel specification
+ * @num_channels:      Number of channels
+ * @has_ctrl:          Chip has a control register
+ */
+struct ad5449_chip_info {
+       const struct iio_chan_spec *channels;
+       unsigned int num_channels;
+       bool has_ctrl;
+};
+
+/**
+ * struct ad5449 - driver instance specific data
+ * @spi:               the SPI device for this driver instance
+ * @chip_info:         chip model specific constants, available modes etc
+ * @vref_reg:          vref supply regulators
+ * @has_sdo:           whether the SDO line is connected
+ * @dac_cache:         Cache for the DAC values
+ * @data:              spi transfer buffers
+ */
+struct ad5449 {
+       struct spi_device               *spi;
+       const struct ad5449_chip_info   *chip_info;
+       struct regulator_bulk_data      vref_reg[AD5449_MAX_VREFS];
+
+       bool has_sdo;
+       uint16_t dac_cache[AD5449_MAX_CHANNELS];
+
+       /*
+        * DMA (thus cache coherency maintenance) requires the
+        * transfer buffers to live in their own cache lines.
+        */
+       __be16 data[2] ____cacheline_aligned;
+};
+
+enum ad5449_type {
+       ID_AD5426,
+       ID_AD5429,
+       ID_AD5432,
+       ID_AD5439,
+       ID_AD5443,
+       ID_AD5449,
+};
+
+static int ad5449_write(struct iio_dev *indio_dev, unsigned int addr,
+       unsigned int val)
+{
+       struct ad5449 *st = iio_priv(indio_dev);
+       int ret;
+
+       mutex_lock(&indio_dev->mlock);
+       st->data[0] = cpu_to_be16((addr << 12) | val);
+       ret = spi_write(st->spi, st->data, 2);
+       mutex_unlock(&indio_dev->mlock);
+
+       return ret;
+}
+
+static int ad5449_read(struct iio_dev *indio_dev, unsigned int addr,
+       unsigned int *val)
+{
+       struct ad5449 *st = iio_priv(indio_dev);
+       int ret;
+       struct spi_message msg;
+       struct spi_transfer t[] = {
+               {
+                       .tx_buf = &st->data[0],
+                       .len = 2,
+                       .cs_change = 1,
+               }, {
+                       .tx_buf = &st->data[1],
+                       .rx_buf = &st->data[1],
+                       .len = 2,
+               },
+       };
+
+       spi_message_init(&msg);
+       spi_message_add_tail(&t[0], &msg);
+       spi_message_add_tail(&t[1], &msg);
+
+       mutex_lock(&indio_dev->mlock);
+       st->data[0] = cpu_to_be16(addr << 12);
+       st->data[1] = cpu_to_be16(AD5449_CMD_NOOP);
+
+       ret = spi_sync(st->spi, &msg);
+       if (ret < 0)
+               return ret;
+
+       *val = be16_to_cpu(st->data[1]);
+       mutex_unlock(&indio_dev->mlock);
+
+       return 0;
+}
+
+static int ad5449_read_raw(struct iio_dev *indio_dev,
+       struct iio_chan_spec const *chan, int *val, int *val2, long info)
+{
+       struct ad5449 *st = iio_priv(indio_dev);
+       struct regulator_bulk_data *reg;
+       int scale_uv;
+       int ret;
+
+       switch (info) {
+       case IIO_CHAN_INFO_RAW:
+               if (st->has_sdo) {
+                       ret = ad5449_read(indio_dev,
+                               AD5449_CMD_READ(chan->address), val);
+                       if (ret)
+                               return ret;
+                       *val &= 0xfff;
+               } else {
+                       *val = st->dac_cache[chan->address];
+               }
+
+               return IIO_VAL_INT;
+       case IIO_CHAN_INFO_SCALE:
+               reg = &st->vref_reg[chan->channel];
+               scale_uv = regulator_get_voltage(reg->consumer);
+               if (scale_uv < 0)
+                       return scale_uv;
+
+               *val = scale_uv / 1000;
+               *val2 = chan->scan_type.realbits;
+
+               return IIO_VAL_FRACTIONAL_LOG2;
+       default:
+               break;
+       }
+
+       return -EINVAL;
+}
+
+static int ad5449_write_raw(struct iio_dev *indio_dev,
+       struct iio_chan_spec const *chan, int val, int val2, long info)
+{
+       struct ad5449 *st = iio_priv(indio_dev);
+       int ret;
+
+       switch (info) {
+       case IIO_CHAN_INFO_RAW:
+               if (val < 0 || val >= (1 << chan->scan_type.realbits))
+                       return -EINVAL;
+
+               ret = ad5449_write(indio_dev,
+                       AD5449_CMD_LOAD_AND_UPDATE(chan->address),
+                       val << chan->scan_type.shift);
+               if (ret == 0)
+                       st->dac_cache[chan->address] = val;
+               break;
+       default:
+               ret = -EINVAL;
+       }
+
+       return ret;
+}
+
+static const struct iio_info ad5449_info = {
+       .read_raw = ad5449_read_raw,
+       .write_raw = ad5449_write_raw,
+       .driver_module = THIS_MODULE,
+};
+
+#define AD5449_CHANNEL(chan, bits) {                           \
+       .type = IIO_VOLTAGE,                                    \
+       .indexed = 1,                                           \
+       .output = 1,                                            \
+       .channel = (chan),                                      \
+       .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |           \
+               IIO_CHAN_INFO_SCALE_SEPARATE_BIT,               \
+       .address = (chan),                                      \
+       .scan_type = IIO_ST('u', (bits), 16, 12 - (bits)),      \
+}
+
+#define DECLARE_AD5449_CHANNELS(name, bits) \
+const struct iio_chan_spec name[] = { \
+       AD5449_CHANNEL(0, bits), \
+       AD5449_CHANNEL(1, bits), \
+}
+
+static DECLARE_AD5449_CHANNELS(ad5429_channels, 8);
+static DECLARE_AD5449_CHANNELS(ad5439_channels, 10);
+static DECLARE_AD5449_CHANNELS(ad5449_channels, 12);
+
+static const struct ad5449_chip_info ad5449_chip_info[] = {
+       [ID_AD5426] = {
+               .channels = ad5429_channels,
+               .num_channels = 1,
+               .has_ctrl = false,
+       },
+       [ID_AD5429] = {
+               .channels = ad5429_channels,
+               .num_channels = 2,
+               .has_ctrl = true,
+       },
+       [ID_AD5432] = {
+               .channels = ad5439_channels,
+               .num_channels = 1,
+               .has_ctrl = false,
+       },
+       [ID_AD5439] = {
+               .channels = ad5439_channels,
+               .num_channels = 2,
+               .has_ctrl = true,
+       },
+       [ID_AD5443] = {
+               .channels = ad5449_channels,
+               .num_channels = 1,
+               .has_ctrl = false,
+       },
+       [ID_AD5449] = {
+               .channels = ad5449_channels,
+               .num_channels = 2,
+               .has_ctrl = true,
+       },
+};
+
+static const char *ad5449_vref_name(struct ad5449 *st, int n)
+{
+       if (st->chip_info->num_channels == 1)
+               return "VREF";
+
+       if (n == 0)
+               return "VREFA";
+       else
+               return "VREFB";
+}
+
+static int __devinit ad5449_spi_probe(struct spi_device *spi)
+{
+       struct ad5449_platform_data *pdata = spi->dev.platform_data;
+       const struct spi_device_id *id = spi_get_device_id(spi);
+       struct iio_dev *indio_dev;
+       struct ad5449 *st;
+       unsigned int i;
+       int ret;
+
+       indio_dev = iio_device_alloc(sizeof(*st));
+       if (indio_dev == NULL)
+               return -ENOMEM;
+
+       st = iio_priv(indio_dev);
+       spi_set_drvdata(spi, indio_dev);
+
+       st->chip_info = &ad5449_chip_info[id->driver_data];
+       st->spi = spi;
+
+       for (i = 0; i < st->chip_info->num_channels; ++i)
+               st->vref_reg[i].supply = ad5449_vref_name(st, i);
+
+       ret = regulator_bulk_get(&spi->dev, st->chip_info->num_channels,
+                               st->vref_reg);
+       if (ret)
+               goto error_free;
+
+       ret = regulator_bulk_enable(st->chip_info->num_channels, st->vref_reg);
+       if (ret)
+               goto error_free_reg;
+
+       indio_dev->dev.parent = &spi->dev;
+       indio_dev->name = id->name;
+       indio_dev->info = &ad5449_info;
+       indio_dev->modes = INDIO_DIRECT_MODE;
+       indio_dev->channels = st->chip_info->channels;
+       indio_dev->num_channels = st->chip_info->num_channels;
+
+       if (st->chip_info->has_ctrl) {
+               unsigned int ctrl = 0x00;
+               if (pdata) {
+                       if (pdata->hardware_clear_to_midscale)
+                               ctrl |= AD5449_CTRL_HCLR_TO_MIDSCALE;
+                       ctrl |= pdata->sdo_mode << AD5449_CTRL_SDO_OFFSET;
+                       st->has_sdo = pdata->sdo_mode != AD5449_SDO_DISABLED;
+               } else {
+                       st->has_sdo = true;
+               }
+               ad5449_write(indio_dev, AD5449_CMD_CTRL, ctrl);
+       }
+
+       ret = iio_device_register(indio_dev);
+       if (ret)
+               goto error_disable_reg;
+
+       return 0;
+
+error_disable_reg:
+       regulator_bulk_disable(st->chip_info->num_channels, st->vref_reg);
+error_free_reg:
+       regulator_bulk_free(st->chip_info->num_channels, st->vref_reg);
+error_free:
+       iio_device_free(indio_dev);
+
+       return ret;
+}
+
+static int __devexit ad5449_spi_remove(struct spi_device *spi)
+{
+       struct iio_dev *indio_dev = spi_get_drvdata(spi);
+       struct ad5449 *st = iio_priv(indio_dev);
+
+       iio_device_unregister(indio_dev);
+
+       regulator_bulk_disable(st->chip_info->num_channels, st->vref_reg);
+       regulator_bulk_free(st->chip_info->num_channels, st->vref_reg);
+
+       iio_device_free(indio_dev);
+
+       return 0;
+}
+
+static const struct spi_device_id ad5449_spi_ids[] = {
+       { "ad5415", ID_AD5449 },
+       { "ad5426", ID_AD5426 },
+       { "ad5429", ID_AD5429 },
+       { "ad5432", ID_AD5432 },
+       { "ad5439", ID_AD5439 },
+       { "ad5443", ID_AD5443 },
+       { "ad5449", ID_AD5449 },
+       {}
+};
+MODULE_DEVICE_TABLE(spi, ad5449_spi_ids);
+
+static struct spi_driver ad5449_spi_driver = {
+       .driver = {
+               .name = "ad5449",
+               .owner = THIS_MODULE,
+       },
+       .probe = ad5449_spi_probe,
+       .remove = __devexit_p(ad5449_spi_remove),
+       .id_table = ad5449_spi_ids,
+};
+module_spi_driver(ad5449_spi_driver);
+
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_DESCRIPTION("Analog Devices AD5449 and similar DACs");
+MODULE_LICENSE("GPL v2");
index 6948d75e1036cf9265f2bccd44e1beffcca7926a..bc92ff9309c2b6012c0cfd25ac36bb8f54898690 100644 (file)
@@ -188,7 +188,7 @@ static ssize_t ad5686_write_dac_powerdown(struct iio_dev *indio_dev,
        if (ret)
                return ret;
 
-       if (readin == true)
+       if (readin)
                st->pwr_down_mask |= (0x3 << (chan->channel * 2));
        else
                st->pwr_down_mask &= ~(0x3 << (chan->channel * 2));
index d4ad37455a678a15caf58dde7449ff82d323c510..722a83fd8d85a4b2bb8bd4fde7fc315627e43d5f 100644 (file)
@@ -371,12 +371,12 @@ ssize_t iio_buffer_write_length(struct device *dev,
                                const char *buf,
                                size_t len)
 {
-       int ret;
-       ulong val;
        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
        struct iio_buffer *buffer = indio_dev->buffer;
+       unsigned int val;
+       int ret;
 
-       ret = strict_strtoul(buf, 10, &val);
+       ret = kstrtouint(buf, 10, &val);
        if (ret)
                return ret;
 
index 6eb24dbc081ed2f158d9c46b4ccb5ee75ff20272..37650a72b31f11fc75d0afb6123233c724ce8270 100644 (file)
@@ -397,6 +397,11 @@ static ssize_t iio_read_channel_info(struct device *dev,
                val2 = do_div(tmp, 1000000000LL);
                val = tmp;
                return sprintf(buf, "%d.%09u\n", val, val2);
+       case IIO_VAL_FRACTIONAL_LOG2:
+               tmp = (s64)val * 1000000000LL >> val2;
+               val2 = do_div(tmp, 1000000000LL);
+               val = tmp;
+               return sprintf(buf, "%d.%09u\n", val, val2);
        default:
                return 0;
        }
index fa6543bf67312702d14793946b6b902334f35c9d..857e6306c5c335560b30dfda06148b39c275ea32 100644 (file)
@@ -239,13 +239,13 @@ static ssize_t iio_ev_value_store(struct device *dev,
 {
        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
        struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
-       unsigned long val;
+       int val;
        int ret;
 
        if (!indio_dev->info->write_event_value)
                return -EINVAL;
 
-       ret = strict_strtoul(buf, 10, &val);
+       ret = kstrtoint(buf, 10, &val);
        if (ret)
                return ret;
 
index f2b78d4fe45778d01f05a97eb1e3a9b1bc8164e4..b394621d362cb54da7b7e303499cb79bde339472 100644 (file)
@@ -78,7 +78,7 @@ int iio_map_array_unregister(struct iio_dev *indio_dev,
                                found_it = true;
                                break;
                        }
-               if (found_it == false) {
+               if (!found_it) {
                        ret = -ENODEV;
                        goto error_ret;
                }
@@ -314,6 +314,9 @@ static int iio_convert_raw_to_processed_unlocked(struct iio_channel *chan,
                *processed = div_s64(raw64 * (s64)scale_val * scale,
                                     scale_val2);
                break;
+       case IIO_VAL_FRACTIONAL_LOG2:
+               *processed = (raw64 * (s64)scale_val * scale) >> scale_val2;
+               break;
        default:
                return -EINVAL;
        }
index 57e07c61ace2e8147badfcd87e7f19fa211e4746..afd81790ab3c3e818c73b26fb6856e4f327c133a 100644 (file)
@@ -468,7 +468,7 @@ struct ib_mr *c4iw_register_phys_mem(struct ib_pd *pd,
        ret = alloc_pbl(mhp, npages);
        if (ret) {
                kfree(page_list);
-               goto err_pbl;
+               goto err;
        }
 
        ret = write_pbl(&mhp->rhp->rdev, page_list, mhp->attr.pbl_addr,
index d2fb38d43571d9f5ebba2dbc33e94ff5fc4cf737..2f215b93db6ba5a68b6d7e6fc38d21c91ff0cfa9 100644 (file)
@@ -107,7 +107,7 @@ static __be64 get_cached_alias_guid(struct mlx4_ib_dev *dev, int port, int index
 {
        if (index >= NUM_ALIAS_GUID_PER_PORT) {
                pr_err("%s: ERROR: asked for index:%d\n", __func__, index);
-               return  (__force __be64) ((u64) 0xFFFFFFFFFFFFFFFFUL);
+               return (__force __be64) -1;
        }
        return *(__be64 *)&dev->sriov.demux[port - 1].guid_cache[index];
 }
index 21a794152d15acea2a2e450258f4aaa915bce03a..0a903c129f0a19bfd0175de7aaea382dddec6d88 100644 (file)
@@ -409,38 +409,45 @@ int mlx4_ib_find_real_gid(struct ib_device *ibdev, u8 port, __be64 guid)
 }
 
 
-static int get_pkey_phys_indices(struct mlx4_ib_dev *ibdev, u8 port, u8 ph_pkey_ix,
-                                u8 *full_pk_ix, u8 *partial_pk_ix,
-                                int *is_full_member)
+static int find_slave_port_pkey_ix(struct mlx4_ib_dev *dev, int slave,
+                                  u8 port, u16 pkey, u16 *ix)
 {
-       u16 search_pkey;
-       int fm;
-       int err = 0;
-       u16 pk;
+       int i, ret;
+       u8 unassigned_pkey_ix, pkey_ix, partial_ix = 0xFF;
+       u16 slot_pkey;
 
-       err = ib_get_cached_pkey(&ibdev->ib_dev, port, ph_pkey_ix, &search_pkey);
-       if (err)
-               return err;
+       if (slave == mlx4_master_func_num(dev->dev))
+               return ib_find_cached_pkey(&dev->ib_dev, port, pkey, ix);
 
-       fm = (search_pkey & 0x8000) ? 1 : 0;
-       if (fm) {
-               *full_pk_ix = ph_pkey_ix;
-               search_pkey &= 0x7FFF;
-       } else {
-               *partial_pk_ix = ph_pkey_ix;
-               search_pkey |= 0x8000;
-       }
+       unassigned_pkey_ix = dev->dev->phys_caps.pkey_phys_table_len[port] - 1;
 
-       if (ib_find_exact_cached_pkey(&ibdev->ib_dev, port, search_pkey, &pk))
-               pk = 0xFFFF;
+       for (i = 0; i < dev->dev->caps.pkey_table_len[port]; i++) {
+               if (dev->pkeys.virt2phys_pkey[slave][port - 1][i] == unassigned_pkey_ix)
+                       continue;
 
-       if (fm)
-               *partial_pk_ix = (pk & 0xFF);
-       else
-               *full_pk_ix = (pk & 0xFF);
+               pkey_ix = dev->pkeys.virt2phys_pkey[slave][port - 1][i];
 
-       *is_full_member = fm;
-       return err;
+               ret = ib_get_cached_pkey(&dev->ib_dev, port, pkey_ix, &slot_pkey);
+               if (ret)
+                       continue;
+               if ((slot_pkey & 0x7FFF) == (pkey & 0x7FFF)) {
+                       if (slot_pkey & 0x8000) {
+                               *ix = (u16) pkey_ix;
+                               return 0;
+                       } else {
+                               /* take first partial pkey index found */
+                               if (partial_ix == 0xFF)
+                                       partial_ix = pkey_ix;
+                       }
+               }
+       }
+
+       if (partial_ix < 0xFF) {
+               *ix = (u16) partial_ix;
+               return 0;
+       }
+
+       return -EINVAL;
 }
 
 int mlx4_ib_send_to_slave(struct mlx4_ib_dev *dev, int slave, u8 port,
@@ -458,10 +465,8 @@ int mlx4_ib_send_to_slave(struct mlx4_ib_dev *dev, int slave, u8 port,
        unsigned tun_tx_ix = 0;
        int dqpn;
        int ret = 0;
-       int i;
-       int is_full_member = 0;
        u16 tun_pkey_ix;
-       u8 ph_pkey_ix, full_pk_ix = 0, partial_pk_ix = 0;
+       u16 cached_pkey;
 
        if (dest_qpt > IB_QPT_GSI)
                return -EINVAL;
@@ -481,27 +486,17 @@ int mlx4_ib_send_to_slave(struct mlx4_ib_dev *dev, int slave, u8 port,
        else
                tun_qp = &tun_ctx->qp[1];
 
-       /* compute pkey index for slave */
-       /* get physical pkey -- virtualized Dom0 pkey to phys*/
+       /* compute P_Key index to put in tunnel header for slave */
        if (dest_qpt) {
-               ph_pkey_ix =
-                       dev->pkeys.virt2phys_pkey[mlx4_master_func_num(dev->dev)][port - 1][wc->pkey_index];
-
-               /* now, translate this to the slave pkey index */
-               ret = get_pkey_phys_indices(dev, port, ph_pkey_ix, &full_pk_ix,
-                                           &partial_pk_ix, &is_full_member);
+               u16 pkey_ix;
+               ret = ib_get_cached_pkey(&dev->ib_dev, port, wc->pkey_index, &cached_pkey);
                if (ret)
                        return -EINVAL;
 
-               for (i = 0; i < dev->dev->caps.pkey_table_len[port]; i++) {
-                       if ((dev->pkeys.virt2phys_pkey[slave][port - 1][i] == full_pk_ix) ||
-                           (is_full_member &&
-                            (dev->pkeys.virt2phys_pkey[slave][port - 1][i] == partial_pk_ix)))
-                               break;
-               }
-               if (i == dev->dev->caps.pkey_table_len[port])
+               ret = find_slave_port_pkey_ix(dev, slave, port, cached_pkey, &pkey_ix);
+               if (ret)
                        return -EINVAL;
-               tun_pkey_ix = i;
+               tun_pkey_ix = pkey_ix;
        } else
                tun_pkey_ix = dev->pkeys.virt2phys_pkey[slave][port - 1][0];
 
index 3c3b54c3fdd93206e60b85c421bc313d952c9655..25b2cdff00f8e4bcd76044e8916b2aa257a7276e 100644 (file)
@@ -233,7 +233,8 @@ static int send_mad_to_slave(int slave, struct mlx4_ib_demux_ctx *ctx,
 
        ib_query_ah(dev->sm_ah[ctx->port - 1], &ah_attr);
 
-       wc.pkey_index = 0;
+       if (ib_find_cached_pkey(&dev->ib_dev, ctx->port, IB_DEFAULT_PKEY_FULL, &wc.pkey_index))
+               return -EINVAL;
        wc.sl = 0;
        wc.dlid_path_bits = 0;
        wc.port_num = ctx->port;
@@ -1074,10 +1075,6 @@ static void _mlx4_ib_mcg_port_cleanup(struct mlx4_ib_demux_ctx *ctx, int destroy
        unsigned long end;
        int count;
 
-       if (ctx->flushing)
-               return;
-
-       ctx->flushing = 1;
        for (i = 0; i < MAX_VFS; ++i)
                clean_vf_mcast(ctx, i);
 
@@ -1107,9 +1104,6 @@ static void _mlx4_ib_mcg_port_cleanup(struct mlx4_ib_demux_ctx *ctx, int destroy
                force_clean_group(group);
        }
        mutex_unlock(&ctx->mcg_table_lock);
-
-       if (!destroy_wq)
-               ctx->flushing = 0;
 }
 
 struct clean_work {
@@ -1123,6 +1117,7 @@ static void mcg_clean_task(struct work_struct *work)
        struct clean_work *cw = container_of(work, struct clean_work, work);
 
        _mlx4_ib_mcg_port_cleanup(cw->ctx, cw->destroy_wq);
+       cw->ctx->flushing = 0;
        kfree(cw);
 }
 
@@ -1130,13 +1125,20 @@ void mlx4_ib_mcg_port_cleanup(struct mlx4_ib_demux_ctx *ctx, int destroy_wq)
 {
        struct clean_work *work;
 
+       if (ctx->flushing)
+               return;
+
+       ctx->flushing = 1;
+
        if (destroy_wq) {
                _mlx4_ib_mcg_port_cleanup(ctx, destroy_wq);
+               ctx->flushing = 0;
                return;
        }
 
        work = kmalloc(sizeof *work, GFP_KERNEL);
        if (!work) {
+               ctx->flushing = 0;
                mcg_warn("failed allocating work for cleanup\n");
                return;
        }
index 6ae2ac47c9c806ecf5224e2eb02c49a704b40432..f0f8928b3c8a2902295ccfdf4803b43e00f3a0c9 100644 (file)
@@ -292,7 +292,6 @@ static int evdev_release(struct inode *inode, struct file *file)
        kfree(client);
 
        evdev_close_device(evdev);
-       put_device(&evdev->dev);
 
        return 0;
 }
@@ -331,7 +330,6 @@ static int evdev_open(struct inode *inode, struct file *file)
        file->private_data = client;
        nonseekable_open(inode, file);
 
-       get_device(&evdev->dev);
        return 0;
 
  err_free_client:
@@ -1001,6 +999,7 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
                goto err_free_evdev;
 
        cdev_init(&evdev->cdev, &evdev_fops);
+       evdev->cdev.kobj.parent = &evdev->dev.kobj;
        error = cdev_add(&evdev->cdev, evdev->dev.devt, 1);
        if (error)
                goto err_unregister_handle;
index b62b5891f3999573893c732297ecd0467a094147..f362883c94e37ce828d18938b7d25790135cf2d1 100644 (file)
@@ -243,7 +243,6 @@ static int joydev_release(struct inode *inode, struct file *file)
        kfree(client);
 
        joydev_close_device(joydev);
-       put_device(&joydev->dev);
 
        return 0;
 }
@@ -270,7 +269,6 @@ static int joydev_open(struct inode *inode, struct file *file)
        file->private_data = client;
        nonseekable_open(inode, file);
 
-       get_device(&joydev->dev);
        return 0;
 
  err_free_client:
@@ -858,6 +856,7 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
                goto err_free_joydev;
 
        cdev_init(&joydev->cdev, &joydev_fops);
+       joydev->cdev.kobj.parent = &joydev->dev.kobj;
        error = cdev_add(&joydev->cdev, joydev->dev.devt, 1);
        if (error)
                goto err_unregister_handle;
index c96653b58867deb406a13913774a7e35c074dec7..9d869e202b81862b05b4448b1cf15ad21da71415 100644 (file)
@@ -85,7 +85,10 @@ static int as5011_i2c_write(struct i2c_client *client,
 {
        uint8_t data[2] = { aregaddr, avalue };
        struct i2c_msg msg = {
-               client->addr, I2C_M_IGNORE_NAK, 2, (uint8_t *)data
+               .addr = client->addr,
+               .flags = I2C_M_IGNORE_NAK,
+               .len = 2,
+               .buf = (uint8_t *)data
        };
        int error;
 
@@ -98,8 +101,18 @@ static int as5011_i2c_read(struct i2c_client *client,
 {
        uint8_t data[2] = { aregaddr };
        struct i2c_msg msg_set[2] = {
-               { client->addr, I2C_M_REV_DIR_ADDR, 1, (uint8_t *)data },
-               { client->addr, I2C_M_RD | I2C_M_NOSTART, 1, (uint8_t *)data }
+               {
+                       .addr = client->addr,
+                       .flags = I2C_M_REV_DIR_ADDR,
+                       .len = 1,
+                       .buf = (uint8_t *)data
+               },
+               {
+                       .addr = client->addr,
+                       .flags = I2C_M_RD | I2C_M_NOSTART,
+                       .len = 1,
+                       .buf = (uint8_t *)data
+               }
        };
        int error;
 
index 6790a812a1db7ecf66b2c990687e162211624537..fa8b3900d98176f52c4eba51e047ef07972dd800 100644 (file)
@@ -76,7 +76,8 @@ static int __devinit wm831x_on_probe(struct platform_device *pdev)
        int irq = wm831x_irq(wm831x, platform_get_irq(pdev, 0));
        int ret;
 
-       wm831x_on = kzalloc(sizeof(struct wm831x_on), GFP_KERNEL);
+       wm831x_on = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_on),
+                                GFP_KERNEL);
        if (!wm831x_on) {
                dev_err(&pdev->dev, "Can't allocate data\n");
                return -ENOMEM;
@@ -120,7 +121,6 @@ err_irq:
 err_input_dev:
        input_free_device(wm831x_on->dev);
 err:
-       kfree(wm831x_on);
        return ret;
 }
 
@@ -132,7 +132,6 @@ static int __devexit wm831x_on_remove(struct platform_device *pdev)
        free_irq(irq, wm831x_on);
        cancel_delayed_work_sync(&wm831x_on->work);
        input_unregister_device(wm831x_on->dev);
-       kfree(wm831x_on);
 
        return 0;
 }
index a1b4c37956b2ef3af055e5c66ccd7753225cabeb..8f02e3d0e712789dc2cccbb0cb52fe40fc0620db 100644 (file)
@@ -523,7 +523,6 @@ static int mousedev_release(struct inode *inode, struct file *file)
        kfree(client);
 
        mousedev_close_device(mousedev);
-       put_device(&mousedev->dev);
 
        return 0;
 }
@@ -558,7 +557,6 @@ static int mousedev_open(struct inode *inode, struct file *file)
        file->private_data = client;
        nonseekable_open(inode, file);
 
-       get_device(&mousedev->dev);
        return 0;
 
  err_free_client:
@@ -892,6 +890,7 @@ static struct mousedev *mousedev_create(struct input_dev *dev,
        }
 
        cdev_init(&mousedev->cdev, &mousedev_fops);
+       mousedev->cdev.kobj.parent = &mousedev->dev.kobj;
        error = cdev_add(&mousedev->cdev, mousedev->dev.devt, 1);
        if (error)
                goto err_unregister_handle;
index 55f2c2293ec6a7aee2c1a7573af2c0d43c1f9c28..4a4e182c33e7a0c540a52a566b4eeabe038a5e4a 100644 (file)
@@ -234,4 +234,13 @@ config SERIO_PS2MULT
          To compile this driver as a module, choose M here: the
          module will be called ps2mult.
 
+config SERIO_ARC_PS2
+       tristate "ARC PS/2 support"
+       help
+         Say Y here if you have an ARC FPGA platform with a PS/2
+         controller in it.
+
+         To compile this driver as a module, choose M here; the module
+         will be called arc_ps2.
+
 endif
index dbbe37616c92ece327bada8c39cde862aff6e196..4b0c8f84f1c19d3d9210d6b66dc498ad35dc5ee4 100644 (file)
@@ -25,3 +25,4 @@ obj-$(CONFIG_SERIO_RAW)               += serio_raw.o
 obj-$(CONFIG_SERIO_AMS_DELTA)  += ams_delta_serio.o
 obj-$(CONFIG_SERIO_XILINX_XPS_PS2)     += xilinx_ps2.o
 obj-$(CONFIG_SERIO_ALTERA_PS2) += altera_ps2.o
+obj-$(CONFIG_SERIO_ARC_PS2)    += arc_ps2.o
diff --git a/drivers/input/serio/arc_ps2.c b/drivers/input/serio/arc_ps2.c
new file mode 100644 (file)
index 0000000..f8c026a
--- /dev/null
@@ -0,0 +1,279 @@
+/*
+ * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Driver is originally developed by Pavel Sokolov <psokolov@synopsys.com>
+ */
+
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/input.h>
+#include <linux/serio.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+
+#define ARC_PS2_PORTS                   2
+
+#define ARC_ARC_PS2_ID                  0x0001f609
+
+#define STAT_TIMEOUT                    128
+
+#define PS2_STAT_RX_FRM_ERR             (1)
+#define PS2_STAT_RX_BUF_OVER            (1 << 1)
+#define PS2_STAT_RX_INT_EN              (1 << 2)
+#define PS2_STAT_RX_VAL                 (1 << 3)
+#define PS2_STAT_TX_ISNOT_FUL           (1 << 4)
+#define PS2_STAT_TX_INT_EN              (1 << 5)
+
+struct arc_ps2_port {
+       void __iomem *data_addr;
+       void __iomem *status_addr;
+       struct serio *io;
+};
+
+struct arc_ps2_data {
+       struct arc_ps2_port port[ARC_PS2_PORTS];
+       struct resource *iomem_res;
+       int irq;
+       void __iomem *addr;
+       unsigned int frame_error;
+       unsigned int buf_overflow;
+       unsigned int total_int;
+};
+
+static void arc_ps2_check_rx(struct arc_ps2_data *arc_ps2,
+                            struct arc_ps2_port *port)
+{
+       unsigned int timeout = 1000;
+       unsigned int flag, status;
+       unsigned char data;
+
+       do {
+               status = ioread32(port->status_addr);
+               if (!(status & PS2_STAT_RX_VAL))
+                       return;
+
+               data = ioread32(port->data_addr) & 0xff;
+
+               flag = 0;
+               arc_ps2->total_int++;
+               if (status & PS2_STAT_RX_FRM_ERR) {
+                       arc_ps2->frame_error++;
+                       flag |= SERIO_PARITY;
+               } else if (status & PS2_STAT_RX_BUF_OVER) {
+                       arc_ps2->buf_overflow++;
+                       flag |= SERIO_FRAME;
+               }
+
+               serio_interrupt(port->io, data, flag);
+       } while (--timeout);
+
+       dev_err(&port->io->dev, "PS/2 hardware stuck\n");
+}
+
+static irqreturn_t arc_ps2_interrupt(int irq, void *dev)
+{
+       struct arc_ps2_data *arc_ps2 = dev;
+       int i;
+
+       for (i = 0; i < ARC_PS2_PORTS; i++)
+               arc_ps2_check_rx(arc_ps2, &arc_ps2->port[i]);
+
+       return IRQ_HANDLED;
+}
+
+static int arc_ps2_write(struct serio *io, unsigned char val)
+{
+       unsigned status;
+       struct arc_ps2_port *port = io->port_data;
+       int timeout = STAT_TIMEOUT;
+
+       do {
+               status = ioread32(port->status_addr);
+               cpu_relax();
+
+               if (status & PS2_STAT_TX_ISNOT_FUL) {
+                       iowrite32(val & 0xff, port->data_addr);
+                       return 0;
+               }
+
+       } while (--timeout);
+
+       dev_err(&io->dev, "write timeout\n");
+       return -ETIMEDOUT;
+}
+
+static int arc_ps2_open(struct serio *io)
+{
+       struct arc_ps2_port *port = io->port_data;
+
+       iowrite32(PS2_STAT_RX_INT_EN, port->status_addr);
+
+       return 0;
+}
+
+static void arc_ps2_close(struct serio *io)
+{
+       struct arc_ps2_port *port = io->port_data;
+
+       iowrite32(ioread32(port->status_addr) & ~PS2_STAT_RX_INT_EN,
+                 port->status_addr);
+}
+
+static int __devinit arc_ps2_create_port(struct platform_device *pdev,
+                                        struct arc_ps2_data *arc_ps2,
+                                        int index)
+{
+       struct arc_ps2_port *port = &arc_ps2->port[index];
+       struct serio *io;
+
+       io = kzalloc(sizeof(struct serio), GFP_KERNEL);
+       if (!io)
+               return -ENOMEM;
+
+       io->id.type = SERIO_8042;
+       io->write = arc_ps2_write;
+       io->open = arc_ps2_open;
+       io->close = arc_ps2_close;
+       snprintf(io->name, sizeof(io->name), "ARC PS/2 port%d", index);
+       snprintf(io->phys, sizeof(io->phys), "arc/serio%d", index);
+       io->port_data = port;
+
+       port->io = io;
+
+       port->data_addr = arc_ps2->addr + 4 + index * 4;
+       port->status_addr = arc_ps2->addr + 4 + ARC_PS2_PORTS * 4 + index * 4;
+
+       dev_dbg(&pdev->dev, "port%d is allocated (data = 0x%p, status = 0x%p)\n",
+               index, port->data_addr, port->status_addr);
+
+       serio_register_port(port->io);
+       return 0;
+}
+
+static int __devinit arc_ps2_probe(struct platform_device *pdev)
+{
+       struct arc_ps2_data *arc_ps2;
+       int error, id, i;
+
+       arc_ps2 = kzalloc(sizeof(struct arc_ps2_data), GFP_KERNEL);
+       if (!arc_ps2) {
+               dev_err(&pdev->dev, "out of memory\n");
+               return -ENOMEM;
+       }
+
+       arc_ps2->iomem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!arc_ps2->iomem_res) {
+               dev_err(&pdev->dev, "no IO memory defined\n");
+               error = -EINVAL;
+               goto err_free_mem;
+       }
+
+       arc_ps2->irq = platform_get_irq_byname(pdev, "arc_ps2_irq");
+       if (arc_ps2->irq < 0) {
+               dev_err(&pdev->dev, "no IRQ defined\n");
+               error = -EINVAL;
+               goto err_free_mem;
+       }
+
+       if (!request_mem_region(arc_ps2->iomem_res->start,
+           resource_size(arc_ps2->iomem_res), pdev->name)) {
+               dev_err(&pdev->dev, "memory region allocation failed for %pR\n",
+                       arc_ps2->iomem_res);
+
+               error = -EBUSY;
+               goto err_free_mem;
+       }
+
+       arc_ps2->addr = ioremap_nocache(arc_ps2->iomem_res->start,
+                                       resource_size(arc_ps2->iomem_res));
+       if (!arc_ps2->addr) {
+               dev_err(&pdev->dev, "memory mapping failed\n");
+               error = -ENOMEM;
+               goto err_release_region;
+       }
+
+       dev_info(&pdev->dev, "irq = %d, address = 0x%p, ports = %i\n",
+                arc_ps2->irq, arc_ps2->addr, ARC_PS2_PORTS);
+
+       id = ioread32(arc_ps2->addr);
+       if (id != ARC_ARC_PS2_ID) {
+               dev_err(&pdev->dev, "device id does not match\n");
+               error = -ENXIO;
+               goto err_unmap;
+       }
+
+       for (i = 0; i < ARC_PS2_PORTS; i++) {
+               error = arc_ps2_create_port(pdev, arc_ps2, i);
+               if (error)
+                       goto err_unregister_ports;
+       }
+
+       error = request_irq(arc_ps2->irq, arc_ps2_interrupt, 0,
+                           "arc_ps2", arc_ps2);
+       if (error) {
+               dev_err(&pdev->dev, "Could not allocate IRQ\n");
+               goto err_unregister_ports;
+       }
+
+       platform_set_drvdata(pdev, arc_ps2);
+
+       return 0;
+
+err_unregister_ports:
+       for (i = 0; i < ARC_PS2_PORTS; i++) {
+               if (arc_ps2->port[i].io)
+                       serio_unregister_port(arc_ps2->port[i].io);
+       }
+err_unmap:
+       iounmap(arc_ps2->addr);
+err_release_region:
+       release_mem_region(arc_ps2->iomem_res->start,
+                          resource_size(arc_ps2->iomem_res));
+err_free_mem:
+       kfree(arc_ps2);
+       return error;
+}
+
+static int __devexit arc_ps2_remove(struct platform_device *pdev)
+{
+       struct arc_ps2_data *arc_ps2 = platform_get_drvdata(pdev);
+       int i;
+
+       for (i = 0; i < ARC_PS2_PORTS; i++)
+               serio_unregister_port(arc_ps2->port[i].io);
+
+       free_irq(arc_ps2->irq, arc_ps2);
+       iounmap(arc_ps2->addr);
+       release_mem_region(arc_ps2->iomem_res->start,
+                          resource_size(arc_ps2->iomem_res));
+
+       dev_dbg(&pdev->dev, "interrupt count = %i\n", arc_ps2->total_int);
+       dev_dbg(&pdev->dev, "frame error count = %i\n", arc_ps2->frame_error);
+       dev_dbg(&pdev->dev, "buffer overflow count = %i\n",
+               arc_ps2->buf_overflow);
+
+       kfree(arc_ps2);
+
+       return 0;
+}
+
+static struct platform_driver arc_ps2_driver = {
+       .driver = {
+               .name   = "arc_ps2",
+               .owner  = THIS_MODULE,
+       },
+       .probe  = arc_ps2_probe,
+       .remove = __devexit_p(arc_ps2_remove),
+};
+
+module_platform_driver(arc_ps2_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Pavel Sokolov <psokolov@synopsys.com>");
+MODULE_DESCRIPTION("ARC PS/2 Driver");
index 5d48bb66aa738dd85e72f2d47f4b3ad3e88dd57e..a5eed2ade53de3a4e1d06776288ec17baba52530 100644 (file)
@@ -76,7 +76,7 @@ static inline int i8042_platform_init(void)
        if (check_legacy_ioport(I8042_DATA_REG))
                return -ENODEV;
 #endif
-#if !defined(__sh__) && !defined(__alpha__) && !defined(__mips__)
+#if !defined(__sh__) && !defined(__alpha__)
        if (!request_region(I8042_DATA_REG, 16, "i8042"))
                return -EBUSY;
 #endif
index 464f1bf4b61dcbf62af90196ba28608b6896e6f8..ad6a6640f385da6fcf4f0575701bece678aa41b2 100644 (file)
@@ -99,9 +99,18 @@ static int cy8ctmg110_read_regs(struct cy8ctmg110 *tsc,
        int ret;
        struct i2c_msg msg[2] = {
                /* first write slave position to i2c devices */
-               { client->addr, 0, 1, &cmd },
+               {
+                       .addr = client->addr,
+                       .len = 1,
+                       .buf = &cmd
+               },
                /* Second read data from position */
-               { client->addr, I2C_M_RD, len, data }
+               {
+                       .addr = client->addr,
+                       .flags = I2C_M_RD,
+                       .len = len,
+                       .buf = data
+               }
        };
 
        ret = i2c_transfer(client->adapter, msg, 2);
index 099d144ab7c96a92bba2814869a9e1ab325718cf..d9c6007e445f0196684ee16e70907145623bebe5 100644 (file)
@@ -491,14 +491,6 @@ static int edt_ft5x06_debugfs_mode_set(void *data, u64 mode)
 DEFINE_SIMPLE_ATTRIBUTE(debugfs_mode_fops, edt_ft5x06_debugfs_mode_get,
                        edt_ft5x06_debugfs_mode_set, "%llu\n");
 
-static int edt_ft5x06_debugfs_raw_data_open(struct inode *inode,
-                                           struct file *file)
-{
-       file->private_data = inode->i_private;
-
-       return 0;
-}
-
 static ssize_t edt_ft5x06_debugfs_raw_data_read(struct file *file,
                                char __user *buf, size_t count, loff_t *off)
 {
@@ -579,7 +571,7 @@ out:
 
 
 static const struct file_operations debugfs_raw_data_fops = {
-       .open = edt_ft5x06_debugfs_raw_data_open,
+       .open = simple_open,
        .read = edt_ft5x06_debugfs_raw_data_read,
 };
 
index 560cf09d1c5a893215f9aca033a6ea4327dfed7c..3426d2e11a36dd668a4b7600048ed9ed12f8b0d7 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/delay.h>
+#include <linux/of.h>
 #include <linux/i2c.h>
 #include <linux/i2c/mms114.h>
 #include <linux/input/mt.h>
@@ -360,14 +361,63 @@ static void mms114_input_close(struct input_dev *dev)
        mms114_stop(data);
 }
 
+#ifdef CONFIG_OF
+static struct mms114_platform_data * __devinit mms114_parse_dt(struct device *dev)
+{
+       struct mms114_platform_data *pdata;
+       struct device_node *np = dev->of_node;
+
+       if (!np)
+               return NULL;
+
+       pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+       if (!pdata) {
+               dev_err(dev, "failed to allocate platform data\n");
+               return NULL;
+       }
+
+       if (of_property_read_u32(np, "x-size", &pdata->x_size)) {
+               dev_err(dev, "failed to get x-size property\n");
+               return NULL;
+       };
+
+       if (of_property_read_u32(np, "y-size", &pdata->y_size)) {
+               dev_err(dev, "failed to get y-size property\n");
+               return NULL;
+       };
+
+       of_property_read_u32(np, "contact-threshold",
+                               &pdata->contact_threshold);
+       of_property_read_u32(np, "moving-threshold",
+                               &pdata->moving_threshold);
+
+       if (of_find_property(np, "x-invert", NULL))
+               pdata->x_invert = true;
+       if (of_find_property(np, "y-invert", NULL))
+               pdata->y_invert = true;
+
+       return pdata;
+}
+#else
+static inline struct mms114_platform_data *mms114_parse_dt(struct device *dev)
+{
+       return NULL;
+}
+#endif
+
 static int __devinit mms114_probe(struct i2c_client *client,
                                  const struct i2c_device_id *id)
 {
+       const struct mms114_platform_data *pdata;
        struct mms114_data *data;
        struct input_dev *input_dev;
        int error;
 
-       if (!client->dev.platform_data) {
+       pdata = dev_get_platdata(&client->dev);
+       if (!pdata)
+               pdata = mms114_parse_dt(&client->dev);
+
+       if (!pdata) {
                dev_err(&client->dev, "Need platform data\n");
                return -EINVAL;
        }
@@ -389,7 +439,7 @@ static int __devinit mms114_probe(struct i2c_client *client,
 
        data->client = client;
        data->input_dev = input_dev;
-       data->pdata = client->dev.platform_data;
+       data->pdata = pdata;
 
        input_dev->name = "MELPAS MMS114 Touchscreen";
        input_dev->id.bustype = BUS_I2C;
@@ -525,11 +575,19 @@ static const struct i2c_device_id mms114_id[] = {
 };
 MODULE_DEVICE_TABLE(i2c, mms114_id);
 
+#ifdef CONFIG_OF
+static struct of_device_id __devinitdata mms114_dt_match[] = {
+       { .compatible = "melfas,mms114" },
+       { }
+};
+#endif
+
 static struct i2c_driver mms114_driver = {
        .driver = {
                .name   = "mms114",
                .owner  = THIS_MODULE,
                .pm     = &mms114_pm_ops,
+               .of_match_table = of_match_ptr(mms114_dt_match),
        },
        .probe          = mms114_probe,
        .remove         = __devexit_p(mms114_remove),
index 52abb98a8ae5cadcaa38091daf74ca39e65f354e..c7eee56d0087e395f37e27b3f59a4e9c940bf56f 100644 (file)
@@ -245,7 +245,8 @@ static __devinit int wm831x_ts_probe(struct platform_device *pdev)
        if (core_pdata)
                pdata = core_pdata->touch;
 
-       wm831x_ts = kzalloc(sizeof(struct wm831x_ts), GFP_KERNEL);
+       wm831x_ts = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_ts),
+                                GFP_KERNEL);
        input_dev = input_allocate_device();
        if (!wm831x_ts || !input_dev) {
                error = -ENOMEM;
@@ -376,7 +377,6 @@ err_data_irq:
        free_irq(wm831x_ts->data_irq, wm831x_ts);
 err_alloc:
        input_free_device(input_dev);
-       kfree(wm831x_ts);
 
        return error;
 }
@@ -388,9 +388,7 @@ static __devexit int wm831x_ts_remove(struct platform_device *pdev)
        free_irq(wm831x_ts->pd_irq, wm831x_ts);
        free_irq(wm831x_ts->data_irq, wm831x_ts);
        input_unregister_device(wm831x_ts->input_dev);
-       kfree(wm831x_ts);
 
-       platform_set_drvdata(pdev, NULL);
        return 0;
 }
 
index 55074cba20eba9012d6a310acef62b965728bcea..cb63cc5d94d71d70802a0bbea55575b5b3da5f34 100644 (file)
@@ -140,6 +140,9 @@ static void free_dev_data(struct iommu_dev_data *dev_data)
        list_del(&dev_data->dev_data_list);
        spin_unlock_irqrestore(&dev_data_list_lock, flags);
 
+       if (dev_data->group)
+               iommu_group_put(dev_data->group);
+
        kfree(dev_data);
 }
 
@@ -274,41 +277,23 @@ static void swap_pci_ref(struct pci_dev **from, struct pci_dev *to)
        *from = to;
 }
 
-#define REQ_ACS_FLAGS  (PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF)
-
-static int iommu_init_device(struct device *dev)
+static struct pci_bus *find_hosted_bus(struct pci_bus *bus)
 {
-       struct pci_dev *dma_pdev = NULL, *pdev = to_pci_dev(dev);
-       struct iommu_dev_data *dev_data;
-       struct iommu_group *group;
-       u16 alias;
-       int ret;
-
-       if (dev->archdata.iommu)
-               return 0;
-
-       dev_data = find_dev_data(get_device_id(dev));
-       if (!dev_data)
-               return -ENOMEM;
-
-       alias = amd_iommu_alias_table[dev_data->devid];
-       if (alias != dev_data->devid) {
-               struct iommu_dev_data *alias_data;
+       while (!bus->self) {
+               if (!pci_is_root_bus(bus))
+                       bus = bus->parent;
+               else
+                       return ERR_PTR(-ENODEV);
+       }
 
-               alias_data = find_dev_data(alias);
-               if (alias_data == NULL) {
-                       pr_err("AMD-Vi: Warning: Unhandled device %s\n",
-                                       dev_name(dev));
-                       free_dev_data(dev_data);
-                       return -ENOTSUPP;
-               }
-               dev_data->alias_data = alias_data;
+       return bus;
+}
 
-               dma_pdev = pci_get_bus_and_slot(alias >> 8, alias & 0xff);
-       }
+#define REQ_ACS_FLAGS  (PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF)
 
-       if (dma_pdev == NULL)
-               dma_pdev = pci_dev_get(pdev);
+static struct pci_dev *get_isolation_root(struct pci_dev *pdev)
+{
+       struct pci_dev *dma_pdev = pdev;
 
        /* Account for quirked devices */
        swap_pci_ref(&dma_pdev, pci_get_dma_source(dma_pdev));
@@ -330,14 +315,9 @@ static int iommu_init_device(struct device *dev)
         * Finding the next device may require skipping virtual buses.
         */
        while (!pci_is_root_bus(dma_pdev->bus)) {
-               struct pci_bus *bus = dma_pdev->bus;
-
-               while (!bus->self) {
-                       if (!pci_is_root_bus(bus))
-                               bus = bus->parent;
-                       else
-                               goto root_bus;
-               }
+               struct pci_bus *bus = find_hosted_bus(dma_pdev->bus);
+               if (IS_ERR(bus))
+                       break;
 
                if (pci_acs_path_enabled(bus->self, NULL, REQ_ACS_FLAGS))
                        break;
@@ -345,19 +325,137 @@ static int iommu_init_device(struct device *dev)
                swap_pci_ref(&dma_pdev, pci_dev_get(bus->self));
        }
 
-root_bus:
-       group = iommu_group_get(&dma_pdev->dev);
-       pci_dev_put(dma_pdev);
+       return dma_pdev;
+}
+
+static int use_pdev_iommu_group(struct pci_dev *pdev, struct device *dev)
+{
+       struct iommu_group *group = iommu_group_get(&pdev->dev);
+       int ret;
+
        if (!group) {
                group = iommu_group_alloc();
                if (IS_ERR(group))
                        return PTR_ERR(group);
+
+               WARN_ON(&pdev->dev != dev);
        }
 
        ret = iommu_group_add_device(group, dev);
-
        iommu_group_put(group);
+       return ret;
+}
+
+static int use_dev_data_iommu_group(struct iommu_dev_data *dev_data,
+                                   struct device *dev)
+{
+       if (!dev_data->group) {
+               struct iommu_group *group = iommu_group_alloc();
+               if (IS_ERR(group))
+                       return PTR_ERR(group);
+
+               dev_data->group = group;
+       }
+
+       return iommu_group_add_device(dev_data->group, dev);
+}
+
+static int init_iommu_group(struct device *dev)
+{
+       struct iommu_dev_data *dev_data;
+       struct iommu_group *group;
+       struct pci_dev *dma_pdev;
+       int ret;
+
+       group = iommu_group_get(dev);
+       if (group) {
+               iommu_group_put(group);
+               return 0;
+       }
+
+       dev_data = find_dev_data(get_device_id(dev));
+       if (!dev_data)
+               return -ENOMEM;
+
+       if (dev_data->alias_data) {
+               u16 alias;
+               struct pci_bus *bus;
+
+               if (dev_data->alias_data->group)
+                       goto use_group;
+
+               /*
+                * If the alias device exists, it's effectively just a first
+                * level quirk for finding the DMA source.
+                */
+               alias = amd_iommu_alias_table[dev_data->devid];
+               dma_pdev = pci_get_bus_and_slot(alias >> 8, alias & 0xff);
+               if (dma_pdev) {
+                       dma_pdev = get_isolation_root(dma_pdev);
+                       goto use_pdev;
+               }
+
+               /*
+                * If the alias is virtual, try to find a parent device
+                * and test whether the IOMMU group is actualy rooted above
+                * the alias.  Be careful to also test the parent device if
+                * we think the alias is the root of the group.
+                */
+               bus = pci_find_bus(0, alias >> 8);
+               if (!bus)
+                       goto use_group;
+
+               bus = find_hosted_bus(bus);
+               if (IS_ERR(bus) || !bus->self)
+                       goto use_group;
+
+               dma_pdev = get_isolation_root(pci_dev_get(bus->self));
+               if (dma_pdev != bus->self || (dma_pdev->multifunction &&
+                   !pci_acs_enabled(dma_pdev, REQ_ACS_FLAGS)))
+                       goto use_pdev;
+
+               pci_dev_put(dma_pdev);
+               goto use_group;
+       }
+
+       dma_pdev = get_isolation_root(pci_dev_get(to_pci_dev(dev)));
+use_pdev:
+       ret = use_pdev_iommu_group(dma_pdev, dev);
+       pci_dev_put(dma_pdev);
+       return ret;
+use_group:
+       return use_dev_data_iommu_group(dev_data->alias_data, dev);
+}
+
+static int iommu_init_device(struct device *dev)
+{
+       struct pci_dev *pdev = to_pci_dev(dev);
+       struct iommu_dev_data *dev_data;
+       u16 alias;
+       int ret;
+
+       if (dev->archdata.iommu)
+               return 0;
+
+       dev_data = find_dev_data(get_device_id(dev));
+       if (!dev_data)
+               return -ENOMEM;
+
+       alias = amd_iommu_alias_table[dev_data->devid];
+       if (alias != dev_data->devid) {
+               struct iommu_dev_data *alias_data;
+
+               alias_data = find_dev_data(alias);
+               if (alias_data == NULL) {
+                       pr_err("AMD-Vi: Warning: Unhandled device %s\n",
+                                       dev_name(dev));
+                       free_dev_data(dev_data);
+                       return -ENOTSUPP;
+               }
+               dev_data->alias_data = alias_data;
+       }
 
+       ret = init_iommu_group(dev);
        if (ret)
                return ret;
 
index 18b0d99bd4d6686b3727f83896769d0a116dcf1f..81837b0710a9ba0240b1eba3c1b3f8b51d997e2f 100644 (file)
@@ -1599,21 +1599,46 @@ static void __init free_on_init_error(void)
 #endif
 }
 
+/* SB IOAPIC is always on this device in AMD systems */
+#define IOAPIC_SB_DEVID                ((0x00 << 8) | PCI_DEVFN(0x14, 0))
+
 static bool __init check_ioapic_information(void)
 {
+       bool ret, has_sb_ioapic;
        int idx;
 
-       for (idx = 0; idx < nr_ioapics; idx++) {
-               int id = mpc_ioapic_id(idx);
+       has_sb_ioapic = false;
+       ret           = false;
 
-               if (get_ioapic_devid(id) < 0) {
-                       pr_err(FW_BUG "AMD-Vi: IO-APIC[%d] not in IVRS table\n", id);
-                       pr_err("AMD-Vi: Disabling interrupt remapping due to BIOS Bug\n");
-                       return false;
+       for (idx = 0; idx < nr_ioapics; idx++) {
+               int devid, id = mpc_ioapic_id(idx);
+
+               devid = get_ioapic_devid(id);
+               if (devid < 0) {
+                       pr_err(FW_BUG "AMD-Vi: IOAPIC[%d] not in IVRS table\n", id);
+                       ret = false;
+               } else if (devid == IOAPIC_SB_DEVID) {
+                       has_sb_ioapic = true;
+                       ret           = true;
                }
        }
 
-       return true;
+       if (!has_sb_ioapic) {
+               /*
+                * We expect the SB IOAPIC to be listed in the IVRS
+                * table. The system timer is connected to the SB IOAPIC
+                * and if we don't have it in the list the system will
+                * panic at boot time.  This situation usually happens
+                * when the BIOS is buggy and provides us the wrong
+                * device id for the IOAPIC in the system.
+                */
+               pr_err(FW_BUG "AMD-Vi: No southbridge IOAPIC found in IVRS table\n");
+       }
+
+       if (!ret)
+               pr_err("AMD-Vi: Disabling interrupt remapping due to BIOS Bug(s)\n");
+
+       return ret;
 }
 
 static void __init free_dma_resources(void)
index c9aa3d079ff0377c376012bb5130b62e6bcefb8e..e38ab438bb342e241c1b5e545a0b01a4e4ea5017 100644 (file)
@@ -426,6 +426,7 @@ struct iommu_dev_data {
        struct iommu_dev_data *alias_data;/* The alias dev_data */
        struct protection_domain *domain; /* Domain the device is bound to */
        atomic_t bind;                    /* Domain attach reference count */
+       struct iommu_group *group;        /* IOMMU group for virtual aliases */
        u16 devid;                        /* PCI Device ID */
        bool iommu_v2;                    /* Device can make use of IOMMUv2 */
        bool passthrough;                 /* Default for device is pt_domain */
index 0b4d62e0c64573cea96dc38f237436a036aa74cf..41678639b7e3fbd21b5131e4d6ddce89d5abbe61 100644 (file)
 #include <linux/of_iommu.h>
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
+#include <linux/tegra-ahb.h>
 
 #include <asm/page.h>
 #include <asm/cacheflush.h>
 
-#include <mach/iomap.h>
-#include <mach/tegra-ahb.h>
-
 enum smmu_hwgrp {
        HWGRP_AFI,
        HWGRP_AVPC,
@@ -200,7 +198,7 @@ enum {
 
 #define SMMU_ADDR_TO_PFN(addr) ((addr) >> 12)
 #define SMMU_ADDR_TO_PDN(addr) ((addr) >> 22)
-#define SMMU_PDN_TO_ADDR(addr) ((pdn) << 22)
+#define SMMU_PDN_TO_ADDR(pdn)  ((pdn) << 22)
 
 #define _READABLE      (1 << SMMU_PTB_DATA_ASID_READABLE_SHIFT)
 #define _WRITABLE      (1 << SMMU_PTB_DATA_ASID_WRITABLE_SHIFT)
index b5fdcb78a75b8620e61288c5717f450b2c588592..a5ebc0083d87ad02e03f23ed8be7e66267c5d97e 100644 (file)
@@ -225,7 +225,7 @@ int run_guest(struct lg_cpu *cpu, unsigned long __user *user)
                         * eventfd (ie. the appropriate virtqueue thread)?
                         */
                        if (!send_notify_to_eventfd(cpu)) {
-                               /* OK, we tell the main Laucher. */
+                               /* OK, we tell the main Launcher. */
                                if (put_user(cpu->pending_notify, user))
                                        return -EFAULT;
                                return sizeof(cpu->pending_notify);
index fd61f98ee1f68af3085297afc0b1c46dc0899e2f..cec5f9b3a27817c7d5845b7ce02a69579b6c8a68 100644 (file)
@@ -1195,11 +1195,9 @@ static int mirror_map(struct dm_target *ti, struct bio *bio,
                return -EIO;
 
        read_record = mempool_alloc(ms->read_record_pool, GFP_NOIO);
-       if (likely(read_record)) {
-               dm_bio_record(&read_record->details, bio);
-               map_context->ptr = read_record;
-               read_record->m = m;
-       }
+       dm_bio_record(&read_record->details, bio);
+       map_context->ptr = read_record;
+       read_record->m = m;
 
        map_bio(m, bio);
 
@@ -1259,7 +1257,7 @@ static int mirror_end_io(struct dm_target *ti, struct bio *bio,
                        mempool_free(read_record, ms->read_record_pool);
                        map_context->ptr = NULL;
                        queue_bio(ms, bio, rw);
-                       return 1;
+                       return DM_ENDIO_INCOMPLETE;
                }
                DMERR("All replicated volumes dead, failing I/O");
        }
index a143921feaf6480119f77d4f8600aefc98c7b583..223e7ebf24f7e7f4198a49bba48615885c719e20 100644 (file)
@@ -198,14 +198,13 @@ static struct dm_snap_tracked_chunk *track_chunk(struct dm_snapshot *s,
 {
        struct dm_snap_tracked_chunk *c = mempool_alloc(s->tracked_chunk_pool,
                                                        GFP_NOIO);
-       unsigned long flags;
 
        c->chunk = chunk;
 
-       spin_lock_irqsave(&s->tracked_chunk_lock, flags);
+       spin_lock_irq(&s->tracked_chunk_lock);
        hlist_add_head(&c->node,
                       &s->tracked_chunk_hash[DM_TRACKED_CHUNK_HASH(chunk)]);
-       spin_unlock_irqrestore(&s->tracked_chunk_lock, flags);
+       spin_unlock_irq(&s->tracked_chunk_lock);
 
        return c;
 }
index 45135f69509c89e83b6cc7190f1f25972ae28076..5e7dc772f5deca223ea9142d073cc66785f54b27 100644 (file)
@@ -315,8 +315,11 @@ static int run(struct mddev *mddev)
        }
        conf->nfaults = 0;
 
-       rdev_for_each(rdev, mddev)
+       rdev_for_each(rdev, mddev) {
                conf->rdev = rdev;
+               disk_stack_limits(mddev->gendisk, rdev->bdev,
+                                 rdev->data_offset << 9);
+       }
 
        md_set_array_sectors(mddev, faulty_size(mddev, 0, 0));
        mddev->private = conf;
index 9ab768acfb623f8bbb13870e5f65150a60ecad07..12293a04bde34573e939901120e4fe273783c64b 100644 (file)
@@ -603,9 +603,9 @@ static struct mddev * mddev_find(dev_t unit)
        goto retry;
 }
 
-static inline int mddev_lock(struct mddev * mddev)
+int md_queue_misc_work(struct work_struct *work)
 {
-       return mutex_lock_interruptible(&mddev->reconfig_mutex);
+       return queue_work(md_misc_wq, work);
 }
 
 static inline int mddev_is_locked(struct mddev *mddev)
@@ -620,7 +620,7 @@ static inline int mddev_trylock(struct mddev * mddev)
 
 static struct attribute_group md_redundancy_group;
 
-static void mddev_unlock(struct mddev * mddev)
+void mddev_unlock(struct mddev * mddev)
 {
        if (mddev->to_remove) {
                /* These cannot be removed under reconfig_mutex as
@@ -8604,6 +8604,8 @@ EXPORT_SYMBOL(md_register_thread);
 EXPORT_SYMBOL(md_unregister_thread);
 EXPORT_SYMBOL(md_wakeup_thread);
 EXPORT_SYMBOL(md_check_recovery);
+EXPORT_SYMBOL(mddev_unlock);
+EXPORT_SYMBOL(md_queue_misc_work);
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("MD RAID framework");
 MODULE_ALIAS("md");
index af443ab868db910f2db2d35d53ffacca701f1e60..719a6eb1abf3d8406146e1a28030d1d4fc02fd7b 100644 (file)
@@ -636,4 +636,12 @@ static inline int mddev_check_plugged(struct mddev *mddev)
        return !!blk_check_plugged(md_unplug, mddev,
                                   sizeof(struct blk_plug_cb));
 }
+
+static inline int mddev_lock(struct mddev * mddev)
+{
+       return mutex_lock_interruptible(&mddev->reconfig_mutex);
+}
+extern void mddev_unlock(struct mddev *mddev);
+extern int md_queue_misc_work(struct work_struct *work);
+
 #endif /* _MD_MD_H */
index 5709bfeab1e8fb29af17ba7a66dc78a9432d86a2..accbb05f17b628456231d94e8a4a880862f980dd 100644 (file)
@@ -36,13 +36,13 @@ struct node_header {
        __le32 padding;
 } __packed;
 
-struct node {
+struct btree_node {
        struct node_header header;
        __le64 keys[0];
 } __packed;
 
 
-void inc_children(struct dm_transaction_manager *tm, struct node *n,
+void inc_children(struct dm_transaction_manager *tm, struct btree_node *n,
                  struct dm_btree_value_type *vt);
 
 int new_block(struct dm_btree_info *info, struct dm_block **result);
@@ -64,7 +64,7 @@ struct ro_spine {
 void init_ro_spine(struct ro_spine *s, struct dm_btree_info *info);
 int exit_ro_spine(struct ro_spine *s);
 int ro_step(struct ro_spine *s, dm_block_t new_child);
-struct node *ro_node(struct ro_spine *s);
+struct btree_node *ro_node(struct ro_spine *s);
 
 struct shadow_spine {
        struct dm_btree_info *info;
@@ -98,17 +98,17 @@ int shadow_root(struct shadow_spine *s);
 /*
  * Some inlines.
  */
-static inline __le64 *key_ptr(struct node *n, uint32_t index)
+static inline __le64 *key_ptr(struct btree_node *n, uint32_t index)
 {
        return n->keys + index;
 }
 
-static inline void *value_base(struct node *n)
+static inline void *value_base(struct btree_node *n)
 {
        return &n->keys[le32_to_cpu(n->header.max_entries)];
 }
 
-static inline void *value_ptr(struct node *n, uint32_t index)
+static inline void *value_ptr(struct btree_node *n, uint32_t index)
 {
        uint32_t value_size = le32_to_cpu(n->header.value_size);
        return value_base(n) + (value_size * index);
@@ -117,7 +117,7 @@ static inline void *value_ptr(struct node *n, uint32_t index)
 /*
  * Assumes the values are suitably-aligned and converts to core format.
  */
-static inline uint64_t value64(struct node *n, uint32_t index)
+static inline uint64_t value64(struct btree_node *n, uint32_t index)
 {
        __le64 *values_le = value_base(n);
 
@@ -127,7 +127,7 @@ static inline uint64_t value64(struct node *n, uint32_t index)
 /*
  * Searching for a key within a single node.
  */
-int lower_bound(struct node *n, uint64_t key);
+int lower_bound(struct btree_node *n, uint64_t key);
 
 extern struct dm_block_validator btree_node_validator;
 
index aa71e2359a0704050b0b61054d4faa21bac10b53..c4f28133ef829340d966393f7e6d9eba6857111d 100644 (file)
@@ -53,7 +53,7 @@
 /*
  * Some little utilities for moving node data around.
  */
-static void node_shift(struct node *n, int shift)
+static void node_shift(struct btree_node *n, int shift)
 {
        uint32_t nr_entries = le32_to_cpu(n->header.nr_entries);
        uint32_t value_size = le32_to_cpu(n->header.value_size);
@@ -79,7 +79,7 @@ static void node_shift(struct node *n, int shift)
        }
 }
 
-static void node_copy(struct node *left, struct node *right, int shift)
+static void node_copy(struct btree_node *left, struct btree_node *right, int shift)
 {
        uint32_t nr_left = le32_to_cpu(left->header.nr_entries);
        uint32_t value_size = le32_to_cpu(left->header.value_size);
@@ -108,7 +108,7 @@ static void node_copy(struct node *left, struct node *right, int shift)
 /*
  * Delete a specific entry from a leaf node.
  */
-static void delete_at(struct node *n, unsigned index)
+static void delete_at(struct btree_node *n, unsigned index)
 {
        unsigned nr_entries = le32_to_cpu(n->header.nr_entries);
        unsigned nr_to_copy = nr_entries - (index + 1);
@@ -128,7 +128,7 @@ static void delete_at(struct node *n, unsigned index)
        n->header.nr_entries = cpu_to_le32(nr_entries - 1);
 }
 
-static unsigned merge_threshold(struct node *n)
+static unsigned merge_threshold(struct btree_node *n)
 {
        return le32_to_cpu(n->header.max_entries) / 3;
 }
@@ -136,7 +136,7 @@ static unsigned merge_threshold(struct node *n)
 struct child {
        unsigned index;
        struct dm_block *block;
-       struct node *n;
+       struct btree_node *n;
 };
 
 static struct dm_btree_value_type le64_type = {
@@ -147,7 +147,7 @@ static struct dm_btree_value_type le64_type = {
        .equal = NULL
 };
 
-static int init_child(struct dm_btree_info *info, struct node *parent,
+static int init_child(struct dm_btree_info *info, struct btree_node *parent,
                      unsigned index, struct child *result)
 {
        int r, inc;
@@ -177,7 +177,7 @@ static int exit_child(struct dm_btree_info *info, struct child *c)
        return dm_tm_unlock(info->tm, c->block);
 }
 
-static void shift(struct node *left, struct node *right, int count)
+static void shift(struct btree_node *left, struct btree_node *right, int count)
 {
        uint32_t nr_left = le32_to_cpu(left->header.nr_entries);
        uint32_t nr_right = le32_to_cpu(right->header.nr_entries);
@@ -203,11 +203,11 @@ static void shift(struct node *left, struct node *right, int count)
        right->header.nr_entries = cpu_to_le32(nr_right + count);
 }
 
-static void __rebalance2(struct dm_btree_info *info, struct node *parent,
+static void __rebalance2(struct dm_btree_info *info, struct btree_node *parent,
                         struct child *l, struct child *r)
 {
-       struct node *left = l->n;
-       struct node *right = r->n;
+       struct btree_node *left = l->n;
+       struct btree_node *right = r->n;
        uint32_t nr_left = le32_to_cpu(left->header.nr_entries);
        uint32_t nr_right = le32_to_cpu(right->header.nr_entries);
        unsigned threshold = 2 * merge_threshold(left) + 1;
@@ -239,7 +239,7 @@ static int rebalance2(struct shadow_spine *s, struct dm_btree_info *info,
                      unsigned left_index)
 {
        int r;
-       struct node *parent;
+       struct btree_node *parent;
        struct child left, right;
 
        parent = dm_block_data(shadow_current(s));
@@ -270,9 +270,9 @@ static int rebalance2(struct shadow_spine *s, struct dm_btree_info *info,
  * in right, then rebalance2.  This wastes some cpu, but I want something
  * simple atm.
  */
-static void delete_center_node(struct dm_btree_info *info, struct node *parent,
+static void delete_center_node(struct dm_btree_info *info, struct btree_node *parent,
                               struct child *l, struct child *c, struct child *r,
-                              struct node *left, struct node *center, struct node *right,
+                              struct btree_node *left, struct btree_node *center, struct btree_node *right,
                               uint32_t nr_left, uint32_t nr_center, uint32_t nr_right)
 {
        uint32_t max_entries = le32_to_cpu(left->header.max_entries);
@@ -301,9 +301,9 @@ static void delete_center_node(struct dm_btree_info *info, struct node *parent,
 /*
  * Redistributes entries among 3 sibling nodes.
  */
-static void redistribute3(struct dm_btree_info *info, struct node *parent,
+static void redistribute3(struct dm_btree_info *info, struct btree_node *parent,
                          struct child *l, struct child *c, struct child *r,
-                         struct node *left, struct node *center, struct node *right,
+                         struct btree_node *left, struct btree_node *center, struct btree_node *right,
                          uint32_t nr_left, uint32_t nr_center, uint32_t nr_right)
 {
        int s;
@@ -343,12 +343,12 @@ static void redistribute3(struct dm_btree_info *info, struct node *parent,
        *key_ptr(parent, r->index) = right->keys[0];
 }
 
-static void __rebalance3(struct dm_btree_info *info, struct node *parent,
+static void __rebalance3(struct dm_btree_info *info, struct btree_node *parent,
                         struct child *l, struct child *c, struct child *r)
 {
-       struct node *left = l->n;
-       struct node *center = c->n;
-       struct node *right = r->n;
+       struct btree_node *left = l->n;
+       struct btree_node *center = c->n;
+       struct btree_node *right = r->n;
 
        uint32_t nr_left = le32_to_cpu(left->header.nr_entries);
        uint32_t nr_center = le32_to_cpu(center->header.nr_entries);
@@ -371,7 +371,7 @@ static int rebalance3(struct shadow_spine *s, struct dm_btree_info *info,
                      unsigned left_index)
 {
        int r;
-       struct node *parent = dm_block_data(shadow_current(s));
+       struct btree_node *parent = dm_block_data(shadow_current(s));
        struct child left, center, right;
 
        /*
@@ -421,7 +421,7 @@ static int get_nr_entries(struct dm_transaction_manager *tm,
 {
        int r;
        struct dm_block *block;
-       struct node *n;
+       struct btree_node *n;
 
        r = dm_tm_read_lock(tm, b, &btree_node_validator, &block);
        if (r)
@@ -438,7 +438,7 @@ static int rebalance_children(struct shadow_spine *s,
 {
        int i, r, has_left_sibling, has_right_sibling;
        uint32_t child_entries;
-       struct node *n;
+       struct btree_node *n;
 
        n = dm_block_data(shadow_current(s));
 
@@ -483,7 +483,7 @@ static int rebalance_children(struct shadow_spine *s,
        return r;
 }
 
-static int do_leaf(struct node *n, uint64_t key, unsigned *index)
+static int do_leaf(struct btree_node *n, uint64_t key, unsigned *index)
 {
        int i = lower_bound(n, key);
 
@@ -506,7 +506,7 @@ static int remove_raw(struct shadow_spine *s, struct dm_btree_info *info,
                      uint64_t key, unsigned *index)
 {
        int i = *index, r;
-       struct node *n;
+       struct btree_node *n;
 
        for (;;) {
                r = shadow_step(s, root, vt);
@@ -556,7 +556,7 @@ int dm_btree_remove(struct dm_btree_info *info, dm_block_t root,
        unsigned level, last_level = info->levels - 1;
        int index = 0, r = 0;
        struct shadow_spine spine;
-       struct node *n;
+       struct btree_node *n;
 
        init_shadow_spine(&spine, info);
        for (level = 0; level < info->levels; level++) {
index d9a7912ee8ee67be0bd127fc797076f493e6cc8c..2f0805c3263e6f8ce41e9aac7c227884bdeb4ea3 100644 (file)
@@ -23,7 +23,7 @@ static void node_prepare_for_write(struct dm_block_validator *v,
                                   struct dm_block *b,
                                   size_t block_size)
 {
-       struct node *n = dm_block_data(b);
+       struct btree_node *n = dm_block_data(b);
        struct node_header *h = &n->header;
 
        h->blocknr = cpu_to_le64(dm_block_location(b));
@@ -38,7 +38,7 @@ static int node_check(struct dm_block_validator *v,
                      struct dm_block *b,
                      size_t block_size)
 {
-       struct node *n = dm_block_data(b);
+       struct btree_node *n = dm_block_data(b);
        struct node_header *h = &n->header;
        size_t value_size;
        __le32 csum_disk;
@@ -164,7 +164,7 @@ int ro_step(struct ro_spine *s, dm_block_t new_child)
        return r;
 }
 
-struct node *ro_node(struct ro_spine *s)
+struct btree_node *ro_node(struct ro_spine *s)
 {
        struct dm_block *block;
 
index d12b2cc51f1a37711586fe6d13f6261f0b56c1be..371f3d49d18e717316ad39b2d1277e77ce0903b6 100644 (file)
@@ -38,7 +38,7 @@ static void array_insert(void *base, size_t elt_size, unsigned nr_elts,
 /*----------------------------------------------------------------*/
 
 /* makes the assumption that no two keys are the same. */
-static int bsearch(struct node *n, uint64_t key, int want_hi)
+static int bsearch(struct btree_node *n, uint64_t key, int want_hi)
 {
        int lo = -1, hi = le32_to_cpu(n->header.nr_entries);
 
@@ -58,12 +58,12 @@ static int bsearch(struct node *n, uint64_t key, int want_hi)
        return want_hi ? hi : lo;
 }
 
-int lower_bound(struct node *n, uint64_t key)
+int lower_bound(struct btree_node *n, uint64_t key)
 {
        return bsearch(n, key, 0);
 }
 
-void inc_children(struct dm_transaction_manager *tm, struct node *n,
+void inc_children(struct dm_transaction_manager *tm, struct btree_node *n,
                  struct dm_btree_value_type *vt)
 {
        unsigned i;
@@ -77,7 +77,7 @@ void inc_children(struct dm_transaction_manager *tm, struct node *n,
                        vt->inc(vt->context, value_ptr(n, i));
 }
 
-static int insert_at(size_t value_size, struct node *node, unsigned index,
+static int insert_at(size_t value_size, struct btree_node *node, unsigned index,
                      uint64_t key, void *value)
                      __dm_written_to_disk(value)
 {
@@ -122,7 +122,7 @@ int dm_btree_empty(struct dm_btree_info *info, dm_block_t *root)
 {
        int r;
        struct dm_block *b;
-       struct node *n;
+       struct btree_node *n;
        size_t block_size;
        uint32_t max_entries;
 
@@ -154,7 +154,7 @@ EXPORT_SYMBOL_GPL(dm_btree_empty);
 #define MAX_SPINE_DEPTH 64
 struct frame {
        struct dm_block *b;
-       struct node *n;
+       struct btree_node *n;
        unsigned level;
        unsigned nr_children;
        unsigned current_child;
@@ -295,7 +295,7 @@ EXPORT_SYMBOL_GPL(dm_btree_del);
 /*----------------------------------------------------------------*/
 
 static int btree_lookup_raw(struct ro_spine *s, dm_block_t block, uint64_t key,
-                           int (*search_fn)(struct node *, uint64_t),
+                           int (*search_fn)(struct btree_node *, uint64_t),
                            uint64_t *result_key, void *v, size_t value_size)
 {
        int i, r;
@@ -406,7 +406,7 @@ static int btree_split_sibling(struct shadow_spine *s, dm_block_t root,
        size_t size;
        unsigned nr_left, nr_right;
        struct dm_block *left, *right, *parent;
-       struct node *ln, *rn, *pn;
+       struct btree_node *ln, *rn, *pn;
        __le64 location;
 
        left = shadow_current(s);
@@ -491,7 +491,7 @@ static int btree_split_beneath(struct shadow_spine *s, uint64_t key)
        size_t size;
        unsigned nr_left, nr_right;
        struct dm_block *left, *right, *new_parent;
-       struct node *pn, *ln, *rn;
+       struct btree_node *pn, *ln, *rn;
        __le64 val;
 
        new_parent = shadow_current(s);
@@ -576,7 +576,7 @@ static int btree_insert_raw(struct shadow_spine *s, dm_block_t root,
                            uint64_t key, unsigned *index)
 {
        int r, i = *index, top = 1;
-       struct node *node;
+       struct btree_node *node;
 
        for (;;) {
                r = shadow_step(s, root, vt);
@@ -643,7 +643,7 @@ static int insert(struct dm_btree_info *info, dm_block_t root,
        unsigned level, index = -1, last_level = info->levels - 1;
        dm_block_t block = root;
        struct shadow_spine spine;
-       struct node *n;
+       struct btree_node *n;
        struct dm_btree_value_type le64_type;
 
        le64_type.context = NULL;
index c5439dce0295078ecf82094af5474a649284ce61..8f2a2ffd470285268ed3c121781e82e899ed9781 100644 (file)
@@ -53,6 +53,8 @@
 #include <linux/cpu.h>
 #include <linux/slab.h>
 #include <linux/ratelimit.h>
+#include <trace/events/block.h>
+
 #include "md.h"
 #include "raid5.h"
 #include "raid0.h"
@@ -182,6 +184,8 @@ static void return_io(struct bio *return_bi)
                return_bi = bi->bi_next;
                bi->bi_next = NULL;
                bi->bi_size = 0;
+               trace_block_bio_complete(bdev_get_queue(bi->bi_bdev),
+                                        bi, 0);
                bio_endio(bi, 0);
                bi = return_bi;
        }
@@ -196,6 +200,21 @@ static int stripe_operations_active(struct stripe_head *sh)
               test_bit(STRIPE_COMPUTE_RUN, &sh->state);
 }
 
+static void raid5_wakeup_stripe_thread(struct stripe_head *sh)
+{
+       struct r5conf *conf = sh->raid_conf;
+       struct raid5_percpu *percpu;
+       int i, orphaned = 1;
+
+       percpu = per_cpu_ptr(conf->percpu, sh->cpu);
+       for_each_cpu(i, &percpu->handle_threads) {
+               md_wakeup_thread(conf->aux_threads[i]->thread);
+               orphaned = 0;
+       }
+       if (orphaned)
+               md_wakeup_thread(conf->mddev->thread);
+}
+
 static void do_release_stripe(struct r5conf *conf, struct stripe_head *sh)
 {
        BUG_ON(!list_empty(&sh->lru));
@@ -208,9 +227,19 @@ static void do_release_stripe(struct r5conf *conf, struct stripe_head *sh)
                           sh->bm_seq - conf->seq_write > 0)
                        list_add_tail(&sh->lru, &conf->bitmap_list);
                else {
+                       int cpu = sh->cpu;
+                       struct raid5_percpu *percpu;
+                       if (!cpu_online(cpu)) {
+                               cpu = cpumask_any(cpu_online_mask);
+                               sh->cpu = cpu;
+                       }
+                       percpu = per_cpu_ptr(conf->percpu, cpu);
+
                        clear_bit(STRIPE_DELAYED, &sh->state);
                        clear_bit(STRIPE_BIT_DELAY, &sh->state);
-                       list_add_tail(&sh->lru, &conf->handle_list);
+                       list_add_tail(&sh->lru, &percpu->handle_list);
+                       raid5_wakeup_stripe_thread(sh);
+                       return;
                }
                md_wakeup_thread(conf->mddev->thread);
        } else {
@@ -355,6 +384,7 @@ static void init_stripe(struct stripe_head *sh, sector_t sector, int previous)
                raid5_build_block(sh, i, previous);
        }
        insert_hash(conf, sh);
+       sh->cpu = smp_processor_id();
 }
 
 static struct stripe_head *__find_stripe(struct r5conf *conf, sector_t sector,
@@ -671,6 +701,9 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
                        bi->bi_next = NULL;
                        if (rrdev)
                                set_bit(R5_DOUBLE_LOCKED, &sh->dev[i].flags);
+                       trace_block_bio_remap(bdev_get_queue(bi->bi_bdev),
+                                             bi, disk_devt(conf->mddev->gendisk),
+                                             sh->dev[i].sector);
                        generic_make_request(bi);
                }
                if (rrdev) {
@@ -698,6 +731,9 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
                        rbi->bi_io_vec[0].bv_offset = 0;
                        rbi->bi_size = STRIPE_SIZE;
                        rbi->bi_next = NULL;
+                       trace_block_bio_remap(bdev_get_queue(rbi->bi_bdev),
+                                             rbi, disk_devt(conf->mddev->gendisk),
+                                             sh->dev[i].sector);
                        generic_make_request(rbi);
                }
                if (!rdev && !rrdev) {
@@ -2852,8 +2888,10 @@ static void handle_stripe_dirtying(struct r5conf *conf,
        pr_debug("for sector %llu, rmw=%d rcw=%d\n",
                (unsigned long long)sh->sector, rmw, rcw);
        set_bit(STRIPE_HANDLE, &sh->state);
-       if (rmw < rcw && rmw > 0)
+       if (rmw < rcw && rmw > 0) {
                /* prefer read-modify-write, but need to get some data */
+               blk_add_trace_msg(conf->mddev->queue, "raid5 rmw %llu %d",
+                                 (unsigned long long)sh->sector, rmw);
                for (i = disks; i--; ) {
                        struct r5dev *dev = &sh->dev[i];
                        if ((dev->towrite || i == sh->pd_idx) &&
@@ -2864,7 +2902,7 @@ static void handle_stripe_dirtying(struct r5conf *conf,
                                if (
                                  test_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
                                        pr_debug("Read_old block "
-                                               "%d for r-m-w\n", i);
+                                                "%d for r-m-w\n", i);
                                        set_bit(R5_LOCKED, &dev->flags);
                                        set_bit(R5_Wantread, &dev->flags);
                                        s->locked++;
@@ -2874,8 +2912,10 @@ static void handle_stripe_dirtying(struct r5conf *conf,
                                }
                        }
                }
+       }
        if (rcw <= rmw && rcw > 0) {
                /* want reconstruct write, but need to get some data */
+               int qread =0;
                rcw = 0;
                for (i = disks; i--; ) {
                        struct r5dev *dev = &sh->dev[i];
@@ -2894,12 +2934,17 @@ static void handle_stripe_dirtying(struct r5conf *conf,
                                        set_bit(R5_LOCKED, &dev->flags);
                                        set_bit(R5_Wantread, &dev->flags);
                                        s->locked++;
+                                       qread++;
                                } else {
                                        set_bit(STRIPE_DELAYED, &sh->state);
                                        set_bit(STRIPE_HANDLE, &sh->state);
                                }
                        }
                }
+               if (rcw)
+                       blk_add_trace_msg(conf->mddev->queue, "raid5 rcw %llu %d %d %d",
+                                         (unsigned long long)sh->sector,
+                                         rcw, qread, test_bit(STRIPE_DELAYED, &sh->state));
        }
        /* now if nothing is locked, and if we have enough data,
         * we can start a write request
@@ -3744,12 +3789,19 @@ static void raid5_activate_delayed(struct r5conf *conf)
                while (!list_empty(&conf->delayed_list)) {
                        struct list_head *l = conf->delayed_list.next;
                        struct stripe_head *sh;
+                       int cpu;
                        sh = list_entry(l, struct stripe_head, lru);
                        list_del_init(l);
                        clear_bit(STRIPE_DELAYED, &sh->state);
                        if (!test_and_set_bit(STRIPE_PREREAD_ACTIVE, &sh->state))
                                atomic_inc(&conf->preread_active_stripes);
                        list_add_tail(&sh->lru, &conf->hold_list);
+                       cpu = sh->cpu;
+                       if (!cpu_online(cpu)) {
+                               cpu = cpumask_any(cpu_online_mask);
+                               sh->cpu = cpu;
+                       }
+                       raid5_wakeup_stripe_thread(sh);
                }
        }
 }
@@ -3900,6 +3952,8 @@ static void raid5_align_endio(struct bio *bi, int error)
        rdev_dec_pending(rdev, conf->mddev);
 
        if (!error && uptodate) {
+               trace_block_bio_complete(bdev_get_queue(raid_bi->bi_bdev),
+                                        raid_bi, 0);
                bio_endio(raid_bi, 0);
                if (atomic_dec_and_test(&conf->active_aligned_reads))
                        wake_up(&conf->wait_for_stripe);
@@ -4004,6 +4058,9 @@ static int chunk_aligned_read(struct mddev *mddev, struct bio * raid_bio)
                atomic_inc(&conf->active_aligned_reads);
                spin_unlock_irq(&conf->device_lock);
 
+               trace_block_bio_remap(bdev_get_queue(align_bi->bi_bdev),
+                                     align_bi, disk_devt(mddev->gendisk),
+                                     raid_bio->bi_sector);
                generic_make_request(align_bi);
                return 1;
        } else {
@@ -4023,18 +4080,29 @@ static int chunk_aligned_read(struct mddev *mddev, struct bio * raid_bio)
  * head of the hold_list has changed, i.e. the head was promoted to the
  * handle_list.
  */
-static struct stripe_head *__get_priority_stripe(struct r5conf *conf)
-{
-       struct stripe_head *sh;
-
+static struct stripe_head *__get_priority_stripe(struct r5conf *conf,
+       cpumask_t *mask)
+{
+       struct stripe_head *sh = NULL, *tmp;
+       struct list_head *handle_list = NULL;
+       int cpu;
+
+       /* Should we take action to avoid starvation of latter CPUs ? */
+       for_each_cpu(cpu, mask) {
+               struct raid5_percpu *percpu = per_cpu_ptr(conf->percpu, cpu);
+               if (!list_empty(&percpu->handle_list)) {
+                       handle_list = &percpu->handle_list;
+                       break;
+               }
+       }
        pr_debug("%s: handle: %s hold: %s full_writes: %d bypass_count: %d\n",
                  __func__,
-                 list_empty(&conf->handle_list) ? "empty" : "busy",
+                 !handle_list ? "empty" : "busy",
                  list_empty(&conf->hold_list) ? "empty" : "busy",
                  atomic_read(&conf->pending_full_writes), conf->bypass_count);
 
-       if (!list_empty(&conf->handle_list)) {
-               sh = list_entry(conf->handle_list.next, typeof(*sh), lru);
+       if (handle_list) {
+               sh = list_entry(handle_list->next, typeof(*sh), lru);
 
                if (list_empty(&conf->hold_list))
                        conf->bypass_count = 0;
@@ -4052,12 +4120,23 @@ static struct stripe_head *__get_priority_stripe(struct r5conf *conf)
                   ((conf->bypass_threshold &&
                     conf->bypass_count > conf->bypass_threshold) ||
                    atomic_read(&conf->pending_full_writes) == 0)) {
-               sh = list_entry(conf->hold_list.next,
-                               typeof(*sh), lru);
-               conf->bypass_count -= conf->bypass_threshold;
-               if (conf->bypass_count < 0)
-                       conf->bypass_count = 0;
-       } else
+
+               list_for_each_entry(tmp, &conf->hold_list,  lru) {
+                       if (cpumask_test_cpu(tmp->cpu, mask) ||
+                           !cpu_online(tmp->cpu)) {
+                               sh = tmp;
+                               break;
+                       }
+               }
+
+               if (sh) {
+                       conf->bypass_count -= conf->bypass_threshold;
+                       if (conf->bypass_count < 0)
+                               conf->bypass_count = 0;
+               }
+       }
+
+       if (!sh)
                return NULL;
 
        list_del_init(&sh->lru);
@@ -4078,6 +4157,7 @@ static void raid5_unplug(struct blk_plug_cb *blk_cb, bool from_schedule)
        struct stripe_head *sh;
        struct mddev *mddev = cb->cb.data;
        struct r5conf *conf = mddev->private;
+       int cnt = 0;
 
        if (cb->list.next && !list_empty(&cb->list)) {
                spin_lock_irq(&conf->device_lock);
@@ -4092,9 +4172,11 @@ static void raid5_unplug(struct blk_plug_cb *blk_cb, bool from_schedule)
                        smp_mb__before_clear_bit();
                        clear_bit(STRIPE_ON_UNPLUG_LIST, &sh->state);
                        __release_stripe(conf, sh);
+                       cnt++;
                }
                spin_unlock_irq(&conf->device_lock);
        }
+       trace_block_unplug(mddev->queue, cnt, !from_schedule);
        kfree(cb);
 }
 
@@ -4352,6 +4434,8 @@ static void make_request(struct mddev *mddev, struct bio * bi)
                if ( rw == WRITE )
                        md_write_end(mddev);
 
+               trace_block_bio_complete(bdev_get_queue(bi->bi_bdev),
+                                        bi, 0);
                bio_endio(bi, 0);
        }
 }
@@ -4728,21 +4812,24 @@ static int  retry_aligned_read(struct r5conf *conf, struct bio *raid_bio)
                handled++;
        }
        remaining = raid5_dec_bi_active_stripes(raid_bio);
-       if (remaining == 0)
+       if (remaining == 0) {
+               trace_block_bio_complete(bdev_get_queue(raid_bio->bi_bdev),
+                                        raid_bio, 0);
                bio_endio(raid_bio, 0);
+       }
        if (atomic_dec_and_test(&conf->active_aligned_reads))
                wake_up(&conf->wait_for_stripe);
        return handled;
 }
 
 #define MAX_STRIPE_BATCH 8
-static int handle_active_stripes(struct r5conf *conf)
+static int handle_active_stripes(struct r5conf *conf, cpumask_t *mask)
 {
        struct stripe_head *batch[MAX_STRIPE_BATCH], *sh;
        int i, batch_size = 0;
 
        while (batch_size < MAX_STRIPE_BATCH &&
-                       (sh = __get_priority_stripe(conf)) != NULL)
+                       (sh = __get_priority_stripe(conf, mask)) != NULL)
                batch[batch_size++] = sh;
 
        if (batch_size == 0)
@@ -4760,6 +4847,35 @@ static int handle_active_stripes(struct r5conf *conf)
        return batch_size;
 }
 
+static void raid5auxd(struct md_thread *thread)
+{
+       struct mddev *mddev = thread->mddev;
+       struct r5conf *conf = mddev->private;
+       struct blk_plug plug;
+       int handled;
+       struct raid5_auxth *auxth = thread->private;
+
+       pr_debug("+++ raid5auxd active\n");
+
+       blk_start_plug(&plug);
+       handled = 0;
+       spin_lock_irq(&conf->device_lock);
+       while (1) {
+               int batch_size;
+
+               batch_size = handle_active_stripes(conf, &auxth->work_mask);
+               if (!batch_size)
+                       break;
+               handled += batch_size;
+       }
+       pr_debug("%d stripes handled\n", handled);
+
+       spin_unlock_irq(&conf->device_lock);
+       blk_finish_plug(&plug);
+
+       pr_debug("--- raid5auxd inactive\n");
+}
+
 /*
  * This is our raid5 kernel thread.
  *
@@ -4807,7 +4923,7 @@ static void raid5d(struct md_thread *thread)
                        handled++;
                }
 
-               batch_size = handle_active_stripes(conf);
+               batch_size = handle_active_stripes(conf, &conf->work_mask);
                if (!batch_size)
                        break;
                handled += batch_size;
@@ -4936,10 +5052,270 @@ stripe_cache_active_show(struct mddev *mddev, char *page)
 static struct md_sysfs_entry
 raid5_stripecache_active = __ATTR_RO(stripe_cache_active);
 
+static void raid5_update_threads_handle_mask(struct mddev *mddev)
+{
+       int cpu, i;
+       struct raid5_percpu *percpu;
+       struct r5conf *conf = mddev->private;
+
+       for_each_online_cpu(cpu) {
+               percpu = per_cpu_ptr(conf->percpu, cpu);
+               cpumask_clear(&percpu->handle_threads);
+       }
+       cpumask_copy(&conf->work_mask, cpu_online_mask);
+
+       for (i = 0; i < conf->aux_thread_num; i++) {
+               cpumask_t *work_mask = &conf->aux_threads[i]->work_mask;
+               for_each_cpu(cpu, work_mask) {
+                       percpu = per_cpu_ptr(conf->percpu, cpu);
+                       cpumask_set_cpu(i, &percpu->handle_threads);
+               }
+               cpumask_andnot(&conf->work_mask, &conf->work_mask,
+                               work_mask);
+       }
+}
+
+struct raid5_auxth_sysfs {
+       struct attribute attr;
+       ssize_t (*show)(struct mddev *, struct raid5_auxth *, char *);
+       ssize_t (*store)(struct mddev *, struct raid5_auxth *,
+               const char *, size_t);
+};
+
+static ssize_t raid5_show_thread_cpulist(struct mddev *mddev,
+       struct raid5_auxth *thread, char *page)
+{
+       if (!mddev->private)
+               return 0;
+       return cpulist_scnprintf(page, PAGE_SIZE, &thread->work_mask);
+}
+
+static ssize_t
+raid5_store_thread_cpulist(struct mddev *mddev, struct raid5_auxth *thread,
+       const char *page, size_t len)
+{
+       struct r5conf *conf = mddev->private;
+       cpumask_var_t mask;
+
+       if (!conf)
+               return -ENODEV;
+       if (!alloc_cpumask_var(&mask, GFP_KERNEL))
+               return -ENOMEM;
+
+       if (cpulist_parse(page, mask)) {
+               free_cpumask_var(mask);
+               return -EINVAL;
+       }
+
+       get_online_cpus();
+       spin_lock_irq(&conf->device_lock);
+       cpumask_copy(&thread->work_mask, mask);
+       raid5_update_threads_handle_mask(mddev);
+       spin_unlock_irq(&conf->device_lock);
+       put_online_cpus();
+       set_cpus_allowed_ptr(thread->thread->tsk, mask);
+
+       free_cpumask_var(mask);
+       return len;
+}
+
+static struct raid5_auxth_sysfs thread_cpulist =
+__ATTR(cpulist, S_IRUGO|S_IWUSR, raid5_show_thread_cpulist,
+       raid5_store_thread_cpulist);
+
+static struct attribute *auxth_attrs[] = {
+       &thread_cpulist.attr,
+       NULL,
+};
+
+static ssize_t
+raid5_auxth_attr_show(struct kobject *kobj, struct attribute *attr, char *page)
+{
+       struct raid5_auxth_sysfs *entry = container_of(attr,
+               struct raid5_auxth_sysfs, attr);
+       struct raid5_auxth *thread = container_of(kobj,
+               struct raid5_auxth, kobj);
+       struct mddev *mddev = thread->thread->mddev;
+       ssize_t ret;
+
+       if (!entry->show)
+               return -EIO;
+       mddev_lock(mddev);
+       ret = entry->show(mddev, thread, page);
+       mddev_unlock(mddev);
+       return ret;
+}
+
+static ssize_t
+raid5_auxth_attr_store(struct kobject *kobj, struct attribute *attr,
+             const char *page, size_t length)
+{
+       struct raid5_auxth_sysfs *entry = container_of(attr,
+               struct raid5_auxth_sysfs, attr);
+       struct raid5_auxth *thread = container_of(kobj,
+               struct raid5_auxth, kobj);
+       struct mddev *mddev = thread->thread->mddev;
+       ssize_t ret;
+
+       if (!entry->store)
+               return -EIO;
+       if (!capable(CAP_SYS_ADMIN))
+               return -EACCES;
+       mddev_lock(mddev);
+       ret = entry->store(mddev, thread, page, length);
+       mddev_unlock(mddev);
+       return ret;
+}
+
+static void raid5_auxth_release(struct kobject *kobj)
+{
+       struct raid5_auxth *thread = container_of(kobj,
+               struct raid5_auxth, kobj);
+       kfree(thread);
+}
+
+static const struct sysfs_ops raid5_auxth_sysfsops = {
+       .show = raid5_auxth_attr_show,
+       .store = raid5_auxth_attr_store,
+};
+static struct kobj_type raid5_auxth_ktype = {
+       .release = raid5_auxth_release,
+       .sysfs_ops = &raid5_auxth_sysfsops,
+       .default_attrs = auxth_attrs,
+};
+
+static ssize_t
+raid5_show_auxthread_number(struct mddev *mddev, char *page)
+{
+       struct r5conf *conf = mddev->private;
+       if (conf)
+               return sprintf(page, "%d\n", conf->aux_thread_num);
+       else
+               return 0;
+}
+
+static void raid5_auxth_delete(struct work_struct *ws)
+{
+       struct raid5_auxth *thread = container_of(ws, struct raid5_auxth,
+               del_work);
+
+       kobject_del(&thread->kobj);
+       kobject_put(&thread->kobj);
+}
+
+static void __free_aux_thread(struct mddev *mddev, struct raid5_auxth *thread)
+{
+       md_unregister_thread(&thread->thread);
+       INIT_WORK(&thread->del_work, raid5_auxth_delete);
+       kobject_get(&thread->kobj);
+       md_queue_misc_work(&thread->del_work);
+}
+
+static struct raid5_auxth *__create_aux_thread(struct mddev *mddev, int i)
+{
+       struct raid5_auxth *thread;
+       char name[10];
+
+       thread = kzalloc(sizeof(*thread), GFP_KERNEL);
+       if (!thread)
+               return NULL;
+       snprintf(name, 10, "aux%d", i);
+       thread->thread = md_register_thread(raid5auxd, mddev, name);
+       if (!thread->thread) {
+               kfree(thread);
+               return NULL;
+       }
+       thread->thread->private = thread;
+
+       cpumask_copy(&thread->work_mask, cpu_online_mask);
+
+       if (kobject_init_and_add(&thread->kobj, &raid5_auxth_ktype,
+           &mddev->kobj, "auxth%d", i)) {
+               md_unregister_thread(&thread->thread);
+               kfree(thread);
+               return NULL;
+       }
+       return thread;
+}
+
+static ssize_t
+raid5_store_auxthread_number(struct mddev *mddev, const char *page, size_t len)
+{
+       struct r5conf *conf = mddev->private;
+       unsigned long new;
+       int i;
+       struct raid5_auxth **threads;
+
+       if (len >= PAGE_SIZE)
+               return -EINVAL;
+       if (!conf)
+               return -ENODEV;
+
+       if (kstrtoul(page, 10, &new))
+               return -EINVAL;
+
+       if (new == conf->aux_thread_num)
+               return len;
+
+       /* There is no point creating more threads than cpu number */
+       if (new > num_online_cpus())
+               return -EINVAL;
+
+       if (new > conf->aux_thread_num) {
+               threads = kzalloc(sizeof(struct raid5_auxth *) * new,
+                               GFP_KERNEL);
+               if (!threads)
+                       return -ENOMEM;
+
+               i = conf->aux_thread_num;
+               while (i < new) {
+                       threads[i] = __create_aux_thread(mddev, i);
+                       if (!threads[i])
+                               goto error;
+
+                       i++;
+               }
+               memcpy(threads, conf->aux_threads,
+                       sizeof(struct raid5_auxth *) * conf->aux_thread_num);
+               get_online_cpus();
+               spin_lock_irq(&conf->device_lock);
+               kfree(conf->aux_threads);
+               conf->aux_threads = threads;
+               conf->aux_thread_num = new;
+               raid5_update_threads_handle_mask(mddev);
+               spin_unlock_irq(&conf->device_lock);
+               put_online_cpus();
+       } else {
+               int old = conf->aux_thread_num;
+
+               get_online_cpus();
+               spin_lock_irq(&conf->device_lock);
+               conf->aux_thread_num = new;
+               raid5_update_threads_handle_mask(mddev);
+               spin_unlock_irq(&conf->device_lock);
+               put_online_cpus();
+               for (i = new; i < old; i++)
+                       __free_aux_thread(mddev, conf->aux_threads[i]);
+       }
+
+       return len;
+error:
+       while (--i >= conf->aux_thread_num)
+               __free_aux_thread(mddev, threads[i]);
+       kfree(threads);
+       return -ENOMEM;
+}
+
+static struct md_sysfs_entry
+raid5_auxthread_number = __ATTR(auxthread_number, S_IRUGO|S_IWUSR,
+                               raid5_show_auxthread_number,
+                               raid5_store_auxthread_number);
+
 static struct attribute *raid5_attrs[] =  {
        &raid5_stripecache_size.attr,
        &raid5_stripecache_active.attr,
        &raid5_preread_bypass_threshold.attr,
+       &raid5_auxthread_number.attr,
        NULL,
 };
 static struct attribute_group raid5_attrs_group = {
@@ -4987,6 +5363,7 @@ static void raid5_free_percpu(struct r5conf *conf)
 
 static void free_conf(struct r5conf *conf)
 {
+       kfree(conf->aux_threads);
        shrink_stripes(conf);
        raid5_free_percpu(conf);
        kfree(conf->disks);
@@ -4999,7 +5376,7 @@ static int raid456_cpu_notify(struct notifier_block *nfb, unsigned long action,
                              void *hcpu)
 {
        struct r5conf *conf = container_of(nfb, struct r5conf, cpu_notify);
-       long cpu = (long)hcpu;
+       long cpu = (long)hcpu, anycpu;
        struct raid5_percpu *percpu = per_cpu_ptr(conf->percpu, cpu);
 
        switch (action) {
@@ -5018,9 +5395,17 @@ static int raid456_cpu_notify(struct notifier_block *nfb, unsigned long action,
                               __func__, cpu);
                        return notifier_from_errno(-ENOMEM);
                }
+               INIT_LIST_HEAD(&(percpu->handle_list));
+               cpumask_clear(&percpu->handle_threads);
                break;
        case CPU_DEAD:
        case CPU_DEAD_FROZEN:
+               spin_lock_irq(&conf->device_lock);
+               anycpu = cpumask_any(cpu_online_mask);
+               list_splice_tail_init(&percpu->handle_list,
+                       &per_cpu_ptr(conf->percpu, anycpu)->handle_list);
+               spin_unlock_irq(&conf->device_lock);
+
                safe_put_page(percpu->spare_page);
                kfree(percpu->scribble);
                percpu->spare_page = NULL;
@@ -5029,6 +5414,10 @@ static int raid456_cpu_notify(struct notifier_block *nfb, unsigned long action,
        default:
                break;
        }
+
+       spin_lock_irq(&conf->device_lock);
+       raid5_update_threads_handle_mask(conf->mddev);
+       spin_unlock_irq(&conf->device_lock);
        return NOTIFY_OK;
 }
 #endif
@@ -5049,20 +5438,24 @@ static int raid5_alloc_percpu(struct r5conf *conf)
        get_online_cpus();
        err = 0;
        for_each_present_cpu(cpu) {
+               struct raid5_percpu *percpu = per_cpu_ptr(conf->percpu, cpu);
+
                if (conf->level == 6) {
                        spare_page = alloc_page(GFP_KERNEL);
                        if (!spare_page) {
                                err = -ENOMEM;
                                break;
                        }
-                       per_cpu_ptr(conf->percpu, cpu)->spare_page = spare_page;
+                       percpu->spare_page = spare_page;
                }
                scribble = kmalloc(conf->scribble_len, GFP_KERNEL);
                if (!scribble) {
                        err = -ENOMEM;
                        break;
                }
-               per_cpu_ptr(conf->percpu, cpu)->scribble = scribble;
+               percpu->scribble = scribble;
+               INIT_LIST_HEAD(&percpu->handle_list);
+               cpumask_clear(&percpu->handle_threads);
        }
 #ifdef CONFIG_HOTPLUG_CPU
        conf->cpu_notify.notifier_call = raid456_cpu_notify;
@@ -5118,7 +5511,6 @@ static struct r5conf *setup_conf(struct mddev *mddev)
        spin_lock_init(&conf->device_lock);
        init_waitqueue_head(&conf->wait_for_stripe);
        init_waitqueue_head(&conf->wait_for_overlap);
-       INIT_LIST_HEAD(&conf->handle_list);
        INIT_LIST_HEAD(&conf->hold_list);
        INIT_LIST_HEAD(&conf->delayed_list);
        INIT_LIST_HEAD(&conf->bitmap_list);
@@ -5129,6 +5521,8 @@ static struct r5conf *setup_conf(struct mddev *mddev)
        conf->bypass_threshold = BYPASS_THRESHOLD;
        conf->recovery_disabled = mddev->recovery_disabled - 1;
 
+       cpumask_copy(&conf->work_mask, cpu_online_mask);
+
        conf->raid_disks = mddev->raid_disks;
        if (mddev->reshape_position == MaxSector)
                conf->previous_raid_disks = mddev->raid_disks;
@@ -5581,6 +5975,10 @@ abort:
 static int stop(struct mddev *mddev)
 {
        struct r5conf *conf = mddev->private;
+       int i;
+
+       for (i = 0; i < conf->aux_thread_num; i++)
+               __free_aux_thread(mddev, conf->aux_threads[i]);
 
        md_unregister_thread(&mddev->thread);
        if (mddev->queue)
index 18b2c4a8a1fdf55af4af03ccd5ca71d2e84db1cb..2afd8358556b6989668add1e25c187b9caa6b1ed 100644 (file)
@@ -211,6 +211,7 @@ struct stripe_head {
        enum check_states       check_state;
        enum reconstruct_states reconstruct_state;
        spinlock_t              stripe_lock;
+       int                     cpu;
        /**
         * struct stripe_operations
         * @target - STRIPE_OP_COMPUTE_BLK target
@@ -365,6 +366,14 @@ struct disk_info {
        struct md_rdev  *rdev, *replacement;
 };
 
+struct raid5_auxth {
+       struct md_thread        *thread;
+       /* which CPUs should the auxiliary thread handle stripes from */
+       cpumask_t               work_mask;
+       struct kobject          kobj;
+       struct work_struct      del_work;
+};
+
 struct r5conf {
        struct hlist_head       *stripe_hashtbl;
        struct mddev            *mddev;
@@ -433,6 +442,12 @@ struct r5conf {
                                              * lists and performing address
                                              * conversions
                                              */
+               struct list_head handle_list;
+               cpumask_t       handle_threads; /* Which threads can the CPU's
+                                                * stripes be handled. It really
+                                                * is a bitmap to aux_threads[],
+                                                * but has max bits NR_CPUS
+                                                */
        } __percpu *percpu;
        size_t                  scribble_len; /* size of scribble region must be
                                               * associated with conf to handle
@@ -460,6 +475,10 @@ struct r5conf {
         * the new thread here until we fully activate the array.
         */
        struct md_thread        *thread;
+       int                     aux_thread_num;
+       struct raid5_auxth      **aux_threads;
+       /* which CPUs should raid5d thread handle stripes from */
+       cpumask_t               work_mask;
 };
 
 /*
index 9fd9d1c5b218a5b51ff0522b9969db06e795706c..e575ae82771d5ffcefefc3950addf6d15fa73546 100644 (file)
@@ -41,7 +41,6 @@
 #include <linux/videodev2.h>
 
 #include <linux/platform_data/camera-mx2.h>
-#include <mach/hardware.h>
 
 #include <asm/dma.h>
 
 
 #define CSICR1                 0x00
 #define CSICR2                 0x04
-#define CSISR                  (cpu_is_mx27() ? 0x08 : 0x18)
+#define CSISR_IMX25            0x18
+#define CSISR_IMX27            0x08
 #define CSISTATFIFO            0x0c
 #define CSIRFIFO               0x10
 #define CSIRXCNT               0x14
-#define CSICR3                 (cpu_is_mx27() ? 0x1C : 0x08)
+#define CSICR3_IMX25           0x08
+#define CSICR3_IMX27           0x1c
 #define CSIDMASA_STATFIFO      0x20
 #define CSIDMATA_STATFIFO      0x24
 #define CSIDMASA_FB1           0x28
@@ -268,6 +269,11 @@ struct mx2_buffer {
        struct mx2_buf_internal         internal;
 };
 
+enum mx2_camera_type {
+       IMX25_CAMERA,
+       IMX27_CAMERA,
+};
+
 struct mx2_camera_dev {
        struct device           *dev;
        struct soc_camera_host  soc_host;
@@ -291,6 +297,9 @@ struct mx2_camera_dev {
        struct mx2_buffer       *fb2_active;
 
        u32                     csicr1;
+       u32                     reg_csisr;
+       u32                     reg_csicr3;
+       enum mx2_camera_type    devtype;
 
        struct mx2_buf_internal buf_discard[2];
        void                    *discard_buffer;
@@ -303,6 +312,29 @@ struct mx2_camera_dev {
        struct vb2_alloc_ctx    *alloc_ctx;
 };
 
+static struct platform_device_id mx2_camera_devtype[] = {
+       {
+               .name = "imx25-camera",
+               .driver_data = IMX25_CAMERA,
+       }, {
+               .name = "imx27-camera",
+               .driver_data = IMX27_CAMERA,
+       }, {
+               /* sentinel */
+       }
+};
+MODULE_DEVICE_TABLE(platform, mx2_camera_devtype);
+
+static inline int is_imx25_camera(struct mx2_camera_dev *pcdev)
+{
+       return pcdev->devtype == IMX25_CAMERA;
+}
+
+static inline int is_imx27_camera(struct mx2_camera_dev *pcdev)
+{
+       return pcdev->devtype == IMX27_CAMERA;
+}
+
 static struct mx2_buffer *mx2_ibuf_to_buf(struct mx2_buf_internal *int_buf)
 {
        return container_of(int_buf, struct mx2_buffer, internal);
@@ -434,9 +466,9 @@ static void mx2_camera_deactivate(struct mx2_camera_dev *pcdev)
 
        clk_disable_unprepare(pcdev->clk_csi);
        writel(0, pcdev->base_csi + CSICR1);
-       if (cpu_is_mx27()) {
+       if (is_imx27_camera(pcdev)) {
                writel(0, pcdev->base_emma + PRP_CNTL);
-       } else if (cpu_is_mx25()) {
+       } else if (is_imx25_camera(pcdev)) {
                spin_lock_irqsave(&pcdev->lock, flags);
                pcdev->fb1_active = NULL;
                pcdev->fb2_active = NULL;
@@ -466,7 +498,7 @@ static int mx2_camera_add_device(struct soc_camera_device *icd)
 
        csicr1 = CSICR1_MCLKEN;
 
-       if (cpu_is_mx27())
+       if (is_imx27_camera(pcdev))
                csicr1 |= CSICR1_PRP_IF_EN | CSICR1_FCC |
                        CSICR1_RXFF_LEVEL(0);
 
@@ -542,7 +574,7 @@ out:
 static irqreturn_t mx25_camera_irq(int irq_csi, void *data)
 {
        struct mx2_camera_dev *pcdev = data;
-       u32 status = readl(pcdev->base_csi + CSISR);
+       u32 status = readl(pcdev->base_csi + pcdev->reg_csisr);
 
        if (status & CSISR_DMA_TSF_FB1_INT)
                mx25_camera_frame_done(pcdev, 1, MX2_STATE_DONE);
@@ -551,7 +583,7 @@ static irqreturn_t mx25_camera_irq(int irq_csi, void *data)
 
        /* FIXME: handle CSISR_RFF_OR_INT */
 
-       writel(status, pcdev->base_csi + CSISR);
+       writel(status, pcdev->base_csi + pcdev->reg_csisr);
 
        return IRQ_HANDLED;
 }
@@ -636,7 +668,7 @@ static void mx2_videobuf_queue(struct vb2_buffer *vb)
        buf->state = MX2_STATE_QUEUED;
        list_add_tail(&buf->internal.queue, &pcdev->capture);
 
-       if (cpu_is_mx25()) {
+       if (is_imx25_camera(pcdev)) {
                u32 csicr3, dma_inten = 0;
 
                if (pcdev->fb1_active == NULL) {
@@ -655,20 +687,20 @@ static void mx2_videobuf_queue(struct vb2_buffer *vb)
                        list_del(&buf->internal.queue);
                        buf->state = MX2_STATE_ACTIVE;
 
-                       csicr3 = readl(pcdev->base_csi + CSICR3);
+                       csicr3 = readl(pcdev->base_csi + pcdev->reg_csicr3);
 
                        /* Reflash DMA */
                        writel(csicr3 | CSICR3_DMA_REFLASH_RFF,
-                                       pcdev->base_csi + CSICR3);
+                                       pcdev->base_csi + pcdev->reg_csicr3);
 
                        /* clear & enable interrupts */
-                       writel(dma_inten, pcdev->base_csi + CSISR);
+                       writel(dma_inten, pcdev->base_csi + pcdev->reg_csisr);
                        pcdev->csicr1 |= dma_inten;
                        writel(pcdev->csicr1, pcdev->base_csi + CSICR1);
 
                        /* enable DMA */
                        csicr3 |= CSICR3_DMA_REQ_EN_RFF | CSICR3_RXFF_LEVEL(1);
-                       writel(csicr3, pcdev->base_csi + CSICR3);
+                       writel(csicr3, pcdev->base_csi + pcdev->reg_csicr3);
                }
        }
 
@@ -712,7 +744,7 @@ static void mx2_videobuf_release(struct vb2_buffer *vb)
         */
 
        spin_lock_irqsave(&pcdev->lock, flags);
-       if (cpu_is_mx25() && buf->state == MX2_STATE_ACTIVE) {
+       if (is_imx25_camera(pcdev) && buf->state == MX2_STATE_ACTIVE) {
                if (pcdev->fb1_active == buf) {
                        pcdev->csicr1 &= ~CSICR1_FB1_DMA_INTEN;
                        writel(0, pcdev->base_csi + CSIDMASA_FB1);
@@ -835,7 +867,7 @@ static int mx2_start_streaming(struct vb2_queue *q, unsigned int count)
        unsigned long phys;
        int bytesperline;
 
-       if (cpu_is_mx27()) {
+       if (is_imx27_camera(pcdev)) {
                unsigned long flags;
                if (count < 2)
                        return -EINVAL;
@@ -930,7 +962,7 @@ static int mx2_stop_streaming(struct vb2_queue *q)
        void *b;
        u32 cntl;
 
-       if (cpu_is_mx27()) {
+       if (is_imx27_camera(pcdev)) {
                spin_lock_irqsave(&pcdev->lock, flags);
 
                cntl = readl(pcdev->base_emma + PRP_CNTL);
@@ -1082,11 +1114,11 @@ static int mx2_camera_set_bus_param(struct soc_camera_device *icd)
        if (bytesperline < 0)
                return bytesperline;
 
-       if (cpu_is_mx27()) {
+       if (is_imx27_camera(pcdev)) {
                ret = mx27_camera_emma_prp_reset(pcdev);
                if (ret)
                        return ret;
-       } else if (cpu_is_mx25()) {
+       } else if (is_imx25_camera(pcdev)) {
                writel((bytesperline * icd->user_height) >> 2,
                                pcdev->base_csi + CSIRXCNT);
                writel((bytesperline << 16) | icd->user_height,
@@ -1392,7 +1424,7 @@ static int mx2_camera_try_fmt(struct soc_camera_device *icd,
        /* FIXME: implement MX27 limits */
 
        /* limit to MX25 hardware capabilities */
-       if (cpu_is_mx25()) {
+       if (is_imx25_camera(pcdev)) {
                if (xlate->host_fmt->bits_per_sample <= 8)
                        width_limit = 0xffff * 4;
                else
@@ -1726,6 +1758,20 @@ static int __devinit mx2_camera_probe(struct platform_device *pdev)
                goto exit;
        }
 
+       pcdev->devtype = pdev->id_entry->driver_data;
+       switch (pcdev->devtype) {
+       case IMX25_CAMERA:
+               pcdev->reg_csisr = CSISR_IMX25;
+               pcdev->reg_csicr3 = CSICR3_IMX25;
+               break;
+       case IMX27_CAMERA:
+               pcdev->reg_csisr = CSISR_IMX27;
+               pcdev->reg_csicr3 = CSICR3_IMX27;
+               break;
+       default:
+               break;
+       }
+
        pcdev->clk_csi = devm_clk_get(&pdev->dev, "ahb");
        if (IS_ERR(pcdev->clk_csi)) {
                dev_err(&pdev->dev, "Could not get csi clock\n");
@@ -1763,7 +1809,7 @@ static int __devinit mx2_camera_probe(struct platform_device *pdev)
        pcdev->dev = &pdev->dev;
        platform_set_drvdata(pdev, pcdev);
 
-       if (cpu_is_mx25()) {
+       if (is_imx25_camera(pcdev)) {
                err = devm_request_irq(&pdev->dev, irq_csi, mx25_camera_irq, 0,
                                       MX2_CAM_DRV_NAME, pcdev);
                if (err) {
@@ -1772,7 +1818,7 @@ static int __devinit mx2_camera_probe(struct platform_device *pdev)
                }
        }
 
-       if (cpu_is_mx27()) {
+       if (is_imx27_camera(pcdev)) {
                err = mx27_camera_emma_init(pdev);
                if (err)
                        goto exit;
@@ -1789,7 +1835,7 @@ static int __devinit mx2_camera_probe(struct platform_device *pdev)
        pcdev->soc_host.priv            = pcdev;
        pcdev->soc_host.v4l2_dev.dev    = &pdev->dev;
        pcdev->soc_host.nr              = pdev->id;
-       if (cpu_is_mx25())
+       if (is_imx25_camera(pcdev))
                pcdev->soc_host.capabilities = SOCAM_HOST_CAP_STRIDE;
 
        pcdev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
@@ -1809,7 +1855,7 @@ static int __devinit mx2_camera_probe(struct platform_device *pdev)
 exit_free_emma:
        vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx);
 eallocctx:
-       if (cpu_is_mx27()) {
+       if (is_imx27_camera(pcdev)) {
                clk_disable_unprepare(pcdev->clk_emma_ipg);
                clk_disable_unprepare(pcdev->clk_emma_ahb);
        }
@@ -1827,7 +1873,7 @@ static int __devexit mx2_camera_remove(struct platform_device *pdev)
 
        vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx);
 
-       if (cpu_is_mx27()) {
+       if (is_imx27_camera(pcdev)) {
                clk_disable_unprepare(pcdev->clk_emma_ipg);
                clk_disable_unprepare(pcdev->clk_emma_ahb);
        }
@@ -1841,6 +1887,7 @@ static struct platform_driver mx2_camera_driver = {
        .driver         = {
                .name   = MX2_CAM_DRV_NAME,
        },
+       .id_table       = mx2_camera_devtype,
        .remove         = __devexit_p(mx2_camera_remove),
 };
 
index 3557ac97e4303f4743330850a5144f43cb06cbd0..64d39b1b5582c96027208850e8a708e7e8c29c05 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/vmalloc.h>
 #include <linux/interrupt.h>
 #include <linux/sched.h>
+#include <linux/dma/ipu-dma.h>
 
 #include <media/v4l2-common.h>
 #include <media/v4l2-dev.h>
@@ -24,7 +25,6 @@
 #include <media/soc_camera.h>
 #include <media/soc_mediabus.h>
 
-#include <mach/ipu.h>
 #include <linux/platform_data/camera-mx3.h>
 #include <linux/platform_data/dma-imx.h>
 
index 95f1814b5368c55bd05e7f2eef1c5759b476c41f..f79f2a88484da217c5ae5283668d5c2f469773e5 100644 (file)
@@ -24,3 +24,15 @@ config MSPRO_BLOCK
          support. This provides a block device driver, which you can use
          to mount the filesystem. Almost everyone wishing MemoryStick
          support should say Y or M here.
+
+config MS_BLOCK
+       tristate "MemoryStick Standard device driver"
+       depends on BLOCK && EXPERIMENTAL
+       help
+         Say Y here to enable the MemoryStick Standard device driver
+         support. This provides a block device driver, which you can use
+         to mount the filesystem.
+         This driver works with old (bulky) MemoryStick and MemoryStick Duo
+         but not PRO. Say Y if you have such card.
+         Driver is new and not yet well tested, thus it can damage your card
+         (even permanently)
index ecd0299377386fee7e062a87c9209a5ad36f22f1..0d7f90c0ff25d6a03ef85d0a6c950af465565321 100644 (file)
@@ -3,5 +3,5 @@
 #
 
 obj-$(CONFIG_MEMSTICK)         += memstick.o
-
+obj-$(CONFIG_MS_BLOCK)         += ms_block.o
 obj-$(CONFIG_MSPRO_BLOCK)      += mspro_block.o
diff --git a/drivers/memstick/core/ms_block.c b/drivers/memstick/core/ms_block.c
new file mode 100644 (file)
index 0000000..c815fe5
--- /dev/null
@@ -0,0 +1,2395 @@
+/*
+ *  ms_block.c - Sony MemoryStick (legacy) storage support
+
+ *  Copyright (C) 2012 Maxim Levitsky <maximlevitsky@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Minor portions of the driver were copied from mspro_block.c which is
+ * Copyright (C) 2007 Alex Dubov <oakad@yahoo.com>
+ *
+ */
+
+#define pr_fmt(fmt) DRIVER_NAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/blkdev.h>
+#include <linux/memstick.h>
+#include <linux/idr.h>
+#include <linux/hdreg.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/bitmap.h>
+#include <linux/scatterlist.h>
+#include <linux/jiffies.h>
+#include <linux/workqueue.h>
+#include <linux/mutex.h>
+#include "ms_block.h"
+
+static int debug;
+static int cache_flush_timeout = 1000;
+static bool verify_writes;
+
+/*
+ * Copies section of 'sg_from' starting from offset 'offset' and with length
+ * 'len' To another scatterlist of to_nents enties
+ */
+static size_t msb_sg_copy(struct scatterlist *sg_from, struct scatterlist *sg_to,
+                                       int to_nents, size_t offset, size_t len)
+{
+       size_t copied = 0;
+
+       while (offset > 0) {
+               if (offset >= sg_from->length) {
+                       if (sg_is_last(sg_from))
+                               return 0;
+
+                       offset -= sg_from->length;
+                       sg_from = sg_next(sg_from);
+                       continue;
+               }
+
+               copied = min(len, sg_from->length - offset);
+               sg_set_page(sg_to, sg_page(sg_from),
+                       copied, sg_from->offset + offset);
+
+               len -= copied;
+               offset = 0;
+
+               if (sg_is_last(sg_from) || !len)
+                       goto out;
+
+               sg_to = sg_next(sg_to);
+               to_nents--;
+               sg_from = sg_next(sg_from);
+       }
+
+       while (len > sg_from->length && to_nents--) {
+               len -= sg_from->length;
+               copied += sg_from->length;
+
+               sg_set_page(sg_to, sg_page(sg_from),
+                               sg_from->length, sg_from->offset);
+
+               if (sg_is_last(sg_from) || !len)
+                       goto out;
+
+               sg_from = sg_next(sg_from);
+               sg_to = sg_next(sg_to);
+       }
+
+       if (len && to_nents) {
+               sg_set_page(sg_to, sg_page(sg_from), len, sg_from->offset);
+               copied += len;
+       }
+out:
+       sg_mark_end(sg_to);
+       return copied;
+}
+
+/*
+ * Compares section of 'sg' starting from offset 'offset' and with length 'len'
+ * to linear buffer of length 'len' at address 'buffer'
+ * Returns 0 if equal and  -1 otherwice
+ */
+static int msb_sg_compare_to_buffer(struct scatterlist *sg,
+                                       size_t offset, u8 *buffer, size_t len)
+{
+       int retval = 0, cmplen;
+       struct sg_mapping_iter miter;
+
+       sg_miter_start(&miter, sg, sg_nents(sg),
+                                       SG_MITER_ATOMIC | SG_MITER_FROM_SG);
+
+       while (sg_miter_next(&miter) && len > 0) {
+               if (offset >= miter.length) {
+                       offset -= miter.length;
+                       continue;
+               }
+
+               cmplen = min(miter.length - offset, len);
+               retval = memcmp(miter.addr + offset, buffer, cmplen) ? -1 : 0;
+               if (retval)
+                       break;
+
+               buffer += cmplen;
+               len -= cmplen;
+               offset = 0;
+       }
+
+       if (!retval && len)
+               retval = -1;
+
+       sg_miter_stop(&miter);
+       return retval;
+}
+
+
+/* Get zone at which block with logical address 'lba' lives
+ * Flash is broken into zones.
+ * Each zone consists of 512 eraseblocks, out of which in first
+ * zone 494 are used and 496 are for all following zones.
+ * Therefore zone #0 hosts blocks 0-493, zone #1 blocks 494-988, etc...
+*/
+static int msb_get_zone_from_lba(int lba)
+{
+       if (lba < 494)
+               return 0;
+       return ((lba - 494) / 496) + 1;
+}
+
+/* Get zone of physical block. Trivial */
+static int msb_get_zone_from_pba(int pba)
+{
+       return pba / MS_BLOCKS_IN_ZONE;
+}
+
+/* Debug test to validate free block counts */
+#ifdef DEBUG
+static int msb_validate_used_block_bitmap(struct msb_data *msb)
+{
+       int total_free_blocks = 0;
+       int i;
+
+       for (i = 0 ; i < msb->zone_count ; i++)
+               total_free_blocks += msb->free_block_count[i];
+
+       if (msb->block_count - bitmap_weight(msb->used_blocks_bitmap,
+                                       msb->block_count) == total_free_blocks)
+               return 0;
+
+       pr_err("BUG: free block counts don't match the bitmap");
+       msb->read_only = true;
+       return -EINVAL;
+}
+#endif
+
+/* Mark physical block as used */
+static void msb_mark_block_used(struct msb_data *msb, int pba)
+{
+       int zone = msb_get_zone_from_pba(pba);
+
+       if (test_bit(pba, msb->used_blocks_bitmap)) {
+               pr_err(
+               "BUG: attempt to mark already used pba %d as used", pba);
+               msb->read_only = true;
+               return;
+       }
+
+#ifdef DEBUG
+       if (msb_validate_used_block_bitmap(msb))
+               return;
+#endif
+       /* No races because all IO is single threaded */
+       __set_bit(pba, msb->used_blocks_bitmap);
+       msb->free_block_count[zone]--;
+}
+
+/* Mark physical block as free */
+static void msb_mark_block_unused(struct msb_data *msb, int pba)
+{
+       int zone = msb_get_zone_from_pba(pba);
+
+       if (!test_bit(pba, msb->used_blocks_bitmap)) {
+               pr_err("BUG: attempt to mark "
+                               "already unused pba %d as unused" , pba);
+               msb->read_only = true;
+               return;
+       }
+
+#ifdef DEBUG
+       if (msb_validate_used_block_bitmap(msb))
+               return;
+#endif
+       /* No races because all IO is single threaded */
+       __clear_bit(pba, msb->used_blocks_bitmap);
+       msb->free_block_count[zone]++;
+}
+
+/* Invalidate current register window */
+static void msb_invalidate_reg_window(struct msb_data *msb)
+{
+       msb->reg_addr.w_offset = offsetof(struct ms_register, id);
+       msb->reg_addr.w_length = sizeof(struct ms_id_register);
+       msb->reg_addr.r_offset = offsetof(struct ms_register, id);
+       msb->reg_addr.r_length = sizeof(struct ms_id_register);
+       msb->addr_valid = false;
+}
+
+/* Start a state machine */
+static int msb_run_state_machine(struct msb_data *msb, int   (*state_func)
+               (struct memstick_dev *card, struct memstick_request **req))
+{
+       struct memstick_dev *card = msb->card;
+
+       WARN_ON(msb->state != -1);
+       msb->int_polling = false;
+       msb->state = 0;
+       msb->exit_error = 0;
+
+       memset(&card->current_mrq, 0, sizeof(card->current_mrq));
+
+       card->next_request = state_func;
+       memstick_new_req(card->host);
+       wait_for_completion(&card->mrq_complete);
+
+       WARN_ON(msb->state != -1);
+       return msb->exit_error;
+}
+
+/* State machines call that to exit */
+static int msb_exit_state_machine(struct msb_data *msb, int error)
+{
+       WARN_ON(msb->state == -1);
+
+       msb->state = -1;
+       msb->exit_error = error;
+       msb->card->next_request = h_msb_default_bad;
+
+       /* Invalidate reg window on errors */
+       if (error)
+               msb_invalidate_reg_window(msb);
+
+       complete(&msb->card->mrq_complete);
+       return -ENXIO;
+}
+
+/* read INT register */
+static int msb_read_int_reg(struct msb_data *msb, long timeout)
+{
+       struct memstick_request *mrq = &msb->card->current_mrq;
+
+       WARN_ON(msb->state == -1);
+
+       if (!msb->int_polling) {
+               msb->int_timeout = jiffies +
+                       msecs_to_jiffies(timeout == -1 ? 500 : timeout);
+               msb->int_polling = true;
+       } else if (time_after(jiffies, msb->int_timeout)) {
+               mrq->data[0] = MEMSTICK_INT_CMDNAK;
+               return 0;
+       }
+
+       if ((msb->caps & MEMSTICK_CAP_AUTO_GET_INT) &&
+                               mrq->need_card_int && !mrq->error) {
+               mrq->data[0] = mrq->int_reg;
+               mrq->need_card_int = false;
+               return 0;
+       } else {
+               memstick_init_req(mrq, MS_TPC_GET_INT, NULL, 1);
+               return 1;
+       }
+}
+
+/* Read a register */
+static int msb_read_regs(struct msb_data *msb, int offset, int len)
+{
+       struct memstick_request *req = &msb->card->current_mrq;
+
+       if (msb->reg_addr.r_offset != offset ||
+           msb->reg_addr.r_length != len || !msb->addr_valid) {
+
+               msb->reg_addr.r_offset = offset;
+               msb->reg_addr.r_length = len;
+               msb->addr_valid = true;
+
+               memstick_init_req(req, MS_TPC_SET_RW_REG_ADRS,
+                       &msb->reg_addr, sizeof(msb->reg_addr));
+               return 0;
+       }
+
+       memstick_init_req(req, MS_TPC_READ_REG, NULL, len);
+       return 1;
+}
+
+/* Write a card register */
+static int msb_write_regs(struct msb_data *msb, int offset, int len, void *buf)
+{
+       struct memstick_request *req = &msb->card->current_mrq;
+
+       if (msb->reg_addr.w_offset != offset ||
+               msb->reg_addr.w_length != len  || !msb->addr_valid) {
+
+               msb->reg_addr.w_offset = offset;
+               msb->reg_addr.w_length = len;
+               msb->addr_valid = true;
+
+               memstick_init_req(req, MS_TPC_SET_RW_REG_ADRS,
+                       &msb->reg_addr, sizeof(msb->reg_addr));
+               return 0;
+       }
+
+       memstick_init_req(req, MS_TPC_WRITE_REG, buf, len);
+       return 1;
+}
+
+/* Handler for absence of IO */
+static int h_msb_default_bad(struct memstick_dev *card,
+                                               struct memstick_request **mrq)
+{
+       return -ENXIO;
+}
+
+/*
+ * This function is a handler for reads of one page from device.
+ * Writes output to msb->current_sg, takes sector address from msb->reg.param
+ * Can also be used to read extra data only. Set params accordintly.
+ */
+static int h_msb_read_page(struct memstick_dev *card,
+                                       struct memstick_request **out_mrq)
+{
+       struct msb_data *msb = memstick_get_drvdata(card);
+       struct memstick_request *mrq = *out_mrq = &card->current_mrq;
+       struct scatterlist sg[2];
+       u8 command, intreg;
+
+       if (mrq->error) {
+               dbg("read_page, unknown error");
+               return msb_exit_state_machine(msb, mrq->error);
+       }
+again:
+       switch (msb->state) {
+       case MSB_RP_SEND_BLOCK_ADDRESS:
+               /* msb_write_regs sometimes "fails" because it needs to update
+                       the reg window, and thus it returns request for that.
+                       Then we stay in this state and retry */
+               if (!msb_write_regs(msb,
+                       offsetof(struct ms_register, param),
+                       sizeof(struct ms_param_register),
+                       (unsigned char *)&msb->regs.param))
+                       return 0;
+
+               msb->state = MSB_RP_SEND_READ_COMMAND;
+               return 0;
+
+       case MSB_RP_SEND_READ_COMMAND:
+               command = MS_CMD_BLOCK_READ;
+               memstick_init_req(mrq, MS_TPC_SET_CMD, &command, 1);
+               msb->state = MSB_RP_SEND_INT_REQ;
+               return 0;
+
+       case MSB_RP_SEND_INT_REQ:
+               msb->state = MSB_RP_RECEIVE_INT_REQ_RESULT;
+               /* If dont actually need to send the int read request (only in
+                       serial mode), then just fall through */
+               if (msb_read_int_reg(msb, -1))
+                       return 0;
+               /* fallthrough */
+
+       case MSB_RP_RECEIVE_INT_REQ_RESULT:
+               intreg = mrq->data[0];
+               msb->regs.status.interrupt = intreg;
+
+               if (intreg & MEMSTICK_INT_CMDNAK)
+                       return msb_exit_state_machine(msb, -EIO);
+
+               if (!(intreg & MEMSTICK_INT_CED)) {
+                       msb->state = MSB_RP_SEND_INT_REQ;
+                       goto again;
+               }
+
+               msb->int_polling = false;
+               msb->state = (intreg & MEMSTICK_INT_ERR) ?
+                       MSB_RP_SEND_READ_STATUS_REG : MSB_RP_SEND_OOB_READ;
+               goto again;
+
+       case MSB_RP_SEND_READ_STATUS_REG:
+                /* read the status register to understand source of the INT_ERR */
+               if (!msb_read_regs(msb,
+                       offsetof(struct ms_register, status),
+                       sizeof(struct ms_status_register)))
+                       return 0;
+
+               msb->state = MSB_RP_RECEIVE_OOB_READ;
+               return 0;
+
+       case MSB_RP_RECIVE_STATUS_REG:
+               msb->regs.status = *(struct ms_status_register *)mrq->data;
+               msb->state = MSB_RP_SEND_OOB_READ;
+               /* fallthrough */
+
+       case MSB_RP_SEND_OOB_READ:
+               if (!msb_read_regs(msb,
+                       offsetof(struct ms_register, extra_data),
+                       sizeof(struct ms_extra_data_register)))
+                       return 0;
+
+               msb->state = MSB_RP_RECEIVE_OOB_READ;
+               return 0;
+
+       case MSB_RP_RECEIVE_OOB_READ:
+               msb->regs.extra_data =
+                       *(struct ms_extra_data_register *) mrq->data;
+               msb->state = MSB_RP_SEND_READ_DATA;
+               /* fallthrough */
+
+       case MSB_RP_SEND_READ_DATA:
+               /* Skip that state if we only read the oob */
+               if (msb->regs.param.cp == MEMSTICK_CP_EXTRA) {
+                       msb->state = MSB_RP_RECEIVE_READ_DATA;
+                       goto again;
+               }
+
+               sg_init_table(sg, ARRAY_SIZE(sg));
+               msb_sg_copy(msb->current_sg, sg, ARRAY_SIZE(sg),
+                       msb->current_sg_offset,
+                       msb->page_size);
+
+               memstick_init_req_sg(mrq, MS_TPC_READ_LONG_DATA, sg);
+               msb->state = MSB_RP_RECEIVE_READ_DATA;
+               return 0;
+
+       case MSB_RP_RECEIVE_READ_DATA:
+               if (!(msb->regs.status.interrupt & MEMSTICK_INT_ERR)) {
+                       msb->current_sg_offset += msb->page_size;
+                       return msb_exit_state_machine(msb, 0);
+               }
+
+               if (msb->regs.status.status1 & MEMSTICK_UNCORR_ERROR) {
+                       dbg("read_page: uncorrectable error");
+                       return msb_exit_state_machine(msb, -EBADMSG);
+               }
+
+               if (msb->regs.status.status1 & MEMSTICK_CORR_ERROR) {
+                       dbg("read_page: correctable error");
+                       msb->current_sg_offset += msb->page_size;
+                       return msb_exit_state_machine(msb, -EUCLEAN);
+               } else {
+                       dbg("read_page: INT error, but no status error bits");
+                       return msb_exit_state_machine(msb, -EIO);
+               }
+       }
+
+       BUG();
+}
+
+/*
+ * Handler of writes of exactly one block.
+ * Takes address from msb->regs.param.
+ * Writes same extra data to blocks, also taken
+ * from msb->regs.extra
+ * Returns -EBADMSG if write fails due to uncorrectable error, or -EIO if
+ * device refuses to take the command or something else
+ */
+static int h_msb_write_block(struct memstick_dev *card,
+                                       struct memstick_request **out_mrq)
+{
+       struct msb_data *msb = memstick_get_drvdata(card);
+       struct memstick_request *mrq = *out_mrq = &card->current_mrq;
+       struct scatterlist sg[2];
+       u8 intreg, command;
+
+       if (mrq->error)
+               return msb_exit_state_machine(msb, mrq->error);
+
+again:
+       switch (msb->state) {
+
+       /* HACK: Jmicon handling of TPCs between 8 and
+        *      sizeof(memstick_request.data) is broken due to hardware
+        *      bug in PIO mode that is used for these TPCs
+        *      Therefore split the write
+        */
+
+       case MSB_WB_SEND_WRITE_PARAMS:
+               if (!msb_write_regs(msb,
+                       offsetof(struct ms_register, param),
+                       sizeof(struct ms_param_register),
+                       &msb->regs.param))
+                       return 0;
+
+               msb->state = MSB_WB_SEND_WRITE_OOB;
+               return 0;
+
+       case MSB_WB_SEND_WRITE_OOB:
+               if (!msb_write_regs(msb,
+                       offsetof(struct ms_register, extra_data),
+                       sizeof(struct ms_extra_data_register),
+                       &msb->regs.extra_data))
+                       return 0;
+               msb->state = MSB_WB_SEND_WRITE_COMMAND;
+               return 0;
+
+
+       case MSB_WB_SEND_WRITE_COMMAND:
+               command = MS_CMD_BLOCK_WRITE;
+               memstick_init_req(mrq, MS_TPC_SET_CMD, &command, 1);
+               msb->state = MSB_WB_SEND_INT_REQ;
+               return 0;
+
+       case MSB_WB_SEND_INT_REQ:
+               msb->state = MSB_WB_RECEIVE_INT_REQ;
+               if (msb_read_int_reg(msb, -1))
+                       return 0;
+               /* fallthrough */
+
+       case MSB_WB_RECEIVE_INT_REQ:
+               intreg = mrq->data[0];
+               msb->regs.status.interrupt = intreg;
+
+               /* errors mean out of here, and fast... */
+               if (intreg & (MEMSTICK_INT_CMDNAK))
+                       return msb_exit_state_machine(msb, -EIO);
+
+               if (intreg & MEMSTICK_INT_ERR)
+                       return msb_exit_state_machine(msb, -EBADMSG);
+
+
+               /* for last page we need to poll CED */
+               if (msb->current_page == msb->pages_in_block) {
+                       if (intreg & MEMSTICK_INT_CED)
+                               return msb_exit_state_machine(msb, 0);
+                       msb->state = MSB_WB_SEND_INT_REQ;
+                       goto again;
+
+               }
+
+               /* for non-last page we need BREQ before writing next chunk */
+               if (!(intreg & MEMSTICK_INT_BREQ)) {
+                       msb->state = MSB_WB_SEND_INT_REQ;
+                       goto again;
+               }
+
+               msb->int_polling = false;
+               msb->state = MSB_WB_SEND_WRITE_DATA;
+               /* fallthrough */
+
+       case MSB_WB_SEND_WRITE_DATA:
+               sg_init_table(sg, ARRAY_SIZE(sg));
+
+               if (msb_sg_copy(msb->current_sg, sg, ARRAY_SIZE(sg),
+                       msb->current_sg_offset,
+                       msb->page_size) < msb->page_size)
+                       return msb_exit_state_machine(msb, -EIO);
+
+               memstick_init_req_sg(mrq, MS_TPC_WRITE_LONG_DATA, sg);
+               mrq->need_card_int = 1;
+               msb->state = MSB_WB_RECEIVE_WRITE_CONFIRMATION;
+               return 0;
+
+       case MSB_WB_RECEIVE_WRITE_CONFIRMATION:
+               msb->current_page++;
+               msb->current_sg_offset += msb->page_size;
+               msb->state = MSB_WB_SEND_INT_REQ;
+               goto again;
+       default:
+               BUG();
+       }
+
+       return 0;
+}
+
+/*
+ * This function is used to send simple IO requests to device that consist
+ * of register write + command
+ */
+static int h_msb_send_command(struct memstick_dev *card,
+                                       struct memstick_request **out_mrq)
+{
+       struct msb_data *msb = memstick_get_drvdata(card);
+       struct memstick_request *mrq = *out_mrq = &card->current_mrq;
+       u8 intreg;
+
+       if (mrq->error) {
+               dbg("send_command: unknown error");
+               return msb_exit_state_machine(msb, mrq->error);
+       }
+again:
+       switch (msb->state) {
+
+       /* HACK: see h_msb_write_block */
+       case MSB_SC_SEND_WRITE_PARAMS: /* write param register*/
+               if (!msb_write_regs(msb,
+                       offsetof(struct ms_register, param),
+                       sizeof(struct ms_param_register),
+                       &msb->regs.param))
+                       return 0;
+               msb->state = MSB_SC_SEND_WRITE_OOB;
+               return 0;
+
+       case MSB_SC_SEND_WRITE_OOB:
+               if (!msb->command_need_oob) {
+                       msb->state = MSB_SC_SEND_COMMAND;
+                       goto again;
+               }
+
+               if (!msb_write_regs(msb,
+                       offsetof(struct ms_register, extra_data),
+                       sizeof(struct ms_extra_data_register),
+                       &msb->regs.extra_data))
+                       return 0;
+
+               msb->state = MSB_SC_SEND_COMMAND;
+               return 0;
+
+       case MSB_SC_SEND_COMMAND:
+               memstick_init_req(mrq, MS_TPC_SET_CMD, &msb->command_value, 1);
+               msb->state = MSB_SC_SEND_INT_REQ;
+               return 0;
+
+       case MSB_SC_SEND_INT_REQ:
+               msb->state = MSB_SC_RECEIVE_INT_REQ;
+               if (msb_read_int_reg(msb, -1))
+                       return 0;
+               /* fallthrough */
+
+       case MSB_SC_RECEIVE_INT_REQ:
+               intreg = mrq->data[0];
+
+               if (intreg & MEMSTICK_INT_CMDNAK)
+                       return msb_exit_state_machine(msb, -EIO);
+               if (intreg & MEMSTICK_INT_ERR)
+                       return msb_exit_state_machine(msb, -EBADMSG);
+
+               if (!(intreg & MEMSTICK_INT_CED)) {
+                       msb->state = MSB_SC_SEND_INT_REQ;
+                       goto again;
+               }
+
+               return msb_exit_state_machine(msb, 0);
+       }
+
+       BUG();
+}
+
+/* Small handler for card reset */
+static int h_msb_reset(struct memstick_dev *card,
+                                       struct memstick_request **out_mrq)
+{
+       u8 command = MS_CMD_RESET;
+       struct msb_data *msb = memstick_get_drvdata(card);
+       struct memstick_request *mrq = *out_mrq = &card->current_mrq;
+
+       if (mrq->error)
+               return msb_exit_state_machine(msb, mrq->error);
+
+       switch (msb->state) {
+       case MSB_RS_SEND:
+               memstick_init_req(mrq, MS_TPC_SET_CMD, &command, 1);
+               mrq->need_card_int = 0;
+               msb->state = MSB_RS_CONFIRM;
+               return 0;
+       case MSB_RS_CONFIRM:
+               return msb_exit_state_machine(msb, 0);
+       }
+       BUG();
+}
+
+/* This handler is used to do serial->parallel switch */
+static int h_msb_parallel_switch(struct memstick_dev *card,
+                                       struct memstick_request **out_mrq)
+{
+       struct msb_data *msb = memstick_get_drvdata(card);
+       struct memstick_request *mrq = *out_mrq = &card->current_mrq;
+       struct memstick_host *host = card->host;
+
+       if (mrq->error) {
+               dbg("parallel_switch: error");
+               msb->regs.param.system &= ~MEMSTICK_SYS_PAM;
+               return msb_exit_state_machine(msb, mrq->error);
+       }
+
+       switch (msb->state) {
+       case MSB_PS_SEND_SWITCH_COMMAND:
+               /* Set the parallel interface on memstick side */
+               msb->regs.param.system |= MEMSTICK_SYS_PAM;
+
+               if (!msb_write_regs(msb,
+                       offsetof(struct ms_register, param),
+                       1,
+                       (unsigned char *)&msb->regs.param))
+                       return 0;
+
+               msb->state = MSB_PS_SWICH_HOST;
+               return 0;
+
+       case MSB_PS_SWICH_HOST:
+                /* Set parallel interface on our side + send a dummy request
+                       to see if card responds */
+               host->set_param(host, MEMSTICK_INTERFACE, MEMSTICK_PAR4);
+               memstick_init_req(mrq, MS_TPC_GET_INT, NULL, 1);
+               msb->state = MSB_PS_CONFIRM;
+               return 0;
+
+       case MSB_PS_CONFIRM:
+               return msb_exit_state_machine(msb, 0);
+       }
+
+       BUG();
+}
+
+static int msb_switch_to_parallel(struct msb_data *msb);
+
+/* Reset the card, to guard against hw errors beeing treated as bad blocks */
+static int msb_reset(struct msb_data *msb, bool full)
+{
+
+       bool was_parallel = msb->regs.param.system & MEMSTICK_SYS_PAM;
+       struct memstick_dev *card = msb->card;
+       struct memstick_host *host = card->host;
+       int error;
+
+       /* Reset the card */
+       msb->regs.param.system = MEMSTICK_SYS_BAMD;
+
+       if (full) {
+               error =  host->set_param(host,
+                                       MEMSTICK_POWER, MEMSTICK_POWER_OFF);
+               if (error)
+                       goto out_error;
+
+               msb_invalidate_reg_window(msb);
+
+               error = host->set_param(host,
+                                       MEMSTICK_POWER, MEMSTICK_POWER_ON);
+               if (error)
+                       goto out_error;
+
+               error = host->set_param(host,
+                                       MEMSTICK_INTERFACE, MEMSTICK_SERIAL);
+               if (error) {
+out_error:
+                       dbg("Failed to reset the host controller");
+                       msb->read_only = true;
+                       return -EFAULT;
+               }
+       }
+
+       error = msb_run_state_machine(msb, h_msb_reset);
+       if (error) {
+               dbg("Failed to reset the card");
+               msb->read_only = true;
+               return -ENODEV;
+       }
+
+       /* Set parallel mode */
+       if (was_parallel)
+               msb_switch_to_parallel(msb);
+       return 0;
+}
+
+/* Attempts to switch interface to parallel mode */
+static int msb_switch_to_parallel(struct msb_data *msb)
+{
+       int error;
+
+       error = msb_run_state_machine(msb, h_msb_parallel_switch);
+       if (error) {
+               pr_err("Switch to parallel failed");
+               msb->regs.param.system &= ~MEMSTICK_SYS_PAM;
+               msb_reset(msb, true);
+               return -EFAULT;
+       }
+
+       msb->caps |= MEMSTICK_CAP_AUTO_GET_INT;
+       return 0;
+}
+
+/* Changes overwrite flag on a page */
+static int msb_set_overwrite_flag(struct msb_data *msb,
+                                               u16 pba, u8 page, u8 flag)
+{
+       if (msb->read_only)
+               return -EROFS;
+
+       msb->regs.param.block_address = cpu_to_be16(pba);
+       msb->regs.param.page_address = page;
+       msb->regs.param.cp = MEMSTICK_CP_OVERWRITE;
+       msb->regs.extra_data.overwrite_flag = flag;
+       msb->command_value = MS_CMD_BLOCK_WRITE;
+       msb->command_need_oob = true;
+
+       dbg_verbose("changing overwrite flag to %02x for sector %d, page %d",
+                                                       flag, pba, page);
+       return msb_run_state_machine(msb, h_msb_send_command);
+}
+
+static int msb_mark_bad(struct msb_data *msb, int pba)
+{
+       pr_notice("marking pba %d as bad", pba);
+       msb_reset(msb, true);
+       return msb_set_overwrite_flag(
+                       msb, pba, 0, 0xFF & ~MEMSTICK_OVERWRITE_BKST);
+}
+
+static int msb_mark_page_bad(struct msb_data *msb, int pba, int page)
+{
+       dbg("marking page %d of pba %d as bad", page, pba);
+       msb_reset(msb, true);
+       return msb_set_overwrite_flag(msb,
+               pba, page, ~MEMSTICK_OVERWRITE_PGST0);
+}
+
+/* Erases one physical block */
+static int msb_erase_block(struct msb_data *msb, u16 pba)
+{
+       int error, try;
+       if (msb->read_only)
+               return -EROFS;
+
+       dbg_verbose("erasing pba %d", pba);
+
+       for (try = 1 ; try < 3 ; try++) {
+               msb->regs.param.block_address = cpu_to_be16(pba);
+               msb->regs.param.page_address = 0;
+               msb->regs.param.cp = MEMSTICK_CP_BLOCK;
+               msb->command_value = MS_CMD_BLOCK_ERASE;
+               msb->command_need_oob = false;
+
+
+               error = msb_run_state_machine(msb, h_msb_send_command);
+               if (!error || msb_reset(msb, true))
+                       break;
+       }
+
+       if (error) {
+               pr_err("erase failed, marking pba %d as bad", pba);
+               msb_mark_bad(msb, pba);
+       }
+
+       dbg_verbose("erase success, marking pba %d as unused", pba);
+       msb_mark_block_unused(msb, pba);
+       __set_bit(pba, msb->erased_blocks_bitmap);
+       return error;
+}
+
+/* Reads one page from device */
+static int msb_read_page(struct msb_data *msb,
+       u16 pba, u8 page, struct ms_extra_data_register *extra,
+                                       struct scatterlist *sg,  int offset)
+{
+       int try, error;
+
+       if (pba == MS_BLOCK_INVALID) {
+               unsigned long flags;
+               struct sg_mapping_iter miter;
+               size_t len = msb->page_size;
+
+               dbg_verbose("read unmapped sector. returning 0xFF");
+
+               local_irq_save(flags);
+               sg_miter_start(&miter, sg, sg_nents(sg),
+                               SG_MITER_ATOMIC | SG_MITER_TO_SG);
+
+               while (sg_miter_next(&miter) && len > 0) {
+
+                       int chunklen;
+
+                       if (offset && offset >= miter.length) {
+                               offset -= miter.length;
+                               continue;
+                       }
+
+                       chunklen = min(miter.length - offset, len);
+                       memset(miter.addr + offset, 0xFF, chunklen);
+                       len -= chunklen;
+                       offset = 0;
+               }
+
+               sg_miter_stop(&miter);
+               local_irq_restore(flags);
+
+               if (offset)
+                       return -EFAULT;
+
+               if (extra)
+                       memset(extra, 0xFF, sizeof(*extra));
+               return 0;
+       }
+
+       if (pba >= msb->block_count) {
+               pr_err("BUG: attempt to read beyond"
+                                       " the end of the card at pba %d", pba);
+               return -EINVAL;
+       }
+
+       for (try = 1 ; try < 3 ; try++) {
+               msb->regs.param.block_address = cpu_to_be16(pba);
+               msb->regs.param.page_address = page;
+               msb->regs.param.cp = MEMSTICK_CP_PAGE;
+
+               msb->current_sg = sg;
+               msb->current_sg_offset = offset;
+               error = msb_run_state_machine(msb, h_msb_read_page);
+
+
+               if (error == -EUCLEAN) {
+                       pr_notice("correctable error on pba %d, page %d",
+                               pba, page);
+                       error = 0;
+               }
+
+               if (!error && extra)
+                       *extra = msb->regs.extra_data;
+
+               if (!error || msb_reset(msb, true))
+                       break;
+
+       }
+
+       /* Mark bad pages */
+       if (error == -EBADMSG) {
+               pr_err("uncorrectable error on read of pba %d, page %d",
+                       pba, page);
+
+               if (msb->regs.extra_data.overwrite_flag &
+                                       MEMSTICK_OVERWRITE_PGST0)
+                       msb_mark_page_bad(msb, pba, page);
+               return -EBADMSG;
+       }
+
+       if (error)
+               pr_err("read of pba %d, page %d failed with error %d",
+                       pba, page, error);
+       return error;
+}
+
+/* Reads oob of page only */
+static int msb_read_oob(struct msb_data *msb, u16 pba, u16 page,
+       struct ms_extra_data_register *extra)
+{
+       int error;
+
+       BUG_ON(!extra);
+       msb->regs.param.block_address = cpu_to_be16(pba);
+       msb->regs.param.page_address = page;
+       msb->regs.param.cp = MEMSTICK_CP_EXTRA;
+
+       if (pba > msb->block_count) {
+               pr_err("BUG: attempt to read beyond"
+                                       " the end of card at pba %d", pba);
+               return -EINVAL;
+       }
+
+       error = msb_run_state_machine(msb, h_msb_read_page);
+       *extra = msb->regs.extra_data;
+
+       if (error == -EUCLEAN) {
+               pr_notice("correctable error on pba %d, page %d",
+                       pba, page);
+               return 0;
+       }
+
+       return error;
+}
+
+
+/* Reads a block and compares it with data contained in scatterlist orig_sg */
+static int msb_verify_block(struct msb_data *msb, u16 pba,
+                               struct scatterlist *orig_sg,  int offset)
+{
+       struct scatterlist sg;
+       int page = 0, error;
+
+       sg_init_one(&sg, msb->block_buffer, msb->block_size);
+
+       while (page < msb->pages_in_block) {
+
+               error = msb_read_page(msb, pba, page,
+                               NULL, &sg, page * msb->page_size);
+               if (error)
+                       return error;
+               page++;
+       }
+
+       if (msb_sg_compare_to_buffer(orig_sg, offset,
+                               msb->block_buffer, msb->block_size))
+               return -EIO;
+       return 0;
+}
+
+/* Writes exectly one block + oob */
+static int msb_write_block(struct msb_data *msb,
+                       u16 pba, u32 lba, struct scatterlist *sg, int offset)
+{
+       int error, current_try = 1;
+       BUG_ON(sg->length < msb->page_size);
+
+       if (msb->read_only)
+               return -EROFS;
+
+       if (pba == MS_BLOCK_INVALID) {
+               pr_err(
+                       "BUG: write: attempt to write MS_BLOCK_INVALID block");
+               return -EINVAL;
+       }
+
+       if (pba >= msb->block_count || lba >= msb->logical_block_count) {
+               pr_err(
+               "BUG: write: attempt to write beyond the end of device");
+               return -EINVAL;
+       }
+
+       if (msb_get_zone_from_lba(lba) != msb_get_zone_from_pba(pba)) {
+               pr_err("BUG: write: lba zone mismatch");
+               return -EINVAL;
+       }
+
+       if (pba == msb->boot_block_locations[0] ||
+               pba == msb->boot_block_locations[1]) {
+               pr_err("BUG: write: attempt to write to boot blocks!");
+               return -EINVAL;
+       }
+
+       while (1) {
+
+               if (msb->read_only)
+                       return -EROFS;
+
+               msb->regs.param.cp = MEMSTICK_CP_BLOCK;
+               msb->regs.param.page_address = 0;
+               msb->regs.param.block_address = cpu_to_be16(pba);
+
+               msb->regs.extra_data.management_flag = 0xFF;
+               msb->regs.extra_data.overwrite_flag = 0xF8;
+               msb->regs.extra_data.logical_address = cpu_to_be16(lba);
+
+               msb->current_sg = sg;
+               msb->current_sg_offset = offset;
+               msb->current_page = 0;
+
+               error = msb_run_state_machine(msb, h_msb_write_block);
+
+               /* Sector we just wrote to is assumed erased since its pba
+                       was erased. If it wasn't erased, write will succeed
+                       and will just clear the bits that were set in the block
+                       thus test that what we have written,
+                       matches what we expect.
+                       We do trust the blocks that we erased */
+               if (!error && (verify_writes ||
+                               !test_bit(pba, msb->erased_blocks_bitmap)))
+                       error = msb_verify_block(msb, pba, sg, offset);
+
+               if (!error)
+                       break;
+
+               if (current_try > 1 || msb_reset(msb, true))
+                       break;
+
+               pr_err("write failed, trying to erase the pba %d", pba);
+               error = msb_erase_block(msb, pba);
+               if (error)
+                       break;
+
+               current_try++;
+       }
+       return error;
+}
+
+/* Finds a free block for write replacement */
+static u16 msb_get_free_block(struct msb_data *msb, int zone)
+{
+       u16 pos;
+       int pba = zone * MS_BLOCKS_IN_ZONE;
+       int i;
+
+       get_random_bytes(&pos, sizeof(pos));
+
+       if (!msb->free_block_count[zone]) {
+               pr_err("NO free blocks in the zone %d, to use for a write, "
+                       "(media is WORN out) switching to RO mode", zone);
+               msb->read_only = true;
+               return MS_BLOCK_INVALID;
+       }
+
+       pos %= msb->free_block_count[zone];
+
+       dbg_verbose("have %d choices for a free block, selected randomally: %d",
+               msb->free_block_count[zone], pos);
+
+       pba = find_next_zero_bit(msb->used_blocks_bitmap,
+                                                       msb->block_count, pba);
+       for (i = 0 ; i < pos ; ++i)
+               pba = find_next_zero_bit(msb->used_blocks_bitmap,
+                                               msb->block_count, pba + 1);
+
+       dbg_verbose("result of the free blocks scan: pba %d", pba);
+
+       if (pba == msb->block_count || (msb_get_zone_from_pba(pba)) != zone) {
+               pr_err("BUG: cant get a free block");
+               msb->read_only = true;
+               return MS_BLOCK_INVALID;
+       }
+
+       msb_mark_block_used(msb, pba);
+       return pba;
+}
+
+static int msb_update_block(struct msb_data *msb, u16 lba,
+       struct scatterlist *sg, int offset)
+{
+       u16 pba, new_pba;
+       int error, try;
+
+       pba = msb->lba_to_pba_table[lba];
+       dbg_verbose("start of a block update at lba  %d, pba %d", lba, pba);
+
+       if (pba != MS_BLOCK_INVALID) {
+               dbg_verbose("setting the update flag on the block");
+               msb_set_overwrite_flag(msb, pba, 0,
+                               0xFF & ~MEMSTICK_OVERWRITE_UDST);
+       }
+
+       for (try = 0 ; try < 3 ; try++) {
+               new_pba = msb_get_free_block(msb,
+                       msb_get_zone_from_lba(lba));
+
+               if (new_pba == MS_BLOCK_INVALID) {
+                       error = -EIO;
+                       goto out;
+               }
+
+               dbg_verbose("block update: writing updated block to the pba %d",
+                                                               new_pba);
+               error = msb_write_block(msb, new_pba, lba, sg, offset);
+               if (error == -EBADMSG) {
+                       msb_mark_bad(msb, new_pba);
+                       continue;
+               }
+
+               if (error)
+                       goto out;
+
+               dbg_verbose("block update: erasing the old block");
+               msb_erase_block(msb, pba);
+               msb->lba_to_pba_table[lba] = new_pba;
+               return 0;
+       }
+out:
+       if (error) {
+               pr_err("block update error after %d tries, "
+                                               "switching to r/o mode", try);
+               msb->read_only = true;
+       }
+       return error;
+}
+
+/* Converts endiannes in the boot block for easy use */
+static void msb_fix_boot_page_endianness(struct ms_boot_page *p)
+{
+       p->header.block_id = be16_to_cpu(p->header.block_id);
+       p->header.format_reserved = be16_to_cpu(p->header.format_reserved);
+       p->entry.disabled_block.start_addr
+               = be32_to_cpu(p->entry.disabled_block.start_addr);
+       p->entry.disabled_block.data_size
+               = be32_to_cpu(p->entry.disabled_block.data_size);
+       p->entry.cis_idi.start_addr
+               = be32_to_cpu(p->entry.cis_idi.start_addr);
+       p->entry.cis_idi.data_size
+               = be32_to_cpu(p->entry.cis_idi.data_size);
+       p->attr.block_size = be16_to_cpu(p->attr.block_size);
+       p->attr.number_of_blocks = be16_to_cpu(p->attr.number_of_blocks);
+       p->attr.number_of_effective_blocks
+               = be16_to_cpu(p->attr.number_of_effective_blocks);
+       p->attr.page_size = be16_to_cpu(p->attr.page_size);
+       p->attr.memory_manufacturer_code
+               = be16_to_cpu(p->attr.memory_manufacturer_code);
+       p->attr.memory_device_code = be16_to_cpu(p->attr.memory_device_code);
+       p->attr.implemented_capacity
+               = be16_to_cpu(p->attr.implemented_capacity);
+       p->attr.controller_number = be16_to_cpu(p->attr.controller_number);
+       p->attr.controller_function = be16_to_cpu(p->attr.controller_function);
+}
+
+static int msb_read_boot_blocks(struct msb_data *msb)
+{
+       int pba = 0;
+       struct scatterlist sg;
+       struct ms_extra_data_register extra;
+       struct ms_boot_page *page;
+
+       msb->boot_block_locations[0] = MS_BLOCK_INVALID;
+       msb->boot_block_locations[1] = MS_BLOCK_INVALID;
+       msb->boot_block_count = 0;
+
+       dbg_verbose("Start of a scan for the boot blocks");
+
+       if (!msb->boot_page) {
+               page = kmalloc(sizeof(struct ms_boot_page)*2, GFP_KERNEL);
+               if (!page)
+                       return -ENOMEM;
+
+               msb->boot_page = page;
+       } else
+               page = msb->boot_page;
+
+       msb->block_count = MS_BLOCK_MAX_BOOT_ADDR;
+
+       for (pba = 0 ; pba < MS_BLOCK_MAX_BOOT_ADDR ; pba++) {
+
+               sg_init_one(&sg, page, sizeof(*page));
+               if (msb_read_page(msb, pba, 0, &extra, &sg, 0)) {
+                       dbg("boot scan: can't read pba %d", pba);
+                       continue;
+               }
+
+               if (extra.management_flag & MEMSTICK_MANAGEMENT_SYSFLG) {
+                       dbg("managment flag doesn't indicate boot block %d",
+                                                                       pba);
+                       continue;
+               }
+
+               if (be16_to_cpu(page->header.block_id) != MS_BLOCK_BOOT_ID) {
+                       dbg("the pba at %d doesn' contain boot block ID", pba);
+                       continue;
+               }
+
+               msb_fix_boot_page_endianness(page);
+               msb->boot_block_locations[msb->boot_block_count] = pba;
+
+               page++;
+               msb->boot_block_count++;
+
+               if (msb->boot_block_count == 2)
+                       break;
+       }
+
+       if (!msb->boot_block_count) {
+               pr_err("media doesn't contain master page, aborting");
+               return -EIO;
+       }
+
+       dbg_verbose("End of scan for boot blocks");
+       return 0;
+}
+
+static int msb_read_bad_block_table(struct msb_data *msb, int block_nr)
+{
+       struct ms_boot_page *boot_block;
+       struct scatterlist sg;
+       u16 *buffer = NULL;
+       int offset = 0;
+       int i, error = 0;
+       int data_size, data_offset, page, page_offset, size_to_read;
+       u16 pba;
+
+       BUG_ON(block_nr > 1);
+       boot_block = &msb->boot_page[block_nr];
+       pba = msb->boot_block_locations[block_nr];
+
+       if (msb->boot_block_locations[block_nr] == MS_BLOCK_INVALID)
+               return -EINVAL;
+
+       data_size = boot_block->entry.disabled_block.data_size;
+       data_offset = sizeof(struct ms_boot_page) +
+                       boot_block->entry.disabled_block.start_addr;
+       if (!data_size)
+               return 0;
+
+       page = data_offset / msb->page_size;
+       page_offset = data_offset % msb->page_size;
+       size_to_read =
+               DIV_ROUND_UP(data_size + page_offset, msb->page_size) *
+                       msb->page_size;
+
+       dbg("reading bad block of boot block at pba %d, offset %d len %d",
+               pba, data_offset, data_size);
+
+       buffer = kzalloc(size_to_read, GFP_KERNEL);
+       if (!buffer)
+               return -ENOMEM;
+
+       /* Read the buffer */
+       sg_init_one(&sg, buffer, size_to_read);
+
+       while (offset < size_to_read) {
+               error = msb_read_page(msb, pba, page, NULL, &sg, offset);
+               if (error)
+                       goto out;
+
+               page++;
+               offset += msb->page_size;
+
+               if (page == msb->pages_in_block) {
+                       pr_err(
+                       "bad block table extends beyond the boot block");
+                       break;
+               }
+       }
+
+       /* Process the bad block table */
+       for (i = page_offset ; i < data_size / sizeof(u16) ; i++) {
+
+               u16 bad_block = be16_to_cpu(buffer[i]);
+
+               if (bad_block >= msb->block_count) {
+                       dbg("bad block table contains invalid block %d",
+                                                               bad_block);
+                       continue;
+               }
+
+               if (test_bit(bad_block, msb->used_blocks_bitmap))  {
+                       dbg("duplicate bad block %d in the table",
+                               bad_block);
+                       continue;
+               }
+
+               dbg("block %d is marked as factory bad", bad_block);
+               msb_mark_block_used(msb, bad_block);
+       }
+out:
+       kfree(buffer);
+       return error;
+}
+
+static int msb_ftl_initialize(struct msb_data *msb)
+{
+       int i;
+
+       if (msb->ftl_initialized)
+               return 0;
+
+       msb->zone_count = msb->block_count / MS_BLOCKS_IN_ZONE;
+       msb->logical_block_count = msb->zone_count * 496 - 2;
+
+       msb->used_blocks_bitmap = kzalloc(msb->block_count / 8, GFP_KERNEL);
+       msb->erased_blocks_bitmap = kzalloc(msb->block_count / 8, GFP_KERNEL);
+       msb->lba_to_pba_table =
+               kmalloc(msb->logical_block_count * sizeof(u16), GFP_KERNEL);
+
+       if (!msb->used_blocks_bitmap || !msb->lba_to_pba_table ||
+                                               !msb->erased_blocks_bitmap) {
+               kfree(msb->used_blocks_bitmap);
+               kfree(msb->lba_to_pba_table);
+               kfree(msb->erased_blocks_bitmap);
+               return -ENOMEM;
+       }
+
+       for (i = 0 ; i < msb->zone_count ; i++)
+               msb->free_block_count[i] = MS_BLOCKS_IN_ZONE;
+
+       memset(msb->lba_to_pba_table, MS_BLOCK_INVALID,
+                       msb->logical_block_count * sizeof(u16));
+
+       dbg("initial FTL tables created. Zone count = %d, "
+                                       "Logical block count = %d",
+               msb->zone_count, msb->logical_block_count);
+
+       msb->ftl_initialized = true;
+       return 0;
+}
+
+static int msb_ftl_scan(struct msb_data *msb)
+{
+       u16 pba, lba, other_block;
+       u8 overwrite_flag, managment_flag, other_overwrite_flag;
+       int error;
+       struct ms_extra_data_register extra;
+       u8 *overwrite_flags = kzalloc(msb->block_count, GFP_KERNEL);
+
+       if (!overwrite_flags)
+               return -ENOMEM;
+
+       dbg("Start of media scanning");
+       for (pba = 0 ; pba < msb->block_count ; pba++) {
+
+               if (pba == msb->boot_block_locations[0] ||
+                       pba == msb->boot_block_locations[1]) {
+                       dbg_verbose("pba %05d -> [boot block]", pba);
+                       msb_mark_block_used(msb, pba);
+                       continue;
+               }
+
+               if (test_bit(pba, msb->used_blocks_bitmap)) {
+                       dbg_verbose("pba %05d -> [factory bad]", pba);
+                       continue;
+               }
+
+               memset(&extra, 0, sizeof(extra));
+               error = msb_read_oob(msb, pba, 0, &extra);
+
+               /* can't trust the page if we can't read the oob */
+               if (error == -EBADMSG) {
+                       pr_notice(
+                       "oob of pba %d damaged, will try to erase it", pba);
+                       msb_mark_block_used(msb, pba);
+                       msb_erase_block(msb, pba);
+                       continue;
+               } else if (error)
+                       return error;
+
+               lba = be16_to_cpu(extra.logical_address);
+               managment_flag = extra.management_flag;
+               overwrite_flag = extra.overwrite_flag;
+               overwrite_flags[pba] = overwrite_flag;
+
+               /* Skip bad blocks */
+               if (!(overwrite_flag & MEMSTICK_OVERWRITE_BKST)) {
+                       dbg("pba %05d -> [BAD]", pba);
+                       msb_mark_block_used(msb, pba);
+                       continue;
+               }
+
+               /* Skip system/drm blocks */
+               if ((managment_flag & MEMSTICK_MANAGMENT_FLAG_NORMAL) !=
+                       MEMSTICK_MANAGMENT_FLAG_NORMAL) {
+                       dbg("pba %05d -> [reserved managment flag %02x]",
+                                                       pba, managment_flag);
+                       msb_mark_block_used(msb, pba);
+                       continue;
+               }
+
+               /* Erase temporary tables */
+               if (!(managment_flag & MEMSTICK_MANAGEMENT_ATFLG)) {
+                       dbg("pba %05d -> [temp table] - will erase", pba);
+
+                       msb_mark_block_used(msb, pba);
+                       msb_erase_block(msb, pba);
+                       continue;
+               }
+
+               if (lba == MS_BLOCK_INVALID) {
+                       dbg_verbose("pba %05d -> [free]", pba);
+                       continue;
+               }
+
+               msb_mark_block_used(msb, pba);
+
+               /* Block has LBA not according to zoning*/
+               if (msb_get_zone_from_lba(lba) != msb_get_zone_from_pba(pba)) {
+                       pr_notice("pba %05d -> [bad lba %05d] - will erase",
+                                                               pba, lba);
+                       msb_erase_block(msb, pba);
+                       continue;
+               }
+
+               /* No collisions - great */
+               if (msb->lba_to_pba_table[lba] == MS_BLOCK_INVALID) {
+                       dbg_verbose("pba %05d -> [lba %05d]", pba, lba);
+                       msb->lba_to_pba_table[lba] = pba;
+                       continue;
+               }
+
+               other_block = msb->lba_to_pba_table[lba];
+               other_overwrite_flag = overwrite_flags[other_block];
+
+               pr_notice("Collision between pba %d and pba %d",
+                       pba, other_block);
+
+               if (!(overwrite_flag & MEMSTICK_OVERWRITE_UDST)) {
+                       pr_notice("pba %d is marked as stable, use it", pba);
+                       msb_erase_block(msb, other_block);
+                       msb->lba_to_pba_table[lba] = pba;
+                       continue;
+               }
+
+               if (!(other_overwrite_flag & MEMSTICK_OVERWRITE_UDST)) {
+                       pr_notice("pba %d is marked as stable, use it",
+                                                               other_block);
+                       msb_erase_block(msb, pba);
+                       continue;
+               }
+
+               pr_notice("collision between blocks %d and %d,"
+               " without stable flag set on both, erasing pba %d",
+                               pba, other_block, other_block);
+
+               msb_erase_block(msb, other_block);
+               msb->lba_to_pba_table[lba] = pba;
+       }
+
+       dbg("End of media scanning");
+       kfree(overwrite_flags);
+       return 0;
+}
+
+static void msb_cache_flush_timer(unsigned long data)
+{
+       struct msb_data *msb = (struct msb_data *)data;
+       msb->need_flush_cache = true;
+       queue_work(msb->io_queue, &msb->io_work);
+}
+
+
+static void msb_cache_discard(struct msb_data *msb)
+{
+       if (msb->cache_block_lba == MS_BLOCK_INVALID)
+               return;
+
+       del_timer_sync(&msb->cache_flush_timer);
+
+       dbg_verbose("Discarding the write cache");
+       msb->cache_block_lba = MS_BLOCK_INVALID;
+       bitmap_zero(&msb->valid_cache_bitmap, msb->pages_in_block);
+}
+
+static int msb_cache_init(struct msb_data *msb)
+{
+       setup_timer(&msb->cache_flush_timer, msb_cache_flush_timer,
+               (unsigned long)msb);
+
+       if (!msb->cache)
+               msb->cache = kzalloc(msb->block_size, GFP_KERNEL);
+       if (!msb->cache)
+               return -ENOMEM;
+
+       msb_cache_discard(msb);
+       return 0;
+}
+
+static int msb_cache_flush(struct msb_data *msb)
+{
+       struct scatterlist sg;
+       struct ms_extra_data_register extra;
+       int page, offset, error;
+       u16 pba, lba;
+
+       if (msb->read_only)
+               return -EROFS;
+
+       if (msb->cache_block_lba == MS_BLOCK_INVALID)
+               return 0;
+
+       lba = msb->cache_block_lba;
+       pba = msb->lba_to_pba_table[lba];
+
+       dbg_verbose("Flushing the write cache of pba %d (LBA %d)",
+                                               pba, msb->cache_block_lba);
+
+       sg_init_one(&sg, msb->cache , msb->block_size);
+
+       /* Read all missing pages in cache */
+       for (page = 0 ; page < msb->pages_in_block ; page++) {
+
+               if (test_bit(page, &msb->valid_cache_bitmap))
+                       continue;
+
+               offset = page * msb->page_size;
+
+               dbg_verbose("reading non-present sector %d of cache block %d",
+                       page, lba);
+               error = msb_read_page(msb, pba, page, &extra, &sg, offset);
+
+               /* Bad pages are copied with 00 page status */
+               if (error == -EBADMSG) {
+                       pr_err("read error on sector %d, contents probably"
+                               " damaged", page);
+                       continue;
+               }
+
+               if (error)
+                       return error;
+
+               if ((extra.overwrite_flag & MEMSTICK_OV_PG_NORMAL) !=
+                                                       MEMSTICK_OV_PG_NORMAL) {
+                       dbg("page %d is marked as bad", page);
+                       continue;
+               }
+
+               set_bit(page, &msb->valid_cache_bitmap);
+       }
+
+       /* Write the cache now */
+       error = msb_update_block(msb, msb->cache_block_lba, &sg, 0);
+       pba = msb->lba_to_pba_table[msb->cache_block_lba];
+
+       /* Mark invalid pages */
+       if (!error) {
+               for (page = 0 ; page < msb->pages_in_block ; page++) {
+
+                       if (test_bit(page, &msb->valid_cache_bitmap))
+                               continue;
+
+                       dbg("marking page %d as containing damaged data",
+                               page);
+                       msb_set_overwrite_flag(msb,
+                               pba , page, 0xFF & ~MEMSTICK_OV_PG_NORMAL);
+               }
+       }
+
+       msb_cache_discard(msb);
+       return error;
+}
+
+static int msb_cache_write(struct msb_data *msb, int lba,
+       int page, bool add_to_cache_only, struct scatterlist *sg, int offset)
+{
+       int error;
+       struct scatterlist sg_tmp[10];
+
+       if (msb->read_only)
+               return -EROFS;
+
+       if (msb->cache_block_lba == MS_BLOCK_INVALID ||
+                                               lba != msb->cache_block_lba)
+               if (add_to_cache_only)
+                       return 0;
+
+       /* If we need to write different block */
+       if (msb->cache_block_lba != MS_BLOCK_INVALID &&
+                                               lba != msb->cache_block_lba) {
+               dbg_verbose("first flush the cache");
+               error = msb_cache_flush(msb);
+               if (error)
+                       return error;
+       }
+
+       if (msb->cache_block_lba  == MS_BLOCK_INVALID) {
+               msb->cache_block_lba  = lba;
+               mod_timer(&msb->cache_flush_timer,
+                       jiffies + msecs_to_jiffies(cache_flush_timeout));
+       }
+
+       dbg_verbose("Write of LBA %d page %d to cache ", lba, page);
+
+       sg_init_table(sg_tmp, ARRAY_SIZE(sg_tmp));
+       msb_sg_copy(sg, sg_tmp, ARRAY_SIZE(sg_tmp), offset, msb->page_size);
+
+       sg_copy_to_buffer(sg_tmp, sg_nents(sg_tmp),
+               msb->cache + page * msb->page_size, msb->page_size);
+
+       set_bit(page, &msb->valid_cache_bitmap);
+       return 0;
+}
+
+static int msb_cache_read(struct msb_data *msb, int lba,
+                               int page, struct scatterlist *sg, int offset)
+{
+       int pba = msb->lba_to_pba_table[lba];
+       struct scatterlist sg_tmp[10];
+       int error = 0;
+
+       if (lba == msb->cache_block_lba &&
+                       test_bit(page, &msb->valid_cache_bitmap)) {
+
+               dbg_verbose("Read of LBA %d (pba %d) sector %d from cache",
+                                                       lba, pba, page);
+
+               sg_init_table(sg_tmp, ARRAY_SIZE(sg_tmp));
+               msb_sg_copy(sg, sg_tmp, ARRAY_SIZE(sg_tmp), offset, msb->page_size);
+               sg_copy_from_buffer(sg_tmp, sg_nents(sg_tmp),
+                       msb->cache + msb->page_size * page,
+                                                       msb->page_size);
+       } else {
+               dbg_verbose("Read of LBA %d (pba %d) sector %d from device",
+                                                       lba, pba, page);
+
+               error = msb_read_page(msb, pba, page, NULL, sg, offset);
+               if (error)
+                       return error;
+
+               msb_cache_write(msb, lba, page, true, sg, offset);
+       }
+       return error;
+}
+
+/* Emulated geometry table
+ * This table content isn't that importaint,
+ * One could put here different values, providing that they still
+ * cover whole disk.
+ * 64 MB entry is what windows reports for my 64M memstick */
+
+static const struct chs_entry chs_table[] = {
+/*        size sectors cylynders  heads */
+       { 4,    16,    247,       2  },
+       { 8,    16,    495,       2  },
+       { 16,   16,    495,       4  },
+       { 32,   16,    991,       4  },
+       { 64,   16,    991,       8  },
+       {128,   16,    991,       16 },
+       { 0 }
+};
+
+/* Load information about the card */
+static int msb_init_card(struct memstick_dev *card)
+{
+       struct msb_data *msb = memstick_get_drvdata(card);
+       struct memstick_host *host = card->host;
+       struct ms_boot_page *boot_block;
+       int error = 0, i, raw_size_in_megs;
+
+       msb->caps = 0;
+
+       if (card->id.class >= MEMSTICK_CLASS_ROM &&
+                               card->id.class <= MEMSTICK_CLASS_ROM)
+               msb->read_only = true;
+
+       msb->state = -1;
+       error = msb_reset(msb, false);
+       if (error)
+               return error;
+
+       /* Due to a bug in Jmicron driver written by Alex Dubov,
+        its serial mode barely works,
+        so we switch to parallel mode right away */
+       if (host->caps & MEMSTICK_CAP_PAR4)
+               msb_switch_to_parallel(msb);
+
+       msb->page_size = sizeof(struct ms_boot_page);
+
+       /* Read the boot page */
+       error = msb_read_boot_blocks(msb);
+       if (error)
+               return -EIO;
+
+       boot_block = &msb->boot_page[0];
+
+       /* Save intersting attributes from boot page */
+       msb->block_count = boot_block->attr.number_of_blocks;
+       msb->page_size = boot_block->attr.page_size;
+
+       msb->pages_in_block = boot_block->attr.block_size * 2;
+       msb->block_size = msb->page_size * msb->pages_in_block;
+
+       if (msb->page_size > PAGE_SIZE) {
+               /* this isn't supported by linux at all, anyway*/
+               dbg("device page %d size isn't supported", msb->page_size);
+               return -EINVAL;
+       }
+
+       msb->block_buffer = kzalloc(msb->block_size, GFP_KERNEL);
+       if (!msb->block_buffer)
+               return -ENOMEM;
+
+       raw_size_in_megs = (msb->block_size * msb->block_count) >> 20;
+
+       for (i = 0 ; chs_table[i].size ; i++) {
+
+               if (chs_table[i].size != raw_size_in_megs)
+                       continue;
+
+               msb->geometry.cylinders = chs_table[i].cyl;
+               msb->geometry.heads = chs_table[i].head;
+               msb->geometry.sectors = chs_table[i].sec;
+               break;
+       }
+
+       if (boot_block->attr.transfer_supporting == 1)
+               msb->caps |= MEMSTICK_CAP_PAR4;
+
+       if (boot_block->attr.device_type & 0x03)
+               msb->read_only = true;
+
+       dbg("Total block count = %d", msb->block_count);
+       dbg("Each block consists of %d pages", msb->pages_in_block);
+       dbg("Page size = %d bytes", msb->page_size);
+       dbg("Parallel mode supported: %d", !!(msb->caps & MEMSTICK_CAP_PAR4));
+       dbg("Read only: %d", msb->read_only);
+
+#if 0
+       /* Now we can switch the interface */
+       if (host->caps & msb->caps & MEMSTICK_CAP_PAR4)
+               msb_switch_to_parallel(msb);
+#endif
+
+       error = msb_cache_init(msb);
+       if (error)
+               return error;
+
+       error = msb_ftl_initialize(msb);
+       if (error)
+               return error;
+
+
+       /* Read the bad block table */
+       error = msb_read_bad_block_table(msb, 0);
+
+       if (error && error != -ENOMEM) {
+               dbg("failed to read bad block table from primary boot block,"
+                                                       " trying from backup");
+               error = msb_read_bad_block_table(msb, 1);
+       }
+
+       if (error)
+               return error;
+
+       /* *drum roll* Scan the media */
+       error = msb_ftl_scan(msb);
+       if (error) {
+               pr_err("Scan of media failed");
+               return error;
+       }
+
+       return 0;
+
+}
+
+static int msb_do_write_request(struct msb_data *msb, int lba,
+       int page, struct scatterlist *sg, size_t len, int *sucessfuly_written)
+{
+       int error = 0;
+       off_t offset = 0;
+       *sucessfuly_written = 0;
+
+       while (offset < len) {
+               if (page == 0 && len - offset >= msb->block_size) {
+
+                       if (msb->cache_block_lba == lba)
+                               msb_cache_discard(msb);
+
+                       dbg_verbose("Writing whole lba %d", lba);
+                       error = msb_update_block(msb, lba, sg, offset);
+                       if (error)
+                               return error;
+
+                       offset += msb->block_size;
+                       *sucessfuly_written += msb->block_size;
+                       lba++;
+                       continue;
+               }
+
+               error = msb_cache_write(msb, lba, page, false, sg, offset);
+               if (error)
+                       return error;
+
+               offset += msb->page_size;
+               *sucessfuly_written += msb->page_size;
+
+               page++;
+               if (page == msb->pages_in_block) {
+                       page = 0;
+                       lba++;
+               }
+       }
+       return 0;
+}
+
+static int msb_do_read_request(struct msb_data *msb, int lba,
+               int page, struct scatterlist *sg, int len, int *sucessfuly_read)
+{
+       int error = 0;
+       int offset = 0;
+       *sucessfuly_read = 0;
+
+       while (offset < len) {
+
+               error = msb_cache_read(msb, lba, page, sg, offset);
+               if (error)
+                       return error;
+
+               offset += msb->page_size;
+               *sucessfuly_read += msb->page_size;
+
+               page++;
+               if (page == msb->pages_in_block) {
+                       page = 0;
+                       lba++;
+               }
+       }
+       return 0;
+}
+
+static void msb_io_work(struct work_struct *work)
+{
+       struct msb_data *msb = container_of(work, struct msb_data, io_work);
+       int page, error, len;
+       sector_t lba;
+       unsigned long flags;
+       struct scatterlist *sg = msb->prealloc_sg;
+
+       dbg_verbose("IO: work started");
+
+       while (1) {
+               spin_lock_irqsave(&msb->q_lock, flags);
+
+               if (msb->need_flush_cache) {
+                       msb->need_flush_cache = false;
+                       spin_unlock_irqrestore(&msb->q_lock, flags);
+                       msb_cache_flush(msb);
+                       continue;
+               }
+
+               if (!msb->req) {
+                       msb->req = blk_fetch_request(msb->queue);
+                       if (!msb->req) {
+                               dbg_verbose("IO: no more requests exiting");
+                               spin_unlock_irqrestore(&msb->q_lock, flags);
+                               return;
+                       }
+               }
+
+               spin_unlock_irqrestore(&msb->q_lock, flags);
+
+               /* If card was removed meanwhile */
+               if (!msb->req)
+                       return;
+
+               /* process the request */
+               dbg_verbose("IO: processing new request");
+               blk_rq_map_sg(msb->queue, msb->req, sg);
+
+               lba = blk_rq_pos(msb->req);
+
+               sector_div(lba, msb->page_size / 512);
+               page = do_div(lba, msb->pages_in_block);
+
+               if (rq_data_dir(msb->req) == READ)
+                       error = msb_do_read_request(msb, lba, page, sg,
+                               blk_rq_bytes(msb->req), &len);
+               else
+                       error = msb_do_write_request(msb, lba, page, sg,
+                               blk_rq_bytes(msb->req), &len);
+
+               spin_lock_irqsave(&msb->q_lock, flags);
+
+               if (len)
+                       if (!__blk_end_request(msb->req, 0, len))
+                               msb->req = NULL;
+
+               if (error && msb->req) {
+                       dbg_verbose("IO: ending one sector "
+                                       "of the request with error");
+                       if (!__blk_end_request(msb->req, error, msb->page_size))
+                               msb->req = NULL;
+               }
+
+               if (msb->req)
+                       dbg_verbose("IO: request still pending");
+
+               spin_unlock_irqrestore(&msb->q_lock, flags);
+       }
+}
+
+static DEFINE_IDR(msb_disk_idr); /*set of used disk numbers */
+static DEFINE_MUTEX(msb_disk_lock); /* protects against races in open/release */
+
+static int msb_bd_open(struct block_device *bdev, fmode_t mode)
+{
+       struct gendisk *disk = bdev->bd_disk;
+       struct msb_data *msb = disk->private_data;
+
+       dbg_verbose("block device open");
+
+       mutex_lock(&msb_disk_lock);
+
+       if (msb && msb->card)
+               msb->usage_count++;
+
+       mutex_unlock(&msb_disk_lock);
+       return 0;
+}
+
+static void msb_data_clear(struct msb_data *msb)
+{
+       kfree(msb->boot_page);
+       kfree(msb->used_blocks_bitmap);
+       kfree(msb->lba_to_pba_table);
+       kfree(msb->cache);
+       msb->card = NULL;
+}
+
+static int msb_disk_release(struct gendisk *disk)
+{
+       struct msb_data *msb = disk->private_data;
+
+       dbg_verbose("block device release");
+       mutex_lock(&msb_disk_lock);
+
+       if (msb) {
+               if (msb->usage_count)
+                       msb->usage_count--;
+
+               if (!msb->usage_count) {
+                       kfree(msb);
+                       disk->private_data = NULL;
+                       idr_remove(&msb_disk_idr, msb->disk_id);
+                       put_disk(disk);
+               }
+       }
+       mutex_unlock(&msb_disk_lock);
+       return 0;
+}
+
+static int msb_bd_release(struct gendisk *disk, fmode_t mode)
+{
+       return msb_disk_release(disk);
+}
+
+static int msb_bd_getgeo(struct block_device *bdev,
+                                struct hd_geometry *geo)
+{
+       struct msb_data *msb = bdev->bd_disk->private_data;
+       *geo = msb->geometry;
+       return 0;
+}
+
+static int msb_prepare_req(struct request_queue *q, struct request *req)
+{
+       if (req->cmd_type != REQ_TYPE_FS &&
+                               req->cmd_type != REQ_TYPE_BLOCK_PC) {
+               blk_dump_rq_flags(req, "MS unsupported request");
+               return BLKPREP_KILL;
+       }
+       req->cmd_flags |= REQ_DONTPREP;
+       return BLKPREP_OK;
+}
+
+static void msb_submit_req(struct request_queue *q)
+{
+       struct memstick_dev *card = q->queuedata;
+       struct msb_data *msb = memstick_get_drvdata(card);
+       struct request *req = NULL;
+
+       dbg_verbose("Submit request");
+
+       if (msb->card_dead) {
+               dbg("Refusing requests on removed card");
+
+               WARN_ON(!msb->io_queue_stopped);
+
+               while ((req = blk_fetch_request(q)) != NULL)
+                       __blk_end_request_all(req, -ENODEV);
+               return;
+       }
+
+       if (msb->req)
+               return;
+
+       if (!msb->io_queue_stopped)
+               queue_work(msb->io_queue, &msb->io_work);
+}
+
+static int msb_check_card(struct memstick_dev *card)
+{
+       struct msb_data *msb = memstick_get_drvdata(card);
+       return (msb->card_dead == 0);
+}
+
+static void msb_stop(struct memstick_dev *card)
+{
+       struct msb_data *msb = memstick_get_drvdata(card);
+       unsigned long flags;
+
+       dbg("Stopping all msblock IO");
+
+       spin_lock_irqsave(&msb->q_lock, flags);
+       blk_stop_queue(msb->queue);
+       msb->io_queue_stopped = true;
+       spin_unlock_irqrestore(&msb->q_lock, flags);
+
+       del_timer_sync(&msb->cache_flush_timer);
+       flush_workqueue(msb->io_queue);
+
+       if (msb->req) {
+               spin_lock_irqsave(&msb->q_lock, flags);
+               blk_requeue_request(msb->queue, msb->req);
+               msb->req = NULL;
+               spin_unlock_irqrestore(&msb->q_lock, flags);
+       }
+
+}
+
+static void msb_start(struct memstick_dev *card)
+{
+       struct msb_data *msb = memstick_get_drvdata(card);
+       unsigned long flags;
+
+       dbg("Resuming IO from msblock");
+
+       msb_invalidate_reg_window(msb);
+
+       spin_lock_irqsave(&msb->q_lock, flags);
+       if (!msb->io_queue_stopped || msb->card_dead) {
+               spin_unlock_irqrestore(&msb->q_lock, flags);
+               return;
+       }
+       spin_unlock_irqrestore(&msb->q_lock, flags);
+
+       /* Kick cache flush anyway, its harmless */
+       msb->need_flush_cache = true;
+       msb->io_queue_stopped = false;
+
+       spin_lock_irqsave(&msb->q_lock, flags);
+       blk_start_queue(msb->queue);
+       spin_unlock_irqrestore(&msb->q_lock, flags);
+
+       queue_work(msb->io_queue, &msb->io_work);
+
+}
+
+static const struct block_device_operations msb_bdops = {
+       .open    = msb_bd_open,
+       .release = msb_bd_release,
+       .getgeo  = msb_bd_getgeo,
+       .owner   = THIS_MODULE
+};
+
+/* Registers the block device */
+static int msb_init_disk(struct memstick_dev *card)
+{
+       struct msb_data *msb = memstick_get_drvdata(card);
+       struct memstick_host *host = card->host;
+       int rc;
+       u64 limit = BLK_BOUNCE_HIGH;
+       unsigned long capacity;
+
+       if (host->dev.dma_mask && *(host->dev.dma_mask))
+               limit = *(host->dev.dma_mask);
+
+       mutex_lock(&msb_disk_lock);
+       if (!idr_pre_get(&msb_disk_idr, GFP_KERNEL)) {
+               mutex_unlock(&msb_disk_lock);
+               return -ENOMEM;
+       }
+       rc = idr_get_new(&msb_disk_idr, card, &msb->disk_id);
+       mutex_unlock(&msb_disk_lock);
+
+       if (rc)
+               return rc;
+
+       msb->disk = alloc_disk(0);
+       if (!msb->disk) {
+               rc = -ENOMEM;
+               goto out_release_id;
+       }
+
+       msb->queue = blk_init_queue(msb_submit_req, &msb->q_lock);
+       if (!msb->queue) {
+               rc = -ENOMEM;
+               goto out_put_disk;
+       }
+
+       msb->queue->queuedata = card;
+       blk_queue_prep_rq(msb->queue, msb_prepare_req);
+
+       blk_queue_bounce_limit(msb->queue, limit);
+       blk_queue_max_hw_sectors(msb->queue, MS_BLOCK_MAX_PAGES);
+       blk_queue_max_segments(msb->queue, MS_BLOCK_MAX_SEGS);
+       blk_queue_max_segment_size(msb->queue,
+                                  MS_BLOCK_MAX_PAGES * msb->page_size);
+       blk_queue_logical_block_size(msb->queue, msb->page_size);
+
+       sprintf(msb->disk->disk_name, "msblk%d", msb->disk_id);
+       msb->disk->fops = &msb_bdops;
+       msb->disk->private_data = msb;
+       msb->disk->queue = msb->queue;
+       msb->disk->driverfs_dev = &card->dev;
+       msb->disk->flags |= GENHD_FL_EXT_DEVT;
+
+       capacity = msb->pages_in_block * msb->logical_block_count;
+       capacity *= (msb->page_size / 512);
+       set_capacity(msb->disk, capacity);
+       dbg("Set total disk size to %lu sectors", capacity);
+
+       msb->usage_count = 1;
+       msb->io_queue = alloc_ordered_workqueue("ms_block", WQ_MEM_RECLAIM);
+       INIT_WORK(&msb->io_work, msb_io_work);
+       sg_init_table(msb->prealloc_sg, MS_BLOCK_MAX_SEGS+1);
+
+       if (msb->read_only)
+               set_disk_ro(msb->disk, 1);
+
+       msb_start(card);
+       add_disk(msb->disk);
+       dbg("Disk added");
+       return 0;
+
+out_put_disk:
+       put_disk(msb->disk);
+out_release_id:
+       mutex_lock(&msb_disk_lock);
+       idr_remove(&msb_disk_idr, msb->disk_id);
+       mutex_unlock(&msb_disk_lock);
+       return rc;
+}
+
+static int msb_probe(struct memstick_dev *card)
+{
+       struct msb_data *msb;
+       int rc = 0;
+
+       msb = kzalloc(sizeof(struct msb_data), GFP_KERNEL);
+       if (!msb)
+               return -ENOMEM;
+       memstick_set_drvdata(card, msb);
+       msb->card = card;
+       spin_lock_init(&msb->q_lock);
+
+       rc = msb_init_card(card);
+       if (rc)
+               goto out_free;
+
+       rc = msb_init_disk(card);
+       if (!rc) {
+               card->check = msb_check_card;
+               card->stop = msb_stop;
+               card->start = msb_start;
+               return 0;
+       }
+out_free:
+       memstick_set_drvdata(card, NULL);
+       msb_data_clear(msb);
+       kfree(msb);
+       return rc;
+}
+
+static void msb_remove(struct memstick_dev *card)
+{
+       struct msb_data *msb = memstick_get_drvdata(card);
+       unsigned long flags;
+
+       if (!msb->io_queue_stopped)
+               msb_stop(card);
+
+       dbg("Removing the disk device");
+
+       /* Take care of unhandled + new requests from now on */
+       spin_lock_irqsave(&msb->q_lock, flags);
+       msb->card_dead = true;
+       blk_start_queue(msb->queue);
+       spin_unlock_irqrestore(&msb->q_lock, flags);
+
+       /* Remove the disk */
+       del_gendisk(msb->disk);
+       blk_cleanup_queue(msb->queue);
+       msb->queue = NULL;
+
+       mutex_lock(&msb_disk_lock);
+       msb_data_clear(msb);
+       mutex_unlock(&msb_disk_lock);
+
+       msb_disk_release(msb->disk);
+       memstick_set_drvdata(card, NULL);
+}
+
+#ifdef CONFIG_PM
+
+static int msb_suspend(struct memstick_dev *card, pm_message_t state)
+{
+       msb_stop(card);
+       return 0;
+}
+
+static int msb_resume(struct memstick_dev *card)
+{
+       struct msb_data *msb = memstick_get_drvdata(card);
+       struct msb_data *new_msb = NULL;
+       bool card_dead = true;
+
+#ifndef CONFIG_MEMSTICK_UNSAFE_RESUME
+       msb->card_dead = true;
+       return 0;
+#endif
+       mutex_lock(&card->host->lock);
+
+       new_msb = kzalloc(sizeof(struct msb_data), GFP_KERNEL);
+       if (!new_msb)
+               goto out;
+
+       new_msb->card = card;
+       memstick_set_drvdata(card, new_msb);
+       spin_lock_init(&new_msb->q_lock);
+       sg_init_table(msb->prealloc_sg, MS_BLOCK_MAX_SEGS+1);
+
+       if (msb_init_card(card))
+               goto out;
+
+       if (msb->block_size != new_msb->block_size)
+               goto out;
+
+       if (memcmp(msb->boot_page, new_msb->boot_page,
+                                       sizeof(struct ms_boot_page)))
+               goto out;
+
+       if (msb->logical_block_count != new_msb->logical_block_count ||
+               memcmp(msb->lba_to_pba_table, new_msb->lba_to_pba_table,
+                                               msb->logical_block_count))
+               goto out;
+
+       if (msb->block_count != new_msb->block_count ||
+               memcmp(msb->used_blocks_bitmap, new_msb->used_blocks_bitmap,
+                                                       msb->block_count / 8))
+               goto out;
+
+       card_dead = false;
+out:
+       if (card_dead)
+               dbg("Card was removed/replaced during suspend");
+
+       msb->card_dead = card_dead;
+       memstick_set_drvdata(card, msb);
+
+       if (new_msb) {
+               msb_data_clear(new_msb);
+               kfree(new_msb);
+       }
+
+       msb_start(card);
+       mutex_unlock(&card->host->lock);
+       return 0;
+}
+#else
+
+#define msb_suspend NULL
+#define msb_resume NULL
+
+#endif /* CONFIG_PM */
+
+static struct memstick_device_id msb_id_tbl[] = {
+       {MEMSTICK_MATCH_ALL, MEMSTICK_TYPE_LEGACY, MEMSTICK_CATEGORY_STORAGE,
+        MEMSTICK_CLASS_FLASH},
+
+       {MEMSTICK_MATCH_ALL, MEMSTICK_TYPE_LEGACY, MEMSTICK_CATEGORY_STORAGE,
+        MEMSTICK_CLASS_ROM},
+
+       {MEMSTICK_MATCH_ALL, MEMSTICK_TYPE_LEGACY, MEMSTICK_CATEGORY_STORAGE,
+        MEMSTICK_CLASS_RO},
+
+       {MEMSTICK_MATCH_ALL, MEMSTICK_TYPE_LEGACY, MEMSTICK_CATEGORY_STORAGE,
+        MEMSTICK_CLASS_WP},
+
+       {MEMSTICK_MATCH_ALL, MEMSTICK_TYPE_DUO, MEMSTICK_CATEGORY_STORAGE_DUO,
+        MEMSTICK_CLASS_DUO},
+       {}
+};
+MODULE_DEVICE_TABLE(memstick, msb_id_tbl);
+
+
+static struct memstick_driver msb_driver = {
+       .driver = {
+               .name  = DRIVER_NAME,
+               .owner = THIS_MODULE
+       },
+       .id_table = msb_id_tbl,
+       .probe    = msb_probe,
+       .remove   = msb_remove,
+       .suspend  = msb_suspend,
+       .resume   = msb_resume
+};
+
+static int major;
+
+static int __init msb_init(void)
+{
+       int rc = register_blkdev(0, DRIVER_NAME);
+
+       if (rc < 0) {
+               pr_err("failed to register major (error %d)\n", rc);
+               return rc;
+       }
+
+       major = rc;
+       rc = memstick_register_driver(&msb_driver);
+       if (rc) {
+               unregister_blkdev(major, DRIVER_NAME);
+               pr_err("failed to register memstick driver (error %d)\n", rc);
+       }
+
+       return rc;
+}
+
+static void __exit msb_exit(void)
+{
+       memstick_unregister_driver(&msb_driver);
+       unregister_blkdev(major, DRIVER_NAME);
+       idr_destroy(&msb_disk_idr);
+}
+
+module_init(msb_init);
+module_exit(msb_exit);
+
+module_param(cache_flush_timeout, int, S_IRUGO);
+MODULE_PARM_DESC(cache_flush_timeout,
+                               "Cache flush timeout in msec (1000 default)");
+module_param(debug, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug level (0-2)");
+
+module_param(verify_writes, bool, S_IRUGO);
+MODULE_PARM_DESC(verify_writes, "Read back and check all data that is written");
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Maxim Levitsky");
+MODULE_DESCRIPTION("Sony MemoryStick block device driver");
diff --git a/drivers/memstick/core/ms_block.h b/drivers/memstick/core/ms_block.h
new file mode 100644 (file)
index 0000000..6b5b83e
--- /dev/null
@@ -0,0 +1,293 @@
+/*
+ *  ms_block.c - Sony MemoryStick (legacy) storage support
+
+ *  Copyright (C) 2010 Maxim Levitsky <maximlevitsky@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Minor portions of the driver are copied from mspro_block.c which is
+ * Copyright (C) 2007 Alex Dubov <oakad@yahoo.com>
+ *
+ * Also ms structures were copied from old broken driver by same author
+ * These probably come from MS spec
+ *
+ */
+
+#ifndef MS_BLOCK_NEW_H
+#define MS_BLOCK_NEW_H
+
+#define MS_BLOCK_MAX_SEGS      32
+#define MS_BLOCK_MAX_PAGES     ((2 << 16) - 1)
+
+#define MS_BLOCK_MAX_BOOT_ADDR 0x000c
+#define MS_BLOCK_BOOT_ID       0x0001
+#define MS_BLOCK_INVALID       0xffff
+#define MS_MAX_ZONES           16
+#define MS_BLOCKS_IN_ZONE      512
+
+#define MS_BLOCK_MAP_LINE_SZ   16
+#define MS_BLOCK_PART_SHIFT    3
+
+
+#define MEMSTICK_UNCORR_ERROR (MEMSTICK_STATUS1_UCFG | \
+               MEMSTICK_STATUS1_UCEX | MEMSTICK_STATUS1_UCDT)
+
+#define MEMSTICK_CORR_ERROR (MEMSTICK_STATUS1_FGER | MEMSTICK_STATUS1_EXER | \
+       MEMSTICK_STATUS1_DTER)
+
+#define MEMSTICK_INT_ERROR (MEMSTICK_INT_CMDNAK | MEMSTICK_INT_ERR)
+
+#define MEMSTICK_OVERWRITE_FLAG_NORMAL \
+       (MEMSTICK_OVERWRITE_PGST1 | \
+       MEMSTICK_OVERWRITE_PGST0  | \
+       MEMSTICK_OVERWRITE_BKST)
+
+#define MEMSTICK_OV_PG_NORMAL \
+       (MEMSTICK_OVERWRITE_PGST1 | MEMSTICK_OVERWRITE_PGST0)
+
+#define MEMSTICK_MANAGMENT_FLAG_NORMAL \
+       (MEMSTICK_MANAGEMENT_SYSFLG |  \
+       MEMSTICK_MANAGEMENT_SCMS1   |  \
+       MEMSTICK_MANAGEMENT_SCMS0)     \
+
+struct ms_boot_header {
+       unsigned short block_id;
+       unsigned short format_reserved;
+       unsigned char  reserved0[184];
+       unsigned char  data_entry;
+       unsigned char  reserved1[179];
+} __packed;
+
+
+struct ms_system_item {
+       unsigned int  start_addr;
+       unsigned int  data_size;
+       unsigned char data_type_id;
+       unsigned char reserved[3];
+} __packed;
+
+struct ms_system_entry {
+       struct ms_system_item disabled_block;
+       struct ms_system_item cis_idi;
+       unsigned char         reserved[24];
+} __packed;
+
+struct ms_boot_attr_info {
+       unsigned char      memorystick_class;
+       unsigned char      format_unique_value1;
+       unsigned short     block_size;
+       unsigned short     number_of_blocks;
+       unsigned short     number_of_effective_blocks;
+       unsigned short     page_size;
+       unsigned char      extra_data_size;
+       unsigned char      format_unique_value2;
+       unsigned char      assembly_time[8];
+       unsigned char      format_unique_value3;
+       unsigned char      serial_number[3];
+       unsigned char      assembly_manufacturer_code;
+       unsigned char      assembly_model_code[3];
+       unsigned short     memory_manufacturer_code;
+       unsigned short     memory_device_code;
+       unsigned short     implemented_capacity;
+       unsigned char      format_unique_value4[2];
+       unsigned char      vcc;
+       unsigned char      vpp;
+       unsigned short     controller_number;
+       unsigned short     controller_function;
+       unsigned char      reserved0[9];
+       unsigned char      transfer_supporting;
+       unsigned short     format_unique_value5;
+       unsigned char      format_type;
+       unsigned char      memorystick_application;
+       unsigned char      device_type;
+       unsigned char      reserved1[22];
+       unsigned char      format_uniqure_value6[2];
+       unsigned char      reserved2[15];
+} __packed;
+
+struct ms_cis_idi {
+       unsigned short general_config;
+       unsigned short logical_cylinders;
+       unsigned short reserved0;
+       unsigned short logical_heads;
+       unsigned short track_size;
+       unsigned short page_size;
+       unsigned short pages_per_track;
+       unsigned short msw;
+       unsigned short lsw;
+       unsigned short reserved1;
+       unsigned char  serial_number[20];
+       unsigned short buffer_type;
+       unsigned short buffer_size_increments;
+       unsigned short long_command_ecc;
+       unsigned char  firmware_version[28];
+       unsigned char  model_name[18];
+       unsigned short reserved2[5];
+       unsigned short pio_mode_number;
+       unsigned short dma_mode_number;
+       unsigned short field_validity;
+       unsigned short current_logical_cylinders;
+       unsigned short current_logical_heads;
+       unsigned short current_pages_per_track;
+       unsigned int   current_page_capacity;
+       unsigned short mutiple_page_setting;
+       unsigned int   addressable_pages;
+       unsigned short single_word_dma;
+       unsigned short multi_word_dma;
+       unsigned char  reserved3[128];
+} __packed;
+
+
+struct ms_boot_page {
+       struct ms_boot_header    header;
+       struct ms_system_entry   entry;
+       struct ms_boot_attr_info attr;
+} __packed;
+
+struct msb_data {
+       unsigned int                    usage_count;
+       struct memstick_dev             *card;
+       struct gendisk                  *disk;
+       struct request_queue            *queue;
+       spinlock_t                      q_lock;
+       struct hd_geometry              geometry;
+       struct attribute_group          attr_group;
+       struct request                  *req;
+       int                             caps;
+       int                             disk_id;
+
+       /* IO */
+       struct workqueue_struct         *io_queue;
+       bool                            io_queue_stopped;
+       struct work_struct              io_work;
+       struct scatterlist              prealloc_sg[MS_BLOCK_MAX_SEGS+1];
+       bool                            card_dead;
+
+       /* Media properties */
+       struct ms_boot_page             *boot_page;
+       u16                             boot_block_locations[2];
+       int                             boot_block_count;
+
+       bool                            read_only;
+       unsigned short                  page_size;
+       int                             block_size;
+       int                             pages_in_block;
+       int                             zone_count;
+       int                             block_count;
+       int                             logical_block_count;
+
+       /* FTL tables */
+       unsigned long                   *used_blocks_bitmap;
+       unsigned long                   *erased_blocks_bitmap;
+       u16                             *lba_to_pba_table;
+       int                             free_block_count[MS_MAX_ZONES];
+       bool                            ftl_initialized;
+
+       /* Cache */
+       unsigned char                   *cache;
+       unsigned long                   valid_cache_bitmap;
+       int                             cache_block_lba;
+       bool                            need_flush_cache;
+       struct timer_list               cache_flush_timer;
+
+       /* Preallocated buffers */
+       unsigned char                   *block_buffer;
+       struct scatterlist              sg[MS_BLOCK_MAX_SEGS+1];
+
+
+       /* handler's local data */
+       struct ms_register_addr         reg_addr;
+       bool                            addr_valid;
+
+       u8                              command_value;
+       bool                            command_need_oob;
+       struct scatterlist              *current_sg;
+       int                             current_sg_offset;
+
+       struct ms_register              regs;
+       int                             current_page;
+
+       int                             state;
+       int                             exit_error;
+       bool                            int_polling;
+       unsigned long                   int_timeout;
+
+};
+
+enum msb_readpage_states {
+       MSB_RP_SEND_BLOCK_ADDRESS = 0,
+       MSB_RP_SEND_READ_COMMAND,
+
+       MSB_RP_SEND_INT_REQ,
+       MSB_RP_RECEIVE_INT_REQ_RESULT,
+
+       MSB_RP_SEND_READ_STATUS_REG,
+       MSB_RP_RECIVE_STATUS_REG,
+
+       MSB_RP_SEND_OOB_READ,
+       MSB_RP_RECEIVE_OOB_READ,
+
+       MSB_RP_SEND_READ_DATA,
+       MSB_RP_RECEIVE_READ_DATA,
+};
+
+enum msb_write_block_states {
+       MSB_WB_SEND_WRITE_PARAMS = 0,
+       MSB_WB_SEND_WRITE_OOB,
+       MSB_WB_SEND_WRITE_COMMAND,
+
+       MSB_WB_SEND_INT_REQ,
+       MSB_WB_RECEIVE_INT_REQ,
+
+       MSB_WB_SEND_WRITE_DATA,
+       MSB_WB_RECEIVE_WRITE_CONFIRMATION,
+};
+
+enum msb_send_command_states {
+       MSB_SC_SEND_WRITE_PARAMS,
+       MSB_SC_SEND_WRITE_OOB,
+       MSB_SC_SEND_COMMAND,
+
+       MSB_SC_SEND_INT_REQ,
+       MSB_SC_RECEIVE_INT_REQ,
+
+};
+
+enum msb_reset_states {
+       MSB_RS_SEND,
+       MSB_RS_CONFIRM,
+};
+
+enum msb_par_switch_states {
+       MSB_PS_SEND_SWITCH_COMMAND,
+       MSB_PS_SWICH_HOST,
+       MSB_PS_CONFIRM,
+};
+
+struct chs_entry {
+       unsigned long size;
+       unsigned char sec;
+       unsigned short cyl;
+       unsigned char head;
+};
+
+static int msb_reset(struct msb_data *msb, bool full);
+
+static int h_msb_default_bad(struct memstick_dev *card,
+                                               struct memstick_request **mrq);
+
+#define DRIVER_NAME "ms_block"
+
+#define __dbg(level, format, ...) \
+       do { \
+               if (debug >= level) \
+                       pr_err(format "\n", ## __VA_ARGS__); \
+       } while (0)
+
+
+#define dbg(format, ...)               __dbg(1, format, ## __VA_ARGS__)
+#define dbg_verbose(format, ...)       __dbg(2, format, ## __VA_ARGS__)
+
+#endif
index 5bb1877810749da2581aff03c6d7d50c18b875c3..ac00f83ea86b44311a4cb307676939a9bcf3a73e 100644 (file)
@@ -68,39 +68,35 @@ void ssc_free(struct ssc_device *ssc)
 }
 EXPORT_SYMBOL(ssc_free);
 
-static int __init ssc_probe(struct platform_device *pdev)
+static int ssc_probe(struct platform_device *pdev)
 {
-       int retval = 0;
        struct resource *regs;
        struct ssc_device *ssc;
 
-       ssc = kzalloc(sizeof(struct ssc_device), GFP_KERNEL);
+       ssc = devm_kzalloc(&pdev->dev, sizeof(struct ssc_device), GFP_KERNEL);
        if (!ssc) {
                dev_dbg(&pdev->dev, "out of memory\n");
-               retval = -ENOMEM;
-               goto out;
+               return -ENOMEM;
        }
 
+       ssc->pdev = pdev;
+
        regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!regs) {
                dev_dbg(&pdev->dev, "no mmio resource defined\n");
-               retval = -ENXIO;
-               goto out_free;
-       }
-
-       ssc->clk = clk_get(&pdev->dev, "pclk");
-       if (IS_ERR(ssc->clk)) {
-               dev_dbg(&pdev->dev, "no pclk clock defined\n");
-               retval = -ENXIO;
-               goto out_free;
+               return -ENXIO;
        }
 
-       ssc->pdev = pdev;
-       ssc->regs = ioremap(regs->start, resource_size(regs));
+       ssc->regs = devm_request_and_ioremap(&pdev->dev, regs);
        if (!ssc->regs) {
                dev_dbg(&pdev->dev, "ioremap failed\n");
-               retval = -EINVAL;
-               goto out_clk;
+               return -EINVAL;
+       }
+
+       ssc->clk = devm_clk_get(&pdev->dev, "pclk");
+       if (IS_ERR(ssc->clk)) {
+               dev_dbg(&pdev->dev, "no pclk clock defined\n");
+               return -ENXIO;
        }
 
        /* disable all interrupts */
@@ -112,8 +108,7 @@ static int __init ssc_probe(struct platform_device *pdev)
        ssc->irq = platform_get_irq(pdev, 0);
        if (!ssc->irq) {
                dev_dbg(&pdev->dev, "could not get irq\n");
-               retval = -ENXIO;
-               goto out_unmap;
+               return -ENXIO;
        }
 
        spin_lock(&user_lock);
@@ -125,16 +120,7 @@ static int __init ssc_probe(struct platform_device *pdev)
        dev_info(&pdev->dev, "Atmel SSC device at 0x%p (irq %d)\n",
                        ssc->regs, ssc->irq);
 
-       goto out;
-
-out_unmap:
-       iounmap(ssc->regs);
-out_clk:
-       clk_put(ssc->clk);
-out_free:
-       kfree(ssc);
-out:
-       return retval;
+       return 0;
 }
 
 static int __devexit ssc_remove(struct platform_device *pdev)
@@ -142,34 +128,21 @@ static int __devexit ssc_remove(struct platform_device *pdev)
        struct ssc_device *ssc = platform_get_drvdata(pdev);
 
        spin_lock(&user_lock);
-       iounmap(ssc->regs);
-       clk_put(ssc->clk);
        list_del(&ssc->list);
-       kfree(ssc);
        spin_unlock(&user_lock);
 
        return 0;
 }
 
 static struct platform_driver ssc_driver = {
-       .remove         = __devexit_p(ssc_remove),
        .driver         = {
                .name           = "ssc",
                .owner          = THIS_MODULE,
        },
+       .probe          = ssc_probe,
+       .remove         = __devexit_p(ssc_remove),
 };
-
-static int __init ssc_init(void)
-{
-       return platform_driver_probe(&ssc_driver, ssc_probe);
-}
-module_init(ssc_init);
-
-static void __exit ssc_exit(void)
-{
-       platform_driver_unregister(&ssc_driver);
-}
-module_exit(ssc_exit);
+module_platform_driver(ssc_driver);
 
 MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>");
 MODULE_DESCRIPTION("SSC driver for Atmel AVR32 and AT91");
index 98f1430e3e1446b272725bffbf25da609c0aa3e7..1f13eb97a10a43ae84e0d4f5def8e3b40ed5daf8 100644 (file)
@@ -47,35 +47,23 @@ const uuid_le mei_amthi_guid  = UUID_LE(0x12f80028, 0xb4b7, 0x4b2d, 0xac,
                                                0xa8, 0x46, 0xe0, 0xff, 0x65,
                                                0x81, 0x4c);
 
-/**
- * mei_io_list_init - Sets up a queue list.
- *
- * @list: An instance io list structure
- * @dev: the device structure
- */
-void mei_io_list_init(struct mei_io_list *list)
-{
-       /* initialize our queue list */
-       INIT_LIST_HEAD(&list->mei_cb.cb_list);
-}
-
 /**
  * mei_io_list_flush - removes list entry belonging to cl.
  *
  * @list:  An instance of our list structure
  * @cl: private data of the file object
  */
-void mei_io_list_flush(struct mei_io_list *list, struct mei_cl *cl)
+void mei_io_list_flush(struct mei_cl_cb *list, struct mei_cl *cl)
 {
        struct mei_cl_cb *pos;
        struct mei_cl_cb *next;
 
-       list_for_each_entry_safe(pos, next, &list->mei_cb.cb_list, cb_list) {
+       list_for_each_entry_safe(pos, next, &list->list, list) {
                if (pos->file_private) {
                        struct mei_cl *cl_tmp;
                        cl_tmp = (struct mei_cl *)pos->file_private;
                        if (mei_cl_cmp_id(cl, cl_tmp))
-                               list_del(&pos->cb_list);
+                               list_del(&pos->list);
                }
        }
 }
@@ -351,10 +339,9 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled)
                }
        }
        /* remove all waiting requests */
-       list_for_each_entry_safe(cb_pos, cb_next,
-                       &dev->write_list.mei_cb.cb_list, cb_list) {
-               list_del(&cb_pos->cb_list);
-               mei_free_cb_private(cb_pos);
+       list_for_each_entry_safe(cb_pos, cb_next, &dev->write_list.list, list) {
+               list_del(&cb_pos->list);
+               mei_io_cb_free(cb_pos);
        }
 }
 
@@ -681,12 +668,10 @@ int mei_disconnect_host_client(struct mei_device *dev, struct mei_cl *cl)
        if (cl->state != MEI_FILE_DISCONNECTING)
                return 0;
 
-       cb = kzalloc(sizeof(struct mei_cl_cb), GFP_KERNEL);
+       cb = mei_io_cb_init(cl, NULL);
        if (!cb)
                return -ENOMEM;
 
-       INIT_LIST_HEAD(&cb->cb_list);
-       cb->file_private = cl;
        cb->major_file_operations = MEI_CLOSE;
        if (dev->mei_host_buffer_is_empty) {
                dev->mei_host_buffer_is_empty = false;
@@ -696,11 +681,11 @@ int mei_disconnect_host_client(struct mei_device *dev, struct mei_cl *cl)
                        goto free;
                }
                mdelay(10); /* Wait for hardware disconnection ready */
-               list_add_tail(&cb->cb_list, &dev->ctrl_rd_list.mei_cb.cb_list);
+               list_add_tail(&cb->list, &dev->ctrl_rd_list.list);
        } else {
                dev_dbg(&dev->pdev->dev, "add disconnect cb to control write list\n");
-               list_add_tail(&cb->cb_list,
-                               &dev->ctrl_wr_list.mei_cb.cb_list);
+               list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
+
        }
        mutex_unlock(&dev->device_lock);
 
@@ -728,7 +713,7 @@ int mei_disconnect_host_client(struct mei_device *dev, struct mei_cl *cl)
        mei_io_list_flush(&dev->ctrl_rd_list, cl);
        mei_io_list_flush(&dev->ctrl_wr_list, cl);
 free:
-       mei_free_cb_private(cb);
+       mei_io_cb_free(cb);
        return rets;
 }
 
index 3533edde04a525518624111b86e3b4c76c1c699d..5c65bac2fdecc321655d6b8503f7f73db13996c0 100644 (file)
@@ -58,7 +58,7 @@ irqreturn_t mei_interrupt_quick_handler(int irq, void *dev_id)
 static void _mei_cmpl(struct mei_cl *cl, struct mei_cl_cb *cb_pos)
 {
        if (cb_pos->major_file_operations == MEI_WRITE) {
-               mei_free_cb_private(cb_pos);
+               mei_io_cb_free(cb_pos);
                cb_pos = NULL;
                cl->writing_state = MEI_WRITE_COMPLETE;
                if (waitqueue_active(&cl->tx_wait))
@@ -87,9 +87,8 @@ static void _mei_cmpl_iamthif(struct mei_device *dev, struct mei_cl_cb *cb_pos)
                memcpy(cb_pos->response_buffer.data,
                                dev->iamthif_msg_buf,
                                dev->iamthif_msg_buf_index);
-               list_add_tail(&cb_pos->cb_list,
-                               &dev->amthi_read_complete_list.mei_cb.cb_list);
-               dev_dbg(&dev->pdev->dev, "amthi read completed.\n");
+               list_add_tail(&cb_pos->list, &dev->amthi_read_complete_list.list);
+               dev_dbg(&dev->pdev->dev, "amthi read completed\n");
                dev->iamthif_timer = jiffies;
                dev_dbg(&dev->pdev->dev, "dev->iamthif_timer = %ld\n",
                                dev->iamthif_timer);
@@ -112,7 +111,7 @@ static void _mei_cmpl_iamthif(struct mei_device *dev, struct mei_cl_cb *cb_pos)
  *
  * returns 0 on success, <0 on failure.
  */
-static int mei_irq_thread_read_amthi_message(struct mei_io_list *complete_list,
+static int mei_irq_thread_read_amthi_message(struct mei_cl_cb *complete_list,
                struct mei_device *dev,
                struct mei_msg_hdr *mei_hdr)
 {
@@ -149,14 +148,13 @@ static int mei_irq_thread_read_amthi_message(struct mei_io_list *complete_list,
                return -ENODEV;
 
        dev->iamthif_stall_timer = 0;
-       cb->information =       dev->iamthif_msg_buf_index;
+       cb->buf_idx = dev->iamthif_msg_buf_index;
        cb->read_time = jiffies;
        if (dev->iamthif_ioctl && cl == &dev->iamthif_cl) {
                /* found the iamthif cb */
                dev_dbg(&dev->pdev->dev, "complete the amthi read cb.\n ");
                dev_dbg(&dev->pdev->dev, "add the amthi read cb to complete.\n ");
-               list_add_tail(&cb->cb_list,
-                                               &complete_list->mei_cb.cb_list);
+               list_add_tail(&cb->list, &complete_list->list);
        }
        return 0;
 }
@@ -188,7 +186,7 @@ static int _mei_irq_thread_state_ok(struct mei_cl *cl,
  *
  * returns 0 on success, <0 on failure.
  */
-static int mei_irq_thread_read_client_message(struct mei_io_list *complete_list,
+static int mei_irq_thread_read_client_message(struct mei_cl_cb *complete_list,
                struct mei_device *dev,
                struct mei_msg_hdr *mei_hdr)
 {
@@ -197,36 +195,36 @@ static int mei_irq_thread_read_client_message(struct mei_io_list *complete_list,
        unsigned char *buffer = NULL;
 
        dev_dbg(&dev->pdev->dev, "start client msg\n");
-       if (list_empty(&dev->read_list.mei_cb.cb_list))
+       if (list_empty(&dev->read_list.list))
                goto quit;
 
-       list_for_each_entry_safe(cb_pos, cb_next,
-                       &dev->read_list.mei_cb.cb_list, cb_list) {
+       list_for_each_entry_safe(cb_pos, cb_next, &dev->read_list.list, list) {
                cl = (struct mei_cl *)cb_pos->file_private;
                if (cl && _mei_irq_thread_state_ok(cl, mei_hdr)) {
                        cl->reading_state = MEI_READING;
-                       buffer = cb_pos->response_buffer.data + cb_pos->information;
+                       buffer = cb_pos->response_buffer.data + cb_pos->buf_idx;
 
                        if (cb_pos->response_buffer.size <
-                                       mei_hdr->length + cb_pos->information) {
+                                       mei_hdr->length + cb_pos->buf_idx) {
                                dev_dbg(&dev->pdev->dev, "message overflow.\n");
-                               list_del(&cb_pos->cb_list);
+                               list_del(&cb_pos->list);
                                return -ENOMEM;
                        }
                        if (buffer)
                                mei_read_slots(dev, buffer, mei_hdr->length);
 
-                       cb_pos->information += mei_hdr->length;
+                       cb_pos->buf_idx += mei_hdr->length;
                        if (mei_hdr->msg_complete) {
                                cl->status = 0;
-                               list_del(&cb_pos->cb_list);
+                               list_del(&cb_pos->list);
                                dev_dbg(&dev->pdev->dev,
                                        "completed read H cl = %d, ME cl = %d, length = %lu\n",
                                        cl->host_client_id,
                                        cl->me_client_id,
-                                       cb_pos->information);
-                               list_add_tail(&cb_pos->cb_list,
-                                       &complete_list->mei_cb.cb_list);
+                                       cb_pos->buf_idx);
+
+                               list_add_tail(&cb_pos->list,
+                                               &complete_list->list);
                        }
 
                        break;
@@ -290,7 +288,7 @@ static int _mei_irq_thread_iamthif_read(struct mei_device *dev, s32 *slots)
 static int _mei_irq_thread_close(struct mei_device *dev, s32 *slots,
                                struct mei_cl_cb *cb_pos,
                                struct mei_cl *cl,
-                               struct mei_io_list *cmpl_list)
+                               struct mei_cl_cb *cmpl_list)
 {
        if ((*slots * sizeof(u32)) < (sizeof(struct mei_msg_hdr) +
                        sizeof(struct hbm_client_disconnect_request)))
@@ -300,16 +298,14 @@ static int _mei_irq_thread_close(struct mei_device *dev, s32 *slots,
 
        if (mei_disconnect(dev, cl)) {
                cl->status = 0;
-               cb_pos->information = 0;
-               list_move_tail(&cb_pos->cb_list,
-                               &cmpl_list->mei_cb.cb_list);
+               cb_pos->buf_idx = 0;
+               list_move_tail(&cb_pos->list, &cmpl_list->list);
                return -EMSGSIZE;
        } else {
                cl->state = MEI_FILE_DISCONNECTING;
                cl->status = 0;
-               cb_pos->information = 0;
-               list_move_tail(&cb_pos->cb_list,
-                               &dev->ctrl_rd_list.mei_cb.cb_list);
+               cb_pos->buf_idx = 0;
+               list_move_tail(&cb_pos->list, &dev->ctrl_rd_list.list);
                cl->timer_count = MEI_CONNECT_TIMEOUT;
        }
 
@@ -356,7 +352,7 @@ static void mei_client_connect_response(struct mei_device *dev,
 {
 
        struct mei_cl *cl;
-       struct mei_cl_cb *cb_pos = NULL, *cb_next = NULL;
+       struct mei_cl_cb *pos = NULL, *next = NULL;
 
        dev_dbg(&dev->pdev->dev,
                        "connect_response:\n"
@@ -382,17 +378,16 @@ static void mei_client_connect_response(struct mei_device *dev,
                dev->iamthif_state = MEI_IAMTHIF_IDLE;
                return;
        }
-       list_for_each_entry_safe(cb_pos, cb_next,
-                               &dev->ctrl_rd_list.mei_cb.cb_list, cb_list) {
+       list_for_each_entry_safe(pos, next, &dev->ctrl_rd_list.list, list) {
 
-               cl = (struct mei_cl *)cb_pos->file_private;
+               cl = (struct mei_cl *)pos->file_private;
                if (!cl) {
-                       list_del(&cb_pos->cb_list);
+                       list_del(&pos->list);
                        return;
                }
-               if (MEI_IOCTL == cb_pos->major_file_operations) {
+               if (MEI_IOCTL == pos->major_file_operations) {
                        if (is_treat_specially_client(cl, rs)) {
-                               list_del(&cb_pos->cb_list);
+                               list_del(&pos->list);
                                cl->status = 0;
                                cl->timer_count = 0;
                                break;
@@ -411,7 +406,7 @@ static void mei_client_disconnect_response(struct mei_device *dev,
                                        struct hbm_client_connect_response *rs)
 {
        struct mei_cl *cl;
-       struct mei_cl_cb *cb_pos = NULL, *cb_next = NULL;
+       struct mei_cl_cb *pos = NULL, *next = NULL;
 
        dev_dbg(&dev->pdev->dev,
                        "disconnect_response:\n"
@@ -422,12 +417,11 @@ static void mei_client_disconnect_response(struct mei_device *dev,
                        rs->host_addr,
                        rs->status);
 
-       list_for_each_entry_safe(cb_pos, cb_next,
-                       &dev->ctrl_rd_list.mei_cb.cb_list, cb_list) {
-               cl = (struct mei_cl *)cb_pos->file_private;
+       list_for_each_entry_safe(pos, next, &dev->ctrl_rd_list.list, list) {
+               cl = (struct mei_cl *)pos->file_private;
 
                if (!cl) {
-                       list_del(&cb_pos->cb_list);
+                       list_del(&pos->list);
                        return;
                }
 
@@ -435,7 +429,7 @@ static void mei_client_disconnect_response(struct mei_device *dev,
                if (cl->host_client_id == rs->host_addr &&
                    cl->me_client_id == rs->me_addr) {
 
-                       list_del(&cb_pos->cb_list);
+                       list_del(&pos->list);
                        if (!rs->status)
                                cl->state = MEI_FILE_DISCONNECTED;
 
@@ -821,12 +815,12 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev,
 static int _mei_irq_thread_read(struct mei_device *dev,        s32 *slots,
                        struct mei_cl_cb *cb_pos,
                        struct mei_cl *cl,
-                       struct mei_io_list *cmpl_list)
+                       struct mei_cl_cb *cmpl_list)
 {
        if ((*slots * sizeof(u32)) < (sizeof(struct mei_msg_hdr) +
                        sizeof(struct hbm_flow_control))) {
                /* return the cancel routine */
-               list_del(&cb_pos->cb_list);
+               list_del(&cb_pos->list);
                return -EBADMSG;
        }
 
@@ -834,11 +828,11 @@ static int _mei_irq_thread_read(struct mei_device *dev,   s32 *slots,
 
        if (mei_send_flow_control(dev, cl)) {
                cl->status = -ENODEV;
-               cb_pos->information = 0;
-               list_move_tail(&cb_pos->cb_list, &cmpl_list->mei_cb.cb_list);
+               cb_pos->buf_idx = 0;
+               list_move_tail(&cb_pos->list, &cmpl_list->list);
                return -ENODEV;
        }
-       list_move_tail(&cb_pos->cb_list, &dev->read_list.mei_cb.cb_list);
+       list_move_tail(&cb_pos->list, &dev->read_list.list);
 
        return 0;
 }
@@ -858,12 +852,12 @@ static int _mei_irq_thread_read(struct mei_device *dev,   s32 *slots,
 static int _mei_irq_thread_ioctl(struct mei_device *dev, s32 *slots,
                        struct mei_cl_cb *cb_pos,
                        struct mei_cl *cl,
-                       struct mei_io_list *cmpl_list)
+                       struct mei_cl_cb *cmpl_list)
 {
        if ((*slots * sizeof(u32)) < (sizeof(struct mei_msg_hdr) +
                        sizeof(struct hbm_client_connect_request))) {
                /* return the cancel routine */
-               list_del(&cb_pos->cb_list);
+               list_del(&cb_pos->list);
                return -EBADMSG;
        }
 
@@ -871,12 +865,11 @@ static int _mei_irq_thread_ioctl(struct mei_device *dev, s32 *slots,
         *slots -= mei_data2slots(sizeof(struct hbm_client_connect_request));
        if (mei_connect(dev, cl)) {
                cl->status = -ENODEV;
-               cb_pos->information = 0;
-               list_del(&cb_pos->cb_list);
+               cb_pos->buf_idx = 0;
+               list_del(&cb_pos->list);
                return -ENODEV;
        } else {
-               list_move_tail(&cb_pos->cb_list,
-                       &dev->ctrl_rd_list.mei_cb.cb_list);
+               list_move_tail(&cb_pos->list, &dev->ctrl_rd_list.list);
                cl->timer_count = MEI_CONNECT_TIMEOUT;
        }
        return 0;
@@ -896,45 +889,41 @@ static int _mei_irq_thread_ioctl(struct mei_device *dev, s32 *slots,
 static int _mei_irq_thread_cmpl(struct mei_device *dev,        s32 *slots,
                        struct mei_cl_cb *cb_pos,
                        struct mei_cl *cl,
-                       struct mei_io_list *cmpl_list)
+                       struct mei_cl_cb *cmpl_list)
 {
        struct mei_msg_hdr *mei_hdr;
 
        if ((*slots * sizeof(u32)) >= (sizeof(struct mei_msg_hdr) +
-                       (cb_pos->request_buffer.size -
-                       cb_pos->information))) {
+                       (cb_pos->request_buffer.size - cb_pos->buf_idx))) {
                mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
                mei_hdr->host_addr = cl->host_client_id;
                mei_hdr->me_addr = cl->me_client_id;
-               mei_hdr->length = cb_pos->request_buffer.size -
-                                       cb_pos->information;
+               mei_hdr->length = cb_pos->request_buffer.size - cb_pos->buf_idx;
                mei_hdr->msg_complete = 1;
                mei_hdr->reserved = 0;
                dev_dbg(&dev->pdev->dev, "cb_pos->request_buffer.size =%d"
                        "mei_hdr->msg_complete = %d\n",
                                cb_pos->request_buffer.size,
                                mei_hdr->msg_complete);
-               dev_dbg(&dev->pdev->dev, "cb_pos->information  =%lu\n",
-                               cb_pos->information);
+               dev_dbg(&dev->pdev->dev, "cb_pos->buf_idx  =%lu\n",
+                               cb_pos->buf_idx);
                dev_dbg(&dev->pdev->dev, "mei_hdr->length  =%d\n",
                                mei_hdr->length);
                *slots -= mei_data2slots(mei_hdr->length);
                if (mei_write_message(dev, mei_hdr,
                                (unsigned char *)
                                (cb_pos->request_buffer.data +
-                               cb_pos->information),
+                               cb_pos->buf_idx),
                                mei_hdr->length)) {
                        cl->status = -ENODEV;
-                       list_move_tail(&cb_pos->cb_list,
-                               &cmpl_list->mei_cb.cb_list);
+                       list_move_tail(&cb_pos->list, &cmpl_list->list);
                        return -ENODEV;
                } else {
                        if (mei_flow_ctrl_reduce(dev, cl))
                                return -ENODEV;
                        cl->status = 0;
-                       cb_pos->information += mei_hdr->length;
-                       list_move_tail(&cb_pos->cb_list,
-                               &dev->write_waiting_list.mei_cb.cb_list);
+                       cb_pos->buf_idx += mei_hdr->length;
+                       list_move_tail(&cb_pos->list, &dev->write_waiting_list.list);
                }
        } else if (*slots == dev->hbuf_depth) {
                /* buffer is still empty */
@@ -949,21 +938,20 @@ static int _mei_irq_thread_cmpl(struct mei_device *dev,   s32 *slots,
                if (mei_write_message(dev, mei_hdr,
                                        (unsigned char *)
                                        (cb_pos->request_buffer.data +
-                                       cb_pos->information),
+                                       cb_pos->buf_idx),
                                        mei_hdr->length)) {
                        cl->status = -ENODEV;
-                       list_move_tail(&cb_pos->cb_list,
-                               &cmpl_list->mei_cb.cb_list);
+                       list_move_tail(&cb_pos->list, &cmpl_list->list);
                        return -ENODEV;
                } else {
-                       cb_pos->information += mei_hdr->length;
+                       cb_pos->buf_idx += mei_hdr->length;
                        dev_dbg(&dev->pdev->dev,
                                        "cb_pos->request_buffer.size =%d"
                                        " mei_hdr->msg_complete = %d\n",
                                        cb_pos->request_buffer.size,
                                        mei_hdr->msg_complete);
-                       dev_dbg(&dev->pdev->dev, "cb_pos->information  =%lu\n",
-                                       cb_pos->information);
+                       dev_dbg(&dev->pdev->dev, "cb_pos->buf_idx  =%lu\n",
+                                       cb_pos->buf_idx);
                        dev_dbg(&dev->pdev->dev, "mei_hdr->length  =%d\n",
                                        mei_hdr->length);
                }
@@ -989,7 +977,7 @@ static int _mei_irq_thread_cmpl(struct mei_device *dev,     s32 *slots,
 static int _mei_irq_thread_cmpl_iamthif(struct mei_device *dev, s32 *slots,
                        struct mei_cl_cb *cb_pos,
                        struct mei_cl *cl,
-                       struct mei_io_list *cmpl_list)
+                       struct mei_cl_cb *cmpl_list)
 {
        struct mei_msg_hdr *mei_hdr;
 
@@ -1012,20 +1000,19 @@ static int _mei_irq_thread_cmpl_iamthif(struct mei_device *dev, s32 *slots,
                                        mei_hdr->length)) {
                        dev->iamthif_state = MEI_IAMTHIF_IDLE;
                        cl->status = -ENODEV;
-                       list_del(&cb_pos->cb_list);
+                       list_del(&cb_pos->list);
                        return -ENODEV;
                } else {
                        if (mei_flow_ctrl_reduce(dev, cl))
                                return -ENODEV;
                        dev->iamthif_msg_buf_index += mei_hdr->length;
-                       cb_pos->information = dev->iamthif_msg_buf_index;
+                       cb_pos->buf_idx = dev->iamthif_msg_buf_index;
                        cl->status = 0;
                        dev->iamthif_state = MEI_IAMTHIF_FLOW_CONTROL;
                        dev->iamthif_flow_control_pending = true;
                        /* save iamthif cb sent to amthi client */
                        dev->iamthif_current_cb = cb_pos;
-                       list_move_tail(&cb_pos->cb_list,
-                               &dev->write_waiting_list.mei_cb.cb_list);
+                       list_move_tail(&cb_pos->list, &dev->write_waiting_list.list);
 
                }
        } else if (*slots == dev->hbuf_depth) {
@@ -1045,7 +1032,7 @@ static int _mei_irq_thread_cmpl_iamthif(struct mei_device *dev, s32 *slots,
                                        dev->iamthif_msg_buf_index),
                                        mei_hdr->length)) {
                        cl->status = -ENODEV;
-                       list_del(&cb_pos->cb_list);
+                       list_del(&cb_pos->list);
                } else {
                        dev->iamthif_msg_buf_index += mei_hdr->length;
                }
@@ -1067,7 +1054,7 @@ static int _mei_irq_thread_cmpl_iamthif(struct mei_device *dev, s32 *slots,
  *
  * returns 0 on success, <0 on failure.
  */
-static int mei_irq_thread_read_handler(struct mei_io_list *cmpl_list,
+static int mei_irq_thread_read_handler(struct mei_cl_cb *cmpl_list,
                struct mei_device *dev,
                s32 *slots)
 {
@@ -1170,14 +1157,13 @@ end:
  *
  * returns 0 on success, <0 on failure.
  */
-static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list,
-               struct mei_device *dev,
-               s32 *slots)
+static int mei_irq_thread_write_handler(struct mei_cl_cb *cmpl_list,
+               struct mei_device *dev, s32 *slots)
 {
 
        struct mei_cl *cl;
        struct mei_cl_cb *pos = NULL, *next = NULL;
-       struct mei_io_list *list;
+       struct mei_cl_cb *list;
        int ret;
 
        if (!mei_hbuf_is_empty(dev)) {
@@ -1192,20 +1178,19 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list,
        dev_dbg(&dev->pdev->dev, "complete all waiting for write cb.\n");
 
        list = &dev->write_waiting_list;
-       list_for_each_entry_safe(pos, next, &list->mei_cb.cb_list, cb_list) {
+       list_for_each_entry_safe(pos, next, &list->list, list) {
                cl = (struct mei_cl *)pos->file_private;
                if (cl == NULL)
                        continue;
 
                cl->status = 0;
-               list_del(&pos->cb_list);
+               list_del(&pos->list);
                if (MEI_WRITING == cl->writing_state &&
                   (pos->major_file_operations == MEI_WRITE) &&
                   (cl != &dev->iamthif_cl)) {
                        dev_dbg(&dev->pdev->dev, "MEI WRITE COMPLETE\n");
                        cl->writing_state = MEI_WRITE_COMPLETE;
-                       list_add_tail(&pos->cb_list,
-                                     &cmpl_list->mei_cb.cb_list);
+                       list_add_tail(&pos->list, &cmpl_list->list);
                }
                if (cl == &dev->iamthif_cl) {
                        dev_dbg(&dev->pdev->dev, "check iamthif flow control.\n");
@@ -1251,11 +1236,10 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list,
 
        /* complete control write list CB */
        dev_dbg(&dev->pdev->dev, "complete control write list cb.\n");
-       list_for_each_entry_safe(pos, next,
-                               &dev->ctrl_wr_list.mei_cb.cb_list, cb_list) {
+       list_for_each_entry_safe(pos, next, &dev->ctrl_wr_list.list, list) {
                cl = (struct mei_cl *) pos->file_private;
                if (!cl) {
-                       list_del(&pos->cb_list);
+                       list_del(&pos->list);
                        return -ENODEV;
                }
                switch (pos->major_file_operations) {
@@ -1290,8 +1274,7 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list,
        }
        /* complete  write list CB */
        dev_dbg(&dev->pdev->dev, "complete write list cb.\n");
-       list_for_each_entry_safe(pos, next,
-                               &dev->write_list.mei_cb.cb_list, cb_list) {
+       list_for_each_entry_safe(pos, next, &dev->write_list.list, list) {
                cl = (struct mei_cl *)pos->file_private;
                if (cl == NULL)
                        continue;
@@ -1385,11 +1368,10 @@ void mei_timer(struct work_struct *work)
                        dev->iamthif_state = MEI_IAMTHIF_IDLE;
                        dev->iamthif_timer = 0;
 
-                       if (dev->iamthif_current_cb)
-                               mei_free_cb_private(dev->iamthif_current_cb);
+                       mei_io_cb_free(dev->iamthif_current_cb);
+                       dev->iamthif_current_cb = NULL;
 
                        dev->iamthif_file_object = NULL;
-                       dev->iamthif_current_cb = NULL;
                        mei_run_next_iamthif_cmd(dev);
                }
        }
@@ -1411,23 +1393,21 @@ void mei_timer(struct work_struct *work)
 
                        dev_dbg(&dev->pdev->dev, "freeing AMTHI for other requests\n");
 
-                       amthi_complete_list = &dev->amthi_read_complete_list.
-                                       mei_cb.cb_list;
+                       amthi_complete_list = &dev->amthi_read_complete_list.list;
 
-                       list_for_each_entry_safe(cb_pos, cb_next, amthi_complete_list, cb_list) {
+                       list_for_each_entry_safe(cb_pos, cb_next, amthi_complete_list, list) {
 
                                cl_pos = cb_pos->file_object->private_data;
 
                                /* Finding the AMTHI entry. */
                                if (cl_pos == &dev->iamthif_cl)
-                                       list_del(&cb_pos->cb_list);
+                                       list_del(&cb_pos->list);
                        }
-                       if (dev->iamthif_current_cb)
-                               mei_free_cb_private(dev->iamthif_current_cb);
+                       mei_io_cb_free(dev->iamthif_current_cb);
+                       dev->iamthif_current_cb = NULL;
 
                        dev->iamthif_file_object->private_data = NULL;
                        dev->iamthif_file_object = NULL;
-                       dev->iamthif_current_cb = NULL;
                        dev->iamthif_timer = 0;
                        mei_run_next_iamthif_cmd(dev);
 
@@ -1451,7 +1431,7 @@ out:
 irqreturn_t mei_interrupt_thread_handler(int irq, void *dev_id)
 {
        struct mei_device *dev = (struct mei_device *) dev_id;
-       struct mei_io_list complete_list;
+       struct mei_cl_cb complete_list;
        struct mei_cl_cb *cb_pos = NULL, *cb_next = NULL;
        struct mei_cl *cl;
        s32 slots;
@@ -1531,14 +1511,13 @@ end:
                wake_up_interruptible(&dev->wait_recvd_msg);
                bus_message_received = false;
        }
-       if (list_empty(&complete_list.mei_cb.cb_list))
+       if (list_empty(&complete_list.list))
                return IRQ_HANDLED;
 
 
-       list_for_each_entry_safe(cb_pos, cb_next,
-                       &complete_list.mei_cb.cb_list, cb_list) {
+       list_for_each_entry_safe(cb_pos, cb_next, &complete_list.list, list) {
                cl = (struct mei_cl *)cb_pos->file_private;
-               list_del(&cb_pos->cb_list);
+               list_del(&cb_pos->list);
                if (cl) {
                        if (cl != &dev->iamthif_cl) {
                                dev_dbg(&dev->pdev->dev, "completing call back.\n");
index fcba98eb892e1e410d62a4c198d978ab82b667f5..541c157f325a3214a8524b8ddca0674f20d149c1 100644 (file)
 #include <linux/mei.h>
 #include "interface.h"
 
+/**
+ * mei_io_cb_free - free mei_cb_private related memory
+ *
+ * @cb: mei callback struct
+ */
+void mei_io_cb_free(struct mei_cl_cb *cb)
+{
+       if (cb == NULL)
+               return;
+
+       kfree(cb->request_buffer.data);
+       kfree(cb->response_buffer.data);
+       kfree(cb);
+}
+/**
+ * mei_io_cb_init - allocate and initialize io callback
+ *
+ * @cl - mei client
+ * @file: pointer to file structure
+ *
+ * returns mei_cl_cb pointer or NULL;
+ */
+struct mei_cl_cb *mei_io_cb_init(struct mei_cl *cl, struct file *fp)
+{
+       struct mei_cl_cb *cb;
+
+       cb = kzalloc(sizeof(struct mei_cl_cb), GFP_KERNEL);
+       if (!cb)
+               return NULL;
+
+       mei_io_list_init(cb);
+
+       cb->file_object = fp;
+       cb->file_private = cl;
+       cb->buf_idx = 0;
+       return cb;
+}
+
+
+/**
+ * mei_io_cb_alloc_req_buf - allocate request buffer
+ *
+ * @cb -  io callback structure
+ * @size: size of the buffer
+ *
+ * returns 0 on success
+ *         -EINVAL if cb is NULL
+ *         -ENOMEM if allocation failed
+ */
+int mei_io_cb_alloc_req_buf(struct mei_cl_cb *cb, size_t length)
+{
+       if (!cb)
+               return -EINVAL;
+
+       if (length == 0)
+               return 0;
+
+       cb->request_buffer.data = kmalloc(length, GFP_KERNEL);
+       if (!cb->request_buffer.data)
+               return -ENOMEM;
+       cb->request_buffer.size = length;
+       return 0;
+}
+/**
+ * mei_io_cb_alloc_req_buf - allocate respose buffer
+ *
+ * @cb -  io callback structure
+ * @size: size of the buffer
+ *
+ * returns 0 on success
+ *         -EINVAL if cb is NULL
+ *         -ENOMEM if allocation failed
+ */
+int mei_io_cb_alloc_resp_buf(struct mei_cl_cb *cb, size_t length)
+{
+       if (!cb)
+               return -EINVAL;
+
+       if (length == 0)
+               return 0;
+
+       cb->response_buffer.data = kmalloc(length, GFP_KERNEL);
+       if (!cb->response_buffer.data)
+               return -ENOMEM;
+       cb->response_buffer.size = length;
+       return 0;
+}
+
+
 /**
  * mei_me_cl_by_id return index to me_clients for client_id
  *
@@ -97,14 +186,12 @@ int mei_ioctl_connect_client(struct file *file,
 
        dev_dbg(&dev->pdev->dev, "mei_ioctl_connect_client() Entry\n");
 
-
        /* buffered ioctl cb */
-       cb = kzalloc(sizeof(struct mei_cl_cb), GFP_KERNEL);
+       cb = mei_io_cb_init(cl, file);
        if (!cb) {
                rets = -ENOMEM;
                goto end;
        }
-       INIT_LIST_HEAD(&cb->cb_list);
 
        cb->major_file_operations = MEI_IOCTL;
 
@@ -192,19 +279,14 @@ int mei_ioctl_connect_client(struct file *file,
                } else {
                        dev_dbg(&dev->pdev->dev, "Sending connect message - succeeded\n");
                        cl->timer_count = MEI_CONNECT_TIMEOUT;
-                       cb->file_private = cl;
-                       list_add_tail(&cb->cb_list,
-                                     &dev->ctrl_rd_list.mei_cb.
-                                     cb_list);
+                       list_add_tail(&cb->list, &dev->ctrl_rd_list.list);
                }
 
 
        } else {
                dev_dbg(&dev->pdev->dev, "Queuing the connect request due to device busy\n");
-               cb->file_private = cl;
                dev_dbg(&dev->pdev->dev, "add connect cb to control write list.\n");
-               list_add_tail(&cb->cb_list,
-                             &dev->ctrl_wr_list.mei_cb.cb_list);
+               list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
        }
        mutex_unlock(&dev->device_lock);
        err = wait_event_timeout(dev->wait_recvd_msg,
@@ -234,7 +316,7 @@ int mei_ioctl_connect_client(struct file *file,
        rets = 0;
 end:
        dev_dbg(&dev->pdev->dev, "free connect cb memory.");
-       kfree(cb);
+       mei_io_cb_free(cb);
        return rets;
 }
 
@@ -255,7 +337,7 @@ struct mei_cl_cb *find_amthi_read_list_entry(
        struct mei_cl_cb *next = NULL;
 
        list_for_each_entry_safe(pos, next,
-           &dev->amthi_read_complete_list.mei_cb.cb_list, cb_list) {
+           &dev->amthi_read_complete_list.list, list) {
                cl_temp = (struct mei_cl *)pos->file_private;
                if (cl_temp && cl_temp == &dev->iamthif_cl &&
                        pos->file_object == file)
@@ -340,17 +422,17 @@ int amthi_read(struct mei_device *dev, struct file *file,
                if  (time_after(jiffies, timeout)) {
                        dev_dbg(&dev->pdev->dev, "amthi Time out\n");
                        /* 15 sec for the message has expired */
-                       list_del(&cb->cb_list);
+                       list_del(&cb->list);
                        rets = -ETIMEDOUT;
                        goto free;
                }
        }
        /* if the whole message will fit remove it from the list */
-       if (cb->information >= *offset && length >= (cb->information - *offset))
-               list_del(&cb->cb_list);
-       else if (cb->information > 0 && cb->information <= *offset) {
+       if (cb->buf_idx >= *offset && length >= (cb->buf_idx - *offset))
+               list_del(&cb->list);
+       else if (cb->buf_idx > 0 && cb->buf_idx <= *offset) {
                /* end of the message has been reached */
-               list_del(&cb->cb_list);
+               list_del(&cb->list);
                rets = 0;
                goto free;
        }
@@ -360,18 +442,17 @@ int amthi_read(struct mei_device *dev, struct file *file,
 
        dev_dbg(&dev->pdev->dev, "amthi cb->response_buffer size - %d\n",
            cb->response_buffer.size);
-       dev_dbg(&dev->pdev->dev, "amthi cb->information - %lu\n",
-           cb->information);
+       dev_dbg(&dev->pdev->dev, "amthi cb->buf_idx - %lu\n", cb->buf_idx);
 
        /* length is being turncated to PAGE_SIZE, however,
-        * the information may be longer */
-       length = min_t(size_t, length, (cb->information - *offset));
+        * the buf_idx may point beyond */
+       length = min_t(size_t, length, (cb->buf_idx - *offset));
 
        if (copy_to_user(ubuf, cb->response_buffer.data + *offset, length))
                rets = -EFAULT;
        else {
                rets = length;
-               if ((*offset + length) < cb->information) {
+               if ((*offset + length) < cb->buf_idx) {
                        *offset += length;
                        goto out;
                }
@@ -379,7 +460,7 @@ int amthi_read(struct mei_device *dev, struct file *file,
 free:
        dev_dbg(&dev->pdev->dev, "free amthi cb memory.\n");
        *offset = 0;
-       mei_free_cb_private(cb);
+       mei_io_cb_free(cb);
 out:
        return rets;
 }
@@ -396,7 +477,7 @@ out:
 int mei_start_read(struct mei_device *dev, struct mei_cl *cl)
 {
        struct mei_cl_cb *cb;
-       int rets = 0;
+       int rets;
        int i;
 
        if (cl->state != MEI_FILE_CONNECTED)
@@ -405,50 +486,41 @@ int mei_start_read(struct mei_device *dev, struct mei_cl *cl)
        if (dev->dev_state != MEI_DEV_ENABLED)
                return -ENODEV;
 
-       dev_dbg(&dev->pdev->dev, "check if read is pending.\n");
        if (cl->read_pending || cl->read_cb) {
                dev_dbg(&dev->pdev->dev, "read is pending.\n");
                return -EBUSY;
        }
+       i = mei_me_cl_by_id(dev, cl->me_client_id);
+       if (i < 0) {
+               dev_err(&dev->pdev->dev, "no such me client %d\n",
+                       cl->me_client_id);
+               return  -ENODEV;
+       }
 
-       cb = kzalloc(sizeof(struct mei_cl_cb), GFP_KERNEL);
+       cb = mei_io_cb_init(cl, NULL);
        if (!cb)
                return -ENOMEM;
 
-       dev_dbg(&dev->pdev->dev, "allocation call back successful. host client = %d, ME client = %d\n",
-               cl->host_client_id, cl->me_client_id);
-       i = mei_me_cl_by_id(dev, cl->me_client_id);
-       if (i < 0) {
-               rets = -ENODEV;
-               goto unlock;
-       }
+       rets = mei_io_cb_alloc_resp_buf(cb,
+                       dev->me_clients[i].props.max_msg_length);
+       if (rets)
+               goto err;
 
-       cb->response_buffer.size = dev->me_clients[i].props.max_msg_length;
-       cb->response_buffer.data =
-                       kmalloc(cb->response_buffer.size, GFP_KERNEL);
-       if (!cb->response_buffer.data) {
-               rets = -ENOMEM;
-               goto unlock;
-       }
-       dev_dbg(&dev->pdev->dev, "allocation call back data success.\n");
        cb->major_file_operations = MEI_READ;
-       /* make sure information is zero before we start */
-       cb->information = 0;
-       cb->file_private = (void *) cl;
        cl->read_cb = cb;
        if (dev->mei_host_buffer_is_empty) {
                dev->mei_host_buffer_is_empty = false;
                if (mei_send_flow_control(dev, cl)) {
                        rets = -ENODEV;
-                       goto unlock;
+                       goto err;
                }
-               list_add_tail(&cb->cb_list, &dev->read_list.mei_cb.cb_list);
+               list_add_tail(&cb->list, &dev->read_list.list);
        } else {
-               list_add_tail(&cb->cb_list, &dev->ctrl_wr_list.mei_cb.cb_list);
+               list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
        }
        return rets;
-unlock:
-       mei_free_cb_private(cb);
+err:
+       mei_io_cb_free(cb);
        return rets;
 }
 
@@ -511,13 +583,11 @@ int amthi_write(struct mei_device *dev, struct mei_cl_cb *cb)
                        dev_dbg(&dev->pdev->dev, "add amthi cb to write waiting list\n");
                        dev->iamthif_current_cb = cb;
                        dev->iamthif_file_object = cb->file_object;
-                       list_add_tail(&cb->cb_list,
-                                     &dev->write_waiting_list.mei_cb.cb_list);
+                       list_add_tail(&cb->list, &dev->write_waiting_list.list);
                } else {
                        dev_dbg(&dev->pdev->dev, "message does not complete, "
                                        "so add amthi cb to write list.\n");
-                       list_add_tail(&cb->cb_list,
-                                     &dev->write_list.mei_cb.cb_list);
+                       list_add_tail(&cb->list, &dev->write_list.list);
                }
        } else {
                if (!(dev->mei_host_buffer_is_empty))
@@ -525,7 +595,7 @@ int amthi_write(struct mei_device *dev, struct mei_cl_cb *cb)
 
                dev_dbg(&dev->pdev->dev, "No flow control credentials, "
                                "so add iamthif cb to write list.\n");
-               list_add_tail(&cb->cb_list, &dev->write_list.mei_cb.cb_list);
+               list_add_tail(&cb->list, &dev->write_list.list);
        }
        return 0;
 }
@@ -557,9 +627,8 @@ void mei_run_next_iamthif_cmd(struct mei_device *dev)
 
        dev_dbg(&dev->pdev->dev, "complete amthi cmd_list cb.\n");
 
-       list_for_each_entry_safe(pos, next,
-                       &dev->amthi_cmd_list.mei_cb.cb_list, cb_list) {
-               list_del(&pos->cb_list);
+       list_for_each_entry_safe(pos, next, &dev->amthi_cmd_list.list, list) {
+               list_del(&pos->list);
                cl_tmp = (struct mei_cl *)pos->file_private;
 
                if (cl_tmp && cl_tmp == &dev->iamthif_cl) {
@@ -575,17 +644,3 @@ void mei_run_next_iamthif_cmd(struct mei_device *dev)
        }
 }
 
-/**
- * mei_free_cb_private - free mei_cb_private related memory
- *
- * @cb: mei callback struct
- */
-void mei_free_cb_private(struct mei_cl_cb *cb)
-{
-       if (cb == NULL)
-               return;
-
-       kfree(cb->request_buffer.data);
-       kfree(cb->response_buffer.data);
-       kfree(cb);
-}
index e8b0858132c1560c7103e3f0b8f8e3d31f1ac424..ed4943f6b6c21e6c8e4ccb0c86a34b75afc1409c 100644 (file)
@@ -111,12 +111,12 @@ static bool mei_clear_list(struct mei_device *dev,
        bool removed = false;
 
        /* list all list member */
-       list_for_each_entry_safe(cb_pos, cb_next, mei_cb_list, cb_list) {
+       list_for_each_entry_safe(cb_pos, cb_next, mei_cb_list, list) {
                file_temp = (struct file *)cb_pos->file_object;
                /* check if list member associated with a file */
                if (file_temp == file) {
                        /* remove member from the list */
-                       list_del(&cb_pos->cb_list);
+                       list_del(&cb_pos->list);
                        /* check if cb equal to current iamthif cb */
                        if (dev->iamthif_current_cb == cb_pos) {
                                dev->iamthif_current_cb = NULL;
@@ -124,7 +124,7 @@ static bool mei_clear_list(struct mei_device *dev,
                                mei_send_flow_control(dev, &dev->iamthif_cl);
                        }
                        /* free all allocated buffers */
-                       mei_free_cb_private(cb_pos);
+                       mei_io_cb_free(cb_pos);
                        cb_pos = NULL;
                        removed = true;
                }
@@ -148,20 +148,20 @@ static bool mei_clear_lists(struct mei_device *dev, struct file *file)
        bool removed = false;
 
        /* remove callbacks associated with a file */
-       mei_clear_list(dev, file, &dev->amthi_cmd_list.mei_cb.cb_list);
+       mei_clear_list(dev, file, &dev->amthi_cmd_list.list);
        if (mei_clear_list(dev, file,
-                           &dev->amthi_read_complete_list.mei_cb.cb_list))
+                           &dev->amthi_read_complete_list.list))
                removed = true;
 
-       mei_clear_list(dev, file, &dev->ctrl_rd_list.mei_cb.cb_list);
+       mei_clear_list(dev, file, &dev->ctrl_rd_list.list);
 
-       if (mei_clear_list(dev, file, &dev->ctrl_wr_list.mei_cb.cb_list))
+       if (mei_clear_list(dev, file, &dev->ctrl_wr_list.list))
                removed = true;
 
-       if (mei_clear_list(dev, file, &dev->write_waiting_list.mei_cb.cb_list))
+       if (mei_clear_list(dev, file, &dev->write_waiting_list.list))
                removed = true;
 
-       if (mei_clear_list(dev, file, &dev->write_list.mei_cb.cb_list))
+       if (mei_clear_list(dev, file, &dev->write_list.list))
                removed = true;
 
        /* check if iamthif_current_cb not NULL */
@@ -169,7 +169,7 @@ static bool mei_clear_lists(struct mei_device *dev, struct file *file)
                /* check file and iamthif current cb association */
                if (dev->iamthif_current_cb->file_object == file) {
                        /* remove cb */
-                       mei_free_cb_private(dev->iamthif_current_cb);
+                       mei_io_cb_free(dev->iamthif_current_cb);
                        dev->iamthif_current_cb = NULL;
                        removed = true;
                }
@@ -192,8 +192,7 @@ static struct mei_cl_cb *find_read_list_entry(
        struct mei_cl_cb *next = NULL;
 
        dev_dbg(&dev->pdev->dev, "remove read_list CB\n");
-       list_for_each_entry_safe(pos, next,
-                       &dev->read_list.mei_cb.cb_list, cb_list) {
+       list_for_each_entry_safe(pos, next, &dev->read_list.list, list) {
                struct mei_cl *cl_temp;
                cl_temp = (struct mei_cl *)pos->file_private;
 
@@ -324,7 +323,7 @@ static int mei_release(struct inode *inode, struct file *file)
                        cb = find_read_list_entry(dev, cl);
                        /* Remove entry from read list */
                        if (cb)
-                               list_del(&cb->cb_list);
+                               list_del(&cb->list);
 
                        cb = cl->read_cb;
                        cl->read_cb = NULL;
@@ -333,7 +332,7 @@ static int mei_release(struct inode *inode, struct file *file)
                file->private_data = NULL;
 
                if (cb) {
-                       mei_free_cb_private(cb);
+                       mei_io_cb_free(cb);
                        cb = NULL;
                }
 
@@ -415,16 +414,15 @@ static ssize_t mei_read(struct file *file, char __user *ubuf,
                goto out;
        }
 
-       if (cl->read_cb && cl->read_cb->information > *offset) {
+       if (cl->read_cb && cl->read_cb->buf_idx > *offset) {
                cb = cl->read_cb;
                goto copy_buffer;
-       } else if (cl->read_cb && cl->read_cb->information > 0 &&
-                  cl->read_cb->information <= *offset) {
+       } else if (cl->read_cb && cl->read_cb->buf_idx > 0 &&
+                  cl->read_cb->buf_idx <= *offset) {
                cb = cl->read_cb;
                rets = 0;
                goto free;
-       } else if ((!cl->read_cb || !cl->read_cb->information) &&
-                   *offset > 0) {
+       } else if ((!cl->read_cb || !cl->read_cb->buf_idx) && *offset > 0) {
                /*Offset needs to be cleaned for contiguous reads*/
                *offset = 0;
                rets = 0;
@@ -481,16 +479,15 @@ static ssize_t mei_read(struct file *file, char __user *ubuf,
 copy_buffer:
        dev_dbg(&dev->pdev->dev, "cb->response_buffer size - %d\n",
            cb->response_buffer.size);
-       dev_dbg(&dev->pdev->dev, "cb->information - %lu\n",
-           cb->information);
-       if (length == 0 || ubuf == NULL || *offset > cb->information) {
+       dev_dbg(&dev->pdev->dev, "cb->buf_idx - %lu\n", cb->buf_idx);
+       if (length == 0 || ubuf == NULL || *offset > cb->buf_idx) {
                rets = -EMSGSIZE;
                goto free;
        }
 
-       /* length is being truncated to PAGE_SIZE, however, */
-       /* information size may be longer */
-       length = min_t(size_t, length, (cb->information - *offset));
+       /* length is being truncated to PAGE_SIZE,
+        * however buf_idx may point beyond that */
+       length = min_t(size_t, length, cb->buf_idx - *offset);
 
        if (copy_to_user(ubuf, cb->response_buffer.data + *offset, length)) {
                rets = -EFAULT;
@@ -499,15 +496,15 @@ copy_buffer:
 
        rets = length;
        *offset += length;
-       if ((unsigned long)*offset < cb->information)
+       if ((unsigned long)*offset < cb->buf_idx)
                goto out;
 
 free:
        cb_pos = find_read_list_entry(dev, cl);
        /* Remove entry from read list */
        if (cb_pos)
-               list_del(&cb_pos->cb_list);
-       mei_free_cb_private(cb);
+               list_del(&cb_pos->list);
+       mei_io_cb_free(cb);
        cl->reading_state = MEI_IDLE;
        cl->read_cb = NULL;
        cl->read_pending = 0;
@@ -516,7 +513,6 @@ out:
        mutex_unlock(&dev->device_lock);
        return rets;
 }
-
 /**
  * mei_write - the write function.
  *
@@ -546,10 +542,26 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
        mutex_lock(&dev->device_lock);
 
        if (dev->dev_state != MEI_DEV_ENABLED) {
-               mutex_unlock(&dev->device_lock);
-               return -ENODEV;
+               rets = -ENODEV;
+               goto unlock_dev;
        }
 
+       i = mei_me_cl_by_id(dev, cl->me_client_id);
+       if (i < 0) {
+               rets = -ENODEV;
+               goto unlock_dev;
+       }
+       if (length > dev->me_clients[i].props.max_msg_length || length <= 0) {
+               rets = -EMSGSIZE;
+               goto unlock_dev;
+       }
+
+       if (cl->state != MEI_FILE_CONNECTED) {
+               rets = -ENODEV;
+               dev_err(&dev->pdev->dev, "host client = %d,  is not connected to ME client = %d",
+                       cl->host_client_id, cl->me_client_id);
+               goto unlock_dev;
+       }
        if (cl == &dev->iamthif_cl) {
                write_cb = find_amthi_read_list_entry(dev, file);
 
@@ -558,11 +570,11 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
                                        msecs_to_jiffies(IAMTHIF_READ_TIMER);
 
                        if (time_after(jiffies, timeout) ||
-                                cl->reading_state == MEI_READ_COMPLETE) {
-                                       *offset = 0;
-                                       list_del(&write_cb->cb_list);
-                                       mei_free_cb_private(write_cb);
-                                       write_cb = NULL;
+                           cl->reading_state == MEI_READ_COMPLETE) {
+                               *offset = 0;
+                               list_del(&write_cb->list);
+                               mei_io_cb_free(write_cb);
+                               write_cb = NULL;
                        }
                }
        }
@@ -572,8 +584,8 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
                *offset = 0;
                write_cb = find_read_list_entry(dev, cl);
                if (write_cb) {
-                       list_del(&write_cb->cb_list);
-                       mei_free_cb_private(write_cb);
+                       list_del(&write_cb->list);
+                       mei_io_cb_free(write_cb);
                        write_cb = NULL;
                        cl->reading_state = MEI_IDLE;
                        cl->read_cb = NULL;
@@ -583,23 +595,20 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
                *offset = 0;
 
 
-       write_cb = kzalloc(sizeof(struct mei_cl_cb), GFP_KERNEL);
+       write_cb = mei_io_cb_init(cl, file);
        if (!write_cb) {
-               mutex_unlock(&dev->device_lock);
-               return -ENOMEM;
+               dev_err(&dev->pdev->dev, "write cb allocation failed\n");
+               rets = -ENOMEM;
+               goto unlock_dev;
        }
-
-       write_cb->file_object = file;
-       write_cb->file_private = cl;
-       write_cb->request_buffer.data = kmalloc(length, GFP_KERNEL);
-       rets = -ENOMEM;
-       if (!write_cb->request_buffer.data)
+       rets = mei_io_cb_alloc_req_buf(write_cb, length);
+       if (rets)
                goto unlock_dev;
 
-       dev_dbg(&dev->pdev->dev, "length =%d\n", (int) length);
+       dev_dbg(&dev->pdev->dev, "cb request size = %zd\n", length);
 
-       rets = -EFAULT;
-       if (copy_from_user(write_cb->request_buffer.data, ubuf, length))
+       rets = copy_from_user(write_cb->request_buffer.data, ubuf, length);
+       if (rets)
                goto unlock_dev;
 
        cl->sm_state = 0;
@@ -612,87 +621,37 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
                                 write_cb->request_buffer.data, 4) == 0)))
                cl->sm_state |= MEI_WD_STATE_INDEPENDENCE_MSG_SENT;
 
-       INIT_LIST_HEAD(&write_cb->cb_list);
        if (cl == &dev->iamthif_cl) {
-               write_cb->response_buffer.data =
-                   kmalloc(dev->iamthif_mtu, GFP_KERNEL);
-               if (!write_cb->response_buffer.data) {
-                       rets = -ENOMEM;
+               rets = mei_io_cb_alloc_resp_buf(write_cb, dev->iamthif_mtu);
+               if (rets)
                        goto unlock_dev;
-               }
-               if (dev->dev_state != MEI_DEV_ENABLED) {
-                       rets = -ENODEV;
-                       goto unlock_dev;
-               }
-               i = mei_me_cl_by_id(dev, dev->iamthif_cl.me_client_id);
-               if (i < 0) {
-                       rets = -ENODEV;
-                       goto unlock_dev;
-               }
-               if (length > dev->me_clients[i].props.max_msg_length ||
-                          length <= 0) {
-                       rets = -EMSGSIZE;
-                       goto unlock_dev;
-               }
 
-               write_cb->response_buffer.size = dev->iamthif_mtu;
                write_cb->major_file_operations = MEI_IOCTL;
-               write_cb->information = 0;
-               write_cb->request_buffer.size = length;
-               if (dev->iamthif_cl.state != MEI_FILE_CONNECTED) {
-                       rets = -ENODEV;
-                       goto unlock_dev;
-               }
 
-               if (!list_empty(&dev->amthi_cmd_list.mei_cb.cb_list) ||
+               if (!list_empty(&dev->amthi_cmd_list.list) ||
                                dev->iamthif_state != MEI_IAMTHIF_IDLE) {
                        dev_dbg(&dev->pdev->dev, "amthi_state = %d\n",
                                        (int) dev->iamthif_state);
                        dev_dbg(&dev->pdev->dev, "add amthi cb to amthi cmd waiting list\n");
-                       list_add_tail(&write_cb->cb_list,
-                                       &dev->amthi_cmd_list.mei_cb.cb_list);
-                       rets = length;
+                       list_add_tail(&write_cb->list, &dev->amthi_cmd_list.list);
                } else {
                        dev_dbg(&dev->pdev->dev, "call amthi write\n");
                        rets = amthi_write(dev, write_cb);
 
                        if (rets) {
-                               dev_dbg(&dev->pdev->dev, "amthi write failed with status = %d\n",
+                               dev_err(&dev->pdev->dev, "amthi write failed with status = %d\n",
                                    rets);
                                goto unlock_dev;
                        }
-                       rets = length;
                }
                mutex_unlock(&dev->device_lock);
-               return rets;
+               return length;
        }
 
        write_cb->major_file_operations = MEI_WRITE;
-       /* make sure information is zero before we start */
-
-       write_cb->information = 0;
-       write_cb->request_buffer.size = length;
 
        dev_dbg(&dev->pdev->dev, "host client = %d, ME client = %d\n",
            cl->host_client_id, cl->me_client_id);
-       if (cl->state != MEI_FILE_CONNECTED) {
-               rets = -ENODEV;
-               dev_dbg(&dev->pdev->dev, "host client = %d,  is not connected to ME client = %d",
-                   cl->host_client_id,
-                   cl->me_client_id);
-               goto unlock_dev;
-       }
-       i = mei_me_cl_by_id(dev, cl->me_client_id);
-       if (i < 0) {
-               rets = -ENODEV;
-               goto unlock_dev;
-       }
-       if (length > dev->me_clients[i].props.max_msg_length || length <= 0) {
-               rets = -EINVAL;
-               goto unlock_dev;
-       }
-       write_cb->file_private = cl;
-
        rets = mei_flow_ctrl_creds(dev, cl);
        if (rets < 0)
                goto unlock_dev;
@@ -719,32 +678,29 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
                        goto unlock_dev;
                }
                cl->writing_state = MEI_WRITING;
-               write_cb->information = mei_hdr.length;
+               write_cb->buf_idx = mei_hdr.length;
                if (mei_hdr.msg_complete) {
                        if (mei_flow_ctrl_reduce(dev, cl)) {
                                rets = -ENODEV;
                                goto unlock_dev;
                        }
-                       list_add_tail(&write_cb->cb_list,
-                                     &dev->write_waiting_list.mei_cb.cb_list);
+                       list_add_tail(&write_cb->list, &dev->write_waiting_list.list);
                } else {
-                       list_add_tail(&write_cb->cb_list,
-                                     &dev->write_list.mei_cb.cb_list);
+                       list_add_tail(&write_cb->list, &dev->write_list.list);
                }
 
        } else {
 
-               write_cb->information = 0;
+               write_cb->buf_idx = 0;
                cl->writing_state = MEI_WRITING;
-               list_add_tail(&write_cb->cb_list,
-                             &dev->write_list.mei_cb.cb_list);
+               list_add_tail(&write_cb->list, &dev->write_list.list);
        }
        mutex_unlock(&dev->device_lock);
        return length;
 
 unlock_dev:
        mutex_unlock(&dev->device_lock);
-       mei_free_cb_private(write_cb);
+       mei_io_cb_free(write_cb);
        return rets;
 }
 
index adb35fb9281c4ae82ba2a617c062293faa2b2bca..6adcb3f6621ae77c7ca1e25b7522387409023314 100644 (file)
@@ -144,12 +144,12 @@ struct mei_message_data {
 
 
 struct mei_cl_cb {
-       struct list_head cb_list;
+       struct list_head list;
        enum mei_cb_major_types major_file_operations;
        void *file_private;
        struct mei_message_data request_buffer;
        struct mei_message_data response_buffer;
-       unsigned long information;
+       unsigned long buf_idx;
        unsigned long read_time;
        struct file *file_object;
 };
@@ -175,10 +175,6 @@ struct mei_cl {
        struct mei_cl_cb *read_cb;
 };
 
-struct mei_io_list {
-       struct mei_cl_cb mei_cb;
-};
-
 /**
  * struct mei_deive -  MEI private device struct
  * @hbuf_depth - depth of host(write) buffer
@@ -189,15 +185,15 @@ struct mei_device {
         * lists of queues
         */
         /* array of pointers to aio lists */
-       struct mei_io_list read_list;           /* driver read queue */
-       struct mei_io_list write_list;          /* driver write queue */
-       struct mei_io_list write_waiting_list;  /* write waiting queue */
-       struct mei_io_list ctrl_wr_list;        /* managed write IOCTL list */
-       struct mei_io_list ctrl_rd_list;        /* managed read IOCTL list */
-       struct mei_io_list amthi_cmd_list;      /* amthi list for cmd waiting */
+       struct mei_cl_cb read_list;             /* driver read queue */
+       struct mei_cl_cb write_list;            /* driver write queue */
+       struct mei_cl_cb write_waiting_list;    /* write waiting queue */
+       struct mei_cl_cb ctrl_wr_list;          /* managed write IOCTL list */
+       struct mei_cl_cb ctrl_rd_list;          /* managed read IOCTL list */
+       struct mei_cl_cb amthi_cmd_list;        /* amthi list for cmd waiting */
 
        /* driver managed amthi list for reading completed amthi cmd data */
-       struct mei_io_list amthi_read_complete_list;
+       struct mei_cl_cb amthi_read_complete_list;
        /*
         * list of files
         */
@@ -295,10 +291,24 @@ int mei_me_cl_by_uuid(const struct mei_device *dev, const uuid_le *cuuid);
 int mei_me_cl_by_id(struct mei_device *dev, u8 client_id);
 
 /*
- * MEI IO List Functions
+ * MEI IO Functions
  */
-void mei_io_list_init(struct mei_io_list *list);
-void mei_io_list_flush(struct mei_io_list *list, struct mei_cl *cl);
+struct mei_cl_cb *mei_io_cb_init(struct mei_cl *cl, struct file *fp);
+void mei_io_cb_free(struct mei_cl_cb *priv_cb);
+int mei_io_cb_alloc_req_buf(struct mei_cl_cb *cb, size_t length);
+int mei_io_cb_alloc_resp_buf(struct mei_cl_cb *cb, size_t length);
+
+
+/**
+ * mei_io_list_init - Sets up a queue list.
+ *
+ * @list: An instance cl callback structure
+ */
+static inline void mei_io_list_init(struct mei_cl_cb *list)
+{
+       INIT_LIST_HEAD(&list->list);
+}
+void mei_io_list_flush(struct mei_cl_cb *list, struct mei_cl *cl);
 
 /*
  * MEI ME Client Functions
@@ -357,7 +367,6 @@ struct mei_cl_cb *find_amthi_read_list_entry(struct mei_device *dev,
 
 void mei_run_next_iamthif_cmd(struct mei_device *dev);
 
-void mei_free_cb_private(struct mei_cl_cb *priv_cb);
 
 
 /*
index e360a979857d297e1468a7c9aa41b86a975a2f82..fadf52eb5d70d410bc0055d379b248413e680d6b 100644 (file)
@@ -68,6 +68,16 @@ static int mmc_queue_thread(void *d)
                if (req || mq->mqrq_prev->req) {
                        set_current_state(TASK_RUNNING);
                        mq->issue_fn(mq, req);
+
+                       /*
+                        * Current request becomes previous request
+                        * and vice versa.
+                        */
+                       mq->mqrq_prev->brq.mrq.data = NULL;
+                       mq->mqrq_prev->req = NULL;
+                       tmp = mq->mqrq_prev;
+                       mq->mqrq_prev = mq->mqrq_cur;
+                       mq->mqrq_cur = tmp;
                } else {
                        if (kthread_should_stop()) {
                                set_current_state(TASK_RUNNING);
@@ -77,13 +87,6 @@ static int mmc_queue_thread(void *d)
                        schedule();
                        down(&mq->thread_sem);
                }
-
-               /* Current request becomes previous request and vice versa. */
-               mq->mqrq_prev->brq.mrq.data = NULL;
-               mq->mqrq_prev->req = NULL;
-               tmp = mq->mqrq_prev;
-               mq->mqrq_prev = mq->mqrq_cur;
-               mq->mqrq_cur = tmp;
        } while (1);
        up(&mq->thread_sem);
 
index 9bf10e7bbfaffaafed7a373cb320cfb76c5e7fce..dee73c0dc7dfd3cc477e8e662cd4c366cf10b1b9 100644 (file)
@@ -621,3 +621,10 @@ config MMC_USHC
 
          Note: These controllers only support SDIO cards and do not
          support MMC or SD memory cards.
+
+config MMC_REALTEK_PCI
+       tristate "Realtek PCI-E SD/MMC card interface driver"
+       depends on MFD_RTSX_PCI
+       help
+         Say Y or M here to include driver code to support the SD/MMC
+         card interfaces of Realtek PCI-E driver-based card readers.
index 17ad0a7ba40b4bfcb79c665df49c4798747cece3..0f804d1a3ce4b474ce0c4797eff059d7c557f98e 100644 (file)
@@ -45,6 +45,7 @@ obj-$(CONFIG_MMC_SH_MMCIF)    += sh_mmcif.o
 obj-$(CONFIG_MMC_JZ4740)       += jz4740_mmc.o
 obj-$(CONFIG_MMC_VUB300)       += vub300.o
 obj-$(CONFIG_MMC_USHC)         += ushc.o
+obj-$(CONFIG_MMC_REALTEK_PCI)  += rtsx_pci_sdmmc.o
 
 obj-$(CONFIG_MMC_SDHCI_PLTFM)          += sdhci-pltfm.o
 obj-$(CONFIG_MMC_SDHCI_CNS3XXX)                += sdhci-cns3xxx.o
index edb37e9135ae3741b5bafef61633c2740e01f8f1..53a09cbb2c7c98ce3863d9c18b43a015dc6570ef 100644 (file)
@@ -134,7 +134,7 @@ static struct pci_driver dw_mci_pci_driver = {
        .name           = "dw_mmc_pci",
        .id_table       = dw_mci_pci_id,
        .probe          = dw_mci_pci_probe,
-       .remove         = dw_mci_pci_remove,
+       .remove         = __devexit_p(dw_mci_pci_remove),
        .driver         =       {
                .pm =   &dw_mci_pci_pmops
        },
index c960ca7ffbe694fa367ff7ca88c83003b3da59a6..779335bc8e9390e39679472e5f80ef480627a7d5 100644 (file)
@@ -119,7 +119,8 @@ static const struct of_device_id dw_mci_pltfm_match[] = {
 MODULE_DEVICE_TABLE(of, dw_mci_pltfm_match);
 
 static struct platform_driver dw_mci_pltfm_driver = {
-       .remove         = __exit_p(dw_mci_pltfm_remove),
+       .probe          = dw_mci_pltfm_probe,
+       .remove         = __devexit_p(dw_mci_pltfm_remove),
        .driver         = {
                .name           = "dw_mmc",
                .of_match_table = of_match_ptr(dw_mci_pltfm_match),
@@ -127,18 +128,7 @@ static struct platform_driver dw_mci_pltfm_driver = {
        },
 };
 
-static int __init dw_mci_init(void)
-{
-       return platform_driver_probe(&dw_mci_pltfm_driver, dw_mci_pltfm_probe);
-}
-
-static void __exit dw_mci_exit(void)
-{
-       platform_driver_unregister(&dw_mci_pltfm_driver);
-}
-
-module_init(dw_mci_init);
-module_exit(dw_mci_exit);
+module_platform_driver(dw_mci_pltfm_driver);
 
 MODULE_DESCRIPTION("DW Multimedia Card Interface driver");
 MODULE_AUTHOR("NXP Semiconductor VietNam");
index c2828f35c3b8812b4de12cb0fd4b75c28fa09bbf..250aa1836591bf48ec6b007c5833c8cfc67c0955 100644 (file)
@@ -1968,7 +1968,7 @@ static void dw_mci_init_dma(struct dw_mci *host)
        /* Determine which DMA interface to use */
 #ifdef CONFIG_MMC_DW_IDMAC
        host->dma_ops = &dw_mci_idmac_ops;
-       dev_info(&host->dev, "Using internal DMA controller.\n");
+       dev_info(host->dev, "Using internal DMA controller.\n");
 #endif
 
        if (!host->dma_ops)
index edc3e9baf0e7bea7be23841c11692968ad2a344b..cd0fbee0b1c0ad2e33da671cb2d7d7110c0c540b 100644 (file)
@@ -654,9 +654,31 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data)
 
        /* The ST Micro variants has a special bit to enable SDIO */
        if (variant->sdio && host->mmc->card)
-               if (mmc_card_sdio(host->mmc->card))
+               if (mmc_card_sdio(host->mmc->card)) {
+                       /*
+                        * The ST Micro variants has a special bit
+                        * to enable SDIO.
+                        */
+                       u32 clk;
+
                        datactrl |= MCI_ST_DPSM_SDIOEN;
 
+                       /*
+                        * The ST Micro variant for SDIO small write transfers
+                        * needs to have clock H/W flow control disabled,
+                        * otherwise the transfer will not start. The threshold
+                        * depends on the rate of MCLK.
+                        */
+                       if (data->flags & MMC_DATA_WRITE &&
+                           (host->size < 8 ||
+                            (host->size <= 8 && host->mclk > 50000000)))
+                               clk = host->clk_reg & ~variant->clkreg_enable;
+                       else
+                               clk = host->clk_reg | variant->clkreg_enable;
+
+                       mmci_write_clkreg(host, clk);
+               }
+
        /*
         * Attempt to use DMA operation mode, if this
         * should fail, fall back to PIO mode
@@ -876,22 +898,6 @@ static int mmci_pio_write(struct mmci_host *host, char *buffer, unsigned int rem
                         variant->fifosize : variant->fifohalfsize;
                count = min(remain, maxcnt);
 
-               /*
-                * The ST Micro variant for SDIO transfer sizes
-                * less then 8 bytes should have clock H/W flow
-                * control disabled.
-                */
-               if (variant->sdio &&
-                   mmc_card_sdio(host->mmc->card)) {
-                       u32 clk;
-                       if (count < 8)
-                               clk = host->clk_reg & ~variant->clkreg_enable;
-                       else
-                               clk = host->clk_reg | variant->clkreg_enable;
-
-                       mmci_write_clkreg(host, clk);
-               }
-
                /*
                 * SDIO especially may want to send something that is
                 * not divisible by 4 (as opposed to card sectors
index 565c2e4fac75cecd8890ec2d9885ffb50cc23060..d735ba913f9b23f0a65861bee2fa975fdeb3e97f 100644 (file)
@@ -41,7 +41,6 @@
 #include <linux/platform_data/mmc-mxcmmc.h>
 
 #include <linux/platform_data/dma-imx.h>
-#include <mach/hardware.h>
 
 #define DRIVER_NAME "mxc-mmc"
 #define MXCMCI_TIMEOUT_MS 10000
 #define INT_WRITE_OP_DONE_EN           (1 << 1)
 #define INT_READ_OP_EN                 (1 << 0)
 
+enum mxcmci_type {
+       IMX21_MMC,
+       IMX31_MMC,
+};
+
 struct mxcmci_host {
        struct mmc_host         *mmc;
        struct resource         *res;
@@ -153,7 +157,26 @@ struct mxcmci_host {
        struct imx_dma_data     dma_data;
 
        struct timer_list       watchdog;
+       enum mxcmci_type        devtype;
+};
+
+static struct platform_device_id mxcmci_devtype[] = {
+       {
+               .name = "imx21-mmc",
+               .driver_data = IMX21_MMC,
+       }, {
+               .name = "imx31-mmc",
+               .driver_data = IMX31_MMC,
+       }, {
+               /* sentinel */
+       }
 };
+MODULE_DEVICE_TABLE(platform, mxcmci_devtype);
+
+static inline int is_imx31_mmc(struct mxcmci_host *host)
+{
+       return host->devtype == IMX31_MMC;
+}
 
 static void mxcmci_set_clk_rate(struct mxcmci_host *host, unsigned int clk_ios);
 
@@ -843,6 +866,8 @@ static void mxcmci_enable_sdio_irq(struct mmc_host *mmc, int enable)
 
 static void mxcmci_init_card(struct mmc_host *host, struct mmc_card *card)
 {
+       struct mxcmci_host *mxcmci = mmc_priv(host);
+
        /*
         * MX3 SoCs have a silicon bug which corrupts CRC calculation of
         * multi-block transfers when connected SDIO peripheral doesn't
@@ -850,7 +875,7 @@ static void mxcmci_init_card(struct mmc_host *host, struct mmc_card *card)
         * One way to prevent this is to only allow 1-bit transfers.
         */
 
-       if (cpu_is_mx3() && card->type == MMC_TYPE_SDIO)
+       if (is_imx31_mmc(mxcmci) && card->type == MMC_TYPE_SDIO)
                host->caps &= ~MMC_CAP_4_BIT_DATA;
        else
                host->caps |= MMC_CAP_4_BIT_DATA;
@@ -948,6 +973,7 @@ static int mxcmci_probe(struct platform_device *pdev)
 
        host->mmc = mmc;
        host->pdata = pdev->dev.platform_data;
+       host->devtype = pdev->id_entry->driver_data;
        spin_lock_init(&host->lock);
 
        mxcmci_init_ocr(host);
@@ -1120,6 +1146,7 @@ static const struct dev_pm_ops mxcmci_pm_ops = {
 static struct platform_driver mxcmci_driver = {
        .probe          = mxcmci_probe,
        .remove         = mxcmci_remove,
+       .id_table       = mxcmci_devtype,
        .driver         = {
                .name           = DRIVER_NAME,
                .owner          = THIS_MODULE,
diff --git a/drivers/mmc/host/rtsx_pci_sdmmc.c b/drivers/mmc/host/rtsx_pci_sdmmc.c
new file mode 100644 (file)
index 0000000..6afbb3c
--- /dev/null
@@ -0,0 +1,1332 @@
+/* Realtek PCI-Express SD/MMC Card Interface driver
+ *
+ * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author:
+ *   Wei WANG <wei_wang@realsil.com.cn>
+ *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
+ */
+
+#include <linux/module.h>
+#include <linux/highmem.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/sd.h>
+#include <linux/mmc/card.h>
+#include <linux/mfd/rtsx_pci.h>
+#include <asm/unaligned.h>
+
+/* SD Tuning Data Structure
+ * Record continuous timing phase path
+ */
+struct timing_phase_path {
+       int start;
+       int end;
+       int mid;
+       int len;
+};
+
+struct realtek_pci_sdmmc {
+       struct platform_device  *pdev;
+       struct rtsx_pcr         *pcr;
+       struct mmc_host         *mmc;
+       struct mmc_request      *mrq;
+
+       struct mutex            host_mutex;
+
+       u8                      ssc_depth;
+       unsigned int            clock;
+       bool                    vpclk;
+       bool                    double_clk;
+       bool                    eject;
+       bool                    initial_mode;
+       bool                    ddr_mode;
+};
+
+static inline struct device *sdmmc_dev(struct realtek_pci_sdmmc *host)
+{
+       return &(host->pdev->dev);
+}
+
+static inline void sd_clear_error(struct realtek_pci_sdmmc *host)
+{
+       rtsx_pci_write_register(host->pcr, CARD_STOP,
+                       SD_STOP | SD_CLR_ERR, SD_STOP | SD_CLR_ERR);
+}
+
+#ifdef DEBUG
+static void sd_print_debug_regs(struct realtek_pci_sdmmc *host)
+{
+       struct rtsx_pcr *pcr = host->pcr;
+       u16 i;
+       u8 *ptr;
+
+       /* Print SD host internal registers */
+       rtsx_pci_init_cmd(pcr);
+       for (i = 0xFDA0; i <= 0xFDAE; i++)
+               rtsx_pci_add_cmd(pcr, READ_REG_CMD, i, 0, 0);
+       for (i = 0xFD52; i <= 0xFD69; i++)
+               rtsx_pci_add_cmd(pcr, READ_REG_CMD, i, 0, 0);
+       rtsx_pci_send_cmd(pcr, 100);
+
+       ptr = rtsx_pci_get_cmd_data(pcr);
+       for (i = 0xFDA0; i <= 0xFDAE; i++)
+               dev_dbg(sdmmc_dev(host), "0x%04X: 0x%02x\n", i, *(ptr++));
+       for (i = 0xFD52; i <= 0xFD69; i++)
+               dev_dbg(sdmmc_dev(host), "0x%04X: 0x%02x\n", i, *(ptr++));
+}
+#else
+#define sd_print_debug_regs(host)
+#endif /* DEBUG */
+
+static int sd_read_data(struct realtek_pci_sdmmc *host, u8 *cmd, u16 byte_cnt,
+               u8 *buf, int buf_len, int timeout)
+{
+       struct rtsx_pcr *pcr = host->pcr;
+       int err, i;
+       u8 trans_mode;
+
+       dev_dbg(sdmmc_dev(host), "%s: SD/MMC CMD%d\n", __func__, cmd[0] - 0x40);
+
+       if (!buf)
+               buf_len = 0;
+
+       if ((cmd[0] & 0x3F) == MMC_SEND_TUNING_BLOCK)
+               trans_mode = SD_TM_AUTO_TUNING;
+       else
+               trans_mode = SD_TM_NORMAL_READ;
+
+       rtsx_pci_init_cmd(pcr);
+
+       for (i = 0; i < 5; i++)
+               rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CMD0 + i, 0xFF, cmd[i]);
+
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BYTE_CNT_L, 0xFF, (u8)byte_cnt);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BYTE_CNT_H,
+                       0xFF, (u8)(byte_cnt >> 8));
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BLOCK_CNT_L, 0xFF, 1);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BLOCK_CNT_H, 0xFF, 0);
+
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CFG2, 0xFF,
+                       SD_CALCULATE_CRC7 | SD_CHECK_CRC16 |
+                       SD_NO_WAIT_BUSY_END | SD_CHECK_CRC7 | SD_RSP_LEN_6);
+       if (trans_mode != SD_TM_AUTO_TUNING)
+               rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
+                               CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER);
+
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_TRANSFER,
+                       0xFF, trans_mode | SD_TRANSFER_START);
+       rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, SD_TRANSFER,
+                       SD_TRANSFER_END, SD_TRANSFER_END);
+
+       err = rtsx_pci_send_cmd(pcr, timeout);
+       if (err < 0) {
+               sd_print_debug_regs(host);
+               dev_dbg(sdmmc_dev(host),
+                       "rtsx_pci_send_cmd fail (err = %d)\n", err);
+               return err;
+       }
+
+       if (buf && buf_len) {
+               err = rtsx_pci_read_ppbuf(pcr, buf, buf_len);
+               if (err < 0) {
+                       dev_dbg(sdmmc_dev(host),
+                               "rtsx_pci_read_ppbuf fail (err = %d)\n", err);
+                       return err;
+               }
+       }
+
+       return 0;
+}
+
+static int sd_write_data(struct realtek_pci_sdmmc *host, u8 *cmd, u16 byte_cnt,
+               u8 *buf, int buf_len, int timeout)
+{
+       struct rtsx_pcr *pcr = host->pcr;
+       int err, i;
+       u8 trans_mode;
+
+       if (!buf)
+               buf_len = 0;
+
+       if (buf && buf_len) {
+               err = rtsx_pci_write_ppbuf(pcr, buf, buf_len);
+               if (err < 0) {
+                       dev_dbg(sdmmc_dev(host),
+                               "rtsx_pci_write_ppbuf fail (err = %d)\n", err);
+                       return err;
+               }
+       }
+
+       trans_mode = cmd ? SD_TM_AUTO_WRITE_2 : SD_TM_AUTO_WRITE_3;
+       rtsx_pci_init_cmd(pcr);
+
+       if (cmd) {
+               dev_dbg(sdmmc_dev(host), "%s: SD/MMC CMD %d\n", __func__,
+                               cmd[0] - 0x40);
+
+               for (i = 0; i < 5; i++)
+                       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
+                                       SD_CMD0 + i, 0xFF, cmd[i]);
+       }
+
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BYTE_CNT_L, 0xFF, (u8)byte_cnt);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BYTE_CNT_H,
+                       0xFF, (u8)(byte_cnt >> 8));
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BLOCK_CNT_L, 0xFF, 1);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BLOCK_CNT_H, 0xFF, 0);
+
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CFG2, 0xFF,
+               SD_CALCULATE_CRC7 | SD_CHECK_CRC16 |
+               SD_NO_WAIT_BUSY_END | SD_CHECK_CRC7 | SD_RSP_LEN_6);
+
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_TRANSFER, 0xFF,
+                       trans_mode | SD_TRANSFER_START);
+       rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, SD_TRANSFER,
+                       SD_TRANSFER_END, SD_TRANSFER_END);
+
+       err = rtsx_pci_send_cmd(pcr, timeout);
+       if (err < 0) {
+               sd_print_debug_regs(host);
+               dev_dbg(sdmmc_dev(host),
+                       "rtsx_pci_send_cmd fail (err = %d)\n", err);
+               return err;
+       }
+
+       return 0;
+}
+
+static void sd_send_cmd_get_rsp(struct realtek_pci_sdmmc *host,
+               struct mmc_command *cmd)
+{
+       struct rtsx_pcr *pcr = host->pcr;
+       u8 cmd_idx = (u8)cmd->opcode;
+       u32 arg = cmd->arg;
+       int err = 0;
+       int timeout = 100;
+       int i;
+       u8 *ptr;
+       int stat_idx = 0;
+       u8 rsp_type;
+       int rsp_len = 5;
+
+       dev_dbg(sdmmc_dev(host), "%s: SD/MMC CMD %d, arg = 0x%08x\n",
+                       __func__, cmd_idx, arg);
+
+       /* Response type:
+        * R0
+        * R1, R5, R6, R7
+        * R1b
+        * R2
+        * R3, R4
+        */
+       switch (mmc_resp_type(cmd)) {
+       case MMC_RSP_NONE:
+               rsp_type = SD_RSP_TYPE_R0;
+               rsp_len = 0;
+               break;
+       case MMC_RSP_R1:
+               rsp_type = SD_RSP_TYPE_R1;
+               break;
+       case MMC_RSP_R1B:
+               rsp_type = SD_RSP_TYPE_R1b;
+               break;
+       case MMC_RSP_R2:
+               rsp_type = SD_RSP_TYPE_R2;
+               rsp_len = 16;
+               break;
+       case MMC_RSP_R3:
+               rsp_type = SD_RSP_TYPE_R3;
+               break;
+       default:
+               dev_dbg(sdmmc_dev(host), "cmd->flag is not valid\n");
+               err = -EINVAL;
+               goto out;
+       }
+
+       if (rsp_type == SD_RSP_TYPE_R1b)
+               timeout = 3000;
+
+       if (cmd->opcode == SD_SWITCH_VOLTAGE) {
+               err = rtsx_pci_write_register(pcr, SD_BUS_STAT,
+                               0xFF, SD_CLK_TOGGLE_EN);
+               if (err < 0)
+                       goto out;
+       }
+
+       rtsx_pci_init_cmd(pcr);
+
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CMD0, 0xFF, 0x40 | cmd_idx);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CMD1, 0xFF, (u8)(arg >> 24));
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CMD2, 0xFF, (u8)(arg >> 16));
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CMD3, 0xFF, (u8)(arg >> 8));
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CMD4, 0xFF, (u8)arg);
+
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CFG2, 0xFF, rsp_type);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_DATA_SOURCE,
+                       0x01, PINGPONG_BUFFER);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_TRANSFER,
+                       0xFF, SD_TM_CMD_RSP | SD_TRANSFER_START);
+       rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, SD_TRANSFER,
+                    SD_TRANSFER_END | SD_STAT_IDLE,
+                    SD_TRANSFER_END | SD_STAT_IDLE);
+
+       if (rsp_type == SD_RSP_TYPE_R2) {
+               /* Read data from ping-pong buffer */
+               for (i = PPBUF_BASE2; i < PPBUF_BASE2 + 16; i++)
+                       rtsx_pci_add_cmd(pcr, READ_REG_CMD, (u16)i, 0, 0);
+               stat_idx = 16;
+       } else if (rsp_type != SD_RSP_TYPE_R0) {
+               /* Read data from SD_CMDx registers */
+               for (i = SD_CMD0; i <= SD_CMD4; i++)
+                       rtsx_pci_add_cmd(pcr, READ_REG_CMD, (u16)i, 0, 0);
+               stat_idx = 5;
+       }
+
+       rtsx_pci_add_cmd(pcr, READ_REG_CMD, SD_STAT1, 0, 0);
+
+       err = rtsx_pci_send_cmd(pcr, timeout);
+       if (err < 0) {
+               sd_print_debug_regs(host);
+               sd_clear_error(host);
+               dev_dbg(sdmmc_dev(host),
+                       "rtsx_pci_send_cmd error (err = %d)\n", err);
+               goto out;
+       }
+
+       if (rsp_type == SD_RSP_TYPE_R0) {
+               err = 0;
+               goto out;
+       }
+
+       /* Eliminate returned value of CHECK_REG_CMD */
+       ptr = rtsx_pci_get_cmd_data(pcr) + 1;
+
+       /* Check (Start,Transmission) bit of Response */
+       if ((ptr[0] & 0xC0) != 0) {
+               err = -EILSEQ;
+               dev_dbg(sdmmc_dev(host), "Invalid response bit\n");
+               goto out;
+       }
+
+       /* Check CRC7 */
+       if (!(rsp_type & SD_NO_CHECK_CRC7)) {
+               if (ptr[stat_idx] & SD_CRC7_ERR) {
+                       err = -EILSEQ;
+                       dev_dbg(sdmmc_dev(host), "CRC7 error\n");
+                       goto out;
+               }
+       }
+
+       if (rsp_type == SD_RSP_TYPE_R2) {
+               for (i = 0; i < 4; i++) {
+                       cmd->resp[i] = get_unaligned_be32(ptr + 1 + i * 4);
+                       dev_dbg(sdmmc_dev(host), "cmd->resp[%d] = 0x%08x\n",
+                                       i, cmd->resp[i]);
+               }
+       } else {
+               cmd->resp[0] = get_unaligned_be32(ptr + 1);
+               dev_dbg(sdmmc_dev(host), "cmd->resp[0] = 0x%08x\n",
+                               cmd->resp[0]);
+       }
+
+out:
+       cmd->error = err;
+}
+
+static int sd_rw_multi(struct realtek_pci_sdmmc *host, struct mmc_request *mrq)
+{
+       struct rtsx_pcr *pcr = host->pcr;
+       struct mmc_host *mmc = host->mmc;
+       struct mmc_card *card = mmc->card;
+       struct mmc_data *data = mrq->data;
+       int uhs = mmc_sd_card_uhs(card);
+       int read = (data->flags & MMC_DATA_READ) ? 1 : 0;
+       u8 cfg2, trans_mode;
+       int err;
+       size_t data_len = data->blksz * data->blocks;
+
+       if (read) {
+               cfg2 = SD_CALCULATE_CRC7 | SD_CHECK_CRC16 |
+                       SD_NO_WAIT_BUSY_END | SD_CHECK_CRC7 | SD_RSP_LEN_0;
+               trans_mode = SD_TM_AUTO_READ_3;
+       } else {
+               cfg2 = SD_NO_CALCULATE_CRC7 | SD_CHECK_CRC16 |
+                       SD_NO_WAIT_BUSY_END | SD_NO_CHECK_CRC7 | SD_RSP_LEN_0;
+               trans_mode = SD_TM_AUTO_WRITE_3;
+       }
+
+       if (!uhs)
+               cfg2 |= SD_NO_CHECK_WAIT_CRC_TO;
+
+       rtsx_pci_init_cmd(pcr);
+
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BYTE_CNT_L, 0xFF, 0x00);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BYTE_CNT_H, 0xFF, 0x02);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BLOCK_CNT_L,
+                       0xFF, (u8)data->blocks);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BLOCK_CNT_H,
+                       0xFF, (u8)(data->blocks >> 8));
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
+                       CARD_DATA_SOURCE, 0x01, RING_BUFFER);
+
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, IRQSTAT0,
+                       DMA_DONE_INT, DMA_DONE_INT);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC3,
+                       0xFF, (u8)(data_len >> 24));
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC2,
+                       0xFF, (u8)(data_len >> 16));
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC1,
+                       0xFF, (u8)(data_len >> 8));
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC0, 0xFF, (u8)data_len);
+       if (read) {
+               rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMACTL,
+                               0x03 | DMA_PACK_SIZE_MASK,
+                               DMA_DIR_FROM_CARD | DMA_EN | DMA_512);
+       } else {
+               rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMACTL,
+                               0x03 | DMA_PACK_SIZE_MASK,
+                               DMA_DIR_TO_CARD | DMA_EN | DMA_512);
+       }
+
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_DATA_SOURCE,
+                       0x01, RING_BUFFER);
+
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_TRANSFER, 0xFF,
+                       trans_mode | SD_TRANSFER_START);
+       rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, SD_TRANSFER,
+                       SD_TRANSFER_END, SD_TRANSFER_END);
+
+       rtsx_pci_send_cmd_no_wait(pcr);
+
+       err = rtsx_pci_transfer_data(pcr, data->sg, data->sg_len, read, 10000);
+       if (err < 0) {
+               sd_clear_error(host);
+               return err;
+       }
+
+       return 0;
+}
+
+static inline void sd_enable_initial_mode(struct realtek_pci_sdmmc *host)
+{
+       rtsx_pci_write_register(host->pcr, SD_CFG1,
+                       SD_CLK_DIVIDE_MASK, SD_CLK_DIVIDE_128);
+}
+
+static inline void sd_disable_initial_mode(struct realtek_pci_sdmmc *host)
+{
+       rtsx_pci_write_register(host->pcr, SD_CFG1,
+                       SD_CLK_DIVIDE_MASK, SD_CLK_DIVIDE_0);
+}
+
+static void sd_normal_rw(struct realtek_pci_sdmmc *host,
+               struct mmc_request *mrq)
+{
+       struct mmc_command *cmd = mrq->cmd;
+       struct mmc_data *data = mrq->data;
+       u8 _cmd[5], *buf;
+
+       _cmd[0] = 0x40 | (u8)cmd->opcode;
+       put_unaligned_be32(cmd->arg, (u32 *)(&_cmd[1]));
+
+       buf = kzalloc(data->blksz, GFP_NOIO);
+       if (!buf) {
+               cmd->error = -ENOMEM;
+               return;
+       }
+
+       if (data->flags & MMC_DATA_READ) {
+               if (host->initial_mode)
+                       sd_disable_initial_mode(host);
+
+               cmd->error = sd_read_data(host, _cmd, (u16)data->blksz, buf,
+                               data->blksz, 200);
+
+               if (host->initial_mode)
+                       sd_enable_initial_mode(host);
+
+               sg_copy_from_buffer(data->sg, data->sg_len, buf, data->blksz);
+       } else {
+               sg_copy_to_buffer(data->sg, data->sg_len, buf, data->blksz);
+
+               cmd->error = sd_write_data(host, _cmd, (u16)data->blksz, buf,
+                               data->blksz, 200);
+       }
+
+       kfree(buf);
+}
+
+static int sd_change_phase(struct realtek_pci_sdmmc *host, u8 sample_point)
+{
+       struct rtsx_pcr *pcr = host->pcr;
+       int err;
+
+       dev_dbg(sdmmc_dev(host), "%s: sample_point = %d\n",
+                       __func__, sample_point);
+
+       rtsx_pci_init_cmd(pcr);
+
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL, CHANGE_CLK, CHANGE_CLK);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_VPRX_CTL, 0x1F, sample_point);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_VPCLK0_CTL, PHASE_NOT_RESET, 0);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_VPCLK0_CTL,
+                       PHASE_NOT_RESET, PHASE_NOT_RESET);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL, CHANGE_CLK, 0);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CFG1, SD_ASYNC_FIFO_NOT_RST, 0);
+
+       err = rtsx_pci_send_cmd(pcr, 100);
+       if (err < 0)
+               return err;
+
+       return 0;
+}
+
+static u8 sd_search_final_phase(struct realtek_pci_sdmmc *host, u32 phase_map)
+{
+       struct timing_phase_path path[MAX_PHASE + 1];
+       int i, j, cont_path_cnt;
+       int new_block, max_len, final_path_idx;
+       u8 final_phase = 0xFF;
+
+       /* Parse phase_map, take it as a bit-ring */
+       cont_path_cnt = 0;
+       new_block = 1;
+       j = 0;
+       for (i = 0; i < MAX_PHASE + 1; i++) {
+               if (phase_map & (1 << i)) {
+                       if (new_block) {
+                               new_block = 0;
+                               j = cont_path_cnt++;
+                               path[j].start = i;
+                               path[j].end = i;
+                       } else {
+                               path[j].end = i;
+                       }
+               } else {
+                       new_block = 1;
+                       if (cont_path_cnt) {
+                               /* Calculate path length and middle point */
+                               int idx = cont_path_cnt - 1;
+                               path[idx].len =
+                                       path[idx].end - path[idx].start + 1;
+                               path[idx].mid =
+                                       path[idx].start + path[idx].len / 2;
+                       }
+               }
+       }
+
+       if (cont_path_cnt == 0) {
+               dev_dbg(sdmmc_dev(host), "No continuous phase path\n");
+               goto finish;
+       } else {
+               /* Calculate last continuous path length and middle point */
+               int idx = cont_path_cnt - 1;
+               path[idx].len = path[idx].end - path[idx].start + 1;
+               path[idx].mid = path[idx].start + path[idx].len / 2;
+       }
+
+       /* Connect the first and last continuous paths if they are adjacent */
+       if (!path[0].start && (path[cont_path_cnt - 1].end == MAX_PHASE)) {
+               /* Using negative index */
+               path[0].start = path[cont_path_cnt - 1].start - MAX_PHASE - 1;
+               path[0].len += path[cont_path_cnt - 1].len;
+               path[0].mid = path[0].start + path[0].len / 2;
+               /* Convert negative middle point index to positive one */
+               if (path[0].mid < 0)
+                       path[0].mid += MAX_PHASE + 1;
+               cont_path_cnt--;
+       }
+
+       /* Choose the longest continuous phase path */
+       max_len = 0;
+       final_phase = 0;
+       final_path_idx = 0;
+       for (i = 0; i < cont_path_cnt; i++) {
+               if (path[i].len > max_len) {
+                       max_len = path[i].len;
+                       final_phase = (u8)path[i].mid;
+                       final_path_idx = i;
+               }
+
+               dev_dbg(sdmmc_dev(host), "path[%d].start = %d\n",
+                               i, path[i].start);
+               dev_dbg(sdmmc_dev(host), "path[%d].end = %d\n",
+                               i, path[i].end);
+               dev_dbg(sdmmc_dev(host), "path[%d].len = %d\n",
+                               i, path[i].len);
+               dev_dbg(sdmmc_dev(host), "path[%d].mid = %d\n",
+                               i, path[i].mid);
+       }
+
+finish:
+       dev_dbg(sdmmc_dev(host), "Final chosen phase: %d\n", final_phase);
+       return final_phase;
+}
+
+static void sd_wait_data_idle(struct realtek_pci_sdmmc *host)
+{
+       int err, i;
+       u8 val = 0;
+
+       for (i = 0; i < 100; i++) {
+               err = rtsx_pci_read_register(host->pcr, SD_DATA_STATE, &val);
+               if (val & SD_DATA_IDLE)
+                       return;
+
+               udelay(100);
+       }
+}
+
+static int sd_tuning_rx_cmd(struct realtek_pci_sdmmc *host,
+               u8 opcode, u8 sample_point)
+{
+       int err;
+       u8 cmd[5] = {0};
+
+       err = sd_change_phase(host, sample_point);
+       if (err < 0)
+               return err;
+
+       cmd[0] = 0x40 | opcode;
+       err = sd_read_data(host, cmd, 0x40, NULL, 0, 100);
+       if (err < 0) {
+               /* Wait till SD DATA IDLE */
+               sd_wait_data_idle(host);
+               sd_clear_error(host);
+               return err;
+       }
+
+       return 0;
+}
+
+static int sd_tuning_phase(struct realtek_pci_sdmmc *host,
+               u8 opcode, u32 *phase_map)
+{
+       int err, i;
+       u32 raw_phase_map = 0;
+
+       for (i = MAX_PHASE; i >= 0; i--) {
+               err = sd_tuning_rx_cmd(host, opcode, (u8)i);
+               if (err == 0)
+                       raw_phase_map |= 1 << i;
+       }
+
+       if (phase_map)
+               *phase_map = raw_phase_map;
+
+       return 0;
+}
+
+static int sd_tuning_rx(struct realtek_pci_sdmmc *host, u8 opcode)
+{
+       int err, i;
+       u32 raw_phase_map[RX_TUNING_CNT] = {0}, phase_map;
+       u8 final_phase;
+
+       for (i = 0; i < RX_TUNING_CNT; i++) {
+               err = sd_tuning_phase(host, opcode, &(raw_phase_map[i]));
+               if (err < 0)
+                       return err;
+
+               if (raw_phase_map[i] == 0)
+                       break;
+       }
+
+       phase_map = 0xFFFFFFFF;
+       for (i = 0; i < RX_TUNING_CNT; i++) {
+               dev_dbg(sdmmc_dev(host), "RX raw_phase_map[%d] = 0x%08x\n",
+                               i, raw_phase_map[i]);
+               phase_map &= raw_phase_map[i];
+       }
+       dev_dbg(sdmmc_dev(host), "RX phase_map = 0x%08x\n", phase_map);
+
+       if (phase_map) {
+               final_phase = sd_search_final_phase(host, phase_map);
+               if (final_phase == 0xFF)
+                       return -EINVAL;
+
+               err = sd_change_phase(host, final_phase);
+               if (err < 0)
+                       return err;
+       } else {
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static void sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
+{
+       struct realtek_pci_sdmmc *host = mmc_priv(mmc);
+       struct rtsx_pcr *pcr = host->pcr;
+       struct mmc_command *cmd = mrq->cmd;
+       struct mmc_data *data = mrq->data;
+       unsigned int data_size = 0;
+
+       if (host->eject) {
+               cmd->error = -ENOMEDIUM;
+               goto finish;
+       }
+
+       mutex_lock(&pcr->pcr_mutex);
+
+       rtsx_pci_start_run(pcr);
+
+       rtsx_pci_switch_clock(pcr, host->clock, host->ssc_depth,
+                       host->initial_mode, host->double_clk, host->vpclk);
+       rtsx_pci_write_register(pcr, CARD_SELECT, 0x07, SD_MOD_SEL);
+       rtsx_pci_write_register(pcr, CARD_SHARE_MODE,
+                       CARD_SHARE_MASK, CARD_SHARE_48_SD);
+
+       mutex_lock(&host->host_mutex);
+       host->mrq = mrq;
+       mutex_unlock(&host->host_mutex);
+
+       if (mrq->data)
+               data_size = data->blocks * data->blksz;
+
+       if (!data_size || mmc_op_multi(cmd->opcode) ||
+                       (cmd->opcode == MMC_READ_SINGLE_BLOCK) ||
+                       (cmd->opcode == MMC_WRITE_BLOCK)) {
+               sd_send_cmd_get_rsp(host, cmd);
+
+               if (!cmd->error && data_size) {
+                       sd_rw_multi(host, mrq);
+
+                       if (mmc_op_multi(cmd->opcode) && mrq->stop)
+                               sd_send_cmd_get_rsp(host, mrq->stop);
+               }
+       } else {
+               sd_normal_rw(host, mrq);
+       }
+
+       if (mrq->data) {
+               if (cmd->error || data->error)
+                       data->bytes_xfered = 0;
+               else
+                       data->bytes_xfered = data->blocks * data->blksz;
+       }
+
+       mutex_unlock(&pcr->pcr_mutex);
+
+finish:
+       if (cmd->error)
+               dev_dbg(sdmmc_dev(host), "cmd->error = %d\n", cmd->error);
+
+       mutex_lock(&host->host_mutex);
+       host->mrq = NULL;
+       mutex_unlock(&host->host_mutex);
+
+       mmc_request_done(mmc, mrq);
+}
+
+static int sd_set_bus_width(struct realtek_pci_sdmmc *host,
+               unsigned char bus_width)
+{
+       int err = 0;
+       u8 width[] = {
+               [MMC_BUS_WIDTH_1] = SD_BUS_WIDTH_1BIT,
+               [MMC_BUS_WIDTH_4] = SD_BUS_WIDTH_4BIT,
+               [MMC_BUS_WIDTH_8] = SD_BUS_WIDTH_8BIT,
+       };
+
+       if (bus_width <= MMC_BUS_WIDTH_8)
+               err = rtsx_pci_write_register(host->pcr, SD_CFG1,
+                               0x03, width[bus_width]);
+
+       return err;
+}
+
+static int sd_power_on(struct realtek_pci_sdmmc *host)
+{
+       struct rtsx_pcr *pcr = host->pcr;
+       int err;
+
+       rtsx_pci_init_cmd(pcr);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_SELECT, 0x07, SD_MOD_SEL);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_SHARE_MODE,
+                       CARD_SHARE_MASK, CARD_SHARE_48_SD);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_CLK_EN,
+                       SD_CLK_EN, SD_CLK_EN);
+       err = rtsx_pci_send_cmd(pcr, 100);
+       if (err < 0)
+               return err;
+
+       err = rtsx_pci_card_pull_ctl_enable(pcr, RTSX_SD_CARD);
+       if (err < 0)
+               return err;
+
+       err = rtsx_pci_card_power_on(pcr, RTSX_SD_CARD);
+       if (err < 0)
+               return err;
+
+       err = rtsx_pci_write_register(pcr, CARD_OE, SD_OUTPUT_EN, SD_OUTPUT_EN);
+       if (err < 0)
+               return err;
+
+       return 0;
+}
+
+static int sd_power_off(struct realtek_pci_sdmmc *host)
+{
+       struct rtsx_pcr *pcr = host->pcr;
+       int err;
+
+       rtsx_pci_init_cmd(pcr);
+
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_CLK_EN, SD_CLK_EN, 0);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_OE, SD_OUTPUT_EN, 0);
+
+       err = rtsx_pci_send_cmd(pcr, 100);
+       if (err < 0)
+               return err;
+
+       err = rtsx_pci_card_power_off(pcr, RTSX_SD_CARD);
+       if (err < 0)
+               return err;
+
+       return rtsx_pci_card_pull_ctl_disable(pcr, RTSX_SD_CARD);
+}
+
+static int sd_set_power_mode(struct realtek_pci_sdmmc *host,
+               unsigned char power_mode)
+{
+       int err;
+
+       if (power_mode == MMC_POWER_OFF)
+               err = sd_power_off(host);
+       else
+               err = sd_power_on(host);
+
+       return err;
+}
+
+static int sd_set_timing(struct realtek_pci_sdmmc *host,
+               unsigned char timing, bool *ddr_mode)
+{
+       struct rtsx_pcr *pcr = host->pcr;
+       int err = 0;
+
+       *ddr_mode = false;
+
+       rtsx_pci_init_cmd(pcr);
+
+       switch (timing) {
+       case MMC_TIMING_UHS_SDR104:
+       case MMC_TIMING_UHS_SDR50:
+               rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CFG1,
+                               0x0C | SD_ASYNC_FIFO_NOT_RST,
+                               SD_30_MODE | SD_ASYNC_FIFO_NOT_RST);
+               rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL,
+                               CLK_LOW_FREQ, CLK_LOW_FREQ);
+               rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_CLK_SOURCE, 0xFF,
+                               CRC_VAR_CLK0 | SD30_FIX_CLK | SAMPLE_VAR_CLK1);
+               rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL, CLK_LOW_FREQ, 0);
+               break;
+
+       case MMC_TIMING_UHS_DDR50:
+               *ddr_mode = true;
+
+               rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CFG1,
+                               0x0C | SD_ASYNC_FIFO_NOT_RST,
+                               SD_DDR_MODE | SD_ASYNC_FIFO_NOT_RST);
+               rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL,
+                               CLK_LOW_FREQ, CLK_LOW_FREQ);
+               rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_CLK_SOURCE, 0xFF,
+                               CRC_VAR_CLK0 | SD30_FIX_CLK | SAMPLE_VAR_CLK1);
+               rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL, CLK_LOW_FREQ, 0);
+               rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_PUSH_POINT_CTL,
+                               DDR_VAR_TX_CMD_DAT, DDR_VAR_TX_CMD_DAT);
+               rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_SAMPLE_POINT_CTL,
+                               DDR_VAR_RX_DAT | DDR_VAR_RX_CMD,
+                               DDR_VAR_RX_DAT | DDR_VAR_RX_CMD);
+               break;
+
+       case MMC_TIMING_MMC_HS:
+       case MMC_TIMING_SD_HS:
+               rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CFG1,
+                               0x0C, SD_20_MODE);
+               rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL,
+                               CLK_LOW_FREQ, CLK_LOW_FREQ);
+               rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_CLK_SOURCE, 0xFF,
+                               CRC_FIX_CLK | SD30_VAR_CLK0 | SAMPLE_VAR_CLK1);
+               rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL, CLK_LOW_FREQ, 0);
+               rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_PUSH_POINT_CTL,
+                               SD20_TX_SEL_MASK, SD20_TX_14_AHEAD);
+               rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_SAMPLE_POINT_CTL,
+                               SD20_RX_SEL_MASK, SD20_RX_14_DELAY);
+               break;
+
+       default:
+               rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
+                               SD_CFG1, 0x0C, SD_20_MODE);
+               rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL,
+                               CLK_LOW_FREQ, CLK_LOW_FREQ);
+               rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_CLK_SOURCE, 0xFF,
+                               CRC_FIX_CLK | SD30_VAR_CLK0 | SAMPLE_VAR_CLK1);
+               rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL, CLK_LOW_FREQ, 0);
+               rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
+                               SD_PUSH_POINT_CTL, 0xFF, 0);
+               rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_SAMPLE_POINT_CTL,
+                               SD20_RX_SEL_MASK, SD20_RX_POS_EDGE);
+               break;
+       }
+
+       err = rtsx_pci_send_cmd(pcr, 100);
+
+       return err;
+}
+
+static void sdmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+       struct realtek_pci_sdmmc *host = mmc_priv(mmc);
+       struct rtsx_pcr *pcr = host->pcr;
+
+       if (host->eject)
+               return;
+
+       mutex_lock(&pcr->pcr_mutex);
+
+       rtsx_pci_start_run(pcr);
+
+       sd_set_bus_width(host, ios->bus_width);
+       sd_set_power_mode(host, ios->power_mode);
+       sd_set_timing(host, ios->timing, &host->ddr_mode);
+
+       host->vpclk = false;
+       host->double_clk = true;
+
+       switch (ios->timing) {
+       case MMC_TIMING_UHS_SDR104:
+       case MMC_TIMING_UHS_SDR50:
+               host->ssc_depth = RTSX_SSC_DEPTH_2M;
+               host->vpclk = true;
+               host->double_clk = false;
+               break;
+       case MMC_TIMING_UHS_DDR50:
+       case MMC_TIMING_UHS_SDR25:
+               host->ssc_depth = RTSX_SSC_DEPTH_1M;
+               break;
+       default:
+               host->ssc_depth = RTSX_SSC_DEPTH_500K;
+               break;
+       }
+
+       host->initial_mode = (ios->clock <= 1000000) ? true : false;
+
+       host->clock = ios->clock;
+       rtsx_pci_switch_clock(pcr, ios->clock, host->ssc_depth,
+                       host->initial_mode, host->double_clk, host->vpclk);
+
+       mutex_unlock(&pcr->pcr_mutex);
+}
+
+static int sdmmc_get_ro(struct mmc_host *mmc)
+{
+       struct realtek_pci_sdmmc *host = mmc_priv(mmc);
+       struct rtsx_pcr *pcr = host->pcr;
+       int ro = 0;
+       u32 val;
+
+       if (host->eject)
+               return -ENOMEDIUM;
+
+       mutex_lock(&pcr->pcr_mutex);
+
+       rtsx_pci_start_run(pcr);
+
+       /* Check SD mechanical write-protect switch */
+       val = rtsx_pci_readl(pcr, RTSX_BIPR);
+       dev_dbg(sdmmc_dev(host), "%s: RTSX_BIPR = 0x%08x\n", __func__, val);
+       if (val & SD_WRITE_PROTECT)
+               ro = 1;
+
+       mutex_unlock(&pcr->pcr_mutex);
+
+       return ro;
+}
+
+static int sdmmc_get_cd(struct mmc_host *mmc)
+{
+       struct realtek_pci_sdmmc *host = mmc_priv(mmc);
+       struct rtsx_pcr *pcr = host->pcr;
+       int cd = 0;
+       u32 val;
+
+       if (host->eject)
+               return -ENOMEDIUM;
+
+       mutex_lock(&pcr->pcr_mutex);
+
+       rtsx_pci_start_run(pcr);
+
+       /* Check SD card detect */
+       val = rtsx_pci_readl(pcr, RTSX_BIPR);
+       dev_dbg(sdmmc_dev(host), "%s: RTSX_BIPR = 0x%08x\n", __func__, val);
+       if (val & SD_EXIST)
+               cd = 1;
+
+       mutex_unlock(&pcr->pcr_mutex);
+
+       return cd;
+}
+
+static int sd_wait_voltage_stable_1(struct realtek_pci_sdmmc *host)
+{
+       struct rtsx_pcr *pcr = host->pcr;
+       int err;
+       u8 stat;
+
+       /* Reference to Signal Voltage Switch Sequence in SD spec.
+        * Wait for a period of time so that the card can drive SD_CMD and
+        * SD_DAT[3:0] to low after sending back CMD11 response.
+        */
+       mdelay(1);
+
+       /* SD_CMD, SD_DAT[3:0] should be driven to low by card;
+        * If either one of SD_CMD,SD_DAT[3:0] is not low,
+        * abort the voltage switch sequence;
+        */
+       err = rtsx_pci_read_register(pcr, SD_BUS_STAT, &stat);
+       if (err < 0)
+               return err;
+
+       if (stat & (SD_CMD_STATUS | SD_DAT3_STATUS | SD_DAT2_STATUS |
+                               SD_DAT1_STATUS | SD_DAT0_STATUS))
+               return -EINVAL;
+
+       /* Stop toggle SD clock */
+       err = rtsx_pci_write_register(pcr, SD_BUS_STAT,
+                       0xFF, SD_CLK_FORCE_STOP);
+       if (err < 0)
+               return err;
+
+       return 0;
+}
+
+static int sd_wait_voltage_stable_2(struct realtek_pci_sdmmc *host)
+{
+       struct rtsx_pcr *pcr = host->pcr;
+       int err;
+       u8 stat, mask, val;
+
+       /* Wait 1.8V output of voltage regulator in card stable */
+       msleep(50);
+
+       /* Toggle SD clock again */
+       err = rtsx_pci_write_register(pcr, SD_BUS_STAT, 0xFF, SD_CLK_TOGGLE_EN);
+       if (err < 0)
+               return err;
+
+       /* Wait for a period of time so that the card can drive
+        * SD_DAT[3:0] to high at 1.8V
+        */
+       msleep(20);
+
+       /* SD_CMD, SD_DAT[3:0] should be pulled high by host */
+       err = rtsx_pci_read_register(pcr, SD_BUS_STAT, &stat);
+       if (err < 0)
+               return err;
+
+       mask = SD_CMD_STATUS | SD_DAT3_STATUS | SD_DAT2_STATUS |
+               SD_DAT1_STATUS | SD_DAT0_STATUS;
+       val = SD_CMD_STATUS | SD_DAT3_STATUS | SD_DAT2_STATUS |
+               SD_DAT1_STATUS | SD_DAT0_STATUS;
+       if ((stat & mask) != val) {
+               dev_dbg(sdmmc_dev(host),
+                       "%s: SD_BUS_STAT = 0x%x\n", __func__, stat);
+               rtsx_pci_write_register(pcr, SD_BUS_STAT,
+                               SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, 0);
+               rtsx_pci_write_register(pcr, CARD_CLK_EN, 0xFF, 0);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int sd_change_bank_voltage(struct realtek_pci_sdmmc *host, u8 voltage)
+{
+       struct rtsx_pcr *pcr = host->pcr;
+       int err;
+
+       if (voltage == SD_IO_3V3) {
+               err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4FC0 | 0x24);
+               if (err < 0)
+                       return err;
+       } else if (voltage == SD_IO_1V8) {
+               err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4C40 | 0x24);
+               if (err < 0)
+                       return err;
+       } else {
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int sdmmc_switch_voltage(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+       struct realtek_pci_sdmmc *host = mmc_priv(mmc);
+       struct rtsx_pcr *pcr = host->pcr;
+       int err = 0;
+       u8 voltage;
+
+       dev_dbg(sdmmc_dev(host), "%s: signal_voltage = %d\n",
+                       __func__, ios->signal_voltage);
+
+       if (host->eject)
+               return -ENOMEDIUM;
+
+       mutex_lock(&pcr->pcr_mutex);
+
+       rtsx_pci_start_run(pcr);
+
+       if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330)
+               voltage = SD_IO_3V3;
+       else
+               voltage = SD_IO_1V8;
+
+       if (voltage == SD_IO_1V8) {
+               err = rtsx_pci_write_register(pcr,
+                               SD30_DRIVE_SEL, 0x07, DRIVER_TYPE_B);
+               if (err < 0)
+                       goto out;
+
+               err = sd_wait_voltage_stable_1(host);
+               if (err < 0)
+                       goto out;
+       }
+
+       err = sd_change_bank_voltage(host, voltage);
+       if (err < 0)
+               goto out;
+
+       if (voltage == SD_IO_1V8) {
+               err = sd_wait_voltage_stable_2(host);
+               if (err < 0)
+                       goto out;
+       }
+
+       /* Stop toggle SD clock in idle */
+       err = rtsx_pci_write_register(pcr, SD_BUS_STAT,
+                       SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, 0);
+
+out:
+       mutex_unlock(&pcr->pcr_mutex);
+
+       return err;
+}
+
+static int sdmmc_execute_tuning(struct mmc_host *mmc, u32 opcode)
+{
+       struct realtek_pci_sdmmc *host = mmc_priv(mmc);
+       struct rtsx_pcr *pcr = host->pcr;
+       int err = 0;
+
+       if (host->eject)
+               return -ENOMEDIUM;
+
+       mutex_lock(&pcr->pcr_mutex);
+
+       rtsx_pci_start_run(pcr);
+
+       if (!host->ddr_mode)
+               err = sd_tuning_rx(host, MMC_SEND_TUNING_BLOCK);
+
+       mutex_unlock(&pcr->pcr_mutex);
+
+       return err;
+}
+
+static const struct mmc_host_ops realtek_pci_sdmmc_ops = {
+       .request = sdmmc_request,
+       .set_ios = sdmmc_set_ios,
+       .get_ro = sdmmc_get_ro,
+       .get_cd = sdmmc_get_cd,
+       .start_signal_voltage_switch = sdmmc_switch_voltage,
+       .execute_tuning = sdmmc_execute_tuning,
+};
+
+#ifdef CONFIG_PM
+static int rtsx_pci_sdmmc_suspend(struct platform_device *pdev,
+               pm_message_t state)
+{
+       struct realtek_pci_sdmmc *host = platform_get_drvdata(pdev);
+       struct mmc_host *mmc = host->mmc;
+       int err;
+
+       dev_dbg(sdmmc_dev(host), "--> %s\n", __func__);
+
+       err = mmc_suspend_host(mmc);
+       if (err)
+               return err;
+
+       return 0;
+}
+
+static int rtsx_pci_sdmmc_resume(struct platform_device *pdev)
+{
+       struct realtek_pci_sdmmc *host = platform_get_drvdata(pdev);
+       struct mmc_host *mmc = host->mmc;
+
+       dev_dbg(sdmmc_dev(host), "--> %s\n", __func__);
+
+       return mmc_resume_host(mmc);
+}
+#else /* CONFIG_PM */
+#define rtsx_pci_sdmmc_suspend NULL
+#define rtsx_pci_sdmmc_resume NULL
+#endif /* CONFIG_PM */
+
+static void init_extra_caps(struct realtek_pci_sdmmc *host)
+{
+       struct mmc_host *mmc = host->mmc;
+       struct rtsx_pcr *pcr = host->pcr;
+
+       dev_dbg(sdmmc_dev(host), "pcr->extra_caps = 0x%x\n", pcr->extra_caps);
+
+       if (pcr->extra_caps & EXTRA_CAPS_SD_SDR50)
+               mmc->caps |= MMC_CAP_UHS_SDR50;
+       if (pcr->extra_caps & EXTRA_CAPS_SD_SDR104)
+               mmc->caps |= MMC_CAP_UHS_SDR104;
+       if (pcr->extra_caps & EXTRA_CAPS_SD_DDR50)
+               mmc->caps |= MMC_CAP_UHS_DDR50;
+       if (pcr->extra_caps & EXTRA_CAPS_MMC_HSDDR)
+               mmc->caps |= MMC_CAP_1_8V_DDR;
+       if (pcr->extra_caps & EXTRA_CAPS_MMC_8BIT)
+               mmc->caps |= MMC_CAP_8_BIT_DATA;
+}
+
+static void realtek_init_host(struct realtek_pci_sdmmc *host)
+{
+       struct mmc_host *mmc = host->mmc;
+
+       mmc->f_min = 250000;
+       mmc->f_max = 208000000;
+       mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
+       mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SD_HIGHSPEED |
+               MMC_CAP_MMC_HIGHSPEED | MMC_CAP_BUS_WIDTH_TEST |
+               MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25;
+       mmc->max_current_330 = 400;
+       mmc->max_current_180 = 800;
+       mmc->ops = &realtek_pci_sdmmc_ops;
+
+       init_extra_caps(host);
+
+       mmc->max_segs = 256;
+       mmc->max_seg_size = 65536;
+       mmc->max_blk_size = 512;
+       mmc->max_blk_count = 65535;
+       mmc->max_req_size = 524288;
+}
+
+static int rtsx_pci_sdmmc_drv_probe(struct platform_device *pdev)
+{
+       struct mmc_host *mmc;
+       struct realtek_pci_sdmmc *host;
+       struct rtsx_pcr *pcr = platform_get_drvdata(pdev);
+
+       if (!pcr)
+               return -ENXIO;
+
+       dev_dbg(&(pdev->dev), ": Realtek PCI-E SDMMC controller found\n");
+
+       mmc = mmc_alloc_host(sizeof(*host), &pcr->pci->dev);
+       if (!mmc)
+               return -ENOMEM;
+
+       host = mmc_priv(mmc);
+       host->pcr = pcr;
+       host->mmc = mmc;
+       host->pdev = pdev;
+       platform_set_drvdata(pdev, host);
+
+       mutex_init(&host->host_mutex);
+
+       realtek_init_host(host);
+
+       mmc_add_host(mmc);
+
+       return 0;
+}
+
+static int rtsx_pci_sdmmc_drv_remove(struct platform_device *pdev)
+{
+       struct realtek_pci_sdmmc *host = platform_get_drvdata(pdev);
+       struct rtsx_pcr *pcr;
+       struct mmc_host *mmc;
+
+       if (!host)
+               return 0;
+
+       pcr = host->pcr;
+       mmc = host->mmc;
+       host->eject = true;
+
+       mutex_lock(&host->host_mutex);
+       if (host->mrq) {
+               dev_dbg(&(pdev->dev),
+                       "%s: Controller removed during transfer\n",
+                       mmc_hostname(mmc));
+
+               rtsx_pci_complete_unfinished_transfer(pcr);
+
+               host->mrq->cmd->error = -ENOMEDIUM;
+               if (host->mrq->stop)
+                       host->mrq->stop->error = -ENOMEDIUM;
+               mmc_request_done(mmc, host->mrq);
+       }
+       mutex_unlock(&host->host_mutex);
+
+       mmc_remove_host(mmc);
+       mmc_free_host(mmc);
+
+       platform_set_drvdata(pdev, NULL);
+
+       dev_dbg(&(pdev->dev),
+               ": Realtek PCI-E SDMMC controller has been removed\n");
+
+       return 0;
+}
+
+static struct platform_device_id rtsx_pci_sdmmc_ids[] = {
+       {
+               .name = DRV_NAME_RTSX_PCI_SDMMC,
+       }, {
+               /* sentinel */
+       }
+};
+MODULE_DEVICE_TABLE(platform, rtsx_pci_sdmmc_ids);
+
+static struct platform_driver rtsx_pci_sdmmc_driver = {
+       .probe          = rtsx_pci_sdmmc_drv_probe,
+       .remove         = rtsx_pci_sdmmc_drv_remove,
+       .id_table       = rtsx_pci_sdmmc_ids,
+       .suspend        = rtsx_pci_sdmmc_suspend,
+       .resume         = rtsx_pci_sdmmc_resume,
+       .driver         = {
+               .owner  = THIS_MODULE,
+               .name   = DRV_NAME_RTSX_PCI_SDMMC,
+       },
+};
+module_platform_driver(rtsx_pci_sdmmc_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Wei WANG <wei_wang@realsil.com.cn>");
+MODULE_DESCRIPTION("Realtek PCI-E SD/MMC Card Host Driver");
index 2903949594c6a1d3168d5a021c82ebec795ed138..a093e2ecaf809e764b3715df569d69bcba38abeb 100644 (file)
@@ -211,8 +211,8 @@ static void sdhci_s3c_set_clock(struct sdhci_host *host, unsigned int clock)
        if (ourhost->cur_clk != best_src) {
                struct clk *clk = ourhost->clk_bus[best_src];
 
-               clk_enable(clk);
-               clk_disable(ourhost->clk_bus[ourhost->cur_clk]);
+               clk_prepare_enable(clk);
+               clk_disable_unprepare(ourhost->clk_bus[ourhost->cur_clk]);
 
                /* turn clock off to card before changing clock source */
                writew(0, host->ioaddr + SDHCI_CLOCK_CONTROL);
@@ -607,7 +607,7 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
        }
 
        /* enable the local io clock and keep it running for the moment. */
-       clk_enable(sc->clk_io);
+       clk_prepare_enable(sc->clk_io);
 
        for (clks = 0, ptr = 0; ptr < MAX_BUS_CLK; ptr++) {
                struct clk *clk;
@@ -638,7 +638,7 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
        }
 
 #ifndef CONFIG_PM_RUNTIME
-       clk_enable(sc->clk_bus[sc->cur_clk]);
+       clk_prepare_enable(sc->clk_bus[sc->cur_clk]);
 #endif
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -747,13 +747,13 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
                sdhci_s3c_setup_card_detect_gpio(sc);
 
 #ifdef CONFIG_PM_RUNTIME
-       clk_disable(sc->clk_io);
+       clk_disable_unprepare(sc->clk_io);
 #endif
        return 0;
 
  err_req_regs:
 #ifndef CONFIG_PM_RUNTIME
-       clk_disable(sc->clk_bus[sc->cur_clk]);
+       clk_disable_unprepare(sc->clk_bus[sc->cur_clk]);
 #endif
        for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) {
                if (sc->clk_bus[ptr]) {
@@ -762,7 +762,7 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
        }
 
  err_no_busclks:
-       clk_disable(sc->clk_io);
+       clk_disable_unprepare(sc->clk_io);
        clk_put(sc->clk_io);
 
  err_io_clk:
@@ -794,7 +794,7 @@ static int __devexit sdhci_s3c_remove(struct platform_device *pdev)
                gpio_free(sc->ext_cd_gpio);
 
 #ifdef CONFIG_PM_RUNTIME
-       clk_enable(sc->clk_io);
+       clk_prepare_enable(sc->clk_io);
 #endif
        sdhci_remove_host(host, 1);
 
@@ -802,14 +802,14 @@ static int __devexit sdhci_s3c_remove(struct platform_device *pdev)
        pm_runtime_disable(&pdev->dev);
 
 #ifndef CONFIG_PM_RUNTIME
-       clk_disable(sc->clk_bus[sc->cur_clk]);
+       clk_disable_unprepare(sc->clk_bus[sc->cur_clk]);
 #endif
        for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) {
                if (sc->clk_bus[ptr]) {
                        clk_put(sc->clk_bus[ptr]);
                }
        }
-       clk_disable(sc->clk_io);
+       clk_disable_unprepare(sc->clk_io);
        clk_put(sc->clk_io);
 
        if (pdev->dev.of_node) {
@@ -849,8 +849,8 @@ static int sdhci_s3c_runtime_suspend(struct device *dev)
 
        ret = sdhci_runtime_suspend_host(host);
 
-       clk_disable(ourhost->clk_bus[ourhost->cur_clk]);
-       clk_disable(busclk);
+       clk_disable_unprepare(ourhost->clk_bus[ourhost->cur_clk]);
+       clk_disable_unprepare(busclk);
        return ret;
 }
 
@@ -861,8 +861,8 @@ static int sdhci_s3c_runtime_resume(struct device *dev)
        struct clk *busclk = ourhost->clk_io;
        int ret;
 
-       clk_enable(busclk);
-       clk_enable(ourhost->clk_bus[ourhost->cur_clk]);
+       clk_prepare_enable(busclk);
+       clk_prepare_enable(ourhost->clk_bus[ourhost->cur_clk]);
        ret = sdhci_runtime_resume_host(host);
        return ret;
 }
index aed1b8a63c9feee71caceccc93842b188349f349..4baab3bc61367fb5d3d00855c2e8ac36b065d947 100644 (file)
@@ -308,48 +308,52 @@ static int parse_cmdline_partitions(struct mtd_info *master,
                        return err;
        }
 
+       /*
+        * Search for the partition definition matching master->name.
+        * If master->name is not set, stop at first partition definition.
+        */
        for (part = partitions; part; part = part->next) {
-               if ((!mtd_id) || (!strcmp(part->mtd_id, mtd_id))) {
-                       for (i = 0, offset = 0; i < part->num_parts; i++) {
-                               if (part->parts[i].offset == OFFSET_CONTINUOUS)
-                                       part->parts[i].offset = offset;
-                               else
-                                       offset = part->parts[i].offset;
-
-                               if (part->parts[i].size == SIZE_REMAINING)
-                                       part->parts[i].size = master->size - offset;
-
-                               if (part->parts[i].size == 0) {
-                                       printk(KERN_WARNING ERRP
-                                              "%s: skipping zero sized partition\n",
-                                              part->mtd_id);
-                                       part->num_parts--;
-                                       memmove(&part->parts[i],
-                                               &part->parts[i + 1],
-                                               sizeof(*part->parts) * (part->num_parts - i));
-                                       continue;
-                               }
-
-                               if (offset + part->parts[i].size > master->size) {
-                                       printk(KERN_WARNING ERRP
-                                              "%s: partitioning exceeds flash size, truncating\n",
-                                              part->mtd_id);
-                                       part->parts[i].size = master->size - offset;
-                               }
-                               offset += part->parts[i].size;
-                       }
-
-                       *pparts = kmemdup(part->parts,
-                                       sizeof(*part->parts) * part->num_parts,
-                                       GFP_KERNEL);
-                       if (!*pparts)
-                               return -ENOMEM;
-
-                       return part->num_parts;
+               if ((!mtd_id) || (!strcmp(part->mtd_id, mtd_id)))
+                       break;
+       }
+
+       if (!part)
+               return 0;
+
+       for (i = 0, offset = 0; i < part->num_parts; i++) {
+               if (part->parts[i].offset == OFFSET_CONTINUOUS)
+                       part->parts[i].offset = offset;
+               else
+                       offset = part->parts[i].offset;
+
+               if (part->parts[i].size == SIZE_REMAINING)
+                       part->parts[i].size = master->size - offset;
+
+               if (part->parts[i].size == 0) {
+                       printk(KERN_WARNING ERRP
+                              "%s: skipping zero sized partition\n",
+                              part->mtd_id);
+                       part->num_parts--;
+                       memmove(&part->parts[i], &part->parts[i + 1],
+                               sizeof(*part->parts) * (part->num_parts - i));
+                       continue;
                }
+
+               if (offset + part->parts[i].size > master->size) {
+                       printk(KERN_WARNING ERRP
+                              "%s: partitioning exceeds flash size, truncating\n",
+                              part->mtd_id);
+                       part->parts[i].size = master->size - offset;
+               }
+               offset += part->parts[i].size;
        }
 
-       return 0;
+       *pparts = kmemdup(part->parts, sizeof(*part->parts) * part->num_parts,
+                         GFP_KERNEL);
+       if (!*pparts)
+               return -ENOMEM;
+
+       return part->num_parts;
 }
 
 
index 03838bab1f594e01bce9554d292a2ffdd4ef600c..7e2d8f9525b071a6e3c435d22e718df28f1be1e6 100644 (file)
 #define        MAX_READY_WAIT_JIFFIES  (40 * HZ)       /* M25P16 specs 40s max chip erase */
 #define        MAX_CMD_SIZE            5
 
-#ifdef CONFIG_M25PXX_USE_FAST_READ
-#define OPCODE_READ    OPCODE_FAST_READ
-#define FAST_READ_DUMMY_BYTE 1
-#else
-#define OPCODE_READ    OPCODE_NORM_READ
-#define FAST_READ_DUMMY_BYTE 0
-#endif
-
 #define JEDEC_MFR(_jedec_id)   ((_jedec_id) >> 16)
 
 /****************************************************************************/
@@ -93,6 +85,7 @@ struct m25p {
        u16                     addr_width;
        u8                      erase_opcode;
        u8                      *command;
+       bool                    fast_read;
 };
 
 static inline struct m25p *mtd_to_m25p(struct mtd_info *mtd)
@@ -168,6 +161,7 @@ static inline int set_4byte(struct m25p *flash, u32 jedec_id, int enable)
 {
        switch (JEDEC_MFR(jedec_id)) {
        case CFI_MFR_MACRONIX:
+       case 0xEF /* winbond */:
                flash->command[0] = enable ? OPCODE_EN4B : OPCODE_EX4B;
                return spi_write(flash->spi, flash->command, 1);
        default:
@@ -342,6 +336,7 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
        struct m25p *flash = mtd_to_m25p(mtd);
        struct spi_transfer t[2];
        struct spi_message m;
+       uint8_t opcode;
 
        pr_debug("%s: %s from 0x%08x, len %zd\n", dev_name(&flash->spi->dev),
                        __func__, (u32)from, len);
@@ -354,7 +349,7 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
         * Should add 1 byte DUMMY_BYTE.
         */
        t[0].tx_buf = flash->command;
-       t[0].len = m25p_cmdsz(flash) + FAST_READ_DUMMY_BYTE;
+       t[0].len = m25p_cmdsz(flash) + (flash->fast_read ? 1 : 0);
        spi_message_add_tail(&t[0], &m);
 
        t[1].rx_buf = buf;
@@ -376,12 +371,14 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
         */
 
        /* Set up the write data buffer. */
-       flash->command[0] = OPCODE_READ;
+       opcode = flash->fast_read ? OPCODE_FAST_READ : OPCODE_NORM_READ;
+       flash->command[0] = opcode;
        m25p_addr2cmd(flash, from, flash->command);
 
        spi_sync(flash->spi, &m);
 
-       *retlen = m.actual_length - m25p_cmdsz(flash) - FAST_READ_DUMMY_BYTE;
+       *retlen = m.actual_length - m25p_cmdsz(flash) -
+                       (flash->fast_read ? 1 : 0);
 
        mutex_unlock(&flash->lock);
 
@@ -745,6 +742,7 @@ static const struct spi_device_id m25p_ids[] = {
        { "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) },
        { "w25q64", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) },
        { "w25q80", INFO(0xef5014, 0, 64 * 1024,  16, SECT_4K) },
+       { "w25q256", INFO(0xef4019, 0, 64 * 1024, 512, SECT_4K) },
 
        /* Catalyst / On Semiconductor -- non-JEDEC */
        { "cat25c11", CAT25_INFO(  16, 8, 16, 1) },
@@ -809,9 +807,10 @@ static int __devinit m25p_probe(struct spi_device *spi)
        struct flash_info               *info;
        unsigned                        i;
        struct mtd_part_parser_data     ppdata;
+       struct device_node __maybe_unused *np = spi->dev.of_node;
 
 #ifdef CONFIG_MTD_OF_PARTS
-       if (!of_device_is_available(spi->dev.of_node))
+       if (!of_device_is_available(np))
                return -ENODEV;
 #endif
 
@@ -863,7 +862,8 @@ static int __devinit m25p_probe(struct spi_device *spi)
        flash = kzalloc(sizeof *flash, GFP_KERNEL);
        if (!flash)
                return -ENOMEM;
-       flash->command = kmalloc(MAX_CMD_SIZE + FAST_READ_DUMMY_BYTE, GFP_KERNEL);
+       flash->command = kmalloc(MAX_CMD_SIZE + (flash->fast_read ? 1 : 0),
+                                       GFP_KERNEL);
        if (!flash->command) {
                kfree(flash);
                return -ENOMEM;
@@ -920,6 +920,16 @@ static int __devinit m25p_probe(struct spi_device *spi)
        flash->page_size = info->page_size;
        flash->mtd.writebufsize = flash->page_size;
 
+       flash->fast_read = false;
+#ifdef CONFIG_OF
+       if (np && of_property_read_bool(np, "m25p,fast-read"))
+               flash->fast_read = true;
+#endif
+
+#ifdef CONFIG_M25PXX_USE_FAST_READ
+       flash->fast_read = true;
+#endif
+
        if (info->addr_width)
                flash->addr_width = info->addr_width;
        else {
index 8f52fc858e48bec08f900963996c0d37bd4601cb..5a5cd2ace4a6b05126e642e06d04950f52108ab8 100644 (file)
@@ -240,7 +240,7 @@ static int parse_cmdline(char *devname, char *szstart, char *szlength)
 
        if (*(szlength) != '+') {
                devlength = simple_strtoul(szlength, &buffer, 0);
-               devlength = handle_unit(devlength, buffer) - devstart;
+               devlength = handle_unit(devlength, buffer);
                if (devlength < devstart)
                        goto err_out;
 
index dcc3c9511530c064e93d91f941e90023a81fc3d3..39e95673cdd2a7dc92971d88c287f954d8d66e74 100644 (file)
@@ -1094,18 +1094,7 @@ static struct platform_driver spear_smi_driver = {
        .probe = spear_smi_probe,
        .remove = __devexit_p(spear_smi_remove),
 };
-
-static int spear_smi_init(void)
-{
-       return platform_driver_register(&spear_smi_driver);
-}
-module_init(spear_smi_init);
-
-static void spear_smi_exit(void)
-{
-       platform_driver_unregister(&spear_smi_driver);
-}
-module_exit(spear_smi_exit);
+module_platform_driver(spear_smi_driver);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Ashish Priyadarshi, Shiraz Hashim <shiraz.hashim@st.com>");
index 4883139460be90ba7385b059651f1a52bab608c5..a803d9ba55bdca037dd89d61bbbe9298abc58f9a 100644 (file)
@@ -57,16 +57,30 @@ config MTD_NAND_AUTCPU12
          access the SmartMediaCard.
 
 config MTD_NAND_DENALI
-       depends on PCI
+        tristate "Support Denali NAND controller"
+        help
+         Enable support for the Denali NAND controller.  This should be
+         combined with either the PCI or platform drivers to provide device
+         registration.
+
+config MTD_NAND_DENALI_PCI
         tristate "Support Denali NAND controller on Intel Moorestown"
+       depends on PCI && MTD_NAND_DENALI
         help
           Enable the driver for NAND flash on Intel Moorestown, using the
           Denali NAND controller core.
+
+config MTD_NAND_DENALI_DT
+       tristate "Support Denali NAND controller as a DT device"
+       depends on HAVE_CLK && MTD_NAND_DENALI
+       help
+         Enable the driver for NAND flash on platforms using a Denali NAND
+         controller as a DT device.
+
 config MTD_NAND_DENALI_SCRATCH_REG_ADDR
         hex "Denali NAND size scratch register address"
         default "0xFF108018"
-        depends on MTD_NAND_DENALI
+        depends on MTD_NAND_DENALI_PCI
         help
           Some platforms place the NAND chip size in a scratch register
           because (some versions of) the driver aren't able to automatically
@@ -512,12 +526,6 @@ config MTD_NAND_MXC
          This enables the driver for the NAND flash controller on the
          MXC processors.
 
-config MTD_NAND_NOMADIK
-       tristate "ST Nomadik 8815 NAND support"
-       depends on ARCH_NOMADIK
-       help
-         Driver for the NAND flash controller on the Nomadik, with ECC.
-
 config MTD_NAND_SH_FLCTL
        tristate "Support for NAND on Renesas SuperH FLCTL"
        depends on SUPERH || ARCH_SHMOBILE
index 2cbd0916b733e67f5981541d0c29c6336a6b1678..44fca05533659d1128adee2d71819c7791294ef2 100644 (file)
@@ -13,6 +13,8 @@ obj-$(CONFIG_MTD_NAND_SPIA)           += spia.o
 obj-$(CONFIG_MTD_NAND_AMS_DELTA)       += ams-delta.o
 obj-$(CONFIG_MTD_NAND_AUTCPU12)                += autcpu12.o
 obj-$(CONFIG_MTD_NAND_DENALI)          += denali.o
+obj-$(CONFIG_MTD_NAND_DENALI_PCI)      += denali_pci.o
+obj-$(CONFIG_MTD_NAND_DENALI_DT)       += denali_dt.o
 obj-$(CONFIG_MTD_NAND_AU1550)          += au1550nd.o
 obj-$(CONFIG_MTD_NAND_BF5XX)           += bf5xx_nand.o
 obj-$(CONFIG_MTD_NAND_PPCHAMELEONEVB)  += ppchameleonevb.o
@@ -47,7 +49,6 @@ obj-$(CONFIG_MTD_NAND_MXC)            += mxc_nand.o
 obj-$(CONFIG_MTD_NAND_SOCRATES)                += socrates_nand.o
 obj-$(CONFIG_MTD_NAND_TXX9NDFMC)       += txx9ndfmc.o
 obj-$(CONFIG_MTD_NAND_NUC900)          += nuc900_nand.o
-obj-$(CONFIG_MTD_NAND_NOMADIK)         += nomadik_nand.o
 obj-$(CONFIG_MTD_NAND_MPC5121_NFC)     += mpc5121_nfc.o
 obj-$(CONFIG_MTD_NAND_RICOH)           += r852.o
 obj-$(CONFIG_MTD_NAND_JZ4740)          += jz4740_nand.o
index 9144557833027ad4cf1eeae236239bfc4a0a1c3b..92623ac2015a75fab52a8b6842a5a5b61572d547 100644 (file)
@@ -41,6 +41,7 @@
 #include <linux/gpio.h>
 #include <linux/io.h>
 #include <linux/platform_data/atmel.h>
+#include <linux/pinctrl/consumer.h>
 
 #include <mach/cpu.h>
 
@@ -1370,6 +1371,7 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
        struct resource *mem;
        struct mtd_part_parser_data ppdata = {};
        int res;
+       struct pinctrl *pinctrl;
 
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!mem) {
@@ -1414,6 +1416,13 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
        nand_chip->IO_ADDR_W = host->io_base;
        nand_chip->cmd_ctrl = atmel_nand_cmd_ctrl;
 
+       pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+       if (IS_ERR(pinctrl)) {
+               dev_err(host->dev, "Failed to request pinctrl\n");
+               res = PTR_ERR(pinctrl);
+               goto err_ecc_ioremap;
+       }
+
        if (gpio_is_valid(host->board.rdy_pin)) {
                res = gpio_request(host->board.rdy_pin, "nand_rdy");
                if (res < 0) {
index e706a237170f503142089cb5644fe2957cafae07..0c8bb6bf8424732b068f17f4793c3a957e86031a 100644 (file)
  * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
  *
  */
-
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/dma-mapping.h>
 #include <linux/wait.h>
 #include <linux/mutex.h>
 #include <linux/slab.h>
-#include <linux/pci.h>
 #include <linux/mtd/mtd.h>
 #include <linux/module.h>
 
@@ -89,13 +87,6 @@ MODULE_PARM_DESC(onfi_timing_mode, "Overrides default ONFI setting."
  * format the bank into the proper bits for the controller */
 #define BANK(x) ((x) << 24)
 
-/* List of platforms this NAND controller has be integrated into */
-static const struct pci_device_id denali_pci_ids[] = {
-       { PCI_VDEVICE(INTEL, 0x0701), INTEL_CE4100 },
-       { PCI_VDEVICE(INTEL, 0x0809), INTEL_MRST },
-       { /* end: all zeroes */ }
-};
-
 /* forward declarations */
 static void clear_interrupts(struct denali_nand_info *denali);
 static uint32_t wait_for_irq(struct denali_nand_info *denali,
@@ -699,7 +690,7 @@ static uint32_t wait_for_irq(struct denali_nand_info *denali, uint32_t irq_mask)
 
        if (comp_res == 0) {
                /* timeout */
-               printk(KERN_ERR "timeout occurred, status = 0x%x, mask = 0x%x\n",
+               pr_err("timeout occurred, status = 0x%x, mask = 0x%x\n",
                                intr_status, irq_mask);
 
                intr_status = 0;
@@ -1305,8 +1296,7 @@ static void denali_cmdfunc(struct mtd_info *mtd, unsigned int cmd, int col,
                /* TODO: Read OOB data */
                break;
        default:
-               printk(KERN_ERR ": unsupported command"
-                               " received 0x%x\n", cmd);
+               pr_err(": unsupported command received 0x%x\n", cmd);
                break;
        }
 }
@@ -1425,107 +1415,48 @@ void denali_drv_init(struct denali_nand_info *denali)
        denali->irq_status = 0;
 }
 
-/* driver entry point */
-static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+int denali_init(struct denali_nand_info *denali)
 {
-       int ret = -ENODEV;
-       resource_size_t csr_base, mem_base;
-       unsigned long csr_len, mem_len;
-       struct denali_nand_info *denali;
-
-       denali = kzalloc(sizeof(*denali), GFP_KERNEL);
-       if (!denali)
-               return -ENOMEM;
+       int ret;
 
-       ret = pci_enable_device(dev);
-       if (ret) {
-               printk(KERN_ERR "Spectra: pci_enable_device failed.\n");
-               goto failed_alloc_memery;
-       }
-
-       if (id->driver_data == INTEL_CE4100) {
+       if (denali->platform == INTEL_CE4100) {
                /* Due to a silicon limitation, we can only support
                 * ONFI timing mode 1 and below.
                 */
                if (onfi_timing_mode < -1 || onfi_timing_mode > 1) {
-                       printk(KERN_ERR "Intel CE4100 only supports"
-                                       " ONFI timing mode 1 or below\n");
-                       ret = -EINVAL;
-                       goto failed_enable_dev;
-               }
-               denali->platform = INTEL_CE4100;
-               mem_base = pci_resource_start(dev, 0);
-               mem_len = pci_resource_len(dev, 1);
-               csr_base = pci_resource_start(dev, 1);
-               csr_len = pci_resource_len(dev, 1);
-       } else {
-               denali->platform = INTEL_MRST;
-               csr_base = pci_resource_start(dev, 0);
-               csr_len = pci_resource_len(dev, 0);
-               mem_base = pci_resource_start(dev, 1);
-               mem_len = pci_resource_len(dev, 1);
-               if (!mem_len) {
-                       mem_base = csr_base + csr_len;
-                       mem_len = csr_len;
+                       pr_err("Intel CE4100 only supports ONFI timing mode 1 or below\n");
+                       return -EINVAL;
                }
        }
 
        /* Is 32-bit DMA supported? */
-       ret = dma_set_mask(&dev->dev, DMA_BIT_MASK(32));
+       ret = dma_set_mask(denali->dev, DMA_BIT_MASK(32));
        if (ret) {
-               printk(KERN_ERR "Spectra: no usable DMA configuration\n");
-               goto failed_enable_dev;
+               pr_err("Spectra: no usable DMA configuration\n");
+               return ret;
        }
-       denali->buf.dma_buf = dma_map_single(&dev->dev, denali->buf.buf,
+       denali->buf.dma_buf = dma_map_single(denali->dev, denali->buf.buf,
                                             DENALI_BUF_SIZE,
                                             DMA_BIDIRECTIONAL);
 
-       if (dma_mapping_error(&dev->dev, denali->buf.dma_buf)) {
-               dev_err(&dev->dev, "Spectra: failed to map DMA buffer\n");
-               goto failed_enable_dev;
-       }
-
-       pci_set_master(dev);
-       denali->dev = &dev->dev;
-       denali->mtd.dev.parent = &dev->dev;
-
-       ret = pci_request_regions(dev, DENALI_NAND_NAME);
-       if (ret) {
-               printk(KERN_ERR "Spectra: Unable to request memory regions\n");
-               goto failed_dma_map;
-       }
-
-       denali->flash_reg = ioremap_nocache(csr_base, csr_len);
-       if (!denali->flash_reg) {
-               printk(KERN_ERR "Spectra: Unable to remap memory region\n");
-               ret = -ENOMEM;
-               goto failed_req_regions;
-       }
-
-       denali->flash_mem = ioremap_nocache(mem_base, mem_len);
-       if (!denali->flash_mem) {
-               printk(KERN_ERR "Spectra: ioremap_nocache failed!");
-               ret = -ENOMEM;
-               goto failed_remap_reg;
+       if (dma_mapping_error(denali->dev, denali->buf.dma_buf)) {
+               dev_err(denali->dev, "Spectra: failed to map DMA buffer\n");
+               return -EIO;
        }
-
+       denali->mtd.dev.parent = denali->dev;
        denali_hw_init(denali);
        denali_drv_init(denali);
 
        /* denali_isr register is done after all the hardware
         * initilization is finished*/
-       if (request_irq(dev->irq, denali_isr, IRQF_SHARED,
+       if (request_irq(denali->irq, denali_isr, IRQF_SHARED,
                        DENALI_NAND_NAME, denali)) {
-               printk(KERN_ERR "Spectra: Unable to allocate IRQ\n");
-               ret = -ENODEV;
-               goto failed_remap_mem;
+               pr_err("Spectra: Unable to allocate IRQ\n");
+               return -ENODEV;
        }
 
        /* now that our ISR is registered, we can enable interrupts */
        denali_set_intr_modes(denali, true);
-
-       pci_set_drvdata(dev, denali);
-
        denali->mtd.name = "denali-nand";
        denali->mtd.owner = THIS_MODULE;
        denali->mtd.priv = &denali->nand;
@@ -1549,8 +1480,7 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
         */
        if (denali->mtd.writesize > NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE) {
                ret = -ENODEV;
-               printk(KERN_ERR "Spectra: device size not supported by this "
-                       "version of MTD.");
+               pr_err("Spectra: device size not supported by this version of MTD.");
                goto failed_req_irq;
        }
 
@@ -1602,8 +1532,8 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
        } else if (denali->mtd.oobsize < (denali->bbtskipbytes +
                        ECC_8BITS * (denali->mtd.writesize /
                        ECC_SECTOR_SIZE))) {
-               printk(KERN_ERR "Your NAND chip OOB is not large enough to"
-                               contain 8bit ECC correction codes");
+               pr_err("Your NAND chip OOB is not large enough to \
+                               contain 8bit ECC correction codes");
                goto failed_req_irq;
        } else {
                denali->nand.ecc.strength = 8;
@@ -1655,56 +1585,24 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 
        ret = mtd_device_register(&denali->mtd, NULL, 0);
        if (ret) {
-               dev_err(&dev->dev, "Spectra: Failed to register MTD: %d\n",
+               dev_err(denali->dev, "Spectra: Failed to register MTD: %d\n",
                                ret);
                goto failed_req_irq;
        }
        return 0;
 
 failed_req_irq:
-       denali_irq_cleanup(dev->irq, denali);
-failed_remap_mem:
-       iounmap(denali->flash_mem);
-failed_remap_reg:
-       iounmap(denali->flash_reg);
-failed_req_regions:
-       pci_release_regions(dev);
-failed_dma_map:
-       dma_unmap_single(&dev->dev, denali->buf.dma_buf, DENALI_BUF_SIZE,
-                        DMA_BIDIRECTIONAL);
-failed_enable_dev:
-       pci_disable_device(dev);
-failed_alloc_memery:
-       kfree(denali);
+       denali_irq_cleanup(denali->irq, denali);
+
        return ret;
 }
+EXPORT_SYMBOL(denali_init);
 
 /* driver exit point */
-static void denali_pci_remove(struct pci_dev *dev)
+void denali_remove(struct denali_nand_info *denali)
 {
-       struct denali_nand_info *denali = pci_get_drvdata(dev);
-
-       nand_release(&denali->mtd);
-
-       denali_irq_cleanup(dev->irq, denali);
-
-       iounmap(denali->flash_reg);
-       iounmap(denali->flash_mem);
-       pci_release_regions(dev);
-       pci_disable_device(dev);
-       dma_unmap_single(&dev->dev, denali->buf.dma_buf, DENALI_BUF_SIZE,
-                        DMA_BIDIRECTIONAL);
-       pci_set_drvdata(dev, NULL);
-       kfree(denali);
+       denali_irq_cleanup(denali->irq, denali);
+       dma_unmap_single(denali->dev, denali->buf.dma_buf, DENALI_BUF_SIZE,
+                       DMA_BIDIRECTIONAL);
 }
-
-MODULE_DEVICE_TABLE(pci, denali_pci_ids);
-
-static struct pci_driver denali_pci_driver = {
-       .name = DENALI_NAND_NAME,
-       .id_table = denali_pci_ids,
-       .probe = denali_pci_probe,
-       .remove = denali_pci_remove,
-};
-
-module_pci_driver(denali_pci_driver);
+EXPORT_SYMBOL(denali_remove);
index fabb9d56b39e0d7adf14337abcd5c448320610dd..cec5712862c9d01c50c417cad96f0bf3aa9a60ec 100644 (file)
@@ -466,6 +466,7 @@ struct nand_buf {
 
 #define INTEL_CE4100   1
 #define INTEL_MRST     2
+#define DT             3
 
 struct denali_nand_info {
        struct mtd_info mtd;
@@ -487,6 +488,7 @@ struct denali_nand_info {
        uint32_t irq_status;
        int irq_debug_array[32];
        int idx;
+       int irq;
 
        uint32_t devnum;        /* represent how many nands connected */
        uint32_t fwblks; /* represent how many blocks FW used */
@@ -496,4 +498,7 @@ struct denali_nand_info {
        uint32_t max_banks;
 };
 
+extern int denali_init(struct denali_nand_info *denali);
+extern void denali_remove(struct denali_nand_info *denali);
+
 #endif /*_LLD_NAND_*/
diff --git a/drivers/mtd/nand/denali_dt.c b/drivers/mtd/nand/denali_dt.c
new file mode 100644 (file)
index 0000000..fbabbaa
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ * NAND Flash Controller Device Driver for DT
+ *
+ * Copyright © 2011, Picochip.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ */
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/slab.h>
+
+#include "denali.h"
+
+struct denali_dt {
+       struct denali_nand_info denali;
+       struct clk              *clk;
+};
+
+static void __iomem *request_and_map(struct device *dev,
+                                    const struct resource *res)
+{
+       void __iomem *ptr;
+
+       if (!devm_request_mem_region(dev, res->start, resource_size(res),
+                                    "denali-dt")) {
+               dev_err(dev, "unable to request %s\n", res->name);
+               return NULL;
+       }
+
+       ptr = devm_ioremap_nocache(dev, res->start, resource_size(res));
+       if (!res)
+               dev_err(dev, "ioremap_nocache of %s failed!", res->name);
+
+       return ptr;
+}
+
+static const struct of_device_id denali_nand_dt_ids[] = {
+               { .compatible = "denali,denali-nand-dt" },
+               { /* sentinel */ }
+       };
+
+MODULE_DEVICE_TABLE(of, denali_nand_dt_ids);
+
+static u64 denali_dma_mask;
+
+static int __devinit denali_dt_probe(struct platform_device *ofdev)
+{
+       struct resource *denali_reg, *nand_data;
+       struct denali_dt *dt;
+       struct denali_nand_info *denali;
+       int ret;
+       const struct of_device_id *of_id;
+
+       of_id = of_match_device(denali_nand_dt_ids, &ofdev->dev);
+       if (of_id) {
+               ofdev->id_entry = of_id->data;
+       } else {
+               pr_err("Failed to find the right device id.\n");
+               return -ENOMEM;
+       }
+
+       dt = devm_kzalloc(&ofdev->dev, sizeof(*dt), GFP_KERNEL);
+       if (!dt)
+               return -ENOMEM;
+       denali = &dt->denali;
+
+       denali_reg = platform_get_resource_byname(ofdev, IORESOURCE_MEM, "denali_reg");
+       nand_data = platform_get_resource_byname(ofdev, IORESOURCE_MEM, "nand_data");
+       if (!denali_reg || !nand_data) {
+               dev_err(&ofdev->dev, "resources not completely defined\n");
+               return -EINVAL;
+       }
+
+       denali->platform = DT;
+       denali->dev = &ofdev->dev;
+       denali->irq = platform_get_irq(ofdev, 0);
+       if (denali->irq < 0) {
+               dev_err(&ofdev->dev, "no irq defined\n");
+               return -ENXIO;
+       }
+
+       denali->flash_reg = request_and_map(&ofdev->dev, denali_reg);
+       if (!denali->flash_reg)
+               return -ENOMEM;
+
+       denali->flash_mem = request_and_map(&ofdev->dev, nand_data);
+       if (!denali->flash_mem)
+               return -ENOMEM;
+
+       if (!of_property_read_u32(ofdev->dev.of_node,
+               "dma-mask", (u32 *)&denali_dma_mask)) {
+               denali->dev->dma_mask = &denali_dma_mask;
+       } else {
+               denali->dev->dma_mask = NULL;
+       }
+
+       dt->clk = clk_get(&ofdev->dev, NULL);
+       if (IS_ERR(dt->clk)) {
+               dev_err(&ofdev->dev, "no clk available\n");
+               return PTR_ERR(dt->clk);
+       }
+       clk_prepare_enable(dt->clk);
+
+       ret = denali_init(denali);
+       if (ret)
+               goto out_disable_clk;
+
+       platform_set_drvdata(ofdev, dt);
+       return 0;
+
+out_disable_clk:
+       clk_disable_unprepare(dt->clk);
+       clk_put(dt->clk);
+
+       return ret;
+}
+
+static int __devexit denali_dt_remove(struct platform_device *ofdev)
+{
+       struct denali_dt *dt = platform_get_drvdata(ofdev);
+
+       denali_remove(&dt->denali);
+       clk_disable(dt->clk);
+       clk_put(dt->clk);
+
+       return 0;
+}
+
+static struct platform_driver denali_dt_driver = {
+       .probe          = denali_dt_probe,
+       .remove         = __devexit_p(denali_dt_remove),
+       .driver         = {
+               .name   = "denali-nand-dt",
+               .owner  = THIS_MODULE,
+               .of_match_table = of_match_ptr(denali_nand_dt_ids),
+       },
+};
+
+static int __init denali_init_dt(void)
+{
+       return platform_driver_register(&denali_dt_driver);
+}
+module_init(denali_init_dt);
+
+static void __exit denali_exit_dt(void)
+{
+       platform_driver_unregister(&denali_dt_driver);
+}
+module_exit(denali_exit_dt);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jamie Iles");
+MODULE_DESCRIPTION("DT driver for Denali NAND controller");
diff --git a/drivers/mtd/nand/denali_pci.c b/drivers/mtd/nand/denali_pci.c
new file mode 100644 (file)
index 0000000..ea074e6
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * NAND Flash Controller Device Driver
+ * Copyright © 2009-2010, Intel Corporation and its suppliers.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+
+#include "denali.h"
+
+#define DENALI_NAND_NAME    "denali-nand-pci"
+
+/* List of platforms this NAND controller has be integrated into */
+static DEFINE_PCI_DEVICE_TABLE(denali_pci_ids) = {
+       { PCI_VDEVICE(INTEL, 0x0701), INTEL_CE4100 },
+       { PCI_VDEVICE(INTEL, 0x0809), INTEL_MRST },
+       { /* end: all zeroes */ }
+};
+MODULE_DEVICE_TABLE(pci, denali_pci_ids);
+
+static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+       int ret = -ENODEV;
+       resource_size_t csr_base, mem_base;
+       unsigned long csr_len, mem_len;
+       struct denali_nand_info *denali;
+
+       denali = kzalloc(sizeof(*denali), GFP_KERNEL);
+       if (!denali)
+               return -ENOMEM;
+
+       ret = pci_enable_device(dev);
+       if (ret) {
+               pr_err("Spectra: pci_enable_device failed.\n");
+               goto failed_alloc_memery;
+       }
+
+       if (id->driver_data == INTEL_CE4100) {
+               denali->platform = INTEL_CE4100;
+               mem_base = pci_resource_start(dev, 0);
+               mem_len = pci_resource_len(dev, 1);
+               csr_base = pci_resource_start(dev, 1);
+               csr_len = pci_resource_len(dev, 1);
+       } else {
+               denali->platform = INTEL_MRST;
+               csr_base = pci_resource_start(dev, 0);
+               csr_len = pci_resource_len(dev, 0);
+               mem_base = pci_resource_start(dev, 1);
+               mem_len = pci_resource_len(dev, 1);
+               if (!mem_len) {
+                       mem_base = csr_base + csr_len;
+                       mem_len = csr_len;
+               }
+       }
+
+       pci_set_master(dev);
+       denali->dev = &dev->dev;
+       denali->irq = dev->irq;
+
+       ret = pci_request_regions(dev, DENALI_NAND_NAME);
+       if (ret) {
+               pr_err("Spectra: Unable to request memory regions\n");
+               goto failed_enable_dev;
+       }
+
+       denali->flash_reg = ioremap_nocache(csr_base, csr_len);
+       if (!denali->flash_reg) {
+               pr_err("Spectra: Unable to remap memory region\n");
+               ret = -ENOMEM;
+               goto failed_req_regions;
+       }
+
+       denali->flash_mem = ioremap_nocache(mem_base, mem_len);
+       if (!denali->flash_mem) {
+               pr_err("Spectra: ioremap_nocache failed!");
+               ret = -ENOMEM;
+               goto failed_remap_reg;
+       }
+
+       ret = denali_init(denali);
+       if (ret)
+               goto failed_remap_mem;
+
+       pci_set_drvdata(dev, denali);
+
+       return 0;
+
+failed_remap_mem:
+       iounmap(denali->flash_mem);
+failed_remap_reg:
+       iounmap(denali->flash_reg);
+failed_req_regions:
+       pci_release_regions(dev);
+failed_enable_dev:
+       pci_disable_device(dev);
+failed_alloc_memery:
+       kfree(denali);
+
+       return ret;
+}
+
+/* driver exit point */
+static void denali_pci_remove(struct pci_dev *dev)
+{
+       struct denali_nand_info *denali = pci_get_drvdata(dev);
+
+       denali_remove(denali);
+       iounmap(denali->flash_reg);
+       iounmap(denali->flash_mem);
+       pci_release_regions(dev);
+       pci_disable_device(dev);
+       pci_set_drvdata(dev, NULL);
+       kfree(denali);
+}
+
+static struct pci_driver denali_pci_driver = {
+       .name = DENALI_NAND_NAME,
+       .id_table = denali_pci_ids,
+       .probe = denali_pci_probe,
+       .remove = denali_pci_remove,
+};
+
+static int __devinit denali_init_pci(void)
+{
+       pr_info("Spectra MTD driver built on %s @ %s\n", __DATE__, __TIME__);
+       return pci_register_driver(&denali_pci_driver);
+}
+module_init(denali_init_pci);
+
+static void __devexit denali_exit_pci(void)
+{
+       pci_unregister_driver(&denali_pci_driver);
+}
+module_exit(denali_exit_pci);
index cc1480a5e4c1e0a23f262a4c880890217fa4ca6c..4c4d3e5bca189a374e4611eb2fa3162ffee40d4a 100644 (file)
@@ -108,20 +108,6 @@ static struct nand_ecclayout fsl_elbc_oob_lp_eccm1 = {
        .oobfree = { {1, 7}, {11, 13}, {27, 13}, {43, 13}, {59, 5} },
 };
 
-/*
- * fsl_elbc_oob_lp_eccm* specify that LP NAND's OOB free area starts at offset
- * 1, so we have to adjust bad block pattern. This pattern should be used for
- * x8 chips only. So far hardware does not support x16 chips anyway.
- */
-static u8 scan_ff_pattern[] = { 0xff, };
-
-static struct nand_bbt_descr largepage_memorybased = {
-       .options = 0,
-       .offs = 0,
-       .len = 1,
-       .pattern = scan_ff_pattern,
-};
-
 /*
  * ELBC may use HW ECC, so that OOB offsets, that NAND core uses for bbt,
  * interfere with ECC positions, that's why we implement our own descriptors.
@@ -699,7 +685,6 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
                        chip->ecc.layout = (priv->fmr & FMR_ECCM) ?
                                           &fsl_elbc_oob_lp_eccm1 :
                                           &fsl_elbc_oob_lp_eccm0;
-                       chip->badblock_pattern = &largepage_memorybased;
                }
        } else {
                dev_err(priv->dev,
index 38d26240d8b152b06462794ed688905951bf7f4b..6b592235f84749fd7b8446f1c3e6ebe96836c31d 100644 (file)
@@ -361,7 +361,7 @@ static void fsmc_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
        struct nand_chip *this = mtd->priv;
        struct fsmc_nand_data *host = container_of(mtd,
                                        struct fsmc_nand_data, mtd);
-       void *__iomem *regs = host->regs_va;
+       void __iomem *regs = host->regs_va;
        unsigned int bank = host->bank;
 
        if (ctrl & NAND_CTRL_CHANGE) {
@@ -383,13 +383,13 @@ static void fsmc_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
                        pc |= FSMC_ENABLE;
                else
                        pc &= ~FSMC_ENABLE;
-               writel(pc, FSMC_NAND_REG(regs, bank, PC));
+               writel_relaxed(pc, FSMC_NAND_REG(regs, bank, PC));
        }
 
        mb();
 
        if (cmd != NAND_CMD_NONE)
-               writeb(cmd, this->IO_ADDR_W);
+               writeb_relaxed(cmd, this->IO_ADDR_W);
 }
 
 /*
@@ -426,14 +426,18 @@ static void fsmc_nand_setup(void __iomem *regs, uint32_t bank,
        tset = (tims->tset & FSMC_TSET_MASK) << FSMC_TSET_SHIFT;
 
        if (busw)
-               writel(value | FSMC_DEVWID_16, FSMC_NAND_REG(regs, bank, PC));
+               writel_relaxed(value | FSMC_DEVWID_16,
+                               FSMC_NAND_REG(regs, bank, PC));
        else
-               writel(value | FSMC_DEVWID_8, FSMC_NAND_REG(regs, bank, PC));
+               writel_relaxed(value | FSMC_DEVWID_8,
+                               FSMC_NAND_REG(regs, bank, PC));
 
-       writel(readl(FSMC_NAND_REG(regs, bank, PC)) | tclr | tar,
+       writel_relaxed(readl(FSMC_NAND_REG(regs, bank, PC)) | tclr | tar,
                        FSMC_NAND_REG(regs, bank, PC));
-       writel(thiz | thold | twait | tset, FSMC_NAND_REG(regs, bank, COMM));
-       writel(thiz | thold | twait | tset, FSMC_NAND_REG(regs, bank, ATTRIB));
+       writel_relaxed(thiz | thold | twait | tset,
+                       FSMC_NAND_REG(regs, bank, COMM));
+       writel_relaxed(thiz | thold | twait | tset,
+                       FSMC_NAND_REG(regs, bank, ATTRIB));
 }
 
 /*
@@ -446,11 +450,11 @@ static void fsmc_enable_hwecc(struct mtd_info *mtd, int mode)
        void __iomem *regs = host->regs_va;
        uint32_t bank = host->bank;
 
-       writel(readl(FSMC_NAND_REG(regs, bank, PC)) & ~FSMC_ECCPLEN_256,
+       writel_relaxed(readl(FSMC_NAND_REG(regs, bank, PC)) & ~FSMC_ECCPLEN_256,
                        FSMC_NAND_REG(regs, bank, PC));
-       writel(readl(FSMC_NAND_REG(regs, bank, PC)) & ~FSMC_ECCEN,
+       writel_relaxed(readl(FSMC_NAND_REG(regs, bank, PC)) & ~FSMC_ECCEN,
                        FSMC_NAND_REG(regs, bank, PC));
-       writel(readl(FSMC_NAND_REG(regs, bank, PC)) | FSMC_ECCEN,
+       writel_relaxed(readl(FSMC_NAND_REG(regs, bank, PC)) | FSMC_ECCEN,
                        FSMC_NAND_REG(regs, bank, PC));
 }
 
@@ -470,7 +474,7 @@ static int fsmc_read_hwecc_ecc4(struct mtd_info *mtd, const uint8_t *data,
        unsigned long deadline = jiffies + FSMC_BUSY_WAIT_TIMEOUT;
 
        do {
-               if (readl(FSMC_NAND_REG(regs, bank, STS)) & FSMC_CODE_RDY)
+               if (readl_relaxed(FSMC_NAND_REG(regs, bank, STS)) & FSMC_CODE_RDY)
                        break;
                else
                        cond_resched();
@@ -481,25 +485,25 @@ static int fsmc_read_hwecc_ecc4(struct mtd_info *mtd, const uint8_t *data,
                return -ETIMEDOUT;
        }
 
-       ecc_tmp = readl(FSMC_NAND_REG(regs, bank, ECC1));
+       ecc_tmp = readl_relaxed(FSMC_NAND_REG(regs, bank, ECC1));
        ecc[0] = (uint8_t) (ecc_tmp >> 0);
        ecc[1] = (uint8_t) (ecc_tmp >> 8);
        ecc[2] = (uint8_t) (ecc_tmp >> 16);
        ecc[3] = (uint8_t) (ecc_tmp >> 24);
 
-       ecc_tmp = readl(FSMC_NAND_REG(regs, bank, ECC2));
+       ecc_tmp = readl_relaxed(FSMC_NAND_REG(regs, bank, ECC2));
        ecc[4] = (uint8_t) (ecc_tmp >> 0);
        ecc[5] = (uint8_t) (ecc_tmp >> 8);
        ecc[6] = (uint8_t) (ecc_tmp >> 16);
        ecc[7] = (uint8_t) (ecc_tmp >> 24);
 
-       ecc_tmp = readl(FSMC_NAND_REG(regs, bank, ECC3));
+       ecc_tmp = readl_relaxed(FSMC_NAND_REG(regs, bank, ECC3));
        ecc[8] = (uint8_t) (ecc_tmp >> 0);
        ecc[9] = (uint8_t) (ecc_tmp >> 8);
        ecc[10] = (uint8_t) (ecc_tmp >> 16);
        ecc[11] = (uint8_t) (ecc_tmp >> 24);
 
-       ecc_tmp = readl(FSMC_NAND_REG(regs, bank, STS));
+       ecc_tmp = readl_relaxed(FSMC_NAND_REG(regs, bank, STS));
        ecc[12] = (uint8_t) (ecc_tmp >> 16);
 
        return 0;
@@ -519,7 +523,7 @@ static int fsmc_read_hwecc_ecc1(struct mtd_info *mtd, const uint8_t *data,
        uint32_t bank = host->bank;
        uint32_t ecc_tmp;
 
-       ecc_tmp = readl(FSMC_NAND_REG(regs, bank, ECC1));
+       ecc_tmp = readl_relaxed(FSMC_NAND_REG(regs, bank, ECC1));
        ecc[0] = (uint8_t) (ecc_tmp >> 0);
        ecc[1] = (uint8_t) (ecc_tmp >> 8);
        ecc[2] = (uint8_t) (ecc_tmp >> 16);
@@ -601,7 +605,7 @@ static int dma_xfer(struct fsmc_nand_data *host, void *buffer, int len,
        dma_async_issue_pending(chan);
 
        ret =
-       wait_for_completion_interruptible_timeout(&host->dma_access_complete,
+       wait_for_completion_timeout(&host->dma_access_complete,
                                msecs_to_jiffies(3000));
        if (ret <= 0) {
                chan->device->device_control(chan, DMA_TERMINATE_ALL, 0);
@@ -628,10 +632,10 @@ static void fsmc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
                uint32_t *p = (uint32_t *)buf;
                len = len >> 2;
                for (i = 0; i < len; i++)
-                       writel(p[i], chip->IO_ADDR_W);
+                       writel_relaxed(p[i], chip->IO_ADDR_W);
        } else {
                for (i = 0; i < len; i++)
-                       writeb(buf[i], chip->IO_ADDR_W);
+                       writeb_relaxed(buf[i], chip->IO_ADDR_W);
        }
 }
 
@@ -651,10 +655,10 @@ static void fsmc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
                uint32_t *p = (uint32_t *)buf;
                len = len >> 2;
                for (i = 0; i < len; i++)
-                       p[i] = readl(chip->IO_ADDR_R);
+                       p[i] = readl_relaxed(chip->IO_ADDR_R);
        } else {
                for (i = 0; i < len; i++)
-                       buf[i] = readb(chip->IO_ADDR_R);
+                       buf[i] = readb_relaxed(chip->IO_ADDR_R);
        }
 }
 
@@ -783,7 +787,7 @@ static int fsmc_bch8_correct_data(struct mtd_info *mtd, uint8_t *dat,
        uint32_t num_err, i;
        uint32_t ecc1, ecc2, ecc3, ecc4;
 
-       num_err = (readl(FSMC_NAND_REG(regs, bank, STS)) >> 10) & 0xF;
+       num_err = (readl_relaxed(FSMC_NAND_REG(regs, bank, STS)) >> 10) & 0xF;
 
        /* no bit flipping */
        if (likely(num_err == 0))
@@ -826,10 +830,10 @@ static int fsmc_bch8_correct_data(struct mtd_info *mtd, uint8_t *dat,
         * uint64_t array and error offset indexes are populated in err_idx
         * array
         */
-       ecc1 = readl(FSMC_NAND_REG(regs, bank, ECC1));
-       ecc2 = readl(FSMC_NAND_REG(regs, bank, ECC2));
-       ecc3 = readl(FSMC_NAND_REG(regs, bank, ECC3));
-       ecc4 = readl(FSMC_NAND_REG(regs, bank, STS));
+       ecc1 = readl_relaxed(FSMC_NAND_REG(regs, bank, ECC1));
+       ecc2 = readl_relaxed(FSMC_NAND_REG(regs, bank, ECC2));
+       ecc3 = readl_relaxed(FSMC_NAND_REG(regs, bank, ECC3));
+       ecc4 = readl_relaxed(FSMC_NAND_REG(regs, bank, STS));
 
        err_idx[0] = (ecc1 >> 0) & 0x1FFF;
        err_idx[1] = (ecc1 >> 13) & 0x1FFF;
@@ -876,8 +880,6 @@ static int __devinit fsmc_nand_probe_config_dt(struct platform_device *pdev,
                        return -EINVAL;
                }
        }
-       of_property_read_u32(np, "st,ale-off", &pdata->ale_off);
-       of_property_read_u32(np, "st,cle-off", &pdata->cle_off);
        if (of_get_property(np, "nand-skip-bbtscan", NULL))
                pdata->options = NAND_SKIP_BBTSCAN;
 
@@ -935,41 +937,28 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
        if (!res)
                return -EINVAL;
 
-       if (!devm_request_mem_region(&pdev->dev, res->start, resource_size(res),
-                               pdev->name)) {
-               dev_err(&pdev->dev, "Failed to get memory data resourse\n");
-               return -ENOENT;
-       }
-
-       host->data_pa = (dma_addr_t)res->start;
-       host->data_va = devm_ioremap(&pdev->dev, res->start,
-                       resource_size(res));
+       host->data_va = devm_request_and_ioremap(&pdev->dev, res);
        if (!host->data_va) {
                dev_err(&pdev->dev, "data ioremap failed\n");
                return -ENOMEM;
        }
+       host->data_pa = (dma_addr_t)res->start;
 
-       if (!devm_request_mem_region(&pdev->dev, res->start + pdata->ale_off,
-                       resource_size(res), pdev->name)) {
-               dev_err(&pdev->dev, "Failed to get memory ale resourse\n");
-               return -ENOENT;
-       }
+       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nand_addr");
+       if (!res)
+               return -EINVAL;
 
-       host->addr_va = devm_ioremap(&pdev->dev, res->start + pdata->ale_off,
-                       resource_size(res));
+       host->addr_va = devm_request_and_ioremap(&pdev->dev, res);
        if (!host->addr_va) {
                dev_err(&pdev->dev, "ale ioremap failed\n");
                return -ENOMEM;
        }
 
-       if (!devm_request_mem_region(&pdev->dev, res->start + pdata->cle_off,
-                       resource_size(res), pdev->name)) {
-               dev_err(&pdev->dev, "Failed to get memory cle resourse\n");
-               return -ENOENT;
-       }
+       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nand_cmd");
+       if (!res)
+               return -EINVAL;
 
-       host->cmd_va = devm_ioremap(&pdev->dev, res->start + pdata->cle_off,
-                       resource_size(res));
+       host->cmd_va = devm_request_and_ioremap(&pdev->dev, res);
        if (!host->cmd_va) {
                dev_err(&pdev->dev, "ale ioremap failed\n");
                return -ENOMEM;
@@ -979,14 +968,7 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
        if (!res)
                return -EINVAL;
 
-       if (!devm_request_mem_region(&pdev->dev, res->start, resource_size(res),
-                       pdev->name)) {
-               dev_err(&pdev->dev, "Failed to get memory regs resourse\n");
-               return -ENOENT;
-       }
-
-       host->regs_va = devm_ioremap(&pdev->dev, res->start,
-                       resource_size(res));
+       host->regs_va = devm_request_and_ioremap(&pdev->dev, res);
        if (!host->regs_va) {
                dev_err(&pdev->dev, "regs ioremap failed\n");
                return -ENOMEM;
index d79696b2f19b8a50cf2c91f6c88225925a478d43..e2c56fc4574be517b87e437a635da83cc91e5122 100644 (file)
@@ -222,7 +222,7 @@ void prepare_data_dma(struct gpmi_nand_data *this, enum dma_data_direction dr)
 
                ret = dma_map_sg(this->dev, sgl, 1, dr);
                if (ret == 0)
-                       pr_err("map failed.\n");
+                       pr_err("DMA mapping failed.\n");
 
                this->direct_dma_map_ok = false;
        }
@@ -456,7 +456,7 @@ static int __devinit acquire_dma_channels(struct gpmi_nand_data *this)
 
        dma_chan = dma_request_channel(mask, gpmi_dma_filter, this);
        if (!dma_chan) {
-               pr_err("dma_request_channel failed.\n");
+               pr_err("Failed to request DMA channel.\n");
                goto acquire_err;
        }
 
@@ -625,7 +625,8 @@ static int read_page_prepare(struct gpmi_nand_data *this,
                                                length, DMA_FROM_DEVICE);
                if (dma_mapping_error(dev, dest_phys)) {
                        if (alt_size < length) {
-                               pr_err("Alternate buffer is too small\n");
+                               pr_err("%s, Alternate buffer is too small\n",
+                                       __func__);
                                return -ENOMEM;
                        }
                        goto map_failed;
@@ -675,7 +676,8 @@ static int send_page_prepare(struct gpmi_nand_data *this,
                                                DMA_TO_DEVICE);
                if (dma_mapping_error(dev, source_phys)) {
                        if (alt_size < length) {
-                               pr_err("Alternate buffer is too small\n");
+                               pr_err("%s, Alternate buffer is too small\n",
+                                       __func__);
                                return -ENOMEM;
                        }
                        goto map_failed;
@@ -763,7 +765,7 @@ static int gpmi_alloc_dma_buffer(struct gpmi_nand_data *this)
 
 error_alloc:
        gpmi_free_dma_buffer(this);
-       pr_err("allocate DMA buffer ret!!\n");
+       pr_err("Error allocating DMA buffers!\n");
        return -ENOMEM;
 }
 
@@ -1474,7 +1476,7 @@ static int gpmi_set_geometry(struct gpmi_nand_data *this)
        /* Set up the NFC geometry which is used by BCH. */
        ret = bch_set_geometry(this);
        if (ret) {
-               pr_err("set geometry ret : %d\n", ret);
+               pr_err("Error setting BCH geometry : %d\n", ret);
                return ret;
        }
 
index 72e31d86030d9c2e2b7f9cb20302b4b7955877f0..022dcdc256fb68932634242ccff9d86d37dfcb74 100644 (file)
 
 #include <asm/mach/flash.h>
 #include <linux/platform_data/mtd-mxc_nand.h>
-#include <mach/hardware.h>
 
 #define DRIVER_NAME "mxc_nand"
 
-#define nfc_is_v21()           (cpu_is_mx25() || cpu_is_mx35())
-#define nfc_is_v1()            (cpu_is_mx31() || cpu_is_mx27() || cpu_is_mx21())
-#define nfc_is_v3_2a()         cpu_is_mx51()
-#define nfc_is_v3_2b()         cpu_is_mx53()
-
 /* Addresses for NFC registers */
 #define NFC_V1_V2_BUF_SIZE             (host->regs + 0x00)
 #define NFC_V1_V2_BUF_ADDR             (host->regs + 0x04)
@@ -1283,6 +1277,53 @@ static const struct mxc_nand_devtype_data imx53_nand_devtype_data = {
        .ppb_shift = 8,
 };
 
+static inline int is_imx21_nfc(struct mxc_nand_host *host)
+{
+       return host->devtype_data == &imx21_nand_devtype_data;
+}
+
+static inline int is_imx27_nfc(struct mxc_nand_host *host)
+{
+       return host->devtype_data == &imx27_nand_devtype_data;
+}
+
+static inline int is_imx25_nfc(struct mxc_nand_host *host)
+{
+       return host->devtype_data == &imx25_nand_devtype_data;
+}
+
+static inline int is_imx51_nfc(struct mxc_nand_host *host)
+{
+       return host->devtype_data == &imx51_nand_devtype_data;
+}
+
+static inline int is_imx53_nfc(struct mxc_nand_host *host)
+{
+       return host->devtype_data == &imx53_nand_devtype_data;
+}
+
+static struct platform_device_id mxcnd_devtype[] = {
+       {
+               .name = "imx21-nand",
+               .driver_data = (kernel_ulong_t) &imx21_nand_devtype_data,
+       }, {
+               .name = "imx27-nand",
+               .driver_data = (kernel_ulong_t) &imx27_nand_devtype_data,
+       }, {
+               .name = "imx25-nand",
+               .driver_data = (kernel_ulong_t) &imx25_nand_devtype_data,
+       }, {
+               .name = "imx51-nand",
+               .driver_data = (kernel_ulong_t) &imx51_nand_devtype_data,
+       }, {
+               .name = "imx53-nand",
+               .driver_data = (kernel_ulong_t) &imx53_nand_devtype_data,
+       }, {
+               /* sentinel */
+       }
+};
+MODULE_DEVICE_TABLE(platform, mxcnd_devtype);
+
 #ifdef CONFIG_OF_MTD
 static const struct of_device_id mxcnd_dt_ids[] = {
        {
@@ -1337,32 +1378,6 @@ static int __init mxcnd_probe_dt(struct mxc_nand_host *host)
 }
 #endif
 
-static int __init mxcnd_probe_pdata(struct mxc_nand_host *host)
-{
-       struct mxc_nand_platform_data *pdata = host->dev->platform_data;
-
-       if (!pdata)
-               return -ENODEV;
-
-       host->pdata = *pdata;
-
-       if (nfc_is_v1()) {
-               if (cpu_is_mx21())
-                       host->devtype_data = &imx21_nand_devtype_data;
-               else
-                       host->devtype_data = &imx27_nand_devtype_data;
-       } else if (nfc_is_v21()) {
-               host->devtype_data = &imx25_nand_devtype_data;
-       } else if (nfc_is_v3_2a()) {
-               host->devtype_data = &imx51_nand_devtype_data;
-       } else if (nfc_is_v3_2b()) {
-               host->devtype_data = &imx53_nand_devtype_data;
-       } else
-               BUG();
-
-       return 0;
-}
-
 static int __devinit mxcnd_probe(struct platform_device *pdev)
 {
        struct nand_chip *this;
@@ -1404,8 +1419,16 @@ static int __devinit mxcnd_probe(struct platform_device *pdev)
                return PTR_ERR(host->clk);
 
        err = mxcnd_probe_dt(host);
-       if (err > 0)
-               err = mxcnd_probe_pdata(host);
+       if (err > 0) {
+               struct mxc_nand_platform_data *pdata = pdev->dev.platform_data;
+               if (pdata) {
+                       host->pdata = *pdata;
+                       host->devtype_data = (struct mxc_nand_devtype_data *)
+                                               pdev->id_entry->driver_data;
+               } else {
+                       err = -ENODEV;
+               }
+       }
        if (err < 0)
                return err;
 
@@ -1494,7 +1517,7 @@ static int __devinit mxcnd_probe(struct platform_device *pdev)
        }
 
        /* first scan to find the device and get the page size */
-       if (nand_scan_ident(mtd, nfc_is_v21() ? 4 : 1, NULL)) {
+       if (nand_scan_ident(mtd, is_imx25_nfc(host) ? 4 : 1, NULL)) {
                err = -ENXIO;
                goto escan;
        }
@@ -1508,7 +1531,7 @@ static int __devinit mxcnd_probe(struct platform_device *pdev)
                this->ecc.layout = host->devtype_data->ecclayout_4k;
 
        if (this->ecc.mode == NAND_ECC_HW) {
-               if (nfc_is_v1())
+               if (is_imx21_nfc(host) || is_imx27_nfc(host))
                        this->ecc.strength = 1;
                else
                        this->ecc.strength = (host->eccsize == 4) ? 4 : 8;
@@ -1555,6 +1578,7 @@ static struct platform_driver mxcnd_driver = {
                   .owner = THIS_MODULE,
                   .of_match_table = of_match_ptr(mxcnd_dt_ids),
        },
+       .id_table = mxcnd_devtype,
        .probe = mxcnd_probe,
        .remove = __devexit_p(mxcnd_remove),
 };
index ec6841d8e956f74f5224363392632900a39e1f8e..d5ece6ea6f984c428c3905c08d25f19981d446a8 100644 (file)
@@ -2983,13 +2983,14 @@ static void nand_decode_ext_id(struct mtd_info *mtd, struct nand_chip *chip,
        /*
         * Field definitions are in the following datasheets:
         * Old style (4,5 byte ID): Samsung K9GAG08U0M (p.32)
-        * New style   (6 byte ID): Samsung K9GAG08U0F (p.44)
+        * New Samsung (6 byte ID): Samsung K9GAG08U0F (p.44)
         * Hynix MLC   (6 byte ID): Hynix H27UBG8T2B (p.22)
         *
-        * Check for ID length, cell type, and Hynix/Samsung ID to decide what
-        * to do.
+        * Check for ID length, non-zero 6th byte, cell type, and Hynix/Samsung
+        * ID to decide what to do.
         */
-       if (id_len == 6 && id_data[0] == NAND_MFR_SAMSUNG) {
+       if (id_len == 6 && id_data[0] == NAND_MFR_SAMSUNG &&
+                       id_data[5] != 0x00) {
                /* Calc pagesize */
                mtd->writesize = 2048 << (extid & 0x03);
                extid >>= 2;
diff --git a/drivers/mtd/nand/nomadik_nand.c b/drivers/mtd/nand/nomadik_nand.c
deleted file mode 100644 (file)
index 9ee0c4e..0000000
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- *  drivers/mtd/nand/nomadik_nand.c
- *
- *  Overview:
- *     Driver for on-board NAND flash on Nomadik Platforms
- *
- * Copyright © 2007 STMicroelectronics Pvt. Ltd.
- * Author: Sachin Verma <sachin.verma@st.com>
- *
- * Copyright © 2009 Alessandro Rubini
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
-#include <linux/mtd/nand_ecc.h>
-#include <linux/platform_device.h>
-#include <linux/mtd/partitions.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-#include <linux/platform_data/mtd-nomadik-nand.h>
-#include <mach/fsmc.h>
-
-#include <mtd/mtd-abi.h>
-
-struct nomadik_nand_host {
-       struct mtd_info         mtd;
-       struct nand_chip        nand;
-       void __iomem *data_va;
-       void __iomem *cmd_va;
-       void __iomem *addr_va;
-       struct nand_bbt_descr *bbt_desc;
-};
-
-static struct nand_ecclayout nomadik_ecc_layout = {
-       .eccbytes = 3 * 4,
-       .eccpos = { /* each subpage has 16 bytes: pos 2,3,4 hosts ECC */
-               0x02, 0x03, 0x04,
-               0x12, 0x13, 0x14,
-               0x22, 0x23, 0x24,
-               0x32, 0x33, 0x34},
-       /* let's keep bytes 5,6,7 for us, just in case we change ECC algo */
-       .oobfree = { {0x08, 0x08}, {0x18, 0x08}, {0x28, 0x08}, {0x38, 0x08} },
-};
-
-static void nomadik_ecc_control(struct mtd_info *mtd, int mode)
-{
-       /* No need to enable hw ecc, it's on by default */
-}
-
-static void nomadik_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
-{
-       struct nand_chip *nand = mtd->priv;
-       struct nomadik_nand_host *host = nand->priv;
-
-       if (cmd == NAND_CMD_NONE)
-               return;
-
-       if (ctrl & NAND_CLE)
-               writeb(cmd, host->cmd_va);
-       else
-               writeb(cmd, host->addr_va);
-}
-
-static int nomadik_nand_probe(struct platform_device *pdev)
-{
-       struct nomadik_nand_platform_data *pdata = pdev->dev.platform_data;
-       struct nomadik_nand_host *host;
-       struct mtd_info *mtd;
-       struct nand_chip *nand;
-       struct resource *res;
-       int ret = 0;
-
-       /* Allocate memory for the device structure (and zero it) */
-       host = kzalloc(sizeof(struct nomadik_nand_host), GFP_KERNEL);
-       if (!host) {
-               dev_err(&pdev->dev, "Failed to allocate device structure.\n");
-               return -ENOMEM;
-       }
-
-       /* Call the client's init function, if any */
-       if (pdata->init)
-               ret = pdata->init();
-       if (ret < 0) {
-               dev_err(&pdev->dev, "Init function failed\n");
-               goto err;
-       }
-
-       /* ioremap three regions */
-       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nand_addr");
-       if (!res) {
-               ret = -EIO;
-               goto err_unmap;
-       }
-       host->addr_va = ioremap(res->start, resource_size(res));
-
-       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nand_data");
-       if (!res) {
-               ret = -EIO;
-               goto err_unmap;
-       }
-       host->data_va = ioremap(res->start, resource_size(res));
-
-       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nand_cmd");
-       if (!res) {
-               ret = -EIO;
-               goto err_unmap;
-       }
-       host->cmd_va = ioremap(res->start, resource_size(res));
-
-       if (!host->addr_va || !host->data_va || !host->cmd_va) {
-               ret = -ENOMEM;
-               goto err_unmap;
-       }
-
-       /* Link all private pointers */
-       mtd = &host->mtd;
-       nand = &host->nand;
-       mtd->priv = nand;
-       nand->priv = host;
-
-       host->mtd.owner = THIS_MODULE;
-       nand->IO_ADDR_R = host->data_va;
-       nand->IO_ADDR_W = host->data_va;
-       nand->cmd_ctrl = nomadik_cmd_ctrl;
-
-       /*
-        * This stanza declares ECC_HW but uses soft routines. It's because
-        * HW claims to make the calculation but not the correction. However,
-        * I haven't managed to get the desired data out of it until now.
-        */
-       nand->ecc.mode = NAND_ECC_SOFT;
-       nand->ecc.layout = &nomadik_ecc_layout;
-       nand->ecc.hwctl = nomadik_ecc_control;
-       nand->ecc.size = 512;
-       nand->ecc.bytes = 3;
-
-       nand->options = pdata->options;
-
-       /*
-        * Scan to find existence of the device
-        */
-       if (nand_scan(&host->mtd, 1)) {
-               ret = -ENXIO;
-               goto err_unmap;
-       }
-
-       mtd_device_register(&host->mtd, pdata->parts, pdata->nparts);
-
-       platform_set_drvdata(pdev, host);
-       return 0;
-
- err_unmap:
-       if (host->cmd_va)
-               iounmap(host->cmd_va);
-       if (host->data_va)
-               iounmap(host->data_va);
-       if (host->addr_va)
-               iounmap(host->addr_va);
- err:
-       kfree(host);
-       return ret;
-}
-
-/*
- * Clean up routine
- */
-static int nomadik_nand_remove(struct platform_device *pdev)
-{
-       struct nomadik_nand_host *host = platform_get_drvdata(pdev);
-       struct nomadik_nand_platform_data *pdata = pdev->dev.platform_data;
-
-       if (pdata->exit)
-               pdata->exit();
-
-       if (host) {
-               nand_release(&host->mtd);
-               iounmap(host->cmd_va);
-               iounmap(host->data_va);
-               iounmap(host->addr_va);
-               kfree(host);
-       }
-       return 0;
-}
-
-static int nomadik_nand_suspend(struct device *dev)
-{
-       struct nomadik_nand_host *host = dev_get_drvdata(dev);
-       int ret = 0;
-       if (host)
-               ret = mtd_suspend(&host->mtd);
-       return ret;
-}
-
-static int nomadik_nand_resume(struct device *dev)
-{
-       struct nomadik_nand_host *host = dev_get_drvdata(dev);
-       if (host)
-               mtd_resume(&host->mtd);
-       return 0;
-}
-
-static const struct dev_pm_ops nomadik_nand_pm_ops = {
-       .suspend = nomadik_nand_suspend,
-       .resume = nomadik_nand_resume,
-};
-
-static struct platform_driver nomadik_nand_driver = {
-       .probe = nomadik_nand_probe,
-       .remove = nomadik_nand_remove,
-       .driver = {
-               .owner = THIS_MODULE,
-               .name = "nomadik_nand",
-               .pm = &nomadik_nand_pm_ops,
-       },
-};
-
-module_platform_driver(nomadik_nand_driver);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("ST Microelectronics (sachin.verma@st.com)");
-MODULE_DESCRIPTION("NAND driver for Nomadik Platform");
index 4fbfe96e37a1f93dd58dd2b9dae063e8568cb0a9..f48ac5d80bbf84e917c815aef8c54f77567da376 100644 (file)
@@ -727,7 +727,9 @@ static void flctl_select_chip(struct mtd_info *mtd, int chipnr)
 
                if (!flctl->qos_request) {
                        ret = dev_pm_qos_add_request(&flctl->pdev->dev,
-                                                       &flctl->pm_qos, 100);
+                                                       &flctl->pm_qos,
+                                                       DEV_PM_QOS_LATENCY,
+                                                       100);
                        if (ret < 0)
                                dev_err(&flctl->pdev->dev,
                                        "PM QoS request failed: %d\n", ret);
index 64be8f0848b075cdccb647309ff88d12b3fa547d..d9127e2ed808eab6ddfe5835c68cfa88ef490cf0 100644 (file)
@@ -121,7 +121,7 @@ static int parse_ofoldpart_partitions(struct mtd_info *master,
        nr_parts = plen / sizeof(part[0]);
 
        *pparts = kzalloc(nr_parts * sizeof(*(*pparts)), GFP_KERNEL);
-       if (!pparts)
+       if (!*pparts)
                return -ENOMEM;
 
        names = of_get_property(dp, "partition-names", &plen);
index 7153e0d27101e3eed06ac17addcdbd4734c7ccc3..b3f41f200622b39f5ef7d46ab6b772ed2eb9e97e 100644 (file)
@@ -3694,7 +3694,7 @@ static int flexonenand_check_blocks_erased(struct mtd_info *mtd, int start, int
  * flexonenand_set_boundary    - Writes the SLC boundary
  * @param mtd                  - mtd info structure
  */
-int flexonenand_set_boundary(struct mtd_info *mtd, int die,
+static int flexonenand_set_boundary(struct mtd_info *mtd, int die,
                                    int boundary, int lock)
 {
        struct onenand_chip *this = mtd->priv;
index cc8d62cb280ca3c0c9d1059b277912326805cd67..207bf9a9972f3ee400412a1bb40ea4e06cc19745 100644 (file)
@@ -39,6 +39,9 @@
  * this program; see the file COPYING. If not, write to the Free Software
  * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
+
+#define pr_fmt(fmt)    KBUILD_MODNAME ": " fmt
+
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
@@ -47,8 +50,6 @@
 #include <linux/mtd/nand.h>
 #include <linux/slab.h>
 
-#define msg(FMT, VA...) pr_info("mtd_nandbiterrs: "FMT, ##VA)
-
 static int dev;
 module_param(dev, int, S_IRUGO);
 MODULE_PARM_DESC(dev, "MTD device number to use");
@@ -103,7 +104,7 @@ static int erase_block(void)
        struct erase_info ei;
        loff_t addr = eraseblock * mtd->erasesize;
 
-       msg("erase_block\n");
+       pr_info("erase_block\n");
 
        memset(&ei, 0, sizeof(struct erase_info));
        ei.mtd  = mtd;
@@ -112,7 +113,7 @@ static int erase_block(void)
 
        err = mtd_erase(mtd, &ei);
        if (err || ei.state == MTD_ERASE_FAILED) {
-               msg("error %d while erasing\n", err);
+               pr_err("error %d while erasing\n", err);
                if (!err)
                        err = -EIO;
                return err;
@@ -128,11 +129,11 @@ static int write_page(int log)
        size_t written;
 
        if (log)
-               msg("write_page\n");
+               pr_info("write_page\n");
 
        err = mtd_write(mtd, offset, mtd->writesize, &written, wbuffer);
        if (err || written != mtd->writesize) {
-               msg("error: write failed at %#llx\n", (long long)offset);
+               pr_err("error: write failed at %#llx\n", (long long)offset);
                if (!err)
                        err = -EIO;
        }
@@ -147,7 +148,7 @@ static int rewrite_page(int log)
        struct mtd_oob_ops ops;
 
        if (log)
-               msg("rewrite page\n");
+               pr_info("rewrite page\n");
 
        ops.mode      = MTD_OPS_RAW; /* No ECC */
        ops.len       = mtd->writesize;
@@ -160,7 +161,7 @@ static int rewrite_page(int log)
 
        err = mtd_write_oob(mtd, offset, &ops);
        if (err || ops.retlen != mtd->writesize) {
-               msg("error: write_oob failed (%d)\n", err);
+               pr_err("error: write_oob failed (%d)\n", err);
                if (!err)
                        err = -EIO;
        }
@@ -177,7 +178,7 @@ static int read_page(int log)
        struct mtd_ecc_stats oldstats;
 
        if (log)
-               msg("read_page\n");
+               pr_info("read_page\n");
 
        /* Saving last mtd stats */
        memcpy(&oldstats, &mtd->ecc_stats, sizeof(oldstats));
@@ -187,7 +188,7 @@ static int read_page(int log)
                err = mtd->ecc_stats.corrected - oldstats.corrected;
 
        if (err < 0 || read != mtd->writesize) {
-               msg("error: read failed at %#llx\n", (long long)offset);
+               pr_err("error: read failed at %#llx\n", (long long)offset);
                if (err >= 0)
                        err = -EIO;
        }
@@ -201,11 +202,11 @@ static int verify_page(int log)
        unsigned i, errs = 0;
 
        if (log)
-               msg("verify_page\n");
+               pr_info("verify_page\n");
 
        for (i = 0; i < mtd->writesize; i++) {
                if (rbuffer[i] != hash(i+seed)) {
-                       msg("Error: page offset %u, expected %02x, got %02x\n",
+                       pr_err("Error: page offset %u, expected %02x, got %02x\n",
                                i, hash(i+seed), rbuffer[i]);
                        errs++;
                }
@@ -230,13 +231,13 @@ static int insert_biterror(unsigned byte)
                for (bit = 7; bit >= 0; bit--) {
                        if (CBIT(wbuffer[byte], bit)) {
                                BCLR(wbuffer[byte], bit);
-                               msg("Inserted biterror @ %u/%u\n", byte, bit);
+                               pr_info("Inserted biterror @ %u/%u\n", byte, bit);
                                return 0;
                        }
                }
                byte++;
        }
-       msg("biterror: Failed to find a '1' bit\n");
+       pr_err("biterror: Failed to find a '1' bit\n");
        return -EIO;
 }
 
@@ -248,7 +249,7 @@ static int incremental_errors_test(void)
        unsigned i;
        unsigned errs_per_subpage = 0;
 
-       msg("incremental biterrors test\n");
+       pr_info("incremental biterrors test\n");
 
        for (i = 0; i < mtd->writesize; i++)
                wbuffer[i] = hash(i+seed);
@@ -265,9 +266,9 @@ static int incremental_errors_test(void)
 
                err = read_page(1);
                if (err > 0)
-                       msg("Read reported %d corrected bit errors\n", err);
+                       pr_info("Read reported %d corrected bit errors\n", err);
                if (err < 0) {
-                       msg("After %d biterrors per subpage, read reported error %d\n",
+                       pr_err("After %d biterrors per subpage, read reported error %d\n",
                                errs_per_subpage, err);
                        err = 0;
                        goto exit;
@@ -275,11 +276,11 @@ static int incremental_errors_test(void)
 
                err = verify_page(1);
                if (err) {
-                       msg("ECC failure, read data is incorrect despite read success\n");
+                       pr_err("ECC failure, read data is incorrect despite read success\n");
                        goto exit;
                }
 
-               msg("Successfully corrected %d bit errors per subpage\n",
+               pr_info("Successfully corrected %d bit errors per subpage\n",
                        errs_per_subpage);
 
                for (i = 0; i < subcount; i++) {
@@ -311,7 +312,7 @@ static int overwrite_test(void)
 
        memset(bitstats, 0, sizeof(bitstats));
 
-       msg("overwrite biterrors test\n");
+       pr_info("overwrite biterrors test\n");
 
        for (i = 0; i < mtd->writesize; i++)
                wbuffer[i] = hash(i+seed);
@@ -329,18 +330,18 @@ static int overwrite_test(void)
                err = read_page(0);
                if (err >= 0) {
                        if (err >= MAXBITS) {
-                               msg("Implausible number of bit errors corrected\n");
+                               pr_info("Implausible number of bit errors corrected\n");
                                err = -EIO;
                                break;
                        }
                        bitstats[err]++;
                        if (err > max_corrected) {
                                max_corrected = err;
-                               msg("Read reported %d corrected bit errors\n",
+                               pr_info("Read reported %d corrected bit errors\n",
                                        err);
                        }
                } else { /* err < 0 */
-                       msg("Read reported error %d\n", err);
+                       pr_info("Read reported error %d\n", err);
                        err = 0;
                        break;
                }
@@ -348,7 +349,7 @@ static int overwrite_test(void)
                err = verify_page(0);
                if (err) {
                        bitstats[max_corrected] = opno;
-                       msg("ECC failure, read data is incorrect despite read success\n");
+                       pr_info("ECC failure, read data is incorrect despite read success\n");
                        break;
                }
 
@@ -357,9 +358,9 @@ static int overwrite_test(void)
 
        /* At this point bitstats[0] contains the number of ops with no bit
         * errors, bitstats[1] the number of ops with 1 bit error, etc. */
-       msg("Bit error histogram (%d operations total):\n", opno);
+       pr_info("Bit error histogram (%d operations total):\n", opno);
        for (i = 0; i < max_corrected; i++)
-               msg("Page reads with %3d corrected bit errors: %d\n",
+               pr_info("Page reads with %3d corrected bit errors: %d\n",
                        i, bitstats[i]);
 
 exit:
@@ -370,36 +371,36 @@ static int __init mtd_nandbiterrs_init(void)
 {
        int err = 0;
 
-       msg("\n");
-       msg("==================================================\n");
-       msg("MTD device: %d\n", dev);
+       printk("\n");
+       printk(KERN_INFO "==================================================\n");
+       pr_info("MTD device: %d\n", dev);
 
        mtd = get_mtd_device(NULL, dev);
        if (IS_ERR(mtd)) {
                err = PTR_ERR(mtd);
-               msg("error: cannot get MTD device\n");
+               pr_err("error: cannot get MTD device\n");
                goto exit_mtddev;
        }
 
        if (mtd->type != MTD_NANDFLASH) {
-               msg("this test requires NAND flash\n");
+               pr_info("this test requires NAND flash\n");
                err = -ENODEV;
                goto exit_nand;
        }
 
-       msg("MTD device size %llu, eraseblock=%u, page=%u, oob=%u\n",
+       pr_info("MTD device size %llu, eraseblock=%u, page=%u, oob=%u\n",
                (unsigned long long)mtd->size, mtd->erasesize,
                mtd->writesize, mtd->oobsize);
 
        subsize  = mtd->writesize >> mtd->subpage_sft;
        subcount = mtd->writesize / subsize;
 
-       msg("Device uses %d subpages of %d bytes\n", subcount, subsize);
+       pr_info("Device uses %d subpages of %d bytes\n", subcount, subsize);
 
        offset     = page_offset * mtd->writesize;
        eraseblock = mtd_div_by_eb(offset, mtd);
 
-       msg("Using page=%u, offset=%llu, eraseblock=%u\n",
+       pr_info("Using page=%u, offset=%llu, eraseblock=%u\n",
                page_offset, offset, eraseblock);
 
        wbuffer = kmalloc(mtd->writesize, GFP_KERNEL);
@@ -432,8 +433,8 @@ static int __init mtd_nandbiterrs_init(void)
                goto exit_error;
 
        err = -EIO;
-       msg("finished successfully.\n");
-       msg("==================================================\n");
+       pr_info("finished successfully.\n");
+       printk(KERN_INFO "==================================================\n");
 
 exit_error:
        kfree(rbuffer);
index b437fa425077db48d4bb76da8d343e9739e56205..1eee264509a86cce86421e7fe730dbdf94d79a75 100644 (file)
@@ -1,3 +1,5 @@
+#define pr_fmt(fmt)    KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/list.h>
@@ -264,13 +266,13 @@ static int nand_ecc_test_run(const size_t size)
                                                correct_data, size);
 
                if (err) {
-                       pr_err("mtd_nandecctest: not ok - %s-%zd\n",
+                       pr_err("not ok - %s-%zd\n",
                                nand_ecc_test[i].name, size);
                        dump_data_ecc(error_data, error_ecc,
                                correct_data, correct_ecc, size);
                        break;
                }
-               pr_info("mtd_nandecctest: ok - %s-%zd\n",
+               pr_info("ok - %s-%zd\n",
                        nand_ecc_test[i].name, size);
        }
 error:
index ed9b62827f1bee15e6f5236e4c47f92cae6bfd5c..e86bb29419a21fe343eda838bc79c74cb660f73f 100644 (file)
@@ -19,6 +19,8 @@
  * Author: Adrian Hunter <ext-adrian.hunter@nokia.com>
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <asm/div64.h>
 #include <linux/init.h>
 #include <linux/module.h>
@@ -28,8 +30,6 @@
 #include <linux/slab.h>
 #include <linux/sched.h>
 
-#define PRINT_PREF KERN_INFO "mtd_oobtest: "
-
 static int dev = -EINVAL;
 module_param(dev, int, S_IRUGO);
 MODULE_PARM_DESC(dev, "MTD device number to use");
@@ -80,13 +80,12 @@ static int erase_eraseblock(int ebnum)
 
        err = mtd_erase(mtd, &ei);
        if (err) {
-               printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum);
+               pr_err("error %d while erasing EB %d\n", err, ebnum);
                return err;
        }
 
        if (ei.state == MTD_ERASE_FAILED) {
-               printk(PRINT_PREF "some erase error occurred at EB %d\n",
-                      ebnum);
+               pr_err("some erase error occurred at EB %d\n", ebnum);
                return -EIO;
        }
 
@@ -98,7 +97,7 @@ static int erase_whole_device(void)
        int err;
        unsigned int i;
 
-       printk(PRINT_PREF "erasing whole device\n");
+       pr_info("erasing whole device\n");
        for (i = 0; i < ebcnt; ++i) {
                if (bbt[i])
                        continue;
@@ -107,7 +106,7 @@ static int erase_whole_device(void)
                        return err;
                cond_resched();
        }
-       printk(PRINT_PREF "erased %u eraseblocks\n", i);
+       pr_info("erased %u eraseblocks\n", i);
        return 0;
 }
 
@@ -141,9 +140,9 @@ static int write_eraseblock(int ebnum)
                ops.oobbuf    = writebuf;
                err = mtd_write_oob(mtd, addr, &ops);
                if (err || ops.oobretlen != use_len) {
-                       printk(PRINT_PREF "error: writeoob failed at %#llx\n",
+                       pr_err("error: writeoob failed at %#llx\n",
                               (long long)addr);
-                       printk(PRINT_PREF "error: use_len %d, use_offset %d\n",
+                       pr_err("error: use_len %d, use_offset %d\n",
                               use_len, use_offset);
                        errcnt += 1;
                        return err ? err : -1;
@@ -160,7 +159,7 @@ static int write_whole_device(void)
        int err;
        unsigned int i;
 
-       printk(PRINT_PREF "writing OOBs of whole device\n");
+       pr_info("writing OOBs of whole device\n");
        for (i = 0; i < ebcnt; ++i) {
                if (bbt[i])
                        continue;
@@ -168,10 +167,10 @@ static int write_whole_device(void)
                if (err)
                        return err;
                if (i % 256 == 0)
-                       printk(PRINT_PREF "written up to eraseblock %u\n", i);
+                       pr_info("written up to eraseblock %u\n", i);
                cond_resched();
        }
-       printk(PRINT_PREF "written %u eraseblocks\n", i);
+       pr_info("written %u eraseblocks\n", i);
        return 0;
 }
 
@@ -194,17 +193,17 @@ static int verify_eraseblock(int ebnum)
                ops.oobbuf    = readbuf;
                err = mtd_read_oob(mtd, addr, &ops);
                if (err || ops.oobretlen != use_len) {
-                       printk(PRINT_PREF "error: readoob failed at %#llx\n",
+                       pr_err("error: readoob failed at %#llx\n",
                               (long long)addr);
                        errcnt += 1;
                        return err ? err : -1;
                }
                if (memcmp(readbuf, writebuf, use_len)) {
-                       printk(PRINT_PREF "error: verify failed at %#llx\n",
+                       pr_err("error: verify failed at %#llx\n",
                               (long long)addr);
                        errcnt += 1;
                        if (errcnt > 1000) {
-                               printk(PRINT_PREF "error: too many errors\n");
+                               pr_err("error: too many errors\n");
                                return -1;
                        }
                }
@@ -221,29 +220,28 @@ static int verify_eraseblock(int ebnum)
                        ops.oobbuf    = readbuf;
                        err = mtd_read_oob(mtd, addr, &ops);
                        if (err || ops.oobretlen != mtd->ecclayout->oobavail) {
-                               printk(PRINT_PREF "error: readoob failed at "
-                                      "%#llx\n", (long long)addr);
+                               pr_err("error: readoob failed at %#llx\n",
+                                               (long long)addr);
                                errcnt += 1;
                                return err ? err : -1;
                        }
                        if (memcmp(readbuf + use_offset, writebuf, use_len)) {
-                               printk(PRINT_PREF "error: verify failed at "
-                                      "%#llx\n", (long long)addr);
+                               pr_err("error: verify failed at %#llx\n",
+                                               (long long)addr);
                                errcnt += 1;
                                if (errcnt > 1000) {
-                                       printk(PRINT_PREF "error: too many "
-                                              "errors\n");
+                                       pr_err("error: too many errors\n");
                                        return -1;
                                }
                        }
                        for (k = 0; k < use_offset; ++k)
                                if (readbuf[k] != 0xff) {
-                                       printk(PRINT_PREF "error: verify 0xff "
+                                       pr_err("error: verify 0xff "
                                               "failed at %#llx\n",
                                               (long long)addr);
                                        errcnt += 1;
                                        if (errcnt > 1000) {
-                                               printk(PRINT_PREF "error: too "
+                                               pr_err("error: too "
                                                       "many errors\n");
                                                return -1;
                                        }
@@ -251,12 +249,12 @@ static int verify_eraseblock(int ebnum)
                        for (k = use_offset + use_len;
                             k < mtd->ecclayout->oobavail; ++k)
                                if (readbuf[k] != 0xff) {
-                                       printk(PRINT_PREF "error: verify 0xff "
+                                       pr_err("error: verify 0xff "
                                               "failed at %#llx\n",
                                               (long long)addr);
                                        errcnt += 1;
                                        if (errcnt > 1000) {
-                                               printk(PRINT_PREF "error: too "
+                                               pr_err("error: too "
                                                       "many errors\n");
                                                return -1;
                                        }
@@ -286,17 +284,17 @@ static int verify_eraseblock_in_one_go(int ebnum)
        ops.oobbuf    = readbuf;
        err = mtd_read_oob(mtd, addr, &ops);
        if (err || ops.oobretlen != len) {
-               printk(PRINT_PREF "error: readoob failed at %#llx\n",
+               pr_err("error: readoob failed at %#llx\n",
                       (long long)addr);
                errcnt += 1;
                return err ? err : -1;
        }
        if (memcmp(readbuf, writebuf, len)) {
-               printk(PRINT_PREF "error: verify failed at %#llx\n",
+               pr_err("error: verify failed at %#llx\n",
                       (long long)addr);
                errcnt += 1;
                if (errcnt > 1000) {
-                       printk(PRINT_PREF "error: too many errors\n");
+                       pr_err("error: too many errors\n");
                        return -1;
                }
        }
@@ -309,7 +307,7 @@ static int verify_all_eraseblocks(void)
        int err;
        unsigned int i;
 
-       printk(PRINT_PREF "verifying all eraseblocks\n");
+       pr_info("verifying all eraseblocks\n");
        for (i = 0; i < ebcnt; ++i) {
                if (bbt[i])
                        continue;
@@ -317,10 +315,10 @@ static int verify_all_eraseblocks(void)
                if (err)
                        return err;
                if (i % 256 == 0)
-                       printk(PRINT_PREF "verified up to eraseblock %u\n", i);
+                       pr_info("verified up to eraseblock %u\n", i);
                cond_resched();
        }
-       printk(PRINT_PREF "verified %u eraseblocks\n", i);
+       pr_info("verified %u eraseblocks\n", i);
        return 0;
 }
 
@@ -331,7 +329,7 @@ static int is_block_bad(int ebnum)
 
        ret = mtd_block_isbad(mtd, addr);
        if (ret)
-               printk(PRINT_PREF "block %d is bad\n", ebnum);
+               pr_info("block %d is bad\n", ebnum);
        return ret;
 }
 
@@ -341,18 +339,18 @@ static int scan_for_bad_eraseblocks(void)
 
        bbt = kmalloc(ebcnt, GFP_KERNEL);
        if (!bbt) {
-               printk(PRINT_PREF "error: cannot allocate memory\n");
+               pr_err("error: cannot allocate memory\n");
                return -ENOMEM;
        }
 
-       printk(PRINT_PREF "scanning for bad eraseblocks\n");
+       pr_info("scanning for bad eraseblocks\n");
        for (i = 0; i < ebcnt; ++i) {
                bbt[i] = is_block_bad(i) ? 1 : 0;
                if (bbt[i])
                        bad += 1;
                cond_resched();
        }
-       printk(PRINT_PREF "scanned %d eraseblocks, %d are bad\n", i, bad);
+       pr_info("scanned %d eraseblocks, %d are bad\n", i, bad);
        return 0;
 }
 
@@ -368,22 +366,22 @@ static int __init mtd_oobtest_init(void)
        printk(KERN_INFO "=================================================\n");
 
        if (dev < 0) {
-               printk(PRINT_PREF "Please specify a valid mtd-device via module paramter\n");
-               printk(KERN_CRIT "CAREFUL: This test wipes all data on the specified MTD device!\n");
+               pr_info("Please specify a valid mtd-device via module paramter\n");
+               pr_crit(KERN_CRIT "CAREFUL: This test wipes all data on the specified MTD device!\n");
                return -EINVAL;
        }
 
-       printk(PRINT_PREF "MTD device: %d\n", dev);
+       pr_info("MTD device: %d\n", dev);
 
        mtd = get_mtd_device(NULL, dev);
        if (IS_ERR(mtd)) {
                err = PTR_ERR(mtd);
-               printk(PRINT_PREF "error: cannot get MTD device\n");
+               pr_err("error: cannot get MTD device\n");
                return err;
        }
 
        if (mtd->type != MTD_NANDFLASH) {
-               printk(PRINT_PREF "this test requires NAND flash\n");
+               pr_info("this test requires NAND flash\n");
                goto out;
        }
 
@@ -392,7 +390,7 @@ static int __init mtd_oobtest_init(void)
        ebcnt = tmp;
        pgcnt = mtd->erasesize / mtd->writesize;
 
-       printk(PRINT_PREF "MTD device size %llu, eraseblock size %u, "
+       pr_info("MTD device size %llu, eraseblock size %u, "
               "page size %u, count of eraseblocks %u, pages per "
               "eraseblock %u, OOB size %u\n",
               (unsigned long long)mtd->size, mtd->erasesize,
@@ -401,12 +399,12 @@ static int __init mtd_oobtest_init(void)
        err = -ENOMEM;
        readbuf = kmalloc(mtd->erasesize, GFP_KERNEL);
        if (!readbuf) {
-               printk(PRINT_PREF "error: cannot allocate memory\n");
+               pr_err("error: cannot allocate memory\n");
                goto out;
        }
        writebuf = kmalloc(mtd->erasesize, GFP_KERNEL);
        if (!writebuf) {
-               printk(PRINT_PREF "error: cannot allocate memory\n");
+               pr_err("error: cannot allocate memory\n");
                goto out;
        }
 
@@ -420,7 +418,7 @@ static int __init mtd_oobtest_init(void)
        vary_offset = 0;
 
        /* First test: write all OOB, read it back and verify */
-       printk(PRINT_PREF "test 1 of 5\n");
+       pr_info("test 1 of 5\n");
 
        err = erase_whole_device();
        if (err)
@@ -440,7 +438,7 @@ static int __init mtd_oobtest_init(void)
         * Second test: write all OOB, a block at a time, read it back and
         * verify.
         */
-       printk(PRINT_PREF "test 2 of 5\n");
+       pr_info("test 2 of 5\n");
 
        err = erase_whole_device();
        if (err)
@@ -453,7 +451,7 @@ static int __init mtd_oobtest_init(void)
 
        /* Check all eraseblocks */
        simple_srand(3);
-       printk(PRINT_PREF "verifying all eraseblocks\n");
+       pr_info("verifying all eraseblocks\n");
        for (i = 0; i < ebcnt; ++i) {
                if (bbt[i])
                        continue;
@@ -461,16 +459,16 @@ static int __init mtd_oobtest_init(void)
                if (err)
                        goto out;
                if (i % 256 == 0)
-                       printk(PRINT_PREF "verified up to eraseblock %u\n", i);
+                       pr_info("verified up to eraseblock %u\n", i);
                cond_resched();
        }
-       printk(PRINT_PREF "verified %u eraseblocks\n", i);
+       pr_info("verified %u eraseblocks\n", i);
 
        /*
         * Third test: write OOB at varying offsets and lengths, read it back
         * and verify.
         */
-       printk(PRINT_PREF "test 3 of 5\n");
+       pr_info("test 3 of 5\n");
 
        err = erase_whole_device();
        if (err)
@@ -503,7 +501,7 @@ static int __init mtd_oobtest_init(void)
        vary_offset = 0;
 
        /* Fourth test: try to write off end of device */
-       printk(PRINT_PREF "test 4 of 5\n");
+       pr_info("test 4 of 5\n");
 
        err = erase_whole_device();
        if (err)
@@ -522,14 +520,14 @@ static int __init mtd_oobtest_init(void)
        ops.ooboffs   = mtd->ecclayout->oobavail;
        ops.datbuf    = NULL;
        ops.oobbuf    = writebuf;
-       printk(PRINT_PREF "attempting to start write past end of OOB\n");
-       printk(PRINT_PREF "an error is expected...\n");
+       pr_info("attempting to start write past end of OOB\n");
+       pr_info("an error is expected...\n");
        err = mtd_write_oob(mtd, addr0, &ops);
        if (err) {
-               printk(PRINT_PREF "error occurred as expected\n");
+               pr_info("error occurred as expected\n");
                err = 0;
        } else {
-               printk(PRINT_PREF "error: can write past end of OOB\n");
+               pr_err("error: can write past end of OOB\n");
                errcnt += 1;
        }
 
@@ -542,19 +540,19 @@ static int __init mtd_oobtest_init(void)
        ops.ooboffs   = mtd->ecclayout->oobavail;
        ops.datbuf    = NULL;
        ops.oobbuf    = readbuf;
-       printk(PRINT_PREF "attempting to start read past end of OOB\n");
-       printk(PRINT_PREF "an error is expected...\n");
+       pr_info("attempting to start read past end of OOB\n");
+       pr_info("an error is expected...\n");
        err = mtd_read_oob(mtd, addr0, &ops);
        if (err) {
-               printk(PRINT_PREF "error occurred as expected\n");
+               pr_info("error occurred as expected\n");
                err = 0;
        } else {
-               printk(PRINT_PREF "error: can read past end of OOB\n");
+               pr_err("error: can read past end of OOB\n");
                errcnt += 1;
        }
 
        if (bbt[ebcnt - 1])
-               printk(PRINT_PREF "skipping end of device tests because last "
+               pr_info("skipping end of device tests because last "
                       "block is bad\n");
        else {
                /* Attempt to write off end of device */
@@ -566,14 +564,14 @@ static int __init mtd_oobtest_init(void)
                ops.ooboffs   = 0;
                ops.datbuf    = NULL;
                ops.oobbuf    = writebuf;
-               printk(PRINT_PREF "attempting to write past end of device\n");
-               printk(PRINT_PREF "an error is expected...\n");
+               pr_info("attempting to write past end of device\n");
+               pr_info("an error is expected...\n");
                err = mtd_write_oob(mtd, mtd->size - mtd->writesize, &ops);
                if (err) {
-                       printk(PRINT_PREF "error occurred as expected\n");
+                       pr_info("error occurred as expected\n");
                        err = 0;
                } else {
-                       printk(PRINT_PREF "error: wrote past end of device\n");
+                       pr_err("error: wrote past end of device\n");
                        errcnt += 1;
                }
 
@@ -586,14 +584,14 @@ static int __init mtd_oobtest_init(void)
                ops.ooboffs   = 0;
                ops.datbuf    = NULL;
                ops.oobbuf    = readbuf;
-               printk(PRINT_PREF "attempting to read past end of device\n");
-               printk(PRINT_PREF "an error is expected...\n");
+               pr_info("attempting to read past end of device\n");
+               pr_info("an error is expected...\n");
                err = mtd_read_oob(mtd, mtd->size - mtd->writesize, &ops);
                if (err) {
-                       printk(PRINT_PREF "error occurred as expected\n");
+                       pr_info("error occurred as expected\n");
                        err = 0;
                } else {
-                       printk(PRINT_PREF "error: read past end of device\n");
+                       pr_err("error: read past end of device\n");
                        errcnt += 1;
                }
 
@@ -610,14 +608,14 @@ static int __init mtd_oobtest_init(void)
                ops.ooboffs   = 1;
                ops.datbuf    = NULL;
                ops.oobbuf    = writebuf;
-               printk(PRINT_PREF "attempting to write past end of device\n");
-               printk(PRINT_PREF "an error is expected...\n");
+               pr_info("attempting to write past end of device\n");
+               pr_info("an error is expected...\n");
                err = mtd_write_oob(mtd, mtd->size - mtd->writesize, &ops);
                if (err) {
-                       printk(PRINT_PREF "error occurred as expected\n");
+                       pr_info("error occurred as expected\n");
                        err = 0;
                } else {
-                       printk(PRINT_PREF "error: wrote past end of device\n");
+                       pr_err("error: wrote past end of device\n");
                        errcnt += 1;
                }
 
@@ -630,20 +628,20 @@ static int __init mtd_oobtest_init(void)
                ops.ooboffs   = 1;
                ops.datbuf    = NULL;
                ops.oobbuf    = readbuf;
-               printk(PRINT_PREF "attempting to read past end of device\n");
-               printk(PRINT_PREF "an error is expected...\n");
+               pr_info("attempting to read past end of device\n");
+               pr_info("an error is expected...\n");
                err = mtd_read_oob(mtd, mtd->size - mtd->writesize, &ops);
                if (err) {
-                       printk(PRINT_PREF "error occurred as expected\n");
+                       pr_info("error occurred as expected\n");
                        err = 0;
                } else {
-                       printk(PRINT_PREF "error: read past end of device\n");
+                       pr_err("error: read past end of device\n");
                        errcnt += 1;
                }
        }
 
        /* Fifth test: write / read across block boundaries */
-       printk(PRINT_PREF "test 5 of 5\n");
+       pr_info("test 5 of 5\n");
 
        /* Erase all eraseblocks */
        err = erase_whole_device();
@@ -652,7 +650,7 @@ static int __init mtd_oobtest_init(void)
 
        /* Write all eraseblocks */
        simple_srand(11);
-       printk(PRINT_PREF "writing OOBs of whole device\n");
+       pr_info("writing OOBs of whole device\n");
        for (i = 0; i < ebcnt - 1; ++i) {
                int cnt = 2;
                int pg;
@@ -674,17 +672,16 @@ static int __init mtd_oobtest_init(void)
                        if (err)
                                goto out;
                        if (i % 256 == 0)
-                               printk(PRINT_PREF "written up to eraseblock "
-                                      "%u\n", i);
+                               pr_info("written up to eraseblock %u\n", i);
                        cond_resched();
                        addr += mtd->writesize;
                }
        }
-       printk(PRINT_PREF "written %u eraseblocks\n", i);
+       pr_info("written %u eraseblocks\n", i);
 
        /* Check all eraseblocks */
        simple_srand(11);
-       printk(PRINT_PREF "verifying all eraseblocks\n");
+       pr_info("verifying all eraseblocks\n");
        for (i = 0; i < ebcnt - 1; ++i) {
                if (bbt[i] || bbt[i + 1])
                        continue;
@@ -702,28 +699,28 @@ static int __init mtd_oobtest_init(void)
                if (err)
                        goto out;
                if (memcmp(readbuf, writebuf, mtd->ecclayout->oobavail * 2)) {
-                       printk(PRINT_PREF "error: verify failed at %#llx\n",
+                       pr_err("error: verify failed at %#llx\n",
                               (long long)addr);
                        errcnt += 1;
                        if (errcnt > 1000) {
-                               printk(PRINT_PREF "error: too many errors\n");
+                               pr_err("error: too many errors\n");
                                goto out;
                        }
                }
                if (i % 256 == 0)
-                       printk(PRINT_PREF "verified up to eraseblock %u\n", i);
+                       pr_info("verified up to eraseblock %u\n", i);
                cond_resched();
        }
-       printk(PRINT_PREF "verified %u eraseblocks\n", i);
+       pr_info("verified %u eraseblocks\n", i);
 
-       printk(PRINT_PREF "finished with %d errors\n", errcnt);
+       pr_info("finished with %d errors\n", errcnt);
 out:
        kfree(bbt);
        kfree(writebuf);
        kfree(readbuf);
        put_mtd_device(mtd);
        if (err)
-               printk(PRINT_PREF "error %d occurred\n", err);
+               pr_info("error %d occurred\n", err);
        printk(KERN_INFO "=================================================\n");
        return err;
 }
index 252ddb092fb2312f96db0e82abf573fe22137318..3ba2a77dbdaa26427dfee0bfb2fb9aadd342c1da 100644 (file)
@@ -19,6 +19,8 @@
  * Author: Adrian Hunter <ext-adrian.hunter@nokia.com>
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <asm/div64.h>
 #include <linux/init.h>
 #include <linux/module.h>
@@ -28,8 +30,6 @@
 #include <linux/slab.h>
 #include <linux/sched.h>
 
-#define PRINT_PREF KERN_INFO "mtd_pagetest: "
-
 static int dev = -EINVAL;
 module_param(dev, int, S_IRUGO);
 MODULE_PARM_DESC(dev, "MTD device number to use");
@@ -79,12 +79,12 @@ static int erase_eraseblock(int ebnum)
 
        err = mtd_erase(mtd, &ei);
        if (err) {
-               printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum);
+               pr_err("error %d while erasing EB %d\n", err, ebnum);
                return err;
        }
 
        if (ei.state == MTD_ERASE_FAILED) {
-               printk(PRINT_PREF "some erase error occurred at EB %d\n",
+               pr_err("some erase error occurred at EB %d\n",
                       ebnum);
                return -EIO;
        }
@@ -102,7 +102,7 @@ static int write_eraseblock(int ebnum)
        cond_resched();
        err = mtd_write(mtd, addr, mtd->erasesize, &written, writebuf);
        if (err || written != mtd->erasesize)
-               printk(PRINT_PREF "error: write failed at %#llx\n",
+               pr_err("error: write failed at %#llx\n",
                       (long long)addr);
 
        return err;
@@ -131,7 +131,7 @@ static int verify_eraseblock(int ebnum)
                if (mtd_is_bitflip(err))
                        err = 0;
                if (err || read != bufsize) {
-                       printk(PRINT_PREF "error: read failed at %#llx\n",
+                       pr_err("error: read failed at %#llx\n",
                               (long long)addr0);
                        return err;
                }
@@ -139,7 +139,7 @@ static int verify_eraseblock(int ebnum)
                if (mtd_is_bitflip(err))
                        err = 0;
                if (err || read != bufsize) {
-                       printk(PRINT_PREF "error: read failed at %#llx\n",
+                       pr_err("error: read failed at %#llx\n",
                               (long long)(addrn - bufsize));
                        return err;
                }
@@ -148,12 +148,12 @@ static int verify_eraseblock(int ebnum)
                if (mtd_is_bitflip(err))
                        err = 0;
                if (err || read != bufsize) {
-                       printk(PRINT_PREF "error: read failed at %#llx\n",
+                       pr_err("error: read failed at %#llx\n",
                               (long long)addr);
                        break;
                }
                if (memcmp(twopages, writebuf + (j * pgsize), bufsize)) {
-                       printk(PRINT_PREF "error: verify failed at %#llx\n",
+                       pr_err("error: verify failed at %#llx\n",
                               (long long)addr);
                        errcnt += 1;
                }
@@ -166,7 +166,7 @@ static int verify_eraseblock(int ebnum)
                if (mtd_is_bitflip(err))
                        err = 0;
                if (err || read != bufsize) {
-                       printk(PRINT_PREF "error: read failed at %#llx\n",
+                       pr_err("error: read failed at %#llx\n",
                               (long long)addr0);
                        return err;
                }
@@ -174,7 +174,7 @@ static int verify_eraseblock(int ebnum)
                if (mtd_is_bitflip(err))
                        err = 0;
                if (err || read != bufsize) {
-                       printk(PRINT_PREF "error: read failed at %#llx\n",
+                       pr_err("error: read failed at %#llx\n",
                               (long long)(addrn - bufsize));
                        return err;
                }
@@ -183,14 +183,14 @@ static int verify_eraseblock(int ebnum)
                if (mtd_is_bitflip(err))
                        err = 0;
                if (err || read != bufsize) {
-                       printk(PRINT_PREF "error: read failed at %#llx\n",
+                       pr_err("error: read failed at %#llx\n",
                               (long long)addr);
                        return err;
                }
                memcpy(boundary, writebuf + mtd->erasesize - pgsize, pgsize);
                set_random_data(boundary + pgsize, pgsize);
                if (memcmp(twopages, boundary, bufsize)) {
-                       printk(PRINT_PREF "error: verify failed at %#llx\n",
+                       pr_err("error: verify failed at %#llx\n",
                               (long long)addr);
                        errcnt += 1;
                }
@@ -206,10 +206,10 @@ static int crosstest(void)
        loff_t addr, addr0, addrn;
        unsigned char *pp1, *pp2, *pp3, *pp4;
 
-       printk(PRINT_PREF "crosstest\n");
+       pr_info("crosstest\n");
        pp1 = kmalloc(pgsize * 4, GFP_KERNEL);
        if (!pp1) {
-               printk(PRINT_PREF "error: cannot allocate memory\n");
+               pr_err("error: cannot allocate memory\n");
                return -ENOMEM;
        }
        pp2 = pp1 + pgsize;
@@ -231,7 +231,7 @@ static int crosstest(void)
        if (mtd_is_bitflip(err))
                err = 0;
        if (err || read != pgsize) {
-               printk(PRINT_PREF "error: read failed at %#llx\n",
+               pr_err("error: read failed at %#llx\n",
                       (long long)addr);
                kfree(pp1);
                return err;
@@ -243,7 +243,7 @@ static int crosstest(void)
        if (mtd_is_bitflip(err))
                err = 0;
        if (err || read != pgsize) {
-               printk(PRINT_PREF "error: read failed at %#llx\n",
+               pr_err("error: read failed at %#llx\n",
                       (long long)addr);
                kfree(pp1);
                return err;
@@ -251,12 +251,12 @@ static int crosstest(void)
 
        /* Read first page to pp2 */
        addr = addr0;
-       printk(PRINT_PREF "reading page at %#llx\n", (long long)addr);
+       pr_info("reading page at %#llx\n", (long long)addr);
        err = mtd_read(mtd, addr, pgsize, &read, pp2);
        if (mtd_is_bitflip(err))
                err = 0;
        if (err || read != pgsize) {
-               printk(PRINT_PREF "error: read failed at %#llx\n",
+               pr_err("error: read failed at %#llx\n",
                       (long long)addr);
                kfree(pp1);
                return err;
@@ -264,12 +264,12 @@ static int crosstest(void)
 
        /* Read last page to pp3 */
        addr = addrn - pgsize;
-       printk(PRINT_PREF "reading page at %#llx\n", (long long)addr);
+       pr_info("reading page at %#llx\n", (long long)addr);
        err = mtd_read(mtd, addr, pgsize, &read, pp3);
        if (mtd_is_bitflip(err))
                err = 0;
        if (err || read != pgsize) {
-               printk(PRINT_PREF "error: read failed at %#llx\n",
+               pr_err("error: read failed at %#llx\n",
                       (long long)addr);
                kfree(pp1);
                return err;
@@ -277,25 +277,25 @@ static int crosstest(void)
 
        /* Read first page again to pp4 */
        addr = addr0;
-       printk(PRINT_PREF "reading page at %#llx\n", (long long)addr);
+       pr_info("reading page at %#llx\n", (long long)addr);
        err = mtd_read(mtd, addr, pgsize, &read, pp4);
        if (mtd_is_bitflip(err))
                err = 0;
        if (err || read != pgsize) {
-               printk(PRINT_PREF "error: read failed at %#llx\n",
+               pr_err("error: read failed at %#llx\n",
                       (long long)addr);
                kfree(pp1);
                return err;
        }
 
        /* pp2 and pp4 should be the same */
-       printk(PRINT_PREF "verifying pages read at %#llx match\n",
+       pr_info("verifying pages read at %#llx match\n",
               (long long)addr0);
        if (memcmp(pp2, pp4, pgsize)) {
-               printk(PRINT_PREF "verify failed!\n");
+               pr_err("verify failed!\n");
                errcnt += 1;
        } else if (!err)
-               printk(PRINT_PREF "crosstest ok\n");
+               pr_info("crosstest ok\n");
        kfree(pp1);
        return err;
 }
@@ -307,7 +307,7 @@ static int erasecrosstest(void)
        loff_t addr0;
        char *readbuf = twopages;
 
-       printk(PRINT_PREF "erasecrosstest\n");
+       pr_info("erasecrosstest\n");
 
        ebnum = 0;
        addr0 = 0;
@@ -320,79 +320,79 @@ static int erasecrosstest(void)
        while (ebnum2 && bbt[ebnum2])
                ebnum2 -= 1;
 
-       printk(PRINT_PREF "erasing block %d\n", ebnum);
+       pr_info("erasing block %d\n", ebnum);
        err = erase_eraseblock(ebnum);
        if (err)
                return err;
 
-       printk(PRINT_PREF "writing 1st page of block %d\n", ebnum);
+       pr_info("writing 1st page of block %d\n", ebnum);
        set_random_data(writebuf, pgsize);
        strcpy(writebuf, "There is no data like this!");
        err = mtd_write(mtd, addr0, pgsize, &written, writebuf);
        if (err || written != pgsize) {
-               printk(PRINT_PREF "error: write failed at %#llx\n",
+               pr_info("error: write failed at %#llx\n",
                       (long long)addr0);
                return err ? err : -1;
        }
 
-       printk(PRINT_PREF "reading 1st page of block %d\n", ebnum);
+       pr_info("reading 1st page of block %d\n", ebnum);
        memset(readbuf, 0, pgsize);
        err = mtd_read(mtd, addr0, pgsize, &read, readbuf);
        if (mtd_is_bitflip(err))
                err = 0;
        if (err || read != pgsize) {
-               printk(PRINT_PREF "error: read failed at %#llx\n",
+               pr_err("error: read failed at %#llx\n",
                       (long long)addr0);
                return err ? err : -1;
        }
 
-       printk(PRINT_PREF "verifying 1st page of block %d\n", ebnum);
+       pr_info("verifying 1st page of block %d\n", ebnum);
        if (memcmp(writebuf, readbuf, pgsize)) {
-               printk(PRINT_PREF "verify failed!\n");
+               pr_err("verify failed!\n");
                errcnt += 1;
                return -1;
        }
 
-       printk(PRINT_PREF "erasing block %d\n", ebnum);
+       pr_info("erasing block %d\n", ebnum);
        err = erase_eraseblock(ebnum);
        if (err)
                return err;
 
-       printk(PRINT_PREF "writing 1st page of block %d\n", ebnum);
+       pr_info("writing 1st page of block %d\n", ebnum);
        set_random_data(writebuf, pgsize);
        strcpy(writebuf, "There is no data like this!");
        err = mtd_write(mtd, addr0, pgsize, &written, writebuf);
        if (err || written != pgsize) {
-               printk(PRINT_PREF "error: write failed at %#llx\n",
+               pr_err("error: write failed at %#llx\n",
                       (long long)addr0);
                return err ? err : -1;
        }
 
-       printk(PRINT_PREF "erasing block %d\n", ebnum2);
+       pr_info("erasing block %d\n", ebnum2);
        err = erase_eraseblock(ebnum2);
        if (err)
                return err;
 
-       printk(PRINT_PREF "reading 1st page of block %d\n", ebnum);
+       pr_info("reading 1st page of block %d\n", ebnum);
        memset(readbuf, 0, pgsize);
        err = mtd_read(mtd, addr0, pgsize, &read, readbuf);
        if (mtd_is_bitflip(err))
                err = 0;
        if (err || read != pgsize) {
-               printk(PRINT_PREF "error: read failed at %#llx\n",
+               pr_err("error: read failed at %#llx\n",
                       (long long)addr0);
                return err ? err : -1;
        }
 
-       printk(PRINT_PREF "verifying 1st page of block %d\n", ebnum);
+       pr_info("verifying 1st page of block %d\n", ebnum);
        if (memcmp(writebuf, readbuf, pgsize)) {
-               printk(PRINT_PREF "verify failed!\n");
+               pr_err("verify failed!\n");
                errcnt += 1;
                return -1;
        }
 
        if (!err)
-               printk(PRINT_PREF "erasecrosstest ok\n");
+               pr_info("erasecrosstest ok\n");
        return err;
 }
 
@@ -402,7 +402,7 @@ static int erasetest(void)
        int err = 0, i, ebnum, ok = 1;
        loff_t addr0;
 
-       printk(PRINT_PREF "erasetest\n");
+       pr_info("erasetest\n");
 
        ebnum = 0;
        addr0 = 0;
@@ -411,40 +411,40 @@ static int erasetest(void)
                ebnum += 1;
        }
 
-       printk(PRINT_PREF "erasing block %d\n", ebnum);
+       pr_info("erasing block %d\n", ebnum);
        err = erase_eraseblock(ebnum);
        if (err)
                return err;
 
-       printk(PRINT_PREF "writing 1st page of block %d\n", ebnum);
+       pr_info("writing 1st page of block %d\n", ebnum);
        set_random_data(writebuf, pgsize);
        err = mtd_write(mtd, addr0, pgsize, &written, writebuf);
        if (err || written != pgsize) {
-               printk(PRINT_PREF "error: write failed at %#llx\n",
+               pr_err("error: write failed at %#llx\n",
                       (long long)addr0);
                return err ? err : -1;
        }
 
-       printk(PRINT_PREF "erasing block %d\n", ebnum);
+       pr_info("erasing block %d\n", ebnum);
        err = erase_eraseblock(ebnum);
        if (err)
                return err;
 
-       printk(PRINT_PREF "reading 1st page of block %d\n", ebnum);
+       pr_info("reading 1st page of block %d\n", ebnum);
        err = mtd_read(mtd, addr0, pgsize, &read, twopages);
        if (mtd_is_bitflip(err))
                err = 0;
        if (err || read != pgsize) {
-               printk(PRINT_PREF "error: read failed at %#llx\n",
+               pr_err("error: read failed at %#llx\n",
                       (long long)addr0);
                return err ? err : -1;
        }
 
-       printk(PRINT_PREF "verifying 1st page of block %d is all 0xff\n",
+       pr_info("verifying 1st page of block %d is all 0xff\n",
               ebnum);
        for (i = 0; i < pgsize; ++i)
                if (twopages[i] != 0xff) {
-                       printk(PRINT_PREF "verifying all 0xff failed at %d\n",
+                       pr_err("verifying all 0xff failed at %d\n",
                               i);
                        errcnt += 1;
                        ok = 0;
@@ -452,7 +452,7 @@ static int erasetest(void)
                }
 
        if (ok && !err)
-               printk(PRINT_PREF "erasetest ok\n");
+               pr_info("erasetest ok\n");
 
        return err;
 }
@@ -464,7 +464,7 @@ static int is_block_bad(int ebnum)
 
        ret = mtd_block_isbad(mtd, addr);
        if (ret)
-               printk(PRINT_PREF "block %d is bad\n", ebnum);
+               pr_info("block %d is bad\n", ebnum);
        return ret;
 }
 
@@ -474,18 +474,18 @@ static int scan_for_bad_eraseblocks(void)
 
        bbt = kzalloc(ebcnt, GFP_KERNEL);
        if (!bbt) {
-               printk(PRINT_PREF "error: cannot allocate memory\n");
+               pr_err("error: cannot allocate memory\n");
                return -ENOMEM;
        }
 
-       printk(PRINT_PREF "scanning for bad eraseblocks\n");
+       pr_info("scanning for bad eraseblocks\n");
        for (i = 0; i < ebcnt; ++i) {
                bbt[i] = is_block_bad(i) ? 1 : 0;
                if (bbt[i])
                        bad += 1;
                cond_resched();
        }
-       printk(PRINT_PREF "scanned %d eraseblocks, %d are bad\n", i, bad);
+       pr_info("scanned %d eraseblocks, %d are bad\n", i, bad);
        return 0;
 }
 
@@ -499,22 +499,22 @@ static int __init mtd_pagetest_init(void)
        printk(KERN_INFO "=================================================\n");
 
        if (dev < 0) {
-               printk(PRINT_PREF "Please specify a valid mtd-device via module paramter\n");
-               printk(KERN_CRIT "CAREFUL: This test wipes all data on the specified MTD device!\n");
+               pr_info("Please specify a valid mtd-device via module paramter\n");
+               pr_crit("CAREFUL: This test wipes all data on the specified MTD device!\n");
                return -EINVAL;
        }
 
-       printk(PRINT_PREF "MTD device: %d\n", dev);
+       pr_info("MTD device: %d\n", dev);
 
        mtd = get_mtd_device(NULL, dev);
        if (IS_ERR(mtd)) {
                err = PTR_ERR(mtd);
-               printk(PRINT_PREF "error: cannot get MTD device\n");
+               pr_err("error: cannot get MTD device\n");
                return err;
        }
 
        if (mtd->type != MTD_NANDFLASH) {
-               printk(PRINT_PREF "this test requires NAND flash\n");
+               pr_info("this test requires NAND flash\n");
                goto out;
        }
 
@@ -524,7 +524,7 @@ static int __init mtd_pagetest_init(void)
        pgcnt = mtd->erasesize / mtd->writesize;
        pgsize = mtd->writesize;
 
-       printk(PRINT_PREF "MTD device size %llu, eraseblock size %u, "
+       pr_info("MTD device size %llu, eraseblock size %u, "
               "page size %u, count of eraseblocks %u, pages per "
               "eraseblock %u, OOB size %u\n",
               (unsigned long long)mtd->size, mtd->erasesize,
@@ -534,17 +534,17 @@ static int __init mtd_pagetest_init(void)
        bufsize = pgsize * 2;
        writebuf = kmalloc(mtd->erasesize, GFP_KERNEL);
        if (!writebuf) {
-               printk(PRINT_PREF "error: cannot allocate memory\n");
+               pr_err("error: cannot allocate memory\n");
                goto out;
        }
        twopages = kmalloc(bufsize, GFP_KERNEL);
        if (!twopages) {
-               printk(PRINT_PREF "error: cannot allocate memory\n");
+               pr_err("error: cannot allocate memory\n");
                goto out;
        }
        boundary = kmalloc(bufsize, GFP_KERNEL);
        if (!boundary) {
-               printk(PRINT_PREF "error: cannot allocate memory\n");
+               pr_err("error: cannot allocate memory\n");
                goto out;
        }
 
@@ -553,7 +553,7 @@ static int __init mtd_pagetest_init(void)
                goto out;
 
        /* Erase all eraseblocks */
-       printk(PRINT_PREF "erasing whole device\n");
+       pr_info("erasing whole device\n");
        for (i = 0; i < ebcnt; ++i) {
                if (bbt[i])
                        continue;
@@ -562,11 +562,11 @@ static int __init mtd_pagetest_init(void)
                        goto out;
                cond_resched();
        }
-       printk(PRINT_PREF "erased %u eraseblocks\n", i);
+       pr_info("erased %u eraseblocks\n", i);
 
        /* Write all eraseblocks */
        simple_srand(1);
-       printk(PRINT_PREF "writing whole device\n");
+       pr_info("writing whole device\n");
        for (i = 0; i < ebcnt; ++i) {
                if (bbt[i])
                        continue;
@@ -574,14 +574,14 @@ static int __init mtd_pagetest_init(void)
                if (err)
                        goto out;
                if (i % 256 == 0)
-                       printk(PRINT_PREF "written up to eraseblock %u\n", i);
+                       pr_info("written up to eraseblock %u\n", i);
                cond_resched();
        }
-       printk(PRINT_PREF "written %u eraseblocks\n", i);
+       pr_info("written %u eraseblocks\n", i);
 
        /* Check all eraseblocks */
        simple_srand(1);
-       printk(PRINT_PREF "verifying all eraseblocks\n");
+       pr_info("verifying all eraseblocks\n");
        for (i = 0; i < ebcnt; ++i) {
                if (bbt[i])
                        continue;
@@ -589,10 +589,10 @@ static int __init mtd_pagetest_init(void)
                if (err)
                        goto out;
                if (i % 256 == 0)
-                       printk(PRINT_PREF "verified up to eraseblock %u\n", i);
+                       pr_info("verified up to eraseblock %u\n", i);
                cond_resched();
        }
-       printk(PRINT_PREF "verified %u eraseblocks\n", i);
+       pr_info("verified %u eraseblocks\n", i);
 
        err = crosstest();
        if (err)
@@ -606,7 +606,7 @@ static int __init mtd_pagetest_init(void)
        if (err)
                goto out;
 
-       printk(PRINT_PREF "finished with %d errors\n", errcnt);
+       pr_info("finished with %d errors\n", errcnt);
 out:
 
        kfree(bbt);
@@ -615,7 +615,7 @@ out:
        kfree(writebuf);
        put_mtd_device(mtd);
        if (err)
-               printk(PRINT_PREF "error %d occurred\n", err);
+               pr_info("error %d occurred\n", err);
        printk(KERN_INFO "=================================================\n");
        return err;
 }
index 121aba189cec6de33297a2afb88ecd7892d329f5..ec3efb53826c0369819acc8b927708df189fd3e4 100644 (file)
@@ -19,6 +19,8 @@
  * Author: Adrian Hunter <ext-adrian.hunter@nokia.com>
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
@@ -27,8 +29,6 @@
 #include <linux/slab.h>
 #include <linux/sched.h>
 
-#define PRINT_PREF KERN_INFO "mtd_readtest: "
-
 static int dev = -EINVAL;
 module_param(dev, int, S_IRUGO);
 MODULE_PARM_DESC(dev, "MTD device number to use");
@@ -56,7 +56,7 @@ static int read_eraseblock_by_page(int ebnum)
                if (ret == -EUCLEAN)
                        ret = 0;
                if (ret || read != pgsize) {
-                       printk(PRINT_PREF "error: read failed at %#llx\n",
+                       pr_err("error: read failed at %#llx\n",
                               (long long)addr);
                        if (!err)
                                err = ret;
@@ -77,7 +77,7 @@ static int read_eraseblock_by_page(int ebnum)
                        ret = mtd_read_oob(mtd, addr, &ops);
                        if ((ret && !mtd_is_bitflip(ret)) ||
                                        ops.oobretlen != mtd->oobsize) {
-                               printk(PRINT_PREF "error: read oob failed at "
+                               pr_err("error: read oob failed at "
                                                  "%#llx\n", (long long)addr);
                                if (!err)
                                        err = ret;
@@ -99,7 +99,7 @@ static void dump_eraseblock(int ebnum)
        char line[128];
        int pg, oob;
 
-       printk(PRINT_PREF "dumping eraseblock %d\n", ebnum);
+       pr_info("dumping eraseblock %d\n", ebnum);
        n = mtd->erasesize;
        for (i = 0; i < n;) {
                char *p = line;
@@ -112,7 +112,7 @@ static void dump_eraseblock(int ebnum)
        }
        if (!mtd->oobsize)
                return;
-       printk(PRINT_PREF "dumping oob from eraseblock %d\n", ebnum);
+       pr_info("dumping oob from eraseblock %d\n", ebnum);
        n = mtd->oobsize;
        for (pg = 0, i = 0; pg < pgcnt; pg++)
                for (oob = 0; oob < n;) {
@@ -134,7 +134,7 @@ static int is_block_bad(int ebnum)
 
        ret = mtd_block_isbad(mtd, addr);
        if (ret)
-               printk(PRINT_PREF "block %d is bad\n", ebnum);
+               pr_info("block %d is bad\n", ebnum);
        return ret;
 }
 
@@ -144,21 +144,21 @@ static int scan_for_bad_eraseblocks(void)
 
        bbt = kzalloc(ebcnt, GFP_KERNEL);
        if (!bbt) {
-               printk(PRINT_PREF "error: cannot allocate memory\n");
+               pr_err("error: cannot allocate memory\n");
                return -ENOMEM;
        }
 
        if (!mtd_can_have_bb(mtd))
                return 0;
 
-       printk(PRINT_PREF "scanning for bad eraseblocks\n");
+       pr_info("scanning for bad eraseblocks\n");
        for (i = 0; i < ebcnt; ++i) {
                bbt[i] = is_block_bad(i) ? 1 : 0;
                if (bbt[i])
                        bad += 1;
                cond_resched();
        }
-       printk(PRINT_PREF "scanned %d eraseblocks, %d are bad\n", i, bad);
+       pr_info("scanned %d eraseblocks, %d are bad\n", i, bad);
        return 0;
 }
 
@@ -171,21 +171,21 @@ static int __init mtd_readtest_init(void)
        printk(KERN_INFO "=================================================\n");
 
        if (dev < 0) {
-               printk(PRINT_PREF "Please specify a valid mtd-device via module paramter\n");
+               pr_info("Please specify a valid mtd-device via module paramter\n");
                return -EINVAL;
        }
 
-       printk(PRINT_PREF "MTD device: %d\n", dev);
+       pr_info("MTD device: %d\n", dev);
 
        mtd = get_mtd_device(NULL, dev);
        if (IS_ERR(mtd)) {
                err = PTR_ERR(mtd);
-               printk(PRINT_PREF "error: Cannot get MTD device\n");
+               pr_err("error: Cannot get MTD device\n");
                return err;
        }
 
        if (mtd->writesize == 1) {
-               printk(PRINT_PREF "not NAND flash, assume page size is 512 "
+               pr_info("not NAND flash, assume page size is 512 "
                       "bytes.\n");
                pgsize = 512;
        } else
@@ -196,7 +196,7 @@ static int __init mtd_readtest_init(void)
        ebcnt = tmp;
        pgcnt = mtd->erasesize / pgsize;
 
-       printk(PRINT_PREF "MTD device size %llu, eraseblock size %u, "
+       pr_info("MTD device size %llu, eraseblock size %u, "
               "page size %u, count of eraseblocks %u, pages per "
               "eraseblock %u, OOB size %u\n",
               (unsigned long long)mtd->size, mtd->erasesize,
@@ -205,12 +205,12 @@ static int __init mtd_readtest_init(void)
        err = -ENOMEM;
        iobuf = kmalloc(mtd->erasesize, GFP_KERNEL);
        if (!iobuf) {
-               printk(PRINT_PREF "error: cannot allocate memory\n");
+               pr_err("error: cannot allocate memory\n");
                goto out;
        }
        iobuf1 = kmalloc(mtd->erasesize, GFP_KERNEL);
        if (!iobuf1) {
-               printk(PRINT_PREF "error: cannot allocate memory\n");
+               pr_err("error: cannot allocate memory\n");
                goto out;
        }
 
@@ -219,7 +219,7 @@ static int __init mtd_readtest_init(void)
                goto out;
 
        /* Read all eraseblocks 1 page at a time */
-       printk(PRINT_PREF "testing page read\n");
+       pr_info("testing page read\n");
        for (i = 0; i < ebcnt; ++i) {
                int ret;
 
@@ -235,9 +235,9 @@ static int __init mtd_readtest_init(void)
        }
 
        if (err)
-               printk(PRINT_PREF "finished with errors\n");
+               pr_info("finished with errors\n");
        else
-               printk(PRINT_PREF "finished\n");
+               pr_info("finished\n");
 
 out:
 
@@ -246,7 +246,7 @@ out:
        kfree(bbt);
        put_mtd_device(mtd);
        if (err)
-               printk(PRINT_PREF "error %d occurred\n", err);
+               pr_info("error %d occurred\n", err);
        printk(KERN_INFO "=================================================\n");
        return err;
 }
index 42b0f7456fc4a4876d94ed1131c5dab1c7ff7dee..8a5803b1724cef4a4eb56e4258f7f9e6960ab53c 100644 (file)
@@ -19,6 +19,8 @@
  * Author: Adrian Hunter <adrian.hunter@nokia.com>
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
@@ -28,8 +30,6 @@
 #include <linux/sched.h>
 #include <linux/random.h>
 
-#define PRINT_PREF KERN_INFO "mtd_speedtest: "
-
 static int dev = -EINVAL;
 module_param(dev, int, S_IRUGO);
 MODULE_PARM_DESC(dev, "MTD device number to use");
@@ -70,12 +70,12 @@ static int erase_eraseblock(int ebnum)
 
        err = mtd_erase(mtd, &ei);
        if (err) {
-               printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum);
+               pr_err("error %d while erasing EB %d\n", err, ebnum);
                return err;
        }
 
        if (ei.state == MTD_ERASE_FAILED) {
-               printk(PRINT_PREF "some erase error occurred at EB %d\n",
+               pr_err("some erase error occurred at EB %d\n",
                       ebnum);
                return -EIO;
        }
@@ -96,13 +96,13 @@ static int multiblock_erase(int ebnum, int blocks)
 
        err = mtd_erase(mtd, &ei);
        if (err) {
-               printk(PRINT_PREF "error %d while erasing EB %d, blocks %d\n",
+               pr_err("error %d while erasing EB %d, blocks %d\n",
                       err, ebnum, blocks);
                return err;
        }
 
        if (ei.state == MTD_ERASE_FAILED) {
-               printk(PRINT_PREF "some erase error occurred at EB %d,"
+               pr_err("some erase error occurred at EB %d,"
                       "blocks %d\n", ebnum, blocks);
                return -EIO;
        }
@@ -134,7 +134,7 @@ static int write_eraseblock(int ebnum)
 
        err = mtd_write(mtd, addr, mtd->erasesize, &written, iobuf);
        if (err || written != mtd->erasesize) {
-               printk(PRINT_PREF "error: write failed at %#llx\n", addr);
+               pr_err("error: write failed at %#llx\n", addr);
                if (!err)
                        err = -EINVAL;
        }
@@ -152,7 +152,7 @@ static int write_eraseblock_by_page(int ebnum)
        for (i = 0; i < pgcnt; i++) {
                err = mtd_write(mtd, addr, pgsize, &written, buf);
                if (err || written != pgsize) {
-                       printk(PRINT_PREF "error: write failed at %#llx\n",
+                       pr_err("error: write failed at %#llx\n",
                               addr);
                        if (!err)
                                err = -EINVAL;
@@ -175,7 +175,7 @@ static int write_eraseblock_by_2pages(int ebnum)
        for (i = 0; i < n; i++) {
                err = mtd_write(mtd, addr, sz, &written, buf);
                if (err || written != sz) {
-                       printk(PRINT_PREF "error: write failed at %#llx\n",
+                       pr_err("error: write failed at %#llx\n",
                               addr);
                        if (!err)
                                err = -EINVAL;
@@ -187,7 +187,7 @@ static int write_eraseblock_by_2pages(int ebnum)
        if (pgcnt % 2) {
                err = mtd_write(mtd, addr, pgsize, &written, buf);
                if (err || written != pgsize) {
-                       printk(PRINT_PREF "error: write failed at %#llx\n",
+                       pr_err("error: write failed at %#llx\n",
                               addr);
                        if (!err)
                                err = -EINVAL;
@@ -208,7 +208,7 @@ static int read_eraseblock(int ebnum)
        if (mtd_is_bitflip(err))
                err = 0;
        if (err || read != mtd->erasesize) {
-               printk(PRINT_PREF "error: read failed at %#llx\n", addr);
+               pr_err("error: read failed at %#llx\n", addr);
                if (!err)
                        err = -EINVAL;
        }
@@ -229,7 +229,7 @@ static int read_eraseblock_by_page(int ebnum)
                if (mtd_is_bitflip(err))
                        err = 0;
                if (err || read != pgsize) {
-                       printk(PRINT_PREF "error: read failed at %#llx\n",
+                       pr_err("error: read failed at %#llx\n",
                               addr);
                        if (!err)
                                err = -EINVAL;
@@ -255,7 +255,7 @@ static int read_eraseblock_by_2pages(int ebnum)
                if (mtd_is_bitflip(err))
                        err = 0;
                if (err || read != sz) {
-                       printk(PRINT_PREF "error: read failed at %#llx\n",
+                       pr_err("error: read failed at %#llx\n",
                               addr);
                        if (!err)
                                err = -EINVAL;
@@ -270,7 +270,7 @@ static int read_eraseblock_by_2pages(int ebnum)
                if (mtd_is_bitflip(err))
                        err = 0;
                if (err || read != pgsize) {
-                       printk(PRINT_PREF "error: read failed at %#llx\n",
+                       pr_err("error: read failed at %#llx\n",
                               addr);
                        if (!err)
                                err = -EINVAL;
@@ -287,7 +287,7 @@ static int is_block_bad(int ebnum)
 
        ret = mtd_block_isbad(mtd, addr);
        if (ret)
-               printk(PRINT_PREF "block %d is bad\n", ebnum);
+               pr_info("block %d is bad\n", ebnum);
        return ret;
 }
 
@@ -321,21 +321,21 @@ static int scan_for_bad_eraseblocks(void)
 
        bbt = kzalloc(ebcnt, GFP_KERNEL);
        if (!bbt) {
-               printk(PRINT_PREF "error: cannot allocate memory\n");
+               pr_err("error: cannot allocate memory\n");
                return -ENOMEM;
        }
 
        if (!mtd_can_have_bb(mtd))
                goto out;
 
-       printk(PRINT_PREF "scanning for bad eraseblocks\n");
+       pr_info("scanning for bad eraseblocks\n");
        for (i = 0; i < ebcnt; ++i) {
                bbt[i] = is_block_bad(i) ? 1 : 0;
                if (bbt[i])
                        bad += 1;
                cond_resched();
        }
-       printk(PRINT_PREF "scanned %d eraseblocks, %d are bad\n", i, bad);
+       pr_info("scanned %d eraseblocks, %d are bad\n", i, bad);
 out:
        goodebcnt = ebcnt - bad;
        return 0;
@@ -351,25 +351,25 @@ static int __init mtd_speedtest_init(void)
        printk(KERN_INFO "=================================================\n");
 
        if (dev < 0) {
-               printk(PRINT_PREF "Please specify a valid mtd-device via module paramter\n");
-               printk(KERN_CRIT "CAREFUL: This test wipes all data on the specified MTD device!\n");
+               pr_info("Please specify a valid mtd-device via module paramter\n");
+               pr_crit("CAREFUL: This test wipes all data on the specified MTD device!\n");
                return -EINVAL;
        }
 
        if (count)
-               printk(PRINT_PREF "MTD device: %d    count: %d\n", dev, count);
+               pr_info("MTD device: %d    count: %d\n", dev, count);
        else
-               printk(PRINT_PREF "MTD device: %d\n", dev);
+               pr_info("MTD device: %d\n", dev);
 
        mtd = get_mtd_device(NULL, dev);
        if (IS_ERR(mtd)) {
                err = PTR_ERR(mtd);
-               printk(PRINT_PREF "error: cannot get MTD device\n");
+               pr_err("error: cannot get MTD device\n");
                return err;
        }
 
        if (mtd->writesize == 1) {
-               printk(PRINT_PREF "not NAND flash, assume page size is 512 "
+               pr_info("not NAND flash, assume page size is 512 "
                       "bytes.\n");
                pgsize = 512;
        } else
@@ -380,7 +380,7 @@ static int __init mtd_speedtest_init(void)
        ebcnt = tmp;
        pgcnt = mtd->erasesize / pgsize;
 
-       printk(PRINT_PREF "MTD device size %llu, eraseblock size %u, "
+       pr_info("MTD device size %llu, eraseblock size %u, "
               "page size %u, count of eraseblocks %u, pages per "
               "eraseblock %u, OOB size %u\n",
               (unsigned long long)mtd->size, mtd->erasesize,
@@ -392,7 +392,7 @@ static int __init mtd_speedtest_init(void)
        err = -ENOMEM;
        iobuf = kmalloc(mtd->erasesize, GFP_KERNEL);
        if (!iobuf) {
-               printk(PRINT_PREF "error: cannot allocate memory\n");
+               pr_err("error: cannot allocate memory\n");
                goto out;
        }
 
@@ -407,7 +407,7 @@ static int __init mtd_speedtest_init(void)
                goto out;
 
        /* Write all eraseblocks, 1 eraseblock at a time */
-       printk(PRINT_PREF "testing eraseblock write speed\n");
+       pr_info("testing eraseblock write speed\n");
        start_timing();
        for (i = 0; i < ebcnt; ++i) {
                if (bbt[i])
@@ -419,10 +419,10 @@ static int __init mtd_speedtest_init(void)
        }
        stop_timing();
        speed = calc_speed();
-       printk(PRINT_PREF "eraseblock write speed is %ld KiB/s\n", speed);
+       pr_info("eraseblock write speed is %ld KiB/s\n", speed);
 
        /* Read all eraseblocks, 1 eraseblock at a time */
-       printk(PRINT_PREF "testing eraseblock read speed\n");
+       pr_info("testing eraseblock read speed\n");
        start_timing();
        for (i = 0; i < ebcnt; ++i) {
                if (bbt[i])
@@ -434,14 +434,14 @@ static int __init mtd_speedtest_init(void)
        }
        stop_timing();
        speed = calc_speed();
-       printk(PRINT_PREF "eraseblock read speed is %ld KiB/s\n", speed);
+       pr_info("eraseblock read speed is %ld KiB/s\n", speed);
 
        err = erase_whole_device();
        if (err)
                goto out;
 
        /* Write all eraseblocks, 1 page at a time */
-       printk(PRINT_PREF "testing page write speed\n");
+       pr_info("testing page write speed\n");
        start_timing();
        for (i = 0; i < ebcnt; ++i) {
                if (bbt[i])
@@ -453,10 +453,10 @@ static int __init mtd_speedtest_init(void)
        }
        stop_timing();
        speed = calc_speed();
-       printk(PRINT_PREF "page write speed is %ld KiB/s\n", speed);
+       pr_info("page write speed is %ld KiB/s\n", speed);
 
        /* Read all eraseblocks, 1 page at a time */
-       printk(PRINT_PREF "testing page read speed\n");
+       pr_info("testing page read speed\n");
        start_timing();
        for (i = 0; i < ebcnt; ++i) {
                if (bbt[i])
@@ -468,14 +468,14 @@ static int __init mtd_speedtest_init(void)
        }
        stop_timing();
        speed = calc_speed();
-       printk(PRINT_PREF "page read speed is %ld KiB/s\n", speed);
+       pr_info("page read speed is %ld KiB/s\n", speed);
 
        err = erase_whole_device();
        if (err)
                goto out;
 
        /* Write all eraseblocks, 2 pages at a time */
-       printk(PRINT_PREF "testing 2 page write speed\n");
+       pr_info("testing 2 page write speed\n");
        start_timing();
        for (i = 0; i < ebcnt; ++i) {
                if (bbt[i])
@@ -487,10 +487,10 @@ static int __init mtd_speedtest_init(void)
        }
        stop_timing();
        speed = calc_speed();
-       printk(PRINT_PREF "2 page write speed is %ld KiB/s\n", speed);
+       pr_info("2 page write speed is %ld KiB/s\n", speed);
 
        /* Read all eraseblocks, 2 pages at a time */
-       printk(PRINT_PREF "testing 2 page read speed\n");
+       pr_info("testing 2 page read speed\n");
        start_timing();
        for (i = 0; i < ebcnt; ++i) {
                if (bbt[i])
@@ -502,10 +502,10 @@ static int __init mtd_speedtest_init(void)
        }
        stop_timing();
        speed = calc_speed();
-       printk(PRINT_PREF "2 page read speed is %ld KiB/s\n", speed);
+       pr_info("2 page read speed is %ld KiB/s\n", speed);
 
        /* Erase all eraseblocks */
-       printk(PRINT_PREF "Testing erase speed\n");
+       pr_info("Testing erase speed\n");
        start_timing();
        for (i = 0; i < ebcnt; ++i) {
                if (bbt[i])
@@ -517,12 +517,12 @@ static int __init mtd_speedtest_init(void)
        }
        stop_timing();
        speed = calc_speed();
-       printk(PRINT_PREF "erase speed is %ld KiB/s\n", speed);
+       pr_info("erase speed is %ld KiB/s\n", speed);
 
        /* Multi-block erase all eraseblocks */
        for (k = 1; k < 7; k++) {
                blocks = 1 << k;
-               printk(PRINT_PREF "Testing %dx multi-block erase speed\n",
+               pr_info("Testing %dx multi-block erase speed\n",
                       blocks);
                start_timing();
                for (i = 0; i < ebcnt; ) {
@@ -541,16 +541,16 @@ static int __init mtd_speedtest_init(void)
                }
                stop_timing();
                speed = calc_speed();
-               printk(PRINT_PREF "%dx multi-block erase speed is %ld KiB/s\n",
+               pr_info("%dx multi-block erase speed is %ld KiB/s\n",
                       blocks, speed);
        }
-       printk(PRINT_PREF "finished\n");
+       pr_info("finished\n");
 out:
        kfree(iobuf);
        kfree(bbt);
        put_mtd_device(mtd);
        if (err)
-               printk(PRINT_PREF "error %d occurred\n", err);
+               pr_info("error %d occurred\n", err);
        printk(KERN_INFO "=================================================\n");
        return err;
 }
index cb268cebf01ae0c7fec1c3951975bc22bde34daa..fea1dd78ccbecb54eaeae13de165229fc4da3ea6 100644 (file)
@@ -19,6 +19,8 @@
  * Author: Adrian Hunter <ext-adrian.hunter@nokia.com>
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
@@ -29,8 +31,6 @@
 #include <linux/vmalloc.h>
 #include <linux/random.h>
 
-#define PRINT_PREF KERN_INFO "mtd_stresstest: "
-
 static int dev = -EINVAL;
 module_param(dev, int, S_IRUGO);
 MODULE_PARM_DESC(dev, "MTD device number to use");
@@ -94,12 +94,12 @@ static int erase_eraseblock(int ebnum)
 
        err = mtd_erase(mtd, &ei);
        if (unlikely(err)) {
-               printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum);
+               pr_err("error %d while erasing EB %d\n", err, ebnum);
                return err;
        }
 
        if (unlikely(ei.state == MTD_ERASE_FAILED)) {
-               printk(PRINT_PREF "some erase error occurred at EB %d\n",
+               pr_err("some erase error occurred at EB %d\n",
                       ebnum);
                return -EIO;
        }
@@ -114,7 +114,7 @@ static int is_block_bad(int ebnum)
 
        ret = mtd_block_isbad(mtd, addr);
        if (ret)
-               printk(PRINT_PREF "block %d is bad\n", ebnum);
+               pr_info("block %d is bad\n", ebnum);
        return ret;
 }
 
@@ -137,7 +137,7 @@ static int do_read(void)
        if (mtd_is_bitflip(err))
                err = 0;
        if (unlikely(err || read != len)) {
-               printk(PRINT_PREF "error: read failed at 0x%llx\n",
+               pr_err("error: read failed at 0x%llx\n",
                       (long long)addr);
                if (!err)
                        err = -EINVAL;
@@ -174,7 +174,7 @@ static int do_write(void)
        addr = eb * mtd->erasesize + offs;
        err = mtd_write(mtd, addr, len, &written, writebuf);
        if (unlikely(err || written != len)) {
-               printk(PRINT_PREF "error: write failed at 0x%llx\n",
+               pr_err("error: write failed at 0x%llx\n",
                       (long long)addr);
                if (!err)
                        err = -EINVAL;
@@ -203,21 +203,21 @@ static int scan_for_bad_eraseblocks(void)
 
        bbt = kzalloc(ebcnt, GFP_KERNEL);
        if (!bbt) {
-               printk(PRINT_PREF "error: cannot allocate memory\n");
+               pr_err("error: cannot allocate memory\n");
                return -ENOMEM;
        }
 
        if (!mtd_can_have_bb(mtd))
                return 0;
 
-       printk(PRINT_PREF "scanning for bad eraseblocks\n");
+       pr_info("scanning for bad eraseblocks\n");
        for (i = 0; i < ebcnt; ++i) {
                bbt[i] = is_block_bad(i) ? 1 : 0;
                if (bbt[i])
                        bad += 1;
                cond_resched();
        }
-       printk(PRINT_PREF "scanned %d eraseblocks, %d are bad\n", i, bad);
+       pr_info("scanned %d eraseblocks, %d are bad\n", i, bad);
        return 0;
 }
 
@@ -231,22 +231,22 @@ static int __init mtd_stresstest_init(void)
        printk(KERN_INFO "=================================================\n");
 
        if (dev < 0) {
-               printk(PRINT_PREF "Please specify a valid mtd-device via module paramter\n");
-               printk(KERN_CRIT "CAREFUL: This test wipes all data on the specified MTD device!\n");
+               pr_info("Please specify a valid mtd-device via module paramter\n");
+               pr_crit("CAREFUL: This test wipes all data on the specified MTD device!\n");
                return -EINVAL;
        }
 
-       printk(PRINT_PREF "MTD device: %d\n", dev);
+       pr_info("MTD device: %d\n", dev);
 
        mtd = get_mtd_device(NULL, dev);
        if (IS_ERR(mtd)) {
                err = PTR_ERR(mtd);
-               printk(PRINT_PREF "error: cannot get MTD device\n");
+               pr_err("error: cannot get MTD device\n");
                return err;
        }
 
        if (mtd->writesize == 1) {
-               printk(PRINT_PREF "not NAND flash, assume page size is 512 "
+               pr_info("not NAND flash, assume page size is 512 "
                       "bytes.\n");
                pgsize = 512;
        } else
@@ -257,14 +257,14 @@ static int __init mtd_stresstest_init(void)
        ebcnt = tmp;
        pgcnt = mtd->erasesize / pgsize;
 
-       printk(PRINT_PREF "MTD device size %llu, eraseblock size %u, "
+       pr_info("MTD device size %llu, eraseblock size %u, "
               "page size %u, count of eraseblocks %u, pages per "
               "eraseblock %u, OOB size %u\n",
               (unsigned long long)mtd->size, mtd->erasesize,
               pgsize, ebcnt, pgcnt, mtd->oobsize);
 
        if (ebcnt < 2) {
-               printk(PRINT_PREF "error: need at least 2 eraseblocks\n");
+               pr_err("error: need at least 2 eraseblocks\n");
                err = -ENOSPC;
                goto out_put_mtd;
        }
@@ -277,7 +277,7 @@ static int __init mtd_stresstest_init(void)
        writebuf = vmalloc(bufsize);
        offsets = kmalloc(ebcnt * sizeof(int), GFP_KERNEL);
        if (!readbuf || !writebuf || !offsets) {
-               printk(PRINT_PREF "error: cannot allocate memory\n");
+               pr_err("error: cannot allocate memory\n");
                goto out;
        }
        for (i = 0; i < ebcnt; i++)
@@ -290,16 +290,16 @@ static int __init mtd_stresstest_init(void)
                goto out;
 
        /* Do operations */
-       printk(PRINT_PREF "doing operations\n");
+       pr_info("doing operations\n");
        for (op = 0; op < count; op++) {
                if ((op & 1023) == 0)
-                       printk(PRINT_PREF "%d operations done\n", op);
+                       pr_info("%d operations done\n", op);
                err = do_operation();
                if (err)
                        goto out;
                cond_resched();
        }
-       printk(PRINT_PREF "finished, %d operations done\n", op);
+       pr_info("finished, %d operations done\n", op);
 
 out:
        kfree(offsets);
@@ -309,7 +309,7 @@ out:
 out_put_mtd:
        put_mtd_device(mtd);
        if (err)
-               printk(PRINT_PREF "error %d occurred\n", err);
+               pr_info("error %d occurred\n", err);
        printk(KERN_INFO "=================================================\n");
        return err;
 }
index 9667bf53528223a6cec4ab1e04a7358cb323991f..8813b0e86637a1f0418259e5eedc5c8fac3ca962 100644 (file)
@@ -19,6 +19,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
@@ -27,8 +29,6 @@
 #include <linux/slab.h>
 #include <linux/sched.h>
 
-#define PRINT_PREF KERN_INFO "mtd_subpagetest: "
-
 static int dev = -EINVAL;
 module_param(dev, int, S_IRUGO);
 MODULE_PARM_DESC(dev, "MTD device number to use");
@@ -82,12 +82,12 @@ static int erase_eraseblock(int ebnum)
 
        err = mtd_erase(mtd, &ei);
        if (err) {
-               printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum);
+               pr_err("error %d while erasing EB %d\n", err, ebnum);
                return err;
        }
 
        if (ei.state == MTD_ERASE_FAILED) {
-               printk(PRINT_PREF "some erase error occurred at EB %d\n",
+               pr_err("some erase error occurred at EB %d\n",
                       ebnum);
                return -EIO;
        }
@@ -100,7 +100,7 @@ static int erase_whole_device(void)
        int err;
        unsigned int i;
 
-       printk(PRINT_PREF "erasing whole device\n");
+       pr_info("erasing whole device\n");
        for (i = 0; i < ebcnt; ++i) {
                if (bbt[i])
                        continue;
@@ -109,7 +109,7 @@ static int erase_whole_device(void)
                        return err;
                cond_resched();
        }
-       printk(PRINT_PREF "erased %u eraseblocks\n", i);
+       pr_info("erased %u eraseblocks\n", i);
        return 0;
 }
 
@@ -122,11 +122,11 @@ static int write_eraseblock(int ebnum)
        set_random_data(writebuf, subpgsize);
        err = mtd_write(mtd, addr, subpgsize, &written, writebuf);
        if (unlikely(err || written != subpgsize)) {
-               printk(PRINT_PREF "error: write failed at %#llx\n",
+               pr_err("error: write failed at %#llx\n",
                       (long long)addr);
                if (written != subpgsize) {
-                       printk(PRINT_PREF "  write size: %#x\n", subpgsize);
-                       printk(PRINT_PREF "  written: %#zx\n", written);
+                       pr_err("  write size: %#x\n", subpgsize);
+                       pr_err("  written: %#zx\n", written);
                }
                return err ? err : -1;
        }
@@ -136,11 +136,11 @@ static int write_eraseblock(int ebnum)
        set_random_data(writebuf, subpgsize);
        err = mtd_write(mtd, addr, subpgsize, &written, writebuf);
        if (unlikely(err || written != subpgsize)) {
-               printk(PRINT_PREF "error: write failed at %#llx\n",
+               pr_err("error: write failed at %#llx\n",
                       (long long)addr);
                if (written != subpgsize) {
-                       printk(PRINT_PREF "  write size: %#x\n", subpgsize);
-                       printk(PRINT_PREF "  written: %#zx\n", written);
+                       pr_err("  write size: %#x\n", subpgsize);
+                       pr_err("  written: %#zx\n", written);
                }
                return err ? err : -1;
        }
@@ -160,12 +160,12 @@ static int write_eraseblock2(int ebnum)
                set_random_data(writebuf, subpgsize * k);
                err = mtd_write(mtd, addr, subpgsize * k, &written, writebuf);
                if (unlikely(err || written != subpgsize * k)) {
-                       printk(PRINT_PREF "error: write failed at %#llx\n",
+                       pr_err("error: write failed at %#llx\n",
                               (long long)addr);
                        if (written != subpgsize) {
-                               printk(PRINT_PREF "  write size: %#x\n",
+                               pr_err("  write size: %#x\n",
                                       subpgsize * k);
-                               printk(PRINT_PREF "  written: %#08zx\n",
+                               pr_err("  written: %#08zx\n",
                                       written);
                        }
                        return err ? err : -1;
@@ -198,23 +198,23 @@ static int verify_eraseblock(int ebnum)
        err = mtd_read(mtd, addr, subpgsize, &read, readbuf);
        if (unlikely(err || read != subpgsize)) {
                if (mtd_is_bitflip(err) && read == subpgsize) {
-                       printk(PRINT_PREF "ECC correction at %#llx\n",
+                       pr_info("ECC correction at %#llx\n",
                               (long long)addr);
                        err = 0;
                } else {
-                       printk(PRINT_PREF "error: read failed at %#llx\n",
+                       pr_err("error: read failed at %#llx\n",
                               (long long)addr);
                        return err ? err : -1;
                }
        }
        if (unlikely(memcmp(readbuf, writebuf, subpgsize))) {
-               printk(PRINT_PREF "error: verify failed at %#llx\n",
+               pr_err("error: verify failed at %#llx\n",
                       (long long)addr);
-               printk(PRINT_PREF "------------- written----------------\n");
+               pr_info("------------- written----------------\n");
                print_subpage(writebuf);
-               printk(PRINT_PREF "------------- read ------------------\n");
+               pr_info("------------- read ------------------\n");
                print_subpage(readbuf);
-               printk(PRINT_PREF "-------------------------------------\n");
+               pr_info("-------------------------------------\n");
                errcnt += 1;
        }
 
@@ -225,23 +225,23 @@ static int verify_eraseblock(int ebnum)
        err = mtd_read(mtd, addr, subpgsize, &read, readbuf);
        if (unlikely(err || read != subpgsize)) {
                if (mtd_is_bitflip(err) && read == subpgsize) {
-                       printk(PRINT_PREF "ECC correction at %#llx\n",
+                       pr_info("ECC correction at %#llx\n",
                               (long long)addr);
                        err = 0;
                } else {
-                       printk(PRINT_PREF "error: read failed at %#llx\n",
+                       pr_err("error: read failed at %#llx\n",
                               (long long)addr);
                        return err ? err : -1;
                }
        }
        if (unlikely(memcmp(readbuf, writebuf, subpgsize))) {
-               printk(PRINT_PREF "error: verify failed at %#llx\n",
+               pr_info("error: verify failed at %#llx\n",
                       (long long)addr);
-               printk(PRINT_PREF "------------- written----------------\n");
+               pr_info("------------- written----------------\n");
                print_subpage(writebuf);
-               printk(PRINT_PREF "------------- read ------------------\n");
+               pr_info("------------- read ------------------\n");
                print_subpage(readbuf);
-               printk(PRINT_PREF "-------------------------------------\n");
+               pr_info("-------------------------------------\n");
                errcnt += 1;
        }
 
@@ -262,17 +262,17 @@ static int verify_eraseblock2(int ebnum)
                err = mtd_read(mtd, addr, subpgsize * k, &read, readbuf);
                if (unlikely(err || read != subpgsize * k)) {
                        if (mtd_is_bitflip(err) && read == subpgsize * k) {
-                               printk(PRINT_PREF "ECC correction at %#llx\n",
+                               pr_info("ECC correction at %#llx\n",
                                       (long long)addr);
                                err = 0;
                        } else {
-                               printk(PRINT_PREF "error: read failed at "
+                               pr_err("error: read failed at "
                                       "%#llx\n", (long long)addr);
                                return err ? err : -1;
                        }
                }
                if (unlikely(memcmp(readbuf, writebuf, subpgsize * k))) {
-                       printk(PRINT_PREF "error: verify failed at %#llx\n",
+                       pr_err("error: verify failed at %#llx\n",
                               (long long)addr);
                        errcnt += 1;
                }
@@ -295,17 +295,17 @@ static int verify_eraseblock_ff(int ebnum)
                err = mtd_read(mtd, addr, subpgsize, &read, readbuf);
                if (unlikely(err || read != subpgsize)) {
                        if (mtd_is_bitflip(err) && read == subpgsize) {
-                               printk(PRINT_PREF "ECC correction at %#llx\n",
+                               pr_info("ECC correction at %#llx\n",
                                       (long long)addr);
                                err = 0;
                        } else {
-                               printk(PRINT_PREF "error: read failed at "
+                               pr_err("error: read failed at "
                                       "%#llx\n", (long long)addr);
                                return err ? err : -1;
                        }
                }
                if (unlikely(memcmp(readbuf, writebuf, subpgsize))) {
-                       printk(PRINT_PREF "error: verify 0xff failed at "
+                       pr_err("error: verify 0xff failed at "
                               "%#llx\n", (long long)addr);
                        errcnt += 1;
                }
@@ -320,7 +320,7 @@ static int verify_all_eraseblocks_ff(void)
        int err;
        unsigned int i;
 
-       printk(PRINT_PREF "verifying all eraseblocks for 0xff\n");
+       pr_info("verifying all eraseblocks for 0xff\n");
        for (i = 0; i < ebcnt; ++i) {
                if (bbt[i])
                        continue;
@@ -328,10 +328,10 @@ static int verify_all_eraseblocks_ff(void)
                if (err)
                        return err;
                if (i % 256 == 0)
-                       printk(PRINT_PREF "verified up to eraseblock %u\n", i);
+                       pr_info("verified up to eraseblock %u\n", i);
                cond_resched();
        }
-       printk(PRINT_PREF "verified %u eraseblocks\n", i);
+       pr_info("verified %u eraseblocks\n", i);
        return 0;
 }
 
@@ -342,7 +342,7 @@ static int is_block_bad(int ebnum)
 
        ret = mtd_block_isbad(mtd, addr);
        if (ret)
-               printk(PRINT_PREF "block %d is bad\n", ebnum);
+               pr_info("block %d is bad\n", ebnum);
        return ret;
 }
 
@@ -352,18 +352,18 @@ static int scan_for_bad_eraseblocks(void)
 
        bbt = kzalloc(ebcnt, GFP_KERNEL);
        if (!bbt) {
-               printk(PRINT_PREF "error: cannot allocate memory\n");
+               pr_err("error: cannot allocate memory\n");
                return -ENOMEM;
        }
 
-       printk(PRINT_PREF "scanning for bad eraseblocks\n");
+       pr_info("scanning for bad eraseblocks\n");
        for (i = 0; i < ebcnt; ++i) {
                bbt[i] = is_block_bad(i) ? 1 : 0;
                if (bbt[i])
                        bad += 1;
                cond_resched();
        }
-       printk(PRINT_PREF "scanned %d eraseblocks, %d are bad\n", i, bad);
+       pr_info("scanned %d eraseblocks, %d are bad\n", i, bad);
        return 0;
 }
 
@@ -377,22 +377,22 @@ static int __init mtd_subpagetest_init(void)
        printk(KERN_INFO "=================================================\n");
 
        if (dev < 0) {
-               printk(PRINT_PREF "Please specify a valid mtd-device via module paramter\n");
-               printk(KERN_CRIT "CAREFUL: This test wipes all data on the specified MTD device!\n");
+               pr_info("Please specify a valid mtd-device via module paramter\n");
+               pr_crit("CAREFUL: This test wipes all data on the specified MTD device!\n");
                return -EINVAL;
        }
 
-       printk(PRINT_PREF "MTD device: %d\n", dev);
+       pr_info("MTD device: %d\n", dev);
 
        mtd = get_mtd_device(NULL, dev);
        if (IS_ERR(mtd)) {
                err = PTR_ERR(mtd);
-               printk(PRINT_PREF "error: cannot get MTD device\n");
+               pr_err("error: cannot get MTD device\n");
                return err;
        }
 
        if (mtd->type != MTD_NANDFLASH) {
-               printk(PRINT_PREF "this test requires NAND flash\n");
+               pr_info("this test requires NAND flash\n");
                goto out;
        }
 
@@ -402,7 +402,7 @@ static int __init mtd_subpagetest_init(void)
        ebcnt = tmp;
        pgcnt = mtd->erasesize / mtd->writesize;
 
-       printk(PRINT_PREF "MTD device size %llu, eraseblock size %u, "
+       pr_info("MTD device size %llu, eraseblock size %u, "
               "page size %u, subpage size %u, count of eraseblocks %u, "
               "pages per eraseblock %u, OOB size %u\n",
               (unsigned long long)mtd->size, mtd->erasesize,
@@ -412,12 +412,12 @@ static int __init mtd_subpagetest_init(void)
        bufsize = subpgsize * 32;
        writebuf = kmalloc(bufsize, GFP_KERNEL);
        if (!writebuf) {
-               printk(PRINT_PREF "error: cannot allocate memory\n");
+               pr_info("error: cannot allocate memory\n");
                goto out;
        }
        readbuf = kmalloc(bufsize, GFP_KERNEL);
        if (!readbuf) {
-               printk(PRINT_PREF "error: cannot allocate memory\n");
+               pr_info("error: cannot allocate memory\n");
                goto out;
        }
 
@@ -429,7 +429,7 @@ static int __init mtd_subpagetest_init(void)
        if (err)
                goto out;
 
-       printk(PRINT_PREF "writing whole device\n");
+       pr_info("writing whole device\n");
        simple_srand(1);
        for (i = 0; i < ebcnt; ++i) {
                if (bbt[i])
@@ -438,13 +438,13 @@ static int __init mtd_subpagetest_init(void)
                if (unlikely(err))
                        goto out;
                if (i % 256 == 0)
-                       printk(PRINT_PREF "written up to eraseblock %u\n", i);
+                       pr_info("written up to eraseblock %u\n", i);
                cond_resched();
        }
-       printk(PRINT_PREF "written %u eraseblocks\n", i);
+       pr_info("written %u eraseblocks\n", i);
 
        simple_srand(1);
-       printk(PRINT_PREF "verifying all eraseblocks\n");
+       pr_info("verifying all eraseblocks\n");
        for (i = 0; i < ebcnt; ++i) {
                if (bbt[i])
                        continue;
@@ -452,10 +452,10 @@ static int __init mtd_subpagetest_init(void)
                if (unlikely(err))
                        goto out;
                if (i % 256 == 0)
-                       printk(PRINT_PREF "verified up to eraseblock %u\n", i);
+                       pr_info("verified up to eraseblock %u\n", i);
                cond_resched();
        }
-       printk(PRINT_PREF "verified %u eraseblocks\n", i);
+       pr_info("verified %u eraseblocks\n", i);
 
        err = erase_whole_device();
        if (err)
@@ -467,7 +467,7 @@ static int __init mtd_subpagetest_init(void)
 
        /* Write all eraseblocks */
        simple_srand(3);
-       printk(PRINT_PREF "writing whole device\n");
+       pr_info("writing whole device\n");
        for (i = 0; i < ebcnt; ++i) {
                if (bbt[i])
                        continue;
@@ -475,14 +475,14 @@ static int __init mtd_subpagetest_init(void)
                if (unlikely(err))
                        goto out;
                if (i % 256 == 0)
-                       printk(PRINT_PREF "written up to eraseblock %u\n", i);
+                       pr_info("written up to eraseblock %u\n", i);
                cond_resched();
        }
-       printk(PRINT_PREF "written %u eraseblocks\n", i);
+       pr_info("written %u eraseblocks\n", i);
 
        /* Check all eraseblocks */
        simple_srand(3);
-       printk(PRINT_PREF "verifying all eraseblocks\n");
+       pr_info("verifying all eraseblocks\n");
        for (i = 0; i < ebcnt; ++i) {
                if (bbt[i])
                        continue;
@@ -490,10 +490,10 @@ static int __init mtd_subpagetest_init(void)
                if (unlikely(err))
                        goto out;
                if (i % 256 == 0)
-                       printk(PRINT_PREF "verified up to eraseblock %u\n", i);
+                       pr_info("verified up to eraseblock %u\n", i);
                cond_resched();
        }
-       printk(PRINT_PREF "verified %u eraseblocks\n", i);
+       pr_info("verified %u eraseblocks\n", i);
 
        err = erase_whole_device();
        if (err)
@@ -503,7 +503,7 @@ static int __init mtd_subpagetest_init(void)
        if (err)
                goto out;
 
-       printk(PRINT_PREF "finished with %d errors\n", errcnt);
+       pr_info("finished with %d errors\n", errcnt);
 
 out:
        kfree(bbt);
@@ -511,7 +511,7 @@ out:
        kfree(writebuf);
        put_mtd_device(mtd);
        if (err)
-               printk(PRINT_PREF "error %d occurred\n", err);
+               pr_info("error %d occurred\n", err);
        printk(KERN_INFO "=================================================\n");
        return err;
 }
index b65861bc7b8e59397df4b8469774dcb4881705cf..98d2a820625fadb9213602f8ccf8883d475e0a6a 100644 (file)
@@ -23,6 +23,8 @@
  * damage caused by this program.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
@@ -31,7 +33,6 @@
 #include <linux/slab.h>
 #include <linux/sched.h>
 
-#define PRINT_PREF KERN_INFO "mtd_torturetest: "
 #define RETRIES 3
 
 static int eb = 8;
@@ -107,12 +108,12 @@ static inline int erase_eraseblock(int ebnum)
 
        err = mtd_erase(mtd, &ei);
        if (err) {
-               printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum);
+               pr_err("error %d while erasing EB %d\n", err, ebnum);
                return err;
        }
 
        if (ei.state == MTD_ERASE_FAILED) {
-               printk(PRINT_PREF "some erase error occurred at EB %d\n",
+               pr_err("some erase error occurred at EB %d\n",
                       ebnum);
                return -EIO;
        }
@@ -139,40 +140,40 @@ static inline int check_eraseblock(int ebnum, unsigned char *buf)
 retry:
        err = mtd_read(mtd, addr, len, &read, check_buf);
        if (mtd_is_bitflip(err))
-               printk(PRINT_PREF "single bit flip occurred at EB %d "
+               pr_err("single bit flip occurred at EB %d "
                       "MTD reported that it was fixed.\n", ebnum);
        else if (err) {
-               printk(PRINT_PREF "error %d while reading EB %d, "
+               pr_err("error %d while reading EB %d, "
                       "read %zd\n", err, ebnum, read);
                return err;
        }
 
        if (read != len) {
-               printk(PRINT_PREF "failed to read %zd bytes from EB %d, "
+               pr_err("failed to read %zd bytes from EB %d, "
                       "read only %zd, but no error reported\n",
                       len, ebnum, read);
                return -EIO;
        }
 
        if (memcmp(buf, check_buf, len)) {
-               printk(PRINT_PREF "read wrong data from EB %d\n", ebnum);
+               pr_err("read wrong data from EB %d\n", ebnum);
                report_corrupt(check_buf, buf);
 
                if (retries++ < RETRIES) {
                        /* Try read again */
                        yield();
-                       printk(PRINT_PREF "re-try reading data from EB %d\n",
+                       pr_info("re-try reading data from EB %d\n",
                               ebnum);
                        goto retry;
                } else {
-                       printk(PRINT_PREF "retried %d times, still errors, "
+                       pr_info("retried %d times, still errors, "
                               "give-up\n", RETRIES);
                        return -EINVAL;
                }
        }
 
        if (retries != 0)
-               printk(PRINT_PREF "only attempt number %d was OK (!!!)\n",
+               pr_info("only attempt number %d was OK (!!!)\n",
                       retries);
 
        return 0;
@@ -191,12 +192,12 @@ static inline int write_pattern(int ebnum, void *buf)
        }
        err = mtd_write(mtd, addr, len, &written, buf);
        if (err) {
-               printk(PRINT_PREF "error %d while writing EB %d, written %zd"
+               pr_err("error %d while writing EB %d, written %zd"
                      " bytes\n", err, ebnum, written);
                return err;
        }
        if (written != len) {
-               printk(PRINT_PREF "written only %zd bytes of %zd, but no error"
+               pr_info("written only %zd bytes of %zd, but no error"
                       " reported\n", written, len);
                return -EIO;
        }
@@ -211,64 +212,64 @@ static int __init tort_init(void)
 
        printk(KERN_INFO "\n");
        printk(KERN_INFO "=================================================\n");
-       printk(PRINT_PREF "Warning: this program is trying to wear out your "
+       pr_info("Warning: this program is trying to wear out your "
               "flash, stop it if this is not wanted.\n");
 
        if (dev < 0) {
-               printk(PRINT_PREF "Please specify a valid mtd-device via module paramter\n");
-               printk(KERN_CRIT "CAREFUL: This test wipes all data on the specified MTD device!\n");
+               pr_info("Please specify a valid mtd-device via module paramter\n");
+               pr_crit("CAREFUL: This test wipes all data on the specified MTD device!\n");
                return -EINVAL;
        }
 
-       printk(PRINT_PREF "MTD device: %d\n", dev);
-       printk(PRINT_PREF "torture %d eraseblocks (%d-%d) of mtd%d\n",
+       pr_info("MTD device: %d\n", dev);
+       pr_info("torture %d eraseblocks (%d-%d) of mtd%d\n",
               ebcnt, eb, eb + ebcnt - 1, dev);
        if (pgcnt)
-               printk(PRINT_PREF "torturing just %d pages per eraseblock\n",
+               pr_info("torturing just %d pages per eraseblock\n",
                        pgcnt);
-       printk(PRINT_PREF "write verify %s\n", check ? "enabled" : "disabled");
+       pr_info("write verify %s\n", check ? "enabled" : "disabled");
 
        mtd = get_mtd_device(NULL, dev);
        if (IS_ERR(mtd)) {
                err = PTR_ERR(mtd);
-               printk(PRINT_PREF "error: cannot get MTD device\n");
+               pr_err("error: cannot get MTD device\n");
                return err;
        }
 
        if (mtd->writesize == 1) {
-               printk(PRINT_PREF "not NAND flash, assume page size is 512 "
+               pr_info("not NAND flash, assume page size is 512 "
                       "bytes.\n");
                pgsize = 512;
        } else
                pgsize = mtd->writesize;
 
        if (pgcnt && (pgcnt > mtd->erasesize / pgsize || pgcnt < 0)) {
-               printk(PRINT_PREF "error: invalid pgcnt value %d\n", pgcnt);
+               pr_err("error: invalid pgcnt value %d\n", pgcnt);
                goto out_mtd;
        }
 
        err = -ENOMEM;
        patt_5A5 = kmalloc(mtd->erasesize, GFP_KERNEL);
        if (!patt_5A5) {
-               printk(PRINT_PREF "error: cannot allocate memory\n");
+               pr_err("error: cannot allocate memory\n");
                goto out_mtd;
        }
 
        patt_A5A = kmalloc(mtd->erasesize, GFP_KERNEL);
        if (!patt_A5A) {
-               printk(PRINT_PREF "error: cannot allocate memory\n");
+               pr_err("error: cannot allocate memory\n");
                goto out_patt_5A5;
        }
 
        patt_FF = kmalloc(mtd->erasesize, GFP_KERNEL);
        if (!patt_FF) {
-               printk(PRINT_PREF "error: cannot allocate memory\n");
+               pr_err("error: cannot allocate memory\n");
                goto out_patt_A5A;
        }
 
        check_buf = kmalloc(mtd->erasesize, GFP_KERNEL);
        if (!check_buf) {
-               printk(PRINT_PREF "error: cannot allocate memory\n");
+               pr_err("error: cannot allocate memory\n");
                goto out_patt_FF;
        }
 
@@ -295,13 +296,13 @@ static int __init tort_init(void)
                        err = mtd_block_isbad(mtd, (loff_t)i * mtd->erasesize);
 
                        if (err < 0) {
-                               printk(PRINT_PREF "block_isbad() returned %d "
+                               pr_info("block_isbad() returned %d "
                                       "for EB %d\n", err, i);
                                goto out;
                        }
 
                        if (err) {
-                               printk("EB %d is bad. Skip it.\n", i);
+                               pr_err("EB %d is bad. Skip it.\n", i);
                                bad_ebs[i - eb] = 1;
                        }
                }
@@ -329,7 +330,7 @@ static int __init tort_init(void)
                                        continue;
                                err = check_eraseblock(i, patt_FF);
                                if (err) {
-                                       printk(PRINT_PREF "verify failed"
+                                       pr_info("verify failed"
                                               " for 0xFF... pattern\n");
                                        goto out;
                                }
@@ -362,7 +363,7 @@ static int __init tort_init(void)
                                        patt = patt_A5A;
                                err = check_eraseblock(i, patt);
                                if (err) {
-                                       printk(PRINT_PREF "verify failed for %s"
+                                       pr_info("verify failed for %s"
                                               " pattern\n",
                                               ((eb + erase_cycles) & 1) ?
                                               "0x55AA55..." : "0xAA55AA...");
@@ -380,7 +381,7 @@ static int __init tort_init(void)
                        stop_timing();
                        ms = (finish.tv_sec - start.tv_sec) * 1000 +
                             (finish.tv_usec - start.tv_usec) / 1000;
-                       printk(PRINT_PREF "%08u erase cycles done, took %lu "
+                       pr_info("%08u erase cycles done, took %lu "
                               "milliseconds (%lu seconds)\n",
                               erase_cycles, ms, ms / 1000);
                        start_timing();
@@ -391,7 +392,7 @@ static int __init tort_init(void)
        }
 out:
 
-       printk(PRINT_PREF "finished after %u erase cycles\n",
+       pr_info("finished after %u erase cycles\n",
               erase_cycles);
        kfree(check_buf);
 out_patt_FF:
@@ -403,7 +404,7 @@ out_patt_5A5:
 out_mtd:
        put_mtd_device(mtd);
        if (err)
-               printk(PRINT_PREF "error %d occurred during torturing\n", err);
+               pr_info("error %d occurred during torturing\n", err);
        printk(KERN_INFO "=================================================\n");
        return err;
 }
@@ -441,9 +442,9 @@ static void report_corrupt(unsigned char *read, unsigned char *written)
                               &bits) >= 0)
                        pages++;
 
-       printk(PRINT_PREF "verify fails on %d pages, %d bytes/%d bits\n",
+       pr_info("verify fails on %d pages, %d bytes/%d bits\n",
               pages, bytes, bits);
-       printk(PRINT_PREF "The following is a list of all differences between"
+       pr_info("The following is a list of all differences between"
               " what was read from flash and what was expected\n");
 
        for (i = 0; i < check_len; i += pgsize) {
@@ -457,7 +458,7 @@ static void report_corrupt(unsigned char *read, unsigned char *written)
                printk("-------------------------------------------------------"
                       "----------------------------------\n");
 
-               printk(PRINT_PREF "Page %zd has %d bytes/%d bits failing verify,"
+               pr_info("Page %zd has %d bytes/%d bits failing verify,"
                       " starting at offset 0x%x\n",
                       (mtd->erasesize - check_len + i) / pgsize,
                       bytes, bits, first);
index db931916da08c8ddfd26b9068a94b7dddd1bfb46..40172d1ca605636ce4dc1103937245857fab376b 100644 (file)
@@ -2,13 +2,9 @@
 # Atmel device configuration
 #
 
-config HAVE_NET_MACB
-       bool
-
 config NET_CADENCE
        bool "Cadence devices"
        default y
-       depends on HAVE_NET_MACB || (ARM && ARCH_AT91RM9200)
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y.
          Make sure you know the name of your card. Read the Ethernet-HOWTO,
@@ -25,16 +21,14 @@ if NET_CADENCE
 
 config ARM_AT91_ETHER
        tristate "AT91RM9200 Ethernet support"
-       depends on ARM && ARCH_AT91RM9200
        select NET_CORE
-       select MII
+       select MACB
        ---help---
          If you wish to compile a kernel for the AT91RM9200 and enable
          ethernet support, then you should always answer Y to this.
 
 config MACB
        tristate "Cadence MACB/GEM support"
-       depends on HAVE_NET_MACB
        select PHYLIB
        ---help---
          The Cadence MACB ethernet interface is found on many Atmel AT32 and
index 4e980a7886fb58758fa84071b2494f56364da1f2..b92815aabc6594b8ef878820e356f2fb4d5f6c23 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
-#include <linux/mii.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/clk.h>
 #include <linux/gfp.h>
 #include <linux/phy.h>
+#include <linux/io.h>
 
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/mach-types.h>
-
-#include <mach/at91rm9200_emac.h>
-#include <asm/gpio.h>
-#include <mach/board.h>
-
-#include "at91_ether.h"
+#include "macb.h"
 
 #define DRV_NAME       "at91_ether"
 #define DRV_VERSION    "1.0"
 
-#define LINK_POLL_INTERVAL     (HZ)
-
-/* ..................................................................... */
-
-/*
- * Read from a EMAC register.
- */
-static inline unsigned long at91_emac_read(struct at91_private *lp, unsigned int reg)
-{
-       return __raw_readl(lp->emac_base + reg);
-}
-
-/*
- * Write to a EMAC register.
- */
-static inline void at91_emac_write(struct at91_private *lp, unsigned int reg, unsigned long value)
-{
-       __raw_writel(value, lp->emac_base + reg);
-}
-
-/* ........................... PHY INTERFACE ........................... */
-
-/*
- * Enable the MDIO bit in MAC control register
- * When not called from an interrupt-handler, access to the PHY must be
- *  protected by a spinlock.
- */
-static void enable_mdi(struct at91_private *lp)
-{
-       unsigned long ctl;
-
-       ctl = at91_emac_read(lp, AT91_EMAC_CTL);
-       at91_emac_write(lp, AT91_EMAC_CTL, ctl | AT91_EMAC_MPE);        /* enable management port */
-}
-
-/*
- * Disable the MDIO bit in the MAC control register
- */
-static void disable_mdi(struct at91_private *lp)
-{
-       unsigned long ctl;
-
-       ctl = at91_emac_read(lp, AT91_EMAC_CTL);
-       at91_emac_write(lp, AT91_EMAC_CTL, ctl & ~AT91_EMAC_MPE);       /* disable management port */
-}
-
-/*
- * Wait until the PHY operation is complete.
- */
-static inline void at91_phy_wait(struct at91_private *lp)
-{
-       unsigned long timeout = jiffies + 2;
-
-       while (!(at91_emac_read(lp, AT91_EMAC_SR) & AT91_EMAC_SR_IDLE)) {
-               if (time_after(jiffies, timeout)) {
-                       printk("at91_ether: MIO timeout\n");
-                       break;
-               }
-               cpu_relax();
-       }
-}
-
-/*
- * Write value to the a PHY register
- * Note: MDI interface is assumed to already have been enabled.
- */
-static void write_phy(struct at91_private *lp, unsigned char phy_addr, unsigned char address, unsigned int value)
-{
-       at91_emac_write(lp, AT91_EMAC_MAN, AT91_EMAC_MAN_802_3 | AT91_EMAC_RW_W
-               | ((phy_addr & 0x1f) << 23) | (address << 18) | (value & AT91_EMAC_DATA));
-
-       /* Wait until IDLE bit in Network Status register is cleared */
-       at91_phy_wait(lp);
-}
-
-/*
- * Read value stored in a PHY register.
- * Note: MDI interface is assumed to already have been enabled.
- */
-static void read_phy(struct at91_private *lp, unsigned char phy_addr, unsigned char address, unsigned int *value)
-{
-       at91_emac_write(lp, AT91_EMAC_MAN, AT91_EMAC_MAN_802_3 | AT91_EMAC_RW_R
-               | ((phy_addr & 0x1f) << 23) | (address << 18));
-
-       /* Wait until IDLE bit in Network Status register is cleared */
-       at91_phy_wait(lp);
-
-       *value = at91_emac_read(lp, AT91_EMAC_MAN) & AT91_EMAC_DATA;
-}
-
-/* ........................... PHY MANAGEMENT .......................... */
-
-/*
- * Access the PHY to determine the current link speed and mode, and update the
- * MAC accordingly.
- * If no link or auto-negotiation is busy, then no changes are made.
- */
-static void update_linkspeed(struct net_device *dev, int silent)
-{
-       struct at91_private *lp = netdev_priv(dev);
-       unsigned int bmsr, bmcr, lpa, mac_cfg;
-       unsigned int speed, duplex;
-
-       if (!mii_link_ok(&lp->mii)) {           /* no link */
-               netif_carrier_off(dev);
-               if (!silent)
-                       printk(KERN_INFO "%s: Link down.\n", dev->name);
-               return;
-       }
-
-       /* Link up, or auto-negotiation still in progress */
-       read_phy(lp, lp->phy_address, MII_BMSR, &bmsr);
-       read_phy(lp, lp->phy_address, MII_BMCR, &bmcr);
-       if (bmcr & BMCR_ANENABLE) {                             /* AutoNegotiation is enabled */
-               if (!(bmsr & BMSR_ANEGCOMPLETE))
-                       return;                 /* Do nothing - another interrupt generated when negotiation complete */
-
-               read_phy(lp, lp->phy_address, MII_LPA, &lpa);
-               if ((lpa & LPA_100FULL) || (lpa & LPA_100HALF)) speed = SPEED_100;
-               else speed = SPEED_10;
-               if ((lpa & LPA_100FULL) || (lpa & LPA_10FULL)) duplex = DUPLEX_FULL;
-               else duplex = DUPLEX_HALF;
-       } else {
-               speed = (bmcr & BMCR_SPEED100) ? SPEED_100 : SPEED_10;
-               duplex = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF;
-       }
-
-       /* Update the MAC */
-       mac_cfg = at91_emac_read(lp, AT91_EMAC_CFG) & ~(AT91_EMAC_SPD | AT91_EMAC_FD);
-       if (speed == SPEED_100) {
-               if (duplex == DUPLEX_FULL)              /* 100 Full Duplex */
-                       mac_cfg |= AT91_EMAC_SPD | AT91_EMAC_FD;
-               else                                    /* 100 Half Duplex */
-                       mac_cfg |= AT91_EMAC_SPD;
-       } else {
-               if (duplex == DUPLEX_FULL)              /* 10 Full Duplex */
-                       mac_cfg |= AT91_EMAC_FD;
-               else {}                                 /* 10 Half Duplex */
-       }
-       at91_emac_write(lp, AT91_EMAC_CFG, mac_cfg);
-
-       if (!silent)
-               printk(KERN_INFO "%s: Link now %i-%s\n", dev->name, speed, (duplex == DUPLEX_FULL) ? "FullDuplex" : "HalfDuplex");
-       netif_carrier_on(dev);
-}
-
-/*
- * Handle interrupts from the PHY
- */
-static irqreturn_t at91ether_phy_interrupt(int irq, void *dev_id)
-{
-       struct net_device *dev = (struct net_device *) dev_id;
-       struct at91_private *lp = netdev_priv(dev);
-       unsigned int phy;
-
-       /*
-        * This hander is triggered on both edges, but the PHY chips expect
-        * level-triggering.  We therefore have to check if the PHY actually has
-        * an IRQ pending.
-        */
-       enable_mdi(lp);
-       if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) {
-               read_phy(lp, lp->phy_address, MII_DSINTR_REG, &phy);    /* ack interrupt in Davicom PHY */
-               if (!(phy & (1 << 0)))
-                       goto done;
-       }
-       else if (lp->phy_type == MII_LXT971A_ID) {
-               read_phy(lp, lp->phy_address, MII_ISINTS_REG, &phy);    /* ack interrupt in Intel PHY */
-               if (!(phy & (1 << 2)))
-                       goto done;
-       }
-       else if (lp->phy_type == MII_BCM5221_ID) {
-               read_phy(lp, lp->phy_address, MII_BCMINTR_REG, &phy);   /* ack interrupt in Broadcom PHY */
-               if (!(phy & (1 << 0)))
-                       goto done;
-       }
-       else if (lp->phy_type == MII_KS8721_ID) {
-               read_phy(lp, lp->phy_address, MII_TPISTATUS, &phy);             /* ack interrupt in Micrel PHY */
-               if (!(phy & ((1 << 2) | 1)))
-                       goto done;
-       }
-       else if (lp->phy_type == MII_T78Q21x3_ID) {                                     /* ack interrupt in Teridian PHY */
-               read_phy(lp, lp->phy_address, MII_T78Q21INT_REG, &phy);
-               if (!(phy & ((1 << 2) | 1)))
-                       goto done;
-       }
-       else if (lp->phy_type == MII_DP83848_ID) {
-               read_phy(lp, lp->phy_address, MII_DPPHYSTS_REG, &phy);  /* ack interrupt in DP83848 PHY */
-               if (!(phy & (1 << 7)))
-                       goto done;
-       }
-
-       update_linkspeed(dev, 0);
-
-done:
-       disable_mdi(lp);
-
-       return IRQ_HANDLED;
-}
-
-/*
- * Initialize and enable the PHY interrupt for link-state changes
- */
-static void enable_phyirq(struct net_device *dev)
-{
-       struct at91_private *lp = netdev_priv(dev);
-       unsigned int dsintr, irq_number;
-       int status;
-
-       if (!gpio_is_valid(lp->board_data.phy_irq_pin)) {
-               /*
-                * PHY doesn't have an IRQ pin (RTL8201, DP83847, AC101L),
-                * or board does not have it connected.
-                */
-               mod_timer(&lp->check_timer, jiffies + LINK_POLL_INTERVAL);
-               return;
-       }
-
-       irq_number = gpio_to_irq(lp->board_data.phy_irq_pin);
-       status = request_irq(irq_number, at91ether_phy_interrupt, 0, dev->name, dev);
-       if (status) {
-               printk(KERN_ERR "at91_ether: PHY IRQ %d request failed - status %d!\n", irq_number, status);
-               return;
-       }
-
-       spin_lock_irq(&lp->lock);
-       enable_mdi(lp);
-
-       if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) {      /* for Davicom PHY */
-               read_phy(lp, lp->phy_address, MII_DSINTR_REG, &dsintr);
-               dsintr = dsintr & ~0xf00;               /* clear bits 8..11 */
-               write_phy(lp, lp->phy_address, MII_DSINTR_REG, dsintr);
-       }
-       else if (lp->phy_type == MII_LXT971A_ID) {      /* for Intel PHY */
-               read_phy(lp, lp->phy_address, MII_ISINTE_REG, &dsintr);
-               dsintr = dsintr | 0xf2;                 /* set bits 1, 4..7 */
-               write_phy(lp, lp->phy_address, MII_ISINTE_REG, dsintr);
-       }
-       else if (lp->phy_type == MII_BCM5221_ID) {      /* for Broadcom PHY */
-               dsintr = (1 << 15) | ( 1 << 14);
-               write_phy(lp, lp->phy_address, MII_BCMINTR_REG, dsintr);
-       }
-       else if (lp->phy_type == MII_KS8721_ID) {       /* for Micrel PHY */
-               dsintr = (1 << 10) | ( 1 << 8);
-               write_phy(lp, lp->phy_address, MII_TPISTATUS, dsintr);
-       }
-       else if (lp->phy_type == MII_T78Q21x3_ID) {     /* for Teridian PHY */
-               read_phy(lp, lp->phy_address, MII_T78Q21INT_REG, &dsintr);
-               dsintr = dsintr | 0x500;                /* set bits 8, 10 */
-               write_phy(lp, lp->phy_address, MII_T78Q21INT_REG, dsintr);
-       }
-       else if (lp->phy_type == MII_DP83848_ID) {      /* National Semiconductor DP83848 PHY */
-               read_phy(lp, lp->phy_address, MII_DPMISR_REG, &dsintr);
-               dsintr = dsintr | 0x3c;                 /* set bits 2..5 */
-               write_phy(lp, lp->phy_address, MII_DPMISR_REG, dsintr);
-               read_phy(lp, lp->phy_address, MII_DPMICR_REG, &dsintr);
-               dsintr = dsintr | 0x3;                  /* set bits 0,1 */
-               write_phy(lp, lp->phy_address, MII_DPMICR_REG, dsintr);
-       }
-
-       disable_mdi(lp);
-       spin_unlock_irq(&lp->lock);
-}
-
-/*
- * Disable the PHY interrupt
- */
-static void disable_phyirq(struct net_device *dev)
-{
-       struct at91_private *lp = netdev_priv(dev);
-       unsigned int dsintr;
-       unsigned int irq_number;
-
-       if (!gpio_is_valid(lp->board_data.phy_irq_pin)) {
-               del_timer_sync(&lp->check_timer);
-               return;
-       }
-
-       spin_lock_irq(&lp->lock);
-       enable_mdi(lp);
-
-       if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) {      /* for Davicom PHY */
-               read_phy(lp, lp->phy_address, MII_DSINTR_REG, &dsintr);
-               dsintr = dsintr | 0xf00;                        /* set bits 8..11 */
-               write_phy(lp, lp->phy_address, MII_DSINTR_REG, dsintr);
-       }
-       else if (lp->phy_type == MII_LXT971A_ID) {      /* for Intel PHY */
-               read_phy(lp, lp->phy_address, MII_ISINTE_REG, &dsintr);
-               dsintr = dsintr & ~0xf2;                        /* clear bits 1, 4..7 */
-               write_phy(lp, lp->phy_address, MII_ISINTE_REG, dsintr);
-       }
-       else if (lp->phy_type == MII_BCM5221_ID) {      /* for Broadcom PHY */
-               read_phy(lp, lp->phy_address, MII_BCMINTR_REG, &dsintr);
-               dsintr = ~(1 << 14);
-               write_phy(lp, lp->phy_address, MII_BCMINTR_REG, dsintr);
-       }
-       else if (lp->phy_type == MII_KS8721_ID) {       /* for Micrel PHY */
-               read_phy(lp, lp->phy_address, MII_TPISTATUS, &dsintr);
-               dsintr = ~((1 << 10) | (1 << 8));
-               write_phy(lp, lp->phy_address, MII_TPISTATUS, dsintr);
-       }
-       else if (lp->phy_type == MII_T78Q21x3_ID) {     /* for Teridian PHY */
-               read_phy(lp, lp->phy_address, MII_T78Q21INT_REG, &dsintr);
-               dsintr = dsintr & ~0x500;                       /* clear bits 8, 10 */
-               write_phy(lp, lp->phy_address, MII_T78Q21INT_REG, dsintr);
-       }
-       else if (lp->phy_type == MII_DP83848_ID) {      /* National Semiconductor DP83848 PHY */
-               read_phy(lp, lp->phy_address, MII_DPMICR_REG, &dsintr);
-               dsintr = dsintr & ~0x3;                         /* clear bits 0, 1 */
-               write_phy(lp, lp->phy_address, MII_DPMICR_REG, dsintr);
-               read_phy(lp, lp->phy_address, MII_DPMISR_REG, &dsintr);
-               dsintr = dsintr & ~0x3c;                        /* clear bits 2..5 */
-               write_phy(lp, lp->phy_address, MII_DPMISR_REG, dsintr);
-       }
-
-       disable_mdi(lp);
-       spin_unlock_irq(&lp->lock);
-
-       irq_number = gpio_to_irq(lp->board_data.phy_irq_pin);
-       free_irq(irq_number, dev);                      /* Free interrupt handler */
-}
-
-/*
- * Perform a software reset of the PHY.
- */
-#if 0
-static void reset_phy(struct net_device *dev)
-{
-       struct at91_private *lp = netdev_priv(dev);
-       unsigned int bmcr;
-
-       spin_lock_irq(&lp->lock);
-       enable_mdi(lp);
-
-       /* Perform PHY reset */
-       write_phy(lp, lp->phy_address, MII_BMCR, BMCR_RESET);
-
-       /* Wait until PHY reset is complete */
-       do {
-               read_phy(lp, lp->phy_address, MII_BMCR, &bmcr);
-       } while (!(bmcr & BMCR_RESET));
-
-       disable_mdi(lp);
-       spin_unlock_irq(&lp->lock);
-}
-#endif
-
-static void at91ether_check_link(unsigned long dev_id)
-{
-       struct net_device *dev = (struct net_device *) dev_id;
-       struct at91_private *lp = netdev_priv(dev);
-
-       enable_mdi(lp);
-       update_linkspeed(dev, 1);
-       disable_mdi(lp);
-
-       mod_timer(&lp->check_timer, jiffies + LINK_POLL_INTERVAL);
-}
-
-/*
- * Perform any PHY-specific initialization.
- */
-static void __init initialize_phy(struct at91_private *lp)
-{
-       unsigned int val;
-
-       spin_lock_irq(&lp->lock);
-       enable_mdi(lp);
-
-       if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) {
-               read_phy(lp, lp->phy_address, MII_DSCR_REG, &val);
-               if ((val & (1 << 10)) == 0)                     /* DSCR bit 10 is 0 -- fiber mode */
-                       lp->phy_media = PORT_FIBRE;
-       } else if (machine_is_csb337()) {
-               /* mix link activity status into LED2 link state */
-               write_phy(lp, lp->phy_address, MII_LEDCTRL_REG, 0x0d22);
-       } else if (machine_is_ecbat91())
-               write_phy(lp, lp->phy_address, MII_LEDCTRL_REG, 0x156A);
-
-       disable_mdi(lp);
-       spin_unlock_irq(&lp->lock);
-}
+/* 1518 rounded up */
+#define MAX_RBUFF_SZ   0x600
+/* max number of receive buffers */
+#define MAX_RX_DESCR   9
 
 /* ......................... ADDRESS MANAGEMENT ........................ */
 
@@ -445,9 +59,10 @@ static void __init initialize_phy(struct at91_private *lp)
 
 static short __init unpack_mac_address(struct net_device *dev, unsigned int hi, unsigned int lo)
 {
+       struct macb *lp = netdev_priv(dev);
        char addr[6];
 
-       if (machine_is_csb337()) {
+       if (lp->board_data.rev_eth_addr) {
                addr[5] = (lo & 0xff);                  /* The CSB337 bootloader stores the MAC the wrong-way around */
                addr[4] = (lo & 0xff00) >> 8;
                addr[3] = (lo & 0xff0000) >> 16;
@@ -476,19 +91,19 @@ static short __init unpack_mac_address(struct net_device *dev, unsigned int hi,
  */
 static void __init get_mac_address(struct net_device *dev)
 {
-       struct at91_private *lp = netdev_priv(dev);
+       struct macb *lp = netdev_priv(dev);
 
        /* Check Specific-Address 1 */
-       if (unpack_mac_address(dev, at91_emac_read(lp, AT91_EMAC_SA1H), at91_emac_read(lp, AT91_EMAC_SA1L)))
+       if (unpack_mac_address(dev, macb_readl(lp, SA1T), macb_readl(lp, SA1B)))
                return;
        /* Check Specific-Address 2 */
-       if (unpack_mac_address(dev, at91_emac_read(lp, AT91_EMAC_SA2H), at91_emac_read(lp, AT91_EMAC_SA2L)))
+       if (unpack_mac_address(dev, macb_readl(lp, SA2T), macb_readl(lp, SA2B)))
                return;
        /* Check Specific-Address 3 */
-       if (unpack_mac_address(dev, at91_emac_read(lp, AT91_EMAC_SA3H), at91_emac_read(lp, AT91_EMAC_SA3L)))
+       if (unpack_mac_address(dev, macb_readl(lp, SA3T), macb_readl(lp, SA3B)))
                return;
        /* Check Specific-Address 4 */
-       if (unpack_mac_address(dev, at91_emac_read(lp, AT91_EMAC_SA4H), at91_emac_read(lp, AT91_EMAC_SA4L)))
+       if (unpack_mac_address(dev, macb_readl(lp, SA4T), macb_readl(lp, SA4B)))
                return;
 
        printk(KERN_ERR "at91_ether: Your bootloader did not configure a MAC address.\n");
@@ -499,13 +114,14 @@ static void __init get_mac_address(struct net_device *dev)
  */
 static void update_mac_address(struct net_device *dev)
 {
-       struct at91_private *lp = netdev_priv(dev);
+       struct macb *lp = netdev_priv(dev);
 
-       at91_emac_write(lp, AT91_EMAC_SA1L, (dev->dev_addr[3] << 24) | (dev->dev_addr[2] << 16) | (dev->dev_addr[1] << 8) | (dev->dev_addr[0]));
-       at91_emac_write(lp, AT91_EMAC_SA1H, (dev->dev_addr[5] << 8) | (dev->dev_addr[4]));
+       macb_writel(lp, SA1B, (dev->dev_addr[3] << 24) | (dev->dev_addr[2] << 16)
+                                       | (dev->dev_addr[1] << 8) | (dev->dev_addr[0]));
+       macb_writel(lp, SA1T, (dev->dev_addr[5] << 8) | (dev->dev_addr[4]));
 
-       at91_emac_write(lp, AT91_EMAC_SA2L, 0);
-       at91_emac_write(lp, AT91_EMAC_SA2H, 0);
+       macb_writel(lp, SA2B, 0);
+       macb_writel(lp, SA2T, 0);
 }
 
 /*
@@ -527,246 +143,60 @@ static int set_mac_address(struct net_device *dev, void* addr)
        return 0;
 }
 
-static int inline hash_bit_value(int bitnr, __u8 *addr)
-{
-       if (addr[bitnr / 8] & (1 << (bitnr % 8)))
-               return 1;
-       return 0;
-}
-
-/*
- * The hash address register is 64 bits long and takes up two locations in the memory map.
- * The least significant bits are stored in EMAC_HSL and the most significant
- * bits in EMAC_HSH.
- *
- * The unicast hash enable and the multicast hash enable bits in the network configuration
- *  register enable the reception of hash matched frames. The destination address is
- *  reduced to a 6 bit index into the 64 bit hash register using the following hash function.
- * The hash function is an exclusive or of every sixth bit of the destination address.
- *   hash_index[5] = da[5] ^ da[11] ^ da[17] ^ da[23] ^ da[29] ^ da[35] ^ da[41] ^ da[47]
- *   hash_index[4] = da[4] ^ da[10] ^ da[16] ^ da[22] ^ da[28] ^ da[34] ^ da[40] ^ da[46]
- *   hash_index[3] = da[3] ^ da[09] ^ da[15] ^ da[21] ^ da[27] ^ da[33] ^ da[39] ^ da[45]
- *   hash_index[2] = da[2] ^ da[08] ^ da[14] ^ da[20] ^ da[26] ^ da[32] ^ da[38] ^ da[44]
- *   hash_index[1] = da[1] ^ da[07] ^ da[13] ^ da[19] ^ da[25] ^ da[31] ^ da[37] ^ da[43]
- *   hash_index[0] = da[0] ^ da[06] ^ da[12] ^ da[18] ^ da[24] ^ da[30] ^ da[36] ^ da[42]
- * da[0] represents the least significant bit of the first byte received, that is, the multicast/
- *  unicast indicator, and da[47] represents the most significant bit of the last byte
- *  received.
- * If the hash index points to a bit that is set in the hash register then the frame will be
- *  matched according to whether the frame is multicast or unicast.
- * A multicast match will be signalled if the multicast hash enable bit is set, da[0] is 1 and
- *  the hash index points to a bit set in the hash register.
- * A unicast match will be signalled if the unicast hash enable bit is set, da[0] is 0 and the
- *  hash index points to a bit set in the hash register.
- * To receive all multicast frames, the hash register should be set with all ones and the
- *  multicast hash enable bit should be set in the network configuration register.
- */
-
-/*
- * Return the hash index value for the specified address.
- */
-static int hash_get_index(__u8 *addr)
-{
-       int i, j, bitval;
-       int hash_index = 0;
-
-       for (j = 0; j < 6; j++) {
-               for (i = 0, bitval = 0; i < 8; i++)
-                       bitval ^= hash_bit_value(i*6 + j, addr);
-
-               hash_index |= (bitval << j);
-       }
-
-       return hash_index;
-}
+/* ................................ MAC ................................ */
 
 /*
- * Add multicast addresses to the internal multicast-hash table.
+ * Initialize and start the Receiver and Transmit subsystems
  */
-static void at91ether_sethashtable(struct net_device *dev)
+static int at91ether_start(struct net_device *dev)
 {
-       struct at91_private *lp = netdev_priv(dev);
-       struct netdev_hw_addr *ha;
-       unsigned long mc_filter[2];
-       unsigned int bitnr;
-
-       mc_filter[0] = mc_filter[1] = 0;
-
-       netdev_for_each_mc_addr(ha, dev) {
-               bitnr = hash_get_index(ha->addr);
-               mc_filter[bitnr >> 5] |= 1 << (bitnr & 31);
-       }
-
-       at91_emac_write(lp, AT91_EMAC_HSL, mc_filter[0]);
-       at91_emac_write(lp, AT91_EMAC_HSH, mc_filter[1]);
-}
+       struct macb *lp = netdev_priv(dev);
+       unsigned long ctl;
+       dma_addr_t addr;
+       int i;
 
-/*
- * Enable/Disable promiscuous and multicast modes.
- */
-static void at91ether_set_multicast_list(struct net_device *dev)
-{
-       struct at91_private *lp = netdev_priv(dev);
-       unsigned long cfg;
-
-       cfg = at91_emac_read(lp, AT91_EMAC_CFG);
-
-       if (dev->flags & IFF_PROMISC)                   /* Enable promiscuous mode */
-               cfg |= AT91_EMAC_CAF;
-       else if (dev->flags & (~IFF_PROMISC))           /* Disable promiscuous mode */
-               cfg &= ~AT91_EMAC_CAF;
-
-       if (dev->flags & IFF_ALLMULTI) {                /* Enable all multicast mode */
-               at91_emac_write(lp, AT91_EMAC_HSH, -1);
-               at91_emac_write(lp, AT91_EMAC_HSL, -1);
-               cfg |= AT91_EMAC_MTI;
-       } else if (!netdev_mc_empty(dev)) { /* Enable specific multicasts */
-               at91ether_sethashtable(dev);
-               cfg |= AT91_EMAC_MTI;
-       } else if (dev->flags & (~IFF_ALLMULTI)) {      /* Disable all multicast mode */
-               at91_emac_write(lp, AT91_EMAC_HSH, 0);
-               at91_emac_write(lp, AT91_EMAC_HSL, 0);
-               cfg &= ~AT91_EMAC_MTI;
+       lp->rx_ring = dma_alloc_coherent(&lp->pdev->dev,
+                                       MAX_RX_DESCR * sizeof(struct dma_desc),
+                                       &lp->rx_ring_dma, GFP_KERNEL);
+       if (!lp->rx_ring) {
+               netdev_err(lp->dev, "unable to alloc rx ring DMA buffer\n");
+               return -ENOMEM;
        }
 
-       at91_emac_write(lp, AT91_EMAC_CFG, cfg);
-}
-
-/* ......................... ETHTOOL SUPPORT ........................... */
-
-static int mdio_read(struct net_device *dev, int phy_id, int location)
-{
-       struct at91_private *lp = netdev_priv(dev);
-       unsigned int value;
-
-       read_phy(lp, phy_id, location, &value);
-       return value;
-}
-
-static void mdio_write(struct net_device *dev, int phy_id, int location, int value)
-{
-       struct at91_private *lp = netdev_priv(dev);
+       lp->rx_buffers = dma_alloc_coherent(&lp->pdev->dev,
+                                       MAX_RX_DESCR * MAX_RBUFF_SZ,
+                                       &lp->rx_buffers_dma, GFP_KERNEL);
+       if (!lp->rx_buffers) {
+               netdev_err(lp->dev, "unable to alloc rx data DMA buffer\n");
 
-       write_phy(lp, phy_id, location, value);
-}
-
-static int at91ether_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-       struct at91_private *lp = netdev_priv(dev);
-       int ret;
-
-       spin_lock_irq(&lp->lock);
-       enable_mdi(lp);
-
-       ret = mii_ethtool_gset(&lp->mii, cmd);
-
-       disable_mdi(lp);
-       spin_unlock_irq(&lp->lock);
-
-       if (lp->phy_media == PORT_FIBRE) {              /* override media type since mii.c doesn't know */
-               cmd->supported = SUPPORTED_FIBRE;
-               cmd->port = PORT_FIBRE;
+               dma_free_coherent(&lp->pdev->dev,
+                                       MAX_RX_DESCR * sizeof(struct dma_desc),
+                                       lp->rx_ring, lp->rx_ring_dma);
+               lp->rx_ring = NULL;
+               return -ENOMEM;
        }
 
-       return ret;
-}
-
-static int at91ether_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-       struct at91_private *lp = netdev_priv(dev);
-       int ret;
-
-       spin_lock_irq(&lp->lock);
-       enable_mdi(lp);
-
-       ret = mii_ethtool_sset(&lp->mii, cmd);
-
-       disable_mdi(lp);
-       spin_unlock_irq(&lp->lock);
-
-       return ret;
-}
-
-static int at91ether_nwayreset(struct net_device *dev)
-{
-       struct at91_private *lp = netdev_priv(dev);
-       int ret;
-
-       spin_lock_irq(&lp->lock);
-       enable_mdi(lp);
-
-       ret = mii_nway_restart(&lp->mii);
-
-       disable_mdi(lp);
-       spin_unlock_irq(&lp->lock);
-
-       return ret;
-}
-
-static void at91ether_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
-{
-       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
-       strlcpy(info->version, DRV_VERSION, sizeof(info->version));
-       strlcpy(info->bus_info, dev_name(dev->dev.parent), sizeof(info->bus_info));
-}
-
-static const struct ethtool_ops at91ether_ethtool_ops = {
-       .get_settings   = at91ether_get_settings,
-       .set_settings   = at91ether_set_settings,
-       .get_drvinfo    = at91ether_get_drvinfo,
-       .nway_reset     = at91ether_nwayreset,
-       .get_link       = ethtool_op_get_link,
-};
-
-static int at91ether_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-{
-       struct at91_private *lp = netdev_priv(dev);
-       int res;
-
-       if (!netif_running(dev))
-               return -EINVAL;
-
-       spin_lock_irq(&lp->lock);
-       enable_mdi(lp);
-       res = generic_mii_ioctl(&lp->mii, if_mii(rq), cmd, NULL);
-       disable_mdi(lp);
-       spin_unlock_irq(&lp->lock);
-
-       return res;
-}
-
-/* ................................ MAC ................................ */
-
-/*
- * Initialize and start the Receiver and Transmit subsystems
- */
-static void at91ether_start(struct net_device *dev)
-{
-       struct at91_private *lp = netdev_priv(dev);
-       struct recv_desc_bufs *dlist, *dlist_phys;
-       int i;
-       unsigned long ctl;
-
-       dlist = lp->dlist;
-       dlist_phys = lp->dlist_phys;
-
+       addr = lp->rx_buffers_dma;
        for (i = 0; i < MAX_RX_DESCR; i++) {
-               dlist->descriptors[i].addr = (unsigned int) &dlist_phys->recv_buf[i][0];
-               dlist->descriptors[i].size = 0;
+               lp->rx_ring[i].addr = addr;
+               lp->rx_ring[i].ctrl = 0;
+               addr += MAX_RBUFF_SZ;
        }
 
        /* Set the Wrap bit on the last descriptor */
-       dlist->descriptors[i-1].addr |= EMAC_DESC_WRAP;
+       lp->rx_ring[MAX_RX_DESCR - 1].addr |= MACB_BIT(RX_WRAP);
 
        /* Reset buffer index */
-       lp->rxBuffIndex = 0;
+       lp->rx_tail = 0;
 
        /* Program address of descriptor list in Rx Buffer Queue register */
-       at91_emac_write(lp, AT91_EMAC_RBQP, (unsigned long) dlist_phys);
+       macb_writel(lp, RBQP, lp->rx_ring_dma);
 
        /* Enable Receive and Transmit */
-       ctl = at91_emac_read(lp, AT91_EMAC_CTL);
-       at91_emac_write(lp, AT91_EMAC_CTL, ctl | AT91_EMAC_RE | AT91_EMAC_TE);
+       ctl = macb_readl(lp, NCR);
+       macb_writel(lp, NCR, ctl | MACB_BIT(RE) | MACB_BIT(TE));
+
+       return 0;
 }
 
 /*
@@ -774,38 +204,34 @@ static void at91ether_start(struct net_device *dev)
  */
 static int at91ether_open(struct net_device *dev)
 {
-       struct at91_private *lp = netdev_priv(dev);
+       struct macb *lp = netdev_priv(dev);
        unsigned long ctl;
+       int ret;
 
        if (!is_valid_ether_addr(dev->dev_addr))
                return -EADDRNOTAVAIL;
 
-       clk_enable(lp->ether_clk);              /* Re-enable Peripheral clock */
-
        /* Clear internal statistics */
-       ctl = at91_emac_read(lp, AT91_EMAC_CTL);
-       at91_emac_write(lp, AT91_EMAC_CTL, ctl | AT91_EMAC_CSR);
+       ctl = macb_readl(lp, NCR);
+       macb_writel(lp, NCR, ctl | MACB_BIT(CLRSTAT));
 
        /* Update the MAC address (incase user has changed it) */
        update_mac_address(dev);
 
-       /* Enable PHY interrupt */
-       enable_phyirq(dev);
+       ret = at91ether_start(dev);
+       if (ret)
+               return ret;
 
        /* Enable MAC interrupts */
-       at91_emac_write(lp, AT91_EMAC_IER, AT91_EMAC_RCOM | AT91_EMAC_RBNA
-                               | AT91_EMAC_TUND | AT91_EMAC_RTRY | AT91_EMAC_TCOM
-                               | AT91_EMAC_ROVR | AT91_EMAC_ABT);
-
-       /* Determine current link speed */
-       spin_lock_irq(&lp->lock);
-       enable_mdi(lp);
-       update_linkspeed(dev, 0);
-       disable_mdi(lp);
-       spin_unlock_irq(&lp->lock);
-
-       at91ether_start(dev);
+       macb_writel(lp, IER, MACB_BIT(RCOMP) | MACB_BIT(RXUBR)
+                               | MACB_BIT(ISR_TUND) | MACB_BIT(ISR_RLE) | MACB_BIT(TCOMP)
+                               | MACB_BIT(ISR_ROVR) | MACB_BIT(HRESP));
+
+       /* schedule a link state check */
+       phy_start(lp->phy_dev);
+
        netif_start_queue(dev);
+
        return 0;
 }
 
@@ -814,24 +240,30 @@ static int at91ether_open(struct net_device *dev)
  */
 static int at91ether_close(struct net_device *dev)
 {
-       struct at91_private *lp = netdev_priv(dev);
+       struct macb *lp = netdev_priv(dev);
        unsigned long ctl;
 
        /* Disable Receiver and Transmitter */
-       ctl = at91_emac_read(lp, AT91_EMAC_CTL);
-       at91_emac_write(lp, AT91_EMAC_CTL, ctl & ~(AT91_EMAC_TE | AT91_EMAC_RE));
-
-       /* Disable PHY interrupt */
-       disable_phyirq(dev);
+       ctl = macb_readl(lp, NCR);
+       macb_writel(lp, NCR, ctl & ~(MACB_BIT(TE) | MACB_BIT(RE)));
 
        /* Disable MAC interrupts */
-       at91_emac_write(lp, AT91_EMAC_IDR, AT91_EMAC_RCOM | AT91_EMAC_RBNA
-                               | AT91_EMAC_TUND | AT91_EMAC_RTRY | AT91_EMAC_TCOM
-                               | AT91_EMAC_ROVR | AT91_EMAC_ABT);
+       macb_writel(lp, IDR, MACB_BIT(RCOMP) | MACB_BIT(RXUBR)
+                               | MACB_BIT(ISR_TUND) | MACB_BIT(ISR_RLE)
+                               | MACB_BIT(TCOMP) | MACB_BIT(ISR_ROVR)
+                               | MACB_BIT(HRESP));
 
        netif_stop_queue(dev);
 
-       clk_disable(lp->ether_clk);             /* Disable Peripheral clock */
+       dma_free_coherent(&lp->pdev->dev,
+                               MAX_RX_DESCR * sizeof(struct dma_desc),
+                               lp->rx_ring, lp->rx_ring_dma);
+       lp->rx_ring = NULL;
+
+       dma_free_coherent(&lp->pdev->dev,
+                               MAX_RX_DESCR * MAX_RBUFF_SZ,
+                               lp->rx_buffers, lp->rx_buffers_dma);
+       lp->rx_buffers = NULL;
 
        return 0;
 }
@@ -841,9 +273,9 @@ static int at91ether_close(struct net_device *dev)
  */
 static int at91ether_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-       struct at91_private *lp = netdev_priv(dev);
+       struct macb *lp = netdev_priv(dev);
 
-       if (at91_emac_read(lp, AT91_EMAC_TSR) & AT91_EMAC_TSR_BNQ) {
+       if (macb_readl(lp, TSR) & MACB_BIT(RM9200_BNQ)) {
                netif_stop_queue(dev);
 
                /* Store packet information (to free when Tx completed) */
@@ -853,9 +285,9 @@ static int at91ether_start_xmit(struct sk_buff *skb, struct net_device *dev)
                dev->stats.tx_bytes += skb->len;
 
                /* Set address of the data in the Transmit Address register */
-               at91_emac_write(lp, AT91_EMAC_TAR, lp->skb_physaddr);
+               macb_writel(lp, TAR, lp->skb_physaddr);
                /* Set length of the packet in the Transmit Control register */
-               at91_emac_write(lp, AT91_EMAC_TCR, skb->len);
+               macb_writel(lp, TCR, skb->len);
 
        } else {
                printk(KERN_ERR "at91_ether.c: at91ether_start_xmit() called, but device is busy!\n");
@@ -872,32 +304,32 @@ static int at91ether_start_xmit(struct sk_buff *skb, struct net_device *dev)
  */
 static struct net_device_stats *at91ether_stats(struct net_device *dev)
 {
-       struct at91_private *lp = netdev_priv(dev);
+       struct macb *lp = netdev_priv(dev);
        int ale, lenerr, seqe, lcol, ecol;
 
        if (netif_running(dev)) {
-               dev->stats.rx_packets += at91_emac_read(lp, AT91_EMAC_OK);      /* Good frames received */
-               ale = at91_emac_read(lp, AT91_EMAC_ALE);
+               dev->stats.rx_packets += macb_readl(lp, FRO);   /* Good frames received */
+               ale = macb_readl(lp, ALE);
                dev->stats.rx_frame_errors += ale;                              /* Alignment errors */
-               lenerr = at91_emac_read(lp, AT91_EMAC_ELR) + at91_emac_read(lp, AT91_EMAC_USF);
+               lenerr = macb_readl(lp, ELE) + macb_readl(lp, USF);
                dev->stats.rx_length_errors += lenerr;                          /* Excessive Length or Undersize Frame error */
-               seqe = at91_emac_read(lp, AT91_EMAC_SEQE);
+               seqe = macb_readl(lp, FCSE);
                dev->stats.rx_crc_errors += seqe;                               /* CRC error */
-               dev->stats.rx_fifo_errors += at91_emac_read(lp, AT91_EMAC_DRFC);/* Receive buffer not available */
+               dev->stats.rx_fifo_errors += macb_readl(lp, RRE);/* Receive buffer not available */
                dev->stats.rx_errors += (ale + lenerr + seqe
-                       + at91_emac_read(lp, AT91_EMAC_CDE) + at91_emac_read(lp, AT91_EMAC_RJB));
+                       + macb_readl(lp, RSE) + macb_readl(lp, RJA));
 
-               dev->stats.tx_packets += at91_emac_read(lp, AT91_EMAC_FRA);     /* Frames successfully transmitted */
-               dev->stats.tx_fifo_errors += at91_emac_read(lp, AT91_EMAC_TUE); /* Transmit FIFO underruns */
-               dev->stats.tx_carrier_errors += at91_emac_read(lp, AT91_EMAC_CSE);      /* Carrier Sense errors */
-               dev->stats.tx_heartbeat_errors += at91_emac_read(lp, AT91_EMAC_SQEE);/* Heartbeat error */
+               dev->stats.tx_packets += macb_readl(lp, FTO);   /* Frames successfully transmitted */
+               dev->stats.tx_fifo_errors += macb_readl(lp, TUND);      /* Transmit FIFO underruns */
+               dev->stats.tx_carrier_errors += macb_readl(lp, CSE);    /* Carrier Sense errors */
+               dev->stats.tx_heartbeat_errors += macb_readl(lp, STE);/* Heartbeat error */
 
-               lcol = at91_emac_read(lp, AT91_EMAC_LCOL);
-               ecol = at91_emac_read(lp, AT91_EMAC_ECOL);
+               lcol = macb_readl(lp, LCOL);
+               ecol = macb_readl(lp, EXCOL);
                dev->stats.tx_window_errors += lcol;                    /* Late collisions */
                dev->stats.tx_aborted_errors += ecol;                   /* 16 collisions */
 
-               dev->stats.collisions += (at91_emac_read(lp, AT91_EMAC_SCOL) + at91_emac_read(lp, AT91_EMAC_MCOL) + lcol + ecol);
+               dev->stats.collisions += (macb_readl(lp, SCF) + macb_readl(lp, MCF) + lcol + ecol);
        }
        return &dev->stats;
 }
@@ -908,38 +340,38 @@ static struct net_device_stats *at91ether_stats(struct net_device *dev)
  */
 static void at91ether_rx(struct net_device *dev)
 {
-       struct at91_private *lp = netdev_priv(dev);
-       struct recv_desc_bufs *dlist;
+       struct macb *lp = netdev_priv(dev);
        unsigned char *p_recv;
        struct sk_buff *skb;
        unsigned int pktlen;
 
-       dlist = lp->dlist;
-       while (dlist->descriptors[lp->rxBuffIndex].addr & EMAC_DESC_DONE) {
-               p_recv = dlist->recv_buf[lp->rxBuffIndex];
-               pktlen = dlist->descriptors[lp->rxBuffIndex].size & 0x7ff;      /* Length of frame including FCS */
+       while (lp->rx_ring[lp->rx_tail].addr & MACB_BIT(RX_USED)) {
+               p_recv = lp->rx_buffers + lp->rx_tail * MAX_RBUFF_SZ;
+               pktlen = MACB_BF(RX_FRMLEN, lp->rx_ring[lp->rx_tail].ctrl);
                skb = netdev_alloc_skb(dev, pktlen + 2);
-               if (skb != NULL) {
+               if (skb) {
                        skb_reserve(skb, 2);
                        memcpy(skb_put(skb, pktlen), p_recv, pktlen);
 
                        skb->protocol = eth_type_trans(skb, dev);
                        dev->stats.rx_bytes += pktlen;
                        netif_rx(skb);
-               }
-               else {
+               } else {
                        dev->stats.rx_dropped += 1;
-                       printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name);
+                       netdev_notice(dev, "Memory squeeze, dropping packet.\n");
                }
 
-               if (dlist->descriptors[lp->rxBuffIndex].size & EMAC_MULTICAST)
+               if (lp->rx_ring[lp->rx_tail].ctrl & MACB_BIT(RX_MHASH_MATCH))
                        dev->stats.multicast++;
 
-               dlist->descriptors[lp->rxBuffIndex].addr &= ~EMAC_DESC_DONE;    /* reset ownership bit */
-               if (lp->rxBuffIndex == MAX_RX_DESCR-1)                          /* wrap after last buffer */
-                       lp->rxBuffIndex = 0;
+               /* reset ownership bit */
+               lp->rx_ring[lp->rx_tail].addr &= ~MACB_BIT(RX_USED);
+
+               /* wrap after last buffer */
+               if (lp->rx_tail == MAX_RX_DESCR - 1)
+                       lp->rx_tail = 0;
                else
-                       lp->rxBuffIndex++;
+                       lp->rx_tail++;
        }
 }
 
@@ -949,19 +381,19 @@ static void at91ether_rx(struct net_device *dev)
 static irqreturn_t at91ether_interrupt(int irq, void *dev_id)
 {
        struct net_device *dev = (struct net_device *) dev_id;
-       struct at91_private *lp = netdev_priv(dev);
+       struct macb *lp = netdev_priv(dev);
        unsigned long intstatus, ctl;
 
        /* MAC Interrupt Status register indicates what interrupts are pending.
           It is automatically cleared once read. */
-       intstatus = at91_emac_read(lp, AT91_EMAC_ISR);
+       intstatus = macb_readl(lp, ISR);
 
-       if (intstatus & AT91_EMAC_RCOM)         /* Receive complete */
+       if (intstatus & MACB_BIT(RCOMP))                /* Receive complete */
                at91ether_rx(dev);
 
-       if (intstatus & AT91_EMAC_TCOM) {       /* Transmit complete */
+       if (intstatus & MACB_BIT(TCOMP)) {      /* Transmit complete */
                /* The TCOM bit is set even if the transmission failed. */
-               if (intstatus & (AT91_EMAC_TUND | AT91_EMAC_RTRY))
+               if (intstatus & (MACB_BIT(ISR_TUND) | MACB_BIT(ISR_RLE)))
                        dev->stats.tx_errors += 1;
 
                if (lp->skb) {
@@ -973,13 +405,13 @@ static irqreturn_t at91ether_interrupt(int irq, void *dev_id)
        }
 
        /* Work-around for Errata #11 */
-       if (intstatus & AT91_EMAC_RBNA) {
-               ctl = at91_emac_read(lp, AT91_EMAC_CTL);
-               at91_emac_write(lp, AT91_EMAC_CTL, ctl & ~AT91_EMAC_RE);
-               at91_emac_write(lp, AT91_EMAC_CTL, ctl | AT91_EMAC_RE);
+       if (intstatus & MACB_BIT(RXUBR)) {
+               ctl = macb_readl(lp, NCR);
+               macb_writel(lp, NCR, ctl & ~MACB_BIT(RE));
+               macb_writel(lp, NCR, ctl | MACB_BIT(RE));
        }
 
-       if (intstatus & AT91_EMAC_ROVR)
+       if (intstatus & MACB_BIT(ISR_ROVR))
                printk("%s: ROVR error\n", dev->name);
 
        return IRQ_HANDLED;
@@ -1001,9 +433,9 @@ static const struct net_device_ops at91ether_netdev_ops = {
        .ndo_stop               = at91ether_close,
        .ndo_start_xmit         = at91ether_start_xmit,
        .ndo_get_stats          = at91ether_stats,
-       .ndo_set_rx_mode        = at91ether_set_multicast_list,
+       .ndo_set_rx_mode        = macb_set_rx_mode,
        .ndo_set_mac_address    = set_mac_address,
-       .ndo_do_ioctl           = at91ether_ioctl,
+       .ndo_do_ioctl           = macb_ioctl,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_change_mtu         = eth_change_mtu,
 #ifdef CONFIG_NET_POLL_CONTROLLER
@@ -1011,48 +443,6 @@ static const struct net_device_ops at91ether_netdev_ops = {
 #endif
 };
 
-/*
- * Detect the PHY type, and its address.
- */
-static int __init at91ether_phy_detect(struct at91_private *lp)
-{
-       unsigned int phyid1, phyid2;
-       unsigned long phy_id;
-       unsigned short phy_address = 0;
-
-       while (phy_address < PHY_MAX_ADDR) {
-               /* Read the PHY ID registers */
-               enable_mdi(lp);
-               read_phy(lp, phy_address, MII_PHYSID1, &phyid1);
-               read_phy(lp, phy_address, MII_PHYSID2, &phyid2);
-               disable_mdi(lp);
-
-               phy_id = (phyid1 << 16) | (phyid2 & 0xfff0);
-               switch (phy_id) {
-                       case MII_DM9161_ID:             /* Davicom 9161: PHY_ID1 = 0x181, PHY_ID2 = B881 */
-                       case MII_DM9161A_ID:            /* Davicom 9161A: PHY_ID1 = 0x181, PHY_ID2 = B8A0 */
-                       case MII_LXT971A_ID:            /* Intel LXT971A: PHY_ID1 = 0x13, PHY_ID2 = 78E0 */
-                       case MII_RTL8201_ID:            /* Realtek RTL8201: PHY_ID1 = 0, PHY_ID2 = 0x8201 */
-                       case MII_BCM5221_ID:            /* Broadcom BCM5221: PHY_ID1 = 0x40, PHY_ID2 = 0x61e0 */
-                       case MII_DP83847_ID:            /* National Semiconductor DP83847:  */
-                       case MII_DP83848_ID:            /* National Semiconductor DP83848:  */
-                       case MII_AC101L_ID:             /* Altima AC101L: PHY_ID1 = 0x22, PHY_ID2 = 0x5520 */
-                       case MII_KS8721_ID:             /* Micrel KS8721: PHY_ID1 = 0x22, PHY_ID2 = 0x1610 */
-                       case MII_T78Q21x3_ID:           /* Teridian 78Q21x3: PHY_ID1 = 0x0E, PHY_ID2 = 7237 */
-                       case MII_LAN83C185_ID:          /* SMSC LAN83C185: PHY_ID1 = 0x0007, PHY_ID2 = 0xC0A1 */
-                               /* store detected values */
-                               lp->phy_type = phy_id;          /* Type of PHY connected */
-                               lp->phy_address = phy_address;  /* MDI address of PHY */
-                               return 1;
-               }
-
-               phy_address++;
-       }
-
-       return 0;               /* not detected */
-}
-
-
 /*
  * Detect MAC & PHY and perform ethernet interface initialization
  */
@@ -1061,147 +451,91 @@ static int __init at91ether_probe(struct platform_device *pdev)
        struct macb_platform_data *board_data = pdev->dev.platform_data;
        struct resource *regs;
        struct net_device *dev;
-       struct at91_private *lp;
+       struct phy_device *phydev;
+       struct macb *lp;
        int res;
 
        regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!regs)
                return -ENOENT;
 
-       dev = alloc_etherdev(sizeof(struct at91_private));
+       dev = alloc_etherdev(sizeof(struct macb));
        if (!dev)
                return -ENOMEM;
 
        lp = netdev_priv(dev);
+       lp->pdev = pdev;
+       lp->dev = dev;
        lp->board_data = *board_data;
        spin_lock_init(&lp->lock);
 
        dev->base_addr = regs->start;           /* physical base address */
-       lp->emac_base = ioremap(regs->start, regs->end - regs->start + 1);
-       if (!lp->emac_base) {
+       lp->regs = devm_ioremap(&pdev->dev, regs->start, resource_size(regs));
+       if (!lp->regs) {
                res = -ENOMEM;
                goto err_free_dev;
        }
 
        /* Clock */
-       lp->ether_clk = clk_get(&pdev->dev, "ether_clk");
-       if (IS_ERR(lp->ether_clk)) {
-               res = PTR_ERR(lp->ether_clk);
-               goto err_ioumap;
+       lp->pclk = devm_clk_get(&pdev->dev, "ether_clk");
+       if (IS_ERR(lp->pclk)) {
+               res = PTR_ERR(lp->pclk);
+               goto err_free_dev;
        }
-       clk_enable(lp->ether_clk);
+       clk_enable(lp->pclk);
 
        /* Install the interrupt handler */
        dev->irq = platform_get_irq(pdev, 0);
-       if (request_irq(dev->irq, at91ether_interrupt, 0, dev->name, dev)) {
-               res = -EBUSY;
+       res = devm_request_irq(&pdev->dev, dev->irq, at91ether_interrupt, 0, dev->name, dev);
+       if (res)
                goto err_disable_clock;
-       }
-
-       /* Allocate memory for DMA Receive descriptors */
-       lp->dlist = (struct recv_desc_bufs *) dma_alloc_coherent(NULL, sizeof(struct recv_desc_bufs), (dma_addr_t *) &lp->dlist_phys, GFP_KERNEL);
-       if (lp->dlist == NULL) {
-               res = -ENOMEM;
-               goto err_free_irq;
-       }
 
        ether_setup(dev);
        dev->netdev_ops = &at91ether_netdev_ops;
-       dev->ethtool_ops = &at91ether_ethtool_ops;
+       dev->ethtool_ops = &macb_ethtool_ops;
        platform_set_drvdata(pdev, dev);
        SET_NETDEV_DEV(dev, &pdev->dev);
 
        get_mac_address(dev);           /* Get ethernet address and store it in dev->dev_addr */
        update_mac_address(dev);        /* Program ethernet address into MAC */
 
-       at91_emac_write(lp, AT91_EMAC_CTL, 0);
-
-       if (board_data->is_rmii)
-               at91_emac_write(lp, AT91_EMAC_CFG, AT91_EMAC_CLK_DIV32 | AT91_EMAC_BIG | AT91_EMAC_RMII);
-       else
-               at91_emac_write(lp, AT91_EMAC_CFG, AT91_EMAC_CLK_DIV32 | AT91_EMAC_BIG);
+       macb_writel(lp, NCR, 0);
 
-       /* Detect PHY */
-       if (!at91ether_phy_detect(lp)) {
-               printk(KERN_ERR "at91_ether: Could not detect ethernet PHY\n");
-               res = -ENODEV;
-               goto err_free_dmamem;
+       if (board_data->is_rmii) {
+               macb_writel(lp, NCFGR, MACB_BF(CLK, MACB_CLK_DIV32) | MACB_BIT(BIG) | MACB_BIT(RM9200_RMII));
+               lp->phy_interface = PHY_INTERFACE_MODE_RMII;
+       } else {
+               macb_writel(lp, NCFGR, MACB_BF(CLK, MACB_CLK_DIV32) | MACB_BIT(BIG));
+               lp->phy_interface = PHY_INTERFACE_MODE_MII;
        }
 
-       initialize_phy(lp);
-
-       lp->mii.dev = dev;              /* Support for ethtool */
-       lp->mii.mdio_read = mdio_read;
-       lp->mii.mdio_write = mdio_write;
-       lp->mii.phy_id = lp->phy_address;
-       lp->mii.phy_id_mask = 0x1f;
-       lp->mii.reg_num_mask = 0x1f;
-
        /* Register the network interface */
        res = register_netdev(dev);
        if (res)
-               goto err_free_dmamem;
-
-       /* Determine current link speed */
-       spin_lock_irq(&lp->lock);
-       enable_mdi(lp);
-       update_linkspeed(dev, 0);
-       disable_mdi(lp);
-       spin_unlock_irq(&lp->lock);
+               goto err_disable_clock;
+
+       if (macb_mii_init(lp) != 0)
+               goto err_out_unregister_netdev;
+
        netif_carrier_off(dev);         /* will be enabled in open() */
 
-       /* If board has no PHY IRQ, use a timer to poll the PHY */
-       if (gpio_is_valid(lp->board_data.phy_irq_pin)) {
-               gpio_request(board_data->phy_irq_pin, "ethernet_phy");
-       } else {
-               /* If board has no PHY IRQ, use a timer to poll the PHY */
-               init_timer(&lp->check_timer);
-               lp->check_timer.data = (unsigned long)dev;
-               lp->check_timer.function = at91ether_check_link;
-       }
+       phydev = lp->phy_dev;
+       netdev_info(dev, "attached PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n",
+               phydev->drv->name, dev_name(&phydev->dev), phydev->irq);
 
        /* Display ethernet banner */
        printk(KERN_INFO "%s: AT91 ethernet at 0x%08x int=%d %s%s (%pM)\n",
               dev->name, (uint) dev->base_addr, dev->irq,
-              at91_emac_read(lp, AT91_EMAC_CFG) & AT91_EMAC_SPD ? "100-" : "10-",
-              at91_emac_read(lp, AT91_EMAC_CFG) & AT91_EMAC_FD ? "FullDuplex" : "HalfDuplex",
+              macb_readl(lp, NCFGR) & MACB_BIT(SPD) ? "100-" : "10-",
+              macb_readl(lp, NCFGR) & MACB_BIT(FD) ? "FullDuplex" : "HalfDuplex",
               dev->dev_addr);
-       if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID))
-               printk(KERN_INFO "%s: Davicom 9161 PHY %s\n", dev->name, (lp->phy_media == PORT_FIBRE) ? "(Fiber)" : "(Copper)");
-       else if (lp->phy_type == MII_LXT971A_ID)
-               printk(KERN_INFO "%s: Intel LXT971A PHY\n", dev->name);
-       else if (lp->phy_type == MII_RTL8201_ID)
-               printk(KERN_INFO "%s: Realtek RTL8201(B)L PHY\n", dev->name);
-       else if (lp->phy_type == MII_BCM5221_ID)
-               printk(KERN_INFO "%s: Broadcom BCM5221 PHY\n", dev->name);
-       else if (lp->phy_type == MII_DP83847_ID)
-               printk(KERN_INFO "%s: National Semiconductor DP83847 PHY\n", dev->name);
-       else if (lp->phy_type == MII_DP83848_ID)
-               printk(KERN_INFO "%s: National Semiconductor DP83848 PHY\n", dev->name);
-       else if (lp->phy_type == MII_AC101L_ID)
-               printk(KERN_INFO "%s: Altima AC101L PHY\n", dev->name);
-       else if (lp->phy_type == MII_KS8721_ID)
-               printk(KERN_INFO "%s: Micrel KS8721 PHY\n", dev->name);
-       else if (lp->phy_type == MII_T78Q21x3_ID)
-               printk(KERN_INFO "%s: Teridian 78Q21x3 PHY\n", dev->name);
-       else if (lp->phy_type == MII_LAN83C185_ID)
-               printk(KERN_INFO "%s: SMSC LAN83C185 PHY\n", dev->name);
-
-       clk_disable(lp->ether_clk);                                     /* Disable Peripheral clock */
 
        return 0;
 
-
-err_free_dmamem:
-       platform_set_drvdata(pdev, NULL);
-       dma_free_coherent(NULL, sizeof(struct recv_desc_bufs), lp->dlist, (dma_addr_t)lp->dlist_phys);
-err_free_irq:
-       free_irq(dev->irq, dev);
+err_out_unregister_netdev:
+       unregister_netdev(dev);
 err_disable_clock:
-       clk_disable(lp->ether_clk);
-       clk_put(lp->ether_clk);
-err_ioumap:
-       iounmap(lp->emac_base);
+       clk_disable(lp->pclk);
 err_free_dev:
        free_netdev(dev);
        return res;
@@ -1210,18 +544,19 @@ err_free_dev:
 static int __devexit at91ether_remove(struct platform_device *pdev)
 {
        struct net_device *dev = platform_get_drvdata(pdev);
-       struct at91_private *lp = netdev_priv(dev);
+       struct macb *lp = netdev_priv(dev);
 
-       if (gpio_is_valid(lp->board_data.phy_irq_pin))
-               gpio_free(lp->board_data.phy_irq_pin);
+       if (lp->phy_dev)
+               phy_disconnect(lp->phy_dev);
 
+       mdiobus_unregister(lp->mii_bus);
+       kfree(lp->mii_bus->irq);
+       mdiobus_free(lp->mii_bus);
        unregister_netdev(dev);
-       free_irq(dev->irq, dev);
-       dma_free_coherent(NULL, sizeof(struct recv_desc_bufs), lp->dlist, (dma_addr_t)lp->dlist_phys);
-       clk_put(lp->ether_clk);
-
-       platform_set_drvdata(pdev, NULL);
+       clk_disable(lp->pclk);
        free_netdev(dev);
+       platform_set_drvdata(pdev, NULL);
+
        return 0;
 }
 
@@ -1230,18 +565,13 @@ static int __devexit at91ether_remove(struct platform_device *pdev)
 static int at91ether_suspend(struct platform_device *pdev, pm_message_t mesg)
 {
        struct net_device *net_dev = platform_get_drvdata(pdev);
-       struct at91_private *lp = netdev_priv(net_dev);
+       struct macb *lp = netdev_priv(net_dev);
 
        if (netif_running(net_dev)) {
-               if (gpio_is_valid(lp->board_data.phy_irq_pin)) {
-                       int phy_irq = gpio_to_irq(lp->board_data.phy_irq_pin);
-                       disable_irq(phy_irq);
-               }
-
                netif_stop_queue(net_dev);
                netif_device_detach(net_dev);
 
-               clk_disable(lp->ether_clk);
+               clk_disable(lp->pclk);
        }
        return 0;
 }
@@ -1249,18 +579,13 @@ static int at91ether_suspend(struct platform_device *pdev, pm_message_t mesg)
 static int at91ether_resume(struct platform_device *pdev)
 {
        struct net_device *net_dev = platform_get_drvdata(pdev);
-       struct at91_private *lp = netdev_priv(net_dev);
+       struct macb *lp = netdev_priv(net_dev);
 
        if (netif_running(net_dev)) {
-               clk_enable(lp->ether_clk);
+               clk_enable(lp->pclk);
 
                netif_device_attach(net_dev);
                netif_start_queue(net_dev);
-
-               if (gpio_is_valid(lp->board_data.phy_irq_pin)) {
-                       int phy_irq = gpio_to_irq(lp->board_data.phy_irq_pin);
-                       enable_irq(phy_irq);
-               }
        }
        return 0;
 }
diff --git a/drivers/net/ethernet/cadence/at91_ether.h b/drivers/net/ethernet/cadence/at91_ether.h
deleted file mode 100644 (file)
index 0ef6328..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Ethernet driver for the Atmel AT91RM9200 (Thunder)
- *
- *  Copyright (C) SAN People (Pty) Ltd
- *
- * Based on an earlier Atmel EMAC macrocell driver by Atmel and Lineo Inc.
- * Initial version by Rick Bronson.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#ifndef AT91_ETHERNET
-#define AT91_ETHERNET
-
-
-/* Davicom 9161 PHY */
-#define MII_DM9161_ID          0x0181b880
-#define MII_DM9161A_ID         0x0181b8a0
-#define MII_DSCR_REG           16
-#define MII_DSCSR_REG          17
-#define MII_DSINTR_REG         21
-
-/* Intel LXT971A PHY */
-#define MII_LXT971A_ID         0x001378E0
-#define MII_ISINTE_REG         18
-#define MII_ISINTS_REG         19
-#define MII_LEDCTRL_REG                20
-
-/* Realtek RTL8201 PHY */
-#define MII_RTL8201_ID         0x00008200
-
-/* Broadcom BCM5221 PHY */
-#define MII_BCM5221_ID         0x004061e0
-#define MII_BCMINTR_REG                26
-
-/* National Semiconductor DP83847 */
-#define MII_DP83847_ID         0x20005c30
-
-/* National Semiconductor DP83848 */
-#define MII_DP83848_ID         0x20005c90
-#define MII_DPPHYSTS_REG       16
-#define MII_DPMICR_REG         17
-#define MII_DPMISR_REG         18
-
-/* Altima AC101L PHY */
-#define MII_AC101L_ID          0x00225520
-
-/* Micrel KS8721 PHY */
-#define MII_KS8721_ID          0x00221610
-
-/* Teridian 78Q2123/78Q2133 */
-#define MII_T78Q21x3_ID                0x000e7230
-#define MII_T78Q21INT_REG      17
-
-/* SMSC LAN83C185 */
-#define MII_LAN83C185_ID       0x0007C0A0
-
-/* ........................................................................ */
-
-#define MAX_RBUFF_SZ   0x600           /* 1518 rounded up */
-#define MAX_RX_DESCR   9               /* max number of receive buffers */
-
-#define EMAC_DESC_DONE 0x00000001      /* bit for if DMA is done */
-#define EMAC_DESC_WRAP 0x00000002      /* bit for wrap */
-
-#define EMAC_BROADCAST 0x80000000      /* broadcast address */
-#define EMAC_MULTICAST 0x40000000      /* multicast address */
-#define EMAC_UNICAST   0x20000000      /* unicast address */
-
-struct rbf_t
-{
-       unsigned int addr;
-       unsigned long size;
-};
-
-struct recv_desc_bufs
-{
-       struct rbf_t descriptors[MAX_RX_DESCR];         /* must be on sizeof (rbf_t) boundary */
-       char recv_buf[MAX_RX_DESCR][MAX_RBUFF_SZ];      /* must be on long boundary */
-};
-
-struct at91_private
-{
-       struct mii_if_info mii;                 /* ethtool support */
-       struct macb_platform_data board_data;   /* board-specific
-                                                * configuration (shared with
-                                                * macb for common data */
-       void __iomem *emac_base;                /* base register address */
-       struct clk *ether_clk;                  /* clock */
-
-       /* PHY */
-       unsigned long phy_type;                 /* type of PHY (PHY_ID) */
-       spinlock_t lock;                        /* lock for MDI interface */
-       short phy_media;                        /* media interface type */
-       unsigned short phy_address;             /* 5-bit MDI address of PHY (0..31) */
-       struct timer_list check_timer;          /* Poll link status */
-
-       /* Transmit */
-       struct sk_buff *skb;                    /* holds skb until xmit interrupt completes */
-       dma_addr_t skb_physaddr;                /* phys addr from pci_map_single */
-       int skb_length;                         /* saved skb length for pci_unmap_single */
-
-       /* Receive */
-       int rxBuffIndex;                        /* index into receive descriptor list */
-       struct recv_desc_bufs *dlist;           /* descriptor list address */
-       struct recv_desc_bufs *dlist_phys;      /* descriptor list physical address */
-};
-
-#endif
index 033064b7b576ad9199702d0a515331dda141fe41..6a4f4998cfe54601d952fd196746786c8a968998 100644 (file)
@@ -228,7 +228,7 @@ static int macb_mii_probe(struct net_device *dev)
        return 0;
 }
 
-static int macb_mii_init(struct macb *bp)
+int macb_mii_init(struct macb *bp)
 {
        struct macb_platform_data *pdata;
        int err = -ENXIO, i;
@@ -284,6 +284,7 @@ err_out_free_mdiobus:
 err_out:
        return err;
 }
+EXPORT_SYMBOL_GPL(macb_mii_init);
 
 static void macb_update_stats(struct macb *bp)
 {
@@ -552,7 +553,7 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id)
        while (status) {
                /* close possible race with dev_close */
                if (unlikely(!netif_running(dev))) {
-                       macb_writel(bp, IDR, ~0UL);
+                       macb_writel(bp, IDR, -1);
                        break;
                }
 
@@ -788,11 +789,11 @@ static void macb_reset_hw(struct macb *bp)
        macb_writel(bp, NCR, MACB_BIT(CLRSTAT));
 
        /* Clear all status flags */
-       macb_writel(bp, TSR, ~0UL);
-       macb_writel(bp, RSR, ~0UL);
+       macb_writel(bp, TSR, -1);
+       macb_writel(bp, RSR, -1);
 
        /* Disable all interrupts */
-       macb_writel(bp, IDR, ~0UL);
+       macb_writel(bp, IDR, -1);
        macb_readl(bp, ISR);
 }
 
@@ -996,7 +997,7 @@ static void macb_sethashtable(struct net_device *dev)
 /*
  * Enable/Disable promiscuous and multicast modes.
  */
-static void macb_set_rx_mode(struct net_device *dev)
+void macb_set_rx_mode(struct net_device *dev)
 {
        unsigned long cfg;
        struct macb *bp = netdev_priv(dev);
@@ -1028,6 +1029,7 @@ static void macb_set_rx_mode(struct net_device *dev)
 
        macb_writel(bp, NCFGR, cfg);
 }
+EXPORT_SYMBOL_GPL(macb_set_rx_mode);
 
 static int macb_open(struct net_device *dev)
 {
@@ -1214,15 +1216,16 @@ static void macb_get_drvinfo(struct net_device *dev,
        strcpy(info->bus_info, dev_name(&bp->pdev->dev));
 }
 
-static const struct ethtool_ops macb_ethtool_ops = {
+const struct ethtool_ops macb_ethtool_ops = {
        .get_settings           = macb_get_settings,
        .set_settings           = macb_set_settings,
        .get_drvinfo            = macb_get_drvinfo,
        .get_link               = ethtool_op_get_link,
        .get_ts_info            = ethtool_op_get_ts_info,
 };
+EXPORT_SYMBOL_GPL(macb_ethtool_ops);
 
-static int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
        struct macb *bp = netdev_priv(dev);
        struct phy_device *phydev = bp->phy_dev;
@@ -1235,6 +1238,7 @@ static int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 
        return phy_mii_ioctl(phydev, rq, cmd);
 }
+EXPORT_SYMBOL_GPL(macb_ioctl);
 
 static const struct net_device_ops macb_netdev_ops = {
        .ndo_open               = macb_open,
index 335e288f53140159e2f1956a716713b69c03933a..a3627517ec9533005e10bc57ef7e41cae49d18d1 100644 (file)
@@ -14,6 +14,8 @@
 #define MACB_NCR                               0x0000
 #define MACB_NCFGR                             0x0004
 #define MACB_NSR                               0x0008
+#define MACB_TAR                               0x000c /* AT91RM9200 only */
+#define MACB_TCR                               0x0010 /* AT91RM9200 only */
 #define MACB_TSR                               0x0014
 #define MACB_RBQP                              0x0018
 #define MACB_TBQP                              0x001c
 #define MACB_RTY_SIZE                          1
 #define MACB_PAE_OFFSET                                13
 #define MACB_PAE_SIZE                          1
+#define MACB_RM9200_RMII_OFFSET                        13 /* AT91RM9200 only */
+#define MACB_RM9200_RMII_SIZE                  1  /* AT91RM9200 only */
 #define MACB_RBOF_OFFSET                       14
 #define MACB_RBOF_SIZE                         2
 #define MACB_RLCE_OFFSET                       16
 #define MACB_TGO_SIZE                          1
 #define MACB_BEX_OFFSET                                4
 #define MACB_BEX_SIZE                          1
+#define MACB_RM9200_BNQ_OFFSET                 4 /* AT91RM9200 only */
+#define MACB_RM9200_BNQ_SIZE                   1 /* AT91RM9200 only */
 #define MACB_COMP_OFFSET                       5
 #define MACB_COMP_SIZE                         1
 #define MACB_UND_OFFSET                                6
@@ -534,8 +540,24 @@ struct macb {
        unsigned int            duplex;
 
        phy_interface_t         phy_interface;
+
+       /* at91_private */
+       struct macb_platform_data board_data;   /* board-specific
+                                                * configuration (shared with
+                                                * macb for common data */
+
+       /* Transmit */
+       struct sk_buff *skb;                    /* holds skb until xmit interrupt completes */
+       dma_addr_t skb_physaddr;                /* phys addr from pci_map_single */
+       int skb_length;                         /* saved skb length for pci_unmap_single */
 };
 
+extern const struct ethtool_ops macb_ethtool_ops;
+
+int macb_mii_init(struct macb *bp);
+int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+void macb_set_rx_mode(struct net_device *dev);
+
 static inline bool macb_is_gem(struct macb *bp)
 {
        return MACB_BFEXT(IDNUM, macb_readl(bp, MID)) == 0x2;
index a4da893ac1e15cfd02a2d071503afaa21838e51c..378988b5709a2262b98c0a790072be38b837cdf3 100644 (file)
@@ -251,6 +251,8 @@ struct adapter_params {
        unsigned char rev;                /* chip revision */
        unsigned char offload;
 
+       unsigned char bypass;
+
        unsigned int ofldq_wr_cred;
 };
 
@@ -642,6 +644,23 @@ extern int dbfifo_int_thresh;
 #define for_each_port(adapter, iter) \
        for (iter = 0; iter < (adapter)->params.nports; ++iter)
 
+static inline int is_bypass(struct adapter *adap)
+{
+       return adap->params.bypass;
+}
+
+static inline int is_bypass_device(int device)
+{
+       /* this should be set based upon device capabilities */
+       switch (device) {
+       case 0x440b:
+       case 0x440c:
+               return 1;
+       default:
+               return 0;
+       }
+}
+
 static inline unsigned int core_ticks_per_usec(const struct adapter *adap)
 {
        return adap->params.vpd.cclk / 1000;
index 604f4f87f550c879a087fd128892d97450aa2d19..c1cde11b0c6d5114e62ba400caab0195905ada3d 100644 (file)
@@ -3513,18 +3513,6 @@ static int adap_init0_no_config(struct adapter *adapter, int reset)
        if (ret < 0)
                goto bye;
 
-#ifndef CONFIG_CHELSIO_T4_OFFLOAD
-       /*
-        * If we're a pure NIC driver then disable all offloading facilities.
-        * This will allow the firmware to optimize aspects of the hardware
-        * configuration which will result in improved performance.
-        */
-       caps_cmd.ofldcaps = 0;
-       caps_cmd.iscsicaps = 0;
-       caps_cmd.rdmacaps = 0;
-       caps_cmd.fcoecaps = 0;
-#endif
-
        if (caps_cmd.niccaps & htons(FW_CAPS_CONFIG_NIC_VM)) {
                if (!vf_acls)
                        caps_cmd.niccaps ^= htons(FW_CAPS_CONFIG_NIC_VM);
@@ -3745,6 +3733,7 @@ static int adap_init0(struct adapter *adap)
        u32 v, port_vec;
        enum dev_state state;
        u32 params[7], val[7];
+       struct fw_caps_config_cmd caps_cmd;
        int reset = 1, j;
 
        /*
@@ -3898,6 +3887,9 @@ static int adap_init0(struct adapter *adap)
                        goto bye;
        }
 
+       if (is_bypass_device(adap->pdev->device))
+               adap->params.bypass = 1;
+
        /*
         * Grab some of our basic fundamental operating parameters.
         */
@@ -3940,13 +3932,12 @@ static int adap_init0(struct adapter *adap)
                adap->tids.aftid_end = val[1];
        }
 
-#ifdef CONFIG_CHELSIO_T4_OFFLOAD
        /*
         * Get device capabilities so we can determine what resources we need
         * to manage.
         */
        memset(&caps_cmd, 0, sizeof(caps_cmd));
-       caps_cmd.op_to_write = htonl(V_FW_CMD_OP(FW_CAPS_CONFIG_CMD) |
+       caps_cmd.op_to_write = htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) |
                                     FW_CMD_REQUEST | FW_CMD_READ);
        caps_cmd.retval_len16 = htonl(FW_LEN16(caps_cmd));
        ret = t4_wr_mbox(adap, adap->mbox, &caps_cmd, sizeof(caps_cmd),
@@ -3991,15 +3982,6 @@ static int adap_init0(struct adapter *adap)
                adap->vres.ddp.size = val[4] - val[3] + 1;
                adap->params.ofldq_wr_cred = val[5];
 
-               params[0] = FW_PARAM_PFVF(ETHOFLD_START);
-               params[1] = FW_PARAM_PFVF(ETHOFLD_END);
-               ret = t4_query_params(adap, adap->mbox, adap->fn, 0, 2,
-                                     params, val);
-               if ((val[0] != val[1]) && (ret >= 0)) {
-                       adap->tids.uotid_base = val[0];
-                       adap->tids.nuotids = val[1] - val[0] + 1;
-               }
-
                adap->params.offload = 1;
        }
        if (caps_cmd.rdmacaps) {
@@ -4048,7 +4030,6 @@ static int adap_init0(struct adapter *adap)
        }
 #undef FW_PARAM_PFVF
 #undef FW_PARAM_DEV
-#endif /* CONFIG_CHELSIO_T4_OFFLOAD */
 
        /*
         * These are finalized by FW initialization, load their values now.
index 1b899fea1a91427bac31b171cd799fad2fc384f0..39bec73ff87c5879a9b1f6ca9ad1425d4d78c9b2 100644 (file)
@@ -102,6 +102,9 @@ struct tid_info {
        unsigned int ftid_base;
        unsigned int aftid_base;
        unsigned int aftid_end;
+       /* Server filter region */
+       unsigned int sftid_base;
+       unsigned int nsftids;
 
        spinlock_t atid_lock ____cacheline_aligned_in_smp;
        union aopen_entry *afree;
index cf4c05bdf5fe71262abf8fd4ac10e11e0cb0240a..f920a6521ce7c2b78454c2172e6fd1e0f85c5937 100644 (file)
@@ -34,7 +34,7 @@
 #include "be_hw.h"
 #include "be_roce.h"
 
-#define DRV_VER                        "4.4.31.0u"
+#define DRV_VER                        "4.4.161.0u"
 #define DRV_NAME               "be2net"
 #define BE_NAME                        "ServerEngines BladeEngine2 10Gbps NIC"
 #define BE3_NAME               "ServerEngines BladeEngine3 10Gbps NIC"
@@ -53,6 +53,7 @@
 #define OC_DEVICE_ID3          0xe220  /* Device id for Lancer cards */
 #define OC_DEVICE_ID4           0xe228   /* Device id for VF in Lancer */
 #define OC_DEVICE_ID5          0x720   /* Device Id for Skyhawk cards */
+#define OC_DEVICE_ID6          0x728   /* Device id for VF in SkyHawk */
 #define OC_SUBSYS_DEVICE_ID1   0xE602
 #define OC_SUBSYS_DEVICE_ID2   0xE642
 #define OC_SUBSYS_DEVICE_ID3   0xE612
@@ -71,6 +72,7 @@ static inline char *nic_name(struct pci_dev *pdev)
        case BE_DEVICE_ID2:
                return BE3_NAME;
        case OC_DEVICE_ID5:
+       case OC_DEVICE_ID6:
                return OC_NAME_SH;
        default:
                return BE_NAME;
@@ -378,7 +380,6 @@ struct be_adapter {
        struct be_drv_stats drv_stats;
 
        u16 vlans_added;
-       u16 max_vlans;  /* Number of vlans supported */
        u8 vlan_tag[VLAN_N_VID];
        u8 vlan_prio_bmap;      /* Available Priority BitMap */
        u16 recommended_prio;   /* Recommended Priority */
@@ -391,6 +392,7 @@ struct be_adapter {
 
        struct delayed_work func_recovery_work;
        u32 flags;
+       u32 cmd_privileges;
        /* Ethtool knobs and info */
        char fw_ver[FW_VER_LEN];
        int if_handle;          /* Used to configure filtering */
@@ -434,10 +436,18 @@ struct be_adapter {
        struct phy_info phy;
        u8 wol_cap;
        bool wol;
-       u32 max_pmac_cnt;       /* Max secondary UC MACs programmable */
        u32 uc_macs;            /* Count of secondary UC MAC programmed */
        u32 msg_enable;
        int be_get_temp_freq;
+       u16 max_mcast_mac;
+       u16 max_tx_queues;
+       u16 max_rss_queues;
+       u16 max_rx_queues;
+       u16 max_pmac_cnt;
+       u16 max_vlans;
+       u16 max_event_queues;
+       u32 if_cap_flags;
+       u8 pf_number;
 };
 
 #define be_physfn(adapter)             (!adapter->virtfn)
@@ -451,13 +461,15 @@ struct be_adapter {
 /* BladeEngine Generation numbers */
 #define BE_GEN2 2
 #define BE_GEN3 3
+#define SH_HW  4
 
 #define ON                             1
 #define OFF                            0
 #define lancer_chip(adapter)   ((adapter->pdev->device == OC_DEVICE_ID3) || \
                                 (adapter->pdev->device == OC_DEVICE_ID4))
 
-#define skyhawk_chip(adapter)  (adapter->pdev->device == OC_DEVICE_ID5)
+#define skyhawk_chip(adapter)  (adapter->pdev->device == OC_DEVICE_ID5 || \
+                                adapter->pdev->device == OC_DEVICE_ID6)
 
 
 #define be_roce_supported(adapter) ((adapter->if_type == SLI_INTF_TYPE_3 || \
index af60bb26e33023ac523b672f76e68dcbdd172f92..7ea1ea4ff24281d7264be7ccf3cfa114ee6c5de2 100644 (file)
 #include "be.h"
 #include "be_cmds.h"
 
+static struct be_cmd_priv_map cmd_priv_map[] = {
+       {
+               OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG,
+               CMD_SUBSYSTEM_ETH,
+               BE_PRIV_LNKMGMT | BE_PRIV_VHADM |
+               BE_PRIV_DEVCFG | BE_PRIV_DEVSEC
+       },
+       {
+               OPCODE_COMMON_GET_FLOW_CONTROL,
+               CMD_SUBSYSTEM_COMMON,
+               BE_PRIV_LNKQUERY | BE_PRIV_VHADM |
+               BE_PRIV_DEVCFG | BE_PRIV_DEVSEC
+       },
+       {
+               OPCODE_COMMON_SET_FLOW_CONTROL,
+               CMD_SUBSYSTEM_COMMON,
+               BE_PRIV_LNKMGMT | BE_PRIV_VHADM |
+               BE_PRIV_DEVCFG | BE_PRIV_DEVSEC
+       },
+       {
+               OPCODE_ETH_GET_PPORT_STATS,
+               CMD_SUBSYSTEM_ETH,
+               BE_PRIV_LNKMGMT | BE_PRIV_VHADM |
+               BE_PRIV_DEVCFG | BE_PRIV_DEVSEC
+       },
+       {
+               OPCODE_COMMON_GET_PHY_DETAILS,
+               CMD_SUBSYSTEM_COMMON,
+               BE_PRIV_LNKMGMT | BE_PRIV_VHADM |
+               BE_PRIV_DEVCFG | BE_PRIV_DEVSEC
+       }
+};
+
+static bool be_cmd_allowed(struct be_adapter *adapter, u8 opcode,
+                          u8 subsystem)
+{
+       int i;
+       int num_entries = sizeof(cmd_priv_map)/sizeof(struct be_cmd_priv_map);
+       u32 cmd_privileges = adapter->cmd_privileges;
+
+       for (i = 0; i < num_entries; i++)
+               if (opcode == cmd_priv_map[i].opcode &&
+                   subsystem == cmd_priv_map[i].subsystem)
+                       if (!(cmd_privileges & cmd_priv_map[i].priv_mask))
+                               return false;
+
+       return true;
+}
+
 static inline void *embedded_payload(struct be_mcc_wrb *wrb)
 {
        return wrb->payload.embedded_payload;
@@ -452,10 +501,33 @@ int lancer_wait_ready(struct be_adapter *adapter)
        return status;
 }
 
+static bool lancer_provisioning_error(struct be_adapter *adapter)
+{
+       u32 sliport_status = 0, sliport_err1 = 0, sliport_err2 = 0;
+       sliport_status = ioread32(adapter->db + SLIPORT_STATUS_OFFSET);
+       if (sliport_status & SLIPORT_STATUS_ERR_MASK) {
+               sliport_err1 = ioread32(adapter->db +
+                                       SLIPORT_ERROR1_OFFSET);
+               sliport_err2 = ioread32(adapter->db +
+                                       SLIPORT_ERROR2_OFFSET);
+
+               if (sliport_err1 == SLIPORT_ERROR_NO_RESOURCE1 &&
+                   sliport_err2 == SLIPORT_ERROR_NO_RESOURCE2)
+                       return true;
+       }
+       return false;
+}
+
 int lancer_test_and_set_rdy_state(struct be_adapter *adapter)
 {
        int status;
        u32 sliport_status, err, reset_needed;
+       bool resource_error;
+
+       resource_error = lancer_provisioning_error(adapter);
+       if (resource_error)
+               return -1;
+
        status = lancer_wait_ready(adapter);
        if (!status) {
                sliport_status = ioread32(adapter->db + SLIPORT_STATUS_OFFSET);
@@ -477,6 +549,14 @@ int lancer_test_and_set_rdy_state(struct be_adapter *adapter)
                        status = -1;
                }
        }
+       /* Stop error recovery if error is not recoverable.
+        * No resource error is temporary errors and will go away
+        * when PF provisions resources.
+        */
+       resource_error = lancer_provisioning_error(adapter);
+       if (status == -1 && !resource_error)
+               adapter->eeh_error = true;
+
        return status;
 }
 
@@ -601,6 +681,9 @@ static struct be_mcc_wrb *wrb_from_mccq(struct be_adapter *adapter)
        struct be_queue_info *mccq = &adapter->mcc_obj.q;
        struct be_mcc_wrb *wrb;
 
+       if (!mccq->created)
+               return NULL;
+
        if (atomic_read(&mccq->used) >= mccq->len) {
                dev_err(&adapter->pdev->dev, "Out of MCCQ wrbs\n");
                return NULL;
@@ -1155,8 +1238,7 @@ int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q,
        req->id = cpu_to_le16(q->id);
 
        status = be_mbox_notify_wait(adapter);
-       if (!status)
-               q->created = false;
+       q->created = false;
 
        mutex_unlock(&adapter->mbox_lock);
        return status;
@@ -1183,8 +1265,7 @@ int be_cmd_rxq_destroy(struct be_adapter *adapter, struct be_queue_info *q)
        req->id = cpu_to_le16(q->id);
 
        status = be_mcc_notify_wait(adapter);
-       if (!status)
-               q->created = false;
+       q->created = false;
 
 err:
        spin_unlock_bh(&adapter->mcc_lock);
@@ -1301,6 +1382,10 @@ int lancer_cmd_get_pport_stats(struct be_adapter *adapter,
        struct lancer_cmd_req_pport_stats *req;
        int status = 0;
 
+       if (!be_cmd_allowed(adapter, OPCODE_ETH_GET_PPORT_STATS,
+                           CMD_SUBSYSTEM_ETH))
+               return -EPERM;
+
        spin_lock_bh(&adapter->mcc_lock);
 
        wrb = wrb_from_mccq(adapter);
@@ -1658,9 +1743,9 @@ int be_cmd_rx_filter(struct be_adapter *adapter, u32 flags, u32 value)
                /* Reset mcast promisc mode if already set by setting mask
                 * and not setting flags field
                 */
-               if (!lancer_chip(adapter) || be_physfn(adapter))
-                       req->if_flags_mask |=
-                               cpu_to_le32(BE_IF_FLAGS_MCAST_PROMISCUOUS);
+               req->if_flags_mask |=
+                       cpu_to_le32(BE_IF_FLAGS_MCAST_PROMISCUOUS &
+                                   adapter->if_cap_flags);
 
                req->mcast_num = cpu_to_le32(netdev_mc_count(adapter->netdev));
                netdev_for_each_mc_addr(ha, adapter->netdev)
@@ -1680,6 +1765,10 @@ int be_cmd_set_flow_control(struct be_adapter *adapter, u32 tx_fc, u32 rx_fc)
        struct be_cmd_req_set_flow_control *req;
        int status;
 
+       if (!be_cmd_allowed(adapter, OPCODE_COMMON_SET_FLOW_CONTROL,
+                           CMD_SUBSYSTEM_COMMON))
+               return -EPERM;
+
        spin_lock_bh(&adapter->mcc_lock);
 
        wrb = wrb_from_mccq(adapter);
@@ -1709,6 +1798,10 @@ int be_cmd_get_flow_control(struct be_adapter *adapter, u32 *tx_fc, u32 *rx_fc)
        struct be_cmd_req_get_flow_control *req;
        int status;
 
+       if (!be_cmd_allowed(adapter, OPCODE_COMMON_GET_FLOW_CONTROL,
+                           CMD_SUBSYSTEM_COMMON))
+               return -EPERM;
+
        spin_lock_bh(&adapter->mcc_lock);
 
        wrb = wrb_from_mccq(adapter);
@@ -2067,7 +2160,7 @@ int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc,
                         int offset)
 {
        struct be_mcc_wrb *wrb;
-       struct be_cmd_write_flashrom *req;
+       struct be_cmd_read_flash_crc *req;
        int status;
 
        spin_lock_bh(&adapter->mcc_lock);
@@ -2080,7 +2173,8 @@ int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc,
        req = embedded_payload(wrb);
 
        be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
-               OPCODE_COMMON_READ_FLASHROM, sizeof(*req)+4, wrb, NULL);
+                              OPCODE_COMMON_READ_FLASHROM, sizeof(*req),
+                              wrb, NULL);
 
        req->params.op_type = cpu_to_le32(OPTYPE_REDBOOT);
        req->params.op_code = cpu_to_le32(FLASHROM_OPER_REPORT);
@@ -2089,7 +2183,7 @@ int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc,
 
        status = be_mcc_notify_wait(adapter);
        if (!status)
-               memcpy(flashed_crc, req->params.data_buf, 4);
+               memcpy(flashed_crc, req->crc, 4);
 
 err:
        spin_unlock_bh(&adapter->mcc_lock);
@@ -2275,6 +2369,10 @@ int be_cmd_get_phy_info(struct be_adapter *adapter)
        struct be_dma_mem cmd;
        int status;
 
+       if (!be_cmd_allowed(adapter, OPCODE_COMMON_GET_PHY_DETAILS,
+                           CMD_SUBSYSTEM_COMMON))
+               return -EPERM;
+
        spin_lock_bh(&adapter->mcc_lock);
 
        wrb = wrb_from_mccq(adapter);
@@ -2434,6 +2532,42 @@ err:
        return status;
 }
 
+/* Get privilege(s) for a function */
+int be_cmd_get_fn_privileges(struct be_adapter *adapter, u32 *privilege,
+                            u32 domain)
+{
+       struct be_mcc_wrb *wrb;
+       struct be_cmd_req_get_fn_privileges *req;
+       int status;
+
+       spin_lock_bh(&adapter->mcc_lock);
+
+       wrb = wrb_from_mccq(adapter);
+       if (!wrb) {
+               status = -EBUSY;
+               goto err;
+       }
+
+       req = embedded_payload(wrb);
+
+       be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+                              OPCODE_COMMON_GET_FN_PRIVILEGES, sizeof(*req),
+                              wrb, NULL);
+
+       req->hdr.domain = domain;
+
+       status = be_mcc_notify_wait(adapter);
+       if (!status) {
+               struct be_cmd_resp_get_fn_privileges *resp =
+                                               embedded_payload(wrb);
+               *privilege = le32_to_cpu(resp->privilege_mask);
+       }
+
+err:
+       spin_unlock_bh(&adapter->mcc_lock);
+       return status;
+}
+
 /* Uses synchronous MCCQ */
 int be_cmd_get_mac_from_list(struct be_adapter *adapter, u8 *mac,
                             bool *pmac_id_active, u32 *pmac_id, u8 domain)
@@ -2651,6 +2785,10 @@ int be_cmd_get_acpi_wol_cap(struct be_adapter *adapter)
        int payload_len = sizeof(*req);
        struct be_dma_mem cmd;
 
+       if (!be_cmd_allowed(adapter, OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG,
+                           CMD_SUBSYSTEM_ETH))
+               return -EPERM;
+
        memset(&cmd, 0, sizeof(struct be_dma_mem));
        cmd.size = sizeof(struct be_cmd_resp_acpi_wol_magic_config_v1);
        cmd.va = pci_alloc_consistent(adapter->pdev, cmd.size,
@@ -2792,6 +2930,240 @@ err:
        return status;
 }
 
+static struct be_nic_resource_desc *be_get_nic_desc(u8 *buf, u32 desc_count,
+                                                   u32 max_buf_size)
+{
+       struct be_nic_resource_desc *desc = (struct be_nic_resource_desc *)buf;
+       int i;
+
+       for (i = 0; i < desc_count; i++) {
+               desc->desc_len = RESOURCE_DESC_SIZE;
+               if (((void *)desc + desc->desc_len) >
+                   (void *)(buf + max_buf_size)) {
+                       desc = NULL;
+                       break;
+               }
+
+               if (desc->desc_type == NIC_RESOURCE_DESC_TYPE_ID)
+                       break;
+
+               desc = (void *)desc + desc->desc_len;
+       }
+
+       if (!desc || i == MAX_RESOURCE_DESC)
+               return NULL;
+
+       return desc;
+}
+
+/* Uses Mbox */
+int be_cmd_get_func_config(struct be_adapter *adapter)
+{
+       struct be_mcc_wrb *wrb;
+       struct be_cmd_req_get_func_config *req;
+       int status;
+       struct be_dma_mem cmd;
+
+       memset(&cmd, 0, sizeof(struct be_dma_mem));
+       cmd.size = sizeof(struct be_cmd_resp_get_func_config);
+       cmd.va = pci_alloc_consistent(adapter->pdev, cmd.size,
+                                     &cmd.dma);
+       if (!cmd.va) {
+               dev_err(&adapter->pdev->dev, "Memory alloc failure\n");
+               return -ENOMEM;
+       }
+       if (mutex_lock_interruptible(&adapter->mbox_lock))
+               return -1;
+
+       wrb = wrb_from_mbox(adapter);
+       if (!wrb) {
+               status = -EBUSY;
+               goto err;
+       }
+
+       req = cmd.va;
+
+       be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+                              OPCODE_COMMON_GET_FUNC_CONFIG,
+                              cmd.size, wrb, &cmd);
+
+       status = be_mbox_notify_wait(adapter);
+       if (!status) {
+               struct be_cmd_resp_get_func_config *resp = cmd.va;
+               u32 desc_count = le32_to_cpu(resp->desc_count);
+               struct be_nic_resource_desc *desc;
+
+               desc = be_get_nic_desc(resp->func_param, desc_count,
+                                      sizeof(resp->func_param));
+               if (!desc) {
+                       status = -EINVAL;
+                       goto err;
+               }
+
+               adapter->pf_number = desc->pf_num;
+               adapter->max_pmac_cnt = le16_to_cpu(desc->unicast_mac_count);
+               adapter->max_vlans = le16_to_cpu(desc->vlan_count);
+               adapter->max_mcast_mac = le16_to_cpu(desc->mcast_mac_count);
+               adapter->max_tx_queues = le16_to_cpu(desc->txq_count);
+               adapter->max_rss_queues = le16_to_cpu(desc->rssq_count);
+               adapter->max_rx_queues = le16_to_cpu(desc->rq_count);
+
+               adapter->max_event_queues = le16_to_cpu(desc->eq_count);
+               adapter->if_cap_flags = le32_to_cpu(desc->cap_flags);
+       }
+err:
+       mutex_unlock(&adapter->mbox_lock);
+       pci_free_consistent(adapter->pdev, cmd.size,
+                           cmd.va, cmd.dma);
+       return status;
+}
+
+ /* Uses sync mcc */
+int be_cmd_get_profile_config(struct be_adapter *adapter, u32 *cap_flags,
+                             u8 domain)
+{
+       struct be_mcc_wrb *wrb;
+       struct be_cmd_req_get_profile_config *req;
+       int status;
+       struct be_dma_mem cmd;
+
+       memset(&cmd, 0, sizeof(struct be_dma_mem));
+       cmd.size = sizeof(struct be_cmd_resp_get_profile_config);
+       cmd.va = pci_alloc_consistent(adapter->pdev, cmd.size,
+                                     &cmd.dma);
+       if (!cmd.va) {
+               dev_err(&adapter->pdev->dev, "Memory alloc failure\n");
+               return -ENOMEM;
+       }
+
+       spin_lock_bh(&adapter->mcc_lock);
+
+       wrb = wrb_from_mccq(adapter);
+       if (!wrb) {
+               status = -EBUSY;
+               goto err;
+       }
+
+       req = cmd.va;
+
+       be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+                              OPCODE_COMMON_GET_PROFILE_CONFIG,
+                              cmd.size, wrb, &cmd);
+
+       req->type = ACTIVE_PROFILE_TYPE;
+       req->hdr.domain = domain;
+
+       status = be_mcc_notify_wait(adapter);
+       if (!status) {
+               struct be_cmd_resp_get_profile_config *resp = cmd.va;
+               u32 desc_count = le32_to_cpu(resp->desc_count);
+               struct be_nic_resource_desc *desc;
+
+               desc = be_get_nic_desc(resp->func_param, desc_count,
+                                      sizeof(resp->func_param));
+
+               if (!desc) {
+                       status = -EINVAL;
+                       goto err;
+               }
+               *cap_flags = le32_to_cpu(desc->cap_flags);
+       }
+err:
+       spin_unlock_bh(&adapter->mcc_lock);
+       pci_free_consistent(adapter->pdev, cmd.size,
+                           cmd.va, cmd.dma);
+       return status;
+}
+
+/* Uses sync mcc */
+int be_cmd_set_profile_config(struct be_adapter *adapter, u32 bps,
+                             u8 domain)
+{
+       struct be_mcc_wrb *wrb;
+       struct be_cmd_req_set_profile_config *req;
+       int status;
+
+       spin_lock_bh(&adapter->mcc_lock);
+
+       wrb = wrb_from_mccq(adapter);
+       if (!wrb) {
+               status = -EBUSY;
+               goto err;
+       }
+
+       req = embedded_payload(wrb);
+
+       be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+                              OPCODE_COMMON_SET_PROFILE_CONFIG, sizeof(*req),
+                              wrb, NULL);
+
+       req->hdr.domain = domain;
+       req->desc_count = cpu_to_le32(1);
+
+       req->nic_desc.desc_type = NIC_RESOURCE_DESC_TYPE_ID;
+       req->nic_desc.desc_len = RESOURCE_DESC_SIZE;
+       req->nic_desc.flags = (1 << QUN) | (1 << IMM) | (1 << NOSV);
+       req->nic_desc.pf_num = adapter->pf_number;
+       req->nic_desc.vf_num = domain;
+
+       /* Mark fields invalid */
+       req->nic_desc.unicast_mac_count = 0xFFFF;
+       req->nic_desc.mcc_count = 0xFFFF;
+       req->nic_desc.vlan_count = 0xFFFF;
+       req->nic_desc.mcast_mac_count = 0xFFFF;
+       req->nic_desc.txq_count = 0xFFFF;
+       req->nic_desc.rq_count = 0xFFFF;
+       req->nic_desc.rssq_count = 0xFFFF;
+       req->nic_desc.lro_count = 0xFFFF;
+       req->nic_desc.cq_count = 0xFFFF;
+       req->nic_desc.toe_conn_count = 0xFFFF;
+       req->nic_desc.eq_count = 0xFFFF;
+       req->nic_desc.link_param = 0xFF;
+       req->nic_desc.bw_min = 0xFFFFFFFF;
+       req->nic_desc.acpi_params = 0xFF;
+       req->nic_desc.wol_param = 0x0F;
+
+       /* Change BW */
+       req->nic_desc.bw_min = cpu_to_le32(bps);
+       req->nic_desc.bw_max = cpu_to_le32(bps);
+       status = be_mcc_notify_wait(adapter);
+err:
+       spin_unlock_bh(&adapter->mcc_lock);
+       return status;
+}
+
+/* Uses sync mcc */
+int be_cmd_enable_vf(struct be_adapter *adapter, u8 domain)
+{
+       struct be_mcc_wrb *wrb;
+       struct be_cmd_enable_disable_vf *req;
+       int status;
+
+       if (!lancer_chip(adapter))
+               return 0;
+
+       spin_lock_bh(&adapter->mcc_lock);
+
+       wrb = wrb_from_mccq(adapter);
+       if (!wrb) {
+               status = -EBUSY;
+               goto err;
+       }
+
+       req = embedded_payload(wrb);
+
+       be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+                              OPCODE_COMMON_ENABLE_DISABLE_VF, sizeof(*req),
+                              wrb, NULL);
+
+       req->hdr.domain = domain;
+       req->enable = 1;
+       status = be_mcc_notify_wait(adapter);
+err:
+       spin_unlock_bh(&adapter->mcc_lock);
+       return status;
+}
+
 int be_roce_mcc_cmd(void *netdev_handle, void *wrb_payload,
                        int wrb_payload_size, u16 *cmd_status, u16 *ext_status)
 {
index 0936e21e3cff3d6cdf3767dbf1d0e708744f9b26..06fc22738b9dba567850576c2508579bfe57fc48 100644 (file)
@@ -196,9 +196,14 @@ struct be_mcc_mailbox {
 #define OPCODE_COMMON_GET_MAC_LIST                     147
 #define OPCODE_COMMON_SET_MAC_LIST                     148
 #define OPCODE_COMMON_GET_HSW_CONFIG                   152
+#define OPCODE_COMMON_GET_FUNC_CONFIG                  160
+#define OPCODE_COMMON_GET_PROFILE_CONFIG               164
+#define OPCODE_COMMON_SET_PROFILE_CONFIG               165
 #define OPCODE_COMMON_SET_HSW_CONFIG                   153
+#define OPCODE_COMMON_GET_FN_PRIVILEGES                        170
 #define OPCODE_COMMON_READ_OBJECT                      171
 #define OPCODE_COMMON_WRITE_OBJECT                     172
+#define OPCODE_COMMON_ENABLE_DISABLE_VF                        196
 
 #define OPCODE_ETH_RSS_CONFIG                          1
 #define OPCODE_ETH_ACPI_CONFIG                         2
@@ -1151,14 +1156,22 @@ struct flashrom_params {
        u32 op_type;
        u32 data_buf_size;
        u32 offset;
-       u8 data_buf[4];
 };
 
 struct be_cmd_write_flashrom {
        struct be_cmd_req_hdr hdr;
        struct flashrom_params params;
-};
+       u8 data_buf[32768];
+       u8 rsvd[4];
+} __packed;
 
+/* cmd to read flash crc */
+struct be_cmd_read_flash_crc {
+       struct be_cmd_req_hdr hdr;
+       struct flashrom_params params;
+       u8 crc[4];
+       u8 rsvd[4];
+};
 /**************** Lancer Firmware Flash ************/
 struct amap_lancer_write_obj_context {
        u8 write_length[24];
@@ -1429,6 +1442,41 @@ struct be_cmd_resp_set_func_cap {
        u8 rsvd[212];
 };
 
+/*********************** Function Privileges ***********************/
+enum {
+       BE_PRIV_DEFAULT = 0x1,
+       BE_PRIV_LNKQUERY = 0x2,
+       BE_PRIV_LNKSTATS = 0x4,
+       BE_PRIV_LNKMGMT = 0x8,
+       BE_PRIV_LNKDIAG = 0x10,
+       BE_PRIV_UTILQUERY = 0x20,
+       BE_PRIV_FILTMGMT = 0x40,
+       BE_PRIV_IFACEMGMT = 0x80,
+       BE_PRIV_VHADM = 0x100,
+       BE_PRIV_DEVCFG = 0x200,
+       BE_PRIV_DEVSEC = 0x400
+};
+#define MAX_PRIVILEGES         (BE_PRIV_VHADM | BE_PRIV_DEVCFG | \
+                                BE_PRIV_DEVSEC)
+#define MIN_PRIVILEGES         BE_PRIV_DEFAULT
+
+struct be_cmd_priv_map {
+       u8 opcode;
+       u8 subsystem;
+       u32 priv_mask;
+};
+
+struct be_cmd_req_get_fn_privileges {
+       struct be_cmd_req_hdr hdr;
+       u32 rsvd;
+};
+
+struct be_cmd_resp_get_fn_privileges {
+       struct be_cmd_resp_hdr hdr;
+       u32 privilege_mask;
+};
+
+
 /******************** GET/SET_MACLIST  **************************/
 #define BE_MAX_MAC                     64
 struct be_cmd_req_get_mac_list {
@@ -1684,6 +1732,96 @@ struct be_cmd_req_set_ext_fat_caps {
        struct be_fat_conf_params set_params;
 };
 
+#define RESOURCE_DESC_SIZE                     72
+#define NIC_RESOURCE_DESC_TYPE_ID              0x41
+#define MAX_RESOURCE_DESC                      4
+
+/* QOS unit number */
+#define QUN                                    4
+/* Immediate */
+#define IMM                                    6
+/* No save */
+#define NOSV                                   7
+
+struct be_nic_resource_desc {
+       u8 desc_type;
+       u8 desc_len;
+       u8 rsvd1;
+       u8 flags;
+       u8 vf_num;
+       u8 rsvd2;
+       u8 pf_num;
+       u8 rsvd3;
+       u16 unicast_mac_count;
+       u8 rsvd4[6];
+       u16 mcc_count;
+       u16 vlan_count;
+       u16 mcast_mac_count;
+       u16 txq_count;
+       u16 rq_count;
+       u16 rssq_count;
+       u16 lro_count;
+       u16 cq_count;
+       u16 toe_conn_count;
+       u16 eq_count;
+       u32 rsvd5;
+       u32 cap_flags;
+       u8 link_param;
+       u8 rsvd6[3];
+       u32 bw_min;
+       u32 bw_max;
+       u8 acpi_params;
+       u8 wol_param;
+       u16 rsvd7;
+       u32 rsvd8[3];
+};
+
+struct be_cmd_req_get_func_config {
+       struct be_cmd_req_hdr hdr;
+};
+
+struct be_cmd_resp_get_func_config {
+       struct be_cmd_req_hdr hdr;
+       u32 desc_count;
+       u8 func_param[MAX_RESOURCE_DESC * RESOURCE_DESC_SIZE];
+};
+
+#define ACTIVE_PROFILE_TYPE                    0x2
+struct be_cmd_req_get_profile_config {
+       struct be_cmd_req_hdr hdr;
+       u8 rsvd;
+       u8 type;
+       u16 rsvd1;
+};
+
+struct be_cmd_resp_get_profile_config {
+       struct be_cmd_req_hdr hdr;
+       u32 desc_count;
+       u8 func_param[MAX_RESOURCE_DESC * RESOURCE_DESC_SIZE];
+};
+
+struct be_cmd_req_set_profile_config {
+       struct be_cmd_req_hdr hdr;
+       u32 rsvd;
+       u32 desc_count;
+       struct be_nic_resource_desc nic_desc;
+};
+
+struct be_cmd_resp_set_profile_config {
+       struct be_cmd_req_hdr hdr;
+};
+
+struct be_cmd_enable_disable_vf {
+       struct be_cmd_req_hdr hdr;
+       u8 enable;
+       u8 rsvd[3];
+};
+
+static inline bool check_privilege(struct be_adapter *adapter, u32 flags)
+{
+       return flags & adapter->cmd_privileges ? true : false;
+}
+
 extern int be_pci_fnum_get(struct be_adapter *adapter);
 extern int be_fw_wait_ready(struct be_adapter *adapter);
 extern int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr,
@@ -1780,6 +1918,8 @@ extern int be_cmd_get_cntl_attributes(struct be_adapter *adapter);
 extern int be_cmd_req_native_mode(struct be_adapter *adapter);
 extern int be_cmd_get_reg_len(struct be_adapter *adapter, u32 *log_size);
 extern void be_cmd_get_regs(struct be_adapter *adapter, u32 buf_len, void *buf);
+extern int be_cmd_get_fn_privileges(struct be_adapter *adapter,
+                                   u32 *privilege, u32 domain);
 extern int be_cmd_get_mac_from_list(struct be_adapter *adapter, u8 *mac,
                                    bool *pmac_id_active, u32 *pmac_id,
                                    u8 domain);
@@ -1798,4 +1938,10 @@ extern int be_cmd_set_ext_fat_capabilites(struct be_adapter *adapter,
 extern int lancer_wait_ready(struct be_adapter *adapter);
 extern int lancer_test_and_set_rdy_state(struct be_adapter *adapter);
 extern int be_cmd_query_port_name(struct be_adapter *adapter, u8 *port_name);
+extern int be_cmd_get_func_config(struct be_adapter *adapter);
+extern int be_cmd_get_profile_config(struct be_adapter *adapter, u32 *cap_flags,
+                                    u8 domain);
 
+extern int be_cmd_set_profile_config(struct be_adapter *adapter, u32 bps,
+                                    u8 domain);
+extern int be_cmd_enable_vf(struct be_adapter *adapter, u8 domain);
index 8e6fb0ba6aa9631132686566859a8228c0c1fb86..00454a10f88d6111f5bfb30987703c04d807e8ba 100644 (file)
@@ -261,6 +261,9 @@ be_get_reg_len(struct net_device *netdev)
        struct be_adapter *adapter = netdev_priv(netdev);
        u32 log_size = 0;
 
+       if (!check_privilege(adapter, MAX_PRIVILEGES))
+               return 0;
+
        if (be_physfn(adapter)) {
                if (lancer_chip(adapter))
                        log_size = lancer_cmd_get_file_len(adapter,
@@ -525,6 +528,10 @@ static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
        u8 link_status;
        u16 link_speed = 0;
        int status;
+       u32 auto_speeds;
+       u32 fixed_speeds;
+       u32 dac_cable_len;
+       u16 interface_type;
 
        if (adapter->phy.link_speed < 0) {
                status = be_cmd_link_status_query(adapter, &link_speed,
@@ -534,39 +541,46 @@ static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
                ethtool_cmd_speed_set(ecmd, link_speed);
 
                status = be_cmd_get_phy_info(adapter);
-               if (status)
-                       return status;
-
-               ecmd->supported =
-                       convert_to_et_setting(adapter->phy.interface_type,
-                                       adapter->phy.auto_speeds_supported |
-                                       adapter->phy.fixed_speeds_supported);
-               ecmd->advertising =
-                       convert_to_et_setting(adapter->phy.interface_type,
-                                       adapter->phy.auto_speeds_supported);
-
-               ecmd->port = be_get_port_type(adapter->phy.interface_type,
-                                             adapter->phy.dac_cable_len);
-
-               if (adapter->phy.auto_speeds_supported) {
-                       ecmd->supported |= SUPPORTED_Autoneg;
-                       ecmd->autoneg = AUTONEG_ENABLE;
-                       ecmd->advertising |= ADVERTISED_Autoneg;
-               }
+               if (!status) {
+                       interface_type = adapter->phy.interface_type;
+                       auto_speeds = adapter->phy.auto_speeds_supported;
+                       fixed_speeds = adapter->phy.fixed_speeds_supported;
+                       dac_cable_len = adapter->phy.dac_cable_len;
+
+                       ecmd->supported =
+                               convert_to_et_setting(interface_type,
+                                                     auto_speeds |
+                                                     fixed_speeds);
+                       ecmd->advertising =
+                               convert_to_et_setting(interface_type,
+                                                     auto_speeds);
+
+                       ecmd->port = be_get_port_type(interface_type,
+                                                     dac_cable_len);
+
+                       if (adapter->phy.auto_speeds_supported) {
+                               ecmd->supported |= SUPPORTED_Autoneg;
+                               ecmd->autoneg = AUTONEG_ENABLE;
+                               ecmd->advertising |= ADVERTISED_Autoneg;
+                       }
 
-               if (be_pause_supported(adapter)) {
                        ecmd->supported |= SUPPORTED_Pause;
-                       ecmd->advertising |= ADVERTISED_Pause;
-               }
-
-               switch (adapter->phy.interface_type) {
-               case PHY_TYPE_KR_10GB:
-               case PHY_TYPE_KX4_10GB:
-                       ecmd->transceiver = XCVR_INTERNAL;
-                       break;
-               default:
-                       ecmd->transceiver = XCVR_EXTERNAL;
-                       break;
+                       if (be_pause_supported(adapter))
+                               ecmd->advertising |= ADVERTISED_Pause;
+
+                       switch (adapter->phy.interface_type) {
+                       case PHY_TYPE_KR_10GB:
+                       case PHY_TYPE_KX4_10GB:
+                               ecmd->transceiver = XCVR_INTERNAL;
+                               break;
+                       default:
+                               ecmd->transceiver = XCVR_EXTERNAL;
+                               break;
+                       }
+               } else {
+                       ecmd->port = PORT_OTHER;
+                       ecmd->autoneg = AUTONEG_DISABLE;
+                       ecmd->transceiver = XCVR_DUMMY1;
                }
 
                /* Save for future use */
@@ -787,6 +801,10 @@ static int
 be_get_eeprom_len(struct net_device *netdev)
 {
        struct be_adapter *adapter = netdev_priv(netdev);
+
+       if (!check_privilege(adapter, MAX_PRIVILEGES))
+               return 0;
+
        if (lancer_chip(adapter)) {
                if (be_physfn(adapter))
                        return lancer_cmd_get_file_len(adapter,
index b755f7061dce56edf88e486662c7d0c0b100a2a8..4ccbc36874e9ee6336cc287d98b0faad8ebaa9f2 100644 (file)
@@ -59,6 +59,9 @@
 #define PHYSDEV_CONTROL_FW_RESET_MASK  0x00000002
 #define PHYSDEV_CONTROL_INP_MASK       0x40000000
 
+#define SLIPORT_ERROR_NO_RESOURCE1     0x2
+#define SLIPORT_ERROR_NO_RESOURCE2     0x9
+
 /********* Memory BAR register ************/
 #define PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET     0xfc
 /* Host Interrupt Enable, if set interrupts are enabled although "PCI Interrupt
index d1b6cc5876393cc598a5d473fab158bb13477bdd..5e48674f72456cc7595a92e1bb77365ddd661a0e 100644 (file)
@@ -44,6 +44,7 @@ static DEFINE_PCI_DEVICE_TABLE(be_dev_ids) = {
        { PCI_DEVICE(EMULEX_VENDOR_ID, OC_DEVICE_ID3)},
        { PCI_DEVICE(EMULEX_VENDOR_ID, OC_DEVICE_ID4)},
        { PCI_DEVICE(EMULEX_VENDOR_ID, OC_DEVICE_ID5)},
+       { PCI_DEVICE(EMULEX_VENDOR_ID, OC_DEVICE_ID6)},
        { 0 }
 };
 MODULE_DEVICE_TABLE(pci, be_dev_ids);
@@ -237,23 +238,46 @@ static int be_mac_addr_set(struct net_device *netdev, void *p)
        int status = 0;
        u8 current_mac[ETH_ALEN];
        u32 pmac_id = adapter->pmac_id[0];
+       bool active_mac = true;
 
        if (!is_valid_ether_addr(addr->sa_data))
                return -EADDRNOTAVAIL;
 
-       status = be_cmd_mac_addr_query(adapter, current_mac, false,
-                                      adapter->if_handle, 0);
+       /* For BE VF, MAC address is already activated by PF.
+        * Hence only operation left is updating netdev->devaddr.
+        * Update it if user is passing the same MAC which was used
+        * during configuring VF MAC from PF(Hypervisor).
+        */
+       if (!lancer_chip(adapter) && !be_physfn(adapter)) {
+               status = be_cmd_mac_addr_query(adapter, current_mac,
+                                              false, adapter->if_handle, 0);
+               if (!status && !memcmp(current_mac, addr->sa_data, ETH_ALEN))
+                       goto done;
+               else
+                       goto err;
+       }
+
+       if (!memcmp(addr->sa_data, netdev->dev_addr, ETH_ALEN))
+               goto done;
+
+       /* For Lancer check if any MAC is active.
+        * If active, get its mac id.
+        */
+       if (lancer_chip(adapter) && !be_physfn(adapter))
+               be_cmd_get_mac_from_list(adapter, current_mac, &active_mac,
+                                        &pmac_id, 0);
+
+       status = be_cmd_pmac_add(adapter, (u8 *)addr->sa_data,
+                                adapter->if_handle,
+                                &adapter->pmac_id[0], 0);
+
        if (status)
                goto err;
 
-       if (memcmp(addr->sa_data, current_mac, ETH_ALEN)) {
-               status = be_cmd_pmac_add(adapter, (u8 *)addr->sa_data,
-                               adapter->if_handle, &adapter->pmac_id[0], 0);
-               if (status)
-                       goto err;
-
-               be_cmd_pmac_del(adapter, adapter->if_handle, pmac_id, 0);
-       }
+       if (active_mac)
+               be_cmd_pmac_del(adapter, adapter->if_handle,
+                               pmac_id, 0);
+done:
        memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
        return 0;
 err:
@@ -856,11 +880,15 @@ static int be_vlan_add_vid(struct net_device *netdev, u16 vid)
        struct be_adapter *adapter = netdev_priv(netdev);
        int status = 0;
 
-       if (!be_physfn(adapter)) {
+       if (!lancer_chip(adapter) && !be_physfn(adapter)) {
                status = -EINVAL;
                goto ret;
        }
 
+       /* Packets with VID 0 are always received by Lancer by default */
+       if (lancer_chip(adapter) && vid == 0)
+               goto ret;
+
        adapter->vlan_tag[vid] = 1;
        if (adapter->vlans_added <= (adapter->max_vlans + 1))
                status = be_vid_config(adapter);
@@ -878,11 +906,15 @@ static int be_vlan_rem_vid(struct net_device *netdev, u16 vid)
        struct be_adapter *adapter = netdev_priv(netdev);
        int status = 0;
 
-       if (!be_physfn(adapter)) {
+       if (!lancer_chip(adapter) && !be_physfn(adapter)) {
                status = -EINVAL;
                goto ret;
        }
 
+       /* Packets with VID 0 are always received by Lancer by default */
+       if (lancer_chip(adapter) && vid == 0)
+               goto ret;
+
        adapter->vlan_tag[vid] = 0;
        if (adapter->vlans_added <= adapter->max_vlans)
                status = be_vid_config(adapter);
@@ -917,7 +949,7 @@ static void be_set_rx_mode(struct net_device *netdev)
 
        /* Enable multicast promisc if num configured exceeds what we support */
        if (netdev->flags & IFF_ALLMULTI ||
-                       netdev_mc_count(netdev) > BE_MAX_MC) {
+           netdev_mc_count(netdev) > adapter->max_mcast_mac) {
                be_cmd_rx_filter(adapter, IFF_ALLMULTI, ON);
                goto done;
        }
@@ -962,6 +994,9 @@ static int be_set_vf_mac(struct net_device *netdev, int vf, u8 *mac)
        struct be_adapter *adapter = netdev_priv(netdev);
        struct be_vf_cfg *vf_cfg = &adapter->vf_cfg[vf];
        int status;
+       bool active_mac = false;
+       u32 pmac_id;
+       u8 old_mac[ETH_ALEN];
 
        if (!sriov_enabled(adapter))
                return -EPERM;
@@ -970,6 +1005,12 @@ static int be_set_vf_mac(struct net_device *netdev, int vf, u8 *mac)
                return -EINVAL;
 
        if (lancer_chip(adapter)) {
+               status = be_cmd_get_mac_from_list(adapter, old_mac, &active_mac,
+                                                 &pmac_id, vf + 1);
+               if (!status && active_mac)
+                       be_cmd_pmac_del(adapter, vf_cfg->if_handle,
+                                       pmac_id, vf + 1);
+
                status = be_cmd_set_mac_list(adapter,  mac, 1, vf + 1);
        } else {
                status = be_cmd_pmac_del(adapter, vf_cfg->if_handle,
@@ -1062,7 +1103,10 @@ static int be_set_vf_tx_rate(struct net_device *netdev,
                return -EINVAL;
        }
 
-       status = be_cmd_set_qos(adapter, rate / 10, vf + 1);
+       if (lancer_chip(adapter))
+               status = be_cmd_set_profile_config(adapter, rate / 10, vf + 1);
+       else
+               status = be_cmd_set_qos(adapter, rate / 10, vf + 1);
 
        if (status)
                dev_err(&adapter->pdev->dev,
@@ -1837,12 +1881,13 @@ static void be_tx_queues_destroy(struct be_adapter *adapter)
 
 static int be_num_txqs_want(struct be_adapter *adapter)
 {
-       if (sriov_want(adapter) || be_is_mc(adapter) ||
-           lancer_chip(adapter) || !be_physfn(adapter) ||
+       if ((!lancer_chip(adapter) && sriov_want(adapter)) ||
+           be_is_mc(adapter) ||
+           (!lancer_chip(adapter) && !be_physfn(adapter)) ||
            adapter->generation == BE_GEN2)
                return 1;
        else
-               return MAX_TX_QS;
+               return adapter->max_tx_queues;
 }
 
 static int be_tx_cqs_create(struct be_adapter *adapter)
@@ -2177,9 +2222,11 @@ static void be_msix_disable(struct be_adapter *adapter)
 static uint be_num_rss_want(struct be_adapter *adapter)
 {
        u32 num = 0;
+
        if ((adapter->function_caps & BE_FUNCTION_CAPS_RSS) &&
-            !sriov_want(adapter) && be_physfn(adapter)) {
-               num = (adapter->be3_native) ? BE3_MAX_RSS_QS : BE2_MAX_RSS_QS;
+           (lancer_chip(adapter) ||
+            (!sriov_want(adapter) && be_physfn(adapter)))) {
+               num = adapter->max_rss_queues;
                num = min_t(u32, num, (u32)netif_get_num_default_rss_queues());
        }
        return num;
@@ -2579,10 +2626,30 @@ static int be_clear(struct be_adapter *adapter)
        be_tx_queues_destroy(adapter);
        be_evt_queues_destroy(adapter);
 
+       kfree(adapter->pmac_id);
+       adapter->pmac_id = NULL;
+
        be_msix_disable(adapter);
        return 0;
 }
 
+static void be_get_vf_if_cap_flags(struct be_adapter *adapter,
+                                  u32 *cap_flags, u8 domain)
+{
+       bool profile_present = false;
+       int status;
+
+       if (lancer_chip(adapter)) {
+               status = be_cmd_get_profile_config(adapter, cap_flags, domain);
+               if (!status)
+                       profile_present = true;
+       }
+
+       if (!profile_present)
+               *cap_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST |
+                            BE_IF_FLAGS_MULTICAST;
+}
+
 static int be_vf_setup_init(struct be_adapter *adapter)
 {
        struct be_vf_cfg *vf_cfg;
@@ -2634,9 +2701,13 @@ static int be_vf_setup(struct be_adapter *adapter)
        if (status)
                goto err;
 
-       cap_flags = en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST |
-                               BE_IF_FLAGS_MULTICAST;
        for_all_vfs(adapter, vf_cfg, vf) {
+               be_get_vf_if_cap_flags(adapter, &cap_flags, vf + 1);
+
+               en_flags = cap_flags & (BE_IF_FLAGS_UNTAGGED |
+                                       BE_IF_FLAGS_BROADCAST |
+                                       BE_IF_FLAGS_MULTICAST);
+
                status = be_cmd_if_create(adapter, cap_flags, en_flags,
                                          &vf_cfg->if_handle, vf + 1);
                if (status)
@@ -2661,6 +2732,8 @@ static int be_vf_setup(struct be_adapter *adapter)
                if (status)
                        goto err;
                vf_cfg->def_vid = def_vlan;
+
+               be_cmd_enable_vf(adapter, vf + 1);
        }
        return 0;
 err:
@@ -2675,6 +2748,11 @@ static void be_setup_init(struct be_adapter *adapter)
        adapter->be3_native = false;
        adapter->promiscuous = false;
        adapter->eq_next_idx = 0;
+
+       if (be_physfn(adapter))
+               adapter->cmd_privileges = MAX_PRIVILEGES;
+       else
+               adapter->cmd_privileges = MIN_PRIVILEGES;
 }
 
 static int be_get_mac_addr(struct be_adapter *adapter, u8 *mac, u32 if_handle,
@@ -2712,12 +2790,93 @@ static int be_get_mac_addr(struct be_adapter *adapter, u8 *mac, u32 if_handle,
        return status;
 }
 
+static void be_get_resources(struct be_adapter *adapter)
+{
+       int status;
+       bool profile_present = false;
+
+       if (lancer_chip(adapter)) {
+               status = be_cmd_get_func_config(adapter);
+
+               if (!status)
+                       profile_present = true;
+       }
+
+       if (profile_present) {
+               /* Sanity fixes for Lancer */
+               adapter->max_pmac_cnt = min_t(u16, adapter->max_pmac_cnt,
+                                             BE_UC_PMAC_COUNT);
+               adapter->max_vlans = min_t(u16, adapter->max_vlans,
+                                          BE_NUM_VLANS_SUPPORTED);
+               adapter->max_mcast_mac = min_t(u16, adapter->max_mcast_mac,
+                                              BE_MAX_MC);
+               adapter->max_tx_queues = min_t(u16, adapter->max_tx_queues,
+                                              MAX_TX_QS);
+               adapter->max_rss_queues = min_t(u16, adapter->max_rss_queues,
+                                               BE3_MAX_RSS_QS);
+               adapter->max_event_queues = min_t(u16,
+                                                 adapter->max_event_queues,
+                                                 BE3_MAX_RSS_QS);
+
+               if (adapter->max_rss_queues &&
+                   adapter->max_rss_queues == adapter->max_rx_queues)
+                       adapter->max_rss_queues -= 1;
+
+               if (adapter->max_event_queues < adapter->max_rss_queues)
+                       adapter->max_rss_queues = adapter->max_event_queues;
+
+       } else {
+               if (be_physfn(adapter))
+                       adapter->max_pmac_cnt = BE_UC_PMAC_COUNT;
+               else
+                       adapter->max_pmac_cnt = BE_VF_UC_PMAC_COUNT;
+
+               if (adapter->function_mode & FLEX10_MODE)
+                       adapter->max_vlans = BE_NUM_VLANS_SUPPORTED/8;
+               else
+                       adapter->max_vlans = BE_NUM_VLANS_SUPPORTED;
+
+               adapter->max_mcast_mac = BE_MAX_MC;
+               adapter->max_tx_queues = MAX_TX_QS;
+               adapter->max_rss_queues = (adapter->be3_native) ?
+                                          BE3_MAX_RSS_QS : BE2_MAX_RSS_QS;
+               adapter->max_event_queues = BE3_MAX_RSS_QS;
+
+               adapter->if_cap_flags = BE_IF_FLAGS_UNTAGGED |
+                                       BE_IF_FLAGS_BROADCAST |
+                                       BE_IF_FLAGS_MULTICAST |
+                                       BE_IF_FLAGS_PASS_L3L4_ERRORS |
+                                       BE_IF_FLAGS_MCAST_PROMISCUOUS |
+                                       BE_IF_FLAGS_VLAN_PROMISCUOUS |
+                                       BE_IF_FLAGS_PROMISCUOUS;
+
+               if (adapter->function_caps & BE_FUNCTION_CAPS_RSS)
+                       adapter->if_cap_flags |= BE_IF_FLAGS_RSS;
+       }
+}
+
 /* Routine to query per function resource limits */
 static int be_get_config(struct be_adapter *adapter)
 {
-       int pos;
+       int pos, status;
        u16 dev_num_vfs;
 
+       status = be_cmd_query_fw_cfg(adapter, &adapter->port_num,
+                                    &adapter->function_mode,
+                                    &adapter->function_caps);
+       if (status)
+               goto err;
+
+       be_get_resources(adapter);
+
+       /* primary mac needs 1 pmac entry */
+       adapter->pmac_id = kcalloc(adapter->max_pmac_cnt + 1,
+                                  sizeof(u32), GFP_KERNEL);
+       if (!adapter->pmac_id) {
+               status = -ENOMEM;
+               goto err;
+       }
+
        pos = pci_find_ext_capability(adapter->pdev, PCI_EXT_CAP_ID_SRIOV);
        if (pos) {
                pci_read_config_word(adapter->pdev, pos + PCI_SRIOV_TOTAL_VF,
@@ -2726,13 +2885,14 @@ static int be_get_config(struct be_adapter *adapter)
                        dev_num_vfs = min_t(u16, dev_num_vfs, MAX_VFS);
                adapter->dev_num_vfs = dev_num_vfs;
        }
-       return 0;
+err:
+       return status;
 }
 
 static int be_setup(struct be_adapter *adapter)
 {
        struct device *dev = &adapter->pdev->dev;
-       u32 cap_flags, en_flags;
+       u32 en_flags;
        u32 tx_fc, rx_fc;
        int status;
        u8 mac[ETH_ALEN];
@@ -2740,9 +2900,12 @@ static int be_setup(struct be_adapter *adapter)
 
        be_setup_init(adapter);
 
-       be_get_config(adapter);
+       if (!lancer_chip(adapter))
+               be_cmd_req_native_mode(adapter);
 
-       be_cmd_req_native_mode(adapter);
+       status = be_get_config(adapter);
+       if (status)
+               goto err;
 
        be_msix_enable(adapter);
 
@@ -2762,24 +2925,22 @@ static int be_setup(struct be_adapter *adapter)
        if (status)
                goto err;
 
+       be_cmd_get_fn_privileges(adapter, &adapter->cmd_privileges, 0);
+       /* In UMC mode FW does not return right privileges.
+        * Override with correct privilege equivalent to PF.
+        */
+       if (be_is_mc(adapter))
+               adapter->cmd_privileges = MAX_PRIVILEGES;
+
        en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST |
                        BE_IF_FLAGS_MULTICAST | BE_IF_FLAGS_PASS_L3L4_ERRORS;
-       cap_flags = en_flags | BE_IF_FLAGS_MCAST_PROMISCUOUS |
-                       BE_IF_FLAGS_VLAN_PROMISCUOUS | BE_IF_FLAGS_PROMISCUOUS;
 
-       if (adapter->function_caps & BE_FUNCTION_CAPS_RSS) {
-               cap_flags |= BE_IF_FLAGS_RSS;
+       if (adapter->function_caps & BE_FUNCTION_CAPS_RSS)
                en_flags |= BE_IF_FLAGS_RSS;
-       }
 
-       if (lancer_chip(adapter) && !be_physfn(adapter)) {
-               en_flags = BE_IF_FLAGS_UNTAGGED |
-                           BE_IF_FLAGS_BROADCAST |
-                           BE_IF_FLAGS_MULTICAST;
-               cap_flags = en_flags;
-       }
+       en_flags = en_flags & adapter->if_cap_flags;
 
-       status = be_cmd_if_create(adapter, cap_flags, en_flags,
+       status = be_cmd_if_create(adapter, adapter->if_cap_flags, en_flags,
                                  &adapter->if_handle, 0);
        if (status != 0)
                goto err;
@@ -2827,8 +2988,8 @@ static int be_setup(struct be_adapter *adapter)
                        dev_warn(dev, "device doesn't support SRIOV\n");
        }
 
-       be_cmd_get_phy_info(adapter);
-       if (be_pause_supported(adapter))
+       status = be_cmd_get_phy_info(adapter);
+       if (!status && be_pause_supported(adapter))
                adapter->phy.fc_autoneg = 1;
 
        schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000));
@@ -2928,6 +3089,47 @@ struct flash_section_info *get_fsec_info(struct be_adapter *adapter,
        return NULL;
 }
 
+static int be_flash(struct be_adapter *adapter, const u8 *img,
+               struct be_dma_mem *flash_cmd, int optype, int img_size)
+{
+       u32 total_bytes = 0, flash_op, num_bytes = 0;
+       int status = 0;
+       struct be_cmd_write_flashrom *req = flash_cmd->va;
+
+       total_bytes = img_size;
+       while (total_bytes) {
+               num_bytes = min_t(u32, 32*1024, total_bytes);
+
+               total_bytes -= num_bytes;
+
+               if (!total_bytes) {
+                       if (optype == OPTYPE_PHY_FW)
+                               flash_op = FLASHROM_OPER_PHY_FLASH;
+                       else
+                               flash_op = FLASHROM_OPER_FLASH;
+               } else {
+                       if (optype == OPTYPE_PHY_FW)
+                               flash_op = FLASHROM_OPER_PHY_SAVE;
+                       else
+                               flash_op = FLASHROM_OPER_SAVE;
+               }
+
+               memcpy(req->data_buf, img, num_bytes);
+               img += num_bytes;
+               status = be_cmd_write_flashrom(adapter, flash_cmd, optype,
+                                               flash_op, num_bytes);
+               if (status) {
+                       if (status == ILLEGAL_IOCTL_REQ &&
+                           optype == OPTYPE_PHY_FW)
+                               break;
+                       dev_err(&adapter->pdev->dev,
+                               "cmd to write to flash rom failed.\n");
+                       return status;
+               }
+       }
+       return 0;
+}
+
 static int be_flash_data(struct be_adapter *adapter,
                         const struct firmware *fw,
                         struct be_dma_mem *flash_cmd,
@@ -2936,12 +3138,9 @@ static int be_flash_data(struct be_adapter *adapter,
 {
        int status = 0, i, filehdr_size = 0;
        int img_hdrs_size = (num_of_images * sizeof(struct image_hdr));
-       u32 total_bytes = 0, flash_op;
-       int num_bytes;
        const u8 *p = fw->data;
-       struct be_cmd_write_flashrom *req = flash_cmd->va;
        const struct flash_comp *pflashcomp;
-       int num_comp, hdr_size;
+       int num_comp, redboot;
        struct flash_section_info *fsec = NULL;
 
        struct flash_comp gen3_flash_types[] = {
@@ -3010,70 +3209,105 @@ static int be_flash_data(struct be_adapter *adapter,
                    memcmp(adapter->fw_ver, "3.102.148.0", 11) < 0)
                        continue;
 
-               if (pflashcomp[i].optype == OPTYPE_PHY_FW) {
-                       if (!phy_flashing_required(adapter))
+               if (pflashcomp[i].optype == OPTYPE_PHY_FW  &&
+                   !phy_flashing_required(adapter))
                                continue;
-               }
 
-               hdr_size = filehdr_size +
-                          (num_of_images * sizeof(struct image_hdr));
-
-               if ((pflashcomp[i].optype == OPTYPE_REDBOOT) &&
-                   (!be_flash_redboot(adapter, fw->data, pflashcomp[i].offset,
-                                      pflashcomp[i].size, hdr_size)))
-                       continue;
+               if (pflashcomp[i].optype == OPTYPE_REDBOOT) {
+                       redboot = be_flash_redboot(adapter, fw->data,
+                               pflashcomp[i].offset, pflashcomp[i].size,
+                               filehdr_size + img_hdrs_size);
+                       if (!redboot)
+                               continue;
+               }
 
-               /* Flash the component */
                p = fw->data;
                p += filehdr_size + pflashcomp[i].offset + img_hdrs_size;
                if (p + pflashcomp[i].size > fw->data + fw->size)
                        return -1;
-               total_bytes = pflashcomp[i].size;
-               while (total_bytes) {
-                       if (total_bytes > 32*1024)
-                               num_bytes = 32*1024;
-                       else
-                               num_bytes = total_bytes;
-                       total_bytes -= num_bytes;
-                       if (!total_bytes) {
-                               if (pflashcomp[i].optype == OPTYPE_PHY_FW)
-                                       flash_op = FLASHROM_OPER_PHY_FLASH;
-                               else
-                                       flash_op = FLASHROM_OPER_FLASH;
-                       } else {
-                               if (pflashcomp[i].optype == OPTYPE_PHY_FW)
-                                       flash_op = FLASHROM_OPER_PHY_SAVE;
-                               else
-                                       flash_op = FLASHROM_OPER_SAVE;
-                       }
-                       memcpy(req->params.data_buf, p, num_bytes);
-                       p += num_bytes;
-                       status = be_cmd_write_flashrom(adapter, flash_cmd,
-                               pflashcomp[i].optype, flash_op, num_bytes);
-                       if (status) {
-                               if ((status == ILLEGAL_IOCTL_REQ) &&
-                                       (pflashcomp[i].optype ==
-                                               OPTYPE_PHY_FW))
-                                       break;
-                               dev_err(&adapter->pdev->dev,
-                                       "cmd to write to flash rom failed.\n");
-                               return -1;
-                       }
+
+               status = be_flash(adapter, p, flash_cmd, pflashcomp[i].optype,
+                                       pflashcomp[i].size);
+               if (status) {
+                       dev_err(&adapter->pdev->dev,
+                               "Flashing section type %d failed.\n",
+                               pflashcomp[i].img_type);
+                       return status;
                }
        }
        return 0;
 }
 
-static int get_ufigen_type(struct flash_file_hdr_g2 *fhdr)
+static int be_flash_skyhawk(struct be_adapter *adapter,
+               const struct firmware *fw,
+               struct be_dma_mem *flash_cmd, int num_of_images)
 {
-       if (fhdr == NULL)
-               return 0;
-       if (fhdr->build[0] == '3')
-               return BE_GEN3;
-       else if (fhdr->build[0] == '2')
-               return BE_GEN2;
-       else
-               return 0;
+       int status = 0, i, filehdr_size = 0;
+       int img_offset, img_size, img_optype, redboot;
+       int img_hdrs_size = num_of_images * sizeof(struct image_hdr);
+       const u8 *p = fw->data;
+       struct flash_section_info *fsec = NULL;
+
+       filehdr_size = sizeof(struct flash_file_hdr_g3);
+       fsec = get_fsec_info(adapter, filehdr_size + img_hdrs_size, fw);
+       if (!fsec) {
+               dev_err(&adapter->pdev->dev,
+                       "Invalid Cookie. UFI corrupted ?\n");
+               return -1;
+       }
+
+       for (i = 0; i < le32_to_cpu(fsec->fsec_hdr.num_images); i++) {
+               img_offset = le32_to_cpu(fsec->fsec_entry[i].offset);
+               img_size   = le32_to_cpu(fsec->fsec_entry[i].pad_size);
+
+               switch (le32_to_cpu(fsec->fsec_entry[i].type)) {
+               case IMAGE_FIRMWARE_iSCSI:
+                       img_optype = OPTYPE_ISCSI_ACTIVE;
+                       break;
+               case IMAGE_BOOT_CODE:
+                       img_optype = OPTYPE_REDBOOT;
+                       break;
+               case IMAGE_OPTION_ROM_ISCSI:
+                       img_optype = OPTYPE_BIOS;
+                       break;
+               case IMAGE_OPTION_ROM_PXE:
+                       img_optype = OPTYPE_PXE_BIOS;
+                       break;
+               case IMAGE_OPTION_ROM_FCoE:
+                       img_optype = OPTYPE_FCOE_BIOS;
+                       break;
+               case IMAGE_FIRMWARE_BACKUP_iSCSI:
+                       img_optype = OPTYPE_ISCSI_BACKUP;
+                       break;
+               case IMAGE_NCSI:
+                       img_optype = OPTYPE_NCSI_FW;
+                       break;
+               default:
+                       continue;
+               }
+
+               if (img_optype == OPTYPE_REDBOOT) {
+                       redboot = be_flash_redboot(adapter, fw->data,
+                                       img_offset, img_size,
+                                       filehdr_size + img_hdrs_size);
+                       if (!redboot)
+                               continue;
+               }
+
+               p = fw->data;
+               p += filehdr_size + img_offset + img_hdrs_size;
+               if (p + img_size > fw->data + fw->size)
+                       return -1;
+
+               status = be_flash(adapter, p, flash_cmd, img_optype, img_size);
+               if (status) {
+                       dev_err(&adapter->pdev->dev,
+                               "Flashing section type %d failed.\n",
+                               fsec->fsec_entry[i].type);
+                       return status;
+               }
+       }
+       return 0;
 }
 
 static int lancer_wait_idle(struct be_adapter *adapter)
@@ -3207,6 +3441,27 @@ lancer_fw_exit:
        return status;
 }
 
+static int be_get_ufi_gen(struct be_adapter *adapter,
+                       struct flash_file_hdr_g2 *fhdr)
+{
+       if (fhdr == NULL)
+               goto be_get_ufi_exit;
+
+       if (adapter->generation == BE_GEN3) {
+               if (skyhawk_chip(adapter) && fhdr->build[0] == '4')
+                       return SH_HW;
+               else if (!skyhawk_chip(adapter) && fhdr->build[0] == '3')
+                       return BE_GEN3;
+       } else if (adapter->generation == BE_GEN2 && fhdr->build[0] == '2') {
+                       return BE_GEN2;
+       }
+
+be_get_ufi_exit:
+       dev_err(&adapter->pdev->dev,
+               "UFI and Interface are not compatible for flashing\n");
+       return -1;
+}
+
 static int be_fw_download(struct be_adapter *adapter, const struct firmware* fw)
 {
        struct flash_file_hdr_g2 *fhdr;
@@ -3214,12 +3469,9 @@ static int be_fw_download(struct be_adapter *adapter, const struct firmware* fw)
        struct image_hdr *img_hdr_ptr = NULL;
        struct be_dma_mem flash_cmd;
        const u8 *p;
-       int status = 0, i = 0, num_imgs = 0;
-
-       p = fw->data;
-       fhdr = (struct flash_file_hdr_g2 *) p;
+       int status = 0, i = 0, num_imgs = 0, ufi_type = 0;
 
-       flash_cmd.size = sizeof(struct be_cmd_write_flashrom) + 32*1024;
+       flash_cmd.size = sizeof(struct be_cmd_write_flashrom);
        flash_cmd.va = dma_alloc_coherent(&adapter->pdev->dev, flash_cmd.size,
                                          &flash_cmd.dma, GFP_KERNEL);
        if (!flash_cmd.va) {
@@ -3229,26 +3481,31 @@ static int be_fw_download(struct be_adapter *adapter, const struct firmware* fw)
                goto be_fw_exit;
        }
 
-       if ((adapter->generation == BE_GEN3) &&
-                       (get_ufigen_type(fhdr) == BE_GEN3)) {
-               fhdr3 = (struct flash_file_hdr_g3 *) fw->data;
-               num_imgs = le32_to_cpu(fhdr3->num_imgs);
-               for (i = 0; i < num_imgs; i++) {
-                       img_hdr_ptr = (struct image_hdr *) (fw->data +
-                                       (sizeof(struct flash_file_hdr_g3) +
-                                        i * sizeof(struct image_hdr)));
-                       if (le32_to_cpu(img_hdr_ptr->imageid) == 1)
-                               status = be_flash_data(adapter, fw, &flash_cmd,
-                                                       num_imgs);
+       p = fw->data;
+       fhdr = (struct flash_file_hdr_g2 *)p;
+
+       ufi_type = be_get_ufi_gen(adapter, fhdr);
+
+       fhdr3 = (struct flash_file_hdr_g3 *)fw->data;
+       num_imgs = le32_to_cpu(fhdr3->num_imgs);
+       for (i = 0; i < num_imgs; i++) {
+               img_hdr_ptr = (struct image_hdr *)(fw->data +
+                               (sizeof(struct flash_file_hdr_g3) +
+                                i * sizeof(struct image_hdr)));
+               if (le32_to_cpu(img_hdr_ptr->imageid) == 1) {
+                       if (ufi_type == SH_HW)
+                               status = be_flash_skyhawk(adapter, fw,
+                                                       &flash_cmd, num_imgs);
+                       else if (ufi_type == BE_GEN3)
+                               status = be_flash_data(adapter, fw,
+                                                       &flash_cmd, num_imgs);
                }
-       } else if ((adapter->generation == BE_GEN2) &&
-                       (get_ufigen_type(fhdr) == BE_GEN2)) {
+       }
+
+       if (ufi_type == BE_GEN2)
                status = be_flash_data(adapter, fw, &flash_cmd, 0);
-       } else {
-               dev_err(&adapter->pdev->dev,
-                       "UFI and Interface are not compatible for flashing\n");
+       else if (ufi_type == -1)
                status = -1;
-       }
 
        dma_free_coherent(&adapter->pdev->dev, flash_cmd.size, flash_cmd.va,
                          flash_cmd.dma);
@@ -3437,7 +3694,6 @@ static void be_ctrl_cleanup(struct be_adapter *adapter)
        if (mem->va)
                dma_free_coherent(&adapter->pdev->dev, mem->size, mem->va,
                                  mem->dma);
-       kfree(adapter->pmac_id);
 }
 
 static int be_ctrl_init(struct be_adapter *adapter)
@@ -3473,13 +3729,6 @@ static int be_ctrl_init(struct be_adapter *adapter)
                goto free_mbox;
        }
        memset(rx_filter->va, 0, rx_filter->size);
-
-       /* primary mac needs 1 pmac entry */
-       adapter->pmac_id = kcalloc(adapter->max_pmac_cnt + 1,
-                                  sizeof(*adapter->pmac_id), GFP_KERNEL);
-       if (!adapter->pmac_id)
-               return -ENOMEM;
-
        mutex_init(&adapter->mbox_lock);
        spin_lock_init(&adapter->mcc_lock);
        spin_lock_init(&adapter->mcc_cq_lock);
@@ -3573,6 +3822,9 @@ u32 be_get_fw_log_level(struct be_adapter *adapter)
        u32 level = 0;
        int j;
 
+       if (lancer_chip(adapter))
+               return 0;
+
        memset(&extfat_cmd, 0, sizeof(struct be_dma_mem));
        extfat_cmd.size = sizeof(struct be_cmd_resp_get_ext_fat_caps);
        extfat_cmd.va = pci_alloc_consistent(adapter->pdev, extfat_cmd.size,
@@ -3598,26 +3850,12 @@ u32 be_get_fw_log_level(struct be_adapter *adapter)
 err:
        return level;
 }
+
 static int be_get_initial_config(struct be_adapter *adapter)
 {
        int status;
        u32 level;
 
-       status = be_cmd_query_fw_cfg(adapter, &adapter->port_num,
-                       &adapter->function_mode, &adapter->function_caps);
-       if (status)
-               return status;
-
-       if (adapter->function_mode & FLEX10_MODE)
-               adapter->max_vlans = BE_NUM_VLANS_SUPPORTED/8;
-       else
-               adapter->max_vlans = BE_NUM_VLANS_SUPPORTED;
-
-       if (be_physfn(adapter))
-               adapter->max_pmac_cnt = BE_UC_PMAC_COUNT;
-       else
-               adapter->max_pmac_cnt = BE_VF_UC_PMAC_COUNT;
-
        status = be_cmd_get_cntl_attributes(adapter);
        if (status)
                return status;
@@ -3673,6 +3911,7 @@ static int be_dev_type_check(struct be_adapter *adapter)
                adapter->generation = BE_GEN3;
                break;
        case OC_DEVICE_ID5:
+       case OC_DEVICE_ID6:
                pci_read_config_dword(pdev, SLI_INTF_REG_OFFSET, &sli_intf);
                if ((sli_intf & SLI_INTF_VALID_MASK) != SLI_INTF_VALID) {
                        dev_err(&pdev->dev, "SLI_INTF reg val is not valid\n");
@@ -3721,8 +3960,9 @@ static int lancer_recover_func(struct be_adapter *adapter)
                "Adapter SLIPORT recovery succeeded\n");
        return 0;
 err:
-       dev_err(&adapter->pdev->dev,
-               "Adapter SLIPORT recovery failed\n");
+       if (adapter->eeh_error)
+               dev_err(&adapter->pdev->dev,
+                       "Adapter SLIPORT recovery failed\n");
 
        return status;
 }
@@ -4023,9 +4263,6 @@ static void be_shutdown(struct pci_dev *pdev)
 
        netif_device_detach(adapter->netdev);
 
-       if (adapter->wol)
-               be_setup_wol(adapter, true);
-
        be_cmd_reset_function(adapter);
 
        pci_disable_device(pdev);
@@ -4061,9 +4298,13 @@ static pci_ers_result_t be_eeh_err_detected(struct pci_dev *pdev,
 
        /* The error could cause the FW to trigger a flash debug dump.
         * Resetting the card while flash dump is in progress
-        * can cause it not to recover; wait for it to finish
+        * can cause it not to recover; wait for it to finish.
+        * Wait only for first function as it is needed only once per
+        * adapter.
         */
-       ssleep(30);
+       if (pdev->devfn == 0)
+               ssleep(30);
+
        return PCI_ERS_RESULT_NEED_RESET;
 }
 
index f444eb0b76d8d9c0c7147b8dc4a9fa7266d517b9..dadb13be479af807812c4291e74cf99481f4019d 100644 (file)
@@ -5067,6 +5067,17 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
                return NETDEV_TX_OK;
        }
 
+       /*
+        * The minimum packet size with TCTL.PSP set is 17 bytes so
+        * pad skb in order to meet this minimum size requirement
+        */
+       if (unlikely(skb->len < 17)) {
+               if (skb_pad(skb, 17 - skb->len))
+                       return NETDEV_TX_OK;
+               skb->len = 17;
+               skb_set_tail_pointer(skb, 17);
+       }
+
        mss = skb_shinfo(skb)->gso_size;
        if (mss) {
                u8 hdr_len;
index e85c453f5428cf31723373468d51f64099e10fca..44b76b3b6816692f2bcea6682950791a92164bda 100644 (file)
@@ -172,10 +172,13 @@ struct e1000_adv_tx_context_desc {
 #define E1000_DCA_RXCTRL_DESC_DCA_EN (1 << 5) /* DCA Rx Desc enable */
 #define E1000_DCA_RXCTRL_HEAD_DCA_EN (1 << 6) /* DCA Rx Desc header enable */
 #define E1000_DCA_RXCTRL_DATA_DCA_EN (1 << 7) /* DCA Rx Desc payload enable */
+#define E1000_DCA_RXCTRL_DESC_RRO_EN (1 << 9) /* DCA Rx rd Desc Relax Order */
 
 #define E1000_DCA_TXCTRL_CPUID_MASK 0x0000001F /* Tx CPUID Mask */
 #define E1000_DCA_TXCTRL_DESC_DCA_EN (1 << 5) /* DCA Tx Desc enable */
+#define E1000_DCA_TXCTRL_DESC_RRO_EN (1 << 9) /* Tx rd Desc Relax Order */
 #define E1000_DCA_TXCTRL_TX_WB_RO_EN (1 << 11) /* Tx Desc writeback RO bit */
+#define E1000_DCA_TXCTRL_DATA_RRO_EN (1 << 13) /* Tx rd data Relax Order */
 
 /* Additional DCA related definitions, note change in position of CPUID */
 #define E1000_DCA_TXCTRL_CPUID_MASK_82576 0xFF000000 /* Tx CPUID Mask */
index 3404bc79f4cadf76382c5dbfca62b4d4ebe1f693..c62a4c388194f6e31e0bb793c45e0b28f20c406e 100644 (file)
@@ -1710,6 +1710,26 @@ s32 igb_get_cable_length_m88_gen2(struct e1000_hw *hw)
 
        switch (hw->phy.id) {
        case I210_I_PHY_ID:
+               /* Get cable length from PHY Cable Diagnostics Control Reg */
+               ret_val = phy->ops.read_reg(hw, (0x7 << GS40G_PAGE_SHIFT) +
+                                           (I347AT4_PCDL + phy->addr),
+                                           &phy_data);
+               if (ret_val)
+                       return ret_val;
+
+               /* Check if the unit of cable length is meters or cm */
+               ret_val = phy->ops.read_reg(hw, (0x7 << GS40G_PAGE_SHIFT) +
+                                           I347AT4_PCDC, &phy_data2);
+               if (ret_val)
+                       return ret_val;
+
+               is_cm = !(phy_data2 & I347AT4_PCDC_CABLE_LENGTH_UNIT);
+
+               /* Populate the phy structure with cable length in meters */
+               phy->min_cable_length = phy_data / (is_cm ? 100 : 1);
+               phy->max_cable_length = phy_data / (is_cm ? 100 : 1);
+               phy->cable_length = phy_data / (is_cm ? 100 : 1);
+               break;
        case I347AT4_E_PHY_ID:
                /* Remember the original page select and set it to 7 */
                ret_val = phy->ops.read_reg(hw, I347AT4_PAGE_SELECT,
index 8aad230c0592e03f5f3b753f636f0a38dd35d4a3..be1971b18297e4f9791ab8a6d8f8c15bc60642e5 100644 (file)
@@ -132,9 +132,10 @@ struct vf_data_storage {
 #define MAXIMUM_ETHERNET_VLAN_SIZE 1522
 
 /* Supported Rx Buffer Sizes */
-#define IGB_RXBUFFER_256   256
-#define IGB_RXBUFFER_16384 16384
-#define IGB_RX_HDR_LEN     IGB_RXBUFFER_256
+#define IGB_RXBUFFER_256       256
+#define IGB_RXBUFFER_2048      2048
+#define IGB_RX_HDR_LEN         IGB_RXBUFFER_256
+#define IGB_RX_BUFSZ           IGB_RXBUFFER_2048
 
 /* How many Tx Descriptors do we need to call netif_wake_queue ? */
 #define IGB_TX_QUEUE_WAKE      16
@@ -174,11 +175,9 @@ struct igb_tx_buffer {
 };
 
 struct igb_rx_buffer {
-       struct sk_buff *skb;
        dma_addr_t dma;
        struct page *page;
-       dma_addr_t page_dma;
-       u32 page_offset;
+       unsigned int page_offset;
 };
 
 struct igb_tx_queue_stats {
@@ -205,22 +204,6 @@ struct igb_ring_container {
        u8 itr;                         /* current ITR setting for ring */
 };
 
-struct igb_q_vector {
-       struct igb_adapter *adapter;    /* backlink */
-       int cpu;                        /* CPU for DCA */
-       u32 eims_value;                 /* EIMS mask value */
-
-       struct igb_ring_container rx, tx;
-
-       struct napi_struct napi;
-
-       u16 itr_val;
-       u8 set_itr;
-       void __iomem *itr_register;
-
-       char name[IFNAMSIZ + 9];
-};
-
 struct igb_ring {
        struct igb_q_vector *q_vector;  /* backlink to q_vector */
        struct net_device *netdev;      /* back pointer to net_device */
@@ -232,15 +215,17 @@ struct igb_ring {
        void *desc;                     /* descriptor ring memory */
        unsigned long flags;            /* ring specific flags */
        void __iomem *tail;             /* pointer to ring tail register */
+       dma_addr_t dma;                 /* phys address of the ring */
+       unsigned int  size;             /* length of desc. ring in bytes */
 
        u16 count;                      /* number of desc. in the ring */
        u8 queue_index;                 /* logical index of the ring*/
        u8 reg_idx;                     /* physical index of the ring */
-       u32 size;                       /* length of desc. ring in bytes */
 
        /* everything past this point are written often */
-       u16 next_to_clean ____cacheline_aligned_in_smp;
+       u16 next_to_clean;
        u16 next_to_use;
+       u16 next_to_alloc;
 
        union {
                /* TX */
@@ -251,12 +236,30 @@ struct igb_ring {
                };
                /* RX */
                struct {
+                       struct sk_buff *skb;
                        struct igb_rx_queue_stats rx_stats;
                        struct u64_stats_sync rx_syncp;
                };
        };
-       /* Items past this point are only used during ring alloc / free */
-       dma_addr_t dma;                /* phys address of the ring */
+} ____cacheline_internodealigned_in_smp;
+
+struct igb_q_vector {
+       struct igb_adapter *adapter;    /* backlink */
+       int cpu;                        /* CPU for DCA */
+       u32 eims_value;                 /* EIMS mask value */
+
+       u16 itr_val;
+       u8 set_itr;
+       void __iomem *itr_register;
+
+       struct igb_ring_container rx, tx;
+
+       struct napi_struct napi;
+       struct rcu_head rcu;    /* to avoid race with update stats on free */
+       char name[IFNAMSIZ + 9];
+
+       /* for dynamic allocation of rings associated with this q_vector */
+       struct igb_ring ring[0] ____cacheline_internodealigned_in_smp;
 };
 
 enum e1000_ring_flags_t {
@@ -442,9 +445,20 @@ extern void igb_ptp_stop(struct igb_adapter *adapter);
 extern void igb_ptp_reset(struct igb_adapter *adapter);
 extern void igb_ptp_tx_work(struct work_struct *work);
 extern void igb_ptp_tx_hwtstamp(struct igb_adapter *adapter);
-extern void igb_ptp_rx_hwtstamp(struct igb_q_vector *q_vector,
-                               union e1000_adv_rx_desc *rx_desc,
+extern void igb_ptp_rx_rgtstamp(struct igb_q_vector *q_vector,
                                struct sk_buff *skb);
+extern void igb_ptp_rx_pktstamp(struct igb_q_vector *q_vector,
+                               unsigned char *va,
+                               struct sk_buff *skb);
+static inline void igb_ptp_rx_hwtstamp(struct igb_q_vector *q_vector,
+                                      union e1000_adv_rx_desc *rx_desc,
+                                      struct sk_buff *skb)
+{
+       if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TS) &&
+           !igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP))
+               igb_ptp_rx_rgtstamp(q_vector, skb);
+}
+
 extern int igb_ptp_hwtstamp_ioctl(struct net_device *netdev,
                                  struct ifreq *ifr, int cmd);
 #endif /* CONFIG_IGB_PTP */
index 2ea012849825224af910ba7189aa850b58610806..375c0dad8d2999065ef6934017dd93ef30fc8a1a 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/pm_runtime.h>
+#include <linux/highmem.h>
 
 #include "igb.h"
 
@@ -1685,16 +1686,24 @@ static void igb_create_lbtest_frame(struct sk_buff *skb,
        memset(&skb->data[frame_size + 12], 0xAF, 1);
 }
 
-static int igb_check_lbtest_frame(struct sk_buff *skb, unsigned int frame_size)
+static int igb_check_lbtest_frame(struct igb_rx_buffer *rx_buffer,
+                                 unsigned int frame_size)
 {
-       frame_size /= 2;
-       if (*(skb->data + 3) == 0xFF) {
-               if ((*(skb->data + frame_size + 10) == 0xBE) &&
-                  (*(skb->data + frame_size + 12) == 0xAF)) {
-                       return 0;
-               }
-       }
-       return 13;
+       unsigned char *data;
+       bool match = true;
+
+       frame_size >>= 1;
+
+       data = kmap(rx_buffer->page);
+
+       if (data[3] != 0xFF ||
+           data[frame_size + 10] != 0xBE ||
+           data[frame_size + 12] != 0xAF)
+               match = false;
+
+       kunmap(rx_buffer->page);
+
+       return match;
 }
 
 static int igb_clean_test_rings(struct igb_ring *rx_ring,
@@ -1704,9 +1713,7 @@ static int igb_clean_test_rings(struct igb_ring *rx_ring,
        union e1000_adv_rx_desc *rx_desc;
        struct igb_rx_buffer *rx_buffer_info;
        struct igb_tx_buffer *tx_buffer_info;
-       struct netdev_queue *txq;
        u16 rx_ntc, tx_ntc, count = 0;
-       unsigned int total_bytes = 0, total_packets = 0;
 
        /* initialize next to clean and descriptor values */
        rx_ntc = rx_ring->next_to_clean;
@@ -1717,21 +1724,24 @@ static int igb_clean_test_rings(struct igb_ring *rx_ring,
                /* check rx buffer */
                rx_buffer_info = &rx_ring->rx_buffer_info[rx_ntc];
 
-               /* unmap rx buffer, will be remapped by alloc_rx_buffers */
-               dma_unmap_single(rx_ring->dev,
-                                rx_buffer_info->dma,
-                                IGB_RX_HDR_LEN,
-                                DMA_FROM_DEVICE);
-               rx_buffer_info->dma = 0;
+               /* sync Rx buffer for CPU read */
+               dma_sync_single_for_cpu(rx_ring->dev,
+                                       rx_buffer_info->dma,
+                                       IGB_RX_BUFSZ,
+                                       DMA_FROM_DEVICE);
 
                /* verify contents of skb */
-               if (!igb_check_lbtest_frame(rx_buffer_info->skb, size))
+               if (igb_check_lbtest_frame(rx_buffer_info, size))
                        count++;
 
+               /* sync Rx buffer for device write */
+               dma_sync_single_for_device(rx_ring->dev,
+                                          rx_buffer_info->dma,
+                                          IGB_RX_BUFSZ,
+                                          DMA_FROM_DEVICE);
+
                /* unmap buffer on tx side */
                tx_buffer_info = &tx_ring->tx_buffer_info[tx_ntc];
-               total_bytes += tx_buffer_info->bytecount;
-               total_packets += tx_buffer_info->gso_segs;
                igb_unmap_and_free_tx_resource(tx_ring, tx_buffer_info);
 
                /* increment rx/tx next to clean counters */
@@ -1746,8 +1756,7 @@ static int igb_clean_test_rings(struct igb_ring *rx_ring,
                rx_desc = IGB_RX_DESC(rx_ring, rx_ntc);
        }
 
-       txq = netdev_get_tx_queue(tx_ring->netdev, tx_ring->queue_index);
-       netdev_tx_completed_queue(txq, total_packets, total_bytes);
+       netdev_tx_reset_queue(txring_txq(tx_ring));
 
        /* re-map buffers to ring, store next to clean values */
        igb_alloc_rx_buffers(rx_ring, count);
index e1ceb37ef12e406fd7ff6dff13b08c18548fcea6..b07d679b46f295d4535b5fadd948e63432e966df 100644 (file)
@@ -61,7 +61,7 @@
 
 #define MAJ 4
 #define MIN 0
-#define BUILD 1
+#define BUILD 17
 #define DRV_VERSION __stringify(MAJ) "." __stringify(MIN) "." \
 __stringify(BUILD) "-k"
 char igb_driver_name[] = "igb";
@@ -534,31 +534,27 @@ rx_ring_summary:
 
                        if (staterr & E1000_RXD_STAT_DD) {
                                /* Descriptor Done */
-                               pr_info("%s[0x%03X]     %016llX %016llX -------"
-                                       "--------- %p%s\n", "RWB", i,
+                               pr_info("%s[0x%03X]     %016llX %016llX ---------------- %s\n",
+                                       "RWB", i,
                                        le64_to_cpu(u0->a),
                                        le64_to_cpu(u0->b),
-                                       buffer_info->skb, next_desc);
+                                       next_desc);
                        } else {
-                               pr_info("%s[0x%03X]     %016llX %016llX %016llX"
-                                       " %p%s\n", "R  ", i,
+                               pr_info("%s[0x%03X]     %016llX %016llX %016llX %s\n",
+                                       "R  ", i,
                                        le64_to_cpu(u0->a),
                                        le64_to_cpu(u0->b),
                                        (u64)buffer_info->dma,
-                                       buffer_info->skb, next_desc);
+                                       next_desc);
 
                                if (netif_msg_pktdata(adapter) &&
-                                   buffer_info->dma && buffer_info->skb) {
-                                       print_hex_dump(KERN_INFO, "",
-                                                 DUMP_PREFIX_ADDRESS,
-                                                 16, 1, buffer_info->skb->data,
-                                                 IGB_RX_HDR_LEN, true);
+                                   buffer_info->dma && buffer_info->page) {
                                        print_hex_dump(KERN_INFO, "",
                                          DUMP_PREFIX_ADDRESS,
                                          16, 1,
                                          page_address(buffer_info->page) +
                                                      buffer_info->page_offset,
-                                         PAGE_SIZE/2, true);
+                                         IGB_RX_BUFSZ, true);
                                }
                        }
                }
@@ -656,80 +652,6 @@ static void igb_cache_ring_register(struct igb_adapter *adapter)
        }
 }
 
-static void igb_free_queues(struct igb_adapter *adapter)
-{
-       int i;
-
-       for (i = 0; i < adapter->num_tx_queues; i++) {
-               kfree(adapter->tx_ring[i]);
-               adapter->tx_ring[i] = NULL;
-       }
-       for (i = 0; i < adapter->num_rx_queues; i++) {
-               kfree(adapter->rx_ring[i]);
-               adapter->rx_ring[i] = NULL;
-       }
-       adapter->num_rx_queues = 0;
-       adapter->num_tx_queues = 0;
-}
-
-/**
- * igb_alloc_queues - Allocate memory for all rings
- * @adapter: board private structure to initialize
- *
- * We allocate one ring per queue at run-time since we don't know the
- * number of queues at compile-time.
- **/
-static int igb_alloc_queues(struct igb_adapter *adapter)
-{
-       struct igb_ring *ring;
-       int i;
-
-       for (i = 0; i < adapter->num_tx_queues; i++) {
-               ring = kzalloc(sizeof(struct igb_ring), GFP_KERNEL);
-               if (!ring)
-                       goto err;
-               ring->count = adapter->tx_ring_count;
-               ring->queue_index = i;
-               ring->dev = &adapter->pdev->dev;
-               ring->netdev = adapter->netdev;
-               /* For 82575, context index must be unique per ring. */
-               if (adapter->hw.mac.type == e1000_82575)
-                       set_bit(IGB_RING_FLAG_TX_CTX_IDX, &ring->flags);
-               adapter->tx_ring[i] = ring;
-       }
-
-       for (i = 0; i < adapter->num_rx_queues; i++) {
-               ring = kzalloc(sizeof(struct igb_ring), GFP_KERNEL);
-               if (!ring)
-                       goto err;
-               ring->count = adapter->rx_ring_count;
-               ring->queue_index = i;
-               ring->dev = &adapter->pdev->dev;
-               ring->netdev = adapter->netdev;
-               /* set flag indicating ring supports SCTP checksum offload */
-               if (adapter->hw.mac.type >= e1000_82576)
-                       set_bit(IGB_RING_FLAG_RX_SCTP_CSUM, &ring->flags);
-
-               /*
-                * On i350, i210, and i211, loopback VLAN packets
-                * have the tag byte-swapped.
-                * */
-               if (adapter->hw.mac.type >= e1000_i350)
-                       set_bit(IGB_RING_FLAG_RX_LB_VLAN_BSWAP, &ring->flags);
-
-               adapter->rx_ring[i] = ring;
-       }
-
-       igb_cache_ring_register(adapter);
-
-       return 0;
-
-err:
-       igb_free_queues(adapter);
-
-       return -ENOMEM;
-}
-
 /**
  *  igb_write_ivar - configure ivar for given MSI-X vector
  *  @hw: pointer to the HW structure
@@ -959,6 +881,35 @@ static void igb_reset_interrupt_capability(struct igb_adapter *adapter)
        }
 }
 
+/**
+ * igb_free_q_vector - Free memory allocated for specific interrupt vector
+ * @adapter: board private structure to initialize
+ * @v_idx: Index of vector to be freed
+ *
+ * This function frees the memory allocated to the q_vector.  In addition if
+ * NAPI is enabled it will delete any references to the NAPI struct prior
+ * to freeing the q_vector.
+ **/
+static void igb_free_q_vector(struct igb_adapter *adapter, int v_idx)
+{
+       struct igb_q_vector *q_vector = adapter->q_vector[v_idx];
+
+       if (q_vector->tx.ring)
+               adapter->tx_ring[q_vector->tx.ring->queue_index] = NULL;
+
+       if (q_vector->rx.ring)
+               adapter->tx_ring[q_vector->rx.ring->queue_index] = NULL;
+
+       adapter->q_vector[v_idx] = NULL;
+       netif_napi_del(&q_vector->napi);
+
+       /*
+        * ixgbe_get_stats64() might access the rings on this vector,
+        * we must wait a grace period before freeing it.
+        */
+       kfree_rcu(q_vector, rcu);
+}
+
 /**
  * igb_free_q_vectors - Free memory allocated for interrupt vectors
  * @adapter: board private structure to initialize
@@ -969,17 +920,14 @@ static void igb_reset_interrupt_capability(struct igb_adapter *adapter)
  **/
 static void igb_free_q_vectors(struct igb_adapter *adapter)
 {
-       int v_idx;
+       int v_idx = adapter->num_q_vectors;
 
-       for (v_idx = 0; v_idx < adapter->num_q_vectors; v_idx++) {
-               struct igb_q_vector *q_vector = adapter->q_vector[v_idx];
-               adapter->q_vector[v_idx] = NULL;
-               if (!q_vector)
-                       continue;
-               netif_napi_del(&q_vector->napi);
-               kfree(q_vector);
-       }
+       adapter->num_tx_queues = 0;
+       adapter->num_rx_queues = 0;
        adapter->num_q_vectors = 0;
+
+       while (v_idx--)
+               igb_free_q_vector(adapter, v_idx);
 }
 
 /**
@@ -990,7 +938,6 @@ static void igb_free_q_vectors(struct igb_adapter *adapter)
  */
 static void igb_clear_interrupt_scheme(struct igb_adapter *adapter)
 {
-       igb_free_queues(adapter);
        igb_free_q_vectors(adapter);
        igb_reset_interrupt_capability(adapter);
 }
@@ -1001,7 +948,7 @@ static void igb_clear_interrupt_scheme(struct igb_adapter *adapter)
  * Attempt to configure interrupts using the best available
  * capabilities of the hardware and kernel.
  **/
-static int igb_set_interrupt_capability(struct igb_adapter *adapter)
+static void igb_set_interrupt_capability(struct igb_adapter *adapter)
 {
        int err;
        int numvecs, i;
@@ -1038,7 +985,7 @@ static int igb_set_interrupt_capability(struct igb_adapter *adapter)
                              adapter->msix_entries,
                              numvecs);
        if (err == 0)
-               goto out;
+               return;
 
        igb_reset_interrupt_capability(adapter);
 
@@ -1068,105 +1015,183 @@ msi_only:
        adapter->num_q_vectors = 1;
        if (!pci_enable_msi(adapter->pdev))
                adapter->flags |= IGB_FLAG_HAS_MSI;
-out:
-       /* Notify the stack of the (possibly) reduced queue counts. */
-       rtnl_lock();
-       netif_set_real_num_tx_queues(adapter->netdev, adapter->num_tx_queues);
-       err = netif_set_real_num_rx_queues(adapter->netdev,
-               adapter->num_rx_queues);
-       rtnl_unlock();
-       return err;
+}
+
+static void igb_add_ring(struct igb_ring *ring,
+                        struct igb_ring_container *head)
+{
+       head->ring = ring;
+       head->count++;
 }
 
 /**
- * igb_alloc_q_vectors - Allocate memory for interrupt vectors
+ * igb_alloc_q_vector - Allocate memory for a single interrupt vector
  * @adapter: board private structure to initialize
+ * @v_count: q_vectors allocated on adapter, used for ring interleaving
+ * @v_idx: index of vector in adapter struct
+ * @txr_count: total number of Tx rings to allocate
+ * @txr_idx: index of first Tx ring to allocate
+ * @rxr_count: total number of Rx rings to allocate
+ * @rxr_idx: index of first Rx ring to allocate
  *
- * We allocate one q_vector per queue interrupt.  If allocation fails we
- * return -ENOMEM.
+ * We allocate one q_vector.  If allocation fails we return -ENOMEM.
  **/
-static int igb_alloc_q_vectors(struct igb_adapter *adapter)
+static int igb_alloc_q_vector(struct igb_adapter *adapter,
+                             int v_count, int v_idx,
+                             int txr_count, int txr_idx,
+                             int rxr_count, int rxr_idx)
 {
        struct igb_q_vector *q_vector;
-       struct e1000_hw *hw = &adapter->hw;
-       int v_idx;
+       struct igb_ring *ring;
+       int ring_count, size;
 
-       for (v_idx = 0; v_idx < adapter->num_q_vectors; v_idx++) {
-               q_vector = kzalloc(sizeof(struct igb_q_vector),
-                                  GFP_KERNEL);
-               if (!q_vector)
-                       goto err_out;
-               q_vector->adapter = adapter;
-               q_vector->itr_register = hw->hw_addr + E1000_EITR(0);
-               q_vector->itr_val = IGB_START_ITR;
-               netif_napi_add(adapter->netdev, &q_vector->napi, igb_poll, 64);
-               adapter->q_vector[v_idx] = q_vector;
+       /* igb only supports 1 Tx and/or 1 Rx queue per vector */
+       if (txr_count > 1 || rxr_count > 1)
+               return -ENOMEM;
+
+       ring_count = txr_count + rxr_count;
+       size = sizeof(struct igb_q_vector) +
+              (sizeof(struct igb_ring) * ring_count);
+
+       /* allocate q_vector and rings */
+       q_vector = kzalloc(size, GFP_KERNEL);
+       if (!q_vector)
+               return -ENOMEM;
+
+       /* initialize NAPI */
+       netif_napi_add(adapter->netdev, &q_vector->napi,
+                      igb_poll, 64);
+
+       /* tie q_vector and adapter together */
+       adapter->q_vector[v_idx] = q_vector;
+       q_vector->adapter = adapter;
+
+       /* initialize work limits */
+       q_vector->tx.work_limit = adapter->tx_work_limit;
+
+       /* initialize ITR configuration */
+       q_vector->itr_register = adapter->hw.hw_addr + E1000_EITR(0);
+       q_vector->itr_val = IGB_START_ITR;
+
+       /* initialize pointer to rings */
+       ring = q_vector->ring;
+
+       if (txr_count) {
+               /* assign generic ring traits */
+               ring->dev = &adapter->pdev->dev;
+               ring->netdev = adapter->netdev;
+
+               /* configure backlink on ring */
+               ring->q_vector = q_vector;
+
+               /* update q_vector Tx values */
+               igb_add_ring(ring, &q_vector->tx);
+
+               /* For 82575, context index must be unique per ring. */
+               if (adapter->hw.mac.type == e1000_82575)
+                       set_bit(IGB_RING_FLAG_TX_CTX_IDX, &ring->flags);
+
+               /* apply Tx specific ring traits */
+               ring->count = adapter->tx_ring_count;
+               ring->queue_index = txr_idx;
+
+               /* assign ring to adapter */
+               adapter->tx_ring[txr_idx] = ring;
+
+               /* push pointer to next ring */
+               ring++;
        }
 
-       return 0;
+       if (rxr_count) {
+               /* assign generic ring traits */
+               ring->dev = &adapter->pdev->dev;
+               ring->netdev = adapter->netdev;
 
-err_out:
-       igb_free_q_vectors(adapter);
-       return -ENOMEM;
-}
+               /* configure backlink on ring */
+               ring->q_vector = q_vector;
 
-static void igb_map_rx_ring_to_vector(struct igb_adapter *adapter,
-                                      int ring_idx, int v_idx)
-{
-       struct igb_q_vector *q_vector = adapter->q_vector[v_idx];
+               /* update q_vector Rx values */
+               igb_add_ring(ring, &q_vector->rx);
 
-       q_vector->rx.ring = adapter->rx_ring[ring_idx];
-       q_vector->rx.ring->q_vector = q_vector;
-       q_vector->rx.count++;
-       q_vector->itr_val = adapter->rx_itr_setting;
-       if (q_vector->itr_val && q_vector->itr_val <= 3)
-               q_vector->itr_val = IGB_START_ITR;
-}
+               /* set flag indicating ring supports SCTP checksum offload */
+               if (adapter->hw.mac.type >= e1000_82576)
+                       set_bit(IGB_RING_FLAG_RX_SCTP_CSUM, &ring->flags);
 
-static void igb_map_tx_ring_to_vector(struct igb_adapter *adapter,
-                                      int ring_idx, int v_idx)
-{
-       struct igb_q_vector *q_vector = adapter->q_vector[v_idx];
+               /*
+                * On i350, i210, and i211, loopback VLAN packets
+                * have the tag byte-swapped.
+                * */
+               if (adapter->hw.mac.type >= e1000_i350)
+                       set_bit(IGB_RING_FLAG_RX_LB_VLAN_BSWAP, &ring->flags);
 
-       q_vector->tx.ring = adapter->tx_ring[ring_idx];
-       q_vector->tx.ring->q_vector = q_vector;
-       q_vector->tx.count++;
-       q_vector->itr_val = adapter->tx_itr_setting;
-       q_vector->tx.work_limit = adapter->tx_work_limit;
-       if (q_vector->itr_val && q_vector->itr_val <= 3)
-               q_vector->itr_val = IGB_START_ITR;
+               /* apply Rx specific ring traits */
+               ring->count = adapter->rx_ring_count;
+               ring->queue_index = rxr_idx;
+
+               /* assign ring to adapter */
+               adapter->rx_ring[rxr_idx] = ring;
+       }
+
+       return 0;
 }
 
+
 /**
- * igb_map_ring_to_vector - maps allocated queues to vectors
+ * igb_alloc_q_vectors - Allocate memory for interrupt vectors
+ * @adapter: board private structure to initialize
  *
- * This function maps the recently allocated queues to vectors.
+ * We allocate one q_vector per queue interrupt.  If allocation fails we
+ * return -ENOMEM.
  **/
-static int igb_map_ring_to_vector(struct igb_adapter *adapter)
+static int igb_alloc_q_vectors(struct igb_adapter *adapter)
 {
-       int i;
-       int v_idx = 0;
+       int q_vectors = adapter->num_q_vectors;
+       int rxr_remaining = adapter->num_rx_queues;
+       int txr_remaining = adapter->num_tx_queues;
+       int rxr_idx = 0, txr_idx = 0, v_idx = 0;
+       int err;
 
-       if ((adapter->num_q_vectors < adapter->num_rx_queues) ||
-           (adapter->num_q_vectors < adapter->num_tx_queues))
-               return -ENOMEM;
+       if (q_vectors >= (rxr_remaining + txr_remaining)) {
+               for (; rxr_remaining; v_idx++) {
+                       err = igb_alloc_q_vector(adapter, q_vectors, v_idx,
+                                                0, 0, 1, rxr_idx);
 
-       if (adapter->num_q_vectors >=
-           (adapter->num_rx_queues + adapter->num_tx_queues)) {
-               for (i = 0; i < adapter->num_rx_queues; i++)
-                       igb_map_rx_ring_to_vector(adapter, i, v_idx++);
-               for (i = 0; i < adapter->num_tx_queues; i++)
-                       igb_map_tx_ring_to_vector(adapter, i, v_idx++);
-       } else {
-               for (i = 0; i < adapter->num_rx_queues; i++) {
-                       if (i < adapter->num_tx_queues)
-                               igb_map_tx_ring_to_vector(adapter, i, v_idx);
-                       igb_map_rx_ring_to_vector(adapter, i, v_idx++);
+                       if (err)
+                               goto err_out;
+
+                       /* update counts and index */
+                       rxr_remaining--;
+                       rxr_idx++;
                }
-               for (; i < adapter->num_tx_queues; i++)
-                       igb_map_tx_ring_to_vector(adapter, i, v_idx++);
        }
+
+       for (; v_idx < q_vectors; v_idx++) {
+               int rqpv = DIV_ROUND_UP(rxr_remaining, q_vectors - v_idx);
+               int tqpv = DIV_ROUND_UP(txr_remaining, q_vectors - v_idx);
+               err = igb_alloc_q_vector(adapter, q_vectors, v_idx,
+                                        tqpv, txr_idx, rqpv, rxr_idx);
+
+               if (err)
+                       goto err_out;
+
+               /* update counts and index */
+               rxr_remaining -= rqpv;
+               txr_remaining -= tqpv;
+               rxr_idx++;
+               txr_idx++;
+       }
+
        return 0;
+
+err_out:
+       adapter->num_tx_queues = 0;
+       adapter->num_rx_queues = 0;
+       adapter->num_q_vectors = 0;
+
+       while (v_idx--)
+               igb_free_q_vector(adapter, v_idx);
+
+       return -ENOMEM;
 }
 
 /**
@@ -1179,9 +1204,7 @@ static int igb_init_interrupt_scheme(struct igb_adapter *adapter)
        struct pci_dev *pdev = adapter->pdev;
        int err;
 
-       err = igb_set_interrupt_capability(adapter);
-       if (err)
-               return err;
+       igb_set_interrupt_capability(adapter);
 
        err = igb_alloc_q_vectors(adapter);
        if (err) {
@@ -1189,24 +1212,10 @@ static int igb_init_interrupt_scheme(struct igb_adapter *adapter)
                goto err_alloc_q_vectors;
        }
 
-       err = igb_alloc_queues(adapter);
-       if (err) {
-               dev_err(&pdev->dev, "Unable to allocate memory for queues\n");
-               goto err_alloc_queues;
-       }
-
-       err = igb_map_ring_to_vector(adapter);
-       if (err) {
-               dev_err(&pdev->dev, "Invalid q_vector to ring mapping\n");
-               goto err_map_queues;
-       }
-
+       igb_cache_ring_register(adapter);
 
        return 0;
-err_map_queues:
-       igb_free_queues(adapter);
-err_alloc_queues:
-       igb_free_q_vectors(adapter);
+
 err_alloc_q_vectors:
        igb_reset_interrupt_capability(adapter);
        return err;
@@ -1229,11 +1238,11 @@ static int igb_request_irq(struct igb_adapter *adapter)
                if (!err)
                        goto request_done;
                /* fall back to MSI */
+               igb_free_all_tx_resources(adapter);
+               igb_free_all_rx_resources(adapter);
                igb_clear_interrupt_scheme(adapter);
                if (!pci_enable_msi(pdev))
                        adapter->flags |= IGB_FLAG_HAS_MSI;
-               igb_free_all_tx_resources(adapter);
-               igb_free_all_rx_resources(adapter);
                adapter->num_tx_queues = 1;
                adapter->num_rx_queues = 1;
                adapter->num_q_vectors = 1;
@@ -1243,13 +1252,6 @@ static int igb_request_irq(struct igb_adapter *adapter)
                                "Unable to allocate memory for vectors\n");
                        goto request_done;
                }
-               err = igb_alloc_queues(adapter);
-               if (err) {
-                       dev_err(&pdev->dev,
-                               "Unable to allocate memory for queues\n");
-                       igb_free_q_vectors(adapter);
-                       goto request_done;
-               }
                igb_setup_all_tx_resources(adapter);
                igb_setup_all_rx_resources(adapter);
        }
@@ -2531,6 +2533,17 @@ static int __igb_open(struct net_device *netdev, bool resuming)
        if (err)
                goto err_req_irq;
 
+       /* Notify the stack of the actual queue counts. */
+       err = netif_set_real_num_tx_queues(adapter->netdev,
+                                          adapter->num_tx_queues);
+       if (err)
+               goto err_set_queues;
+
+       err = netif_set_real_num_rx_queues(adapter->netdev,
+                                          adapter->num_rx_queues);
+       if (err)
+               goto err_set_queues;
+
        /* From here on the code is the same as igb_up() */
        clear_bit(__IGB_DOWN, &adapter->state);
 
@@ -2560,6 +2573,8 @@ static int __igb_open(struct net_device *netdev, bool resuming)
 
        return 0;
 
+err_set_queues:
+       igb_free_irq(adapter);
 err_req_irq:
        igb_release_hw_control(adapter);
        igb_power_down_link(adapter);
@@ -2637,10 +2652,8 @@ int igb_setup_tx_resources(struct igb_ring *tx_ring)
        tx_ring->size = tx_ring->count * sizeof(union e1000_adv_tx_desc);
        tx_ring->size = ALIGN(tx_ring->size, 4096);
 
-       tx_ring->desc = dma_alloc_coherent(dev,
-                                          tx_ring->size,
-                                          &tx_ring->dma,
-                                          GFP_KERNEL);
+       tx_ring->desc = dma_alloc_coherent(dev, tx_ring->size,
+                                          &tx_ring->dma, GFP_KERNEL);
        if (!tx_ring->desc)
                goto err;
 
@@ -2777,18 +2790,16 @@ int igb_setup_rx_resources(struct igb_ring *rx_ring)
        if (!rx_ring->rx_buffer_info)
                goto err;
 
-
        /* Round up to nearest 4K */
        rx_ring->size = rx_ring->count * sizeof(union e1000_adv_rx_desc);
        rx_ring->size = ALIGN(rx_ring->size, 4096);
 
-       rx_ring->desc = dma_alloc_coherent(dev,
-                                          rx_ring->size,
-                                          &rx_ring->dma,
-                                          GFP_KERNEL);
+       rx_ring->desc = dma_alloc_coherent(dev, rx_ring->size,
+                                          &rx_ring->dma, GFP_KERNEL);
        if (!rx_ring->desc)
                goto err;
 
+       rx_ring->next_to_alloc = 0;
        rx_ring->next_to_clean = 0;
        rx_ring->next_to_use = 0;
 
@@ -3106,12 +3117,8 @@ void igb_configure_rx_ring(struct igb_adapter *adapter,
 
        /* set descriptor configuration */
        srrctl = IGB_RX_HDR_LEN << E1000_SRRCTL_BSIZEHDRSIZE_SHIFT;
-#if (PAGE_SIZE / 2) > IGB_RXBUFFER_16384
-       srrctl |= IGB_RXBUFFER_16384 >> E1000_SRRCTL_BSIZEPKT_SHIFT;
-#else
-       srrctl |= (PAGE_SIZE / 2) >> E1000_SRRCTL_BSIZEPKT_SHIFT;
-#endif
-       srrctl |= E1000_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS;
+       srrctl |= IGB_RX_BUFSZ >> E1000_SRRCTL_BSIZEPKT_SHIFT;
+       srrctl |= E1000_SRRCTL_DESCTYPE_ADV_ONEBUF;
 #ifdef CONFIG_IGB_PTP
        if (hw->mac.type >= e1000_82580)
                srrctl |= E1000_SRRCTL_TIMESTAMP;
@@ -3305,36 +3312,27 @@ static void igb_clean_rx_ring(struct igb_ring *rx_ring)
        unsigned long size;
        u16 i;
 
+       if (rx_ring->skb)
+               dev_kfree_skb(rx_ring->skb);
+       rx_ring->skb = NULL;
+
        if (!rx_ring->rx_buffer_info)
                return;
 
        /* Free all the Rx ring sk_buffs */
        for (i = 0; i < rx_ring->count; i++) {
                struct igb_rx_buffer *buffer_info = &rx_ring->rx_buffer_info[i];
-               if (buffer_info->dma) {
-                       dma_unmap_single(rx_ring->dev,
-                                        buffer_info->dma,
-                                        IGB_RX_HDR_LEN,
-                                        DMA_FROM_DEVICE);
-                       buffer_info->dma = 0;
-               }
 
-               if (buffer_info->skb) {
-                       dev_kfree_skb(buffer_info->skb);
-                       buffer_info->skb = NULL;
-               }
-               if (buffer_info->page_dma) {
-                       dma_unmap_page(rx_ring->dev,
-                                      buffer_info->page_dma,
-                                      PAGE_SIZE / 2,
-                                      DMA_FROM_DEVICE);
-                       buffer_info->page_dma = 0;
-               }
-               if (buffer_info->page) {
-                       put_page(buffer_info->page);
-                       buffer_info->page = NULL;
-                       buffer_info->page_offset = 0;
-               }
+               if (!buffer_info->page)
+                       continue;
+
+               dma_unmap_page(rx_ring->dev,
+                              buffer_info->dma,
+                              PAGE_SIZE,
+                              DMA_FROM_DEVICE);
+               __free_page(buffer_info->page);
+
+               buffer_info->page = NULL;
        }
 
        size = sizeof(struct igb_rx_buffer) * rx_ring->count;
@@ -3343,6 +3341,7 @@ static void igb_clean_rx_ring(struct igb_ring *rx_ring)
        /* Zero out the descriptor ring */
        memset(rx_ring->desc, 0, rx_ring->size);
 
+       rx_ring->next_to_alloc = 0;
        rx_ring->next_to_clean = 0;
        rx_ring->next_to_use = 0;
 }
@@ -4467,10 +4466,11 @@ static netdev_tx_t igb_xmit_frame(struct sk_buff *skb,
         * The minimum packet size with TCTL.PSP set is 17 so pad the skb
         * in order to meet this minimum size requirement.
         */
-       if (skb->len < 17) {
-               if (skb_padto(skb, 17))
+       if (unlikely(skb->len < 17)) {
+               if (skb_pad(skb, 17 - skb->len))
                        return NETDEV_TX_OK;
                skb->len = 17;
+               skb_set_tail_pointer(skb, 17);
        }
 
        return igb_xmit_frame_ring(skb, igb_tx_queue_mapping(adapter, skb));
@@ -4851,45 +4851,63 @@ static irqreturn_t igb_msix_ring(int irq, void *data)
 }
 
 #ifdef CONFIG_IGB_DCA
+static void igb_update_tx_dca(struct igb_adapter *adapter,
+                             struct igb_ring *tx_ring,
+                             int cpu)
+{
+       struct e1000_hw *hw = &adapter->hw;
+       u32 txctrl = dca3_get_tag(tx_ring->dev, cpu);
+
+       if (hw->mac.type != e1000_82575)
+               txctrl <<= E1000_DCA_TXCTRL_CPUID_SHIFT;
+
+       /*
+        * We can enable relaxed ordering for reads, but not writes when
+        * DCA is enabled.  This is due to a known issue in some chipsets
+        * which will cause the DCA tag to be cleared.
+        */
+       txctrl |= E1000_DCA_TXCTRL_DESC_RRO_EN |
+                 E1000_DCA_TXCTRL_DATA_RRO_EN |
+                 E1000_DCA_TXCTRL_DESC_DCA_EN;
+
+       wr32(E1000_DCA_TXCTRL(tx_ring->reg_idx), txctrl);
+}
+
+static void igb_update_rx_dca(struct igb_adapter *adapter,
+                             struct igb_ring *rx_ring,
+                             int cpu)
+{
+       struct e1000_hw *hw = &adapter->hw;
+       u32 rxctrl = dca3_get_tag(&adapter->pdev->dev, cpu);
+
+       if (hw->mac.type != e1000_82575)
+               rxctrl <<= E1000_DCA_RXCTRL_CPUID_SHIFT;
+
+       /*
+        * We can enable relaxed ordering for reads, but not writes when
+        * DCA is enabled.  This is due to a known issue in some chipsets
+        * which will cause the DCA tag to be cleared.
+        */
+       rxctrl |= E1000_DCA_RXCTRL_DESC_RRO_EN |
+                 E1000_DCA_RXCTRL_DESC_DCA_EN;
+
+       wr32(E1000_DCA_RXCTRL(rx_ring->reg_idx), rxctrl);
+}
+
 static void igb_update_dca(struct igb_q_vector *q_vector)
 {
        struct igb_adapter *adapter = q_vector->adapter;
-       struct e1000_hw *hw = &adapter->hw;
        int cpu = get_cpu();
 
        if (q_vector->cpu == cpu)
                goto out_no_update;
 
-       if (q_vector->tx.ring) {
-               int q = q_vector->tx.ring->reg_idx;
-               u32 dca_txctrl = rd32(E1000_DCA_TXCTRL(q));
-               if (hw->mac.type == e1000_82575) {
-                       dca_txctrl &= ~E1000_DCA_TXCTRL_CPUID_MASK;
-                       dca_txctrl |= dca3_get_tag(&adapter->pdev->dev, cpu);
-               } else {
-                       dca_txctrl &= ~E1000_DCA_TXCTRL_CPUID_MASK_82576;
-                       dca_txctrl |= dca3_get_tag(&adapter->pdev->dev, cpu) <<
-                                     E1000_DCA_TXCTRL_CPUID_SHIFT;
-               }
-               dca_txctrl |= E1000_DCA_TXCTRL_DESC_DCA_EN;
-               wr32(E1000_DCA_TXCTRL(q), dca_txctrl);
-       }
-       if (q_vector->rx.ring) {
-               int q = q_vector->rx.ring->reg_idx;
-               u32 dca_rxctrl = rd32(E1000_DCA_RXCTRL(q));
-               if (hw->mac.type == e1000_82575) {
-                       dca_rxctrl &= ~E1000_DCA_RXCTRL_CPUID_MASK;
-                       dca_rxctrl |= dca3_get_tag(&adapter->pdev->dev, cpu);
-               } else {
-                       dca_rxctrl &= ~E1000_DCA_RXCTRL_CPUID_MASK_82576;
-                       dca_rxctrl |= dca3_get_tag(&adapter->pdev->dev, cpu) <<
-                                     E1000_DCA_RXCTRL_CPUID_SHIFT;
-               }
-               dca_rxctrl |= E1000_DCA_RXCTRL_DESC_DCA_EN;
-               dca_rxctrl |= E1000_DCA_RXCTRL_HEAD_DCA_EN;
-               dca_rxctrl |= E1000_DCA_RXCTRL_DATA_DCA_EN;
-               wr32(E1000_DCA_RXCTRL(q), dca_rxctrl);
-       }
+       if (q_vector->tx.ring)
+               igb_update_tx_dca(adapter, q_vector->tx.ring, cpu);
+
+       if (q_vector->rx.ring)
+               igb_update_rx_dca(adapter, q_vector->rx.ring, cpu);
+
        q_vector->cpu = cpu;
 out_no_update:
        put_cpu();
@@ -5840,6 +5858,183 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector)
        return !!budget;
 }
 
+/**
+ * igb_reuse_rx_page - page flip buffer and store it back on the ring
+ * @rx_ring: rx descriptor ring to store buffers on
+ * @old_buff: donor buffer to have page reused
+ *
+ * Synchronizes page for reuse by the adapter
+ **/
+static void igb_reuse_rx_page(struct igb_ring *rx_ring,
+                             struct igb_rx_buffer *old_buff)
+{
+       struct igb_rx_buffer *new_buff;
+       u16 nta = rx_ring->next_to_alloc;
+
+       new_buff = &rx_ring->rx_buffer_info[nta];
+
+       /* update, and store next to alloc */
+       nta++;
+       rx_ring->next_to_alloc = (nta < rx_ring->count) ? nta : 0;
+
+       /* transfer page from old buffer to new buffer */
+       memcpy(new_buff, old_buff, sizeof(struct igb_rx_buffer));
+
+       /* sync the buffer for use by the device */
+       dma_sync_single_range_for_device(rx_ring->dev, old_buff->dma,
+                                        old_buff->page_offset,
+                                        IGB_RX_BUFSZ,
+                                        DMA_FROM_DEVICE);
+}
+
+/**
+ * igb_add_rx_frag - Add contents of Rx buffer to sk_buff
+ * @rx_ring: rx descriptor ring to transact packets on
+ * @rx_buffer: buffer containing page to add
+ * @rx_desc: descriptor containing length of buffer written by hardware
+ * @skb: sk_buff to place the data into
+ *
+ * This function will add the data contained in rx_buffer->page to the skb.
+ * This is done either through a direct copy if the data in the buffer is
+ * less than the skb header size, otherwise it will just attach the page as
+ * a frag to the skb.
+ *
+ * The function will then update the page offset if necessary and return
+ * true if the buffer can be reused by the adapter.
+ **/
+static bool igb_add_rx_frag(struct igb_ring *rx_ring,
+                           struct igb_rx_buffer *rx_buffer,
+                           union e1000_adv_rx_desc *rx_desc,
+                           struct sk_buff *skb)
+{
+       struct page *page = rx_buffer->page;
+       unsigned int size = le16_to_cpu(rx_desc->wb.upper.length);
+
+       if ((size <= IGB_RX_HDR_LEN) && !skb_is_nonlinear(skb)) {
+               unsigned char *va = page_address(page) + rx_buffer->page_offset;
+
+#ifdef CONFIG_IGB_PTP
+               if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP)) {
+                       igb_ptp_rx_pktstamp(rx_ring->q_vector, va, skb);
+                       va += IGB_TS_HDR_LEN;
+                       size -= IGB_TS_HDR_LEN;
+               }
+
+#endif
+               memcpy(__skb_put(skb, size), va, ALIGN(size, sizeof(long)));
+
+               /* we can reuse buffer as-is, just make sure it is local */
+               if (likely(page_to_nid(page) == numa_node_id()))
+                       return true;
+
+               /* this page cannot be reused so discard it */
+               put_page(page);
+               return false;
+       }
+
+       skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page,
+                       rx_buffer->page_offset, size, IGB_RX_BUFSZ);
+
+       /* avoid re-using remote pages */
+       if (unlikely(page_to_nid(page) != numa_node_id()))
+               return false;
+
+#if (PAGE_SIZE < 8192)
+       /* if we are only owner of page we can reuse it */
+       if (unlikely(page_count(page) != 1))
+               return false;
+
+       /* flip page offset to other buffer */
+       rx_buffer->page_offset ^= IGB_RX_BUFSZ;
+
+       /*
+        * since we are the only owner of the page and we need to
+        * increment it, just set the value to 2 in order to avoid
+        * an unnecessary locked operation
+        */
+       atomic_set(&page->_count, 2);
+#else
+       /* move offset up to the next cache line */
+       rx_buffer->page_offset += SKB_DATA_ALIGN(size);
+
+       if (rx_buffer->page_offset > (PAGE_SIZE - IGB_RX_BUFSZ))
+               return false;
+
+       /* bump ref count on page before it is given to the stack */
+       get_page(page);
+#endif
+
+       return true;
+}
+
+static struct sk_buff *igb_fetch_rx_buffer(struct igb_ring *rx_ring,
+                                          union e1000_adv_rx_desc *rx_desc,
+                                          struct sk_buff *skb)
+{
+       struct igb_rx_buffer *rx_buffer;
+       struct page *page;
+
+       rx_buffer = &rx_ring->rx_buffer_info[rx_ring->next_to_clean];
+
+       /*
+        * This memory barrier is needed to keep us from reading
+        * any other fields out of the rx_desc until we know the
+        * RXD_STAT_DD bit is set
+        */
+       rmb();
+
+       page = rx_buffer->page;
+       prefetchw(page);
+
+       if (likely(!skb)) {
+               void *page_addr = page_address(page) +
+                                 rx_buffer->page_offset;
+
+               /* prefetch first cache line of first page */
+               prefetch(page_addr);
+#if L1_CACHE_BYTES < 128
+               prefetch(page_addr + L1_CACHE_BYTES);
+#endif
+
+               /* allocate a skb to store the frags */
+               skb = netdev_alloc_skb_ip_align(rx_ring->netdev,
+                                               IGB_RX_HDR_LEN);
+               if (unlikely(!skb)) {
+                       rx_ring->rx_stats.alloc_failed++;
+                       return NULL;
+               }
+
+               /*
+                * we will be copying header into skb->data in
+                * pskb_may_pull so it is in our interest to prefetch
+                * it now to avoid a possible cache miss
+                */
+               prefetchw(skb->data);
+       }
+
+       /* we are reusing so sync this buffer for CPU use */
+       dma_sync_single_range_for_cpu(rx_ring->dev,
+                                     rx_buffer->dma,
+                                     rx_buffer->page_offset,
+                                     IGB_RX_BUFSZ,
+                                     DMA_FROM_DEVICE);
+
+       /* pull page into skb */
+       if (igb_add_rx_frag(rx_ring, rx_buffer, rx_desc, skb)) {
+               /* hand second half of page back to the ring */
+               igb_reuse_rx_page(rx_ring, rx_buffer);
+       } else {
+               /* we are not reusing the buffer so unmap it */
+               dma_unmap_page(rx_ring->dev, rx_buffer->dma,
+                              PAGE_SIZE, DMA_FROM_DEVICE);
+       }
+
+       /* clear contents of rx_buffer */
+       rx_buffer->page = NULL;
+
+       return skb;
+}
+
 static inline void igb_rx_checksum(struct igb_ring *ring,
                                   union e1000_adv_rx_desc *rx_desc,
                                   struct sk_buff *skb)
@@ -5889,224 +6084,390 @@ static inline void igb_rx_hash(struct igb_ring *ring,
                skb->rxhash = le32_to_cpu(rx_desc->wb.lower.hi_dword.rss);
 }
 
-static void igb_rx_vlan(struct igb_ring *ring,
-                       union e1000_adv_rx_desc *rx_desc,
-                       struct sk_buff *skb)
+/**
+ * igb_is_non_eop - process handling of non-EOP buffers
+ * @rx_ring: Rx ring being processed
+ * @rx_desc: Rx descriptor for current buffer
+ * @skb: current socket buffer containing buffer in progress
+ *
+ * This function updates next to clean.  If the buffer is an EOP buffer
+ * this function exits returning false, otherwise it will place the
+ * sk_buff in the next buffer to be chained and return true indicating
+ * that this is in fact a non-EOP buffer.
+ **/
+static bool igb_is_non_eop(struct igb_ring *rx_ring,
+                          union e1000_adv_rx_desc *rx_desc)
 {
-       if (igb_test_staterr(rx_desc, E1000_RXD_STAT_VP)) {
-               u16 vid;
-               if (igb_test_staterr(rx_desc, E1000_RXDEXT_STATERR_LB) &&
-                   test_bit(IGB_RING_FLAG_RX_LB_VLAN_BSWAP, &ring->flags))
-                       vid = be16_to_cpu(rx_desc->wb.upper.vlan);
-               else
-                       vid = le16_to_cpu(rx_desc->wb.upper.vlan);
+       u32 ntc = rx_ring->next_to_clean + 1;
 
-               __vlan_hwaccel_put_tag(skb, vid);
-       }
+       /* fetch, update, and store next to clean */
+       ntc = (ntc < rx_ring->count) ? ntc : 0;
+       rx_ring->next_to_clean = ntc;
+
+       prefetch(IGB_RX_DESC(rx_ring, ntc));
+
+       if (likely(igb_test_staterr(rx_desc, E1000_RXD_STAT_EOP)))
+               return false;
+
+       return true;
 }
 
-static inline u16 igb_get_hlen(union e1000_adv_rx_desc *rx_desc)
-{
-       /* HW will not DMA in data larger than the given buffer, even if it
-        * parses the (NFS, of course) header to be larger.  In that case, it
-        * fills the header buffer and spills the rest into the page.
+/**
+ * igb_get_headlen - determine size of header for LRO/GRO
+ * @data: pointer to the start of the headers
+ * @max_len: total length of section to find headers in
+ *
+ * This function is meant to determine the length of headers that will
+ * be recognized by hardware for LRO, and GRO offloads.  The main
+ * motivation of doing this is to only perform one pull for IPv4 TCP
+ * packets so that we can do basic things like calculating the gso_size
+ * based on the average data per packet.
+ **/
+static unsigned int igb_get_headlen(unsigned char *data,
+                                   unsigned int max_len)
+{
+       union {
+               unsigned char *network;
+               /* l2 headers */
+               struct ethhdr *eth;
+               struct vlan_hdr *vlan;
+               /* l3 headers */
+               struct iphdr *ipv4;
+               struct ipv6hdr *ipv6;
+       } hdr;
+       __be16 protocol;
+       u8 nexthdr = 0; /* default to not TCP */
+       u8 hlen;
+
+       /* this should never happen, but better safe than sorry */
+       if (max_len < ETH_HLEN)
+               return max_len;
+
+       /* initialize network frame pointer */
+       hdr.network = data;
+
+       /* set first protocol and move network header forward */
+       protocol = hdr.eth->h_proto;
+       hdr.network += ETH_HLEN;
+
+       /* handle any vlan tag if present */
+       if (protocol == __constant_htons(ETH_P_8021Q)) {
+               if ((hdr.network - data) > (max_len - VLAN_HLEN))
+                       return max_len;
+
+               protocol = hdr.vlan->h_vlan_encapsulated_proto;
+               hdr.network += VLAN_HLEN;
+       }
+
+       /* handle L3 protocols */
+       if (protocol == __constant_htons(ETH_P_IP)) {
+               if ((hdr.network - data) > (max_len - sizeof(struct iphdr)))
+                       return max_len;
+
+               /* access ihl as a u8 to avoid unaligned access on ia64 */
+               hlen = (hdr.network[0] & 0x0F) << 2;
+
+               /* verify hlen meets minimum size requirements */
+               if (hlen < sizeof(struct iphdr))
+                       return hdr.network - data;
+
+               /* record next protocol */
+               nexthdr = hdr.ipv4->protocol;
+               hdr.network += hlen;
+       } else if (protocol == __constant_htons(ETH_P_IPV6)) {
+               if ((hdr.network - data) > (max_len - sizeof(struct ipv6hdr)))
+                       return max_len;
+
+               /* record next protocol */
+               nexthdr = hdr.ipv6->nexthdr;
+               hdr.network += sizeof(struct ipv6hdr);
+       } else {
+               return hdr.network - data;
+       }
+
+       /* finally sort out TCP */
+       if (nexthdr == IPPROTO_TCP) {
+               if ((hdr.network - data) > (max_len - sizeof(struct tcphdr)))
+                       return max_len;
+
+               /* access doff as a u8 to avoid unaligned access on ia64 */
+               hlen = (hdr.network[12] & 0xF0) >> 2;
+
+               /* verify hlen meets minimum size requirements */
+               if (hlen < sizeof(struct tcphdr))
+                       return hdr.network - data;
+
+               hdr.network += hlen;
+       } else if (nexthdr == IPPROTO_UDP) {
+               if ((hdr.network - data) > (max_len - sizeof(struct udphdr)))
+                       return max_len;
+
+               hdr.network += sizeof(struct udphdr);
+       }
+
+       /*
+        * If everything has gone correctly hdr.network should be the
+        * data section of the packet and will be the end of the header.
+        * If not then it probably represents the end of the last recognized
+        * header.
         */
-       u16 hlen = (le16_to_cpu(rx_desc->wb.lower.lo_dword.hdr_info) &
-                  E1000_RXDADV_HDRBUFLEN_MASK) >> E1000_RXDADV_HDRBUFLEN_SHIFT;
-       if (hlen > IGB_RX_HDR_LEN)
-               hlen = IGB_RX_HDR_LEN;
-       return hlen;
+       if ((hdr.network - data) < max_len)
+               return hdr.network - data;
+       else
+               return max_len;
 }
 
-static bool igb_clean_rx_irq(struct igb_q_vector *q_vector, int budget)
+/**
+ * igb_pull_tail - igb specific version of skb_pull_tail
+ * @rx_ring: rx descriptor ring packet is being transacted on
+ * @rx_desc: pointer to the EOP Rx descriptor
+ * @skb: pointer to current skb being adjusted
+ *
+ * This function is an igb specific version of __pskb_pull_tail.  The
+ * main difference between this version and the original function is that
+ * this function can make several assumptions about the state of things
+ * that allow for significant optimizations versus the standard function.
+ * As a result we can do things like drop a frag and maintain an accurate
+ * truesize for the skb.
+ */
+static void igb_pull_tail(struct igb_ring *rx_ring,
+                         union e1000_adv_rx_desc *rx_desc,
+                         struct sk_buff *skb)
 {
-       struct igb_ring *rx_ring = q_vector->rx.ring;
-       union e1000_adv_rx_desc *rx_desc;
-       const int current_node = numa_node_id();
-       unsigned int total_bytes = 0, total_packets = 0;
-       u16 cleaned_count = igb_desc_unused(rx_ring);
-       u16 i = rx_ring->next_to_clean;
+       struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[0];
+       unsigned char *va;
+       unsigned int pull_len;
 
-       rx_desc = IGB_RX_DESC(rx_ring, i);
+       /*
+        * it is valid to use page_address instead of kmap since we are
+        * working with pages allocated out of the lomem pool per
+        * alloc_page(GFP_ATOMIC)
+        */
+       va = skb_frag_address(frag);
 
-       while (igb_test_staterr(rx_desc, E1000_RXD_STAT_DD)) {
-               struct igb_rx_buffer *buffer_info = &rx_ring->rx_buffer_info[i];
-               struct sk_buff *skb = buffer_info->skb;
-               union e1000_adv_rx_desc *next_rxd;
+#ifdef CONFIG_IGB_PTP
+       if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP)) {
+               /* retrieve timestamp from buffer */
+               igb_ptp_rx_pktstamp(rx_ring->q_vector, va, skb);
 
-               buffer_info->skb = NULL;
-               prefetch(skb->data);
+               /* update pointers to remove timestamp header */
+               skb_frag_size_sub(frag, IGB_TS_HDR_LEN);
+               frag->page_offset += IGB_TS_HDR_LEN;
+               skb->data_len -= IGB_TS_HDR_LEN;
+               skb->len -= IGB_TS_HDR_LEN;
 
-               i++;
-               if (i == rx_ring->count)
-                       i = 0;
+               /* move va to start of packet data */
+               va += IGB_TS_HDR_LEN;
+       }
 
-               next_rxd = IGB_RX_DESC(rx_ring, i);
-               prefetch(next_rxd);
+#endif
+       /*
+        * we need the header to contain the greater of either ETH_HLEN or
+        * 60 bytes if the skb->len is less than 60 for skb_pad.
+        */
+       pull_len = igb_get_headlen(va, IGB_RX_HDR_LEN);
 
-               /*
-                * This memory barrier is needed to keep us from reading
-                * any other fields out of the rx_desc until we know the
-                * RXD_STAT_DD bit is set
-                */
-               rmb();
+       /* align pull length to size of long to optimize memcpy performance */
+       skb_copy_to_linear_data(skb, va, ALIGN(pull_len, sizeof(long)));
 
-               if (!skb_is_nonlinear(skb)) {
-                       __skb_put(skb, igb_get_hlen(rx_desc));
-                       dma_unmap_single(rx_ring->dev, buffer_info->dma,
-                                        IGB_RX_HDR_LEN,
-                                        DMA_FROM_DEVICE);
-                       buffer_info->dma = 0;
+       /* update all of the pointers */
+       skb_frag_size_sub(frag, pull_len);
+       frag->page_offset += pull_len;
+       skb->data_len -= pull_len;
+       skb->tail += pull_len;
+}
+
+/**
+ * igb_cleanup_headers - Correct corrupted or empty headers
+ * @rx_ring: rx descriptor ring packet is being transacted on
+ * @rx_desc: pointer to the EOP Rx descriptor
+ * @skb: pointer to current skb being fixed
+ *
+ * Address the case where we are pulling data in on pages only
+ * and as such no data is present in the skb header.
+ *
+ * In addition if skb is not at least 60 bytes we need to pad it so that
+ * it is large enough to qualify as a valid Ethernet frame.
+ *
+ * Returns true if an error was encountered and skb was freed.
+ **/
+static bool igb_cleanup_headers(struct igb_ring *rx_ring,
+                               union e1000_adv_rx_desc *rx_desc,
+                               struct sk_buff *skb)
+{
+
+       if (unlikely((igb_test_staterr(rx_desc,
+                                      E1000_RXDEXT_ERR_FRAME_ERR_MASK)))) {
+               struct net_device *netdev = rx_ring->netdev;
+               if (!(netdev->features & NETIF_F_RXALL)) {
+                       dev_kfree_skb_any(skb);
+                       return true;
                }
+       }
 
-               if (rx_desc->wb.upper.length) {
-                       u16 length = le16_to_cpu(rx_desc->wb.upper.length);
+       /* place header in linear portion of buffer */
+       if (skb_is_nonlinear(skb))
+               igb_pull_tail(rx_ring, rx_desc, skb);
 
-                       skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags,
-                                               buffer_info->page,
-                                               buffer_info->page_offset,
-                                               length);
+       /* if skb_pad returns an error the skb was freed */
+       if (unlikely(skb->len < 60)) {
+               int pad_len = 60 - skb->len;
 
-                       skb->len += length;
-                       skb->data_len += length;
-                       skb->truesize += PAGE_SIZE / 2;
+               if (skb_pad(skb, pad_len))
+                       return true;
+               __skb_put(skb, pad_len);
+       }
 
-                       if ((page_count(buffer_info->page) != 1) ||
-                           (page_to_nid(buffer_info->page) != current_node))
-                               buffer_info->page = NULL;
-                       else
-                               get_page(buffer_info->page);
+       return false;
+}
 
-                       dma_unmap_page(rx_ring->dev, buffer_info->page_dma,
-                                      PAGE_SIZE / 2, DMA_FROM_DEVICE);
-                       buffer_info->page_dma = 0;
-               }
+/**
+ * igb_process_skb_fields - Populate skb header fields from Rx descriptor
+ * @rx_ring: rx descriptor ring packet is being transacted on
+ * @rx_desc: pointer to the EOP Rx descriptor
+ * @skb: pointer to current skb being populated
+ *
+ * This function checks the ring, descriptor, and packet information in
+ * order to populate the hash, checksum, VLAN, timestamp, protocol, and
+ * other fields within the skb.
+ **/
+static void igb_process_skb_fields(struct igb_ring *rx_ring,
+                                  union e1000_adv_rx_desc *rx_desc,
+                                  struct sk_buff *skb)
+{
+       struct net_device *dev = rx_ring->netdev;
 
-               if (!igb_test_staterr(rx_desc, E1000_RXD_STAT_EOP)) {
-                       struct igb_rx_buffer *next_buffer;
-                       next_buffer = &rx_ring->rx_buffer_info[i];
-                       buffer_info->skb = next_buffer->skb;
-                       buffer_info->dma = next_buffer->dma;
-                       next_buffer->skb = skb;
-                       next_buffer->dma = 0;
-                       goto next_desc;
-               }
+       igb_rx_hash(rx_ring, rx_desc, skb);
 
-               if (unlikely((igb_test_staterr(rx_desc,
-                                              E1000_RXDEXT_ERR_FRAME_ERR_MASK))
-                            && !(rx_ring->netdev->features & NETIF_F_RXALL))) {
-                       dev_kfree_skb_any(skb);
-                       goto next_desc;
-               }
+       igb_rx_checksum(rx_ring, rx_desc, skb);
 
 #ifdef CONFIG_IGB_PTP
-               igb_ptp_rx_hwtstamp(q_vector, rx_desc, skb);
+       igb_ptp_rx_hwtstamp(rx_ring->q_vector, rx_desc, skb);
 #endif /* CONFIG_IGB_PTP */
-               igb_rx_hash(rx_ring, rx_desc, skb);
-               igb_rx_checksum(rx_ring, rx_desc, skb);
-               igb_rx_vlan(rx_ring, rx_desc, skb);
 
-               total_bytes += skb->len;
-               total_packets++;
+       if ((dev->features & NETIF_F_HW_VLAN_RX) &&
+           igb_test_staterr(rx_desc, E1000_RXD_STAT_VP)) {
+               u16 vid;
+               if (igb_test_staterr(rx_desc, E1000_RXDEXT_STATERR_LB) &&
+                   test_bit(IGB_RING_FLAG_RX_LB_VLAN_BSWAP, &rx_ring->flags))
+                       vid = be16_to_cpu(rx_desc->wb.upper.vlan);
+               else
+                       vid = le16_to_cpu(rx_desc->wb.upper.vlan);
 
-               skb->protocol = eth_type_trans(skb, rx_ring->netdev);
+               __vlan_hwaccel_put_tag(skb, vid);
+       }
 
-               napi_gro_receive(&q_vector->napi, skb);
+       skb_record_rx_queue(skb, rx_ring->queue_index);
 
-               budget--;
-next_desc:
-               if (!budget)
-                       break;
+       skb->protocol = eth_type_trans(skb, rx_ring->netdev);
+}
+
+static bool igb_clean_rx_irq(struct igb_q_vector *q_vector, const int budget)
+{
+       struct igb_ring *rx_ring = q_vector->rx.ring;
+       struct sk_buff *skb = rx_ring->skb;
+       unsigned int total_bytes = 0, total_packets = 0;
+       u16 cleaned_count = igb_desc_unused(rx_ring);
+
+       do {
+               union e1000_adv_rx_desc *rx_desc;
 
-               cleaned_count++;
                /* return some buffers to hardware, one at a time is too slow */
                if (cleaned_count >= IGB_RX_BUFFER_WRITE) {
                        igb_alloc_rx_buffers(rx_ring, cleaned_count);
                        cleaned_count = 0;
                }
 
-               /* use prefetched values */
-               rx_desc = next_rxd;
-       }
+               rx_desc = IGB_RX_DESC(rx_ring, rx_ring->next_to_clean);
 
-       rx_ring->next_to_clean = i;
-       u64_stats_update_begin(&rx_ring->rx_syncp);
-       rx_ring->rx_stats.packets += total_packets;
-       rx_ring->rx_stats.bytes += total_bytes;
-       u64_stats_update_end(&rx_ring->rx_syncp);
-       q_vector->rx.total_packets += total_packets;
-       q_vector->rx.total_bytes += total_bytes;
+               if (!igb_test_staterr(rx_desc, E1000_RXD_STAT_DD))
+                       break;
 
-       if (cleaned_count)
-               igb_alloc_rx_buffers(rx_ring, cleaned_count);
+               /* retrieve a buffer from the ring */
+               skb = igb_fetch_rx_buffer(rx_ring, rx_desc, skb);
 
-       return !!budget;
-}
+               /* exit if we failed to retrieve a buffer */
+               if (!skb)
+                       break;
 
-static bool igb_alloc_mapped_skb(struct igb_ring *rx_ring,
-                                struct igb_rx_buffer *bi)
-{
-       struct sk_buff *skb = bi->skb;
-       dma_addr_t dma = bi->dma;
+               cleaned_count++;
 
-       if (dma)
-               return true;
+               /* fetch next buffer in frame if non-eop */
+               if (igb_is_non_eop(rx_ring, rx_desc))
+                       continue;
 
-       if (likely(!skb)) {
-               skb = netdev_alloc_skb_ip_align(rx_ring->netdev,
-                                               IGB_RX_HDR_LEN);
-               bi->skb = skb;
-               if (!skb) {
-                       rx_ring->rx_stats.alloc_failed++;
-                       return false;
+               /* verify the packet layout is correct */
+               if (igb_cleanup_headers(rx_ring, rx_desc, skb)) {
+                       skb = NULL;
+                       continue;
                }
 
-               /* initialize skb for ring */
-               skb_record_rx_queue(skb, rx_ring->queue_index);
-       }
+               /* probably a little skewed due to removing CRC */
+               total_bytes += skb->len;
 
-       dma = dma_map_single(rx_ring->dev, skb->data,
-                            IGB_RX_HDR_LEN, DMA_FROM_DEVICE);
+               /* populate checksum, timestamp, VLAN, and protocol */
+               igb_process_skb_fields(rx_ring, rx_desc, skb);
 
-       if (dma_mapping_error(rx_ring->dev, dma)) {
-               rx_ring->rx_stats.alloc_failed++;
-               return false;
-       }
+               napi_gro_receive(&q_vector->napi, skb);
 
-       bi->dma = dma;
-       return true;
+               /* reset skb pointer */
+               skb = NULL;
+
+               /* update budget accounting */
+               total_packets++;
+       } while (likely(total_packets < budget));
+
+       /* place incomplete frames back on ring for completion */
+       rx_ring->skb = skb;
+
+       u64_stats_update_begin(&rx_ring->rx_syncp);
+       rx_ring->rx_stats.packets += total_packets;
+       rx_ring->rx_stats.bytes += total_bytes;
+       u64_stats_update_end(&rx_ring->rx_syncp);
+       q_vector->rx.total_packets += total_packets;
+       q_vector->rx.total_bytes += total_bytes;
+
+       if (cleaned_count)
+               igb_alloc_rx_buffers(rx_ring, cleaned_count);
+
+       return (total_packets < budget);
 }
 
 static bool igb_alloc_mapped_page(struct igb_ring *rx_ring,
                                  struct igb_rx_buffer *bi)
 {
        struct page *page = bi->page;
-       dma_addr_t page_dma = bi->page_dma;
-       unsigned int page_offset = bi->page_offset ^ (PAGE_SIZE / 2);
+       dma_addr_t dma;
 
-       if (page_dma)
+       /* since we are recycling buffers we should seldom need to alloc */
+       if (likely(page))
                return true;
 
-       if (!page) {
-               page = __skb_alloc_page(GFP_ATOMIC, bi->skb);
-               bi->page = page;
-               if (unlikely(!page)) {
-                       rx_ring->rx_stats.alloc_failed++;
-                       return false;
-               }
+       /* alloc new page for storage */
+       page = __skb_alloc_page(GFP_ATOMIC | __GFP_COLD, NULL);
+       if (unlikely(!page)) {
+               rx_ring->rx_stats.alloc_failed++;
+               return false;
        }
 
-       page_dma = dma_map_page(rx_ring->dev, page,
-                               page_offset, PAGE_SIZE / 2,
-                               DMA_FROM_DEVICE);
+       /* map page for use */
+       dma = dma_map_page(rx_ring->dev, page, 0, PAGE_SIZE, DMA_FROM_DEVICE);
+
+       /*
+        * if mapping failed free memory back to system since
+        * there isn't much point in holding memory we can't use
+        */
+       if (dma_mapping_error(rx_ring->dev, dma)) {
+               __free_page(page);
 
-       if (dma_mapping_error(rx_ring->dev, page_dma)) {
                rx_ring->rx_stats.alloc_failed++;
                return false;
        }
 
-       bi->page_dma = page_dma;
-       bi->page_offset = page_offset;
+       bi->dma = dma;
+       bi->page = page;
+       bi->page_offset = 0;
+
        return true;
 }
 
@@ -6120,22 +6481,23 @@ void igb_alloc_rx_buffers(struct igb_ring *rx_ring, u16 cleaned_count)
        struct igb_rx_buffer *bi;
        u16 i = rx_ring->next_to_use;
 
+       /* nothing to do */
+       if (!cleaned_count)
+               return;
+
        rx_desc = IGB_RX_DESC(rx_ring, i);
        bi = &rx_ring->rx_buffer_info[i];
        i -= rx_ring->count;
 
-       while (cleaned_count--) {
-               if (!igb_alloc_mapped_skb(rx_ring, bi))
-                       break;
-
-               /* Refresh the desc even if buffer_addrs didn't change
-                * because each write-back erases this info. */
-               rx_desc->read.hdr_addr = cpu_to_le64(bi->dma);
-
+       do {
                if (!igb_alloc_mapped_page(rx_ring, bi))
                        break;
 
-               rx_desc->read.pkt_addr = cpu_to_le64(bi->page_dma);
+               /*
+                * Refresh the desc even if buffer_addrs didn't change
+                * because each write-back erases this info.
+                */
+               rx_desc->read.pkt_addr = cpu_to_le64(bi->dma + bi->page_offset);
 
                rx_desc++;
                bi++;
@@ -6148,17 +6510,25 @@ void igb_alloc_rx_buffers(struct igb_ring *rx_ring, u16 cleaned_count)
 
                /* clear the hdr_addr for the next_to_use descriptor */
                rx_desc->read.hdr_addr = 0;
-       }
+
+               cleaned_count--;
+       } while (cleaned_count);
 
        i += rx_ring->count;
 
        if (rx_ring->next_to_use != i) {
+               /* record the next descriptor to use */
                rx_ring->next_to_use = i;
 
-               /* Force memory writes to complete before letting h/w
+               /* update next to alloc since we have filled the ring */
+               rx_ring->next_to_alloc = i;
+
+               /*
+                * Force memory writes to complete before letting h/w
                 * know there are new descriptors to fetch.  (Only
                 * applicable for weak-ordered memory model archs,
-                * such as IA-64). */
+                * such as IA-64).
+                */
                wmb();
                writel(i, rx_ring->tail);
        }
@@ -6492,7 +6862,9 @@ static int igb_resume(struct device *dev)
        wr32(E1000_WUS, ~0);
 
        if (netdev->flags & IFF_UP) {
+               rtnl_lock();
                err = __igb_open(netdev, true);
+               rtnl_unlock();
                if (err)
                        return err;
        }
index ee21445157a3e8907a7b01267806d10b3ffab6e2..a7db4cec7a1c850bb6f1822941671c17416c72cb 100644 (file)
@@ -441,18 +441,46 @@ void igb_ptp_tx_hwtstamp(struct igb_adapter *adapter)
        adapter->ptp_tx_skb = NULL;
 }
 
-void igb_ptp_rx_hwtstamp(struct igb_q_vector *q_vector,
-                        union e1000_adv_rx_desc *rx_desc,
+/**
+ * igb_ptp_rx_pktstamp - retrieve Rx per packet timestamp
+ * @q_vector: Pointer to interrupt specific structure
+ * @va: Pointer to address containing Rx buffer
+ * @skb: Buffer containing timestamp and packet
+ *
+ * This function is meant to retrieve a timestamp from the first buffer of an
+ * incoming frame.  The value is stored in little endian format starting on
+ * byte 8.
+ */
+void igb_ptp_rx_pktstamp(struct igb_q_vector *q_vector,
+                        unsigned char *va,
+                        struct sk_buff *skb)
+{
+       u64 *regval = (u64 *)va;
+
+       /*
+        * The timestamp is recorded in little endian format.
+        * DWORD: 0        1        2        3
+        * Field: Reserved Reserved SYSTIML  SYSTIMH
+        */
+       igb_ptp_systim_to_hwtstamp(q_vector->adapter, skb_hwtstamps(skb),
+                                  le64_to_cpu(regval[1]));
+}
+
+/**
+ * igb_ptp_rx_rgtstamp - retrieve Rx timestamp stored in register
+ * @q_vector: Pointer to interrupt specific structure
+ * @skb: Buffer containing timestamp and packet
+ *
+ * This function is meant to retrieve a timestamp from the internal registers
+ * of the adapter and store it in the skb.
+ */
+void igb_ptp_rx_rgtstamp(struct igb_q_vector *q_vector,
                         struct sk_buff *skb)
 {
        struct igb_adapter *adapter = q_vector->adapter;
        struct e1000_hw *hw = &adapter->hw;
        u64 regval;
 
-       if (!igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP |
-                                      E1000_RXDADV_STAT_TS))
-               return;
-
        /*
         * If this bit is set, then the RX registers contain the time stamp. No
         * other packet will be time stamped until we read these registers, so
@@ -464,18 +492,11 @@ void igb_ptp_rx_hwtstamp(struct igb_q_vector *q_vector,
         * If nothing went wrong, then it should have a shared tx_flags that we
         * can turn into a skb_shared_hwtstamps.
         */
-       if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP)) {
-               u32 *stamp = (u32 *)skb->data;
-               regval = le32_to_cpu(*(stamp + 2));
-               regval |= (u64)le32_to_cpu(*(stamp + 3)) << 32;
-               skb_pull(skb, IGB_TS_HDR_LEN);
-       } else {
-               if (!(rd32(E1000_TSYNCRXCTL) & E1000_TSYNCRXCTL_VALID))
-                       return;
+       if (!(rd32(E1000_TSYNCRXCTL) & E1000_TSYNCRXCTL_VALID))
+               return;
 
-               regval = rd32(E1000_RXSTMPL);
-               regval |= (u64)rd32(E1000_RXSTMPH) << 32;
-       }
+       regval = rd32(E1000_RXSTMPL);
+       regval |= (u64)rd32(E1000_RXSTMPH) << 32;
 
        igb_ptp_systim_to_hwtstamp(adapter, skb_hwtstamps(skb), regval);
 }
index 30efc9f0f47a3cea7cf5aee5438b5ad70c208f30..c64a777b2c0b91f15645c3281eeeb8426a8c1105 100644 (file)
@@ -135,6 +135,7 @@ struct vf_data_storage {
        u16 tx_rate;
        u16 vlan_count;
        u8 spoofchk_enabled;
+       unsigned int vf_api;
 };
 
 struct vf_macvlans {
@@ -482,7 +483,7 @@ struct ixgbe_adapter {
 #define IXGBE_FLAG2_FDIR_REQUIRES_REINIT        (u32)(1 << 7)
 #define IXGBE_FLAG2_RSS_FIELD_IPV4_UDP         (u32)(1 << 8)
 #define IXGBE_FLAG2_RSS_FIELD_IPV6_UDP         (u32)(1 << 9)
-#define IXGBE_FLAG2_OVERFLOW_CHECK_ENABLED     (u32)(1 << 10)
+#define IXGBE_FLAG2_PTP_ENABLED                        (u32)(1 << 10)
 #define IXGBE_FLAG2_PTP_PPS_ENABLED            (u32)(1 << 11)
 
        /* Tx fast path data */
@@ -580,7 +581,6 @@ struct ixgbe_adapter {
        struct timecounter tc;
        int rx_hwtstamp_filter;
        u32 base_incval;
-       u32 cycle_speed;
 #endif /* CONFIG_IXGBE_PTP */
 
        /* SR-IOV */
@@ -600,6 +600,8 @@ struct ixgbe_adapter {
 #ifdef CONFIG_DEBUG_FS
        struct dentry *ixgbe_dbg_adapter;
 #endif /*CONFIG_DEBUG_FS*/
+
+       u8 default_up;
 };
 
 struct ixgbe_fdir_filter {
@@ -751,6 +753,7 @@ extern void ixgbe_ptp_rx_hwtstamp(struct ixgbe_q_vector *q_vector,
 extern int ixgbe_ptp_hwtstamp_ioctl(struct ixgbe_adapter *adapter,
                                    struct ifreq *ifr, int cmd);
 extern void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter);
+extern void ixgbe_ptp_reset(struct ixgbe_adapter *adapter);
 extern void ixgbe_ptp_check_pps_event(struct ixgbe_adapter *adapter, u32 eicr);
 #endif /* CONFIG_IXGBE_PTP */
 
index 1077cb2b38db15f4123eca7d9d71492df86b0a05..b52781351659b3be6268a9c54dddebd7878e31d1 100644 (file)
@@ -2080,6 +2080,50 @@ static s32 ixgbe_read_eeprom_82599(struct ixgbe_hw *hw,
        return ret_val;
 }
 
+/**
+ * ixgbe_reset_pipeline_82599 - perform pipeline reset
+ *
+ * @hw: pointer to hardware structure
+ *
+ * Reset pipeline by asserting Restart_AN together with LMS change to ensure
+ * full pipeline reset.  Note - We must hold the SW/FW semaphore before writing
+ * to AUTOC, so this function assumes the semaphore is held.
+ **/
+s32 ixgbe_reset_pipeline_82599(struct ixgbe_hw *hw)
+{
+       s32 i, autoc_reg, ret_val;
+       s32 anlp1_reg = 0;
+
+       autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
+       autoc_reg |= IXGBE_AUTOC_AN_RESTART;
+
+       /* Write AUTOC register with toggled LMS[2] bit and Restart_AN */
+       IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg ^ IXGBE_AUTOC_LMS_1G_AN);
+
+       /* Wait for AN to leave state 0 */
+       for (i = 0; i < 10; i++) {
+               usleep_range(4000, 8000);
+               anlp1_reg = IXGBE_READ_REG(hw, IXGBE_ANLP1);
+               if (anlp1_reg & IXGBE_ANLP1_AN_STATE_MASK)
+                       break;
+       }
+
+       if (!(anlp1_reg & IXGBE_ANLP1_AN_STATE_MASK)) {
+               hw_dbg(hw, "auto negotiation not completed\n");
+               ret_val = IXGBE_ERR_RESET_FAILED;
+               goto reset_pipeline_out;
+       }
+
+       ret_val = 0;
+
+reset_pipeline_out:
+       /* Write AUTOC register with original LMS field and Restart_AN */
+       IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg);
+       IXGBE_WRITE_FLUSH(hw);
+
+       return ret_val;
+}
+
 static struct ixgbe_mac_operations mac_ops_82599 = {
        .init_hw                = &ixgbe_init_hw_generic,
        .reset_hw               = &ixgbe_reset_hw_82599,
index dbf37e4a45fda722df461cc11eaaf8b2bd0449f8..a2a9bcca491546eeb90e9102b69151ddcf54ce0c 100644 (file)
@@ -1778,8 +1778,7 @@ s32 ixgbe_validate_mac_addr(u8 *mac_addr)
        else if (IXGBE_IS_BROADCAST(mac_addr))
                status = IXGBE_ERR_INVALID_MAC_ADDR;
        /* Reject the zero address */
-       else if (mac_addr[0] == 0 && mac_addr[1] == 0 && mac_addr[2] == 0 &&
-                mac_addr[3] == 0 && mac_addr[4] == 0 && mac_addr[5] == 0)
+       else if (is_zero_ether_addr(mac_addr))
                status = IXGBE_ERR_INVALID_MAC_ADDR;
 
        return status;
index d813d1188c3617156e6e35ed260aaf1ec3ab2482..587db4728072f94d241a4d53827630586f2a1bf1 100644 (file)
@@ -107,6 +107,7 @@ void ixgbe_clear_tx_pending(struct ixgbe_hw *hw);
 
 void ixgbe_set_rxpba_generic(struct ixgbe_hw *hw, int num_pb,
                             u32 headroom, int strategy);
+s32 ixgbe_reset_pipeline_82599(struct ixgbe_hw *hw);
 
 #define IXGBE_I2C_THERMAL_SENSOR_ADDR  0xF8
 #define IXGBE_EMC_INTERNAL_DATA                0x00
index 56b20d17d0e4c5577828040fddf8bd294868c84d..872c3374ddfa4c3ccd3b2a2b1af2a713c9119120 100644 (file)
@@ -887,24 +887,23 @@ static int ixgbe_set_ringparam(struct net_device *netdev,
                                struct ethtool_ringparam *ring)
 {
        struct ixgbe_adapter *adapter = netdev_priv(netdev);
-       struct ixgbe_ring *temp_tx_ring, *temp_rx_ring;
+       struct ixgbe_ring *temp_ring;
        int i, err = 0;
        u32 new_rx_count, new_tx_count;
-       bool need_update = false;
 
        if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
                return -EINVAL;
 
-       new_rx_count = max_t(u32, ring->rx_pending, IXGBE_MIN_RXD);
-       new_rx_count = min_t(u32, new_rx_count, IXGBE_MAX_RXD);
-       new_rx_count = ALIGN(new_rx_count, IXGBE_REQ_RX_DESCRIPTOR_MULTIPLE);
-
-       new_tx_count = max_t(u32, ring->tx_pending, IXGBE_MIN_TXD);
-       new_tx_count = min_t(u32, new_tx_count, IXGBE_MAX_TXD);
+       new_tx_count = clamp_t(u32, ring->tx_pending,
+                              IXGBE_MIN_TXD, IXGBE_MAX_TXD);
        new_tx_count = ALIGN(new_tx_count, IXGBE_REQ_TX_DESCRIPTOR_MULTIPLE);
 
-       if ((new_tx_count == adapter->tx_ring[0]->count) &&
-           (new_rx_count == adapter->rx_ring[0]->count)) {
+       new_rx_count = clamp_t(u32, ring->rx_pending,
+                              IXGBE_MIN_RXD, IXGBE_MAX_RXD);
+       new_rx_count = ALIGN(new_rx_count, IXGBE_REQ_RX_DESCRIPTOR_MULTIPLE);
+
+       if ((new_tx_count == adapter->tx_ring_count) &&
+           (new_rx_count == adapter->rx_ring_count)) {
                /* nothing to do */
                return 0;
        }
@@ -922,81 +921,80 @@ static int ixgbe_set_ringparam(struct net_device *netdev,
                goto clear_reset;
        }
 
-       temp_tx_ring = vmalloc(adapter->num_tx_queues * sizeof(struct ixgbe_ring));
-       if (!temp_tx_ring) {
+       /* allocate temporary buffer to store rings in */
+       i = max_t(int, adapter->num_tx_queues, adapter->num_rx_queues);
+       temp_ring = vmalloc(i * sizeof(struct ixgbe_ring));
+
+       if (!temp_ring) {
                err = -ENOMEM;
                goto clear_reset;
        }
 
+       ixgbe_down(adapter);
+
+       /*
+        * Setup new Tx resources and free the old Tx resources in that order.
+        * We can then assign the new resources to the rings via a memcpy.
+        * The advantage to this approach is that we are guaranteed to still
+        * have resources even in the case of an allocation failure.
+        */
        if (new_tx_count != adapter->tx_ring_count) {
                for (i = 0; i < adapter->num_tx_queues; i++) {
-                       memcpy(&temp_tx_ring[i], adapter->tx_ring[i],
+                       memcpy(&temp_ring[i], adapter->tx_ring[i],
                               sizeof(struct ixgbe_ring));
-                       temp_tx_ring[i].count = new_tx_count;
-                       err = ixgbe_setup_tx_resources(&temp_tx_ring[i]);
+
+                       temp_ring[i].count = new_tx_count;
+                       err = ixgbe_setup_tx_resources(&temp_ring[i]);
                        if (err) {
                                while (i) {
                                        i--;
-                                       ixgbe_free_tx_resources(&temp_tx_ring[i]);
+                                       ixgbe_free_tx_resources(&temp_ring[i]);
                                }
-                               goto clear_reset;
+                               goto err_setup;
                        }
                }
-               need_update = true;
-       }
 
-       temp_rx_ring = vmalloc(adapter->num_rx_queues * sizeof(struct ixgbe_ring));
-       if (!temp_rx_ring) {
-               err = -ENOMEM;
-               goto err_setup;
+               for (i = 0; i < adapter->num_tx_queues; i++) {
+                       ixgbe_free_tx_resources(adapter->tx_ring[i]);
+
+                       memcpy(adapter->tx_ring[i], &temp_ring[i],
+                              sizeof(struct ixgbe_ring));
+               }
+
+               adapter->tx_ring_count = new_tx_count;
        }
 
+       /* Repeat the process for the Rx rings if needed */
        if (new_rx_count != adapter->rx_ring_count) {
                for (i = 0; i < adapter->num_rx_queues; i++) {
-                       memcpy(&temp_rx_ring[i], adapter->rx_ring[i],
+                       memcpy(&temp_ring[i], adapter->rx_ring[i],
                               sizeof(struct ixgbe_ring));
-                       temp_rx_ring[i].count = new_rx_count;
-                       err = ixgbe_setup_rx_resources(&temp_rx_ring[i]);
+
+                       temp_ring[i].count = new_rx_count;
+                       err = ixgbe_setup_rx_resources(&temp_ring[i]);
                        if (err) {
                                while (i) {
                                        i--;
-                                       ixgbe_free_rx_resources(&temp_rx_ring[i]);
+                                       ixgbe_free_rx_resources(&temp_ring[i]);
                                }
                                goto err_setup;
                        }
+
                }
-               need_update = true;
-       }
 
-       /* if rings need to be updated, here's the place to do it in one shot */
-       if (need_update) {
-               ixgbe_down(adapter);
+               for (i = 0; i < adapter->num_rx_queues; i++) {
+                       ixgbe_free_rx_resources(adapter->rx_ring[i]);
 
-               /* tx */
-               if (new_tx_count != adapter->tx_ring_count) {
-                       for (i = 0; i < adapter->num_tx_queues; i++) {
-                               ixgbe_free_tx_resources(adapter->tx_ring[i]);
-                               memcpy(adapter->tx_ring[i], &temp_tx_ring[i],
-                                      sizeof(struct ixgbe_ring));
-                       }
-                       adapter->tx_ring_count = new_tx_count;
+                       memcpy(adapter->rx_ring[i], &temp_ring[i],
+                              sizeof(struct ixgbe_ring));
                }
 
-               /* rx */
-               if (new_rx_count != adapter->rx_ring_count) {
-                       for (i = 0; i < adapter->num_rx_queues; i++) {
-                               ixgbe_free_rx_resources(adapter->rx_ring[i]);
-                               memcpy(adapter->rx_ring[i], &temp_rx_ring[i],
-                                      sizeof(struct ixgbe_ring));
-                       }
-                       adapter->rx_ring_count = new_rx_count;
-               }
-               ixgbe_up(adapter);
+               adapter->rx_ring_count = new_rx_count;
        }
 
-       vfree(temp_rx_ring);
 err_setup:
-       vfree(temp_tx_ring);
+       ixgbe_up(adapter);
+       vfree(temp_ring);
 clear_reset:
        clear_bit(__IXGBE_RESETTING, &adapter->state);
        return err;
index ae73ef14fdf341795cf499c5abab207704a70d34..252850d9a3e0925b45bcb3524dd7c6e490540616 100644 (file)
@@ -800,6 +800,10 @@ int ixgbe_fcoe_enable(struct net_device *netdev)
                return -EINVAL;
 
        e_info(drv, "Enabling FCoE offload features.\n");
+
+       if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)
+               e_warn(probe, "Enabling FCoE on PF will disable legacy VFs\n");
+
        if (netif_running(netdev))
                netdev->netdev_ops->ndo_stop(netdev);
 
index 17ecbcedd5481d0dcafa46138839088478cbf2c6..5e508b614dc376d5ac7a7473f4cce9767ec8d848 100644 (file)
@@ -802,10 +802,13 @@ static int ixgbe_alloc_q_vector(struct ixgbe_adapter *adapter,
        /* setup affinity mask and node */
        if (cpu != -1)
                cpumask_set_cpu(cpu, &q_vector->affinity_mask);
-       else
-               cpumask_copy(&q_vector->affinity_mask, cpu_online_mask);
        q_vector->numa_node = node;
 
+#ifdef CONFIG_IXGBE_DCA
+       /* initialize CPU for DCA */
+       q_vector->cpu = -1;
+
+#endif
        /* initialize NAPI */
        netif_napi_add(adapter->netdev, &q_vector->napi,
                       ixgbe_poll, 64);
index fa3d552e1f4a1e6b0cad19c4e4d5610551866638..88d636a7459cde58f987de6063dddc8ccdbf8f83 100644 (file)
@@ -1244,6 +1244,7 @@ static unsigned int ixgbe_get_headlen(unsigned char *data,
                struct vlan_hdr *vlan;
                /* l3 headers */
                struct iphdr *ipv4;
+               struct ipv6hdr *ipv6;
        } hdr;
        __be16 protocol;
        u8 nexthdr = 0; /* default to not TCP */
@@ -1284,6 +1285,13 @@ static unsigned int ixgbe_get_headlen(unsigned char *data,
                /* record next protocol */
                nexthdr = hdr.ipv4->protocol;
                hdr.network += hlen;
+       } else if (protocol == __constant_htons(ETH_P_IPV6)) {
+               if ((hdr.network - data) > (max_len - sizeof(struct ipv6hdr)))
+                       return max_len;
+
+               /* record next protocol */
+               nexthdr = hdr.ipv6->nexthdr;
+               hdr.network += sizeof(struct ipv6hdr);
 #ifdef IXGBE_FCOE
        } else if (protocol == __constant_htons(ETH_P_FCOE)) {
                if ((hdr.network - data) > (max_len - FCOE_HEADER_LEN))
@@ -1294,7 +1302,7 @@ static unsigned int ixgbe_get_headlen(unsigned char *data,
                return hdr.network - data;
        }
 
-       /* finally sort out TCP */
+       /* finally sort out TCP/UDP */
        if (nexthdr == IPPROTO_TCP) {
                if ((hdr.network - data) > (max_len - sizeof(struct tcphdr)))
                        return max_len;
@@ -1307,6 +1315,11 @@ static unsigned int ixgbe_get_headlen(unsigned char *data,
                        return hdr.network - data;
 
                hdr.network += hlen;
+       } else if (nexthdr == IPPROTO_UDP) {
+               if ((hdr.network - data) > (max_len - sizeof(struct udphdr)))
+                       return max_len;
+
+               hdr.network += sizeof(struct udphdr);
        }
 
        /*
@@ -3263,6 +3276,11 @@ static void ixgbe_set_rx_buffer_len(struct ixgbe_adapter *adapter)
                max_frame = IXGBE_FCOE_JUMBO_FRAME_SIZE;
 
 #endif /* IXGBE_FCOE */
+
+       /* adjust max frame to be at least the size of a standard frame */
+       if (max_frame < (ETH_FRAME_LEN + ETH_FCS_LEN))
+               max_frame = (ETH_FRAME_LEN + ETH_FCS_LEN);
+
        mhadd = IXGBE_READ_REG(hw, IXGBE_MHADD);
        if (max_frame != (mhadd >> IXGBE_MHADD_MFS_SHIFT)) {
                mhadd &= ~IXGBE_MHADD_MFS_MASK;
@@ -3271,9 +3289,6 @@ static void ixgbe_set_rx_buffer_len(struct ixgbe_adapter *adapter)
                IXGBE_WRITE_REG(hw, IXGBE_MHADD, mhadd);
        }
 
-       /* MHADD will allow an extra 4 bytes past for vlan tagged frames */
-       max_frame += VLAN_HLEN;
-
        hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0);
        /* set jumbo enable since MHADD.MFS is keeping size locked at max_frame */
        hlreg0 |= IXGBE_HLREG0_JUMBOEN;
@@ -4192,6 +4207,11 @@ void ixgbe_reset(struct ixgbe_adapter *adapter)
        /* update SAN MAC vmdq pool selection */
        if (hw->mac.san_mac_rar_index)
                hw->mac.ops.set_vmdq_san_mac(hw, VMDQ_P(0));
+
+#ifdef CONFIG_IXGBE_PTP
+       if (adapter->flags2 & IXGBE_FLAG2_PTP_ENABLED)
+               ixgbe_ptp_reset(adapter);
+#endif
 }
 
 /**
@@ -4828,14 +4848,14 @@ static int ixgbe_change_mtu(struct net_device *netdev, int new_mtu)
                return -EINVAL;
 
        /*
-        * For 82599EB we cannot allow PF to change MTU greater than 1500
-        * in SR-IOV mode as it may cause buffer overruns in guest VFs that
-        * don't allocate and chain buffers correctly.
+        * For 82599EB we cannot allow legacy VFs to enable their receive
+        * paths when MTU greater than 1500 is configured.  So display a
+        * warning that legacy VFs will be disabled.
         */
        if ((adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) &&
            (adapter->hw.mac.type == ixgbe_mac_82599EB) &&
            (max_frame > MAXIMUM_ETHERNET_VLAN_SIZE))
-                       return -EINVAL;
+               e_warn(probe, "Setting MTU > 1500 will disable legacy VFs\n");
 
        e_info(probe, "changing MTU from %d to %d\n", netdev->mtu, new_mtu);
 
@@ -4901,6 +4921,10 @@ static int ixgbe_open(struct net_device *netdev)
        if (err)
                goto err_set_queues;
 
+#ifdef CONFIG_IXGBE_PTP
+       ixgbe_ptp_init(adapter);
+#endif /* CONFIG_IXGBE_PTP*/
+
        ixgbe_up_complete(adapter);
 
        return 0;
@@ -4932,6 +4956,10 @@ static int ixgbe_close(struct net_device *netdev)
 {
        struct ixgbe_adapter *adapter = netdev_priv(netdev);
 
+#ifdef CONFIG_IXGBE_PTP
+       ixgbe_ptp_stop(adapter);
+#endif
+
        ixgbe_down(adapter);
        ixgbe_free_irq(adapter);
 
@@ -5442,6 +5470,23 @@ static void ixgbe_watchdog_update_link(struct ixgbe_adapter *adapter)
        adapter->link_speed = link_speed;
 }
 
+static void ixgbe_update_default_up(struct ixgbe_adapter *adapter)
+{
+#ifdef CONFIG_IXGBE_DCB
+       struct net_device *netdev = adapter->netdev;
+       struct dcb_app app = {
+                             .selector = IEEE_8021QAZ_APP_SEL_ETHERTYPE,
+                             .protocol = 0,
+                            };
+       u8 up = 0;
+
+       if (adapter->dcbx_cap & DCB_CAP_DCBX_VER_IEEE)
+               up = dcb_ieee_getapp_mask(netdev, &app);
+
+       adapter->default_up = (up > 1) ? (ffs(up) - 1) : 0;
+#endif
+}
+
 /**
  * ixgbe_watchdog_link_is_up - update netif_carrier status and
  *                             print link up message
@@ -5483,7 +5528,8 @@ static void ixgbe_watchdog_link_is_up(struct ixgbe_adapter *adapter)
        }
 
 #ifdef CONFIG_IXGBE_PTP
-       ixgbe_ptp_start_cyclecounter(adapter);
+       if (adapter->flags2 & IXGBE_FLAG2_PTP_ENABLED)
+               ixgbe_ptp_start_cyclecounter(adapter);
 #endif
 
        e_info(drv, "NIC Link is Up %s, Flow Control: %s\n",
@@ -5501,6 +5547,9 @@ static void ixgbe_watchdog_link_is_up(struct ixgbe_adapter *adapter)
        netif_carrier_on(netdev);
        ixgbe_check_vf_rate_limit(adapter);
 
+       /* update the default user priority for VFs */
+       ixgbe_update_default_up(adapter);
+
        /* ping all the active vfs to let them know link has changed */
        ixgbe_ping_all_vfs(adapter);
 }
@@ -5527,7 +5576,8 @@ static void ixgbe_watchdog_link_is_down(struct ixgbe_adapter *adapter)
                adapter->flags2 |= IXGBE_FLAG2_SEARCH_FOR_SFP;
 
 #ifdef CONFIG_IXGBE_PTP
-       ixgbe_ptp_start_cyclecounter(adapter);
+       if (adapter->flags2 & IXGBE_FLAG2_PTP_ENABLED)
+               ixgbe_ptp_start_cyclecounter(adapter);
 #endif
 
        e_info(drv, "NIC Link is Down\n");
@@ -6485,6 +6535,7 @@ static netdev_tx_t ixgbe_xmit_frame(struct sk_buff *skb,
                if (skb_pad(skb, 17 - skb->len))
                        return NETDEV_TX_OK;
                skb->len = 17;
+               skb_set_tail_pointer(skb, 17);
        }
 
        tx_ring = adapter->tx_ring[skb->queue_mapping];
@@ -7042,6 +7093,7 @@ int ixgbe_wol_supported(struct ixgbe_adapter *adapter, u16 device_id,
                                break;
                case IXGBE_SUBDEV_ID_82599_SFP:
                case IXGBE_SUBDEV_ID_82599_RNDC:
+               case IXGBE_SUBDEV_ID_82599_ECNA_DP:
                        is_wol_supported = 1;
                        break;
                }
@@ -7364,10 +7416,6 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
 
        device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
 
-#ifdef CONFIG_IXGBE_PTP
-       ixgbe_ptp_init(adapter);
-#endif /* CONFIG_IXGBE_PTP*/
-
        /* save off EEPROM version number */
        hw->eeprom.ops.read(hw, 0x2e, &adapter->eeprom_verh);
        hw->eeprom.ops.read(hw, 0x2d, &adapter->eeprom_verl);
@@ -7505,9 +7553,6 @@ static void __devexit ixgbe_remove(struct pci_dev *pdev)
        set_bit(__IXGBE_DOWN, &adapter->state);
        cancel_work_sync(&adapter->service_task);
 
-#ifdef CONFIG_IXGBE_PTP
-       ixgbe_ptp_stop(adapter);
-#endif
 
 #ifdef CONFIG_IXGBE_DCA
        if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) {
index 310bdd9610757558827d31155ad1bc839d617bfb..42dd65e6ac978906b70bd565c1811a26fda3bb3f 100644 (file)
 /* bits 23:16 are used for exra info for certain messages */
 #define IXGBE_VT_MSGINFO_MASK     (0xFF << IXGBE_VT_MSGINFO_SHIFT)
 
+/* definitions to support mailbox API version negotiation */
+
+/*
+ * Each element denotes a version of the API; existing numbers may not
+ * change; any additions must go at the end
+ */
+enum ixgbe_pfvf_api_rev {
+       ixgbe_mbox_api_10,      /* API version 1.0, linux/freebsd VF driver */
+       ixgbe_mbox_api_20,      /* API version 2.0, solaris Phase1 VF driver */
+       ixgbe_mbox_api_11,      /* API version 1.1, linux/freebsd VF driver */
+       /* This value should always be last */
+       ixgbe_mbox_api_unknown, /* indicates that API version is not known */
+};
+
+/* mailbox API, legacy requests */
 #define IXGBE_VF_RESET            0x01 /* VF requests reset */
 #define IXGBE_VF_SET_MAC_ADDR     0x02 /* VF requests PF to set MAC addr */
 #define IXGBE_VF_SET_MULTICAST    0x03 /* VF requests PF to set MC addr */
 #define IXGBE_VF_SET_VLAN         0x04 /* VF requests PF to set VLAN */
-#define IXGBE_VF_SET_LPE          0x05 /* VF requests PF to set VMOLR.LPE */
-#define IXGBE_VF_SET_MACVLAN      0x06 /* VF requests PF for unicast filter */
+
+/* mailbox API, version 1.0 VF requests */
+#define IXGBE_VF_SET_LPE       0x05 /* VF requests PF to set VMOLR.LPE */
+#define IXGBE_VF_SET_MACVLAN   0x06 /* VF requests PF for unicast filter */
+#define IXGBE_VF_API_NEGOTIATE 0x08 /* negotiate API version */
+
+/* mailbox API, version 1.1 VF requests */
+#define IXGBE_VF_GET_QUEUES    0x09 /* get queue configuration */
+
+/* GET_QUEUES return data indices within the mailbox */
+#define IXGBE_VF_TX_QUEUES     1       /* number of Tx queues supported */
+#define IXGBE_VF_RX_QUEUES     2       /* number of Rx queues supported */
+#define IXGBE_VF_TRANS_VLAN    3       /* Indication of port vlan */
+#define IXGBE_VF_DEF_QUEUE     4       /* Default queue offset */
 
 /* length of permanent address message returned from PF */
 #define IXGBE_VF_PERMADDR_MSG_LEN 4
index d9291316ee9f3aee8bbe54710a6ebcffb37c6ef7..5e71ddbb34149e749601a2db2352065a2e5b2a14 100644 (file)
@@ -411,7 +411,7 @@ void ixgbe_ptp_overflow_check(struct ixgbe_adapter *adapter)
        unsigned long elapsed_jiffies = adapter->last_overflow_check - jiffies;
        struct timespec ts;
 
-       if ((adapter->flags2 & IXGBE_FLAG2_OVERFLOW_CHECK_ENABLED) &&
+       if ((adapter->flags2 & IXGBE_FLAG2_PTP_ENABLED) &&
            (elapsed_jiffies >= IXGBE_OVERFLOW_PERIOD)) {
                ixgbe_ptp_gettime(&adapter->ptp_caps, &ts);
                adapter->last_overflow_check = jiffies;
@@ -759,57 +759,19 @@ int ixgbe_ptp_hwtstamp_ioctl(struct ixgbe_adapter *adapter,
  * ixgbe_ptp_start_cyclecounter - create the cycle counter from hw
  * @adapter: pointer to the adapter structure
  *
- * this function initializes the timecounter and cyclecounter
- * structures for use in generated a ns counter from the arbitrary
- * fixed point cycles registers in the hardware.
- *
- * A change in link speed impacts the frequency of the DMA clock on
- * the device, which is used to generate the cycle counter
- * registers. Therefor this function is called whenever the link speed
- * changes.
- *
- * This function also turns on the SDP pin for clock out feature (X540
- * only), because this is where the shift is first calculated.
+ * This function should be called to set the proper values for the TIMINCA
+ * register and tell the cyclecounter structure what the tick rate of SYSTIME
+ * is. It does not directly modify SYSTIME registers or the timecounter
+ * structure. It should be called whenever a new TIMINCA value is necessary,
+ * such as during initialization or when the link speed changes.
  */
 void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter)
 {
        struct ixgbe_hw *hw = &adapter->hw;
        u32 incval = 0;
-       u32 timinca = 0;
        u32 shift = 0;
-       u32 cycle_speed;
        unsigned long flags;
 
-       /**
-        * Determine what speed we need to set the cyclecounter
-        * for. It should be different for 100Mb, 1Gb, and 10Gb. Treat
-        * unknown speeds as 10Gb. (Hence why we can't just copy the
-        * link_speed.
-        */
-       switch (adapter->link_speed) {
-       case IXGBE_LINK_SPEED_100_FULL:
-       case IXGBE_LINK_SPEED_1GB_FULL:
-       case IXGBE_LINK_SPEED_10GB_FULL:
-               cycle_speed = adapter->link_speed;
-               break;
-       default:
-               /* cycle speed should be 10Gb when there is no link */
-               cycle_speed = IXGBE_LINK_SPEED_10GB_FULL;
-               break;
-       }
-
-       /*
-        * grab the current TIMINCA value from the register so that it can be
-        * double checked. If the register value has been cleared, it must be
-        * reset to the correct value for generating a cyclecounter. If
-        * TIMINCA is zero, the SYSTIME registers do not increment at all.
-        */
-       timinca = IXGBE_READ_REG(hw, IXGBE_TIMINCA);
-
-       /* Bail if the cycle speed didn't change and TIMINCA is non-zero */
-       if (adapter->cycle_speed == cycle_speed && timinca)
-               return;
-
        /**
         * Scale the NIC cycle counter by a large factor so that
         * relatively small corrections to the frequency can be added
@@ -819,8 +781,12 @@ void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter)
         * to nanoseconds using only a multiplier and a right-shift,
         * and (c) the value must fit within the timinca register space
         * => math based on internal DMA clock rate and available bits
+        *
+        * Note that when there is no link, internal DMA clock is same as when
+        * link speed is 10Gb. Set the registers correctly even when link is
+        * down to preserve the clock setting
         */
-       switch (cycle_speed) {
+       switch (adapter->link_speed) {
        case IXGBE_LINK_SPEED_100_FULL:
                incval = IXGBE_INCVAL_100;
                shift = IXGBE_INCVAL_SHIFT_100;
@@ -830,6 +796,7 @@ void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter)
                shift = IXGBE_INCVAL_SHIFT_1GB;
                break;
        case IXGBE_LINK_SPEED_10GB_FULL:
+       default:
                incval = IXGBE_INCVAL_10GB;
                shift = IXGBE_INCVAL_SHIFT_10GB;
                break;
@@ -857,18 +824,11 @@ void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter)
                return;
        }
 
-       /* reset the system time registers */
-       IXGBE_WRITE_REG(hw, IXGBE_SYSTIML, 0x00000000);
-       IXGBE_WRITE_REG(hw, IXGBE_SYSTIMH, 0x00000000);
-       IXGBE_WRITE_FLUSH(hw);
-
-       /* store the new cycle speed */
-       adapter->cycle_speed = cycle_speed;
-
+       /* update the base incval used to calculate frequency adjustment */
        ACCESS_ONCE(adapter->base_incval) = incval;
        smp_mb();
 
-       /* grab the ptp lock */
+       /* need lock to prevent incorrect read while modifying cyclecounter */
        spin_lock_irqsave(&adapter->tmreg_lock, flags);
 
        memset(&adapter->cc, 0, sizeof(adapter->cc));
@@ -877,6 +837,31 @@ void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter)
        adapter->cc.shift = shift;
        adapter->cc.mult = 1;
 
+       spin_unlock_irqrestore(&adapter->tmreg_lock, flags);
+}
+
+/**
+ * ixgbe_ptp_reset
+ * @adapter: the ixgbe private board structure
+ *
+ * When the MAC resets, all timesync features are reset. This function should be
+ * called to re-enable the PTP clock structure. It will re-init the timecounter
+ * structure based on the kernel time as well as setup the cycle counter data.
+ */
+void ixgbe_ptp_reset(struct ixgbe_adapter *adapter)
+{
+       struct ixgbe_hw *hw = &adapter->hw;
+       unsigned long flags;
+
+       /* set SYSTIME registers to 0 just in case */
+       IXGBE_WRITE_REG(hw, IXGBE_SYSTIML, 0x00000000);
+       IXGBE_WRITE_REG(hw, IXGBE_SYSTIMH, 0x00000000);
+       IXGBE_WRITE_FLUSH(hw);
+
+       ixgbe_ptp_start_cyclecounter(adapter);
+
+       spin_lock_irqsave(&adapter->tmreg_lock, flags);
+
        /* reset the ns time counter */
        timecounter_init(&adapter->tc, &adapter->cc,
                         ktime_to_ns(ktime_get_real()));
@@ -904,7 +889,7 @@ void ixgbe_ptp_init(struct ixgbe_adapter *adapter)
 
        switch (adapter->hw.mac.type) {
        case ixgbe_mac_X540:
-               snprintf(adapter->ptp_caps.name, 16, "%pm", netdev->dev_addr);
+               snprintf(adapter->ptp_caps.name, 16, "%s", netdev->name);
                adapter->ptp_caps.owner = THIS_MODULE;
                adapter->ptp_caps.max_adj = 250000000;
                adapter->ptp_caps.n_alarm = 0;
@@ -918,7 +903,7 @@ void ixgbe_ptp_init(struct ixgbe_adapter *adapter)
                adapter->ptp_caps.enable = ixgbe_ptp_enable;
                break;
        case ixgbe_mac_82599EB:
-               snprintf(adapter->ptp_caps.name, 16, "%pm", netdev->dev_addr);
+               snprintf(adapter->ptp_caps.name, 16, "%s", netdev->name);
                adapter->ptp_caps.owner = THIS_MODULE;
                adapter->ptp_caps.max_adj = 250000000;
                adapter->ptp_caps.n_alarm = 0;
@@ -942,11 +927,6 @@ void ixgbe_ptp_init(struct ixgbe_adapter *adapter)
 
        spin_lock_init(&adapter->tmreg_lock);
 
-       ixgbe_ptp_start_cyclecounter(adapter);
-
-       /* (Re)start the overflow check */
-       adapter->flags2 |= IXGBE_FLAG2_OVERFLOW_CHECK_ENABLED;
-
        adapter->ptp_clock = ptp_clock_register(&adapter->ptp_caps,
                                                &adapter->pdev->dev);
        if (IS_ERR(adapter->ptp_clock)) {
@@ -955,6 +935,11 @@ void ixgbe_ptp_init(struct ixgbe_adapter *adapter)
        } else
                e_dev_info("registered PHC device on %s\n", netdev->name);
 
+       ixgbe_ptp_reset(adapter);
+
+       /* set the flag that PTP has been enabled */
+       adapter->flags2 |= IXGBE_FLAG2_PTP_ENABLED;
+
        return;
 }
 
@@ -967,7 +952,7 @@ void ixgbe_ptp_init(struct ixgbe_adapter *adapter)
 void ixgbe_ptp_stop(struct ixgbe_adapter *adapter)
 {
        /* stop the overflow check task */
-       adapter->flags2 &= ~(IXGBE_FLAG2_OVERFLOW_CHECK_ENABLED |
+       adapter->flags2 &= ~(IXGBE_FLAG2_PTP_ENABLED |
                             IXGBE_FLAG2_PTP_PPS_ENABLED);
 
        ixgbe_ptp_setup_sdp(adapter);
index dce48bf64d9616beacb3ea9b081b6d7aea0730c2..96876b7442b12a0d85fc9c974043d5e2d1ad7a43 100644 (file)
@@ -150,16 +150,6 @@ void ixgbe_enable_sriov(struct ixgbe_adapter *adapter,
                adapter->flags2 &= ~(IXGBE_FLAG2_RSC_CAPABLE |
                                     IXGBE_FLAG2_RSC_ENABLED);
 
-#ifdef IXGBE_FCOE
-               /*
-                * When SR-IOV is enabled 82599 cannot support jumbo frames
-                * so we must disable FCoE because we cannot support FCoE MTU.
-                */
-               if (adapter->hw.mac.type == ixgbe_mac_82599EB)
-                       adapter->flags &= ~(IXGBE_FLAG_FCOE_ENABLED |
-                                           IXGBE_FLAG_FCOE_CAPABLE);
-#endif
-
                /* enable spoof checking for all VFs */
                for (i = 0; i < adapter->num_vfs; i++)
                        adapter->vfinfo[i].spoofchk_enabled = true;
@@ -265,8 +255,11 @@ void ixgbe_disable_sriov(struct ixgbe_adapter *adapter)
 }
 
 static int ixgbe_set_vf_multicasts(struct ixgbe_adapter *adapter,
-                                  int entries, u16 *hash_list, u32 vf)
+                                  u32 *msgbuf, u32 vf)
 {
+       int entries = (msgbuf[0] & IXGBE_VT_MSGINFO_MASK)
+                      >> IXGBE_VT_MSGINFO_SHIFT;
+       u16 *hash_list = (u16 *)&msgbuf[1];
        struct vf_data_storage *vfinfo = &adapter->vfinfo[vf];
        struct ixgbe_hw *hw = &adapter->hw;
        int i;
@@ -353,31 +346,89 @@ static int ixgbe_set_vf_vlan(struct ixgbe_adapter *adapter, int add, int vid,
        return adapter->hw.mac.ops.set_vfta(&adapter->hw, vid, vf, (bool)add);
 }
 
-static void ixgbe_set_vf_lpe(struct ixgbe_adapter *adapter, u32 *msgbuf)
+static s32 ixgbe_set_vf_lpe(struct ixgbe_adapter *adapter, u32 *msgbuf, u32 vf)
 {
        struct ixgbe_hw *hw = &adapter->hw;
-       int new_mtu = msgbuf[1];
+       int max_frame = msgbuf[1];
        u32 max_frs;
-       int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;
 
-       /* Only X540 supports jumbo frames in IOV mode */
-       if (adapter->hw.mac.type != ixgbe_mac_X540)
-               return;
+       /*
+        * For 82599EB we have to keep all PFs and VFs operating with
+        * the same max_frame value in order to avoid sending an oversize
+        * frame to a VF.  In order to guarantee this is handled correctly
+        * for all cases we have several special exceptions to take into
+        * account before we can enable the VF for receive
+        */
+       if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
+               struct net_device *dev = adapter->netdev;
+               int pf_max_frame = dev->mtu + ETH_HLEN;
+               u32 reg_offset, vf_shift, vfre;
+               s32 err = 0;
+
+#ifdef CONFIG_FCOE
+               if (dev->features & NETIF_F_FCOE_MTU)
+                       pf_max_frame = max_t(int, pf_max_frame,
+                                            IXGBE_FCOE_JUMBO_FRAME_SIZE);
+
+#endif /* CONFIG_FCOE */
+               switch (adapter->vfinfo[vf].vf_api) {
+               case ixgbe_mbox_api_11:
+                       /*
+                        * Version 1.1 supports jumbo frames on VFs if PF has
+                        * jumbo frames enabled which means legacy VFs are
+                        * disabled
+                        */
+                       if (pf_max_frame > ETH_FRAME_LEN)
+                               break;
+               default:
+                       /*
+                        * If the PF or VF are running w/ jumbo frames enabled
+                        * we need to shut down the VF Rx path as we cannot
+                        * support jumbo frames on legacy VFs
+                        */
+                       if ((pf_max_frame > ETH_FRAME_LEN) ||
+                           (max_frame > (ETH_FRAME_LEN + ETH_FCS_LEN)))
+                               err = -EINVAL;
+                       break;
+               }
+
+               /* determine VF receive enable location */
+               vf_shift = vf % 32;
+               reg_offset = vf / 32;
+
+               /* enable or disable receive depending on error */
+               vfre = IXGBE_READ_REG(hw, IXGBE_VFRE(reg_offset));
+               if (err)
+                       vfre &= ~(1 << vf_shift);
+               else
+                       vfre |= 1 << vf_shift;
+               IXGBE_WRITE_REG(hw, IXGBE_VFRE(reg_offset), vfre);
+
+               if (err) {
+                       e_err(drv, "VF max_frame %d out of range\n", max_frame);
+                       return err;
+               }
+       }
 
        /* MTU < 68 is an error and causes problems on some kernels */
-       if ((new_mtu < 68) || (max_frame > IXGBE_MAX_JUMBO_FRAME_SIZE)) {
-               e_err(drv, "VF mtu %d out of range\n", new_mtu);
-               return;
+       if (max_frame > IXGBE_MAX_JUMBO_FRAME_SIZE) {
+               e_err(drv, "VF max_frame %d out of range\n", max_frame);
+               return -EINVAL;
        }
 
-       max_frs = (IXGBE_READ_REG(hw, IXGBE_MAXFRS) &
-                  IXGBE_MHADD_MFS_MASK) >> IXGBE_MHADD_MFS_SHIFT;
-       if (max_frs < new_mtu) {
-               max_frs = new_mtu << IXGBE_MHADD_MFS_SHIFT;
+       /* pull current max frame size from hardware */
+       max_frs = IXGBE_READ_REG(hw, IXGBE_MAXFRS);
+       max_frs &= IXGBE_MHADD_MFS_MASK;
+       max_frs >>= IXGBE_MHADD_MFS_SHIFT;
+
+       if (max_frs < max_frame) {
+               max_frs = max_frame << IXGBE_MHADD_MFS_SHIFT;
                IXGBE_WRITE_REG(hw, IXGBE_MAXFRS, max_frs);
        }
 
-       e_info(hw, "VF requests change max MTU to %d\n", new_mtu);
+       e_info(hw, "VF requests change max MTU to %d\n", max_frame);
+
+       return 0;
 }
 
 static void ixgbe_set_vmolr(struct ixgbe_hw *hw, u32 vf, bool aupe)
@@ -392,35 +443,47 @@ static void ixgbe_set_vmolr(struct ixgbe_hw *hw, u32 vf, bool aupe)
        IXGBE_WRITE_REG(hw, IXGBE_VMOLR(vf), vmolr);
 }
 
-static void ixgbe_set_vmvir(struct ixgbe_adapter *adapter, u32 vid, u32 vf)
+static void ixgbe_set_vmvir(struct ixgbe_adapter *adapter,
+                           u16 vid, u16 qos, u32 vf)
 {
        struct ixgbe_hw *hw = &adapter->hw;
+       u32 vmvir = vid | (qos << VLAN_PRIO_SHIFT) | IXGBE_VMVIR_VLANA_DEFAULT;
 
-       if (vid)
-               IXGBE_WRITE_REG(hw, IXGBE_VMVIR(vf),
-                               (vid | IXGBE_VMVIR_VLANA_DEFAULT));
-       else
-               IXGBE_WRITE_REG(hw, IXGBE_VMVIR(vf), 0);
+       IXGBE_WRITE_REG(hw, IXGBE_VMVIR(vf), vmvir);
 }
 
+static void ixgbe_clear_vmvir(struct ixgbe_adapter *adapter, u32 vf)
+{
+       struct ixgbe_hw *hw = &adapter->hw;
+
+       IXGBE_WRITE_REG(hw, IXGBE_VMVIR(vf), 0);
+}
 static inline void ixgbe_vf_reset_event(struct ixgbe_adapter *adapter, u32 vf)
 {
        struct ixgbe_hw *hw = &adapter->hw;
+       struct vf_data_storage *vfinfo = &adapter->vfinfo[vf];
        int rar_entry = hw->mac.num_rar_entries - (vf + 1);
+       u8 num_tcs = netdev_get_num_tc(adapter->netdev);
+
+       /* add PF assigned VLAN or VLAN 0 */
+       ixgbe_set_vf_vlan(adapter, true, vfinfo->pf_vlan, vf);
 
        /* reset offloads to defaults */
-       if (adapter->vfinfo[vf].pf_vlan) {
-               ixgbe_set_vf_vlan(adapter, true,
-                                 adapter->vfinfo[vf].pf_vlan, vf);
-               ixgbe_set_vmvir(adapter,
-                               (adapter->vfinfo[vf].pf_vlan |
-                                (adapter->vfinfo[vf].pf_qos <<
-                                 VLAN_PRIO_SHIFT)), vf);
-               ixgbe_set_vmolr(hw, vf, false);
+       ixgbe_set_vmolr(hw, vf, !vfinfo->pf_vlan);
+
+       /* set outgoing tags for VFs */
+       if (!vfinfo->pf_vlan && !vfinfo->pf_qos && !num_tcs) {
+               ixgbe_clear_vmvir(adapter, vf);
        } else {
-               ixgbe_set_vf_vlan(adapter, true, 0, vf);
-               ixgbe_set_vmvir(adapter, 0, vf);
-               ixgbe_set_vmolr(hw, vf, true);
+               if (vfinfo->pf_qos || !num_tcs)
+                       ixgbe_set_vmvir(adapter, vfinfo->pf_vlan,
+                                       vfinfo->pf_qos, vf);
+               else
+                       ixgbe_set_vmvir(adapter, vfinfo->pf_vlan,
+                                       adapter->default_up, vf);
+
+               if (vfinfo->spoofchk_enabled)
+                       hw->mac.ops.set_vlan_anti_spoofing(hw, true, vf);
        }
 
        /* reset multicast table array for vf */
@@ -430,6 +493,9 @@ static inline void ixgbe_vf_reset_event(struct ixgbe_adapter *adapter, u32 vf)
        ixgbe_set_rx_mode(adapter->netdev);
 
        hw->mac.ops.clear_rar(hw, rar_entry);
+
+       /* reset VF api back to unknown */
+       adapter->vfinfo[vf].vf_api = ixgbe_mbox_api_10;
 }
 
 static int ixgbe_set_vf_mac(struct ixgbe_adapter *adapter,
@@ -521,30 +587,220 @@ int ixgbe_vf_configuration(struct pci_dev *pdev, unsigned int event_mask)
        return 0;
 }
 
-static inline void ixgbe_vf_reset_msg(struct ixgbe_adapter *adapter, u32 vf)
+static int ixgbe_vf_reset_msg(struct ixgbe_adapter *adapter, u32 vf)
 {
        struct ixgbe_hw *hw = &adapter->hw;
-       u32 reg;
+       unsigned char *vf_mac = adapter->vfinfo[vf].vf_mac_addresses;
+       u32 reg, msgbuf[4];
        u32 reg_offset, vf_shift;
+       u8 *addr = (u8 *)(&msgbuf[1]);
+
+       e_info(probe, "VF Reset msg received from vf %d\n", vf);
+
+       /* reset the filters for the device */
+       ixgbe_vf_reset_event(adapter, vf);
+
+       /* set vf mac address */
+       ixgbe_set_vf_mac(adapter, vf, vf_mac);
 
        vf_shift = vf % 32;
        reg_offset = vf / 32;
 
-       /* enable transmit and receive for vf */
+       /* enable transmit for vf */
        reg = IXGBE_READ_REG(hw, IXGBE_VFTE(reg_offset));
-       reg |= (reg | (1 << vf_shift));
+       reg |= 1 << vf_shift;
        IXGBE_WRITE_REG(hw, IXGBE_VFTE(reg_offset), reg);
 
+       /* enable receive for vf */
        reg = IXGBE_READ_REG(hw, IXGBE_VFRE(reg_offset));
-       reg |= (reg | (1 << vf_shift));
+       reg |= 1 << vf_shift;
+       /*
+        * The 82599 cannot support a mix of jumbo and non-jumbo PF/VFs.
+        * For more info take a look at ixgbe_set_vf_lpe
+        */
+       if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
+               struct net_device *dev = adapter->netdev;
+               int pf_max_frame = dev->mtu + ETH_HLEN;
+
+#ifdef CONFIG_FCOE
+               if (dev->features & NETIF_F_FCOE_MTU)
+                       pf_max_frame = max_t(int, pf_max_frame,
+                                            IXGBE_FCOE_JUMBO_FRAME_SIZE);
+
+#endif /* CONFIG_FCOE */
+               if (pf_max_frame > ETH_FRAME_LEN)
+                       reg &= ~(1 << vf_shift);
+       }
        IXGBE_WRITE_REG(hw, IXGBE_VFRE(reg_offset), reg);
 
+       /* enable VF mailbox for further messages */
+       adapter->vfinfo[vf].clear_to_send = true;
+
        /* Enable counting of spoofed packets in the SSVPC register */
        reg = IXGBE_READ_REG(hw, IXGBE_VMECM(reg_offset));
        reg |= (1 << vf_shift);
        IXGBE_WRITE_REG(hw, IXGBE_VMECM(reg_offset), reg);
 
-       ixgbe_vf_reset_event(adapter, vf);
+       /* reply to reset with ack and vf mac address */
+       msgbuf[0] = IXGBE_VF_RESET | IXGBE_VT_MSGTYPE_ACK;
+       memcpy(addr, vf_mac, ETH_ALEN);
+
+       /*
+        * Piggyback the multicast filter type so VF can compute the
+        * correct vectors
+        */
+       msgbuf[3] = hw->mac.mc_filter_type;
+       ixgbe_write_mbx(hw, msgbuf, IXGBE_VF_PERMADDR_MSG_LEN, vf);
+
+       return 0;
+}
+
+static int ixgbe_set_vf_mac_addr(struct ixgbe_adapter *adapter,
+                                u32 *msgbuf, u32 vf)
+{
+       u8 *new_mac = ((u8 *)(&msgbuf[1]));
+
+       if (!is_valid_ether_addr(new_mac)) {
+               e_warn(drv, "VF %d attempted to set invalid mac\n", vf);
+               return -1;
+       }
+
+       if (adapter->vfinfo[vf].pf_set_mac &&
+           memcmp(adapter->vfinfo[vf].vf_mac_addresses, new_mac,
+                  ETH_ALEN)) {
+               e_warn(drv,
+                      "VF %d attempted to override administratively set MAC address\n"
+                      "Reload the VF driver to resume operations\n",
+                      vf);
+               return -1;
+       }
+
+       return ixgbe_set_vf_mac(adapter, vf, new_mac);
+}
+
+static int ixgbe_set_vf_vlan_msg(struct ixgbe_adapter *adapter,
+                                u32 *msgbuf, u32 vf)
+{
+       struct ixgbe_hw *hw = &adapter->hw;
+       int add = (msgbuf[0] & IXGBE_VT_MSGINFO_MASK) >> IXGBE_VT_MSGINFO_SHIFT;
+       int vid = (msgbuf[1] & IXGBE_VLVF_VLANID_MASK);
+       int err;
+       u8 tcs = netdev_get_num_tc(adapter->netdev);
+
+       if (adapter->vfinfo[vf].pf_vlan || tcs) {
+               e_warn(drv,
+                      "VF %d attempted to override administratively set VLAN configuration\n"
+                      "Reload the VF driver to resume operations\n",
+                      vf);
+               return -1;
+       }
+
+       if (add)
+               adapter->vfinfo[vf].vlan_count++;
+       else if (adapter->vfinfo[vf].vlan_count)
+               adapter->vfinfo[vf].vlan_count--;
+
+       err = ixgbe_set_vf_vlan(adapter, add, vid, vf);
+       if (!err && adapter->vfinfo[vf].spoofchk_enabled)
+               hw->mac.ops.set_vlan_anti_spoofing(hw, true, vf);
+
+       return err;
+}
+
+static int ixgbe_set_vf_macvlan_msg(struct ixgbe_adapter *adapter,
+                                   u32 *msgbuf, u32 vf)
+{
+       u8 *new_mac = ((u8 *)(&msgbuf[1]));
+       int index = (msgbuf[0] & IXGBE_VT_MSGINFO_MASK) >>
+                   IXGBE_VT_MSGINFO_SHIFT;
+       int err;
+
+       if (adapter->vfinfo[vf].pf_set_mac && index > 0) {
+               e_warn(drv,
+                      "VF %d requested MACVLAN filter but is administratively denied\n",
+                      vf);
+               return -1;
+       }
+
+       /* An non-zero index indicates the VF is setting a filter */
+       if (index) {
+               if (!is_valid_ether_addr(new_mac)) {
+                       e_warn(drv, "VF %d attempted to set invalid mac\n", vf);
+                       return -1;
+               }
+
+               /*
+                * If the VF is allowed to set MAC filters then turn off
+                * anti-spoofing to avoid false positives.
+                */
+               if (adapter->vfinfo[vf].spoofchk_enabled)
+                       ixgbe_ndo_set_vf_spoofchk(adapter->netdev, vf, false);
+       }
+
+       err = ixgbe_set_vf_macvlan(adapter, vf, index, new_mac);
+       if (err == -ENOSPC)
+               e_warn(drv,
+                      "VF %d has requested a MACVLAN filter but there is no space for it\n",
+                      vf);
+       return err;
+}
+
+static int ixgbe_negotiate_vf_api(struct ixgbe_adapter *adapter,
+                                 u32 *msgbuf, u32 vf)
+{
+       int api = msgbuf[1];
+
+       switch (api) {
+       case ixgbe_mbox_api_10:
+       case ixgbe_mbox_api_11:
+               adapter->vfinfo[vf].vf_api = api;
+               return 0;
+       default:
+               break;
+       }
+
+       e_info(drv, "VF %d requested invalid api version %u\n", vf, api);
+
+       return -1;
+}
+
+static int ixgbe_get_vf_queues(struct ixgbe_adapter *adapter,
+                              u32 *msgbuf, u32 vf)
+{
+       struct net_device *dev = adapter->netdev;
+       struct ixgbe_ring_feature *vmdq = &adapter->ring_feature[RING_F_VMDQ];
+       unsigned int default_tc = 0;
+       u8 num_tcs = netdev_get_num_tc(dev);
+
+       /* verify the PF is supporting the correct APIs */
+       switch (adapter->vfinfo[vf].vf_api) {
+       case ixgbe_mbox_api_20:
+       case ixgbe_mbox_api_11:
+               break;
+       default:
+               return -1;
+       }
+
+       /* only allow 1 Tx queue for bandwidth limiting */
+       msgbuf[IXGBE_VF_TX_QUEUES] = __ALIGN_MASK(1, ~vmdq->mask);
+       msgbuf[IXGBE_VF_RX_QUEUES] = __ALIGN_MASK(1, ~vmdq->mask);
+
+       /* if TCs > 1 determine which TC belongs to default user priority */
+       if (num_tcs > 1)
+               default_tc = netdev_get_prio_tc_map(dev, adapter->default_up);
+
+       /* notify VF of need for VLAN tag stripping, and correct queue */
+       if (num_tcs)
+               msgbuf[IXGBE_VF_TRANS_VLAN] = num_tcs;
+       else if (adapter->vfinfo[vf].pf_vlan || adapter->vfinfo[vf].pf_qos)
+               msgbuf[IXGBE_VF_TRANS_VLAN] = 1;
+       else
+               msgbuf[IXGBE_VF_TRANS_VLAN] = 0;
+
+       /* notify VF of default queue */
+       msgbuf[IXGBE_VF_DEF_QUEUE] = default_tc;
+
+       return 0;
 }
 
 static int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter *adapter, u32 vf)
@@ -553,10 +809,6 @@ static int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter *adapter, u32 vf)
        u32 msgbuf[IXGBE_VFMAILBOX_SIZE];
        struct ixgbe_hw *hw = &adapter->hw;
        s32 retval;
-       int entries;
-       u16 *hash_list;
-       int add, vid, index;
-       u8 *new_mac;
 
        retval = ixgbe_read_mbx(hw, msgbuf, mbx_size, vf);
 
@@ -572,39 +824,13 @@ static int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter *adapter, u32 vf)
        /* flush the ack before we write any messages back */
        IXGBE_WRITE_FLUSH(hw);
 
+       if (msgbuf[0] == IXGBE_VF_RESET)
+               return ixgbe_vf_reset_msg(adapter, vf);
+
        /*
         * until the vf completes a virtual function reset it should not be
         * allowed to start any configuration.
         */
-
-       if (msgbuf[0] == IXGBE_VF_RESET) {
-               unsigned char *vf_mac = adapter->vfinfo[vf].vf_mac_addresses;
-               new_mac = (u8 *)(&msgbuf[1]);
-               e_info(probe, "VF Reset msg received from vf %d\n", vf);
-               adapter->vfinfo[vf].clear_to_send = false;
-               ixgbe_vf_reset_msg(adapter, vf);
-               adapter->vfinfo[vf].clear_to_send = true;
-
-               if (is_valid_ether_addr(new_mac) &&
-                   !adapter->vfinfo[vf].pf_set_mac)
-                       ixgbe_set_vf_mac(adapter, vf, vf_mac);
-               else
-                       ixgbe_set_vf_mac(adapter,
-                                vf, adapter->vfinfo[vf].vf_mac_addresses);
-
-               /* reply to reset with ack and vf mac address */
-               msgbuf[0] = IXGBE_VF_RESET | IXGBE_VT_MSGTYPE_ACK;
-               memcpy(new_mac, vf_mac, ETH_ALEN);
-               /*
-                * Piggyback the multicast filter type so VF can compute the
-                * correct vectors
-                */
-               msgbuf[3] = hw->mac.mc_filter_type;
-               ixgbe_write_mbx(hw, msgbuf, IXGBE_VF_PERMADDR_MSG_LEN, vf);
-
-               return retval;
-       }
-
        if (!adapter->vfinfo[vf].clear_to_send) {
                msgbuf[0] |= IXGBE_VT_MSGTYPE_NACK;
                ixgbe_write_mbx(hw, msgbuf, 1, vf);
@@ -613,70 +839,25 @@ static int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter *adapter, u32 vf)
 
        switch ((msgbuf[0] & 0xFFFF)) {
        case IXGBE_VF_SET_MAC_ADDR:
-               new_mac = ((u8 *)(&msgbuf[1]));
-               if (is_valid_ether_addr(new_mac) &&
-                   !adapter->vfinfo[vf].pf_set_mac) {
-                       ixgbe_set_vf_mac(adapter, vf, new_mac);
-               } else if (memcmp(adapter->vfinfo[vf].vf_mac_addresses,
-                                 new_mac, ETH_ALEN)) {
-                       e_warn(drv, "VF %d attempted to override "
-                              "administratively set MAC address\nReload "
-                              "the VF driver to resume operations\n", vf);
-                       retval = -1;
-               }
+               retval = ixgbe_set_vf_mac_addr(adapter, msgbuf, vf);
                break;
        case IXGBE_VF_SET_MULTICAST:
-               entries = (msgbuf[0] & IXGBE_VT_MSGINFO_MASK)
-                         >> IXGBE_VT_MSGINFO_SHIFT;
-               hash_list = (u16 *)&msgbuf[1];
-               retval = ixgbe_set_vf_multicasts(adapter, entries,
-                                                hash_list, vf);
-               break;
-       case IXGBE_VF_SET_LPE:
-               ixgbe_set_vf_lpe(adapter, msgbuf);
+               retval = ixgbe_set_vf_multicasts(adapter, msgbuf, vf);
                break;
        case IXGBE_VF_SET_VLAN:
-               add = (msgbuf[0] & IXGBE_VT_MSGINFO_MASK)
-                     >> IXGBE_VT_MSGINFO_SHIFT;
-               vid = (msgbuf[1] & IXGBE_VLVF_VLANID_MASK);
-               if (adapter->vfinfo[vf].pf_vlan) {
-                       e_warn(drv, "VF %d attempted to override "
-                              "administratively set VLAN configuration\n"
-                              "Reload the VF driver to resume operations\n",
-                              vf);
-                       retval = -1;
-               } else {
-                       if (add)
-                               adapter->vfinfo[vf].vlan_count++;
-                       else if (adapter->vfinfo[vf].vlan_count)
-                               adapter->vfinfo[vf].vlan_count--;
-                       retval = ixgbe_set_vf_vlan(adapter, add, vid, vf);
-                       if (!retval && adapter->vfinfo[vf].spoofchk_enabled)
-                               hw->mac.ops.set_vlan_anti_spoofing(hw, true, vf);
-               }
+               retval = ixgbe_set_vf_vlan_msg(adapter, msgbuf, vf);
+               break;
+       case IXGBE_VF_SET_LPE:
+               retval = ixgbe_set_vf_lpe(adapter, msgbuf, vf);
                break;
        case IXGBE_VF_SET_MACVLAN:
-               index = (msgbuf[0] & IXGBE_VT_MSGINFO_MASK) >>
-                       IXGBE_VT_MSGINFO_SHIFT;
-               if (adapter->vfinfo[vf].pf_set_mac && index > 0) {
-                       e_warn(drv, "VF %d requested MACVLAN filter but is "
-                                   "administratively denied\n", vf);
-                       retval = -1;
-                       break;
-               }
-               /*
-                * If the VF is allowed to set MAC filters then turn off
-                * anti-spoofing to avoid false positives.  An index
-                * greater than 0 will indicate the VF is setting a
-                * macvlan MAC filter.
-                */
-               if (index > 0 && adapter->vfinfo[vf].spoofchk_enabled)
-                       ixgbe_ndo_set_vf_spoofchk(adapter->netdev, vf, false);
-               retval = ixgbe_set_vf_macvlan(adapter, vf, index,
-                                             (unsigned char *)(&msgbuf[1]));
-               if (retval == -ENOSPC)
-                       e_warn(drv, "VF %d has requested a MACVLAN filter "
-                                   "but there is no space for it\n", vf);
+               retval = ixgbe_set_vf_macvlan_msg(adapter, msgbuf, vf);
+               break;
+       case IXGBE_VF_API_NEGOTIATE:
+               retval = ixgbe_negotiate_vf_api(adapter, msgbuf, vf);
+               break;
+       case IXGBE_VF_GET_QUEUES:
+               retval = ixgbe_get_vf_queues(adapter, msgbuf, vf);
                break;
        default:
                e_err(drv, "Unhandled Msg %8.8x\n", msgbuf[0]);
@@ -692,7 +873,7 @@ static int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter *adapter, u32 vf)
 
        msgbuf[0] |= IXGBE_VT_MSGTYPE_CTS;
 
-       ixgbe_write_mbx(hw, msgbuf, 1, vf);
+       ixgbe_write_mbx(hw, msgbuf, mbx_size, vf);
 
        return retval;
 }
@@ -783,7 +964,7 @@ int ixgbe_ndo_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos)
                err = ixgbe_set_vf_vlan(adapter, true, vlan, vf);
                if (err)
                        goto out;
-               ixgbe_set_vmvir(adapter, vlan | (qos << VLAN_PRIO_SHIFT), vf);
+               ixgbe_set_vmvir(adapter, vlan, qos, vf);
                ixgbe_set_vmolr(hw, vf, false);
                if (adapter->vfinfo[vf].spoofchk_enabled)
                        hw->mac.ops.set_vlan_anti_spoofing(hw, true, vf);
@@ -803,7 +984,7 @@ int ixgbe_ndo_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos)
        } else {
                err = ixgbe_set_vf_vlan(adapter, false,
                                        adapter->vfinfo[vf].pf_vlan, vf);
-               ixgbe_set_vmvir(adapter, vlan, vf);
+               ixgbe_clear_vmvir(adapter, vf);
                ixgbe_set_vmolr(hw, vf, true);
                hw->mac.ops.set_vlan_anti_spoofing(hw, false, vf);
                if (adapter->vfinfo[vf].vlan_count)
index 0722f33680926e9c8e79a0592708cfc0c42806e2..21915e20399a8ddaafe60347a1508a75df1de968 100644 (file)
@@ -56,6 +56,7 @@
 #define IXGBE_SUBDEV_ID_82599_SFP        0x11A9
 #define IXGBE_SUBDEV_ID_82599_RNDC       0x1F72
 #define IXGBE_SUBDEV_ID_82599_560FLR     0x17D0
+#define IXGBE_SUBDEV_ID_82599_ECNA_DP    0x0470
 #define IXGBE_DEV_ID_82599_SFP_EM        0x1507
 #define IXGBE_DEV_ID_82599_SFP_SF2       0x154D
 #define IXGBE_DEV_ID_82599EN_SFP         0x1557
index da17ccf5c09db9b8647a724c55d9c98eae4fa94f..3147795bd135b57137105a3b4769d0f34a7c6faf 100644 (file)
 #define IXGBE_DEV_ID_X540_VF            0x1515
 
 #define IXGBE_VF_IRQ_CLEAR_MASK         7
-#define IXGBE_VF_MAX_TX_QUEUES          1
-#define IXGBE_VF_MAX_RX_QUEUES          1
+#define IXGBE_VF_MAX_TX_QUEUES          8
+#define IXGBE_VF_MAX_RX_QUEUES          8
+
+/* DCB define */
+#define IXGBE_VF_MAX_TRAFFIC_CLASS     8
 
 /* Link speed */
 typedef u32 ixgbe_link_speed;
index 4a9c9c285685294df5b5531c689f0e11171056be..2323ccd211c08a02eeb6f9ef6d8c6cdfcb1c27d9 100644 (file)
@@ -89,8 +89,8 @@ struct ixgbevf_ring {
 /* How many Rx Buffers do we bundle into one write to the hardware ? */
 #define IXGBEVF_RX_BUFFER_WRITE        16      /* Must be power of 2 */
 
-#define MAX_RX_QUEUES 1
-#define MAX_TX_QUEUES 1
+#define MAX_RX_QUEUES IXGBE_VF_MAX_RX_QUEUES
+#define MAX_TX_QUEUES IXGBE_VF_MAX_TX_QUEUES
 
 #define IXGBEVF_DEFAULT_TXD   1024
 #define IXGBEVF_DEFAULT_RXD   512
index de1ad506665d6a33c223c8a73fbada54f39df832..07d7eaba6f1b3aa088d7be45f994220a8af27331 100644 (file)
@@ -58,7 +58,7 @@ const char ixgbevf_driver_name[] = "ixgbevf";
 static const char ixgbevf_driver_string[] =
        "Intel(R) 10 Gigabit PCI Express Virtual Function Network Driver";
 
-#define DRV_VERSION "2.6.0-k"
+#define DRV_VERSION "2.7.12-k"
 const char ixgbevf_driver_version[] = DRV_VERSION;
 static char ixgbevf_copyright[] =
        "Copyright (c) 2009 - 2012 Intel Corporation.";
@@ -99,6 +99,7 @@ MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
 
 /* forward decls */
 static void ixgbevf_set_itr(struct ixgbevf_q_vector *q_vector);
+static void ixgbevf_free_all_rx_resources(struct ixgbevf_adapter *adapter);
 
 static inline void ixgbevf_release_rx_desc(struct ixgbe_hw *hw,
                                           struct ixgbevf_ring *rx_ring,
@@ -358,6 +359,12 @@ static void ixgbevf_alloc_rx_buffers(struct ixgbevf_adapter *adapter,
                        bi->dma = dma_map_single(&pdev->dev, skb->data,
                                                 rx_ring->rx_buf_len,
                                                 DMA_FROM_DEVICE);
+                       if (dma_mapping_error(&pdev->dev, bi->dma)) {
+                               dev_kfree_skb(skb);
+                               bi->skb = NULL;
+                               dev_err(&pdev->dev, "RX DMA map failed\n");
+                               break;
+                       }
                }
                rx_desc->read.pkt_addr = cpu_to_le64(bi->dma);
 
@@ -1131,12 +1138,12 @@ static int ixgbevf_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
        if (!hw->mac.ops.set_vfta)
                return -EOPNOTSUPP;
 
-       spin_lock(&adapter->mbx_lock);
+       spin_lock_bh(&adapter->mbx_lock);
 
        /* add VID to filter table */
        err = hw->mac.ops.set_vfta(hw, vid, 0, true);
 
-       spin_unlock(&adapter->mbx_lock);
+       spin_unlock_bh(&adapter->mbx_lock);
 
        /* translate error return types so error makes sense */
        if (err == IXGBE_ERR_MBX)
@@ -1156,13 +1163,13 @@ static int ixgbevf_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
        struct ixgbe_hw *hw = &adapter->hw;
        int err = -EOPNOTSUPP;
 
-       spin_lock(&adapter->mbx_lock);
+       spin_lock_bh(&adapter->mbx_lock);
 
        /* remove VID from filter table */
        if (hw->mac.ops.set_vfta)
                err = hw->mac.ops.set_vfta(hw, vid, 0, false);
 
-       spin_unlock(&adapter->mbx_lock);
+       spin_unlock_bh(&adapter->mbx_lock);
 
        clear_bit(vid, adapter->active_vlans);
 
@@ -1218,7 +1225,7 @@ static void ixgbevf_set_rx_mode(struct net_device *netdev)
        struct ixgbevf_adapter *adapter = netdev_priv(netdev);
        struct ixgbe_hw *hw = &adapter->hw;
 
-       spin_lock(&adapter->mbx_lock);
+       spin_lock_bh(&adapter->mbx_lock);
 
        /* reprogram multicast list */
        if (hw->mac.ops.update_mc_addr_list)
@@ -1226,7 +1233,7 @@ static void ixgbevf_set_rx_mode(struct net_device *netdev)
 
        ixgbevf_write_uc_addr_list(netdev);
 
-       spin_unlock(&adapter->mbx_lock);
+       spin_unlock_bh(&adapter->mbx_lock);
 }
 
 static void ixgbevf_napi_enable_all(struct ixgbevf_adapter *adapter)
@@ -1335,11 +1342,12 @@ static void ixgbevf_init_last_counter_stats(struct ixgbevf_adapter *adapter)
 static void ixgbevf_negotiate_api(struct ixgbevf_adapter *adapter)
 {
        struct ixgbe_hw *hw = &adapter->hw;
-       int api[] = { ixgbe_mbox_api_10,
+       int api[] = { ixgbe_mbox_api_11,
+                     ixgbe_mbox_api_10,
                      ixgbe_mbox_api_unknown };
        int err = 0, idx = 0;
 
-       spin_lock(&adapter->mbx_lock);
+       spin_lock_bh(&adapter->mbx_lock);
 
        while (api[idx] != ixgbe_mbox_api_unknown) {
                err = ixgbevf_negotiate_api_version(hw, api[idx]);
@@ -1348,7 +1356,7 @@ static void ixgbevf_negotiate_api(struct ixgbevf_adapter *adapter)
                idx++;
        }
 
-       spin_unlock(&adapter->mbx_lock);
+       spin_unlock_bh(&adapter->mbx_lock);
 }
 
 static void ixgbevf_up_complete(struct ixgbevf_adapter *adapter)
@@ -1389,7 +1397,7 @@ static void ixgbevf_up_complete(struct ixgbevf_adapter *adapter)
 
        ixgbevf_configure_msix(adapter);
 
-       spin_lock(&adapter->mbx_lock);
+       spin_lock_bh(&adapter->mbx_lock);
 
        if (hw->mac.ops.set_rar) {
                if (is_valid_ether_addr(hw->mac.addr))
@@ -1398,7 +1406,7 @@ static void ixgbevf_up_complete(struct ixgbevf_adapter *adapter)
                        hw->mac.ops.set_rar(hw, 0, hw->mac.perm_addr, 0);
        }
 
-       spin_unlock(&adapter->mbx_lock);
+       spin_unlock_bh(&adapter->mbx_lock);
 
        clear_bit(__IXGBEVF_DOWN, &adapter->state);
        ixgbevf_napi_enable_all(adapter);
@@ -1413,12 +1421,87 @@ static void ixgbevf_up_complete(struct ixgbevf_adapter *adapter)
        mod_timer(&adapter->watchdog_timer, jiffies);
 }
 
+static int ixgbevf_reset_queues(struct ixgbevf_adapter *adapter)
+{
+       struct ixgbe_hw *hw = &adapter->hw;
+       struct ixgbevf_ring *rx_ring;
+       unsigned int def_q = 0;
+       unsigned int num_tcs = 0;
+       unsigned int num_rx_queues = 1;
+       int err, i;
+
+       spin_lock_bh(&adapter->mbx_lock);
+
+       /* fetch queue configuration from the PF */
+       err = ixgbevf_get_queues(hw, &num_tcs, &def_q);
+
+       spin_unlock_bh(&adapter->mbx_lock);
+
+       if (err)
+               return err;
+
+       if (num_tcs > 1) {
+               /* update default Tx ring register index */
+               adapter->tx_ring[0].reg_idx = def_q;
+
+               /* we need as many queues as traffic classes */
+               num_rx_queues = num_tcs;
+       }
+
+       /* nothing to do if we have the correct number of queues */
+       if (adapter->num_rx_queues == num_rx_queues)
+               return 0;
+
+       /* allocate new rings */
+       rx_ring = kcalloc(num_rx_queues,
+                         sizeof(struct ixgbevf_ring), GFP_KERNEL);
+       if (!rx_ring)
+               return -ENOMEM;
+
+       /* setup ring fields */
+       for (i = 0; i < num_rx_queues; i++) {
+               rx_ring[i].count = adapter->rx_ring_count;
+               rx_ring[i].queue_index = i;
+               rx_ring[i].reg_idx = i;
+               rx_ring[i].dev = &adapter->pdev->dev;
+               rx_ring[i].netdev = adapter->netdev;
+
+               /* allocate resources on the ring */
+               err = ixgbevf_setup_rx_resources(adapter, &rx_ring[i]);
+               if (err) {
+                       while (i) {
+                               i--;
+                               ixgbevf_free_rx_resources(adapter, &rx_ring[i]);
+                       }
+                       kfree(rx_ring);
+                       return err;
+               }
+       }
+
+       /* free the existing rings and queues */
+       ixgbevf_free_all_rx_resources(adapter);
+       adapter->num_rx_queues = 0;
+       kfree(adapter->rx_ring);
+
+       /* move new rings into position on the adapter struct */
+       adapter->rx_ring = rx_ring;
+       adapter->num_rx_queues = num_rx_queues;
+
+       /* reset ring to vector mapping */
+       ixgbevf_reset_q_vectors(adapter);
+       ixgbevf_map_rings_to_vectors(adapter);
+
+       return 0;
+}
+
 void ixgbevf_up(struct ixgbevf_adapter *adapter)
 {
        struct ixgbe_hw *hw = &adapter->hw;
 
        ixgbevf_negotiate_api(adapter);
 
+       ixgbevf_reset_queues(adapter);
+
        ixgbevf_configure(adapter);
 
        ixgbevf_up_complete(adapter);
@@ -1611,14 +1694,14 @@ void ixgbevf_reset(struct ixgbevf_adapter *adapter)
        struct ixgbe_hw *hw = &adapter->hw;
        struct net_device *netdev = adapter->netdev;
 
-       spin_lock(&adapter->mbx_lock);
+       spin_lock_bh(&adapter->mbx_lock);
 
        if (hw->mac.ops.reset_hw(hw))
                hw_dbg(hw, "PF still resetting\n");
        else
                hw->mac.ops.init_hw(hw);
 
-       spin_unlock(&adapter->mbx_lock);
+       spin_unlock_bh(&adapter->mbx_lock);
 
        if (is_valid_ether_addr(adapter->hw.mac.addr)) {
                memcpy(netdev->dev_addr, adapter->hw.mac.addr,
@@ -1717,6 +1800,7 @@ static int ixgbevf_alloc_queues(struct ixgbevf_adapter *adapter)
        for (i = 0; i < adapter->num_tx_queues; i++) {
                adapter->tx_ring[i].count = adapter->tx_ring_count;
                adapter->tx_ring[i].queue_index = i;
+               /* reg_idx may be remapped later by DCB config */
                adapter->tx_ring[i].reg_idx = i;
                adapter->tx_ring[i].dev = &adapter->pdev->dev;
                adapter->tx_ring[i].netdev = adapter->netdev;
@@ -1834,18 +1918,13 @@ err_out:
  **/
 static void ixgbevf_free_q_vectors(struct ixgbevf_adapter *adapter)
 {
-       int q_idx, num_q_vectors;
-       int napi_vectors;
-
-       num_q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
-       napi_vectors = adapter->num_rx_queues;
+       int q_idx, num_q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
 
        for (q_idx = 0; q_idx < num_q_vectors; q_idx++) {
                struct ixgbevf_q_vector *q_vector = adapter->q_vector[q_idx];
 
                adapter->q_vector[q_idx] = NULL;
-               if (q_idx < napi_vectors)
-                       netif_napi_del(&q_vector->napi);
+               netif_napi_del(&q_vector->napi);
                kfree(q_vector);
        }
 }
@@ -1950,8 +2029,11 @@ static int __devinit ixgbevf_sw_init(struct ixgbevf_adapter *adapter)
        hw->subsystem_device_id = pdev->subsystem_device;
 
        hw->mbx.ops.init_params(hw);
-       hw->mac.max_tx_queues = MAX_TX_QUEUES;
-       hw->mac.max_rx_queues = MAX_RX_QUEUES;
+
+       /* assume legacy case in which PF would only give VF 2 queues */
+       hw->mac.max_tx_queues = 2;
+       hw->mac.max_rx_queues = 2;
+
        err = hw->mac.ops.reset_hw(hw);
        if (err) {
                dev_info(&pdev->dev,
@@ -2113,12 +2195,12 @@ static void ixgbevf_watchdog_task(struct work_struct *work)
        if (hw->mac.ops.check_link) {
                s32 need_reset;
 
-               spin_lock(&adapter->mbx_lock);
+               spin_lock_bh(&adapter->mbx_lock);
 
                need_reset = hw->mac.ops.check_link(hw, &link_speed,
                                                    &link_up, false);
 
-               spin_unlock(&adapter->mbx_lock);
+               spin_unlock_bh(&adapter->mbx_lock);
 
                if (need_reset) {
                        adapter->link_up = link_up;
@@ -2377,6 +2459,63 @@ static void ixgbevf_free_all_rx_resources(struct ixgbevf_adapter *adapter)
                                                  &adapter->rx_ring[i]);
 }
 
+static int ixgbevf_setup_queues(struct ixgbevf_adapter *adapter)
+{
+       struct ixgbe_hw *hw = &adapter->hw;
+       struct ixgbevf_ring *rx_ring;
+       unsigned int def_q = 0;
+       unsigned int num_tcs = 0;
+       unsigned int num_rx_queues = 1;
+       int err, i;
+
+       spin_lock_bh(&adapter->mbx_lock);
+
+       /* fetch queue configuration from the PF */
+       err = ixgbevf_get_queues(hw, &num_tcs, &def_q);
+
+       spin_unlock_bh(&adapter->mbx_lock);
+
+       if (err)
+               return err;
+
+       if (num_tcs > 1) {
+               /* update default Tx ring register index */
+               adapter->tx_ring[0].reg_idx = def_q;
+
+               /* we need as many queues as traffic classes */
+               num_rx_queues = num_tcs;
+       }
+
+       /* nothing to do if we have the correct number of queues */
+       if (adapter->num_rx_queues == num_rx_queues)
+               return 0;
+
+       /* allocate new rings */
+       rx_ring = kcalloc(num_rx_queues,
+                         sizeof(struct ixgbevf_ring), GFP_KERNEL);
+       if (!rx_ring)
+               return -ENOMEM;
+
+       /* setup ring fields */
+       for (i = 0; i < num_rx_queues; i++) {
+               rx_ring[i].count = adapter->rx_ring_count;
+               rx_ring[i].queue_index = i;
+               rx_ring[i].reg_idx = i;
+               rx_ring[i].dev = &adapter->pdev->dev;
+               rx_ring[i].netdev = adapter->netdev;
+       }
+
+       /* free the existing ring and queues */
+       adapter->num_rx_queues = 0;
+       kfree(adapter->rx_ring);
+
+       /* move new rings into position on the adapter struct */
+       adapter->rx_ring = rx_ring;
+       adapter->num_rx_queues = num_rx_queues;
+
+       return 0;
+}
+
 /**
  * ixgbevf_open - Called when a network interface is made active
  * @netdev: network interface device structure
@@ -2413,6 +2552,11 @@ static int ixgbevf_open(struct net_device *netdev)
 
        ixgbevf_negotiate_api(adapter);
 
+       /* setup queue reg_idx and Rx queue count */
+       err = ixgbevf_setup_queues(adapter);
+       if (err)
+               goto err_setup_queues;
+
        /* allocate transmit descriptors */
        err = ixgbevf_setup_all_tx_resources(adapter);
        if (err)
@@ -2451,6 +2595,7 @@ err_setup_rx:
        ixgbevf_free_all_rx_resources(adapter);
 err_setup_tx:
        ixgbevf_free_all_tx_resources(adapter);
+err_setup_queues:
        ixgbevf_reset(adapter);
 
 err_setup_reset:
@@ -2678,10 +2823,10 @@ static int ixgbevf_tx_map(struct ixgbevf_ring *tx_ring,
                        tx_buffer_info->dma =
                                skb_frag_dma_map(tx_ring->dev, frag,
                                                 offset, size, DMA_TO_DEVICE);
-                       tx_buffer_info->mapped_as_page = true;
                        if (dma_mapping_error(tx_ring->dev,
                                              tx_buffer_info->dma))
                                goto dma_error;
+                       tx_buffer_info->mapped_as_page = true;
                        tx_buffer_info->next_to_watch = i;
 
                        len -= size;
@@ -2902,12 +3047,12 @@ static int ixgbevf_set_mac(struct net_device *netdev, void *p)
        memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
        memcpy(hw->mac.addr, addr->sa_data, netdev->addr_len);
 
-       spin_lock(&adapter->mbx_lock);
+       spin_lock_bh(&adapter->mbx_lock);
 
        if (hw->mac.ops.set_rar)
                hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0);
 
-       spin_unlock(&adapter->mbx_lock);
+       spin_unlock_bh(&adapter->mbx_lock);
 
        return 0;
 }
@@ -2925,8 +3070,15 @@ static int ixgbevf_change_mtu(struct net_device *netdev, int new_mtu)
        int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;
        int max_possible_frame = MAXIMUM_ETHERNET_VLAN_SIZE;
 
-       if (adapter->hw.mac.type == ixgbe_mac_X540_vf)
+       switch (adapter->hw.api_version) {
+       case ixgbe_mbox_api_11:
                max_possible_frame = IXGBE_MAX_JUMBO_FRAME_SIZE;
+               break;
+       default:
+               if (adapter->hw.mac.type == ixgbe_mac_X540_vf)
+                       max_possible_frame = IXGBE_MAX_JUMBO_FRAME_SIZE;
+               break;
+       }
 
        /* MTU < 68 is an error and causes problems on some kernels */
        if ((new_mtu < 68) || (max_frame > max_possible_frame))
index 946ce86f337f702701f10133faa8c71b099d81c3..0bc30058ff82010c81bcc7c15906f2d962e0f4a8 100644 (file)
@@ -85,6 +85,7 @@
 enum ixgbe_pfvf_api_rev {
        ixgbe_mbox_api_10,      /* API version 1.0, linux/freebsd VF driver */
        ixgbe_mbox_api_20,      /* API version 2.0, solaris Phase1 VF driver */
+       ixgbe_mbox_api_11,      /* API version 1.1, linux/freebsd VF driver */
        /* This value should always be last */
        ixgbe_mbox_api_unknown, /* indicates that API version is not known */
 };
@@ -100,6 +101,15 @@ enum ixgbe_pfvf_api_rev {
 #define IXGBE_VF_SET_MACVLAN   0x06 /* VF requests PF for unicast filter */
 #define IXGBE_VF_API_NEGOTIATE 0x08 /* negotiate API version */
 
+/* mailbox API, version 1.1 VF requests */
+#define IXGBE_VF_GET_QUEUE     0x09 /* get queue configuration */
+
+/* GET_QUEUES return data indices within the mailbox */
+#define IXGBE_VF_TX_QUEUES     1       /* number of Tx queues supported */
+#define IXGBE_VF_RX_QUEUES     2       /* number of Rx queues supported */
+#define IXGBE_VF_TRANS_VLAN    3       /* Indication of port vlan */
+#define IXGBE_VF_DEF_QUEUE     4       /* Default queue offset */
+
 /* length of permanent address message returned from PF */
 #define IXGBE_VF_PERMADDR_MSG_LEN 4
 /* word in permanent address message with the current multicast type */
index 0c7447e6fcc84a3a42044b11d0f85fbe3f2d0904..5fa397b953ebdf944c8972b8c551a9e08be02f22 100644 (file)
@@ -513,6 +513,64 @@ int ixgbevf_negotiate_api_version(struct ixgbe_hw *hw, int api)
        return err;
 }
 
+int ixgbevf_get_queues(struct ixgbe_hw *hw, unsigned int *num_tcs,
+                      unsigned int *default_tc)
+{
+       int err;
+       u32 msg[5];
+
+       /* do nothing if API doesn't support ixgbevf_get_queues */
+       switch (hw->api_version) {
+       case ixgbe_mbox_api_11:
+               break;
+       default:
+               return 0;
+       }
+
+       /* Fetch queue configuration from the PF */
+       msg[0] = IXGBE_VF_GET_QUEUE;
+       msg[1] = msg[2] = msg[3] = msg[4] = 0;
+       err = hw->mbx.ops.write_posted(hw, msg, 5);
+
+       if (!err)
+               err = hw->mbx.ops.read_posted(hw, msg, 5);
+
+       if (!err) {
+               msg[0] &= ~IXGBE_VT_MSGTYPE_CTS;
+
+               /*
+                * if we we didn't get an ACK there must have been
+                * some sort of mailbox error so we should treat it
+                * as such
+                */
+               if (msg[0] != (IXGBE_VF_GET_QUEUE | IXGBE_VT_MSGTYPE_ACK))
+                       return IXGBE_ERR_MBX;
+
+               /* record and validate values from message */
+               hw->mac.max_tx_queues = msg[IXGBE_VF_TX_QUEUES];
+               if (hw->mac.max_tx_queues == 0 ||
+                   hw->mac.max_tx_queues > IXGBE_VF_MAX_TX_QUEUES)
+                       hw->mac.max_tx_queues = IXGBE_VF_MAX_TX_QUEUES;
+
+               hw->mac.max_rx_queues = msg[IXGBE_VF_RX_QUEUES];
+               if (hw->mac.max_rx_queues == 0 ||
+                   hw->mac.max_rx_queues > IXGBE_VF_MAX_RX_QUEUES)
+                       hw->mac.max_rx_queues = IXGBE_VF_MAX_RX_QUEUES;
+
+               *num_tcs = msg[IXGBE_VF_TRANS_VLAN];
+               /* in case of unknown state assume we cannot tag frames */
+               if (*num_tcs > hw->mac.max_rx_queues)
+                       *num_tcs = 1;
+
+               *default_tc = msg[IXGBE_VF_DEF_QUEUE];
+               /* default to queue 0 on out-of-bounds queue number */
+               if (*default_tc >= hw->mac.max_tx_queues)
+                       *default_tc = 0;
+       }
+
+       return err;
+}
+
 static const struct ixgbe_mac_operations ixgbevf_mac_ops = {
        .init_hw             = ixgbevf_init_hw_vf,
        .reset_hw            = ixgbevf_reset_hw_vf,
index 47f11a584d8c04f9f4deaeecc643729362ea6917..7b1f502d171606366c06c767a65eb7ead6add2aa 100644 (file)
@@ -174,5 +174,7 @@ struct ixgbevf_info {
 
 void ixgbevf_rlpml_set_vf(struct ixgbe_hw *hw, u16 max_size);
 int ixgbevf_negotiate_api_version(struct ixgbe_hw *hw, int api);
+int ixgbevf_get_queues(struct ixgbe_hw *hw, unsigned int *num_tcs,
+                      unsigned int *default_tc);
 #endif /* __IXGBE_VF_H__ */
 
index 51c764901ad257bce17199496d895f788a647f8b..194221b75b90889444b4fd3315f04a645f9b0c9c 100644 (file)
@@ -329,9 +329,6 @@ int set_and_calc_slave_port_state(struct mlx4_dev *dev, int slave,
        ctx = &priv->mfunc.master.slave_state[slave];
        spin_lock_irqsave(&ctx->lock, flags);
 
-       mlx4_dbg(dev, "%s: slave: %d, current state: %d new event :%d\n",
-                __func__, slave, cur_state, event);
-
        switch (cur_state) {
        case SLAVE_PORT_DOWN:
                if (MLX4_PORT_STATE_DEV_EVENT_PORT_UP == event)
@@ -366,9 +363,6 @@ int set_and_calc_slave_port_state(struct mlx4_dev *dev, int slave,
                        goto out;
        }
        ret = mlx4_get_slave_port_state(dev, slave, port);
-       mlx4_dbg(dev, "%s: slave: %d, current state: %d new event"
-                " :%d gen_event: %d\n",
-                __func__, slave, cur_state, event, *gen_event);
 
 out:
        spin_unlock_irqrestore(&ctx->lock, flags);
index 80df2ab0177c398122725a85c82133788b711198..2aa80afd98d20038b2a174ac38a52a5eb003eaba 100644 (file)
@@ -1405,7 +1405,10 @@ unmap_bf:
        unmap_bf_area(dev);
 
 err_close:
-       mlx4_close_hca(dev);
+       if (mlx4_is_slave(dev))
+               mlx4_slave_exit(dev);
+       else
+               mlx4_CLOSE_HCA(dev, 0);
 
 err_free_icm:
        if (!mlx4_is_slave(dev))
index 926c911c0ac4b184d9d0f3fa70632b5ed84cb33b..b05705f50f0fae529e3f728471280ea4a1a1d753 100644 (file)
@@ -330,9 +330,6 @@ static void update_pkey_index(struct mlx4_dev *dev, int slave,
 
        new_index = priv->virt2phys_pkey[slave][port - 1][orig_index];
        *(u8 *)(inbox->buf + 35) = new_index;
-
-       mlx4_dbg(dev, "port = %d, orig pkey index = %d, "
-                "new pkey index = %d\n", port, orig_index, new_index);
 }
 
 static void update_gid(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *inbox,
@@ -351,9 +348,6 @@ static void update_gid(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *inbox,
                if (optpar & MLX4_QP_OPTPAR_ALT_ADDR_PATH)
                        qp_ctx->alt_path.mgid_index = slave & 0x7F;
        }
-
-       mlx4_dbg(dev, "slave %d, new gid index: 0x%x ",
-               slave, qp_ctx->pri_path.mgid_index);
 }
 
 static int mpt_mask(struct mlx4_dev *dev)
index b2a94d02a5217db7638164962d59b16f8def20ad..a8854d04c275c69790c562036fa489ad7b4ba105 100644 (file)
@@ -338,26 +338,6 @@ static void pch_gbe_wait_clr_bit(void *reg, u32 bit)
                pr_err("Error: busy bit is not cleared\n");
 }
 
-/**
- * pch_gbe_wait_clr_bit_irq - Wait to clear a bit for interrupt context
- * @reg:       Pointer of register
- * @busy:      Busy bit
- */
-static int pch_gbe_wait_clr_bit_irq(void *reg, u32 bit)
-{
-       u32 tmp;
-       int ret = -1;
-       /* wait busy */
-       tmp = 20;
-       while ((ioread32(reg) & bit) && --tmp)
-               udelay(5);
-       if (!tmp)
-               pr_err("Error: busy bit is not cleared\n");
-       else
-               ret = 0;
-       return ret;
-}
-
 /**
  * pch_gbe_mac_mar_set - Set MAC address register
  * @hw:            Pointer to the HW structure
@@ -409,15 +389,20 @@ static void pch_gbe_mac_reset_hw(struct pch_gbe_hw *hw)
        return;
 }
 
-static void pch_gbe_mac_reset_rx(struct pch_gbe_hw *hw)
+static void pch_gbe_disable_mac_rx(struct pch_gbe_hw *hw)
 {
-       /* Read the MAC addresses. and store to the private data */
-       pch_gbe_mac_read_mac_addr(hw);
-       iowrite32(PCH_GBE_RX_RST, &hw->reg->RESET);
-       pch_gbe_wait_clr_bit_irq(&hw->reg->RESET, PCH_GBE_RX_RST);
-       /* Setup the MAC addresses */
-       pch_gbe_mac_mar_set(hw, hw->mac.addr, 0);
-       return;
+       u32 rctl;
+       /* Disables Receive MAC */
+       rctl = ioread32(&hw->reg->MAC_RX_EN);
+       iowrite32((rctl & ~PCH_GBE_MRE_MAC_RX_EN), &hw->reg->MAC_RX_EN);
+}
+
+static void pch_gbe_enable_mac_rx(struct pch_gbe_hw *hw)
+{
+       u32 rctl;
+       /* Enables Receive MAC */
+       rctl = ioread32(&hw->reg->MAC_RX_EN);
+       iowrite32((rctl | PCH_GBE_MRE_MAC_RX_EN), &hw->reg->MAC_RX_EN);
 }
 
 /**
@@ -913,7 +898,7 @@ static void pch_gbe_setup_rctl(struct pch_gbe_adapter *adapter)
 static void pch_gbe_configure_rx(struct pch_gbe_adapter *adapter)
 {
        struct pch_gbe_hw *hw = &adapter->hw;
-       u32 rdba, rdlen, rctl, rxdma;
+       u32 rdba, rdlen, rxdma;
 
        pr_debug("dma adr = 0x%08llx  size = 0x%08x\n",
                 (unsigned long long)adapter->rx_ring->dma,
@@ -921,9 +906,7 @@ static void pch_gbe_configure_rx(struct pch_gbe_adapter *adapter)
 
        pch_gbe_mac_force_mac_fc(hw);
 
-       /* Disables Receive MAC */
-       rctl = ioread32(&hw->reg->MAC_RX_EN);
-       iowrite32((rctl & ~PCH_GBE_MRE_MAC_RX_EN), &hw->reg->MAC_RX_EN);
+       pch_gbe_disable_mac_rx(hw);
 
        /* Disables Receive DMA */
        rxdma = ioread32(&hw->reg->DMA_CTRL);
@@ -1316,38 +1299,17 @@ void pch_gbe_update_stats(struct pch_gbe_adapter *adapter)
        spin_unlock_irqrestore(&adapter->stats_lock, flags);
 }
 
-static void pch_gbe_stop_receive(struct pch_gbe_adapter *adapter)
+static void pch_gbe_disable_dma_rx(struct pch_gbe_hw *hw)
 {
-       struct pch_gbe_hw *hw = &adapter->hw;
        u32 rxdma;
-       u16 value;
-       int ret;
 
        /* Disable Receive DMA */
        rxdma = ioread32(&hw->reg->DMA_CTRL);
        rxdma &= ~PCH_GBE_RX_DMA_EN;
        iowrite32(rxdma, &hw->reg->DMA_CTRL);
-       /* Wait Rx DMA BUS is IDLE */
-       ret = pch_gbe_wait_clr_bit_irq(&hw->reg->RX_DMA_ST, PCH_GBE_IDLE_CHECK);
-       if (ret) {
-               /* Disable Bus master */
-               pci_read_config_word(adapter->pdev, PCI_COMMAND, &value);
-               value &= ~PCI_COMMAND_MASTER;
-               pci_write_config_word(adapter->pdev, PCI_COMMAND, value);
-               /* Stop Receive */
-               pch_gbe_mac_reset_rx(hw);
-               /* Enable Bus master */
-               value |= PCI_COMMAND_MASTER;
-               pci_write_config_word(adapter->pdev, PCI_COMMAND, value);
-       } else {
-               /* Stop Receive */
-               pch_gbe_mac_reset_rx(hw);
-       }
-       /* reprogram multicast address register after reset */
-       pch_gbe_set_multi(adapter->netdev);
 }
 
-static void pch_gbe_start_receive(struct pch_gbe_hw *hw)
+static void pch_gbe_enable_dma_rx(struct pch_gbe_hw *hw)
 {
        u32 rxdma;
 
@@ -1355,9 +1317,6 @@ static void pch_gbe_start_receive(struct pch_gbe_hw *hw)
        rxdma = ioread32(&hw->reg->DMA_CTRL);
        rxdma |= PCH_GBE_RX_DMA_EN;
        iowrite32(rxdma, &hw->reg->DMA_CTRL);
-       /* Enables Receive */
-       iowrite32(PCH_GBE_MRE_MAC_RX_EN, &hw->reg->MAC_RX_EN);
-       return;
 }
 
 /**
@@ -1393,7 +1352,7 @@ static irqreturn_t pch_gbe_intr(int irq, void *data)
                        int_en = ioread32(&hw->reg->INT_EN);
                        iowrite32((int_en & ~PCH_GBE_INT_RX_FIFO_ERR),
                                  &hw->reg->INT_EN);
-                       pch_gbe_stop_receive(adapter);
+                       pch_gbe_disable_dma_rx(&adapter->hw);
                        int_st |= ioread32(&hw->reg->INT_ST);
                        int_st = int_st & ioread32(&hw->reg->INT_EN);
                }
@@ -2000,7 +1959,8 @@ int pch_gbe_up(struct pch_gbe_adapter *adapter)
        pch_gbe_alloc_tx_buffers(adapter, tx_ring);
        pch_gbe_alloc_rx_buffers(adapter, rx_ring, rx_ring->count);
        adapter->tx_queue_len = netdev->tx_queue_len;
-       pch_gbe_start_receive(&adapter->hw);
+       pch_gbe_enable_dma_rx(&adapter->hw);
+       pch_gbe_enable_mac_rx(&adapter->hw);
 
        mod_timer(&adapter->watchdog_timer, jiffies);
 
@@ -2405,7 +2365,6 @@ static int pch_gbe_napi_poll(struct napi_struct *napi, int budget)
        int work_done = 0;
        bool poll_end_flag = false;
        bool cleaned = false;
-       u32 int_en;
 
        pr_debug("budget : %d\n", budget);
 
@@ -2422,19 +2381,13 @@ static int pch_gbe_napi_poll(struct napi_struct *napi, int budget)
 
        if (poll_end_flag) {
                napi_complete(napi);
-               if (adapter->rx_stop_flag) {
-                       adapter->rx_stop_flag = false;
-                       pch_gbe_start_receive(&adapter->hw);
-               }
                pch_gbe_irq_enable(adapter);
-       } else
-               if (adapter->rx_stop_flag) {
-                       adapter->rx_stop_flag = false;
-                       pch_gbe_start_receive(&adapter->hw);
-                       int_en = ioread32(&adapter->hw.reg->INT_EN);
-                       iowrite32((int_en | PCH_GBE_INT_RX_FIFO_ERR),
-                               &adapter->hw.reg->INT_EN);
-               }
+       }
+
+       if (adapter->rx_stop_flag) {
+               adapter->rx_stop_flag = false;
+               pch_gbe_enable_dma_rx(&adapter->hw);
+       }
 
        pr_debug("poll_end_flag : %d  work_done : %d  budget : %d\n",
                 poll_end_flag, work_done, budget);
index df09b1cb742fb211f639e0e6a16d658a768cf7d6..6407d0d77e810f038da14dfdf1447bae50794a8c 100644 (file)
@@ -2525,6 +2525,13 @@ static int ql_alloc_net_req_rsp_queues(struct ql3_adapter *qdev)
        qdev->req_q_size =
            (u32) (NUM_REQ_Q_ENTRIES * sizeof(struct ob_mac_iocb_req));
 
+       qdev->rsp_q_size = NUM_RSP_Q_ENTRIES * sizeof(struct net_rsp_iocb);
+
+       /* The barrier is required to ensure request and response queue
+        * addr writes to the registers.
+        */
+       wmb();
+
        qdev->req_q_virt_addr =
            pci_alloc_consistent(qdev->pdev,
                                 (size_t) qdev->req_q_size,
@@ -2536,8 +2543,6 @@ static int ql_alloc_net_req_rsp_queues(struct ql3_adapter *qdev)
                return -ENOMEM;
        }
 
-       qdev->rsp_q_size = NUM_RSP_Q_ENTRIES * sizeof(struct net_rsp_iocb);
-
        qdev->rsp_q_virt_addr =
            pci_alloc_consistent(qdev->pdev,
                                 (size_t) qdev->rsp_q_size,
index 961c8321451f5551e85847076dcdfb845c51342a..72b775fd49c8d887da18d4d380bc333a76247128 100644 (file)
@@ -452,7 +452,7 @@ static size_t gelic_wl_synthesize_ie(u8 *buf,
        if (rsn)
                *buf++ = WLAN_EID_RSN;
        else
-               *buf++ = WLAN_EID_GENERIC;
+               *buf++ = WLAN_EID_VENDOR_SPECIFIC;
 
        /* length filed; set later */
        buf++;
@@ -540,7 +540,7 @@ static void gelic_wl_parse_ie(u8 *data, size_t len,
                        break;
 
                switch (item_id) {
-               case WLAN_EID_GENERIC:
+               case WLAN_EID_VENDOR_SPECIFIC:
                        if ((OUI_LEN + 1 <= item_len) &&
                            !memcmp(pos, wpa_oui, OUI_LEN) &&
                            pos[OUI_LEN] == 0x01) {
index 928148cc32207a90da8cf173258c0ef8cc2b7e36..7fdeb528133d0b5374bd02e2ebf25a0a5ef6843d 100644 (file)
@@ -363,11 +363,6 @@ static void rndis_filter_receive_data(struct rndis_device *dev,
 
        rndis_pkt = &msg->msg.pkt;
 
-       /*
-        * FIXME: Handle multiple rndis pkt msgs that maybe enclosed in this
-        * netvsc packet (ie TotalDataBufferLength != MessageLength)
-        */
-
        /* Remove the rndis header and pass it back up the stack */
        data_offset = RNDIS_HEADER_SIZE + rndis_pkt->data_offset;
 
index 983bbf4d5ef6a7437118ac2d21ba2cb66599bc8c..961f0b2939132b0b2e50a94e7610cfb72ce8faf4 100644 (file)
@@ -15,6 +15,11 @@ if PHYLIB
 
 comment "MII PHY device drivers"
 
+config AT803X_PHY
+       tristate "Drivers for Atheros AT803X PHYs"
+       ---help---
+         Currently supports the AT8030 and AT8035 model
+
 config AMD_PHY
        tristate "Drivers for the AMD PHYs"
        ---help---
index 426674debae44dfb9967e305ad571f7012010afb..9645e389a58d34fbdb0c74a737d61b33a4885b6a 100644 (file)
@@ -25,6 +25,7 @@ obj-$(CONFIG_STE10XP)         += ste10Xp.o
 obj-$(CONFIG_MICREL_PHY)       += micrel.o
 obj-$(CONFIG_MDIO_OCTEON)      += mdio-octeon.o
 obj-$(CONFIG_MICREL_KS8995MA)  += spi_ks8995.o
+obj-$(CONFIG_AT803X_PHY)       += at803x.o
 obj-$(CONFIG_AMD_PHY)          += amd.o
 obj-$(CONFIG_MDIO_BUS_MUX)     += mdio-mux.o
 obj-$(CONFIG_MDIO_BUS_MUX_GPIO)        += mdio-mux-gpio.o
diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c
new file mode 100644 (file)
index 0000000..45cbc10
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ * drivers/net/phy/at803x.c
+ *
+ * Driver for Atheros 803x PHY
+ *
+ * Author: Matus Ujhelyi <ujhelyi.m@gmail.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/phy.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+
+#define AT803X_INTR_ENABLE                     0x12
+#define AT803X_INTR_STATUS                     0x13
+#define AT803X_WOL_ENABLE                      0x01
+#define AT803X_DEVICE_ADDR                     0x03
+#define AT803X_LOC_MAC_ADDR_0_15_OFFSET                0x804C
+#define AT803X_LOC_MAC_ADDR_16_31_OFFSET       0x804B
+#define AT803X_LOC_MAC_ADDR_32_47_OFFSET       0x804A
+#define AT803X_MMD_ACCESS_CONTROL              0x0D
+#define AT803X_MMD_ACCESS_CONTROL_DATA         0x0E
+#define AT803X_FUNC_DATA                       0x4003
+
+MODULE_DESCRIPTION("Atheros 803x PHY driver");
+MODULE_AUTHOR("Matus Ujhelyi");
+MODULE_LICENSE("GPL");
+
+static void at803x_set_wol_mac_addr(struct phy_device *phydev)
+{
+       struct net_device *ndev = phydev->attached_dev;
+       const u8 *mac;
+       unsigned int i, offsets[] = {
+               AT803X_LOC_MAC_ADDR_32_47_OFFSET,
+               AT803X_LOC_MAC_ADDR_16_31_OFFSET,
+               AT803X_LOC_MAC_ADDR_0_15_OFFSET,
+       };
+
+       if (!ndev)
+               return;
+
+       mac = (const u8 *) ndev->dev_addr;
+
+       if (!is_valid_ether_addr(mac))
+               return;
+
+       for (i = 0; i < 3; i++) {
+               phy_write(phydev, AT803X_MMD_ACCESS_CONTROL,
+                                 AT803X_DEVICE_ADDR);
+               phy_write(phydev, AT803X_MMD_ACCESS_CONTROL_DATA,
+                                 offsets[i]);
+               phy_write(phydev, AT803X_MMD_ACCESS_CONTROL,
+                                 AT803X_FUNC_DATA);
+               phy_write(phydev, AT803X_MMD_ACCESS_CONTROL_DATA,
+                                 mac[(i * 2) + 1] | (mac[(i * 2)] << 8));
+       }
+}
+
+static int at803x_config_init(struct phy_device *phydev)
+{
+       int val;
+       u32 features;
+       int status;
+
+       features = SUPPORTED_TP | SUPPORTED_MII | SUPPORTED_AUI |
+                  SUPPORTED_FIBRE | SUPPORTED_BNC;
+
+       val = phy_read(phydev, MII_BMSR);
+       if (val < 0)
+               return val;
+
+       if (val & BMSR_ANEGCAPABLE)
+               features |= SUPPORTED_Autoneg;
+       if (val & BMSR_100FULL)
+               features |= SUPPORTED_100baseT_Full;
+       if (val & BMSR_100HALF)
+               features |= SUPPORTED_100baseT_Half;
+       if (val & BMSR_10FULL)
+               features |= SUPPORTED_10baseT_Full;
+       if (val & BMSR_10HALF)
+               features |= SUPPORTED_10baseT_Half;
+
+       if (val & BMSR_ESTATEN) {
+               val = phy_read(phydev, MII_ESTATUS);
+               if (val < 0)
+                       return val;
+
+               if (val & ESTATUS_1000_TFULL)
+                       features |= SUPPORTED_1000baseT_Full;
+               if (val & ESTATUS_1000_THALF)
+                       features |= SUPPORTED_1000baseT_Half;
+       }
+
+       phydev->supported = features;
+       phydev->advertising = features;
+
+       /* enable WOL */
+       at803x_set_wol_mac_addr(phydev);
+       status = phy_write(phydev, AT803X_INTR_ENABLE, AT803X_WOL_ENABLE);
+       status = phy_read(phydev, AT803X_INTR_STATUS);
+
+       return 0;
+}
+
+/* ATHEROS 8035 */
+static struct phy_driver at8035_driver = {
+       .phy_id         = 0x004dd072,
+       .name           = "Atheros 8035 ethernet",
+       .phy_id_mask    = 0xffffffef,
+       .config_init    = at803x_config_init,
+       .features       = PHY_GBIT_FEATURES,
+       .flags          = PHY_HAS_INTERRUPT,
+       .config_aneg    = &genphy_config_aneg,
+       .read_status    = &genphy_read_status,
+       .driver         = {
+               .owner = THIS_MODULE,
+       },
+};
+
+/* ATHEROS 8030 */
+static struct phy_driver at8030_driver = {
+       .phy_id         = 0x004dd076,
+       .name           = "Atheros 8030 ethernet",
+       .phy_id_mask    = 0xffffffef,
+       .config_init    = at803x_config_init,
+       .features       = PHY_GBIT_FEATURES,
+       .flags          = PHY_HAS_INTERRUPT,
+       .config_aneg    = &genphy_config_aneg,
+       .read_status    = &genphy_read_status,
+       .driver         = {
+               .owner = THIS_MODULE,
+       },
+};
+
+static int __init atheros_init(void)
+{
+       int ret;
+
+       ret = phy_driver_register(&at8035_driver);
+       if (ret)
+               goto err1;
+
+       ret = phy_driver_register(&at8030_driver);
+       if (ret)
+               goto err2;
+
+       return 0;
+
+err2:
+       phy_driver_unregister(&at8035_driver);
+err1:
+       return ret;
+}
+
+static void __exit atheros_exit(void)
+{
+       phy_driver_unregister(&at8035_driver);
+       phy_driver_unregister(&at8030_driver);
+}
+
+module_init(atheros_init);
+module_exit(atheros_exit);
+
+static struct mdio_device_id __maybe_unused atheros_tbl[] = {
+       { 0x004dd076, 0xffffffef },
+       { 0x004dd072, 0xffffffef },
+       { }
+};
+
+MODULE_DEVICE_TABLE(mdio, atheros_tbl);
index c1ae76968f47ee5fa0191d07f53c4b6eddd09078..2ab8043e1e288a871bdd496a2c014290127f5ade 100644 (file)
@@ -219,6 +219,24 @@ config USB_NET_CDC_NCM
            * ST-Ericsson M343 HSPA Mobile Broadband Modem (reference design)
            * Ericsson F5521gw Mobile Broadband Module
 
+config USB_NET_CDC_MBIM
+       tristate "CDC MBIM support"
+       depends on USB_USBNET
+       select USB_WDM
+       select USB_NET_CDC_NCM
+       help
+         This driver provides support for CDC MBIM (Mobile Broadband
+         Interface Model) devices. The CDC MBIM specification is
+         available from <http://www.usb.org/>.
+
+         MBIM devices require configuration using the management
+         protocol defined by the MBIM specification.  This driver
+         provides unfiltered access to the MBIM control channel
+         through the associated /dev/cdc-wdmx character device.
+
+         To compile this driver as a module, choose M here: the
+         module will be called cdc_mbim.
+
 config USB_NET_DM9601
        tristate "Davicom DM9601 based USB 1.1 10/100 ethernet devices"
        depends on USB_USBNET
index bf063008c1afc240a8854c75c3de42d22e7d93b9..478691326f37fc3303199a07dd9e83ae087615be 100644 (file)
@@ -31,4 +31,5 @@ obj-$(CONFIG_USB_NET_CX82310_ETH)     += cx82310_eth.o
 obj-$(CONFIG_USB_NET_CDC_NCM)  += cdc_ncm.o
 obj-$(CONFIG_USB_VL600)                += lg-vl600.o
 obj-$(CONFIG_USB_NET_QMI_WWAN) += qmi_wwan.o
+obj-$(CONFIG_USB_NET_CDC_MBIM) += cdc_mbim.o
 
diff --git a/drivers/net/usb/cdc_mbim.c b/drivers/net/usb/cdc_mbim.c
new file mode 100644 (file)
index 0000000..42f51c7
--- /dev/null
@@ -0,0 +1,412 @@
+/*
+ * Copyright (c) 2012  Smith Micro Software, Inc.
+ * Copyright (c) 2012  Bjørn Mork <bjorn@mork.no>
+ *
+ * This driver is based on and reuse most of cdc_ncm, which is
+ * Copyright (C) ST-Ericsson 2010-2012
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/ethtool.h>
+#include <linux/if_vlan.h>
+#include <linux/ip.h>
+#include <linux/mii.h>
+#include <linux/usb.h>
+#include <linux/usb/cdc.h>
+#include <linux/usb/usbnet.h>
+#include <linux/usb/cdc-wdm.h>
+#include <linux/usb/cdc_ncm.h>
+
+/* driver specific data - must match cdc_ncm usage */
+struct cdc_mbim_state {
+       struct cdc_ncm_ctx *ctx;
+       atomic_t pmcount;
+       struct usb_driver *subdriver;
+       struct usb_interface *control;
+       struct usb_interface *data;
+};
+
+/* using a counter to merge subdriver requests with our own into a combined state */
+static int cdc_mbim_manage_power(struct usbnet *dev, int on)
+{
+       struct cdc_mbim_state *info = (void *)&dev->data;
+       int rv = 0;
+
+       dev_dbg(&dev->intf->dev, "%s() pmcount=%d, on=%d\n", __func__, atomic_read(&info->pmcount), on);
+
+       if ((on && atomic_add_return(1, &info->pmcount) == 1) || (!on && atomic_dec_and_test(&info->pmcount))) {
+               /* need autopm_get/put here to ensure the usbcore sees the new value */
+               rv = usb_autopm_get_interface(dev->intf);
+               if (rv < 0)
+                       goto err;
+               dev->intf->needs_remote_wakeup = on;
+               usb_autopm_put_interface(dev->intf);
+       }
+err:
+       return rv;
+}
+
+static int cdc_mbim_wdm_manage_power(struct usb_interface *intf, int status)
+{
+       struct usbnet *dev = usb_get_intfdata(intf);
+
+       /* can be called while disconnecting */
+       if (!dev)
+               return 0;
+
+       return cdc_mbim_manage_power(dev, status);
+}
+
+
+static int cdc_mbim_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+       struct cdc_ncm_ctx *ctx;
+       struct usb_driver *subdriver = ERR_PTR(-ENODEV);
+       int ret = -ENODEV;
+       u8 data_altsetting = CDC_NCM_DATA_ALTSETTING_NCM;
+       struct cdc_mbim_state *info = (void *)&dev->data;
+
+       /* see if interface supports MBIM alternate setting */
+       if (intf->num_altsetting == 2) {
+               if (!cdc_ncm_comm_intf_is_mbim(intf->cur_altsetting))
+                       usb_set_interface(dev->udev,
+                                         intf->cur_altsetting->desc.bInterfaceNumber,
+                                         CDC_NCM_COMM_ALTSETTING_MBIM);
+               data_altsetting = CDC_NCM_DATA_ALTSETTING_MBIM;
+       }
+
+       /* Probably NCM, defer for cdc_ncm_bind */
+       if (!cdc_ncm_comm_intf_is_mbim(intf->cur_altsetting))
+               goto err;
+
+       ret = cdc_ncm_bind_common(dev, intf, data_altsetting);
+       if (ret)
+               goto err;
+
+       ctx = info->ctx;
+
+       /* The MBIM descriptor and the status endpoint are required */
+       if (ctx->mbim_desc && dev->status)
+               subdriver = usb_cdc_wdm_register(ctx->control,
+                                                &dev->status->desc,
+                                                le16_to_cpu(ctx->mbim_desc->wMaxControlMessage),
+                                                cdc_mbim_wdm_manage_power);
+       if (IS_ERR(subdriver)) {
+               ret = PTR_ERR(subdriver);
+               cdc_ncm_unbind(dev, intf);
+               goto err;
+       }
+
+       /* can't let usbnet use the interrupt endpoint */
+       dev->status = NULL;
+       info->subdriver = subdriver;
+
+       /* MBIM cannot do ARP */
+       dev->net->flags |= IFF_NOARP;
+
+       /* no need to put the VLAN tci in the packet headers */
+       dev->net->features |= NETIF_F_HW_VLAN_TX;
+err:
+       return ret;
+}
+
+static void cdc_mbim_unbind(struct usbnet *dev, struct usb_interface *intf)
+{
+       struct cdc_mbim_state *info = (void *)&dev->data;
+       struct cdc_ncm_ctx *ctx = info->ctx;
+
+       /* disconnect subdriver from control interface */
+       if (info->subdriver && info->subdriver->disconnect)
+               info->subdriver->disconnect(ctx->control);
+       info->subdriver = NULL;
+
+       /* let NCM unbind clean up both control and data interface */
+       cdc_ncm_unbind(dev, intf);
+}
+
+
+static struct sk_buff *cdc_mbim_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
+{
+       struct sk_buff *skb_out;
+       struct cdc_mbim_state *info = (void *)&dev->data;
+       struct cdc_ncm_ctx *ctx = info->ctx;
+       __le32 sign = cpu_to_le32(USB_CDC_MBIM_NDP16_IPS_SIGN);
+       u16 tci = 0;
+       u8 *c;
+
+       if (!ctx)
+               goto error;
+
+       if (skb) {
+               if (skb->len <= sizeof(ETH_HLEN))
+                       goto error;
+
+               /* mapping VLANs to MBIM sessions:
+                *   no tag     => IPS session <0>
+                *   1 - 255    => IPS session <vlanid>
+                *   256 - 511  => DSS session <vlanid - 256>
+                *   512 - 4095 => unsupported, drop
+                */
+               vlan_get_tag(skb, &tci);
+
+               switch (tci & 0x0f00) {
+               case 0x0000: /* VLAN ID 0 - 255 */
+                       /* verify that datagram is IPv4 or IPv6 */
+                       skb_reset_mac_header(skb);
+                       switch (eth_hdr(skb)->h_proto) {
+                       case htons(ETH_P_IP):
+                       case htons(ETH_P_IPV6):
+                               break;
+                       default:
+                               goto error;
+                       }
+                       c = (u8 *)&sign;
+                       c[3] = tci;
+                       break;
+               case 0x0100: /* VLAN ID 256 - 511 */
+                       sign = cpu_to_le32(USB_CDC_MBIM_NDP16_DSS_SIGN);
+                       c = (u8 *)&sign;
+                       c[3] = tci;
+                       break;
+               default:
+                       netif_err(dev, tx_err, dev->net,
+                                 "unsupported tci=0x%04x\n", tci);
+                       goto error;
+               }
+               skb_pull(skb, ETH_HLEN);
+       }
+
+       spin_lock_bh(&ctx->mtx);
+       skb_out = cdc_ncm_fill_tx_frame(ctx, skb, sign);
+       spin_unlock_bh(&ctx->mtx);
+       return skb_out;
+
+error:
+       if (skb)
+               dev_kfree_skb_any(skb);
+
+       return NULL;
+}
+
+static struct sk_buff *cdc_mbim_process_dgram(struct usbnet *dev, u8 *buf, size_t len, u16 tci)
+{
+       __be16 proto = htons(ETH_P_802_3);
+       struct sk_buff *skb = NULL;
+
+       if (tci < 256) { /* IPS session? */
+               if (len < sizeof(struct iphdr))
+                       goto err;
+
+               switch (*buf & 0xf0) {
+               case 0x40:
+                       proto = htons(ETH_P_IP);
+                       break;
+               case 0x60:
+                       proto = htons(ETH_P_IPV6);
+                       break;
+               default:
+                       goto err;
+               }
+       }
+
+       skb = netdev_alloc_skb_ip_align(dev->net,  len + ETH_HLEN);
+       if (!skb)
+               goto err;
+
+       /* add an ethernet header */
+       skb_put(skb, ETH_HLEN);
+       skb_reset_mac_header(skb);
+       eth_hdr(skb)->h_proto = proto;
+       memset(eth_hdr(skb)->h_source, 0, ETH_ALEN);
+       memcpy(eth_hdr(skb)->h_dest, dev->net->dev_addr, ETH_ALEN);
+
+       /* add datagram */
+       memcpy(skb_put(skb, len), buf, len);
+
+       /* map MBIM session to VLAN */
+       if (tci)
+               vlan_put_tag(skb, tci);
+err:
+       return skb;
+}
+
+static int cdc_mbim_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
+{
+       struct sk_buff *skb;
+       struct cdc_mbim_state *info = (void *)&dev->data;
+       struct cdc_ncm_ctx *ctx = info->ctx;
+       int len;
+       int nframes;
+       int x;
+       int offset;
+       struct usb_cdc_ncm_ndp16 *ndp16;
+       struct usb_cdc_ncm_dpe16 *dpe16;
+       int ndpoffset;
+       int loopcount = 50; /* arbitrary max preventing infinite loop */
+       u8 *c;
+       u16 tci;
+
+       ndpoffset = cdc_ncm_rx_verify_nth16(ctx, skb_in);
+       if (ndpoffset < 0)
+               goto error;
+
+next_ndp:
+       nframes = cdc_ncm_rx_verify_ndp16(skb_in, ndpoffset);
+       if (nframes < 0)
+               goto error;
+
+       ndp16 = (struct usb_cdc_ncm_ndp16 *)(skb_in->data + ndpoffset);
+
+       switch (ndp16->dwSignature & cpu_to_le32(0x00ffffff)) {
+       case cpu_to_le32(USB_CDC_MBIM_NDP16_IPS_SIGN):
+               c = (u8 *)&ndp16->dwSignature;
+               tci = c[3];
+               break;
+       case cpu_to_le32(USB_CDC_MBIM_NDP16_DSS_SIGN):
+               c = (u8 *)&ndp16->dwSignature;
+               tci = c[3] + 256;
+               break;
+       default:
+               netif_dbg(dev, rx_err, dev->net,
+                         "unsupported NDP signature <0x%08x>\n",
+                         le32_to_cpu(ndp16->dwSignature));
+               goto err_ndp;
+
+       }
+
+       dpe16 = ndp16->dpe16;
+       for (x = 0; x < nframes; x++, dpe16++) {
+               offset = le16_to_cpu(dpe16->wDatagramIndex);
+               len = le16_to_cpu(dpe16->wDatagramLength);
+
+               /*
+                * CDC NCM ch. 3.7
+                * All entries after first NULL entry are to be ignored
+                */
+               if ((offset == 0) || (len == 0)) {
+                       if (!x)
+                               goto err_ndp; /* empty NTB */
+                       break;
+               }
+
+               /* sanity checking */
+               if (((offset + len) > skb_in->len) || (len > ctx->rx_max)) {
+                       netif_dbg(dev, rx_err, dev->net,
+                                 "invalid frame detected (ignored) offset[%u]=%u, length=%u, skb=%p\n",
+                                 x, offset, len, skb_in);
+                       if (!x)
+                               goto err_ndp;
+                       break;
+               } else {
+                       skb = cdc_mbim_process_dgram(dev, skb_in->data + offset, len, tci);
+                       if (!skb)
+                               goto error;
+                       usbnet_skb_return(dev, skb);
+               }
+       }
+err_ndp:
+       /* are there more NDPs to process? */
+       ndpoffset = le16_to_cpu(ndp16->wNextNdpIndex);
+       if (ndpoffset && loopcount--)
+               goto next_ndp;
+
+       return 1;
+error:
+       return 0;
+}
+
+static int cdc_mbim_suspend(struct usb_interface *intf, pm_message_t message)
+{
+       int ret = 0;
+       struct usbnet *dev = usb_get_intfdata(intf);
+       struct cdc_mbim_state *info = (void *)&dev->data;
+       struct cdc_ncm_ctx *ctx = info->ctx;
+
+       if (ctx == NULL) {
+               ret = -1;
+               goto error;
+       }
+
+       ret = usbnet_suspend(intf, message);
+       if (ret < 0)
+               goto error;
+
+       if (intf == ctx->control && info->subdriver && info->subdriver->suspend)
+               ret = info->subdriver->suspend(intf, message);
+       if (ret < 0)
+               usbnet_resume(intf);
+
+error:
+       return ret;
+}
+
+static int cdc_mbim_resume(struct usb_interface *intf)
+{
+       int  ret = 0;
+       struct usbnet *dev = usb_get_intfdata(intf);
+       struct cdc_mbim_state *info = (void *)&dev->data;
+       struct cdc_ncm_ctx *ctx = info->ctx;
+       bool callsub = (intf == ctx->control && info->subdriver && info->subdriver->resume);
+
+       if (callsub)
+               ret = info->subdriver->resume(intf);
+       if (ret < 0)
+               goto err;
+       ret = usbnet_resume(intf);
+       if (ret < 0 && callsub && info->subdriver->suspend)
+               info->subdriver->suspend(intf, PMSG_SUSPEND);
+err:
+       return ret;
+}
+
+static const struct driver_info cdc_mbim_info = {
+       .description = "CDC MBIM",
+       .flags = FLAG_NO_SETINT | FLAG_MULTI_PACKET | FLAG_WWAN,
+       .bind = cdc_mbim_bind,
+       .unbind = cdc_mbim_unbind,
+       .manage_power = cdc_mbim_manage_power,
+       .rx_fixup = cdc_mbim_rx_fixup,
+       .tx_fixup = cdc_mbim_tx_fixup,
+};
+
+static const struct usb_device_id mbim_devs[] = {
+       /* This duplicate NCM entry is intentional. MBIM devices can
+        * be disguised as NCM by default, and this is necessary to
+        * allow us to bind the correct driver_info to such devices.
+        *
+        * bind() will sort out this for us, selecting the correct
+        * entry and reject the other
+        */
+       { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE),
+         .driver_info = (unsigned long)&cdc_mbim_info,
+       },
+       { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_MBIM, USB_CDC_PROTO_NONE),
+         .driver_info = (unsigned long)&cdc_mbim_info,
+       },
+       {
+       },
+};
+MODULE_DEVICE_TABLE(usb, mbim_devs);
+
+static struct usb_driver cdc_mbim_driver = {
+       .name = "cdc_mbim",
+       .id_table = mbim_devs,
+       .probe = usbnet_probe,
+       .disconnect = usbnet_disconnect,
+       .suspend = cdc_mbim_suspend,
+       .resume = cdc_mbim_resume,
+       .reset_resume = cdc_mbim_resume,
+       .supports_autosuspend = 1,
+       .disable_hub_initiated_lpm = 1,
+};
+module_usb_driver(cdc_mbim_driver);
+
+MODULE_AUTHOR("Greg Suarez <gsuarez@smithmicro.com>");
+MODULE_AUTHOR("Bjørn Mork <bjorn@mork.no>");
+MODULE_DESCRIPTION("USB CDC MBIM host driver");
+MODULE_LICENSE("GPL");
index 4cd582a4f625d55d5edd8c2cd3952d5571074921..0ed03b1ba39a0b5b1dfa0371350e340dbb223aa3 100644 (file)
 #include <linux/atomic.h>
 #include <linux/usb/usbnet.h>
 #include <linux/usb/cdc.h>
+#include <linux/usb/cdc_ncm.h>
 
 #define        DRIVER_VERSION                          "14-Mar-2012"
 
-/* CDC NCM subclass 3.2.1 */
-#define USB_CDC_NCM_NDP16_LENGTH_MIN           0x10
-
-/* Maximum NTB length */
-#define        CDC_NCM_NTB_MAX_SIZE_TX                 32768   /* bytes */
-#define        CDC_NCM_NTB_MAX_SIZE_RX                 32768   /* bytes */
-
-/* Minimum value for MaxDatagramSize, ch. 6.2.9 */
-#define        CDC_NCM_MIN_DATAGRAM_SIZE               1514    /* bytes */
-
-#define        CDC_NCM_MIN_TX_PKT                      512     /* bytes */
-
-/* Default value for MaxDatagramSize */
-#define        CDC_NCM_MAX_DATAGRAM_SIZE               8192    /* bytes */
-
-/*
- * Maximum amount of datagrams in NCM Datagram Pointer Table, not counting
- * the last NULL entry.
- */
-#define        CDC_NCM_DPT_DATAGRAMS_MAX               40
-
-/* Restart the timer, if amount of datagrams is less than given value */
-#define        CDC_NCM_RESTART_TIMER_DATAGRAM_CNT      3
-#define        CDC_NCM_TIMER_PENDING_CNT               2
-#define CDC_NCM_TIMER_INTERVAL                 (400UL * NSEC_PER_USEC)
-
-/* The following macro defines the minimum header space */
-#define        CDC_NCM_MIN_HDR_SIZE \
-       (sizeof(struct usb_cdc_ncm_nth16) + sizeof(struct usb_cdc_ncm_ndp16) + \
-       (CDC_NCM_DPT_DATAGRAMS_MAX + 1) * sizeof(struct usb_cdc_ncm_dpe16))
-
-struct cdc_ncm_data {
-       struct usb_cdc_ncm_nth16 nth16;
-       struct usb_cdc_ncm_ndp16 ndp16;
-       struct usb_cdc_ncm_dpe16 dpe16[CDC_NCM_DPT_DATAGRAMS_MAX + 1];
-};
-
-struct cdc_ncm_ctx {
-       struct cdc_ncm_data tx_ncm;
-       struct usb_cdc_ncm_ntb_parameters ncm_parm;
-       struct hrtimer tx_timer;
-       struct tasklet_struct bh;
-
-       const struct usb_cdc_ncm_desc *func_desc;
-       const struct usb_cdc_header_desc *header_desc;
-       const struct usb_cdc_union_desc *union_desc;
-       const struct usb_cdc_ether_desc *ether_desc;
-
-       struct net_device *netdev;
-       struct usb_device *udev;
-       struct usb_host_endpoint *in_ep;
-       struct usb_host_endpoint *out_ep;
-       struct usb_host_endpoint *status_ep;
-       struct usb_interface *intf;
-       struct usb_interface *control;
-       struct usb_interface *data;
-
-       struct sk_buff *tx_curr_skb;
-       struct sk_buff *tx_rem_skb;
-
-       spinlock_t mtx;
-       atomic_t stop;
-
-       u32 tx_timer_pending;
-       u32 tx_curr_offset;
-       u32 tx_curr_last_offset;
-       u32 tx_curr_frame_num;
-       u32 rx_speed;
-       u32 tx_speed;
-       u32 rx_max;
-       u32 tx_max;
-       u32 max_datagram_size;
-       u16 tx_max_datagrams;
-       u16 tx_remainder;
-       u16 tx_modulus;
-       u16 tx_ndp_modulus;
-       u16 tx_seq;
-       u16 rx_seq;
-       u16 connected;
-};
-
 static void cdc_ncm_txpath_bh(unsigned long param);
 static void cdc_ncm_tx_timeout_start(struct cdc_ncm_ctx *ctx);
 static enum hrtimer_restart cdc_ncm_tx_timer_cb(struct hrtimer *hr_timer);
@@ -158,7 +78,10 @@ static u8 cdc_ncm_setup(struct cdc_ncm_ctx *ctx)
        u8 flags;
        u8 iface_no;
        int err;
+       int eth_hlen;
        u16 ntb_fmt_supported;
+       u32 min_dgram_size;
+       u32 min_hdr_size;
 
        iface_no = ctx->control->cur_altsetting->desc.bInterfaceNumber;
 
@@ -184,10 +107,19 @@ static u8 cdc_ncm_setup(struct cdc_ncm_ctx *ctx)
        ctx->tx_max_datagrams = le16_to_cpu(ctx->ncm_parm.wNtbOutMaxDatagrams);
        ntb_fmt_supported = le16_to_cpu(ctx->ncm_parm.bmNtbFormatsSupported);
 
-       if (ctx->func_desc != NULL)
+       eth_hlen = ETH_HLEN;
+       min_dgram_size = CDC_NCM_MIN_DATAGRAM_SIZE;
+       min_hdr_size = CDC_NCM_MIN_HDR_SIZE;
+       if (ctx->mbim_desc != NULL) {
+               flags = ctx->mbim_desc->bmNetworkCapabilities;
+               eth_hlen = 0;
+               min_dgram_size = CDC_MBIM_MIN_DATAGRAM_SIZE;
+               min_hdr_size = 0;
+       } else if (ctx->func_desc != NULL) {
                flags = ctx->func_desc->bmNetworkCapabilities;
-       else
+       } else {
                flags = 0;
+       }
 
        pr_debug("dwNtbInMaxSize=%u dwNtbOutMaxSize=%u "
                 "wNdpOutPayloadRemainder=%u wNdpOutDivisor=%u "
@@ -215,41 +147,21 @@ static u8 cdc_ncm_setup(struct cdc_ncm_ctx *ctx)
 
        /* inform device about NTB input size changes */
        if (ctx->rx_max != le32_to_cpu(ctx->ncm_parm.dwNtbInMaxSize)) {
+               __le32 *dwNtbInMaxSize;
 
-               if (flags & USB_CDC_NCM_NCAP_NTB_INPUT_SIZE) {
-                       struct usb_cdc_ncm_ndp_input_size *ndp_in_sz;
-
-                       ndp_in_sz = kzalloc(sizeof(*ndp_in_sz), GFP_KERNEL);
-                       if (!ndp_in_sz) {
-                               err = -ENOMEM;
-                               goto size_err;
-                       }
-
-                       err = usb_control_msg(ctx->udev,
-                                       usb_sndctrlpipe(ctx->udev, 0),
-                                       USB_CDC_SET_NTB_INPUT_SIZE,
-                                       USB_TYPE_CLASS | USB_DIR_OUT
-                                        | USB_RECIP_INTERFACE,
-                                       0, iface_no, ndp_in_sz, 8, 1000);
-                       kfree(ndp_in_sz);
-               } else {
-                       __le32 *dwNtbInMaxSize;
-                       dwNtbInMaxSize = kzalloc(sizeof(*dwNtbInMaxSize),
-                                       GFP_KERNEL);
-                       if (!dwNtbInMaxSize) {
-                               err = -ENOMEM;
-                               goto size_err;
-                       }
-                       *dwNtbInMaxSize = cpu_to_le32(ctx->rx_max);
-
-                       err = usb_control_msg(ctx->udev,
-                                       usb_sndctrlpipe(ctx->udev, 0),
-                                       USB_CDC_SET_NTB_INPUT_SIZE,
-                                       USB_TYPE_CLASS | USB_DIR_OUT
-                                        | USB_RECIP_INTERFACE,
-                                       0, iface_no, dwNtbInMaxSize, 4, 1000);
-                       kfree(dwNtbInMaxSize);
+               dwNtbInMaxSize = kzalloc(sizeof(*dwNtbInMaxSize), GFP_KERNEL);
+               if (!dwNtbInMaxSize) {
+                       err = -ENOMEM;
+                       goto size_err;
                }
+               *dwNtbInMaxSize = cpu_to_le32(ctx->rx_max);
+               err = usb_control_msg(ctx->udev,
+                                     usb_sndctrlpipe(ctx->udev, 0),
+                                     USB_CDC_SET_NTB_INPUT_SIZE,
+                                     USB_TYPE_CLASS | USB_DIR_OUT
+                                     | USB_RECIP_INTERFACE,
+                                     0, iface_no, dwNtbInMaxSize, 4, 1000);
+               kfree(dwNtbInMaxSize);
 size_err:
                if (err < 0)
                        pr_debug("Setting NTB Input Size failed\n");
@@ -257,7 +169,7 @@ size_err:
 
        /* verify maximum size of transmitted NTB in bytes */
        if ((ctx->tx_max <
-           (CDC_NCM_MIN_HDR_SIZE + CDC_NCM_MIN_DATAGRAM_SIZE)) ||
+           (min_hdr_size + min_dgram_size)) ||
            (ctx->tx_max > CDC_NCM_NTB_MAX_SIZE_TX)) {
                pr_debug("Using default maximum transmit length=%d\n",
                                                CDC_NCM_NTB_MAX_SIZE_TX);
@@ -299,8 +211,8 @@ size_err:
        }
 
        /* adjust TX-remainder according to NCM specification. */
-       ctx->tx_remainder = ((ctx->tx_remainder - ETH_HLEN) &
-                                               (ctx->tx_modulus - 1));
+       ctx->tx_remainder = ((ctx->tx_remainder - eth_hlen) &
+                            (ctx->tx_modulus - 1));
 
        /* additional configuration */
 
@@ -327,12 +239,18 @@ size_err:
                        pr_debug("Setting NTB format to 16-bit failed\n");
        }
 
-       ctx->max_datagram_size = CDC_NCM_MIN_DATAGRAM_SIZE;
+       ctx->max_datagram_size = min_dgram_size;
 
        /* set Max Datagram Size (MTU) */
        if (flags & USB_CDC_NCM_NCAP_MAX_DATAGRAM_SIZE) {
                __le16 *max_datagram_size;
-               u16 eth_max_sz = le16_to_cpu(ctx->ether_desc->wMaxSegmentSize);
+               u16 eth_max_sz;
+               if (ctx->ether_desc != NULL)
+                       eth_max_sz = le16_to_cpu(ctx->ether_desc->wMaxSegmentSize);
+               else if (ctx->mbim_desc != NULL)
+                       eth_max_sz = le16_to_cpu(ctx->mbim_desc->wMaxSegmentSize);
+               else
+                       goto max_dgram_err;
 
                max_datagram_size = kzalloc(sizeof(*max_datagram_size),
                                GFP_KERNEL);
@@ -349,7 +267,7 @@ size_err:
                                2, 1000);
                if (err < 0) {
                        pr_debug("GET_MAX_DATAGRAM_SIZE failed, use size=%u\n",
-                                               CDC_NCM_MIN_DATAGRAM_SIZE);
+                                min_dgram_size);
                } else {
                        ctx->max_datagram_size =
                                le16_to_cpu(*max_datagram_size);
@@ -358,12 +276,10 @@ size_err:
                                        ctx->max_datagram_size = eth_max_sz;
 
                        if (ctx->max_datagram_size > CDC_NCM_MAX_DATAGRAM_SIZE)
-                               ctx->max_datagram_size =
-                                               CDC_NCM_MAX_DATAGRAM_SIZE;
+                               ctx->max_datagram_size = CDC_NCM_MAX_DATAGRAM_SIZE;
 
-                       if (ctx->max_datagram_size < CDC_NCM_MIN_DATAGRAM_SIZE)
-                               ctx->max_datagram_size =
-                                       CDC_NCM_MIN_DATAGRAM_SIZE;
+                       if (ctx->max_datagram_size < min_dgram_size)
+                               ctx->max_datagram_size = min_dgram_size;
 
                        /* if value changed, update device */
                        if (ctx->max_datagram_size !=
@@ -384,8 +300,8 @@ size_err:
        }
 
 max_dgram_err:
-       if (ctx->netdev->mtu != (ctx->max_datagram_size - ETH_HLEN))
-               ctx->netdev->mtu = ctx->max_datagram_size - ETH_HLEN;
+       if (ctx->netdev->mtu != (ctx->max_datagram_size - eth_hlen))
+               ctx->netdev->mtu = ctx->max_datagram_size - eth_hlen;
 
        return 0;
 }
@@ -451,7 +367,7 @@ static const struct ethtool_ops cdc_ncm_ethtool_ops = {
        .nway_reset = usbnet_nway_reset,
 };
 
-static int cdc_ncm_bind(struct usbnet *dev, struct usb_interface *intf)
+int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_altsetting)
 {
        struct cdc_ncm_ctx *ctx;
        struct usb_driver *driver;
@@ -525,6 +441,13 @@ static int cdc_ncm_bind(struct usbnet *dev, struct usb_interface *intf)
                        ctx->func_desc = (const struct usb_cdc_ncm_desc *)buf;
                        break;
 
+               case USB_CDC_MBIM_TYPE:
+                       if (buf[0] < sizeof(*(ctx->mbim_desc)))
+                               break;
+
+                       ctx->mbim_desc = (const struct usb_cdc_mbim_desc *)buf;
+                       break;
+
                default:
                        break;
                }
@@ -537,7 +460,7 @@ advance:
 
        /* check if we got everything */
        if ((ctx->control == NULL) || (ctx->data == NULL) ||
-           (ctx->ether_desc == NULL) || (ctx->control != intf))
+           ((!ctx->mbim_desc) && ((ctx->ether_desc == NULL) || (ctx->control != intf))))
                goto error;
 
        /* claim interfaces, if any */
@@ -557,7 +480,7 @@ advance:
                goto error2;
 
        /* configure data interface */
-       temp = usb_set_interface(dev->udev, iface_no, 1);
+       temp = usb_set_interface(dev->udev, iface_no, data_altsetting);
        if (temp)
                goto error2;
 
@@ -574,11 +497,13 @@ advance:
        usb_set_intfdata(ctx->control, dev);
        usb_set_intfdata(ctx->intf, dev);
 
-       temp = usbnet_get_ethernet_addr(dev, ctx->ether_desc->iMACAddress);
-       if (temp)
-               goto error2;
+       if (ctx->ether_desc) {
+               temp = usbnet_get_ethernet_addr(dev, ctx->ether_desc->iMACAddress);
+               if (temp)
+                       goto error2;
+               dev_info(&dev->udev->dev, "MAC-Address: %pM\n", dev->net->dev_addr);
+       }
 
-       dev_info(&dev->udev->dev, "MAC-Address: %pM\n", dev->net->dev_addr);
 
        dev->in = usb_rcvbulkpipe(dev->udev,
                ctx->in_ep->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
@@ -587,13 +512,6 @@ advance:
        dev->status = ctx->status_ep;
        dev->rx_urb_size = ctx->rx_max;
 
-       /*
-        * We should get an event when network connection is "connected" or
-        * "disconnected". Set network connection in "disconnected" state
-        * (carrier is OFF) during attach, so the IP network stack does not
-        * start IPv6 negotiation and more.
-        */
-       netif_carrier_off(dev->net);
        ctx->tx_speed = ctx->rx_speed = 0;
        return 0;
 
@@ -607,8 +525,9 @@ error:
        dev_info(&dev->udev->dev, "bind() failure\n");
        return -ENODEV;
 }
+EXPORT_SYMBOL_GPL(cdc_ncm_bind_common);
 
-static void cdc_ncm_unbind(struct usbnet *dev, struct usb_interface *intf)
+void cdc_ncm_unbind(struct usbnet *dev, struct usb_interface *intf)
 {
        struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0];
        struct usb_driver *driver = driver_of(intf);
@@ -638,52 +557,121 @@ static void cdc_ncm_unbind(struct usbnet *dev, struct usb_interface *intf)
        usb_set_intfdata(ctx->intf, NULL);
        cdc_ncm_free(ctx);
 }
+EXPORT_SYMBOL_GPL(cdc_ncm_unbind);
 
-static void cdc_ncm_zero_fill(u8 *ptr, u32 first, u32 end, u32 max)
+static int cdc_ncm_bind(struct usbnet *dev, struct usb_interface *intf)
 {
-       if (first >= max)
-               return;
-       if (first >= end)
-               return;
-       if (end > max)
-               end = max;
-       memset(ptr + first, 0, end - first);
+       int ret;
+
+       /* The MBIM spec defines a NCM compatible default altsetting,
+        * which we may have matched:
+        *
+        *  "Functions that implement both NCM 1.0 and MBIM (an
+        *   “NCM/MBIM function”) according to this recommendation
+        *   shall provide two alternate settings for the
+        *   Communication Interface.  Alternate setting 0, and the
+        *   associated class and endpoint descriptors, shall be
+        *   constructed according to the rules given for the
+        *   Communication Interface in section 5 of [USBNCM10].
+        *   Alternate setting 1, and the associated class and
+        *   endpoint descriptors, shall be constructed according to
+        *   the rules given in section 6 (USB Device Model) of this
+        *   specification."
+        *
+        * Do not bind to such interfaces, allowing cdc_mbim to handle
+        * them
+        */
+#if IS_ENABLED(CONFIG_USB_NET_CDC_MBIM)
+       if ((intf->num_altsetting == 2) &&
+           !usb_set_interface(dev->udev,
+                              intf->cur_altsetting->desc.bInterfaceNumber,
+                              CDC_NCM_COMM_ALTSETTING_MBIM) &&
+           cdc_ncm_comm_intf_is_mbim(intf->cur_altsetting))
+               return -ENODEV;
+#endif
+
+       /* NCM data altsetting is always 1 */
+       ret = cdc_ncm_bind_common(dev, intf, 1);
+
+       /*
+        * We should get an event when network connection is "connected" or
+        * "disconnected". Set network connection in "disconnected" state
+        * (carrier is OFF) during attach, so the IP network stack does not
+        * start IPv6 negotiation and more.
+        */
+       netif_carrier_off(dev->net);
+       return ret;
 }
 
-static struct sk_buff *
-cdc_ncm_fill_tx_frame(struct cdc_ncm_ctx *ctx, struct sk_buff *skb)
+static void cdc_ncm_align_tail(struct sk_buff *skb, size_t modulus, size_t remainder, size_t max)
+{
+       size_t align = ALIGN(skb->len, modulus) - skb->len + remainder;
+
+       if (skb->len + align > max)
+               align = max - skb->len;
+       if (align && skb_tailroom(skb) >= align)
+               memset(skb_put(skb, align), 0, align);
+}
+
+/* return a pointer to a valid struct usb_cdc_ncm_ndp16 of type sign, possibly
+ * allocating a new one within skb
+ */
+static struct usb_cdc_ncm_ndp16 *cdc_ncm_ndp(struct cdc_ncm_ctx *ctx, struct sk_buff *skb, __le32 sign, size_t reserve)
+{
+       struct usb_cdc_ncm_ndp16 *ndp16 = NULL;
+       struct usb_cdc_ncm_nth16 *nth16 = (void *)skb->data;
+       size_t ndpoffset = le16_to_cpu(nth16->wNdpIndex);
+
+       /* follow the chain of NDPs, looking for a match */
+       while (ndpoffset) {
+               ndp16 = (struct usb_cdc_ncm_ndp16 *)(skb->data + ndpoffset);
+               if  (ndp16->dwSignature == sign)
+                       return ndp16;
+               ndpoffset = le16_to_cpu(ndp16->wNextNdpIndex);
+       }
+
+       /* align new NDP */
+       cdc_ncm_align_tail(skb, ctx->tx_ndp_modulus, 0, ctx->tx_max);
+
+       /* verify that there is room for the NDP and the datagram (reserve) */
+       if ((ctx->tx_max - skb->len - reserve) < CDC_NCM_NDP_SIZE)
+               return NULL;
+
+       /* link to it */
+       if (ndp16)
+               ndp16->wNextNdpIndex = cpu_to_le16(skb->len);
+       else
+               nth16->wNdpIndex = cpu_to_le16(skb->len);
+
+       /* push a new empty NDP */
+       ndp16 = (struct usb_cdc_ncm_ndp16 *)memset(skb_put(skb, CDC_NCM_NDP_SIZE), 0, CDC_NCM_NDP_SIZE);
+       ndp16->dwSignature = sign;
+       ndp16->wLength = cpu_to_le16(sizeof(struct usb_cdc_ncm_ndp16) + sizeof(struct usb_cdc_ncm_dpe16));
+       return ndp16;
+}
+
+struct sk_buff *
+cdc_ncm_fill_tx_frame(struct cdc_ncm_ctx *ctx, struct sk_buff *skb, __le32 sign)
 {
+       struct usb_cdc_ncm_nth16 *nth16;
+       struct usb_cdc_ncm_ndp16 *ndp16;
        struct sk_buff *skb_out;
-       u32 rem;
-       u32 offset;
-       u32 last_offset;
-       u16 n = 0, index;
+       u16 n = 0, index, ndplen;
        u8 ready2send = 0;
 
        /* if there is a remaining skb, it gets priority */
-       if (skb != NULL)
+       if (skb != NULL) {
                swap(skb, ctx->tx_rem_skb);
-       else
+               swap(sign, ctx->tx_rem_sign);
+       } else {
                ready2send = 1;
-
-       /*
-        * +----------------+
-        * | skb_out        |
-        * +----------------+
-        *           ^ offset
-        *        ^ last_offset
-        */
+       }
 
        /* check if we are resuming an OUT skb */
-       if (ctx->tx_curr_skb != NULL) {
-               /* pop variables */
-               skb_out = ctx->tx_curr_skb;
-               offset = ctx->tx_curr_offset;
-               last_offset = ctx->tx_curr_last_offset;
-               n = ctx->tx_curr_frame_num;
+       skb_out = ctx->tx_curr_skb;
 
-       } else {
-               /* reset variables */
+       /* allocate a new OUT skb */
+       if (!skb_out) {
                skb_out = alloc_skb((ctx->tx_max + 1), GFP_ATOMIC);
                if (skb_out == NULL) {
                        if (skb != NULL) {
@@ -692,35 +680,21 @@ cdc_ncm_fill_tx_frame(struct cdc_ncm_ctx *ctx, struct sk_buff *skb)
                        }
                        goto exit_no_skb;
                }
+               /* fill out the initial 16-bit NTB header */
+               nth16 = (struct usb_cdc_ncm_nth16 *)memset(skb_put(skb_out, sizeof(struct usb_cdc_ncm_nth16)), 0, sizeof(struct usb_cdc_ncm_nth16));
+               nth16->dwSignature = cpu_to_le32(USB_CDC_NCM_NTH16_SIGN);
+               nth16->wHeaderLength = cpu_to_le16(sizeof(struct usb_cdc_ncm_nth16));
+               nth16->wSequence = cpu_to_le16(ctx->tx_seq++);
 
-               /* make room for NTH and NDP */
-               offset = ALIGN(sizeof(struct usb_cdc_ncm_nth16),
-                                       ctx->tx_ndp_modulus) +
-                                       sizeof(struct usb_cdc_ncm_ndp16) +
-                                       (ctx->tx_max_datagrams + 1) *
-                                       sizeof(struct usb_cdc_ncm_dpe16);
-
-               /* store last valid offset before alignment */
-               last_offset = offset;
-               /* align first Datagram offset correctly */
-               offset = ALIGN(offset, ctx->tx_modulus) + ctx->tx_remainder;
-               /* zero buffer till the first IP datagram */
-               cdc_ncm_zero_fill(skb_out->data, 0, offset, offset);
-               n = 0;
+               /* count total number of frames in this NTB */
                ctx->tx_curr_frame_num = 0;
        }
 
-       for (; n < ctx->tx_max_datagrams; n++) {
-               /* check if end of transmit buffer is reached */
-               if (offset >= ctx->tx_max) {
-                       ready2send = 1;
-                       break;
-               }
-               /* compute maximum buffer size */
-               rem = ctx->tx_max - offset;
-
+       for (n = ctx->tx_curr_frame_num; n < ctx->tx_max_datagrams; n++) {
+               /* send any remaining skb first */
                if (skb == NULL) {
                        skb = ctx->tx_rem_skb;
+                       sign = ctx->tx_rem_sign;
                        ctx->tx_rem_skb = NULL;
 
                        /* check for end of skb */
@@ -728,7 +702,14 @@ cdc_ncm_fill_tx_frame(struct cdc_ncm_ctx *ctx, struct sk_buff *skb)
                                break;
                }
 
-               if (skb->len > rem) {
+               /* get the appropriate NDP for this skb */
+               ndp16 = cdc_ncm_ndp(ctx, skb_out, sign, skb->len + ctx->tx_modulus + ctx->tx_remainder);
+
+               /* align beginning of next frame */
+               cdc_ncm_align_tail(skb_out,  ctx->tx_modulus, ctx->tx_remainder, ctx->tx_max);
+
+               /* check if we had enough room left for both NDP and frame */
+               if (!ndp16 || skb_out->len + skb->len > ctx->tx_max) {
                        if (n == 0) {
                                /* won't fit, MTU problem? */
                                dev_kfree_skb_any(skb);
@@ -741,31 +722,30 @@ cdc_ncm_fill_tx_frame(struct cdc_ncm_ctx *ctx, struct sk_buff *skb)
                                        ctx->netdev->stats.tx_dropped++;
                                }
                                ctx->tx_rem_skb = skb;
+                               ctx->tx_rem_sign = sign;
                                skb = NULL;
                                ready2send = 1;
                        }
                        break;
                }
 
-               memcpy(((u8 *)skb_out->data) + offset, skb->data, skb->len);
-
-               ctx->tx_ncm.dpe16[n].wDatagramLength = cpu_to_le16(skb->len);
-               ctx->tx_ncm.dpe16[n].wDatagramIndex = cpu_to_le16(offset);
-
-               /* update offset */
-               offset += skb->len;
-
-               /* store last valid offset before alignment */
-               last_offset = offset;
-
-               /* align offset correctly */
-               offset = ALIGN(offset, ctx->tx_modulus) + ctx->tx_remainder;
+               /* calculate frame number withing this NDP */
+               ndplen = le16_to_cpu(ndp16->wLength);
+               index = (ndplen - sizeof(struct usb_cdc_ncm_ndp16)) / sizeof(struct usb_cdc_ncm_dpe16) - 1;
 
-               /* zero padding */
-               cdc_ncm_zero_fill(skb_out->data, last_offset, offset,
-                                                               ctx->tx_max);
+               /* OK, add this skb */
+               ndp16->dpe16[index].wDatagramLength = cpu_to_le16(skb->len);
+               ndp16->dpe16[index].wDatagramIndex = cpu_to_le16(skb_out->len);
+               ndp16->wLength = cpu_to_le16(ndplen + sizeof(struct usb_cdc_ncm_dpe16));
+               memcpy(skb_put(skb_out, skb->len), skb->data, skb->len);
                dev_kfree_skb_any(skb);
                skb = NULL;
+
+               /* send now if this NDP is full */
+               if (index >= CDC_NCM_DPT_DATAGRAMS_MAX) {
+                       ready2send = 1;
+                       break;
+               }
        }
 
        /* free up any dangling skb */
@@ -781,16 +761,12 @@ cdc_ncm_fill_tx_frame(struct cdc_ncm_ctx *ctx, struct sk_buff *skb)
                /* wait for more frames */
                /* push variables */
                ctx->tx_curr_skb = skb_out;
-               ctx->tx_curr_offset = offset;
-               ctx->tx_curr_last_offset = last_offset;
                goto exit_no_skb;
 
        } else if ((n < ctx->tx_max_datagrams) && (ready2send == 0)) {
                /* wait for more frames */
                /* push variables */
                ctx->tx_curr_skb = skb_out;
-               ctx->tx_curr_offset = offset;
-               ctx->tx_curr_last_offset = last_offset;
                /* set the pending count */
                if (n < CDC_NCM_RESTART_TIMER_DATAGRAM_CNT)
                        ctx->tx_timer_pending = CDC_NCM_TIMER_PENDING_CNT;
@@ -801,75 +777,24 @@ cdc_ncm_fill_tx_frame(struct cdc_ncm_ctx *ctx, struct sk_buff *skb)
                /* variables will be reset at next call */
        }
 
-       /* check for overflow */
-       if (last_offset > ctx->tx_max)
-               last_offset = ctx->tx_max;
-
-       /* revert offset */
-       offset = last_offset;
-
        /*
         * If collected data size is less or equal CDC_NCM_MIN_TX_PKT bytes,
         * we send buffers as it is. If we get more data, it would be more
         * efficient for USB HS mobile device with DMA engine to receive a full
         * size NTB, than canceling DMA transfer and receiving a short packet.
         */
-       if (offset > CDC_NCM_MIN_TX_PKT)
-               offset = ctx->tx_max;
-
-       /* final zero padding */
-       cdc_ncm_zero_fill(skb_out->data, last_offset, offset, ctx->tx_max);
-
-       /* store last offset */
-       last_offset = offset;
-
-       if (((last_offset < ctx->tx_max) && ((last_offset %
-                       le16_to_cpu(ctx->out_ep->desc.wMaxPacketSize)) == 0)) ||
-           (((last_offset == ctx->tx_max) && ((ctx->tx_max %
-               le16_to_cpu(ctx->out_ep->desc.wMaxPacketSize)) == 0)) &&
-               (ctx->tx_max < le32_to_cpu(ctx->ncm_parm.dwNtbOutMaxSize)))) {
-               /* force short packet */
-               *(((u8 *)skb_out->data) + last_offset) = 0;
-               last_offset++;
-       }
-
-       /* zero the rest of the DPEs plus the last NULL entry */
-       for (; n <= CDC_NCM_DPT_DATAGRAMS_MAX; n++) {
-               ctx->tx_ncm.dpe16[n].wDatagramLength = 0;
-               ctx->tx_ncm.dpe16[n].wDatagramIndex = 0;
-       }
+       if (skb_out->len > CDC_NCM_MIN_TX_PKT)
+               /* final zero padding */
+               memset(skb_put(skb_out, ctx->tx_max - skb_out->len), 0, ctx->tx_max - skb_out->len);
 
-       /* fill out 16-bit NTB header */
-       ctx->tx_ncm.nth16.dwSignature = cpu_to_le32(USB_CDC_NCM_NTH16_SIGN);
-       ctx->tx_ncm.nth16.wHeaderLength =
-                                       cpu_to_le16(sizeof(ctx->tx_ncm.nth16));
-       ctx->tx_ncm.nth16.wSequence = cpu_to_le16(ctx->tx_seq);
-       ctx->tx_ncm.nth16.wBlockLength = cpu_to_le16(last_offset);
-       index = ALIGN(sizeof(struct usb_cdc_ncm_nth16), ctx->tx_ndp_modulus);
-       ctx->tx_ncm.nth16.wNdpIndex = cpu_to_le16(index);
-
-       memcpy(skb_out->data, &(ctx->tx_ncm.nth16), sizeof(ctx->tx_ncm.nth16));
-       ctx->tx_seq++;
-
-       /* fill out 16-bit NDP table */
-       ctx->tx_ncm.ndp16.dwSignature =
-                               cpu_to_le32(USB_CDC_NCM_NDP16_NOCRC_SIGN);
-       rem = sizeof(ctx->tx_ncm.ndp16) + ((ctx->tx_curr_frame_num + 1) *
-                                       sizeof(struct usb_cdc_ncm_dpe16));
-       ctx->tx_ncm.ndp16.wLength = cpu_to_le16(rem);
-       ctx->tx_ncm.ndp16.wNextNdpIndex = 0; /* reserved */
-
-       memcpy(((u8 *)skb_out->data) + index,
-                                               &(ctx->tx_ncm.ndp16),
-                                               sizeof(ctx->tx_ncm.ndp16));
-
-       memcpy(((u8 *)skb_out->data) + index + sizeof(ctx->tx_ncm.ndp16),
-                                       &(ctx->tx_ncm.dpe16),
-                                       (ctx->tx_curr_frame_num + 1) *
-                                       sizeof(struct usb_cdc_ncm_dpe16));
+       /* do we need to prevent a ZLP? */
+       if (((skb_out->len % le16_to_cpu(ctx->out_ep->desc.wMaxPacketSize)) == 0) &&
+           (skb_out->len < le32_to_cpu(ctx->ncm_parm.dwNtbOutMaxSize)) && skb_tailroom(skb_out))
+               *skb_put(skb_out, 1) = 0;       /* force short packet */
 
-       /* set frame length */
-       skb_put(skb_out, last_offset);
+       /* set final frame length */
+       nth16 = (struct usb_cdc_ncm_nth16 *)skb_out->data;
+       nth16->wBlockLength = cpu_to_le16(skb_out->len);
 
        /* return skb */
        ctx->tx_curr_skb = NULL;
@@ -882,6 +807,7 @@ exit_no_skb:
                cdc_ncm_tx_timeout_start(ctx);
        return NULL;
 }
+EXPORT_SYMBOL_GPL(cdc_ncm_fill_tx_frame);
 
 static void cdc_ncm_tx_timeout_start(struct cdc_ncm_ctx *ctx)
 {
@@ -936,7 +862,7 @@ cdc_ncm_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
                goto error;
 
        spin_lock_bh(&ctx->mtx);
-       skb_out = cdc_ncm_fill_tx_frame(ctx, skb);
+       skb_out = cdc_ncm_fill_tx_frame(ctx, skb, cpu_to_le32(USB_CDC_NCM_NDP16_NOCRC_SIGN));
        spin_unlock_bh(&ctx->mtx);
        return skb_out;
 
@@ -947,17 +873,12 @@ error:
        return NULL;
 }
 
-static int cdc_ncm_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
+/* verify NTB header and return offset of first NDP, or negative error */
+int cdc_ncm_rx_verify_nth16(struct cdc_ncm_ctx *ctx, struct sk_buff *skb_in)
 {
-       struct sk_buff *skb;
-       struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0];
-       int len;
-       int nframes;
-       int x;
-       int offset;
        struct usb_cdc_ncm_nth16 *nth16;
-       struct usb_cdc_ncm_ndp16 *ndp16;
-       struct usb_cdc_ncm_dpe16 *dpe16;
+       int len;
+       int ret = -EINVAL;
 
        if (ctx == NULL)
                goto error;
@@ -991,20 +912,23 @@ static int cdc_ncm_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
        }
        ctx->rx_seq = le16_to_cpu(nth16->wSequence);
 
-       len = le16_to_cpu(nth16->wNdpIndex);
-       if ((len + sizeof(struct usb_cdc_ncm_ndp16)) > skb_in->len) {
-               pr_debug("invalid DPT16 index <%u>\n",
-                                       le16_to_cpu(nth16->wNdpIndex));
-               goto error;
-       }
+       ret = le16_to_cpu(nth16->wNdpIndex);
+error:
+       return ret;
+}
+EXPORT_SYMBOL_GPL(cdc_ncm_rx_verify_nth16);
 
-       ndp16 = (struct usb_cdc_ncm_ndp16 *)(((u8 *)skb_in->data) + len);
+/* verify NDP header and return number of datagrams, or negative error */
+int cdc_ncm_rx_verify_ndp16(struct sk_buff *skb_in, int ndpoffset)
+{
+       struct usb_cdc_ncm_ndp16 *ndp16;
+       int ret = -EINVAL;
 
-       if (le32_to_cpu(ndp16->dwSignature) != USB_CDC_NCM_NDP16_NOCRC_SIGN) {
-               pr_debug("invalid DPT16 signature <%u>\n",
-                                       le32_to_cpu(ndp16->dwSignature));
+       if ((ndpoffset + sizeof(struct usb_cdc_ncm_ndp16)) > skb_in->len) {
+               pr_debug("invalid NDP offset  <%u>\n", ndpoffset);
                goto error;
        }
+       ndp16 = (struct usb_cdc_ncm_ndp16 *)(skb_in->data + ndpoffset);
 
        if (le16_to_cpu(ndp16->wLength) < USB_CDC_NCM_NDP16_LENGTH_MIN) {
                pr_debug("invalid DPT16 length <%u>\n",
@@ -1012,20 +936,52 @@ static int cdc_ncm_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
                goto error;
        }
 
-       nframes = ((le16_to_cpu(ndp16->wLength) -
+       ret = ((le16_to_cpu(ndp16->wLength) -
                                        sizeof(struct usb_cdc_ncm_ndp16)) /
                                        sizeof(struct usb_cdc_ncm_dpe16));
-       nframes--; /* we process NDP entries except for the last one */
-
-       len += sizeof(struct usb_cdc_ncm_ndp16);
+       ret--; /* we process NDP entries except for the last one */
 
-       if ((len + nframes * (sizeof(struct usb_cdc_ncm_dpe16))) >
+       if ((sizeof(struct usb_cdc_ncm_ndp16) + ret * (sizeof(struct usb_cdc_ncm_dpe16))) >
                                                                skb_in->len) {
-               pr_debug("Invalid nframes = %d\n", nframes);
-               goto error;
+               pr_debug("Invalid nframes = %d\n", ret);
+               ret = -EINVAL;
        }
 
-       dpe16 = (struct usb_cdc_ncm_dpe16 *)(((u8 *)skb_in->data) + len);
+error:
+       return ret;
+}
+EXPORT_SYMBOL_GPL(cdc_ncm_rx_verify_ndp16);
+
+static int cdc_ncm_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
+{
+       struct sk_buff *skb;
+       struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0];
+       int len;
+       int nframes;
+       int x;
+       int offset;
+       struct usb_cdc_ncm_ndp16 *ndp16;
+       struct usb_cdc_ncm_dpe16 *dpe16;
+       int ndpoffset;
+       int loopcount = 50; /* arbitrary max preventing infinite loop */
+
+       ndpoffset = cdc_ncm_rx_verify_nth16(ctx, skb_in);
+       if (ndpoffset < 0)
+               goto error;
+
+next_ndp:
+       nframes = cdc_ncm_rx_verify_ndp16(skb_in, ndpoffset);
+       if (nframes < 0)
+               goto error;
+
+       ndp16 = (struct usb_cdc_ncm_ndp16 *)(skb_in->data + ndpoffset);
+
+       if (le32_to_cpu(ndp16->dwSignature) != USB_CDC_NCM_NDP16_NOCRC_SIGN) {
+               pr_debug("invalid DPT16 signature <%u>\n",
+                        le32_to_cpu(ndp16->dwSignature));
+               goto err_ndp;
+       }
+       dpe16 = ndp16->dpe16;
 
        for (x = 0; x < nframes; x++, dpe16++) {
                offset = le16_to_cpu(dpe16->wDatagramIndex);
@@ -1037,7 +993,7 @@ static int cdc_ncm_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
                 */
                if ((offset == 0) || (len == 0)) {
                        if (!x)
-                               goto error; /* empty NTB */
+                               goto err_ndp; /* empty NTB */
                        break;
                }
 
@@ -1048,7 +1004,7 @@ static int cdc_ncm_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
                                        "offset[%u]=%u, length=%u, skb=%p\n",
                                        x, offset, len, skb_in);
                        if (!x)
-                               goto error;
+                               goto err_ndp;
                        break;
 
                } else {
@@ -1061,6 +1017,12 @@ static int cdc_ncm_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
                        usbnet_skb_return(dev, skb);
                }
        }
+err_ndp:
+       /* are there more NDPs to process? */
+       ndpoffset = le16_to_cpu(ndp16->wNextNdpIndex);
+       if (ndpoffset && loopcount--)
+               goto next_ndp;
+
        return 1;
 error:
        return 0;
index a28a983d465e6d434a3272a36a9ab35a7b5b3eee..534d8becbbdc779219f26c3df0481cd07171bcc7 100644 (file)
@@ -62,6 +62,7 @@
 #define USB_PRODUCT_IPAD 0x129a
 #define USB_PRODUCT_IPHONE_4_VZW 0x129c
 #define USB_PRODUCT_IPHONE_4S  0x12a0
+#define USB_PRODUCT_IPHONE_5   0x12a8
 
 #define IPHETH_USBINTF_CLASS    255
 #define IPHETH_USBINTF_SUBCLASS 253
@@ -113,6 +114,10 @@ static struct usb_device_id ipheth_table[] = {
                USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_4S,
                IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS,
                IPHETH_USBINTF_PROTO) },
+       { USB_DEVICE_AND_INTERFACE_INFO(
+               USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_5,
+               IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS,
+               IPHETH_USBINTF_PROTO) },
        { }
 };
 MODULE_DEVICE_TABLE(usb, ipheth_table);
index 6883c371c59f5a2eb416466563cad5e1fbaa5b9a..9d23ba2fe981841c23c8e05e3783e54fdf1b6847 100644 (file)
@@ -371,16 +371,57 @@ static const struct usb_device_id products[] = {
        },
 
        /* 3. Combined interface devices matching on interface number */
+       {QMI_FIXED_INTF(0x19d2, 0x0002, 1)},
+       {QMI_FIXED_INTF(0x19d2, 0x0012, 1)},
+       {QMI_FIXED_INTF(0x19d2, 0x0017, 3)},
+       {QMI_FIXED_INTF(0x19d2, 0x0021, 4)},
+       {QMI_FIXED_INTF(0x19d2, 0x0025, 1)},
+       {QMI_FIXED_INTF(0x19d2, 0x0031, 4)},
+       {QMI_FIXED_INTF(0x19d2, 0x0042, 4)},
+       {QMI_FIXED_INTF(0x19d2, 0x0049, 5)},
+       {QMI_FIXED_INTF(0x19d2, 0x0052, 4)},
        {QMI_FIXED_INTF(0x19d2, 0x0055, 1)},    /* ZTE (Vodafone) K3520-Z */
+       {QMI_FIXED_INTF(0x19d2, 0x0058, 4)},
        {QMI_FIXED_INTF(0x19d2, 0x0063, 4)},    /* ZTE (Vodafone) K3565-Z */
        {QMI_FIXED_INTF(0x19d2, 0x0104, 4)},    /* ZTE (Vodafone) K4505-Z */
+       {QMI_FIXED_INTF(0x19d2, 0x0113, 5)},
+       {QMI_FIXED_INTF(0x19d2, 0x0118, 5)},
+       {QMI_FIXED_INTF(0x19d2, 0x0121, 5)},
+       {QMI_FIXED_INTF(0x19d2, 0x0123, 4)},
+       {QMI_FIXED_INTF(0x19d2, 0x0124, 5)},
+       {QMI_FIXED_INTF(0x19d2, 0x0125, 6)},
+       {QMI_FIXED_INTF(0x19d2, 0x0126, 5)},
+       {QMI_FIXED_INTF(0x19d2, 0x0130, 1)},
+       {QMI_FIXED_INTF(0x19d2, 0x0133, 3)},
+       {QMI_FIXED_INTF(0x19d2, 0x0141, 5)},
        {QMI_FIXED_INTF(0x19d2, 0x0157, 5)},    /* ZTE MF683 */
+       {QMI_FIXED_INTF(0x19d2, 0x0158, 3)},
        {QMI_FIXED_INTF(0x19d2, 0x0167, 4)},    /* ZTE MF820D */
+       {QMI_FIXED_INTF(0x19d2, 0x0168, 4)},
+       {QMI_FIXED_INTF(0x19d2, 0x0176, 3)},
+       {QMI_FIXED_INTF(0x19d2, 0x0178, 3)},
+       {QMI_FIXED_INTF(0x19d2, 0x0191, 4)},    /* ZTE EuFi890 */
+       {QMI_FIXED_INTF(0x19d2, 0x0199, 1)},    /* ZTE MF820S */
+       {QMI_FIXED_INTF(0x19d2, 0x0200, 1)},
+       {QMI_FIXED_INTF(0x19d2, 0x0257, 3)},    /* ZTE MF821 */
        {QMI_FIXED_INTF(0x19d2, 0x0326, 4)},    /* ZTE MF821D */
        {QMI_FIXED_INTF(0x19d2, 0x1008, 4)},    /* ZTE (Vodafone) K3570-Z */
        {QMI_FIXED_INTF(0x19d2, 0x1010, 4)},    /* ZTE (Vodafone) K3571-Z */
+       {QMI_FIXED_INTF(0x19d2, 0x1012, 4)},
        {QMI_FIXED_INTF(0x19d2, 0x1018, 3)},    /* ZTE (Vodafone) K5006-Z */
+       {QMI_FIXED_INTF(0x19d2, 0x1021, 2)},
+       {QMI_FIXED_INTF(0x19d2, 0x1245, 4)},
+       {QMI_FIXED_INTF(0x19d2, 0x1247, 4)},
+       {QMI_FIXED_INTF(0x19d2, 0x1252, 4)},
+       {QMI_FIXED_INTF(0x19d2, 0x1254, 4)},
+       {QMI_FIXED_INTF(0x19d2, 0x1255, 3)},
+       {QMI_FIXED_INTF(0x19d2, 0x1255, 4)},
+       {QMI_FIXED_INTF(0x19d2, 0x1256, 4)},
+       {QMI_FIXED_INTF(0x19d2, 0x1401, 2)},
        {QMI_FIXED_INTF(0x19d2, 0x1402, 2)},    /* ZTE MF60 */
+       {QMI_FIXED_INTF(0x19d2, 0x1424, 2)},
+       {QMI_FIXED_INTF(0x19d2, 0x1425, 2)},
+       {QMI_FIXED_INTF(0x19d2, 0x1426, 2)},    /* ZTE MF91 */
        {QMI_FIXED_INTF(0x19d2, 0x2002, 4)},    /* ZTE (Vodafone) K3765-Z */
        {QMI_FIXED_INTF(0x0f3d, 0x68a2, 8)},    /* Sierra Wireless MC7700 */
        {QMI_FIXED_INTF(0x114f, 0x68a2, 8)},    /* Sierra Wireless MC7750 */
index cbf8b06253528e9e5557c31e844581d7334d7e21..62898910708a6ed7451cbbb81e9874f83cd87c8c 100644 (file)
@@ -95,7 +95,6 @@ struct skb_vnet_hdr {
                struct virtio_net_hdr hdr;
                struct virtio_net_hdr_mrg_rxbuf mhdr;
        };
-       unsigned int num_sg;
 };
 
 struct padded_vnet_hdr {
@@ -472,10 +471,11 @@ static bool try_fill_recv(struct virtnet_info *vi, gfp_t gfp)
                        err = add_recvbuf_small(vi, gfp);
 
                oom = err == -ENOMEM;
-               if (err < 0)
+               if (err)
                        break;
                ++vi->num;
-       } while (err > 0);
+       } while (vi->rvq->num_free);
+
        if (unlikely(vi->num > vi->max))
                vi->max = vi->num;
        virtqueue_kick(vi->rvq);
@@ -557,10 +557,10 @@ again:
        return received;
 }
 
-static unsigned int free_old_xmit_skbs(struct virtnet_info *vi)
+static void free_old_xmit_skbs(struct virtnet_info *vi)
 {
        struct sk_buff *skb;
-       unsigned int len, tot_sgs = 0;
+       unsigned int len;
        struct virtnet_stats *stats = this_cpu_ptr(vi->stats);
 
        while ((skb = virtqueue_get_buf(vi->svq, &len)) != NULL) {
@@ -571,16 +571,15 @@ static unsigned int free_old_xmit_skbs(struct virtnet_info *vi)
                stats->tx_packets++;
                u64_stats_update_end(&stats->tx_syncp);
 
-               tot_sgs += skb_vnet_hdr(skb)->num_sg;
                dev_kfree_skb_any(skb);
        }
-       return tot_sgs;
 }
 
 static int xmit_skb(struct virtnet_info *vi, struct sk_buff *skb)
 {
        struct skb_vnet_hdr *hdr = skb_vnet_hdr(skb);
        const unsigned char *dest = ((struct ethhdr *)skb->data)->h_dest;
+       unsigned num_sg;
 
        pr_debug("%s: xmit %p %pM\n", vi->dev->name, skb, dest);
 
@@ -619,35 +618,28 @@ static int xmit_skb(struct virtnet_info *vi, struct sk_buff *skb)
        else
                sg_set_buf(vi->tx_sg, &hdr->hdr, sizeof hdr->hdr);
 
-       hdr->num_sg = skb_to_sgvec(skb, vi->tx_sg + 1, 0, skb->len) + 1;
-       return virtqueue_add_buf(vi->svq, vi->tx_sg, hdr->num_sg,
+       num_sg = skb_to_sgvec(skb, vi->tx_sg + 1, 0, skb->len) + 1;
+       return virtqueue_add_buf(vi->svq, vi->tx_sg, num_sg,
                                 0, skb, GFP_ATOMIC);
 }
 
 static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct virtnet_info *vi = netdev_priv(dev);
-       int capacity;
+       int err;
 
        /* Free up any pending old buffers before queueing new ones. */
        free_old_xmit_skbs(vi);
 
        /* Try to transmit */
-       capacity = xmit_skb(vi, skb);
+       err = xmit_skb(vi, skb);
 
-       /* This can happen with OOM and indirect buffers. */
-       if (unlikely(capacity < 0)) {
-               if (likely(capacity == -ENOMEM)) {
-                       if (net_ratelimit())
-                               dev_warn(&dev->dev,
-                                        "TX queue failure: out of memory\n");
-               } else {
-                       dev->stats.tx_fifo_errors++;
-                       if (net_ratelimit())
-                               dev_warn(&dev->dev,
-                                        "Unexpected TX queue failure: %d\n",
-                                        capacity);
-               }
+       /* This should not happen! */
+       if (unlikely(err)) {
+               dev->stats.tx_fifo_errors++;
+               if (net_ratelimit())
+                       dev_warn(&dev->dev,
+                                "Unexpected TX queue failure: %d\n", err);
                dev->stats.tx_dropped++;
                kfree_skb(skb);
                return NETDEV_TX_OK;
@@ -660,12 +652,12 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
 
        /* Apparently nice girls don't return TX_BUSY; stop the queue
         * before it gets out of hand.  Naturally, this wastes entries. */
-       if (capacity < 2+MAX_SKB_FRAGS) {
+       if (vi->svq->num_free < 2+MAX_SKB_FRAGS) {
                netif_stop_queue(dev);
                if (unlikely(!virtqueue_enable_cb_delayed(vi->svq))) {
                        /* More just got used, free them then recheck. */
-                       capacity += free_old_xmit_skbs(vi);
-                       if (capacity >= 2+MAX_SKB_FRAGS) {
+                       free_old_xmit_skbs(vi);
+                       if (vi->svq->num_free >= 2+MAX_SKB_FRAGS) {
                                netif_start_queue(dev);
                                virtqueue_disable_cb(vi->svq);
                        }
index 3f575afd8cfcb03f283df0932f6fb33bb1495cca..0fe36d770e1fb44be3fc0a7cf44edd821edc73ce 100644 (file)
@@ -1363,7 +1363,7 @@ static int __devinit hss_init_one(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, port);
 
-       netdev_info(dev, "HSS-%i\n", port->id);
+       netdev_info(dev, "initialized\n");
        return 0;
 
 err_free_netdev:
index 3cd05a7173f6ce37945c04237d3dc493aa080647..57f7db1ac31beacc943c7d3d1960c2c1e1712adc 100644 (file)
@@ -7433,7 +7433,7 @@ static inline char *airo_translate_scan(struct net_device *dev,
                                        num_null_ies++;
                                break;
 
-                       case WLAN_EID_GENERIC:
+                       case WLAN_EID_VENDOR_SPECIFIC:
                                if (ie[1] >= 4 &&
                                    ie[2] == 0x00 &&
                                    ie[3] == 0x50 &&
index 7089f8160ad5bb7f2a7377bbc0adae68229274b2..277089963eb44acc2d99134f2920e8b4eed586c8 100644 (file)
@@ -301,7 +301,7 @@ static bool ath6kl_cfg80211_ready(struct ath6kl_vif *vif)
 
 static bool ath6kl_is_wpa_ie(const u8 *pos)
 {
-       return pos[0] == WLAN_EID_WPA && pos[1] >= 4 &&
+       return pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
                pos[2] == 0x00 && pos[3] == 0x50 &&
                pos[4] == 0xf2 && pos[5] == 0x01;
 }
@@ -3651,7 +3651,7 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)
 
        if (test_bit(ATH6KL_FW_CAPABILITY_INACTIVITY_TIMEOUT,
                     ar->fw_capabilities))
-               ar->wiphy->features = NL80211_FEATURE_INACTIVITY_TIMER;
+               ar->wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
 
        ar->wiphy->probe_resp_offload =
                NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS |
index 89bf94d4d8a1e1799715eacf684bdd6892e419c9..6f7cf49eff4d0d1dd3bd6e6b954ec5c507969a44 100644 (file)
@@ -534,107 +534,107 @@ static const u32 ar9300_2p2_baseband_core[][2] = {
 
 static const u32 ar9300Modes_high_power_tx_gain_table_2p2[][5] = {
        /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
-       {0x0000a2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352},
-       {0x0000a2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584},
-       {0x0000a2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800},
+       {0x0000a2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352},
+       {0x0000a2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584},
+       {0x0000a2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800},
        {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
        {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
        {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
        {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
        {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004},
        {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200},
-       {0x0000a510, 0x15000028, 0x15000028, 0x0f000202, 0x0f000202},
-       {0x0000a514, 0x1b00002b, 0x1b00002b, 0x12000400, 0x12000400},
-       {0x0000a518, 0x1f020028, 0x1f020028, 0x16000402, 0x16000402},
-       {0x0000a51c, 0x2502002b, 0x2502002b, 0x19000404, 0x19000404},
-       {0x0000a520, 0x2a04002a, 0x2a04002a, 0x1c000603, 0x1c000603},
-       {0x0000a524, 0x2e06002a, 0x2e06002a, 0x21000a02, 0x21000a02},
-       {0x0000a528, 0x3302202d, 0x3302202d, 0x25000a04, 0x25000a04},
-       {0x0000a52c, 0x3804202c, 0x3804202c, 0x28000a20, 0x28000a20},
-       {0x0000a530, 0x3c06202c, 0x3c06202c, 0x2c000e20, 0x2c000e20},
-       {0x0000a534, 0x4108202d, 0x4108202d, 0x30000e22, 0x30000e22},
-       {0x0000a538, 0x4506402d, 0x4506402d, 0x34000e24, 0x34000e24},
-       {0x0000a53c, 0x4906222d, 0x4906222d, 0x38001640, 0x38001640},
-       {0x0000a540, 0x4d062231, 0x4d062231, 0x3c001660, 0x3c001660},
-       {0x0000a544, 0x50082231, 0x50082231, 0x3f001861, 0x3f001861},
-       {0x0000a548, 0x5608422e, 0x5608422e, 0x43001a81, 0x43001a81},
-       {0x0000a54c, 0x5a08442e, 0x5a08442e, 0x47001a83, 0x47001a83},
-       {0x0000a550, 0x5e0a4431, 0x5e0a4431, 0x4a001c84, 0x4a001c84},
-       {0x0000a554, 0x640a4432, 0x640a4432, 0x4e001ce3, 0x4e001ce3},
-       {0x0000a558, 0x680a4434, 0x680a4434, 0x52001ce5, 0x52001ce5},
-       {0x0000a55c, 0x6c0a6434, 0x6c0a6434, 0x56001ce9, 0x56001ce9},
-       {0x0000a560, 0x6f0a6633, 0x6f0a6633, 0x5a001ceb, 0x5a001ceb},
-       {0x0000a564, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
-       {0x0000a568, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
-       {0x0000a56c, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
-       {0x0000a570, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
-       {0x0000a574, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
-       {0x0000a578, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
-       {0x0000a57c, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
+       {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202},
+       {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400},
+       {0x0000a518, 0x21002220, 0x21002220, 0x16000402, 0x16000402},
+       {0x0000a51c, 0x27002223, 0x27002223, 0x19000404, 0x19000404},
+       {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603},
+       {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02},
+       {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04},
+       {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20},
+       {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20},
+       {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22},
+       {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24},
+       {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640},
+       {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660},
+       {0x0000a544, 0x52022470, 0x52022470, 0x3f001861, 0x3f001861},
+       {0x0000a548, 0x55022490, 0x55022490, 0x43001a81, 0x43001a81},
+       {0x0000a54c, 0x59022492, 0x59022492, 0x47001a83, 0x47001a83},
+       {0x0000a550, 0x5d022692, 0x5d022692, 0x4a001c84, 0x4a001c84},
+       {0x0000a554, 0x61022892, 0x61022892, 0x4e001ce3, 0x4e001ce3},
+       {0x0000a558, 0x65024890, 0x65024890, 0x52001ce5, 0x52001ce5},
+       {0x0000a55c, 0x69024892, 0x69024892, 0x56001ce9, 0x56001ce9},
+       {0x0000a560, 0x6e024c92, 0x6e024c92, 0x5a001ceb, 0x5a001ceb},
+       {0x0000a564, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+       {0x0000a568, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+       {0x0000a56c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+       {0x0000a570, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+       {0x0000a574, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+       {0x0000a578, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+       {0x0000a57c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
        {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000},
        {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002},
        {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004},
        {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200},
-       {0x0000a590, 0x15800028, 0x15800028, 0x0f800202, 0x0f800202},
-       {0x0000a594, 0x1b80002b, 0x1b80002b, 0x12800400, 0x12800400},
-       {0x0000a598, 0x1f820028, 0x1f820028, 0x16800402, 0x16800402},
-       {0x0000a59c, 0x2582002b, 0x2582002b, 0x19800404, 0x19800404},
-       {0x0000a5a0, 0x2a84002a, 0x2a84002a, 0x1c800603, 0x1c800603},
-       {0x0000a5a4, 0x2e86002a, 0x2e86002a, 0x21800a02, 0x21800a02},
-       {0x0000a5a8, 0x3382202d, 0x3382202d, 0x25800a04, 0x25800a04},
-       {0x0000a5ac, 0x3884202c, 0x3884202c, 0x28800a20, 0x28800a20},
-       {0x0000a5b0, 0x3c86202c, 0x3c86202c, 0x2c800e20, 0x2c800e20},
-       {0x0000a5b4, 0x4188202d, 0x4188202d, 0x30800e22, 0x30800e22},
-       {0x0000a5b8, 0x4586402d, 0x4586402d, 0x34800e24, 0x34800e24},
-       {0x0000a5bc, 0x4986222d, 0x4986222d, 0x38801640, 0x38801640},
-       {0x0000a5c0, 0x4d862231, 0x4d862231, 0x3c801660, 0x3c801660},
-       {0x0000a5c4, 0x50882231, 0x50882231, 0x3f801861, 0x3f801861},
-       {0x0000a5c8, 0x5688422e, 0x5688422e, 0x43801a81, 0x43801a81},
-       {0x0000a5cc, 0x5a88442e, 0x5a88442e, 0x47801a83, 0x47801a83},
-       {0x0000a5d0, 0x5e8a4431, 0x5e8a4431, 0x4a801c84, 0x4a801c84},
-       {0x0000a5d4, 0x648a4432, 0x648a4432, 0x4e801ce3, 0x4e801ce3},
-       {0x0000a5d8, 0x688a4434, 0x688a4434, 0x52801ce5, 0x52801ce5},
-       {0x0000a5dc, 0x6c8a6434, 0x6c8a6434, 0x56801ce9, 0x56801ce9},
-       {0x0000a5e0, 0x6f8a6633, 0x6f8a6633, 0x5a801ceb, 0x5a801ceb},
-       {0x0000a5e4, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
-       {0x0000a5e8, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
-       {0x0000a5ec, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
-       {0x0000a5f0, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
-       {0x0000a5f4, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
-       {0x0000a5f8, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
-       {0x0000a5fc, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
+       {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202},
+       {0x0000a594, 0x1c800223, 0x1c800223, 0x12800400, 0x12800400},
+       {0x0000a598, 0x21802220, 0x21802220, 0x16800402, 0x16800402},
+       {0x0000a59c, 0x27802223, 0x27802223, 0x19800404, 0x19800404},
+       {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1c800603, 0x1c800603},
+       {0x0000a5a4, 0x2f822222, 0x2f822222, 0x21800a02, 0x21800a02},
+       {0x0000a5a8, 0x34822225, 0x34822225, 0x25800a04, 0x25800a04},
+       {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x28800a20, 0x28800a20},
+       {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2c800e20, 0x2c800e20},
+       {0x0000a5b4, 0x4282242a, 0x4282242a, 0x30800e22, 0x30800e22},
+       {0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24},
+       {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640},
+       {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660},
+       {0x0000a5c4, 0x52822470, 0x52822470, 0x3f801861, 0x3f801861},
+       {0x0000a5c8, 0x55822490, 0x55822490, 0x43801a81, 0x43801a81},
+       {0x0000a5cc, 0x59822492, 0x59822492, 0x47801a83, 0x47801a83},
+       {0x0000a5d0, 0x5d822692, 0x5d822692, 0x4a801c84, 0x4a801c84},
+       {0x0000a5d4, 0x61822892, 0x61822892, 0x4e801ce3, 0x4e801ce3},
+       {0x0000a5d8, 0x65824890, 0x65824890, 0x52801ce5, 0x52801ce5},
+       {0x0000a5dc, 0x69824892, 0x69824892, 0x56801ce9, 0x56801ce9},
+       {0x0000a5e0, 0x6e824c92, 0x6e824c92, 0x5a801ceb, 0x5a801ceb},
+       {0x0000a5e4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+       {0x0000a5e8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+       {0x0000a5ec, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+       {0x0000a5f0, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+       {0x0000a5f4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+       {0x0000a5f8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+       {0x0000a5fc, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
        {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
        {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a608, 0x01804601, 0x01804601, 0x00000000, 0x00000000},
-       {0x0000a60c, 0x01804601, 0x01804601, 0x00000000, 0x00000000},
-       {0x0000a610, 0x01804601, 0x01804601, 0x00000000, 0x00000000},
-       {0x0000a614, 0x01804601, 0x01804601, 0x01404000, 0x01404000},
-       {0x0000a618, 0x01804601, 0x01804601, 0x01404501, 0x01404501},
-       {0x0000a61c, 0x01804601, 0x01804601, 0x02008501, 0x02008501},
-       {0x0000a620, 0x03408d02, 0x03408d02, 0x0280ca03, 0x0280ca03},
-       {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04},
-       {0x0000a628, 0x03410d04, 0x03410d04, 0x04014c04, 0x04014c04},
-       {0x0000a62c, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
-       {0x0000a630, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
-       {0x0000a634, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
-       {0x0000a638, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
-       {0x0000a63c, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
-       {0x0000b2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352},
-       {0x0000b2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584},
-       {0x0000b2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800},
+       {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a614, 0x02004000, 0x02004000, 0x01404000, 0x01404000},
+       {0x0000a618, 0x02004801, 0x02004801, 0x01404501, 0x01404501},
+       {0x0000a61c, 0x02808a02, 0x02808a02, 0x02008501, 0x02008501},
+       {0x0000a620, 0x0380ce03, 0x0380ce03, 0x0280ca03, 0x0280ca03},
+       {0x0000a624, 0x04411104, 0x04411104, 0x03010c04, 0x03010c04},
+       {0x0000a628, 0x04411104, 0x04411104, 0x04014c04, 0x04014c04},
+       {0x0000a62c, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
+       {0x0000a630, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
+       {0x0000a634, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
+       {0x0000a638, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
+       {0x0000a63c, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
+       {0x0000b2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352},
+       {0x0000b2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584},
+       {0x0000b2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800},
        {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
-       {0x0000c2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352},
-       {0x0000c2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584},
-       {0x0000c2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800},
+       {0x0000c2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352},
+       {0x0000c2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584},
+       {0x0000c2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800},
        {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
        {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
-       {0x00016048, 0x61200001, 0x61200001, 0x66480001, 0x66480001},
+       {0x00016048, 0x66480001, 0x66480001, 0x66480001, 0x66480001},
        {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
        {0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
-       {0x00016448, 0x61200001, 0x61200001, 0x66480001, 0x66480001},
+       {0x00016448, 0x66480001, 0x66480001, 0x66480001, 0x66480001},
        {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
        {0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
-       {0x00016848, 0x61200001, 0x61200001, 0x66480001, 0x66480001},
+       {0x00016848, 0x66480001, 0x66480001, 0x66480001, 0x66480001},
        {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
 };
 
index 5bbe5057ba18ae35408c2aa78dfbdf4d5cefdf0f..189aeb22f5551b3e3e9ae9ea64e500be296b8a99 100644 (file)
@@ -2989,7 +2989,7 @@ static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah,
        case EEP_PAPRD:
                if (AR_SREV_9462(ah))
                        return false;
-               if (!ah->config.enable_paprd);
+               if (!ah->config.enable_paprd)
                        return false;
                return !!(pBase->featureEnable & BIT(5));
        case EEP_CHAIN_MASK_REDUCE:
index dfe6a4707fd22684a5994de3b6c4d9dcadd456f2..77c2c16b69610e6186497a0e2cbfc6fb8ca12aa8 100644 (file)
@@ -437,6 +437,7 @@ void ath9k_set_beacon(struct ath_softc *sc);
 #define ATH_LONG_CALINTERVAL_INT  1000    /* 1000 ms */
 #define ATH_LONG_CALINTERVAL      30000   /* 30 seconds */
 #define ATH_RESTART_CALINTERVAL   1200000 /* 20 minutes */
+#define ATH_ANI_MAX_SKIP_COUNT  10
 
 #define ATH_PAPRD_TIMEOUT      100 /* msecs */
 #define ATH_PLL_WORK_INTERVAL   100
@@ -642,6 +643,7 @@ enum sc_op_flags {
 #define PS_WAIT_FOR_PSPOLL_DATA   BIT(2)
 #define PS_WAIT_FOR_TX_ACK        BIT(3)
 #define PS_BEACON_SYNC            BIT(4)
+#define PS_WAIT_FOR_ANI           BIT(5)
 
 struct ath_rate_table;
 
index d9ed141a053e6a885fcdf031866f9daa1e5918d2..bf4fb7db15eb20e14ea4e2aa68c7b18ae01caf2a 100644 (file)
@@ -187,6 +187,25 @@ static void ath9k_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer)
        }
 }
 
+static void ath_mci_ftp_adjust(struct ath_softc *sc)
+{
+       struct ath_btcoex *btcoex = &sc->btcoex;
+       struct ath_mci_profile *mci = &btcoex->mci;
+       struct ath_hw *ah = sc->sc_ah;
+
+       btcoex->bt_wait_time += btcoex->btcoex_period;
+       if (btcoex->bt_wait_time > ATH_BTCOEX_RX_WAIT_TIME) {
+               if (ar9003_mci_state(ah, MCI_STATE_NEED_FTP_STOMP) &&
+                   (mci->num_pan || mci->num_other_acl))
+                       ah->btcoex_hw.mci.stomp_ftp =
+                               (sc->rx.num_pkts < ATH_BTCOEX_STOMP_FTP_THRESH);
+               else
+                       ah->btcoex_hw.mci.stomp_ftp = false;
+               btcoex->bt_wait_time = 0;
+               sc->rx.num_pkts = 0;
+       }
+}
+
 /*
  * This is the master bt coex timer which runs for every
  * 45ms, bt traffic will be given priority during 55% of this
@@ -197,9 +216,8 @@ static void ath_btcoex_period_timer(unsigned long data)
        struct ath_softc *sc = (struct ath_softc *) data;
        struct ath_hw *ah = sc->sc_ah;
        struct ath_btcoex *btcoex = &sc->btcoex;
-       struct ath_mci_profile *mci = &btcoex->mci;
+       enum ath_stomp_type stomp_type;
        u32 timer_period;
-       bool is_btscan;
        unsigned long flags;
 
        spin_lock_irqsave(&sc->sc_pm_lock, flags);
@@ -210,28 +228,28 @@ static void ath_btcoex_period_timer(unsigned long data)
        spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
 
        ath9k_ps_wakeup(sc);
+
        if (!(ah->caps.hw_caps & ATH9K_HW_CAP_MCI))
                ath_detect_bt_priority(sc);
-       is_btscan = test_bit(BT_OP_SCAN, &btcoex->op_flags);
 
-       btcoex->bt_wait_time += btcoex->btcoex_period;
-       if (btcoex->bt_wait_time > ATH_BTCOEX_RX_WAIT_TIME) {
-               if (ar9003_mci_state(ah, MCI_STATE_NEED_FTP_STOMP) &&
-                   (mci->num_pan || mci->num_other_acl))
-                       ah->btcoex_hw.mci.stomp_ftp =
-                               (sc->rx.num_pkts < ATH_BTCOEX_STOMP_FTP_THRESH);
-               else
-                       ah->btcoex_hw.mci.stomp_ftp = false;
-               btcoex->bt_wait_time = 0;
-               sc->rx.num_pkts = 0;
-       }
+       if (ah->caps.hw_caps & ATH9K_HW_CAP_MCI)
+               ath_mci_ftp_adjust(sc);
 
        spin_lock_bh(&btcoex->btcoex_lock);
 
-       ath9k_hw_btcoex_bt_stomp(ah, is_btscan ? ATH_BTCOEX_STOMP_ALL :
-                             btcoex->bt_stomp_type);
+       stomp_type = btcoex->bt_stomp_type;
+       timer_period = btcoex->btcoex_no_stomp;
 
+       if (!(ah->caps.hw_caps & ATH9K_HW_CAP_MCI)) {
+               if (test_bit(BT_OP_SCAN, &btcoex->op_flags)) {
+                       stomp_type = ATH_BTCOEX_STOMP_ALL;
+                       timer_period = btcoex->btscan_no_stomp;
+               }
+       }
+
+       ath9k_hw_btcoex_bt_stomp(ah, stomp_type);
        ath9k_hw_btcoex_enable(ah);
+
        spin_unlock_bh(&btcoex->btcoex_lock);
 
        /*
@@ -243,17 +261,16 @@ static void ath_btcoex_period_timer(unsigned long data)
                if (btcoex->hw_timer_enabled)
                        ath9k_gen_timer_stop(ah, btcoex->no_stomp_timer);
 
-               timer_period = is_btscan ? btcoex->btscan_no_stomp :
-                                          btcoex->btcoex_no_stomp;
                ath9k_gen_timer_start(ah, btcoex->no_stomp_timer, timer_period,
                                      timer_period * 10);
                btcoex->hw_timer_enabled = true;
        }
 
        ath9k_ps_restore(sc);
+
 skip_hw_wakeup:
-       timer_period = btcoex->btcoex_period;
-       mod_timer(&btcoex->period_timer, jiffies + msecs_to_jiffies(timer_period));
+       mod_timer(&btcoex->period_timer,
+                 jiffies + msecs_to_jiffies(btcoex->btcoex_period));
 }
 
 /*
@@ -273,7 +290,8 @@ static void ath_btcoex_no_stomp_timer(void *arg)
        spin_lock_bh(&btcoex->btcoex_lock);
 
        if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW ||
-           test_bit(BT_OP_SCAN, &btcoex->op_flags))
+           (!(ah->caps.hw_caps & ATH9K_HW_CAP_MCI) &&
+            test_bit(BT_OP_SCAN, &btcoex->op_flags)))
                ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_NONE);
         else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL)
                ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_LOW);
index 924c4616c3d990dc7f03e46ed299bdc94396d765..f5dda84176c3d4ae8277c069df06fa3bbc11922d 100644 (file)
@@ -38,6 +38,7 @@ static struct usb_device_id ath9k_hif_usb_ids[] = {
        { USB_DEVICE(0x04CA, 0x4605) }, /* Liteon */
        { USB_DEVICE(0x040D, 0x3801) }, /* VIA */
        { USB_DEVICE(0x0cf3, 0xb003) }, /* Ubiquiti WifiStation Ext */
+       { USB_DEVICE(0x0cf3, 0xb002) }, /* Ubiquiti WifiStation */
        { USB_DEVICE(0x057c, 0x8403) }, /* AVM FRITZ!WLAN 11N v2 USB */
 
        { USB_DEVICE(0x0cf3, 0x7015),
index dbc1b7a4cbfdc0eeca59efa19f4d52e7e09044ec..1d4f5f1fdd8d78d52038e238dcc3ace6fb3f0390 100644 (file)
@@ -834,6 +834,7 @@ struct ath_hw {
        int coarse_low[5];
        int firpwr[5];
        enum ath9k_ani_cmd ani_function;
+       u32 ani_skip_count;
 
 #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
        struct ath_btcoex_hw btcoex_hw;
index 7b88b9c39ccddc4ef4e3aeafb53e437d0f35a0ce..223b9693527e0c3da4e4e111d89f4d1c2481fd36 100644 (file)
@@ -350,8 +350,18 @@ void ath_ani_calibrate(unsigned long data)
                ATH_AP_SHORT_CALINTERVAL : ATH_STA_SHORT_CALINTERVAL;
 
        /* Only calibrate if awake */
-       if (sc->sc_ah->power_mode != ATH9K_PM_AWAKE)
+       if (sc->sc_ah->power_mode != ATH9K_PM_AWAKE) {
+               if (++ah->ani_skip_count >= ATH_ANI_MAX_SKIP_COUNT) {
+                       spin_lock_irqsave(&sc->sc_pm_lock, flags);
+                       sc->ps_flags |= PS_WAIT_FOR_ANI;
+                       spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
+               }
                goto set_timer;
+       }
+       ah->ani_skip_count = 0;
+       spin_lock_irqsave(&sc->sc_pm_lock, flags);
+       sc->ps_flags &= ~PS_WAIT_FOR_ANI;
+       spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
 
        ath9k_ps_wakeup(sc);
 
index dd45edfa6baec25304af0a07ccea22f1c0910f29..2da62be081f7b610a8233d12f54991cfe76a4c11 100644 (file)
@@ -131,7 +131,8 @@ void ath9k_ps_restore(struct ath_softc *sc)
                   !(sc->ps_flags & (PS_WAIT_FOR_BEACON |
                                     PS_WAIT_FOR_CAB |
                                     PS_WAIT_FOR_PSPOLL_DATA |
-                                    PS_WAIT_FOR_TX_ACK))) {
+                                    PS_WAIT_FOR_TX_ACK |
+                                    PS_WAIT_FOR_ANI))) {
                mode = ATH9K_PM_NETWORK_SLEEP;
                if (ath9k_hw_btcoex_is_enabled(sc->sc_ah))
                        ath9k_btcoex_stop_gen_timer(sc);
index a0b72307854799b81c36649d916da2940be90ad6..9cd93f1d8bef358a7c46f6a6c7d2b6e6696295b6 100644 (file)
@@ -164,9 +164,6 @@ void carl9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len)
        struct carl9170_rsp *cmd = buf;
        struct ieee80211_vif *vif;
 
-       if (carl9170_check_sequence(ar, cmd->hdr.seq))
-               return;
-
        if ((cmd->hdr.cmd & CARL9170_RSP_FLAG) != CARL9170_RSP_FLAG) {
                if (!(cmd->hdr.cmd & CARL9170_CMD_ASYNC_FLAG))
                        carl9170_cmd_callback(ar, len, buf);
@@ -820,6 +817,9 @@ static void carl9170_rx_untie_cmds(struct ar9170 *ar, const u8 *respbuf,
                if (unlikely(i > resplen))
                        break;
 
+               if (carl9170_check_sequence(ar, cmd->hdr.seq))
+                       break;
+
                carl9170_handle_command_response(ar, cmd, cmd->hdr.len + 4);
        }
 
index 888152ce3eca98193b01147a827b4daee59c7ff3..307bc0ddff99091a1f224bb236013a1a90b5fa76 100644 (file)
@@ -295,6 +295,13 @@ static void carl9170_usb_rx_irq_complete(struct urb *urb)
                goto resubmit;
        }
 
+       /*
+        * While the carl9170 firmware does not use this EP, the
+        * firmware loader in the EEPROM unfortunately does.
+        * Therefore we need to be ready to handle out-of-band
+        * responses and traps in case the firmware crashed and
+        * the loader took over again.
+        */
        carl9170_handle_command_response(ar, urb->transfer_buffer,
                                         urb->actual_length);
 
index 19befb33107348e949cf958c05ee2683f9ba28d9..39e8a590d7fc86feb3dd70cb55a21d7a6c63e335 100644 (file)
@@ -20,8 +20,8 @@
 #include "ath.h"
 #include "reg.h"
 
-#define REG_READ       (common->ops->read)
-#define REG_WRITE      (common->ops->write)
+#define REG_READ                       (common->ops->read)
+#define REG_WRITE(_ah, _reg, _val)     (common->ops->write)(_ah, _val, _reg)
 
 /**
  * ath_hw_set_bssid_mask - filter out bssids we listen
@@ -119,8 +119,8 @@ void ath_hw_setbssidmask(struct ath_common *common)
 {
        void *ah = common->ah;
 
-       REG_WRITE(ah, get_unaligned_le32(common->bssidmask), AR_BSSMSKL);
-       REG_WRITE(ah, get_unaligned_le16(common->bssidmask + 4), AR_BSSMSKU);
+       REG_WRITE(ah, AR_BSSMSKL, get_unaligned_le32(common->bssidmask));
+       REG_WRITE(ah, AR_BSSMSKU, get_unaligned_le16(common->bssidmask + 4));
 }
 EXPORT_SYMBOL(ath_hw_setbssidmask);
 
@@ -139,7 +139,7 @@ void ath_hw_cycle_counters_update(struct ath_common *common)
        void *ah = common->ah;
 
        /* freeze */
-       REG_WRITE(ah, AR_MIBC_FMC, AR_MIBC);
+       REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC);
 
        /* read */
        cycles = REG_READ(ah, AR_CCCNT);
@@ -148,13 +148,13 @@ void ath_hw_cycle_counters_update(struct ath_common *common)
        tx = REG_READ(ah, AR_TFCNT);
 
        /* clear */
-       REG_WRITE(ah, 0, AR_CCCNT);
-       REG_WRITE(ah, 0, AR_RFCNT);
-       REG_WRITE(ah, 0, AR_RCCNT);
-       REG_WRITE(ah, 0, AR_TFCNT);
+       REG_WRITE(ah, AR_CCCNT, 0);
+       REG_WRITE(ah, AR_RFCNT, 0);
+       REG_WRITE(ah, AR_RCCNT, 0);
+       REG_WRITE(ah, AR_TFCNT, 0);
 
        /* unfreeze */
-       REG_WRITE(ah, 0, AR_MIBC);
+       REG_WRITE(ah, AR_MIBC, 0);
 
        /* update all cycle counters here */
        common->cc_ani.cycles += cycles;
index 73730e94e0ac79fdbdf257f1cf969179e1c62a46..ddd6a4f780975d80256fadb5f421cd37cb846d6c 100644 (file)
@@ -4652,7 +4652,7 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
        switch (dev->dev->bus_type) {
 #ifdef CONFIG_B43_BCMA
        case B43_BUS_BCMA:
-               bcma_core_pci_irq_ctl(&dev->dev->bdev->bus->drv_pci,
+               bcma_core_pci_irq_ctl(&dev->dev->bdev->bus->drv_pci[0],
                                      dev->dev->bdev, true);
                break;
 #endif
@@ -5404,6 +5404,8 @@ static void b43_bcma_remove(struct bcma_device *core)
        cancel_work_sync(&wldev->restart_work);
 
        B43_WARN_ON(!wl);
+       if (!wldev->fw.ucode.data)
+               return;                 /* NULL if firmware never loaded */
        if (wl->current_dev == wldev && wl->hw_registred) {
                b43_leds_stop(wldev);
                ieee80211_unregister_hw(wl->hw);
@@ -5478,6 +5480,8 @@ static void b43_ssb_remove(struct ssb_device *sdev)
        cancel_work_sync(&wldev->restart_work);
 
        B43_WARN_ON(!wl);
+       if (!wldev->fw.ucode.data)
+               return;                 /* NULL if firmware never loaded */
        if (wl->current_dev == wldev && wl->hw_registred) {
                b43_leds_stop(wldev);
                ieee80211_unregister_hw(wl->hw);
index 17e7ae73e0089600780a54a35ab0e7c75dc08a87..0510960ad5ff1d99b4e258f30d1673e2a70032ea 100644 (file)
@@ -702,10 +702,6 @@ extern char *brcmf_ifname(struct brcmf_pub *drvr, int idx);
 extern int brcmf_proto_cdc_query_dcmd(struct brcmf_pub *drvr, int ifidx,
                                       uint cmd, void *buf, uint len);
 
-#ifdef DEBUG
-extern int brcmf_write_to_file(struct brcmf_pub *drvr, const u8 *buf, int size);
-#endif                         /* DEBUG */
-
 extern int brcmf_ifname2idx(struct brcmf_pub *drvr, char *name);
 extern int brcmf_c_host_event(struct brcmf_pub *drvr, int *idx,
                              void *pktdata, struct brcmf_event_msg *,
index 15c5db5752d199d2ec4c78913c44a5713dfb78a8..a081e683743b37e9044f7001d519747522af2614 100644 (file)
@@ -106,7 +106,7 @@ brcmf_c_mkiovar_bsscfg(char *name, char *data, uint datalen,
        namelen = (u32) strlen(name) + 1; /* lengh of iovar  name + null */
        iolen = prefixlen + namelen + sizeof(bssidx_le) + datalen;
 
-       if (buflen < 0 || iolen > (u32)buflen) {
+       if ((u32)buflen < iolen) {
                brcmf_dbg(ERROR, "buffer is too short\n");
                return 0;
        }
index d7c76ce9d8cb3d74dccb79c863e5db1efd9a7446..c462263e0411ab2f4e007e7750eb3451f7da01c8 100644 (file)
@@ -1163,42 +1163,6 @@ int brcmf_netdev_wait_pend8021x(struct net_device *ndev)
        return pend;
 }
 
-#ifdef DEBUG
-int brcmf_write_to_file(struct brcmf_pub *drvr, const u8 *buf, int size)
-{
-       int ret = 0;
-       struct file *fp;
-       mm_segment_t old_fs;
-       loff_t pos = 0;
-
-       /* change to KERNEL_DS address limit */
-       old_fs = get_fs();
-       set_fs(KERNEL_DS);
-
-       /* open file to write */
-       fp = filp_open("/tmp/mem_dump", O_WRONLY | O_CREAT, 0640);
-       if (!fp) {
-               brcmf_dbg(ERROR, "open file error\n");
-               ret = -1;
-               goto exit;
-       }
-
-       /* Write buf to file */
-       fp->f_op->write(fp, (char __user *)buf, size, &pos);
-
-exit:
-       /* free buf before return */
-       kfree(buf);
-       /* close file before return */
-       if (fp)
-               filp_close(fp, NULL);
-       /* restore previous address limit */
-       set_fs(old_fs);
-
-       return ret;
-}
-#endif                         /* DEBUG */
-
 static void brcmf_driver_init(struct work_struct *work)
 {
        brcmf_debugfs_init();
index a2b4b1e71017230b6d7ab262f52b45c4fa353bd7..7a6dfdc67b6cc5ed11ce8e5281cf45c5fa81818a 100644 (file)
@@ -1339,7 +1339,7 @@ static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo,
        }
 
        ret = brcmf_bus_start(dev);
-       if (ret == -ENOLINK) {
+       if (ret) {
                brcmf_dbg(ERROR, "dongle is not responding\n");
                brcmf_detach(dev);
                goto fail;
index c1abaa6db59ec97fc9da4a0419ba81ea922cfb42..27e07a5e04692063bc020c07a1cb6a0616c99b24 100644 (file)
@@ -2674,12 +2674,12 @@ brcmf_tlv_has_ie(u8 *ie, u8 **tlvs, u32 *tlvs_len,
        return false;
 }
 
-struct brcmf_vs_tlv *
+static struct brcmf_vs_tlv *
 brcmf_find_wpaie(u8 *parse, u32 len)
 {
        struct brcmf_tlv *ie;
 
-       while ((ie = brcmf_parse_tlvs(parse, len, WLAN_EID_WPA))) {
+       while ((ie = brcmf_parse_tlvs(parse, len, WLAN_EID_VENDOR_SPECIFIC))) {
                if (brcmf_tlv_has_ie((u8 *)ie, &parse, &len,
                                     WPA_OUI, TLV_OUI_LEN, WPA_OUI_TYPE))
                        return (struct brcmf_vs_tlv *)ie;
@@ -3569,7 +3569,7 @@ brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy,
 
        if (!request || !request->n_ssids || !request->n_match_sets) {
                WL_ERR("Invalid sched scan req!! n_ssids:%d\n",
-                      request->n_ssids);
+                      request ? request->n_ssids : 0);
                return -EINVAL;
        }
 
@@ -3963,7 +3963,7 @@ brcmf_vndr_ie(u8 *iebuf, s32 pktflag, u8 *ie_ptr, u32 ie_len, s8 *add_del_cmd)
        return ie_len + VNDR_IE_HDR_SIZE;
 }
 
-s32
+static s32
 brcmf_set_management_ie(struct brcmf_cfg80211_info *cfg,
                        struct net_device *ndev, s32 bssidx, s32 pktflag,
                        u8 *vndr_ie_buf, u32 vndr_ie_len)
@@ -3972,8 +3972,8 @@ brcmf_set_management_ie(struct brcmf_cfg80211_info *cfg,
        u8  *iovar_ie_buf;
        u8  *curr_ie_buf;
        u8  *mgmt_ie_buf = NULL;
-       u32 mgmt_ie_buf_len = 0;
-       u32 *mgmt_ie_len = 0;
+       int mgmt_ie_buf_len;
+       u32 *mgmt_ie_len;
        u32 del_add_ie_buf_len = 0;
        u32 total_ie_buf_len = 0;
        u32 parsed_ie_buf_len = 0;
@@ -3982,7 +3982,7 @@ brcmf_set_management_ie(struct brcmf_cfg80211_info *cfg,
        struct parsed_vndr_ie_info *vndrie_info;
        s32 i;
        u8 *ptr;
-       u32 remained_buf_len;
+       int remained_buf_len;
 
        WL_TRACE("bssidx %d, pktflag : 0x%02X\n", bssidx, pktflag);
        iovar_ie_buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
@@ -3995,8 +3995,7 @@ brcmf_set_management_ie(struct brcmf_cfg80211_info *cfg,
                case VNDR_IE_PRBRSP_FLAG:
                        mgmt_ie_buf = cfg->ap_info->probe_res_ie;
                        mgmt_ie_len = &cfg->ap_info->probe_res_ie_len;
-                       mgmt_ie_buf_len =
-                               sizeof(cfg->ap_info->probe_res_ie);
+                       mgmt_ie_buf_len = sizeof(cfg->ap_info->probe_res_ie);
                        break;
                case VNDR_IE_BEACON_FLAG:
                        mgmt_ie_buf = cfg->ap_info->beacon_ie;
@@ -4606,12 +4605,13 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg,
        struct brcmf_cfg80211_profile *profile = cfg->profile;
        struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg);
        struct wiphy *wiphy = cfg_to_wiphy(cfg);
-       struct brcmf_channel_info_le channel_le;
-       struct ieee80211_channel *notify_channel;
+       struct ieee80211_channel *notify_channel = NULL;
        struct ieee80211_supported_band *band;
+       struct brcmf_bss_info_le *bi;
        u32 freq;
        s32 err = 0;
        u32 target_channel;
+       u8 *buf;
 
        WL_TRACE("Enter\n");
 
@@ -4619,11 +4619,22 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg,
        memcpy(profile->bssid, e->addr, ETH_ALEN);
        brcmf_update_bss_info(cfg);
 
-       brcmf_exec_dcmd(ndev, BRCMF_C_GET_CHANNEL, &channel_le,
-                       sizeof(channel_le));
+       buf = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);
+       if (buf == NULL) {
+               err = -ENOMEM;
+               goto done;
+       }
 
-       target_channel = le32_to_cpu(channel_le.target_channel);
-       WL_CONN("Roamed to channel %d\n", target_channel);
+       /* data sent to dongle has to be little endian */
+       *(__le32 *)buf = cpu_to_le32(WL_BSS_INFO_MAX);
+       err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_BSS_INFO, buf, WL_BSS_INFO_MAX);
+
+       if (err)
+               goto done;
+
+       bi = (struct brcmf_bss_info_le *)(buf + 4);
+       target_channel = bi->ctl_ch ? bi->ctl_ch :
+                                     CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec));
 
        if (target_channel <= CH_MAX_2G_CHANNEL)
                band = wiphy->bands[IEEE80211_BAND_2GHZ];
@@ -4633,6 +4644,8 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg,
        freq = ieee80211_channel_to_frequency(target_channel, band->band);
        notify_channel = ieee80211_get_channel(wiphy, freq);
 
+done:
+       kfree(buf);
        cfg80211_roamed(ndev, notify_channel, (u8 *)profile->bssid,
                        conn_info->req_ie, conn_info->req_ie_len,
                        conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL);
@@ -5186,41 +5199,6 @@ brcmf_cfg80211_event(struct net_device *ndev,
                schedule_work(&cfg->event_work);
 }
 
-static s32 brcmf_dongle_mode(struct net_device *ndev, s32 iftype)
-{
-       s32 infra = 0;
-       s32 err = 0;
-
-       switch (iftype) {
-       case NL80211_IFTYPE_MONITOR:
-       case NL80211_IFTYPE_WDS:
-               WL_ERR("type (%d) : currently we do not support this mode\n",
-                      iftype);
-               err = -EINVAL;
-               return err;
-       case NL80211_IFTYPE_ADHOC:
-               infra = 0;
-               break;
-       case NL80211_IFTYPE_STATION:
-               infra = 1;
-               break;
-       case NL80211_IFTYPE_AP:
-               infra = 1;
-               break;
-       default:
-               err = -EINVAL;
-               WL_ERR("invalid type (%d)\n", iftype);
-               return err;
-       }
-       err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_INFRA, &infra);
-       if (err) {
-               WL_ERR("WLC_SET_INFRA error (%d)\n", err);
-               return err;
-       }
-
-       return 0;
-}
-
 static s32 brcmf_dongle_eventmsg(struct net_device *ndev)
 {
        /* Room for "event_msgs" + '\0' + bitvec */
@@ -5439,7 +5417,8 @@ static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg)
                                WL_BEACON_TIMEOUT);
        if (err)
                goto default_conf_out;
-       err = brcmf_dongle_mode(ndev, wdev->iftype);
+       err = brcmf_cfg80211_change_iface(wdev->wiphy, ndev, wdev->iftype,
+                                         NULL, NULL);
        if (err && err != -EINPROGRESS)
                goto default_conf_out;
        err = brcmf_dongle_probecap(cfg);
index b89f1272b93f506f24f8cf9e262f9b7c489c6180..de96290f5ccdc6dc9fbd63ac22c7c2f8334757c0 100644 (file)
@@ -692,7 +692,7 @@ void ai_pci_up(struct si_pub *sih)
        sii = container_of(sih, struct si_info, pub);
 
        if (sii->icbus->hosttype == BCMA_HOSTTYPE_PCI)
-               bcma_core_pci_extend_L1timer(&sii->icbus->drv_pci, true);
+               bcma_core_pci_extend_L1timer(&sii->icbus->drv_pci[0], true);
 }
 
 /* Unconfigure and/or apply various WARs when going down */
@@ -703,7 +703,7 @@ void ai_pci_down(struct si_pub *sih)
        sii = container_of(sih, struct si_info, pub);
 
        if (sii->icbus->hosttype == BCMA_HOSTTYPE_PCI)
-               bcma_core_pci_extend_L1timer(&sii->icbus->drv_pci, false);
+               bcma_core_pci_extend_L1timer(&sii->icbus->drv_pci[0], false);
 }
 
 /* Enable BT-COEX & Ex-PA for 4313 */
index 75086b37c817b747fe5482bb097a66a859c14214..565c15abbed546cf4bfe6acb3771dcf34f45f1ad 100644 (file)
@@ -5077,7 +5077,7 @@ static int brcms_b_up_prep(struct brcms_hardware *wlc_hw)
         * Configure pci/pcmcia here instead of in brcms_c_attach()
         * to allow mfg hotswap:  down, hotswap (chip power cycle), up.
         */
-       bcma_core_pci_irq_ctl(&wlc_hw->d11core->bus->drv_pci, wlc_hw->d11core,
+       bcma_core_pci_irq_ctl(&wlc_hw->d11core->bus->drv_pci[0], wlc_hw->d11core,
                              true);
 
        /*
index df7050abe717d9c09a6167ade588553a16041e79..d39e3e24077b1dca873f0ffe0dbce6a221dbaaea 100644 (file)
@@ -415,7 +415,7 @@ static void hostap_rx_sta_beacon(local_info_t *local, struct sk_buff *skb,
                        ssid = pos + 2;
                        ssid_len = pos[1];
                        break;
-               case WLAN_EID_GENERIC:
+               case WLAN_EID_VENDOR_SPECIFIC:
                        if (pos[1] >= 4 &&
                            pos[2] == 0x00 && pos[3] == 0x50 &&
                            pos[4] == 0xf2 && pos[5] == 1) {
index 935120fc8c9397daef4cb822b3d00176e0ca0cb8..768bf612533e04317feb756efa17563400ce6ab2 100644 (file)
@@ -10472,7 +10472,7 @@ static void ipw_handle_promiscuous_tx(struct ipw_priv *priv,
                } else
                        len = src->len;
 
-               dst = alloc_skb(len + sizeof(*rt_hdr), GFP_ATOMIC);
+               dst = alloc_skb(len + sizeof(*rt_hdr) + sizeof(u16)*2, GFP_ATOMIC);
                if (!dst)
                        continue;
 
index 02e057923236bd6133f5008d1c01feb7c911fcda..95a1ca1e895c6de72a7a792b66e32bc137876326 100644 (file)
@@ -1108,7 +1108,7 @@ static const char *get_info_element_string(u16 id)
                MFIE_STRING(ERP_INFO);
                MFIE_STRING(RSN);
                MFIE_STRING(EXT_SUPP_RATES);
-               MFIE_STRING(GENERIC);
+               MFIE_STRING(VENDOR_SPECIFIC);
                MFIE_STRING(QOS_PARAMETER);
        default:
                return "UNKNOWN";
@@ -1248,8 +1248,8 @@ static int libipw_parse_info_param(struct libipw_info_element
                        LIBIPW_DEBUG_MGMT("WLAN_EID_CHALLENGE: ignored\n");
                        break;
 
-               case WLAN_EID_GENERIC:
-                       LIBIPW_DEBUG_MGMT("WLAN_EID_GENERIC: %d bytes\n",
+               case WLAN_EID_VENDOR_SPECIFIC:
+                       LIBIPW_DEBUG_MGMT("WLAN_EID_VENDOR_SPECIFIC: %d bytes\n",
                                             info_element->len);
                        if (!libipw_parse_qos_info_param_IE(info_element,
                                                               network))
index 349c205d5f62e218d3a76226b983818e92732a95..da5862064195159a7052fd92b327ce017b2d1381 100644 (file)
@@ -518,7 +518,7 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
         * See iwlagn_mac_channel_switch.
         */
        struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-       struct iwl6000_channel_switch_cmd cmd;
+       struct iwl6000_channel_switch_cmd *cmd;
        u32 switch_time_in_usec, ucode_switch_time;
        u16 ch;
        u32 tsf_low;
@@ -527,18 +527,25 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
        struct ieee80211_vif *vif = ctx->vif;
        struct iwl_host_cmd hcmd = {
                .id = REPLY_CHANNEL_SWITCH,
-               .len = { sizeof(cmd), },
+               .len = { sizeof(*cmd), },
                .flags = CMD_SYNC,
-               .data = { &cmd, },
+               .dataflags[0] = IWL_HCMD_DFL_NOCOPY,
        };
+       int err;
 
-       cmd.band = priv->band == IEEE80211_BAND_2GHZ;
+       cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+       if (!cmd)
+               return -ENOMEM;
+
+       hcmd.data[0] = cmd;
+
+       cmd->band = priv->band == IEEE80211_BAND_2GHZ;
        ch = ch_switch->channel->hw_value;
        IWL_DEBUG_11H(priv, "channel switch from %u to %u\n",
                      ctx->active.channel, ch);
-       cmd.channel = cpu_to_le16(ch);
-       cmd.rxon_flags = ctx->staging.flags;
-       cmd.rxon_filter_flags = ctx->staging.filter_flags;
+       cmd->channel = cpu_to_le16(ch);
+       cmd->rxon_flags = ctx->staging.flags;
+       cmd->rxon_filter_flags = ctx->staging.filter_flags;
        switch_count = ch_switch->count;
        tsf_low = ch_switch->timestamp & 0x0ffffffff;
        /*
@@ -554,23 +561,25 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
                        switch_count = 0;
        }
        if (switch_count <= 1)
-               cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time);
+               cmd->switch_time = cpu_to_le32(priv->ucode_beacon_time);
        else {
                switch_time_in_usec =
                        vif->bss_conf.beacon_int * switch_count * TIME_UNIT;
                ucode_switch_time = iwl_usecs_to_beacons(priv,
                                                         switch_time_in_usec,
                                                         beacon_interval);
-               cmd.switch_time = iwl_add_beacon_time(priv,
-                                                     priv->ucode_beacon_time,
-                                                     ucode_switch_time,
-                                                     beacon_interval);
+               cmd->switch_time = iwl_add_beacon_time(priv,
+                                                      priv->ucode_beacon_time,
+                                                      ucode_switch_time,
+                                                      beacon_interval);
        }
        IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n",
-                     cmd.switch_time);
-       cmd.expect_beacon = ch_switch->channel->flags & IEEE80211_CHAN_RADAR;
+                     cmd->switch_time);
+       cmd->expect_beacon = ch_switch->channel->flags & IEEE80211_CHAN_RADAR;
 
-       return iwl_dvm_send_cmd(priv, &hcmd);
+       err = iwl_dvm_send_cmd(priv, &hcmd);
+       kfree(cmd);
+       return err;
 }
 
 struct iwl_lib_ops iwl6000_lib = {
index 7ff3f14306784169f886e5c7ca570d8b217a7309..475df45c8320b370010b5f70d4af0c3280ef102d 100644 (file)
@@ -1191,8 +1191,6 @@ static void iwl_option_config(struct iwl_priv *priv)
 
 static int iwl_eeprom_init_hw_params(struct iwl_priv *priv)
 {
-       u16 radio_cfg;
-
        priv->eeprom_data->sku = priv->eeprom_data->sku;
 
        if (priv->eeprom_data->sku & EEPROM_SKU_CAP_11N_ENABLE &&
@@ -1208,8 +1206,6 @@ static int iwl_eeprom_init_hw_params(struct iwl_priv *priv)
 
        IWL_INFO(priv, "Device SKU: 0x%X\n", priv->eeprom_data->sku);
 
-       radio_cfg = priv->eeprom_data->radio_cfg;
-
        priv->hw_params.tx_chains_num =
                num_of_ant(priv->eeprom_data->valid_tx_ant);
        if (priv->cfg->rx_with_siso_diversity)
@@ -1334,6 +1330,9 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
        /* Configure transport layer */
        iwl_trans_configure(priv->trans, &trans_cfg);
 
+       trans->rx_mpdu_cmd = REPLY_RX_MPDU_CMD;
+       trans->rx_mpdu_cmd_hdr_size = sizeof(struct iwl_rx_mpdu_res_start);
+
        /* At this point both hw and priv are allocated. */
 
        SET_IEEE80211_DEV(priv->hw, priv->trans->dev);
@@ -2152,8 +2151,6 @@ static int __init iwl_init(void)
 {
 
        int ret;
-       pr_info(DRV_DESCRIPTION ", " DRV_VERSION "\n");
-       pr_info(DRV_COPYRIGHT "\n");
 
        ret = iwlagn_rate_control_register();
        if (ret) {
index 59a5f78402fce35319014267c33514b7e4b7ef65..678717bf62eb514906aa315efa1fbbfb5f2b2e78 100644 (file)
  *****************************************************************************/
 
 #if !defined(__IWLWIFI_DEVICE_TRACE) || defined(TRACE_HEADER_MULTI_READ)
+#include <linux/skbuff.h>
+#include <linux/ieee80211.h>
+#include <net/cfg80211.h>
+#include "iwl-trans.h"
+#if !defined(__IWLWIFI_DEVICE_TRACE)
+static inline bool iwl_trace_data(struct sk_buff *skb)
+{
+       struct ieee80211_hdr *hdr = (void *)skb->data;
+
+       if (ieee80211_is_data(hdr->frame_control))
+               return skb->protocol != cpu_to_be16(ETH_P_PAE);
+       return false;
+}
+
+static inline size_t iwl_rx_trace_len(const struct iwl_trans *trans,
+                                     void *rxbuf, size_t len)
+{
+       struct iwl_cmd_header *cmd = (void *)((u8 *)rxbuf + sizeof(__le32));
+       struct ieee80211_hdr *hdr;
+
+       if (cmd->cmd != trans->rx_mpdu_cmd)
+               return len;
+
+       hdr = (void *)((u8 *)cmd + sizeof(struct iwl_cmd_header) +
+                       trans->rx_mpdu_cmd_hdr_size);
+       if (!ieee80211_is_data(hdr->frame_control))
+               return len;
+       /* maybe try to identify EAPOL frames? */
+       return sizeof(__le32) + sizeof(*cmd) + trans->rx_mpdu_cmd_hdr_size +
+               ieee80211_hdrlen(hdr->frame_control);
+}
+#endif
+
 #define __IWLWIFI_DEVICE_TRACE
 
 #include <linux/tracepoint.h>
@@ -234,6 +267,48 @@ TRACE_EVENT(iwlwifi_dbg,
        TP_printk("%s", (char *)__get_dynamic_array(msg))
 );
 
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM iwlwifi_data
+
+TRACE_EVENT(iwlwifi_dev_tx_data,
+       TP_PROTO(const struct device *dev,
+                struct sk_buff *skb,
+                void *data, size_t data_len),
+       TP_ARGS(dev, skb, data, data_len),
+       TP_STRUCT__entry(
+               DEV_ENTRY
+
+               __dynamic_array(u8, data, iwl_trace_data(skb) ? data_len : 0)
+       ),
+       TP_fast_assign(
+               DEV_ASSIGN;
+               if (iwl_trace_data(skb))
+                       memcpy(__get_dynamic_array(data), data, data_len);
+       ),
+       TP_printk("[%s] TX frame data", __get_str(dev))
+);
+
+TRACE_EVENT(iwlwifi_dev_rx_data,
+       TP_PROTO(const struct device *dev,
+                const struct iwl_trans *trans,
+                void *rxbuf, size_t len),
+       TP_ARGS(dev, trans, rxbuf, len),
+       TP_STRUCT__entry(
+               DEV_ENTRY
+
+               __dynamic_array(u8, data,
+                               len - iwl_rx_trace_len(trans, rxbuf, len))
+       ),
+       TP_fast_assign(
+               size_t offs = iwl_rx_trace_len(trans, rxbuf, len);
+               DEV_ASSIGN;
+               if (offs < len)
+                       memcpy(__get_dynamic_array(data),
+                              ((u8 *)rxbuf) + offs, len - offs);
+       ),
+       TP_printk("[%s] TX frame data", __get_str(dev))
+);
+
 #undef TRACE_SYSTEM
 #define TRACE_SYSTEM iwlwifi
 
@@ -270,25 +345,28 @@ TRACE_EVENT(iwlwifi_dev_hcmd,
 );
 
 TRACE_EVENT(iwlwifi_dev_rx,
-       TP_PROTO(const struct device *dev, void *rxbuf, size_t len),
-       TP_ARGS(dev, rxbuf, len),
+       TP_PROTO(const struct device *dev, const struct iwl_trans *trans,
+                void *rxbuf, size_t len),
+       TP_ARGS(dev, trans, rxbuf, len),
        TP_STRUCT__entry(
                DEV_ENTRY
-               __dynamic_array(u8, rxbuf, len)
+               __dynamic_array(u8, rxbuf, iwl_rx_trace_len(trans, rxbuf, len))
        ),
        TP_fast_assign(
                DEV_ASSIGN;
-               memcpy(__get_dynamic_array(rxbuf), rxbuf, len);
+               memcpy(__get_dynamic_array(rxbuf), rxbuf,
+                      iwl_rx_trace_len(trans, rxbuf, len));
        ),
        TP_printk("[%s] RX cmd %#.2x",
                  __get_str(dev), ((u8 *)__get_dynamic_array(rxbuf))[4])
 );
 
 TRACE_EVENT(iwlwifi_dev_tx,
-       TP_PROTO(const struct device *dev, void *tfd, size_t tfdlen,
+       TP_PROTO(const struct device *dev, struct sk_buff *skb,
+                void *tfd, size_t tfdlen,
                 void *buf0, size_t buf0_len,
                 void *buf1, size_t buf1_len),
-       TP_ARGS(dev, tfd, tfdlen, buf0, buf0_len, buf1, buf1_len),
+       TP_ARGS(dev, skb, tfd, tfdlen, buf0, buf0_len, buf1, buf1_len),
        TP_STRUCT__entry(
                DEV_ENTRY
 
@@ -301,14 +379,15 @@ TRACE_EVENT(iwlwifi_dev_tx,
                 * for the possible padding).
                 */
                __dynamic_array(u8, buf0, buf0_len)
-               __dynamic_array(u8, buf1, buf1_len)
+               __dynamic_array(u8, buf1, iwl_trace_data(skb) ? 0 : buf1_len)
        ),
        TP_fast_assign(
                DEV_ASSIGN;
                __entry->framelen = buf0_len + buf1_len;
                memcpy(__get_dynamic_array(tfd), tfd, tfdlen);
                memcpy(__get_dynamic_array(buf0), buf0, buf0_len);
-               memcpy(__get_dynamic_array(buf1), buf1, buf1_len);
+               if (!iwl_trace_data(skb))
+                       memcpy(__get_dynamic_array(buf1), buf1, buf1_len);
        ),
        TP_printk("[%s] TX %.2x (%zu bytes)",
                  __get_str(dev), ((u8 *)__get_dynamic_array(buf0))[0],
index 3dfebfb8434ff63e9b2ce7a2b2a86a7b01fad281..54c41b44bffea05581221166b93d3d57d33b1c5e 100644 (file)
@@ -327,11 +327,11 @@ u32 iwl_read_targ_mem(struct iwl_trans *trans, u32 addr)
 EXPORT_SYMBOL_GPL(iwl_read_targ_mem);
 
 int _iwl_write_targ_mem_dwords(struct iwl_trans *trans, u32 addr,
-                              void *buf, int dwords)
+                              const void *buf, int dwords)
 {
        unsigned long flags;
        int offs, result = 0;
-       u32 *vals = buf;
+       const u32 *vals = buf;
 
        spin_lock_irqsave(&trans->reg_lock, flags);
        if (likely(iwl_grab_nic_access(trans))) {
index 50d3819739d12bd8296b3be9dec03425a488f45a..e1aa69f66de633befb027f28d820d738ad43a7e6 100644 (file)
@@ -87,7 +87,7 @@ void _iwl_read_targ_mem_dwords(struct iwl_trans *trans, u32 addr,
        } while (0)
 
 int _iwl_write_targ_mem_dwords(struct iwl_trans *trans, u32 addr,
-                              void *buf, int dwords);
+                              const void *buf, int dwords);
 
 u32 iwl_read_targ_mem(struct iwl_trans *trans, u32 addr);
 int iwl_write_targ_mem(struct iwl_trans *trans, u32 addr, u32 val);
index 9253ef1dba72d005f407b34c1bfb2665fb9b4be6..c3a4bb41e53370931832e8a7427d3361337e469d 100644 (file)
 #define SCD_CONTEXT_QUEUE_OFFSET(x)\
        (SCD_CONTEXT_MEM_LOWER_BOUND + ((x) * 8))
 
+#define SCD_TX_STTS_QUEUE_OFFSET(x)\
+       (SCD_TX_STTS_MEM_LOWER_BOUND + ((x) * 16))
+
 #define SCD_TRANS_TBL_OFFSET_QUEUE(x) \
        ((SCD_TRANS_TBL_MEM_LOWER_BOUND + ((x) * 2)) & 0xfffc)
 
index ff1154232885da82add146706ffe67b325d3e9b2..f75ea6d73ffc4e824bb9dffdb61e63607e4cccbf 100644 (file)
@@ -444,6 +444,10 @@ enum iwl_trans_state {
  * @dev_cmd_headroom: room needed for the transport's private use before the
  *     device_cmd for Tx - for internal use only
  *     The user should use iwl_trans_{alloc,free}_tx_cmd.
+ * @rx_mpdu_cmd: MPDU RX command ID, must be assigned by opmode before
+ *     starting the firmware, used for tracing
+ * @rx_mpdu_cmd_hdr_size: used for tracing, amount of data before the
+ *     start of the 802.11 header in the @rx_mpdu_cmd
  */
 struct iwl_trans {
        const struct iwl_trans_ops *ops;
@@ -457,6 +461,8 @@ struct iwl_trans {
        u32 hw_id;
        char hw_id_str[52];
 
+       u8 rx_mpdu_cmd, rx_mpdu_cmd_hdr_size;
+
        bool pm_support;
 
        wait_queue_head_t wait_command_queue;
@@ -516,6 +522,8 @@ static inline int iwl_trans_start_fw(struct iwl_trans *trans,
 {
        might_sleep();
 
+       WARN_ON_ONCE(!trans->rx_mpdu_cmd);
+
        return trans->ops->start_fw(trans, fw);
 }
 
index 17c8e5d82681022383d657da550924d48d0d9289..137af4c46a6cf7c2c5d055475b6dbdaa17157d40 100644 (file)
@@ -411,7 +411,8 @@ static void iwl_rx_handle_rxbuf(struct iwl_trans *trans,
 
                len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
                len += sizeof(u32); /* account for status word */
-               trace_iwlwifi_dev_rx(trans->dev, pkt, len);
+               trace_iwlwifi_dev_rx(trans->dev, trans, pkt, len);
+               trace_iwlwifi_dev_rx_data(trans->dev, trans, pkt, len);
 
                /* Reclaim a command buffer only if this packet is a response
                 *   to a (driver-originated) command.
index fe0fffd043048f48adca5c110031f537d363d73e..f95d88df7772014a430f620c889303bf135ff9c3 100644 (file)
@@ -300,7 +300,7 @@ static void iwl_trans_pcie_queue_stuck_timer(unsigned long data)
        struct iwl_trans_pcie *trans_pcie = txq->trans_pcie;
        struct iwl_trans *trans = iwl_trans_pcie_get_trans(trans_pcie);
        u32 scd_sram_addr = trans_pcie->scd_base_addr +
-               SCD_TX_STTS_MEM_LOWER_BOUND + (16 * txq->q.id);
+                               SCD_TX_STTS_QUEUE_OFFSET(txq->q.id);
        u8 buf[16];
        int i;
 
@@ -1385,11 +1385,13 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
        dma_sync_single_for_device(trans->dev, txcmd_phys, firstlen,
                                   DMA_BIDIRECTIONAL);
 
-       trace_iwlwifi_dev_tx(trans->dev,
+       trace_iwlwifi_dev_tx(trans->dev, skb,
                             &txq->tfds[txq->q.write_ptr],
                             sizeof(struct iwl_tfd),
                             &dev_cmd->hdr, firstlen,
                             skb->data + hdr_len, secondlen);
+       trace_iwlwifi_dev_tx_data(trans->dev, skb,
+                                 skb->data + hdr_len, secondlen);
 
        /* start timer if queue currently empty */
        if (txq->need_update && q->read_ptr == q->write_ptr &&
@@ -1514,14 +1516,13 @@ static void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
        struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id];
        /* n_bd is usually 256 => n_bd - 1 = 0xff */
        int tfd_num = ssn & (txq->q.n_bd - 1);
-       int freed = 0;
 
        spin_lock(&txq->lock);
 
        if (txq->q.read_ptr != tfd_num) {
                IWL_DEBUG_TX_REPLY(trans, "[Q %d] %d -> %d (%d)\n",
                                   txq_id, txq->q.read_ptr, tfd_num, ssn);
-               freed = iwl_tx_queue_reclaim(trans, txq_id, tfd_num, skbs);
+               iwl_tx_queue_reclaim(trans, txq_id, tfd_num, skbs);
                if (iwl_queue_space(&txq->q) > txq->q.low_mark)
                        iwl_wake_queue(trans, txq);
        }
index 105e3af3c621b0b9e335fbe42d1ea1e444bfa579..db3efbb84d9221d96c933062758504fb74f5f283 100644 (file)
@@ -480,21 +480,20 @@ void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, int fifo,
 void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int txq_id)
 {
        struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-       u16 rd_ptr, wr_ptr;
-       int n_bd = trans_pcie->txq[txq_id].q.n_bd;
+       u32 stts_addr = trans_pcie->scd_base_addr +
+                       SCD_TX_STTS_QUEUE_OFFSET(txq_id);
+       static const u32 zero_val[4] = {};
 
        if (!test_and_clear_bit(txq_id, trans_pcie->queue_used)) {
                WARN_ONCE(1, "queue %d not used", txq_id);
                return;
        }
 
-       rd_ptr = iwl_read_prph(trans, SCD_QUEUE_RDPTR(txq_id)) & (n_bd - 1);
-       wr_ptr = iwl_read_prph(trans, SCD_QUEUE_WRPTR(txq_id));
+       iwl_txq_set_inactive(trans, txq_id);
 
-       WARN_ONCE(rd_ptr != wr_ptr, "queue %d isn't empty: [%d,%d]",
-                 txq_id, rd_ptr, wr_ptr);
+       _iwl_write_targ_mem_dwords(trans, stts_addr,
+                                  zero_val, ARRAY_SIZE(zero_val));
 
-       iwl_txq_set_inactive(trans, txq_id);
        IWL_DEBUG_TX_QUEUES(trans, "Deactivate queue %d\n", txq_id);
 }
 
@@ -549,7 +548,10 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
         * allocated into separate TFDs, then we will need to
         * increase the size of the buffers.
         */
-       if (WARN_ON(copy_size > TFD_MAX_PAYLOAD_SIZE))
+       if (WARN(copy_size > TFD_MAX_PAYLOAD_SIZE,
+                "Command %s (%#x) is too large (%d bytes)\n",
+                trans_pcie_get_cmd_string(trans_pcie, cmd->id),
+                cmd->id, copy_size))
                return -EINVAL;
 
        spin_lock_bh(&txq->lock);
index 97807751ebcfd59204fe6d651ce6874e52d552be..3e81264db81e937d25b3dda0a5fb7543d4c4379e 100644 (file)
@@ -101,7 +101,7 @@ static int lbs_mesh_config(struct lbs_private *priv, uint16_t action,
 
        switch (action) {
        case CMD_ACT_MESH_CONFIG_START:
-               ie->id = WLAN_EID_GENERIC;
+               ie->id = WLAN_EID_VENDOR_SPECIFIC;
                ie->val.oui[0] = 0x00;
                ie->val.oui[1] = 0x50;
                ie->val.oui[2] = 0x43;
index 0679458a1bac44469ddf0d00935e7b165f66f9ed..9aead8af69ef8b972747f70a32233f0c7261e281 100644 (file)
@@ -1825,8 +1825,6 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy,
                return -EBUSY;
        }
 
-       priv->scan_request = request;
-
        priv->user_scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg),
                                      GFP_KERNEL);
        if (!priv->user_scan_cfg) {
@@ -1834,6 +1832,8 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy,
                return -ENOMEM;
        }
 
+       priv->scan_request = request;
+
        priv->user_scan_cfg->num_ssids = request->n_ssids;
        priv->user_scan_cfg->ssid_list = request->ssids;
 
@@ -1870,6 +1870,9 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy,
        ret = mwifiex_scan_networks(priv, priv->user_scan_cfg);
        if (ret) {
                dev_err(priv->adapter->dev, "scan failed: %d\n", ret);
+               priv->scan_request = NULL;
+               kfree(priv->user_scan_cfg);
+               priv->user_scan_cfg = NULL;
                return ret;
        }
 
@@ -2250,8 +2253,8 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
        wiphy->available_antennas_tx = BIT(adapter->number_of_antenna) - 1;
        wiphy->available_antennas_rx = BIT(adapter->number_of_antenna) - 1;
 
-       wiphy->features = NL80211_FEATURE_HT_IBSS |
-                         NL80211_FEATURE_INACTIVITY_TIMER;
+       wiphy->features |= NL80211_FEATURE_HT_IBSS |
+                          NL80211_FEATURE_INACTIVITY_TIMER;
 
        /* Reserve space for mwifiex specific private data for BSS */
        wiphy->bss_priv_size = sizeof(struct mwifiex_bss_priv);
index 8d465107f52b2c5073acad20d8d0acbe0485be5e..da6c49177fccacfc2043d113d4101fb6af0dcbaa 100644 (file)
@@ -917,21 +917,24 @@ mwifiex_cmd_timeout_func(unsigned long function_context)
 
                dev_err(adapter->dev, "last_cmd_index = %d\n",
                        adapter->dbg.last_cmd_index);
-               print_hex_dump_bytes("last_cmd_id: ", DUMP_PREFIX_OFFSET,
-                                    adapter->dbg.last_cmd_id, DBG_CMD_NUM);
-               print_hex_dump_bytes("last_cmd_act: ", DUMP_PREFIX_OFFSET,
-                                    adapter->dbg.last_cmd_act, DBG_CMD_NUM);
+               dev_err(adapter->dev, "last_cmd_id: %*ph\n",
+                       (int)sizeof(adapter->dbg.last_cmd_id),
+                       adapter->dbg.last_cmd_id);
+               dev_err(adapter->dev, "last_cmd_act: %*ph\n",
+                       (int)sizeof(adapter->dbg.last_cmd_act),
+                       adapter->dbg.last_cmd_act);
 
                dev_err(adapter->dev, "last_cmd_resp_index = %d\n",
                        adapter->dbg.last_cmd_resp_index);
-               print_hex_dump_bytes("last_cmd_resp_id: ", DUMP_PREFIX_OFFSET,
-                                    adapter->dbg.last_cmd_resp_id,
-                                    DBG_CMD_NUM);
+               dev_err(adapter->dev, "last_cmd_resp_id: %*ph\n",
+                       (int)sizeof(adapter->dbg.last_cmd_resp_id),
+                       adapter->dbg.last_cmd_resp_id);
 
                dev_err(adapter->dev, "last_event_index = %d\n",
                        adapter->dbg.last_event_index);
-               print_hex_dump_bytes("last_event: ", DUMP_PREFIX_OFFSET,
-                                    adapter->dbg.last_event, DBG_CMD_NUM);
+               dev_err(adapter->dev, "last_event: %*ph\n",
+                       (int)sizeof(adapter->dbg.last_event),
+                       adapter->dbg.last_event);
 
                dev_err(adapter->dev, "data_sent=%d cmd_sent=%d\n",
                        adapter->data_sent, adapter->cmd_sent);
index c2d0ab146af545431b8fe5f3d04916756ef3b782..0b747ec84c4df9c19200170d90e8e45ac563c73a 100644 (file)
@@ -115,8 +115,6 @@ enum {
 #define MWIFIEX_TYPE_DATA                              0
 #define MWIFIEX_TYPE_EVENT                             3
 
-#define DBG_CMD_NUM                                            5
-
 #define MAX_BITMAP_RATES_SIZE                  10
 
 #define MAX_CHANNEL_BAND_BG     14
index 00b658d3b6ecfae72792b055a717aab9c41a0401..fe0568428a71a8722817612adf24a0154f84e362 100644 (file)
@@ -153,7 +153,7 @@ mwifiex_is_wpa_oui_present(struct mwifiex_bssdescriptor *bss_desc, u32 cipher)
 
        if (((bss_desc->bcn_wpa_ie) &&
             ((*(bss_desc->bcn_wpa_ie)).vend_hdr.element_id ==
-             WLAN_EID_WPA))) {
+             WLAN_EID_VENDOR_SPECIFIC))) {
                iebody = (struct ie_body *) bss_desc->bcn_wpa_ie->data;
                oui = &mwifiex_wpa_oui[cipher][0];
                ret = mwifiex_search_oui_in_ie(iebody, oui);
@@ -202,7 +202,7 @@ mwifiex_is_bss_no_sec(struct mwifiex_private *priv,
        if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled &&
            !priv->sec_info.wpa2_enabled && ((!bss_desc->bcn_wpa_ie) ||
                ((*(bss_desc->bcn_wpa_ie)).vend_hdr.element_id !=
-                WLAN_EID_WPA)) &&
+                WLAN_EID_VENDOR_SPECIFIC)) &&
            ((!bss_desc->bcn_rsn_ie) ||
                ((*(bss_desc->bcn_rsn_ie)).ieee_hdr.element_id !=
                 WLAN_EID_RSN)) &&
@@ -237,7 +237,8 @@ mwifiex_is_bss_wpa(struct mwifiex_private *priv,
 {
        if (!priv->sec_info.wep_enabled && priv->sec_info.wpa_enabled &&
            !priv->sec_info.wpa2_enabled && ((bss_desc->bcn_wpa_ie) &&
-           ((*(bss_desc->bcn_wpa_ie)).vend_hdr.element_id == WLAN_EID_WPA))
+           ((*(bss_desc->bcn_wpa_ie)).
+            vend_hdr.element_id == WLAN_EID_VENDOR_SPECIFIC))
           /*
            * Privacy bit may NOT be set in some APs like
            * LinkSys WRT54G && bss_desc->privacy
@@ -309,7 +310,8 @@ mwifiex_is_bss_adhoc_aes(struct mwifiex_private *priv,
        if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled &&
            !priv->sec_info.wpa2_enabled &&
            ((!bss_desc->bcn_wpa_ie) ||
-            ((*(bss_desc->bcn_wpa_ie)).vend_hdr.element_id != WLAN_EID_WPA)) &&
+            ((*(bss_desc->bcn_wpa_ie)).
+             vend_hdr.element_id != WLAN_EID_VENDOR_SPECIFIC)) &&
            ((!bss_desc->bcn_rsn_ie) ||
             ((*(bss_desc->bcn_rsn_ie)).ieee_hdr.element_id != WLAN_EID_RSN)) &&
            !priv->sec_info.encryption_mode && bss_desc->privacy) {
@@ -329,7 +331,8 @@ mwifiex_is_bss_dynamic_wep(struct mwifiex_private *priv,
        if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled &&
            !priv->sec_info.wpa2_enabled &&
            ((!bss_desc->bcn_wpa_ie) ||
-            ((*(bss_desc->bcn_wpa_ie)).vend_hdr.element_id != WLAN_EID_WPA)) &&
+            ((*(bss_desc->bcn_wpa_ie)).
+             vend_hdr.element_id != WLAN_EID_VENDOR_SPECIFIC)) &&
            ((!bss_desc->bcn_rsn_ie) ||
             ((*(bss_desc->bcn_rsn_ie)).ieee_hdr.element_id != WLAN_EID_RSN)) &&
            priv->sec_info.encryption_mode && bss_desc->privacy) {
@@ -1843,21 +1846,18 @@ static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv,
                                      struct cfg80211_ssid *req_ssid)
 {
        struct mwifiex_adapter *adapter = priv->adapter;
-       int ret = 0;
+       int ret;
        struct mwifiex_user_scan_cfg *scan_cfg;
 
-       if (!req_ssid)
-               return -1;
-
        if (adapter->scan_processing) {
-               dev_dbg(adapter->dev, "cmd: Scan already in process...\n");
-               return ret;
+               dev_err(adapter->dev, "cmd: Scan already in process...\n");
+               return -EBUSY;
        }
 
        if (priv->scan_block) {
-               dev_dbg(adapter->dev,
+               dev_err(adapter->dev,
                        "cmd: Scan is blocked during association...\n");
-               return ret;
+               return -EBUSY;
        }
 
        scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg), GFP_KERNEL);
index 0c9f70b2cbe61de8b77084fb71135bc7fda36f00..552d72ed055aa63e96c5d01b0cdeadabed646f98 100644 (file)
@@ -713,7 +713,7 @@ static int mwifiex_set_wpa_ie_helper(struct mwifiex_private *priv,
                dev_dbg(priv->adapter->dev, "cmd: Set Wpa_ie_len=%d IE=%#x\n",
                        priv->wpa_ie_len, priv->wpa_ie[0]);
 
-               if (priv->wpa_ie[0] == WLAN_EID_WPA) {
+               if (priv->wpa_ie[0] == WLAN_EID_VENDOR_SPECIFIC) {
                        priv->sec_info.wpa_enabled = true;
                } else if (priv->wpa_ie[0] == WLAN_EID_RSN) {
                        priv->sec_info.wpa2_enabled = true;
@@ -1253,7 +1253,7 @@ mwifiex_set_gen_ie_helper(struct mwifiex_private *priv, u8 *ie_data_ptr,
        }
        pvendor_ie = (struct ieee_types_vendor_header *) ie_data_ptr;
        /* Test to see if it is a WPA IE, if not, then it is a gen IE */
-       if (((pvendor_ie->element_id == WLAN_EID_WPA) &&
+       if (((pvendor_ie->element_id == WLAN_EID_VENDOR_SPECIFIC) &&
             (!memcmp(pvendor_ie->oui, wpa_oui, sizeof(wpa_oui)))) ||
            (pvendor_ie->element_id == WLAN_EID_RSN)) {
 
index 4dadf9880a974c5820ab915700385b1e9b6d46ab..5a8fec26136ef338455e8ee71d7583c64cd3bce5 100644 (file)
@@ -39,7 +39,7 @@ static inline u8 *orinoco_get_wpa_ie(u8 *data, size_t len)
 {
        u8 *p = data;
        while ((p + 2 + WPA_SELECTOR_LEN) < (data + len)) {
-               if ((p[0] == WLAN_EID_GENERIC) &&
+               if ((p[0] == WLAN_EID_VENDOR_SPECIFIC) &&
                    (memcmp(&p[2], WPA_OUI_TYPE, WPA_SELECTOR_LEN) == 0))
                        return p;
                p += p[1] + 2;
index 7f53cea2f2052ab8b4f23b53d08c2c8eca35ee20..01624dcaf73ed7f2d77b90b46eb342c5f2576816 100644 (file)
@@ -865,7 +865,7 @@ static int ezusb_firmware_download(struct ezusb_priv *upriv,
 static int ezusb_access_ltv(struct ezusb_priv *upriv,
                            struct request_context *ctx,
                            u16 length, const void *data, u16 frame_type,
-                           void *ans_buff, int ans_size, u16 *ans_length)
+                           void *ans_buff, unsigned ans_size, u16 *ans_length)
 {
        int req_size;
        int retval = 0;
@@ -933,7 +933,7 @@ static int ezusb_access_ltv(struct ezusb_priv *upriv,
        }
        if (ctx->in_rid) {
                struct ezusb_packet *ans = ctx->buf;
-               int exp_len;
+               unsigned exp_len;
 
                if (ans->hermes_len != 0)
                        exp_len = le16_to_cpu(ans->hermes_len) * 2 + 12;
@@ -949,8 +949,7 @@ static int ezusb_access_ltv(struct ezusb_priv *upriv,
                }
 
                if (ans_buff)
-                       memcpy(ans_buff, ans->data,
-                              min_t(int, exp_len, ans_size));
+                       memcpy(ans_buff, ans->data, min(exp_len, ans_size));
                if (ans_length)
                        *ans_length = le16_to_cpu(ans->hermes_len);
        }
@@ -995,7 +994,7 @@ static int ezusb_read_ltv(struct hermes *hw, int bap, u16 rid,
        struct ezusb_priv *upriv = hw->priv;
        struct request_context *ctx;
 
-       if ((bufsize < 0) || (bufsize % 2))
+       if (bufsize % 2)
                return -EINVAL;
 
        ctx = ezusb_alloc_ctx(upriv, rid, rid);
index a12e84f892be1d9b13d1762a0369a7841af32645..6b2e1e431dd2fc579d1a2710b2b68ecfd47f043e 100644 (file)
@@ -1988,6 +1988,7 @@ static struct usb_driver rt2500usb_driver = {
        .disconnect     = rt2x00usb_disconnect,
        .suspend        = rt2x00usb_suspend,
        .resume         = rt2x00usb_resume,
+       .reset_resume   = rt2x00usb_resume,
        .disable_hub_initiated_lpm = 1,
 };
 
index 01dc8891070c3729c37b08cce18506ab583c4761..3bc206d06cd1de6721c1d0b6d03cbba765825f1c 100644 (file)
@@ -2520,20 +2520,37 @@ static int rt2800_get_txpower_bw_comp(struct rt2x00_dev *rt2x00dev,
        return comp_value;
 }
 
+static int rt2800_get_txpower_reg_delta(struct rt2x00_dev *rt2x00dev,
+                                       int power_level, int max_power)
+{
+       int delta;
+
+       if (test_bit(CAPABILITY_POWER_LIMIT, &rt2x00dev->cap_flags))
+               return 0;
+
+       /*
+        * XXX: We don't know the maximum transmit power of our hardware since
+        * the EEPROM doesn't expose it. We only know that we are calibrated
+        * to 100% tx power.
+        *
+        * Hence, we assume the regulatory limit that cfg80211 calulated for
+        * the current channel is our maximum and if we are requested to lower
+        * the value we just reduce our tx power accordingly.
+        */
+       delta = power_level - max_power;
+       return min(delta, 0);
+}
+
 static u8 rt2800_compensate_txpower(struct rt2x00_dev *rt2x00dev, int is_rate_b,
                                   enum ieee80211_band band, int power_level,
                                   u8 txpower, int delta)
 {
-       u32 reg;
        u16 eeprom;
        u8 criterion;
        u8 eirp_txpower;
        u8 eirp_txpower_criterion;
        u8 reg_limit;
 
-       if (!((band == IEEE80211_BAND_5GHZ) && is_rate_b))
-               return txpower;
-
        if (test_bit(CAPABILITY_POWER_LIMIT, &rt2x00dev->cap_flags)) {
                /*
                 * Check if eirp txpower exceed txpower_limit.
@@ -2542,11 +2559,13 @@ static u8 rt2800_compensate_txpower(struct rt2x00_dev *rt2x00dev, int is_rate_b,
                 * .11b data rate need add additional 4dbm
                 * when calculating eirp txpower.
                 */
-               rt2800_register_read(rt2x00dev, TX_PWR_CFG_0, &reg);
-               criterion = rt2x00_get_field32(reg, TX_PWR_CFG_0_6MBS);
+               rt2x00_eeprom_read(rt2x00dev, EEPROM_TXPOWER_BYRATE + 1,
+                                  &eeprom);
+               criterion = rt2x00_get_field16(eeprom,
+                                              EEPROM_TXPOWER_BYRATE_RATE0);
 
-               rt2x00_eeprom_read(rt2x00dev,
-                                  EEPROM_EIRP_MAX_TX_POWER, &eeprom);
+               rt2x00_eeprom_read(rt2x00dev, EEPROM_EIRP_MAX_TX_POWER,
+                                  &eeprom);
 
                if (band == IEEE80211_BAND_2GHZ)
                        eirp_txpower_criterion = rt2x00_get_field16(eeprom,
@@ -2563,36 +2582,71 @@ static u8 rt2800_compensate_txpower(struct rt2x00_dev *rt2x00dev, int is_rate_b,
        } else
                reg_limit = 0;
 
-       return txpower + delta - reg_limit;
+       txpower = max(0, txpower + delta - reg_limit);
+       return min_t(u8, txpower, 0xc);
 }
 
+/*
+ * We configure transmit power using MAC TX_PWR_CFG_{0,...,N} registers and
+ * BBP R1 register. TX_PWR_CFG_X allow to configure per rate TX power values,
+ * 4 bits for each rate (tune from 0 to 15 dBm). BBP_R1 controls transmit power
+ * for all rates, but allow to set only 4 discrete values: -12, -6, 0 and 6 dBm.
+ * Reference per rate transmit power values are located in the EEPROM at
+ * EEPROM_TXPOWER_BYRATE offset. We adjust them and BBP R1 settings according to
+ * current conditions (i.e. band, bandwidth, temperature, user settings).
+ */
 static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev,
-                                 enum ieee80211_band band,
+                                 struct ieee80211_channel *chan,
                                  int power_level)
 {
-       u8 txpower;
+       u8 txpower, r1;
        u16 eeprom;
-       int i, is_rate_b;
-       u32 reg;
-       u8 r1;
-       u32 offset;
-       int delta;
+       u32 reg, offset;
+       int i, is_rate_b, delta, power_ctrl;
+       enum ieee80211_band band = chan->band;
 
        /*
-        * Calculate HT40 compensation delta
+        * Calculate HT40 compensation. For 40MHz we need to add or subtract
+        * value read from EEPROM (different for 2GHz and for 5GHz).
         */
        delta = rt2800_get_txpower_bw_comp(rt2x00dev, band);
 
        /*
-        * calculate temperature compensation delta
+        * Calculate temperature compensation. Depends on measurement of current
+        * TSSI (Transmitter Signal Strength Indication) we know TX power (due
+        * to temperature or maybe other factors) is smaller or bigger than
+        * expected. We adjust it, based on TSSI reference and boundaries values
+        * provided in EEPROM.
         */
        delta += rt2800_get_gain_calibration_delta(rt2x00dev);
 
        /*
-        * set to normal bbp tx power control mode: +/- 0dBm
+        * Decrease power according to user settings, on devices with unknown
+        * maximum tx power. For other devices we take user power_level into
+        * consideration on rt2800_compensate_txpower().
+        */
+       delta += rt2800_get_txpower_reg_delta(rt2x00dev, power_level,
+                                             chan->max_power);
+
+       /*
+        * BBP_R1 controls TX power for all rates, it allow to set the following
+        * gains -12, -6, 0, +6 dBm by setting values 2, 1, 0, 3 respectively.
+        *
+        * TODO: we do not use +6 dBm option to do not increase power beyond
+        * regulatory limit, however this could be utilized for devices with
+        * CAPABILITY_POWER_LIMIT.
         */
        rt2800_bbp_read(rt2x00dev, 1, &r1);
-       rt2x00_set_field8(&r1, BBP1_TX_POWER_CTRL, 0);
+       if (delta <= -12) {
+               power_ctrl = 2;
+               delta += 12;
+       } else if (delta <= -6) {
+               power_ctrl = 1;
+               delta += 6;
+       } else {
+               power_ctrl = 0;
+       }
+       rt2x00_set_field8(&r1, BBP1_TX_POWER_CTRL, power_ctrl);
        rt2800_bbp_write(rt2x00dev, 1, r1);
        offset = TX_PWR_CFG_0;
 
@@ -2710,7 +2764,7 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev,
 
 void rt2800_gain_calibration(struct rt2x00_dev *rt2x00dev)
 {
-       rt2800_config_txpower(rt2x00dev, rt2x00dev->curr_band,
+       rt2800_config_txpower(rt2x00dev, rt2x00dev->hw->conf.channel,
                              rt2x00dev->tx_power);
 }
 EXPORT_SYMBOL_GPL(rt2800_gain_calibration);
@@ -2845,11 +2899,11 @@ void rt2800_config(struct rt2x00_dev *rt2x00dev,
        if (flags & IEEE80211_CONF_CHANGE_CHANNEL) {
                rt2800_config_channel(rt2x00dev, libconf->conf,
                                      &libconf->rf, &libconf->channel);
-               rt2800_config_txpower(rt2x00dev, libconf->conf->channel->band,
+               rt2800_config_txpower(rt2x00dev, libconf->conf->channel,
                                      libconf->conf->power_level);
        }
        if (flags & IEEE80211_CONF_CHANGE_POWER)
-               rt2800_config_txpower(rt2x00dev, libconf->conf->channel->band,
+               rt2800_config_txpower(rt2x00dev, libconf->conf->channel,
                                      libconf->conf->power_level);
        if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
                rt2800_config_retry_limit(rt2x00dev, libconf);
index c9e9370eb789c04ec91fd97a2a85d8d21977a144..3b8fb5a603f25244241a3219bff169962cf54733 100644 (file)
@@ -1282,6 +1282,7 @@ static struct usb_driver rt2800usb_driver = {
        .disconnect     = rt2x00usb_disconnect,
        .suspend        = rt2x00usb_suspend,
        .resume         = rt2x00usb_resume,
+       .reset_resume   = rt2x00usb_resume,
        .disable_hub_initiated_lpm = 1,
 };
 
index e5eb43b3eee74f94db85349436f0ba1e15925059..24eec66e9fd2049ae14aa709e7e2ecab0294751c 100644 (file)
@@ -2535,6 +2535,7 @@ static struct usb_driver rt73usb_driver = {
        .disconnect     = rt2x00usb_disconnect,
        .suspend        = rt2x00usb_suspend,
        .resume         = rt2x00usb_resume,
+       .reset_resume   = rt2x00usb_resume,
        .disable_hub_initiated_lpm = 1,
 };
 
index 5b4b4d4eaf9e9273916131eba6830955a17da5b6..ca69e35e50f126582ae73b2b9a35f96a8a075469 100644 (file)
@@ -52,11 +52,8 @@ static void rtl_cam_program_entry(struct ieee80211_hw *hw, u32 entry_no,
        u32 target_content = 0;
        u8 entry_i;
 
-       RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
-                "key_cont_128:\n %x:%x:%x:%x:%x:%x\n",
-                key_cont_128[0], key_cont_128[1],
-                key_cont_128[2], key_cont_128[3],
-                key_cont_128[4], key_cont_128[5]);
+       RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, "key_cont_128: %6phC\n",
+                key_cont_128);
 
        for (entry_i = 0; entry_i < CAM_CONTENT_COUNT; entry_i++) {
                target_command = entry_i + CAM_CONTENT_COUNT * entry_no;
index 86d73b32d9956c81f9b43886805bc23cb4adaa10..038c02c9afed7f94a80a52f41afb539663c0f362 100644 (file)
@@ -1918,10 +1918,8 @@ static void rtl92ce_update_hal_rate_mask(struct ieee80211_hw *hw,
                                     (ratr_index << 28);
        rate_mask[4] = macid | (shortgi ? 0x20 : 0x00) | 0x80;
        RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG,
-                "Rate_index:%x, ratr_val:%x, %x:%x:%x:%x:%x\n",
-                ratr_index, ratr_bitmap,
-                rate_mask[0], rate_mask[1], rate_mask[2], rate_mask[3],
-                rate_mask[4]);
+                "Rate_index:%x, ratr_val:%x, %5phC\n",
+                ratr_index, ratr_bitmap, rate_mask);
        rtl92c_fill_h2c_cmd(hw, H2C_RA_MASK, 5, rate_mask);
 
        if (macid != 0)
index 4bbb711a36c5fd6e4cfa4b14d08009ffaedcad49..7d36a94263b06c1594906bbb6c4f27a853ec7f86 100644 (file)
@@ -2169,10 +2169,8 @@ void rtl92cu_update_hal_rate_mask(struct ieee80211_hw *hw, u8 rssi_level)
                                      ratr_index << 28);
        rate_mask[4] = macid | (shortgi ? 0x20 : 0x00) | 0x80;
        RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG,
-                "Rate_index:%x, ratr_val:%x, %x:%x:%x:%x:%x\n",
-                ratr_index, ratr_bitmap,
-                rate_mask[0], rate_mask[1], rate_mask[2], rate_mask[3],
-                rate_mask[4]);
+                "Rate_index:%x, ratr_val:%x, %5phC\n",
+                ratr_index, ratr_bitmap, rate_mask);
        rtl92c_fill_h2c_cmd(hw, H2C_RA_MASK, 5, rate_mask);
 }
 
index 030beb45d8b0b2b30669e945eb1ccc2e2cbd5fd7..e3ea4b346889430dfb07d604f052adb6522f18bb 100644 (file)
@@ -673,7 +673,7 @@ static int rtl_usb_start(struct ieee80211_hw *hw)
                set_hal_start(rtlhal);
 
                /* Start bulk IN */
-               _rtl_usb_receive(hw);
+               err = _rtl_usb_receive(hw);
        }
 
        return err;
index f2d6b78d901d92d3965fe3bd849751f04fb7ccf3..aab86772facfef3465d9fc59aab0e9bca45ccd3e 100644 (file)
@@ -666,7 +666,9 @@ static void xen_netbk_rx_action(struct xen_netbk *netbk)
                return;
 
        BUG_ON(npo.copy_prod > ARRAY_SIZE(netbk->grant_copy_op));
-       gnttab_batch_copy(netbk->grant_copy_op, npo.copy_prod);
+       ret = HYPERVISOR_grant_table_op(GNTTABOP_copy, &netbk->grant_copy_op,
+                                       npo.copy_prod);
+       BUG_ON(ret != 0);
 
        while ((skb = __skb_dequeue(&rxq)) != NULL) {
                sco = (struct skb_cb_overlay *)skb->cb;
@@ -1489,15 +1491,18 @@ static void xen_netbk_tx_submit(struct xen_netbk *netbk)
 static void xen_netbk_tx_action(struct xen_netbk *netbk)
 {
        unsigned nr_gops;
+       int ret;
 
        nr_gops = xen_netbk_tx_build_gops(netbk);
 
        if (nr_gops == 0)
                return;
-
-       gnttab_batch_copy(netbk->tx_copy_ops, nr_gops);
+       ret = HYPERVISOR_grant_table_op(GNTTABOP_copy,
+                                       netbk->tx_copy_ops, nr_gops);
+       BUG_ON(ret);
 
        xen_netbk_tx_submit(netbk);
+
 }
 
 static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx)
index af3b22ac762755b532286ac505fb85ef936ca64b..38892a9f5400097973f8abfa536bd6ae6caafc39 100644 (file)
@@ -1011,6 +1011,8 @@ int of_parse_phandle_with_args(struct device_node *np, const char *list_name,
                                out_args->args_count = count;
                                for (i = 0; i < count; i++)
                                        out_args->args[i] = be32_to_cpup(list++);
+                       } else {
+                               of_node_put(node);
                        }
                        return 0;
                }
index c5792d622dc4528ba572632d39c7c1f1d7ae438d..63d6618a4804acc42fd9ab2b44aa3df41a530422 100644 (file)
@@ -17,6 +17,7 @@
 
 #include <linux/pci-acpi.h>
 #include <linux/pm_runtime.h>
+#include <linux/pm_qos.h>
 #include "pci.h"
 
 static DEFINE_MUTEX(pci_acpi_pm_notify_mtx);
@@ -257,11 +258,16 @@ static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state)
                return -ENODEV;
 
        switch (state) {
+       case PCI_D3cold:
+               if (dev_pm_qos_flags(&dev->dev, PM_QOS_FLAG_NO_POWER_OFF) ==
+                               PM_QOS_FLAGS_ALL) {
+                       error = -EBUSY;
+                       break;
+               }
        case PCI_D0:
        case PCI_D1:
        case PCI_D2:
        case PCI_D3hot:
-       case PCI_D3cold:
                error = acpi_bus_set_power(handle, state_conv[state]);
        }
 
index b066273b6b4f4dc5a87ee9c37ee589938f8b0d39..7dd879ce514df8cffdf23de397923fb96e878eef 100644 (file)
@@ -194,7 +194,7 @@ static void sharpsl_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
        sharpsl_pcmcia_init_reset(skt);
 }
 
-static struct pcmcia_low_level sharpsl_pcmcia_ops __initdata = {
+static struct pcmcia_low_level sharpsl_pcmcia_ops = {
        .owner                  = THIS_MODULE,
        .hw_init                = sharpsl_pcmcia_hw_init,
        .socket_state           = sharpsl_pcmcia_socket_state,
index 7bf914df6e91a6129d23f5d12828b8228a8c2775..4787f0e4597d07dfaad14a9db0fcbf6922952e32 100644 (file)
@@ -26,6 +26,15 @@ config DEBUG_PINCTRL
        help
          Say Y here to add some extra checks and diagnostics to PINCTRL calls.
 
+config PINCTRL_AT91
+       bool "AT91 pinctrl driver"
+       depends on OF
+       depends on ARCH_AT91
+       select PINMUX
+       select PINCONF
+       help
+         Say Y here to enable the at91 pinctrl driver
+
 config PINCTRL_BCM2835
        bool
        select PINMUX
index f395ba5cec2579c4ab1372db251beaacf0f31491..78a191c85adcf264dc3437df59dbdff093472508 100644 (file)
@@ -9,6 +9,7 @@ ifeq ($(CONFIG_OF),y)
 obj-$(CONFIG_PINCTRL)          += devicetree.o
 endif
 obj-$(CONFIG_GENERIC_PINCONF)  += pinconf-generic.o
+obj-$(CONFIG_PINCTRL_AT91)     += pinctrl-at91.o
 obj-$(CONFIG_PINCTRL_BCM2835)  += pinctrl-bcm2835.o
 obj-$(CONFIG_PINCTRL_IMX)      += pinctrl-imx.o
 obj-$(CONFIG_PINCTRL_IMX35)    += pinctrl-imx35.o
index 0f1ec9e8ff14b02448877cb4f4872f45baeeccd3..cec6072cd7c1247436064c764a343d2948be06a0 100644 (file)
@@ -563,6 +563,8 @@ static int add_setting(struct pinctrl *p, struct pinctrl_map const *map)
                return -EPROBE_DEFER;
        }
 
+       setting->dev_name = map->dev_name;
+
        switch (map->type) {
        case PIN_MAP_TYPE_MUX_GROUP:
                ret = pinmux_map_to_setting(map, setting);
@@ -1061,8 +1063,10 @@ static int pinctrl_groups_show(struct seq_file *s, void *what)
                        seq_printf(s, "group: %s\n", gname);
                        for (i = 0; i < num_pins; i++) {
                                pname = pin_get_name(pctldev, pins[i]);
-                               if (WARN_ON(!pname))
+                               if (WARN_ON(!pname)) {
+                                       mutex_unlock(&pinctrl_mutex);
                                        return -EINVAL;
+                               }
                                seq_printf(s, "pin %d (%s)\n", pins[i], pname);
                        }
                        seq_puts(s, "\n");
index 1f40ff68a8c406ff08234f463ebb3f088951e8f2..12f5694f3d5d9f02020cd2369603d6202e488b24 100644 (file)
@@ -105,12 +105,14 @@ struct pinctrl_setting_configs {
  * @type: the type of setting
  * @pctldev: pin control device handling to be programmed. Not used for
  *   PIN_MAP_TYPE_DUMMY_STATE.
+ * @dev_name: the name of the device using this state
  * @data: Data specific to the setting type
  */
 struct pinctrl_setting {
        struct list_head node;
        enum pinctrl_map_type type;
        struct pinctrl_dev *pctldev;
+       const char *dev_name;
        union {
                struct pinctrl_setting_mux mux;
                struct pinctrl_setting_configs configs;
index 43f474cdc11082717c881b757c6bcaf104bcbb97..baee2cc46a17a7c5c328f98c7eaa25f8f10d8fba 100644 (file)
@@ -537,8 +537,6 @@ static int pinconf_groups_show(struct seq_file *s, void *what)
        seq_puts(s, "Pin config settings per pin group\n");
        seq_puts(s, "Format: group (name): configs\n");
 
-       mutex_lock(&pinctrl_mutex);
-
        while (selector < ngroups) {
                const char *gname = pctlops->get_group_name(pctldev, selector);
 
@@ -549,8 +547,6 @@ static int pinconf_groups_show(struct seq_file *s, void *what)
                selector++;
        }
 
-       mutex_unlock(&pinctrl_mutex);
-
        return 0;
 }
 
diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c
new file mode 100644 (file)
index 0000000..01bf924
--- /dev/null
@@ -0,0 +1,1490 @@
+/*
+ * at91 pinctrl driver based on at91 pinmux core
+ *
+ * Copyright (C) 2011-2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * Under GPLv2 only
+ */
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/irqdomain.h>
+#include <linux/pinctrl/machine.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+/* Since we request GPIOs from ourself */
+#include <linux/pinctrl/consumer.h>
+
+#include <asm/mach/irq.h>
+
+#include <mach/hardware.h>
+#include <mach/at91_pio.h>
+
+#include "core.h"
+
+#define MAX_NB_GPIO_PER_BANK   32
+
+struct at91_pinctrl_mux_ops;
+
+struct at91_gpio_chip {
+       struct gpio_chip        chip;
+       struct pinctrl_gpio_range range;
+       struct at91_gpio_chip   *next;          /* Bank sharing same clock */
+       int                     pioc_hwirq;     /* PIO bank interrupt identifier on AIC */
+       int                     pioc_virq;      /* PIO bank Linux virtual interrupt */
+       int                     pioc_idx;       /* PIO bank index */
+       void __iomem            *regbase;       /* PIO bank virtual address */
+       struct clk              *clock;         /* associated clock */
+       struct irq_domain       *domain;        /* associated irq domain */
+       struct at91_pinctrl_mux_ops *ops;       /* ops */
+};
+
+#define to_at91_gpio_chip(c) container_of(c, struct at91_gpio_chip, chip)
+
+static struct at91_gpio_chip *gpio_chips[MAX_GPIO_BANKS];
+
+static int gpio_banks;
+
+#define PULL_UP                (0 << 1)
+#define MULTI_DRIVE    (1 << 1)
+
+/**
+ * struct at91_pmx_func - describes AT91 pinmux functions
+ * @name: the name of this specific function
+ * @groups: corresponding pin groups
+ * @ngroups: the number of groups
+ */
+struct at91_pmx_func {
+       const char      *name;
+       const char      **groups;
+       unsigned        ngroups;
+};
+
+enum at91_mux {
+       AT91_MUX_GPIO = 0,
+       AT91_MUX_PERIPH_A = 1,
+       AT91_MUX_PERIPH_B = 2,
+       AT91_MUX_PERIPH_C = 3,
+       AT91_MUX_PERIPH_D = 4,
+};
+
+/**
+ * struct at91_pmx_pin - describes an At91 pin mux
+ * @bank: the bank of the pin
+ * @pin: the pin number in the @bank
+ * @mux: the mux mode : gpio or periph_x of the pin i.e. alternate function.
+ * @conf: the configuration of the pin: PULL_UP, MULTIDRIVE etc...
+ */
+struct at91_pmx_pin {
+       uint32_t        bank;
+       uint32_t        pin;
+       enum at91_mux   mux;
+       unsigned long   conf;
+};
+
+/**
+ * struct at91_pin_group - describes an At91 pin group
+ * @name: the name of this specific pin group
+ * @pins_conf: the mux mode for each pin in this group. The size of this
+ *     array is the same as pins.
+ * @pins: an array of discrete physical pins used in this group, taken
+ *     from the driver-local pin enumeration space
+ * @npins: the number of pins in this group array, i.e. the number of
+ *     elements in .pins so we can iterate over that array
+ */
+struct at91_pin_group {
+       const char              *name;
+       struct at91_pmx_pin     *pins_conf;
+       unsigned int            *pins;
+       unsigned                npins;
+};
+
+/**
+ * struct at91_pinctrl_mux_ops - describes an At91 mux ops group
+ * on new IP with support for periph C and D the way to mux in
+ * periph A and B has changed
+ * So provide the right call back
+ * if not present means the IP does not support it
+ * @get_periph: return the periph mode configured
+ * @mux_A_periph: mux as periph A
+ * @mux_B_periph: mux as periph B
+ * @mux_C_periph: mux as periph C
+ * @mux_D_periph: mux as periph D
+ * @irq_type: return irq type
+ */
+struct at91_pinctrl_mux_ops {
+       enum at91_mux (*get_periph)(void __iomem *pio, unsigned mask);
+       void (*mux_A_periph)(void __iomem *pio, unsigned mask);
+       void (*mux_B_periph)(void __iomem *pio, unsigned mask);
+       void (*mux_C_periph)(void __iomem *pio, unsigned mask);
+       void (*mux_D_periph)(void __iomem *pio, unsigned mask);
+       /* irq */
+       int (*irq_type)(struct irq_data *d, unsigned type);
+};
+
+static int gpio_irq_type(struct irq_data *d, unsigned type);
+static int alt_gpio_irq_type(struct irq_data *d, unsigned type);
+
+struct at91_pinctrl {
+       struct device           *dev;
+       struct pinctrl_dev      *pctl;
+
+       int                     nbanks;
+
+       uint32_t                *mux_mask;
+       int                     nmux;
+
+       struct at91_pmx_func    *functions;
+       int                     nfunctions;
+
+       struct at91_pin_group   *groups;
+       int                     ngroups;
+
+       struct at91_pinctrl_mux_ops *ops;
+};
+
+static const inline struct at91_pin_group *at91_pinctrl_find_group_by_name(
+                               const struct at91_pinctrl *info,
+                               const char *name)
+{
+       const struct at91_pin_group *grp = NULL;
+       int i;
+
+       for (i = 0; i < info->ngroups; i++) {
+               if (strcmp(info->groups[i].name, name))
+                       continue;
+
+               grp = &info->groups[i];
+               dev_dbg(info->dev, "%s: %d 0:%d\n", name, grp->npins, grp->pins[0]);
+               break;
+       }
+
+       return grp;
+}
+
+static int at91_get_groups_count(struct pinctrl_dev *pctldev)
+{
+       struct at91_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+       return info->ngroups;
+}
+
+static const char *at91_get_group_name(struct pinctrl_dev *pctldev,
+                                      unsigned selector)
+{
+       struct at91_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+       return info->groups[selector].name;
+}
+
+static int at91_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector,
+                              const unsigned **pins,
+                              unsigned *npins)
+{
+       struct at91_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+       if (selector >= info->ngroups)
+               return -EINVAL;
+
+       *pins = info->groups[selector].pins;
+       *npins = info->groups[selector].npins;
+
+       return 0;
+}
+
+static void at91_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
+                  unsigned offset)
+{
+       seq_printf(s, "%s", dev_name(pctldev->dev));
+}
+
+static int at91_dt_node_to_map(struct pinctrl_dev *pctldev,
+                       struct device_node *np,
+                       struct pinctrl_map **map, unsigned *num_maps)
+{
+       struct at91_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+       const struct at91_pin_group *grp;
+       struct pinctrl_map *new_map;
+       struct device_node *parent;
+       int map_num = 1;
+       int i;
+       struct at91_pmx_pin *pin;
+
+       /*
+        * first find the group of this node and check if we need create
+        * config maps for pins
+        */
+       grp = at91_pinctrl_find_group_by_name(info, np->name);
+       if (!grp) {
+               dev_err(info->dev, "unable to find group for node %s\n",
+                       np->name);
+               return -EINVAL;
+       }
+
+       map_num += grp->npins;
+       new_map = devm_kzalloc(pctldev->dev, sizeof(*new_map) * map_num, GFP_KERNEL);
+       if (!new_map)
+               return -ENOMEM;
+
+       *map = new_map;
+       *num_maps = map_num;
+
+       /* create mux map */
+       parent = of_get_parent(np);
+       if (!parent) {
+               kfree(new_map);
+               return -EINVAL;
+       }
+       new_map[0].type = PIN_MAP_TYPE_MUX_GROUP;
+       new_map[0].data.mux.function = parent->name;
+       new_map[0].data.mux.group = np->name;
+       of_node_put(parent);
+
+       /* create config map */
+       new_map++;
+       for (i = 0; i < grp->npins; i++) {
+               pin = &grp->pins_conf[i];
+
+               new_map[i].type = PIN_MAP_TYPE_CONFIGS_PIN;
+               new_map[i].data.configs.group_or_pin =
+                               pin_get_name(pctldev, grp->pins[i]);
+               new_map[i].data.configs.configs = &grp->pins_conf[i].conf;
+               new_map[i].data.configs.num_configs = 1;
+       }
+
+       dev_dbg(pctldev->dev, "maps: function %s group %s num %d\n",
+               (*map)->data.mux.function, (*map)->data.mux.group, map_num);
+
+       return 0;
+}
+
+static void at91_dt_free_map(struct pinctrl_dev *pctldev,
+                               struct pinctrl_map *map, unsigned num_maps)
+{
+}
+
+static struct pinctrl_ops at91_pctrl_ops = {
+       .get_groups_count       = at91_get_groups_count,
+       .get_group_name         = at91_get_group_name,
+       .get_group_pins         = at91_get_group_pins,
+       .pin_dbg_show           = at91_pin_dbg_show,
+       .dt_node_to_map         = at91_dt_node_to_map,
+       .dt_free_map            = at91_dt_free_map,
+};
+
+static void __iomem * pin_to_controller(struct at91_pinctrl *info,
+                                unsigned int bank)
+{
+       return gpio_chips[bank]->regbase;
+}
+
+static inline int pin_to_bank(unsigned pin)
+{
+       return pin /= MAX_NB_GPIO_PER_BANK;
+}
+
+static unsigned pin_to_mask(unsigned int pin)
+{
+       return 1 << pin;
+}
+
+static void at91_mux_disable_interrupt(void __iomem *pio, unsigned mask)
+{
+       writel_relaxed(mask, pio + PIO_IDR);
+}
+
+static unsigned at91_mux_get_pullup(void __iomem *pio, unsigned pin)
+{
+       return (readl_relaxed(pio + PIO_PUSR) >> pin) & 0x1;
+}
+
+static void at91_mux_set_pullup(void __iomem *pio, unsigned mask, bool on)
+{
+       writel_relaxed(mask, pio + (on ? PIO_PUER : PIO_PUDR));
+}
+
+static unsigned at91_mux_get_multidrive(void __iomem *pio, unsigned pin)
+{
+       return (readl_relaxed(pio + PIO_MDSR) >> pin) & 0x1;
+}
+
+static void at91_mux_set_multidrive(void __iomem *pio, unsigned mask, bool on)
+{
+       writel_relaxed(mask, pio + (on ? PIO_MDER : PIO_MDDR));
+}
+
+static void at91_mux_set_A_periph(void __iomem *pio, unsigned mask)
+{
+       writel_relaxed(mask, pio + PIO_ASR);
+}
+
+static void at91_mux_set_B_periph(void __iomem *pio, unsigned mask)
+{
+       writel_relaxed(mask, pio + PIO_BSR);
+}
+
+static void at91_mux_pio3_set_A_periph(void __iomem *pio, unsigned mask)
+{
+
+       writel_relaxed(readl_relaxed(pio + PIO_ABCDSR1) & ~mask,
+                                               pio + PIO_ABCDSR1);
+       writel_relaxed(readl_relaxed(pio + PIO_ABCDSR2) & ~mask,
+                                               pio + PIO_ABCDSR2);
+}
+
+static void at91_mux_pio3_set_B_periph(void __iomem *pio, unsigned mask)
+{
+       writel_relaxed(readl_relaxed(pio + PIO_ABCDSR1) | mask,
+                                               pio + PIO_ABCDSR1);
+       writel_relaxed(readl_relaxed(pio + PIO_ABCDSR2) & ~mask,
+                                               pio + PIO_ABCDSR2);
+}
+
+static void at91_mux_pio3_set_C_periph(void __iomem *pio, unsigned mask)
+{
+       writel_relaxed(readl_relaxed(pio + PIO_ABCDSR1) & ~mask, pio + PIO_ABCDSR1);
+       writel_relaxed(readl_relaxed(pio + PIO_ABCDSR2) | mask, pio + PIO_ABCDSR2);
+}
+
+static void at91_mux_pio3_set_D_periph(void __iomem *pio, unsigned mask)
+{
+       writel_relaxed(readl_relaxed(pio + PIO_ABCDSR1) | mask, pio + PIO_ABCDSR1);
+       writel_relaxed(readl_relaxed(pio + PIO_ABCDSR2) | mask, pio + PIO_ABCDSR2);
+}
+
+static enum at91_mux at91_mux_pio3_get_periph(void __iomem *pio, unsigned mask)
+{
+       unsigned select;
+
+       if (readl_relaxed(pio + PIO_PSR) & mask)
+               return AT91_MUX_GPIO;
+
+       select = !!(readl_relaxed(pio + PIO_ABCDSR1) & mask);
+       select |= (!!(readl_relaxed(pio + PIO_ABCDSR2) & mask) << 1);
+
+       return select + 1;
+}
+
+static enum at91_mux at91_mux_get_periph(void __iomem *pio, unsigned mask)
+{
+       unsigned select;
+
+       if (readl_relaxed(pio + PIO_PSR) & mask)
+               return AT91_MUX_GPIO;
+
+       select = readl_relaxed(pio + PIO_ABSR) & mask;
+
+       return select + 1;
+}
+
+static struct at91_pinctrl_mux_ops at91rm9200_ops = {
+       .get_periph     = at91_mux_get_periph,
+       .mux_A_periph   = at91_mux_set_A_periph,
+       .mux_B_periph   = at91_mux_set_B_periph,
+       .irq_type       = gpio_irq_type,
+};
+
+static struct at91_pinctrl_mux_ops at91sam9x5_ops = {
+       .get_periph     = at91_mux_pio3_get_periph,
+       .mux_A_periph   = at91_mux_pio3_set_A_periph,
+       .mux_B_periph   = at91_mux_pio3_set_B_periph,
+       .mux_C_periph   = at91_mux_pio3_set_C_periph,
+       .mux_D_periph   = at91_mux_pio3_set_D_periph,
+       .irq_type       = alt_gpio_irq_type,
+};
+
+static void at91_pin_dbg(const struct device *dev, const struct at91_pmx_pin *pin)
+{
+       if (pin->mux) {
+               dev_dbg(dev, "pio%c%d configured as periph%c with conf = 0x%lu\n",
+                       pin->bank + 'A', pin->pin, pin->mux - 1 + 'A', pin->conf);
+       } else {
+               dev_dbg(dev, "pio%c%d configured as gpio with conf = 0x%lu\n",
+                       pin->bank + 'A', pin->pin, pin->conf);
+       }
+}
+
+static int pin_check_config(struct at91_pinctrl *info, const char* name,
+                           int index, const struct at91_pmx_pin *pin)
+{
+       int mux;
+
+       /* check if it's a valid config */
+       if (pin->bank >= info->nbanks) {
+               dev_err(info->dev, "%s: pin conf %d bank_id %d >= nbanks %d\n",
+                       name, index, pin->bank, info->nbanks);
+               return -EINVAL;
+       }
+
+       if (pin->pin >= MAX_NB_GPIO_PER_BANK) {
+               dev_err(info->dev, "%s: pin conf %d pin_bank_id %d >= %d\n",
+                       name, index, pin->pin, MAX_NB_GPIO_PER_BANK);
+               return -EINVAL;
+       }
+
+       if (!pin->mux)
+               return 0;
+
+       mux = pin->mux - 1;
+
+       if (mux >= info->nmux) {
+               dev_err(info->dev, "%s: pin conf %d mux_id %d >= nmux %d\n",
+                       name, index, mux, info->nmux);
+               return -EINVAL;
+       }
+
+       if (!(info->mux_mask[pin->bank * info->nmux + mux] & 1 << pin->pin)) {
+               dev_err(info->dev, "%s: pin conf %d mux_id %d not supported for pio%c%d\n",
+                       name, index, mux, pin->bank + 'A', pin->pin);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static void at91_mux_gpio_disable(void __iomem *pio, unsigned mask)
+{
+       writel_relaxed(mask, pio + PIO_PDR);
+}
+
+static void at91_mux_gpio_enable(void __iomem *pio, unsigned mask, bool input)
+{
+       writel_relaxed(mask, pio + PIO_PER);
+       writel_relaxed(mask, pio + (input ? PIO_ODR : PIO_OER));
+}
+
+static int at91_pmx_enable(struct pinctrl_dev *pctldev, unsigned selector,
+                          unsigned group)
+{
+       struct at91_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+       const struct at91_pmx_pin *pins_conf = info->groups[group].pins_conf;
+       const struct at91_pmx_pin *pin;
+       uint32_t npins = info->groups[group].npins;
+       int i, ret;
+       unsigned mask;
+       void __iomem *pio;
+
+       dev_dbg(info->dev, "enable function %s group %s\n",
+               info->functions[selector].name, info->groups[group].name);
+
+       /* first check that all the pins of the group are valid with a valid
+        * paramter */
+       for (i = 0; i < npins; i++) {
+               pin = &pins_conf[i];
+               ret = pin_check_config(info, info->groups[group].name, i, pin);
+               if (ret)
+                       return ret;
+       }
+
+       for (i = 0; i < npins; i++) {
+               pin = &pins_conf[i];
+               at91_pin_dbg(info->dev, pin);
+               pio = pin_to_controller(info, pin->bank);
+               mask = pin_to_mask(pin->pin);
+               at91_mux_disable_interrupt(pio, mask);
+               switch(pin->mux) {
+               case AT91_MUX_GPIO:
+                       at91_mux_gpio_enable(pio, mask, 1);
+                       break;
+               case AT91_MUX_PERIPH_A:
+                       info->ops->mux_A_periph(pio, mask);
+                       break;
+               case AT91_MUX_PERIPH_B:
+                       info->ops->mux_B_periph(pio, mask);
+                       break;
+               case AT91_MUX_PERIPH_C:
+                       if (!info->ops->mux_C_periph)
+                               return -EINVAL;
+                       info->ops->mux_C_periph(pio, mask);
+                       break;
+               case AT91_MUX_PERIPH_D:
+                       if (!info->ops->mux_D_periph)
+                               return -EINVAL;
+                       info->ops->mux_D_periph(pio, mask);
+                       break;
+               }
+               if (pin->mux)
+                       at91_mux_gpio_disable(pio, mask);
+       }
+
+       return 0;
+}
+
+static void at91_pmx_disable(struct pinctrl_dev *pctldev, unsigned selector,
+                          unsigned group)
+{
+       struct at91_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+       const struct at91_pmx_pin *pins_conf = info->groups[group].pins_conf;
+       const struct at91_pmx_pin *pin;
+       uint32_t npins = info->groups[group].npins;
+       int i;
+       unsigned mask;
+       void __iomem *pio;
+
+       for (i = 0; i < npins; i++) {
+               pin = &pins_conf[i];
+               at91_pin_dbg(info->dev, pin);
+               pio = pin_to_controller(info, pin->bank);
+               mask = pin_to_mask(pin->pin);
+               at91_mux_gpio_enable(pio, mask, 1);
+       }
+}
+
+static int at91_pmx_get_funcs_count(struct pinctrl_dev *pctldev)
+{
+       struct at91_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+       return info->nfunctions;
+}
+
+static const char *at91_pmx_get_func_name(struct pinctrl_dev *pctldev,
+                                         unsigned selector)
+{
+       struct at91_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+       return info->functions[selector].name;
+}
+
+static int at91_pmx_get_groups(struct pinctrl_dev *pctldev, unsigned selector,
+                              const char * const **groups,
+                              unsigned * const num_groups)
+{
+       struct at91_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+       *groups = info->functions[selector].groups;
+       *num_groups = info->functions[selector].ngroups;
+
+       return 0;
+}
+
+int at91_gpio_request_enable(struct pinctrl_dev *pctldev,
+                           struct pinctrl_gpio_range *range,
+                           unsigned offset)
+{
+       struct at91_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
+       struct at91_gpio_chip *at91_chip;
+       struct gpio_chip *chip;
+       unsigned mask;
+
+       if (!range) {
+               dev_err(npct->dev, "invalid range\n");
+               return -EINVAL;
+       }
+       if (!range->gc) {
+               dev_err(npct->dev, "missing GPIO chip in range\n");
+               return -EINVAL;
+       }
+       chip = range->gc;
+       at91_chip = container_of(chip, struct at91_gpio_chip, chip);
+
+       dev_dbg(npct->dev, "enable pin %u as GPIO\n", offset);
+
+       mask = 1 << (offset - chip->base);
+
+       dev_dbg(npct->dev, "enable pin %u as PIO%c%d 0x%x\n",
+               offset, 'A' + range->id, offset - chip->base, mask);
+
+       writel_relaxed(mask, at91_chip->regbase + PIO_PER);
+
+       return 0;
+}
+
+void at91_gpio_disable_free(struct pinctrl_dev *pctldev,
+                          struct pinctrl_gpio_range *range,
+                          unsigned offset)
+{
+       struct at91_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
+
+       dev_dbg(npct->dev, "disable pin %u as GPIO\n", offset);
+       /* Set the pin to some default state, GPIO is usually default */
+}
+
+static struct pinmux_ops at91_pmx_ops = {
+       .get_functions_count    = at91_pmx_get_funcs_count,
+       .get_function_name      = at91_pmx_get_func_name,
+       .get_function_groups    = at91_pmx_get_groups,
+       .enable                 = at91_pmx_enable,
+       .disable                = at91_pmx_disable,
+       .gpio_request_enable    = at91_gpio_request_enable,
+       .gpio_disable_free      = at91_gpio_disable_free,
+};
+
+static int at91_pinconf_get(struct pinctrl_dev *pctldev,
+                            unsigned pin_id, unsigned long *config)
+{
+       struct at91_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+       void __iomem *pio;
+       unsigned pin;
+
+       dev_dbg(info->dev, "%s:%d, pin_id=%d, config=0x%lx", __func__, __LINE__, pin_id, *config);
+       pio = pin_to_controller(info, pin_to_bank(pin_id));
+       pin = pin_id % MAX_NB_GPIO_PER_BANK;
+
+       if (at91_mux_get_multidrive(pio, pin))
+               *config |= MULTI_DRIVE;
+
+       if (at91_mux_get_pullup(pio, pin))
+               *config |= PULL_UP;
+
+       return 0;
+}
+
+static int at91_pinconf_set(struct pinctrl_dev *pctldev,
+                            unsigned pin_id, unsigned long config)
+{
+       struct at91_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+       unsigned mask;
+       void __iomem *pio;
+
+       dev_dbg(info->dev, "%s:%d, pin_id=%d, config=0x%lx", __func__, __LINE__, pin_id, config);
+       pio = pin_to_controller(info, pin_to_bank(pin_id));
+       mask = pin_to_mask(pin_id % MAX_NB_GPIO_PER_BANK);
+
+       at91_mux_set_pullup(pio, mask, config & PULL_UP);
+       at91_mux_set_multidrive(pio, mask, config & MULTI_DRIVE);
+       return 0;
+}
+
+static void at91_pinconf_dbg_show(struct pinctrl_dev *pctldev,
+                                  struct seq_file *s, unsigned pin_id)
+{
+
+}
+
+static void at91_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
+                                        struct seq_file *s, unsigned group)
+{
+}
+
+struct pinconf_ops at91_pinconf_ops = {
+       .pin_config_get                 = at91_pinconf_get,
+       .pin_config_set                 = at91_pinconf_set,
+       .pin_config_dbg_show            = at91_pinconf_dbg_show,
+       .pin_config_group_dbg_show      = at91_pinconf_group_dbg_show,
+};
+
+static struct pinctrl_desc at91_pinctrl_desc = {
+       .pctlops        = &at91_pctrl_ops,
+       .pmxops         = &at91_pmx_ops,
+       .confops        = &at91_pinconf_ops,
+       .owner          = THIS_MODULE,
+};
+
+static const char *gpio_compat = "atmel,at91rm9200-gpio";
+
+static void __devinit at91_pinctrl_child_count(struct at91_pinctrl *info,
+                                             struct device_node *np)
+{
+       struct device_node *child;
+
+       for_each_child_of_node(np, child) {
+               if (of_device_is_compatible(child, gpio_compat)) {
+                       info->nbanks++;
+               } else {
+                       info->nfunctions++;
+                       info->ngroups += of_get_child_count(child);
+               }
+       }
+}
+
+static int __devinit at91_pinctrl_mux_mask(struct at91_pinctrl *info,
+                                         struct device_node *np)
+{
+       int ret = 0;
+       int size;
+       const const __be32 *list;
+
+       list = of_get_property(np, "atmel,mux-mask", &size);
+       if (!list) {
+               dev_err(info->dev, "can not read the mux-mask of %d\n", size);
+               return -EINVAL;
+       }
+
+       size /= sizeof(*list);
+       if (!size || size % info->nbanks) {
+               dev_err(info->dev, "wrong mux mask array should be by %d\n", info->nbanks);
+               return -EINVAL;
+       }
+       info->nmux = size / info->nbanks;
+
+       info->mux_mask = devm_kzalloc(info->dev, sizeof(u32) * size, GFP_KERNEL);
+       if (!info->mux_mask) {
+               dev_err(info->dev, "could not alloc mux_mask\n");
+               return -ENOMEM;
+       }
+
+       ret = of_property_read_u32_array(np, "atmel,mux-mask",
+                                         info->mux_mask, size);
+       if (ret)
+               dev_err(info->dev, "can not read the mux-mask of %d\n", size);
+       return ret;
+}
+
+static int __devinit at91_pinctrl_parse_groups(struct device_node *np,
+                               struct at91_pin_group *grp,
+                               struct at91_pinctrl *info,
+                               u32 index)
+{
+       struct at91_pmx_pin *pin;
+       int size;
+       const const __be32 *list;
+       int i, j;
+
+       dev_dbg(info->dev, "group(%d): %s\n", index, np->name);
+
+       /* Initialise group */
+       grp->name = np->name;
+
+       /*
+        * the binding format is atmel,pins = <bank pin mux CONFIG ...>,
+        * do sanity check and calculate pins number
+        */
+       list = of_get_property(np, "atmel,pins", &size);
+       /* we do not check return since it's safe node passed down */
+       size /= sizeof(*list);
+       if (!size || size % 4) {
+               dev_err(info->dev, "wrong pins number or pins and configs should be by 4\n");
+               return -EINVAL;
+       }
+
+       grp->npins = size / 4;
+       pin = grp->pins_conf = devm_kzalloc(info->dev, grp->npins * sizeof(struct at91_pmx_pin),
+                               GFP_KERNEL);
+       grp->pins = devm_kzalloc(info->dev, grp->npins * sizeof(unsigned int),
+                               GFP_KERNEL);
+       if (!grp->pins_conf || !grp->pins)
+               return -ENOMEM;
+
+       for (i = 0, j = 0; i < size; i += 4, j++) {
+               pin->bank = be32_to_cpu(*list++);
+               pin->pin = be32_to_cpu(*list++);
+               grp->pins[j] = pin->bank * MAX_NB_GPIO_PER_BANK + pin->pin;
+               pin->mux = be32_to_cpu(*list++);
+               pin->conf = be32_to_cpu(*list++);
+
+               at91_pin_dbg(info->dev, pin);
+               pin++;
+       }
+
+       return 0;
+}
+
+static int __devinit at91_pinctrl_parse_functions(struct device_node *np,
+                       struct at91_pinctrl *info, u32 index)
+{
+       struct device_node *child;
+       struct at91_pmx_func *func;
+       struct at91_pin_group *grp;
+       int ret;
+       static u32 grp_index;
+       u32 i = 0;
+
+       dev_dbg(info->dev, "parse function(%d): %s\n", index, np->name);
+
+       func = &info->functions[index];
+
+       /* Initialise function */
+       func->name = np->name;
+       func->ngroups = of_get_child_count(np);
+       if (func->ngroups <= 0) {
+               dev_err(info->dev, "no groups defined\n");
+               return -EINVAL;
+       }
+       func->groups = devm_kzalloc(info->dev,
+                       func->ngroups * sizeof(char *), GFP_KERNEL);
+       if (!func->groups)
+               return -ENOMEM;
+
+       for_each_child_of_node(np, child) {
+               func->groups[i] = child->name;
+               grp = &info->groups[grp_index++];
+               ret = at91_pinctrl_parse_groups(child, grp, info, i++);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static struct of_device_id at91_pinctrl_of_match[] __devinitdata = {
+       { .compatible = "atmel,at91sam9x5-pinctrl", .data = &at91sam9x5_ops },
+       { .compatible = "atmel,at91rm9200-pinctrl", .data = &at91rm9200_ops },
+       { /* sentinel */ }
+};
+
+static int __devinit at91_pinctrl_probe_dt(struct platform_device *pdev,
+                                          struct at91_pinctrl *info)
+{
+       int ret = 0;
+       int i, j;
+       uint32_t *tmp;
+       struct device_node *np = pdev->dev.of_node;
+       struct device_node *child;
+
+       if (!np)
+               return -ENODEV;
+
+       info->dev = &pdev->dev;
+       info->ops =
+               of_match_device(at91_pinctrl_of_match, &pdev->dev)->data;
+       at91_pinctrl_child_count(info, np);
+
+       if (info->nbanks < 1) {
+               dev_err(&pdev->dev, "you need to specify atleast one gpio-controller\n");
+               return -EINVAL;
+       }
+
+       ret = at91_pinctrl_mux_mask(info, np);
+       if (ret)
+               return ret;
+
+       dev_dbg(&pdev->dev, "nmux = %d\n", info->nmux);
+
+       dev_dbg(&pdev->dev, "mux-mask\n");
+       tmp = info->mux_mask;
+       for (i = 0; i < info->nbanks; i++) {
+               for (j = 0; j < info->nmux; j++, tmp++) {
+                       dev_dbg(&pdev->dev, "%d:%d\t0x%x\n", i, j, tmp[0]);
+               }
+       }
+
+       dev_dbg(&pdev->dev, "nfunctions = %d\n", info->nfunctions);
+       dev_dbg(&pdev->dev, "ngroups = %d\n", info->ngroups);
+       info->functions = devm_kzalloc(&pdev->dev, info->nfunctions * sizeof(struct at91_pmx_func),
+                                       GFP_KERNEL);
+       if (!info->functions)
+               return -ENOMEM;
+
+       info->groups = devm_kzalloc(&pdev->dev, info->ngroups * sizeof(struct at91_pin_group),
+                                       GFP_KERNEL);
+       if (!info->groups)
+               return -ENOMEM;
+
+       dev_dbg(&pdev->dev, "nbanks = %d\n", info->nbanks);
+       dev_dbg(&pdev->dev, "nfunctions = %d\n", info->nfunctions);
+       dev_dbg(&pdev->dev, "ngroups = %d\n", info->ngroups);
+
+       i = 0;
+
+       for_each_child_of_node(np, child) {
+               if (of_device_is_compatible(child, gpio_compat))
+                       continue;
+               ret = at91_pinctrl_parse_functions(child, info, i++);
+               if (ret) {
+                       dev_err(&pdev->dev, "failed to parse function\n");
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+
+static int __devinit at91_pinctrl_probe(struct platform_device *pdev)
+{
+       struct at91_pinctrl *info;
+       struct pinctrl_pin_desc *pdesc;
+       int ret, i, j ,k;
+
+       info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
+       if (!info)
+               return -ENOMEM;
+
+       ret = at91_pinctrl_probe_dt(pdev, info);
+       if (ret)
+               return ret;
+
+       /*
+        * We need all the GPIO drivers to probe FIRST, or we will not be able
+        * to obtain references to the struct gpio_chip * for them, and we
+        * need this to proceed.
+        */
+       for (i = 0; i < info->nbanks; i++) {
+               if (!gpio_chips[i]) {
+                       dev_warn(&pdev->dev, "GPIO chip %d not registered yet\n", i);
+                       devm_kfree(&pdev->dev, info);
+                       return -EPROBE_DEFER;
+               }
+       }
+
+       at91_pinctrl_desc.name = dev_name(&pdev->dev);
+       at91_pinctrl_desc.npins = info->nbanks * MAX_NB_GPIO_PER_BANK;
+       at91_pinctrl_desc.pins = pdesc =
+               devm_kzalloc(&pdev->dev, sizeof(*pdesc) * at91_pinctrl_desc.npins, GFP_KERNEL);
+
+       if (!at91_pinctrl_desc.pins)
+               return -ENOMEM;
+
+       for (i = 0 , k = 0; i < info->nbanks; i++) {
+               for (j = 0; j < MAX_NB_GPIO_PER_BANK; j++, k++) {
+                       pdesc->number = k;
+                       pdesc->name = kasprintf(GFP_KERNEL, "pio%c%d", i + 'A', j);
+                       pdesc++;
+               }
+       }
+
+       platform_set_drvdata(pdev, info);
+       info->pctl = pinctrl_register(&at91_pinctrl_desc, &pdev->dev, info);
+
+       if (!info->pctl) {
+               dev_err(&pdev->dev, "could not register AT91 pinctrl driver\n");
+               ret = -EINVAL;
+               goto err;
+       }
+
+       /* We will handle a range of GPIO pins */
+       for (i = 0; i < info->nbanks; i++)
+               pinctrl_add_gpio_range(info->pctl, &gpio_chips[i]->range);
+
+       dev_info(&pdev->dev, "initialized AT91 pinctrl driver\n");
+
+       return 0;
+
+err:
+       return ret;
+}
+
+int __devexit at91_pinctrl_remove(struct platform_device *pdev)
+{
+       struct at91_pinctrl *info = platform_get_drvdata(pdev);
+
+       pinctrl_unregister(info->pctl);
+
+       return 0;
+}
+
+static int at91_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+       /*
+        * Map back to global GPIO space and request muxing, the direction
+        * parameter does not matter for this controller.
+        */
+       int gpio = chip->base + offset;
+       int bank = chip->base / chip->ngpio;
+
+       dev_dbg(chip->dev, "%s:%d pio%c%d(%d)\n", __func__, __LINE__,
+                'A' + bank, offset, gpio);
+
+       return pinctrl_request_gpio(gpio);
+}
+
+static void at91_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+       int gpio = chip->base + offset;
+
+       pinctrl_free_gpio(gpio);
+}
+
+static int at91_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+       struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
+       void __iomem *pio = at91_gpio->regbase;
+       unsigned mask = 1 << offset;
+
+       writel_relaxed(mask, pio + PIO_ODR);
+       return 0;
+}
+
+static int at91_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+       struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
+       void __iomem *pio = at91_gpio->regbase;
+       unsigned mask = 1 << offset;
+       u32 pdsr;
+
+       pdsr = readl_relaxed(pio + PIO_PDSR);
+       return (pdsr & mask) != 0;
+}
+
+static void at91_gpio_set(struct gpio_chip *chip, unsigned offset,
+                               int val)
+{
+       struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
+       void __iomem *pio = at91_gpio->regbase;
+       unsigned mask = 1 << offset;
+
+       writel_relaxed(mask, pio + (val ? PIO_SODR : PIO_CODR));
+}
+
+static int at91_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
+                               int val)
+{
+       struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
+       void __iomem *pio = at91_gpio->regbase;
+       unsigned mask = 1 << offset;
+
+       writel_relaxed(mask, pio + (val ? PIO_SODR : PIO_CODR));
+       writel_relaxed(mask, pio + PIO_OER);
+
+       return 0;
+}
+
+static int at91_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+       struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
+       int virq;
+
+       if (offset < chip->ngpio)
+               virq = irq_create_mapping(at91_gpio->domain, offset);
+       else
+               virq = -ENXIO;
+
+       dev_dbg(chip->dev, "%s: request IRQ for GPIO %d, return %d\n",
+                               chip->label, offset + chip->base, virq);
+       return virq;
+}
+
+#ifdef CONFIG_DEBUG_FS
+static void at91_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
+{
+       enum at91_mux mode;
+       int i;
+       struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
+       void __iomem *pio = at91_gpio->regbase;
+
+       for (i = 0; i < chip->ngpio; i++) {
+               unsigned pin = chip->base + i;
+               unsigned mask = pin_to_mask(pin);
+               const char *gpio_label;
+               u32 pdsr;
+
+               gpio_label = gpiochip_is_requested(chip, i);
+               if (!gpio_label)
+                       continue;
+               mode = at91_gpio->ops->get_periph(pio, mask);
+               seq_printf(s, "[%s] GPIO%s%d: ",
+                          gpio_label, chip->label, i);
+               if (mode == AT91_MUX_GPIO) {
+                       pdsr = readl_relaxed(pio + PIO_PDSR);
+
+                       seq_printf(s, "[gpio] %s\n",
+                                  pdsr & mask ?
+                                  "set" : "clear");
+               } else {
+                       seq_printf(s, "[periph %c]\n",
+                                  mode + 'A' - 1);
+               }
+       }
+}
+#else
+#define at91_gpio_dbg_show     NULL
+#endif
+
+/* Several AIC controller irqs are dispatched through this GPIO handler.
+ * To use any AT91_PIN_* as an externally triggered IRQ, first call
+ * at91_set_gpio_input() then maybe enable its glitch filter.
+ * Then just request_irq() with the pin ID; it works like any ARM IRQ
+ * handler.
+ * First implementation always triggers on rising and falling edges
+ * whereas the newer PIO3 can be additionally configured to trigger on
+ * level, edge with any polarity.
+ *
+ * Alternatively, certain pins may be used directly as IRQ0..IRQ6 after
+ * configuring them with at91_set_a_periph() or at91_set_b_periph().
+ * IRQ0..IRQ6 should be configurable, e.g. level vs edge triggering.
+ */
+
+static void gpio_irq_mask(struct irq_data *d)
+{
+       struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(d);
+       void __iomem    *pio = at91_gpio->regbase;
+       unsigned        mask = 1 << d->hwirq;
+
+       if (pio)
+               writel_relaxed(mask, pio + PIO_IDR);
+}
+
+static void gpio_irq_unmask(struct irq_data *d)
+{
+       struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(d);
+       void __iomem    *pio = at91_gpio->regbase;
+       unsigned        mask = 1 << d->hwirq;
+
+       if (pio)
+               writel_relaxed(mask, pio + PIO_IER);
+}
+
+static int gpio_irq_type(struct irq_data *d, unsigned type)
+{
+       switch (type) {
+       case IRQ_TYPE_NONE:
+       case IRQ_TYPE_EDGE_BOTH:
+               return 0;
+       default:
+               return -EINVAL;
+       }
+}
+
+/* Alternate irq type for PIO3 support */
+static int alt_gpio_irq_type(struct irq_data *d, unsigned type)
+{
+       struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(d);
+       void __iomem    *pio = at91_gpio->regbase;
+       unsigned        mask = 1 << d->hwirq;
+
+       switch (type) {
+       case IRQ_TYPE_EDGE_RISING:
+               writel_relaxed(mask, pio + PIO_ESR);
+               writel_relaxed(mask, pio + PIO_REHLSR);
+               break;
+       case IRQ_TYPE_EDGE_FALLING:
+               writel_relaxed(mask, pio + PIO_ESR);
+               writel_relaxed(mask, pio + PIO_FELLSR);
+               break;
+       case IRQ_TYPE_LEVEL_LOW:
+               writel_relaxed(mask, pio + PIO_LSR);
+               writel_relaxed(mask, pio + PIO_FELLSR);
+               break;
+       case IRQ_TYPE_LEVEL_HIGH:
+               writel_relaxed(mask, pio + PIO_LSR);
+               writel_relaxed(mask, pio + PIO_REHLSR);
+               break;
+       case IRQ_TYPE_EDGE_BOTH:
+               /*
+                * disable additional interrupt modes:
+                * fall back to default behavior
+                */
+               writel_relaxed(mask, pio + PIO_AIMDR);
+               return 0;
+       case IRQ_TYPE_NONE:
+       default:
+               pr_warn("AT91: No type for irq %d\n", gpio_to_irq(d->irq));
+               return -EINVAL;
+       }
+
+       /* enable additional interrupt modes */
+       writel_relaxed(mask, pio + PIO_AIMER);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int gpio_irq_set_wake(struct irq_data *d, unsigned state)
+{
+       struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(d);
+       unsigned        bank = at91_gpio->pioc_idx;
+
+       if (unlikely(bank >= MAX_GPIO_BANKS))
+               return -EINVAL;
+
+       irq_set_irq_wake(at91_gpio->pioc_virq, state);
+
+       return 0;
+}
+#else
+#define gpio_irq_set_wake      NULL
+#endif
+
+static struct irq_chip gpio_irqchip = {
+       .name           = "GPIO",
+       .irq_disable    = gpio_irq_mask,
+       .irq_mask       = gpio_irq_mask,
+       .irq_unmask     = gpio_irq_unmask,
+       /* .irq_set_type is set dynamically */
+       .irq_set_wake   = gpio_irq_set_wake,
+};
+
+static void gpio_irq_handler(unsigned irq, struct irq_desc *desc)
+{
+       struct irq_chip *chip = irq_desc_get_chip(desc);
+       struct irq_data *idata = irq_desc_get_irq_data(desc);
+       struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(idata);
+       void __iomem    *pio = at91_gpio->regbase;
+       unsigned long   isr;
+       int             n;
+
+       chained_irq_enter(chip, desc);
+       for (;;) {
+               /* Reading ISR acks pending (edge triggered) GPIO interrupts.
+                * When there none are pending, we're finished unless we need
+                * to process multiple banks (like ID_PIOCDE on sam9263).
+                */
+               isr = readl_relaxed(pio + PIO_ISR) & readl_relaxed(pio + PIO_IMR);
+               if (!isr) {
+                       if (!at91_gpio->next)
+                               break;
+                       at91_gpio = at91_gpio->next;
+                       pio = at91_gpio->regbase;
+                       continue;
+               }
+
+               n = find_first_bit(&isr, BITS_PER_LONG);
+               while (n < BITS_PER_LONG) {
+                       generic_handle_irq(irq_find_mapping(at91_gpio->domain, n));
+                       n = find_next_bit(&isr, BITS_PER_LONG, n + 1);
+               }
+       }
+       chained_irq_exit(chip, desc);
+       /* now it may re-trigger */
+}
+
+/*
+ * This lock class tells lockdep that GPIO irqs are in a different
+ * category than their parents, so it won't report false recursion.
+ */
+static struct lock_class_key gpio_lock_class;
+
+static int at91_gpio_irq_map(struct irq_domain *h, unsigned int virq,
+                                                       irq_hw_number_t hw)
+{
+       struct at91_gpio_chip   *at91_gpio = h->host_data;
+
+       irq_set_lockdep_class(virq, &gpio_lock_class);
+
+       /*
+        * Can use the "simple" and not "edge" handler since it's
+        * shorter, and the AIC handles interrupts sanely.
+        */
+       irq_set_chip_and_handler(virq, &gpio_irqchip,
+                                handle_simple_irq);
+       set_irq_flags(virq, IRQF_VALID);
+       irq_set_chip_data(virq, at91_gpio);
+
+       return 0;
+}
+
+static struct irq_domain_ops at91_gpio_ops = {
+       .map    = at91_gpio_irq_map,
+       .xlate  = irq_domain_xlate_twocell,
+};
+
+static int at91_gpio_of_irq_setup(struct device_node *node,
+                                 struct at91_gpio_chip *at91_gpio)
+{
+       struct at91_gpio_chip   *prev = NULL;
+       struct irq_data         *d = irq_get_irq_data(at91_gpio->pioc_virq);
+
+       at91_gpio->pioc_hwirq = irqd_to_hwirq(d);
+
+       /* Setup proper .irq_set_type function */
+       gpio_irqchip.irq_set_type = at91_gpio->ops->irq_type;
+
+       /* Disable irqs of this PIO controller */
+       writel_relaxed(~0, at91_gpio->regbase + PIO_IDR);
+
+       /* Setup irq domain */
+       at91_gpio->domain = irq_domain_add_linear(node, at91_gpio->chip.ngpio,
+                                               &at91_gpio_ops, at91_gpio);
+       if (!at91_gpio->domain)
+               panic("at91_gpio.%d: couldn't allocate irq domain (DT).\n",
+                       at91_gpio->pioc_idx);
+
+       /* Setup chained handler */
+       if (at91_gpio->pioc_idx)
+               prev = gpio_chips[at91_gpio->pioc_idx - 1];
+
+       /* The toplevel handler handles one bank of GPIOs, except
+        * on some SoC it can handles up to three...
+        * We only set up the handler for the first of the list.
+        */
+       if (prev && prev->next == at91_gpio)
+               return 0;
+
+       irq_set_chip_data(at91_gpio->pioc_virq, at91_gpio);
+       irq_set_chained_handler(at91_gpio->pioc_virq, gpio_irq_handler);
+
+       return 0;
+}
+
+/* This structure is replicated for each GPIO block allocated at probe time */
+static struct gpio_chip at91_gpio_template = {
+       .request                = at91_gpio_request,
+       .free                   = at91_gpio_free,
+       .direction_input        = at91_gpio_direction_input,
+       .get                    = at91_gpio_get,
+       .direction_output       = at91_gpio_direction_output,
+       .set                    = at91_gpio_set,
+       .to_irq                 = at91_gpio_to_irq,
+       .dbg_show               = at91_gpio_dbg_show,
+       .can_sleep              = 0,
+       .ngpio                  = MAX_NB_GPIO_PER_BANK,
+};
+
+static void __devinit at91_gpio_probe_fixup(void)
+{
+       unsigned i;
+       struct at91_gpio_chip *at91_gpio, *last = NULL;
+
+       for (i = 0; i < gpio_banks; i++) {
+               at91_gpio = gpio_chips[i];
+
+               /*
+                * GPIO controller are grouped on some SoC:
+                * PIOC, PIOD and PIOE can share the same IRQ line
+                */
+               if (last && last->pioc_virq == at91_gpio->pioc_virq)
+                       last->next = at91_gpio;
+               last = at91_gpio;
+       }
+}
+
+static struct of_device_id at91_gpio_of_match[] __devinitdata = {
+       { .compatible = "atmel,at91sam9x5-gpio", .data = &at91sam9x5_ops, },
+       { .compatible = "atmel,at91rm9200-gpio", .data = &at91rm9200_ops },
+       { /* sentinel */ }
+};
+
+static int __devinit at91_gpio_probe(struct platform_device *pdev)
+{
+       struct device_node *np = pdev->dev.of_node;
+       struct resource *res;
+       struct at91_gpio_chip *at91_chip = NULL;
+       struct gpio_chip *chip;
+       struct pinctrl_gpio_range *range;
+       int ret = 0;
+       int irq;
+       int alias_idx = of_alias_get_id(np, "gpio");
+       uint32_t ngpio;
+
+       BUG_ON(alias_idx >= ARRAY_SIZE(gpio_chips));
+       if (gpio_chips[alias_idx]) {
+               ret = -EBUSY;
+               goto err;
+       }
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               ret = -ENOENT;
+               goto err;
+       }
+
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0) {
+               ret = irq;
+               goto err;
+       }
+
+       at91_chip = devm_kzalloc(&pdev->dev, sizeof(*at91_chip), GFP_KERNEL);
+       if (!at91_chip) {
+               ret = -ENOMEM;
+               goto err;
+       }
+
+       at91_chip->regbase = devm_request_and_ioremap(&pdev->dev, res);
+       if (!at91_chip->regbase) {
+               dev_err(&pdev->dev, "failed to map registers, ignoring.\n");
+               ret = -EBUSY;
+               goto err;
+       }
+
+       at91_chip->ops =
+               of_match_device(at91_gpio_of_match, &pdev->dev)->data;
+       at91_chip->pioc_virq = irq;
+       at91_chip->pioc_idx = alias_idx;
+
+       at91_chip->clock = clk_get(&pdev->dev, NULL);
+       if (IS_ERR(at91_chip->clock)) {
+               dev_err(&pdev->dev, "failed to get clock, ignoring.\n");
+               goto err;
+       }
+
+       if (clk_prepare(at91_chip->clock))
+               goto clk_prep_err;
+
+       /* enable PIO controller's clock */
+       if (clk_enable(at91_chip->clock)) {
+               dev_err(&pdev->dev, "failed to enable clock, ignoring.\n");
+               goto clk_err;
+       }
+
+       at91_chip->chip = at91_gpio_template;
+
+       chip = &at91_chip->chip;
+       chip->of_node = np;
+       chip->label = dev_name(&pdev->dev);
+       chip->dev = &pdev->dev;
+       chip->owner = THIS_MODULE;
+       chip->base = alias_idx * MAX_NB_GPIO_PER_BANK;
+
+       if (!of_property_read_u32(np, "#gpio-lines", &ngpio)) {
+               if (ngpio >= MAX_NB_GPIO_PER_BANK)
+                       pr_err("at91_gpio.%d, gpio-nb >= %d failback to %d\n",
+                              alias_idx, MAX_NB_GPIO_PER_BANK, MAX_NB_GPIO_PER_BANK);
+               else
+                       chip->ngpio = ngpio;
+       }
+
+       range = &at91_chip->range;
+       range->name = chip->label;
+       range->id = alias_idx;
+       range->pin_base = range->base = range->id * MAX_NB_GPIO_PER_BANK;
+
+       range->npins = chip->ngpio;
+       range->gc = chip;
+
+       ret = gpiochip_add(chip);
+       if (ret)
+               goto clk_err;
+
+       gpio_chips[alias_idx] = at91_chip;
+       gpio_banks = max(gpio_banks, alias_idx + 1);
+
+       at91_gpio_probe_fixup();
+
+       at91_gpio_of_irq_setup(np, at91_chip);
+
+       dev_info(&pdev->dev, "at address %p\n", at91_chip->regbase);
+
+       return 0;
+
+clk_err:
+       clk_unprepare(at91_chip->clock);
+clk_prep_err:
+       clk_put(at91_chip->clock);
+err:
+       dev_err(&pdev->dev, "Failure %i for GPIO %i\n", ret, alias_idx);
+
+       return ret;
+}
+
+static struct platform_driver at91_gpio_driver = {
+       .driver = {
+               .name = "gpio-at91",
+               .owner = THIS_MODULE,
+               .of_match_table = of_match_ptr(at91_gpio_of_match),
+       },
+       .probe = at91_gpio_probe,
+};
+
+static struct platform_driver at91_pinctrl_driver = {
+       .driver = {
+               .name = "pinctrl-at91",
+               .owner = THIS_MODULE,
+               .of_match_table = of_match_ptr(at91_pinctrl_of_match),
+       },
+       .probe = at91_pinctrl_probe,
+       .remove = __devexit_p(at91_pinctrl_remove),
+};
+
+static int __init at91_pinctrl_init(void)
+{
+       int ret;
+
+       ret = platform_driver_register(&at91_gpio_driver);
+       if (ret)
+               return ret;
+       return platform_driver_register(&at91_pinctrl_driver);
+}
+arch_initcall(at91_pinctrl_init);
+
+static void __exit at91_pinctrl_exit(void)
+{
+       platform_driver_unregister(&at91_pinctrl_driver);
+}
+
+module_exit(at91_pinctrl_exit);
+MODULE_AUTHOR("Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>");
+MODULE_DESCRIPTION("Atmel AT91 pinctrl driver");
+MODULE_LICENSE("GPL v2");
index b446c9641212884f8cb2ff5e7df0d81aa032dca3..5c7daf9169e8ba44008afb681c6a108b72aa7d39 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/delay.h>
 #include <linux/errno.h>
 #include <linux/io.h>
+#include <linux/irqdomain.h>
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/platform_device.h>
@@ -64,10 +65,8 @@ struct u300_gpio {
        struct gpio_chip chip;
        struct list_head port_list;
        struct clk *clk;
-       struct resource *memres;
        void __iomem *base;
        struct device *dev;
-       int irq_base;
        u32 stride;
        /* Register offsets */
        u32 pcr;
@@ -83,6 +82,7 @@ struct u300_gpio_port {
        struct list_head node;
        struct u300_gpio *gpio;
        char name[8];
+       struct irq_domain *domain;
        int irq;
        int number;
        u8 toggle_edge_mode;
@@ -314,10 +314,30 @@ static int u300_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
 static int u300_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
 {
        struct u300_gpio *gpio = to_u300_gpio(chip);
-       int retirq = gpio->irq_base + offset;
+       int portno = offset >> 3;
+       struct u300_gpio_port *port = NULL;
+       struct list_head *p;
+       int retirq;
+
+       list_for_each(p, &gpio->port_list) {
+               port = list_entry(p, struct u300_gpio_port, node);
+               if (port->number == portno)
+                       break;
+       }
+       if (port == NULL) {
+               dev_err(gpio->dev, "could not locate port for GPIO %d IRQ\n",
+                       offset);
+               return -EINVAL;
+       }
+
+       /*
+        * The local hwirqs on the port are the lower three bits, there
+        * are exactly 8 IRQs per port since they are 8-bit
+        */
+       retirq = irq_find_mapping(port->domain, (offset & 0x7));
 
-       dev_dbg(gpio->dev, "request IRQ for GPIO %d, return %d\n", offset,
-               retirq);
+       dev_dbg(gpio->dev, "request IRQ for GPIO %d, return %d from port %d\n",
+               offset, retirq, port->number);
        return retirq;
 }
 
@@ -467,7 +487,7 @@ static int u300_gpio_irq_type(struct irq_data *d, unsigned trigger)
 {
        struct u300_gpio_port *port = irq_data_get_irq_chip_data(d);
        struct u300_gpio *gpio = port->gpio;
-       int offset = d->irq - gpio->irq_base;
+       int offset = (port->number << 3) + d->hwirq;
        u32 val;
 
        if ((trigger & IRQF_TRIGGER_RISING) &&
@@ -503,10 +523,12 @@ static void u300_gpio_irq_enable(struct irq_data *d)
 {
        struct u300_gpio_port *port = irq_data_get_irq_chip_data(d);
        struct u300_gpio *gpio = port->gpio;
-       int offset = d->irq - gpio->irq_base;
+       int offset = (port->number << 3) + d->hwirq;
        u32 val;
        unsigned long flags;
 
+       dev_dbg(gpio->dev, "enable IRQ for hwirq %lu on port %s, offset %d\n",
+                d->hwirq, port->name, offset);
        local_irq_save(flags);
        val = readl(U300_PIN_REG(offset, ien));
        writel(val | U300_PIN_BIT(offset), U300_PIN_REG(offset, ien));
@@ -517,7 +539,7 @@ static void u300_gpio_irq_disable(struct irq_data *d)
 {
        struct u300_gpio_port *port = irq_data_get_irq_chip_data(d);
        struct u300_gpio *gpio = port->gpio;
-       int offset = d->irq - gpio->irq_base;
+       int offset = (port->number << 3) + d->hwirq;
        u32 val;
        unsigned long flags;
 
@@ -555,8 +577,7 @@ static void u300_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
                int irqoffset;
 
                for_each_set_bit(irqoffset, &val, U300_GPIO_PINS_PER_PORT) {
-                       int pin_irq = gpio->irq_base + (port->number << 3)
-                               + irqoffset;
+                       int pin_irq = irq_find_mapping(port->domain, irqoffset);
                        int offset = pinoffset + irqoffset;
 
                        dev_dbg(gpio->dev, "GPIO IRQ %d on pin %d\n",
@@ -631,6 +652,8 @@ static inline void u300_gpio_free_ports(struct u300_gpio *gpio)
        list_for_each_safe(p, n, &gpio->port_list) {
                port = list_entry(p, struct u300_gpio_port, node);
                list_del(&port->node);
+               if (port->domain)
+                       irq_domain_remove(port->domain);
                kfree(port);
        }
 }
@@ -639,56 +662,46 @@ static int __init u300_gpio_probe(struct platform_device *pdev)
 {
        struct u300_gpio_platform *plat = dev_get_platdata(&pdev->dev);
        struct u300_gpio *gpio;
+       struct resource *memres;
        int err = 0;
        int portno;
        u32 val;
        u32 ifr;
        int i;
 
-       gpio = kzalloc(sizeof(struct u300_gpio), GFP_KERNEL);
-       if (gpio == NULL) {
-               dev_err(&pdev->dev, "failed to allocate memory\n");
+       gpio = devm_kzalloc(&pdev->dev, sizeof(struct u300_gpio), GFP_KERNEL);
+       if (gpio == NULL)
                return -ENOMEM;
-       }
 
        gpio->chip = u300_gpio_chip;
        gpio->chip.ngpio = plat->ports * U300_GPIO_PINS_PER_PORT;
-       gpio->irq_base = plat->gpio_irq_base;
        gpio->chip.dev = &pdev->dev;
        gpio->chip.base = plat->gpio_base;
        gpio->dev = &pdev->dev;
 
-       /* Get GPIO clock */
-       gpio->clk = clk_get(gpio->dev, NULL);
+       memres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!memres) {
+               dev_err(gpio->dev, "could not get GPIO memory resource\n");
+               return -ENODEV;
+       }
+
+       gpio->base = devm_request_and_ioremap(&pdev->dev, memres);
+       if (!gpio->base) {
+               dev_err(gpio->dev, "could not get remap memory\n");
+               return -ENOMEM;
+       }
+
+       gpio->clk = devm_clk_get(gpio->dev, NULL);
        if (IS_ERR(gpio->clk)) {
                err = PTR_ERR(gpio->clk);
                dev_err(gpio->dev, "could not get GPIO clock\n");
-               goto err_no_clk;
+               return err;
        }
+
        err = clk_prepare_enable(gpio->clk);
        if (err) {
                dev_err(gpio->dev, "could not enable GPIO clock\n");
-               goto err_no_clk_enable;
-       }
-
-       gpio->memres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!gpio->memres) {
-               dev_err(gpio->dev, "could not get GPIO memory resource\n");
-               err = -ENODEV;
-               goto err_no_resource;
-       }
-
-       if (!request_mem_region(gpio->memres->start,
-                               resource_size(gpio->memres),
-                               "GPIO Controller")) {
-               err = -ENODEV;
-               goto err_no_ioregion;
-       }
-
-       gpio->base = ioremap(gpio->memres->start, resource_size(gpio->memres));
-       if (!gpio->base) {
-               err = -ENOMEM;
-               goto err_no_ioremap;
+               return err;
        }
 
        dev_info(gpio->dev,
@@ -732,18 +745,26 @@ static int __init u300_gpio_probe(struct platform_device *pdev)
                port->irq = platform_get_irq_byname(pdev,
                                                    port->name);
 
-               dev_dbg(gpio->dev, "register IRQ %d for %s\n", port->irq,
+               dev_dbg(gpio->dev, "register IRQ %d for port %s\n", port->irq,
                        port->name);
 
+               port->domain = irq_domain_add_linear(pdev->dev.of_node,
+                                                    U300_GPIO_PINS_PER_PORT,
+                                                    &irq_domain_simple_ops,
+                                                    port);
+               if (!port->domain)
+                       goto err_no_domain;
+
                irq_set_chained_handler(port->irq, u300_gpio_irq_handler);
                irq_set_handler_data(port->irq, port);
 
                /* For each GPIO pin set the unique IRQ handler */
                for (i = 0; i < U300_GPIO_PINS_PER_PORT; i++) {
-                       int irqno = gpio->irq_base + (portno << 3) + i;
+                       int irqno = irq_create_mapping(port->domain, i);
 
-                       dev_dbg(gpio->dev, "handler for IRQ %d on %s\n",
-                               irqno, port->name);
+                       dev_dbg(gpio->dev, "GPIO%d on port %s gets IRQ %d\n",
+                               gpio->chip.base + (port->number << 3) + i,
+                               port->name, irqno);
                        irq_set_chip_and_handler(irqno, &u300_gpio_irqchip,
                                                 handle_simple_irq);
                        set_irq_flags(irqno, IRQF_VALID);
@@ -776,18 +797,10 @@ static int __init u300_gpio_probe(struct platform_device *pdev)
 err_no_pinctrl:
        err = gpiochip_remove(&gpio->chip);
 err_no_chip:
+err_no_domain:
 err_no_port:
        u300_gpio_free_ports(gpio);
-       iounmap(gpio->base);
-err_no_ioremap:
-       release_mem_region(gpio->memres->start, resource_size(gpio->memres));
-err_no_ioregion:
-err_no_resource:
        clk_disable_unprepare(gpio->clk);
-err_no_clk_enable:
-       clk_put(gpio->clk);
-err_no_clk:
-       kfree(gpio);
        dev_info(&pdev->dev, "module ERROR:%d\n", err);
        return err;
 }
@@ -806,13 +819,8 @@ static int __exit u300_gpio_remove(struct platform_device *pdev)
                return err;
        }
        u300_gpio_free_ports(gpio);
-       iounmap(gpio->base);
-       release_mem_region(gpio->memres->start,
-                          resource_size(gpio->memres));
        clk_disable_unprepare(gpio->clk);
-       clk_put(gpio->clk);
        platform_set_drvdata(pdev, NULL);
-       kfree(gpio);
        return 0;
 }
 
index 21362f48d3700424244b2870cbfa0cb437af6f66..73a0aa27cd560a45c8e5efb859140a4c6cc55bed 100644 (file)
@@ -40,46 +40,46 @@ static const struct of_device_id exynos_wkup_irq_ids[] = {
 
 static void exynos_gpio_irq_unmask(struct irq_data *irqd)
 {
-       struct samsung_pinctrl_drv_data *d = irqd->domain->host_data;
-       struct exynos_geint_data *edata = irq_data_get_irq_handler_data(irqd);
-       unsigned long reg_mask = d->ctrl->geint_mask + edata->eint_offset;
+       struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
+       struct samsung_pinctrl_drv_data *d = bank->drvdata;
+       unsigned long reg_mask = d->ctrl->geint_mask + bank->eint_offset;
        unsigned long mask;
 
        mask = readl(d->virt_base + reg_mask);
-       mask &= ~(1 << edata->pin);
+       mask &= ~(1 << irqd->hwirq);
        writel(mask, d->virt_base + reg_mask);
 }
 
 static void exynos_gpio_irq_mask(struct irq_data *irqd)
 {
-       struct samsung_pinctrl_drv_data *d = irqd->domain->host_data;
-       struct exynos_geint_data *edata = irq_data_get_irq_handler_data(irqd);
-       unsigned long reg_mask = d->ctrl->geint_mask + edata->eint_offset;
+       struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
+       struct samsung_pinctrl_drv_data *d = bank->drvdata;
+       unsigned long reg_mask = d->ctrl->geint_mask + bank->eint_offset;
        unsigned long mask;
 
        mask = readl(d->virt_base + reg_mask);
-       mask |= 1 << edata->pin;
+       mask |= 1 << irqd->hwirq;
        writel(mask, d->virt_base + reg_mask);
 }
 
 static void exynos_gpio_irq_ack(struct irq_data *irqd)
 {
-       struct samsung_pinctrl_drv_data *d = irqd->domain->host_data;
-       struct exynos_geint_data *edata = irq_data_get_irq_handler_data(irqd);
-       unsigned long reg_pend = d->ctrl->geint_pend + edata->eint_offset;
+       struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
+       struct samsung_pinctrl_drv_data *d = bank->drvdata;
+       unsigned long reg_pend = d->ctrl->geint_pend + bank->eint_offset;
 
-       writel(1 << edata->pin, d->virt_base + reg_pend);
+       writel(1 << irqd->hwirq, d->virt_base + reg_pend);
 }
 
 static int exynos_gpio_irq_set_type(struct irq_data *irqd, unsigned int type)
 {
-       struct samsung_pinctrl_drv_data *d = irqd->domain->host_data;
+       struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
+       struct samsung_pinctrl_drv_data *d = bank->drvdata;
        struct samsung_pin_ctrl *ctrl = d->ctrl;
-       struct exynos_geint_data *edata = irq_data_get_irq_handler_data(irqd);
-       struct samsung_pin_bank *bank = edata->bank;
-       unsigned int shift = EXYNOS_EINT_CON_LEN * edata->pin;
+       unsigned int pin = irqd->hwirq;
+       unsigned int shift = EXYNOS_EINT_CON_LEN * pin;
        unsigned int con, trig_type;
-       unsigned long reg_con = ctrl->geint_con + edata->eint_offset;
+       unsigned long reg_con = ctrl->geint_con + bank->eint_offset;
        unsigned int mask;
 
        switch (type) {
@@ -114,7 +114,7 @@ static int exynos_gpio_irq_set_type(struct irq_data *irqd, unsigned int type)
        writel(con, d->virt_base + reg_con);
 
        reg_con = bank->pctl_offset;
-       shift = edata->pin * bank->func_width;
+       shift = pin * bank->func_width;
        mask = (1 << bank->func_width) - 1;
 
        con = readl(d->virt_base + reg_con);
@@ -136,82 +136,23 @@ static struct irq_chip exynos_gpio_irq_chip = {
        .irq_set_type   = exynos_gpio_irq_set_type,
 };
 
-/*
- * given a controller-local external gpio interrupt number, prepare the handler
- * data for it.
- */
-static struct exynos_geint_data *exynos_get_eint_data(irq_hw_number_t hw,
-                               struct samsung_pinctrl_drv_data *d)
-{
-       struct samsung_pin_bank *bank = d->ctrl->pin_banks;
-       struct exynos_geint_data *eint_data;
-       unsigned int nr_banks = d->ctrl->nr_banks, idx;
-       unsigned int irq_base = 0, eint_offset = 0;
-
-       if (hw >= d->ctrl->nr_gint) {
-               dev_err(d->dev, "unsupported ext-gpio interrupt\n");
-               return NULL;
-       }
-
-       for (idx = 0; idx < nr_banks; idx++, bank++) {
-               if (bank->eint_type != EINT_TYPE_GPIO)
-                       continue;
-               if ((hw >= irq_base) && (hw < (irq_base + bank->nr_pins)))
-                       break;
-               irq_base += bank->nr_pins;
-               eint_offset += 4;
-       }
-
-       if (idx == nr_banks) {
-               dev_err(d->dev, "pin bank not found for ext-gpio interrupt\n");
-               return NULL;
-       }
-
-       eint_data = devm_kzalloc(d->dev, sizeof(*eint_data), GFP_KERNEL);
-       if (!eint_data) {
-               dev_err(d->dev, "no memory for eint-gpio data\n");
-               return NULL;
-       }
-
-       eint_data->bank = bank;
-       eint_data->pin = hw - irq_base;
-       eint_data->eint_offset = eint_offset;
-       return eint_data;
-}
-
 static int exynos_gpio_irq_map(struct irq_domain *h, unsigned int virq,
                                        irq_hw_number_t hw)
 {
-       struct samsung_pinctrl_drv_data *d = h->host_data;
-       struct exynos_geint_data *eint_data;
+       struct samsung_pin_bank *b = h->host_data;
 
-       eint_data = exynos_get_eint_data(hw, d);
-       if (!eint_data)
-               return -EINVAL;
-
-       irq_set_handler_data(virq, eint_data);
-       irq_set_chip_data(virq, h->host_data);
+       irq_set_chip_data(virq, b);
        irq_set_chip_and_handler(virq, &exynos_gpio_irq_chip,
                                        handle_level_irq);
        set_irq_flags(virq, IRQF_VALID);
        return 0;
 }
 
-static void exynos_gpio_irq_unmap(struct irq_domain *h, unsigned int virq)
-{
-       struct samsung_pinctrl_drv_data *d = h->host_data;
-       struct exynos_geint_data *eint_data;
-
-       eint_data = irq_get_handler_data(virq);
-       devm_kfree(d->dev, eint_data);
-}
-
 /*
  * irq domain callbacks for external gpio interrupt controller.
  */
 static const struct irq_domain_ops exynos_gpio_irqd_ops = {
        .map    = exynos_gpio_irq_map,
-       .unmap  = exynos_gpio_irq_unmap,
        .xlate  = irq_domain_xlate_twocell,
 };
 
@@ -230,7 +171,7 @@ static irqreturn_t exynos_eint_gpio_irq(int irq, void *data)
                return IRQ_HANDLED;
        bank += (group - 1);
 
-       virq = irq_linear_revmap(d->gpio_irqd, bank->irq_base + pin);
+       virq = irq_linear_revmap(bank->irq_domain, pin);
        if (!virq)
                return IRQ_NONE;
        generic_handle_irq(virq);
@@ -243,8 +184,10 @@ static irqreturn_t exynos_eint_gpio_irq(int irq, void *data)
  */
 static int exynos_eint_gpio_init(struct samsung_pinctrl_drv_data *d)
 {
+       struct samsung_pin_bank *bank;
        struct device *dev = d->dev;
        unsigned int ret;
+       unsigned int i;
 
        if (!d->irq) {
                dev_err(dev, "irq number not available\n");
@@ -258,11 +201,16 @@ static int exynos_eint_gpio_init(struct samsung_pinctrl_drv_data *d)
                return -ENXIO;
        }
 
-       d->gpio_irqd = irq_domain_add_linear(dev->of_node, d->ctrl->nr_gint,
-                               &exynos_gpio_irqd_ops, d);
-       if (!d->gpio_irqd) {
-               dev_err(dev, "gpio irq domain allocation failed\n");
-               return -ENXIO;
+       bank = d->ctrl->pin_banks;
+       for (i = 0; i < d->ctrl->nr_banks; ++i, ++bank) {
+               if (bank->eint_type != EINT_TYPE_GPIO)
+                       continue;
+               bank->irq_domain = irq_domain_add_linear(bank->of_node,
+                               bank->nr_pins, &exynos_gpio_irqd_ops, bank);
+               if (!bank->irq_domain) {
+                       dev_err(dev, "gpio irq domain add failed\n");
+                       return -ENXIO;
+               }
        }
 
        return 0;
@@ -270,48 +218,46 @@ static int exynos_eint_gpio_init(struct samsung_pinctrl_drv_data *d)
 
 static void exynos_wkup_irq_unmask(struct irq_data *irqd)
 {
-       struct samsung_pinctrl_drv_data *d = irq_data_get_irq_chip_data(irqd);
-       unsigned int bank = irqd->hwirq / EXYNOS_EINT_MAX_PER_BANK;
-       unsigned int pin = irqd->hwirq & (EXYNOS_EINT_MAX_PER_BANK - 1);
-       unsigned long reg_mask = d->ctrl->weint_mask + (bank << 2);
+       struct samsung_pin_bank *b = irq_data_get_irq_chip_data(irqd);
+       struct samsung_pinctrl_drv_data *d = b->drvdata;
+       unsigned long reg_mask = d->ctrl->weint_mask + b->eint_offset;
        unsigned long mask;
 
        mask = readl(d->virt_base + reg_mask);
-       mask &= ~(1 << pin);
+       mask &= ~(1 << irqd->hwirq);
        writel(mask, d->virt_base + reg_mask);
 }
 
 static void exynos_wkup_irq_mask(struct irq_data *irqd)
 {
-       struct samsung_pinctrl_drv_data *d = irq_data_get_irq_chip_data(irqd);
-       unsigned int bank = irqd->hwirq / EXYNOS_EINT_MAX_PER_BANK;
-       unsigned int pin = irqd->hwirq & (EXYNOS_EINT_MAX_PER_BANK - 1);
-       unsigned long reg_mask = d->ctrl->weint_mask + (bank << 2);
+       struct samsung_pin_bank *b = irq_data_get_irq_chip_data(irqd);
+       struct samsung_pinctrl_drv_data *d = b->drvdata;
+       unsigned long reg_mask = d->ctrl->weint_mask + b->eint_offset;
        unsigned long mask;
 
        mask = readl(d->virt_base + reg_mask);
-       mask |= 1 << pin;
+       mask |= 1 << irqd->hwirq;
        writel(mask, d->virt_base + reg_mask);
 }
 
 static void exynos_wkup_irq_ack(struct irq_data *irqd)
 {
-       struct samsung_pinctrl_drv_data *d = irq_data_get_irq_chip_data(irqd);
-       unsigned int bank = irqd->hwirq / EXYNOS_EINT_MAX_PER_BANK;
-       unsigned int pin = irqd->hwirq & (EXYNOS_EINT_MAX_PER_BANK - 1);
-       unsigned long pend = d->ctrl->weint_pend + (bank << 2);
+       struct samsung_pin_bank *b = irq_data_get_irq_chip_data(irqd);
+       struct samsung_pinctrl_drv_data *d = b->drvdata;
+       unsigned long pend = d->ctrl->weint_pend + b->eint_offset;
 
-       writel(1 << pin, d->virt_base + pend);
+       writel(1 << irqd->hwirq, d->virt_base + pend);
 }
 
 static int exynos_wkup_irq_set_type(struct irq_data *irqd, unsigned int type)
 {
-       struct samsung_pinctrl_drv_data *d = irq_data_get_irq_chip_data(irqd);
-       unsigned int bank = irqd->hwirq / EXYNOS_EINT_MAX_PER_BANK;
-       unsigned int pin = irqd->hwirq & (EXYNOS_EINT_MAX_PER_BANK - 1);
-       unsigned long reg_con = d->ctrl->weint_con + (bank << 2);
+       struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
+       struct samsung_pinctrl_drv_data *d = bank->drvdata;
+       unsigned int pin = irqd->hwirq;
+       unsigned long reg_con = d->ctrl->weint_con + bank->eint_offset;
        unsigned long shift = EXYNOS_EINT_CON_LEN * pin;
        unsigned long con, trig_type;
+       unsigned int mask;
 
        switch (type) {
        case IRQ_TYPE_EDGE_RISING:
@@ -343,6 +289,16 @@ static int exynos_wkup_irq_set_type(struct irq_data *irqd, unsigned int type)
        con &= ~(EXYNOS_EINT_CON_MASK << shift);
        con |= trig_type << shift;
        writel(con, d->virt_base + reg_con);
+
+       reg_con = bank->pctl_offset;
+       shift = pin * bank->func_width;
+       mask = (1 << bank->func_width) - 1;
+
+       con = readl(d->virt_base + reg_con);
+       con &= ~(mask << shift);
+       con |= EXYNOS_EINT_FUNC << shift;
+       writel(con, d->virt_base + reg_con);
+
        return 0;
 }
 
@@ -361,6 +317,7 @@ static struct irq_chip exynos_wkup_irq_chip = {
 static void exynos_irq_eint0_15(unsigned int irq, struct irq_desc *desc)
 {
        struct exynos_weint_data *eintd = irq_get_handler_data(irq);
+       struct samsung_pin_bank *bank = eintd->bank;
        struct irq_chip *chip = irq_get_chip(irq);
        int eint_irq;
 
@@ -370,20 +327,20 @@ static void exynos_irq_eint0_15(unsigned int irq, struct irq_desc *desc)
        if (chip->irq_ack)
                chip->irq_ack(&desc->irq_data);
 
-       eint_irq = irq_linear_revmap(eintd->domain, eintd->irq);
+       eint_irq = irq_linear_revmap(bank->irq_domain, eintd->irq);
        generic_handle_irq(eint_irq);
        chip->irq_unmask(&desc->irq_data);
        chained_irq_exit(chip, desc);
 }
 
-static inline void exynos_irq_demux_eint(int irq_base, unsigned long pend,
-                                       struct irq_domain *domain)
+static inline void exynos_irq_demux_eint(unsigned long pend,
+                                               struct irq_domain *domain)
 {
        unsigned int irq;
 
        while (pend) {
                irq = fls(pend) - 1;
-               generic_handle_irq(irq_find_mapping(domain, irq_base + irq));
+               generic_handle_irq(irq_find_mapping(domain, irq));
                pend &= ~(1 << irq);
        }
 }
@@ -392,18 +349,22 @@ static inline void exynos_irq_demux_eint(int irq_base, unsigned long pend,
 static void exynos_irq_demux_eint16_31(unsigned int irq, struct irq_desc *desc)
 {
        struct irq_chip *chip = irq_get_chip(irq);
-       struct exynos_weint_data *eintd = irq_get_handler_data(irq);
-       struct samsung_pinctrl_drv_data *d = eintd->domain->host_data;
+       struct exynos_muxed_weint_data *eintd = irq_get_handler_data(irq);
+       struct samsung_pinctrl_drv_data *d = eintd->banks[0]->drvdata;
+       struct samsung_pin_ctrl *ctrl = d->ctrl;
        unsigned long pend;
        unsigned long mask;
+       int i;
 
        chained_irq_enter(chip, desc);
-       pend = readl(d->virt_base + d->ctrl->weint_pend + 0x8);
-       mask = readl(d->virt_base + d->ctrl->weint_mask + 0x8);
-       exynos_irq_demux_eint(16, pend & ~mask, eintd->domain);
-       pend = readl(d->virt_base + d->ctrl->weint_pend + 0xC);
-       mask = readl(d->virt_base + d->ctrl->weint_mask + 0xC);
-       exynos_irq_demux_eint(24, pend & ~mask, eintd->domain);
+
+       for (i = 0; i < eintd->nr_banks; ++i) {
+               struct samsung_pin_bank *b = eintd->banks[i];
+               pend = readl(d->virt_base + ctrl->weint_pend + b->eint_offset);
+               mask = readl(d->virt_base + ctrl->weint_mask + b->eint_offset);
+               exynos_irq_demux_eint(pend & ~mask, b->irq_domain);
+       }
+
        chained_irq_exit(chip, desc);
 }
 
@@ -433,7 +394,11 @@ static int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d)
        struct device *dev = d->dev;
        struct device_node *wkup_np = NULL;
        struct device_node *np;
+       struct samsung_pin_bank *bank;
        struct exynos_weint_data *weint_data;
+       struct exynos_muxed_weint_data *muxed_data;
+       unsigned int muxed_banks = 0;
+       unsigned int i;
        int idx, irq;
 
        for_each_child_of_node(dev->of_node, np) {
@@ -445,90 +410,124 @@ static int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d)
        if (!wkup_np)
                return -ENODEV;
 
-       d->wkup_irqd = irq_domain_add_linear(wkup_np, d->ctrl->nr_wint,
-                               &exynos_wkup_irqd_ops, d);
-       if (!d->wkup_irqd) {
-               dev_err(dev, "wakeup irq domain allocation failed\n");
-               return -ENXIO;
-       }
+       bank = d->ctrl->pin_banks;
+       for (i = 0; i < d->ctrl->nr_banks; ++i, ++bank) {
+               if (bank->eint_type != EINT_TYPE_WKUP)
+                       continue;
 
-       weint_data = devm_kzalloc(dev, sizeof(*weint_data) * 17, GFP_KERNEL);
-       if (!weint_data) {
-               dev_err(dev, "could not allocate memory for weint_data\n");
-               return -ENOMEM;
-       }
+               bank->irq_domain = irq_domain_add_linear(bank->of_node,
+                               bank->nr_pins, &exynos_wkup_irqd_ops, bank);
+               if (!bank->irq_domain) {
+                       dev_err(dev, "wkup irq domain add failed\n");
+                       return -ENXIO;
+               }
 
-       irq = irq_of_parse_and_map(wkup_np, 16);
-       if (irq) {
-               weint_data[16].domain = d->wkup_irqd;
-               irq_set_chained_handler(irq, exynos_irq_demux_eint16_31);
-               irq_set_handler_data(irq, &weint_data[16]);
-       } else {
-               dev_err(dev, "irq number for EINT16-32 not found\n");
-       }
+               if (!of_find_property(bank->of_node, "interrupts", NULL)) {
+                       bank->eint_type = EINT_TYPE_WKUP_MUX;
+                       ++muxed_banks;
+                       continue;
+               }
 
-       for (idx = 0; idx < 16; idx++) {
-               weint_data[idx].domain = d->wkup_irqd;
-               weint_data[idx].irq = idx;
+               weint_data = devm_kzalloc(dev, bank->nr_pins
+                                       * sizeof(*weint_data), GFP_KERNEL);
+               if (!weint_data) {
+                       dev_err(dev, "could not allocate memory for weint_data\n");
+                       return -ENOMEM;
+               }
 
-               irq = irq_of_parse_and_map(wkup_np, idx);
-               if (irq) {
+               for (idx = 0; idx < bank->nr_pins; ++idx) {
+                       irq = irq_of_parse_and_map(bank->of_node, idx);
+                       if (!irq) {
+                               dev_err(dev, "irq number for eint-%s-%d not found\n",
+                                                       bank->name, idx);
+                               continue;
+                       }
+                       weint_data[idx].irq = idx;
+                       weint_data[idx].bank = bank;
                        irq_set_handler_data(irq, &weint_data[idx]);
                        irq_set_chained_handler(irq, exynos_irq_eint0_15);
-               } else {
-                       dev_err(dev, "irq number for eint-%x not found\n", idx);
                }
        }
+
+       if (!muxed_banks)
+               return 0;
+
+       irq = irq_of_parse_and_map(wkup_np, 0);
+       if (!irq) {
+               dev_err(dev, "irq number for muxed EINTs not found\n");
+               return 0;
+       }
+
+       muxed_data = devm_kzalloc(dev, sizeof(*muxed_data)
+               + muxed_banks*sizeof(struct samsung_pin_bank *), GFP_KERNEL);
+       if (!muxed_data) {
+               dev_err(dev, "could not allocate memory for muxed_data\n");
+               return -ENOMEM;
+       }
+
+       irq_set_chained_handler(irq, exynos_irq_demux_eint16_31);
+       irq_set_handler_data(irq, muxed_data);
+
+       bank = d->ctrl->pin_banks;
+       idx = 0;
+       for (i = 0; i < d->ctrl->nr_banks; ++i, ++bank) {
+               if (bank->eint_type != EINT_TYPE_WKUP_MUX)
+                       continue;
+
+               muxed_data->banks[idx++] = bank;
+       }
+       muxed_data->nr_banks = muxed_banks;
+
        return 0;
 }
 
 /* pin banks of exynos4210 pin-controller 0 */
 static struct samsung_pin_bank exynos4210_pin_banks0[] = {
-       EXYNOS_PIN_BANK_EINTG(0x000, EXYNOS4210_GPIO_A0, "gpa0"),
-       EXYNOS_PIN_BANK_EINTG(0x020, EXYNOS4210_GPIO_A1, "gpa1"),
-       EXYNOS_PIN_BANK_EINTG(0x040, EXYNOS4210_GPIO_B, "gpb"),
-       EXYNOS_PIN_BANK_EINTG(0x060, EXYNOS4210_GPIO_C0, "gpc0"),
-       EXYNOS_PIN_BANK_EINTG(0x080, EXYNOS4210_GPIO_C1, "gpc1"),
-       EXYNOS_PIN_BANK_EINTG(0x0A0, EXYNOS4210_GPIO_D0, "gpd0"),
-       EXYNOS_PIN_BANK_EINTG(0x0C0, EXYNOS4210_GPIO_D1, "gpd1"),
-       EXYNOS_PIN_BANK_EINTG(0x0E0, EXYNOS4210_GPIO_E0, "gpe0"),
-       EXYNOS_PIN_BANK_EINTG(0x100, EXYNOS4210_GPIO_E1, "gpe1"),
-       EXYNOS_PIN_BANK_EINTG(0x120, EXYNOS4210_GPIO_E2, "gpe2"),
-       EXYNOS_PIN_BANK_EINTG(0x140, EXYNOS4210_GPIO_E3, "gpe3"),
-       EXYNOS_PIN_BANK_EINTG(0x160, EXYNOS4210_GPIO_E4, "gpe4"),
-       EXYNOS_PIN_BANK_EINTG(0x180, EXYNOS4210_GPIO_F0, "gpf0"),
-       EXYNOS_PIN_BANK_EINTG(0x1A0, EXYNOS4210_GPIO_F1, "gpf1"),
-       EXYNOS_PIN_BANK_EINTG(0x1C0, EXYNOS4210_GPIO_F2, "gpf2"),
-       EXYNOS_PIN_BANK_EINTG(0x1E0, EXYNOS4210_GPIO_F3, "gpf3"),
+       EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpa0", 0x00),
+       EXYNOS_PIN_BANK_EINTG(6, 0x020, "gpa1", 0x04),
+       EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpb", 0x08),
+       EXYNOS_PIN_BANK_EINTG(5, 0x060, "gpc0", 0x0c),
+       EXYNOS_PIN_BANK_EINTG(5, 0x080, "gpc1", 0x10),
+       EXYNOS_PIN_BANK_EINTG(4, 0x0A0, "gpd0", 0x14),
+       EXYNOS_PIN_BANK_EINTG(4, 0x0C0, "gpd1", 0x18),
+       EXYNOS_PIN_BANK_EINTG(5, 0x0E0, "gpe0", 0x1c),
+       EXYNOS_PIN_BANK_EINTG(8, 0x100, "gpe1", 0x20),
+       EXYNOS_PIN_BANK_EINTG(6, 0x120, "gpe2", 0x24),
+       EXYNOS_PIN_BANK_EINTG(8, 0x140, "gpe3", 0x28),
+       EXYNOS_PIN_BANK_EINTG(8, 0x160, "gpe4", 0x2c),
+       EXYNOS_PIN_BANK_EINTG(8, 0x180, "gpf0", 0x30),
+       EXYNOS_PIN_BANK_EINTG(8, 0x1A0, "gpf1", 0x34),
+       EXYNOS_PIN_BANK_EINTG(8, 0x1C0, "gpf2", 0x38),
+       EXYNOS_PIN_BANK_EINTG(6, 0x1E0, "gpf3", 0x3c),
 };
 
 /* pin banks of exynos4210 pin-controller 1 */
 static struct samsung_pin_bank exynos4210_pin_banks1[] = {
-       EXYNOS_PIN_BANK_EINTG(0x000, EXYNOS4210_GPIO_J0, "gpj0"),
-       EXYNOS_PIN_BANK_EINTG(0x020, EXYNOS4210_GPIO_J1, "gpj1"),
-       EXYNOS_PIN_BANK_EINTG(0x040, EXYNOS4210_GPIO_K0, "gpk0"),
-       EXYNOS_PIN_BANK_EINTG(0x060, EXYNOS4210_GPIO_K1, "gpk1"),
-       EXYNOS_PIN_BANK_EINTG(0x080, EXYNOS4210_GPIO_K2, "gpk2"),
-       EXYNOS_PIN_BANK_EINTG(0x0A0, EXYNOS4210_GPIO_K3, "gpk3"),
-       EXYNOS_PIN_BANK_EINTG(0x0C0, EXYNOS4210_GPIO_L0, "gpl0"),
-       EXYNOS_PIN_BANK_EINTG(0x0E0, EXYNOS4210_GPIO_L1, "gpl1"),
-       EXYNOS_PIN_BANK_EINTG(0x100, EXYNOS4210_GPIO_L2, "gpl2"),
-       EXYNOS_PIN_BANK_EINTN(0x120, EXYNOS4210_GPIO_Y0, "gpy0"),
-       EXYNOS_PIN_BANK_EINTN(0x140, EXYNOS4210_GPIO_Y1, "gpy1"),
-       EXYNOS_PIN_BANK_EINTN(0x160, EXYNOS4210_GPIO_Y2, "gpy2"),
-       EXYNOS_PIN_BANK_EINTN(0x180, EXYNOS4210_GPIO_Y3, "gpy3"),
-       EXYNOS_PIN_BANK_EINTN(0x1A0, EXYNOS4210_GPIO_Y4, "gpy4"),
-       EXYNOS_PIN_BANK_EINTN(0x1C0, EXYNOS4210_GPIO_Y5, "gpy5"),
-       EXYNOS_PIN_BANK_EINTN(0x1E0, EXYNOS4210_GPIO_Y6, "gpy6"),
-       EXYNOS_PIN_BANK_EINTN(0xC00, EXYNOS4210_GPIO_X0, "gpx0"),
-       EXYNOS_PIN_BANK_EINTN(0xC20, EXYNOS4210_GPIO_X1, "gpx1"),
-       EXYNOS_PIN_BANK_EINTN(0xC40, EXYNOS4210_GPIO_X2, "gpx2"),
-       EXYNOS_PIN_BANK_EINTN(0xC60, EXYNOS4210_GPIO_X3, "gpx3"),
+       EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpj0", 0x00),
+       EXYNOS_PIN_BANK_EINTG(5, 0x020, "gpj1", 0x04),
+       EXYNOS_PIN_BANK_EINTG(7, 0x040, "gpk0", 0x08),
+       EXYNOS_PIN_BANK_EINTG(7, 0x060, "gpk1", 0x0c),
+       EXYNOS_PIN_BANK_EINTG(7, 0x080, "gpk2", 0x10),
+       EXYNOS_PIN_BANK_EINTG(7, 0x0A0, "gpk3", 0x14),
+       EXYNOS_PIN_BANK_EINTG(8, 0x0C0, "gpl0", 0x18),
+       EXYNOS_PIN_BANK_EINTG(3, 0x0E0, "gpl1", 0x1c),
+       EXYNOS_PIN_BANK_EINTG(8, 0x100, "gpl2", 0x20),
+       EXYNOS_PIN_BANK_EINTN(6, 0x120, "gpy0"),
+       EXYNOS_PIN_BANK_EINTN(4, 0x140, "gpy1"),
+       EXYNOS_PIN_BANK_EINTN(6, 0x160, "gpy2"),
+       EXYNOS_PIN_BANK_EINTN(8, 0x180, "gpy3"),
+       EXYNOS_PIN_BANK_EINTN(8, 0x1A0, "gpy4"),
+       EXYNOS_PIN_BANK_EINTN(8, 0x1C0, "gpy5"),
+       EXYNOS_PIN_BANK_EINTN(8, 0x1E0, "gpy6"),
+       EXYNOS_PIN_BANK_EINTW(8, 0xC00, "gpx0", 0x00),
+       EXYNOS_PIN_BANK_EINTW(8, 0xC20, "gpx1", 0x04),
+       EXYNOS_PIN_BANK_EINTW(8, 0xC40, "gpx2", 0x08),
+       EXYNOS_PIN_BANK_EINTW(8, 0xC60, "gpx3", 0x0c),
 };
 
 /* pin banks of exynos4210 pin-controller 2 */
 static struct samsung_pin_bank exynos4210_pin_banks2[] = {
-       EXYNOS_PIN_BANK_EINTN(0x000, EXYNOS4210_GPIO_Z, "gpz"),
+       EXYNOS_PIN_BANK_EINTN(7, 0x000, "gpz"),
 };
 
 /*
@@ -540,9 +539,6 @@ struct samsung_pin_ctrl exynos4210_pin_ctrl[] = {
                /* pin-controller instance 0 data */
                .pin_banks      = exynos4210_pin_banks0,
                .nr_banks       = ARRAY_SIZE(exynos4210_pin_banks0),
-               .base           = EXYNOS4210_GPIO_A0_START,
-               .nr_pins        = EXYNOS4210_GPIOA_NR_PINS,
-               .nr_gint        = EXYNOS4210_GPIOA_NR_GINT,
                .geint_con      = EXYNOS_GPIO_ECON_OFFSET,
                .geint_mask     = EXYNOS_GPIO_EMASK_OFFSET,
                .geint_pend     = EXYNOS_GPIO_EPEND_OFFSET,
@@ -553,10 +549,6 @@ struct samsung_pin_ctrl exynos4210_pin_ctrl[] = {
                /* pin-controller instance 1 data */
                .pin_banks      = exynos4210_pin_banks1,
                .nr_banks       = ARRAY_SIZE(exynos4210_pin_banks1),
-               .base           = EXYNOS4210_GPIOA_NR_PINS,
-               .nr_pins        = EXYNOS4210_GPIOB_NR_PINS,
-               .nr_gint        = EXYNOS4210_GPIOB_NR_GINT,
-               .nr_wint        = 32,
                .geint_con      = EXYNOS_GPIO_ECON_OFFSET,
                .geint_mask     = EXYNOS_GPIO_EMASK_OFFSET,
                .geint_pend     = EXYNOS_GPIO_EPEND_OFFSET,
@@ -571,9 +563,6 @@ struct samsung_pin_ctrl exynos4210_pin_ctrl[] = {
                /* pin-controller instance 2 data */
                .pin_banks      = exynos4210_pin_banks2,
                .nr_banks       = ARRAY_SIZE(exynos4210_pin_banks2),
-               .base           = EXYNOS4210_GPIOA_NR_PINS +
-                                       EXYNOS4210_GPIOB_NR_PINS,
-               .nr_pins        = EXYNOS4210_GPIOC_NR_PINS,
                .label          = "exynos4210-gpio-ctrl2",
        },
 };
index 31d0a06174e4a21f53253f9c947ce1d90006a1e7..0a708890d8b4431c701c58b5af9de62782ec0a18 100644 (file)
  * (at your option) any later version.
  */
 
-#define EXYNOS_GPIO_START(__gpio)      ((__gpio##_START) + (__gpio##_NR))
-
-#define EXYNOS4210_GPIO_A0_NR  (8)
-#define EXYNOS4210_GPIO_A1_NR  (6)
-#define EXYNOS4210_GPIO_B_NR   (8)
-#define EXYNOS4210_GPIO_C0_NR  (5)
-#define EXYNOS4210_GPIO_C1_NR  (5)
-#define EXYNOS4210_GPIO_D0_NR  (4)
-#define EXYNOS4210_GPIO_D1_NR  (4)
-#define EXYNOS4210_GPIO_E0_NR  (5)
-#define EXYNOS4210_GPIO_E1_NR  (8)
-#define EXYNOS4210_GPIO_E2_NR  (6)
-#define EXYNOS4210_GPIO_E3_NR  (8)
-#define EXYNOS4210_GPIO_E4_NR  (8)
-#define EXYNOS4210_GPIO_F0_NR  (8)
-#define EXYNOS4210_GPIO_F1_NR  (8)
-#define EXYNOS4210_GPIO_F2_NR  (8)
-#define EXYNOS4210_GPIO_F3_NR  (6)
-#define EXYNOS4210_GPIO_J0_NR  (8)
-#define EXYNOS4210_GPIO_J1_NR  (5)
-#define EXYNOS4210_GPIO_K0_NR  (7)
-#define EXYNOS4210_GPIO_K1_NR  (7)
-#define EXYNOS4210_GPIO_K2_NR  (7)
-#define EXYNOS4210_GPIO_K3_NR  (7)
-#define EXYNOS4210_GPIO_L0_NR  (8)
-#define EXYNOS4210_GPIO_L1_NR  (3)
-#define EXYNOS4210_GPIO_L2_NR  (8)
-#define EXYNOS4210_GPIO_Y0_NR  (6)
-#define EXYNOS4210_GPIO_Y1_NR  (4)
-#define EXYNOS4210_GPIO_Y2_NR  (6)
-#define EXYNOS4210_GPIO_Y3_NR  (8)
-#define EXYNOS4210_GPIO_Y4_NR  (8)
-#define EXYNOS4210_GPIO_Y5_NR  (8)
-#define EXYNOS4210_GPIO_Y6_NR  (8)
-#define EXYNOS4210_GPIO_X0_NR  (8)
-#define EXYNOS4210_GPIO_X1_NR  (8)
-#define EXYNOS4210_GPIO_X2_NR  (8)
-#define EXYNOS4210_GPIO_X3_NR  (8)
-#define EXYNOS4210_GPIO_Z_NR   (7)
-
-enum exynos4210_gpio_xa_start {
-       EXYNOS4210_GPIO_A0_START        = 0,
-       EXYNOS4210_GPIO_A1_START        = EXYNOS_GPIO_START(EXYNOS4210_GPIO_A0),
-       EXYNOS4210_GPIO_B_START         = EXYNOS_GPIO_START(EXYNOS4210_GPIO_A1),
-       EXYNOS4210_GPIO_C0_START        = EXYNOS_GPIO_START(EXYNOS4210_GPIO_B),
-       EXYNOS4210_GPIO_C1_START        = EXYNOS_GPIO_START(EXYNOS4210_GPIO_C0),
-       EXYNOS4210_GPIO_D0_START        = EXYNOS_GPIO_START(EXYNOS4210_GPIO_C1),
-       EXYNOS4210_GPIO_D1_START        = EXYNOS_GPIO_START(EXYNOS4210_GPIO_D0),
-       EXYNOS4210_GPIO_E0_START        = EXYNOS_GPIO_START(EXYNOS4210_GPIO_D1),
-       EXYNOS4210_GPIO_E1_START        = EXYNOS_GPIO_START(EXYNOS4210_GPIO_E0),
-       EXYNOS4210_GPIO_E2_START        = EXYNOS_GPIO_START(EXYNOS4210_GPIO_E1),
-       EXYNOS4210_GPIO_E3_START        = EXYNOS_GPIO_START(EXYNOS4210_GPIO_E2),
-       EXYNOS4210_GPIO_E4_START        = EXYNOS_GPIO_START(EXYNOS4210_GPIO_E3),
-       EXYNOS4210_GPIO_F0_START        = EXYNOS_GPIO_START(EXYNOS4210_GPIO_E4),
-       EXYNOS4210_GPIO_F1_START        = EXYNOS_GPIO_START(EXYNOS4210_GPIO_F0),
-       EXYNOS4210_GPIO_F2_START        = EXYNOS_GPIO_START(EXYNOS4210_GPIO_F1),
-       EXYNOS4210_GPIO_F3_START        = EXYNOS_GPIO_START(EXYNOS4210_GPIO_F2),
-};
-
-enum exynos4210_gpio_xb_start {
-       EXYNOS4210_GPIO_J0_START        = 0,
-       EXYNOS4210_GPIO_J1_START        = EXYNOS_GPIO_START(EXYNOS4210_GPIO_J0),
-       EXYNOS4210_GPIO_K0_START        = EXYNOS_GPIO_START(EXYNOS4210_GPIO_J1),
-       EXYNOS4210_GPIO_K1_START        = EXYNOS_GPIO_START(EXYNOS4210_GPIO_K0),
-       EXYNOS4210_GPIO_K2_START        = EXYNOS_GPIO_START(EXYNOS4210_GPIO_K1),
-       EXYNOS4210_GPIO_K3_START        = EXYNOS_GPIO_START(EXYNOS4210_GPIO_K2),
-       EXYNOS4210_GPIO_L0_START        = EXYNOS_GPIO_START(EXYNOS4210_GPIO_K3),
-       EXYNOS4210_GPIO_L1_START        = EXYNOS_GPIO_START(EXYNOS4210_GPIO_L0),
-       EXYNOS4210_GPIO_L2_START        = EXYNOS_GPIO_START(EXYNOS4210_GPIO_L1),
-       EXYNOS4210_GPIO_Y0_START        = EXYNOS_GPIO_START(EXYNOS4210_GPIO_L2),
-       EXYNOS4210_GPIO_Y1_START        = EXYNOS_GPIO_START(EXYNOS4210_GPIO_Y0),
-       EXYNOS4210_GPIO_Y2_START        = EXYNOS_GPIO_START(EXYNOS4210_GPIO_Y1),
-       EXYNOS4210_GPIO_Y3_START        = EXYNOS_GPIO_START(EXYNOS4210_GPIO_Y2),
-       EXYNOS4210_GPIO_Y4_START        = EXYNOS_GPIO_START(EXYNOS4210_GPIO_Y3),
-       EXYNOS4210_GPIO_Y5_START        = EXYNOS_GPIO_START(EXYNOS4210_GPIO_Y4),
-       EXYNOS4210_GPIO_Y6_START        = EXYNOS_GPIO_START(EXYNOS4210_GPIO_Y5),
-       EXYNOS4210_GPIO_X0_START        = EXYNOS_GPIO_START(EXYNOS4210_GPIO_Y6),
-       EXYNOS4210_GPIO_X1_START        = EXYNOS_GPIO_START(EXYNOS4210_GPIO_X0),
-       EXYNOS4210_GPIO_X2_START        = EXYNOS_GPIO_START(EXYNOS4210_GPIO_X1),
-       EXYNOS4210_GPIO_X3_START        = EXYNOS_GPIO_START(EXYNOS4210_GPIO_X2),
-};
-
-enum exynos4210_gpio_xc_start {
-       EXYNOS4210_GPIO_Z_START         = 0,
-};
-
-#define        EXYNOS4210_GPIO_A0_IRQ          EXYNOS4210_GPIO_A0_START
-#define        EXYNOS4210_GPIO_A1_IRQ          EXYNOS4210_GPIO_A1_START
-#define        EXYNOS4210_GPIO_B_IRQ           EXYNOS4210_GPIO_B_START
-#define        EXYNOS4210_GPIO_C0_IRQ          EXYNOS4210_GPIO_C0_START
-#define        EXYNOS4210_GPIO_C1_IRQ          EXYNOS4210_GPIO_C1_START
-#define        EXYNOS4210_GPIO_D0_IRQ          EXYNOS4210_GPIO_D0_START
-#define        EXYNOS4210_GPIO_D1_IRQ          EXYNOS4210_GPIO_D1_START
-#define        EXYNOS4210_GPIO_E0_IRQ          EXYNOS4210_GPIO_E0_START
-#define        EXYNOS4210_GPIO_E1_IRQ          EXYNOS4210_GPIO_E1_START
-#define        EXYNOS4210_GPIO_E2_IRQ          EXYNOS4210_GPIO_E2_START
-#define        EXYNOS4210_GPIO_E3_IRQ          EXYNOS4210_GPIO_E3_START
-#define        EXYNOS4210_GPIO_E4_IRQ          EXYNOS4210_GPIO_E4_START
-#define        EXYNOS4210_GPIO_F0_IRQ          EXYNOS4210_GPIO_F0_START
-#define        EXYNOS4210_GPIO_F1_IRQ          EXYNOS4210_GPIO_F1_START
-#define        EXYNOS4210_GPIO_F2_IRQ          EXYNOS4210_GPIO_F2_START
-#define        EXYNOS4210_GPIO_F3_IRQ          EXYNOS4210_GPIO_F3_START
-#define        EXYNOS4210_GPIO_J0_IRQ          EXYNOS4210_GPIO_J0_START
-#define        EXYNOS4210_GPIO_J1_IRQ          EXYNOS4210_GPIO_J1_START
-#define        EXYNOS4210_GPIO_K0_IRQ          EXYNOS4210_GPIO_K0_START
-#define        EXYNOS4210_GPIO_K1_IRQ          EXYNOS4210_GPIO_K1_START
-#define        EXYNOS4210_GPIO_K2_IRQ          EXYNOS4210_GPIO_K2_START
-#define        EXYNOS4210_GPIO_K3_IRQ          EXYNOS4210_GPIO_K3_START
-#define        EXYNOS4210_GPIO_L0_IRQ          EXYNOS4210_GPIO_L0_START
-#define        EXYNOS4210_GPIO_L1_IRQ          EXYNOS4210_GPIO_L1_START
-#define        EXYNOS4210_GPIO_L2_IRQ          EXYNOS4210_GPIO_L2_START
-#define        EXYNOS4210_GPIO_Z_IRQ           EXYNOS4210_GPIO_Z_START
-
-#define EXYNOS4210_GPIOA_NR_PINS       EXYNOS_GPIO_START(EXYNOS4210_GPIO_F3)
-#define EXYNOS4210_GPIOA_NR_GINT       EXYNOS_GPIO_START(EXYNOS4210_GPIO_F3)
-#define EXYNOS4210_GPIOB_NR_PINS       EXYNOS_GPIO_START(EXYNOS4210_GPIO_X3)
-#define EXYNOS4210_GPIOB_NR_GINT       EXYNOS_GPIO_START(EXYNOS4210_GPIO_L2)
-#define EXYNOS4210_GPIOC_NR_PINS       EXYNOS_GPIO_START(EXYNOS4210_GPIO_Z)
-
 /* External GPIO and wakeup interrupt related definitions */
 #define EXYNOS_GPIO_ECON_OFFSET                0x700
 #define EXYNOS_GPIO_EMASK_OFFSET       0x900
@@ -165,11 +46,10 @@ enum exynos4210_gpio_xc_start {
 #define EXYNOS_EINT_MAX_PER_BANK       8
 #define EXYNOS_EINT_NR_WKUP_EINT
 
-#define EXYNOS_PIN_BANK_EINTN(reg, __gpio, id)         \
+#define EXYNOS_PIN_BANK_EINTN(pins, reg, id)           \
        {                                               \
                .pctl_offset    = reg,                  \
-               .pin_base       = (__gpio##_START),     \
-               .nr_pins        = (__gpio##_NR),        \
+               .nr_pins        = pins,                 \
                .func_width     = 4,                    \
                .pud_width      = 2,                    \
                .drv_width      = 2,                    \
@@ -179,40 +59,50 @@ enum exynos4210_gpio_xc_start {
                .name           = id                    \
        }
 
-#define EXYNOS_PIN_BANK_EINTG(reg, __gpio, id)         \
+#define EXYNOS_PIN_BANK_EINTG(pins, reg, id, offs)     \
        {                                               \
                .pctl_offset    = reg,                  \
-               .pin_base       = (__gpio##_START),     \
-               .nr_pins        = (__gpio##_NR),        \
+               .nr_pins        = pins,                 \
                .func_width     = 4,                    \
                .pud_width      = 2,                    \
                .drv_width      = 2,                    \
                .conpdn_width   = 2,                    \
                .pudpdn_width   = 2,                    \
                .eint_type      = EINT_TYPE_GPIO,       \
-               .irq_base       = (__gpio##_IRQ),       \
+               .eint_offset    = offs,                 \
                .name           = id                    \
        }
 
-/**
- * struct exynos_geint_data: gpio eint specific data for irq_chip callbacks.
- * @bank: pin bank from which this gpio interrupt originates.
- * @pin: pin number within the bank.
- * @eint_offset: offset to be added to the con/pend/mask register bank base.
- */
-struct exynos_geint_data {
-       struct samsung_pin_bank *bank;
-       u32                     pin;
-       u32                     eint_offset;
-};
+#define EXYNOS_PIN_BANK_EINTW(pins, reg, id, offs)     \
+       {                                               \
+               .pctl_offset    = reg,                  \
+               .nr_pins        = pins,                 \
+               .func_width     = 4,                    \
+               .pud_width      = 2,                    \
+               .drv_width      = 2,                    \
+               .eint_type      = EINT_TYPE_WKUP,       \
+               .eint_offset    = offs,                 \
+               .name           = id                    \
+       }
 
 /**
  * struct exynos_weint_data: irq specific data for all the wakeup interrupts
  * generated by the external wakeup interrupt controller.
- * @domain: irq domain representing the external wakeup interrupts
  * @irq: interrupt number within the domain.
+ * @bank: bank responsible for this interrupt
  */
 struct exynos_weint_data {
-       struct irq_domain       *domain;
-       u32                     irq;
+       unsigned int irq;
+       struct samsung_pin_bank *bank;
+};
+
+/**
+ * struct exynos_muxed_weint_data: irq specific data for muxed wakeup interrupts
+ * generated by the external wakeup interrupt controller.
+ * @nr_banks: count of banks being part of the mux
+ * @banks: array of banks being part of the mux
+ */
+struct exynos_muxed_weint_data {
+       unsigned int nr_banks;
+       struct samsung_pin_bank *banks[];
 };
index debaa75b0552d6daeefc24e4d5ee4dd929baca76..ef6f26d6ab71cc60a3d219d86138166785e0954d 100644 (file)
@@ -600,14 +600,66 @@ static const unsigned usbsim_c_2_pins[] = { DB8500_PIN_AF8 };
 static const unsigned i2c3_c_2_pins[] = { DB8500_PIN_AG7, DB8500_PIN_AF7 };
 
 /* Other C1 column */
+static const unsigned u2rx_oc1_1_pins[] = { DB8500_PIN_AB2 };
+static const unsigned stmape_oc1_1_pins[] = { DB8500_PIN_AA4, DB8500_PIN_Y4,
+       DB8500_PIN_Y2, DB8500_PIN_AA2, DB8500_PIN_AA1 };
+static const unsigned remap0_oc1_1_pins[] = { DB8500_PIN_E1 };
+static const unsigned remap1_oc1_1_pins[] = { DB8500_PIN_E2 };
+static const unsigned ptma9_oc1_1_pins[] = { DB8500_PIN_G5, DB8500_PIN_G4,
+       DB8500_PIN_H4, DB8500_PIN_H3, DB8500_PIN_J3, DB8500_PIN_H2,
+       DB8500_PIN_J2, DB8500_PIN_H1 };
 static const unsigned kp_oc1_1_pins[] = { DB8500_PIN_C6, DB8500_PIN_B3,
        DB8500_PIN_C4, DB8500_PIN_E6, DB8500_PIN_A3, DB8500_PIN_B6,
        DB8500_PIN_D6, DB8500_PIN_B7 };
+static const unsigned rf_oc1_1_pins[] = { DB8500_PIN_D8, DB8500_PIN_D9 };
+static const unsigned hxclk_oc1_1_pins[] = { DB8500_PIN_D16 };
+static const unsigned uartmodrx_oc1_1_pins[] = { DB8500_PIN_B17 };
+static const unsigned uartmodtx_oc1_1_pins[] = { DB8500_PIN_C16 };
+static const unsigned stmmod_oc1_1_pins[] = { DB8500_PIN_C19, DB8500_PIN_C17,
+       DB8500_PIN_A18, DB8500_PIN_C18, DB8500_PIN_B19 };
+static const unsigned hxgpio_oc1_1_pins[] = { DB8500_PIN_D21, DB8500_PIN_D20,
+       DB8500_PIN_C20, DB8500_PIN_B21, DB8500_PIN_C21, DB8500_PIN_A22,
+       DB8500_PIN_B24, DB8500_PIN_C22 };
+static const unsigned rf_oc1_2_pins[] = { DB8500_PIN_C23, DB8500_PIN_D23 };
 static const unsigned spi2_oc1_1_pins[] = { DB8500_PIN_AH13, DB8500_PIN_AG12,
        DB8500_PIN_AH12, DB8500_PIN_AH11 };
 static const unsigned spi2_oc1_2_pins[] = { DB8500_PIN_AH13, DB8500_PIN_AH12,
        DB8500_PIN_AH11 };
 
+/* Other C2 column */
+static const unsigned sbag_oc2_1_pins[] = { DB8500_PIN_AA4, DB8500_PIN_AB2,
+       DB8500_PIN_Y4, DB8500_PIN_Y2, DB8500_PIN_AA2, DB8500_PIN_AA1 };
+static const unsigned etmr4_oc2_1_pins[] = { DB8500_PIN_G5, DB8500_PIN_G4,
+       DB8500_PIN_H4, DB8500_PIN_H3, DB8500_PIN_J3, DB8500_PIN_H2,
+       DB8500_PIN_J2, DB8500_PIN_H1 };
+static const unsigned ptma9_oc2_1_pins[] = { DB8500_PIN_D17, DB8500_PIN_D16,
+       DB8500_PIN_B17, DB8500_PIN_C16, DB8500_PIN_C19, DB8500_PIN_C17,
+       DB8500_PIN_A18, DB8500_PIN_C18, DB8500_PIN_B19, DB8500_PIN_B20,
+       DB8500_PIN_D21, DB8500_PIN_D20, DB8500_PIN_C20, DB8500_PIN_B21,
+       DB8500_PIN_C21, DB8500_PIN_A22, DB8500_PIN_B24, DB8500_PIN_C22 };
+
+/* Other C3 column */
+static const unsigned stmmod_oc3_1_pins[] = { DB8500_PIN_AB2, DB8500_PIN_W2,
+       DB8500_PIN_W3, DB8500_PIN_V3, DB8500_PIN_V2 };
+static const unsigned stmmod_oc3_2_pins[] = { DB8500_PIN_G5, DB8500_PIN_G4,
+       DB8500_PIN_H4, DB8500_PIN_H3, DB8500_PIN_J3 };
+static const unsigned uartmodrx_oc3_1_pins[] = { DB8500_PIN_H2 };
+static const unsigned uartmodtx_oc3_1_pins[] = { DB8500_PIN_J2 };
+static const unsigned etmr4_oc3_1_pins[] = { DB8500_PIN_D17, DB8500_PIN_D16,
+       DB8500_PIN_B17, DB8500_PIN_C16, DB8500_PIN_C19, DB8500_PIN_C17,
+       DB8500_PIN_A18, DB8500_PIN_C18, DB8500_PIN_B19, DB8500_PIN_B20,
+       DB8500_PIN_D21, DB8500_PIN_D20, DB8500_PIN_C20, DB8500_PIN_B21,
+       DB8500_PIN_C21, DB8500_PIN_A22, DB8500_PIN_B24, DB8500_PIN_C22 };
+
+/* Other C4 column */
+static const unsigned sbag_oc4_1_pins[] = { DB8500_PIN_G5, DB8500_PIN_G4,
+       DB8500_PIN_H4, DB8500_PIN_H3, DB8500_PIN_J3, DB8500_PIN_H1 };
+static const unsigned hwobs_oc4_1_pins[] = { DB8500_PIN_D17, DB8500_PIN_D16,
+       DB8500_PIN_B17, DB8500_PIN_C16, DB8500_PIN_C19, DB8500_PIN_C17,
+       DB8500_PIN_A18, DB8500_PIN_C18, DB8500_PIN_B19, DB8500_PIN_B20,
+       DB8500_PIN_D21, DB8500_PIN_D20, DB8500_PIN_C20, DB8500_PIN_B21,
+       DB8500_PIN_C21, DB8500_PIN_A22, DB8500_PIN_B24, DB8500_PIN_C22 };
+
 #define DB8500_PIN_GROUP(a,b) { .name = #a, .pins = a##_pins,          \
                        .npins = ARRAY_SIZE(a##_pins), .altsetting = b }
 
@@ -726,9 +778,34 @@ static const struct nmk_pingroup nmk_db8500_groups[] = {
        DB8500_PIN_GROUP(usbsim_c_2, NMK_GPIO_ALT_C),
        DB8500_PIN_GROUP(i2c3_c_2, NMK_GPIO_ALT_C),
        /* Other alt C1 column */
+       DB8500_PIN_GROUP(u2rx_oc1_1, NMK_GPIO_ALT_C1),
+       DB8500_PIN_GROUP(stmape_oc1_1, NMK_GPIO_ALT_C1),
+       DB8500_PIN_GROUP(remap0_oc1_1, NMK_GPIO_ALT_C1),
+       DB8500_PIN_GROUP(remap1_oc1_1, NMK_GPIO_ALT_C1),
+       DB8500_PIN_GROUP(ptma9_oc1_1, NMK_GPIO_ALT_C1),
        DB8500_PIN_GROUP(kp_oc1_1, NMK_GPIO_ALT_C1),
+       DB8500_PIN_GROUP(rf_oc1_1, NMK_GPIO_ALT_C1),
+       DB8500_PIN_GROUP(hxclk_oc1_1, NMK_GPIO_ALT_C1),
+       DB8500_PIN_GROUP(uartmodrx_oc1_1, NMK_GPIO_ALT_C1),
+       DB8500_PIN_GROUP(uartmodtx_oc1_1, NMK_GPIO_ALT_C1),
+       DB8500_PIN_GROUP(stmmod_oc1_1, NMK_GPIO_ALT_C1),
+       DB8500_PIN_GROUP(hxgpio_oc1_1, NMK_GPIO_ALT_C1),
+       DB8500_PIN_GROUP(rf_oc1_2, NMK_GPIO_ALT_C1),
        DB8500_PIN_GROUP(spi2_oc1_1, NMK_GPIO_ALT_C1),
        DB8500_PIN_GROUP(spi2_oc1_2, NMK_GPIO_ALT_C1),
+       /* Other alt C2 column */
+       DB8500_PIN_GROUP(sbag_oc2_1, NMK_GPIO_ALT_C2),
+       DB8500_PIN_GROUP(etmr4_oc2_1, NMK_GPIO_ALT_C2),
+       DB8500_PIN_GROUP(ptma9_oc2_1, NMK_GPIO_ALT_C2),
+       /* Other alt C3 column */
+       DB8500_PIN_GROUP(stmmod_oc3_1, NMK_GPIO_ALT_C3),
+       DB8500_PIN_GROUP(stmmod_oc3_2, NMK_GPIO_ALT_C3),
+       DB8500_PIN_GROUP(uartmodrx_oc3_1, NMK_GPIO_ALT_C3),
+       DB8500_PIN_GROUP(uartmodtx_oc3_1, NMK_GPIO_ALT_C3),
+       DB8500_PIN_GROUP(etmr4_oc3_1, NMK_GPIO_ALT_C3),
+       /* Other alt C4 column */
+       DB8500_PIN_GROUP(sbag_oc4_1, NMK_GPIO_ALT_C4),
+       DB8500_PIN_GROUP(hwobs_oc4_1, NMK_GPIO_ALT_C4),
 };
 
 /* We use this macro to define the groups applicable to a function */
@@ -742,7 +819,7 @@ DB8500_FUNC_GROUPS(u1, "u1rxtx_a_1", "u1ctsrts_a_1");
  * only available on two pins in alternative function C
  */
 DB8500_FUNC_GROUPS(u2, "u2rxtx_b_1", "u2rxtx_c_1", "u2ctsrts_c_1",
-                  "u2rxtx_c_2", "u2rxtx_c_3");
+                  "u2rxtx_c_2", "u2rxtx_c_3", "u2rx_oc1_1");
 DB8500_FUNC_GROUPS(ipi2c, "ipi2c_a_1", "ipi2c_a_2");
 /*
  * MSP0 can only be on a certain set of pins, but the TX/RX pins can be
@@ -784,8 +861,10 @@ DB8500_FUNC_GROUPS(i2c2, "i2c2_b_1", "i2c2_b_2");
  * so select one of each.
  */
 DB8500_FUNC_GROUPS(uartmod, "uartmodtx_b_1", "uartmodrx_b_1", "uartmodrx_b_2",
-                  "uartmodrx_c_1", "uartmod_tx_c_1");
-DB8500_FUNC_GROUPS(stmmod, "stmmod_b_1", "stmmod_c_1");
+               "uartmodrx_c_1", "uartmod_tx_c_1", "uartmodrx_oc1_1",
+               "uartmodtx_oc1_1", "uartmodrx_oc3_1", "uartmodtx_oc3_1");
+DB8500_FUNC_GROUPS(stmmod, "stmmod_b_1", "stmmod_c_1", "stmmod_oc1_1",
+               "stmmod_oc3_1", "stmmod_oc3_2");
 DB8500_FUNC_GROUPS(spi3, "spi3_b_1");
 /* Select between CS0 on alt B or PS1 on alt C */
 DB8500_FUNC_GROUPS(sm, "sm_b_1", "smcs0_b_1", "smcs1_b_1", "smcleale_c_1",
@@ -799,13 +878,19 @@ DB8500_FUNC_GROUPS(ipjtag, "ipjtag_c_1");
 DB8500_FUNC_GROUPS(slim0, "slim0_c_1");
 DB8500_FUNC_GROUPS(ms, "ms_c_1");
 DB8500_FUNC_GROUPS(iptrigout, "iptrigout_c_1");
-DB8500_FUNC_GROUPS(stmape, "stmape_c_1", "stmape_c_2");
+DB8500_FUNC_GROUPS(stmape, "stmape_c_1", "stmape_c_2", "stmape_oc1_1");
 DB8500_FUNC_GROUPS(mc5, "mc5_c_1");
 DB8500_FUNC_GROUPS(usbsim, "usbsim_c_1", "usbsim_c_2");
 DB8500_FUNC_GROUPS(i2c3, "i2c3_c_1", "i2c3_c_2");
 DB8500_FUNC_GROUPS(spi0, "spi0_c_1");
 DB8500_FUNC_GROUPS(spi2, "spi2_oc1_1", "spi2_oc1_2");
-
+DB8500_FUNC_GROUPS(remap, "remap0_oc1_1", "remap1_oc1_1");
+DB8500_FUNC_GROUPS(sbag, "sbag_oc2_1", "sbag_oc4_1");
+DB8500_FUNC_GROUPS(ptm, "ptma9_oc1_1", "ptma9_oc2_1");
+DB8500_FUNC_GROUPS(rf, "rf_oc1_1", "rf_oc1_2");
+DB8500_FUNC_GROUPS(hx, "hxclk_oc1_1", "hxgpio_oc1_1");
+DB8500_FUNC_GROUPS(etm, "etmr4_oc2_1", "etmr4_oc3_1");
+DB8500_FUNC_GROUPS(hwobs, "hwobs_oc4_1");
 #define FUNCTION(fname)                                        \
        {                                               \
                .name = #fname,                         \
@@ -858,6 +943,12 @@ static const struct nmk_function nmk_db8500_functions[] = {
        FUNCTION(i2c3),
        FUNCTION(spi0),
        FUNCTION(spi2),
+       FUNCTION(remap),
+       FUNCTION(ptm),
+       FUNCTION(rf),
+       FUNCTION(hx),
+       FUNCTION(etm),
+       FUNCTION(hwobs),
 };
 
 static const struct prcm_gpiocr_altcx_pin_desc db8500_altcx_pins[] = {
index 01aea1c3b5fa3188a50cfe4e41ea13e48c50f56d..f2fd99ba40e35ef16e128e1b69800316ef02cf6a 100644 (file)
@@ -44,12 +44,10 @@ static inline u32 prcmu_read(unsigned int reg) {
 static inline void prcmu_write(unsigned int reg, u32 value) {}
 static inline void prcmu_write_masked(unsigned int reg, u32 mask, u32 value) {}
 #endif
+#include <linux/platform_data/pinctrl-nomadik.h>
 
 #include <asm/mach/irq.h>
 
-#include <plat/pincfg.h>
-#include <plat/gpio-nomadik.h>
-
 #include "pinctrl-nomadik.h"
 
 /*
@@ -60,8 +58,6 @@ static inline void prcmu_write_masked(unsigned int reg, u32 mask, u32 value) {}
  * Symbols in this file are called "nmk_gpio" for "nomadik gpio"
  */
 
-#define NMK_GPIO_PER_CHIP      32
-
 struct nmk_gpio_chip {
        struct gpio_chip chip;
        struct irq_domain *domain;
@@ -536,7 +532,7 @@ static int __nmk_config_pins(pin_cfg_t *cfgs, int num, bool sleep)
  * and its sleep mode based on the specified configuration.  The @cfg is
  * usually one of the SoC specific macros defined in mach/<soc>-pins.h.  These
  * are constructed using, and can be further enhanced with, the macros in
- * plat/pincfg.h.
+ * <linux/platform_data/pinctrl-nomadik.h>
  *
  * If a pin's mode is set to GPIO, it is configured as an input to avoid
  * side-effects.  The gpio can be manipulated later using standard GPIO API
@@ -675,6 +671,35 @@ int nmk_gpio_set_mode(int gpio, int gpio_mode)
 }
 EXPORT_SYMBOL(nmk_gpio_set_mode);
 
+static int nmk_prcm_gpiocr_get_mode(struct pinctrl_dev *pctldev, int gpio)
+{
+       int i;
+       u16 reg;
+       u8 bit;
+       struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
+       const struct prcm_gpiocr_altcx_pin_desc *pin_desc;
+       const u16 *gpiocr_regs;
+
+       for (i = 0; i < npct->soc->npins_altcx; i++) {
+               if (npct->soc->altcx_pins[i].pin == gpio)
+                       break;
+       }
+       if (i == npct->soc->npins_altcx)
+               return NMK_GPIO_ALT_C;
+
+       pin_desc = npct->soc->altcx_pins + i;
+       gpiocr_regs = npct->soc->prcm_gpiocr_registers;
+       for (i = 0; i < PRCM_IDX_GPIOCR_ALTC_MAX; i++) {
+               if (pin_desc->altcx[i].used == true) {
+                       reg = gpiocr_regs[pin_desc->altcx[i].reg_index];
+                       bit = pin_desc->altcx[i].control_bit;
+                       if (prcmu_read(reg) & BIT(bit))
+                               return NMK_GPIO_ALT_C+i+1;
+               }
+       }
+       return NMK_GPIO_ALT_C;
+}
+
 int nmk_gpio_get_mode(int gpio)
 {
        struct nmk_gpio_chip *nmk_chip;
@@ -1056,15 +1081,16 @@ static int nmk_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
        struct nmk_gpio_chip *nmk_chip =
                container_of(chip, struct nmk_gpio_chip, chip);
 
-       return irq_find_mapping(nmk_chip->domain, offset);
+       return irq_create_mapping(nmk_chip->domain, offset);
 }
 
 #ifdef CONFIG_DEBUG_FS
 
 #include <linux/seq_file.h>
 
-static void nmk_gpio_dbg_show_one(struct seq_file *s, struct gpio_chip *chip,
-                                 unsigned offset, unsigned gpio)
+static void nmk_gpio_dbg_show_one(struct seq_file *s,
+       struct pinctrl_dev *pctldev, struct gpio_chip *chip,
+       unsigned offset, unsigned gpio)
 {
        const char *label = gpiochip_is_requested(chip, offset);
        struct nmk_gpio_chip *nmk_chip =
@@ -1078,12 +1104,18 @@ static void nmk_gpio_dbg_show_one(struct seq_file *s, struct gpio_chip *chip,
                [NMK_GPIO_ALT_A]        = "altA",
                [NMK_GPIO_ALT_B]        = "altB",
                [NMK_GPIO_ALT_C]        = "altC",
+               [NMK_GPIO_ALT_C+1]      = "altC1",
+               [NMK_GPIO_ALT_C+2]      = "altC2",
+               [NMK_GPIO_ALT_C+3]      = "altC3",
+               [NMK_GPIO_ALT_C+4]      = "altC4",
        };
 
        clk_enable(nmk_chip->clk);
        is_out = !!(readl(nmk_chip->addr + NMK_GPIO_DIR) & bit);
        pull = !(readl(nmk_chip->addr + NMK_GPIO_PDIS) & bit);
        mode = nmk_gpio_get_mode(gpio);
+       if ((mode == NMK_GPIO_ALT_C) && pctldev)
+               mode = nmk_prcm_gpiocr_get_mode(pctldev, gpio);
 
        seq_printf(s, " gpio-%-3d (%-20.20s) %s %s %s %s",
                   gpio, label ?: "(none)",
@@ -1127,13 +1159,14 @@ static void nmk_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
        unsigned                gpio = chip->base;
 
        for (i = 0; i < chip->ngpio; i++, gpio++) {
-               nmk_gpio_dbg_show_one(s, chip, i, gpio);
+               nmk_gpio_dbg_show_one(s, NULL, chip, i, gpio);
                seq_printf(s, "\n");
        }
 }
 
 #else
 static inline void nmk_gpio_dbg_show_one(struct seq_file *s,
+                                        struct pinctrl_dev *pctldev,
                                         struct gpio_chip *chip,
                                         unsigned offset, unsigned gpio)
 {
@@ -1281,7 +1314,7 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev)
        struct clk *clk;
        int secondary_irq;
        void __iomem *base;
-       int irq_start = -1;
+       int irq_start = 0;
        int irq;
        int ret;
 
@@ -1387,7 +1420,7 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev)
 
        if (!np)
                irq_start = NOMADIK_GPIO_TO_IRQ(pdata->first_gpio);
-       nmk_chip->domain = irq_domain_add_simple(NULL,
+       nmk_chip->domain = irq_domain_add_simple(np,
                                NMK_GPIO_PER_CHIP, irq_start,
                                &nmk_gpio_irq_simple_ops, nmk_chip);
        if (!nmk_chip->domain) {
@@ -1464,7 +1497,7 @@ static void nmk_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
                return;
        }
        chip = range->gc;
-       nmk_gpio_dbg_show_one(s, chip, offset - chip->base, offset);
+       nmk_gpio_dbg_show_one(s, pctldev, chip, offset - chip->base, offset);
 }
 
 static struct pinctrl_ops nmk_pinctrl_ops = {
@@ -1845,11 +1878,11 @@ static int __devinit nmk_pinctrl_probe(struct platform_device *pdev)
         * need this to proceed.
         */
        for (i = 0; i < npct->soc->gpio_num_ranges; i++) {
-               if (!nmk_gpio_chips[i]) {
+               if (!nmk_gpio_chips[npct->soc->gpio_ranges[i].id]) {
                        dev_warn(&pdev->dev, "GPIO chip %d not registered yet\n", i);
                        return -EPROBE_DEFER;
                }
-               npct->soc->gpio_ranges[i].gc = &nmk_gpio_chips[i]->chip;
+               npct->soc->gpio_ranges[i].gc = &nmk_gpio_chips[npct->soc->gpio_ranges[i].id]->chip;
        }
 
        nmk_pinctrl_desc.pins = npct->soc->pins;
index eef316e979a02a1156c8ede6ca10c3b039e5d7fc..bcd4191e10ea8ced278c469799d521e4a82dee65 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef PINCTRL_PINCTRL_NOMADIK_H
 #define PINCTRL_PINCTRL_NOMADIK_H
 
-#include <plat/gpio-nomadik.h>
+#include <linux/platform_data/pinctrl-nomadik.h>
 
 /* Package definitions */
 #define PINCTRL_NMK_STN8815    0
index 861cd5f04d5e12ba2aa497cc39934a56b0680a7b..fc34cac8a1b054ca4cc9095cedce2afd2273e17b 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/slab.h>
 #include <linux/err.h>
 #include <linux/gpio.h>
+#include <linux/irqdomain.h>
 
 #include "core.h"
 #include "pinctrl-samsung.h"
@@ -46,6 +47,13 @@ struct pin_config {
        { "samsung,pin-pud-pdn", PINCFG_TYPE_PUD_PDN },
 };
 
+static unsigned int pin_base = 0;
+
+static inline struct samsung_pin_bank *gc_to_pin_bank(struct gpio_chip *gc)
+{
+       return container_of(gc, struct samsung_pin_bank, gpio_chip);
+}
+
 /* check if the selector is a valid pin group selector */
 static int samsung_get_group_count(struct pinctrl_dev *pctldev)
 {
@@ -250,14 +258,12 @@ static int samsung_pinmux_get_groups(struct pinctrl_dev *pctldev,
  * given a pin number that is local to a pin controller, find out the pin bank
  * and the register base of the pin bank.
  */
-static void pin_to_reg_bank(struct gpio_chip *gc, unsigned pin,
-                       void __iomem **reg, u32 *offset,
+static void pin_to_reg_bank(struct samsung_pinctrl_drv_data *drvdata,
+                       unsigned pin, void __iomem **reg, u32 *offset,
                        struct samsung_pin_bank **bank)
 {
-       struct samsung_pinctrl_drv_data *drvdata;
        struct samsung_pin_bank *b;
 
-       drvdata = dev_get_drvdata(gc->dev);
        b = drvdata->ctrl->pin_banks;
 
        while ((pin >= b->pin_base) &&
@@ -292,7 +298,7 @@ static void samsung_pinmux_setup(struct pinctrl_dev *pctldev, unsigned selector,
         * pin function number in the config register.
         */
        for (cnt = 0; cnt < drvdata->pin_groups[group].num_pins; cnt++) {
-               pin_to_reg_bank(drvdata->gc, pins[cnt] - drvdata->ctrl->base,
+               pin_to_reg_bank(drvdata, pins[cnt] - drvdata->ctrl->base,
                                &reg, &pin_offset, &bank);
                mask = (1 << bank->func_width) - 1;
                shift = pin_offset * bank->func_width;
@@ -329,10 +335,16 @@ static int samsung_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev,
                struct pinctrl_gpio_range *range, unsigned offset, bool input)
 {
        struct samsung_pin_bank *bank;
+       struct samsung_pinctrl_drv_data *drvdata;
        void __iomem *reg;
        u32 data, pin_offset, mask, shift;
 
-       pin_to_reg_bank(range->gc, offset, &reg, &pin_offset, &bank);
+       bank = gc_to_pin_bank(range->gc);
+       drvdata = pinctrl_dev_get_drvdata(pctldev);
+
+       pin_offset = offset - bank->pin_base;
+       reg = drvdata->virt_base + bank->pctl_offset;
+
        mask = (1 << bank->func_width) - 1;
        shift = pin_offset * bank->func_width;
 
@@ -366,7 +378,7 @@ static int samsung_pinconf_rw(struct pinctrl_dev *pctldev, unsigned int pin,
        u32 cfg_value, cfg_reg;
 
        drvdata = pinctrl_dev_get_drvdata(pctldev);
-       pin_to_reg_bank(drvdata->gc, pin - drvdata->ctrl->base, &reg_base,
+       pin_to_reg_bank(drvdata, pin - drvdata->ctrl->base, &reg_base,
                                        &pin_offset, &bank);
 
        switch (cfg_type) {
@@ -391,6 +403,9 @@ static int samsung_pinconf_rw(struct pinctrl_dev *pctldev, unsigned int pin,
                return -EINVAL;
        }
 
+       if (!width)
+               return -EINVAL;
+
        mask = (1 << width) - 1;
        shift = pin_offset * width;
        data = readl(reg_base + cfg_reg);
@@ -463,14 +478,16 @@ static struct pinconf_ops samsung_pinconf_ops = {
 /* gpiolib gpio_set callback function */
 static void samsung_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
 {
+       struct samsung_pin_bank *bank = gc_to_pin_bank(gc);
        void __iomem *reg;
-       u32 pin_offset, data;
+       u32 data;
+
+       reg = bank->drvdata->virt_base + bank->pctl_offset;
 
-       pin_to_reg_bank(gc, offset, &reg, &pin_offset, NULL);
        data = readl(reg + DAT_REG);
-       data &= ~(1 << pin_offset);
+       data &= ~(1 << offset);
        if (value)
-               data |= 1 << pin_offset;
+               data |= 1 << offset;
        writel(data, reg + DAT_REG);
 }
 
@@ -478,11 +495,13 @@ static void samsung_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
 static int samsung_gpio_get(struct gpio_chip *gc, unsigned offset)
 {
        void __iomem *reg;
-       u32 pin_offset, data;
+       u32 data;
+       struct samsung_pin_bank *bank = gc_to_pin_bank(gc);
+
+       reg = bank->drvdata->virt_base + bank->pctl_offset;
 
-       pin_to_reg_bank(gc, offset, &reg, &pin_offset, NULL);
        data = readl(reg + DAT_REG);
-       data >>= pin_offset;
+       data >>= offset;
        data &= 1;
        return data;
 }
@@ -509,6 +528,23 @@ static int samsung_gpio_direction_output(struct gpio_chip *gc, unsigned offset,
        return pinctrl_gpio_direction_output(gc->base + offset);
 }
 
+/*
+ * gpiolib gpio_to_irq callback function. Creates a mapping between a GPIO pin
+ * and a virtual IRQ, if not already present.
+ */
+static int samsung_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
+{
+       struct samsung_pin_bank *bank = gc_to_pin_bank(gc);
+       unsigned int virq;
+
+       if (!bank->irq_domain)
+               return -ENXIO;
+
+       virq = irq_create_mapping(bank->irq_domain, offset);
+
+       return (virq) ? : -ENXIO;
+}
+
 /*
  * Parse the pin names listed in the 'samsung,pins' property and convert it
  * into a list of gpio numbers are create a pin group from it.
@@ -597,7 +633,7 @@ static int __devinit samsung_pinctrl_parse_dt(struct platform_device *pdev,
         */
        for_each_child_of_node(dev_np, cfg_np) {
                u32 function;
-               if (of_find_property(cfg_np, "interrupt-controller", NULL))
+               if (!of_find_property(cfg_np, "samsung,pins", NULL))
                        continue;
 
                ret = samsung_pinctrl_parse_dt_pins(pdev, cfg_np,
@@ -712,12 +748,16 @@ static int __devinit samsung_pinctrl_register(struct platform_device *pdev,
                return -EINVAL;
        }
 
-       drvdata->grange.name = "samsung-pctrl-gpio-range";
-       drvdata->grange.id = 0;
-       drvdata->grange.base = drvdata->ctrl->base;
-       drvdata->grange.npins = drvdata->ctrl->nr_pins;
-       drvdata->grange.gc = drvdata->gc;
-       pinctrl_add_gpio_range(drvdata->pctl_dev, &drvdata->grange);
+       for (bank = 0; bank < drvdata->ctrl->nr_banks; ++bank) {
+               pin_bank = &drvdata->ctrl->pin_banks[bank];
+               pin_bank->grange.name = pin_bank->name;
+               pin_bank->grange.id = bank;
+               pin_bank->grange.pin_base = pin_bank->pin_base;
+               pin_bank->grange.base = pin_bank->gpio_chip.base;
+               pin_bank->grange.npins = pin_bank->gpio_chip.ngpio;
+               pin_bank->grange.gc = &pin_bank->gpio_chip;
+               pinctrl_add_gpio_range(drvdata->pctl_dev, &pin_bank->grange);
+       }
 
        ret = samsung_pinctrl_parse_dt(pdev, drvdata);
        if (ret) {
@@ -728,68 +768,117 @@ static int __devinit samsung_pinctrl_register(struct platform_device *pdev,
        return 0;
 }
 
+static const struct gpio_chip samsung_gpiolib_chip = {
+       .set = samsung_gpio_set,
+       .get = samsung_gpio_get,
+       .direction_input = samsung_gpio_direction_input,
+       .direction_output = samsung_gpio_direction_output,
+       .to_irq = samsung_gpio_to_irq,
+       .owner = THIS_MODULE,
+};
+
 /* register the gpiolib interface with the gpiolib subsystem */
 static int __devinit samsung_gpiolib_register(struct platform_device *pdev,
                                struct samsung_pinctrl_drv_data *drvdata)
 {
+       struct samsung_pin_ctrl *ctrl = drvdata->ctrl;
+       struct samsung_pin_bank *bank = ctrl->pin_banks;
        struct gpio_chip *gc;
        int ret;
-
-       gc = devm_kzalloc(&pdev->dev, sizeof(*gc), GFP_KERNEL);
-       if (!gc) {
-               dev_err(&pdev->dev, "mem alloc for gpio_chip failed\n");
-               return -ENOMEM;
-       }
-
-       drvdata->gc = gc;
-       gc->base = drvdata->ctrl->base;
-       gc->ngpio = drvdata->ctrl->nr_pins;
-       gc->dev = &pdev->dev;
-       gc->set = samsung_gpio_set;
-       gc->get = samsung_gpio_get;
-       gc->direction_input = samsung_gpio_direction_input;
-       gc->direction_output = samsung_gpio_direction_output;
-       gc->label = drvdata->ctrl->label;
-       gc->owner = THIS_MODULE;
-       ret = gpiochip_add(gc);
-       if (ret) {
-               dev_err(&pdev->dev, "failed to register gpio_chip %s, error "
-                                       "code: %d\n", gc->label, ret);
-               return ret;
+       int i;
+
+       for (i = 0; i < ctrl->nr_banks; ++i, ++bank) {
+               bank->gpio_chip = samsung_gpiolib_chip;
+
+               gc = &bank->gpio_chip;
+               gc->base = ctrl->base + bank->pin_base;
+               gc->ngpio = bank->nr_pins;
+               gc->dev = &pdev->dev;
+               gc->of_node = bank->of_node;
+               gc->label = bank->name;
+
+               ret = gpiochip_add(gc);
+               if (ret) {
+                       dev_err(&pdev->dev, "failed to register gpio_chip %s, error code: %d\n",
+                                                       gc->label, ret);
+                       goto fail;
+               }
        }
 
        return 0;
+
+fail:
+       for (--i, --bank; i >= 0; --i, --bank)
+               if (gpiochip_remove(&bank->gpio_chip))
+                       dev_err(&pdev->dev, "gpio chip %s remove failed\n",
+                                                       bank->gpio_chip.label);
+       return ret;
 }
 
 /* unregister the gpiolib interface with the gpiolib subsystem */
 static int __devinit samsung_gpiolib_unregister(struct platform_device *pdev,
                                struct samsung_pinctrl_drv_data *drvdata)
 {
-       int ret = gpiochip_remove(drvdata->gc);
-       if (ret) {
+       struct samsung_pin_ctrl *ctrl = drvdata->ctrl;
+       struct samsung_pin_bank *bank = ctrl->pin_banks;
+       int ret = 0;
+       int i;
+
+       for (i = 0; !ret && i < ctrl->nr_banks; ++i, ++bank)
+               ret = gpiochip_remove(&bank->gpio_chip);
+
+       if (ret)
                dev_err(&pdev->dev, "gpio chip remove failed\n");
-               return ret;
-       }
-       return 0;
+
+       return ret;
 }
 
 static const struct of_device_id samsung_pinctrl_dt_match[];
 
 /* retrieve the soc specific data */
 static struct samsung_pin_ctrl *samsung_pinctrl_get_soc_data(
+                               struct samsung_pinctrl_drv_data *d,
                                struct platform_device *pdev)
 {
        int id;
        const struct of_device_id *match;
-       const struct device_node *node = pdev->dev.of_node;
+       struct device_node *node = pdev->dev.of_node;
+       struct device_node *np;
+       struct samsung_pin_ctrl *ctrl;
+       struct samsung_pin_bank *bank;
+       int i;
 
-       id = of_alias_get_id(pdev->dev.of_node, "pinctrl");
+       id = of_alias_get_id(node, "pinctrl");
        if (id < 0) {
                dev_err(&pdev->dev, "failed to get alias id\n");
                return NULL;
        }
        match = of_match_node(samsung_pinctrl_dt_match, node);
-       return (struct samsung_pin_ctrl *)match->data + id;
+       ctrl = (struct samsung_pin_ctrl *)match->data + id;
+
+       bank = ctrl->pin_banks;
+       for (i = 0; i < ctrl->nr_banks; ++i, ++bank) {
+               bank->drvdata = d;
+               bank->pin_base = ctrl->nr_pins;
+               ctrl->nr_pins += bank->nr_pins;
+       }
+
+       for_each_child_of_node(node, np) {
+               if (!of_find_property(np, "gpio-controller", NULL))
+                       continue;
+               bank = ctrl->pin_banks;
+               for (i = 0; i < ctrl->nr_banks; ++i, ++bank) {
+                       if (!strcmp(bank->name, np->name)) {
+                               bank->of_node = np;
+                               break;
+                       }
+               }
+       }
+
+       ctrl->base = pin_base;
+       pin_base += ctrl->nr_pins;
+
+       return ctrl;
 }
 
 static int __devinit samsung_pinctrl_probe(struct platform_device *pdev)
@@ -805,18 +894,18 @@ static int __devinit samsung_pinctrl_probe(struct platform_device *pdev)
                return -ENODEV;
        }
 
-       ctrl = samsung_pinctrl_get_soc_data(pdev);
-       if (!ctrl) {
-               dev_err(&pdev->dev, "driver data not available\n");
-               return -EINVAL;
-       }
-
        drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
        if (!drvdata) {
                dev_err(dev, "failed to allocate memory for driver's "
                                "private data\n");
                return -ENOMEM;
        }
+
+       ctrl = samsung_pinctrl_get_soc_data(drvdata, pdev);
+       if (!ctrl) {
+               dev_err(&pdev->dev, "driver data not available\n");
+               return -EINVAL;
+       }
        drvdata->ctrl = ctrl;
        drvdata->dev = dev;
 
index b8956934cda683c8ecc99f8c8a64b1b0a27bf546..0670d9ea43fa5a45c49ed898288fc8709d57810e 100644 (file)
@@ -23,6 +23,8 @@
 #include <linux/pinctrl/consumer.h>
 #include <linux/pinctrl/machine.h>
 
+#include <linux/gpio.h>
+
 /* register offsets within a pin bank */
 #define DAT_REG                0x4
 #define PUD_REG                0x8
@@ -64,6 +66,7 @@ enum pincfg_type {
  * @EINT_TYPE_NONE: bank does not support external interrupts
  * @EINT_TYPE_GPIO: bank supportes external gpio interrupts
  * @EINT_TYPE_WKUP: bank supportes external wakeup interrupts
+ * @EINT_TYPE_WKUP_MUX: bank supports multiplexed external wakeup interrupts
  *
  * Samsung GPIO controller groups all the available pins into banks. The pins
  * in a pin bank can support external gpio interrupts or external wakeup
@@ -76,6 +79,7 @@ enum eint_type {
        EINT_TYPE_NONE,
        EINT_TYPE_GPIO,
        EINT_TYPE_WKUP,
+       EINT_TYPE_WKUP_MUX,
 };
 
 /* maximum length of a pin in pin descriptor (example: "gpa0-0") */
@@ -109,8 +113,12 @@ struct samsung_pinctrl_drv_data;
  * @conpdn_width: width of the sleep mode function selector bin field.
  * @pudpdn_width: width of the sleep mode pull up/down selector bit field.
  * @eint_type: type of the external interrupt supported by the bank.
- * @irq_base: starting controller local irq number of the bank.
  * @name: name to be prefixed for each pin in this pin bank.
+ * @of_node: OF node of the bank.
+ * @drvdata: link to controller driver data
+ * @irq_domain: IRQ domain of the bank.
+ * @gpio_chip: GPIO chip of the bank.
+ * @grange: linux gpio pin range supported by this bank.
  */
 struct samsung_pin_bank {
        u32             pctl_offset;
@@ -122,8 +130,13 @@ struct samsung_pin_bank {
        u8              conpdn_width;
        u8              pudpdn_width;
        enum eint_type  eint_type;
-       u32             irq_base;
+       u32             eint_offset;
        char            *name;
+       struct device_node *of_node;
+       struct samsung_pinctrl_drv_data *drvdata;
+       struct irq_domain *irq_domain;
+       struct gpio_chip gpio_chip;
+       struct pinctrl_gpio_range grange;
 };
 
 /**
@@ -132,8 +145,6 @@ struct samsung_pin_bank {
  * @nr_banks: number of pin banks.
  * @base: starting system wide pin number.
  * @nr_pins: number of pins supported by the controller.
- * @nr_gint: number of external gpio interrupts supported.
- * @nr_wint: number of external wakeup interrupts supported.
  * @geint_con: offset of the ext-gpio controller registers.
  * @geint_mask: offset of the ext-gpio interrupt mask registers.
  * @geint_pend: offset of the ext-gpio interrupt pending registers.
@@ -153,8 +164,6 @@ struct samsung_pin_ctrl {
 
        u32             base;
        u32             nr_pins;
-       u32             nr_gint;
-       u32             nr_wint;
 
        u32             geint_con;
        u32             geint_mask;
@@ -183,8 +192,6 @@ struct samsung_pin_ctrl {
  * @nr_groups: number of such pin groups.
  * @pmx_functions: list of pin functions available to the driver.
  * @nr_function: number of such pin functions.
- * @gc: gpio_chip instance registered with gpiolib.
- * @grange: linux gpio pin range supported by this controller.
  */
 struct samsung_pinctrl_drv_data {
        void __iomem                    *virt_base;
@@ -199,12 +206,6 @@ struct samsung_pinctrl_drv_data {
        unsigned int                    nr_groups;
        const struct samsung_pmx_func   *pmx_functions;
        unsigned int                    nr_functions;
-
-       struct irq_domain               *gpio_irqd;
-       struct irq_domain               *wkup_irqd;
-
-       struct gpio_chip                *gc;
-       struct pinctrl_gpio_range       grange;
 };
 
 /**
index 729b686c3ad2338e2d4878ed0e1623674ba87f3f..7da0b371fd652a04ac7d55ecf89c55c915d19f8b 100644 (file)
@@ -464,7 +464,7 @@ static int tegra_pinconf_reg(struct tegra_pmx *pmx,
                *bank = g->drv_bank;
                *reg = g->drv_reg;
                *bit = g->lpmd_bit;
-               *width = 1;
+               *width = 2;
                break;
        case TEGRA_PINCONF_PARAM_DRIVE_DOWN_STRENGTH:
                *bank = g->drv_bank;
index 0386fdf0da16441ecc874b1710e55a929d44325a..7894f14c70590058726a6c07da4286e1640058db 100644 (file)
@@ -3345,10 +3345,10 @@ static const struct tegra_function tegra30_functions[] = {
        FUNCTION(vi_alt3),
 };
 
-#define MUXCTL_REG_A   0x3000
-#define PINGROUP_REG_A 0x868
+#define DRV_PINGROUP_REG_A     0x868   /* bank 0 */
+#define PINGROUP_REG_A         0x3000  /* bank 1 */
 
-#define PINGROUP_REG_Y(r) ((r) - MUXCTL_REG_A)
+#define PINGROUP_REG_Y(r) ((r) - PINGROUP_REG_A)
 #define PINGROUP_REG_N(r) -1
 
 #define PINGROUP(pg_name, f0, f1, f2, f3, f_safe, r, od, ior)  \
@@ -3364,25 +3364,25 @@ static const struct tegra_function tegra30_functions[] = {
                },                                              \
                .func_safe = TEGRA_MUX_ ## f_safe,              \
                .mux_reg = PINGROUP_REG_Y(r),                   \
-               .mux_bank = 0,                                  \
+               .mux_bank = 1,                                  \
                .mux_bit = 0,                                   \
                .pupd_reg = PINGROUP_REG_Y(r),                  \
-               .pupd_bank = 0,                                 \
+               .pupd_bank = 1,                                 \
                .pupd_bit = 2,                                  \
                .tri_reg = PINGROUP_REG_Y(r),                   \
-               .tri_bank = 0,                                  \
+               .tri_bank = 1,                                  \
                .tri_bit = 4,                                   \
                .einput_reg = PINGROUP_REG_Y(r),                \
-               .einput_bank = 0,                               \
+               .einput_bank = 1,                               \
                .einput_bit = 5,                                \
                .odrain_reg = PINGROUP_REG_##od(r),             \
-               .odrain_bank = 0,                               \
+               .odrain_bank = 1,                               \
                .odrain_bit = 6,                                \
                .lock_reg = PINGROUP_REG_Y(r),                  \
-               .lock_bank = 0,                                 \
+               .lock_bank = 1,                                 \
                .lock_bit = 7,                                  \
                .ioreset_reg = PINGROUP_REG_##ior(r),           \
-               .ioreset_bank = 0,                              \
+               .ioreset_bank = 1,                              \
                .ioreset_bit = 8,                               \
                .drv_reg = -1,                                  \
        }
@@ -3401,8 +3401,8 @@ static const struct tegra_function tegra30_functions[] = {
                .odrain_reg = -1,                               \
                .lock_reg = -1,                                 \
                .ioreset_reg = -1,                              \
-               .drv_reg = ((r) - PINGROUP_REG_A),              \
-               .drv_bank = 1,                                  \
+               .drv_reg = ((r) - DRV_PINGROUP_REG_A),          \
+               .drv_bank = 0,                                  \
                .hsm_bit = hsm_b,                               \
                .schmitt_bit = schmitt_b,                       \
                .lpmd_bit = lpmd_b,                             \
index 309f5b9a70ec74d4b5e1cca07b6e8e31836f53fa..2e9825e304afa5f609c3cf760ba0c6ae0a40cdf5 100644 (file)
@@ -663,8 +663,6 @@ static const struct pinctrl_pin_desc u300_pads[] = {
 struct u300_pmx {
        struct device *dev;
        struct pinctrl_dev *pctl;
-       u32 phybase;
-       u32 physize;
        void __iomem *virtbase;
 };
 
@@ -1110,7 +1108,6 @@ static int __devinit u300_pmx_probe(struct platform_device *pdev)
        struct u300_pmx *upmx;
        struct resource *res;
        struct gpio_chip *gpio_chip = dev_get_platdata(&pdev->dev);
-       int ret;
        int i;
 
        /* Create state holders etc for this driver */
@@ -1123,26 +1120,15 @@ static int __devinit u300_pmx_probe(struct platform_device *pdev)
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!res)
                return -ENOENT;
-       upmx->phybase = res->start;
-       upmx->physize = resource_size(res);
-
-       if (request_mem_region(upmx->phybase, upmx->physize,
-                              DRIVER_NAME) == NULL) {
-               ret = -ENOMEM;
-               goto out_no_memregion;
-       }
 
-       upmx->virtbase = ioremap(upmx->phybase, upmx->physize);
-       if (!upmx->virtbase) {
-               ret = -ENOMEM;
-               goto out_no_remap;
-       }
+       upmx->virtbase = devm_request_and_ioremap(&pdev->dev, res);
+       if (!upmx->virtbase)
+               return -ENOMEM;
 
        upmx->pctl = pinctrl_register(&u300_pmx_desc, &pdev->dev, upmx);
        if (!upmx->pctl) {
                dev_err(&pdev->dev, "could not register U300 pinmux driver\n");
-               ret = -EINVAL;
-               goto out_no_pmx;
+               return -EINVAL;
        }
 
        /* We will handle a range of GPIO pins */
@@ -1156,14 +1142,6 @@ static int __devinit u300_pmx_probe(struct platform_device *pdev)
        dev_info(&pdev->dev, "initialized U300 pin control driver\n");
 
        return 0;
-
-out_no_pmx:
-       iounmap(upmx->virtbase);
-out_no_remap:
-       platform_set_drvdata(pdev, NULL);
-out_no_memregion:
-       release_mem_region(upmx->phybase, upmx->physize);
-       return ret;
 }
 
 static int __devexit u300_pmx_remove(struct platform_device *pdev)
@@ -1171,8 +1149,6 @@ static int __devexit u300_pmx_remove(struct platform_device *pdev)
        struct u300_pmx *upmx = platform_get_drvdata(pdev);
 
        pinctrl_unregister(upmx->pctl);
-       iounmap(upmx->virtbase);
-       release_mem_region(upmx->phybase, upmx->physize);
        platform_set_drvdata(pdev, NULL);
 
        return 0;
index 9301a7a95effae0a3f447dcc5aefb8030a9e9a62..0ef01ee2835ff350a088492ee7e16d740ed97eba 100644 (file)
@@ -314,14 +314,11 @@ int pinmux_map_to_setting(struct pinctrl_map const *map,
 {
        struct pinctrl_dev *pctldev = setting->pctldev;
        const struct pinmux_ops *pmxops = pctldev->desc->pmxops;
-       const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
        char const * const *groups;
        unsigned num_groups;
        int ret;
        const char *group;
        int i;
-       const unsigned *pins;
-       unsigned num_pins;
 
        if (!pmxops) {
                dev_err(pctldev->dev, "does not support mux function\n");
@@ -376,53 +373,12 @@ int pinmux_map_to_setting(struct pinctrl_map const *map,
        }
        setting->data.mux.group = ret;
 
-       ret = pctlops->get_group_pins(pctldev, setting->data.mux.group, &pins,
-                                     &num_pins);
-       if (ret) {
-               dev_err(pctldev->dev,
-                       "could not get pins for device %s group selector %d\n",
-                       pinctrl_dev_get_name(pctldev), setting->data.mux.group);
-                       return -ENODEV;
-       }
-
-       /* Try to allocate all pins in this group, one by one */
-       for (i = 0; i < num_pins; i++) {
-               ret = pin_request(pctldev, pins[i], map->dev_name, NULL);
-               if (ret) {
-                       dev_err(pctldev->dev,
-                               "could not request pin %d on device %s\n",
-                               pins[i], pinctrl_dev_get_name(pctldev));
-                       /* On error release all taken pins */
-                       i--; /* this pin just failed */
-                       for (; i >= 0; i--)
-                               pin_free(pctldev, pins[i], NULL);
-                       return -ENODEV;
-               }
-       }
-
        return 0;
 }
 
 void pinmux_free_setting(struct pinctrl_setting const *setting)
 {
-       struct pinctrl_dev *pctldev = setting->pctldev;
-       const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
-       const unsigned *pins;
-       unsigned num_pins;
-       int ret;
-       int i;
-
-       ret = pctlops->get_group_pins(pctldev, setting->data.mux.group,
-                                     &pins, &num_pins);
-       if (ret) {
-               dev_err(pctldev->dev,
-                       "could not get pins for device %s group selector %d\n",
-                       pinctrl_dev_get_name(pctldev), setting->data.mux.group);
-               return;
-       }
-
-       for (i = 0; i < num_pins; i++)
-               pin_free(pctldev, pins[i], NULL);
+       /* This function is currently unused */
 }
 
 int pinmux_enable_setting(struct pinctrl_setting const *setting)
@@ -446,6 +402,22 @@ int pinmux_enable_setting(struct pinctrl_setting const *setting)
                num_pins = 0;
        }
 
+       /* Try to allocate all pins in this group, one by one */
+       for (i = 0; i < num_pins; i++) {
+               ret = pin_request(pctldev, pins[i], setting->dev_name, NULL);
+               if (ret) {
+                       dev_err(pctldev->dev,
+                               "could not request pin %d on device %s\n",
+                               pins[i], pinctrl_dev_get_name(pctldev));
+                       /* On error release all taken pins */
+                       i--; /* this pin just failed */
+                       for (; i >= 0; i--)
+                               pin_free(pctldev, pins[i], NULL);
+                       return -ENODEV;
+               }
+       }
+
+       /* Now that we have acquired the pins, encode the mux setting */
        for (i = 0; i < num_pins; i++) {
                desc = pin_desc_get(pctldev, pins[i]);
                if (desc == NULL) {
@@ -482,6 +454,7 @@ void pinmux_disable_setting(struct pinctrl_setting const *setting)
                num_pins = 0;
        }
 
+       /* Flag the descs that no setting is active */
        for (i = 0; i < num_pins; i++) {
                desc = pin_desc_get(pctldev, pins[i]);
                if (desc == NULL) {
@@ -493,6 +466,10 @@ void pinmux_disable_setting(struct pinctrl_setting const *setting)
                desc->mux_setting = NULL;
        }
 
+       /* And release the pins */
+       for (i = 0; i < num_pins; i++)
+               pin_free(pctldev, pins[i], NULL);
+
        if (ops->disable)
                ops->disable(pctldev, setting->data.mux.func, setting->data.mux.group);
 }
index 84c56881ba805c1fa387728b64601a1a471769eb..c2e3e63d2c157880efe22ab44ae1ba049427aa8a 100644 (file)
@@ -662,7 +662,7 @@ static int acerhdf_register_thermal(void)
                return -EINVAL;
 
        thz_dev = thermal_zone_device_register("acerhdf", 1, 0, NULL,
-                                             &acerhdf_dev_ops, 0,
+                                             &acerhdf_dev_ops, NULL, 0,
                                              (kernelmode) ? interval*1000 : 0);
        if (IS_ERR(thz_dev))
                return -EINVAL;
index c0e9ff489b2417f2469e7abc7d2289e4b971c8a2..18f5169e5227c5fb8d3e2aef00f88b4b5efa8bd2 100644 (file)
@@ -187,6 +187,8 @@ struct asus_wmi {
        struct device *hwmon_device;
        struct platform_device *platform_device;
 
+       struct led_classdev wlan_led;
+       int wlan_led_wk;
        struct led_classdev tpd_led;
        int tpd_led_wk;
        struct led_classdev kbd_led;
@@ -194,6 +196,7 @@ struct asus_wmi {
        struct workqueue_struct *led_workqueue;
        struct work_struct tpd_led_work;
        struct work_struct kbd_led_work;
+       struct work_struct wlan_led_work;
 
        struct asus_rfkill wlan;
        struct asus_rfkill bluetooth;
@@ -456,12 +459,65 @@ static enum led_brightness kbd_led_get(struct led_classdev *led_cdev)
        return value;
 }
 
+static int wlan_led_unknown_state(struct asus_wmi *asus)
+{
+       u32 result;
+
+       asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_WIRELESS_LED, &result);
+
+       return result & ASUS_WMI_DSTS_UNKNOWN_BIT;
+}
+
+static int wlan_led_presence(struct asus_wmi *asus)
+{
+       u32 result;
+
+       asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_WIRELESS_LED, &result);
+
+       return result & ASUS_WMI_DSTS_PRESENCE_BIT;
+}
+
+static void wlan_led_update(struct work_struct *work)
+{
+       int ctrl_param;
+       struct asus_wmi *asus;
+
+       asus = container_of(work, struct asus_wmi, wlan_led_work);
+
+       ctrl_param = asus->wlan_led_wk;
+       asus_wmi_set_devstate(ASUS_WMI_DEVID_WIRELESS_LED, ctrl_param, NULL);
+}
+
+static void wlan_led_set(struct led_classdev *led_cdev,
+                        enum led_brightness value)
+{
+       struct asus_wmi *asus;
+
+       asus = container_of(led_cdev, struct asus_wmi, wlan_led);
+
+       asus->wlan_led_wk = !!value;
+       queue_work(asus->led_workqueue, &asus->wlan_led_work);
+}
+
+static enum led_brightness wlan_led_get(struct led_classdev *led_cdev)
+{
+       struct asus_wmi *asus;
+       u32 result;
+
+       asus = container_of(led_cdev, struct asus_wmi, wlan_led);
+       asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_WIRELESS_LED, &result);
+
+       return result & ASUS_WMI_DSTS_BRIGHTNESS_MASK;
+}
+
 static void asus_wmi_led_exit(struct asus_wmi *asus)
 {
        if (!IS_ERR_OR_NULL(asus->kbd_led.dev))
                led_classdev_unregister(&asus->kbd_led);
        if (!IS_ERR_OR_NULL(asus->tpd_led.dev))
                led_classdev_unregister(&asus->tpd_led);
+       if (!IS_ERR_OR_NULL(asus->wlan_led.dev))
+               led_classdev_unregister(&asus->wlan_led);
        if (asus->led_workqueue)
                destroy_workqueue(asus->led_workqueue);
 }
@@ -498,6 +554,23 @@ static int asus_wmi_led_init(struct asus_wmi *asus)
 
                rv = led_classdev_register(&asus->platform_device->dev,
                                           &asus->kbd_led);
+               if (rv)
+                       goto error;
+       }
+
+       if (wlan_led_presence(asus)) {
+               INIT_WORK(&asus->wlan_led_work, wlan_led_update);
+
+               asus->wlan_led.name = "asus::wlan";
+               asus->wlan_led.brightness_set = wlan_led_set;
+               if (!wlan_led_unknown_state(asus))
+                       asus->wlan_led.brightness_get = wlan_led_get;
+               asus->wlan_led.flags = LED_CORE_SUSPENDRESUME;
+               asus->wlan_led.max_brightness = 1;
+               asus->wlan_led.default_trigger = "asus-wlan";
+
+               rv = led_classdev_register(&asus->platform_device->dev,
+                                          &asus->wlan_led);
        }
 
 error:
@@ -813,6 +886,9 @@ static int asus_new_rfkill(struct asus_wmi *asus,
        if (!*rfkill)
                return -EINVAL;
 
+       if (dev_id == ASUS_WMI_DEVID_WLAN)
+               rfkill_set_led_trigger_name(*rfkill, "asus-wlan");
+
        rfkill_init_sw_state(*rfkill, !result);
        result = rfkill_register(*rfkill);
        if (result) {
index c8097616dd62fe89a135f5be607ee0f8c48d70a7..93de09019d1d53649621eda7e83529fcd75624fa 100644 (file)
@@ -502,7 +502,7 @@ static int mid_thermal_probe(struct platform_device *pdev)
                        goto err;
                }
                pinfo->tzd[i] = thermal_zone_device_register(name[i],
-                               0, 0, td_info, &tzd_ops, 0, 0);
+                               0, 0, td_info, &tzd_ops, NULL, 0, 0);
                if (IS_ERR(pinfo->tzd[i])) {
                        kfree(td_info);
                        ret = PTR_ERR(pinfo->tzd[i]);
index 2436f13500132c7bf0e2f997ab8feb9c996767de..f77a41272e5d6f3e5f9fecf1b40b7a4a5e1bb459 100644 (file)
@@ -201,7 +201,7 @@ static int psy_register_thermal(struct power_supply *psy)
        for (i = 0; i < psy->num_properties; i++) {
                if (psy->properties[i] == POWER_SUPPLY_PROP_TEMP) {
                        psy->tzd = thermal_zone_device_register(psy->name, 0, 0,
-                                       psy, &psy_tzd_ops, 0, 0);
+                                       psy, &psy_tzd_ops, NULL, 0, 0);
                        if (IS_ERR(psy->tzd))
                                return PTR_ERR(psy->tzd);
                        break;
index 67d47b59a66d878c9188afaaa62b92f255d657bb..7b920c796ccd9ecec5b4a9633c3d6261b79f44ec 100644 (file)
@@ -335,6 +335,17 @@ config REGULATOR_PALMAS
          on the muxing. This is handled automatically in the driver by
          reading the mux info from OTP.
 
+config REGULATOR_TPS51632
+       tristate "TI TPS51632 Power Regulator"
+       depends on I2C
+       select REGMAP_I2C
+       help
+         This driver supports TPS51632 voltage regulator chip.
+         The TPS52632 is 3-2-1 Phase D-Cap+ Step Down Driverless Controller
+         with Serial VID control and DVFS.
+         The voltage output can be configure through I2C interface or PWM
+         interface.
+
 config REGULATOR_TPS6105X
        tristate "TI TPS6105X Power regulators"
        depends on TPS6105X
@@ -422,6 +433,13 @@ config REGULATOR_TWL4030
          This driver supports the voltage regulators provided by
          this family of companion chips.
 
+config REGULATOR_VEXPRESS
+       tristate "Versatile Express regulators"
+       depends on VEXPRESS_CONFIG
+       help
+         This driver provides support for voltage regulators available
+         on the ARM Ltd's Versatile Express platform.
+
 config REGULATOR_WM831X
        tristate "Wolfson Microelectronics WM831x PMIC regulators"
        depends on MFD_WM831X
index e431eed8a8782f2f49fc1869365b76929dc52001..db274dcce956521491102daa74584b96b3bb5c40 100644 (file)
@@ -41,6 +41,7 @@ obj-$(CONFIG_REGULATOR_MC13783) += mc13783-regulator.o
 obj-$(CONFIG_REGULATOR_MC13892) += mc13892-regulator.o
 obj-$(CONFIG_REGULATOR_MC13XXX_CORE) +=  mc13xxx-regulator-core.o
 obj-$(CONFIG_REGULATOR_PALMAS) += palmas-regulator.o
+obj-$(CONFIG_REGULATOR_TPS51632) += tps51632-regulator.o
 obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o
 obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o
 obj-$(CONFIG_REGULATOR_RC5T583)  += rc5t583-regulator.o
@@ -57,6 +58,7 @@ obj-$(CONFIG_REGULATOR_TPS6586X) += tps6586x-regulator.o
 obj-$(CONFIG_REGULATOR_TPS65910) += tps65910-regulator.o
 obj-$(CONFIG_REGULATOR_TPS65912) += tps65912-regulator.o
 obj-$(CONFIG_REGULATOR_TWL4030) += twl-regulator.o
+obj-$(CONFIG_REGULATOR_VEXPRESS) += vexpress.o
 obj-$(CONFIG_REGULATOR_WM831X) += wm831x-dcdc.o
 obj-$(CONFIG_REGULATOR_WM831X) += wm831x-isink.o
 obj-$(CONFIG_REGULATOR_WM831X) += wm831x-ldo.o
index 5c4829cba6a62de6168c6bb3c4913812e5e8b4e1..f7c74db7465cefa6b375b19ab986f36eda0e7a1c 100644 (file)
@@ -1979,6 +1979,11 @@ int regulator_is_supported_voltage(struct regulator *regulator,
                        return ret;
        }
 
+       /* Any voltage within constrains range is fine? */
+       if (rdev->desc->continuous_voltage_range)
+               return min_uV >= rdev->constraints->min_uV &&
+                               max_uV <= rdev->constraints->max_uV;
+
        ret = regulator_count_voltages(regulator);
        if (ret < 0)
                return ret;
index 8b5944f2d7d1ddd36e82e92d786770e469743dfe..e467d0ac87059339fa1658f88d88c3051a73dc84 100644 (file)
 #include <linux/platform_device.h>
 #include <linux/regulator/driver.h>
 #include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
 #include <linux/regulator/gpio-regulator.h>
 #include <linux/gpio.h>
 #include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
 
 struct gpio_regulator_data {
        struct regulator_desc desc;
@@ -129,6 +132,84 @@ static struct regulator_ops gpio_regulator_voltage_ops = {
        .list_voltage = gpio_regulator_list_voltage,
 };
 
+struct gpio_regulator_config *
+of_get_gpio_regulator_config(struct device *dev, struct device_node *np)
+{
+       struct gpio_regulator_config *config;
+       struct property *prop;
+       const char *regtype;
+       int proplen, gpio, i;
+
+       config = devm_kzalloc(dev,
+                       sizeof(struct gpio_regulator_config),
+                       GFP_KERNEL);
+       if (!config)
+               return ERR_PTR(-ENOMEM);
+
+       config->init_data = of_get_regulator_init_data(dev, np);
+       if (!config->init_data)
+               return ERR_PTR(-EINVAL);
+
+       config->supply_name = config->init_data->constraints.name;
+
+       if (of_property_read_bool(np, "enable-active-high"))
+               config->enable_high = true;
+
+       if (of_property_read_bool(np, "enable-at-boot"))
+               config->enabled_at_boot = true;
+
+       of_property_read_u32(np, "startup-delay-us", &config->startup_delay);
+
+       config->enable_gpio = of_get_named_gpio(np, "enable-gpio", 0);
+
+       /* Fetch GPIOs. */
+       for (i = 0; ; i++)
+               if (of_get_named_gpio(np, "gpios", i) < 0)
+                       break;
+       config->nr_gpios = i;
+
+       config->gpios = devm_kzalloc(dev,
+                               sizeof(struct gpio) * config->nr_gpios,
+                               GFP_KERNEL);
+       if (!config->gpios)
+               return ERR_PTR(-ENOMEM);
+
+       for (i = 0; config->nr_gpios; i++) {
+               gpio = of_get_named_gpio(np, "gpios", i);
+               if (gpio < 0)
+                       break;
+               config->gpios[i].gpio = gpio;
+       }
+
+       /* Fetch states. */
+       prop = of_find_property(np, "states", NULL);
+       proplen = prop->length / sizeof(int);
+
+       config->states = devm_kzalloc(dev,
+                               sizeof(struct gpio_regulator_state)
+                               * (proplen / 2),
+                               GFP_KERNEL);
+       if (!config->states)
+               return ERR_PTR(-ENOMEM);
+
+       for (i = 0; i < proplen / 2; i++) {
+               config->states[i].value =
+                       be32_to_cpup((int *)prop->value + (i * 2));
+               config->states[i].gpios =
+                       be32_to_cpup((int *)prop->value + (i * 2 + 1));
+       }
+       config->nr_states = i;
+
+       of_property_read_string(np, "regulator-type", &regtype);
+
+       if (!strncmp("voltage", regtype, 7))
+               config->type = REGULATOR_VOLTAGE;
+       else if (!strncmp("current", regtype, 7))
+               config->type = REGULATOR_CURRENT;
+
+       return config;
+}
+
 static struct regulator_ops gpio_regulator_current_ops = {
        .get_current_limit = gpio_regulator_get_value,
        .set_current_limit = gpio_regulator_set_current_limit,
@@ -137,10 +218,17 @@ static struct regulator_ops gpio_regulator_current_ops = {
 static int __devinit gpio_regulator_probe(struct platform_device *pdev)
 {
        struct gpio_regulator_config *config = pdev->dev.platform_data;
+       struct device_node *np = pdev->dev.of_node;
        struct gpio_regulator_data *drvdata;
        struct regulator_config cfg = { };
        int ptr, ret, state;
 
+       if (np) {
+               config = of_get_gpio_regulator_config(&pdev->dev, np);
+               if (IS_ERR(config))
+                       return PTR_ERR(config);
+       }
+
        drvdata = devm_kzalloc(&pdev->dev, sizeof(struct gpio_regulator_data),
                               GFP_KERNEL);
        if (drvdata == NULL) {
@@ -270,12 +358,18 @@ static int __devexit gpio_regulator_remove(struct platform_device *pdev)
        return 0;
 }
 
+static const struct of_device_id regulator_gpio_of_match[] __devinitconst = {
+       { .compatible = "regulator-gpio", },
+       {},
+};
+
 static struct platform_driver gpio_regulator_driver = {
        .probe          = gpio_regulator_probe,
        .remove         = __devexit_p(gpio_regulator_remove),
        .driver         = {
                .name           = "gpio-regulator",
                .owner          = THIS_MODULE,
+               .of_match_table = regulator_gpio_of_match,
        },
 };
 
index 6796eeb47dc6f65b1997f75cacc1f04cb8e7d6cf..e496ba0753369b64120ae836f6f9042fcdb0519f 100644 (file)
@@ -126,7 +126,7 @@ struct lp8788_ldo {
 };
 
 /* DLDO 1, 2, 3, 9 voltage table */
-const int lp8788_dldo1239_vtbl[] = {
+static const int lp8788_dldo1239_vtbl[] = {
        1800000, 1900000, 2000000, 2100000, 2200000, 2300000, 2400000, 2500000,
        2600000, 2700000, 2800000, 2900000, 3000000, 2850000, 2850000, 2850000,
        2850000, 2850000, 2850000, 2850000, 2850000, 2850000, 2850000, 2850000,
index 2a67d08658add7dfcabbc1c00d4a0a02b9b70a0d..c9bec1686b88d3baefd146c6605e4393657e161e 100644 (file)
@@ -67,8 +67,94 @@ enum max77686_ramp_rate {
 
 struct max77686_data {
        struct regulator_dev *rdev[MAX77686_REGULATORS];
+       unsigned int opmode[MAX77686_REGULATORS];
 };
 
+/* Some BUCKS supports Normal[ON/OFF] mode during suspend */
+static int max77686_buck_set_suspend_disable(struct regulator_dev *rdev)
+{
+       unsigned int val;
+       struct max77686_data *max77686 = rdev_get_drvdata(rdev);
+
+       if (rdev->desc->id == MAX77686_BUCK1)
+               val = 0x1;
+       else
+               val = 0x1 << MAX77686_OPMODE_BUCK234_SHIFT;
+
+       max77686->opmode[rdev->desc->id] = val;
+       return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
+                                 rdev->desc->enable_mask,
+                                 val);
+}
+
+/* Some LDOs supports [LPM/Normal]ON mode during suspend state */
+static int max77686_set_suspend_mode(struct regulator_dev *rdev,
+                                    unsigned int mode)
+{
+       struct max77686_data *max77686 = rdev_get_drvdata(rdev);
+       unsigned int val;
+
+       /* BUCK[5-9] doesn't support this feature */
+       if (rdev->desc->id >= MAX77686_BUCK5)
+               return 0;
+
+       switch (mode) {
+       case REGULATOR_MODE_IDLE:                       /* ON in LP Mode */
+               val = 0x2 << MAX77686_OPMODE_SHIFT;
+               break;
+       case REGULATOR_MODE_NORMAL:                     /* ON in Normal Mode */
+               val = 0x3 << MAX77686_OPMODE_SHIFT;
+               break;
+       default:
+               pr_warn("%s: regulator_suspend_mode : 0x%x not supported\n",
+                       rdev->desc->name, mode);
+               return -EINVAL;
+       }
+
+       max77686->opmode[rdev->desc->id] = val;
+       return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
+                                 rdev->desc->enable_mask,
+                                 val);
+}
+
+/* Some LDOs supports LPM-ON/OFF/Normal-ON mode during suspend state */
+static int max77686_ldo_set_suspend_mode(struct regulator_dev *rdev,
+                                    unsigned int mode)
+{
+       unsigned int val;
+       struct max77686_data *max77686 = rdev_get_drvdata(rdev);
+
+       switch (mode) {
+       case REGULATOR_MODE_STANDBY:                    /* switch off */
+               val = 0x1 << MAX77686_OPMODE_SHIFT;
+               break;
+       case REGULATOR_MODE_IDLE:                       /* ON in LP Mode */
+               val = 0x2 << MAX77686_OPMODE_SHIFT;
+               break;
+       case REGULATOR_MODE_NORMAL:                     /* ON in Normal Mode */
+               val = 0x3 << MAX77686_OPMODE_SHIFT;
+               break;
+       default:
+               pr_warn("%s: regulator_suspend_mode : 0x%x not supported\n",
+                       rdev->desc->name, mode);
+               return -EINVAL;
+       }
+
+       max77686->opmode[rdev->desc->id] = val;
+       return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
+                                 rdev->desc->enable_mask,
+                                 val);
+}
+
+static int max77686_enable(struct regulator_dev *rdev)
+{
+       struct max77686_data *max77686 = rdev_get_drvdata(rdev);
+
+       return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
+                                 rdev->desc->enable_mask,
+                                 max77686->opmode[rdev->desc->id]);
+}
+
 static int max77686_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
 {
        unsigned int ramp_value = RAMP_RATE_NO_CTRL;
@@ -98,23 +184,49 @@ static struct regulator_ops max77686_ops = {
        .list_voltage           = regulator_list_voltage_linear,
        .map_voltage            = regulator_map_voltage_linear,
        .is_enabled             = regulator_is_enabled_regmap,
-       .enable                 = regulator_enable_regmap,
+       .enable                 = max77686_enable,
+       .disable                = regulator_disable_regmap,
+       .get_voltage_sel        = regulator_get_voltage_sel_regmap,
+       .set_voltage_sel        = regulator_set_voltage_sel_regmap,
+       .set_voltage_time_sel   = regulator_set_voltage_time_sel,
+       .set_suspend_mode       = max77686_set_suspend_mode,
+};
+
+static struct regulator_ops max77686_ldo_ops = {
+       .list_voltage           = regulator_list_voltage_linear,
+       .map_voltage            = regulator_map_voltage_linear,
+       .is_enabled             = regulator_is_enabled_regmap,
+       .enable                 = max77686_enable,
        .disable                = regulator_disable_regmap,
        .get_voltage_sel        = regulator_get_voltage_sel_regmap,
        .set_voltage_sel        = regulator_set_voltage_sel_regmap,
        .set_voltage_time_sel   = regulator_set_voltage_time_sel,
+       .set_suspend_mode       = max77686_ldo_set_suspend_mode,
+};
+
+static struct regulator_ops max77686_buck1_ops = {
+       .list_voltage           = regulator_list_voltage_linear,
+       .map_voltage            = regulator_map_voltage_linear,
+       .is_enabled             = regulator_is_enabled_regmap,
+       .enable                 = max77686_enable,
+       .disable                = regulator_disable_regmap,
+       .get_voltage_sel        = regulator_get_voltage_sel_regmap,
+       .set_voltage_sel        = regulator_set_voltage_sel_regmap,
+       .set_voltage_time_sel   = regulator_set_voltage_time_sel,
+       .set_suspend_disable    = max77686_buck_set_suspend_disable,
 };
 
 static struct regulator_ops max77686_buck_dvs_ops = {
        .list_voltage           = regulator_list_voltage_linear,
        .map_voltage            = regulator_map_voltage_linear,
        .is_enabled             = regulator_is_enabled_regmap,
-       .enable                 = regulator_enable_regmap,
+       .enable                 = max77686_enable,
        .disable                = regulator_disable_regmap,
        .get_voltage_sel        = regulator_get_voltage_sel_regmap,
        .set_voltage_sel        = regulator_set_voltage_sel_regmap,
        .set_voltage_time_sel   = regulator_set_voltage_time_sel,
        .set_ramp_delay         = max77686_set_ramp_delay,
+       .set_suspend_disable    = max77686_buck_set_suspend_disable,
 };
 
 #define regulator_desc_ldo(num)                {                               \
@@ -133,7 +245,39 @@ static struct regulator_ops max77686_buck_dvs_ops = {
        .enable_mask    = MAX77686_OPMODE_MASK                          \
                        << MAX77686_OPMODE_SHIFT,                       \
 }
+#define regulator_desc_lpm_ldo(num)    {                               \
+       .name           = "LDO"#num,                                    \
+       .id             = MAX77686_LDO##num,                            \
+       .ops            = &max77686_ldo_ops,                            \
+       .type           = REGULATOR_VOLTAGE,                            \
+       .owner          = THIS_MODULE,                                  \
+       .min_uV         = MAX77686_LDO_MINUV,                           \
+       .uV_step        = MAX77686_LDO_UVSTEP,                          \
+       .ramp_delay     = MAX77686_RAMP_DELAY,                          \
+       .n_voltages     = MAX77686_VSEL_MASK + 1,                       \
+       .vsel_reg       = MAX77686_REG_LDO1CTRL1 + num - 1,             \
+       .vsel_mask      = MAX77686_VSEL_MASK,                           \
+       .enable_reg     = MAX77686_REG_LDO1CTRL1 + num - 1,             \
+       .enable_mask    = MAX77686_OPMODE_MASK                          \
+                       << MAX77686_OPMODE_SHIFT,                       \
+}
 #define regulator_desc_ldo_low(num)            {                       \
+       .name           = "LDO"#num,                                    \
+       .id             = MAX77686_LDO##num,                            \
+       .ops            = &max77686_ldo_ops,                            \
+       .type           = REGULATOR_VOLTAGE,                            \
+       .owner          = THIS_MODULE,                                  \
+       .min_uV         = MAX77686_LDO_LOW_MINUV,                       \
+       .uV_step        = MAX77686_LDO_LOW_UVSTEP,                      \
+       .ramp_delay     = MAX77686_RAMP_DELAY,                          \
+       .n_voltages     = MAX77686_VSEL_MASK + 1,                       \
+       .vsel_reg       = MAX77686_REG_LDO1CTRL1 + num - 1,             \
+       .vsel_mask      = MAX77686_VSEL_MASK,                           \
+       .enable_reg     = MAX77686_REG_LDO1CTRL1 + num - 1,             \
+       .enable_mask    = MAX77686_OPMODE_MASK                          \
+                       << MAX77686_OPMODE_SHIFT,                       \
+}
+#define regulator_desc_ldo1_low(num)           {                       \
        .name           = "LDO"#num,                                    \
        .id             = MAX77686_LDO##num,                            \
        .ops            = &max77686_ops,                                \
@@ -167,7 +311,7 @@ static struct regulator_ops max77686_buck_dvs_ops = {
 #define regulator_desc_buck1(num)              {                       \
        .name           = "BUCK"#num,                                   \
        .id             = MAX77686_BUCK##num,                           \
-       .ops            = &max77686_ops,                                \
+       .ops            = &max77686_buck1_ops,                          \
        .type           = REGULATOR_VOLTAGE,                            \
        .owner          = THIS_MODULE,                                  \
        .min_uV         = MAX77686_BUCK_MINUV,                          \
@@ -197,7 +341,7 @@ static struct regulator_ops max77686_buck_dvs_ops = {
 }
 
 static struct regulator_desc regulators[] = {
-       regulator_desc_ldo_low(1),
+       regulator_desc_ldo1_low(1),
        regulator_desc_ldo_low(2),
        regulator_desc_ldo(3),
        regulator_desc_ldo(4),
@@ -206,13 +350,13 @@ static struct regulator_desc regulators[] = {
        regulator_desc_ldo_low(7),
        regulator_desc_ldo_low(8),
        regulator_desc_ldo(9),
-       regulator_desc_ldo(10),
-       regulator_desc_ldo(11),
-       regulator_desc_ldo(12),
+       regulator_desc_lpm_ldo(10),
+       regulator_desc_lpm_ldo(11),
+       regulator_desc_lpm_ldo(12),
        regulator_desc_ldo(13),
-       regulator_desc_ldo(14),
+       regulator_desc_lpm_ldo(14),
        regulator_desc_ldo_low(15),
-       regulator_desc_ldo(16),
+       regulator_desc_lpm_ldo(16),
        regulator_desc_ldo(17),
        regulator_desc_ldo(18),
        regulator_desc_ldo(19),
@@ -314,12 +458,14 @@ static __devinit int max77686_pmic_probe(struct platform_device *pdev)
 
        config.dev = &pdev->dev;
        config.regmap = iodev->regmap;
+       config.driver_data = max77686;
        platform_set_drvdata(pdev, max77686);
 
        for (i = 0; i < MAX77686_REGULATORS; i++) {
                config.init_data = pdata->regulators[i].initdata;
                config.of_node = pdata->regulators[i].of_node;
 
+               max77686->opmode[i] = regulators[i].enable_mask;
                max77686->rdev[i] = regulator_register(&regulators[i], &config);
                if (IS_ERR(max77686->rdev[i])) {
                        ret = PTR_ERR(max77686->rdev[i]);
diff --git a/drivers/regulator/tps51632-regulator.c b/drivers/regulator/tps51632-regulator.c
new file mode 100644 (file)
index 0000000..3460364
--- /dev/null
@@ -0,0 +1,332 @@
+/*
+ * tps51632-regulator.c -- TI TPS51632
+ *
+ * Regulator driver for TPS51632 3-2-1 Phase D-Cap Step Down Driverless
+ * Controller with serial VID control and DVFS.
+ *
+ * Copyright (c) 2012, NVIDIA Corporation.
+ *
+ * Author: Laxman Dewangan <ldewangan@nvidia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
+ * whether express or implied; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307, USA
+ */
+
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/tps51632-regulator.h>
+#include <linux/slab.h>
+
+/* Register definitions */
+#define TPS51632_VOLTAGE_SELECT_REG            0x0
+#define TPS51632_VOLTAGE_BASE_REG              0x1
+#define TPS51632_OFFSET_REG                    0x2
+#define TPS51632_IMON_REG                      0x3
+#define TPS51632_VMAX_REG                      0x4
+#define TPS51632_DVFS_CONTROL_REG              0x5
+#define TPS51632_POWER_STATE_REG               0x6
+#define TPS51632_SLEW_REGS                     0x7
+#define TPS51632_FAULT_REG                     0x14
+
+#define TPS51632_MAX_REG                       0x15
+
+#define TPS51632_VOUT_MASK                     0x7F
+#define TPS51632_VOUT_OFFSET_MASK              0x1F
+#define TPS51632_VMAX_MASK                     0x7F
+#define TPS51632_VMAX_LOCK                     0x80
+
+/* TPS51632_DVFS_CONTROL_REG */
+#define TPS51632_DVFS_PWMEN                    0x1
+#define TPS51632_DVFS_STEP_20                  0x2
+#define TPS51632_DVFS_VMAX_PG                  0x4
+#define TPS51632_DVFS_PWMRST                   0x8
+#define TPS51632_DVFS_OCA_EN                   0x10
+#define TPS51632_DVFS_FCCM                     0x20
+
+/* TPS51632_POWER_STATE_REG */
+#define TPS51632_POWER_STATE_MASK              0x03
+#define TPS51632_POWER_STATE_MULTI_PHASE_CCM   0x0
+#define TPS51632_POWER_STATE_SINGLE_PHASE_CCM  0x1
+#define TPS51632_POWER_STATE_SINGLE_PHASE_DCM  0x2
+
+#define TPS51632_MIN_VOLATGE                   500000
+#define TPS51632_MAX_VOLATGE                   1520000
+#define TPS51632_VOLATGE_STEP_10mV             10000
+#define TPS51632_VOLATGE_STEP_20mV             20000
+#define TPS51632_MAX_VSEL                      0x7F
+#define TPS51632_MIN_VSEL                      0x19
+#define TPS51632_DEFAULT_RAMP_DELAY            6000
+#define TPS51632_VOLT_VSEL(uV)                                 \
+               (DIV_ROUND_UP(uV - TPS51632_MIN_VOLATGE,        \
+                       TPS51632_VOLATGE_STEP_10mV) +           \
+                       TPS51632_MIN_VSEL)
+
+/* TPS51632 chip information */
+struct tps51632_chip {
+       struct device *dev;
+       struct regulator_desc desc;
+       struct regulator_dev *rdev;
+       struct regmap *regmap;
+       bool enable_pwm_dvfs;
+};
+
+static int tps51632_dcdc_get_voltage_sel(struct regulator_dev *rdev)
+{
+       struct tps51632_chip *tps = rdev_get_drvdata(rdev);
+       unsigned int data;
+       int ret;
+       unsigned int reg = TPS51632_VOLTAGE_SELECT_REG;
+       int vsel;
+
+       if (tps->enable_pwm_dvfs)
+               reg = TPS51632_VOLTAGE_BASE_REG;
+
+       ret = regmap_read(tps->regmap, reg, &data);
+       if (ret < 0) {
+               dev_err(tps->dev, "reg read failed, err %d\n", ret);
+               return ret;
+       }
+
+       vsel = data & TPS51632_VOUT_MASK;
+
+       if (vsel < TPS51632_MIN_VSEL)
+               return 0;
+       else
+               return vsel - TPS51632_MIN_VSEL;
+}
+
+static int tps51632_dcdc_set_voltage_sel(struct regulator_dev *rdev,
+               unsigned selector)
+{
+       struct tps51632_chip *tps = rdev_get_drvdata(rdev);
+       int vsel;
+       int ret;
+       unsigned int reg = TPS51632_VOLTAGE_SELECT_REG;
+
+       if (tps->enable_pwm_dvfs)
+               reg = TPS51632_VOLTAGE_BASE_REG;
+
+       vsel = selector + TPS51632_MIN_VSEL;
+       if (vsel > TPS51632_MAX_VSEL)
+               return -EINVAL;
+
+       ret = regmap_write(tps->regmap, TPS51632_VOLTAGE_SELECT_REG, vsel);
+       if (ret < 0)
+               dev_err(tps->dev, "reg write failed, err %d\n", ret);
+       return ret;
+}
+
+static int tps51632_dcdc_set_ramp_delay(struct regulator_dev *rdev,
+               int ramp_delay)
+{
+       struct tps51632_chip *tps = rdev_get_drvdata(rdev);
+       int bit = ramp_delay/6000;
+       int ret;
+
+       if (bit)
+               bit--;
+       ret = regmap_write(tps->regmap, TPS51632_SLEW_REGS, BIT(bit));
+       if (ret < 0)
+               dev_err(tps->dev, "SLEW reg write failed, err %d\n", ret);
+       return ret;
+}
+
+static struct regulator_ops tps51632_dcdc_ops = {
+       .get_voltage_sel        = tps51632_dcdc_get_voltage_sel,
+       .set_voltage_sel        = tps51632_dcdc_set_voltage_sel,
+       .list_voltage           = regulator_list_voltage_linear,
+       .set_voltage_time_sel   = regulator_set_voltage_time_sel,
+       .set_ramp_delay         = tps51632_dcdc_set_ramp_delay,
+};
+
+static int __devinit tps51632_init_dcdc(struct tps51632_chip *tps,
+               struct tps51632_regulator_platform_data *pdata)
+{
+       int ret;
+       uint8_t control = 0;
+       int vsel;
+
+       if (!pdata->enable_pwm_dvfs)
+               goto skip_pwm_config;
+
+       control |= TPS51632_DVFS_PWMEN;
+       tps->enable_pwm_dvfs = pdata->enable_pwm_dvfs;
+       vsel = TPS51632_VOLT_VSEL(pdata->base_voltage_uV);
+       ret = regmap_write(tps->regmap, TPS51632_VOLTAGE_BASE_REG, vsel);
+       if (ret < 0) {
+               dev_err(tps->dev, "BASE reg write failed, err %d\n", ret);
+               return ret;
+       }
+
+       if (pdata->dvfs_step_20mV)
+               control |= TPS51632_DVFS_STEP_20;
+
+       if (pdata->max_voltage_uV) {
+               unsigned int vmax;
+               /**
+                * TPS51632 hw behavior: VMAX register can be write only
+                * once as it get locked after first write. The lock get
+                * reset only when device is power-reset.
+                * Write register only when lock bit is not enabled.
+                */
+               ret = regmap_read(tps->regmap, TPS51632_VMAX_REG, &vmax);
+               if (ret < 0) {
+                       dev_err(tps->dev, "VMAX read failed, err %d\n", ret);
+                       return ret;
+               }
+               if (!(vmax & TPS51632_VMAX_LOCK)) {
+                       vsel = TPS51632_VOLT_VSEL(pdata->max_voltage_uV);
+                       ret = regmap_write(tps->regmap, TPS51632_VMAX_REG,
+                                       vsel);
+                       if (ret < 0) {
+                               dev_err(tps->dev,
+                                       "VMAX write failed, err %d\n", ret);
+                               return ret;
+                       }
+               }
+       }
+
+skip_pwm_config:
+       ret = regmap_write(tps->regmap, TPS51632_DVFS_CONTROL_REG, control);
+       if (ret < 0)
+               dev_err(tps->dev, "DVFS reg write failed, err %d\n", ret);
+       return ret;
+}
+
+static bool rd_wr_reg(struct device *dev, unsigned int reg)
+{
+       if ((reg >= 0x8) && (reg <= 0x10))
+               return false;
+       return true;
+}
+
+static const struct regmap_config tps51632_regmap_config = {
+       .reg_bits               = 8,
+       .val_bits               = 8,
+       .writeable_reg          = rd_wr_reg,
+       .readable_reg           = rd_wr_reg,
+       .max_register           = TPS51632_MAX_REG - 1,
+       .cache_type             = REGCACHE_RBTREE,
+};
+
+static int __devinit tps51632_probe(struct i2c_client *client,
+                               const struct i2c_device_id *id)
+{
+       struct tps51632_regulator_platform_data *pdata;
+       struct regulator_dev *rdev;
+       struct tps51632_chip *tps;
+       int ret;
+       struct regulator_config config = { };
+
+       pdata = client->dev.platform_data;
+       if (!pdata) {
+               dev_err(&client->dev, "No Platform data\n");
+               return -EINVAL;
+       }
+
+       tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL);
+       if (!tps) {
+               dev_err(&client->dev, "Memory allocation failed\n");
+               return -ENOMEM;
+       }
+
+       tps->dev = &client->dev;
+       tps->desc.name = id->name;
+       tps->desc.id = 0;
+       tps->desc.ramp_delay = TPS51632_DEFAULT_RAMP_DELAY;
+       tps->desc.min_uV = TPS51632_MIN_VOLATGE;
+       tps->desc.uV_step = TPS51632_VOLATGE_STEP_10mV;
+       tps->desc.n_voltages = (TPS51632_MAX_VSEL - TPS51632_MIN_VSEL) + 1;
+       tps->desc.ops = &tps51632_dcdc_ops;
+       tps->desc.type = REGULATOR_VOLTAGE;
+       tps->desc.owner = THIS_MODULE;
+
+       tps->regmap = devm_regmap_init_i2c(client, &tps51632_regmap_config);
+       if (IS_ERR(tps->regmap)) {
+               ret = PTR_ERR(tps->regmap);
+               dev_err(&client->dev, "regmap init failed, err %d\n", ret);
+               return ret;
+       }
+       i2c_set_clientdata(client, tps);
+
+       ret = tps51632_init_dcdc(tps, pdata);
+       if (ret < 0) {
+               dev_err(tps->dev, "Init failed, err = %d\n", ret);
+               return ret;
+       }
+
+       /* Register the regulators */
+       config.dev = &client->dev;
+       config.init_data = pdata->reg_init_data;
+       config.driver_data = tps;
+       config.regmap = tps->regmap;
+       config.of_node = client->dev.of_node;
+
+       rdev = regulator_register(&tps->desc, &config);
+       if (IS_ERR(rdev)) {
+               dev_err(tps->dev, "regulator register failed\n");
+               return PTR_ERR(rdev);
+       }
+
+       tps->rdev = rdev;
+       return 0;
+}
+
+static int __devexit tps51632_remove(struct i2c_client *client)
+{
+       struct tps51632_chip *tps = i2c_get_clientdata(client);
+
+       regulator_unregister(tps->rdev);
+       return 0;
+}
+
+static const struct i2c_device_id tps51632_id[] = {
+       {.name = "tps51632",},
+       {},
+};
+
+MODULE_DEVICE_TABLE(i2c, tps51632_id);
+
+static struct i2c_driver tps51632_i2c_driver = {
+       .driver = {
+               .name = "tps51632",
+               .owner = THIS_MODULE,
+       },
+       .probe = tps51632_probe,
+       .remove = __devexit_p(tps51632_remove),
+       .id_table = tps51632_id,
+};
+
+static int __init tps51632_init(void)
+{
+       return i2c_add_driver(&tps51632_i2c_driver);
+}
+subsys_initcall(tps51632_init);
+
+static void __exit tps51632_cleanup(void)
+{
+       i2c_del_driver(&tps51632_i2c_driver);
+}
+module_exit(tps51632_cleanup);
+
+MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
+MODULE_DESCRIPTION("TPS51632 voltage regulator driver");
+MODULE_LICENSE("GPL v2");
index 001ad554ac62634c6a77897ffc9a92cf641c2abf..412413838e1247665a67552136fea87fc660c02f 100644 (file)
 
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/gpio.h>
 #include <linux/slab.h>
 #include <linux/err.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/driver.h>
 #include <linux/regulator/machine.h>
 #include <linux/mfd/tps65090.h>
-#include <linux/regulator/tps65090-regulator.h>
 
 struct tps65090_regulator {
-       int             id;
-       /* used by regulator core */
-       struct regulator_desc   desc;
-
-       /* Device */
        struct device           *dev;
+       struct regulator_desc   *desc;
+       struct regulator_dev    *rdev;
+};
+
+static struct regulator_ops tps65090_ext_control_ops = {
+};
+
+static struct regulator_ops tps65090_reg_contol_ops = {
+       .enable         = regulator_enable_regmap,
+       .disable        = regulator_disable_regmap,
+       .is_enabled     = regulator_is_enabled_regmap,
 };
 
-static struct regulator_ops tps65090_ops = {
-       .enable = regulator_enable_regmap,
-       .disable = regulator_disable_regmap,
-       .is_enabled = regulator_is_enabled_regmap,
+static struct regulator_ops tps65090_ldo_ops = {
 };
 
-#define tps65090_REG(_id)                              \
+#define tps65090_REG_DESC(_id, _sname, _en_reg, _ops)  \
 {                                                      \
-       .id             = TPS65090_ID_##_id,            \
-       .desc = {                                       \
-               .name = tps65090_rails(_id),            \
-               .id = TPS65090_ID_##_id,                \
-               .ops = &tps65090_ops,                   \
-               .type = REGULATOR_VOLTAGE,              \
-               .owner = THIS_MODULE,                   \
-               .enable_reg = (TPS65090_ID_##_id) + 12, \
-               .enable_mask = BIT(0),                  \
-       },                                              \
+       .name = "TPS65090_RAILS"#_id,                   \
+       .supply_name = _sname,                          \
+       .id = TPS65090_REGULATOR_##_id,                 \
+       .ops = &_ops,                                   \
+       .enable_reg = _en_reg,                          \
+       .enable_mask = BIT(0),                          \
+       .type = REGULATOR_VOLTAGE,                      \
+       .owner = THIS_MODULE,                           \
 }
 
-static struct tps65090_regulator TPS65090_regulator[] = {
-       tps65090_REG(DCDC1),
-       tps65090_REG(DCDC2),
-       tps65090_REG(DCDC3),
-       tps65090_REG(FET1),
-       tps65090_REG(FET2),
-       tps65090_REG(FET3),
-       tps65090_REG(FET4),
-       tps65090_REG(FET5),
-       tps65090_REG(FET6),
-       tps65090_REG(FET7),
+static struct regulator_desc tps65090_regulator_desc[] = {
+       tps65090_REG_DESC(DCDC1, "vsys1",   0x0C, tps65090_reg_contol_ops),
+       tps65090_REG_DESC(DCDC2, "vsys2",   0x0D, tps65090_reg_contol_ops),
+       tps65090_REG_DESC(DCDC3, "vsys3",   0x0E, tps65090_reg_contol_ops),
+       tps65090_REG_DESC(FET1,  "infet1",  0x0F, tps65090_reg_contol_ops),
+       tps65090_REG_DESC(FET2,  "infet2",  0x10, tps65090_reg_contol_ops),
+       tps65090_REG_DESC(FET3,  "infet3",  0x11, tps65090_reg_contol_ops),
+       tps65090_REG_DESC(FET4,  "infet4",  0x12, tps65090_reg_contol_ops),
+       tps65090_REG_DESC(FET5,  "infet5",  0x13, tps65090_reg_contol_ops),
+       tps65090_REG_DESC(FET6,  "infet6",  0x14, tps65090_reg_contol_ops),
+       tps65090_REG_DESC(FET7,  "infet7",  0x15, tps65090_reg_contol_ops),
+       tps65090_REG_DESC(LDO1,  "vsys_l1", 0,    tps65090_ldo_ops),
+       tps65090_REG_DESC(LDO2,  "vsys_l2", 0,    tps65090_ldo_ops),
 };
 
-static inline struct tps65090_regulator *find_regulator_info(int id)
+static inline bool is_dcdc(int id)
 {
-       struct tps65090_regulator *ri;
-       int i;
+       switch (id) {
+       case TPS65090_REGULATOR_DCDC1:
+       case TPS65090_REGULATOR_DCDC2:
+       case TPS65090_REGULATOR_DCDC3:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static int __devinit tps65090_config_ext_control(
+       struct tps65090_regulator *ri, bool enable)
+{
+       int ret;
+       struct device *parent = ri->dev->parent;
+       unsigned int reg_en_reg = ri->desc->enable_reg;
+
+       if (enable)
+               ret = tps65090_set_bits(parent, reg_en_reg, 1);
+       else
+               ret =  tps65090_clr_bits(parent, reg_en_reg, 1);
+       if (ret < 0)
+               dev_err(ri->dev, "Error in updating reg 0x%x\n", reg_en_reg);
+       return ret;
+}
+
+static int __devinit tps65090_regulator_disable_ext_control(
+               struct tps65090_regulator *ri,
+               struct tps65090_regulator_plat_data *tps_pdata)
+{
+       int ret = 0;
+       struct device *parent = ri->dev->parent;
+       unsigned int reg_en_reg = ri->desc->enable_reg;
+
+       /*
+        * First enable output for internal control if require.
+        * And then disable external control.
+        */
+       if (tps_pdata->reg_init_data->constraints.always_on ||
+                       tps_pdata->reg_init_data->constraints.boot_on) {
+               ret =  tps65090_set_bits(parent, reg_en_reg, 0);
+               if (ret < 0) {
+                       dev_err(ri->dev, "Error in set reg 0x%x\n", reg_en_reg);
+                       return ret;
+               }
+       }
+       return tps65090_config_ext_control(ri, false);
+}
+
+static void __devinit tps65090_configure_regulator_config(
+               struct tps65090_regulator_plat_data *tps_pdata,
+               struct regulator_config *config)
+{
+       if (gpio_is_valid(tps_pdata->gpio)) {
+               int gpio_flag = GPIOF_OUT_INIT_LOW;
+
+               if (tps_pdata->reg_init_data->constraints.always_on ||
+                               tps_pdata->reg_init_data->constraints.boot_on)
+                       gpio_flag = GPIOF_OUT_INIT_HIGH;
 
-       for (i = 0; i < ARRAY_SIZE(TPS65090_regulator); i++) {
-               ri = &TPS65090_regulator[i];
-               if (ri->desc.id == id)
-                       return ri;
+               config->ena_gpio = tps_pdata->gpio;
+               config->ena_gpio_flags = gpio_flag;
        }
-       return NULL;
 }
 
 static int __devinit tps65090_regulator_probe(struct platform_device *pdev)
@@ -87,46 +144,110 @@ static int __devinit tps65090_regulator_probe(struct platform_device *pdev)
        struct tps65090_regulator *ri = NULL;
        struct regulator_config config = { };
        struct regulator_dev *rdev;
-       struct tps65090_regulator_platform_data *tps_pdata;
-       int id = pdev->id;
+       struct tps65090_regulator_plat_data *tps_pdata;
+       struct tps65090_regulator *pmic;
+       struct tps65090_platform_data *tps65090_pdata;
+       int num;
+       int ret;
 
-       dev_dbg(&pdev->dev, "Probing regulator %d\n", id);
+       dev_dbg(&pdev->dev, "Probing regulator\n");
 
-       ri = find_regulator_info(id);
-       if (ri == NULL) {
-               dev_err(&pdev->dev, "invalid regulator ID specified\n");
+       tps65090_pdata = dev_get_platdata(pdev->dev.parent);
+       if (!tps65090_pdata) {
+               dev_err(&pdev->dev, "Platform data missing\n");
                return -EINVAL;
        }
-       tps_pdata = pdev->dev.platform_data;
-       ri->dev = &pdev->dev;
-
-       config.dev = &pdev->dev;
-       config.init_data = &tps_pdata->regulator;
-       config.driver_data = ri;
-       config.regmap = tps65090_mfd->rmap;
-
-       rdev = regulator_register(&ri->desc, &config);
-       if (IS_ERR(rdev)) {
-               dev_err(&pdev->dev, "failed to register regulator %s\n",
-                               ri->desc.name);
-               return PTR_ERR(rdev);
+
+       pmic = devm_kzalloc(&pdev->dev, TPS65090_REGULATOR_MAX * sizeof(*pmic),
+                       GFP_KERNEL);
+       if (!pmic) {
+               dev_err(&pdev->dev, "mem alloc for pmic failed\n");
+               return -ENOMEM;
+       }
+
+       for (num = 0; num < TPS65090_REGULATOR_MAX; num++) {
+               tps_pdata = tps65090_pdata->reg_pdata[num];
+
+               ri = &pmic[num];
+               ri->dev = &pdev->dev;
+               ri->desc = &tps65090_regulator_desc[num];
+
+               /*
+                * TPS5090 DCDC support the control from external digital input.
+                * Configure it as per platform data.
+                */
+               if (tps_pdata && is_dcdc(num) && tps_pdata->reg_init_data) {
+                       if (tps_pdata->enable_ext_control) {
+                               tps65090_configure_regulator_config(
+                                               tps_pdata, &config);
+                               ri->desc->ops = &tps65090_ext_control_ops;
+                       } else {
+                               ret = tps65090_regulator_disable_ext_control(
+                                               ri, tps_pdata);
+                               if (ret < 0) {
+                                       dev_err(&pdev->dev,
+                                               "failed disable ext control\n");
+                                       goto scrub;
+                               }
+                       }
+               }
+
+               config.dev = &pdev->dev;
+               config.driver_data = ri;
+               config.regmap = tps65090_mfd->rmap;
+               if (tps_pdata)
+                       config.init_data = tps_pdata->reg_init_data;
+               else
+                       config.init_data = NULL;
+
+               rdev = regulator_register(ri->desc, &config);
+               if (IS_ERR(rdev)) {
+                       dev_err(&pdev->dev, "failed to register regulator %s\n",
+                               ri->desc->name);
+                       ret = PTR_ERR(rdev);
+                       goto scrub;
+               }
+               ri->rdev = rdev;
+
+               /* Enable external control if it is require */
+               if (tps_pdata && is_dcdc(num) && tps_pdata->reg_init_data &&
+                               tps_pdata->enable_ext_control) {
+                       ret = tps65090_config_ext_control(ri, true);
+                       if (ret < 0) {
+                               /* Increment num to get unregister rdev */
+                               num++;
+                               goto scrub;
+                       }
+               }
        }
 
-       platform_set_drvdata(pdev, rdev);
+       platform_set_drvdata(pdev, pmic);
        return 0;
+
+scrub:
+       while (--num >= 0) {
+               ri = &pmic[num];
+               regulator_unregister(ri->rdev);
+       }
+       return ret;
 }
 
 static int __devexit tps65090_regulator_remove(struct platform_device *pdev)
 {
-       struct regulator_dev *rdev = platform_get_drvdata(pdev);
+       struct tps65090_regulator *pmic = platform_get_drvdata(pdev);
+       struct tps65090_regulator *ri;
+       int num;
 
-       regulator_unregister(rdev);
+       for (num = 0; num < TPS65090_REGULATOR_MAX; ++num) {
+               ri = &pmic[num];
+               regulator_unregister(ri->rdev);
+       }
        return 0;
 }
 
 static struct platform_driver tps65090_regulator_driver = {
        .driver = {
-               .name   = "tps65090-regulator",
+               .name   = "tps65090-pmic",
                .owner  = THIS_MODULE,
        },
        .probe          = tps65090_regulator_probe,
diff --git a/drivers/regulator/vexpress.c b/drivers/regulator/vexpress.c
new file mode 100644 (file)
index 0000000..1d55811
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * Copyright (C) 2012 ARM Limited
+ */
+
+#define DRVNAME "vexpress-regulator"
+#define pr_fmt(fmt) DRVNAME ": " fmt
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/vexpress.h>
+
+struct vexpress_regulator {
+       struct regulator_desc desc;
+       struct regulator_dev *regdev;
+       struct vexpress_config_func *func;
+};
+
+static int vexpress_regulator_get_voltage(struct regulator_dev *regdev)
+{
+       struct vexpress_regulator *reg = rdev_get_drvdata(regdev);
+       u32 uV;
+       int err = vexpress_config_read(reg->func, 0, &uV);
+
+       return err ? err : uV;
+}
+
+static int vexpress_regulator_set_voltage(struct regulator_dev *regdev,
+               int min_uV, int max_uV, unsigned *selector)
+{
+       struct vexpress_regulator *reg = rdev_get_drvdata(regdev);
+
+       return vexpress_config_write(reg->func, 0, min_uV);
+}
+
+static struct regulator_ops vexpress_regulator_ops_ro = {
+       .get_voltage = vexpress_regulator_get_voltage,
+};
+
+static struct regulator_ops vexpress_regulator_ops = {
+       .get_voltage = vexpress_regulator_get_voltage,
+       .set_voltage = vexpress_regulator_set_voltage,
+};
+
+static int vexpress_regulator_probe(struct platform_device *pdev)
+{
+       int err;
+       struct vexpress_regulator *reg;
+       struct regulator_init_data *init_data;
+       struct regulator_config config = { };
+
+       reg = devm_kzalloc(&pdev->dev, sizeof(*reg), GFP_KERNEL);
+       if (!reg) {
+               err = -ENOMEM;
+               goto error_kzalloc;
+       }
+
+       reg->func = vexpress_config_func_get_by_dev(&pdev->dev);
+       if (!reg->func) {
+               err = -ENXIO;
+               goto error_get_func;
+       }
+
+       reg->desc.name = dev_name(&pdev->dev);
+       reg->desc.type = REGULATOR_VOLTAGE;
+       reg->desc.owner = THIS_MODULE;
+       reg->desc.continuous_voltage_range = true;
+
+       init_data = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node);
+       if (!init_data) {
+               err = -EINVAL;
+               goto error_get_regulator_init_data;
+       }
+
+       init_data->constraints.apply_uV = 0;
+       if (init_data->constraints.min_uV && init_data->constraints.max_uV)
+               reg->desc.ops = &vexpress_regulator_ops;
+       else
+               reg->desc.ops = &vexpress_regulator_ops_ro;
+
+       config.dev = &pdev->dev;
+       config.init_data = init_data;
+       config.driver_data = reg;
+       config.of_node = pdev->dev.of_node;
+
+       reg->regdev = regulator_register(&reg->desc, &config);
+       if (IS_ERR(reg->regdev)) {
+               err = PTR_ERR(reg->regdev);
+               goto error_regulator_register;
+       }
+
+       platform_set_drvdata(pdev, reg);
+
+       return 0;
+
+error_regulator_register:
+error_get_regulator_init_data:
+       vexpress_config_func_put(reg->func);
+error_get_func:
+error_kzalloc:
+       return err;
+}
+
+static int __devexit vexpress_regulator_remove(struct platform_device *pdev)
+{
+       struct vexpress_regulator *reg = platform_get_drvdata(pdev);
+
+       vexpress_config_func_put(reg->func);
+       regulator_unregister(reg->regdev);
+
+       return 0;
+}
+
+static struct of_device_id vexpress_regulator_of_match[] = {
+       { .compatible = "arm,vexpress-volt", },
+       { }
+};
+
+static struct platform_driver vexpress_regulator_driver = {
+       .probe = vexpress_regulator_probe,
+       .remove = __devexit_p(vexpress_regulator_remove),
+       .driver = {
+               .name = DRVNAME,
+               .owner = THIS_MODULE,
+               .of_match_table = vexpress_regulator_of_match,
+       },
+};
+
+module_platform_driver(vexpress_regulator_driver);
+
+MODULE_AUTHOR("Pawel Moll <pawel.moll@arm.com>");
+MODULE_DESCRIPTION("Versatile Express regulator");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:vexpress-regulator");
index 1859f71372e24912203dca245f3d60c71c80a35d..027096fe6a124dc9edde55da90517c5daac38747 100644 (file)
@@ -764,7 +764,7 @@ int rpmsg_send_offchannel_raw(struct rpmsg_channel *rpdev, u32 src, u32 dst,
 
        /* add message to the remote processor's virtqueue */
        err = virtqueue_add_buf(vrp->svq, &sg, 1, 0, msg, GFP_KERNEL);
-       if (err < 0) {
+       if (err) {
                /*
                 * need to reclaim the buffer here, otherwise it's lost
                 * (memory won't leak, but rpmsg won't use it again for TX).
@@ -776,8 +776,6 @@ int rpmsg_send_offchannel_raw(struct rpmsg_channel *rpdev, u32 src, u32 dst,
 
        /* tell the remote processor it has a pending message to read */
        virtqueue_kick(vrp->svq);
-
-       err = 0;
 out:
        mutex_unlock(&vrp->tx_lock);
        return err;
@@ -980,7 +978,7 @@ static int rpmsg_probe(struct virtio_device *vdev)
 
                err = virtqueue_add_buf(vrp->rvq, &sg, 0, 1, cpu_addr,
                                                                GFP_KERNEL);
-               WARN_ON(err < 0); /* sanity check; this can't really happen */
+               WARN_ON(err); /* sanity check; this can't really happen */
        }
 
        /* suppress "tx-complete" interrupts */
index cd0106293a4903672f2de56c008ecc7f0534c2e7..7304139934aaff357cde2f88b0b5db49d9095d43 100644 (file)
@@ -17,8 +17,6 @@
 #include <linux/platform_device.h>
 #include <linux/clk.h>
 
-#include <mach/hardware.h>
-
 #define RTC_INPUT_CLK_32768HZ  (0x00 << 5)
 #define RTC_INPUT_CLK_32000HZ  (0x01 << 5)
 #define RTC_INPUT_CLK_38400HZ  (0x02 << 5)
@@ -72,14 +70,38 @@ static const u32 PIE_BIT_DEF[MAX_PIE_NUM][2] = {
 #define RTC_TEST2      0x2C    /*  32bit rtc test reg 2 */
 #define RTC_TEST3      0x30    /*  32bit rtc test reg 3 */
 
+enum imx_rtc_type {
+       IMX1_RTC,
+       IMX21_RTC,
+};
+
 struct rtc_plat_data {
        struct rtc_device *rtc;
        void __iomem *ioaddr;
        int irq;
        struct clk *clk;
        struct rtc_time g_rtc_alarm;
+       enum imx_rtc_type devtype;
 };
 
+static struct platform_device_id imx_rtc_devtype[] = {
+       {
+               .name = "imx1-rtc",
+               .driver_data = IMX1_RTC,
+       }, {
+               .name = "imx21-rtc",
+               .driver_data = IMX21_RTC,
+       }, {
+               /* sentinel */
+       }
+};
+MODULE_DEVICE_TABLE(platform, imx_rtc_devtype);
+
+static inline int is_imx1_rtc(struct rtc_plat_data *data)
+{
+       return data->devtype == IMX1_RTC;
+}
+
 /*
  * This function is used to obtain the RTC time or the alarm value in
  * second.
@@ -278,10 +300,13 @@ static int mxc_rtc_read_time(struct device *dev, struct rtc_time *tm)
  */
 static int mxc_rtc_set_mmss(struct device *dev, unsigned long time)
 {
+       struct platform_device *pdev = to_platform_device(dev);
+       struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+
        /*
         * TTC_DAYR register is 9-bit in MX1 SoC, save time and day of year only
         */
-       if (cpu_is_mx1()) {
+       if (is_imx1_rtc(pdata)) {
                struct rtc_time tm;
 
                rtc_time_to_tm(time, &tm);
@@ -360,6 +385,8 @@ static int __devinit mxc_rtc_probe(struct platform_device *pdev)
        if (!pdata)
                return -ENOMEM;
 
+       pdata->devtype = pdev->id_entry->driver_data;
+
        if (!devm_request_mem_region(&pdev->dev, res->start,
                                     resource_size(res), pdev->name))
                return -EBUSY;
@@ -480,6 +507,7 @@ static struct platform_driver mxc_rtc_driver = {
 #endif
                   .owner       = THIS_MODULE,
        },
+       .id_table = imx_rtc_devtype,
        .probe = mxc_rtc_probe,
        .remove = __devexit_p(mxc_rtc_remove),
 };
index b4d572f65f079d93650cebd8ff5f7bb39bcb75d2..fd00afd8b850da2abaa916ba485dccd748939319 100644 (file)
@@ -377,7 +377,11 @@ static int css_evaluate_new_subchannel(struct subchannel_id schid, int slow)
                /* Will be done on the slow path. */
                return -EAGAIN;
        }
-       if (stsch_err(schid, &schib) || !css_sch_is_valid(&schib)) {
+       if (stsch_err(schid, &schib)) {
+               /* Subchannel is not provided. */
+               return -ENXIO;
+       }
+       if (!css_sch_is_valid(&schib)) {
                /* Unusable - ignore. */
                return 0;
        }
@@ -536,6 +540,7 @@ static int slow_eval_unknown_fn(struct subchannel_id schid, void *data)
                case -ENOMEM:
                case -EIO:
                        /* These should abort looping */
+                       idset_sch_del_subseq(slow_subchannel_set, schid);
                        break;
                default:
                        rc = 0;
index e6d5f8c49524d05f78f6548a2937b1747bd7ffe6..199bc6791177491bea28b360845911a282b259b5 100644 (file)
@@ -1,9 +1,10 @@
 /*
- *    Copyright IBM Corp. 2007
+ *    Copyright IBM Corp. 2007, 2012
  *    Author(s): Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
  */
 
 #include <linux/vmalloc.h>
+#include <linux/bitmap.h>
 #include <linux/bitops.h>
 #include "idset.h"
 #include "css.h"
@@ -89,6 +90,14 @@ void idset_sch_del(struct idset *set, struct subchannel_id schid)
        idset_del(set, schid.ssid, schid.sch_no);
 }
 
+/* Clear ids starting from @schid up to end of subchannel set. */
+void idset_sch_del_subseq(struct idset *set, struct subchannel_id schid)
+{
+       int pos = schid.ssid * set->num_id + schid.sch_no;
+
+       bitmap_clear(set->bitmap, pos, set->num_id - schid.sch_no);
+}
+
 int idset_sch_contains(struct idset *set, struct subchannel_id schid)
 {
        return idset_contains(set, schid.ssid, schid.sch_no);
@@ -111,20 +120,13 @@ int idset_sch_get_first(struct idset *set, struct subchannel_id *schid)
 
 int idset_is_empty(struct idset *set)
 {
-       int bitnum;
-
-       bitnum = find_first_bit(set->bitmap, set->num_ssid * set->num_id);
-       if (bitnum >= set->num_ssid * set->num_id)
-               return 1;
-       return 0;
+       return bitmap_empty(set->bitmap, set->num_ssid * set->num_id);
 }
 
 void idset_add_set(struct idset *to, struct idset *from)
 {
-       unsigned long i, len;
+       int len = min(__BITOPS_WORDS(to->num_ssid * to->num_id),
+                     __BITOPS_WORDS(from->num_ssid * from->num_id));
 
-       len = min(__BITOPS_WORDS(to->num_ssid * to->num_id),
-                 __BITOPS_WORDS(from->num_ssid * from->num_id));
-       for (i = 0; i < len ; i++)
-               to->bitmap[i] |= from->bitmap[i];
+       bitmap_or(to->bitmap, to->bitmap, from->bitmap, len);
 }
index 3d943f03591e1b2180cc6fdd9c92e54c99a0d0e4..06d3bc01bb0934a52198349da2657e8787c46c13 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *    Copyright IBM Corp. 2007
+ *    Copyright IBM Corp. 2007, 2012
  *    Author(s): Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
  */
 
@@ -17,6 +17,7 @@ void idset_fill(struct idset *set);
 struct idset *idset_sch_new(void);
 void idset_sch_add(struct idset *set, struct subchannel_id id);
 void idset_sch_del(struct idset *set, struct subchannel_id id);
+void idset_sch_del_subseq(struct idset *set, struct subchannel_id schid);
 int idset_sch_contains(struct idset *set, struct subchannel_id id);
 int idset_sch_get_first(struct idset *set, struct subchannel_id *id);
 int idset_is_empty(struct idset *set);
index 6206a666a8ec6d76a5ecba29f5069d77be339b61..737554c37d9ec1ea2f794bf026d4ee96bb5f0c1b 100644 (file)
@@ -179,6 +179,7 @@ static void print_SCp(struct scsi_pointer *SCp, const char *prefix, const char *
                SCp->buffers_residual, suffix);
 }
 
+#ifdef CHECK_STRUCTURE
 static void fas216_dumpinfo(FAS216_Info *info)
 {
        static int used = 0;
@@ -223,7 +224,6 @@ static void fas216_dumpinfo(FAS216_Info *info)
                info->internal_done, info->magic_end);
 }
 
-#ifdef CHECK_STRUCTURE
 static void __fas216_checkmagic(FAS216_Info *info, const char *func)
 {
        int corruption = 0;
index d25f944b59c27a42e1c034a3e85b75a68326f5e9..fc6a5aabf66eadf9a90d2e6c11e2cc45018d6f8a 100644 (file)
@@ -21,6 +21,7 @@
 /*#define PSEUDO_DMA*/
 
 #define OAKSCSI_PUBLIC_RELEASE 1
+#define DONT_USE_INTR
 
 #define priv(host)                     ((struct NCR5380_hostdata *)(host)->hostdata)
 #define NCR5380_local_declare()                void __iomem *_base
index d4ed9eb526572e07814e167eca89f94d22a3f73a..43754176a7b7efdacaaab1953a3a826ec1cdc53d 100644 (file)
@@ -97,9 +97,37 @@ struct osd_dev_handle {
 
 static DEFINE_IDA(osd_minor_ida);
 
+/*
+ * scsi sysfs attribute operations
+ */
+static ssize_t osdname_show(struct device *dev, struct device_attribute *attr,
+                           char *buf)
+{
+       struct osd_uld_device *ould = container_of(dev, struct osd_uld_device,
+                                                  class_dev);
+       return sprintf(buf, "%s\n", ould->odi.osdname);
+}
+
+static ssize_t systemid_show(struct device *dev, struct device_attribute *attr,
+                           char *buf)
+{
+       struct osd_uld_device *ould = container_of(dev, struct osd_uld_device,
+                                                  class_dev);
+
+       memcpy(buf, ould->odi.systemid, ould->odi.systemid_len);
+       return ould->odi.systemid_len;
+}
+
+static struct device_attribute osd_uld_attrs[] = {
+       __ATTR(osdname, S_IRUGO, osdname_show, NULL),
+       __ATTR(systemid, S_IRUGO, systemid_show, NULL),
+       __ATTR_NULL,
+};
+
 static struct class osd_uld_class = {
        .owner          = THIS_MODULE,
        .name           = "scsi_osd",
+       .dev_attrs      = osd_uld_attrs,
 };
 
 /*
index 595af1ae4421937ba1b157d79b84d081866e8355..d5f9f4516d887f0e31cc94a2a35057c84651ddea 100644 (file)
@@ -215,7 +215,7 @@ static void virtscsi_ctrl_done(struct virtqueue *vq)
 static int virtscsi_kick_event(struct virtio_scsi *vscsi,
                               struct virtio_scsi_event_node *event_node)
 {
-       int ret;
+       int err;
        struct scatterlist sg;
        unsigned long flags;
 
@@ -223,13 +223,14 @@ static int virtscsi_kick_event(struct virtio_scsi *vscsi,
 
        spin_lock_irqsave(&vscsi->event_vq.vq_lock, flags);
 
-       ret = virtqueue_add_buf(vscsi->event_vq.vq, &sg, 0, 1, event_node, GFP_ATOMIC);
-       if (ret >= 0)
+       err = virtqueue_add_buf(vscsi->event_vq.vq, &sg, 0, 1, event_node,
+                               GFP_ATOMIC);
+       if (!err)
                virtqueue_kick(vscsi->event_vq.vq);
 
        spin_unlock_irqrestore(&vscsi->event_vq.vq_lock, flags);
 
-       return ret;
+       return err;
 }
 
 static int virtscsi_kick_event_all(struct virtio_scsi *vscsi)
@@ -410,22 +411,23 @@ static int virtscsi_kick_cmd(struct virtio_scsi_target_state *tgt,
 {
        unsigned int out_num, in_num;
        unsigned long flags;
-       int ret;
+       int err;
+       bool needs_kick = false;
 
        spin_lock_irqsave(&tgt->tgt_lock, flags);
        virtscsi_map_cmd(tgt, cmd, &out_num, &in_num, req_size, resp_size);
 
        spin_lock(&vq->vq_lock);
-       ret = virtqueue_add_buf(vq->vq, tgt->sg, out_num, in_num, cmd, gfp);
+       err = virtqueue_add_buf(vq->vq, tgt->sg, out_num, in_num, cmd, gfp);
        spin_unlock(&tgt->tgt_lock);
-       if (ret >= 0)
-               ret = virtqueue_kick_prepare(vq->vq);
+       if (!err)
+               needs_kick = virtqueue_kick_prepare(vq->vq);
 
        spin_unlock_irqrestore(&vq->vq_lock, flags);
 
-       if (ret > 0)
+       if (needs_kick)
                virtqueue_notify(vq->vq);
-       return ret;
+       return err;
 }
 
 static int virtscsi_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *sc)
@@ -467,7 +469,7 @@ static int virtscsi_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *sc)
 
        if (virtscsi_kick_cmd(tgt, &vscsi->req_vq, cmd,
                              sizeof cmd->req.cmd, sizeof cmd->resp.cmd,
-                             GFP_ATOMIC) >= 0)
+                             GFP_ATOMIC) == 0)
                ret = 0;
 
 out:
index a9f4049c6769316c368a716b0b6707d7082abd25..6d97047d9242dbe495a2d209255f47fa98f24208 100644 (file)
@@ -36,7 +36,6 @@
 #include <bcm63xx_dev_spi.h>
 
 #define PFX            KBUILD_MODNAME
-#define DRV_VER                "0.1.2"
 
 struct bcm63xx_spi {
        struct completion       done;
@@ -170,13 +169,6 @@ static int bcm63xx_spi_setup(struct spi_device *spi)
                return -EINVAL;
        }
 
-       ret = bcm63xx_spi_check_transfer(spi, NULL);
-       if (ret < 0) {
-               dev_err(&spi->dev, "setup: unsupported mode bits %x\n",
-                       spi->mode & ~MODEBITS);
-               return ret;
-       }
-
        dev_dbg(&spi->dev, "%s, mode %d, %u bits/w, %u nsec/bit\n",
                __func__, spi->mode & MODEBITS, spi->bits_per_word, 0);
 
@@ -441,8 +433,8 @@ static int __devinit bcm63xx_spi_probe(struct platform_device *pdev)
                goto out_clk_disable;
        }
 
-       dev_info(dev, "at 0x%08x (irq %d, FIFOs size %d) v%s\n",
-                r->start, irq, bs->fifo_size, DRV_VER);
+       dev_info(dev, "at 0x%08x (irq %d, FIFOs size %d)\n",
+                r->start, irq, bs->fifo_size);
 
        return 0;
 
@@ -485,6 +477,8 @@ static int bcm63xx_spi_suspend(struct device *dev)
                        platform_get_drvdata(to_platform_device(dev));
        struct bcm63xx_spi *bs = spi_master_get_devdata(master);
 
+       spi_master_suspend(master);
+
        clk_disable(bs->clk);
 
        return 0;
@@ -498,6 +492,8 @@ static int bcm63xx_spi_resume(struct device *dev)
 
        clk_enable(bs->clk);
 
+       spi_master_resume(master);
+
        return 0;
 }
 
index edf1360ab09e5be8311b7338a28d75ce8bbb46a3..86dd04d6bc873dfa30f0bab1148bd863aac818fc 100644 (file)
@@ -323,6 +323,7 @@ static int mxs_spi_txrx_dma(struct mxs_spi *spi, int cs,
        if (!ret) {
                dev_err(ssp->dev, "DMA transfer timeout\n");
                ret = -ETIMEDOUT;
+               dmaengine_terminate_all(ssp->dmach);
                goto err_vmalloc;
        }
 
@@ -480,7 +481,7 @@ static int mxs_spi_transfer_one(struct spi_master *master,
                first = last = 0;
        }
 
-       m->status = 0;
+       m->status = status;
        spi_finalize_current_message(master);
 
        return status;
index 3542fdc664b11abcaecd579b8743b52346453354..51046332677cfe247a476ee4568392a7dbd4d175 100644 (file)
@@ -130,6 +130,7 @@ struct omap2_mcspi {
        struct omap2_mcspi_dma  *dma_channels;
        struct device           *dev;
        struct omap2_mcspi_regs ctx;
+       unsigned int            pin_dir:1;
 };
 
 struct omap2_mcspi_cs {
@@ -765,8 +766,15 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi,
        /* standard 4-wire master mode:  SCK, MOSI/out, MISO/in, nCS
         * REVISIT: this controller could support SPI_3WIRE mode.
         */
-       l &= ~(OMAP2_MCSPI_CHCONF_IS|OMAP2_MCSPI_CHCONF_DPE1);
-       l |= OMAP2_MCSPI_CHCONF_DPE0;
+       if (mcspi->pin_dir == MCSPI_PINDIR_D0_OUT_D1_IN) {
+               l &= ~OMAP2_MCSPI_CHCONF_IS;
+               l &= ~OMAP2_MCSPI_CHCONF_DPE1;
+               l |= OMAP2_MCSPI_CHCONF_DPE0;
+       } else {
+               l |= OMAP2_MCSPI_CHCONF_IS;
+               l |= OMAP2_MCSPI_CHCONF_DPE1;
+               l &= ~OMAP2_MCSPI_CHCONF_DPE0;
+       }
 
        /* wordlength */
        l &= ~OMAP2_MCSPI_CHCONF_WL_MASK;
@@ -1167,6 +1175,11 @@ static int __devinit omap2_mcspi_probe(struct platform_device *pdev)
        master->cleanup = omap2_mcspi_cleanup;
        master->dev.of_node = node;
 
+       dev_set_drvdata(&pdev->dev, master);
+
+       mcspi = spi_master_get_devdata(master);
+       mcspi->master = master;
+
        match = of_match_device(omap_mcspi_of_match, &pdev->dev);
        if (match) {
                u32 num_cs = 1; /* default number of chipselect */
@@ -1175,19 +1188,17 @@ static int __devinit omap2_mcspi_probe(struct platform_device *pdev)
                of_property_read_u32(node, "ti,spi-num-cs", &num_cs);
                master->num_chipselect = num_cs;
                master->bus_num = bus_num++;
+               if (of_get_property(node, "ti,pindir-d0-in-d1-out", NULL))
+                       mcspi->pin_dir = MCSPI_PINDIR_D0_IN_D1_OUT;
        } else {
                pdata = pdev->dev.platform_data;
                master->num_chipselect = pdata->num_cs;
                if (pdev->id != -1)
                        master->bus_num = pdev->id;
+               mcspi->pin_dir = pdata->pin_dir;
        }
        regs_offset = pdata->regs_offset;
 
-       dev_set_drvdata(&pdev->dev, master);
-
-       mcspi = spi_master_get_devdata(master);
-       mcspi->master = master;
-
        r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (r == NULL) {
                status = -ENODEV;
index 919464102d33afb2d493ace07c81c80403d1d51d..1361868fced7d417c9a0a3768cc77bf0327920c6 100644 (file)
@@ -371,6 +371,7 @@ struct pl022 {
        /* Two optional pin states - default & sleep */
        struct pinctrl                  *pinctrl;
        struct pinctrl_state            *pins_default;
+       struct pinctrl_state            *pins_idle;
        struct pinctrl_state            *pins_sleep;
        struct spi_master               *master;
        struct pl022_ssp_controller     *master_info;
@@ -2116,6 +2117,11 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
        } else
                dev_err(dev, "could not get default pinstate\n");
 
+       pl022->pins_idle = pinctrl_lookup_state(pl022->pinctrl,
+                                             PINCTRL_STATE_IDLE);
+       if (IS_ERR(pl022->pins_idle))
+               dev_dbg(dev, "could not get idle pinstate\n");
+
        pl022->pins_sleep = pinctrl_lookup_state(pl022->pinctrl,
                                               PINCTRL_STATE_SLEEP);
        if (IS_ERR(pl022->pins_sleep))
@@ -2186,8 +2192,6 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
        printk(KERN_INFO "pl022: mapped registers from 0x%08x to %p\n",
               adev->res.start, pl022->virtbase);
 
-       pm_runtime_resume(dev);
-
        pl022->clk = devm_clk_get(&adev->dev, NULL);
        if (IS_ERR(pl022->clk)) {
                status = PTR_ERR(pl022->clk);
@@ -2248,10 +2252,9 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
                pm_runtime_set_autosuspend_delay(dev,
                        platform_info->autosuspend_delay);
                pm_runtime_use_autosuspend(dev);
-               pm_runtime_put_autosuspend(dev);
-       } else {
-               pm_runtime_put(dev);
        }
+       pm_runtime_put(dev);
+
        return 0;
 
  err_spi_register:
@@ -2292,7 +2295,6 @@ pl022_remove(struct amba_device *adev)
 
        clk_disable(pl022->clk);
        clk_unprepare(pl022->clk);
-       pm_runtime_disable(&adev->dev);
        amba_release_regions(adev);
        tasklet_disable(&pl022->pump_transfers);
        spi_unregister_master(pl022->master);
@@ -2306,35 +2308,47 @@ pl022_remove(struct amba_device *adev)
  * the runtime counterparts to handle external resources like
  * clocks, pins and regulators when going to sleep.
  */
-static void pl022_suspend_resources(struct pl022 *pl022)
+static void pl022_suspend_resources(struct pl022 *pl022, bool runtime)
 {
        int ret;
+       struct pinctrl_state *pins_state;
 
        clk_disable(pl022->clk);
 
+       pins_state = runtime ? pl022->pins_idle : pl022->pins_sleep;
        /* Optionally let pins go into sleep states */
-       if (!IS_ERR(pl022->pins_sleep)) {
-               ret = pinctrl_select_state(pl022->pinctrl,
-                                          pl022->pins_sleep);
+       if (!IS_ERR(pins_state)) {
+               ret = pinctrl_select_state(pl022->pinctrl, pins_state);
                if (ret)
-                       dev_err(&pl022->adev->dev,
-                               "could not set pins to sleep state\n");
+                       dev_err(&pl022->adev->dev, "could not set %s pins\n",
+                               runtime ? "idle" : "sleep");
        }
 }
 
-static void pl022_resume_resources(struct pl022 *pl022)
+static void pl022_resume_resources(struct pl022 *pl022, bool runtime)
 {
        int ret;
 
        /* Optionaly enable pins to be muxed in and configured */
+       /* First go to the default state */
        if (!IS_ERR(pl022->pins_default)) {
-               ret = pinctrl_select_state(pl022->pinctrl,
-                                          pl022->pins_default);
+               ret = pinctrl_select_state(pl022->pinctrl, pl022->pins_default);
                if (ret)
                        dev_err(&pl022->adev->dev,
                                "could not set default pins\n");
        }
 
+       if (!runtime) {
+               /* Then let's idle the pins until the next transfer happens */
+               if (!IS_ERR(pl022->pins_idle)) {
+                       ret = pinctrl_select_state(pl022->pinctrl,
+                                       pl022->pins_idle);
+               if (ret)
+                       dev_err(&pl022->adev->dev,
+                               "could not set idle pins\n");
+               }
+       }
+
        clk_enable(pl022->clk);
 }
 #endif
@@ -2350,7 +2364,9 @@ static int pl022_suspend(struct device *dev)
                dev_warn(dev, "cannot suspend master\n");
                return ret;
        }
-       pl022_suspend_resources(pl022);
+
+       pm_runtime_get_sync(dev);
+       pl022_suspend_resources(pl022, false);
 
        dev_dbg(dev, "suspended\n");
        return 0;
@@ -2361,7 +2377,8 @@ static int pl022_resume(struct device *dev)
        struct pl022 *pl022 = dev_get_drvdata(dev);
        int ret;
 
-       pl022_resume_resources(pl022);
+       pl022_resume_resources(pl022, false);
+       pm_runtime_put(dev);
 
        /* Start the queue running */
        ret = spi_master_resume(pl022->master);
@@ -2379,7 +2396,7 @@ static int pl022_runtime_suspend(struct device *dev)
 {
        struct pl022 *pl022 = dev_get_drvdata(dev);
 
-       pl022_suspend_resources(pl022);
+       pl022_suspend_resources(pl022, true);
        return 0;
 }
 
@@ -2387,7 +2404,7 @@ static int pl022_runtime_resume(struct device *dev)
 {
        struct pl022 *pl022 = dev_get_drvdata(dev);
 
-       pl022_resume_resources(pl022);
+       pl022_resume_resources(pl022, true);
        return 0;
 }
 #endif
index 4894bde4bbffea3f65d7ff30db4277c92ab79587..30faf6d4ab9135c84ecd8f359626ddd75e896b60 100644 (file)
@@ -147,8 +147,6 @@ struct rspi_data {
        unsigned char spsr;
 
        /* for dmaengine */
-       struct sh_dmae_slave dma_tx;
-       struct sh_dmae_slave dma_rx;
        struct dma_chan *chan_tx;
        struct dma_chan *chan_rx;
        int irq;
@@ -663,20 +661,16 @@ static irqreturn_t rspi_irq(int irq, void *_sr)
        return ret;
 }
 
-static bool rspi_filter(struct dma_chan *chan, void *filter_param)
-{
-       chan->private = filter_param;
-       return true;
-}
-
-static void __devinit rspi_request_dma(struct rspi_data *rspi,
-                                      struct platform_device *pdev)
+static int __devinit rspi_request_dma(struct rspi_data *rspi,
+                                     struct platform_device *pdev)
 {
        struct rspi_plat_data *rspi_pd = pdev->dev.platform_data;
        dma_cap_mask_t mask;
+       struct dma_slave_config cfg;
+       int ret;
 
        if (!rspi_pd)
-               return;
+               return 0;       /* The driver assumes no error. */
 
        rspi->dma_width_16bit = rspi_pd->dma_width_16bit;
 
@@ -684,21 +678,35 @@ static void __devinit rspi_request_dma(struct rspi_data *rspi,
        if (rspi_pd->dma_rx_id && rspi_pd->dma_tx_id) {
                dma_cap_zero(mask);
                dma_cap_set(DMA_SLAVE, mask);
-               rspi->dma_rx.slave_id = rspi_pd->dma_rx_id;
-               rspi->chan_rx = dma_request_channel(mask, rspi_filter,
-                                                   &rspi->dma_rx);
-               if (rspi->chan_rx)
-                       dev_info(&pdev->dev, "Use DMA when rx.\n");
+               rspi->chan_rx = dma_request_channel(mask, shdma_chan_filter,
+                                                   (void *)rspi_pd->dma_rx_id);
+               if (rspi->chan_rx) {
+                       cfg.slave_id = rspi_pd->dma_rx_id;
+                       cfg.direction = DMA_DEV_TO_MEM;
+                       ret = dmaengine_slave_config(rspi->chan_rx, &cfg);
+                       if (!ret)
+                               dev_info(&pdev->dev, "Use DMA when rx.\n");
+                       else
+                               return ret;
+               }
        }
        if (rspi_pd->dma_tx_id) {
                dma_cap_zero(mask);
                dma_cap_set(DMA_SLAVE, mask);
-               rspi->dma_tx.slave_id = rspi_pd->dma_tx_id;
-               rspi->chan_tx = dma_request_channel(mask, rspi_filter,
-                                                   &rspi->dma_tx);
-               if (rspi->chan_tx)
-                       dev_info(&pdev->dev, "Use DMA when tx\n");
+               rspi->chan_tx = dma_request_channel(mask, shdma_chan_filter,
+                                                   (void *)rspi_pd->dma_tx_id);
+               if (rspi->chan_tx) {
+                       cfg.slave_id = rspi_pd->dma_tx_id;
+                       cfg.direction = DMA_MEM_TO_DEV;
+                       ret = dmaengine_slave_config(rspi->chan_tx, &cfg);
+                       if (!ret)
+                               dev_info(&pdev->dev, "Use DMA when tx\n");
+                       else
+                               return ret;
+               }
        }
+
+       return 0;
 }
 
 static void __devexit rspi_release_dma(struct rspi_data *rspi)
@@ -788,7 +796,11 @@ static int __devinit rspi_probe(struct platform_device *pdev)
        }
 
        rspi->irq = irq;
-       rspi_request_dma(rspi, pdev);
+       ret = rspi_request_dma(rspi, pdev);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "rspi_request_dma failed.\n");
+               goto error4;
+       }
 
        ret = spi_register_master(master);
        if (ret < 0) {
index 1a81c90a4a71dc69ce4ec459342a98af3d26b872..253d0539fb7b7f9ebaefea78de895a8b13e37304 100644 (file)
 
 struct s3c64xx_spi_dma_data {
        unsigned                ch;
-       enum dma_data_direction direction;
+       enum dma_transfer_direction direction;
        enum dma_ch     dmach;
        struct property         *dma_prop;
 };
@@ -214,6 +214,10 @@ static void flush_fifo(struct s3c64xx_spi_driver_data *sdd)
 
        writel(0, regs + S3C64XX_SPI_PACKET_CNT);
 
+       val = readl(regs + S3C64XX_SPI_CH_CFG);
+       val &= ~(S3C64XX_SPI_CH_RXCH_ON | S3C64XX_SPI_CH_TXCH_ON);
+       writel(val, regs + S3C64XX_SPI_CH_CFG);
+
        val = readl(regs + S3C64XX_SPI_CH_CFG);
        val |= S3C64XX_SPI_CH_SW_RST;
        val &= ~S3C64XX_SPI_CH_HS_EN;
@@ -248,10 +252,6 @@ static void flush_fifo(struct s3c64xx_spi_driver_data *sdd)
        val = readl(regs + S3C64XX_SPI_MODE_CFG);
        val &= ~(S3C64XX_SPI_MODE_TXDMA_ON | S3C64XX_SPI_MODE_RXDMA_ON);
        writel(val, regs + S3C64XX_SPI_MODE_CFG);
-
-       val = readl(regs + S3C64XX_SPI_CH_CFG);
-       val &= ~(S3C64XX_SPI_CH_RXCH_ON | S3C64XX_SPI_CH_TXCH_ON);
-       writel(val, regs + S3C64XX_SPI_CH_CFG);
 }
 
 static void s3c64xx_spi_dmacb(void *data)
@@ -516,7 +516,7 @@ static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd)
 
        /* Disable Clock */
        if (sdd->port_conf->clk_from_cmu) {
-               clk_disable(sdd->src_clk);
+               clk_disable_unprepare(sdd->src_clk);
        } else {
                val = readl(regs + S3C64XX_SPI_CLK_CFG);
                val &= ~S3C64XX_SPI_ENCLK_ENABLE;
@@ -564,7 +564,7 @@ static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd)
                /* There is half-multiplier before the SPI */
                clk_set_rate(sdd->src_clk, sdd->cur_speed * 2);
                /* Enable Clock */
-               clk_enable(sdd->src_clk);
+               clk_prepare_enable(sdd->src_clk);
        } else {
                /* Configure Clock */
                val = readl(regs + S3C64XX_SPI_CLK_CFG);
@@ -771,8 +771,6 @@ static int s3c64xx_spi_transfer_one_message(struct spi_master *master,
                        if (list_is_last(&xfer->transfer_list,
                                                &msg->transfers))
                                cs_toggle = 1;
-                       else
-                               disable_cs(sdd, spi);
                }
 
                msg->actual_length += xfer->len;
@@ -1067,11 +1065,11 @@ static int __devinit s3c64xx_spi_get_dmares(
 
        if (tx) {
                dma_data = &sdd->tx_dma;
-               dma_data->direction = DMA_TO_DEVICE;
+               dma_data->direction = DMA_MEM_TO_DEV;
                chan_str = "tx";
        } else {
                dma_data = &sdd->rx_dma;
-               dma_data->direction = DMA_FROM_DEVICE;
+               dma_data->direction = DMA_DEV_TO_MEM;
                chan_str = "rx";
        }
 
@@ -1302,7 +1300,7 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev)
                goto err3;
        }
 
-       if (clk_enable(sdd->clk)) {
+       if (clk_prepare_enable(sdd->clk)) {
                dev_err(&pdev->dev, "Couldn't enable clock 'spi'\n");
                ret = -EBUSY;
                goto err4;
@@ -1317,7 +1315,7 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev)
                goto err5;
        }
 
-       if (clk_enable(sdd->src_clk)) {
+       if (clk_prepare_enable(sdd->src_clk)) {
                dev_err(&pdev->dev, "Couldn't enable clock '%s'\n", clk_name);
                ret = -EBUSY;
                goto err6;
@@ -1361,11 +1359,11 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev)
 err8:
        free_irq(irq, sdd);
 err7:
-       clk_disable(sdd->src_clk);
+       clk_disable_unprepare(sdd->src_clk);
 err6:
        clk_put(sdd->src_clk);
 err5:
-       clk_disable(sdd->clk);
+       clk_disable_unprepare(sdd->clk);
 err4:
        clk_put(sdd->clk);
 err3:
@@ -1393,10 +1391,10 @@ static int s3c64xx_spi_remove(struct platform_device *pdev)
 
        free_irq(platform_get_irq(pdev, 0), sdd);
 
-       clk_disable(sdd->src_clk);
+       clk_disable_unprepare(sdd->src_clk);
        clk_put(sdd->src_clk);
 
-       clk_disable(sdd->clk);
+       clk_disable_unprepare(sdd->clk);
        clk_put(sdd->clk);
 
        if (!sdd->cntrlr_info->cfg_gpio && pdev->dev.of_node)
@@ -1417,8 +1415,8 @@ static int s3c64xx_spi_suspend(struct device *dev)
        spi_master_suspend(master);
 
        /* Disable the clock */
-       clk_disable(sdd->src_clk);
-       clk_disable(sdd->clk);
+       clk_disable_unprepare(sdd->src_clk);
+       clk_disable_unprepare(sdd->clk);
 
        if (!sdd->cntrlr_info->cfg_gpio && dev->of_node)
                s3c64xx_spi_dt_gpio_free(sdd);
@@ -1440,8 +1438,8 @@ static int s3c64xx_spi_resume(struct device *dev)
                sci->cfg_gpio();
 
        /* Enable the clock */
-       clk_enable(sdd->src_clk);
-       clk_enable(sdd->clk);
+       clk_prepare_enable(sdd->src_clk);
+       clk_prepare_enable(sdd->clk);
 
        s3c64xx_spi_hwinit(sdd, sdd->port_id);
 
@@ -1457,8 +1455,8 @@ static int s3c64xx_spi_runtime_suspend(struct device *dev)
        struct spi_master *master = dev_get_drvdata(dev);
        struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master);
 
-       clk_disable(sdd->clk);
-       clk_disable(sdd->src_clk);
+       clk_disable_unprepare(sdd->clk);
+       clk_disable_unprepare(sdd->src_clk);
 
        return 0;
 }
@@ -1468,8 +1466,8 @@ static int s3c64xx_spi_runtime_resume(struct device *dev)
        struct spi_master *master = dev_get_drvdata(dev);
        struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master);
 
-       clk_enable(sdd->src_clk);
-       clk_enable(sdd->clk);
+       clk_prepare_enable(sdd->src_clk);
+       clk_prepare_enable(sdd->clk);
 
        return 0;
 }
index 84c2861d6f4dde2a602e44f292c6efbd248c602b..fc0da392c424873b2c00b288e7b98cd264165d44 100644 (file)
@@ -813,6 +813,7 @@ static void of_register_spi_devices(struct spi_master *master)
        struct spi_device *spi;
        struct device_node *nc;
        const __be32 *prop;
+       char modalias[SPI_NAME_SIZE + 4];
        int rc;
        int len;
 
@@ -874,7 +875,9 @@ static void of_register_spi_devices(struct spi_master *master)
                spi->dev.of_node = nc;
 
                /* Register the new device */
-               request_module(spi->modalias);
+               snprintf(modalias, sizeof(modalias), "%s%s", SPI_MODULE_PREFIX,
+                        spi->modalias);
+               request_module(modalias);
                rc = spi_add_device(spi);
                if (rc) {
                        dev_err(&master->dev, "spi_device register error %s\n",
index c6250867a95d4cb0de8ec92e498b995aaf84d99f..b918ba9223067bdc8219c3c54828dd31f0a0d819 100644 (file)
@@ -192,9 +192,10 @@ static void ssb_mips_flash_detect(struct ssb_mipscore *mcore)
 
        /* When there is no chipcommon on the bus there is 4MB flash */
        if (!bus->chipco.dev) {
-               mcore->flash_buswidth = 2;
-               mcore->flash_window = SSB_FLASH1;
-               mcore->flash_window_size = SSB_FLASH1_SZ;
+               mcore->pflash.present = true;
+               mcore->pflash.buswidth = 2;
+               mcore->pflash.window = SSB_FLASH1;
+               mcore->pflash.window_size = SSB_FLASH1_SZ;
                return;
        }
 
@@ -206,13 +207,14 @@ static void ssb_mips_flash_detect(struct ssb_mipscore *mcore)
                break;
        case SSB_CHIPCO_FLASHT_PARA:
                pr_debug("Found parallel flash\n");
-               mcore->flash_window = SSB_FLASH2;
-               mcore->flash_window_size = SSB_FLASH2_SZ;
+               mcore->pflash.present = true;
+               mcore->pflash.window = SSB_FLASH2;
+               mcore->pflash.window_size = SSB_FLASH2_SZ;
                if ((ssb_read32(bus->chipco.dev, SSB_CHIPCO_FLASH_CFG)
                               & SSB_CHIPCO_CFG_DS16) == 0)
-                       mcore->flash_buswidth = 1;
+                       mcore->pflash.buswidth = 1;
                else
-                       mcore->flash_buswidth = 2;
+                       mcore->pflash.buswidth = 2;
                break;
        }
 }
index e16fcd51716e527abc2022c31d6321a2dde79d73..b35a631734d6313e9c6dce8f945b9dd68ab8dd1c 100644 (file)
@@ -1,3 +1,5 @@
+ccflags-y += -I$(src)                  # needed for trace events
+
 obj-$(CONFIG_ANDROID_BINDER_IPC)       += binder.o
 obj-$(CONFIG_ASHMEM)                   += ashmem.o
 obj-$(CONFIG_ANDROID_LOGGER)           += logger.o
index 7b0ba92e7e46730d1d5c72137c9f1b2b9ddc3201..9fbc06e5012ecdb70f7825896bcb156b86469d58 100644 (file)
@@ -35,8 +35,9 @@
 #include <linux/slab.h>
 
 #include "binder.h"
+#include "binder_trace.h"
 
-static DEFINE_MUTEX(binder_lock);
+static DEFINE_MUTEX(binder_main_lock);
 static DEFINE_MUTEX(binder_deferred_lock);
 static DEFINE_MUTEX(binder_mmap_lock);
 
@@ -411,6 +412,19 @@ static long task_close_fd(struct binder_proc *proc, unsigned int fd)
        return retval;
 }
 
+static inline void binder_lock(const char *tag)
+{
+       trace_binder_lock(tag);
+       mutex_lock(&binder_main_lock);
+       trace_binder_locked(tag);
+}
+
+static inline void binder_unlock(const char *tag)
+{
+       trace_binder_unlock(tag);
+       mutex_unlock(&binder_main_lock);
+}
+
 static void binder_set_nice(long nice)
 {
        long min_nice;
@@ -537,6 +551,8 @@ static int binder_update_page_range(struct binder_proc *proc, int allocate,
        if (end <= start)
                return 0;
 
+       trace_binder_update_page_range(proc, allocate, start, end);
+
        if (vma)
                mm = NULL;
        else
@@ -567,7 +583,7 @@ static int binder_update_page_range(struct binder_proc *proc, int allocate,
                page = &proc->pages[(page_addr - proc->buffer) / PAGE_SIZE];
 
                BUG_ON(*page);
-               *page = alloc_page(GFP_KERNEL | __GFP_ZERO);
+               *page = alloc_page(GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO);
                if (*page == NULL) {
                        pr_err("binder: %d: binder_alloc_buf failed "
                               "for page at %p\n", proc->pid, page_addr);
@@ -1461,6 +1477,9 @@ static void binder_transaction(struct binder_proc *proc,
        t->code = tr->code;
        t->flags = tr->flags;
        t->priority = task_nice(current);
+
+       trace_binder_transaction(reply, t, target_node);
+
        t->buffer = binder_alloc_buf(target_proc, tr->data_size,
                tr->offsets_size, !reply && (t->flags & TF_ONE_WAY));
        if (t->buffer == NULL) {
@@ -1471,6 +1490,7 @@ static void binder_transaction(struct binder_proc *proc,
        t->buffer->debug_id = t->debug_id;
        t->buffer->transaction = t;
        t->buffer->target_node = target_node;
+       trace_binder_transaction_alloc_buf(t->buffer);
        if (target_node)
                binder_inc_node(target_node, 1, 0, NULL);
 
@@ -1543,6 +1563,7 @@ static void binder_transaction(struct binder_proc *proc,
                        binder_inc_ref(ref, fp->type == BINDER_TYPE_HANDLE,
                                       &thread->todo);
 
+                       trace_binder_transaction_node_to_ref(t, node, ref);
                        binder_debug(BINDER_DEBUG_TRANSACTION,
                                     "        node %d u%p -> ref %d desc %d\n",
                                     node->debug_id, node->ptr, ref->debug_id,
@@ -1567,6 +1588,7 @@ static void binder_transaction(struct binder_proc *proc,
                                fp->binder = ref->node->ptr;
                                fp->cookie = ref->node->cookie;
                                binder_inc_node(ref->node, fp->type == BINDER_TYPE_BINDER, 0, NULL);
+                               trace_binder_transaction_ref_to_node(t, ref);
                                binder_debug(BINDER_DEBUG_TRANSACTION,
                                             "        ref %d desc %d -> node %d u%p\n",
                                             ref->debug_id, ref->desc, ref->node->debug_id,
@@ -1580,6 +1602,8 @@ static void binder_transaction(struct binder_proc *proc,
                                }
                                fp->handle = new_ref->desc;
                                binder_inc_ref(new_ref, fp->type == BINDER_TYPE_HANDLE, NULL);
+                               trace_binder_transaction_ref_to_ref(t, ref,
+                                                                   new_ref);
                                binder_debug(BINDER_DEBUG_TRANSACTION,
                                             "        ref %d desc %d -> ref %d desc %d (node %d)\n",
                                             ref->debug_id, ref->desc, new_ref->debug_id,
@@ -1619,6 +1643,7 @@ static void binder_transaction(struct binder_proc *proc,
                                goto err_get_unused_fd_failed;
                        }
                        task_fd_install(target_proc, target_fd, file);
+                       trace_binder_transaction_fd(t, fp->handle, target_fd);
                        binder_debug(BINDER_DEBUG_TRANSACTION,
                                     "        fd %ld -> %d\n", fp->handle, target_fd);
                        /* TODO: fput? */
@@ -1667,6 +1692,7 @@ err_binder_new_node_failed:
 err_bad_object_type:
 err_bad_offset:
 err_copy_data_failed:
+       trace_binder_transaction_failed_buffer_release(t->buffer);
        binder_transaction_buffer_release(target_proc, t->buffer, offp);
        t->buffer->transaction = NULL;
        binder_free_buf(target_proc, t->buffer);
@@ -1712,6 +1738,7 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
                if (get_user(cmd, (uint32_t __user *)ptr))
                        return -EFAULT;
                ptr += sizeof(uint32_t);
+               trace_binder_command(cmd);
                if (_IOC_NR(cmd) < ARRAY_SIZE(binder_stats.bc)) {
                        binder_stats.bc[_IOC_NR(cmd)]++;
                        proc->stats.bc[_IOC_NR(cmd)]++;
@@ -1881,6 +1908,7 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
                                else
                                        list_move_tail(buffer->target_node->async_todo.next, &thread->todo);
                        }
+                       trace_binder_transaction_buffer_release(buffer);
                        binder_transaction_buffer_release(proc, buffer, NULL);
                        binder_free_buf(proc, buffer);
                        break;
@@ -2089,6 +2117,7 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
 void binder_stat_br(struct binder_proc *proc, struct binder_thread *thread,
                    uint32_t cmd)
 {
+       trace_binder_return(cmd);
        if (_IOC_NR(cmd) < ARRAY_SIZE(binder_stats.br)) {
                binder_stats.br[_IOC_NR(cmd)]++;
                proc->stats.br[_IOC_NR(cmd)]++;
@@ -2135,6 +2164,7 @@ retry:
                        if (put_user(thread->return_error2, (uint32_t __user *)ptr))
                                return -EFAULT;
                        ptr += sizeof(uint32_t);
+                       binder_stat_br(proc, thread, thread->return_error2);
                        if (ptr == end)
                                goto done;
                        thread->return_error2 = BR_OK;
@@ -2142,6 +2172,7 @@ retry:
                if (put_user(thread->return_error, (uint32_t __user *)ptr))
                        return -EFAULT;
                ptr += sizeof(uint32_t);
+               binder_stat_br(proc, thread, thread->return_error);
                thread->return_error = BR_OK;
                goto done;
        }
@@ -2150,7 +2181,12 @@ retry:
        thread->looper |= BINDER_LOOPER_STATE_WAITING;
        if (wait_for_proc_work)
                proc->ready_threads++;
-       mutex_unlock(&binder_lock);
+
+       binder_unlock(__func__);
+
+       trace_binder_wait_for_work(wait_for_proc_work,
+                                  !!thread->transaction_stack,
+                                  !list_empty(&thread->todo));
        if (wait_for_proc_work) {
                if (!(thread->looper & (BINDER_LOOPER_STATE_REGISTERED |
                                        BINDER_LOOPER_STATE_ENTERED))) {
@@ -2174,7 +2210,9 @@ retry:
                } else
                        ret = wait_event_interruptible(thread->wait, binder_has_thread_work(thread));
        }
-       mutex_lock(&binder_lock);
+
+       binder_lock(__func__);
+
        if (wait_for_proc_work)
                proc->ready_threads--;
        thread->looper &= ~BINDER_LOOPER_STATE_WAITING;
@@ -2297,6 +2335,7 @@ retry:
                        if (put_user(death->cookie, (void * __user *)ptr))
                                return -EFAULT;
                        ptr += sizeof(void *);
+                       binder_stat_br(proc, thread, cmd);
                        binder_debug(BINDER_DEBUG_DEATH_NOTIFICATION,
                                     "binder: %d:%d %s %p\n",
                                      proc->pid, thread->pid,
@@ -2364,6 +2403,7 @@ retry:
                        return -EFAULT;
                ptr += sizeof(tr);
 
+               trace_binder_transaction_received(t);
                binder_stat_br(proc, thread, cmd);
                binder_debug(BINDER_DEBUG_TRANSACTION,
                             "binder: %d:%d %s %d %d:%d, cmd %d"
@@ -2404,6 +2444,7 @@ done:
                             proc->pid, thread->pid);
                if (put_user(BR_SPAWN_LOOPER, (uint32_t __user *)buffer))
                        return -EFAULT;
+               binder_stat_br(proc, thread, BR_SPAWN_LOOPER);
        }
        return 0;
 }
@@ -2419,14 +2460,38 @@ static void binder_release_work(struct list_head *list)
                        struct binder_transaction *t;
 
                        t = container_of(w, struct binder_transaction, work);
-                       if (t->buffer->target_node && !(t->flags & TF_ONE_WAY))
+                       if (t->buffer->target_node &&
+                           !(t->flags & TF_ONE_WAY)) {
                                binder_send_failed_reply(t, BR_DEAD_REPLY);
+                       } else {
+                               binder_debug(BINDER_DEBUG_DEAD_TRANSACTION,
+                                       "binder: undelivered transaction %d\n",
+                                       t->debug_id);
+                               t->buffer->transaction = NULL;
+                               kfree(t);
+                               binder_stats_deleted(BINDER_STAT_TRANSACTION);
+                       }
                } break;
                case BINDER_WORK_TRANSACTION_COMPLETE: {
+                       binder_debug(BINDER_DEBUG_DEAD_TRANSACTION,
+                               "binder: undelivered TRANSACTION_COMPLETE\n");
                        kfree(w);
                        binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
                } break;
+               case BINDER_WORK_DEAD_BINDER_AND_CLEAR:
+               case BINDER_WORK_CLEAR_DEATH_NOTIFICATION: {
+                       struct binder_ref_death *death;
+
+                       death = container_of(w, struct binder_ref_death, work);
+                       binder_debug(BINDER_DEBUG_DEAD_TRANSACTION,
+                               "binder: undelivered death notification, %p\n",
+                               death->cookie);
+                       kfree(death);
+                       binder_stats_deleted(BINDER_STAT_DEATH);
+               } break;
                default:
+                       pr_err("binder: unexpected work type, %d, not freed\n",
+                              w->type);
                        break;
                }
        }
@@ -2516,12 +2581,14 @@ static unsigned int binder_poll(struct file *filp,
        struct binder_thread *thread = NULL;
        int wait_for_proc_work;
 
-       mutex_lock(&binder_lock);
+       binder_lock(__func__);
+
        thread = binder_get_thread(proc);
 
        wait_for_proc_work = thread->transaction_stack == NULL &&
                list_empty(&thread->todo) && thread->return_error == BR_OK;
-       mutex_unlock(&binder_lock);
+
+       binder_unlock(__func__);
 
        if (wait_for_proc_work) {
                if (binder_has_proc_work(proc, thread))
@@ -2549,11 +2616,13 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 
        /*pr_info("binder_ioctl: %d:%d %x %lx\n", proc->pid, current->pid, cmd, arg);*/
 
+       trace_binder_ioctl(cmd, arg);
+
        ret = wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);
        if (ret)
-               return ret;
+               goto err_unlocked;
 
-       mutex_lock(&binder_lock);
+       binder_lock(__func__);
        thread = binder_get_thread(proc);
        if (thread == NULL) {
                ret = -ENOMEM;
@@ -2578,6 +2647,7 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 
                if (bwr.write_size > 0) {
                        ret = binder_thread_write(proc, thread, (void __user *)bwr.write_buffer, bwr.write_size, &bwr.write_consumed);
+                       trace_binder_write_done(ret);
                        if (ret < 0) {
                                bwr.read_consumed = 0;
                                if (copy_to_user(ubuf, &bwr, sizeof(bwr)))
@@ -2587,6 +2657,7 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
                }
                if (bwr.read_size > 0) {
                        ret = binder_thread_read(proc, thread, (void __user *)bwr.read_buffer, bwr.read_size, &bwr.read_consumed, filp->f_flags & O_NONBLOCK);
+                       trace_binder_read_done(ret);
                        if (!list_empty(&proc->todo))
                                wake_up_interruptible(&proc->wait);
                        if (ret < 0) {
@@ -2662,10 +2733,12 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 err:
        if (thread)
                thread->looper &= ~BINDER_LOOPER_STATE_NEED_RETURN;
-       mutex_unlock(&binder_lock);
+       binder_unlock(__func__);
        wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);
        if (ret && ret != -ERESTARTSYS)
                pr_info("binder: %d:%d ioctl %x %lx returned %d\n", proc->pid, current->pid, cmd, arg, ret);
+err_unlocked:
+       trace_binder_ioctl_done(ret);
        return ret;
 }
 
@@ -2811,13 +2884,16 @@ static int binder_open(struct inode *nodp, struct file *filp)
        INIT_LIST_HEAD(&proc->todo);
        init_waitqueue_head(&proc->wait);
        proc->default_priority = task_nice(current);
-       mutex_lock(&binder_lock);
+
+       binder_lock(__func__);
+
        binder_stats_created(BINDER_STAT_PROC);
        hlist_add_head(&proc->proc_node, &binder_procs);
        proc->pid = current->group_leader->pid;
        INIT_LIST_HEAD(&proc->delivered_death);
        filp->private_data = proc;
-       mutex_unlock(&binder_lock);
+
+       binder_unlock(__func__);
 
        if (binder_debugfs_dir_entry_proc) {
                char strbuf[11];
@@ -2899,6 +2975,7 @@ static void binder_deferred_release(struct binder_proc *proc)
                nodes++;
                rb_erase(&node->rb_node, &proc->nodes);
                list_del_init(&node->work.entry);
+               binder_release_work(&node->async_todo);
                if (hlist_empty(&node->refs)) {
                        kfree(node);
                        binder_stats_deleted(BINDER_STAT_NODE);
@@ -2937,6 +3014,7 @@ static void binder_deferred_release(struct binder_proc *proc)
                binder_delete_ref(ref);
        }
        binder_release_work(&proc->todo);
+       binder_release_work(&proc->delivered_death);
        buffers = 0;
 
        while ((n = rb_first(&proc->allocated_buffers))) {
@@ -2997,7 +3075,7 @@ static void binder_deferred_func(struct work_struct *work)
 
        int defer;
        do {
-               mutex_lock(&binder_lock);
+               binder_lock(__func__);
                mutex_lock(&binder_deferred_lock);
                if (!hlist_empty(&binder_deferred_list)) {
                        proc = hlist_entry(binder_deferred_list.first,
@@ -3024,7 +3102,7 @@ static void binder_deferred_func(struct work_struct *work)
                if (defer & BINDER_DEFERRED_RELEASE)
                        binder_deferred_release(proc); /* frees proc */
 
-               mutex_unlock(&binder_lock);
+               binder_unlock(__func__);
                if (files)
                        put_files_struct(files);
        } while (proc);
@@ -3365,7 +3443,7 @@ static int binder_state_show(struct seq_file *m, void *unused)
        int do_lock = !binder_debug_no_lock;
 
        if (do_lock)
-               mutex_lock(&binder_lock);
+               binder_lock(__func__);
 
        seq_puts(m, "binder state:\n");
 
@@ -3377,7 +3455,7 @@ static int binder_state_show(struct seq_file *m, void *unused)
        hlist_for_each_entry(proc, pos, &binder_procs, proc_node)
                print_binder_proc(m, proc, 1);
        if (do_lock)
-               mutex_unlock(&binder_lock);
+               binder_unlock(__func__);
        return 0;
 }
 
@@ -3388,7 +3466,7 @@ static int binder_stats_show(struct seq_file *m, void *unused)
        int do_lock = !binder_debug_no_lock;
 
        if (do_lock)
-               mutex_lock(&binder_lock);
+               binder_lock(__func__);
 
        seq_puts(m, "binder stats:\n");
 
@@ -3397,7 +3475,7 @@ static int binder_stats_show(struct seq_file *m, void *unused)
        hlist_for_each_entry(proc, pos, &binder_procs, proc_node)
                print_binder_proc_stats(m, proc);
        if (do_lock)
-               mutex_unlock(&binder_lock);
+               binder_unlock(__func__);
        return 0;
 }
 
@@ -3408,13 +3486,13 @@ static int binder_transactions_show(struct seq_file *m, void *unused)
        int do_lock = !binder_debug_no_lock;
 
        if (do_lock)
-               mutex_lock(&binder_lock);
+               binder_lock(__func__);
 
        seq_puts(m, "binder transactions:\n");
        hlist_for_each_entry(proc, pos, &binder_procs, proc_node)
                print_binder_proc(m, proc, 0);
        if (do_lock)
-               mutex_unlock(&binder_lock);
+               binder_unlock(__func__);
        return 0;
 }
 
@@ -3424,11 +3502,11 @@ static int binder_proc_show(struct seq_file *m, void *unused)
        int do_lock = !binder_debug_no_lock;
 
        if (do_lock)
-               mutex_lock(&binder_lock);
+               binder_lock(__func__);
        seq_puts(m, "binder proc state:\n");
        print_binder_proc(m, proc, 1);
        if (do_lock)
-               mutex_unlock(&binder_lock);
+               binder_unlock(__func__);
        return 0;
 }
 
@@ -3523,4 +3601,7 @@ static int __init binder_init(void)
 
 device_initcall(binder_init);
 
+#define CREATE_TRACE_POINTS
+#include "binder_trace.h"
+
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/android/binder_trace.h b/drivers/staging/android/binder_trace.h
new file mode 100644 (file)
index 0000000..82a567c
--- /dev/null
@@ -0,0 +1,327 @@
+/*
+ * Copyright (C) 2012 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM binder
+
+#if !defined(_BINDER_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _BINDER_TRACE_H
+
+#include <linux/tracepoint.h>
+
+struct binder_buffer;
+struct binder_node;
+struct binder_proc;
+struct binder_ref;
+struct binder_thread;
+struct binder_transaction;
+
+TRACE_EVENT(binder_ioctl,
+       TP_PROTO(unsigned int cmd, unsigned long arg),
+       TP_ARGS(cmd, arg),
+
+       TP_STRUCT__entry(
+               __field(unsigned int, cmd)
+               __field(unsigned long, arg)
+       ),
+       TP_fast_assign(
+               __entry->cmd = cmd;
+               __entry->arg = arg;
+       ),
+       TP_printk("cmd=0x%x arg=0x%lx", __entry->cmd, __entry->arg)
+);
+
+DECLARE_EVENT_CLASS(binder_lock_class,
+       TP_PROTO(const char *tag),
+       TP_ARGS(tag),
+       TP_STRUCT__entry(
+               __field(const char *, tag)
+       ),
+       TP_fast_assign(
+               __entry->tag = tag;
+       ),
+       TP_printk("tag=%s", __entry->tag)
+);
+
+#define DEFINE_BINDER_LOCK_EVENT(name) \
+DEFINE_EVENT(binder_lock_class, name,  \
+       TP_PROTO(const char *func), \
+       TP_ARGS(func))
+
+DEFINE_BINDER_LOCK_EVENT(binder_lock);
+DEFINE_BINDER_LOCK_EVENT(binder_locked);
+DEFINE_BINDER_LOCK_EVENT(binder_unlock);
+
+DECLARE_EVENT_CLASS(binder_function_return_class,
+       TP_PROTO(int ret),
+       TP_ARGS(ret),
+       TP_STRUCT__entry(
+               __field(int, ret)
+       ),
+       TP_fast_assign(
+               __entry->ret = ret;
+       ),
+       TP_printk("ret=%d", __entry->ret)
+);
+
+#define DEFINE_BINDER_FUNCTION_RETURN_EVENT(name)      \
+DEFINE_EVENT(binder_function_return_class, name,       \
+       TP_PROTO(int ret), \
+       TP_ARGS(ret))
+
+DEFINE_BINDER_FUNCTION_RETURN_EVENT(binder_ioctl_done);
+DEFINE_BINDER_FUNCTION_RETURN_EVENT(binder_write_done);
+DEFINE_BINDER_FUNCTION_RETURN_EVENT(binder_read_done);
+
+TRACE_EVENT(binder_wait_for_work,
+       TP_PROTO(bool proc_work, bool transaction_stack, bool thread_todo),
+       TP_ARGS(proc_work, transaction_stack, thread_todo),
+
+       TP_STRUCT__entry(
+               __field(bool, proc_work)
+               __field(bool, transaction_stack)
+               __field(bool, thread_todo)
+       ),
+       TP_fast_assign(
+               __entry->proc_work = proc_work;
+               __entry->transaction_stack = transaction_stack;
+               __entry->thread_todo = thread_todo;
+       ),
+       TP_printk("proc_work=%d transaction_stack=%d thread_todo=%d",
+                 __entry->proc_work, __entry->transaction_stack,
+                 __entry->thread_todo)
+);
+
+TRACE_EVENT(binder_transaction,
+       TP_PROTO(bool reply, struct binder_transaction *t,
+                struct binder_node *target_node),
+       TP_ARGS(reply, t, target_node),
+       TP_STRUCT__entry(
+               __field(int, debug_id)
+               __field(int, target_node)
+               __field(int, to_proc)
+               __field(int, to_thread)
+               __field(int, reply)
+               __field(unsigned int, code)
+               __field(unsigned int, flags)
+       ),
+       TP_fast_assign(
+               __entry->debug_id = t->debug_id;
+               __entry->target_node = target_node ? target_node->debug_id : 0;
+               __entry->to_proc = t->to_proc->pid;
+               __entry->to_thread = t->to_thread ? t->to_thread->pid : 0;
+               __entry->reply = reply;
+               __entry->code = t->code;
+               __entry->flags = t->flags;
+       ),
+       TP_printk("transaction=%d dest_node=%d dest_proc=%d dest_thread=%d reply=%d flags=0x%x code=0x%x",
+                 __entry->debug_id, __entry->target_node,
+                 __entry->to_proc, __entry->to_thread,
+                 __entry->reply, __entry->flags, __entry->code)
+);
+
+TRACE_EVENT(binder_transaction_received,
+       TP_PROTO(struct binder_transaction *t),
+       TP_ARGS(t),
+
+       TP_STRUCT__entry(
+               __field(int, debug_id)
+       ),
+       TP_fast_assign(
+               __entry->debug_id = t->debug_id;
+       ),
+       TP_printk("transaction=%d", __entry->debug_id)
+);
+
+TRACE_EVENT(binder_transaction_node_to_ref,
+       TP_PROTO(struct binder_transaction *t, struct binder_node *node,
+                struct binder_ref *ref),
+       TP_ARGS(t, node, ref),
+
+       TP_STRUCT__entry(
+               __field(int, debug_id)
+               __field(int, node_debug_id)
+               __field(void __user *, node_ptr)
+               __field(int, ref_debug_id)
+               __field(uint32_t, ref_desc)
+       ),
+       TP_fast_assign(
+               __entry->debug_id = t->debug_id;
+               __entry->node_debug_id = node->debug_id;
+               __entry->node_ptr = node->ptr;
+               __entry->ref_debug_id = ref->debug_id;
+               __entry->ref_desc = ref->desc;
+       ),
+       TP_printk("transaction=%d node=%d src_ptr=0x%p ==> dest_ref=%d dest_desc=%d",
+                 __entry->debug_id, __entry->node_debug_id, __entry->node_ptr,
+                 __entry->ref_debug_id, __entry->ref_desc)
+);
+
+TRACE_EVENT(binder_transaction_ref_to_node,
+       TP_PROTO(struct binder_transaction *t, struct binder_ref *ref),
+       TP_ARGS(t, ref),
+
+       TP_STRUCT__entry(
+               __field(int, debug_id)
+               __field(int, ref_debug_id)
+               __field(uint32_t, ref_desc)
+               __field(int, node_debug_id)
+               __field(void __user *, node_ptr)
+       ),
+       TP_fast_assign(
+               __entry->debug_id = t->debug_id;
+               __entry->ref_debug_id = ref->debug_id;
+               __entry->ref_desc = ref->desc;
+               __entry->node_debug_id = ref->node->debug_id;
+               __entry->node_ptr = ref->node->ptr;
+       ),
+       TP_printk("transaction=%d node=%d src_ref=%d src_desc=%d ==> dest_ptr=0x%p",
+                 __entry->debug_id, __entry->node_debug_id,
+                 __entry->ref_debug_id, __entry->ref_desc, __entry->node_ptr)
+);
+
+TRACE_EVENT(binder_transaction_ref_to_ref,
+       TP_PROTO(struct binder_transaction *t, struct binder_ref *src_ref,
+                struct binder_ref *dest_ref),
+       TP_ARGS(t, src_ref, dest_ref),
+
+       TP_STRUCT__entry(
+               __field(int, debug_id)
+               __field(int, node_debug_id)
+               __field(int, src_ref_debug_id)
+               __field(uint32_t, src_ref_desc)
+               __field(int, dest_ref_debug_id)
+               __field(uint32_t, dest_ref_desc)
+       ),
+       TP_fast_assign(
+               __entry->debug_id = t->debug_id;
+               __entry->node_debug_id = src_ref->node->debug_id;
+               __entry->src_ref_debug_id = src_ref->debug_id;
+               __entry->src_ref_desc = src_ref->desc;
+               __entry->dest_ref_debug_id = dest_ref->debug_id;
+               __entry->dest_ref_desc = dest_ref->desc;
+       ),
+       TP_printk("transaction=%d node=%d src_ref=%d src_desc=%d ==> dest_ref=%d dest_desc=%d",
+                 __entry->debug_id, __entry->node_debug_id,
+                 __entry->src_ref_debug_id, __entry->src_ref_desc,
+                 __entry->dest_ref_debug_id, __entry->dest_ref_desc)
+);
+
+TRACE_EVENT(binder_transaction_fd,
+       TP_PROTO(struct binder_transaction *t, int src_fd, int dest_fd),
+       TP_ARGS(t, src_fd, dest_fd),
+
+       TP_STRUCT__entry(
+               __field(int, debug_id)
+               __field(int, src_fd)
+               __field(int, dest_fd)
+       ),
+       TP_fast_assign(
+               __entry->debug_id = t->debug_id;
+               __entry->src_fd = src_fd;
+               __entry->dest_fd = dest_fd;
+       ),
+       TP_printk("transaction=%d src_fd=%d ==> dest_fd=%d",
+                 __entry->debug_id, __entry->src_fd, __entry->dest_fd)
+);
+
+DECLARE_EVENT_CLASS(binder_buffer_class,
+       TP_PROTO(struct binder_buffer *buf),
+       TP_ARGS(buf),
+       TP_STRUCT__entry(
+               __field(int, debug_id)
+               __field(size_t, data_size)
+               __field(size_t, offsets_size)
+       ),
+       TP_fast_assign(
+               __entry->debug_id = buf->debug_id;
+               __entry->data_size = buf->data_size;
+               __entry->offsets_size = buf->offsets_size;
+       ),
+       TP_printk("transaction=%d data_size=%zd offsets_size=%zd",
+                 __entry->debug_id, __entry->data_size, __entry->offsets_size)
+);
+
+DEFINE_EVENT(binder_buffer_class, binder_transaction_alloc_buf,
+       TP_PROTO(struct binder_buffer *buffer),
+       TP_ARGS(buffer));
+
+DEFINE_EVENT(binder_buffer_class, binder_transaction_buffer_release,
+       TP_PROTO(struct binder_buffer *buffer),
+       TP_ARGS(buffer));
+
+DEFINE_EVENT(binder_buffer_class, binder_transaction_failed_buffer_release,
+       TP_PROTO(struct binder_buffer *buffer),
+       TP_ARGS(buffer));
+
+TRACE_EVENT(binder_update_page_range,
+       TP_PROTO(struct binder_proc *proc, bool allocate,
+                void *start, void *end),
+       TP_ARGS(proc, allocate, start, end),
+       TP_STRUCT__entry(
+               __field(int, proc)
+               __field(bool, allocate)
+               __field(size_t, offset)
+               __field(size_t, size)
+       ),
+       TP_fast_assign(
+               __entry->proc = proc->pid;
+               __entry->allocate = allocate;
+               __entry->offset = start - proc->buffer;
+               __entry->size = end - start;
+       ),
+       TP_printk("proc=%d allocate=%d offset=%zu size=%zu",
+                 __entry->proc, __entry->allocate,
+                 __entry->offset, __entry->size)
+);
+
+TRACE_EVENT(binder_command,
+       TP_PROTO(uint32_t cmd),
+       TP_ARGS(cmd),
+       TP_STRUCT__entry(
+               __field(uint32_t, cmd)
+       ),
+       TP_fast_assign(
+               __entry->cmd = cmd;
+       ),
+       TP_printk("cmd=0x%x %s",
+                 __entry->cmd,
+                 _IOC_NR(__entry->cmd) < ARRAY_SIZE(binder_command_strings) ?
+                         binder_command_strings[_IOC_NR(__entry->cmd)] :
+                         "unknown")
+);
+
+TRACE_EVENT(binder_return,
+       TP_PROTO(uint32_t cmd),
+       TP_ARGS(cmd),
+       TP_STRUCT__entry(
+               __field(uint32_t, cmd)
+       ),
+       TP_fast_assign(
+               __entry->cmd = cmd;
+       ),
+       TP_printk("cmd=0x%x %s",
+                 __entry->cmd,
+                 _IOC_NR(__entry->cmd) < ARRAY_SIZE(binder_return_strings) ?
+                         binder_return_strings[_IOC_NR(__entry->cmd)] :
+                         "unknown")
+);
+
+#endif /* _BINDER_TRACE_H */
+
+#undef TRACE_INCLUDE_PATH
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_PATH .
+#define TRACE_INCLUDE_FILE binder_trace
+#include <trace/define_trace.h>
index 325b592fd41f00626066b01d9ca5796c2f5082cf..48302ee7ebf15291a4ece9d2f56f60d121313ecb 100644 (file)
@@ -1573,36 +1573,36 @@ ULONG SetUpTargetDsxBuffers(struct bcm_mini_adapter *Adapter)
 
 static ULONG GetNextTargetBufferLocation(struct bcm_mini_adapter *Adapter, B_UINT16 tid)
 {
-       ULONG ulTargetDSXBufferAddress;
-       ULONG ulTargetDsxBufferIndexToUse, ulMaxTry;
+       ULONG dsx_buf;
+       ULONG idx, max_try;
 
        if ((Adapter->ulTotalTargetBuffersAvailable == 0) || (Adapter->ulFreeTargetBufferCnt == 0)) {
                ClearTargetDSXBuffer(Adapter, tid, FALSE);
                return 0;
        }
 
-       ulTargetDsxBufferIndexToUse = Adapter->ulCurrentTargetBuffer;
-       ulMaxTry = Adapter->ulTotalTargetBuffersAvailable;
-       while ((ulMaxTry) && (Adapter->astTargetDsxBuffer[ulTargetDsxBufferIndexToUse].valid != 1)) {
-               ulTargetDsxBufferIndexToUse = (ulTargetDsxBufferIndexToUse+1) % Adapter->ulTotalTargetBuffersAvailable;
-               ulMaxTry--;
+       idx = Adapter->ulCurrentTargetBuffer;
+       max_try = Adapter->ulTotalTargetBuffersAvailable;
+       while ((max_try) && (Adapter->astTargetDsxBuffer[idx].valid != 1)) {
+               idx = (idx+1) % Adapter->ulTotalTargetBuffersAvailable;
+               max_try--;
        }
 
-       if (ulMaxTry == 0) {
+       if (max_try == 0) {
                BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "\n GetNextTargetBufferLocation : Error No Free Target DSX Buffers FreeCnt : %lx ", Adapter->ulFreeTargetBufferCnt);
                ClearTargetDSXBuffer(Adapter, tid, FALSE);
                return 0;
        }
 
-       ulTargetDSXBufferAddress = Adapter->astTargetDsxBuffer[ulTargetDsxBufferIndexToUse].ulTargetDsxBuffer;
-       Adapter->astTargetDsxBuffer[ulTargetDsxBufferIndexToUse].valid = 0;
-       Adapter->astTargetDsxBuffer[ulTargetDsxBufferIndexToUse].tid = tid;
+       dsx_buf = Adapter->astTargetDsxBuffer[idx].ulTargetDsxBuffer;
+       Adapter->astTargetDsxBuffer[idx].valid = 0;
+       Adapter->astTargetDsxBuffer[idx].tid = tid;
        Adapter->ulFreeTargetBufferCnt--;
-       ulTargetDsxBufferIndexToUse = (ulTargetDsxBufferIndexToUse+1)%Adapter->ulTotalTargetBuffersAvailable;
-       Adapter->ulCurrentTargetBuffer = ulTargetDsxBufferIndexToUse;
-       BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "GetNextTargetBufferLocation :Returning address %lx tid %d\n", ulTargetDSXBufferAddress, tid);
+       idx = (idx+1)%Adapter->ulTotalTargetBuffersAvailable;
+       Adapter->ulCurrentTargetBuffer = idx;
+       BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "GetNextTargetBufferLocation :Returning address %lx tid %d\n", dsx_buf, tid);
 
-       return ulTargetDSXBufferAddress;
+       return dsx_buf;
 }
 
 int AllocAdapterDsxBuffer(struct bcm_mini_adapter *Adapter)
index c3338c8a1dc89ad5173439e5b3c2480057d5d2ac..2ef64003aa8965d29587f85825fc1d54d95f6739 100644 (file)
@@ -3,11 +3,12 @@
 
 INT InterfaceIdleModeWakeup(struct bcm_mini_adapter *Adapter);
 
-INT InterfaceIdleModeRespond(struct bcm_mini_adapter *Adapter, unsigned int *puiBuffer);
+INT InterfaceIdleModeRespond(struct bcm_mini_adapter *Adapter,
+                               unsigned int *puiBuffer);
 
 VOID InterfaceWriteIdleModeWakePattern(struct bcm_mini_adapter *Adapter);
 
-INT InterfaceWakeUp(struct bcm_mini_adapter * Adapter);
+INT InterfaceWakeUp(struct bcm_mini_adapter *Adapter);
 
 VOID InterfaceHandleShutdownModeWakeup(struct bcm_mini_adapter *Adapter);
 #endif
index bbe909946091c24b284c57ba65f8ac043430d370..9c832b323837d41ebf4c2243a184f51b40118f71 100644 (file)
@@ -1,17 +1,14 @@
 #include "headers.h"
 
-INT InterfaceRDM(PS_INTERFACE_ADAPTER psIntfAdapter,
-               UINT addr,
-               PVOID buff,
-               INT len)
+int InterfaceRDM(PS_INTERFACE_ADAPTER psIntfAdapter,
+               unsigned int addr,
+               void *buff,
+               int len)
 {
        int bytes;
-       USHORT usRetries = 0;
 
-       if (psIntfAdapter == NULL) {
-               BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0, "Interface Adapter is NULL");
+       if (!psIntfAdapter)
                return -EINVAL;
-       }
 
        if (psIntfAdapter->psAdapter->device_removed == TRUE) {
                BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0, "Device got removed");
@@ -29,27 +26,21 @@ INT InterfaceRDM(PS_INTERFACE_ADAPTER psIntfAdapter,
        }
        psIntfAdapter->psAdapter->DeviceAccess = TRUE;
 
-       do {
-               bytes = usb_control_msg(psIntfAdapter->udev,
-                                       usb_rcvctrlpipe(psIntfAdapter->udev, 0),
-                                       0x02,
-                                       0xC2,
-                                       (addr & 0xFFFF),
-                                       ((addr >> 16) & 0xFFFF),
-                                       buff,
-                                       len,
-                                       5000);
-
-               usRetries++;
-               if (-ENODEV == bytes) {
-                       psIntfAdapter->psAdapter->device_removed = TRUE;
-                       break;
-               }
+       bytes = usb_control_msg(psIntfAdapter->udev,
+                               usb_rcvctrlpipe(psIntfAdapter->udev, 0),
+                               0x02,
+                               0xC2,
+                               (addr & 0xFFFF),
+                               ((addr >> 16) & 0xFFFF),
+                               buff,
+                               len,
+                               5000);
 
-       } while ((bytes < 0) && (usRetries < MAX_RDM_WRM_RETIRES));
+       if (-ENODEV == bytes)
+               psIntfAdapter->psAdapter->device_removed = TRUE;
 
        if (bytes < 0)
-               BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "RDM failed status :%d, retires :%d", bytes, usRetries);
+               BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "RDM failed status :%d", bytes);
        else
                BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "RDM sent %d", bytes);
 
@@ -57,18 +48,15 @@ INT InterfaceRDM(PS_INTERFACE_ADAPTER psIntfAdapter,
        return bytes;
 }
 
-INT InterfaceWRM(PS_INTERFACE_ADAPTER psIntfAdapter,
-               UINT addr,
-               PVOID buff,
-               INT len)
+int InterfaceWRM(PS_INTERFACE_ADAPTER psIntfAdapter,
+               unsigned int addr,
+               void *buff,
+               int len)
 {
        int retval = 0;
-       USHORT usRetries = 0;
 
-       if (psIntfAdapter == NULL) {
-               BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0, "Interface Adapter  is NULL");
+       if (!psIntfAdapter)
                return -EINVAL;
-       }
 
        if (psIntfAdapter->psAdapter->device_removed == TRUE) {
                BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0, "Device got removed");
@@ -87,27 +75,21 @@ INT InterfaceWRM(PS_INTERFACE_ADAPTER psIntfAdapter,
 
        psIntfAdapter->psAdapter->DeviceAccess = TRUE;
 
-       do {
-               retval = usb_control_msg(psIntfAdapter->udev,
-                                       usb_sndctrlpipe(psIntfAdapter->udev, 0),
-                                       0x01,
-                                       0x42,
-                                       (addr & 0xFFFF),
-                                       ((addr >> 16) & 0xFFFF),
-                                       buff,
-                                       len,
-                                       5000);
-
-               usRetries++;
-               if (-ENODEV == retval) {
-                       psIntfAdapter->psAdapter->device_removed = TRUE;
-                       break;
-               }
+       retval = usb_control_msg(psIntfAdapter->udev,
+                               usb_sndctrlpipe(psIntfAdapter->udev, 0),
+                               0x01,
+                               0x42,
+                               (addr & 0xFFFF),
+                               ((addr >> 16) & 0xFFFF),
+                               buff,
+                               len,
+                               5000);
 
-       } while ((retval < 0) && (usRetries < MAX_RDM_WRM_RETIRES));
+       if (-ENODEV == retval)
+               psIntfAdapter->psAdapter->device_removed = TRUE;
 
        if (retval < 0) {
-               BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL, "WRM failed status :%d, retires :%d", retval, usRetries);
+               BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL, "WRM failed status :%d", retval);
                psIntfAdapter->psAdapter->DeviceAccess = FALSE;
                return retval;
        } else {
@@ -117,26 +99,26 @@ INT InterfaceWRM(PS_INTERFACE_ADAPTER psIntfAdapter,
        }
 }
 
-INT BcmRDM(PVOID arg,
-       UINT addr,
-       PVOID buff,
-       INT len)
+int BcmRDM(void *arg,
+       unsigned int addr,
+       void *buff,
+       int len)
 {
        return InterfaceRDM((PS_INTERFACE_ADAPTER)arg, addr, buff, len);
 }
 
-INT BcmWRM(PVOID arg,
-       UINT addr,
-       PVOID buff,
-       INT len)
+int BcmWRM(void *arg,
+       unsigned int addr,
+       void *buff,
+       int len)
 {
        return InterfaceWRM((PS_INTERFACE_ADAPTER)arg, addr, buff, len);
 }
 
-INT Bcm_clear_halt_of_endpoints(struct bcm_mini_adapter *Adapter)
+int Bcm_clear_halt_of_endpoints(struct bcm_mini_adapter *Adapter)
 {
        PS_INTERFACE_ADAPTER psIntfAdapter = (PS_INTERFACE_ADAPTER)(Adapter->pvInterfaceAdapter);
-       INT status = STATUS_SUCCESS;
+       int status = STATUS_SUCCESS;
 
        /*
         * usb_clear_halt - tells device to clear endpoint halt/stall condition
@@ -172,10 +154,10 @@ INT Bcm_clear_halt_of_endpoints(struct bcm_mini_adapter *Adapter)
        return status;
 }
 
-VOID Bcm_kill_all_URBs(PS_INTERFACE_ADAPTER psIntfAdapter)
+void Bcm_kill_all_URBs(PS_INTERFACE_ADAPTER psIntfAdapter)
 {
        struct urb *tempUrb = NULL;
-       UINT i;
+       unsigned int i;
 
        /*
         * usb_kill_urb - cancel a transfer request and wait for it to finish
@@ -193,7 +175,7 @@ VOID Bcm_kill_all_URBs(PS_INTERFACE_ADAPTER psIntfAdapter)
         */
 
        /* Cancel submitted Interrupt-URB's */
-       if (psIntfAdapter->psInterruptUrb != NULL) {
+       if (psIntfAdapter->psInterruptUrb) {
                if (psIntfAdapter->psInterruptUrb->status == -EINPROGRESS)
                        usb_kill_urb(psIntfAdapter->psInterruptUrb);
        }
@@ -222,7 +204,7 @@ VOID Bcm_kill_all_URBs(PS_INTERFACE_ADAPTER psIntfAdapter)
        atomic_set(&psIntfAdapter->uCurrRcb, 0);
 }
 
-VOID putUsbSuspend(struct work_struct *work)
+void putUsbSuspend(struct work_struct *work)
 {
        PS_INTERFACE_ADAPTER psIntfAdapter = NULL;
        struct usb_interface *intf = NULL;
index 6e8a3279698baa7c226a018c857c2805dd96f83a..877cf0b2bee1bb44a3cb86b3d71b00abd7e1401d 100644 (file)
@@ -21,10 +21,12 @@ static VOID UpdateTokenCount(register struct bcm_mini_adapter *Adapter)
        INT     i = 0;
        struct timeval tv;
 
-       BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "=====>\n");
+       BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL,
+                       "=====>\n");
        if(NULL == Adapter)
        {
-               BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "Adapter found NULL!\n");
+               BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, 
+                               DBG_LVL_ALL, "Adapter found NULL!\n");
                return;
        }
 
index f13a9582a82f0007406f564a77d0ef444dbd0c91..c3866d9f35801603d7230a65f40e3912c7338f56 100644 (file)
@@ -1,14 +1,14 @@
 #include "headers.h"
 
 static int BcmFileDownload(struct bcm_mini_adapter *Adapter, const char *path, unsigned int loc);
-static VOID doPowerAutoCorrection(struct bcm_mini_adapter *psAdapter);
+static void doPowerAutoCorrection(struct bcm_mini_adapter *psAdapter);
 static void HandleShutDownModeRequest(struct bcm_mini_adapter *Adapter, PUCHAR pucBuffer);
 static int bcm_parse_target_params(struct bcm_mini_adapter *Adapter);
 static void beceem_protocol_reset(struct bcm_mini_adapter *Adapter);
 
-static VOID default_wimax_protocol_initialize(struct bcm_mini_adapter *Adapter)
+static void default_wimax_protocol_initialize(struct bcm_mini_adapter *Adapter)
 {
-       UINT uiLoopIndex;
+       unsigned int uiLoopIndex;
 
        for (uiLoopIndex = 0; uiLoopIndex < NO_OF_QUEUES-1; uiLoopIndex++) {
                Adapter->PackInfo[uiLoopIndex].uiThreshold = TX_PACKET_THRESHOLD;
@@ -24,10 +24,10 @@ static VOID default_wimax_protocol_initialize(struct bcm_mini_adapter *Adapter)
        return;
 }
 
-INT InitAdapter(struct bcm_mini_adapter *psAdapter)
+int InitAdapter(struct bcm_mini_adapter *psAdapter)
 {
        int i = 0;
-       INT Status = STATUS_SUCCESS;
+       int Status = STATUS_SUCCESS;
        BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Initialising Adapter = %p", psAdapter);
 
        if (psAdapter == NULL) {
@@ -93,7 +93,7 @@ INT InitAdapter(struct bcm_mini_adapter *psAdapter)
        return STATUS_SUCCESS;
 }
 
-VOID AdapterFree(struct bcm_mini_adapter *Adapter)
+void AdapterFree(struct bcm_mini_adapter *Adapter)
 {
        int count;
        beceem_protocol_reset(Adapter);
@@ -216,12 +216,12 @@ exit_download:
  * Logical Adapter
  * Control Packet Buffer
  */
-INT CopyBufferToControlPacket(struct bcm_mini_adapter *Adapter, PVOID ioBuffer)
+int CopyBufferToControlPacket(struct bcm_mini_adapter *Adapter, void *ioBuffer)
 {
        struct bcm_leader *pLeader = NULL;
-       INT Status = 0;
-       unsigned char *ctrl_buff = NULL;
-       UINT pktlen = 0;
+       int Status = 0;
+       unsigned char *ctrl_buff;
+       unsigned int pktlen = 0;
        struct bcm_link_request *pLinkReq = NULL;
        PUCHAR pucAddIndication = NULL;
 
@@ -253,7 +253,7 @@ INT CopyBufferToControlPacket(struct bcm_mini_adapter *Adapter, PVOID ioBuffer)
                        return STATUS_FAILURE;
                }
 
-               if (TRUE == Adapter->bShutStatus) {
+               if (Adapter->bShutStatus == TRUE) {
                        BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "SYNC UP IN SHUTDOWN..Device WakeUp\n");
                        if (Adapter->bTriedToWakeUpFromlowPowerMode == FALSE) {
                                BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Waking up for the First Time..\n");
@@ -275,7 +275,7 @@ INT CopyBufferToControlPacket(struct bcm_mini_adapter *Adapter, PVOID ioBuffer)
                }
        }
 
-       if (TRUE == Adapter->IdleMode) {
+       if (Adapter->IdleMode == TRUE) {
                /* BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Device is in Idle mode ... hence\n"); */
                if (pLeader->Status == LINK_UP_CONTROL_REQ || pLeader->Status == 0x80 ||
                        pLeader->Status == CM_CONTROL_NEWDSX_MULTICLASSIFIER_REQ) {
@@ -325,64 +325,66 @@ INT CopyBufferToControlPacket(struct bcm_mini_adapter *Adapter, PVOID ioBuffer)
        pktlen = pLeader->PLength;
        ctrl_buff = (char *)Adapter->txctlpacket[atomic_read(&Adapter->index_wr_txcntrlpkt)%MAX_CNTRL_PKTS];
 
+       if (!ctrl_buff) {
+               BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "mem allocation Failed");
+               return -ENOMEM;
+       }
+
        BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Control packet to be taken =%d and address is =%pincoming address is =%p and packet len=%x",
                        atomic_read(&Adapter->index_wr_txcntrlpkt), ctrl_buff, ioBuffer, pktlen);
-       if (ctrl_buff) {
-               if (pLeader) {
-                       if ((pLeader->Status == 0x80) ||
-                               (pLeader->Status == CM_CONTROL_NEWDSX_MULTICLASSIFIER_REQ)) {
-                               /*
-                                * Restructure the DSX message to handle Multiple classifier Support
-                                * Write the Service Flow param Structures directly to the target
-                                * and embed the pointers in the DSX messages sent to target.
-                                */
-                               /* Lets store the current length of the control packet we are transmitting */
-                               pucAddIndication = (PUCHAR)ioBuffer + LEADER_SIZE;
-                               pktlen = pLeader->PLength;
-                               Status = StoreCmControlResponseMessage(Adapter, pucAddIndication, &pktlen);
-                               if (Status != 1) {
-                                       ClearTargetDSXBuffer(Adapter, ((stLocalSFAddIndicationAlt *)pucAddIndication)->u16TID, FALSE);
-                                       BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, " Error Restoring The DSX Control Packet. Dsx Buffers on Target may not be Setup Properly ");
-                                       return STATUS_FAILURE;
-                               }
-                               /*
-                                * update the leader to use the new length
-                                * The length of the control packet is length of message being sent + Leader length
-                                */
-                               pLeader->PLength = pktlen;
+
+       if (pLeader) {
+               if ((pLeader->Status == 0x80) ||
+                       (pLeader->Status == CM_CONTROL_NEWDSX_MULTICLASSIFIER_REQ)) {
+                       /*
+                        * Restructure the DSX message to handle Multiple classifier Support
+                        * Write the Service Flow param Structures directly to the target
+                        * and embed the pointers in the DSX messages sent to target.
+                        */
+                       /* Lets store the current length of the control packet we are transmitting */
+                       pucAddIndication = (PUCHAR)ioBuffer + LEADER_SIZE;
+                       pktlen = pLeader->PLength;
+                       Status = StoreCmControlResponseMessage(Adapter, pucAddIndication, &pktlen);
+                       if (Status != 1) {
+                               ClearTargetDSXBuffer(Adapter, ((stLocalSFAddIndicationAlt *)pucAddIndication)->u16TID, FALSE);
+                               BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, " Error Restoring The DSX Control Packet. Dsx Buffers on Target may not be Setup Properly ");
+                               return STATUS_FAILURE;
                        }
+                       /*
+                        * update the leader to use the new length
+                        * The length of the control packet is length of message being sent + Leader length
+                        */
+                       pLeader->PLength = pktlen;
                }
-
-               if (pktlen + LEADER_SIZE > MAX_CNTL_PKT_SIZE)
-                       return -EINVAL;
-
-               memset(ctrl_buff, 0, pktlen+LEADER_SIZE);
-               BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Copying the Control Packet Buffer with length=%d\n", pLeader->PLength);
-               *(struct bcm_leader *)ctrl_buff = *pLeader;
-               memcpy(ctrl_buff + LEADER_SIZE, ((PUCHAR)ioBuffer + LEADER_SIZE), pLeader->PLength);
-               BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Enqueuing the Control Packet");
-
-               /* Update the statistics counters */
-               spin_lock_bh(&Adapter->PackInfo[HiPriority].SFQueueLock);
-               Adapter->PackInfo[HiPriority].uiCurrentBytesOnHost += pLeader->PLength;
-               Adapter->PackInfo[HiPriority].uiCurrentPacketsOnHost++;
-               atomic_inc(&Adapter->TotalPacketCount);
-               spin_unlock_bh(&Adapter->PackInfo[HiPriority].SFQueueLock);
-               Adapter->PackInfo[HiPriority].bValid = TRUE;
-
-               BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "CurrBytesOnHost: %x bValid: %x",
-                               Adapter->PackInfo[HiPriority].uiCurrentBytesOnHost,
-                               Adapter->PackInfo[HiPriority].bValid);
-               Status = STATUS_SUCCESS;
-               /*Queue the packet for transmission */
-               atomic_inc(&Adapter->index_wr_txcntrlpkt);
-               BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Calling transmit_packets");
-               atomic_set(&Adapter->TxPktAvail, 1);
-               wake_up(&Adapter->tx_packet_wait_queue);
-       } else {
-               Status = -ENOMEM;
-               BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "mem allocation Failed");
        }
+
+       if (pktlen + LEADER_SIZE > MAX_CNTL_PKT_SIZE)
+               return -EINVAL;
+
+       memset(ctrl_buff, 0, pktlen+LEADER_SIZE);
+       BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Copying the Control Packet Buffer with length=%d\n", pLeader->PLength);
+       *(struct bcm_leader *)ctrl_buff = *pLeader;
+       memcpy(ctrl_buff + LEADER_SIZE, ((PUCHAR)ioBuffer + LEADER_SIZE), pLeader->PLength);
+       BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Enqueuing the Control Packet");
+
+       /* Update the statistics counters */
+       spin_lock_bh(&Adapter->PackInfo[HiPriority].SFQueueLock);
+       Adapter->PackInfo[HiPriority].uiCurrentBytesOnHost += pLeader->PLength;
+       Adapter->PackInfo[HiPriority].uiCurrentPacketsOnHost++;
+       atomic_inc(&Adapter->TotalPacketCount);
+       spin_unlock_bh(&Adapter->PackInfo[HiPriority].SFQueueLock);
+       Adapter->PackInfo[HiPriority].bValid = TRUE;
+
+       BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "CurrBytesOnHost: %x bValid: %x",
+                       Adapter->PackInfo[HiPriority].uiCurrentBytesOnHost,
+                       Adapter->PackInfo[HiPriority].bValid);
+       Status = STATUS_SUCCESS;
+       /*Queue the packet for transmission */
+       atomic_inc(&Adapter->index_wr_txcntrlpkt);
+       BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Calling transmit_packets");
+       atomic_set(&Adapter->TxPktAvail, 1);
+       wake_up(&Adapter->tx_packet_wait_queue);
+
        BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "<====");
        return Status;
 }
@@ -397,7 +399,7 @@ INT CopyBufferToControlPacket(struct bcm_mini_adapter *Adapter, PVOID ioBuffer)
 *
 * Returns     - None.
 *******************************************************************/
-VOID LinkMessage(struct bcm_mini_adapter *Adapter)
+void LinkMessage(struct bcm_mini_adapter *Adapter)
 {
        struct bcm_link_request *pstLinkRequest = NULL;
        BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "=====>");
@@ -448,11 +450,11 @@ VOID LinkMessage(struct bcm_mini_adapter *Adapter)
 *
 * Returns     - None.
 ************************************************************************/
-VOID StatisticsResponse(struct bcm_mini_adapter *Adapter, PVOID pvBuffer)
+void StatisticsResponse(struct bcm_mini_adapter *Adapter, void *pvBuffer)
 {
        BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "%s====>", __func__);
        Adapter->StatisticsPointer = ntohl(*(__be32 *)pvBuffer);
-       BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "Stats at %x", (UINT)Adapter->StatisticsPointer);
+       BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "Stats at %x", (unsigned int)Adapter->StatisticsPointer);
        BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "%s <====", __func__);
        return;
 }
@@ -467,7 +469,7 @@ VOID StatisticsResponse(struct bcm_mini_adapter *Adapter, PVOID pvBuffer)
 *
 * Returns     - None.
 ***********************************************************************/
-VOID LinkControlResponseMessage(struct bcm_mini_adapter *Adapter, PUCHAR pucBuffer)
+void LinkControlResponseMessage(struct bcm_mini_adapter *Adapter, PUCHAR pucBuffer)
 {
        BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "=====>");
 
@@ -543,7 +545,7 @@ VOID LinkControlResponseMessage(struct bcm_mini_adapter *Adapter, PUCHAR pucBuff
 
 void SendIdleModeResponse(struct bcm_mini_adapter *Adapter)
 {
-       INT status = 0, NVMAccess = 0, lowPwrAbortMsg = 0;
+       int status = 0, NVMAccess = 0, lowPwrAbortMsg = 0;
        struct timeval tv;
        struct bcm_link_request stIdleResponse = {{0} };
        memset(&tv, 0, sizeof(tv));
@@ -583,7 +585,7 @@ void SendIdleModeResponse(struct bcm_mini_adapter *Adapter)
 
                /* Wait for the LED to TURN OFF before sending ACK response */
                if (Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) {
-                       INT iRetVal = 0;
+                       int iRetVal = 0;
 
                        /* Wake the LED Thread with IDLEMODE_ENTER State */
                        Adapter->DriverState = LOWPOWER_MODE_ENTER;
@@ -640,11 +642,11 @@ void SendIdleModeResponse(struct bcm_mini_adapter *Adapter)
 *
 * Returns     - None.
 *******************************************************************/
-VOID DumpPackInfo(struct bcm_mini_adapter *Adapter)
+void DumpPackInfo(struct bcm_mini_adapter *Adapter)
 {
-       UINT uiLoopIndex = 0;
-       UINT uiIndex = 0;
-       UINT uiClsfrIndex = 0;
+       unsigned int uiLoopIndex = 0;
+       unsigned int uiIndex = 0;
+       unsigned int uiClsfrIndex = 0;
        struct bcm_classifier_rule *pstClassifierEntry = NULL;
 
        for (uiLoopIndex = 0; uiLoopIndex < NO_OF_QUEUES; uiLoopIndex++) {
@@ -920,7 +922,7 @@ int run_card_proc(struct bcm_mini_adapter *ps_adapter)
 int InitCardAndDownloadFirmware(struct bcm_mini_adapter *ps_adapter)
 {
        int status;
-       UINT value = 0;
+       unsigned int value = 0;
        /*
         * Create the threads first and then download the
         * Firm/DDR Settings..
@@ -1088,7 +1090,7 @@ static int bcm_parse_target_params(struct bcm_mini_adapter *Adapter)
 
 void beceem_parse_target_struct(struct bcm_mini_adapter *Adapter)
 {
-       UINT uiHostDrvrCfg6 = 0, uiEEPROMFlag = 0;
+       unsigned int uiHostDrvrCfg6 = 0, uiEEPROMFlag = 0;
 
        if (ntohl(Adapter->pstargetparams->m_u32PhyParameter2) & AUTO_SYNC_DISABLE) {
                pr_info(DRV_NAME ": AutoSyncup is Disabled\n");
@@ -1144,9 +1146,9 @@ void beceem_parse_target_struct(struct bcm_mini_adapter *Adapter)
                doPowerAutoCorrection(Adapter);
 }
 
-static VOID doPowerAutoCorrection(struct bcm_mini_adapter *psAdapter)
+static void doPowerAutoCorrection(struct bcm_mini_adapter *psAdapter)
 {
-       UINT reporting_mode;
+       unsigned int reporting_mode;
 
        reporting_mode = ntohl(psAdapter->pstargetparams->m_u32PowerSavingModeOptions) & 0x02;
        psAdapter->bIsAutoCorrectEnabled = !((char)(psAdapter->ulPowerSaveMode >> 3) & 0x1);
@@ -1175,26 +1177,26 @@ static VOID doPowerAutoCorrection(struct bcm_mini_adapter *psAdapter)
        }
 }
 
-static void convertEndian(B_UINT8 rwFlag, PUINT puiBuffer, UINT uiByteCount)
+static void convertEndian(unsigned char rwFlag, unsigned int *puiBuffer, unsigned int uiByteCount)
 {
-       UINT uiIndex = 0;
+       unsigned int uiIndex = 0;
 
        if (RWM_WRITE == rwFlag) {
-               for (uiIndex = 0; uiIndex < (uiByteCount/sizeof(UINT)); uiIndex++)
+               for (uiIndex = 0; uiIndex < (uiByteCount/sizeof(unsigned int)); uiIndex++)
                        puiBuffer[uiIndex] = htonl(puiBuffer[uiIndex]);
        } else {
-               for (uiIndex = 0; uiIndex < (uiByteCount/sizeof(UINT)); uiIndex++)
+               for (uiIndex = 0; uiIndex < (uiByteCount/sizeof(unsigned int)); uiIndex++)
                        puiBuffer[uiIndex] = ntohl(puiBuffer[uiIndex]);
        }
 }
 
-int rdm(struct bcm_mini_adapter *Adapter, UINT uiAddress, PCHAR pucBuff, size_t sSize)
+int rdm(struct bcm_mini_adapter *Adapter, unsigned int uiAddress, PCHAR pucBuff, size_t sSize)
 {
        return Adapter->interface_rdm(Adapter->pvInterfaceAdapter,
                                uiAddress, pucBuff, sSize);
 }
 
-int wrm(struct bcm_mini_adapter *Adapter, UINT uiAddress, PCHAR pucBuff, size_t sSize)
+int wrm(struct bcm_mini_adapter *Adapter, unsigned int uiAddress, PCHAR pucBuff, size_t sSize)
 {
        int iRetVal;
 
@@ -1203,25 +1205,25 @@ int wrm(struct bcm_mini_adapter *Adapter, UINT uiAddress, PCHAR pucBuff, size_t
        return iRetVal;
 }
 
-int wrmalt(struct bcm_mini_adapter *Adapter, UINT uiAddress, PUINT pucBuff, size_t size)
+int wrmalt(struct bcm_mini_adapter *Adapter, unsigned int uiAddress, unsigned int *pucBuff, size_t size)
 {
        convertEndian(RWM_WRITE, pucBuff, size);
        return wrm(Adapter, uiAddress, (PUCHAR)pucBuff, size);
 }
 
-int rdmalt(struct bcm_mini_adapter *Adapter, UINT uiAddress, PUINT pucBuff, size_t size)
+int rdmalt(struct bcm_mini_adapter *Adapter, unsigned int uiAddress, unsigned int *pucBuff, size_t size)
 {
-       INT uiRetVal = 0;
+       int uiRetVal = 0;
 
        uiRetVal = rdm(Adapter, uiAddress, (PUCHAR)pucBuff, size);
-       convertEndian(RWM_READ, (PUINT)pucBuff, size);
+       convertEndian(RWM_READ, (unsigned int *)pucBuff, size);
 
        return uiRetVal;
 }
 
-int wrmWithLock(struct bcm_mini_adapter *Adapter, UINT uiAddress, PCHAR pucBuff, size_t sSize)
+int wrmWithLock(struct bcm_mini_adapter *Adapter, unsigned int uiAddress, PCHAR pucBuff, size_t sSize)
 {
-       INT status = STATUS_SUCCESS;
+       int status = STATUS_SUCCESS;
        down(&Adapter->rdmwrmsync);
 
        if ((Adapter->IdleMode == TRUE) ||
@@ -1238,7 +1240,7 @@ exit:
        return status;
 }
 
-int wrmaltWithLock(struct bcm_mini_adapter *Adapter, UINT uiAddress, PUINT pucBuff, size_t size)
+int wrmaltWithLock(struct bcm_mini_adapter *Adapter, unsigned int uiAddress, unsigned int *pucBuff, size_t size)
 {
        int iRetVal = STATUS_SUCCESS;
 
@@ -1258,9 +1260,9 @@ exit:
        return iRetVal;
 }
 
-int rdmaltWithLock(struct bcm_mini_adapter *Adapter, UINT uiAddress, PUINT pucBuff, size_t size)
+int rdmaltWithLock(struct bcm_mini_adapter *Adapter, unsigned int uiAddress, unsigned int *pucBuff, size_t size)
 {
-       INT uiRetVal = STATUS_SUCCESS;
+       int uiRetVal = STATUS_SUCCESS;
 
        down(&Adapter->rdmwrmsync);
        if ((Adapter->IdleMode == TRUE) ||
@@ -1277,13 +1279,13 @@ exit:
        return uiRetVal;
 }
 
-static VOID HandleShutDownModeWakeup(struct bcm_mini_adapter *Adapter)
+static void HandleShutDownModeWakeup(struct bcm_mini_adapter *Adapter)
 {
        int clear_abort_pattern = 0, Status = 0;
        BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "====>\n");
        /* target has woken up From Shut Down */
        BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "Clearing Shut Down Software abort pattern\n");
-       Status = wrmalt(Adapter, SW_ABORT_IDLEMODE_LOC, (PUINT)&clear_abort_pattern, sizeof(clear_abort_pattern));
+       Status = wrmalt(Adapter, SW_ABORT_IDLEMODE_LOC, (unsigned int *)&clear_abort_pattern, sizeof(clear_abort_pattern));
        if (Status) {
                BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "WRM to SW_ABORT_IDLEMODE_LOC failed with err:%d", Status);
                return;
@@ -1306,11 +1308,11 @@ static VOID HandleShutDownModeWakeup(struct bcm_mini_adapter *Adapter)
        BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "<====\n");
 }
 
-static VOID SendShutModeResponse(struct bcm_mini_adapter *Adapter)
+static void SendShutModeResponse(struct bcm_mini_adapter *Adapter)
 {
        struct bcm_link_request stShutdownResponse;
-       UINT NVMAccess = 0, lowPwrAbortMsg = 0;
-       UINT Status = 0;
+       unsigned int NVMAccess = 0, lowPwrAbortMsg = 0;
+       unsigned int Status = 0;
 
        memset(&stShutdownResponse, 0, sizeof(struct bcm_link_request));
        stShutdownResponse.Leader.Status  = LINK_UP_CONTROL_REQ;
@@ -1346,7 +1348,7 @@ static VOID SendShutModeResponse(struct bcm_mini_adapter *Adapter)
 
                /* Wait for the LED to TURN OFF before sending ACK response */
                if (Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) {
-                       INT iRetVal = 0;
+                       int iRetVal = 0;
 
                        /* Wake the LED Thread with LOWPOWER_MODE_ENTER State */
                        Adapter->DriverState = LOWPOWER_MODE_ENTER;
@@ -1392,7 +1394,7 @@ static VOID SendShutModeResponse(struct bcm_mini_adapter *Adapter)
 
 static void HandleShutDownModeRequest(struct bcm_mini_adapter *Adapter, PUCHAR pucBuffer)
 {
-       B_UINT32 uiResetValue = 0;
+       unsigned int uiResetValue = 0;
 
        BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "====>\n");
 
@@ -1412,14 +1414,14 @@ static void HandleShutDownModeRequest(struct bcm_mini_adapter *Adapter, PUCHAR p
                }
 
                SendShutModeResponse(Adapter);
-               BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "ShutDownModeResponse:Notification received: Sending the response(Ack/Nack)\n");
+               BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "ShutDownModeResponse:Notification received: Sending the response(Ack/Nack)\n");
        }
 
        BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "<====\n");
        return;
 }
 
-VOID ResetCounters(struct bcm_mini_adapter *Adapter)
+void ResetCounters(struct bcm_mini_adapter *Adapter)
 {
        beceem_protocol_reset(Adapter);
        Adapter->CurrNumRecvDescs = 0;
@@ -1437,7 +1439,7 @@ VOID ResetCounters(struct bcm_mini_adapter *Adapter)
 
 struct bcm_classifier_rule *GetFragIPClsEntry(struct bcm_mini_adapter *Adapter, USHORT usIpIdentification, ULONG SrcIP)
 {
-       UINT uiIndex = 0;
+       unsigned int uiIndex = 0;
        for (uiIndex = 0; uiIndex < MAX_FRAGMENTEDIP_CLASSIFICATION_ENTRIES; uiIndex++) {
                if ((Adapter->astFragmentedPktClassifierTable[uiIndex].bUsed) &&
                        (Adapter->astFragmentedPktClassifierTable[uiIndex].usIpIdentification == usIpIdentification) &&
@@ -1451,7 +1453,7 @@ struct bcm_classifier_rule *GetFragIPClsEntry(struct bcm_mini_adapter *Adapter,
 
 void AddFragIPClsEntry(struct bcm_mini_adapter *Adapter, struct bcm_fragmented_packet_info *psFragPktInfo)
 {
-       UINT uiIndex = 0;
+       unsigned int uiIndex = 0;
        for (uiIndex = 0; uiIndex < MAX_FRAGMENTEDIP_CLASSIFICATION_ENTRIES; uiIndex++) {
                if (!Adapter->astFragmentedPktClassifierTable[uiIndex].bUsed) {
                        memcpy(&Adapter->astFragmentedPktClassifierTable[uiIndex], psFragPktInfo, sizeof(struct bcm_fragmented_packet_info));
@@ -1462,7 +1464,7 @@ void AddFragIPClsEntry(struct bcm_mini_adapter *Adapter, struct bcm_fragmented_p
 
 void DelFragIPClsEntry(struct bcm_mini_adapter *Adapter, USHORT usIpIdentification, ULONG SrcIp)
 {
-       UINT uiIndex = 0;
+       unsigned int uiIndex = 0;
        for (uiIndex = 0; uiIndex < MAX_FRAGMENTEDIP_CLASSIFICATION_ENTRIES; uiIndex++) {
                if ((Adapter->astFragmentedPktClassifierTable[uiIndex].bUsed) &&
                        (Adapter->astFragmentedPktClassifierTable[uiIndex].usIpIdentification == usIpIdentification) &&
@@ -1474,7 +1476,7 @@ void DelFragIPClsEntry(struct bcm_mini_adapter *Adapter, USHORT usIpIdentificati
 
 void update_per_cid_rx(struct bcm_mini_adapter *Adapter)
 {
-       UINT qindex = 0;
+       unsigned int qindex = 0;
 
        if ((jiffies - Adapter->liDrainCalculated) < XSECONDS)
                return;
@@ -1498,14 +1500,14 @@ void update_per_cid_rx(struct bcm_mini_adapter *Adapter)
 
 void update_per_sf_desc_cnts(struct bcm_mini_adapter *Adapter)
 {
-       INT iIndex = 0;
+       int iIndex = 0;
        u32 uibuff[MAX_TARGET_DSX_BUFFERS];
        int bytes;
 
        if (!atomic_read(&Adapter->uiMBupdate))
                return;
 
-       bytes = rdmaltWithLock(Adapter, TARGET_SFID_TXDESC_MAP_LOC, (PUINT)uibuff, sizeof(UINT) * MAX_TARGET_DSX_BUFFERS);
+       bytes = rdmaltWithLock(Adapter, TARGET_SFID_TXDESC_MAP_LOC, (unsigned int *)uibuff, sizeof(unsigned int) * MAX_TARGET_DSX_BUFFERS);
        if (bytes < 0) {
                BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "rdm failed\n");
                return;
@@ -1522,7 +1524,7 @@ void update_per_sf_desc_cnts(struct bcm_mini_adapter *Adapter)
        atomic_set(&Adapter->uiMBupdate, FALSE);
 }
 
-void flush_queue(struct bcm_mini_adapter *Adapter, UINT iQIndex)
+void flush_queue(struct bcm_mini_adapter *Adapter, unsigned int iQIndex)
 {
        struct sk_buff *PacketToDrop = NULL;
        struct net_device_stats *netstats = &Adapter->dev->stats;
index 3ec8f800a5b03ba4c097b4ce21737654bef7f1d1..e3f01cbe51fa1fddd534c3ca3b34b5b672a9a58e 100644 (file)
@@ -79,9 +79,9 @@ int rdm(struct bcm_mini_adapter *Adapter, UINT uiAddress, PCHAR pucBuff, size_t
 
 int wrm(struct bcm_mini_adapter *Adapter, UINT uiAddress, PCHAR pucBuff, size_t size);
 
-int wrmalt (struct bcm_mini_adapter *Adapter, UINT uiAddress, PUINT pucBuff, size_t sSize);
+int wrmalt (struct bcm_mini_adapter *Adapter, UINT uiAddress, unsigned int *pucBuff, size_t sSize);
 
-int rdmalt (struct bcm_mini_adapter *Adapter, UINT uiAddress, PUINT pucBuff, size_t sSize);
+int rdmalt (struct bcm_mini_adapter *Adapter, UINT uiAddress, unsigned int *pucBuff, size_t sSize);
 
 int get_dsx_sf_data_to_application(struct bcm_mini_adapter *Adapter, UINT uiSFId, void __user * user_buffer);
 
@@ -203,8 +203,8 @@ BOOLEAN IsNonCDLessDevice(struct bcm_mini_adapter *Adapter);
 
 VOID OverrideServiceFlowParams(struct bcm_mini_adapter *Adapter,PUINT puiBuffer);
 
-int wrmaltWithLock (struct bcm_mini_adapter *Adapter, UINT uiAddress, PUINT pucBuff, size_t sSize);
-int rdmaltWithLock (struct bcm_mini_adapter *Adapter, UINT uiAddress, PUINT pucBuff, size_t sSize);
+int wrmaltWithLock (struct bcm_mini_adapter *Adapter, UINT uiAddress, unsigned int *pucBuff, size_t sSize);
+int rdmaltWithLock (struct bcm_mini_adapter *Adapter, UINT uiAddress, unsigned int *pucBuff, size_t sSize);
 
 int wrmWithLock(struct bcm_mini_adapter *Adapter, UINT uiAddress, PCHAR pucBuff, size_t size);
 INT buffDnldVerify(struct bcm_mini_adapter *Adapter, unsigned char *mappedbuffer, unsigned int u32FirmwareLength,
index 93e1e2ffca0c7d953b23fa96f77cac4c7fc1ac57..ffc5f73a5b5b588556cac57ffdb5d7ffb5821b51 100644 (file)
@@ -1239,7 +1239,7 @@ static int ccg_create_device(struct ccg_dev *dev)
 }
 
 
-static int __init init(void)
+static int __init ccg_init(void)
 {
        struct ccg_dev *dev;
        int err;
@@ -1280,13 +1280,13 @@ static int __init init(void)
 
        return err;
 }
-module_init(init);
+module_init(ccg_init);
 
-static void __exit cleanup(void)
+static void __exit ccg_exit(void)
 {
        usb_composite_unregister(&ccg_usb_driver);
        class_destroy(ccg_class);
        kfree(_ccg_dev);
        _ccg_dev = NULL;
 }
-module_exit(cleanup);
+module_exit(ccg_exit);
index c9492edaaddb97ffb06ba796e0079f265549d6d7..0adba75be8b7435f0cb09fe4a887df6650dfa567 100644 (file)
@@ -913,18 +913,24 @@ int GetTransfer(DEVICE_EXTENSION * pdx, TGET_TX_BLOCK __user * pTX)
                iReturn = U14ERR_BADAREA;
        else {
                // Return the best information we have - we don't have physical addresses
-               TGET_TX_BLOCK tx;
-               memset(&tx, 0, sizeof(tx));     // clean out local work structure
-               tx.size = pdx->rTransDef[dwIdent].dwLength;
-               tx.linear = (long long)((long)pdx->rTransDef[dwIdent].lpvBuff);
-               tx.avail = GET_TX_MAXENTRIES;   // how many blocks we could return
-               tx.used = 1;    // number we actually return
-               tx.entries[0].physical =
-                   (long long)(tx.linear + pdx->StagedOffset);
-               tx.entries[0].size = tx.size;
-
-               if (copy_to_user(pTX, &tx, sizeof(tx)))
+               TGET_TX_BLOCK *tx;
+
+               tx = kzalloc(sizeof(*tx), GFP_KERNEL);
+               if (!tx) {
+                       mutex_unlock(&pdx->io_mutex);
+                       return -ENOMEM;
+               }
+               tx->size = pdx->rTransDef[dwIdent].dwLength;
+               tx->linear = (long long)((long)pdx->rTransDef[dwIdent].lpvBuff);
+               tx->avail = GET_TX_MAXENTRIES;  // how many blocks we could return
+               tx->used = 1;   // number we actually return
+               tx->entries[0].physical =
+                   (long long)(tx->linear + pdx->StagedOffset);
+               tx->entries[0].size = tx->size;
+
+               if (copy_to_user(pTX, tx, sizeof(*tx)))
                        iReturn = -EFAULT;
+               kfree(tx);
        }
        mutex_unlock(&pdx->io_mutex);
        return iReturn;
@@ -1508,7 +1514,7 @@ int FreeCircBlock(DEVICE_EXTENSION * pdx, TCIRCBLOCK __user * pCB)
                iReturn = U14ERR_BADAREA;
 
        if (copy_to_user(pCB, &cb, sizeof(cb)))
-               return -EFAULT;
+               iReturn = -EFAULT;
 
        mutex_unlock(&pdx->io_mutex);
        return iReturn;
index 6ba0ef6525611f0de97284ad744de1e0cfa437fd..88e2cc0e2a253cd11225e6870d2a4883ab751272 100644 (file)
@@ -90,13 +90,11 @@ synchronous non-Urb based transfers.
 #include <linux/mm.h>
 #include <linux/highmem.h>
 #include <linux/version.h>
-#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35) )
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/kref.h>
 #include <linux/uaccess.h>
-#endif
 
 #include "usb1401.h"
 
@@ -123,19 +121,6 @@ MODULE_DEVICE_TABLE(usb, ced_table);
 #define WRITES_IN_FLIGHT       8
 /* arbitrarily chosen */
 
-/* 
-The cause for these errors is that the driver makes use of the functions usb_buffer_alloc() and usb_buffer_free() which got renamed in kernel 2.6.35. This is stated in the Changelog:   USB: rename usb_buffer_alloc() and usb_buffer_free() users
-    For more clearance what the functions actually do,
-      usb_buffer_alloc() is renamed to usb_alloc_coherent()
-      usb_buffer_free()  is renamed to usb_free_coherent()
-   This is needed on Debian 2.6.32-5-amd64
-*/
-#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) )
-#define usb_alloc_coherent usb_buffer_alloc
-#define usb_free_coherent  usb_buffer_free
-#define noop_llseek NULL
-#endif
-
 static struct usb_driver ced_driver;
 
 static void ced_delete(struct kref *kref)
@@ -1252,12 +1237,7 @@ int Allowi(DEVICE_EXTENSION * pdx, bool bInCallback)
 ** ulArg    The argument passed in. Note that long is 64-bits in 64-bit system, i.e. it is big
 **          enough for a 64-bit pointer.
 *****************************************************************************/
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)
 static long ced_ioctl(struct file *file, unsigned int cmd, unsigned long ulArg)
-#else
-static int ced_ioctl(struct inode *node, struct file *file, unsigned int cmd,
-                    unsigned long ulArg)
-#endif
 {
        int err = 0;
        DEVICE_EXTENSION *pdx = file->private_data;
@@ -1388,11 +1368,7 @@ static const struct file_operations ced_fops = {
        .release = ced_release,
        .flush = ced_flush,
        .llseek = noop_llseek,
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)
        .unlocked_ioctl = ced_ioctl,
-#else
-       .ioctl = ced_ioctl,
-#endif
 };
 
 /*
@@ -1537,7 +1513,7 @@ error:
 static void ced_disconnect(struct usb_interface *interface)
 {
        DEVICE_EXTENSION *pdx = usb_get_intfdata(interface);
-       int minor = interface->minor;   // save for message at the end
+       int minor = interface->minor;
        int i;
 
        usb_set_intfdata(interface, NULL);      // remove the pdx from the interface
@@ -1572,8 +1548,7 @@ void ced_draw_down(DEVICE_EXTENSION * pdx)
 
        pdx->bInDrawDown = true;
        time = usb_wait_anchor_empty_timeout(&pdx->submitted, 3000);
-       if (!time)              // if we timed out we kill the urbs
-       {
+       if (!time) {            // if we timed out we kill the urbs
                usb_kill_anchored_urbs(&pdx->submitted);
                dev_err(&pdx->interface->dev, "%s timed out", __func__);
        }
index 2093403af2537e87e14ce18a463c92bd871fa6d1..21a6748d7adcc6df5ecb8c1018d104025dc7893a 100644 (file)
@@ -761,10 +761,11 @@ config COMEDI_ADV_PCI_DIO
          called adv_pci_dio.
 
 config COMEDI_AMPLC_DIO200_PCI
-       tristate "Amplicon PCI215 and PCI272 DIO board support"
+       tristate "Amplicon PCI215/PCI272/PCIe215/PCIe236/PCIe296 DIO support"
        select COMEDI_AMPLC_DIO200
        ---help---
-         Enable support for Amplicon PCI215 and PCI272 DIO boards.
+         Enable support for Amplicon PCI215, PCI272, PCIe215, PCIe236
+         and PCIe296 DIO boards.
 
          To compile this driver as a module, choose M here: the module will be
          called amplc_dio200.
@@ -1263,7 +1264,6 @@ config COMEDI_FC
 
 config COMEDI_AMPLC_DIO200
        tristate
-       select COMEDI_8255
 
 config COMEDI_AMPLC_PC236
        tristate
index 133f013e0f6d783c0c7dfb5835f9e978edda7902..3cbd2cda1f7c4f1a01d95a2c38faf60233403d9a 100644 (file)
@@ -888,7 +888,20 @@ enum amplc_dio_clock_source {
                                   subdevice, preceding counter
                                   subdevice is the last counter
                                   subdevice) */
-       AMPLC_DIO_CLK_EXT       /* per chip external input pin */
+       AMPLC_DIO_CLK_EXT,      /* per chip external input pin */
+       /* the following are "enhanced" clock sources for PCIe models */
+       AMPLC_DIO_CLK_VCC,      /* clock input HIGH */
+       AMPLC_DIO_CLK_GND,      /* clock input LOW */
+       AMPLC_DIO_CLK_PAT_PRESENT, /* "pattern present" signal */
+       AMPLC_DIO_CLK_20MHZ     /* 20 MHz internal clock */
+};
+
+/* Values for setting a clock source with INSN_CONFIG_SET_CLOCK_SRC for
+ * timer subdevice on some Amplicon DIO PCIe boards (amplc_dio200 driver). */
+enum amplc_dio_ts_clock_src {
+       AMPLC_DIO_TS_CLK_1GHZ,  /* 1 ns period with 20 ns granularity */
+       AMPLC_DIO_TS_CLK_1MHZ,  /* 1 us period */
+       AMPLC_DIO_TS_CLK_1KHZ   /* 1 ms period */
 };
 
 /* Values for setting a gate source with INSN_CONFIG_SET_GATE_SRC for
@@ -907,7 +920,17 @@ enum amplc_dio_gate_source {
        AMPLC_DIO_GAT_RESERVED4,
        AMPLC_DIO_GAT_RESERVED5,
        AMPLC_DIO_GAT_RESERVED6,
-       AMPLC_DIO_GAT_RESERVED7
+       AMPLC_DIO_GAT_RESERVED7,
+       /* the following are "enhanced" gate sources for PCIe models */
+       AMPLC_DIO_GAT_NGATN = 6, /* negated per channel gate input */
+       AMPLC_DIO_GAT_OUTNM2,   /* non-negated output of counter
+                                  channel minus 2 */
+       AMPLC_DIO_GAT_PAT_PRESENT, /* "pattern present" signal */
+       AMPLC_DIO_GAT_PAT_OCCURRED, /* "pattern occurred" latched */
+       AMPLC_DIO_GAT_PAT_GONE, /* "pattern gone away" latched */
+       AMPLC_DIO_GAT_NPAT_PRESENT, /* negated "pattern present" */
+       AMPLC_DIO_GAT_NPAT_OCCURRED, /* negated "pattern occurred" */
+       AMPLC_DIO_GAT_NPAT_GONE /* negated "pattern gone away" */
 };
 
 #endif /* _COMEDI_H */
index cb67a5cb9c824fd5e1fba9c701ae2a1a628618c1..78a44fc46ef28a632f276b1542dfa1db957ec3c6 100644 (file)
@@ -415,14 +415,6 @@ struct comedi_lrange {
 
 /* some silly little inline functions */
 
-static inline int alloc_private(struct comedi_device *dev, int size)
-{
-       dev->private = kzalloc(size, GFP_KERNEL);
-       if (!dev->private)
-               return -ENOMEM;
-       return 0;
-}
-
 static inline unsigned int bytes_per_sample(const struct comedi_subdevice *subd)
 {
        if (subd->subdev_flags & SDF_LSAMPL)
@@ -436,9 +428,10 @@ into comedi's buffer */
 static inline void comedi_set_hw_dev(struct comedi_device *dev,
                                     struct device *hw_dev)
 {
+       if (dev->hw_dev == hw_dev)
+               return;
        if (dev->hw_dev)
                put_device(dev->hw_dev);
-
        dev->hw_dev = hw_dev;
        if (dev->hw_dev) {
                dev->hw_dev = get_device(dev->hw_dev);
index 1db6bfdbf13bd70695492f3cabea51ca7a325e43..09e1daf95767fb5d3ef2976edac446aea89ab6b5 100644 (file)
@@ -860,6 +860,7 @@ comedi_auto_config_helper(struct device *hardware_device,
        else if (!try_module_get(driver->module))
                ret = -EIO;
        else {
+               comedi_set_hw_dev(comedi_dev, hardware_device);
                /* set comedi_dev->driver here for attach wrapper */
                comedi_dev->driver = driver;
                ret = (*attach_wrapper)(comedi_dev, context);
index 7dff3c01dc29ef3286d5559065a1c2c9e52819d5..a8e2c4d62840e2045a4317a216830f31a97a7ae1 100644 (file)
@@ -227,18 +227,16 @@ static int pci_8255_attach_pci(struct comedi_device *dev,
        int ret;
        int i;
 
-       comedi_set_hw_dev(dev, &pcidev->dev);
-
        board = pci_8255_find_boardinfo(dev, pcidev);
        if (!board)
                return -ENODEV;
        dev->board_ptr = board;
        dev->board_name = board->name;
 
-       ret = alloc_private(dev, sizeof(*devpriv));
-       if (ret < 0)
-               return ret;
-       devpriv = dev->private;
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
+               return -ENOMEM;
+       dev->private = devpriv;
 
        ret = comedi_pci_enable(pcidev, dev->board_name);
        if (ret)
@@ -289,6 +287,8 @@ static void pci_8255_detach(struct comedi_device *dev)
        struct comedi_subdevice *s;
        int i;
 
+       if (!board || !devpriv)
+               return;
        if (dev->subdevices) {
                for (i = 0; i < board->n_8255; i++) {
                        s = &dev->subdevices[i];
index b59f2d484fd99ecb3c1e7b93053d99bf8cf1ef87..8656d0ef2c8df56a83449a892a9575d86bd3c034 100644 (file)
@@ -222,7 +222,7 @@ int i_InsnConfig_InitTimer(struct comedi_device *dev,struct comedi_subdevice *s,
 int i_APCI1710_InsnConfigInitTimer(struct comedi_device *dev, struct comedi_subdevice *s,
                                   struct comedi_insn *insn, unsigned int *data)
 {
-
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
        unsigned char b_ModulNbr;
        unsigned char b_TimerNbr;
@@ -452,6 +452,7 @@ int i_APCI1710_InsnWriteEnableDisableTimer(struct comedi_device *dev,
                                           struct comedi_subdevice *s,
                                           struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
        unsigned int dw_DummyRead;
        unsigned char b_ModulNbr;
@@ -593,6 +594,7 @@ int i_APCI1710_InsnReadAllTimerValue(struct comedi_device *dev,struct comedi_sub
 int i_APCI1710_InsnReadAllTimerValue(struct comedi_device *dev, struct comedi_subdevice *s,
                                     struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
        unsigned char b_ModulNbr, b_ReadType;
        unsigned int *pul_TimerValueArray;
@@ -764,6 +766,7 @@ int i_APCI1710_ReadTimerValue(struct comedi_device *dev,
                              unsigned char b_ModulNbr, unsigned char b_TimerNbr,
                              unsigned int *pul_TimerValue)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
 
        /* Test the module number */
@@ -852,6 +855,7 @@ int i_APCI1710_GetTimerOutputLevel(struct comedi_device *dev,
                                   unsigned char b_ModulNbr, unsigned char b_TimerNbr,
                                   unsigned char *pb_OutputLevel)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
        unsigned int dw_TimerStatus;
 
@@ -931,6 +935,7 @@ int i_APCI1710_GetTimerProgressStatus(struct comedi_device *dev,
                                      unsigned char b_ModulNbr, unsigned char b_TimerNbr,
                                      unsigned char *pb_TimerStatus)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
        unsigned int dw_TimerStatus;
 
@@ -1010,6 +1015,7 @@ int i_APCI1710_WriteTimerValue(struct comedi_device *dev,
                               unsigned char b_ModulNbr, unsigned char b_TimerNbr,
                               unsigned int ul_WriteValue)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
 
        /* Test the module number */
index 482a412aa6524aa6bad2b3838ccfdd9922456ae8..a30fb0ddb749fd41f468a6583bc164c58549b844 100644 (file)
@@ -134,6 +134,7 @@ You should also find the complete GPL in the COPYING file accompanying this sour
 int i_APCI1710_InsnConfigInitChrono(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
        unsigned int ul_TimerValue = 0;
        unsigned int ul_TimingInterval = 0;
@@ -843,6 +844,7 @@ struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)                                              |
 int i_APCI1710_InsnWriteEnableDisableChrono(struct comedi_device *dev,
        struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
        unsigned char b_ModulNbr, b_CycleMode, b_InterruptEnable, b_Action;
        b_ModulNbr = CR_AREF(insn->chanspec);
@@ -1093,6 +1095,7 @@ struct comedi_insn *insn,unsigned int *data)                   |
 int i_APCI1710_InsnReadChrono(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned char b_ReadType;
        int i_ReturnValue = insn->n;
 
@@ -1197,6 +1200,7 @@ int i_APCI1710_InsnReadChrono(struct comedi_device *dev, struct comedi_subdevice
 int i_APCI1710_GetChronoProgressStatus(struct comedi_device *dev,
        unsigned char b_ModulNbr, unsigned char *pb_ChronoStatus)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
        unsigned int dw_Status;
 
@@ -1359,6 +1363,7 @@ int i_APCI1710_ReadChronoValue(struct comedi_device *dev,
        unsigned char b_ModulNbr,
        unsigned int ui_TimeOut, unsigned char *pb_ChronoStatus, unsigned int *pul_ChronoValue)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
        unsigned int dw_Status;
        unsigned int dw_TimeOut = 0;
@@ -1626,6 +1631,7 @@ int i_APCI1710_ConvertChronoValue(struct comedi_device *dev,
        unsigned char *pb_Second,
        unsigned int *pui_MilliSecond, unsigned int *pui_MicroSecond, unsigned int *pui_NanoSecond)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
        double d_Hour;
        double d_Minute;
@@ -1878,6 +1884,7 @@ int i_APCI1710_ConvertChronoValue(struct comedi_device *dev,
 int i_APCI1710_InsnBitsChronoDigitalIO(struct comedi_device *dev,
        struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
        unsigned char b_ModulNbr, b_OutputChannel, b_InputChannel, b_IOType;
        unsigned int dw_Status;
index 07108f9f4a4174c067770b73dc1ed8b12cf91d16..96ca3d26ae6089dd8630c18c83af1bad144a8d53 100644 (file)
@@ -102,6 +102,7 @@ Activates and deactivates the digital output memory.
 int i_APCI1710_InsnConfigDigitalIO(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned char b_ModulNbr, b_ChannelAMode, b_ChannelBMode;
        unsigned char b_MemoryOnOff, b_ConfigType;
        int i_ReturnValue = 0;
@@ -296,6 +297,7 @@ int i_APCI1710_InsnConfigDigitalIO(struct comedi_device *dev, struct comedi_subd
 int i_APCI1710_InsnReadDigitalIOChlValue(struct comedi_device *dev,
        struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
        unsigned int dw_StatusReg;
        unsigned char b_ModulNbr, b_InputChannel;
@@ -484,6 +486,7 @@ int i_APCI1710_InsnReadDigitalIOChlValue(struct comedi_device *dev,
 int i_APCI1710_InsnWriteDigitalIOChlOnOff(struct comedi_device *dev,
        struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
        unsigned int dw_WriteValue = 0;
        unsigned char b_ModulNbr, b_OutputChannel;
@@ -734,6 +737,7 @@ int i_APCI1710_InsnWriteDigitalIOChlOnOff(struct comedi_device *dev,
 int i_APCI1710_InsnBitsDigitalIOPortOnOff(struct comedi_device *dev,
        struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
        unsigned int dw_WriteValue = 0;
        unsigned int dw_StatusReg;
index 14b13eae4c5074b923854b0860050fccc5ef1c38..834685b1885f2f2cd26c7fc030b1894f26eab945 100644 (file)
@@ -78,8 +78,10 @@ struct comedi_insn *insn,unsigned int *data)
 int i_APCI1710_InsnConfigINCCPT(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned int ui_ConfigType;
        int i_ReturnValue = 0;
+
        ui_ConfigType = CR_CHAN(insn->chanspec);
 
        printk("\nINC_CPT");
@@ -306,6 +308,7 @@ int i_APCI1710_InitCounter(struct comedi_device *dev,
        unsigned char b_FirstCounterOption,
        unsigned char b_SecondCounterModus, unsigned char b_SecondCounterOption)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
 
        /*******************************/
@@ -547,6 +550,7 @@ int i_APCI1710_InitCounter(struct comedi_device *dev,
 
 int i_APCI1710_CounterAutoTest(struct comedi_device *dev, unsigned char *pb_TestStatus)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned char b_ModulCpt = 0;
        int i_ReturnValue = 0;
        unsigned int dw_LathchValue;
@@ -713,6 +717,7 @@ int i_APCI1710_InitIndex(struct comedi_device *dev,
        unsigned char b_ReferenceAction,
        unsigned char b_IndexOperation, unsigned char b_AutoMode, unsigned char b_InterruptEnable)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
 
        /**************************/
@@ -1155,6 +1160,7 @@ int i_APCI1710_InitIndex(struct comedi_device *dev,
 int i_APCI1710_InitReference(struct comedi_device *dev,
        unsigned char b_ModulNbr, unsigned char b_ReferenceLevel)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
 
        /**************************/
@@ -1280,6 +1286,7 @@ int i_APCI1710_InitReference(struct comedi_device *dev,
 int i_APCI1710_InitExternalStrobe(struct comedi_device *dev,
        unsigned char b_ModulNbr, unsigned char b_ExternalStrobe, unsigned char b_ExternalStrobeLevel)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
 
        /**************************/
@@ -1394,6 +1401,7 @@ int i_APCI1710_InitExternalStrobe(struct comedi_device *dev,
 int i_APCI1710_InitCompareLogic(struct comedi_device *dev,
        unsigned char b_ModulNbr, unsigned int ui_CompareValue)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
 
        /**************************/
@@ -1493,6 +1501,7 @@ int i_APCI1710_InitFrequencyMeasurement(struct comedi_device *dev,
        unsigned char b_TimingUnity,
        unsigned int ul_TimingInterval, unsigned int *pul_RealTimingInterval)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
        unsigned int ul_TimerValue = 0;
        double d_RealTimingInterval;
@@ -2018,8 +2027,10 @@ struct comedi_insn *insn,unsigned int *data)                   |
 int i_APCI1710_InsnBitsINCCPT(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned int ui_BitsType;
        int i_ReturnValue = 0;
+
        ui_BitsType = CR_CHAN(insn->chanspec);
        devpriv->tsk_Current = current; /*  Save the current process task structure */
 
@@ -2093,6 +2104,7 @@ int i_APCI1710_InsnBitsINCCPT(struct comedi_device *dev, struct comedi_subdevice
 
 int i_APCI1710_ClearCounterValue(struct comedi_device *dev, unsigned char b_ModulNbr)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
 
        /**************************/
@@ -2153,6 +2165,7 @@ int i_APCI1710_ClearCounterValue(struct comedi_device *dev, unsigned char b_Modu
 
 int i_APCI1710_ClearAllCounterValue(struct comedi_device *dev)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned char b_ModulCpt = 0;
        int i_ReturnValue = 0;
 
@@ -2300,6 +2313,7 @@ int i_APCI1710_ClearAllCounterValue(struct comedi_device *dev)
 int i_APCI1710_SetInputFilter(struct comedi_device *dev,
        unsigned char b_ModulNbr, unsigned char b_PCIInputClock, unsigned char b_Filter)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
        unsigned int dw_Status = 0;
 
@@ -2564,6 +2578,7 @@ int i_APCI1710_SetInputFilter(struct comedi_device *dev,
 int i_APCI1710_LatchCounter(struct comedi_device *dev,
        unsigned char b_ModulNbr, unsigned char b_LatchReg)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
 
        /**************************/
@@ -2661,6 +2676,7 @@ int i_APCI1710_LatchCounter(struct comedi_device *dev,
 int i_APCI1710_SetIndexAndReferenceSource(struct comedi_device *dev,
        unsigned char b_ModulNbr, unsigned char b_SourceSelection)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
 
        /**************************/
@@ -2797,6 +2813,7 @@ int i_APCI1710_SetIndexAndReferenceSource(struct comedi_device *dev,
 
 int i_APCI1710_SetDigitalChlOn(struct comedi_device *dev, unsigned char b_ModulNbr)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
 
        /**************************/
@@ -2877,6 +2894,7 @@ int i_APCI1710_SetDigitalChlOn(struct comedi_device *dev, unsigned char b_ModulN
 
 int i_APCI1710_SetDigitalChlOff(struct comedi_device *dev, unsigned char b_ModulNbr)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
 
        /**************************/
@@ -2954,6 +2972,7 @@ struct comedi_insn *insn,unsigned int *data)                   |
 int i_APCI1710_InsnWriteINCCPT(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned int ui_WriteType;
        int i_ReturnValue = 0;
 
@@ -3049,6 +3068,7 @@ int i_APCI1710_InsnWriteINCCPT(struct comedi_device *dev, struct comedi_subdevic
 
 int i_APCI1710_EnableLatchInterrupt(struct comedi_device *dev, unsigned char b_ModulNbr)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
 
        /**************************/
@@ -3135,6 +3155,7 @@ int i_APCI1710_EnableLatchInterrupt(struct comedi_device *dev, unsigned char b_M
 
 int i_APCI1710_DisableLatchInterrupt(struct comedi_device *dev, unsigned char b_ModulNbr)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
 
        /**************************/
@@ -3234,6 +3255,7 @@ int i_APCI1710_DisableLatchInterrupt(struct comedi_device *dev, unsigned char b_
 int i_APCI1710_Write16BitCounterValue(struct comedi_device *dev,
        unsigned char b_ModulNbr, unsigned char b_SelectedCounter, unsigned int ui_WriteValue)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
 
        /**************************/
@@ -3319,6 +3341,7 @@ int i_APCI1710_Write16BitCounterValue(struct comedi_device *dev,
 int i_APCI1710_Write32BitCounterValue(struct comedi_device *dev,
        unsigned char b_ModulNbr, unsigned int ul_WriteValue)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
 
        /**************************/
@@ -3385,6 +3408,7 @@ int i_APCI1710_Write32BitCounterValue(struct comedi_device *dev,
 
 int i_APCI1710_EnableIndex(struct comedi_device *dev, unsigned char b_ModulNbr)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
        unsigned int ul_InterruptLatchReg;
 
@@ -3483,6 +3507,7 @@ int i_APCI1710_EnableIndex(struct comedi_device *dev, unsigned char b_ModulNbr)
 
 int i_APCI1710_DisableIndex(struct comedi_device *dev, unsigned char b_ModulNbr)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
 
        /**************************/
@@ -3582,6 +3607,7 @@ int i_APCI1710_DisableIndex(struct comedi_device *dev, unsigned char b_ModulNbr)
 
 int i_APCI1710_EnableCompareLogic(struct comedi_device *dev, unsigned char b_ModulNbr)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
 
        /**************************/
@@ -3682,6 +3708,7 @@ int i_APCI1710_EnableCompareLogic(struct comedi_device *dev, unsigned char b_Mod
 
 int i_APCI1710_DisableCompareLogic(struct comedi_device *dev, unsigned char b_ModulNbr)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
 
        /**************************/
@@ -3792,6 +3819,7 @@ int i_APCI1710_DisableCompareLogic(struct comedi_device *dev, unsigned char b_Mo
 int i_APCI1710_EnableFrequencyMeasurement(struct comedi_device *dev,
        unsigned char b_ModulNbr, unsigned char b_InterruptEnable)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
 
        /**************************/
@@ -3938,6 +3966,7 @@ int i_APCI1710_EnableFrequencyMeasurement(struct comedi_device *dev,
 
 int i_APCI1710_DisableFrequencyMeasurement(struct comedi_device *dev, unsigned char b_ModulNbr)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
 
        /**************************/
@@ -4052,6 +4081,7 @@ struct comedi_insn *insn,unsigned int *data)                   |
 int i_APCI1710_InsnReadINCCPT(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned int ui_ReadType;
        int i_ReturnValue = 0;
 
@@ -4196,6 +4226,7 @@ int i_APCI1710_InsnReadINCCPT(struct comedi_device *dev, struct comedi_subdevice
 int i_APCI1710_ReadLatchRegisterStatus(struct comedi_device *dev,
        unsigned char b_ModulNbr, unsigned char b_LatchReg, unsigned char *pb_LatchStatus)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
        unsigned int dw_LatchReg;
 
@@ -4283,6 +4314,7 @@ int i_APCI1710_ReadLatchRegisterStatus(struct comedi_device *dev,
 int i_APCI1710_ReadLatchRegisterValue(struct comedi_device *dev,
        unsigned char b_ModulNbr, unsigned char b_LatchReg, unsigned int *pul_LatchValue)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
 
        /**************************/
@@ -4367,6 +4399,7 @@ int i_APCI1710_ReadLatchRegisterValue(struct comedi_device *dev,
 int i_APCI1710_Read16BitCounterValue(struct comedi_device *dev,
        unsigned char b_ModulNbr, unsigned char b_SelectedCounter, unsigned int *pui_CounterValue)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
        unsigned int dw_LathchValue = 0;
 
@@ -4462,6 +4495,7 @@ int i_APCI1710_Read16BitCounterValue(struct comedi_device *dev,
 int i_APCI1710_Read32BitCounterValue(struct comedi_device *dev,
        unsigned char b_ModulNbr, unsigned int *pul_CounterValue)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
 
        /**************************/
@@ -4538,6 +4572,7 @@ int i_APCI1710_Read32BitCounterValue(struct comedi_device *dev,
 int i_APCI1710_GetIndexStatus(struct comedi_device *dev,
        unsigned char b_ModulNbr, unsigned char *pb_IndexStatus)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
        unsigned int dw_StatusReg = 0;
 
@@ -4622,6 +4657,7 @@ int i_APCI1710_GetIndexStatus(struct comedi_device *dev,
 int i_APCI1710_GetReferenceStatus(struct comedi_device *dev,
        unsigned char b_ModulNbr, unsigned char *pb_ReferenceStatus)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
        unsigned int dw_StatusReg = 0;
 
@@ -4706,6 +4742,7 @@ int i_APCI1710_GetReferenceStatus(struct comedi_device *dev,
 int i_APCI1710_GetUASStatus(struct comedi_device *dev,
        unsigned char b_ModulNbr, unsigned char *pb_UASStatus)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
        unsigned int dw_StatusReg = 0;
 
@@ -4774,6 +4811,7 @@ int i_APCI1710_GetUASStatus(struct comedi_device *dev,
 int i_APCI1710_GetCBStatus(struct comedi_device *dev,
        unsigned char b_ModulNbr, unsigned char *pb_CBStatus)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
        unsigned int dw_StatusReg = 0;
 
@@ -4856,6 +4894,7 @@ int i_APCI1710_GetCBStatus(struct comedi_device *dev,
 int i_APCI1710_Get16BitCBStatus(struct comedi_device *dev,
        unsigned char b_ModulNbr, unsigned char *pb_CBStatusCounter0, unsigned char *pb_CBStatusCounter1)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
        unsigned int dw_StatusReg = 0;
 
@@ -4969,6 +5008,7 @@ int i_APCI1710_Get16BitCBStatus(struct comedi_device *dev,
 int i_APCI1710_GetUDStatus(struct comedi_device *dev,
        unsigned char b_ModulNbr, unsigned char *pb_UDStatus)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
        unsigned int dw_StatusReg = 0;
 
@@ -5043,6 +5083,7 @@ int i_APCI1710_GetUDStatus(struct comedi_device *dev,
 int i_APCI1710_GetInterruptUDLatchedStatus(struct comedi_device *dev,
        unsigned char b_ModulNbr, unsigned char *pb_UDStatus)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
        unsigned int dw_StatusReg = 0;
 
@@ -5149,6 +5190,7 @@ int i_APCI1710_ReadFrequencyMeasurement(struct comedi_device *dev,
        unsigned char b_ModulNbr,
        unsigned char *pb_Status, unsigned char *pb_UDStatus, unsigned int *pul_ReadValue)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
        unsigned int ui_16BitValue;
        unsigned int dw_StatusReg;
index 3f9cfa20d8862a8050723b57e51a41e73de7cca8..3aa80090a07a3c84bafb5194f36aebfb3229978a 100644 (file)
@@ -126,9 +126,9 @@ You should also find the complete GPL in the COPYING file accompanying this sour
 int i_APCI1710_InsnConfigInitPulseEncoder(struct comedi_device *dev,
        struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
        unsigned int dw_IntRegister;
-
        unsigned char b_ModulNbr;
        unsigned char b_PulseEncoderNbr;
        unsigned char b_InputLevelSelection;
@@ -417,6 +417,7 @@ int i_APCI1710_InsnConfigInitPulseEncoder(struct comedi_device *dev,
 int i_APCI1710_InsnWriteEnableDisablePulseEncoder(struct comedi_device *dev,
        struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
        unsigned char b_ModulNbr;
        unsigned char b_PulseEncoderNbr;
@@ -711,6 +712,7 @@ int i_APCI1710_InsnWriteEnableDisablePulseEncoder(struct comedi_device *dev,
 int i_APCI1710_InsnBitsReadWritePulseEncoder(struct comedi_device *dev,
        struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
        unsigned int dw_StatusRegister;
        unsigned char b_ModulNbr;
@@ -837,6 +839,7 @@ int i_APCI1710_InsnBitsReadWritePulseEncoder(struct comedi_device *dev,
 int i_APCI1710_InsnReadInterruptPulseEncoder(struct comedi_device *dev,
        struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
 
        data[0] = devpriv->s_InterruptParameters.
                s_FIFOInterruptParameters[devpriv->
index 8883e66621158bb3b73a7e058c9a681e1263783f..9a01ea05b40efb89a8c26b938d5667e7ce6550af 100644 (file)
@@ -188,6 +188,7 @@ int i_APCI1710_InitPWM(struct comedi_device *dev,
        unsigned int ul_HighTiming,
        unsigned int *pul_RealLowTiming, unsigned int *pul_RealHighTiming)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
        unsigned int ul_LowTimerValue = 0;
        unsigned int ul_HighTimerValue = 0;
@@ -1545,6 +1546,7 @@ int i_APCI1710_GetPWMInitialisation(struct comedi_device *dev,
        unsigned char *pb_StopLevel,
        unsigned char *pb_ExternGate, unsigned char *pb_InterruptEnable, unsigned char *pb_Enable)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
        unsigned int dw_Status;
        unsigned int dw_Command;
@@ -1813,6 +1815,7 @@ int i_APCI1710_EnablePWM(struct comedi_device *dev,
        unsigned char b_StopMode,
        unsigned char b_StopLevel, unsigned char b_ExternGate, unsigned char b_InterruptEnable)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
        unsigned int dw_Status;
        unsigned int dw_Command;
@@ -2064,6 +2067,7 @@ int i_APCI1710_EnablePWM(struct comedi_device *dev,
 
 int i_APCI1710_DisablePWM(struct comedi_device *dev, unsigned char b_ModulNbr, unsigned char b_PWM)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
        unsigned int dw_Status;
 
@@ -2193,6 +2197,7 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device *dev,
        unsigned char b_ModulNbr,
        unsigned char b_PWM, unsigned char b_TimingUnit, unsigned int ul_LowTiming, unsigned int ul_HighTiming)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned char b_ClockSelection;
        int i_ReturnValue = 0;
        unsigned int ul_LowTimerValue = 0;
@@ -3463,9 +3468,9 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device *dev,
 int i_APCI1710_InsnReadGetPWMStatus(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
        unsigned int dw_Status;
-
        unsigned char b_ModulNbr;
        unsigned char b_PWM;
        unsigned char *pb_PWMOutputStatus;
@@ -3564,6 +3569,8 @@ int i_APCI1710_InsnReadGetPWMStatus(struct comedi_device *dev, struct comedi_sub
 int i_APCI1710_InsnBitsReadPWMInterrupt(struct comedi_device *dev,
        struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
+
        data[0] = devpriv->s_InterruptParameters.
                s_FIFOInterruptParameters[devpriv->
                s_InterruptParameters.ui_Read].b_OldModuleMask;
index c13b00274923bf55ea09a4c52fe63a1a7e30f09d..298ea485da9a61ecceb56b19975c0fa9e48303fb 100644 (file)
@@ -122,6 +122,7 @@ You should also find the complete GPL in the COPYING file accompanying this sour
 int i_APCI1710_InsnConfigInitSSI(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
        unsigned int ui_TimerValue;
        unsigned char b_ModulNbr, b_SSIProfile, b_PositionTurnLength, b_TurnCptLength,
@@ -389,6 +390,7 @@ pul_Position        =       (unsigned int *) &data[0];
 int i_APCI1710_InsnReadSSIValue(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
        unsigned char b_Cpt;
        unsigned char b_Length;
@@ -722,6 +724,7 @@ int i_APCI1710_InsnReadSSIValue(struct comedi_device *dev, struct comedi_subdevi
 int i_APCI1710_InsnBitsSSIDigitalIO(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
        unsigned int dw_StatusReg;
        unsigned char b_ModulNbr;
@@ -729,6 +732,7 @@ int i_APCI1710_InsnBitsSSIDigitalIO(struct comedi_device *dev, struct comedi_sub
        unsigned char *pb_ChannelStatus;
        unsigned char *pb_InputStatus;
        unsigned char b_IOType;
+
        i_ReturnValue = insn->n;
        b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
        b_IOType = (unsigned char) data[0];
index 0e6affd95962379534b8ba54d1667b59335385fa..28322fbfc1d664128af7b2eab70fe1e91f1694f2 100644 (file)
@@ -133,6 +133,7 @@ You should also find the complete GPL in the COPYING file accompanying this sour
 int i_APCI1710_InsnConfigInitTorCounter(struct comedi_device *dev,
        struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
        unsigned int ul_TimerValue = 0;
        unsigned int dw_Command;
@@ -990,6 +991,7 @@ int i_APCI1710_InsnConfigInitTorCounter(struct comedi_device *dev,
 int i_APCI1710_InsnWriteEnableDisableTorCounter(struct comedi_device *dev,
        struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
        unsigned int dw_Status;
        unsigned int dw_DummyRead;
@@ -1463,6 +1465,7 @@ int i_APCI1710_InsnWriteEnableDisableTorCounter(struct comedi_device *dev,
 int i_APCI1710_InsnReadGetTorCounterInitialisation(struct comedi_device *dev,
        struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
        unsigned int dw_Status;
        unsigned char b_ModulNbr;
@@ -1703,10 +1706,10 @@ int i_APCI1710_InsnReadGetTorCounterInitialisation(struct comedi_device *dev,
 int i_APCI1710_InsnBitsGetTorCounterProgressStatusAndValue(struct comedi_device *dev,
        struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
        unsigned int dw_Status;
        unsigned int dw_TimeOut = 0;
-
        unsigned char b_ModulNbr;
        unsigned char b_TorCounter;
        unsigned char b_ReadType;
index 9e177f4af861fe67cc7a769f666d99b79086e523..4f71a4ce3fbc9093422cbf0fa61ae02a874e2b14 100644 (file)
@@ -103,6 +103,7 @@ You should also find the complete GPL in the COPYING file accompanying this sour
 int i_APCI1710_InsnConfigInitTTLIO(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
        unsigned char b_ModulNbr;
        unsigned char b_InitType;
@@ -409,6 +410,7 @@ APCI1710_TTL_READCHANNEL
 int i_APCI1710_InsnBitsReadTTLIO(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
        unsigned int dw_StatusReg;
        unsigned char b_ModulNbr;
@@ -658,6 +660,7 @@ int i_APCI1710_InsnBitsReadTTLIO(struct comedi_device *dev, struct comedi_subdev
 int i_APCI1710_InsnReadTTLIOAllPortValue(struct comedi_device *dev,
        struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
        unsigned int dw_StatusReg;
        unsigned char b_ModulNbr;
@@ -828,6 +831,7 @@ int i_APCI1710_InsnWriteSetTTLIOChlOnOff(struct comedi_device *dev,struct comedi
 int i_APCI1710_InsnWriteSetTTLIOChlOnOff(struct comedi_device *dev,
        struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = 0;
        unsigned int dw_StatusReg = 0;
        unsigned char b_ModulNbr;
index 99a96bd96716b960e0d7732c226eba315e6a6e49..10ae752f21c8117f49c0c8b0426e0d21d868e618 100644 (file)
@@ -76,7 +76,6 @@ You should also find the complete GPL in the COPYING file accompanying this sour
 /* Update-0.7.57->0.7.68MODULE_DESCRIPTION("Comedi ADDI-DATA module"); */
 /* Update-0.7.57->0.7.68MODULE_LICENSE("GPL"); */
 
-#define devpriv ((struct addi_private *)dev->private)
 #define this_board ((const struct addi_board *)dev->board_ptr)
 
 #if defined(CONFIG_APCI_1710) || defined(CONFIG_APCI_3200) || defined(CONFIG_APCI_3300)
@@ -1472,6 +1471,7 @@ module_exit(driver_addi_cleanup_module);
 
 static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
+       struct addi_private *devpriv;
        struct comedi_subdevice *s;
        int ret, pages, i, n_subdevices;
        unsigned int dw_Dummy;
@@ -1482,9 +1482,10 @@ static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it)
        unsigned char pci_bus, pci_slot, pci_func;
        int i_Dma = 0;
 
-       ret = alloc_private(dev, sizeof(struct addi_private));
-       if (ret < 0)
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
                return -ENOMEM;
+       dev->private = devpriv;
 
        if (!pci_list_builded) {
                v_pci_card_list_init(this_board->i_VendorId, 1);        /* 1 for displaying the list.. */
@@ -1817,7 +1818,9 @@ static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it)
 
 static void i_ADDI_Detach(struct comedi_device *dev)
 {
-       if (dev->private) {
+       struct addi_private *devpriv = dev->private;
+
+       if (devpriv) {
                if (devpriv->b_ValidDriver)
                        i_ADDI_Reset(dev);
                if (dev->irq)
@@ -1923,6 +1926,7 @@ static irqreturn_t v_ADDI_Interrupt(int irq, void *d)
 static int i_ADDIDATA_InsnReadEeprom(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned short w_Data;
        unsigned short w_Address;
        w_Address = CR_CHAN(insn->chanspec);    /*  address to be read as 0,1,2,3...255 */
index 3a9339b926101fc83f4fffaf6bf15438c3327594..0883fe0a930bc0a4879275982646f726e44d28aa 100644 (file)
@@ -805,6 +805,7 @@ void v_EepromCs76Read(unsigned int dw_Address, unsigned short w_offset, unsigned
 int i_EepromReadMainHeader(unsigned short w_PCIBoardEepromAddress,
        char *pc_PCIChipInformation, struct comedi_device *dev)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned short w_Temp, i, w_Count = 0;
        unsigned int ui_Temp;
        struct str_MainHeader s_MainHeader;
index f9a8937be8ed160a2051b3f1d8cfd6940b824c4e..057ef4eb8db7e76cf981808accc5ceabbc1813c7 100644 (file)
@@ -201,6 +201,7 @@ void v_APCI1710_Interrupt(int irq, void *d);
 
 int i_APCI1710_Reset(struct comedi_device *dev)
 {
+       struct addi_private *devpriv = dev->private;
        int ret;
        unsigned int dw_Dummy;
 
@@ -250,6 +251,7 @@ int i_APCI1710_Reset(struct comedi_device *dev)
 void v_APCI1710_Interrupt(int irq, void *d)
 {
        struct comedi_device *dev = d;
+       struct addi_private *devpriv = dev->private;
        unsigned char b_ModuleCpt = 0;
        unsigned char b_InterruptFlag = 0;
        unsigned char b_PWMCpt = 0;
index 5997b2f504ad34f9e5238c62f2796db06ea3d8dd..0fde7a39302339a04b860a7a402390edf25da1d6 100644 (file)
@@ -112,9 +112,11 @@ static int i_Flag = 1;
 int i_APCI035_ConfigTimerWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned int ui_Status = 0;
        unsigned int ui_Command = 0;
        unsigned int ui_Mode = 0;
+
        i_Temp = 0;
        devpriv->tsk_Current = current;
        devpriv->b_TimerSelectMode = data[0];
@@ -281,8 +283,10 @@ int i_APCI035_ConfigTimerWatchdog(struct comedi_device *dev, struct comedi_subde
 int i_APCI035_StartStopWriteTimerWatchdog(struct comedi_device *dev,
        struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned int ui_Command = 0;
        int i_Count = 0;
+
        if (data[0] == 1) {
                ui_Command =
                        inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
@@ -396,7 +400,9 @@ int i_APCI035_StartStopWriteTimerWatchdog(struct comedi_device *dev,
 int i_APCI035_ReadTimerWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned int ui_Status = 0;     /*  Status register */
+
        i_WatchdogNbr = insn->unused[0];
 
        /******************/
@@ -456,6 +462,8 @@ int i_APCI035_ReadTimerWatchdog(struct comedi_device *dev, struct comedi_subdevi
 int i_APCI035_ConfigAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
+
        devpriv->tsk_Current = current;
        outl(0x200 | 0, devpriv->iobase + 128 + 0x4);
        outl(0, devpriv->iobase + 128 + 0);
@@ -493,7 +501,9 @@ int i_APCI035_ConfigAnalogInput(struct comedi_device *dev, struct comedi_subdevi
 int i_APCI035_ReadAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned int ui_CommandRegister = 0;
+
 /******************/
 /*  Set the start */
 /******************/
@@ -527,7 +537,9 @@ int i_APCI035_ReadAnalogInput(struct comedi_device *dev, struct comedi_subdevice
 */
 int i_APCI035_Reset(struct comedi_device *dev)
 {
+       struct addi_private *devpriv = dev->private;
        int i_Count = 0;
+
        for (i_Count = 1; i_Count <= 4; i_Count++) {
                i_WatchdogNbr = i_Count;
                outl(0x0, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 0);    /* stop all timers */
@@ -557,11 +569,13 @@ int i_APCI035_Reset(struct comedi_device *dev)
 static void v_APCI035_Interrupt(int irq, void *d)
 {
        struct comedi_device *dev = d;
+       struct addi_private *devpriv = dev->private;
        unsigned int ui_StatusRegister1 = 0;
        unsigned int ui_StatusRegister2 = 0;
        unsigned int ui_ReadCommand = 0;
        unsigned int ui_ChannelNumber = 0;
        unsigned int ui_DigitalTemperature = 0;
+
        if (i_Temp == 1) {
                i_WatchdogNbr = i_Flag;
                i_Flag = i_Flag + 1;
index bab7b61a53bcb4a6bfe018d4d13fa7cc252837f4..b209cfa0374e2a212f97888485e81c1a89fbfdc0 100644 (file)
@@ -87,10 +87,11 @@ static unsigned int ui_InterruptStatus;
 int i_APCI1032_ConfigDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned int ui_TmpValue;
-
        unsigned int ul_Command1 = 0;
        unsigned int ul_Command2 = 0;
+
        devpriv->tsk_Current = current;
 
   /*******************************/
@@ -147,9 +148,11 @@ int i_APCI1032_ConfigDigitalInput(struct comedi_device *dev, struct comedi_subde
 int i_APCI1032_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned int ui_TmpValue = 0;
        unsigned int ui_Channel;
        ui_Channel = CR_CHAN(insn->chanspec);
+
        if (ui_Channel <= 31) {
                ui_TmpValue = (unsigned int) inl(devpriv->iobase + APCI1032_DIGITAL_IP);
 /*
@@ -188,6 +191,7 @@ int i_APCI1032_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdev
 int i_APCI1032_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned int ui_PortValue = data[0];
        unsigned int ui_Mask = 0;
        unsigned int ui_NoOfChannels;
@@ -248,8 +252,9 @@ int i_APCI1032_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_sub
 static void v_APCI1032_Interrupt(int irq, void *d)
 {
        struct comedi_device *dev = d;
-
+       struct addi_private *devpriv = dev->private;
        unsigned int ui_Temp;
+
        /* disable the interrupt */
        ui_Temp = inl(devpriv->iobase + APCI1032_DIGITAL_IP_IRQ);
        outl(ui_Temp & APCI1032_DIGITAL_IP_INTERRUPT_DISABLE,
@@ -279,6 +284,8 @@ static void v_APCI1032_Interrupt(int irq, void *d)
 
 int i_APCI1032_Reset(struct comedi_device *dev)
 {
+       struct addi_private *devpriv = dev->private;
+
        outl(0x0, devpriv->iobase + APCI1032_DIGITAL_IP_IRQ);   /* disable the interrupts */
        inl(devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_STATUS);    /* Reset the interrupt status register */
        outl(0x0, devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_MODE1);       /* Disable the and/or interrupt */
index 62f421a06f0517dbc988cbd689689563c3c51b03..cc47821a7457b64c6200a0bdf2016ef976dcec40 100644 (file)
@@ -141,6 +141,7 @@ static int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device *dev,
                                              struct comedi_insn *insn,
                                              unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        int i_PatternPolarity = 0, i_PatternTransition = 0, i_PatternMask = 0;
        int i_MaxChannel = 0, i_Count = 0, i_EventMask = 0;
        int i_PatternTransitionCount = 0, i_RegValue;
@@ -525,8 +526,10 @@ static int i_APCI1500_StartStopInputEvent(struct comedi_device *dev,
                                          struct comedi_insn *insn,
                                          unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        int i_Event1InterruptStatus = 0, i_Event2InterruptStatus =
                0, i_RegValue;
+
        switch (data[0]) {
        case START:
              /*************************/
@@ -792,7 +795,9 @@ static int i_APCI1500_Initialisation(struct comedi_device *dev,
                                     struct comedi_insn *insn,
                                     unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        int i_DummyRead = 0;
+
     /******************/
        /* Software reset */
     /******************/
@@ -966,6 +971,7 @@ static int i_APCI1500_ReadMoreDigitalInput(struct comedi_device *dev,
                                           struct comedi_insn *insn,
                                           unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned int ui_PortValue = data[1];
        unsigned int ui_Mask = 0;
        unsigned int ui_Channel;
@@ -1051,6 +1057,8 @@ static int i_APCI1500_ConfigDigitalOutputErrorInterrupt(struct comedi_device *de
                                                        struct comedi_insn *insn,
                                                        unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
+
        devpriv->b_OutputMemoryStatus = data[0];
        return insn->n;
 }
@@ -1079,9 +1087,9 @@ static int i_APCI1500_WriteDigitalOutput(struct comedi_device *dev,
                                         struct comedi_insn *insn,
                                         unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        static unsigned int ui_Temp = 0;
        unsigned int ui_Temp1;
-
        unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec);  /*  get the channel */
 
        if (!devpriv->b_OutputMemoryStatus) {
@@ -1274,6 +1282,7 @@ static int i_APCI1500_ConfigCounterTimerWatchdog(struct comedi_device *dev,
                                                 struct comedi_insn *insn,
                                                 unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        int i_TimerCounterMode, i_MasterConfiguration;
 
        devpriv->tsk_Current = current;
@@ -1875,6 +1884,7 @@ static int i_APCI1500_StartStopTriggerTimerCounterWatchdog(struct comedi_device
                                                           struct comedi_insn *insn,
                                                           unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        int i_CommandAndStatusValue;
 
        switch (data[0]) {
@@ -2198,7 +2208,9 @@ static int i_APCI1500_ReadCounterTimerWatchdog(struct comedi_device *dev,
                                               struct comedi_insn *insn,
                                               unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        int i_CommandAndStatusValue;
+
        switch (data[0]) {
        case COUNTER1:
                /* Read counter/timer1 */
@@ -2421,9 +2433,11 @@ static int i_APCI1500_ConfigureInterrupt(struct comedi_device *dev,
                                         struct comedi_insn *insn,
                                         unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned int ui_Status;
        int i_RegValue;
        int i_Constant;
+
        devpriv->tsk_Current = current;
        outl(0x0, devpriv->i_IobaseAmcc + 0x38);
        if (data[0] == 1) {
@@ -2597,6 +2611,7 @@ static void v_APCI1500_Interrupt(int irq, void *d)
 {
 
        struct comedi_device *dev = d;
+       struct addi_private *devpriv = dev->private;
        unsigned int ui_InterruptStatus = 0;
        int i_RegValue = 0;
        i_InterruptMask = 0;
@@ -2840,7 +2855,9 @@ static void v_APCI1500_Interrupt(int irq, void *d)
 */
 static int i_APCI1500_Reset(struct comedi_device *dev)
 {
+       struct addi_private *devpriv = dev->private;
        int i_DummyRead = 0;
+
        i_TimerCounter1Init = 0;
        i_TimerCounter2Init = 0;
        i_WatchdogCounter3Init = 0;
index 8a584a014b0b8d51b1ae5148e1fbc7cdda9ee1cf..04a87453818ca6edf9c17201e7c21521083967e8 100644 (file)
@@ -76,8 +76,10 @@ You should also find the complete GPL in the COPYING file accompanying this sour
 int i_APCI1516_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned int ui_TmpValue = 0;
        unsigned int ui_Channel;
+
        ui_Channel = CR_CHAN(insn->chanspec);
        if (ui_Channel <= 7) {
                ui_TmpValue = (unsigned int) inw(devpriv->iobase + APCI1516_DIGITAL_IP);
@@ -117,7 +119,7 @@ int i_APCI1516_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdev
 int i_APCI1516_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
-
+       struct addi_private *devpriv = dev->private;
        unsigned int ui_PortValue = data[0];
        unsigned int ui_Mask = 0;
        unsigned int ui_NoOfChannels;
@@ -174,6 +176,8 @@ int i_APCI1516_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_sub
 int i_APCI1516_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
+
        devpriv->b_OutputMemoryStatus = data[0];
        return insn->n;
 }
@@ -202,6 +206,7 @@ int i_APCI1516_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subd
 int i_APCI1516_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned int ui_Temp, ui_Temp1;
        unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec);  /*  get the channel */
 
@@ -363,8 +368,10 @@ int i_APCI1516_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdev
        struct comedi_insn *insn, unsigned int *data)
 {
 
+       struct addi_private *devpriv = dev->private;
        unsigned int ui_Temp;
        unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec);  /*  get the channel */
+
        ui_Temp = data[0];
        *data = inw(devpriv->iobase + APCI1516_DIGITAL_OP_RW);
        if (ui_Temp == 0) {
@@ -422,6 +429,8 @@ int i_APCI1516_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdev
 int i_APCI1516_ConfigWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
+
        if (data[0] == 0) {
                /* Disable the watchdog */
                outw(0x0,
@@ -468,6 +477,8 @@ int i_APCI1516_ConfigWatchdog(struct comedi_device *dev, struct comedi_subdevice
 int i_APCI1516_StartStopWriteWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
+
        switch (data[0]) {
        case 0:         /* stop the watchdog */
                outw(0x0, devpriv->i_IobaseAddon + APCI1516_WATCHDOG_ENABLEDISABLE);    /* disable the watchdog */
@@ -513,6 +524,8 @@ int i_APCI1516_StartStopWriteWatchdog(struct comedi_device *dev, struct comedi_s
 int i_APCI1516_ReadWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
+
        data[0] = inw(devpriv->i_IobaseAddon + APCI1516_WATCHDOG_STATUS) & 0x1;
        return insn->n;
 }
@@ -534,6 +547,8 @@ int i_APCI1516_ReadWatchdog(struct comedi_device *dev, struct comedi_subdevice *
 
 int i_APCI1516_Reset(struct comedi_device *dev)
 {
+       struct addi_private *devpriv = dev->private;
+
        outw(0x0, devpriv->iobase + APCI1516_DIGITAL_OP);       /* RESETS THE DIGITAL OUTPUTS */
        outw(0x0, devpriv->i_IobaseAddon + APCI1516_WATCHDOG_ENABLEDISABLE);
        outw(0x0, devpriv->i_IobaseAddon + APCI1516_WATCHDOG_RELOAD_VALUE);
index 5b92e45c9ae34560784d2fd7a64220d8648b22b5..393d6d198024d433e61481124a03ca0cf5ee1f63 100644 (file)
@@ -89,6 +89,8 @@ static unsigned int ui_InterruptData, ui_Type;
 int i_APCI1564_ConfigDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
+
        devpriv->tsk_Current = current;
    /*******************************/
        /* Set the digital input logic */
@@ -150,6 +152,7 @@ int i_APCI1564_ConfigDigitalInput(struct comedi_device *dev, struct comedi_subde
 int i_APCI1564_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned int ui_TmpValue = 0;
        unsigned int ui_Channel;
 
@@ -192,6 +195,7 @@ int i_APCI1564_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdev
 int i_APCI1564_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned int ui_PortValue = data[0];
        unsigned int ui_Mask = 0;
        unsigned int ui_NoOfChannels;
@@ -260,6 +264,7 @@ int i_APCI1564_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_sub
 int i_APCI1564_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned int ul_Command = 0;
 
        if ((data[0] != 0) && (data[0] != 1)) {
@@ -317,6 +322,7 @@ int i_APCI1564_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subd
 int i_APCI1564_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned int ui_Temp, ui_Temp1;
        unsigned int ui_NoOfChannel;
 
@@ -491,6 +497,7 @@ int i_APCI1564_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subde
 int i_APCI1564_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned int ui_Temp;
        unsigned int ui_NoOfChannel;
 
@@ -569,7 +576,9 @@ int i_APCI1564_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdev
 int i_APCI1564_ConfigTimerCounterWatchdog(struct comedi_device *dev,
        struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned int ul_Command1 = 0;
+
        devpriv->tsk_Current = current;
        if (data[0] == ADDIDATA_WATCHDOG) {
                devpriv->b_TimerSelectMode = ADDIDATA_WATCHDOG;
@@ -723,7 +732,9 @@ int i_APCI1564_ConfigTimerCounterWatchdog(struct comedi_device *dev,
 int i_APCI1564_StartStopWriteTimerCounterWatchdog(struct comedi_device *dev,
        struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned int ul_Command1 = 0;
+
        if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
                switch (data[1]) {
                case 0: /* stop the watchdog */
@@ -818,6 +829,7 @@ int i_APCI1564_StartStopWriteTimerCounterWatchdog(struct comedi_device *dev,
 int i_APCI1564_ReadTimerCounterWatchdog(struct comedi_device *dev,
        struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned int ul_Command1 = 0;
 
        if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
@@ -921,10 +933,12 @@ int i_APCI1564_ReadInterruptStatus(struct comedi_device *dev, struct comedi_subd
 static void v_APCI1564_Interrupt(int irq, void *d)
 {
        struct comedi_device *dev = d;
+       struct addi_private *devpriv = dev->private;
        unsigned int ui_DO, ui_DI;
        unsigned int ui_Timer;
        unsigned int ui_C1, ui_C2, ui_C3, ui_C4;
        unsigned int ul_Command2 = 0;
+
        ui_DI = inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
                APCI1564_DIGITAL_IP_IRQ) & 0x01;
        ui_DO = inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
@@ -1106,6 +1120,8 @@ static void v_APCI1564_Interrupt(int irq, void *d)
 
 int i_APCI1564_Reset(struct comedi_device *dev)
 {
+       struct addi_private *devpriv = dev->private;
+
        outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP_IRQ);     /* disable the interrupts */
        inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP_INTERRUPT_STATUS);      /* Reset the interrupt status register */
        outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP_INTERRUPT_MODE1); /* Disable the and/or interrupt */
index 00a088f820a737ec7c58972b67676bb15a744d38..859c593f95a2e5c6d06ee2eadc7e309f60716715 100644 (file)
@@ -93,6 +93,7 @@ You should also find the complete GPL in the COPYING file accompanying this sour
 int i_APCI16XX_InsnConfigInitTTLIO(struct comedi_device *dev,
        struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = insn->n;
        unsigned char b_Command = 0;
        unsigned char b_Cpt = 0;
@@ -286,6 +287,7 @@ int i_APCI16XX_InsnConfigInitTTLIO(struct comedi_device *dev,
 int i_APCI16XX_InsnBitsReadTTLIO(struct comedi_device *dev,
        struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = insn->n;
        unsigned char b_Command = 0;
        unsigned char b_NumberOfPort =
@@ -433,6 +435,7 @@ int i_APCI16XX_InsnBitsReadTTLIO(struct comedi_device *dev,
 int i_APCI16XX_InsnReadTTLIOAllPortValue(struct comedi_device *dev,
        struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned char b_Command = (unsigned char) CR_AREF(insn->chanspec);
        int i_ReturnValue = insn->n;
        unsigned char b_Cpt = 0;
@@ -573,6 +576,7 @@ int i_APCI16XX_InsnReadTTLIOAllPortValue(struct comedi_device *dev,
 int i_APCI16XX_InsnBitsWriteTTLIO(struct comedi_device *dev,
        struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = insn->n;
        unsigned char b_Command = 0;
        unsigned char b_NumberOfPort =
index 49dcbe24fcd36e03c819c7dae67dc3d0ba8147c1..b8721dd16cb38960228b591bf4e40342ef291bc8 100644 (file)
@@ -78,6 +78,8 @@ You should also find the complete GPL in the COPYING file accompanying this sour
 int i_APCI2016_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
+
        if ((data[0] != 0) && (data[0] != 1)) {
                comedi_error(dev,
                        "Not a valid Data !!! ,Data should be 1 or 0\n");
@@ -114,8 +116,10 @@ int i_APCI2016_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subd
 int i_APCI2016_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned int ui_NoOfChannel;
        unsigned int ui_Temp, ui_Temp1;
+
        ui_NoOfChannel = CR_CHAN(insn->chanspec);
        if (ui_NoOfChannel > 15) {
                comedi_error(dev,
@@ -269,8 +273,10 @@ int i_APCI2016_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subde
 int i_APCI2016_BitsDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned int ui_Temp;
        unsigned int ui_NoOfChannel;
+
        ui_NoOfChannel = CR_CHAN(insn->chanspec);
        if (ui_NoOfChannel > 15) {
                comedi_error(dev,
@@ -340,6 +346,7 @@ int i_APCI2016_BitsDigitalOutput(struct comedi_device *dev, struct comedi_subdev
 int i_APCI2016_ConfigWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
 
        if (data[0] == 0) {
                /* Disable the watchdog */
@@ -383,6 +390,7 @@ int i_APCI2016_ConfigWatchdog(struct comedi_device *dev, struct comedi_subdevice
 int i_APCI2016_StartStopWriteWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
 
        switch (data[0]) {
        case 0:         /* stop the watchdog */
@@ -430,6 +438,8 @@ int i_APCI2016_StartStopWriteWatchdog(struct comedi_device *dev, struct comedi_s
 int i_APCI2016_ReadWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
+
        udelay(5);
        data[0] = inw(devpriv->i_IobaseAddon + APCI2016_WATCHDOG_STATUS) & 0x1;
        return insn->n;
@@ -452,6 +462,8 @@ int i_APCI2016_ReadWatchdog(struct comedi_device *dev, struct comedi_subdevice *
 
 int i_APCI2016_Reset(struct comedi_device *dev)
 {
+       struct addi_private *devpriv = dev->private;
+
        outw(0x0, devpriv->iobase + APCI2016_DIGITAL_OP);       /*  Resets the digital output channels */
        outw(0x0, devpriv->i_IobaseAddon + APCI2016_WATCHDOG_ENABLEDISABLE);
        outw(0x0, devpriv->i_IobaseAddon + APCI2016_WATCHDOG_RELOAD_VALUE);
index 002297dfe33f2fd76fa0fcb30ee3df8276d30c73..ad57f02b5b24552087412e5ffea3d7d3ad035179 100644 (file)
@@ -82,7 +82,9 @@ static unsigned int ui_InterruptData, ui_Type;
 int i_APCI2032_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned int ul_Command = 0;
+
        devpriv->tsk_Current = current;
 
        if ((data[0] != 0) && (data[0] != 1)) {
@@ -137,8 +139,10 @@ int i_APCI2032_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subd
 int i_APCI2032_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned int ui_Temp, ui_Temp1;
        unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec);  /*  get the channel */
+
        if (devpriv->b_OutputMemoryStatus) {
                ui_Temp = inl(devpriv->iobase + APCI2032_DIGITAL_OP);
 
@@ -316,8 +320,10 @@ int i_APCI2032_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subde
 int i_APCI2032_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned int ui_Temp;
        unsigned int ui_NoOfChannel;
+
        ui_NoOfChannel = CR_CHAN(insn->chanspec);
        ui_Temp = data[0];
        *data = inl(devpriv->iobase + APCI2032_DIGITAL_OP_RW);
@@ -383,6 +389,8 @@ int i_APCI2032_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdev
 int i_APCI2032_ConfigWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
+
        if (data[0] == 0) {
                /* Disable the watchdog */
                outl(0x0,
@@ -424,6 +432,8 @@ int i_APCI2032_ConfigWatchdog(struct comedi_device *dev, struct comedi_subdevice
 int i_APCI2032_StartStopWriteWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
+
        switch (data[0]) {
        case 0:         /* stop the watchdog */
                outl(0x0, devpriv->iobase + APCI2032_DIGITAL_OP_WATCHDOG + APCI2032_TCW_PROG);  /* disable the watchdog */
@@ -469,6 +479,7 @@ int i_APCI2032_StartStopWriteWatchdog(struct comedi_device *dev, struct comedi_s
 int i_APCI2032_ReadWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
 
        data[0] =
                inl(devpriv->iobase + APCI2032_DIGITAL_OP_WATCHDOG +
@@ -496,6 +507,7 @@ int i_APCI2032_ReadWatchdog(struct comedi_device *dev, struct comedi_subdevice *
 void v_APCI2032_Interrupt(int irq, void *d)
 {
        struct comedi_device *dev = d;
+       struct addi_private *devpriv = dev->private;
        unsigned int ui_DO;
 
        ui_DO = inl(devpriv->iobase + APCI2032_DIGITAL_OP_IRQ) & 0x1;   /* Check if VCC OR CC interrupt has occurred. */
@@ -569,6 +581,8 @@ int i_APCI2032_ReadInterruptStatus(struct comedi_device *dev, struct comedi_subd
 
 int i_APCI2032_Reset(struct comedi_device *dev)
 {
+       struct addi_private *devpriv = dev->private;
+
        devpriv->b_DigitalOutputRegister = 0;
        ui_Type = 0;
        outl(0x0, devpriv->iobase + APCI2032_DIGITAL_OP);       /* Resets the output channels */
index 3d378b5ecbcef0d8086195b70605d6c166ed8eed..db74f774a91a93ae0ad5c743dfdb8888166b1b83 100644 (file)
@@ -76,8 +76,10 @@ You should also find the complete GPL in the COPYING file accompanying this sour
 int i_APCI2200_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned int ui_TmpValue = 0;
        unsigned int ui_Channel;
+
        ui_Channel = CR_CHAN(insn->chanspec);
        if (ui_Channel <= 7) {
                ui_TmpValue = (unsigned int) inw(devpriv->iobase + APCI2200_DIGITAL_IP);
@@ -115,7 +117,7 @@ int i_APCI2200_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdev
 int i_APCI2200_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
-
+       struct addi_private *devpriv = dev->private;
        unsigned int ui_PortValue = data[0];
        unsigned int ui_Mask = 0;
        unsigned int ui_NoOfChannels;
@@ -172,6 +174,8 @@ int i_APCI2200_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_sub
 int i_APCI2200_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
+
        devpriv->b_OutputMemoryStatus = data[0];
        return insn->n;
 }
@@ -200,8 +204,10 @@ int i_APCI2200_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subd
 int i_APCI2200_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned int ui_Temp, ui_Temp1;
        unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec);  /*  get the channel */
+
        if (devpriv->b_OutputMemoryStatus) {
                ui_Temp = inw(devpriv->iobase + APCI2200_DIGITAL_OP);
 
@@ -357,9 +363,10 @@ int i_APCI2200_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subde
 int i_APCI2200_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
-
+       struct addi_private *devpriv = dev->private;
        unsigned int ui_Temp;
        unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec);  /*  get the channel */
+
        ui_Temp = data[0];
        *data = inw(devpriv->iobase + APCI2200_DIGITAL_OP);
        if (ui_Temp == 0) {
@@ -421,6 +428,8 @@ int i_APCI2200_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdev
 int i_APCI2200_ConfigWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
+
        if (data[0] == 0) {
                /* Disable the watchdog */
                outw(0x0,
@@ -467,6 +476,8 @@ int i_APCI2200_ConfigWatchdog(struct comedi_device *dev, struct comedi_subdevice
 int i_APCI2200_StartStopWriteWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
+
        switch (data[0]) {
        case 0:         /* stop the watchdog */
                outw(0x0, devpriv->iobase + APCI2200_WATCHDOG + APCI2200_WATCHDOG_ENABLEDISABLE);       /* disable the watchdog */
@@ -512,6 +523,8 @@ int i_APCI2200_StartStopWriteWatchdog(struct comedi_device *dev, struct comedi_s
 int i_APCI2200_ReadWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
+
        data[0] =
                inw(devpriv->iobase + APCI2200_WATCHDOG +
                APCI2200_WATCHDOG_STATUS) & 0x1;
@@ -535,6 +548,8 @@ int i_APCI2200_ReadWatchdog(struct comedi_device *dev, struct comedi_subdevice *
 
 int i_APCI2200_Reset(struct comedi_device *dev)
 {
+       struct addi_private *devpriv = dev->private;
+
        outw(0x0, devpriv->iobase + APCI2200_DIGITAL_OP);       /* RESETS THE DIGITAL OUTPUTS */
        outw(0x0,
                devpriv->iobase + APCI2200_WATCHDOG +
index f406dfb2a677d80d2ba24554e1e5e8b7d8623680..0f7c8260264c07de8e23219fd524c43399e4b152 100644 (file)
@@ -77,6 +77,7 @@ static unsigned int ui_Temp;
 int i_APCI3120_InsnConfigAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned int i;
 
        if ((data[0] != APCI3120_EOC_MODE) && (data[0] != APCI3120_EOS_MODE))
@@ -146,6 +147,7 @@ int i_APCI3120_InsnConfigAnalogInput(struct comedi_device *dev, struct comedi_su
 int i_APCI3120_InsnReadAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned short us_ConvertTiming, us_TmpValue, i;
        unsigned char b_Tmp;
 
@@ -407,6 +409,8 @@ int i_APCI3120_InsnReadAnalogInput(struct comedi_device *dev, struct comedi_subd
 
 int i_APCI3120_StopCyclicAcquisition(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+       struct addi_private *devpriv = dev->private;
+
        /*  Disable A2P Fifo write and AMWEN signal */
        outw(0, devpriv->i_IobaseAddon + 4);
 
@@ -478,6 +482,7 @@ int i_APCI3120_StopCyclicAcquisition(struct comedi_device *dev, struct comedi_su
 int i_APCI3120_CommandTestAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_cmd *cmd)
 {
+       struct addi_private *devpriv = dev->private;
        int err = 0;
 
        /* Step 1 : check if triggers are trivially valid */
@@ -604,6 +609,7 @@ int i_APCI3120_CommandTestAnalogInput(struct comedi_device *dev, struct comedi_s
 
 int i_APCI3120_CommandAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+       struct addi_private *devpriv = dev->private;
        struct comedi_cmd *cmd = &s->async->cmd;
 
        /* loading private structure with cmd structure inputs */
@@ -678,6 +684,7 @@ int i_APCI3120_CommandAnalogInput(struct comedi_device *dev, struct comedi_subde
 int i_APCI3120_CyclicAnalogInput(int mode, struct comedi_device *dev,
        struct comedi_subdevice *s)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned char b_Tmp;
        unsigned int ui_Tmp, ui_DelayTiming = 0, ui_TimerValue1 = 0, dmalen0 =
                0, dmalen1 = 0, ui_TimerValue2 =
@@ -1211,6 +1218,7 @@ int i_APCI3120_CyclicAnalogInput(int mode, struct comedi_device *dev,
 
 int i_APCI3120_Reset(struct comedi_device *dev)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned int i;
        unsigned short us_TmpValue;
 
@@ -1292,6 +1300,7 @@ int i_APCI3120_Reset(struct comedi_device *dev)
 int i_APCI3120_SetupChannelList(struct comedi_device *dev, struct comedi_subdevice *s,
        int n_chan, unsigned int *chanlist, char check)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned int i;         /* , differencial=0, bipolar=0; */
        unsigned int gain;
        unsigned short us_TmpValue;
@@ -1354,6 +1363,7 @@ int i_APCI3120_SetupChannelList(struct comedi_device *dev, struct comedi_subdevi
 
 int i_APCI3120_ExttrigEnable(struct comedi_device *dev)
 {
+       struct addi_private *devpriv = dev->private;
 
        devpriv->us_OutputRegister |= APCI3120_ENABLE_EXT_TRIGGER;
        outw(devpriv->us_OutputRegister, dev->iobase + APCI3120_WR_ADDRESS);
@@ -1379,6 +1389,8 @@ int i_APCI3120_ExttrigEnable(struct comedi_device *dev)
 
 int i_APCI3120_ExttrigDisable(struct comedi_device *dev)
 {
+       struct addi_private *devpriv = dev->private;
+
        devpriv->us_OutputRegister &= ~APCI3120_ENABLE_EXT_TRIGGER;
        outw(devpriv->us_OutputRegister, dev->iobase + APCI3120_WR_ADDRESS);
        return 0;
@@ -1414,13 +1426,13 @@ int i_APCI3120_ExttrigDisable(struct comedi_device *dev)
 void v_APCI3120_Interrupt(int irq, void *d)
 {
        struct comedi_device *dev = d;
+       struct addi_private *devpriv = dev->private;
        unsigned short int_daq;
-
        unsigned int int_amcc, ui_Check, i;
        unsigned short us_TmpValue;
        unsigned char b_DummyRead;
-
        struct comedi_subdevice *s = &dev->subdevices[0];
+
        ui_Check = 1;
 
        int_daq = inw(dev->iobase + APCI3120_RD_STATUS) & 0xf000;       /*  get IRQ reasons */
@@ -1624,6 +1636,7 @@ void v_APCI3120_Interrupt(int irq, void *d)
 
 int i_APCI3120_InterruptHandleEos(struct comedi_device *dev)
 {
+       struct addi_private *devpriv = dev->private;
        int n_chan, i;
        struct comedi_subdevice *s = &dev->subdevices[0];
        int err = 1;
@@ -1667,11 +1680,12 @@ int i_APCI3120_InterruptHandleEos(struct comedi_device *dev)
 void v_APCI3120_InterruptDma(int irq, void *d)
 {
        struct comedi_device *dev = d;
+       struct addi_private *devpriv = dev->private;
        struct comedi_subdevice *s = &dev->subdevices[0];
        unsigned int next_dma_buf, samplesinbuf;
        unsigned long low_word, high_word, var;
-
        unsigned int ui_Tmp;
+
        samplesinbuf =
                devpriv->ui_DmaBufferUsesize[devpriv->ui_DmaActualBuffer] -
                inl(devpriv->i_IobaseAmcc + AMCC_OP_REG_MWTC);
@@ -1837,6 +1851,8 @@ void v_APCI3120_InterruptDma(int irq, void *d)
 void v_APCI3120_InterruptDmaMoveBlock16bit(struct comedi_device *dev,
        struct comedi_subdevice *s, short *dma_buffer, unsigned int num_samples)
 {
+       struct addi_private *devpriv = dev->private;
+
        devpriv->ui_AiActualScan +=
                (s->async->cur_chan + num_samples) / devpriv->ui_AiScanLength;
        s->async->cur_chan += num_samples;
@@ -1879,7 +1895,7 @@ void v_APCI3120_InterruptDmaMoveBlock16bit(struct comedi_device *dev,
 int i_APCI3120_InsnConfigTimer(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
-
+       struct addi_private *devpriv = dev->private;
        unsigned int ui_Timervalue2;
        unsigned short us_TmpValue;
        unsigned char b_Tmp;
@@ -2037,7 +2053,7 @@ int i_APCI3120_InsnConfigTimer(struct comedi_device *dev, struct comedi_subdevic
 int i_APCI3120_InsnWriteTimer(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
-
+       struct addi_private *devpriv = dev->private;
        unsigned int ui_Timervalue2 = 0;
        unsigned short us_TmpValue;
        unsigned char b_Tmp;
@@ -2221,6 +2237,7 @@ int i_APCI3120_InsnWriteTimer(struct comedi_device *dev, struct comedi_subdevice
 int i_APCI3120_InsnReadTimer(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned char b_Tmp;
        unsigned short us_TmpValue, us_TmpValue_2, us_StatusValue;
 
@@ -2296,6 +2313,7 @@ int i_APCI3120_InsnReadDigitalInput(struct comedi_device *dev,
                                    struct comedi_insn *insn,
                                    unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned int ui_Chan, ui_TmpValue;
 
        ui_Chan = CR_CHAN(insn->chanspec);      /*  channel specified */
@@ -2340,7 +2358,9 @@ int i_APCI3120_InsnReadDigitalInput(struct comedi_device *dev,
 int i_APCI3120_InsnBitsDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned int ui_TmpValue;
+
        ui_TmpValue = (unsigned int) inw(devpriv->iobase + APCI3120_RD_STATUS);
        /*****  state of 4 channels  in the 11, 10, 9, 8   bits of status reg
                        rotated right 8 times to bring them to last four bits
@@ -2379,6 +2399,7 @@ int i_APCI3120_InsnBitsDigitalInput(struct comedi_device *dev, struct comedi_sub
 int i_APCI3120_InsnConfigDigitalOutput(struct comedi_device *dev,
        struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
 
        if ((data[0] != 0) && (data[0] != 1)) {
                comedi_error(dev,
@@ -2426,6 +2447,8 @@ int i_APCI3120_InsnBitsDigitalOutput(struct comedi_device *dev,
                                     struct comedi_insn *insn,
                                     unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
+
        if ((data[0] > devpriv->s_EeParameters.i_DoMaxdata) || (data[0] < 0)) {
 
                comedi_error(dev, "Data is not valid !!! \n");
@@ -2479,9 +2502,8 @@ int i_APCI3120_InsnWriteDigitalOutput(struct comedi_device *dev,
                                      struct comedi_insn *insn,
                                      unsigned int *data)
 {
-
+       struct addi_private *devpriv = dev->private;
        unsigned int ui_Temp1;
-
        unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec);  /*  get the channel */
 
        if ((data[0] != 0) && (data[0] != 1)) {
@@ -2558,6 +2580,7 @@ int i_APCI3120_InsnWriteAnalogOutput(struct comedi_device *dev,
                                     struct comedi_insn *insn,
                                     unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned int ui_Range, ui_Channel;
        unsigned short us_TmpValue;
 
index 38ab49917d7e39a85903319c28b1ed679125b931..7f5efa39cb76987d1b700836b72c8a55ac895f68 100644 (file)
@@ -548,8 +548,10 @@ int i_APCI3200_GetChannelCalibrationValue(struct comedi_device *dev,
 int i_APCI3200_ReadDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned int ui_Temp = 0;
        unsigned int ui_NoOfChannel = 0;
+
        ui_NoOfChannel = CR_CHAN(insn->chanspec);
        ui_Temp = data[0];
        *data = inl(devpriv->i_IobaseReserved);
@@ -606,6 +608,7 @@ int i_APCI3200_ReadDigitalInput(struct comedi_device *dev, struct comedi_subdevi
 int i_APCI3200_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
 
        if ((data[0] != 0) && (data[0] != 1)) {
                comedi_error(dev,
@@ -651,8 +654,10 @@ int i_APCI3200_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subd
 int i_APCI3200_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned int ui_Temp = 0, ui_Temp1 = 0;
        unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec);  /*  get the channel */
+
        if (devpriv->b_OutputMemoryStatus) {
                ui_Temp = inl(devpriv->i_IobaseAddon);
 
@@ -764,8 +769,10 @@ int i_APCI3200_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subde
 int i_APCI3200_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned int ui_Temp;
        unsigned int ui_NoOfChannel;
+
        ui_NoOfChannel = CR_CHAN(insn->chanspec);
        ui_Temp = data[0];
        *data = inl(devpriv->i_IobaseAddon);
@@ -872,7 +879,7 @@ int i_APCI3200_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdev
 int i_APCI3200_ConfigAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
-
+       struct addi_private *devpriv = dev->private;
        unsigned int ul_Config = 0, ul_Temp = 0;
        unsigned int ui_ChannelNo = 0;
        unsigned int ui_Dummy = 0;
@@ -1649,6 +1656,7 @@ int i_APCI3200_ReadAnalogInput(struct comedi_device *dev, struct comedi_subdevic
 int i_APCI3200_Read1AnalogInputChannel(struct comedi_device *dev,
        struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned int ui_EOC = 0;
        unsigned int ui_ChannelNo = 0;
        unsigned int ui_CommandRegister = 0;
@@ -1773,6 +1781,7 @@ int i_APCI3200_Read1AnalogInputChannel(struct comedi_device *dev,
 */
 int i_APCI3200_ReadCalibrationOffsetValue(struct comedi_device *dev, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned int ui_Temp = 0, ui_EOC = 0;
        unsigned int ui_CommandRegister = 0;
 
@@ -1909,6 +1918,7 @@ int i_APCI3200_ReadCalibrationOffsetValue(struct comedi_device *dev, unsigned in
 */
 int i_APCI3200_ReadCalibrationGainValue(struct comedi_device *dev, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned int ui_EOC = 0;
        int ui_CommandRegister = 0;
 
@@ -2045,6 +2055,7 @@ int i_APCI3200_ReadCalibrationGainValue(struct comedi_device *dev, unsigned int
 
 int i_APCI3200_ReadCJCValue(struct comedi_device *dev, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned int ui_EOC = 0;
        int ui_CommandRegister = 0;
 
@@ -2164,8 +2175,10 @@ int i_APCI3200_ReadCJCValue(struct comedi_device *dev, unsigned int *data)
 */
 int i_APCI3200_ReadCJCCalOffset(struct comedi_device *dev, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned int ui_EOC = 0;
        int ui_CommandRegister = 0;
+
   /*******************************************/
        /*Read calibration offset value for the CJC */
   /*******************************************/
@@ -2280,8 +2293,10 @@ int i_APCI3200_ReadCJCCalOffset(struct comedi_device *dev, unsigned int *data)
 */
 int i_APCI3200_ReadCJCCalGain(struct comedi_device *dev, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned int ui_EOC = 0;
        int ui_CommandRegister = 0;
+
   /*******************************/
        /* Set the convert timing unit */
   /*******************************/
@@ -2402,8 +2417,10 @@ int i_APCI3200_ReadCJCCalGain(struct comedi_device *dev, unsigned int *data)
 int i_APCI3200_InsnBits_AnalogInput_Test(struct comedi_device *dev,
        struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned int ui_Configuration = 0;
        int i_Temp;             /* ,i_TimeUnit; */
+
        /* if(i_Initialised==0) */
 
        if (s_BoardInfos[dev->minor].i_Initialised == 0) {
@@ -2736,7 +2753,9 @@ int i_APCI3200_CommandTestAnalogInput(struct comedi_device *dev, struct comedi_s
 
 int i_APCI3200_StopCyclicAcquisition(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned int ui_Configuration = 0;
+
        /* i_InterruptFlag=0; */
        /* i_Initialised=0; */
        /* i_Count=0; */
@@ -2786,6 +2805,7 @@ int i_APCI3200_StopCyclicAcquisition(struct comedi_device *dev, struct comedi_su
 
 int i_APCI3200_CommandAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+       struct addi_private *devpriv = dev->private;
        struct comedi_cmd *cmd = &s->async->cmd;
        unsigned int ui_Configuration = 0;
        /* INT  i_CurrentSource = 0; */
@@ -2798,6 +2818,7 @@ int i_APCI3200_CommandAnalogInput(struct comedi_device *dev, struct comedi_subde
        unsigned int ui_DelayTime = 0;
        unsigned int ui_DelayTimeBase = 0;
        unsigned int ui_DelayMode = 0;
+
        /* i_FirstChannel=cmd->chanlist[0]; */
        /* i_LastChannel=cmd->chanlist[1]; */
        s_BoardInfos[dev->minor].i_FirstChannel = cmd->chanlist[0];
@@ -2973,8 +2994,10 @@ int i_APCI3200_CommandAnalogInput(struct comedi_device *dev, struct comedi_subde
 
 int i_APCI3200_Reset(struct comedi_device *dev)
 {
+       struct addi_private *devpriv = dev->private;
        int i_Temp;
        unsigned int dw_Dummy;
+
        /* i_InterruptFlag=0; */
        /* i_Initialised==0; */
        /* i_Count=0; */
@@ -3030,6 +3053,7 @@ int i_APCI3200_Reset(struct comedi_device *dev)
 void v_APCI3200_Interrupt(int irq, void *d)
 {
        struct comedi_device *dev = d;
+       struct addi_private *devpriv = dev->private;
        unsigned int ui_StatusRegister = 0;
        unsigned int ui_ChannelNumber = 0;
        int i_CalibrationFlag = 0;
@@ -3038,7 +3062,6 @@ void v_APCI3200_Interrupt(int irq, void *d)
        unsigned int ui_DigitalTemperature = 0;
        unsigned int ui_DigitalInput = 0;
        int i_ConvertCJCCalibration;
-
        /* BEGIN JK TEST */
        int i_ReturnValue = 0;
        /* END JK TEST */
@@ -3471,6 +3494,7 @@ void v_APCI3200_Interrupt(int irq, void *d)
 */
 int i_APCI3200_InterruptHandleEos(struct comedi_device *dev)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned int ui_StatusRegister = 0;
        struct comedi_subdevice *s = &dev->subdevices[0];
 
index acaceb01629a80bf616b5d0924b6de7b898e112d..a730a4a52cb959aac3fd16a3365fa9e55c657db2 100644 (file)
@@ -76,8 +76,10 @@ You should also find the complete GPL in the COPYING file accompanying this sour
 int i_APCI3501_ReadDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned int ui_Temp;
        unsigned int ui_NoOfChannel;
+
        ui_NoOfChannel = CR_CHAN(insn->chanspec);
        ui_Temp = data[0];
        *data = inl(devpriv->iobase + APCI3501_DIGITAL_IP);
@@ -124,6 +126,7 @@ int i_APCI3501_ReadDigitalInput(struct comedi_device *dev, struct comedi_subdevi
 int i_APCI3501_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
 
        if ((data[0] != 0) && (data[0] != 1)) {
                comedi_error(dev,
@@ -164,8 +167,10 @@ int i_APCI3501_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subd
 int i_APCI3501_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned int ui_Temp, ui_Temp1;
        unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec);  /*  get the channel */
+
        if (devpriv->b_OutputMemoryStatus) {
                ui_Temp = inl(devpriv->iobase + APCI3501_DIGITAL_OP);
        }                       /* if(devpriv->b_OutputMemoryStatus ) */
@@ -251,6 +256,7 @@ int i_APCI3501_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subde
 int i_APCI3501_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned int ui_Temp;
        unsigned int ui_NoOfChannel;
 
@@ -301,6 +307,8 @@ int i_APCI3501_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdev
 int i_APCI3501_ConfigAnalogOutput(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
+
        outl(data[0],
                devpriv->iobase + APCI3501_ANALOG_OUTPUT +
                APCI3501_AO_VOLT_MODE);
@@ -339,6 +347,7 @@ int i_APCI3501_ConfigAnalogOutput(struct comedi_device *dev, struct comedi_subde
 int i_APCI3501_WriteAnalogOutput(struct comedi_device *dev, struct comedi_subdevice *s,
        struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned int ul_Command1 = 0, ul_Channel_no, ul_Polarity, ul_DAC_Ready = 0;
 
        ul_Channel_no = CR_CHAN(insn->chanspec);
@@ -413,7 +422,9 @@ int i_APCI3501_WriteAnalogOutput(struct comedi_device *dev, struct comedi_subdev
 int i_APCI3501_ConfigTimerCounterWatchdog(struct comedi_device *dev,
        struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned int ul_Command1 = 0;
+
        devpriv->tsk_Current = current;
        if (data[0] == ADDIDATA_WATCHDOG) {
 
@@ -514,8 +525,10 @@ int i_APCI3501_ConfigTimerCounterWatchdog(struct comedi_device *dev,
 int i_APCI3501_StartStopWriteTimerCounterWatchdog(struct comedi_device *dev,
        struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned int ul_Command1 = 0;
        int i_Temp;
+
        if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
 
                if (data[1] == 1) {
@@ -616,6 +629,7 @@ int i_APCI3501_StartStopWriteTimerCounterWatchdog(struct comedi_device *dev,
 int i_APCI3501_ReadTimerCounterWatchdog(struct comedi_device *dev,
        struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
 
        if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
                data[0] =
@@ -656,8 +670,10 @@ int i_APCI3501_ReadTimerCounterWatchdog(struct comedi_device *dev,
 
 int i_APCI3501_Reset(struct comedi_device *dev)
 {
+       struct addi_private *devpriv = dev->private;
        int i_Count = 0, i_temp = 0;
        unsigned int ul_Command1 = 0, ul_Polarity, ul_DAC_Ready = 0;
+
        outl(0x0, devpriv->iobase + APCI3501_DIGITAL_OP);
        outl(1, devpriv->iobase + APCI3501_ANALOG_OUTPUT +
                APCI3501_AO_VOLT_MODE);
@@ -709,8 +725,10 @@ void v_APCI3501_Interrupt(int irq, void *d)
 {
        int i_temp;
        struct comedi_device *dev = d;
+       struct addi_private *devpriv = dev->private;
        unsigned int ui_Timer_AOWatchdog;
        unsigned long ul_Command1;
+
        /*  Disable Interrupt */
        ul_Command1 =
                inl(devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG);
index fff99df51e927f7519cd68909351901fcb2dc533..431df5c90ce9df26fb89af425279b566041da07b 100644 (file)
@@ -69,6 +69,8 @@ You should also find the complete GPL in the COPYING file accompanying this sour
 */
 static int i_APCI3XXX_TestConversionStarted(struct comedi_device *dev)
 {
+       struct addi_private *devpriv = dev->private;
+
        if ((readl(devpriv->dw_AiBase + 8) & 0x80000UL) == 0x80000UL)
                return 1;
        else
@@ -108,6 +110,7 @@ static int i_APCI3XXX_AnalogInputConfigOperatingMode(struct comedi_device *dev,
                                                     struct comedi_insn *insn,
                                                     unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = insn->n;
        unsigned char b_TimeBase = 0;
        unsigned char b_SingleDiff = 0;
@@ -358,6 +361,7 @@ static int i_APCI3XXX_InsnReadAnalogInput(struct comedi_device *dev,
                                          struct comedi_insn *insn,
                                          unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = insn->n;
        unsigned char b_Configuration = (unsigned char) CR_RANGE(insn->chanspec);
        unsigned char b_Channel = (unsigned char) CR_CHAN(insn->chanspec);
@@ -571,6 +575,7 @@ static int i_APCI3XXX_InsnReadAnalogInput(struct comedi_device *dev,
 static void v_APCI3XXX_Interrupt(int irq, void *d)
 {
        struct comedi_device *dev = d;
+       struct addi_private *devpriv = dev->private;
        unsigned char b_CopyCpt = 0;
        unsigned int dw_Status = 0;
 
@@ -651,6 +656,7 @@ static int i_APCI3XXX_InsnWriteAnalogOutput(struct comedi_device *dev,
                                            struct comedi_insn *insn,
                                            unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned char b_Range = (unsigned char) CR_RANGE(insn->chanspec);
        unsigned char b_Channel = (unsigned char) CR_CHAN(insn->chanspec);
        unsigned int dw_Status = 0;
@@ -755,6 +761,7 @@ static int i_APCI3XXX_InsnConfigInitTTLIO(struct comedi_device *dev,
                                          struct comedi_insn *insn,
                                          unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = insn->n;
        unsigned char b_Command = 0;
 
@@ -884,6 +891,7 @@ static int i_APCI3XXX_InsnBitsTTLIO(struct comedi_device *dev,
                                    struct comedi_insn *insn,
                                    unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = insn->n;
        unsigned char b_ChannelCpt = 0;
        unsigned int dw_ChannelMask = 0;
@@ -1040,6 +1048,7 @@ static int i_APCI3XXX_InsnReadTTLIO(struct comedi_device *dev,
                                    struct comedi_insn *insn,
                                    unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned char b_Channel = (unsigned char) CR_CHAN(insn->chanspec);
        int i_ReturnValue = insn->n;
        unsigned int *pls_ReadData = data;
@@ -1154,6 +1163,7 @@ static int i_APCI3XXX_InsnWriteTTLIO(struct comedi_device *dev,
                                     struct comedi_insn *insn,
                                     unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = insn->n;
        unsigned char b_Channel = (unsigned char) CR_CHAN(insn->chanspec);
        unsigned char b_State = 0;
@@ -1267,6 +1277,7 @@ static int i_APCI3XXX_InsnReadDigitalInput(struct comedi_device *dev,
                                           struct comedi_insn *insn,
                                           unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = insn->n;
        unsigned char b_Channel = (unsigned char) CR_CHAN(insn->chanspec);
        unsigned int dw_Temp = 0;
@@ -1327,6 +1338,7 @@ static int i_APCI3XXX_InsnBitsDigitalInput(struct comedi_device *dev,
                                           struct comedi_insn *insn,
                                           unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = insn->n;
        unsigned int dw_Temp = 0;
 
@@ -1382,6 +1394,7 @@ static int i_APCI3XXX_InsnBitsDigitalOutput(struct comedi_device *dev,
                                            struct comedi_insn *insn,
                                            unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = insn->n;
        unsigned char b_ChannelCpt = 0;
        unsigned int dw_ChannelMask = 0;
@@ -1480,6 +1493,7 @@ static int i_APCI3XXX_InsnWriteDigitalOutput(struct comedi_device *dev,
                                             struct comedi_insn *insn,
                                             unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = insn->n;
        unsigned char b_Channel = CR_CHAN(insn->chanspec);
        unsigned char b_State = 0;
@@ -1557,6 +1571,7 @@ static int i_APCI3XXX_InsnReadDigitalOutput(struct comedi_device *dev,
                                            struct comedi_insn *insn,
                                            unsigned int *data)
 {
+       struct addi_private *devpriv = dev->private;
        int i_ReturnValue = insn->n;
        unsigned char b_Channel = CR_CHAN(insn->chanspec);
        unsigned int dw_Status = 0;
@@ -1614,6 +1629,7 @@ static int i_APCI3XXX_InsnReadDigitalOutput(struct comedi_device *dev,
 
 static int i_APCI3XXX_Reset(struct comedi_device *dev)
 {
+       struct addi_private *devpriv = dev->private;
        unsigned char b_Cpt = 0;
 
        /*************************/
index 3492ce1156e01fdb91af22e9c0228f03e0e7071a..350e87dd04d9ee2228a88400c479f9272fd2af32 100644 (file)
@@ -183,18 +183,16 @@ static int pci6208_attach_pci(struct comedi_device *dev,
        unsigned int val;
        int ret;
 
-       comedi_set_hw_dev(dev, &pcidev->dev);
-
        boardinfo = pci6208_find_boardinfo(dev, pcidev);
        if (!boardinfo)
                return -ENODEV;
        dev->board_ptr = boardinfo;
        dev->board_name = boardinfo->name;
 
-       ret = alloc_private(dev, sizeof(*devpriv));
-       if (ret < 0)
-               return ret;
-       devpriv = dev->private;
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
+               return -ENOMEM;
+       dev->private = devpriv;
 
        ret = comedi_pci_enable(pcidev, dev->board_name);
        if (ret)
index 599714e978b581d184f26c40a7a5f3d6f3c6b668..8eee2fa0bf00bea1e68a20b7d05647a72766d097 100644 (file)
@@ -177,8 +177,6 @@ static int adl_pci7x3x_attach_pci(struct comedi_device *dev,
        int nchan;
        int ret;
 
-       comedi_set_hw_dev(dev, &pcidev->dev);
-
        board = adl_pci7x3x_find_boardinfo(dev, pcidev);
        if (!board)
                return -ENODEV;
index 05e06e7ba9f74f44d42d150f8fb4c318b1cbeadb..9999f938745eebc99a994560326af70661b8cb2c 100644 (file)
@@ -89,9 +89,9 @@ static void adl_pci8164_insn_read(struct comedi_device *dev,
        }
 
        data[0] = inw(dev->iobase + axis_reg + offset);
-       printk(KERN_DEBUG "comedi: pci8164 %s read -> "
-                                                 "%04X:%04X on axis %s\n",
-                               action, data[0], data[1], axisname);
+       dev_dbg(dev->class_dev,
+               "pci8164 %s read -> %04X:%04X on axis %s\n",
+               action, data[0], data[1], axisname);
 }
 
 static int adl_pci8164_insn_read_msts(struct comedi_device *dev,
@@ -170,9 +170,9 @@ static void adl_pci8164_insn_out(struct comedi_device *dev,
 
        outw(data[0], dev->iobase + axis_reg + offset);
 
-       printk(KERN_DEBUG "comedi: pci8164 %s write -> "
-                                               "%04X:%04X on axis %s\n",
-                               action, data[0], data[1], axisname);
+       dev_dbg(dev->class_dev,
+               "pci8164 %s write -> %04X:%04X on axis %s\n",
+               action, data[0], data[1], axisname);
 
 }
 
@@ -218,8 +218,6 @@ static int adl_pci8164_attach_pci(struct comedi_device *dev,
        struct comedi_subdevice *s;
        int ret;
 
-       comedi_set_hw_dev(dev, &pcidev->dev);
-
        dev->board_name = dev->driver->driver_name;
 
        ret = comedi_pci_enable(pcidev, dev->board_name);
index a87192ac2846d939957176eca026801db860f3a5..236a88946d006d0f9b421e7abc1aa2296db97523 100644 (file)
@@ -886,13 +886,12 @@ static int pci9111_attach_pci(struct comedi_device *dev,
        struct comedi_subdevice *s;
        int ret;
 
-       comedi_set_hw_dev(dev, &pcidev->dev);
        dev->board_name = dev->driver->driver_name;
 
-       ret = alloc_private(dev, sizeof(*dev_private));
-       if (ret)
-               return ret;
-       dev_private = dev->private;
+       dev_private = kzalloc(sizeof(*dev_private), GFP_KERNEL);
+       if (!dev_private)
+               return -ENOMEM;
+       dev->private = dev_private;
 
        ret = comedi_pci_enable(pcidev, dev->board_name);
        if (ret)
index 06ff65c85c9fa36dbdfa8ec3af651db6b7bac7c0..4bcc5b1171d94608c78e800cac9ad90be6381cd1 100644 (file)
@@ -1923,12 +1923,10 @@ static int pci9118_attach(struct comedi_device *dev,
        else
                master = 1;
 
-       ret = alloc_private(dev, sizeof(*devpriv));
-       if (ret < 0) {
-               printk(" - Allocation failed!\n");
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
                return -ENOMEM;
-       }
-       devpriv = dev->private;
+       dev->private = devpriv;
 
        pcidev = pci9118_find_pci(dev, it);
        if (!pcidev)
index 3a2aa5628be36cf3d5199b0e65b55304abc6b72b..f7950dfe2ddbca536a112310d56a54bb5bd12913 100644 (file)
@@ -116,15 +116,6 @@ static const struct comedi_lrange range_adq12b_ai_unipolar = { 4, {
                                                                   }
 };
 
-struct adq12b_board {
-       const char *name;
-       int ai_se_chans;
-       int ai_diff_chans;
-       int ai_bits;
-       int di_chans;
-       int do_chans;
-};
-
 struct adq12b_private {
        int unipolar;           /* option 2 of comedi_config (1 is iobase) */
        int differential;       /* option 3 of comedi_config */
@@ -220,13 +211,14 @@ static int adq12b_do_insn_bits(struct comedi_device *dev,
 
 static int adq12b_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
-       const struct adq12b_board *board = comedi_board(dev);
        struct adq12b_private *devpriv;
        struct comedi_subdevice *s;
        unsigned long iobase;
        int unipolar, differential;
        int ret;
 
+       dev->board_name = dev->driver->driver_name;
+
        iobase = it->options[0];
        unipolar = it->options[1];
        differential = it->options[2];
@@ -251,12 +243,10 @@ static int adq12b_attach(struct comedi_device *dev, struct comedi_devconfig *it)
        }
        dev->iobase = iobase;
 
-       dev->board_name = board->name;
-
-       ret = alloc_private(dev, sizeof(*devpriv));
-       if (ret)
-               return ret;
-       devpriv = dev->private;
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
+               return -ENOMEM;
+       dev->private = devpriv;
 
        devpriv->unipolar = unipolar;
        devpriv->differential = differential;
@@ -277,10 +267,10 @@ static int adq12b_attach(struct comedi_device *dev, struct comedi_devconfig *it)
        s->type = COMEDI_SUBD_AI;
        if (differential) {
                s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF;
-               s->n_chan = board->ai_diff_chans;
+               s->n_chan = 8;
        } else {
                s->subdev_flags = SDF_READABLE | SDF_GROUND;
-               s->n_chan = board->ai_se_chans;
+               s->n_chan = 16;
        }
 
        if (unipolar)
@@ -288,7 +278,7 @@ static int adq12b_attach(struct comedi_device *dev, struct comedi_devconfig *it)
        else
                s->range_table = &range_adq12b_ai_bipolar;
 
-       s->maxdata = (1 << board->ai_bits) - 1;
+       s->maxdata = 0xfff;
 
        s->len_chanlist = 4;    /* This is the maximum chanlist length that
                                   the board can handle */
@@ -298,7 +288,7 @@ static int adq12b_attach(struct comedi_device *dev, struct comedi_devconfig *it)
        /* digital input subdevice */
        s->type = COMEDI_SUBD_DI;
        s->subdev_flags = SDF_READABLE;
-       s->n_chan = board->di_chans;
+       s->n_chan = 5;
        s->maxdata = 1;
        s->range_table = &range_digital;
        s->insn_bits = adq12b_di_insn_bits;
@@ -307,7 +297,7 @@ static int adq12b_attach(struct comedi_device *dev, struct comedi_devconfig *it)
        /* digital output subdevice */
        s->type = COMEDI_SUBD_DO;
        s->subdev_flags = SDF_WRITABLE;
-       s->n_chan = board->do_chans;
+       s->n_chan = 8;
        s->maxdata = 1;
        s->range_table = &range_digital;
        s->insn_bits = adq12b_do_insn_bits;
@@ -323,25 +313,11 @@ static void adq12b_detach(struct comedi_device *dev)
                release_region(dev->iobase, ADQ12B_SIZE);
 }
 
-static const struct adq12b_board adq12b_boards[] = {
-       {
-               .name           = "adq12b",
-               .ai_se_chans    = 16,
-               .ai_diff_chans  = 8,
-               .ai_bits        = 12,
-               .di_chans       = 5,
-               .do_chans       = 8,
-       },
-};
-
 static struct comedi_driver adq12b_driver = {
        .driver_name    = "adq12b",
        .module         = THIS_MODULE,
        .attach         = adq12b_attach,
        .detach         = adq12b_detach,
-       .board_name     = &adq12b_boards[0].name,
-       .offset         = sizeof(struct adq12b_board),
-       .num_names      = ARRAY_SIZE(adq12b_boards),
 };
 module_comedi_driver(adq12b_driver);
 
index def37bcc2a66bb2f624c665f4e8ade8038f25d72..6131a0a7aa964357b9aaaacab5a4953e1ea73ba9 100644 (file)
@@ -1265,18 +1265,16 @@ static int pci1710_attach_pci(struct comedi_device *dev,
        struct comedi_subdevice *s;
        int ret, subdev, n_subdevices;
 
-       comedi_set_hw_dev(dev, &pcidev->dev);
-
        this_board = pci1710_find_boardinfo(dev, pcidev);
        if (!this_board)
                return -ENODEV;
        dev->board_ptr = this_board;
        dev->board_name = this_board->name;
 
-       ret = alloc_private(dev, sizeof(*devpriv));
-       if (ret < 0)
-               return ret;
-       devpriv = dev->private;
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
+               return -ENOMEM;
+       dev->private = devpriv;
 
        ret = comedi_pci_enable(pcidev, dev->board_name);
        if (ret)
index df4efc0606dee3d85fa4c7253e2880c8d08cfce0..2eaf56dcc952e94ebebe0b1fe983545386cec35d 100644 (file)
@@ -241,13 +241,12 @@ static int pci1723_attach_pci(struct comedi_device *dev,
        struct comedi_subdevice *s;
        int ret;
 
-       comedi_set_hw_dev(dev, &pcidev->dev);
        dev->board_name = dev->driver->driver_name;
 
-       ret = alloc_private(dev, sizeof(*devpriv));
-       if (ret < 0)
-               return ret;
-       devpriv = dev->private;
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
+               return -ENOMEM;
+       dev->private = devpriv;
 
        ret = comedi_pci_enable(pcidev, dev->board_name);
        if (ret)
index a3c22419cd5f2e6c246c7c77a82235b1a44fd127..4b29f6d050507efbb7a313078a0ac1228ab9b1eb 100644 (file)
@@ -1100,18 +1100,16 @@ static int pci_dio_attach_pci(struct comedi_device *dev,
        struct comedi_subdevice *s;
        int ret, subdev, i, j;
 
-       comedi_set_hw_dev(dev, &pcidev->dev);
-
        this_board = pci_dio_find_boardinfo(dev, pcidev);
        if (!this_board)
                return -ENODEV;
        dev->board_ptr = this_board;
        dev->board_name = this_board->name;
 
-       ret = alloc_private(dev, sizeof(*devpriv));
-       if (ret < 0)
-               return ret;
-       devpriv = dev->private;
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
+               return -ENOMEM;
+       dev->private = devpriv;
 
        ret = comedi_pci_enable(pcidev, dev->board_name);
        if (ret)
index 8acf60d0f20d49a901591d1f06a65102f68dd7f0..601f03d5897faab43d95dd7223826796cb0e4d46 100644 (file)
@@ -212,10 +212,10 @@ static int aio_aio12_8_attach(struct comedi_device *dev,
        }
        dev->iobase = iobase;
 
-       ret = alloc_private(dev, sizeof(*devpriv));
-       if (ret)
-               return ret;
-       devpriv = dev->private;
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
+               return -ENOMEM;
+       dev->private = devpriv;
 
        ret = comedi_alloc_subdevices(dev, 4);
        if (ret)
index b2cb8b02b2a1419ba108520699e06cd7d854206d..64c1ae58ce7fc1ac22d7243ac7273ad995df7f1d 100644 (file)
@@ -44,19 +44,6 @@ Configuration Options:
 #define AIO_IIRO_16_RELAY_8_15 0x04
 #define AIO_IIRO_16_INPUT_8_15 0x05
 
-struct aio_iiro_16_board {
-       const char *name;
-       int do_;
-       int di;
-};
-
-static const struct aio_iiro_16_board aio_iiro_16_boards[] = {
-       {
-        .name = "aio_iiro_16",
-        .di = 16,
-        .do_ = 16},
-};
-
 static int aio_iiro_16_dio_insn_bits_write(struct comedi_device *dev,
                                           struct comedi_subdevice *s,
                                           struct comedi_insn *insn,
@@ -90,14 +77,13 @@ static int aio_iiro_16_dio_insn_bits_read(struct comedi_device *dev,
 static int aio_iiro_16_attach(struct comedi_device *dev,
                              struct comedi_devconfig *it)
 {
-       const struct aio_iiro_16_board *board = comedi_board(dev);
        int iobase;
        struct comedi_subdevice *s;
        int ret;
 
        printk(KERN_INFO "comedi%d: aio_iiro_16: ", dev->minor);
 
-       dev->board_name = board->name;
+       dev->board_name = dev->driver->driver_name;
 
        iobase = it->options[0];
 
@@ -144,9 +130,6 @@ static struct comedi_driver aio_iiro_16_driver = {
        .module         = THIS_MODULE,
        .attach         = aio_iiro_16_attach,
        .detach         = aio_iiro_16_detach,
-       .board_name     = &aio_iiro_16_boards[0].name,
-       .offset         = sizeof(struct aio_iiro_16_board),
-       .num_names      = ARRAY_SIZE(aio_iiro_16_boards),
 };
 module_comedi_driver(aio_iiro_16_driver);
 
index 08f305210a695d57e1ef2c8181ec3d47b2f62c53..95c3f7824d81c34e958040dc55017e890039f9b6 100644 (file)
 
 */
 /*
-Driver: amplc_dio200
-Description: Amplicon 200 Series Digital I/O
-Author: Ian Abbott <abbotti@mev.co.uk>
-Devices: [Amplicon] PC212E (pc212e), PC214E (pc214e), PC215E (pc215e),
-  PCI215 (pci215 or amplc_dio200), PC218E (pc218e), PC272E (pc272e),
-  PCI272 (pci272 or amplc_dio200)
-Updated: Wed, 22 Oct 2008 13:36:02 +0100
-Status: works
-
-Configuration options - PC212E, PC214E, PC215E, PC218E, PC272E:
-  [0] - I/O port base address
-  [1] - IRQ (optional, but commands won't work without it)
-
-Configuration options - PCI215, PCI272:
-  [0] - PCI bus of device (optional)
-  [1] - PCI slot of device (optional)
-  If bus/slot is not specified, the first available PCI device will
-  be used.
-
-Passing a zero for an option is the same as leaving it unspecified.
-
-SUBDEVICES
-
-                   PC218E         PC212E      PC215E/PCI215
-                -------------  -------------  -------------
-  Subdevices           7              6              5
-   0                 CTR-X1         PPI-X          PPI-X
-   1                 CTR-X2         CTR-Y1         PPI-Y
-   2                 CTR-Y1         CTR-Y2         CTR-Z1
-   3                 CTR-Y2         CTR-Z1         CTR-Z2
-   4                 CTR-Z1         CTR-Z2       INTERRUPT
-   5                 CTR-Z2       INTERRUPT
-   6               INTERRUPT
-
-                   PC214E      PC272E/PCI272
-                -------------  -------------
-  Subdevices           4              4
-   0                 PPI-X          PPI-X
-   1                 PPI-Y          PPI-Y
-   2                 CTR-Z1*        PPI-Z
-   3               INTERRUPT*     INTERRUPT
-
-Each PPI is a 8255 chip providing 24 DIO channels.  The DIO channels
-are configurable as inputs or outputs in four groups:
-
-  Port A  - channels  0 to  7
-  Port B  - channels  8 to 15
-  Port CL - channels 16 to 19
-  Port CH - channels 20 to 23
-
-Only mode 0 of the 8255 chips is supported.
-
-Each CTR is a 8254 chip providing 3 16-bit counter channels.  Each
-channel is configured individually with INSN_CONFIG instructions.  The
-specific type of configuration instruction is specified in data[0].
-Some configuration instructions expect an additional parameter in
-data[1]; others return a value in data[1].  The following configuration
-instructions are supported:
-
-  INSN_CONFIG_SET_COUNTER_MODE.  Sets the counter channel's mode and
-    BCD/binary setting specified in data[1].
-
-  INSN_CONFIG_8254_READ_STATUS.  Reads the status register value for the
-    counter channel into data[1].
-
-  INSN_CONFIG_SET_CLOCK_SRC.  Sets the counter channel's clock source as
-    specified in data[1] (this is a hardware-specific value).  Not
-    supported on PC214E.  For the other boards, valid clock sources are
-    0 to 7 as follows:
-
-      0.  CLK n, the counter channel's dedicated CLK input from the SK1
-       connector.  (N.B. for other values, the counter channel's CLKn
-       pin on the SK1 connector is an output!)
-      1.  Internal 10 MHz clock.
-      2.  Internal 1 MHz clock.
-      3.  Internal 100 kHz clock.
-      4.  Internal 10 kHz clock.
-      5.  Internal 1 kHz clock.
-      6.  OUT n-1, the output of counter channel n-1 (see note 1 below).
-      7.  Ext Clock, the counter chip's dedicated Ext Clock input from
-       the SK1 connector.  This pin is shared by all three counter
-       channels on the chip.
-
-  INSN_CONFIG_GET_CLOCK_SRC.  Returns the counter channel's current
-    clock source in data[1].  For internal clock sources, data[2] is set
-    to the period in ns.
-
-  INSN_CONFIG_SET_GATE_SRC.  Sets the counter channel's gate source as
-    specified in data[2] (this is a hardware-specific value).  Not
-    supported on PC214E.  For the other boards, valid gate sources are 0
-    to 7 as follows:
-
-      0.  VCC (internal +5V d.c.), i.e. gate permanently enabled.
-      1.  GND (internal 0V d.c.), i.e. gate permanently disabled.
-      2.  GAT n, the counter channel's dedicated GAT input from the SK1
-       connector.  (N.B. for other values, the counter channel's GATn
-       pin on the SK1 connector is an output!)
-      3.  /OUT n-2, the inverted output of counter channel n-2 (see note
-       2 below).
-      4.  Reserved.
-      5.  Reserved.
-      6.  Reserved.
-      7.  Reserved.
-
-  INSN_CONFIG_GET_GATE_SRC.  Returns the counter channel's current gate
-    source in data[2].
-
-Clock and gate interconnection notes:
-
-  1.  Clock source OUT n-1 is the output of the preceding channel on the
-  same counter subdevice if n > 0, or the output of channel 2 on the
-  preceding counter subdevice (see note 3) if n = 0.
-
-  2.  Gate source /OUT n-2 is the inverted output of channel 0 on the
-  same counter subdevice if n = 2, or the inverted output of channel n+1
-  on the preceding counter subdevice (see note 3) if n < 2.
-
-  3.  The counter subdevices are connected in a ring, so the highest
-  counter subdevice precedes the lowest.
-
-The 'INTERRUPT' subdevice pretends to be a digital input subdevice.  The
-digital inputs come from the interrupt status register.  The number of
-channels matches the number of interrupt sources.  The PC214E does not
-have an interrupt status register; see notes on 'INTERRUPT SOURCES'
-below.
-
-INTERRUPT SOURCES
-
-                   PC218E         PC212E      PC215E/PCI215
-                -------------  -------------  -------------
-  Sources              6              6              6
-   0              CTR-X1-OUT      PPI-X-C0       PPI-X-C0
-   1              CTR-X2-OUT      PPI-X-C3       PPI-X-C3
-   2              CTR-Y1-OUT     CTR-Y1-OUT      PPI-Y-C0
-   3              CTR-Y2-OUT     CTR-Y2-OUT      PPI-Y-C3
-   4              CTR-Z1-OUT     CTR-Z1-OUT     CTR-Z1-OUT
-   5              CTR-Z2-OUT     CTR-Z2-OUT     CTR-Z2-OUT
-
-                   PC214E      PC272E/PCI272
-                -------------  -------------
-  Sources              1              6
-   0               JUMPER-J5      PPI-X-C0
-   1                              PPI-X-C3
-   2                              PPI-Y-C0
-   3                              PPI-Y-C3
-   4                              PPI-Z-C0
-   5                              PPI-Z-C3
-
-When an interrupt source is enabled in the interrupt source enable
-register, a rising edge on the source signal latches the corresponding
-bit to 1 in the interrupt status register.
-
-When the interrupt status register value as a whole (actually, just the
-6 least significant bits) goes from zero to non-zero, the board will
-generate an interrupt.  For level-triggered hardware interrupts (PCI
-card), the interrupt will remain asserted until the interrupt status
-register is cleared to zero.  For edge-triggered hardware interrupts
-(ISA card), no further interrupts will occur until the interrupt status
-register is cleared to zero.  To clear a bit to zero in the interrupt
-status register, the corresponding interrupt source must be disabled
-in the interrupt source enable register (there is no separate interrupt
-clear register).
-
-The PC214E does not have an interrupt source enable register or an
-interrupt status register; its 'INTERRUPT' subdevice has a single
-channel and its interrupt source is selected by the position of jumper
-J5.
-
-COMMANDS
-
-The driver supports a read streaming acquisition command on the
-'INTERRUPT' subdevice.  The channel list selects the interrupt sources
-to be enabled.  All channels will be sampled together (convert_src ==
-TRIG_NOW).  The scan begins a short time after the hardware interrupt
-occurs, subject to interrupt latencies (scan_begin_src == TRIG_EXT,
-scan_begin_arg == 0).  The value read from the interrupt status register
-is packed into a short value, one bit per requested channel, in the
-order they appear in the channel list.
-*/
+ * Driver: amplc_dio200
+ * Description: Amplicon 200 Series Digital I/O
+ * Author: Ian Abbott <abbotti@mev.co.uk>
+ * Devices: [Amplicon] PC212E (pc212e), PC214E (pc214e), PC215E (pc215e),
+ *   PCI215 (pci215), PCIe215 (pcie215), PC218E (pc218e), PCIe236 (pcie236),
+ *   PC272E (pc272e), PCI272 (pci272), PCIe296 (pcie296)
+ * Updated: Wed, 24 Oct 2012 16:22:34 +0100
+ * Status: works
+ *
+ * Configuration options - PC212E, PC214E, PC215E, PC218E, PC272E:
+ *   [0] - I/O port base address
+ *   [1] - IRQ (optional, but commands won't work without it)
+ *
+ * Manual configuration of PCI(e) cards is not supported; they are configured
+ * automatically.
+ *
+ * Passing a zero for an option is the same as leaving it unspecified.
+ *
+ * SUBDEVICES
+ *
+ *                     PC212E         PC214E      PC215E/PCI215
+ *                  -------------  -------------  -------------
+ *   Subdevices           6              4              5
+ *    0                 PPI-X          PPI-X          PPI-X
+ *    1                 CTR-Y1         PPI-Y          PPI-Y
+ *    2                 CTR-Y2         CTR-Z1*        CTR-Z1
+ *    3                 CTR-Z1       INTERRUPT*       CTR-Z2
+ *    4                 CTR-Z2                      INTERRUPT
+ *    5               INTERRUPT
+ *
+ *                     PCIe215        PC218E         PCIe236
+ *                  -------------  -------------  -------------
+ *   Subdevices           8              7              8
+ *    0                 PPI-X          CTR-X1         PPI-X
+ *    1                 UNUSED         CTR-X2         UNUSED
+ *    2                 PPI-Y          CTR-Y1         UNUSED
+ *    3                 UNUSED         CTR-Y2         UNUSED
+ *    4                 CTR-Z1         CTR-Z1         CTR-Z1
+ *    5                 CTR-Z2         CTR-Z2         CTR-Z2
+ *    6                 TIMER        INTERRUPT        TIMER
+ *    7               INTERRUPT                     INTERRUPT
+ *
+ *                  PC272E/PCI272     PCIe296
+ *                  -------------  -------------
+ *   Subdevices           4              8
+ *    0                 PPI-X          PPI-X1
+ *    1                 PPI-Y          PPI-X2
+ *    2                 PPI-Z          PPI-Y1
+ *    3               INTERRUPT        PPI-Y2
+ *    4                                CTR-Z1
+ *    5                                CTR-Z2
+ *    6                                TIMER
+ *    7                              INTERRUPT
+ *
+ * Each PPI is a 8255 chip providing 24 DIO channels.  The DIO channels
+ * are configurable as inputs or outputs in four groups:
+ *
+ *   Port A  - channels  0 to  7
+ *   Port B  - channels  8 to 15
+ *   Port CL - channels 16 to 19
+ *   Port CH - channels 20 to 23
+ *
+ * Only mode 0 of the 8255 chips is supported.
+ *
+ * Each CTR is a 8254 chip providing 3 16-bit counter channels.  Each
+ * channel is configured individually with INSN_CONFIG instructions.  The
+ * specific type of configuration instruction is specified in data[0].
+ * Some configuration instructions expect an additional parameter in
+ * data[1]; others return a value in data[1].  The following configuration
+ * instructions are supported:
+ *
+ *   INSN_CONFIG_SET_COUNTER_MODE.  Sets the counter channel's mode and
+ *     BCD/binary setting specified in data[1].
+ *
+ *   INSN_CONFIG_8254_READ_STATUS.  Reads the status register value for the
+ *     counter channel into data[1].
+ *
+ *   INSN_CONFIG_SET_CLOCK_SRC.  Sets the counter channel's clock source as
+ *     specified in data[1] (this is a hardware-specific value).  Not
+ *     supported on PC214E.  For the other boards, valid clock sources are
+ *     0 to 7 as follows:
+ *
+ *       0.  CLK n, the counter channel's dedicated CLK input from the SK1
+ *         connector.  (N.B. for other values, the counter channel's CLKn
+ *         pin on the SK1 connector is an output!)
+ *       1.  Internal 10 MHz clock.
+ *       2.  Internal 1 MHz clock.
+ *       3.  Internal 100 kHz clock.
+ *       4.  Internal 10 kHz clock.
+ *       5.  Internal 1 kHz clock.
+ *       6.  OUT n-1, the output of counter channel n-1 (see note 1 below).
+ *       7.  Ext Clock, the counter chip's dedicated Ext Clock input from
+ *         the SK1 connector.  This pin is shared by all three counter
+ *         channels on the chip.
+ *
+ *     For the PCIe boards, clock sources in the range 0 to 31 are allowed
+ *     and the following additional clock sources are defined:
+ *
+ *       8.  HIGH logic level.
+ *       9.  LOW logic level.
+ *      10.  "Pattern present" signal.
+ *      11.  Internal 20 MHz clock.
+ *
+ *   INSN_CONFIG_GET_CLOCK_SRC.  Returns the counter channel's current
+ *     clock source in data[1].  For internal clock sources, data[2] is set
+ *     to the period in ns.
+ *
+ *   INSN_CONFIG_SET_GATE_SRC.  Sets the counter channel's gate source as
+ *     specified in data[2] (this is a hardware-specific value).  Not
+ *     supported on PC214E.  For the other boards, valid gate sources are 0
+ *     to 7 as follows:
+ *
+ *       0.  VCC (internal +5V d.c.), i.e. gate permanently enabled.
+ *       1.  GND (internal 0V d.c.), i.e. gate permanently disabled.
+ *       2.  GAT n, the counter channel's dedicated GAT input from the SK1
+ *         connector.  (N.B. for other values, the counter channel's GATn
+ *         pin on the SK1 connector is an output!)
+ *       3.  /OUT n-2, the inverted output of counter channel n-2 (see note
+ *         2 below).
+ *       4.  Reserved.
+ *       5.  Reserved.
+ *       6.  Reserved.
+ *       7.  Reserved.
+ *
+ *     For the PCIe boards, gate sources in the range 0 to 31 are allowed;
+ *     the following additional clock sources and clock sources 6 and 7 are
+ *     (re)defined:
+ *
+ *       6.  /GAT n, negated version of the counter channel's dedicated
+ *         GAT input (negated version of gate source 2).
+ *       7.  OUT n-2, the non-inverted output of counter channel n-2
+ *         (negated version of gate source 3).
+ *       8.  "Pattern present" signal, HIGH while pattern present.
+ *       9.  "Pattern occurred" latched signal, latches HIGH when pattern
+ *         occurs.
+ *      10.  "Pattern gone away" latched signal, latches LOW when pattern
+ *         goes away after it occurred.
+ *      11.  Negated "pattern present" signal, LOW while pattern present
+ *         (negated version of gate source 8).
+ *      12.  Negated "pattern occurred" latched signal, latches LOW when
+ *         pattern occurs (negated version of gate source 9).
+ *      13.  Negated "pattern gone away" latched signal, latches LOW when
+ *         pattern goes away after it occurred (negated version of gate
+ *         source 10).
+ *
+ *   INSN_CONFIG_GET_GATE_SRC.  Returns the counter channel's current gate
+ *     source in data[2].
+ *
+ * Clock and gate interconnection notes:
+ *
+ *   1.  Clock source OUT n-1 is the output of the preceding channel on the
+ *   same counter subdevice if n > 0, or the output of channel 2 on the
+ *   preceding counter subdevice (see note 3) if n = 0.
+ *
+ *   2.  Gate source /OUT n-2 is the inverted output of channel 0 on the
+ *   same counter subdevice if n = 2, or the inverted output of channel n+1
+ *   on the preceding counter subdevice (see note 3) if n < 2.
+ *
+ *   3.  The counter subdevices are connected in a ring, so the highest
+ *   counter subdevice precedes the lowest.
+ *
+ * The 'TIMER' subdevice is a free-running 32-bit timer subdevice.
+ *
+ * The 'INTERRUPT' subdevice pretends to be a digital input subdevice.  The
+ * digital inputs come from the interrupt status register.  The number of
+ * channels matches the number of interrupt sources.  The PC214E does not
+ * have an interrupt status register; see notes on 'INTERRUPT SOURCES'
+ * below.
+ *
+ * INTERRUPT SOURCES
+ *
+ *                     PC212E         PC214E      PC215E/PCI215
+ *                  -------------  -------------  -------------
+ *   Sources              6              1              6
+ *    0               PPI-X-C0       JUMPER-J5      PPI-X-C0
+ *    1               PPI-X-C3                      PPI-X-C3
+ *    2              CTR-Y1-OUT1                    PPI-Y-C0
+ *    3              CTR-Y2-OUT1                    PPI-Y-C3
+ *    4              CTR-Z1-OUT1                   CTR-Z1-OUT1
+ *    5              CTR-Z2-OUT1                   CTR-Z2-OUT1
+ *
+ *                     PCIe215        PC218E         PCIe236
+ *                  -------------  -------------  -------------
+ *   Sources              6              6              6
+ *    0               PPI-X-C0      CTR-X1-OUT1     PPI-X-C0
+ *    1               PPI-X-C3      CTR-X2-OUT1     PPI-X-C3
+ *    2               PPI-Y-C0      CTR-Y1-OUT1      unused
+ *    3               PPI-Y-C3      CTR-Y2-OUT1      unused
+ *    4              CTR-Z1-OUT1    CTR-Z1-OUT1    CTR-Z1-OUT1
+ *    5              CTR-Z2-OUT1    CTR-Z2-OUT1    CTR-Z2-OUT1
+ *
+ *                  PC272E/PCI272     PCIe296
+ *                  -------------  -------------
+ *   Sources              6              6
+ *    0               PPI-X-C0       PPI-X1-C0
+ *    1               PPI-X-C3       PPI-X1-C3
+ *    2               PPI-Y-C0       PPI-Y1-C0
+ *    3               PPI-Y-C3       PPI-Y1-C3
+ *    4               PPI-Z-C0      CTR-Z1-OUT1
+ *    5               PPI-Z-C3      CTR-Z2-OUT1
+ *
+ * When an interrupt source is enabled in the interrupt source enable
+ * register, a rising edge on the source signal latches the corresponding
+ * bit to 1 in the interrupt status register.
+ *
+ * When the interrupt status register value as a whole (actually, just the
+ * 6 least significant bits) goes from zero to non-zero, the board will
+ * generate an interrupt.  For level-triggered hardware interrupts (PCI
+ * card), the interrupt will remain asserted until the interrupt status
+ * register is cleared to zero.  For edge-triggered hardware interrupts
+ * (ISA card), no further interrupts will occur until the interrupt status
+ * register is cleared to zero.  To clear a bit to zero in the interrupt
+ * status register, the corresponding interrupt source must be disabled
+ * in the interrupt source enable register (there is no separate interrupt
+ * clear register).
+ *
+ * The PC214E does not have an interrupt source enable register or an
+ * interrupt status register; its 'INTERRUPT' subdevice has a single
+ * channel and its interrupt source is selected by the position of jumper
+ * J5.
+ *
+ * COMMANDS
+ *
+ * The driver supports a read streaming acquisition command on the
+ * 'INTERRUPT' subdevice.  The channel list selects the interrupt sources
+ * to be enabled.  All channels will be sampled together (convert_src ==
+ * TRIG_NOW).  The scan begins a short time after the hardware interrupt
+ * occurs, subject to interrupt latencies (scan_begin_src == TRIG_EXT,
+ * scan_begin_arg == 0).  The value read from the interrupt status register
+ * is packed into a short value, one bit per requested channel, in the
+ * order they appear in the channel list.
+ */
 
 #include <linux/interrupt.h>
 #include <linux/slab.h>
@@ -211,7 +264,6 @@ order they appear in the channel list.
 #include "../comedidev.h"
 
 #include "comedi_fc.h"
-#include "8255.h"
 #include "8253.h"
 
 #define DIO200_DRIVER_NAME     "amplc_dio200"
@@ -223,10 +275,22 @@ order they appear in the channel list.
 #define PCI_VENDOR_ID_AMPLICON 0x14dc
 #define PCI_DEVICE_ID_AMPLICON_PCI272 0x000a
 #define PCI_DEVICE_ID_AMPLICON_PCI215 0x000b
-#define PCI_DEVICE_ID_INVALID 0xffff
+#define PCI_DEVICE_ID_AMPLICON_PCIE236 0x0011
+#define PCI_DEVICE_ID_AMPLICON_PCIE215 0x0012
+#define PCI_DEVICE_ID_AMPLICON_PCIE296 0x0014
+
+/* 8255 control register bits */
+#define CR_C_LO_IO     0x01
+#define CR_B_IO                0x02
+#define CR_B_MODE      0x04
+#define CR_C_HI_IO     0x08
+#define CR_A_IO                0x10
+#define CR_A_MODE(a)   ((a)<<5)
+#define CR_CW          0x80
 
 /* 200 series registers */
 #define DIO200_IO_SIZE         0x20
+#define DIO200_PCIE_IO_SIZE    0x4000
 #define DIO200_XCLK_SCE                0x18    /* Group X clock selection register */
 #define DIO200_YCLK_SCE                0x19    /* Group Y clock selection register */
 #define DIO200_ZCLK_SCE                0x1a    /* Group Z clock selection register */
@@ -234,30 +298,78 @@ order they appear in the channel list.
 #define DIO200_YGAT_SCE                0x1c    /* Group Y gate selection register */
 #define DIO200_ZGAT_SCE                0x1d    /* Group Z gate selection register */
 #define DIO200_INT_SCE         0x1e    /* Interrupt enable/status register */
+/* Extra registers for new PCIe boards */
+#define DIO200_ENHANCE         0x20    /* 1 to enable enhanced features */
+#define DIO200_VERSION         0x24    /* Hardware version register */
+#define DIO200_TS_CONFIG       0x600   /* Timestamp timer config register */
+#define DIO200_TS_COUNT                0x602   /* Timestamp timer count register */
 
 /*
- * Macros for constructing value for DIO_200_?CLK_SCE and
+ * Functions for constructing value for DIO_200_?CLK_SCE and
  * DIO_200_?GAT_SCE registers:
  *
  * 'which' is: 0 for CTR-X1, CTR-Y1, CTR-Z1; 1 for CTR-X2, CTR-Y2 or CTR-Z2.
  * 'chan' is the channel: 0, 1 or 2.
- * 'source' is the signal source: 0 to 7.
+ * 'source' is the signal source: 0 to 7, or 0 to 31 for "enhanced" boards.
  */
-#define CLK_SCE(which, chan, source) (((which) << 5) | ((chan) << 3) | (source))
-#define GAT_SCE(which, chan, source) (((which) << 5) | ((chan) << 3) | (source))
+static unsigned char clk_gat_sce(unsigned int which, unsigned int chan,
+                                unsigned int source)
+{
+       return (which << 5) | (chan << 3) |
+              ((source & 030) << 3) | (source & 007);
+}
+
+static unsigned char clk_sce(unsigned int which, unsigned int chan,
+                            unsigned int source)
+{
+       return clk_gat_sce(which, chan, source);
+}
+
+static unsigned char gat_sce(unsigned int which, unsigned int chan,
+                            unsigned int source)
+{
+       return clk_gat_sce(which, chan, source);
+}
 
 /*
  * Periods of the internal clock sources in nanoseconds.
  */
-static const unsigned clock_period[8] = {
-       0,                      /* dedicated clock input/output pin */
-       100,                    /* 10 MHz */
-       1000,                   /* 1 MHz */
-       10000,                  /* 100 kHz */
-       100000,                 /* 10 kHz */
-       1000000,                /* 1 kHz */
-       0,                      /* OUT N-1 */
-       0                       /* group clock input pin */
+static const unsigned int clock_period[32] = {
+       [1] = 100,              /* 10 MHz */
+       [2] = 1000,             /* 1 MHz */
+       [3] = 10000,            /* 100 kHz */
+       [4] = 100000,           /* 10 kHz */
+       [5] = 1000000,          /* 1 kHz */
+       [11] = 50,              /* 20 MHz (enhanced boards) */
+       /* clock sources 12 and later reserved for enhanced boards */
+};
+
+/*
+ * Timestamp timer configuration register (for new PCIe boards).
+ */
+#define TS_CONFIG_RESET                0x100   /* Reset counter to zero. */
+#define TS_CONFIG_CLK_SRC_MASK 0x0FF   /* Clock source. */
+#define TS_CONFIG_MAX_CLK_SRC  2       /* Maximum clock source value. */
+
+/*
+ * Periods of the timestamp timer clock sources in nanoseconds.
+ */
+static const unsigned int ts_clock_period[TS_CONFIG_MAX_CLK_SRC + 1] = {
+       1,                      /* 1 nanosecond (but with 20 ns granularity). */
+       1000,                   /* 1 microsecond. */
+       1000000,                /* 1 millisecond. */
+};
+
+/*
+ * Register region.
+ */
+enum dio200_regtype { no_regtype = 0, io_regtype, mmio_regtype };
+struct dio200_region {
+       union {
+               unsigned long iobase;           /* I/O base address */
+               unsigned char __iomem *membase; /* mapped MMIO base address */
+       } u;
+       enum dio200_regtype regtype;
 };
 
 /*
@@ -269,13 +381,14 @@ enum dio200_bustype { isa_bustype, pci_bustype };
 enum dio200_model {
        pc212e_model,
        pc214e_model,
-       pc215e_model, pci215_model,
+       pc215e_model, pci215_model, pcie215_model,
        pc218e_model,
+       pcie236_model,
        pc272e_model, pci272_model,
-       anypci_model
+       pcie296_model,
 };
 
-enum dio200_layout {
+enum dio200_layout_idx {
 #if DO_ISA
        pc212_layout,
        pc214_layout,
@@ -284,7 +397,12 @@ enum dio200_layout {
 #if DO_ISA
        pc218_layout,
 #endif
-       pc272_layout
+       pc272_layout,
+#if DO_PCI
+       pcie215_layout,
+       pcie236_layout,
+       pcie296_layout,
+#endif
 };
 
 struct dio200_board {
@@ -292,7 +410,10 @@ struct dio200_board {
        unsigned short devid;
        enum dio200_bustype bustype;
        enum dio200_model model;
-       enum dio200_layout layout;
+       enum dio200_layout_idx layout;
+       unsigned char mainbar;
+       unsigned char mainshift;
+       unsigned int mainsize;
 };
 
 static const struct dio200_board dio200_boards[] = {
@@ -302,30 +423,35 @@ static const struct dio200_board dio200_boards[] = {
         .bustype = isa_bustype,
         .model = pc212e_model,
         .layout = pc212_layout,
+        .mainsize = DIO200_IO_SIZE,
         },
        {
         .name = "pc214e",
         .bustype = isa_bustype,
         .model = pc214e_model,
         .layout = pc214_layout,
+        .mainsize = DIO200_IO_SIZE,
         },
        {
         .name = "pc215e",
         .bustype = isa_bustype,
         .model = pc215e_model,
         .layout = pc215_layout,
+        .mainsize = DIO200_IO_SIZE,
         },
        {
         .name = "pc218e",
         .bustype = isa_bustype,
         .model = pc218e_model,
         .layout = pc218_layout,
+        .mainsize = DIO200_IO_SIZE,
         },
        {
         .name = "pc272e",
         .bustype = isa_bustype,
         .model = pc272e_model,
         .layout = pc272_layout,
+        .mainsize = DIO200_IO_SIZE,
         },
 #endif
 #if DO_PCI
@@ -335,6 +461,8 @@ static const struct dio200_board dio200_boards[] = {
         .bustype = pci_bustype,
         .model = pci215_model,
         .layout = pc215_layout,
+        .mainbar = 2,
+        .mainsize = DIO200_IO_SIZE,
         },
        {
         .name = "pci272",
@@ -342,12 +470,38 @@ static const struct dio200_board dio200_boards[] = {
         .bustype = pci_bustype,
         .model = pci272_model,
         .layout = pc272_layout,
+        .mainbar = 2,
+        .mainsize = DIO200_IO_SIZE,
         },
        {
-        .name = DIO200_DRIVER_NAME,
-        .devid = PCI_DEVICE_ID_INVALID,
+        .name = "pcie215",
+        .devid = PCI_DEVICE_ID_AMPLICON_PCIE215,
         .bustype = pci_bustype,
-        .model = anypci_model, /* wildcard */
+        .model = pcie215_model,
+        .layout = pcie215_layout,
+        .mainbar = 1,
+        .mainshift = 3,
+        .mainsize = DIO200_PCIE_IO_SIZE,
+        },
+       {
+        .name = "pcie236",
+        .devid = PCI_DEVICE_ID_AMPLICON_PCIE236,
+        .bustype = pci_bustype,
+        .model = pcie236_model,
+        .layout = pcie236_layout,
+        .mainbar = 1,
+        .mainshift = 3,
+        .mainsize = DIO200_PCIE_IO_SIZE,
+        },
+       {
+        .name = "pcie296",
+        .devid = PCI_DEVICE_ID_AMPLICON_PCIE296,
+        .bustype = pci_bustype,
+        .model = pcie296_model,
+        .layout = pcie296_layout,
+        .mainbar = 1,
+        .mainshift = 3,
+        .mainsize = DIO200_PCIE_IO_SIZE,
         },
 #endif
 };
@@ -357,20 +511,21 @@ static const struct dio200_board dio200_boards[] = {
  * layout.
  */
 
-enum dio200_sdtype { sd_none, sd_intr, sd_8255, sd_8254 };
+enum dio200_sdtype { sd_none, sd_intr, sd_8255, sd_8254, sd_timer };
 
-#define DIO200_MAX_SUBDEVS     7
+#define DIO200_MAX_SUBDEVS     8
 #define DIO200_MAX_ISNS                6
 
-struct dio200_layout_struct {
+struct dio200_layout {
        unsigned short n_subdevs;       /* number of subdevices */
        unsigned char sdtype[DIO200_MAX_SUBDEVS];       /* enum dio200_sdtype */
        unsigned char sdinfo[DIO200_MAX_SUBDEVS];       /* depends on sdtype */
        char has_int_sce;       /* has interrupt enable/status register */
        char has_clk_gat_sce;   /* has clock/gate selection registers */
+       char has_enhancements;  /* has enhanced features */
 };
 
-static const struct dio200_layout_struct dio200_layouts[] = {
+static const struct dio200_layout dio200_layouts[] = {
 #if DO_ISA
        [pc212_layout] = {
                          .n_subdevs = 6,
@@ -421,6 +576,38 @@ static const struct dio200_layout_struct dio200_layouts[] = {
                          .has_int_sce = 1,
                          .has_clk_gat_sce = 0,
                          },
+#if DO_PCI
+       [pcie215_layout] = {
+                         .n_subdevs = 8,
+                         .sdtype = {sd_8255, sd_none, sd_8255, sd_none,
+                                    sd_8254, sd_8254, sd_timer, sd_intr},
+                         .sdinfo = {0x00, 0x00, 0x08, 0x00,
+                                    0x10, 0x14, 0x00, 0x3F},
+                         .has_int_sce = 1,
+                         .has_clk_gat_sce = 1,
+                         .has_enhancements = 1,
+                         },
+       [pcie236_layout] = {
+                         .n_subdevs = 8,
+                         .sdtype = {sd_8255, sd_none, sd_none, sd_none,
+                                    sd_8254, sd_8254, sd_timer, sd_intr},
+                         .sdinfo = {0x00, 0x00, 0x00, 0x00,
+                                    0x10, 0x14, 0x00, 0x3F},
+                         .has_int_sce = 1,
+                         .has_clk_gat_sce = 1,
+                         .has_enhancements = 1,
+                         },
+       [pcie296_layout] = {
+                         .n_subdevs = 8,
+                         .sdtype = {sd_8255, sd_8255, sd_8255, sd_8255,
+                                    sd_8254, sd_8254, sd_timer, sd_intr},
+                         .sdinfo = {0x00, 0x04, 0x08, 0x0C,
+                                    0x10, 0x14, 0x00, 0x3F},
+                         .has_int_sce = 1,
+                         .has_clk_gat_sce = 1,
+                         .has_enhancements = 1,
+                         },
+#endif
 };
 
 /* this structure is for data unique to this hardware driver.  If
@@ -428,31 +615,46 @@ static const struct dio200_layout_struct dio200_layouts[] = {
    feel free to suggest moving the variable to the struct comedi_device struct.
  */
 struct dio200_private {
+       struct dio200_region io;        /* Register region */
        int intr_sd;
 };
 
 struct dio200_subdev_8254 {
-       unsigned long iobase;   /* Counter base address */
-       unsigned long clk_sce_iobase;   /* CLK_SCE base address */
-       unsigned long gat_sce_iobase;   /* GAT_SCE base address */
-       int which;              /* Bit 5 of CLK_SCE or GAT_SCE */
-       int has_clk_gat_sce;
-       unsigned clock_src[3];  /* Current clock sources */
-       unsigned gate_src[3];   /* Current gate sources */
+       unsigned int ofs;               /* Counter base offset */
+       unsigned int clk_sce_ofs;       /* CLK_SCE base address */
+       unsigned int gat_sce_ofs;       /* GAT_SCE base address */
+       int which;                      /* Bit 5 of CLK_SCE or GAT_SCE */
+       unsigned int clock_src[3];      /* Current clock sources */
+       unsigned int gate_src[3];       /* Current gate sources */
        spinlock_t spinlock;
 };
 
+struct dio200_subdev_8255 {
+       unsigned int ofs;               /* DIO base offset */
+};
+
 struct dio200_subdev_intr {
-       unsigned long iobase;
+       unsigned int ofs;
        spinlock_t spinlock;
        int active;
-       int has_int_sce;
        unsigned int valid_isns;
        unsigned int enabled_isns;
        unsigned int stopcount;
        int continuous;
 };
 
+static inline const struct dio200_layout *
+dio200_board_layout(const struct dio200_board *board)
+{
+       return &dio200_layouts[board->layout];
+}
+
+static inline const struct dio200_layout *
+dio200_dev_layout(struct comedi_device *dev)
+{
+       return dio200_board_layout(comedi_board(dev));
+}
+
 static inline bool is_pci_board(const struct dio200_board *board)
 {
        return DO_PCI && board->bustype == pci_bustype;
@@ -463,6 +665,70 @@ static inline bool is_isa_board(const struct dio200_board *board)
        return DO_ISA && board->bustype == isa_bustype;
 }
 
+/*
+ * Read 8-bit register.
+ */
+static unsigned char dio200_read8(struct comedi_device *dev,
+                                 unsigned int offset)
+{
+       const struct dio200_board *thisboard = comedi_board(dev);
+       struct dio200_private *devpriv = dev->private;
+
+       offset <<= thisboard->mainshift;
+       if (devpriv->io.regtype == io_regtype)
+               return inb(devpriv->io.u.iobase + offset);
+       else
+               return readb(devpriv->io.u.membase + offset);
+}
+
+/*
+ * Write 8-bit register.
+ */
+static void dio200_write8(struct comedi_device *dev, unsigned int offset,
+                         unsigned char val)
+{
+       const struct dio200_board *thisboard = comedi_board(dev);
+       struct dio200_private *devpriv = dev->private;
+
+       offset <<= thisboard->mainshift;
+       if (devpriv->io.regtype == io_regtype)
+               outb(val, devpriv->io.u.iobase + offset);
+       else
+               writeb(val, devpriv->io.u.membase + offset);
+}
+
+/*
+ * Read 32-bit register.
+ */
+static unsigned int dio200_read32(struct comedi_device *dev,
+                                 unsigned int offset)
+{
+       const struct dio200_board *thisboard = comedi_board(dev);
+       struct dio200_private *devpriv = dev->private;
+
+       offset <<= thisboard->mainshift;
+       if (devpriv->io.regtype == io_regtype)
+               return inl(devpriv->io.u.iobase + offset);
+       else
+               return readl(devpriv->io.u.membase + offset);
+}
+
+/*
+ * Write 32-bit register.
+ */
+static void dio200_write32(struct comedi_device *dev, unsigned int offset,
+                          unsigned int val)
+{
+       const struct dio200_board *thisboard = comedi_board(dev);
+       struct dio200_private *devpriv = dev->private;
+
+       offset <<= thisboard->mainshift;
+       if (devpriv->io.regtype == io_regtype)
+               outl(val, devpriv->io.u.iobase + offset);
+       else
+               writel(val, devpriv->io.u.membase + offset);
+}
+
 /*
  * This function looks for a board matching the supplied PCI device.
  */
@@ -478,49 +744,6 @@ dio200_find_pci_board(struct pci_dev *pci_dev)
        return NULL;
 }
 
-/*
- * This function looks for a PCI device matching the requested board name,
- * bus and slot.
- */
-static struct pci_dev *dio200_find_pci_dev(struct comedi_device *dev,
-                                          struct comedi_devconfig *it)
-{
-       const struct dio200_board *thisboard = comedi_board(dev);
-       struct pci_dev *pci_dev = NULL;
-       int bus = it->options[0];
-       int slot = it->options[1];
-
-       for_each_pci_dev(pci_dev) {
-               if (bus || slot) {
-                       if (bus != pci_dev->bus->number ||
-                           slot != PCI_SLOT(pci_dev->devfn))
-                               continue;
-               }
-               if (pci_dev->vendor != PCI_VENDOR_ID_AMPLICON)
-                       continue;
-
-               if (thisboard->model == anypci_model) {
-                       /* Wildcard board matches any supported PCI board. */
-                       const struct dio200_board *foundboard;
-
-                       foundboard = dio200_find_pci_board(pci_dev);
-                       if (foundboard == NULL)
-                               continue;
-                       /* Replace wildcard board_ptr. */
-                       dev->board_ptr = foundboard;
-               } else {
-                       /* Match specific model name. */
-                       if (pci_dev->device != thisboard->devid)
-                               continue;
-               }
-               return pci_dev;
-       }
-       dev_err(dev->class_dev,
-               "No supported board found! (req. bus %d, slot %d)\n",
-               bus, slot);
-       return NULL;
-}
-
 /*
  * This function checks and requests an I/O region, reporting an error
  * if there is a conflict.
@@ -545,11 +768,12 @@ dio200_subdev_intr_insn_bits(struct comedi_device *dev,
                             struct comedi_subdevice *s,
                             struct comedi_insn *insn, unsigned int *data)
 {
+       const struct dio200_layout *layout = dio200_dev_layout(dev);
        struct dio200_subdev_intr *subpriv = s->private;
 
-       if (subpriv->has_int_sce) {
+       if (layout->has_int_sce) {
                /* Just read the interrupt status register.  */
-               data[1] = inb(subpriv->iobase) & subpriv->valid_isns;
+               data[1] = dio200_read8(dev, subpriv->ofs) & subpriv->valid_isns;
        } else {
                /* No interrupt status register. */
                data[0] = 0;
@@ -564,12 +788,13 @@ dio200_subdev_intr_insn_bits(struct comedi_device *dev,
 static void dio200_stop_intr(struct comedi_device *dev,
                             struct comedi_subdevice *s)
 {
+       const struct dio200_layout *layout = dio200_dev_layout(dev);
        struct dio200_subdev_intr *subpriv = s->private;
 
        subpriv->active = 0;
        subpriv->enabled_isns = 0;
-       if (subpriv->has_int_sce)
-               outb(0, subpriv->iobase);
+       if (layout->has_int_sce)
+               dio200_write8(dev, subpriv->ofs, 0);
 }
 
 /*
@@ -580,6 +805,7 @@ static int dio200_start_intr(struct comedi_device *dev,
 {
        unsigned int n;
        unsigned isn_bits;
+       const struct dio200_layout *layout = dio200_dev_layout(dev);
        struct dio200_subdev_intr *subpriv = s->private;
        struct comedi_cmd *cmd = &s->async->cmd;
        int retval = 0;
@@ -599,8 +825,8 @@ static int dio200_start_intr(struct comedi_device *dev,
                isn_bits &= subpriv->valid_isns;
                /* Enable interrupt sources. */
                subpriv->enabled_isns = isn_bits;
-               if (subpriv->has_int_sce)
-                       outb(isn_bits, subpriv->iobase);
+               if (layout->has_int_sce)
+                       dio200_write8(dev, subpriv->ofs, isn_bits);
        }
 
        return retval;
@@ -642,6 +868,7 @@ dio200_inttrig_start_intr(struct comedi_device *dev, struct comedi_subdevice *s,
 static int dio200_handle_read_intr(struct comedi_device *dev,
                                   struct comedi_subdevice *s)
 {
+       const struct dio200_layout *layout = dio200_dev_layout(dev);
        struct dio200_subdev_intr *subpriv = s->private;
        unsigned triggered;
        unsigned intstat;
@@ -653,7 +880,7 @@ static int dio200_handle_read_intr(struct comedi_device *dev,
 
        spin_lock_irqsave(&subpriv->spinlock, flags);
        oldevents = s->async->events;
-       if (subpriv->has_int_sce) {
+       if (layout->has_int_sce) {
                /*
                 * Collect interrupt sources that have triggered and disable
                 * them temporarily.  Loop around until no extra interrupt
@@ -665,11 +892,11 @@ static int dio200_handle_read_intr(struct comedi_device *dev,
                 * loop in case of misconfiguration.
                 */
                cur_enabled = subpriv->enabled_isns;
-               while ((intstat = (inb(subpriv->iobase) & subpriv->valid_isns
-                                  & ~triggered)) != 0) {
+               while ((intstat = (dio200_read8(dev, subpriv->ofs) &
+                                  subpriv->valid_isns & ~triggered)) != 0) {
                        triggered |= intstat;
                        cur_enabled &= ~triggered;
-                       outb(cur_enabled, subpriv->iobase);
+                       dio200_write8(dev, subpriv->ofs, cur_enabled);
                }
        } else {
                /*
@@ -687,8 +914,8 @@ static int dio200_handle_read_intr(struct comedi_device *dev,
                 * Reenable them NOW to minimize the time they are disabled.
                 */
                cur_enabled = subpriv->enabled_isns;
-               if (subpriv->has_int_sce)
-                       outb(cur_enabled, subpriv->iobase);
+               if (layout->has_int_sce)
+                       dio200_write8(dev, subpriv->ofs, cur_enabled);
 
                if (subpriv->active) {
                        /*
@@ -894,9 +1121,9 @@ static int dio200_subdev_intr_cmd(struct comedi_device *dev,
  */
 static int
 dio200_subdev_intr_init(struct comedi_device *dev, struct comedi_subdevice *s,
-                       unsigned long iobase, unsigned valid_isns,
-                       int has_int_sce)
+                       unsigned int offset, unsigned valid_isns)
 {
+       const struct dio200_layout *layout = dio200_dev_layout(dev);
        struct dio200_subdev_intr *subpriv;
 
        subpriv = kzalloc(sizeof(*subpriv), GFP_KERNEL);
@@ -904,18 +1131,18 @@ dio200_subdev_intr_init(struct comedi_device *dev, struct comedi_subdevice *s,
                dev_err(dev->class_dev, "error! out of memory!\n");
                return -ENOMEM;
        }
-       subpriv->iobase = iobase;
-       subpriv->has_int_sce = has_int_sce;
+       subpriv->ofs = offset;
        subpriv->valid_isns = valid_isns;
        spin_lock_init(&subpriv->spinlock);
 
-       if (has_int_sce)
-               outb(0, subpriv->iobase);       /* Disable interrupt sources. */
+       if (layout->has_int_sce)
+               /* Disable interrupt sources. */
+               dio200_write8(dev, subpriv->ofs, 0);
 
        s->private = subpriv;
        s->type = COMEDI_SUBD_DI;
        s->subdev_flags = SDF_READABLE | SDF_CMD_READ;
-       if (has_int_sce) {
+       if (layout->has_int_sce) {
                s->n_chan = DIO200_MAX_ISNS;
                s->len_chanlist = DIO200_MAX_ISNS;
        } else {
@@ -967,6 +1194,73 @@ static irqreturn_t dio200_interrupt(int irq, void *d)
        return IRQ_RETVAL(handled);
 }
 
+/*
+ * Read an '8254' counter subdevice channel.
+ */
+static unsigned int
+dio200_subdev_8254_read_chan(struct comedi_device *dev,
+                            struct comedi_subdevice *s, unsigned int chan)
+{
+       struct dio200_subdev_8254 *subpriv = s->private;
+       unsigned int val;
+
+       /* latch counter */
+       val = chan << 6;
+       dio200_write8(dev, subpriv->ofs + i8254_control_reg, val);
+       /* read lsb, msb */
+       val = dio200_read8(dev, subpriv->ofs + chan);
+       val += dio200_read8(dev, subpriv->ofs + chan) << 8;
+       return val;
+}
+
+/*
+ * Write an '8254' subdevice channel.
+ */
+static void
+dio200_subdev_8254_write_chan(struct comedi_device *dev,
+                             struct comedi_subdevice *s, unsigned int chan,
+                             unsigned int count)
+{
+       struct dio200_subdev_8254 *subpriv = s->private;
+
+       /* write lsb, msb */
+       dio200_write8(dev, subpriv->ofs + chan, count & 0xff);
+       dio200_write8(dev, subpriv->ofs + chan, (count >> 8) & 0xff);
+}
+
+/*
+ * Set mode of an '8254' subdevice channel.
+ */
+static void
+dio200_subdev_8254_set_mode(struct comedi_device *dev,
+                           struct comedi_subdevice *s, unsigned int chan,
+                           unsigned int mode)
+{
+       struct dio200_subdev_8254 *subpriv = s->private;
+       unsigned int byte;
+
+       byte = chan << 6;
+       byte |= 0x30;           /* access order: lsb, msb */
+       byte |= (mode & 0xf);   /* counter mode and BCD|binary */
+       dio200_write8(dev, subpriv->ofs + i8254_control_reg, byte);
+}
+
+/*
+ * Read status byte of an '8254' counter subdevice channel.
+ */
+static unsigned int
+dio200_subdev_8254_status(struct comedi_device *dev,
+                         struct comedi_subdevice *s, unsigned int chan)
+{
+       struct dio200_subdev_8254 *subpriv = s->private;
+
+       /* latch status */
+       dio200_write8(dev, subpriv->ofs + i8254_control_reg,
+                     0xe0 | (2 << chan));
+       /* read status */
+       return dio200_read8(dev, subpriv->ofs + chan);
+}
+
 /*
  * Handle 'insn_read' for an '8254' counter subdevice.
  */
@@ -976,13 +1270,15 @@ dio200_subdev_8254_read(struct comedi_device *dev, struct comedi_subdevice *s,
 {
        struct dio200_subdev_8254 *subpriv = s->private;
        int chan = CR_CHAN(insn->chanspec);
+       unsigned int n;
        unsigned long flags;
 
-       spin_lock_irqsave(&subpriv->spinlock, flags);
-       data[0] = i8254_read(subpriv->iobase, 0, chan);
-       spin_unlock_irqrestore(&subpriv->spinlock, flags);
-
-       return 1;
+       for (n = 0; n < insn->n; n++) {
+               spin_lock_irqsave(&subpriv->spinlock, flags);
+               data[n] = dio200_subdev_8254_read_chan(dev, s, chan);
+               spin_unlock_irqrestore(&subpriv->spinlock, flags);
+       }
+       return insn->n;
 }
 
 /*
@@ -994,34 +1290,40 @@ dio200_subdev_8254_write(struct comedi_device *dev, struct comedi_subdevice *s,
 {
        struct dio200_subdev_8254 *subpriv = s->private;
        int chan = CR_CHAN(insn->chanspec);
+       unsigned int n;
        unsigned long flags;
 
-       spin_lock_irqsave(&subpriv->spinlock, flags);
-       i8254_write(subpriv->iobase, 0, chan, data[0]);
-       spin_unlock_irqrestore(&subpriv->spinlock, flags);
-
-       return 1;
+       for (n = 0; n < insn->n; n++) {
+               spin_lock_irqsave(&subpriv->spinlock, flags);
+               dio200_subdev_8254_write_chan(dev, s, chan, data[n]);
+               spin_unlock_irqrestore(&subpriv->spinlock, flags);
+       }
+       return insn->n;
 }
 
 /*
  * Set gate source for an '8254' counter subdevice channel.
  */
 static int
-dio200_set_gate_src(struct dio200_subdev_8254 *subpriv,
-                   unsigned int counter_number, unsigned int gate_src)
+dio200_subdev_8254_set_gate_src(struct comedi_device *dev,
+                               struct comedi_subdevice *s,
+                               unsigned int counter_number,
+                               unsigned int gate_src)
 {
+       const struct dio200_layout *layout = dio200_dev_layout(dev);
+       struct dio200_subdev_8254 *subpriv = s->private;
        unsigned char byte;
 
-       if (!subpriv->has_clk_gat_sce)
+       if (!layout->has_clk_gat_sce)
                return -1;
        if (counter_number > 2)
                return -1;
-       if (gate_src > 7)
+       if (gate_src > (layout->has_enhancements ? 31 : 7))
                return -1;
 
        subpriv->gate_src[counter_number] = gate_src;
-       byte = GAT_SCE(subpriv->which, counter_number, gate_src);
-       outb(byte, subpriv->gat_sce_iobase);
+       byte = gat_sce(subpriv->which, counter_number, gate_src);
+       dio200_write8(dev, subpriv->gat_sce_ofs, byte);
 
        return 0;
 }
@@ -1030,10 +1332,14 @@ dio200_set_gate_src(struct dio200_subdev_8254 *subpriv,
  * Get gate source for an '8254' counter subdevice channel.
  */
 static int
-dio200_get_gate_src(struct dio200_subdev_8254 *subpriv,
-                   unsigned int counter_number)
+dio200_subdev_8254_get_gate_src(struct comedi_device *dev,
+                               struct comedi_subdevice *s,
+                               unsigned int counter_number)
 {
-       if (!subpriv->has_clk_gat_sce)
+       const struct dio200_layout *layout = dio200_dev_layout(dev);
+       struct dio200_subdev_8254 *subpriv = s->private;
+
+       if (!layout->has_clk_gat_sce)
                return -1;
        if (counter_number > 2)
                return -1;
@@ -1045,21 +1351,25 @@ dio200_get_gate_src(struct dio200_subdev_8254 *subpriv,
  * Set clock source for an '8254' counter subdevice channel.
  */
 static int
-dio200_set_clock_src(struct dio200_subdev_8254 *subpriv,
-                    unsigned int counter_number, unsigned int clock_src)
+dio200_subdev_8254_set_clock_src(struct comedi_device *dev,
+                                struct comedi_subdevice *s,
+                                unsigned int counter_number,
+                                unsigned int clock_src)
 {
+       const struct dio200_layout *layout = dio200_dev_layout(dev);
+       struct dio200_subdev_8254 *subpriv = s->private;
        unsigned char byte;
 
-       if (!subpriv->has_clk_gat_sce)
+       if (!layout->has_clk_gat_sce)
                return -1;
        if (counter_number > 2)
                return -1;
-       if (clock_src > 7)
+       if (clock_src > (layout->has_enhancements ? 31 : 7))
                return -1;
 
        subpriv->clock_src[counter_number] = clock_src;
-       byte = CLK_SCE(subpriv->which, counter_number, clock_src);
-       outb(byte, subpriv->clk_sce_iobase);
+       byte = clk_sce(subpriv->which, counter_number, clock_src);
+       dio200_write8(dev, subpriv->clk_sce_ofs, byte);
 
        return 0;
 }
@@ -1068,12 +1378,16 @@ dio200_set_clock_src(struct dio200_subdev_8254 *subpriv,
  * Get clock source for an '8254' counter subdevice channel.
  */
 static int
-dio200_get_clock_src(struct dio200_subdev_8254 *subpriv,
-                    unsigned int counter_number, unsigned int *period_ns)
+dio200_subdev_8254_get_clock_src(struct comedi_device *dev,
+                                struct comedi_subdevice *s,
+                                unsigned int counter_number,
+                                unsigned int *period_ns)
 {
+       const struct dio200_layout *layout = dio200_dev_layout(dev);
+       struct dio200_subdev_8254 *subpriv = s->private;
        unsigned clock_src;
 
-       if (!subpriv->has_clk_gat_sce)
+       if (!layout->has_clk_gat_sce)
                return -1;
        if (counter_number > 2)
                return -1;
@@ -1098,20 +1412,21 @@ dio200_subdev_8254_config(struct comedi_device *dev, struct comedi_subdevice *s,
        spin_lock_irqsave(&subpriv->spinlock, flags);
        switch (data[0]) {
        case INSN_CONFIG_SET_COUNTER_MODE:
-               ret = i8254_set_mode(subpriv->iobase, 0, chan, data[1]);
-               if (ret < 0)
+               if (data[1] > (I8254_MODE5 | I8254_BINARY))
                        ret = -EINVAL;
+               else
+                       dio200_subdev_8254_set_mode(dev, s, chan, data[1]);
                break;
        case INSN_CONFIG_8254_READ_STATUS:
-               data[1] = i8254_status(subpriv->iobase, 0, chan);
+               data[1] = dio200_subdev_8254_status(dev, s, chan);
                break;
        case INSN_CONFIG_SET_GATE_SRC:
-               ret = dio200_set_gate_src(subpriv, chan, data[2]);
+               ret = dio200_subdev_8254_set_gate_src(dev, s, chan, data[2]);
                if (ret < 0)
                        ret = -EINVAL;
                break;
        case INSN_CONFIG_GET_GATE_SRC:
-               ret = dio200_get_gate_src(subpriv, chan);
+               ret = dio200_subdev_8254_get_gate_src(dev, s, chan);
                if (ret < 0) {
                        ret = -EINVAL;
                        break;
@@ -1119,12 +1434,12 @@ dio200_subdev_8254_config(struct comedi_device *dev, struct comedi_subdevice *s,
                data[2] = ret;
                break;
        case INSN_CONFIG_SET_CLOCK_SRC:
-               ret = dio200_set_clock_src(subpriv, chan, data[1]);
+               ret = dio200_subdev_8254_set_clock_src(dev, s, chan, data[1]);
                if (ret < 0)
                        ret = -EINVAL;
                break;
        case INSN_CONFIG_GET_CLOCK_SRC:
-               ret = dio200_get_clock_src(subpriv, chan, &data[2]);
+               ret = dio200_subdev_8254_get_clock_src(dev, s, chan, &data[2]);
                if (ret < 0) {
                        ret = -EINVAL;
                        break;
@@ -1141,15 +1456,12 @@ dio200_subdev_8254_config(struct comedi_device *dev, struct comedi_subdevice *s,
 
 /*
  * This function initializes an '8254' counter subdevice.
- *
- * Note: iobase is the base address of the board, not the subdevice;
- * offset is the offset to the 8254 chip.
  */
 static int
 dio200_subdev_8254_init(struct comedi_device *dev, struct comedi_subdevice *s,
-                       unsigned long iobase, unsigned offset,
-                       int has_clk_gat_sce)
+                       unsigned int offset)
 {
+       const struct dio200_layout *layout = dio200_dev_layout(dev);
        struct dio200_subdev_8254 *subpriv;
        unsigned int chan;
 
@@ -1169,27 +1481,24 @@ dio200_subdev_8254_init(struct comedi_device *dev, struct comedi_subdevice *s,
        s->insn_config = dio200_subdev_8254_config;
 
        spin_lock_init(&subpriv->spinlock);
-       subpriv->iobase = offset + iobase;
-       subpriv->has_clk_gat_sce = has_clk_gat_sce;
-       if (has_clk_gat_sce) {
+       subpriv->ofs = offset;
+       if (layout->has_clk_gat_sce) {
                /* Derive CLK_SCE and GAT_SCE register offsets from
                 * 8254 offset. */
-               subpriv->clk_sce_iobase =
-                   DIO200_XCLK_SCE + (offset >> 3) + iobase;
-               subpriv->gat_sce_iobase =
-                   DIO200_XGAT_SCE + (offset >> 3) + iobase;
+               subpriv->clk_sce_ofs = DIO200_XCLK_SCE + (offset >> 3);
+               subpriv->gat_sce_ofs = DIO200_XGAT_SCE + (offset >> 3);
                subpriv->which = (offset >> 2) & 1;
        }
 
        /* Initialize channels. */
        for (chan = 0; chan < 3; chan++) {
-               i8254_set_mode(subpriv->iobase, 0, chan,
-                              I8254_MODE0 | I8254_BINARY);
-               if (subpriv->has_clk_gat_sce) {
+               dio200_subdev_8254_set_mode(dev, s, chan,
+                                           I8254_MODE0 | I8254_BINARY);
+               if (layout->has_clk_gat_sce) {
                        /* Gate source 0 is VCC (logic 1). */
-                       dio200_set_gate_src(subpriv, chan, 0);
+                       dio200_subdev_8254_set_gate_src(dev, s, chan, 0);
                        /* Clock source 0 is the dedicated clock input. */
-                       dio200_set_clock_src(subpriv, chan, 0);
+                       dio200_subdev_8254_set_clock_src(dev, s, chan, 0);
                }
        }
 
@@ -1207,16 +1516,294 @@ dio200_subdev_8254_cleanup(struct comedi_device *dev,
        kfree(subpriv);
 }
 
+/*
+ * This function sets I/O directions for an '8255' DIO subdevice.
+ */
+static void dio200_subdev_8255_set_dir(struct comedi_device *dev,
+                                      struct comedi_subdevice *s)
+{
+       struct dio200_subdev_8255 *subpriv = s->private;
+       int config;
+
+       config = CR_CW;
+       /* 1 in io_bits indicates output, 1 in config indicates input */
+       if (!(s->io_bits & 0x0000ff))
+               config |= CR_A_IO;
+       if (!(s->io_bits & 0x00ff00))
+               config |= CR_B_IO;
+       if (!(s->io_bits & 0x0f0000))
+               config |= CR_C_LO_IO;
+       if (!(s->io_bits & 0xf00000))
+               config |= CR_C_HI_IO;
+       dio200_write8(dev, subpriv->ofs + 3, config);
+}
+
+/*
+ * Handle 'insn_bits' for an '8255' DIO subdevice.
+ */
+static int dio200_subdev_8255_bits(struct comedi_device *dev,
+                                  struct comedi_subdevice *s,
+                                  struct comedi_insn *insn, unsigned int *data)
+{
+       struct dio200_subdev_8255 *subpriv = s->private;
+
+       if (data[0]) {
+               s->state &= ~data[0];
+               s->state |= (data[0] & data[1]);
+               if (data[0] & 0xff)
+                       dio200_write8(dev, subpriv->ofs, s->state & 0xff);
+               if (data[0] & 0xff00)
+                       dio200_write8(dev, subpriv->ofs + 1,
+                                     (s->state >> 8) & 0xff);
+               if (data[0] & 0xff0000)
+                       dio200_write8(dev, subpriv->ofs + 2,
+                                     (s->state >> 16) & 0xff);
+       }
+       data[1] = dio200_read8(dev, subpriv->ofs);
+       data[1] |= dio200_read8(dev, subpriv->ofs + 1) << 8;
+       data[1] |= dio200_read8(dev, subpriv->ofs + 2) << 16;
+       return 2;
+}
+
+/*
+ * Handle 'insn_config' for an '8255' DIO subdevice.
+ */
+static int dio200_subdev_8255_config(struct comedi_device *dev,
+                                    struct comedi_subdevice *s,
+                                    struct comedi_insn *insn,
+                                    unsigned int *data)
+{
+       unsigned int mask;
+       unsigned int bits;
+
+       mask = 1 << CR_CHAN(insn->chanspec);
+       if (mask & 0x0000ff)
+               bits = 0x0000ff;
+       else if (mask & 0x00ff00)
+               bits = 0x00ff00;
+       else if (mask & 0x0f0000)
+               bits = 0x0f0000;
+       else
+               bits = 0xf00000;
+       switch (data[0]) {
+       case INSN_CONFIG_DIO_INPUT:
+               s->io_bits &= ~bits;
+               break;
+       case INSN_CONFIG_DIO_OUTPUT:
+               s->io_bits |= bits;
+               break;
+       case INSN_CONFIG_DIO_QUERY:
+               data[1] = (s->io_bits & bits) ? COMEDI_OUTPUT : COMEDI_INPUT;
+               return insn->n;
+               break;
+       default:
+               return -EINVAL;
+       }
+       dio200_subdev_8255_set_dir(dev, s);
+       return 1;
+}
+
+/*
+ * This function initializes an '8255' DIO subdevice.
+ *
+ * offset is the offset to the 8255 chip.
+ */
+static int dio200_subdev_8255_init(struct comedi_device *dev,
+                                  struct comedi_subdevice *s,
+                                  unsigned int offset)
+{
+       struct dio200_subdev_8255 *subpriv;
+
+       subpriv = kzalloc(sizeof(*subpriv), GFP_KERNEL);
+       if (!subpriv)
+               return -ENOMEM;
+       subpriv->ofs = offset;
+       s->private = subpriv;
+       s->type = COMEDI_SUBD_DIO;
+       s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
+       s->n_chan = 24;
+       s->range_table = &range_digital;
+       s->maxdata = 1;
+       s->insn_bits = dio200_subdev_8255_bits;
+       s->insn_config = dio200_subdev_8255_config;
+       s->state = 0;
+       s->io_bits = 0;
+       dio200_subdev_8255_set_dir(dev, s);
+       return 0;
+}
+
+/*
+ * This function cleans up an '8255' DIO subdevice.
+ */
+static void dio200_subdev_8255_cleanup(struct comedi_device *dev,
+                                      struct comedi_subdevice *s)
+{
+       struct dio200_subdev_8255 *subpriv = s->private;
+
+       kfree(subpriv);
+}
+
+/*
+ * Handle 'insn_read' for a timer subdevice.
+ */
+static int dio200_subdev_timer_read(struct comedi_device *dev,
+                                   struct comedi_subdevice *s,
+                                   struct comedi_insn *insn,
+                                   unsigned int *data)
+{
+       unsigned int n;
+
+       for (n = 0; n < insn->n; n++)
+               data[n] = dio200_read32(dev, DIO200_TS_COUNT);
+       return n;
+}
+
+/*
+ * Reset timer subdevice.
+ */
+static void dio200_subdev_timer_reset(struct comedi_device *dev,
+                                     struct comedi_subdevice *s)
+{
+       unsigned int clock;
+
+       clock = dio200_read32(dev, DIO200_TS_CONFIG) & TS_CONFIG_CLK_SRC_MASK;
+       dio200_write32(dev, DIO200_TS_CONFIG, clock | TS_CONFIG_RESET);
+       dio200_write32(dev, DIO200_TS_CONFIG, clock);
+}
+
+/*
+ * Get timer subdevice clock source and period.
+ */
+static void dio200_subdev_timer_get_clock_src(struct comedi_device *dev,
+                                             struct comedi_subdevice *s,
+                                             unsigned int *src,
+                                             unsigned int *period)
+{
+       unsigned int clk;
+
+       clk = dio200_read32(dev, DIO200_TS_CONFIG) & TS_CONFIG_CLK_SRC_MASK;
+       *src = clk;
+       *period = (clk < ARRAY_SIZE(ts_clock_period)) ?
+                 ts_clock_period[clk] : 0;
+}
+
+/*
+ * Set timer subdevice clock source.
+ */
+static int dio200_subdev_timer_set_clock_src(struct comedi_device *dev,
+                                            struct comedi_subdevice *s,
+                                            unsigned int src)
+{
+       if (src > TS_CONFIG_MAX_CLK_SRC)
+               return -EINVAL;
+       dio200_write32(dev, DIO200_TS_CONFIG, src);
+       return 0;
+}
+
+/*
+ * Handle 'insn_config' for a timer subdevice.
+ */
+static int dio200_subdev_timer_config(struct comedi_device *dev,
+                                     struct comedi_subdevice *s,
+                                     struct comedi_insn *insn,
+                                     unsigned int *data)
+{
+       int ret = 0;
+
+       switch (data[0]) {
+       case INSN_CONFIG_RESET:
+               dio200_subdev_timer_reset(dev, s);
+               break;
+       case INSN_CONFIG_SET_CLOCK_SRC:
+               ret = dio200_subdev_timer_set_clock_src(dev, s, data[1]);
+               if (ret < 0)
+                       ret = -EINVAL;
+               break;
+       case INSN_CONFIG_GET_CLOCK_SRC:
+               dio200_subdev_timer_get_clock_src(dev, s, &data[1], &data[2]);
+               break;
+       default:
+               ret = -EINVAL;
+               break;
+       }
+       return ret < 0 ? ret : insn->n;
+}
+
+/*
+ * This function initializes a timer subdevice.
+ *
+ * Uses the timestamp timer registers.  There is only one timestamp timer.
+ */
+static int dio200_subdev_timer_init(struct comedi_device *dev,
+                                   struct comedi_subdevice *s)
+{
+       s->type = COMEDI_SUBD_TIMER;
+       s->subdev_flags = SDF_READABLE | SDF_LSAMPL;
+       s->n_chan = 1;
+       s->maxdata = 0xFFFFFFFF;
+       s->insn_read = dio200_subdev_timer_read;
+       s->insn_config = dio200_subdev_timer_config;
+       return 0;
+}
+
+/*
+ * This function cleans up a timer subdevice.
+ */
+static void dio200_subdev_timer_cleanup(struct comedi_device *dev,
+                                       struct comedi_subdevice *s)
+{
+       /* Nothing to do. */
+}
+
+/*
+ * This function does some special set-up for the PCIe boards
+ * PCIe215, PCIe236, PCIe296.
+ */
+static int dio200_pcie_board_setup(struct comedi_device *dev)
+{
+       struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+       void __iomem *brbase;
+       resource_size_t brlen;
+
+       /*
+        * The board uses Altera Cyclone IV with PCI-Express hard IP.
+        * The FPGA configuration has the PCI-Express Avalon-MM Bridge
+        * Control registers in PCI BAR 0, offset 0, and the length of
+        * these registers is 0x4000.
+        *
+        * We need to write 0x80 to the "Avalon-MM to PCI-Express Interrupt
+        * Enable" register at offset 0x50 to allow generation of PCIe
+        * interrupts when RXmlrq_i is asserted in the SOPC Builder system.
+        */
+       brlen = pci_resource_len(pcidev, 0);
+       if (brlen < 0x4000 ||
+                       !(pci_resource_flags(pcidev, 0) & IORESOURCE_MEM)) {
+               dev_err(dev->class_dev, "error! bad PCI region!\n");
+               return -EINVAL;
+       }
+       brbase = ioremap_nocache(pci_resource_start(pcidev, 0), brlen);
+       if (!brbase) {
+               dev_err(dev->class_dev, "error! failed to map registers!\n");
+               return -ENOMEM;
+       }
+       writel(0x80, brbase + 0x50);
+       iounmap(brbase);
+       /* Enable "enhanced" features of board. */
+       dio200_write8(dev, DIO200_ENHANCE, 1);
+       return 0;
+}
+
 static void dio200_report_attach(struct comedi_device *dev, unsigned int irq)
 {
        const struct dio200_board *thisboard = comedi_board(dev);
+       struct dio200_private *devpriv = dev->private;
        struct pci_dev *pcidev = comedi_to_pci_dev(dev);
        char tmpbuf[60];
        int tmplen;
 
        if (is_isa_board(thisboard))
                tmplen = scnprintf(tmpbuf, sizeof(tmpbuf),
-                                  "(base %#lx) ", dev->iobase);
+                                  "(base %#lx) ", devpriv->io.u.iobase);
        else if (is_pci_board(thisboard))
                tmplen = scnprintf(tmpbuf, sizeof(tmpbuf),
                                   "(pci %s) ", pci_name(pcidev));
@@ -1232,20 +1819,18 @@ static void dio200_report_attach(struct comedi_device *dev, unsigned int irq)
        dev_info(dev->class_dev, "%s %sattached\n", dev->board_name, tmpbuf);
 }
 
-static int dio200_common_attach(struct comedi_device *dev, unsigned long iobase,
-                               unsigned int irq, unsigned long req_irq_flags)
+static int dio200_common_attach(struct comedi_device *dev, unsigned int irq,
+                               unsigned long req_irq_flags)
 {
        const struct dio200_board *thisboard = comedi_board(dev);
        struct dio200_private *devpriv = dev->private;
-       const struct dio200_layout_struct *layout =
-               &dio200_layouts[thisboard->layout];
+       const struct dio200_layout *layout = dio200_board_layout(thisboard);
        struct comedi_subdevice *s;
        int sdx;
        unsigned int n;
        int ret;
 
        devpriv->intr_sd = -1;
-       dev->iobase = iobase;
        dev->board_name = thisboard->name;
 
        ret = comedi_alloc_subdevices(dev, layout->n_subdevs);
@@ -1257,16 +1842,15 @@ static int dio200_common_attach(struct comedi_device *dev, unsigned long iobase,
                switch (layout->sdtype[n]) {
                case sd_8254:
                        /* counter subdevice (8254) */
-                       ret = dio200_subdev_8254_init(dev, s, iobase,
-                                                     layout->sdinfo[n],
-                                                     layout->has_clk_gat_sce);
+                       ret = dio200_subdev_8254_init(dev, s,
+                                                     layout->sdinfo[n]);
                        if (ret < 0)
                                return ret;
                        break;
                case sd_8255:
                        /* digital i/o subdevice (8255) */
-                       ret = subdev_8255_init(dev, s, NULL,
-                                              iobase + layout->sdinfo[n]);
+                       ret = dio200_subdev_8255_init(dev, s,
+                                                     layout->sdinfo[n]);
                        if (ret < 0)
                                return ret;
                        break;
@@ -1274,11 +1858,9 @@ static int dio200_common_attach(struct comedi_device *dev, unsigned long iobase,
                        /* 'INTERRUPT' subdevice */
                        if (irq) {
                                ret = dio200_subdev_intr_init(dev, s,
-                                                             iobase +
                                                              DIO200_INT_SCE,
-                                                             layout->sdinfo[n],
-                                                             layout->
-                                                             has_int_sce);
+                                                             layout->sdinfo[n]
+                                                            );
                                if (ret < 0)
                                        return ret;
                                devpriv->intr_sd = n;
@@ -1286,6 +1868,16 @@ static int dio200_common_attach(struct comedi_device *dev, unsigned long iobase,
                                s->type = COMEDI_SUBD_UNUSED;
                        }
                        break;
+               case sd_timer:
+                       /* Only on PCIe boards. */
+                       if (DO_PCI) {
+                               ret = dio200_subdev_timer_init(dev, s);
+                               if (ret < 0)
+                                       return ret;
+                       } else {
+                               s->type = COMEDI_SUBD_UNUSED;
+                       }
+                       break;
                default:
                        s->type = COMEDI_SUBD_UNUSED;
                        break;
@@ -1307,24 +1899,6 @@ static int dio200_common_attach(struct comedi_device *dev, unsigned long iobase,
        return 1;
 }
 
-static int dio200_pci_common_attach(struct comedi_device *dev,
-                                   struct pci_dev *pci_dev)
-{
-       unsigned long iobase;
-       int ret;
-
-       comedi_set_hw_dev(dev, &pci_dev->dev);
-
-       ret = comedi_pci_enable(pci_dev, DIO200_DRIVER_NAME);
-       if (ret < 0) {
-               dev_err(dev->class_dev,
-                       "error! cannot enable PCI device and request regions!\n");
-               return ret;
-       }
-       iobase = pci_resource_start(pci_dev, 2);
-       return dio200_common_attach(dev, iobase, pci_dev->irq, IRQF_SHARED);
-}
-
 /*
  * Attach is called by the Comedi core to configure the driver
  * for a particular board.  If you specified a board_name array
@@ -1334,15 +1908,15 @@ static int dio200_pci_common_attach(struct comedi_device *dev,
 static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
        const struct dio200_board *thisboard = comedi_board(dev);
+       struct dio200_private *devpriv;
        int ret;
 
        dev_info(dev->class_dev, DIO200_DRIVER_NAME ": attach\n");
 
-       ret = alloc_private(dev, sizeof(struct dio200_private));
-       if (ret < 0) {
-               dev_err(dev->class_dev, "error! out of memory!\n");
-               return ret;
-       }
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
+               return -ENOMEM;
+       dev->private = devpriv;
 
        /* Process options and reserve resources according to bus type. */
        if (is_isa_board(thisboard)) {
@@ -1351,17 +1925,17 @@ static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 
                iobase = it->options[0];
                irq = it->options[1];
-               ret = dio200_request_region(dev, iobase, DIO200_IO_SIZE);
+               ret = dio200_request_region(dev, iobase, thisboard->mainsize);
                if (ret < 0)
                        return ret;
-               return dio200_common_attach(dev, iobase, irq, 0);
+               devpriv->io.u.iobase = iobase;
+               devpriv->io.regtype = io_regtype;
+               return dio200_common_attach(dev, irq, 0);
        } else if (is_pci_board(thisboard)) {
-               struct pci_dev *pci_dev;
-
-               pci_dev = dio200_find_pci_dev(dev, it);
-               if (!pci_dev)
-                       return -EIO;
-               return dio200_pci_common_attach(dev, pci_dev);
+               dev_err(dev->class_dev,
+                       "Manual configuration of PCI board '%s' is not supported\n",
+                       thisboard->name);
+               return -EIO;
        } else {
                dev_err(dev->class_dev, DIO200_DRIVER_NAME
                        ": BUG! cannot determine board type!\n");
@@ -1377,6 +1951,10 @@ static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 static int __devinit dio200_attach_pci(struct comedi_device *dev,
                                       struct pci_dev *pci_dev)
 {
+       const struct dio200_board *thisboard;
+       struct dio200_private *devpriv;
+       resource_size_t base, len;
+       unsigned int bar;
        int ret;
 
        if (!DO_PCI)
@@ -1384,36 +1962,71 @@ static int __devinit dio200_attach_pci(struct comedi_device *dev,
 
        dev_info(dev->class_dev, DIO200_DRIVER_NAME ": attach pci %s\n",
                 pci_name(pci_dev));
-       ret = alloc_private(dev, sizeof(struct dio200_private));
-       if (ret < 0) {
-               dev_err(dev->class_dev, "error! out of memory!\n");
-               return ret;
-       }
+
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
+               return -ENOMEM;
+       dev->private = devpriv;
+
        dev->board_ptr = dio200_find_pci_board(pci_dev);
        if (dev->board_ptr == NULL) {
                dev_err(dev->class_dev, "BUG! cannot determine board type!\n");
                return -EINVAL;
        }
-       /*
-        * Need to 'get' the PCI device to match the 'put' in dio200_detach().
-        * TODO: Remove the pci_dev_get() and matching pci_dev_put() once
-        * support for manual attachment of PCI devices via dio200_attach()
-        * has been removed.
-        */
-       pci_dev_get(pci_dev);
-       return dio200_pci_common_attach(dev, pci_dev);
+       thisboard = comedi_board(dev);
+       ret = comedi_pci_enable(pci_dev, DIO200_DRIVER_NAME);
+       if (ret < 0) {
+               dev_err(dev->class_dev,
+                       "error! cannot enable PCI device and request regions!\n");
+               return ret;
+       }
+       bar = thisboard->mainbar;
+       base = pci_resource_start(pci_dev, bar);
+       len = pci_resource_len(pci_dev, bar);
+       if (len < thisboard->mainsize) {
+               dev_err(dev->class_dev, "error! PCI region size too small!\n");
+               return -EINVAL;
+       }
+       if ((pci_resource_flags(pci_dev, bar) & IORESOURCE_MEM) != 0) {
+               devpriv->io.u.membase = ioremap_nocache(base, len);
+               if (!devpriv->io.u.membase) {
+                       dev_err(dev->class_dev,
+                               "error! cannot remap registers\n");
+                       return -ENOMEM;
+               }
+               devpriv->io.regtype = mmio_regtype;
+       } else {
+               devpriv->io.u.iobase = (unsigned long)base;
+               devpriv->io.regtype = io_regtype;
+       }
+       switch (thisboard->model)
+       {
+       case pcie215_model:
+       case pcie236_model:
+       case pcie296_model:
+               ret = dio200_pcie_board_setup(dev);
+               if (ret < 0)
+                       return ret;
+               break;
+       default:
+               break;
+       }
+       return dio200_common_attach(dev, pci_dev->irq, IRQF_SHARED);
 }
 
 static void dio200_detach(struct comedi_device *dev)
 {
        const struct dio200_board *thisboard = comedi_board(dev);
-       const struct dio200_layout_struct *layout;
+       struct dio200_private *devpriv = dev->private;
+       const struct dio200_layout *layout;
        unsigned n;
 
+       if (!thisboard || !devpriv)
+               return;
        if (dev->irq)
                free_irq(dev->irq, dev);
        if (dev->subdevices) {
-               layout = &dio200_layouts[thisboard->layout];
+               layout = dio200_board_layout(thisboard);
                for (n = 0; n < dev->n_subdevices; n++) {
                        struct comedi_subdevice *s = &dev->subdevices[n];
                        switch (layout->sdtype[n]) {
@@ -1421,25 +2034,33 @@ static void dio200_detach(struct comedi_device *dev)
                                dio200_subdev_8254_cleanup(dev, s);
                                break;
                        case sd_8255:
-                               subdev_8255_cleanup(dev, s);
+                               dio200_subdev_8255_cleanup(dev, s);
                                break;
                        case sd_intr:
                                dio200_subdev_intr_cleanup(dev, s);
                                break;
+                       case sd_timer:
+                               /* Only on PCIe boards. */
+                               if (DO_PCI)
+                                       dio200_subdev_timer_cleanup(dev, s);
+                               break;
                        default:
                                break;
                        }
                }
        }
        if (is_isa_board(thisboard)) {
-               if (dev->iobase)
-                       release_region(dev->iobase, DIO200_IO_SIZE);
+               if (devpriv->io.regtype == io_regtype)
+                       release_region(devpriv->io.u.iobase,
+                                      thisboard->mainsize);
        } else if (is_pci_board(thisboard)) {
                struct pci_dev *pcidev = comedi_to_pci_dev(dev);
                if (pcidev) {
-                       if (dev->iobase)
+                       if (devpriv->io.regtype != no_regtype) {
+                               if (devpriv->io.regtype == mmio_regtype)
+                                       iounmap(devpriv->io.u.membase);
                                comedi_pci_disable(pcidev);
-                       pci_dev_put(pcidev);
+                       }
                }
        }
 }
@@ -1465,6 +2086,9 @@ static struct comedi_driver amplc_dio200_driver = {
 static DEFINE_PCI_DEVICE_TABLE(dio200_pci_table) = {
        { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI215) },
        { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI272) },
+       { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCIE236) },
+       { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCIE215) },
+       { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCIE296) },
        {0}
 };
 
index eacb5e4735d7df0a3ccf7e794bb0744ab936f71a..150f05244d356d6ee6cb331def74c7040361d8c7 100644 (file)
@@ -505,14 +505,16 @@ static int pc236_pci_common_attach(struct comedi_device *dev,
 static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
        const struct pc236_board *thisboard = comedi_board(dev);
+       struct pc236_private *devpriv;
        int ret;
 
        dev_info(dev->class_dev, PC236_DRIVER_NAME ": attach\n");
-       ret = alloc_private(dev, sizeof(struct pc236_private));
-       if (ret < 0) {
-               dev_err(dev->class_dev, "error! out of memory!\n");
-               return ret;
-       }
+
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
+               return -ENOMEM;
+       dev->private = devpriv;
+
        /* Process options according to bus type. */
        if (is_isa_board(thisboard)) {
                unsigned long iobase = it->options[0];
@@ -543,18 +545,19 @@ static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 static int __devinit pc236_attach_pci(struct comedi_device *dev,
                                      struct pci_dev *pci_dev)
 {
-       int ret;
+       struct pc236_private *devpriv;
 
        if (!DO_PCI)
                return -EINVAL;
 
        dev_info(dev->class_dev, PC236_DRIVER_NAME ": attach pci %s\n",
                 pci_name(pci_dev));
-       ret = alloc_private(dev, sizeof(struct pc236_private));
-       if (ret < 0) {
-               dev_err(dev->class_dev, "error! out of memory!\n");
-               return ret;
-       }
+
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
+               return -ENOMEM;
+       dev->private = devpriv;
+
        dev->board_ptr = pc236_find_pci_board(pci_dev);
        if (dev->board_ptr == NULL) {
                dev_err(dev->class_dev, "BUG! cannot determine board type!\n");
@@ -573,9 +576,10 @@ static int __devinit pc236_attach_pci(struct comedi_device *dev,
 static void pc236_detach(struct comedi_device *dev)
 {
        const struct pc236_board *thisboard = comedi_board(dev);
-       struct pc236_private *devpriv = dev->private;
 
-       if (devpriv)
+       if (!thisboard)
+               return;
+       if (dev->iobase)
                pc236_intr_disable(dev);
        if (dev->irq)
                free_irq(dev->irq, dev);
index 60830ccfb903f48fc9720490040d59bc113f0c5c..d0a4c441228b405d4459f70cb264b13717c26161 100644 (file)
@@ -323,6 +323,8 @@ static void pc263_detach(struct comedi_device *dev)
 {
        const struct pc263_board *thisboard = comedi_board(dev);
 
+       if (!thisboard)
+               return;
        if (is_isa_board(thisboard)) {
                if (dev->iobase)
                        release_region(dev->iobase, PC263_IO_SIZE);
index 1f65ec4d261e7bb1f73e55e15a0ff450fe731e4c..6a9ec11c4f079e83dcd69fd72b7521b250bc9b45 100644 (file)
@@ -1443,16 +1443,15 @@ static int pci224_attach_common(struct comedi_device *dev,
 
 static int pci224_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
+       struct pci224_private *devpriv;
        struct pci_dev *pci_dev;
-       int ret;
 
        dev_info(dev->class_dev, DRIVER_NAME ": attach\n");
 
-       ret = alloc_private(dev, sizeof(struct pci224_private));
-       if (ret < 0) {
-               dev_err(dev->class_dev, "error! out of memory!\n");
-               return ret;
-       }
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
+               return -ENOMEM;
+       dev->private = devpriv;
 
        pci_dev = pci224_find_pci_dev(dev, it);
        if (!pci_dev)
@@ -1464,16 +1463,15 @@ static int pci224_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 static int __devinit
 pci224_attach_pci(struct comedi_device *dev, struct pci_dev *pci_dev)
 {
-       int ret;
+       struct pci224_private *devpriv;
 
        dev_info(dev->class_dev, DRIVER_NAME ": attach_pci %s\n",
                 pci_name(pci_dev));
 
-       ret = alloc_private(dev, sizeof(struct pci224_private));
-       if (ret < 0) {
-               dev_err(dev->class_dev, "error! out of memory!\n");
-               return ret;
-       }
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
+               return -ENOMEM;
+       dev->private = devpriv;
 
        dev->board_ptr = pci224_find_pci_board(pci_dev);
        if (dev->board_ptr == NULL) {
index bd8fb876ce2ed7878e95408defd0c6b212391ad7..2675eefe8b5a41d0406546d30680bb43236d6f1a 100644 (file)
@@ -2660,15 +2660,12 @@ static struct pci_dev *pci230_find_pci_dev(struct comedi_device *dev,
 static int pci230_alloc_private(struct comedi_device *dev)
 {
        struct pci230_private *devpriv;
-       int err;
 
-       /* sets dev->private to allocated memory */
-       err = alloc_private(dev, sizeof(struct pci230_private));
-       if (err) {
-               dev_err(dev->class_dev, "error! out of memory!\n");
-               return err;
-       }
-       devpriv = dev->private;
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
+               return -ENOMEM;
+       dev->private = devpriv;
+
        spin_lock_init(&devpriv->isr_spinlock);
        spin_lock_init(&devpriv->res_spinlock);
        spin_lock_init(&devpriv->ai_stop_spinlock);
@@ -2836,9 +2833,11 @@ static int pci230_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 
        dev_info(dev->class_dev, "amplc_pci230: attach %s %d,%d\n",
                 thisboard->name, it->options[0], it->options[1]);
-       rc = pci230_alloc_private(dev); /* sets dev->private */
+
+       rc = pci230_alloc_private(dev);
        if (rc)
                return rc;
+
        pci_dev = pci230_find_pci_dev(dev, it);
        if (!pci_dev)
                return -EIO;
@@ -2852,9 +2851,11 @@ static int __devinit pci230_attach_pci(struct comedi_device *dev,
 
        dev_info(dev->class_dev, "amplc_pci230: attach pci %s\n",
                 pci_name(pci_dev));
-       rc = pci230_alloc_private(dev); /* sets dev->private */
+
+       rc = pci230_alloc_private(dev);
        if (rc)
                return rc;
+
        dev->board_ptr = pci230_find_pci_board(pci_dev);
        if (dev->board_ptr == NULL) {
                dev_err(dev->class_dev,
index 6d81d8b40ccca8a20e5f5649c413fc7090070734..8b091c61cbc847b625bbf7e9cd95f8a5a95e8cbf 100644 (file)
@@ -428,6 +428,7 @@ static int das16cs_attach(struct comedi_device *dev,
                          struct comedi_devconfig *it)
 {
        const struct das16cs_board *thisboard;
+       struct das16cs_private *devpriv;
        struct pcmcia_device *link;
        struct comedi_subdevice *s;
        int ret;
@@ -451,8 +452,10 @@ static int das16cs_attach(struct comedi_device *dev,
                return ret;
        dev->irq = link->irq;
 
-       if (alloc_private(dev, sizeof(struct das16cs_private)) < 0)
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
                return -ENOMEM;
+       dev->private = devpriv;
 
        ret = comedi_alloc_subdevices(dev, 3);
        if (ret)
index de21a261ff453b9db06ebfe4ac99617d68204408..0e4d189d1951a850973f5d2dfa31c91904be015d 100644 (file)
@@ -1478,18 +1478,16 @@ static int cb_pcidas_attach_pci(struct comedi_device *dev,
        int i;
        int ret;
 
-       comedi_set_hw_dev(dev, &pcidev->dev);
-
        thisboard = cb_pcidas_find_boardinfo(dev, pcidev);
        if (!thisboard)
                return -ENODEV;
        dev->board_ptr  = thisboard;
        dev->board_name = thisboard->name;
 
-       ret = alloc_private(dev, sizeof(*devpriv));
-       if (ret)
-               return ret;
-       devpriv = dev->private;
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
+               return -ENOMEM;
+       dev->private = devpriv;
 
        ret = comedi_pci_enable(pcidev, dev->board_name);
        if (ret)
index 0472a9088abe3603b68a3e603432c4fc9840057b..a6f5e5e92c8e0164b748ca53809b9390c819ccec 100644 (file)
@@ -119,7 +119,7 @@ enum base_address_regions {
        DIO_COUNTER_BADDRINDEX = 3,
 };
 
-/* priv(dev)->main_iobase registers */
+/* devpriv->main_iobase registers */
 enum write_only_registers {
        INTR_ENABLE_REG = 0x0,  /*  interrupt enable register */
        HW_CONFIG_REG = 0x2,    /*  hardware config register */
@@ -179,7 +179,7 @@ enum read_write_registers {
        DAC_FIFO_REG = 0x300,   /* dac data fifo, has weird interactions with external channel queue */
 };
 
-/* priv(dev)->dio_counter_iobase registers */
+/* devpriv->dio_counter_iobase registers */
 enum dio_counter_registers {
        DIO_8255_OFFSET = 0x0,
        DO_REG = 0x20,
@@ -1091,14 +1091,6 @@ struct pcidas64_private {
        short ao_bounce_buffer[DAC_FIFO_SIZE];
 };
 
-/* inline function that makes it easier to
- * access the private structure.
- */
-static inline struct pcidas64_private *priv(struct comedi_device *dev)
-{
-       return dev->private;
-}
-
 static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
                    struct comedi_insn *insn, unsigned int *data);
 static int ai_config_insn(struct comedi_device *dev, struct comedi_subdevice *s,
@@ -1249,17 +1241,18 @@ static inline int ao_cmd_is_supported(const struct pcidas64_board *board)
 /* initialize plx9080 chip */
 static void init_plx9080(struct comedi_device *dev)
 {
+       struct pcidas64_private *devpriv = dev->private;
        uint32_t bits;
-       void __iomem *plx_iobase = priv(dev)->plx9080_iobase;
+       void __iomem *plx_iobase = devpriv->plx9080_iobase;
 
-       priv(dev)->plx_control_bits =
-           readl(priv(dev)->plx9080_iobase + PLX_CONTROL_REG);
+       devpriv->plx_control_bits =
+           readl(devpriv->plx9080_iobase + PLX_CONTROL_REG);
 
        /*  plx9080 dump */
        DEBUG_PRINT(" plx interrupt status 0x%x\n",
                    readl(plx_iobase + PLX_INTRCS_REG));
        DEBUG_PRINT(" plx id bits 0x%x\n", readl(plx_iobase + PLX_ID_REG));
-       DEBUG_PRINT(" plx control reg 0x%x\n", priv(dev)->plx_control_bits);
+       DEBUG_PRINT(" plx control reg 0x%x\n", devpriv->plx_control_bits);
        DEBUG_PRINT(" plx mode/arbitration reg 0x%x\n",
                    readl(plx_iobase + PLX_MARB_REG));
        DEBUG_PRINT(" plx region0 reg 0x%x\n",
@@ -1292,7 +1285,7 @@ static void init_plx9080(struct comedi_device *dev)
 #else
        bits = 0;
 #endif
-       writel(bits, priv(dev)->plx9080_iobase + PLX_BIGEND_REG);
+       writel(bits, devpriv->plx9080_iobase + PLX_BIGEND_REG);
 
        disable_plx_interrupts(dev);
 
@@ -1328,17 +1321,18 @@ static void init_plx9080(struct comedi_device *dev)
                writel(bits, plx_iobase + PLX_DMA0_MODE_REG);
 
        /*  enable interrupts on plx 9080 */
-       priv(dev)->plx_intcsr_bits |=
+       devpriv->plx_intcsr_bits |=
            ICS_AERR | ICS_PERR | ICS_PIE | ICS_PLIE | ICS_PAIE | ICS_LIE |
            ICS_DMA0_E | ICS_DMA1_E;
-       writel(priv(dev)->plx_intcsr_bits,
-              priv(dev)->plx9080_iobase + PLX_INTRCS_REG);
+       writel(devpriv->plx_intcsr_bits,
+              devpriv->plx9080_iobase + PLX_INTRCS_REG);
 }
 
 /* Allocate and initialize the subdevice structures.
  */
 static int setup_subdevices(struct comedi_device *dev)
 {
+       struct pcidas64_private *devpriv = dev->private;
        struct comedi_subdevice *s;
        void __iomem *dio_8255_iobase;
        int i;
@@ -1370,11 +1364,11 @@ static int setup_subdevices(struct comedi_device *dev)
        if (board(dev)->layout == LAYOUT_4020) {
                uint8_t data;
                /*  set adc to read from inputs (not internal calibration sources) */
-               priv(dev)->i2c_cal_range_bits = adc_src_4020_bits(4);
+               devpriv->i2c_cal_range_bits = adc_src_4020_bits(4);
                /*  set channels to +-5 volt input ranges */
                for (i = 0; i < s->n_chan; i++)
-                       priv(dev)->i2c_cal_range_bits |= attenuate_bit(i);
-               data = priv(dev)->i2c_cal_range_bits;
+                       devpriv->i2c_cal_range_bits |= attenuate_bit(i);
+               data = devpriv->i2c_cal_range_bits;
                i2c_write(dev, RANGE_CAL_I2C_ADDR, &data, sizeof(data));
        }
 
@@ -1429,12 +1423,12 @@ static int setup_subdevices(struct comedi_device *dev)
        if (board(dev)->has_8255) {
                if (board(dev)->layout == LAYOUT_4020) {
                        dio_8255_iobase =
-                           priv(dev)->main_iobase + I8255_4020_REG;
+                           devpriv->main_iobase + I8255_4020_REG;
                        subdev_8255_init(dev, s, dio_callback_4020,
                                         (unsigned long)dio_8255_iobase);
                } else {
                        dio_8255_iobase =
-                           priv(dev)->dio_counter_iobase + DIO_8255_OFFSET;
+                           devpriv->dio_counter_iobase + DIO_8255_OFFSET;
                        subdev_8255_init(dev, s, dio_callback,
                                         (unsigned long)dio_8255_iobase);
                }
@@ -1484,7 +1478,7 @@ static int setup_subdevices(struct comedi_device *dev)
 
        /* serial EEPROM, if present */
        s = &dev->subdevices[8];
-       if (readl(priv(dev)->plx9080_iobase + PLX_CONTROL_REG) & CTL_EECHK) {
+       if (readl(devpriv->plx9080_iobase + PLX_CONTROL_REG) & CTL_EECHK) {
                s->type = COMEDI_SUBD_MEMORY;
                s->subdev_flags = SDF_READABLE | SDF_INTERNAL;
                s->n_chan = 128;
@@ -1502,13 +1496,16 @@ static int setup_subdevices(struct comedi_device *dev)
 
 static void disable_plx_interrupts(struct comedi_device *dev)
 {
-       priv(dev)->plx_intcsr_bits = 0;
-       writel(priv(dev)->plx_intcsr_bits,
-              priv(dev)->plx9080_iobase + PLX_INTRCS_REG);
+       struct pcidas64_private *devpriv = dev->private;
+
+       devpriv->plx_intcsr_bits = 0;
+       writel(devpriv->plx_intcsr_bits,
+              devpriv->plx9080_iobase + PLX_INTRCS_REG);
 }
 
 static void init_stc_registers(struct comedi_device *dev)
 {
+       struct pcidas64_private *devpriv = dev->private;
        uint16_t bits;
        unsigned long flags;
 
@@ -1516,35 +1513,35 @@ static void init_stc_registers(struct comedi_device *dev)
 
        /*  bit should be set for 6025, although docs say boards with <= 16 chans should be cleared XXX */
        if (1)
-               priv(dev)->adc_control1_bits |= ADC_QUEUE_CONFIG_BIT;
-       writew(priv(dev)->adc_control1_bits,
-              priv(dev)->main_iobase + ADC_CONTROL1_REG);
+               devpriv->adc_control1_bits |= ADC_QUEUE_CONFIG_BIT;
+       writew(devpriv->adc_control1_bits,
+              devpriv->main_iobase + ADC_CONTROL1_REG);
 
        /*  6402/16 manual says this register must be initialized to 0xff? */
-       writew(0xff, priv(dev)->main_iobase + ADC_SAMPLE_INTERVAL_UPPER_REG);
+       writew(0xff, devpriv->main_iobase + ADC_SAMPLE_INTERVAL_UPPER_REG);
 
        bits = SLOW_DAC_BIT | DMA_CH_SELECT_BIT;
        if (board(dev)->layout == LAYOUT_4020)
                bits |= INTERNAL_CLOCK_4020_BITS;
-       priv(dev)->hw_config_bits |= bits;
-       writew(priv(dev)->hw_config_bits,
-              priv(dev)->main_iobase + HW_CONFIG_REG);
+       devpriv->hw_config_bits |= bits;
+       writew(devpriv->hw_config_bits,
+              devpriv->main_iobase + HW_CONFIG_REG);
 
-       writew(0, priv(dev)->main_iobase + DAQ_SYNC_REG);
-       writew(0, priv(dev)->main_iobase + CALIBRATION_REG);
+       writew(0, devpriv->main_iobase + DAQ_SYNC_REG);
+       writew(0, devpriv->main_iobase + CALIBRATION_REG);
 
        spin_unlock_irqrestore(&dev->spinlock, flags);
 
        /*  set fifos to maximum size */
-       priv(dev)->fifo_size_bits |= DAC_FIFO_BITS;
+       devpriv->fifo_size_bits |= DAC_FIFO_BITS;
        set_ai_fifo_segment_length(dev,
                                   board(dev)->ai_fifo->max_segment_length);
 
-       priv(dev)->dac_control1_bits = DAC_OUTPUT_ENABLE_BIT;
-       priv(dev)->intr_enable_bits =   /* EN_DAC_INTR_SRC_BIT | DAC_INTR_QEMPTY_BITS | */
+       devpriv->dac_control1_bits = DAC_OUTPUT_ENABLE_BIT;
+       devpriv->intr_enable_bits =     /* EN_DAC_INTR_SRC_BIT | DAC_INTR_QEMPTY_BITS | */
            EN_DAC_DONE_INTR_BIT | EN_DAC_UNDERRUN_BIT;
-       writew(priv(dev)->intr_enable_bits,
-              priv(dev)->main_iobase + INTR_ENABLE_REG);
+       writew(devpriv->intr_enable_bits,
+              devpriv->main_iobase + INTR_ENABLE_REG);
 
        disable_ai_pacing(dev);
 };
@@ -1552,88 +1549,89 @@ static void init_stc_registers(struct comedi_device *dev)
 static int alloc_and_init_dma_members(struct comedi_device *dev)
 {
        struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+       struct pcidas64_private *devpriv = dev->private;
        int i;
 
        /*  alocate pci dma buffers */
        for (i = 0; i < ai_dma_ring_count(board(dev)); i++) {
-               priv(dev)->ai_buffer[i] =
+               devpriv->ai_buffer[i] =
                    pci_alloc_consistent(pcidev, DMA_BUFFER_SIZE,
-                                        &priv(dev)->ai_buffer_bus_addr[i]);
-               if (priv(dev)->ai_buffer[i] == NULL)
+                                        &devpriv->ai_buffer_bus_addr[i]);
+               if (devpriv->ai_buffer[i] == NULL)
                        return -ENOMEM;
 
        }
        for (i = 0; i < AO_DMA_RING_COUNT; i++) {
                if (ao_cmd_is_supported(board(dev))) {
-                       priv(dev)->ao_buffer[i] =
+                       devpriv->ao_buffer[i] =
                            pci_alloc_consistent(pcidev,
                                                 DMA_BUFFER_SIZE,
-                                                &priv(dev)->
+                                                &devpriv->
                                                 ao_buffer_bus_addr[i]);
-                       if (priv(dev)->ao_buffer[i] == NULL)
+                       if (devpriv->ao_buffer[i] == NULL)
                                return -ENOMEM;
 
                }
        }
        /*  allocate dma descriptors */
-       priv(dev)->ai_dma_desc =
+       devpriv->ai_dma_desc =
            pci_alloc_consistent(pcidev,
                                 sizeof(struct plx_dma_desc) *
                                 ai_dma_ring_count(board(dev)),
-                                &priv(dev)->ai_dma_desc_bus_addr);
-       if (priv(dev)->ai_dma_desc == NULL)
+                                &devpriv->ai_dma_desc_bus_addr);
+       if (devpriv->ai_dma_desc == NULL)
                return -ENOMEM;
 
        DEBUG_PRINT("ai dma descriptors start at bus addr 0x%x\n",
-                   priv(dev)->ai_dma_desc_bus_addr);
+                   devpriv->ai_dma_desc_bus_addr);
        if (ao_cmd_is_supported(board(dev))) {
-               priv(dev)->ao_dma_desc =
+               devpriv->ao_dma_desc =
                    pci_alloc_consistent(pcidev,
                                         sizeof(struct plx_dma_desc) *
                                         AO_DMA_RING_COUNT,
-                                        &priv(dev)->ao_dma_desc_bus_addr);
-               if (priv(dev)->ao_dma_desc == NULL)
+                                        &devpriv->ao_dma_desc_bus_addr);
+               if (devpriv->ao_dma_desc == NULL)
                        return -ENOMEM;
 
                DEBUG_PRINT("ao dma descriptors start at bus addr 0x%x\n",
-                           priv(dev)->ao_dma_desc_bus_addr);
+                           devpriv->ao_dma_desc_bus_addr);
        }
        /*  initialize dma descriptors */
        for (i = 0; i < ai_dma_ring_count(board(dev)); i++) {
-               priv(dev)->ai_dma_desc[i].pci_start_addr =
-                   cpu_to_le32(priv(dev)->ai_buffer_bus_addr[i]);
+               devpriv->ai_dma_desc[i].pci_start_addr =
+                   cpu_to_le32(devpriv->ai_buffer_bus_addr[i]);
                if (board(dev)->layout == LAYOUT_4020)
-                       priv(dev)->ai_dma_desc[i].local_start_addr =
-                           cpu_to_le32(priv(dev)->local1_iobase +
+                       devpriv->ai_dma_desc[i].local_start_addr =
+                           cpu_to_le32(devpriv->local1_iobase +
                                        ADC_FIFO_REG);
                else
-                       priv(dev)->ai_dma_desc[i].local_start_addr =
-                           cpu_to_le32(priv(dev)->local0_iobase +
+                       devpriv->ai_dma_desc[i].local_start_addr =
+                           cpu_to_le32(devpriv->local0_iobase +
                                        ADC_FIFO_REG);
-               priv(dev)->ai_dma_desc[i].transfer_size = cpu_to_le32(0);
-               priv(dev)->ai_dma_desc[i].next =
-                   cpu_to_le32((priv(dev)->ai_dma_desc_bus_addr + ((i +
+               devpriv->ai_dma_desc[i].transfer_size = cpu_to_le32(0);
+               devpriv->ai_dma_desc[i].next =
+                   cpu_to_le32((devpriv->ai_dma_desc_bus_addr + ((i +
                                                                     1) %
                                                                    ai_dma_ring_count
                                                                    (board
                                                                     (dev))) *
-                                sizeof(priv(dev)->ai_dma_desc[0])) |
+                                sizeof(devpriv->ai_dma_desc[0])) |
                                PLX_DESC_IN_PCI_BIT | PLX_INTR_TERM_COUNT |
                                PLX_XFER_LOCAL_TO_PCI);
        }
        if (ao_cmd_is_supported(board(dev))) {
                for (i = 0; i < AO_DMA_RING_COUNT; i++) {
-                       priv(dev)->ao_dma_desc[i].pci_start_addr =
-                           cpu_to_le32(priv(dev)->ao_buffer_bus_addr[i]);
-                       priv(dev)->ao_dma_desc[i].local_start_addr =
-                           cpu_to_le32(priv(dev)->local0_iobase +
+                       devpriv->ao_dma_desc[i].pci_start_addr =
+                           cpu_to_le32(devpriv->ao_buffer_bus_addr[i]);
+                       devpriv->ao_dma_desc[i].local_start_addr =
+                           cpu_to_le32(devpriv->local0_iobase +
                                        DAC_FIFO_REG);
-                       priv(dev)->ao_dma_desc[i].transfer_size =
+                       devpriv->ao_dma_desc[i].transfer_size =
                            cpu_to_le32(0);
-                       priv(dev)->ao_dma_desc[i].next =
-                           cpu_to_le32((priv(dev)->ao_dma_desc_bus_addr +
+                       devpriv->ao_dma_desc[i].next =
+                           cpu_to_le32((devpriv->ao_dma_desc_bus_addr +
                                         ((i + 1) % (AO_DMA_RING_COUNT)) *
-                                        sizeof(priv(dev)->ao_dma_desc[0])) |
+                                        sizeof(devpriv->ao_dma_desc[0])) |
                                        PLX_DESC_IN_PCI_BIT |
                                        PLX_INTR_TERM_COUNT);
                }
@@ -1685,15 +1683,15 @@ static struct pci_dev *cb_pcidas64_find_pci_dev(struct comedi_device *dev,
  */
 static int attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
+       struct pcidas64_private *devpriv;
        struct pci_dev *pcidev;
        uint32_t local_range, local_decode;
        int retval;
 
-/*
- * Allocate the private structure area.
- */
-       if (alloc_private(dev, sizeof(struct pcidas64_private)) < 0)
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
                return -ENOMEM;
+       dev->private = devpriv;
 
        pcidev = cb_pcidas64_find_pci_dev(dev, it);
        if (!pcidev)
@@ -1712,63 +1710,63 @@ static int attach(struct comedi_device *dev, struct comedi_devconfig *it)
 
        dev->iobase = pci_resource_start(pcidev, MAIN_BADDRINDEX);
 
-       priv(dev)->plx9080_phys_iobase =
+       devpriv->plx9080_phys_iobase =
            pci_resource_start(pcidev, PLX9080_BADDRINDEX);
-       priv(dev)->main_phys_iobase = dev->iobase;
-       priv(dev)->dio_counter_phys_iobase =
+       devpriv->main_phys_iobase = dev->iobase;
+       devpriv->dio_counter_phys_iobase =
            pci_resource_start(pcidev, DIO_COUNTER_BADDRINDEX);
 
        /*  remap, won't work with 2.0 kernels but who cares */
-       priv(dev)->plx9080_iobase = ioremap(priv(dev)->plx9080_phys_iobase,
+       devpriv->plx9080_iobase = ioremap(devpriv->plx9080_phys_iobase,
                                            pci_resource_len(pcidev,
                                                             PLX9080_BADDRINDEX));
-       priv(dev)->main_iobase =
-           ioremap(priv(dev)->main_phys_iobase,
+       devpriv->main_iobase =
+           ioremap(devpriv->main_phys_iobase,
                    pci_resource_len(pcidev, MAIN_BADDRINDEX));
-       priv(dev)->dio_counter_iobase =
-           ioremap(priv(dev)->dio_counter_phys_iobase,
+       devpriv->dio_counter_iobase =
+           ioremap(devpriv->dio_counter_phys_iobase,
                    pci_resource_len(pcidev, DIO_COUNTER_BADDRINDEX));
 
-       if (!priv(dev)->plx9080_iobase || !priv(dev)->main_iobase
-           || !priv(dev)->dio_counter_iobase) {
+       if (!devpriv->plx9080_iobase || !devpriv->main_iobase
+           || !devpriv->dio_counter_iobase) {
                dev_warn(dev->class_dev, "failed to remap io memory\n");
                return -ENOMEM;
        }
 
-       DEBUG_PRINT(" plx9080 remapped to 0x%p\n", priv(dev)->plx9080_iobase);
-       DEBUG_PRINT(" main remapped to 0x%p\n", priv(dev)->main_iobase);
+       DEBUG_PRINT(" plx9080 remapped to 0x%p\n", devpriv->plx9080_iobase);
+       DEBUG_PRINT(" main remapped to 0x%p\n", devpriv->main_iobase);
        DEBUG_PRINT(" diocounter remapped to 0x%p\n",
-                   priv(dev)->dio_counter_iobase);
+                   devpriv->dio_counter_iobase);
 
        /*  figure out what local addresses are */
        local_range =
-           readl(priv(dev)->plx9080_iobase + PLX_LAS0RNG_REG) & LRNG_MEM_MASK;
+           readl(devpriv->plx9080_iobase + PLX_LAS0RNG_REG) & LRNG_MEM_MASK;
        local_decode =
-           readl(priv(dev)->plx9080_iobase +
+           readl(devpriv->plx9080_iobase +
                  PLX_LAS0MAP_REG) & local_range & LMAP_MEM_MASK;
-       priv(dev)->local0_iobase =
-           ((uint32_t) priv(dev)->main_phys_iobase & ~local_range) |
+       devpriv->local0_iobase =
+           ((uint32_t) devpriv->main_phys_iobase & ~local_range) |
            local_decode;
        local_range =
-           readl(priv(dev)->plx9080_iobase + PLX_LAS1RNG_REG) & LRNG_MEM_MASK;
+           readl(devpriv->plx9080_iobase + PLX_LAS1RNG_REG) & LRNG_MEM_MASK;
        local_decode =
-           readl(priv(dev)->plx9080_iobase +
+           readl(devpriv->plx9080_iobase +
                  PLX_LAS1MAP_REG) & local_range & LMAP_MEM_MASK;
-       priv(dev)->local1_iobase =
-           ((uint32_t) priv(dev)->dio_counter_phys_iobase & ~local_range) |
+       devpriv->local1_iobase =
+           ((uint32_t) devpriv->dio_counter_phys_iobase & ~local_range) |
            local_decode;
 
-       DEBUG_PRINT(" local 0 io addr 0x%x\n", priv(dev)->local0_iobase);
-       DEBUG_PRINT(" local 1 io addr 0x%x\n", priv(dev)->local1_iobase);
+       DEBUG_PRINT(" local 0 io addr 0x%x\n", devpriv->local0_iobase);
+       DEBUG_PRINT(" local 1 io addr 0x%x\n", devpriv->local1_iobase);
 
        retval = alloc_and_init_dma_members(dev);
        if (retval < 0)
                return retval;
 
-       priv(dev)->hw_revision =
-           hw_revision(dev, readw(priv(dev)->main_iobase + HW_STATUS_REG));
+       devpriv->hw_revision =
+           hw_revision(dev, readw(devpriv->main_iobase + HW_STATUS_REG));
        dev_dbg(dev->class_dev, "stc hardware revision %i\n",
-               priv(dev)->hw_revision);
+               devpriv->hw_revision);
        init_plx9080(dev);
        init_stc_registers(dev);
        /*  get irq */
@@ -1792,58 +1790,49 @@ static int attach(struct comedi_device *dev, struct comedi_devconfig *it)
 static void detach(struct comedi_device *dev)
 {
        struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+       struct pcidas64_private *devpriv = dev->private;
        unsigned int i;
 
        if (dev->irq)
                free_irq(dev->irq, dev);
-       if (priv(dev)) {
+       if (devpriv) {
                if (pcidev) {
-                       if (priv(dev)->plx9080_iobase) {
+                       if (devpriv->plx9080_iobase) {
                                disable_plx_interrupts(dev);
-                               iounmap(priv(dev)->plx9080_iobase);
+                               iounmap(devpriv->plx9080_iobase);
                        }
-                       if (priv(dev)->main_iobase)
-                               iounmap(priv(dev)->main_iobase);
-                       if (priv(dev)->dio_counter_iobase)
-                               iounmap(priv(dev)->dio_counter_iobase);
+                       if (devpriv->main_iobase)
+                               iounmap(devpriv->main_iobase);
+                       if (devpriv->dio_counter_iobase)
+                               iounmap(devpriv->dio_counter_iobase);
                        /*  free pci dma buffers */
                        for (i = 0; i < ai_dma_ring_count(board(dev)); i++) {
-                               if (priv(dev)->ai_buffer[i])
+                               if (devpriv->ai_buffer[i])
                                        pci_free_consistent(pcidev,
-                                                           DMA_BUFFER_SIZE,
-                                                           priv(dev)->
-                                                           ai_buffer[i],
-                                                           priv
-                                                           (dev)->ai_buffer_bus_addr
-                                                           [i]);
+                                               DMA_BUFFER_SIZE,
+                                               devpriv->ai_buffer[i],
+                                               devpriv->ai_buffer_bus_addr[i]);
                        }
                        for (i = 0; i < AO_DMA_RING_COUNT; i++) {
-                               if (priv(dev)->ao_buffer[i])
+                               if (devpriv->ao_buffer[i])
                                        pci_free_consistent(pcidev,
-                                                           DMA_BUFFER_SIZE,
-                                                           priv(dev)->
-                                                           ao_buffer[i],
-                                                           priv
-                                                           (dev)->ao_buffer_bus_addr
-                                                           [i]);
+                                               DMA_BUFFER_SIZE,
+                                               devpriv->ao_buffer[i],
+                                               devpriv->ao_buffer_bus_addr[i]);
                        }
                        /*  free dma descriptors */
-                       if (priv(dev)->ai_dma_desc)
+                       if (devpriv->ai_dma_desc)
                                pci_free_consistent(pcidev,
-                                                   sizeof(struct plx_dma_desc)
-                                                   *
-                                                   ai_dma_ring_count(board
-                                                                     (dev)),
-                                                   priv(dev)->ai_dma_desc,
-                                                   priv(dev)->
-                                                   ai_dma_desc_bus_addr);
-                       if (priv(dev)->ao_dma_desc)
+                                       sizeof(struct plx_dma_desc) *
+                                       ai_dma_ring_count(board(dev)),
+                                       devpriv->ai_dma_desc,
+                                       devpriv->ai_dma_desc_bus_addr);
+                       if (devpriv->ao_dma_desc)
                                pci_free_consistent(pcidev,
-                                                   sizeof(struct plx_dma_desc)
-                                                   * AO_DMA_RING_COUNT,
-                                                   priv(dev)->ao_dma_desc,
-                                                   priv(dev)->
-                                                   ao_dma_desc_bus_addr);
+                                       sizeof(struct plx_dma_desc) *
+                                       AO_DMA_RING_COUNT,
+                                       devpriv->ao_dma_desc,
+                                       devpriv->ao_dma_desc_bus_addr);
                }
        }
        if (dev->subdevices)
@@ -1859,6 +1848,7 @@ static void detach(struct comedi_device *dev)
 static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
                    struct comedi_insn *insn, unsigned int *data)
 {
+       struct pcidas64_private *devpriv = dev->private;
        unsigned int bits = 0, n, i;
        unsigned int channel, range, aref;
        unsigned long flags;
@@ -1875,18 +1865,18 @@ static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
 
        spin_lock_irqsave(&dev->spinlock, flags);
        if (insn->chanspec & CR_ALT_FILTER)
-               priv(dev)->adc_control1_bits |= ADC_DITHER_BIT;
+               devpriv->adc_control1_bits |= ADC_DITHER_BIT;
        else
-               priv(dev)->adc_control1_bits &= ~ADC_DITHER_BIT;
-       writew(priv(dev)->adc_control1_bits,
-              priv(dev)->main_iobase + ADC_CONTROL1_REG);
+               devpriv->adc_control1_bits &= ~ADC_DITHER_BIT;
+       writew(devpriv->adc_control1_bits,
+              devpriv->main_iobase + ADC_CONTROL1_REG);
        spin_unlock_irqrestore(&dev->spinlock, flags);
 
        if (board(dev)->layout != LAYOUT_4020) {
                /*  use internal queue */
-               priv(dev)->hw_config_bits &= ~EXT_QUEUE_BIT;
-               writew(priv(dev)->hw_config_bits,
-                      priv(dev)->main_iobase + HW_CONFIG_REG);
+               devpriv->hw_config_bits &= ~EXT_QUEUE_BIT;
+               writew(devpriv->hw_config_bits,
+                      devpriv->main_iobase + HW_CONFIG_REG);
 
                /*  ALT_SOURCE is internal calibration reference */
                if (insn->chanspec & CR_ALT_SOURCE) {
@@ -1899,11 +1889,11 @@ static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
                                cal_en_bit = CAL_EN_64XX_BIT;
                        /*  select internal reference source to connect to channel 0 */
                        writew(cal_en_bit |
-                              adc_src_bits(priv(dev)->calibration_source),
-                              priv(dev)->main_iobase + CALIBRATION_REG);
+                              adc_src_bits(devpriv->calibration_source),
+                              devpriv->main_iobase + CALIBRATION_REG);
                } else {
                        /*  make sure internal calibration source is turned off */
-                       writew(0, priv(dev)->main_iobase + CALIBRATION_REG);
+                       writew(0, devpriv->main_iobase + CALIBRATION_REG);
                }
                /*  load internal queue */
                bits = 0;
@@ -1916,29 +1906,29 @@ static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
                bits |= adc_chan_bits(channel);
                /*  set stop channel */
                writew(adc_chan_bits(channel),
-                      priv(dev)->main_iobase + ADC_QUEUE_HIGH_REG);
+                      devpriv->main_iobase + ADC_QUEUE_HIGH_REG);
                /*  set start channel, and rest of settings */
-               writew(bits, priv(dev)->main_iobase + ADC_QUEUE_LOAD_REG);
+               writew(bits, devpriv->main_iobase + ADC_QUEUE_LOAD_REG);
        } else {
-               uint8_t old_cal_range_bits = priv(dev)->i2c_cal_range_bits;
+               uint8_t old_cal_range_bits = devpriv->i2c_cal_range_bits;
 
-               priv(dev)->i2c_cal_range_bits &= ~ADC_SRC_4020_MASK;
+               devpriv->i2c_cal_range_bits &= ~ADC_SRC_4020_MASK;
                if (insn->chanspec & CR_ALT_SOURCE) {
                        DEBUG_PRINT("reading calibration source\n");
-                       priv(dev)->i2c_cal_range_bits |=
-                           adc_src_4020_bits(priv(dev)->calibration_source);
+                       devpriv->i2c_cal_range_bits |=
+                           adc_src_4020_bits(devpriv->calibration_source);
                } else {        /* select BNC inputs */
-                       priv(dev)->i2c_cal_range_bits |= adc_src_4020_bits(4);
+                       devpriv->i2c_cal_range_bits |= adc_src_4020_bits(4);
                }
                /*  select range */
                if (range == 0)
-                       priv(dev)->i2c_cal_range_bits |= attenuate_bit(channel);
+                       devpriv->i2c_cal_range_bits |= attenuate_bit(channel);
                else
-                       priv(dev)->i2c_cal_range_bits &=
+                       devpriv->i2c_cal_range_bits &=
                            ~attenuate_bit(channel);
                /*  update calibration/range i2c register only if necessary, as it is very slow */
-               if (old_cal_range_bits != priv(dev)->i2c_cal_range_bits) {
-                       uint8_t i2c_data = priv(dev)->i2c_cal_range_bits;
+               if (old_cal_range_bits != devpriv->i2c_cal_range_bits) {
+                       uint8_t i2c_data = devpriv->i2c_cal_range_bits;
                        i2c_write(dev, RANGE_CAL_I2C_ADDR, &i2c_data,
                                  sizeof(i2c_data));
                }
@@ -1946,26 +1936,26 @@ static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
                /* 4020 manual asks that sample interval register to be set before writing to convert register.
                 * Using somewhat arbitrary setting of 4 master clock ticks = 0.1 usec */
                writew(0,
-                      priv(dev)->main_iobase + ADC_SAMPLE_INTERVAL_UPPER_REG);
+                      devpriv->main_iobase + ADC_SAMPLE_INTERVAL_UPPER_REG);
                writew(2,
-                      priv(dev)->main_iobase + ADC_SAMPLE_INTERVAL_LOWER_REG);
+                      devpriv->main_iobase + ADC_SAMPLE_INTERVAL_LOWER_REG);
        }
 
        for (n = 0; n < insn->n; n++) {
 
                /*  clear adc buffer (inside loop for 4020 sake) */
-               writew(0, priv(dev)->main_iobase + ADC_BUFFER_CLEAR_REG);
+               writew(0, devpriv->main_iobase + ADC_BUFFER_CLEAR_REG);
 
                /* trigger conversion, bits sent only matter for 4020 */
                writew(adc_convert_chan_4020_bits(CR_CHAN(insn->chanspec)),
-                      priv(dev)->main_iobase + ADC_CONVERT_REG);
+                      devpriv->main_iobase + ADC_CONVERT_REG);
 
                /*  wait for data */
                for (i = 0; i < timeout; i++) {
-                       bits = readw(priv(dev)->main_iobase + HW_STATUS_REG);
+                       bits = readw(devpriv->main_iobase + HW_STATUS_REG);
                        DEBUG_PRINT(" pipe bits 0x%x\n", pipe_full_bits(bits));
                        if (board(dev)->layout == LAYOUT_4020) {
-                               if (readw(priv(dev)->main_iobase +
+                               if (readw(devpriv->main_iobase +
                                          ADC_WRITE_PNTR_REG))
                                        break;
                        } else {
@@ -1982,11 +1972,11 @@ static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
                }
                if (board(dev)->layout == LAYOUT_4020)
                        data[n] =
-                           readl(priv(dev)->dio_counter_iobase +
+                           readl(devpriv->dio_counter_iobase +
                                  ADC_FIFO_REG) & 0xffff;
                else
                        data[n] =
-                           readw(priv(dev)->main_iobase + PIPE1_READ_REG);
+                           readw(devpriv->main_iobase + PIPE1_READ_REG);
        }
 
        return n;
@@ -1995,6 +1985,7 @@ static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
 static int ai_config_calibration_source(struct comedi_device *dev,
                                        unsigned int *data)
 {
+       struct pcidas64_private *devpriv = dev->private;
        unsigned int source = data[1];
        int num_calibration_sources;
 
@@ -2009,7 +2000,7 @@ static int ai_config_calibration_source(struct comedi_device *dev,
        }
 
        DEBUG_PRINT("setting calibration source to %i\n", source);
-       priv(dev)->calibration_source = source;
+       devpriv->calibration_source = source;
 
        return 2;
 }
@@ -2043,6 +2034,7 @@ static int ai_config_block_size(struct comedi_device *dev, unsigned int *data)
 static int ai_config_master_clock_4020(struct comedi_device *dev,
                                       unsigned int *data)
 {
+       struct pcidas64_private *devpriv = dev->private;
        unsigned int divisor = data[4];
        int retval = 0;
 
@@ -2053,8 +2045,8 @@ static int ai_config_master_clock_4020(struct comedi_device *dev,
 
        switch (data[1]) {
        case COMEDI_EV_SCAN_BEGIN:
-               priv(dev)->ext_clock.divisor = divisor;
-               priv(dev)->ext_clock.chanspec = data[2];
+               devpriv->ext_clock.divisor = divisor;
+               devpriv->ext_clock.chanspec = data[2];
                break;
        default:
                return -EINVAL;
@@ -2279,27 +2271,30 @@ static int use_hw_sample_counter(struct comedi_cmd *cmd)
 static void setup_sample_counters(struct comedi_device *dev,
                                  struct comedi_cmd *cmd)
 {
+       struct pcidas64_private *devpriv = dev->private;
+
        if (cmd->stop_src == TRIG_COUNT) {
                /*  set software count */
-               priv(dev)->ai_count = cmd->stop_arg * cmd->chanlist_len;
+               devpriv->ai_count = cmd->stop_arg * cmd->chanlist_len;
        }
        /*  load hardware conversion counter */
        if (use_hw_sample_counter(cmd)) {
                writew(cmd->stop_arg & 0xffff,
-                      priv(dev)->main_iobase + ADC_COUNT_LOWER_REG);
+                      devpriv->main_iobase + ADC_COUNT_LOWER_REG);
                writew((cmd->stop_arg >> 16) & 0xff,
-                      priv(dev)->main_iobase + ADC_COUNT_UPPER_REG);
+                      devpriv->main_iobase + ADC_COUNT_UPPER_REG);
        } else {
-               writew(1, priv(dev)->main_iobase + ADC_COUNT_LOWER_REG);
+               writew(1, devpriv->main_iobase + ADC_COUNT_LOWER_REG);
        }
 }
 
 static inline unsigned int dma_transfer_size(struct comedi_device *dev)
 {
+       struct pcidas64_private *devpriv = dev->private;
        unsigned int num_samples;
 
        num_samples =
-           priv(dev)->ai_fifo_segment_length *
+           devpriv->ai_fifo_segment_length *
            board(dev)->ai_fifo->sample_packing_ratio;
        if (num_samples > DMA_BUFFER_SIZE / sizeof(uint16_t))
                num_samples = DMA_BUFFER_SIZE / sizeof(uint16_t);
@@ -2309,40 +2304,43 @@ static inline unsigned int dma_transfer_size(struct comedi_device *dev)
 
 static void disable_ai_pacing(struct comedi_device *dev)
 {
+       struct pcidas64_private *devpriv = dev->private;
        unsigned long flags;
 
        disable_ai_interrupts(dev);
 
        spin_lock_irqsave(&dev->spinlock, flags);
-       priv(dev)->adc_control1_bits &= ~ADC_SW_GATE_BIT;
-       writew(priv(dev)->adc_control1_bits,
-              priv(dev)->main_iobase + ADC_CONTROL1_REG);
+       devpriv->adc_control1_bits &= ~ADC_SW_GATE_BIT;
+       writew(devpriv->adc_control1_bits,
+              devpriv->main_iobase + ADC_CONTROL1_REG);
        spin_unlock_irqrestore(&dev->spinlock, flags);
 
        /* disable pacing, triggering, etc */
        writew(ADC_DMA_DISABLE_BIT | ADC_SOFT_GATE_BITS | ADC_GATE_LEVEL_BIT,
-              priv(dev)->main_iobase + ADC_CONTROL0_REG);
+              devpriv->main_iobase + ADC_CONTROL0_REG);
 }
 
 static void disable_ai_interrupts(struct comedi_device *dev)
 {
+       struct pcidas64_private *devpriv = dev->private;
        unsigned long flags;
 
        spin_lock_irqsave(&dev->spinlock, flags);
-       priv(dev)->intr_enable_bits &=
+       devpriv->intr_enable_bits &=
            ~EN_ADC_INTR_SRC_BIT & ~EN_ADC_DONE_INTR_BIT &
            ~EN_ADC_ACTIVE_INTR_BIT & ~EN_ADC_STOP_INTR_BIT &
            ~EN_ADC_OVERRUN_BIT & ~ADC_INTR_SRC_MASK;
-       writew(priv(dev)->intr_enable_bits,
-              priv(dev)->main_iobase + INTR_ENABLE_REG);
+       writew(devpriv->intr_enable_bits,
+              devpriv->main_iobase + INTR_ENABLE_REG);
        spin_unlock_irqrestore(&dev->spinlock, flags);
 
-       DEBUG_PRINT("intr enable bits 0x%x\n", priv(dev)->intr_enable_bits);
+       DEBUG_PRINT("intr enable bits 0x%x\n", devpriv->intr_enable_bits);
 }
 
 static void enable_ai_interrupts(struct comedi_device *dev,
                                 const struct comedi_cmd *cmd)
 {
+       struct pcidas64_private *devpriv = dev->private;
        uint32_t bits;
        unsigned long flags;
 
@@ -2355,10 +2353,10 @@ static void enable_ai_interrupts(struct comedi_device *dev,
                        bits |= ADC_INTR_EOSCAN_BITS | EN_ADC_INTR_SRC_BIT;
        }
        spin_lock_irqsave(&dev->spinlock, flags);
-       priv(dev)->intr_enable_bits |= bits;
-       writew(priv(dev)->intr_enable_bits,
-              priv(dev)->main_iobase + INTR_ENABLE_REG);
-       DEBUG_PRINT("intr enable bits 0x%x\n", priv(dev)->intr_enable_bits);
+       devpriv->intr_enable_bits |= bits;
+       writew(devpriv->intr_enable_bits,
+              devpriv->main_iobase + INTR_ENABLE_REG);
+       DEBUG_PRINT("intr enable bits 0x%x\n", devpriv->intr_enable_bits);
        spin_unlock_irqrestore(&dev->spinlock, flags);
 }
 
@@ -2393,6 +2391,7 @@ static uint32_t ai_scan_counter_6xxx(struct comedi_device *dev,
 static uint32_t ai_convert_counter_4020(struct comedi_device *dev,
                                        struct comedi_cmd *cmd)
 {
+       struct pcidas64_private *devpriv = dev->private;
        unsigned int divisor;
 
        switch (cmd->scan_begin_src) {
@@ -2400,7 +2399,7 @@ static uint32_t ai_convert_counter_4020(struct comedi_device *dev,
                divisor = cmd->scan_begin_arg / TIMER_BASE;
                break;
        case TRIG_OTHER:
-               divisor = priv(dev)->ext_clock.divisor;
+               divisor = devpriv->ext_clock.divisor;
                break;
        default:                /*  should never happen */
                comedi_error(dev, "bug! failed to set ai pacing!");
@@ -2415,20 +2414,22 @@ static uint32_t ai_convert_counter_4020(struct comedi_device *dev,
 static void select_master_clock_4020(struct comedi_device *dev,
                                     const struct comedi_cmd *cmd)
 {
+       struct pcidas64_private *devpriv = dev->private;
+
        /*  select internal/external master clock */
-       priv(dev)->hw_config_bits &= ~MASTER_CLOCK_4020_MASK;
+       devpriv->hw_config_bits &= ~MASTER_CLOCK_4020_MASK;
        if (cmd->scan_begin_src == TRIG_OTHER) {
-               int chanspec = priv(dev)->ext_clock.chanspec;
+               int chanspec = devpriv->ext_clock.chanspec;
 
                if (CR_CHAN(chanspec))
-                       priv(dev)->hw_config_bits |= BNC_CLOCK_4020_BITS;
+                       devpriv->hw_config_bits |= BNC_CLOCK_4020_BITS;
                else
-                       priv(dev)->hw_config_bits |= EXT_CLOCK_4020_BITS;
+                       devpriv->hw_config_bits |= EXT_CLOCK_4020_BITS;
        } else {
-               priv(dev)->hw_config_bits |= INTERNAL_CLOCK_4020_BITS;
+               devpriv->hw_config_bits |= INTERNAL_CLOCK_4020_BITS;
        }
-       writew(priv(dev)->hw_config_bits,
-              priv(dev)->main_iobase + HW_CONFIG_REG);
+       writew(devpriv->hw_config_bits,
+              devpriv->main_iobase + HW_CONFIG_REG);
 }
 
 static void select_master_clock(struct comedi_device *dev,
@@ -2446,6 +2447,7 @@ static void select_master_clock(struct comedi_device *dev,
 static inline void dma_start_sync(struct comedi_device *dev,
                                  unsigned int channel)
 {
+       struct pcidas64_private *devpriv = dev->private;
        unsigned long flags;
 
        /*  spinlock for plx dma control/status reg */
@@ -2453,16 +2455,17 @@ static inline void dma_start_sync(struct comedi_device *dev,
        if (channel)
                writeb(PLX_DMA_EN_BIT | PLX_DMA_START_BIT |
                       PLX_CLEAR_DMA_INTR_BIT,
-                      priv(dev)->plx9080_iobase + PLX_DMA1_CS_REG);
+                      devpriv->plx9080_iobase + PLX_DMA1_CS_REG);
        else
                writeb(PLX_DMA_EN_BIT | PLX_DMA_START_BIT |
                       PLX_CLEAR_DMA_INTR_BIT,
-                      priv(dev)->plx9080_iobase + PLX_DMA0_CS_REG);
+                      devpriv->plx9080_iobase + PLX_DMA0_CS_REG);
        spin_unlock_irqrestore(&dev->spinlock, flags);
 }
 
 static void set_ai_pacing(struct comedi_device *dev, struct comedi_cmd *cmd)
 {
+       struct pcidas64_private *devpriv = dev->private;
        uint32_t convert_counter = 0, scan_counter = 0;
 
        check_adc_timing(dev, cmd);
@@ -2478,17 +2481,17 @@ static void set_ai_pacing(struct comedi_device *dev, struct comedi_cmd *cmd)
 
        /*  load lower 16 bits of convert interval */
        writew(convert_counter & 0xffff,
-              priv(dev)->main_iobase + ADC_SAMPLE_INTERVAL_LOWER_REG);
+              devpriv->main_iobase + ADC_SAMPLE_INTERVAL_LOWER_REG);
        DEBUG_PRINT("convert counter 0x%x\n", convert_counter);
        /*  load upper 8 bits of convert interval */
        writew((convert_counter >> 16) & 0xff,
-              priv(dev)->main_iobase + ADC_SAMPLE_INTERVAL_UPPER_REG);
+              devpriv->main_iobase + ADC_SAMPLE_INTERVAL_UPPER_REG);
        /*  load lower 16 bits of scan delay */
        writew(scan_counter & 0xffff,
-              priv(dev)->main_iobase + ADC_DELAY_INTERVAL_LOWER_REG);
+              devpriv->main_iobase + ADC_DELAY_INTERVAL_LOWER_REG);
        /*  load upper 8 bits of scan delay */
        writew((scan_counter >> 16) & 0xff,
-              priv(dev)->main_iobase + ADC_DELAY_INTERVAL_UPPER_REG);
+              devpriv->main_iobase + ADC_DELAY_INTERVAL_UPPER_REG);
        DEBUG_PRINT("scan counter 0x%x\n", scan_counter);
 }
 
@@ -2511,14 +2514,15 @@ static int use_internal_queue_6xxx(const struct comedi_cmd *cmd)
 static int setup_channel_queue(struct comedi_device *dev,
                               const struct comedi_cmd *cmd)
 {
+       struct pcidas64_private *devpriv = dev->private;
        unsigned short bits;
        int i;
 
        if (board(dev)->layout != LAYOUT_4020) {
                if (use_internal_queue_6xxx(cmd)) {
-                       priv(dev)->hw_config_bits &= ~EXT_QUEUE_BIT;
-                       writew(priv(dev)->hw_config_bits,
-                              priv(dev)->main_iobase + HW_CONFIG_REG);
+                       devpriv->hw_config_bits &= ~EXT_QUEUE_BIT;
+                       writew(devpriv->hw_config_bits,
+                              devpriv->main_iobase + HW_CONFIG_REG);
                        bits = 0;
                        /*  set channel */
                        bits |= adc_chan_bits(CR_CHAN(cmd->chanlist[0]));
@@ -2534,24 +2538,24 @@ static int setup_channel_queue(struct comedi_device *dev,
                        /*  set stop channel */
                        writew(adc_chan_bits
                               (CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1])),
-                              priv(dev)->main_iobase + ADC_QUEUE_HIGH_REG);
+                              devpriv->main_iobase + ADC_QUEUE_HIGH_REG);
                        /*  set start channel, and rest of settings */
                        writew(bits,
-                              priv(dev)->main_iobase + ADC_QUEUE_LOAD_REG);
+                              devpriv->main_iobase + ADC_QUEUE_LOAD_REG);
                } else {
                        /*  use external queue */
                        if (dev->write_subdev && dev->write_subdev->busy) {
                                warn_external_queue(dev);
                                return -EBUSY;
                        }
-                       priv(dev)->hw_config_bits |= EXT_QUEUE_BIT;
-                       writew(priv(dev)->hw_config_bits,
-                              priv(dev)->main_iobase + HW_CONFIG_REG);
+                       devpriv->hw_config_bits |= EXT_QUEUE_BIT;
+                       writew(devpriv->hw_config_bits,
+                              devpriv->main_iobase + HW_CONFIG_REG);
                        /*  clear DAC buffer to prevent weird interactions */
                        writew(0,
-                              priv(dev)->main_iobase + DAC_BUFFER_CLEAR_REG);
+                              devpriv->main_iobase + DAC_BUFFER_CLEAR_REG);
                        /*  clear queue pointer */
-                       writew(0, priv(dev)->main_iobase + ADC_QUEUE_CLEAR_REG);
+                       writew(0, devpriv->main_iobase + ADC_QUEUE_CLEAR_REG);
                        /*  load external queue */
                        for (i = 0; i < cmd->chanlist_len; i++) {
                                bits = 0;
@@ -2575,7 +2579,7 @@ static int setup_channel_queue(struct comedi_device *dev,
                                        bits |= QUEUE_EOSCAN_BIT |
                                            QUEUE_EOSEQ_BIT;
                                writew(bits,
-                                      priv(dev)->main_iobase +
+                                      devpriv->main_iobase +
                                       ADC_QUEUE_FIFO_REG);
                                DEBUG_PRINT
                                    ("wrote 0x%x to external channel queue\n",
@@ -2583,32 +2587,32 @@ static int setup_channel_queue(struct comedi_device *dev,
                        }
                        /* doing a queue clear is not specified in board docs,
                         * but required for reliable operation */
-                       writew(0, priv(dev)->main_iobase + ADC_QUEUE_CLEAR_REG);
+                       writew(0, devpriv->main_iobase + ADC_QUEUE_CLEAR_REG);
                        /*  prime queue holding register */
-                       writew(0, priv(dev)->main_iobase + ADC_QUEUE_LOAD_REG);
+                       writew(0, devpriv->main_iobase + ADC_QUEUE_LOAD_REG);
                }
        } else {
                unsigned short old_cal_range_bits =
-                   priv(dev)->i2c_cal_range_bits;
+                   devpriv->i2c_cal_range_bits;
 
-               priv(dev)->i2c_cal_range_bits &= ~ADC_SRC_4020_MASK;
+               devpriv->i2c_cal_range_bits &= ~ADC_SRC_4020_MASK;
                /* select BNC inputs */
-               priv(dev)->i2c_cal_range_bits |= adc_src_4020_bits(4);
+               devpriv->i2c_cal_range_bits |= adc_src_4020_bits(4);
                /*  select ranges */
                for (i = 0; i < cmd->chanlist_len; i++) {
                        unsigned int channel = CR_CHAN(cmd->chanlist[i]);
                        unsigned int range = CR_RANGE(cmd->chanlist[i]);
 
                        if (range == 0)
-                               priv(dev)->i2c_cal_range_bits |=
+                               devpriv->i2c_cal_range_bits |=
                                    attenuate_bit(channel);
                        else
-                               priv(dev)->i2c_cal_range_bits &=
+                               devpriv->i2c_cal_range_bits &=
                                    ~attenuate_bit(channel);
                }
                /*  update calibration/range i2c register only if necessary, as it is very slow */
-               if (old_cal_range_bits != priv(dev)->i2c_cal_range_bits) {
-                       uint8_t i2c_data = priv(dev)->i2c_cal_range_bits;
+               if (old_cal_range_bits != devpriv->i2c_cal_range_bits) {
+                       uint8_t i2c_data = devpriv->i2c_cal_range_bits;
                        i2c_write(dev, RANGE_CAL_I2C_ADDR, &i2c_data,
                                  sizeof(i2c_data));
                }
@@ -2620,6 +2624,8 @@ static inline void load_first_dma_descriptor(struct comedi_device *dev,
                                             unsigned int dma_channel,
                                             unsigned int descriptor_bits)
 {
+       struct pcidas64_private *devpriv = dev->private;
+
        /* The transfer size, pci address, and local address registers
         * are supposedly unused during chained dma,
         * but I have found that left over values from last operation
@@ -2627,25 +2633,26 @@ static inline void load_first_dma_descriptor(struct comedi_device *dev,
         * block.  Initializing them to zero seems to fix the problem. */
        if (dma_channel) {
                writel(0,
-                      priv(dev)->plx9080_iobase + PLX_DMA1_TRANSFER_SIZE_REG);
-               writel(0, priv(dev)->plx9080_iobase + PLX_DMA1_PCI_ADDRESS_REG);
+                      devpriv->plx9080_iobase + PLX_DMA1_TRANSFER_SIZE_REG);
+               writel(0, devpriv->plx9080_iobase + PLX_DMA1_PCI_ADDRESS_REG);
                writel(0,
-                      priv(dev)->plx9080_iobase + PLX_DMA1_LOCAL_ADDRESS_REG);
+                      devpriv->plx9080_iobase + PLX_DMA1_LOCAL_ADDRESS_REG);
                writel(descriptor_bits,
-                      priv(dev)->plx9080_iobase + PLX_DMA1_DESCRIPTOR_REG);
+                      devpriv->plx9080_iobase + PLX_DMA1_DESCRIPTOR_REG);
        } else {
                writel(0,
-                      priv(dev)->plx9080_iobase + PLX_DMA0_TRANSFER_SIZE_REG);
-               writel(0, priv(dev)->plx9080_iobase + PLX_DMA0_PCI_ADDRESS_REG);
+                      devpriv->plx9080_iobase + PLX_DMA0_TRANSFER_SIZE_REG);
+               writel(0, devpriv->plx9080_iobase + PLX_DMA0_PCI_ADDRESS_REG);
                writel(0,
-                      priv(dev)->plx9080_iobase + PLX_DMA0_LOCAL_ADDRESS_REG);
+                      devpriv->plx9080_iobase + PLX_DMA0_LOCAL_ADDRESS_REG);
                writel(descriptor_bits,
-                      priv(dev)->plx9080_iobase + PLX_DMA0_DESCRIPTOR_REG);
+                      devpriv->plx9080_iobase + PLX_DMA0_DESCRIPTOR_REG);
        }
 }
 
 static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+       struct pcidas64_private *devpriv = dev->private;
        struct comedi_async *async = s->async;
        struct comedi_cmd *cmd = &async->cmd;
        uint32_t bits;
@@ -2661,7 +2668,7 @@ static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
                return retval;
 
        /*  make sure internal calibration source is turned off */
-       writew(0, priv(dev)->main_iobase + CALIBRATION_REG);
+       writew(0, devpriv->main_iobase + CALIBRATION_REG);
 
        set_ai_pacing(dev, cmd);
 
@@ -2671,50 +2678,50 @@ static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 
        spin_lock_irqsave(&dev->spinlock, flags);
        /* set mode, allow conversions through software gate */
-       priv(dev)->adc_control1_bits |= ADC_SW_GATE_BIT;
-       priv(dev)->adc_control1_bits &= ~ADC_DITHER_BIT;
+       devpriv->adc_control1_bits |= ADC_SW_GATE_BIT;
+       devpriv->adc_control1_bits &= ~ADC_DITHER_BIT;
        if (board(dev)->layout != LAYOUT_4020) {
-               priv(dev)->adc_control1_bits &= ~ADC_MODE_MASK;
+               devpriv->adc_control1_bits &= ~ADC_MODE_MASK;
                if (cmd->convert_src == TRIG_EXT)
-                       priv(dev)->adc_control1_bits |= adc_mode_bits(13);      /*  good old mode 13 */
+                       devpriv->adc_control1_bits |= adc_mode_bits(13);        /*  good old mode 13 */
                else
-                       priv(dev)->adc_control1_bits |= adc_mode_bits(8);       /*  mode 8.  What else could you need? */
+                       devpriv->adc_control1_bits |= adc_mode_bits(8); /*  mode 8.  What else could you need? */
        } else {
-               priv(dev)->adc_control1_bits &= ~CHANNEL_MODE_4020_MASK;
+               devpriv->adc_control1_bits &= ~CHANNEL_MODE_4020_MASK;
                if (cmd->chanlist_len == 4)
-                       priv(dev)->adc_control1_bits |= FOUR_CHANNEL_4020_BITS;
+                       devpriv->adc_control1_bits |= FOUR_CHANNEL_4020_BITS;
                else if (cmd->chanlist_len == 2)
-                       priv(dev)->adc_control1_bits |= TWO_CHANNEL_4020_BITS;
-               priv(dev)->adc_control1_bits &= ~ADC_LO_CHANNEL_4020_MASK;
-               priv(dev)->adc_control1_bits |=
+                       devpriv->adc_control1_bits |= TWO_CHANNEL_4020_BITS;
+               devpriv->adc_control1_bits &= ~ADC_LO_CHANNEL_4020_MASK;
+               devpriv->adc_control1_bits |=
                    adc_lo_chan_4020_bits(CR_CHAN(cmd->chanlist[0]));
-               priv(dev)->adc_control1_bits &= ~ADC_HI_CHANNEL_4020_MASK;
-               priv(dev)->adc_control1_bits |=
+               devpriv->adc_control1_bits &= ~ADC_HI_CHANNEL_4020_MASK;
+               devpriv->adc_control1_bits |=
                    adc_hi_chan_4020_bits(CR_CHAN
                                          (cmd->
                                           chanlist[cmd->chanlist_len - 1]));
        }
-       writew(priv(dev)->adc_control1_bits,
-              priv(dev)->main_iobase + ADC_CONTROL1_REG);
-       DEBUG_PRINT("control1 bits 0x%x\n", priv(dev)->adc_control1_bits);
+       writew(devpriv->adc_control1_bits,
+              devpriv->main_iobase + ADC_CONTROL1_REG);
+       DEBUG_PRINT("control1 bits 0x%x\n", devpriv->adc_control1_bits);
        spin_unlock_irqrestore(&dev->spinlock, flags);
 
        /*  clear adc buffer */
-       writew(0, priv(dev)->main_iobase + ADC_BUFFER_CLEAR_REG);
+       writew(0, devpriv->main_iobase + ADC_BUFFER_CLEAR_REG);
 
        if ((cmd->flags & TRIG_WAKE_EOS) == 0 ||
            board(dev)->layout == LAYOUT_4020) {
-               priv(dev)->ai_dma_index = 0;
+               devpriv->ai_dma_index = 0;
 
                /*  set dma transfer size */
                for (i = 0; i < ai_dma_ring_count(board(dev)); i++)
-                       priv(dev)->ai_dma_desc[i].transfer_size =
+                       devpriv->ai_dma_desc[i].transfer_size =
                            cpu_to_le32(dma_transfer_size(dev) *
                                        sizeof(uint16_t));
 
                /*  give location of first dma descriptor */
                load_first_dma_descriptor(dev, 1,
-                                         priv(dev)->ai_dma_desc_bus_addr |
+                                         devpriv->ai_dma_desc_bus_addr |
                                          PLX_DESC_IN_PCI_BIT |
                                          PLX_INTR_TERM_COUNT |
                                          PLX_XFER_LOCAL_TO_PCI);
@@ -2729,7 +2736,7 @@ static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
                        bits |= EXT_START_TRIG_BNC_BIT;
                if (cmd->stop_src == TRIG_EXT && CR_CHAN(cmd->stop_arg))
                        bits |= EXT_STOP_TRIG_BNC_BIT;
-               writew(bits, priv(dev)->main_iobase + DAQ_ATRIG_LOW_4020_REG);
+               writew(bits, devpriv->main_iobase + DAQ_ATRIG_LOW_4020_REG);
        }
 
        spin_lock_irqsave(&dev->spinlock, flags);
@@ -2747,16 +2754,16 @@ static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
                bits |= ADC_START_TRIG_SOFT_BITS;
        if (use_hw_sample_counter(cmd))
                bits |= ADC_SAMPLE_COUNTER_EN_BIT;
-       writew(bits, priv(dev)->main_iobase + ADC_CONTROL0_REG);
+       writew(bits, devpriv->main_iobase + ADC_CONTROL0_REG);
        DEBUG_PRINT("control0 bits 0x%x\n", bits);
 
-       priv(dev)->ai_cmd_running = 1;
+       devpriv->ai_cmd_running = 1;
 
        spin_unlock_irqrestore(&dev->spinlock, flags);
 
        /*  start acquisition */
        if (cmd->start_src == TRIG_NOW) {
-               writew(0, priv(dev)->main_iobase + ADC_START_REG);
+               writew(0, devpriv->main_iobase + ADC_START_REG);
                DEBUG_PRINT("soft trig\n");
        }
 
@@ -2766,6 +2773,7 @@ static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 /* read num_samples from 16 bit wide ai fifo */
 static void pio_drain_ai_fifo_16(struct comedi_device *dev)
 {
+       struct pcidas64_private *devpriv = dev->private;
        struct comedi_subdevice *s = dev->read_subdev;
        struct comedi_async *async = s->async;
        struct comedi_cmd *cmd = &async->cmd;
@@ -2777,14 +2785,14 @@ static void pio_drain_ai_fifo_16(struct comedi_device *dev)
        do {
                /*  get least significant 15 bits */
                read_index =
-                   readw(priv(dev)->main_iobase + ADC_READ_PNTR_REG) & 0x7fff;
+                   readw(devpriv->main_iobase + ADC_READ_PNTR_REG) & 0x7fff;
                write_index =
-                   readw(priv(dev)->main_iobase + ADC_WRITE_PNTR_REG) & 0x7fff;
+                   readw(devpriv->main_iobase + ADC_WRITE_PNTR_REG) & 0x7fff;
                /* Get most significant bits (grey code).  Different boards use different code
                 * so use a scheme that doesn't depend on encoding.  This read must
                 * occur after reading least significant 15 bits to avoid race
                 * with fifo switching to next segment. */
-               prepost_bits = readw(priv(dev)->main_iobase + PREPOST_REG);
+               prepost_bits = readw(devpriv->main_iobase + PREPOST_REG);
 
                /* if read and write pointers are not on the same fifo segment, read to the
                 * end of the read segment */
@@ -2797,17 +2805,17 @@ static void pio_drain_ai_fifo_16(struct comedi_device *dev)
 
                if (read_segment != write_segment)
                        num_samples =
-                           priv(dev)->ai_fifo_segment_length - read_index;
+                           devpriv->ai_fifo_segment_length - read_index;
                else
                        num_samples = write_index - read_index;
 
                if (cmd->stop_src == TRIG_COUNT) {
-                       if (priv(dev)->ai_count == 0)
+                       if (devpriv->ai_count == 0)
                                break;
-                       if (num_samples > priv(dev)->ai_count)
-                               num_samples = priv(dev)->ai_count;
+                       if (num_samples > devpriv->ai_count)
+                               num_samples = devpriv->ai_count;
 
-                       priv(dev)->ai_count -= num_samples;
+                       devpriv->ai_count -= num_samples;
                }
 
                if (num_samples < 0) {
@@ -2820,7 +2828,7 @@ static void pio_drain_ai_fifo_16(struct comedi_device *dev)
 
                for (i = 0; i < num_samples; i++) {
                        cfc_write_to_buffer(s,
-                                           readw(priv(dev)->main_iobase +
+                                           readw(devpriv->main_iobase +
                                                  ADC_FIFO_REG));
                }
 
@@ -2834,6 +2842,7 @@ static void pio_drain_ai_fifo_16(struct comedi_device *dev)
  */
 static void pio_drain_ai_fifo_32(struct comedi_device *dev)
 {
+       struct pcidas64_private *devpriv = dev->private;
        struct comedi_subdevice *s = dev->read_subdev;
        struct comedi_async *async = s->async;
        struct comedi_cmd *cmd = &async->cmd;
@@ -2841,17 +2850,17 @@ static void pio_drain_ai_fifo_32(struct comedi_device *dev)
        unsigned int max_transfer = 100000;
        uint32_t fifo_data;
        int write_code =
-           readw(priv(dev)->main_iobase + ADC_WRITE_PNTR_REG) & 0x7fff;
+           readw(devpriv->main_iobase + ADC_WRITE_PNTR_REG) & 0x7fff;
        int read_code =
-           readw(priv(dev)->main_iobase + ADC_READ_PNTR_REG) & 0x7fff;
+           readw(devpriv->main_iobase + ADC_READ_PNTR_REG) & 0x7fff;
 
        if (cmd->stop_src == TRIG_COUNT) {
-               if (max_transfer > priv(dev)->ai_count)
-                       max_transfer = priv(dev)->ai_count;
+               if (max_transfer > devpriv->ai_count)
+                       max_transfer = devpriv->ai_count;
 
        }
        for (i = 0; read_code != write_code && i < max_transfer;) {
-               fifo_data = readl(priv(dev)->dio_counter_iobase + ADC_FIFO_REG);
+               fifo_data = readl(devpriv->dio_counter_iobase + ADC_FIFO_REG);
                cfc_write_to_buffer(s, fifo_data & 0xffff);
                i++;
                if (i < max_transfer) {
@@ -2859,9 +2868,9 @@ static void pio_drain_ai_fifo_32(struct comedi_device *dev)
                        i++;
                }
                read_code =
-                   readw(priv(dev)->main_iobase + ADC_READ_PNTR_REG) & 0x7fff;
+                   readw(devpriv->main_iobase + ADC_READ_PNTR_REG) & 0x7fff;
        }
-       priv(dev)->ai_count -= i;
+       devpriv->ai_count -= i;
 }
 
 /* empty fifo */
@@ -2875,6 +2884,7 @@ static void pio_drain_ai_fifo(struct comedi_device *dev)
 
 static void drain_dma_buffers(struct comedi_device *dev, unsigned int channel)
 {
+       struct pcidas64_private *devpriv = dev->private;
        struct comedi_async *async = dev->read_subdev->async;
        uint32_t next_transfer_addr;
        int j;
@@ -2883,36 +2893,36 @@ static void drain_dma_buffers(struct comedi_device *dev, unsigned int channel)
 
        if (channel)
                pci_addr_reg =
-                   priv(dev)->plx9080_iobase + PLX_DMA1_PCI_ADDRESS_REG;
+                   devpriv->plx9080_iobase + PLX_DMA1_PCI_ADDRESS_REG;
        else
                pci_addr_reg =
-                   priv(dev)->plx9080_iobase + PLX_DMA0_PCI_ADDRESS_REG;
+                   devpriv->plx9080_iobase + PLX_DMA0_PCI_ADDRESS_REG;
 
        /*  loop until we have read all the full buffers */
        for (j = 0, next_transfer_addr = readl(pci_addr_reg);
             (next_transfer_addr <
-             priv(dev)->ai_buffer_bus_addr[priv(dev)->ai_dma_index]
+             devpriv->ai_buffer_bus_addr[devpriv->ai_dma_index]
              || next_transfer_addr >=
-             priv(dev)->ai_buffer_bus_addr[priv(dev)->ai_dma_index] +
+             devpriv->ai_buffer_bus_addr[devpriv->ai_dma_index] +
              DMA_BUFFER_SIZE) && j < ai_dma_ring_count(board(dev)); j++) {
                /*  transfer data from dma buffer to comedi buffer */
                num_samples = dma_transfer_size(dev);
                if (async->cmd.stop_src == TRIG_COUNT) {
-                       if (num_samples > priv(dev)->ai_count)
-                               num_samples = priv(dev)->ai_count;
-                       priv(dev)->ai_count -= num_samples;
+                       if (num_samples > devpriv->ai_count)
+                               num_samples = devpriv->ai_count;
+                       devpriv->ai_count -= num_samples;
                }
                cfc_write_array_to_buffer(dev->read_subdev,
-                                         priv(dev)->ai_buffer[priv(dev)->
+                                         devpriv->ai_buffer[devpriv->
                                                               ai_dma_index],
                                          num_samples * sizeof(uint16_t));
-               priv(dev)->ai_dma_index =
-                   (priv(dev)->ai_dma_index +
+               devpriv->ai_dma_index =
+                   (devpriv->ai_dma_index +
                     1) % ai_dma_ring_count(board(dev));
 
                DEBUG_PRINT("next buffer addr 0x%lx\n",
-                           (unsigned long)priv(dev)->
-                           ai_buffer_bus_addr[priv(dev)->ai_dma_index]);
+                           (unsigned long)devpriv->
+                           ai_buffer_bus_addr[devpriv->ai_dma_index]);
                DEBUG_PRINT("pci addr reg 0x%x\n", next_transfer_addr);
        }
        /* XXX check for dma ring buffer overrun (use end-of-chain bit to mark last
@@ -2923,6 +2933,7 @@ static void handle_ai_interrupt(struct comedi_device *dev,
                                unsigned short status,
                                unsigned int plx_status)
 {
+       struct pcidas64_private *devpriv = dev->private;
        struct comedi_subdevice *s = dev->read_subdev;
        struct comedi_async *async = s->async;
        struct comedi_cmd *cmd = &async->cmd;
@@ -2936,10 +2947,10 @@ static void handle_ai_interrupt(struct comedi_device *dev,
        }
        /*  spin lock makes sure no one else changes plx dma control reg */
        spin_lock_irqsave(&dev->spinlock, flags);
-       dma1_status = readb(priv(dev)->plx9080_iobase + PLX_DMA1_CS_REG);
+       dma1_status = readb(devpriv->plx9080_iobase + PLX_DMA1_CS_REG);
        if (plx_status & ICS_DMA1_A) {  /*  dma chan 1 interrupt */
                writeb((dma1_status & PLX_DMA_EN_BIT) | PLX_CLEAR_DMA_INTR_BIT,
-                      priv(dev)->plx9080_iobase + PLX_DMA1_CS_REG);
+                      devpriv->plx9080_iobase + PLX_DMA1_CS_REG);
                DEBUG_PRINT("dma1 status 0x%x\n", dma1_status);
 
                if (dma1_status & PLX_DMA_EN_BIT)
@@ -2959,14 +2970,14 @@ static void handle_ai_interrupt(struct comedi_device *dev,
             (board(dev)->layout != LAYOUT_4020))) {
                DEBUG_PRINT("pio fifo drain\n");
                spin_lock_irqsave(&dev->spinlock, flags);
-               if (priv(dev)->ai_cmd_running) {
+               if (devpriv->ai_cmd_running) {
                        spin_unlock_irqrestore(&dev->spinlock, flags);
                        pio_drain_ai_fifo(dev);
                } else
                        spin_unlock_irqrestore(&dev->spinlock, flags);
        }
        /*  if we are have all the data, then quit */
-       if ((cmd->stop_src == TRIG_COUNT && (int)priv(dev)->ai_count <= 0) ||
+       if ((cmd->stop_src == TRIG_COUNT && (int)devpriv->ai_count <= 0) ||
            (cmd->stop_src == TRIG_EXT && (status & ADC_STOP_BIT))) {
                async->events |= COMEDI_CB_EOA;
        }
@@ -2976,29 +2987,31 @@ static void handle_ai_interrupt(struct comedi_device *dev,
 
 static inline unsigned int prev_ao_dma_index(struct comedi_device *dev)
 {
+       struct pcidas64_private *devpriv = dev->private;
        unsigned int buffer_index;
 
-       if (priv(dev)->ao_dma_index == 0)
+       if (devpriv->ao_dma_index == 0)
                buffer_index = AO_DMA_RING_COUNT - 1;
        else
-               buffer_index = priv(dev)->ao_dma_index - 1;
+               buffer_index = devpriv->ao_dma_index - 1;
        return buffer_index;
 }
 
 static int last_ao_dma_load_completed(struct comedi_device *dev)
 {
+       struct pcidas64_private *devpriv = dev->private;
        unsigned int buffer_index;
        unsigned int transfer_address;
        unsigned short dma_status;
 
        buffer_index = prev_ao_dma_index(dev);
-       dma_status = readb(priv(dev)->plx9080_iobase + PLX_DMA0_CS_REG);
+       dma_status = readb(devpriv->plx9080_iobase + PLX_DMA0_CS_REG);
        if ((dma_status & PLX_DMA_DONE_BIT) == 0)
                return 0;
 
        transfer_address =
-           readl(priv(dev)->plx9080_iobase + PLX_DMA0_PCI_ADDRESS_REG);
-       if (transfer_address != priv(dev)->ao_buffer_bus_addr[buffer_index])
+           readl(devpriv->plx9080_iobase + PLX_DMA0_PCI_ADDRESS_REG);
+       if (transfer_address != devpriv->ao_buffer_bus_addr[buffer_index])
                return 0;
 
        return 1;
@@ -3007,10 +3020,12 @@ static int last_ao_dma_load_completed(struct comedi_device *dev)
 static int ao_stopped_by_error(struct comedi_device *dev,
                               const struct comedi_cmd *cmd)
 {
+       struct pcidas64_private *devpriv = dev->private;
+
        if (cmd->stop_src == TRIG_NONE)
                return 1;
        if (cmd->stop_src == TRIG_COUNT) {
-               if (priv(dev)->ao_count)
+               if (devpriv->ao_count)
                        return 1;
                if (last_ao_dma_load_completed(dev) == 0)
                        return 1;
@@ -3032,10 +3047,11 @@ static inline int ao_dma_needs_restart(struct comedi_device *dev,
 
 static void restart_ao_dma(struct comedi_device *dev)
 {
+       struct pcidas64_private *devpriv = dev->private;
        unsigned int dma_desc_bits;
 
        dma_desc_bits =
-           readl(priv(dev)->plx9080_iobase + PLX_DMA0_DESCRIPTOR_REG);
+           readl(devpriv->plx9080_iobase + PLX_DMA0_DESCRIPTOR_REG);
        dma_desc_bits &= ~PLX_END_OF_CHAIN_BIT;
        DEBUG_PRINT("restarting ao dma, descriptor reg 0x%x\n", dma_desc_bits);
        load_first_dma_descriptor(dev, 0, dma_desc_bits);
@@ -3046,6 +3062,7 @@ static void restart_ao_dma(struct comedi_device *dev)
 static void handle_ao_interrupt(struct comedi_device *dev,
                                unsigned short status, unsigned int plx_status)
 {
+       struct pcidas64_private *devpriv = dev->private;
        struct comedi_subdevice *s = dev->write_subdev;
        struct comedi_async *async;
        struct comedi_cmd *cmd;
@@ -3060,15 +3077,15 @@ static void handle_ao_interrupt(struct comedi_device *dev,
 
        /*  spin lock makes sure no one else changes plx dma control reg */
        spin_lock_irqsave(&dev->spinlock, flags);
-       dma0_status = readb(priv(dev)->plx9080_iobase + PLX_DMA0_CS_REG);
+       dma0_status = readb(devpriv->plx9080_iobase + PLX_DMA0_CS_REG);
        if (plx_status & ICS_DMA0_A) {  /*  dma chan 0 interrupt */
                if ((dma0_status & PLX_DMA_EN_BIT)
                    && !(dma0_status & PLX_DMA_DONE_BIT))
                        writeb(PLX_DMA_EN_BIT | PLX_CLEAR_DMA_INTR_BIT,
-                              priv(dev)->plx9080_iobase + PLX_DMA0_CS_REG);
+                              devpriv->plx9080_iobase + PLX_DMA0_CS_REG);
                else
                        writeb(PLX_CLEAR_DMA_INTR_BIT,
-                              priv(dev)->plx9080_iobase + PLX_DMA0_CS_REG);
+                              devpriv->plx9080_iobase + PLX_DMA0_CS_REG);
                spin_unlock_irqrestore(&dev->spinlock, flags);
                DEBUG_PRINT("dma0 status 0x%x\n", dma0_status);
                if (dma0_status & PLX_DMA_EN_BIT) {
@@ -3086,10 +3103,10 @@ static void handle_ao_interrupt(struct comedi_device *dev,
                if (ao_stopped_by_error(dev, cmd))
                        async->events |= COMEDI_CB_ERROR;
                DEBUG_PRINT("plx dma0 desc reg 0x%x\n",
-                           readl(priv(dev)->plx9080_iobase +
+                           readl(devpriv->plx9080_iobase +
                                  PLX_DMA0_DESCRIPTOR_REG));
                DEBUG_PRINT("plx dma0 address reg 0x%x\n",
-                           readl(priv(dev)->plx9080_iobase +
+                           readl(devpriv->plx9080_iobase +
                                  PLX_DMA0_PCI_ADDRESS_REG));
        }
        cfc_handle_events(dev, s);
@@ -3098,12 +3115,13 @@ static void handle_ao_interrupt(struct comedi_device *dev,
 static irqreturn_t handle_interrupt(int irq, void *d)
 {
        struct comedi_device *dev = d;
+       struct pcidas64_private *devpriv = dev->private;
        unsigned short status;
        uint32_t plx_status;
        uint32_t plx_bits;
 
-       plx_status = readl(priv(dev)->plx9080_iobase + PLX_INTRCS_REG);
-       status = readw(priv(dev)->main_iobase + HW_STATUS_REG);
+       plx_status = readl(devpriv->plx9080_iobase + PLX_INTRCS_REG);
+       status = readw(devpriv->main_iobase + HW_STATUS_REG);
 
        DEBUG_PRINT("cb_pcidas64: hw status 0x%x ", status);
        DEBUG_PRINT("plx status 0x%x\n", plx_status);
@@ -3121,8 +3139,8 @@ static irqreturn_t handle_interrupt(int irq, void *d)
 
        /*  clear possible plx9080 interrupt sources */
        if (plx_status & ICS_LDIA) {    /*  clear local doorbell interrupt */
-               plx_bits = readl(priv(dev)->plx9080_iobase + PLX_DBR_OUT_REG);
-               writel(plx_bits, priv(dev)->plx9080_iobase + PLX_DBR_OUT_REG);
+               plx_bits = readl(devpriv->plx9080_iobase + PLX_DBR_OUT_REG);
+               writel(plx_bits, devpriv->plx9080_iobase + PLX_DBR_OUT_REG);
                DEBUG_PRINT(" cleared local doorbell bits 0x%x\n", plx_bits);
        }
 
@@ -3133,26 +3151,28 @@ static irqreturn_t handle_interrupt(int irq, void *d)
 
 static void abort_dma(struct comedi_device *dev, unsigned int channel)
 {
+       struct pcidas64_private *devpriv = dev->private;
        unsigned long flags;
 
        /*  spinlock for plx dma control/status reg */
        spin_lock_irqsave(&dev->spinlock, flags);
 
-       plx9080_abort_dma(priv(dev)->plx9080_iobase, channel);
+       plx9080_abort_dma(devpriv->plx9080_iobase, channel);
 
        spin_unlock_irqrestore(&dev->spinlock, flags);
 }
 
 static int ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+       struct pcidas64_private *devpriv = dev->private;
        unsigned long flags;
 
        spin_lock_irqsave(&dev->spinlock, flags);
-       if (priv(dev)->ai_cmd_running == 0) {
+       if (devpriv->ai_cmd_running == 0) {
                spin_unlock_irqrestore(&dev->spinlock, flags);
                return 0;
        }
-       priv(dev)->ai_cmd_running = 0;
+       devpriv->ai_cmd_running = 0;
        spin_unlock_irqrestore(&dev->spinlock, flags);
 
        disable_ai_pacing(dev);
@@ -3166,29 +3186,30 @@ static int ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
 static int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
                    struct comedi_insn *insn, unsigned int *data)
 {
+       struct pcidas64_private *devpriv = dev->private;
        int chan = CR_CHAN(insn->chanspec);
        int range = CR_RANGE(insn->chanspec);
 
        /*  do some initializing */
-       writew(0, priv(dev)->main_iobase + DAC_CONTROL0_REG);
+       writew(0, devpriv->main_iobase + DAC_CONTROL0_REG);
 
        /*  set range */
-       set_dac_range_bits(dev, &priv(dev)->dac_control1_bits, chan, range);
-       writew(priv(dev)->dac_control1_bits,
-              priv(dev)->main_iobase + DAC_CONTROL1_REG);
+       set_dac_range_bits(dev, &devpriv->dac_control1_bits, chan, range);
+       writew(devpriv->dac_control1_bits,
+              devpriv->main_iobase + DAC_CONTROL1_REG);
 
        /*  write to channel */
        if (board(dev)->layout == LAYOUT_4020) {
                writew(data[0] & 0xff,
-                      priv(dev)->main_iobase + dac_lsb_4020_reg(chan));
+                      devpriv->main_iobase + dac_lsb_4020_reg(chan));
                writew((data[0] >> 8) & 0xf,
-                      priv(dev)->main_iobase + dac_msb_4020_reg(chan));
+                      devpriv->main_iobase + dac_msb_4020_reg(chan));
        } else {
-               writew(data[0], priv(dev)->main_iobase + dac_convert_reg(chan));
+               writew(data[0], devpriv->main_iobase + dac_convert_reg(chan));
        }
 
        /*  remember output value */
-       priv(dev)->ao_value[chan] = data[0];
+       devpriv->ao_value[chan] = data[0];
 
        return 1;
 }
@@ -3197,7 +3218,9 @@ static int ao_readback_insn(struct comedi_device *dev,
                            struct comedi_subdevice *s,
                            struct comedi_insn *insn, unsigned int *data)
 {
-       data[0] = priv(dev)->ao_value[CR_CHAN(insn->chanspec)];
+       struct pcidas64_private *devpriv = dev->private;
+
+       data[0] = devpriv->ao_value[CR_CHAN(insn->chanspec)];
 
        return 1;
 }
@@ -3205,6 +3228,7 @@ static int ao_readback_insn(struct comedi_device *dev,
 static void set_dac_control0_reg(struct comedi_device *dev,
                                 const struct comedi_cmd *cmd)
 {
+       struct pcidas64_private *devpriv = dev->private;
        unsigned int bits = DAC_ENABLE_BIT | WAVEFORM_GATE_LEVEL_BIT |
            WAVEFORM_GATE_ENABLE_BIT | WAVEFORM_GATE_SELECT_BIT;
 
@@ -3220,12 +3244,13 @@ static void set_dac_control0_reg(struct comedi_device *dev,
                if (cmd->scan_begin_arg & CR_INVERT)
                        bits |= DAC_EXT_UPDATE_FALLING_BIT;
        }
-       writew(bits, priv(dev)->main_iobase + DAC_CONTROL0_REG);
+       writew(bits, devpriv->main_iobase + DAC_CONTROL0_REG);
 }
 
 static void set_dac_control1_reg(struct comedi_device *dev,
                                 const struct comedi_cmd *cmd)
 {
+       struct pcidas64_private *devpriv = dev->private;
        int i;
 
        for (i = 0; i < cmd->chanlist_len; i++) {
@@ -3233,17 +3258,18 @@ static void set_dac_control1_reg(struct comedi_device *dev,
 
                channel = CR_CHAN(cmd->chanlist[i]);
                range = CR_RANGE(cmd->chanlist[i]);
-               set_dac_range_bits(dev, &priv(dev)->dac_control1_bits, channel,
+               set_dac_range_bits(dev, &devpriv->dac_control1_bits, channel,
                                   range);
        }
-       priv(dev)->dac_control1_bits |= DAC_SW_GATE_BIT;
-       writew(priv(dev)->dac_control1_bits,
-              priv(dev)->main_iobase + DAC_CONTROL1_REG);
+       devpriv->dac_control1_bits |= DAC_SW_GATE_BIT;
+       writew(devpriv->dac_control1_bits,
+              devpriv->main_iobase + DAC_CONTROL1_REG);
 }
 
 static void set_dac_select_reg(struct comedi_device *dev,
                               const struct comedi_cmd *cmd)
 {
+       struct pcidas64_private *devpriv = dev->private;
        uint16_t bits;
        unsigned int first_channel, last_channel;
 
@@ -3254,12 +3280,13 @@ static void set_dac_select_reg(struct comedi_device *dev,
 
        bits = (first_channel & 0x7) | (last_channel & 0x7) << 3;
 
-       writew(bits, priv(dev)->main_iobase + DAC_SELECT_REG);
+       writew(bits, devpriv->main_iobase + DAC_SELECT_REG);
 }
 
 static void set_dac_interval_regs(struct comedi_device *dev,
                                  const struct comedi_cmd *cmd)
 {
+       struct pcidas64_private *devpriv = dev->private;
        unsigned int divisor;
 
        if (cmd->scan_begin_src != TRIG_TIMER)
@@ -3271,28 +3298,29 @@ static void set_dac_interval_regs(struct comedi_device *dev,
                divisor = max_counter_value;
        }
        writew(divisor & 0xffff,
-              priv(dev)->main_iobase + DAC_SAMPLE_INTERVAL_LOWER_REG);
+              devpriv->main_iobase + DAC_SAMPLE_INTERVAL_LOWER_REG);
        writew((divisor >> 16) & 0xff,
-              priv(dev)->main_iobase + DAC_SAMPLE_INTERVAL_UPPER_REG);
+              devpriv->main_iobase + DAC_SAMPLE_INTERVAL_UPPER_REG);
 }
 
 static unsigned int load_ao_dma_buffer(struct comedi_device *dev,
                                       const struct comedi_cmd *cmd)
 {
+       struct pcidas64_private *devpriv = dev->private;
        unsigned int num_bytes, buffer_index, prev_buffer_index;
        unsigned int next_bits;
 
-       buffer_index = priv(dev)->ao_dma_index;
+       buffer_index = devpriv->ao_dma_index;
        prev_buffer_index = prev_ao_dma_index(dev);
 
        DEBUG_PRINT("attempting to load ao buffer %i (0x%x)\n", buffer_index,
-                   priv(dev)->ao_buffer_bus_addr[buffer_index]);
+                   devpriv->ao_buffer_bus_addr[buffer_index]);
 
        num_bytes = comedi_buf_read_n_available(dev->write_subdev->async);
        if (num_bytes > DMA_BUFFER_SIZE)
                num_bytes = DMA_BUFFER_SIZE;
-       if (cmd->stop_src == TRIG_COUNT && num_bytes > priv(dev)->ao_count)
-               num_bytes = priv(dev)->ao_count;
+       if (cmd->stop_src == TRIG_COUNT && num_bytes > devpriv->ao_count)
+               num_bytes = devpriv->ao_count;
        num_bytes -= num_bytes % bytes_in_sample;
 
        if (num_bytes == 0)
@@ -3301,43 +3329,44 @@ static unsigned int load_ao_dma_buffer(struct comedi_device *dev,
        DEBUG_PRINT("loading %i bytes\n", num_bytes);
 
        num_bytes = cfc_read_array_from_buffer(dev->write_subdev,
-                                              priv(dev)->
+                                              devpriv->
                                               ao_buffer[buffer_index],
                                               num_bytes);
-       priv(dev)->ao_dma_desc[buffer_index].transfer_size =
+       devpriv->ao_dma_desc[buffer_index].transfer_size =
            cpu_to_le32(num_bytes);
        /* set end of chain bit so we catch underruns */
-       next_bits = le32_to_cpu(priv(dev)->ao_dma_desc[buffer_index].next);
+       next_bits = le32_to_cpu(devpriv->ao_dma_desc[buffer_index].next);
        next_bits |= PLX_END_OF_CHAIN_BIT;
-       priv(dev)->ao_dma_desc[buffer_index].next = cpu_to_le32(next_bits);
+       devpriv->ao_dma_desc[buffer_index].next = cpu_to_le32(next_bits);
        /* clear end of chain bit on previous buffer now that we have set it
         * for the last buffer */
-       next_bits = le32_to_cpu(priv(dev)->ao_dma_desc[prev_buffer_index].next);
+       next_bits = le32_to_cpu(devpriv->ao_dma_desc[prev_buffer_index].next);
        next_bits &= ~PLX_END_OF_CHAIN_BIT;
-       priv(dev)->ao_dma_desc[prev_buffer_index].next = cpu_to_le32(next_bits);
+       devpriv->ao_dma_desc[prev_buffer_index].next = cpu_to_le32(next_bits);
 
-       priv(dev)->ao_dma_index = (buffer_index + 1) % AO_DMA_RING_COUNT;
-       priv(dev)->ao_count -= num_bytes;
+       devpriv->ao_dma_index = (buffer_index + 1) % AO_DMA_RING_COUNT;
+       devpriv->ao_count -= num_bytes;
 
        return num_bytes;
 }
 
 static void load_ao_dma(struct comedi_device *dev, const struct comedi_cmd *cmd)
 {
+       struct pcidas64_private *devpriv = dev->private;
        unsigned int num_bytes;
        unsigned int next_transfer_addr;
        void __iomem *pci_addr_reg =
-           priv(dev)->plx9080_iobase + PLX_DMA0_PCI_ADDRESS_REG;
+           devpriv->plx9080_iobase + PLX_DMA0_PCI_ADDRESS_REG;
        unsigned int buffer_index;
 
        do {
-               buffer_index = priv(dev)->ao_dma_index;
+               buffer_index = devpriv->ao_dma_index;
                /* don't overwrite data that hasn't been transferred yet */
                next_transfer_addr = readl(pci_addr_reg);
                if (next_transfer_addr >=
-                   priv(dev)->ao_buffer_bus_addr[buffer_index]
+                   devpriv->ao_buffer_bus_addr[buffer_index]
                    && next_transfer_addr <
-                   priv(dev)->ao_buffer_bus_addr[buffer_index] +
+                   devpriv->ao_buffer_bus_addr[buffer_index] +
                    DMA_BUFFER_SIZE)
                        return;
                num_bytes = load_ao_dma_buffer(dev, cmd);
@@ -3346,27 +3375,28 @@ static void load_ao_dma(struct comedi_device *dev, const struct comedi_cmd *cmd)
 
 static int prep_ao_dma(struct comedi_device *dev, const struct comedi_cmd *cmd)
 {
+       struct pcidas64_private *devpriv = dev->private;
        unsigned int num_bytes;
        int i;
 
        /* clear queue pointer too, since external queue has
         * weird interactions with ao fifo */
-       writew(0, priv(dev)->main_iobase + ADC_QUEUE_CLEAR_REG);
-       writew(0, priv(dev)->main_iobase + DAC_BUFFER_CLEAR_REG);
+       writew(0, devpriv->main_iobase + ADC_QUEUE_CLEAR_REG);
+       writew(0, devpriv->main_iobase + DAC_BUFFER_CLEAR_REG);
 
        num_bytes = (DAC_FIFO_SIZE / 2) * bytes_in_sample;
        if (cmd->stop_src == TRIG_COUNT &&
-           num_bytes / bytes_in_sample > priv(dev)->ao_count)
-               num_bytes = priv(dev)->ao_count * bytes_in_sample;
+           num_bytes / bytes_in_sample > devpriv->ao_count)
+               num_bytes = devpriv->ao_count * bytes_in_sample;
        num_bytes = cfc_read_array_from_buffer(dev->write_subdev,
-                                              priv(dev)->ao_bounce_buffer,
+                                              devpriv->ao_bounce_buffer,
                                               num_bytes);
        for (i = 0; i < num_bytes / bytes_in_sample; i++) {
-               writew(priv(dev)->ao_bounce_buffer[i],
-                      priv(dev)->main_iobase + DAC_FIFO_REG);
+               writew(devpriv->ao_bounce_buffer[i],
+                      devpriv->main_iobase + DAC_FIFO_REG);
        }
-       priv(dev)->ao_count -= num_bytes / bytes_in_sample;
-       if (cmd->stop_src == TRIG_COUNT && priv(dev)->ao_count == 0)
+       devpriv->ao_count -= num_bytes / bytes_in_sample;
+       if (cmd->stop_src == TRIG_COUNT && devpriv->ao_count == 0)
                return 0;
        num_bytes = load_ao_dma_buffer(dev, cmd);
        if (num_bytes == 0)
@@ -3392,6 +3422,7 @@ static inline int external_ai_queue_in_use(struct comedi_device *dev)
 
 static int ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+       struct pcidas64_private *devpriv = dev->private;
        struct comedi_cmd *cmd = &s->async->cmd;
 
        if (external_ai_queue_in_use(dev)) {
@@ -3399,14 +3430,14 @@ static int ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
                return -EBUSY;
        }
        /* disable analog output system during setup */
-       writew(0x0, priv(dev)->main_iobase + DAC_CONTROL0_REG);
+       writew(0x0, devpriv->main_iobase + DAC_CONTROL0_REG);
 
-       priv(dev)->ao_dma_index = 0;
-       priv(dev)->ao_count = cmd->stop_arg * cmd->chanlist_len;
+       devpriv->ao_dma_index = 0;
+       devpriv->ao_count = cmd->stop_arg * cmd->chanlist_len;
 
        set_dac_select_reg(dev, cmd);
        set_dac_interval_regs(dev, cmd);
-       load_first_dma_descriptor(dev, 0, priv(dev)->ao_dma_desc_bus_addr |
+       load_first_dma_descriptor(dev, 0, devpriv->ao_dma_desc_bus_addr |
                                  PLX_DESC_IN_PCI_BIT | PLX_INTR_TERM_COUNT);
 
        set_dac_control1_reg(dev, cmd);
@@ -3418,6 +3449,7 @@ static int ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 static int ao_inttrig(struct comedi_device *dev, struct comedi_subdevice *s,
                      unsigned int trig_num)
 {
+       struct pcidas64_private *devpriv = dev->private;
        struct comedi_cmd *cmd = &s->async->cmd;
        int retval;
 
@@ -3431,7 +3463,7 @@ static int ao_inttrig(struct comedi_device *dev, struct comedi_subdevice *s,
        set_dac_control0_reg(dev, cmd);
 
        if (cmd->start_src == TRIG_INT)
-               writew(0, priv(dev)->main_iobase + DAC_START_REG);
+               writew(0, devpriv->main_iobase + DAC_START_REG);
 
        s->async->inttrig = NULL;
 
@@ -3533,7 +3565,9 @@ static int ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
 
 static int ao_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
 {
-       writew(0x0, priv(dev)->main_iobase + DAC_CONTROL0_REG);
+       struct pcidas64_private *devpriv = dev->private;
+
+       writew(0x0, devpriv->main_iobase + DAC_CONTROL0_REG);
        abort_dma(dev, 0);
        return 0;
 }
@@ -3564,9 +3598,10 @@ static int dio_callback_4020(int dir, int port, int data, unsigned long arg)
 static int di_rbits(struct comedi_device *dev, struct comedi_subdevice *s,
                    struct comedi_insn *insn, unsigned int *data)
 {
+       struct pcidas64_private *devpriv = dev->private;
        unsigned int bits;
 
-       bits = readb(priv(dev)->dio_counter_iobase + DI_REG);
+       bits = readb(devpriv->dio_counter_iobase + DI_REG);
        bits &= 0xf;
        data[1] = bits;
        data[0] = 0;
@@ -3577,13 +3612,15 @@ static int di_rbits(struct comedi_device *dev, struct comedi_subdevice *s,
 static int do_wbits(struct comedi_device *dev, struct comedi_subdevice *s,
                    struct comedi_insn *insn, unsigned int *data)
 {
+       struct pcidas64_private *devpriv = dev->private;
+
        data[0] &= 0xf;
        /*  zero bits we are going to change */
        s->state &= ~data[0];
        /*  set new bits */
        s->state |= data[0] & data[1];
 
-       writeb(s->state, priv(dev)->dio_counter_iobase + DO_REG);
+       writeb(s->state, devpriv->dio_counter_iobase + DO_REG);
 
        data[1] = s->state;
 
@@ -3594,6 +3631,7 @@ static int dio_60xx_config_insn(struct comedi_device *dev,
                                struct comedi_subdevice *s,
                                struct comedi_insn *insn, unsigned int *data)
 {
+       struct pcidas64_private *devpriv = dev->private;
        unsigned int mask;
 
        mask = 1 << CR_CHAN(insn->chanspec);
@@ -3613,7 +3651,7 @@ static int dio_60xx_config_insn(struct comedi_device *dev,
        }
 
        writeb(s->io_bits,
-              priv(dev)->dio_counter_iobase + DIO_DIRECTION_60XX_REG);
+              devpriv->dio_counter_iobase + DIO_DIRECTION_60XX_REG);
 
        return 1;
 }
@@ -3621,14 +3659,16 @@ static int dio_60xx_config_insn(struct comedi_device *dev,
 static int dio_60xx_wbits(struct comedi_device *dev, struct comedi_subdevice *s,
                          struct comedi_insn *insn, unsigned int *data)
 {
+       struct pcidas64_private *devpriv = dev->private;
+
        if (data[0]) {
                s->state &= ~data[0];
                s->state |= (data[0] & data[1]);
                writeb(s->state,
-                      priv(dev)->dio_counter_iobase + DIO_DATA_60XX_REG);
+                      devpriv->dio_counter_iobase + DIO_DATA_60XX_REG);
        }
 
-       data[1] = readb(priv(dev)->dio_counter_iobase + DIO_DATA_60XX_REG);
+       data[1] = readb(devpriv->dio_counter_iobase + DIO_DATA_60XX_REG);
 
        return insn->n;
 }
@@ -3636,7 +3676,9 @@ static int dio_60xx_wbits(struct comedi_device *dev, struct comedi_subdevice *s,
 static void caldac_write(struct comedi_device *dev, unsigned int channel,
                         unsigned int value)
 {
-       priv(dev)->caldac_state[channel] = value;
+       struct pcidas64_private *devpriv = dev->private;
+
+       devpriv->caldac_state[channel] = value;
 
        switch (board(dev)->layout) {
        case LAYOUT_60XX:
@@ -3655,11 +3697,12 @@ static int calib_write_insn(struct comedi_device *dev,
                            struct comedi_subdevice *s,
                            struct comedi_insn *insn, unsigned int *data)
 {
+       struct pcidas64_private *devpriv = dev->private;
        int channel = CR_CHAN(insn->chanspec);
 
        /* return immediately if setting hasn't changed, since
         * programming these things is slow */
-       if (priv(dev)->caldac_state[channel] == data[0])
+       if (devpriv->caldac_state[channel] == data[0])
                return 1;
 
        caldac_write(dev, channel, data[0]);
@@ -3671,9 +3714,10 @@ static int calib_read_insn(struct comedi_device *dev,
                           struct comedi_subdevice *s, struct comedi_insn *insn,
                           unsigned int *data)
 {
+       struct pcidas64_private *devpriv = dev->private;
        unsigned int channel = CR_CHAN(insn->chanspec);
 
-       data[0] = priv(dev)->caldac_state[channel];
+       data[0] = devpriv->caldac_state[channel];
 
        return 1;
 }
@@ -3681,16 +3725,17 @@ static int calib_read_insn(struct comedi_device *dev,
 static void ad8402_write(struct comedi_device *dev, unsigned int channel,
                         unsigned int value)
 {
+       struct pcidas64_private *devpriv = dev->private;
        static const int bitstream_length = 10;
        unsigned int bit, register_bits;
        unsigned int bitstream = ((channel & 0x3) << 8) | (value & 0xff);
        static const int ad8402_udelay = 1;
 
-       priv(dev)->ad8402_state[channel] = value;
+       devpriv->ad8402_state[channel] = value;
 
        register_bits = SELECT_8402_64XX_BIT;
        udelay(ad8402_udelay);
-       writew(register_bits, priv(dev)->main_iobase + CALIBRATION_REG);
+       writew(register_bits, devpriv->main_iobase + CALIBRATION_REG);
 
        for (bit = 1 << (bitstream_length - 1); bit; bit >>= 1) {
                if (bitstream & bit)
@@ -3698,14 +3743,14 @@ static void ad8402_write(struct comedi_device *dev, unsigned int channel,
                else
                        register_bits &= ~SERIAL_DATA_IN_BIT;
                udelay(ad8402_udelay);
-               writew(register_bits, priv(dev)->main_iobase + CALIBRATION_REG);
+               writew(register_bits, devpriv->main_iobase + CALIBRATION_REG);
                udelay(ad8402_udelay);
                writew(register_bits | SERIAL_CLOCK_BIT,
-                      priv(dev)->main_iobase + CALIBRATION_REG);
+                      devpriv->main_iobase + CALIBRATION_REG);
        }
 
        udelay(ad8402_udelay);
-       writew(0, priv(dev)->main_iobase + CALIBRATION_REG);
+       writew(0, devpriv->main_iobase + CALIBRATION_REG);
 }
 
 /* for pci-das6402/16, channel 0 is analog input gain and channel 1 is offset */
@@ -3713,14 +3758,15 @@ static int ad8402_write_insn(struct comedi_device *dev,
                             struct comedi_subdevice *s,
                             struct comedi_insn *insn, unsigned int *data)
 {
+       struct pcidas64_private *devpriv = dev->private;
        int channel = CR_CHAN(insn->chanspec);
 
        /* return immediately if setting hasn't changed, since
         * programming these things is slow */
-       if (priv(dev)->ad8402_state[channel] == data[0])
+       if (devpriv->ad8402_state[channel] == data[0])
                return 1;
 
-       priv(dev)->ad8402_state[channel] = data[0];
+       devpriv->ad8402_state[channel] = data[0];
 
        ad8402_write(dev, channel, data[0]);
 
@@ -3731,62 +3777,64 @@ static int ad8402_read_insn(struct comedi_device *dev,
                            struct comedi_subdevice *s,
                            struct comedi_insn *insn, unsigned int *data)
 {
+       struct pcidas64_private *devpriv = dev->private;
        unsigned int channel = CR_CHAN(insn->chanspec);
 
-       data[0] = priv(dev)->ad8402_state[channel];
+       data[0] = devpriv->ad8402_state[channel];
 
        return 1;
 }
 
 static uint16_t read_eeprom(struct comedi_device *dev, uint8_t address)
 {
+       struct pcidas64_private *devpriv = dev->private;
        static const int bitstream_length = 11;
        static const int read_command = 0x6;
        unsigned int bitstream = (read_command << 8) | address;
        unsigned int bit;
        void __iomem * const plx_control_addr =
-           priv(dev)->plx9080_iobase + PLX_CONTROL_REG;
+           devpriv->plx9080_iobase + PLX_CONTROL_REG;
        uint16_t value;
        static const int value_length = 16;
        static const int eeprom_udelay = 1;
 
        udelay(eeprom_udelay);
-       priv(dev)->plx_control_bits &= ~CTL_EE_CLK & ~CTL_EE_CS;
+       devpriv->plx_control_bits &= ~CTL_EE_CLK & ~CTL_EE_CS;
        /*  make sure we don't send anything to the i2c bus on 4020 */
-       priv(dev)->plx_control_bits |= CTL_USERO;
-       writel(priv(dev)->plx_control_bits, plx_control_addr);
+       devpriv->plx_control_bits |= CTL_USERO;
+       writel(devpriv->plx_control_bits, plx_control_addr);
        /*  activate serial eeprom */
        udelay(eeprom_udelay);
-       priv(dev)->plx_control_bits |= CTL_EE_CS;
-       writel(priv(dev)->plx_control_bits, plx_control_addr);
+       devpriv->plx_control_bits |= CTL_EE_CS;
+       writel(devpriv->plx_control_bits, plx_control_addr);
 
        /*  write read command and desired memory address */
        for (bit = 1 << (bitstream_length - 1); bit; bit >>= 1) {
                /*  set bit to be written */
                udelay(eeprom_udelay);
                if (bitstream & bit)
-                       priv(dev)->plx_control_bits |= CTL_EE_W;
+                       devpriv->plx_control_bits |= CTL_EE_W;
                else
-                       priv(dev)->plx_control_bits &= ~CTL_EE_W;
-               writel(priv(dev)->plx_control_bits, plx_control_addr);
+                       devpriv->plx_control_bits &= ~CTL_EE_W;
+               writel(devpriv->plx_control_bits, plx_control_addr);
                /*  clock in bit */
                udelay(eeprom_udelay);
-               priv(dev)->plx_control_bits |= CTL_EE_CLK;
-               writel(priv(dev)->plx_control_bits, plx_control_addr);
+               devpriv->plx_control_bits |= CTL_EE_CLK;
+               writel(devpriv->plx_control_bits, plx_control_addr);
                udelay(eeprom_udelay);
-               priv(dev)->plx_control_bits &= ~CTL_EE_CLK;
-               writel(priv(dev)->plx_control_bits, plx_control_addr);
+               devpriv->plx_control_bits &= ~CTL_EE_CLK;
+               writel(devpriv->plx_control_bits, plx_control_addr);
        }
        /*  read back value from eeprom memory location */
        value = 0;
        for (bit = 1 << (value_length - 1); bit; bit >>= 1) {
                /*  clock out bit */
                udelay(eeprom_udelay);
-               priv(dev)->plx_control_bits |= CTL_EE_CLK;
-               writel(priv(dev)->plx_control_bits, plx_control_addr);
+               devpriv->plx_control_bits |= CTL_EE_CLK;
+               writel(devpriv->plx_control_bits, plx_control_addr);
                udelay(eeprom_udelay);
-               priv(dev)->plx_control_bits &= ~CTL_EE_CLK;
-               writel(priv(dev)->plx_control_bits, plx_control_addr);
+               devpriv->plx_control_bits &= ~CTL_EE_CLK;
+               writel(devpriv->plx_control_bits, plx_control_addr);
                udelay(eeprom_udelay);
                if (readl(plx_control_addr) & CTL_EE_R)
                        value |= bit;
@@ -3794,8 +3842,8 @@ static uint16_t read_eeprom(struct comedi_device *dev, uint8_t address)
 
        /*  deactivate eeprom serial input */
        udelay(eeprom_udelay);
-       priv(dev)->plx_control_bits &= ~CTL_EE_CS;
-       writel(priv(dev)->plx_control_bits, plx_control_addr);
+       devpriv->plx_control_bits &= ~CTL_EE_CS;
+       writel(devpriv->plx_control_bits, plx_control_addr);
 
        return value;
 }
@@ -3911,7 +3959,9 @@ static int set_ai_fifo_size(struct comedi_device *dev, unsigned int num_samples)
 /* query length of fifo */
 static unsigned int ai_fifo_size(struct comedi_device *dev)
 {
-       return priv(dev)->ai_fifo_segment_length *
+       struct pcidas64_private *devpriv = dev->private;
+
+       return devpriv->ai_fifo_segment_length *
            board(dev)->ai_fifo->num_segments *
            board(dev)->ai_fifo->sample_packing_ratio;
 }
@@ -3919,6 +3969,7 @@ static unsigned int ai_fifo_size(struct comedi_device *dev)
 static int set_ai_fifo_segment_length(struct comedi_device *dev,
                                      unsigned int num_entries)
 {
+       struct pcidas64_private *devpriv = dev->private;
        static const int increment_size = 0x100;
        const struct hw_fifo_info *const fifo = board(dev)->ai_fifo;
        unsigned int num_increments;
@@ -3933,17 +3984,17 @@ static int set_ai_fifo_segment_length(struct comedi_device *dev,
        num_increments = (num_entries + increment_size / 2) / increment_size;
 
        bits = (~(num_increments - 1)) & fifo->fifo_size_reg_mask;
-       priv(dev)->fifo_size_bits &= ~fifo->fifo_size_reg_mask;
-       priv(dev)->fifo_size_bits |= bits;
-       writew(priv(dev)->fifo_size_bits,
-              priv(dev)->main_iobase + FIFO_SIZE_REG);
+       devpriv->fifo_size_bits &= ~fifo->fifo_size_reg_mask;
+       devpriv->fifo_size_bits |= bits;
+       writew(devpriv->fifo_size_bits,
+              devpriv->main_iobase + FIFO_SIZE_REG);
 
-       priv(dev)->ai_fifo_segment_length = num_increments * increment_size;
+       devpriv->ai_fifo_segment_length = num_increments * increment_size;
 
        DEBUG_PRINT("set hardware fifo segment length to %i\n",
-                   priv(dev)->ai_fifo_segment_length);
+                   devpriv->ai_fifo_segment_length);
 
-       return priv(dev)->ai_fifo_segment_length;
+       return devpriv->ai_fifo_segment_length;
 }
 
 /* pci-6025 8800 caldac:
@@ -3970,6 +4021,7 @@ static int set_ai_fifo_segment_length(struct comedi_device *dev,
 static int caldac_8800_write(struct comedi_device *dev, unsigned int address,
                             uint8_t value)
 {
+       struct pcidas64_private *devpriv = dev->private;
        static const int num_caldac_channels = 8;
        static const int bitstream_length = 11;
        unsigned int bitstream = ((address & 0x7) << 8) | value;
@@ -3985,15 +4037,15 @@ static int caldac_8800_write(struct comedi_device *dev, unsigned int address,
                if (bitstream & bit)
                        register_bits |= SERIAL_DATA_IN_BIT;
                udelay(caldac_8800_udelay);
-               writew(register_bits, priv(dev)->main_iobase + CALIBRATION_REG);
+               writew(register_bits, devpriv->main_iobase + CALIBRATION_REG);
                register_bits |= SERIAL_CLOCK_BIT;
                udelay(caldac_8800_udelay);
-               writew(register_bits, priv(dev)->main_iobase + CALIBRATION_REG);
+               writew(register_bits, devpriv->main_iobase + CALIBRATION_REG);
        }
        udelay(caldac_8800_udelay);
-       writew(SELECT_8800_BIT, priv(dev)->main_iobase + CALIBRATION_REG);
+       writew(SELECT_8800_BIT, devpriv->main_iobase + CALIBRATION_REG);
        udelay(caldac_8800_udelay);
-       writew(0, priv(dev)->main_iobase + CALIBRATION_REG);
+       writew(0, devpriv->main_iobase + CALIBRATION_REG);
        udelay(caldac_8800_udelay);
        return 0;
 }
@@ -4066,19 +4118,20 @@ static const int i2c_low_udelay = 10;
 /* set i2c data line high or low */
 static void i2c_set_sda(struct comedi_device *dev, int state)
 {
+       struct pcidas64_private *devpriv = dev->private;
        static const int data_bit = CTL_EE_W;
-       void __iomem *plx_control_addr = priv(dev)->plx9080_iobase +
+       void __iomem *plx_control_addr = devpriv->plx9080_iobase +
                                         PLX_CONTROL_REG;
 
        if (state) {
                /*  set data line high */
-               priv(dev)->plx_control_bits &= ~data_bit;
-               writel(priv(dev)->plx_control_bits, plx_control_addr);
+               devpriv->plx_control_bits &= ~data_bit;
+               writel(devpriv->plx_control_bits, plx_control_addr);
                udelay(i2c_high_udelay);
        } else {                /*  set data line low */
 
-               priv(dev)->plx_control_bits |= data_bit;
-               writel(priv(dev)->plx_control_bits, plx_control_addr);
+               devpriv->plx_control_bits |= data_bit;
+               writel(devpriv->plx_control_bits, plx_control_addr);
                udelay(i2c_low_udelay);
        }
 }
@@ -4086,19 +4139,20 @@ static void i2c_set_sda(struct comedi_device *dev, int state)
 /* set i2c clock line high or low */
 static void i2c_set_scl(struct comedi_device *dev, int state)
 {
+       struct pcidas64_private *devpriv = dev->private;
        static const int clock_bit = CTL_USERO;
-       void __iomem *plx_control_addr = priv(dev)->plx9080_iobase +
+       void __iomem *plx_control_addr = devpriv->plx9080_iobase +
                                         PLX_CONTROL_REG;
 
        if (state) {
                /*  set clock line high */
-               priv(dev)->plx_control_bits &= ~clock_bit;
-               writel(priv(dev)->plx_control_bits, plx_control_addr);
+               devpriv->plx_control_bits &= ~clock_bit;
+               writel(devpriv->plx_control_bits, plx_control_addr);
                udelay(i2c_high_udelay);
        } else {                /*  set clock line low */
 
-               priv(dev)->plx_control_bits |= clock_bit;
-               writel(priv(dev)->plx_control_bits, plx_control_addr);
+               devpriv->plx_control_bits |= clock_bit;
+               writel(devpriv->plx_control_bits, plx_control_addr);
                udelay(i2c_low_udelay);
        }
 }
@@ -4150,6 +4204,7 @@ static void i2c_stop(struct comedi_device *dev)
 static void i2c_write(struct comedi_device *dev, unsigned int address,
                      const uint8_t *data, unsigned int length)
 {
+       struct pcidas64_private *devpriv = dev->private;
        unsigned int i;
        uint8_t bitstream;
        static const int read_bit = 0x1;
@@ -4157,7 +4212,7 @@ static void i2c_write(struct comedi_device *dev, unsigned int address,
 /* XXX need mutex to prevent simultaneous attempts to access eeprom and i2c bus */
 
        /*  make sure we dont send anything to eeprom */
-       priv(dev)->plx_control_bits &= ~CTL_EE_CS;
+       devpriv->plx_control_bits &= ~CTL_EE_CS;
 
        i2c_stop(dev);
        i2c_start(dev);
index aef946df27e2f22ba85c48e3072ffbc6866d7431..798374fe8da994472169b9a76f009be565205243 100644 (file)
@@ -656,18 +656,16 @@ static int cb_pcidda_attach_pci(struct comedi_device *dev,
        int index;
        int ret;
 
-       comedi_set_hw_dev(dev, &pcidev->dev);
-
        thisboard = cb_pcidda_find_boardinfo(dev, pcidev);
        if (!pcidev)
                return -ENODEV;
        dev->board_ptr = thisboard;
        dev->board_name = thisboard->name;
 
-       ret = alloc_private(dev, sizeof(*devpriv));
-       if (ret)
-               return ret;
-       devpriv = dev->private;
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
+               return -ENOMEM;
+       dev->private = devpriv;
 
        ret = comedi_pci_enable(pcidev, dev->board_name);
        if (ret)
index 9515b6926662cab66eca241f9b6e0cc8da1f3fd8..138cfb15814c8de8c9d31fb8edcc1cb92c2daef2 100644 (file)
@@ -80,44 +80,6 @@ See http://www.mccdaq.com/PDFs/Manuals/pcim-das1602-16.pdf for more details.
 #define RESID_COUNT_H 13
 #define RESID_COUNT_L 14
 
-/* Board description */
-struct cb_pcimdas_board {
-       const char *name;
-       unsigned short device_id;
-       int ai_se_chans;        /*  Inputs in single-ended mode */
-       int ai_diff_chans;      /*  Inputs in differential mode */
-       int ai_bits;            /*  analog input resolution */
-       int ai_speed;           /*  fastest conversion period in ns */
-       int ao_nchan;           /*  number of analog out channels */
-       int ao_bits;            /*  analogue output resolution */
-       int has_ao_fifo;        /*  analog output has fifo */
-       int ao_scan_speed;      /*  analog output speed for 1602 series (for a scan, not conversion) */
-       int fifo_size;          /*  number of samples fifo can hold */
-       int dio_bits;           /*  number of dio bits */
-       int has_dio;            /*  has DIO */
-       const struct comedi_lrange *ranges;
-};
-
-static const struct cb_pcimdas_board cb_pcimdas_boards[] = {
-       {
-        .name = "PCIM-DAS1602/16",
-        .device_id = 0x56,
-        .ai_se_chans = 16,
-        .ai_diff_chans = 8,
-        .ai_bits = 16,
-        .ai_speed = 10000,     /* ?? */
-        .ao_nchan = 2,
-        .ao_bits = 12,
-        .has_ao_fifo = 0,      /* ?? */
-        .ao_scan_speed = 10000,
-        /* ?? */
-        .fifo_size = 1024,
-        .dio_bits = 24,
-        .has_dio = 1,
-/*     .ranges = &cb_pcimdas_ranges, */
-        },
-};
-
 /*
  * this structure is for data unique to this hardware driver.  If
  * several hardware drivers keep similar information in this structure,
@@ -140,7 +102,6 @@ static int cb_pcimdas_ai_rinsn(struct comedi_device *dev,
                               struct comedi_subdevice *s,
                               struct comedi_insn *insn, unsigned int *data)
 {
-       const struct cb_pcimdas_board *thisboard = comedi_board(dev);
        struct cb_pcimdas_private *devpriv = dev->private;
        int n, i;
        unsigned int d;
@@ -153,9 +114,9 @@ static int cb_pcimdas_ai_rinsn(struct comedi_device *dev,
 
        /* check channel number */
        if ((inb(devpriv->BADR3 + 2) & 0x20) == 0)      /* differential mode */
-               maxchans = thisboard->ai_diff_chans;
+               maxchans = s->n_chan / 2;
        else
-               maxchans = thisboard->ai_se_chans;
+               maxchans = s->n_chan;
 
        if (chan > (maxchans - 1))
                return -ETIMEDOUT;      /* *** Wrong error code. Fixme. */
@@ -195,12 +156,7 @@ static int cb_pcimdas_ai_rinsn(struct comedi_device *dev,
                        return -ETIMEDOUT;
                }
                /* read data */
-               d = inw(dev->iobase + 0);
-
-               /* mangle the data as necessary */
-               /* d ^= 1<<(thisboard->ai_bits-1); // 16 bit data from ADC, so no mangle needed. */
-
-               data[n] = d;
+               data[n] = inw(dev->iobase + 0);
        }
 
        /* return the number of samples read/written */
@@ -251,51 +207,20 @@ static int cb_pcimdas_ao_rinsn(struct comedi_device *dev,
        return i;
 }
 
-static const void *cb_pcimdas_find_boardinfo(struct comedi_device *dev,
-                                            struct pci_dev *pcidev)
-{
-       const struct cb_pcimdas_board *thisboard;
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(cb_pcimdas_boards); i++) {
-               thisboard = &cb_pcimdas_boards[i];
-               if (thisboard->device_id == pcidev->device)
-                       return thisboard;
-       }
-       return NULL;
-}
-
 static int cb_pcimdas_attach_pci(struct comedi_device *dev,
                                 struct pci_dev *pcidev)
 {
-       const struct cb_pcimdas_board *thisboard;
        struct cb_pcimdas_private *devpriv;
        struct comedi_subdevice *s;
        unsigned long iobase_8255;
        int ret;
 
-       comedi_set_hw_dev(dev, &pcidev->dev);
-
-       thisboard = cb_pcimdas_find_boardinfo(dev, pcidev);
-       if (!thisboard)
-               return -ENODEV;
-       dev->board_ptr = thisboard;
-       dev->board_name = thisboard->name;
+       dev->board_name = dev->driver->driver_name;
 
-       ret = alloc_private(dev, sizeof(*devpriv));
-       if (ret)
-               return ret;
-       devpriv = dev->private;
-
-       /*  Warn about non-tested features */
-       switch (thisboard->device_id) {
-       case 0x56:
-               break;
-       default:
-               dev_dbg(dev->class_dev, "THIS CARD IS UNSUPPORTED.\n");
-               dev_dbg(dev->class_dev,
-                       "PLEASE REPORT USAGE TO <mocelet@sucs.org>\n");
-       }
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
+               return -ENOMEM;
+       dev->private = devpriv;
 
        ret = comedi_pci_enable(pcidev, dev->board_name);
        if (ret)
@@ -323,8 +248,8 @@ static int cb_pcimdas_attach_pci(struct comedi_device *dev,
        /*  analog input subdevice */
        s->type = COMEDI_SUBD_AI;
        s->subdev_flags = SDF_READABLE | SDF_GROUND;
-       s->n_chan = thisboard->ai_se_chans;
-       s->maxdata = (1 << thisboard->ai_bits) - 1;
+       s->n_chan = 16;
+       s->maxdata = 0xffff;
        s->range_table = &range_unknown;
        s->len_chanlist = 1;    /*  This is the maximum chanlist length that */
        /*  the board can handle */
@@ -334,8 +259,8 @@ static int cb_pcimdas_attach_pci(struct comedi_device *dev,
        /*  analog output subdevice */
        s->type = COMEDI_SUBD_AO;
        s->subdev_flags = SDF_WRITABLE;
-       s->n_chan = thisboard->ao_nchan;
-       s->maxdata = 1 << thisboard->ao_bits;
+       s->n_chan = 2;
+       s->maxdata = 0xfff;
        /* ranges are hardware settable, but not software readable. */
        s->range_table = &range_unknown;
        s->insn_write = &cb_pcimdas_ao_winsn;
@@ -343,10 +268,7 @@ static int cb_pcimdas_attach_pci(struct comedi_device *dev,
 
        s = &dev->subdevices[2];
        /* digital i/o subdevice */
-       if (thisboard->has_dio)
-               subdev_8255_init(dev, s, NULL, iobase_8255);
-       else
-               s->type = COMEDI_SUBD_UNUSED;
+       subdev_8255_init(dev, s, NULL, iobase_8255);
 
        dev_info(dev->class_dev, "%s attached\n", dev->board_name);
 
index ba9f0599be28b134d20c635ce474cd038ca682ae..9c01500492420de3954e6e718002babe514b789e 100644 (file)
@@ -159,13 +159,12 @@ static int cb_pcimdda_attach_pci(struct comedi_device *dev,
        struct comedi_subdevice *s;
        int ret;
 
-       comedi_set_hw_dev(dev, &pcidev->dev);
        dev->board_name = dev->driver->driver_name;
 
-       ret = alloc_private(dev, sizeof(*devpriv));
-       if (ret)
-               return ret;
-       devpriv = dev->private;
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
+               return -ENOMEM;
+       dev->private = devpriv;
 
        ret = comedi_pci_enable(pcidev, dev->board_name);
        if (ret)
index 5c768bc76eb1ad750a158934957f470de6c683ab..31515999bb97e47b153c4848d192a62321cc3084 100644 (file)
@@ -304,10 +304,10 @@ static int bonding_attach(struct comedi_device *dev,
        struct comedi_subdevice *s;
        int ret;
 
-       ret = alloc_private(dev, sizeof(*devpriv));
-       if (ret)
-               return ret;
-       devpriv = dev->private;
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
+               return -ENOMEM;
+       dev->private = devpriv;
 
        /*
         * Setup our bonding from config params.. sets up our private struct..
index 22ef94242590e9ca640303ef3c83455f876383c3..6d3b56a70aa93e9355ffa2e9ee5a2f6ab9969fea 100644 (file)
@@ -305,10 +305,10 @@ static int parport_attach(struct comedi_device *dev,
        if (ret)
                return ret;
 
-       ret = alloc_private(dev, sizeof(*devpriv));
-       if (ret < 0)
-               return ret;
-       devpriv = dev->private;
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
+               return -ENOMEM;
+       dev->private = devpriv;
 
        s = &dev->subdevices[0];
        s->type = COMEDI_SUBD_DIO;
index 7817def1556cd3ed09c4a8ead9bfb99c0b380714..1be345518b64a06984314d254a817bdf889638a9 100644 (file)
@@ -414,10 +414,10 @@ static int waveform_attach(struct comedi_device *dev,
 
        dev->board_name = dev->driver->driver_name;
 
-       ret = alloc_private(dev, sizeof(*devpriv));
-       if (ret < 0)
-               return ret;
-       devpriv = dev->private;
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
+               return -ENOMEM;
+       dev->private = devpriv;
 
        /* set default amplitude and period */
        if (amplitude <= 0)
index 178a6a4bb7d58203dc197d070078c2b1c480ec9b..70a9243cf33c1c51dd3dae5f06312546ed8bd596 100644 (file)
@@ -74,8 +74,6 @@ static int contec_attach_pci(struct comedi_device *dev,
        struct comedi_subdevice *s;
        int ret;
 
-       comedi_set_hw_dev(dev, &pcidev->dev);
-
        dev->board_name = dev->driver->driver_name;
 
        ret = comedi_pci_enable(pcidev, dev->board_name);
index d13c8c5822bf4dade515d951181feed4f4bea118..87b9cd572f800d714813aad4ad652ed543168a7d 100644 (file)
@@ -698,18 +698,16 @@ static int daqboard2000_attach_pci(struct comedi_device *dev,
        struct comedi_subdevice *s;
        int result;
 
-       comedi_set_hw_dev(dev, &pcidev->dev);
-
        board = daqboard2000_find_boardinfo(dev, pcidev);
        if (!board)
                return -ENODEV;
        dev->board_ptr = board;
        dev->board_name = board->name;
 
-       result = alloc_private(dev, sizeof(*devpriv));
-       if (result < 0)
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
                return -ENOMEM;
-       devpriv = dev->private;
+       dev->private = devpriv;
 
        result = comedi_pci_enable(pcidev, dev->driver->driver_name);
        if (result < 0)
index 5fd21fa6c1c76d25f910c41ca26ecec86b8894e8..bbc0f9994bb24d3f06718a60f18b839cd734faa2 100644 (file)
@@ -778,21 +778,24 @@ das08_find_pci_board(struct pci_dev *pdev)
 static int __devinit __maybe_unused
 das08_attach_pci(struct comedi_device *dev, struct pci_dev *pdev)
 {
+       struct das08_private_struct *devpriv;
        unsigned long iobase;
-       int ret;
 
        if (!DO_PCI)
                return -EINVAL;
-       ret = alloc_private(dev, sizeof(struct das08_private_struct));
-       if (ret < 0)
-               return ret;
+
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
+               return -ENOMEM;
+       dev->private = devpriv;
+
        dev_info(dev->class_dev, "attach pci %s\n", pci_name(pdev));
        dev->board_ptr = das08_find_pci_board(pdev);
        if (dev->board_ptr == NULL) {
                dev_err(dev->class_dev, "BUG! cannot determine board type!\n");
                return -EINVAL;
        }
-       comedi_set_hw_dev(dev, &pdev->dev);
+
        /*  enable PCI device and reserve I/O spaces */
        if (comedi_pci_enable(pdev, dev->driver->driver_name)) {
                dev_err(dev->class_dev,
@@ -809,13 +812,12 @@ das08_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
        const struct das08_board_struct *thisboard = comedi_board(dev);
        struct das08_private_struct *devpriv;
-       int ret;
        unsigned long iobase;
 
-       ret = alloc_private(dev, sizeof(struct das08_private_struct));
-       if (ret < 0)
-               return ret;
-       devpriv = dev->private;
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
+               return -ENOMEM;
+       dev->private = devpriv;
 
        dev_info(dev->class_dev, "attach\n");
        if (is_pci_board(thisboard)) {
@@ -846,6 +848,8 @@ static void __maybe_unused das08_detach(struct comedi_device *dev)
 {
        const struct das08_board_struct *thisboard = comedi_board(dev);
 
+       if (!thisboard)
+               return;
        das08_common_detach(dev);
        if (is_isa_board(thisboard)) {
                if (dev->iobase)
index e4c91e675379ce1c169af21d7deb7f3b84472c02..024262375e3c2abed705da3c753c5f73e3525ef2 100644 (file)
@@ -90,13 +90,14 @@ static int das08_cs_attach(struct comedi_device *dev,
                           struct comedi_devconfig *it)
 {
        const struct das08_board_struct *thisboard = comedi_board(dev);
-       int ret;
+       struct das08_private_struct *devpriv;
        unsigned long iobase;
        struct pcmcia_device *link = cur_dev;   /*  XXX hack */
 
-       ret = alloc_private(dev, sizeof(struct das08_private_struct));
-       if (ret < 0)
-               return ret;
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
+               return -ENOMEM;
+       dev->private = devpriv;
 
        dev_info(dev->class_dev, "das08_cs: attach\n");
        /*  deal with a pci board */
index fcb8a32adb2fa4a969ab7408c3b7443814ba3c7a..2ceadcb97408a03bf754a26c2a4cc7d7cb80b7e2 100644 (file)
@@ -392,12 +392,12 @@ struct das16_private_struct {
        volatile short timer_running;
        volatile short timer_mode;      /*  true if using timer mode */
 };
-#define devpriv ((struct das16_private_struct *)(dev->private))
 
 static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
                          struct comedi_cmd *cmd)
 {
        const struct das16_board *board = comedi_board(dev);
+       struct das16_private_struct *devpriv = dev->private;
        int err = 0, tmp;
        int gain, start_chan, i;
        int mask;
@@ -540,6 +540,7 @@ static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
 static unsigned int das16_suggest_transfer_size(struct comedi_device *dev,
                                                const struct comedi_cmd *cmd)
 {
+       struct das16_private_struct *devpriv = dev->private;
        unsigned int size;
        unsigned int freq;
 
@@ -581,6 +582,8 @@ static unsigned int das16_suggest_transfer_size(struct comedi_device *dev,
 static unsigned int das16_set_pacer(struct comedi_device *dev, unsigned int ns,
                                    int rounding_flags)
 {
+       struct das16_private_struct *devpriv = dev->private;
+
        i8253_cascade_ns_to_timer_2div(devpriv->clockbase, &(devpriv->divisor1),
                                       &(devpriv->divisor2), &ns,
                                       rounding_flags & TRIG_ROUND_MASK);
@@ -595,6 +598,7 @@ static unsigned int das16_set_pacer(struct comedi_device *dev, unsigned int ns,
 static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s)
 {
        const struct das16_board *board = comedi_board(dev);
+       struct das16_private_struct *devpriv = dev->private;
        struct comedi_async *async = s->async;
        struct comedi_cmd *cmd = &async->cmd;
        unsigned int byte;
@@ -701,6 +705,7 @@ static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s)
 static int das16_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
 {
        const struct das16_board *board = comedi_board(dev);
+       struct das16_private_struct *devpriv = dev->private;
        unsigned long flags;
 
        spin_lock_irqsave(&dev->spinlock, flags);
@@ -738,6 +743,7 @@ static int das16_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
                          struct comedi_insn *insn, unsigned int *data)
 {
        const struct das16_board *board = comedi_board(dev);
+       struct das16_private_struct *devpriv = dev->private;
        int i, n;
        int range;
        int chan;
@@ -848,10 +854,12 @@ static int das16_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
 */
 static int disable_dma_on_even(struct comedi_device *dev)
 {
+       struct das16_private_struct *devpriv = dev->private;
        int residue;
        int i;
        static const int disable_limit = 100;
        static const int enable_timeout = 100;
+
        disable_dma(devpriv->dma_chan);
        residue = get_dma_residue(devpriv->dma_chan);
        for (i = 0; i < disable_limit && (residue % 2); ++i) {
@@ -877,6 +885,7 @@ static int disable_dma_on_even(struct comedi_device *dev)
 static void das16_interrupt(struct comedi_device *dev)
 {
        const struct das16_board *board = comedi_board(dev);
+       struct das16_private_struct *devpriv = dev->private;
        unsigned long dma_flags, spin_flags;
        struct comedi_subdevice *s = dev->read_subdev;
        struct comedi_async *async;
@@ -973,6 +982,7 @@ static irqreturn_t das16_dma_interrupt(int irq, void *d)
 static void das16_timer_interrupt(unsigned long arg)
 {
        struct comedi_device *dev = (struct comedi_device *)arg;
+       struct das16_private_struct *devpriv = dev->private;
 
        das16_interrupt(dev);
 
@@ -1001,6 +1011,7 @@ static void reg_dump(struct comedi_device *dev)
 static int das16_probe(struct comedi_device *dev, struct comedi_devconfig *it)
 {
        const struct das16_board *board = comedi_board(dev);
+       struct das16_private_struct *devpriv = dev->private;
        int status;
        int diobits;
 
@@ -1035,6 +1046,7 @@ static int das16_probe(struct comedi_device *dev, struct comedi_devconfig *it)
 
 static int das1600_mode_detect(struct comedi_device *dev)
 {
+       struct das16_private_struct *devpriv = dev->private;
        int status = 0;
 
        status = inb(dev->iobase + DAS1600_STATUS_B);
@@ -1080,6 +1092,7 @@ static void das16_ai_munge(struct comedi_device *dev,
 static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
        const struct das16_board *board = comedi_board(dev);
+       struct das16_private_struct *devpriv;
        struct comedi_subdevice *s;
        int ret;
        unsigned int irq;
@@ -1114,9 +1127,10 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it)
                }
        }
 
-       ret = alloc_private(dev, sizeof(struct das16_private_struct));
-       if (ret < 0)
-               return ret;
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
+               return -ENOMEM;
+       dev->private = devpriv;
 
        if (board->size < 0x400) {
                printk(" 0x%04lx-0x%04lx\n", iobase, iobase + board->size);
@@ -1353,6 +1367,7 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 static void das16_detach(struct comedi_device *dev)
 {
        const struct das16_board *board = comedi_board(dev);
+       struct das16_private_struct *devpriv = dev->private;
 
        das16_reset(dev);
        if (dev->subdevices)
index 3f87d7598e5bd29d419b47a5ff9e79fe26871150..d93d95102af7542ce638c5f663daec65a7c2c0df 100644 (file)
@@ -28,7 +28,7 @@
 Driver: das16m1
 Description: CIO-DAS16/M1
 Author: Frank Mori Hess <fmhess@users.sourceforge.net>
-Devices: [Measurement Computing] CIO-DAS16/M1 (cio-das16/m1)
+Devices: [Measurement Computing] CIO-DAS16/M1 (das16m1)
 Status: works
 
 This driver supports a single board - the CIO-DAS16/M1.
@@ -132,11 +132,6 @@ static const struct comedi_lrange range_das16m1 = { 9,
         }
 };
 
-struct das16m1_board {
-       const char *name;
-       unsigned int ai_speed;
-};
-
 struct das16m1_private_struct {
        unsigned int control_state;
        volatile unsigned int adc_count;        /*  number of samples completed */
@@ -149,7 +144,6 @@ struct das16m1_private_struct {
        unsigned int divisor1;  /*  divides master clock to obtain conversion speed */
        unsigned int divisor2;  /*  divides master clock to obtain conversion speed */
 };
-#define devpriv ((struct das16m1_private_struct *)(dev->private))
 
 static inline short munge_sample(short data)
 {
@@ -167,7 +161,7 @@ static void munge_sample_array(short *array, unsigned int num_elements)
 static int das16m1_cmd_test(struct comedi_device *dev,
                            struct comedi_subdevice *s, struct comedi_cmd *cmd)
 {
-       const struct das16m1_board *board = comedi_board(dev);
+       struct das16m1_private_struct *devpriv = dev->private;
        unsigned int err = 0, tmp, i;
 
        /* Step 1 : check if triggers are trivially valid */
@@ -207,8 +201,8 @@ static int das16m1_cmd_test(struct comedi_device *dev,
        }
 
        if (cmd->convert_src == TRIG_TIMER) {
-               if (cmd->convert_arg < board->ai_speed) {
-                       cmd->convert_arg = board->ai_speed;
+               if (cmd->convert_arg < 1000) {
+                       cmd->convert_arg = 1000;
                        err++;
                }
        }
@@ -277,6 +271,8 @@ static int das16m1_cmd_test(struct comedi_device *dev,
 static unsigned int das16m1_set_pacer(struct comedi_device *dev,
                                      unsigned int ns, int rounding_flags)
 {
+       struct das16m1_private_struct *devpriv = dev->private;
+
        i8253_cascade_ns_to_timer_2div(DAS16M1_XTAL, &(devpriv->divisor1),
                                       &(devpriv->divisor2), &ns,
                                       rounding_flags & TRIG_ROUND_MASK);
@@ -293,6 +289,7 @@ static unsigned int das16m1_set_pacer(struct comedi_device *dev,
 static int das16m1_cmd_exec(struct comedi_device *dev,
                            struct comedi_subdevice *s)
 {
+       struct das16m1_private_struct *devpriv = dev->private;
        struct comedi_async *async = s->async;
        struct comedi_cmd *cmd = &async->cmd;
        unsigned int byte, i;
@@ -356,6 +353,8 @@ static int das16m1_cmd_exec(struct comedi_device *dev,
 
 static int das16m1_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+       struct das16m1_private_struct *devpriv = dev->private;
+
        devpriv->control_state &= ~INTE & ~PACER_MASK;
        outb(devpriv->control_state, dev->iobase + DAS16M1_INTR_CONTROL);
 
@@ -366,6 +365,7 @@ static int das16m1_ai_rinsn(struct comedi_device *dev,
                            struct comedi_subdevice *s,
                            struct comedi_insn *insn, unsigned int *data)
 {
+       struct das16m1_private_struct *devpriv = dev->private;
        int i, n;
        int byte;
        const int timeout = 1000;
@@ -417,6 +417,7 @@ static int das16m1_do_wbits(struct comedi_device *dev,
                            struct comedi_subdevice *s,
                            struct comedi_insn *insn, unsigned int *data)
 {
+       struct das16m1_private_struct *devpriv = dev->private;
        unsigned int wbits;
 
        /*  only set bits that have been masked */
@@ -436,6 +437,7 @@ static int das16m1_do_wbits(struct comedi_device *dev,
 
 static void das16m1_handler(struct comedi_device *dev, unsigned int status)
 {
+       struct das16m1_private_struct *devpriv = dev->private;
        struct comedi_subdevice *s;
        struct comedi_async *async;
        struct comedi_cmd *cmd;
@@ -582,26 +584,27 @@ static int das16m1_irq_bits(unsigned int irq)
 static int das16m1_attach(struct comedi_device *dev,
                          struct comedi_devconfig *it)
 {
-       const struct das16m1_board *board = comedi_board(dev);
+       struct das16m1_private_struct *devpriv;
        struct comedi_subdevice *s;
        int ret;
        unsigned int irq;
        unsigned long iobase;
 
-       iobase = it->options[0];
+       dev->board_name = dev->driver->driver_name;
 
-       ret = alloc_private(dev, sizeof(struct das16m1_private_struct));
-       if (ret < 0)
-               return ret;
+       iobase = it->options[0];
 
-       dev->board_name = board->name;
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
+               return -ENOMEM;
+       dev->private = devpriv;
 
-       if (!request_region(iobase, DAS16M1_SIZE, dev->driver->driver_name)) {
+       if (!request_region(iobase, DAS16M1_SIZE, dev->board_name)) {
                comedi_error(dev, "I/O port conflict\n");
                return -EIO;
        }
        if (!request_region(iobase + DAS16M1_82C55, DAS16M1_SIZE2,
-                           dev->driver->driver_name)) {
+                           dev->board_name)) {
                release_region(iobase, DAS16M1_SIZE);
                comedi_error(dev, "I/O port conflict\n");
                return -EIO;
@@ -698,21 +701,11 @@ static void das16m1_detach(struct comedi_device *dev)
        }
 }
 
-static const struct das16m1_board das16m1_boards[] = {
-       {
-               .name           = "cio-das16/m1",       /*  CIO-DAS16_M1.pdf */
-               .ai_speed       = 1000,                 /*  1MHz max speed */
-       },
-};
-
 static struct comedi_driver das16m1_driver = {
        .driver_name    = "das16m1",
        .module         = THIS_MODULE,
        .attach         = das16m1_attach,
        .detach         = das16m1_detach,
-       .board_name     = &das16m1_boards[0].name,
-       .num_names      = ARRAY_SIZE(das16m1_boards),
-       .offset         = sizeof(das16m1_boards[0]),
 };
 module_comedi_driver(das16m1_driver);
 
index 2555f3297d7b3021be330340e7cac9065f5179d6..2495cd914793b218391839e34099f1c44490075f 100644 (file)
@@ -454,8 +454,6 @@ struct das1800_private {
        short ao_update_bits;   /* remembers the last write to the 'update' dac */
 };
 
-#define devpriv ((struct das1800_private *)dev->private)
-
 /* analog out range for boards with basic analog out */
 static const struct comedi_lrange range_ao_1 = {
        1,
@@ -501,6 +499,7 @@ static void munge_data(struct comedi_device *dev, uint16_t * array,
 static void das1800_handle_fifo_half_full(struct comedi_device *dev,
                                          struct comedi_subdevice *s)
 {
+       struct das1800_private *devpriv = dev->private;
        int numPoints = 0;      /* number of points to read */
        struct comedi_cmd *cmd = &s->async->cmd;
 
@@ -520,6 +519,7 @@ static void das1800_handle_fifo_half_full(struct comedi_device *dev,
 static void das1800_handle_fifo_not_empty(struct comedi_device *dev,
                                          struct comedi_subdevice *s)
 {
+       struct das1800_private *devpriv = dev->private;
        short dpnt;
        int unipolar;
        struct comedi_cmd *cmd = &s->async->cmd;
@@ -548,6 +548,7 @@ static void das1800_flush_dma_channel(struct comedi_device *dev,
                                      struct comedi_subdevice *s,
                                      unsigned int channel, uint16_t *buffer)
 {
+       struct das1800_private *devpriv = dev->private;
        unsigned int num_bytes, num_samples;
        struct comedi_cmd *cmd = &s->async->cmd;
 
@@ -578,6 +579,7 @@ static void das1800_flush_dma_channel(struct comedi_device *dev,
 static void das1800_flush_dma(struct comedi_device *dev,
                              struct comedi_subdevice *s)
 {
+       struct das1800_private *devpriv = dev->private;
        unsigned long flags;
        const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL;
 
@@ -609,6 +611,7 @@ static void das1800_flush_dma(struct comedi_device *dev,
 static void das1800_handle_dma(struct comedi_device *dev,
                               struct comedi_subdevice *s, unsigned int status)
 {
+       struct das1800_private *devpriv = dev->private;
        unsigned long flags;
        const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL;
 
@@ -643,6 +646,8 @@ static void das1800_handle_dma(struct comedi_device *dev,
 
 static int das1800_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+       struct das1800_private *devpriv = dev->private;
+
        outb(0x0, dev->iobase + DAS1800_STATUS);        /* disable conversions */
        outb(0x0, dev->iobase + DAS1800_CONTROL_B);     /* disable interrupts and dma */
        outb(0x0, dev->iobase + DAS1800_CONTROL_A);     /* disable and clear fifo and stop triggering */
@@ -656,6 +661,7 @@ static int das1800_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
 /* the guts of the interrupt handler, that is shared with das1800_ai_poll */
 static void das1800_ai_handler(struct comedi_device *dev)
 {
+       struct das1800_private *devpriv = dev->private;
        struct comedi_subdevice *s = &dev->subdevices[0];
        struct comedi_async *async = s->async;
        struct comedi_cmd *cmd = &async->cmd;
@@ -783,6 +789,7 @@ static int das1800_ai_do_cmdtest(struct comedi_device *dev,
                                 struct comedi_subdevice *s,
                                 struct comedi_cmd *cmd)
 {
+       struct das1800_private *devpriv = dev->private;
        int err = 0;
        unsigned int tmp_arg;
        int i;
@@ -1006,6 +1013,7 @@ static int control_c_bits(const struct comedi_cmd *cmd)
 /* loads counters with divisor1, divisor2 from private structure */
 static int das1800_set_frequency(struct comedi_device *dev)
 {
+       struct das1800_private *devpriv = dev->private;
        int err = 0;
 
        /*  counter 1, mode 2 */
@@ -1026,6 +1034,7 @@ static int das1800_set_frequency(struct comedi_device *dev)
 static int setup_counters(struct comedi_device *dev,
                          const struct comedi_cmd *cmd)
 {
+       struct das1800_private *devpriv = dev->private;
        unsigned int period;
 
        /*  setup cascaded counters for conversion/scan frequency */
@@ -1107,6 +1116,7 @@ static unsigned int suggest_transfer_size(const struct comedi_cmd *cmd)
 /* sets up dma */
 static void setup_dma(struct comedi_device *dev, const struct comedi_cmd *cmd)
 {
+       struct das1800_private *devpriv = dev->private;
        unsigned long lock_flags;
        const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL;
 
@@ -1174,6 +1184,7 @@ static void program_chanlist(struct comedi_device *dev,
 static int das1800_ai_do_cmd(struct comedi_device *dev,
                             struct comedi_subdevice *s)
 {
+       struct das1800_private *devpriv = dev->private;
        int ret;
        int control_a, control_c;
        struct comedi_async *async = s->async;
@@ -1300,6 +1311,7 @@ static int das1800_ao_winsn(struct comedi_device *dev,
                            struct comedi_subdevice *s,
                            struct comedi_insn *insn, unsigned int *data)
 {
+       struct das1800_private *devpriv = dev->private;
        int chan = CR_CHAN(insn->chanspec);
 /* int range = CR_RANGE(insn->chanspec); */
        int update_chan = thisboard->ao_n_chan - 1;
@@ -1342,6 +1354,7 @@ static int das1800_do_wbits(struct comedi_device *dev,
                            struct comedi_subdevice *s,
                            struct comedi_insn *insn, unsigned int *data)
 {
+       struct das1800_private *devpriv = dev->private;
        unsigned int wbits;
 
        /*  only set bits that have been masked */
@@ -1361,6 +1374,7 @@ static int das1800_do_wbits(struct comedi_device *dev,
 static int das1800_init_dma(struct comedi_device *dev, unsigned int dma0,
                            unsigned int dma1)
 {
+       struct das1800_private *devpriv = dev->private;
        unsigned long flags;
 
        /*  need an irq to do dma */
@@ -1518,6 +1532,7 @@ static int das1800_probe(struct comedi_device *dev)
 static int das1800_attach(struct comedi_device *dev,
                          struct comedi_devconfig *it)
 {
+       struct das1800_private *devpriv;
        struct comedi_subdevice *s;
        unsigned long iobase = it->options[0];
        unsigned int irq = it->options[1];
@@ -1527,9 +1542,10 @@ static int das1800_attach(struct comedi_device *dev,
        int board;
        int retval;
 
-       /* allocate and initialize dev->private */
-       if (alloc_private(dev, sizeof(struct das1800_private)) < 0)
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
                return -ENOMEM;
+       dev->private = devpriv;
 
        printk(KERN_DEBUG "comedi%d: %s: io 0x%lx", dev->minor,
               dev->driver->driver_name, iobase);
@@ -1699,11 +1715,13 @@ static int das1800_attach(struct comedi_device *dev,
 
 static void das1800_detach(struct comedi_device *dev)
 {
+       struct das1800_private *devpriv = dev->private;
+
        if (dev->iobase)
                release_region(dev->iobase, DAS1800_SIZE);
        if (dev->irq)
                free_irq(dev->irq, dev);
-       if (dev->private) {
+       if (devpriv) {
                if (devpriv->iobase2)
                        release_region(devpriv->iobase2, DAS1800_SIZE);
                if (devpriv->dma0)
index e134c46dedff9f318748f9d1ca9b62e120842d8d..2efddb89bbcb67c24f6d6f0dbb2a6b20f0e308bf 100644 (file)
@@ -104,7 +104,6 @@ struct das6402_private {
 
        int das6402_ignoreirq;
 };
-#define devpriv ((struct das6402_private *)dev->private)
 
 static void das6402_ai_fifo_dregs(struct comedi_device *dev,
                                  struct comedi_subdevice *s)
@@ -152,6 +151,7 @@ static void das6402_setcounter(struct comedi_device *dev)
 static irqreturn_t intr_handler(int irq, void *d)
 {
        struct comedi_device *dev = d;
+       struct das6402_private *devpriv = dev->private;
        struct comedi_subdevice *s = &dev->subdevices[0];
 
        if (!dev->attached || devpriv->das6402_ignoreirq) {
@@ -196,6 +196,8 @@ static void das6402_ai_fifo_read(struct comedi_device *dev, short *data, int n)
 static int das6402_ai_cancel(struct comedi_device *dev,
                             struct comedi_subdevice *s)
 {
+       struct das6402_private *devpriv = dev->private;
+
        /*
         *  This function should reset the board from whatever condition it
         *  is in (i.e., acquiring data), to a non-active state.
@@ -217,6 +219,8 @@ static int das6402_ai_cancel(struct comedi_device *dev,
 static int das6402_ai_mode2(struct comedi_device *dev,
                            struct comedi_subdevice *s, comedi_trig * it)
 {
+       struct das6402_private *devpriv = dev->private;
+
        devpriv->das6402_ignoreirq = 1;
        dev_dbg(dev->class_dev, "Starting acquisition\n");
        outb_p(0x03, dev->iobase + 10); /* enable external trigging */
@@ -236,6 +240,7 @@ static int das6402_ai_mode2(struct comedi_device *dev,
 
 static int board_init(struct comedi_device *dev)
 {
+       struct das6402_private *devpriv = dev->private;
        BYTE b;
 
        devpriv->das6402_ignoreirq = 1;
@@ -277,6 +282,7 @@ static int board_init(struct comedi_device *dev)
 static int das6402_attach(struct comedi_device *dev,
                          struct comedi_devconfig *it)
 {
+       struct das6402_private *devpriv;
        unsigned int irq;
        unsigned long iobase;
        int ret;
@@ -303,9 +309,11 @@ static int das6402_attach(struct comedi_device *dev,
                return ret;
 
        dev->irq = irq;
-       ret = alloc_private(dev, sizeof(struct das6402_private));
-       if (ret < 0)
-               return ret;
+
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
+               return -ENOMEM;
+       dev->private = devpriv;
 
        ret = comedi_alloc_subdevices(dev, 1);
        if (ret)
index 215deac0a396a1c36c06815f6133511e2a03c33a..1ba26b46fd9a5402dc082cfbd31ec4af19f52c12 100644 (file)
@@ -241,8 +241,6 @@ struct das800_private {
        volatile int do_bits;   /* digital output bits */
 };
 
-#define devpriv ((struct das800_private *)dev->private)
-
 static int das800_attach(struct comedi_device *dev,
                         struct comedi_devconfig *it);
 static void das800_detach(struct comedi_device *dev);
@@ -367,6 +365,7 @@ static irqreturn_t das800_interrupt(int irq, void *d)
        short i;                /* loop index */
        short dataPoint = 0;
        struct comedi_device *dev = d;
+       struct das800_private *devpriv = dev->private;
        struct comedi_subdevice *s = dev->read_subdev;  /* analog input subdevice */
        struct comedi_async *async;
        int status;
@@ -461,6 +460,7 @@ static irqreturn_t das800_interrupt(int irq, void *d)
 
 static int das800_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
+       struct das800_private *devpriv;
        struct comedi_subdevice *s;
        unsigned long iobase = it->options[0];
        unsigned int irq = it->options[1];
@@ -472,9 +472,10 @@ static int das800_attach(struct comedi_device *dev, struct comedi_devconfig *it)
        if (irq)
                dev_dbg(dev->class_dev, "irq %u\n", irq);
 
-       /* allocate and initialize dev->private */
-       if (alloc_private(dev, sizeof(struct das800_private)) < 0)
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
                return -ENOMEM;
+       dev->private = devpriv;
 
        if (iobase == 0) {
                dev_err(dev->class_dev,
@@ -569,6 +570,8 @@ static void das800_detach(struct comedi_device *dev)
 
 static int das800_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+       struct das800_private *devpriv = dev->private;
+
        devpriv->forever = 0;
        devpriv->count = 0;
        disable_das800(dev);
@@ -578,7 +581,9 @@ static int das800_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
 /* enable_das800 makes the card start taking hardware triggered conversions */
 static void enable_das800(struct comedi_device *dev)
 {
+       struct das800_private *devpriv = dev->private;
        unsigned long irq_flags;
+
        spin_lock_irqsave(&dev->spinlock, irq_flags);
        /*  enable fifo-half full interrupts for cio-das802/16 */
        if (thisboard->resolution == 16)
@@ -604,6 +609,7 @@ static int das800_ai_do_cmdtest(struct comedi_device *dev,
                                struct comedi_subdevice *s,
                                struct comedi_cmd *cmd)
 {
+       struct das800_private *devpriv = dev->private;
        int err = 0;
        int tmp;
        int gain, startChan;
@@ -710,6 +716,7 @@ static int das800_ai_do_cmdtest(struct comedi_device *dev,
 static int das800_ai_do_cmd(struct comedi_device *dev,
                            struct comedi_subdevice *s)
 {
+       struct das800_private *devpriv = dev->private;
        int startChan, endChan, scan, gain;
        int conv_bits;
        unsigned long irq_flags;
@@ -793,6 +800,7 @@ static int das800_ai_rinsn(struct comedi_device *dev,
                           struct comedi_subdevice *s, struct comedi_insn *insn,
                           unsigned int *data)
 {
+       struct das800_private *devpriv = dev->private;
        int i, n;
        int chan;
        int range;
@@ -862,6 +870,7 @@ static int das800_do_wbits(struct comedi_device *dev,
                           struct comedi_subdevice *s, struct comedi_insn *insn,
                           unsigned int *data)
 {
+       struct das800_private *devpriv = dev->private;
        int wbits;
        unsigned long irq_flags;
 
@@ -885,6 +894,7 @@ static int das800_do_wbits(struct comedi_device *dev,
 /* loads counters with divisor1, divisor2 from private structure */
 static int das800_set_frequency(struct comedi_device *dev)
 {
+       struct das800_private *devpriv = dev->private;
        int err = 0;
 
        if (i8254_load(dev->iobase + DAS800_8254, 0, 1, devpriv->divisor1, 2))
index 4d5c33c4750f4c9936c4eeba726129072e0b78da..a526c6770bbc040de13bbf2c2052be0e7f289fae 100644 (file)
@@ -158,10 +158,6 @@ static const struct comedi_lrange dmm32at_aoranges = {
         }
 };
 
-struct dmm32at_board {
-       const char *name;
-};
-
 struct dmm32at_private {
 
        int data;
@@ -718,7 +714,6 @@ static int dmm32at_dio_insn_config(struct comedi_device *dev,
 static int dmm32at_attach(struct comedi_device *dev,
                          struct comedi_devconfig *it)
 {
-       const struct dmm32at_board *board = comedi_board(dev);
        struct dmm32at_private *devpriv;
        int ret;
        struct comedi_subdevice *s;
@@ -726,6 +721,8 @@ static int dmm32at_attach(struct comedi_device *dev,
        unsigned long iobase;
        unsigned int irq;
 
+       dev->board_name = dev->driver->driver_name;
+
        iobase = it->options[0];
        irq = it->options[1];
 
@@ -734,7 +731,7 @@ static int dmm32at_attach(struct comedi_device *dev,
               iobase, irq);
 
        /* register address space */
-       if (!request_region(iobase, DMM32AT_MEMSIZE, board->name)) {
+       if (!request_region(iobase, DMM32AT_MEMSIZE, dev->board_name)) {
                printk(KERN_ERR "comedi%d: dmm32at: I/O port conflict\n",
                       dev->minor);
                return -EIO;
@@ -788,7 +785,7 @@ static int dmm32at_attach(struct comedi_device *dev,
 
        /* board is there, register interrupt */
        if (irq) {
-               ret = request_irq(irq, dmm32at_isr, 0, board->name, dev);
+               ret = request_irq(irq, dmm32at_isr, 0, dev->board_name, dev);
                if (ret < 0) {
                        printk(KERN_ERR "dmm32at: irq conflict\n");
                        return ret;
@@ -796,11 +793,10 @@ static int dmm32at_attach(struct comedi_device *dev,
                dev->irq = irq;
        }
 
-       dev->board_name = board->name;
-
-       if (alloc_private(dev, sizeof(*devpriv)) < 0)
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
                return -ENOMEM;
-       devpriv = dev->private;
+       dev->private = devpriv;
 
        ret = comedi_alloc_subdevices(dev, 3);
        if (ret)
@@ -867,20 +863,11 @@ static void dmm32at_detach(struct comedi_device *dev)
                release_region(dev->iobase, DMM32AT_MEMSIZE);
 }
 
-static const struct dmm32at_board dmm32at_boards[] = {
-       {
-               .name           = "dmm32at",
-       },
-};
-
 static struct comedi_driver dmm32at_driver = {
        .driver_name    = "dmm32at",
        .module         = THIS_MODULE,
        .attach         = dmm32at_attach,
        .detach         = dmm32at_detach,
-       .board_name     = &dmm32at_boards[0].name,
-       .offset         = sizeof(struct dmm32at_board),
-       .num_names      = ARRAY_SIZE(dmm32at_boards),
 };
 module_comedi_driver(dmm32at_driver);
 
index c59a652a11944452281ad97c6637d2593dc37d90..f6942aaf0ecd0f485b2dad3237be27e231142a93 100644 (file)
@@ -233,8 +233,6 @@ struct dt2801_private {
        unsigned int ao_readback[2];
 };
 
-#define devpriv ((struct dt2801_private *)dev->private)
-
 /* These are the low-level routines:
    writecommand: write a command to the board
    writedata: write data byte
@@ -508,6 +506,8 @@ static int dt2801_ao_insn_read(struct comedi_device *dev,
                               struct comedi_subdevice *s,
                               struct comedi_insn *insn, unsigned int *data)
 {
+       struct dt2801_private *devpriv = dev->private;
+
        data[0] = devpriv->ao_readback[CR_CHAN(insn->chanspec)];
 
        return 1;
@@ -517,6 +517,8 @@ static int dt2801_ao_insn_write(struct comedi_device *dev,
                                struct comedi_subdevice *s,
                                struct comedi_insn *insn, unsigned int *data)
 {
+       struct dt2801_private *devpriv = dev->private;
+
        dt2801_writecmd(dev, DT_C_WRITE_DAIM);
        dt2801_writedata(dev, CR_CHAN(insn->chanspec));
        dt2801_writedata2(dev, data[0]);
@@ -590,6 +592,7 @@ static int dt2801_dio_insn_config(struct comedi_device *dev,
 */
 static int dt2801_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
+       struct dt2801_private *devpriv;
        struct comedi_subdevice *s;
        unsigned long iobase;
        int board_code, type;
@@ -630,9 +633,10 @@ havetype:
        if (ret)
                goto out;
 
-       ret = alloc_private(dev, sizeof(struct dt2801_private));
-       if (ret < 0)
-               return ret;
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
+               return -ENOMEM;
+       dev->private = devpriv;
 
        dev->board_name = boardtype.name;
 
index d3a8c1aec9d696e86945bd091961882df0d7a9bd..f90ecf494aafd7005b415e35c9023ab5267a3f44 100644 (file)
@@ -226,8 +226,6 @@ struct dt2811_private {
        unsigned int ao_readback[2];
 };
 
-#define devpriv ((struct dt2811_private *)dev->private)
-
 static const struct comedi_lrange *dac_range_types[] = {
        &range_bipolar5,
        &range_bipolar2_5,
@@ -242,6 +240,7 @@ static irqreturn_t dt2811_interrupt(int irq, void *d)
        int lo, hi;
        int data;
        struct comedi_device *dev = d;
+       struct dt2811_private *devpriv = dev->private;
 
        if (!dev->attached) {
                comedi_error(dev, "spurious interrupt");
@@ -318,6 +317,7 @@ int dt2811_adtrig(kdev_t minor, comedi_adtrig *adtrig)
 static int dt2811_ao_insn(struct comedi_device *dev, struct comedi_subdevice *s,
                          struct comedi_insn *insn, unsigned int *data)
 {
+       struct dt2811_private *devpriv = dev->private;
        int i;
        int chan;
 
@@ -337,6 +337,7 @@ static int dt2811_ao_insn_read(struct comedi_device *dev,
                               struct comedi_subdevice *s,
                               struct comedi_insn *insn, unsigned int *data)
 {
+       struct dt2811_private *devpriv = dev->private;
        int i;
        int chan;
 
@@ -397,6 +398,7 @@ static int dt2811_attach(struct comedi_device *dev, struct comedi_devconfig *it)
        /* long flags; */
 
        const struct dt2811_board *board = comedi_board(dev);
+       struct dt2811_private *devpriv;
        int ret;
        struct comedi_subdevice *s;
        unsigned long iobase;
@@ -463,9 +465,10 @@ static int dt2811_attach(struct comedi_device *dev, struct comedi_devconfig *it)
        if (ret)
                return ret;
 
-       ret = alloc_private(dev, sizeof(struct dt2811_private));
-       if (ret < 0)
-               return ret;
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
+               return -ENOMEM;
+       dev->private = devpriv;
 
        switch (it->options[2]) {
        case 0:
index 064a8f215e4df4ab15ed96e49d74fc5f596b72a5..35cb2b55236c6ada7aeb654fa020896ed69472f8 100644 (file)
@@ -68,8 +68,6 @@ struct dt2814_private {
        int curadchan;
 };
 
-#define devpriv ((struct dt2814_private *)dev->private)
-
 #define DT2814_TIMEOUT 10
 #define DT2814_MAX_SPEED 100000        /* Arbitrary 10 khz limit */
 
@@ -200,6 +198,7 @@ static int dt2814_ai_cmdtest(struct comedi_device *dev,
 
 static int dt2814_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+       struct dt2814_private *devpriv = dev->private;
        struct comedi_cmd *cmd = &s->async->cmd;
        int chan;
        int trigvar;
@@ -221,6 +220,7 @@ static irqreturn_t dt2814_interrupt(int irq, void *d)
 {
        int lo, hi;
        struct comedi_device *dev = d;
+       struct dt2814_private *devpriv = dev->private;
        struct comedi_subdevice *s;
        int data;
 
@@ -258,6 +258,7 @@ static irqreturn_t dt2814_interrupt(int irq, void *d)
 
 static int dt2814_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
+       struct dt2814_private *devpriv;
        int i, irq;
        int ret;
        struct comedi_subdevice *s;
@@ -324,9 +325,10 @@ static int dt2814_attach(struct comedi_device *dev, struct comedi_devconfig *it)
        if (ret)
                return ret;
 
-       ret = alloc_private(dev, sizeof(struct dt2814_private));
-       if (ret < 0)
-               return ret;
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
+               return -ENOMEM;
+       dev->private = devpriv;
 
        s = &dev->subdevices[0];
        dev->read_subdev = s;
index b9692ef64c41cf6cfcfb0d2926ea06ea1719e252..1e0cfe4972a6f39ecffdd2ecba2c374b89659ab9 100644 (file)
@@ -78,8 +78,6 @@ struct dt2815_private {
        unsigned int ao_readback[8];
 };
 
-#define devpriv ((struct dt2815_private *)dev->private)
-
 static int dt2815_wait_for_status(struct comedi_device *dev, int status)
 {
        int i;
@@ -95,6 +93,7 @@ static int dt2815_ao_insn_read(struct comedi_device *dev,
                               struct comedi_subdevice *s,
                               struct comedi_insn *insn, unsigned int *data)
 {
+       struct dt2815_private *devpriv = dev->private;
        int i;
        int chan = CR_CHAN(insn->chanspec);
 
@@ -107,6 +106,7 @@ static int dt2815_ao_insn_read(struct comedi_device *dev,
 static int dt2815_ao_insn(struct comedi_device *dev, struct comedi_subdevice *s,
                          struct comedi_insn *insn, unsigned int *data)
 {
+       struct dt2815_private *devpriv = dev->private;
        int i;
        int chan = CR_CHAN(insn->chanspec);
        unsigned int status;
@@ -162,6 +162,7 @@ static int dt2815_ao_insn(struct comedi_device *dev, struct comedi_subdevice *s,
 
 static int dt2815_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
+       struct dt2815_private *devpriv;
        struct comedi_subdevice *s;
        int i;
        const struct comedi_lrange *current_range_type, *voltage_range_type;
@@ -182,8 +183,10 @@ static int dt2815_attach(struct comedi_device *dev, struct comedi_devconfig *it)
        if (ret)
                return ret;
 
-       if (alloc_private(dev, sizeof(struct dt2815_private)) < 0)
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
                return -ENOMEM;
+       dev->private = devpriv;
 
        s = &dev->subdevices[0];
        /* ao subdevice */
index 78d340716d1e792ddb0a154c19f78eb4cade364e..9746294efc94904ec26ccc11ffce1892f74e9a60 100644 (file)
@@ -248,7 +248,6 @@ struct dt282x_private {
        int dma_dir;
 };
 
-#define devpriv ((struct dt282x_private *)dev->private)
 #define boardtype (*(const struct dt282x_board *)dev->board_ptr)
 
 /*
@@ -290,6 +289,7 @@ static int dt282x_grab_dma(struct comedi_device *dev, int dma1, int dma2);
 static void dt282x_munge(struct comedi_device *dev, short *buf,
                         unsigned int nbytes)
 {
+       struct dt282x_private *devpriv = dev->private;
        unsigned int i;
        unsigned short mask = (1 << boardtype.adbits) - 1;
        unsigned short sign = 1 << (boardtype.adbits - 1);
@@ -309,6 +309,7 @@ static void dt282x_munge(struct comedi_device *dev, short *buf,
 
 static void dt282x_ao_dma_interrupt(struct comedi_device *dev)
 {
+       struct dt282x_private *devpriv = dev->private;
        void *ptr;
        int size;
        int i;
@@ -341,6 +342,7 @@ static void dt282x_ao_dma_interrupt(struct comedi_device *dev)
 
 static void dt282x_ai_dma_interrupt(struct comedi_device *dev)
 {
+       struct dt282x_private *devpriv = dev->private;
        void *ptr;
        int size;
        int i;
@@ -393,6 +395,7 @@ static void dt282x_ai_dma_interrupt(struct comedi_device *dev)
 
 static int prep_ai_dma(struct comedi_device *dev, int dma_index, int n)
 {
+       struct dt282x_private *devpriv = dev->private;
        int dma_chan;
        unsigned long dma_ptr;
        unsigned long flags;
@@ -424,6 +427,7 @@ static int prep_ai_dma(struct comedi_device *dev, int dma_index, int n)
 
 static int prep_ao_dma(struct comedi_device *dev, int dma_index, int n)
 {
+       struct dt282x_private *devpriv = dev->private;
        int dma_chan;
        unsigned long dma_ptr;
        unsigned long flags;
@@ -447,6 +451,7 @@ static int prep_ao_dma(struct comedi_device *dev, int dma_index, int n)
 static irqreturn_t dt282x_interrupt(int irq, void *d)
 {
        struct comedi_device *dev = d;
+       struct dt282x_private *devpriv = dev->private;
        struct comedi_subdevice *s;
        struct comedi_subdevice *s_ao;
        unsigned int supcsr, adcsr, dacsr;
@@ -525,6 +530,7 @@ static irqreturn_t dt282x_interrupt(int irq, void *d)
 static void dt282x_load_changain(struct comedi_device *dev, int n,
                                 unsigned int *chanlist)
 {
+       struct dt282x_private *devpriv = dev->private;
        unsigned int i;
        unsigned int chan, range;
 
@@ -548,6 +554,7 @@ static int dt282x_ai_insn_read(struct comedi_device *dev,
                               struct comedi_subdevice *s,
                               struct comedi_insn *insn, unsigned int *data)
 {
+       struct dt282x_private *devpriv = dev->private;
        int i;
 
        /* XXX should we really be enabling the ad clock here? */
@@ -671,6 +678,7 @@ static int dt282x_ai_cmdtest(struct comedi_device *dev,
 static int dt282x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
        const struct dt282x_board *board = comedi_board(dev);
+       struct dt282x_private *devpriv = dev->private;
        struct comedi_cmd *cmd = &s->async->cmd;
        int timer;
 
@@ -733,6 +741,8 @@ static int dt282x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 
 static void dt282x_disable_dma(struct comedi_device *dev)
 {
+       struct dt282x_private *devpriv = dev->private;
+
        if (devpriv->usedma) {
                disable_dma(devpriv->dma[0].chan);
                disable_dma(devpriv->dma[1].chan);
@@ -742,6 +752,8 @@ static void dt282x_disable_dma(struct comedi_device *dev)
 static int dt282x_ai_cancel(struct comedi_device *dev,
                            struct comedi_subdevice *s)
 {
+       struct dt282x_private *devpriv = dev->private;
+
        dt282x_disable_dma(dev);
 
        devpriv->adcsr = 0;
@@ -794,6 +806,8 @@ static int dt282x_ao_insn_read(struct comedi_device *dev,
                               struct comedi_subdevice *s,
                               struct comedi_insn *insn, unsigned int *data)
 {
+       struct dt282x_private *devpriv = dev->private;
+
        data[0] = devpriv->ao[CR_CHAN(insn->chanspec)];
 
        return 1;
@@ -803,6 +817,7 @@ static int dt282x_ao_insn_write(struct comedi_device *dev,
                                struct comedi_subdevice *s,
                                struct comedi_insn *insn, unsigned int *data)
 {
+       struct dt282x_private *devpriv = dev->private;
        short d;
        unsigned int chan;
 
@@ -908,6 +923,7 @@ static int dt282x_ao_cmdtest(struct comedi_device *dev,
 static int dt282x_ao_inttrig(struct comedi_device *dev,
                             struct comedi_subdevice *s, unsigned int x)
 {
+       struct dt282x_private *devpriv = dev->private;
        int size;
 
        if (x != 0)
@@ -937,6 +953,7 @@ static int dt282x_ao_inttrig(struct comedi_device *dev,
 
 static int dt282x_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+       struct dt282x_private *devpriv = dev->private;
        int timer;
        struct comedi_cmd *cmd = &s->async->cmd;
 
@@ -973,6 +990,8 @@ static int dt282x_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 static int dt282x_ao_cancel(struct comedi_device *dev,
                            struct comedi_subdevice *s)
 {
+       struct dt282x_private *devpriv = dev->private;
+
        dt282x_disable_dma(dev);
 
        devpriv->dacsr = 0;
@@ -1003,6 +1022,7 @@ static int dt282x_dio_insn_config(struct comedi_device *dev,
                                  struct comedi_subdevice *s,
                                  struct comedi_insn *insn, unsigned int *data)
 {
+       struct dt282x_private *devpriv = dev->private;
        int mask;
 
        mask = (CR_CHAN(insn->chanspec) < 8) ? 0x00ff : 0xff00;
@@ -1074,6 +1094,7 @@ enum {  /* i/o base, irq, dma channels */
 
 static int dt282x_grab_dma(struct comedi_device *dev, int dma1, int dma2)
 {
+       struct dt282x_private *devpriv = dev->private;
        int ret;
 
        devpriv->usedma = 0;
@@ -1135,6 +1156,7 @@ static int dt282x_grab_dma(struct comedi_device *dev, int dma1, int dma2)
 static int dt282x_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
        const struct dt282x_board *board = comedi_board(dev);
+       struct dt282x_private *devpriv;
        int i, irq;
        int ret;
        struct comedi_subdevice *s;
@@ -1217,9 +1239,10 @@ static int dt282x_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 #endif
        }
 
-       ret = alloc_private(dev, sizeof(struct dt282x_private));
-       if (ret < 0)
-               return ret;
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
+               return -ENOMEM;
+       dev->private = devpriv;
 
        ret = dt282x_grab_dma(dev, it->options[opt_dma1],
                              it->options[opt_dma2]);
@@ -1292,6 +1315,8 @@ static int dt282x_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 
 static void dt282x_detach(struct comedi_device *dev)
 {
+       struct dt282x_private *devpriv = dev->private;
+
        if (dev->irq)
                free_irq(dev->irq, dev);
        if (dev->iobase)
index 43d05ef971573c27a4e1fbdfb523ebd99827cfb6..46645759781d141d192cefb57771dd4732188ecc 100644 (file)
@@ -257,8 +257,6 @@ struct dt3k_private {
        unsigned int ai_rear;
 };
 
-#define devpriv ((struct dt3k_private *)dev->private)
-
 static void dt3k_ai_empty_fifo(struct comedi_device *dev,
                               struct comedi_subdevice *s);
 static int dt3k_ns_to_timer(unsigned int timer_base, unsigned int *arg,
@@ -273,6 +271,7 @@ static void debug_intr_flags(unsigned int flags);
 
 static int dt3k_send_cmd(struct comedi_device *dev, unsigned int cmd)
 {
+       struct dt3k_private *devpriv = dev->private;
        int i;
        unsigned int status = 0;
 
@@ -297,6 +296,8 @@ static unsigned int dt3k_readsingle(struct comedi_device *dev,
                                    unsigned int subsys, unsigned int chan,
                                    unsigned int gain)
 {
+       struct dt3k_private *devpriv = dev->private;
+
        writew(subsys, devpriv->io_addr + DPR_SubSys);
 
        writew(chan, devpriv->io_addr + DPR_Params(0));
@@ -310,6 +311,8 @@ static unsigned int dt3k_readsingle(struct comedi_device *dev,
 static void dt3k_writesingle(struct comedi_device *dev, unsigned int subsys,
                             unsigned int chan, unsigned int data)
 {
+       struct dt3k_private *devpriv = dev->private;
+
        writew(subsys, devpriv->io_addr + DPR_SubSys);
 
        writew(chan, devpriv->io_addr + DPR_Params(0));
@@ -326,6 +329,7 @@ static int debug_n_ints;
 static irqreturn_t dt3k_interrupt(int irq, void *d)
 {
        struct comedi_device *dev = d;
+       struct dt3k_private *devpriv = dev->private;
        struct comedi_subdevice *s;
        unsigned int status;
 
@@ -377,6 +381,7 @@ static void debug_intr_flags(unsigned int flags)
 static void dt3k_ai_empty_fifo(struct comedi_device *dev,
                               struct comedi_subdevice *s)
 {
+       struct dt3k_private *devpriv = dev->private;
        int front;
        int rear;
        int count;
@@ -550,6 +555,7 @@ static int dt3k_ns_to_timer(unsigned int timer_base, unsigned int *nanosec,
 
 static int dt3k_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+       struct dt3k_private *devpriv = dev->private;
        struct comedi_cmd *cmd = &s->async->cmd;
        int i;
        unsigned int chan, range, aref;
@@ -618,6 +624,7 @@ static int dt3k_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 
 static int dt3k_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+       struct dt3k_private *devpriv = dev->private;
        int ret;
 
        writew(SUBS_AI, devpriv->io_addr + DPR_SubSys);
@@ -648,6 +655,7 @@ static int dt3k_ai_insn(struct comedi_device *dev, struct comedi_subdevice *s,
 static int dt3k_ao_insn(struct comedi_device *dev, struct comedi_subdevice *s,
                        struct comedi_insn *insn, unsigned int *data)
 {
+       struct dt3k_private *devpriv = dev->private;
        int i;
        unsigned int chan;
 
@@ -664,6 +672,7 @@ static int dt3k_ao_insn_read(struct comedi_device *dev,
                             struct comedi_subdevice *s,
                             struct comedi_insn *insn, unsigned int *data)
 {
+       struct dt3k_private *devpriv = dev->private;
        int i;
        unsigned int chan;
 
@@ -676,6 +685,8 @@ static int dt3k_ao_insn_read(struct comedi_device *dev,
 
 static void dt3k_dio_config(struct comedi_device *dev, int bits)
 {
+       struct dt3k_private *devpriv = dev->private;
+
        /* XXX */
        writew(SUBS_DOUT, devpriv->io_addr + DPR_SubSys);
 
@@ -739,6 +750,7 @@ static int dt3k_mem_insn_read(struct comedi_device *dev,
                              struct comedi_subdevice *s,
                              struct comedi_insn *insn, unsigned int *data)
 {
+       struct dt3k_private *devpriv = dev->private;
        unsigned int addr = CR_CHAN(insn->chanspec);
        int i;
 
@@ -786,6 +798,7 @@ static struct pci_dev *dt3000_find_pci_dev(struct comedi_device *dev,
 
 static int dt3000_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
+       struct dt3k_private *devpriv;
        struct pci_dev *pcidev;
        struct comedi_subdevice *s;
        resource_size_t pci_base;
@@ -793,9 +806,10 @@ static int dt3000_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 
        dev_dbg(dev->class_dev, "dt3000:\n");
 
-       ret = alloc_private(dev, sizeof(struct dt3k_private));
-       if (ret < 0)
-               return ret;
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
+               return -ENOMEM;
+       dev->private = devpriv;
 
        pcidev = dt3000_find_pci_dev(dev, it);
        if (!pcidev)
@@ -885,6 +899,7 @@ static int dt3000_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 static void dt3000_detach(struct comedi_device *dev)
 {
        struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+       struct dt3k_private *devpriv = dev->private;
 
        if (dev->irq)
                free_irq(dev->irq, dev);
index bc6f409b7e199e39e204cd42b819a805453ac440..176799849d20ec02c70c6860d106c03aebdff239 100644 (file)
@@ -43,6 +43,8 @@ for my needs.
  *      says P1).
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/init.h>
@@ -323,9 +325,6 @@ static const struct comedi_lrange dt9812_2pt5_aout_range = { 1, {
 
 static struct slot_dt9812 dt9812[DT9812_NUM_SLOTS];
 
-/* Useful shorthand access to private data */
-#define devpriv ((struct comedi_dt9812 *)dev->private)
-
 static inline struct usb_dt9812 *to_dt9812_dev(struct kref *d)
 {
        return container_of(d, struct usb_dt9812, kref);
@@ -893,6 +892,7 @@ static struct usb_driver dt9812_usb_driver = {
 
 static int dt9812_comedi_open(struct comedi_device *dev)
 {
+       struct comedi_dt9812 *devpriv = dev->private;
        int result = -ENODEV;
 
        down(&devpriv->slot->mutex);
@@ -947,6 +947,7 @@ static int dt9812_di_rinsn(struct comedi_device *dev,
                           struct comedi_subdevice *s, struct comedi_insn *insn,
                           unsigned int *data)
 {
+       struct comedi_dt9812 *devpriv = dev->private;
        int n;
        u8 bits = 0;
 
@@ -960,6 +961,7 @@ static int dt9812_do_winsn(struct comedi_device *dev,
                           struct comedi_subdevice *s, struct comedi_insn *insn,
                           unsigned int *data)
 {
+       struct comedi_dt9812 *devpriv = dev->private;
        int n;
        u8 bits = 0;
 
@@ -979,6 +981,7 @@ static int dt9812_ai_rinsn(struct comedi_device *dev,
                           struct comedi_subdevice *s, struct comedi_insn *insn,
                           unsigned int *data)
 {
+       struct comedi_dt9812 *devpriv = dev->private;
        int n;
 
        for (n = 0; n < insn->n; n++) {
@@ -995,6 +998,7 @@ static int dt9812_ao_rinsn(struct comedi_device *dev,
                           struct comedi_subdevice *s, struct comedi_insn *insn,
                           unsigned int *data)
 {
+       struct comedi_dt9812 *devpriv = dev->private;
        int n;
        u16 value;
 
@@ -1010,6 +1014,7 @@ static int dt9812_ao_winsn(struct comedi_device *dev,
                           struct comedi_subdevice *s, struct comedi_insn *insn,
                           unsigned int *data)
 {
+       struct comedi_dt9812 *devpriv = dev->private;
        int n;
 
        for (n = 0; n < insn->n; n++)
@@ -1019,14 +1024,17 @@ static int dt9812_ao_winsn(struct comedi_device *dev,
 
 static int dt9812_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
+       struct comedi_dt9812 *devpriv;
        int i;
        struct comedi_subdevice *s;
        int ret;
 
        dev->board_name = "dt9812";
 
-       if (alloc_private(dev, sizeof(struct comedi_dt9812)) < 0)
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
                return -ENOMEM;
+       dev->private = devpriv;
 
        /*
         * Special open routine, since USB unit may be unattached at
@@ -1077,8 +1085,7 @@ static int dt9812_attach(struct comedi_device *dev, struct comedi_devconfig *it)
        s->insn_write = &dt9812_ao_winsn;
        s->insn_read = &dt9812_ao_rinsn;
 
-       printk(KERN_INFO "comedi%d: successfully attached to dt9812.\n",
-              dev->minor);
+       dev_info(dev->class_dev, "successfully attached to dt9812.\n");
 
        down(&dt9812_mutex);
        /* Find a slot for the comedi device */
@@ -1140,17 +1147,15 @@ static int __init usb_dt9812_init(void)
        /* register with the USB subsystem */
        result = usb_register(&dt9812_usb_driver);
        if (result) {
-               printk(KERN_ERR KBUILD_MODNAME
-                      ": usb_register failed. Error number %d\n", result);
+               pr_err("usb_register failed. Error number %d\n", result);
                return result;
        }
        /* register with comedi */
        result = comedi_driver_register(&dt9812_comedi_driver);
        if (result) {
                usb_deregister(&dt9812_usb_driver);
-               printk(KERN_ERR KBUILD_MODNAME
-                       ": comedi_driver_register failed. Error number %d\n",
-                       result);
+               pr_err("comedi_driver_register failed. Error number %d\n",
+                      result);
        }
 
        return result;
index 6f612be1b0a51359a0ce41520ed3735b498c9641..c345660d781aacf9b0bdaf490a2cdd59f15d7b36 100644 (file)
@@ -186,14 +186,12 @@ static int dyna_pci10xx_attach_pci(struct comedi_device *dev,
        struct comedi_subdevice *s;
        int ret;
 
-       comedi_set_hw_dev(dev, &pcidev->dev);
-
        dev->board_name = dev->driver->driver_name;
 
-       ret = alloc_private(dev, sizeof(*devpriv));
-       if (ret)
-               return ret;
-       devpriv = dev->private;
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
+               return -ENOMEM;
+       dev->private = devpriv;
 
        ret = comedi_pci_enable(pcidev, dev->board_name);
        if (ret)
index ae8e8f4602956afd922a55fd2869d475035a8c80..019c96eda6fd25b93f65c59524263bde72157fd7 100644 (file)
@@ -29,8 +29,6 @@ struct fl512_private {
        short ao_readback[2];
 };
 
-#define devpriv ((struct fl512_private *) dev->private)
-
 static const struct comedi_lrange range_fl512 = { 4, {
                                                      BIP_RANGE(0.5),
                                                      BIP_RANGE(1),
@@ -75,6 +73,7 @@ static int fl512_ao_insn(struct comedi_device *dev,
                         struct comedi_subdevice *s, struct comedi_insn *insn,
                         unsigned int *data)
 {
+       struct fl512_private *devpriv = dev->private;
        int n;
        int chan = CR_CHAN(insn->chanspec);     /* get chan to write */
        unsigned long iobase = dev->iobase;     /* get base address  */
@@ -99,6 +98,7 @@ static int fl512_ao_insn_readback(struct comedi_device *dev,
                                  struct comedi_subdevice *s,
                                  struct comedi_insn *insn, unsigned int *data)
 {
+       struct fl512_private *devpriv = dev->private;
        int n;
        int chan = CR_CHAN(insn->chanspec);
 
@@ -110,6 +110,7 @@ static int fl512_ao_insn_readback(struct comedi_device *dev,
 
 static int fl512_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
+       struct fl512_private *devpriv;
        unsigned long iobase;
        int ret;
 
@@ -125,8 +126,11 @@ static int fl512_attach(struct comedi_device *dev, struct comedi_devconfig *it)
        }
        dev->iobase = iobase;
        dev->board_name = "fl512";
-       if (alloc_private(dev, sizeof(struct fl512_private)) < 0)
+
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
                return -ENOMEM;
+       dev->private = devpriv;
 
 #if DEBUG
        printk(KERN_DEBUG "malloc ok\n");
index abff6603952a78afbd386efccb1297770b44d1c8..17aec51343b80e10c9080b9cf3c357b7984d631f 100644 (file)
@@ -104,35 +104,11 @@ enum hpdi_registers {
        INTERRUPT_POLARITY_REG = 0x54,
 };
 
-int command_channel_valid(unsigned int channel)
-{
-       if (channel == 0 || channel > 6) {
-               printk(KERN_WARNING
-                      "gsc_hpdi: bug! invalid cable command channel\n");
-               return 0;
-       }
-       return 1;
-}
-
 /* bit definitions */
 
 enum firmware_revision_bits {
        FEATURES_REG_PRESENT_BIT = 0x8000,
 };
-int firmware_revision(uint32_t fwr_bits)
-{
-       return fwr_bits & 0xff;
-}
-
-int pcb_revision(uint32_t fwr_bits)
-{
-       return (fwr_bits >> 8) & 0xff;
-}
-
-int hpdi_subid(uint32_t fwr_bits)
-{
-       return (fwr_bits >> 16) & 0xff;
-}
 
 enum board_control_bits {
        BOARD_RESET_BIT = 0x1,  /* wait 10usec before accessing fifos */
@@ -147,22 +123,6 @@ enum board_control_bits {
        CABLE_THROTTLE_ENABLE_BIT = 0x20,
        TEST_MODE_ENABLE_BIT = 0x80000000,
 };
-uint32_t command_discrete_output_bits(unsigned int channel, int output,
-                                     int output_value)
-{
-       uint32_t bits = 0;
-
-       if (command_channel_valid(channel) == 0)
-               return 0;
-       if (output) {
-               bits |= 0x1 << (16 + channel);
-               if (output_value)
-                       bits |= 0x1 << (24 + channel);
-       } else
-               bits |= 0x1 << (24 + channel);
-
-       return bits;
-}
 
 enum board_status_bits {
        COMMAND_LINE_STATUS_MASK = 0x7f,
@@ -182,28 +142,17 @@ enum board_status_bits {
        RX_OVERRUN_BIT = 0x800000,
 };
 
-uint32_t almost_full_bits(unsigned int num_words)
+static uint32_t almost_full_bits(unsigned int num_words)
 {
-/* XXX need to add or subtract one? */
+       /* XXX need to add or subtract one? */
        return (num_words << 16) & 0xff0000;
 }
 
-uint32_t almost_empty_bits(unsigned int num_words)
+static uint32_t almost_empty_bits(unsigned int num_words)
 {
        return num_words & 0xffff;
 }
 
-unsigned int almost_full_num_words(uint32_t bits)
-{
-/* XXX need to add or subtract one? */
-       return (bits >> 16) & 0xffff;
-}
-
-unsigned int almost_empty_num_words(uint32_t bits)
-{
-       return bits & 0xffff;
-}
-
 enum features_bits {
        FIFO_SIZE_PRESENT_BIT = 0x1,
        FIFO_WORDS_PRESENT_BIT = 0x2,
@@ -225,43 +174,17 @@ enum interrupt_sources {
        RX_ALMOST_FULL_INTR = 14,
        RX_FULL_INTR = 15,
 };
-int command_intr_source(unsigned int channel)
-{
-       if (command_channel_valid(channel) == 0)
-               channel = 1;
-       return channel + 1;
-}
 
-uint32_t intr_bit(int interrupt_source)
+static uint32_t intr_bit(int interrupt_source)
 {
        return 0x1 << interrupt_source;
 }
 
-uint32_t tx_clock_divisor_bits(unsigned int divisor)
-{
-       return divisor & 0xff;
-}
-
-unsigned int fifo_size(uint32_t fifo_size_bits)
+static unsigned int fifo_size(uint32_t fifo_size_bits)
 {
        return fifo_size_bits & 0xfffff;
 }
 
-unsigned int fifo_words(uint32_t fifo_words_bits)
-{
-       return fifo_words_bits & 0xfffff;
-}
-
-uint32_t intr_edge_bit(int interrupt_source)
-{
-       return 0x1 << interrupt_source;
-}
-
-uint32_t intr_active_high_bit(int interrupt_source)
-{
-       return 0x1 << interrupt_source;
-}
-
 struct hpdi_board {
 
        char *name;
@@ -321,27 +244,24 @@ struct hpdi_private {
        unsigned dio_config_output:1;
 };
 
-static inline struct hpdi_private *priv(struct comedi_device *dev)
-{
-       return dev->private;
-}
-
 static int dio_config_insn(struct comedi_device *dev,
                           struct comedi_subdevice *s, struct comedi_insn *insn,
                           unsigned int *data)
 {
+       struct hpdi_private *devpriv = dev->private;
+
        switch (data[0]) {
        case INSN_CONFIG_DIO_OUTPUT:
-               priv(dev)->dio_config_output = 1;
+               devpriv->dio_config_output = 1;
                return insn->n;
                break;
        case INSN_CONFIG_DIO_INPUT:
-               priv(dev)->dio_config_output = 0;
+               devpriv->dio_config_output = 0;
                return insn->n;
                break;
        case INSN_CONFIG_DIO_QUERY:
                data[1] =
-                   priv(dev)->dio_config_output ? COMEDI_OUTPUT : COMEDI_INPUT;
+                   devpriv->dio_config_output ? COMEDI_OUTPUT : COMEDI_INPUT;
                return insn->n;
                break;
        case INSN_CONFIG_BLOCK_SIZE:
@@ -356,21 +276,24 @@ static int dio_config_insn(struct comedi_device *dev,
 
 static void disable_plx_interrupts(struct comedi_device *dev)
 {
-       writel(0, priv(dev)->plx9080_iobase + PLX_INTRCS_REG);
+       struct hpdi_private *devpriv = dev->private;
+
+       writel(0, devpriv->plx9080_iobase + PLX_INTRCS_REG);
 }
 
 /* initialize plx9080 chip */
 static void init_plx9080(struct comedi_device *dev)
 {
+       struct hpdi_private *devpriv = dev->private;
        uint32_t bits;
-       void __iomem *plx_iobase = priv(dev)->plx9080_iobase;
+       void __iomem *plx_iobase = devpriv->plx9080_iobase;
 
        /*  plx9080 dump */
        DEBUG_PRINT(" plx interrupt status 0x%x\n",
                    readl(plx_iobase + PLX_INTRCS_REG));
        DEBUG_PRINT(" plx id bits 0x%x\n", readl(plx_iobase + PLX_ID_REG));
        DEBUG_PRINT(" plx control reg 0x%x\n",
-                   readl(priv(dev)->plx9080_iobase + PLX_CONTROL_REG));
+                   readl(devpriv->plx9080_iobase + PLX_CONTROL_REG));
 
        DEBUG_PRINT(" plx revision 0x%x\n",
                    readl(plx_iobase + PLX_REVISION_REG));
@@ -396,7 +319,7 @@ static void init_plx9080(struct comedi_device *dev)
 #else
        bits = 0;
 #endif
-       writel(bits, priv(dev)->plx9080_iobase + PLX_BIGEND_REG);
+       writel(bits, devpriv->plx9080_iobase + PLX_BIGEND_REG);
 
        disable_plx_interrupts(dev);
 
@@ -457,28 +380,29 @@ static int setup_subdevices(struct comedi_device *dev)
 
 static int init_hpdi(struct comedi_device *dev)
 {
+       struct hpdi_private *devpriv = dev->private;
        uint32_t plx_intcsr_bits;
 
-       writel(BOARD_RESET_BIT, priv(dev)->hpdi_iobase + BOARD_CONTROL_REG);
+       writel(BOARD_RESET_BIT, devpriv->hpdi_iobase + BOARD_CONTROL_REG);
        udelay(10);
 
        writel(almost_empty_bits(32) | almost_full_bits(32),
-              priv(dev)->hpdi_iobase + RX_PROG_ALMOST_REG);
+              devpriv->hpdi_iobase + RX_PROG_ALMOST_REG);
        writel(almost_empty_bits(32) | almost_full_bits(32),
-              priv(dev)->hpdi_iobase + TX_PROG_ALMOST_REG);
+              devpriv->hpdi_iobase + TX_PROG_ALMOST_REG);
 
-       priv(dev)->tx_fifo_size = fifo_size(readl(priv(dev)->hpdi_iobase +
+       devpriv->tx_fifo_size = fifo_size(readl(devpriv->hpdi_iobase +
                                                  TX_FIFO_SIZE_REG));
-       priv(dev)->rx_fifo_size = fifo_size(readl(priv(dev)->hpdi_iobase +
+       devpriv->rx_fifo_size = fifo_size(readl(devpriv->hpdi_iobase +
                                                  RX_FIFO_SIZE_REG));
 
-       writel(0, priv(dev)->hpdi_iobase + INTERRUPT_CONTROL_REG);
+       writel(0, devpriv->hpdi_iobase + INTERRUPT_CONTROL_REG);
 
        /*  enable interrupts */
        plx_intcsr_bits =
            ICS_AERR | ICS_PERR | ICS_PIE | ICS_PLIE | ICS_PAIE | ICS_LIE |
            ICS_DMA0_E;
-       writel(plx_intcsr_bits, priv(dev)->plx9080_iobase + PLX_INTRCS_REG);
+       writel(plx_intcsr_bits, devpriv->plx9080_iobase + PLX_INTRCS_REG);
 
        return 0;
 }
@@ -487,6 +411,7 @@ static int init_hpdi(struct comedi_device *dev)
 static int setup_dma_descriptors(struct comedi_device *dev,
                                 unsigned int transfer_size)
 {
+       struct hpdi_private *devpriv = dev->private;
        unsigned int buffer_index, buffer_offset;
        uint32_t next_bits = PLX_DESC_IN_PCI_BIT | PLX_INTR_TERM_COUNT |
            PLX_XFER_LOCAL_TO_PCI;
@@ -500,25 +425,25 @@ static int setup_dma_descriptors(struct comedi_device *dev,
 
        DEBUG_PRINT(" transfer_size %i\n", transfer_size);
        DEBUG_PRINT(" descriptors at 0x%lx\n",
-                   (unsigned long)priv(dev)->dma_desc_phys_addr);
+                   (unsigned long)devpriv->dma_desc_phys_addr);
 
        buffer_offset = 0;
        buffer_index = 0;
        for (i = 0; i < NUM_DMA_DESCRIPTORS &&
             buffer_index < NUM_DMA_BUFFERS; i++) {
-               priv(dev)->dma_desc[i].pci_start_addr =
-                   cpu_to_le32(priv(dev)->dio_buffer_phys_addr[buffer_index] +
+               devpriv->dma_desc[i].pci_start_addr =
+                   cpu_to_le32(devpriv->dio_buffer_phys_addr[buffer_index] +
                                buffer_offset);
-               priv(dev)->dma_desc[i].local_start_addr = cpu_to_le32(FIFO_REG);
-               priv(dev)->dma_desc[i].transfer_size =
+               devpriv->dma_desc[i].local_start_addr = cpu_to_le32(FIFO_REG);
+               devpriv->dma_desc[i].transfer_size =
                    cpu_to_le32(transfer_size);
-               priv(dev)->dma_desc[i].next =
-                   cpu_to_le32((priv(dev)->dma_desc_phys_addr + (i +
+               devpriv->dma_desc[i].next =
+                   cpu_to_le32((devpriv->dma_desc_phys_addr + (i +
                                                                  1) *
-                                sizeof(priv(dev)->dma_desc[0])) | next_bits);
+                                sizeof(devpriv->dma_desc[0])) | next_bits);
 
-               priv(dev)->desc_dio_buffer[i] =
-                   priv(dev)->dio_buffer[buffer_index] +
+               devpriv->desc_dio_buffer[i] =
+                   devpriv->dio_buffer[buffer_index] +
                    (buffer_offset / sizeof(uint32_t));
 
                buffer_offset += transfer_size;
@@ -529,34 +454,37 @@ static int setup_dma_descriptors(struct comedi_device *dev,
 
                DEBUG_PRINT(" desc %i\n", i);
                DEBUG_PRINT(" start addr virt 0x%p, phys 0x%lx\n",
-                           priv(dev)->desc_dio_buffer[i],
-                           (unsigned long)priv(dev)->dma_desc[i].
+                           devpriv->desc_dio_buffer[i],
+                           (unsigned long)devpriv->dma_desc[i].
                            pci_start_addr);
                DEBUG_PRINT(" next 0x%lx\n",
-                           (unsigned long)priv(dev)->dma_desc[i].next);
+                           (unsigned long)devpriv->dma_desc[i].next);
        }
-       priv(dev)->num_dma_descriptors = i;
+       devpriv->num_dma_descriptors = i;
        /*  fix last descriptor to point back to first */
-       priv(dev)->dma_desc[i - 1].next =
-           cpu_to_le32(priv(dev)->dma_desc_phys_addr | next_bits);
+       devpriv->dma_desc[i - 1].next =
+           cpu_to_le32(devpriv->dma_desc_phys_addr | next_bits);
        DEBUG_PRINT(" desc %i next fixup 0x%lx\n", i - 1,
-                   (unsigned long)priv(dev)->dma_desc[i - 1].next);
+                   (unsigned long)devpriv->dma_desc[i - 1].next);
 
-       priv(dev)->block_size = transfer_size;
+       devpriv->block_size = transfer_size;
 
        return transfer_size;
 }
 
 static int hpdi_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
+       struct hpdi_private *devpriv;
        struct pci_dev *pcidev;
        int i;
        int retval;
 
        printk(KERN_WARNING "comedi%d: gsc_hpdi\n", dev->minor);
 
-       if (alloc_private(dev, sizeof(struct hpdi_private)) < 0)
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
                return -ENOMEM;
+       dev->private = devpriv;
 
        pcidev = NULL;
        for (i = 0; i < ARRAY_SIZE(hpdi_boards) &&
@@ -575,7 +503,7 @@ static int hpdi_attach(struct comedi_device *dev, struct comedi_devconfig *it)
                                        continue;
                        }
                        if (pcidev) {
-                               priv(dev)->hw_dev = pcidev;
+                               devpriv->hw_dev = pcidev;
                                dev->board_ptr = hpdi_boards + i;
                                break;
                        }
@@ -600,25 +528,25 @@ static int hpdi_attach(struct comedi_device *dev, struct comedi_devconfig *it)
        /* Initialize dev->board_name */
        dev->board_name = board(dev)->name;
 
-       priv(dev)->plx9080_phys_iobase =
+       devpriv->plx9080_phys_iobase =
            pci_resource_start(pcidev, PLX9080_BADDRINDEX);
-       priv(dev)->hpdi_phys_iobase =
+       devpriv->hpdi_phys_iobase =
            pci_resource_start(pcidev, HPDI_BADDRINDEX);
 
        /*  remap, won't work with 2.0 kernels but who cares */
-       priv(dev)->plx9080_iobase = ioremap(priv(dev)->plx9080_phys_iobase,
+       devpriv->plx9080_iobase = ioremap(devpriv->plx9080_phys_iobase,
                                            pci_resource_len(pcidev,
                                            PLX9080_BADDRINDEX));
-       priv(dev)->hpdi_iobase =
-           ioremap(priv(dev)->hpdi_phys_iobase,
+       devpriv->hpdi_iobase =
+           ioremap(devpriv->hpdi_phys_iobase,
                    pci_resource_len(pcidev, HPDI_BADDRINDEX));
-       if (!priv(dev)->plx9080_iobase || !priv(dev)->hpdi_iobase) {
+       if (!devpriv->plx9080_iobase || !devpriv->hpdi_iobase) {
                printk(KERN_WARNING " failed to remap io memory\n");
                return -ENOMEM;
        }
 
-       DEBUG_PRINT(" plx9080 remapped to 0x%p\n", priv(dev)->plx9080_iobase);
-       DEBUG_PRINT(" hpdi remapped to 0x%p\n", priv(dev)->hpdi_iobase);
+       DEBUG_PRINT(" plx9080 remapped to 0x%p\n", devpriv->plx9080_iobase);
+       DEBUG_PRINT(" hpdi remapped to 0x%p\n", devpriv->hpdi_iobase);
 
        init_plx9080(dev);
 
@@ -635,20 +563,20 @@ static int hpdi_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 
        /*  allocate pci dma buffers */
        for (i = 0; i < NUM_DMA_BUFFERS; i++) {
-               priv(dev)->dio_buffer[i] =
-                   pci_alloc_consistent(priv(dev)->hw_dev, DMA_BUFFER_SIZE,
-                                        &priv(dev)->dio_buffer_phys_addr[i]);
+               devpriv->dio_buffer[i] =
+                   pci_alloc_consistent(devpriv->hw_dev, DMA_BUFFER_SIZE,
+                                        &devpriv->dio_buffer_phys_addr[i]);
                DEBUG_PRINT("dio_buffer at virt 0x%p, phys 0x%lx\n",
-                           priv(dev)->dio_buffer[i],
-                           (unsigned long)priv(dev)->dio_buffer_phys_addr[i]);
+                           devpriv->dio_buffer[i],
+                           (unsigned long)devpriv->dio_buffer_phys_addr[i]);
        }
        /*  allocate dma descriptors */
-       priv(dev)->dma_desc = pci_alloc_consistent(priv(dev)->hw_dev,
+       devpriv->dma_desc = pci_alloc_consistent(devpriv->hw_dev,
                                                   sizeof(struct plx_dma_desc) *
                                                   NUM_DMA_DESCRIPTORS,
-                                                  &priv(dev)->
+                                                  &devpriv->
                                                   dma_desc_phys_addr);
-       if (priv(dev)->dma_desc_phys_addr & 0xf) {
+       if (devpriv->dma_desc_phys_addr & 0xf) {
                printk(KERN_WARNING
                       " dma descriptors not quad-word aligned (bug)\n");
                return -EIO;
@@ -667,39 +595,36 @@ static int hpdi_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 
 static void hpdi_detach(struct comedi_device *dev)
 {
+       struct hpdi_private *devpriv = dev->private;
        unsigned int i;
 
        if (dev->irq)
                free_irq(dev->irq, dev);
-       if ((priv(dev)) && (priv(dev)->hw_dev)) {
-               if (priv(dev)->plx9080_iobase) {
+       if (devpriv && devpriv->hw_dev) {
+               if (devpriv->plx9080_iobase) {
                        disable_plx_interrupts(dev);
-                       iounmap(priv(dev)->plx9080_iobase);
+                       iounmap(devpriv->plx9080_iobase);
                }
-               if (priv(dev)->hpdi_iobase)
-                       iounmap(priv(dev)->hpdi_iobase);
+               if (devpriv->hpdi_iobase)
+                       iounmap(devpriv->hpdi_iobase);
                /*  free pci dma buffers */
                for (i = 0; i < NUM_DMA_BUFFERS; i++) {
-                       if (priv(dev)->dio_buffer[i])
-                               pci_free_consistent(priv(dev)->hw_dev,
-                                                   DMA_BUFFER_SIZE,
-                                                   priv(dev)->
-                                                   dio_buffer[i],
-                                                   priv
-                                                   (dev)->dio_buffer_phys_addr
-                                                   [i]);
+                       if (devpriv->dio_buffer[i])
+                               pci_free_consistent(devpriv->hw_dev,
+                                       DMA_BUFFER_SIZE,
+                                       devpriv->dio_buffer[i],
+                                       devpriv->dio_buffer_phys_addr[i]);
                }
                /*  free dma descriptors */
-               if (priv(dev)->dma_desc)
-                       pci_free_consistent(priv(dev)->hw_dev,
-                                           sizeof(struct plx_dma_desc)
-                                           * NUM_DMA_DESCRIPTORS,
-                                           priv(dev)->dma_desc,
-                                           priv(dev)->
-                                           dma_desc_phys_addr);
-               if (priv(dev)->hpdi_phys_iobase)
-                       comedi_pci_disable(priv(dev)->hw_dev);
-               pci_dev_put(priv(dev)->hw_dev);
+               if (devpriv->dma_desc)
+                       pci_free_consistent(devpriv->hw_dev,
+                               sizeof(struct plx_dma_desc) *
+                               NUM_DMA_DESCRIPTORS,
+                               devpriv->dma_desc,
+                               devpriv-> dma_desc_phys_addr);
+               if (devpriv->hpdi_phys_iobase)
+                       comedi_pci_disable(devpriv->hw_dev);
+               pci_dev_put(devpriv->hw_dev);
        }
 }
 
@@ -803,7 +728,9 @@ static int di_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
 static int hpdi_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
                         struct comedi_cmd *cmd)
 {
-       if (priv(dev)->dio_config_output)
+       struct hpdi_private *devpriv = dev->private;
+
+       if (devpriv->dio_config_output)
                return -EINVAL;
        else
                return di_cmd_test(dev, s, cmd);
@@ -812,12 +739,15 @@ static int hpdi_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
 static inline void hpdi_writel(struct comedi_device *dev, uint32_t bits,
                               unsigned int offset)
 {
-       writel(bits | priv(dev)->bits[offset / sizeof(uint32_t)],
-              priv(dev)->hpdi_iobase + offset);
+       struct hpdi_private *devpriv = dev->private;
+
+       writel(bits | devpriv->bits[offset / sizeof(uint32_t)],
+              devpriv->hpdi_iobase + offset);
 }
 
 static int di_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+       struct hpdi_private *devpriv = dev->private;
        uint32_t bits;
        unsigned long flags;
        struct comedi_async *async = s->async;
@@ -829,39 +759,39 @@ static int di_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 
        abort_dma(dev, 0);
 
-       priv(dev)->dma_desc_index = 0;
+       devpriv->dma_desc_index = 0;
 
        /* These register are supposedly unused during chained dma,
         * but I have found that left over values from last operation
         * occasionally cause problems with transfer of first dma
         * block.  Initializing them to zero seems to fix the problem. */
-       writel(0, priv(dev)->plx9080_iobase + PLX_DMA0_TRANSFER_SIZE_REG);
-       writel(0, priv(dev)->plx9080_iobase + PLX_DMA0_PCI_ADDRESS_REG);
-       writel(0, priv(dev)->plx9080_iobase + PLX_DMA0_LOCAL_ADDRESS_REG);
+       writel(0, devpriv->plx9080_iobase + PLX_DMA0_TRANSFER_SIZE_REG);
+       writel(0, devpriv->plx9080_iobase + PLX_DMA0_PCI_ADDRESS_REG);
+       writel(0, devpriv->plx9080_iobase + PLX_DMA0_LOCAL_ADDRESS_REG);
        /*  give location of first dma descriptor */
        bits =
-           priv(dev)->dma_desc_phys_addr | PLX_DESC_IN_PCI_BIT |
+           devpriv->dma_desc_phys_addr | PLX_DESC_IN_PCI_BIT |
            PLX_INTR_TERM_COUNT | PLX_XFER_LOCAL_TO_PCI;
-       writel(bits, priv(dev)->plx9080_iobase + PLX_DMA0_DESCRIPTOR_REG);
+       writel(bits, devpriv->plx9080_iobase + PLX_DMA0_DESCRIPTOR_REG);
 
        /*  spinlock for plx dma control/status reg */
        spin_lock_irqsave(&dev->spinlock, flags);
        /*  enable dma transfer */
        writeb(PLX_DMA_EN_BIT | PLX_DMA_START_BIT | PLX_CLEAR_DMA_INTR_BIT,
-              priv(dev)->plx9080_iobase + PLX_DMA0_CS_REG);
+              devpriv->plx9080_iobase + PLX_DMA0_CS_REG);
        spin_unlock_irqrestore(&dev->spinlock, flags);
 
        if (cmd->stop_src == TRIG_COUNT)
-               priv(dev)->dio_count = cmd->stop_arg;
+               devpriv->dio_count = cmd->stop_arg;
        else
-               priv(dev)->dio_count = 1;
+               devpriv->dio_count = 1;
 
        /*  clear over/under run status flags */
        writel(RX_UNDERRUN_BIT | RX_OVERRUN_BIT,
-              priv(dev)->hpdi_iobase + BOARD_STATUS_REG);
+              devpriv->hpdi_iobase + BOARD_STATUS_REG);
        /*  enable interrupts */
        writel(intr_bit(RX_FULL_INTR),
-              priv(dev)->hpdi_iobase + INTERRUPT_CONTROL_REG);
+              devpriv->hpdi_iobase + INTERRUPT_CONTROL_REG);
 
        DEBUG_PRINT("hpdi: starting rx\n");
        hpdi_writel(dev, RX_ENABLE_BIT, BOARD_CONTROL_REG);
@@ -871,7 +801,9 @@ static int di_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 
 static int hpdi_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
-       if (priv(dev)->dio_config_output)
+       struct hpdi_private *devpriv = dev->private;
+
+       if (devpriv->dio_config_output)
                return -EINVAL;
        else
                return di_cmd(dev, s);
@@ -879,6 +811,7 @@ static int hpdi_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 
 static void drain_dma_buffers(struct comedi_device *dev, unsigned int channel)
 {
+       struct hpdi_private *devpriv = dev->private;
        struct comedi_async *async = dev->read_subdev->async;
        uint32_t next_transfer_addr;
        int j;
@@ -887,37 +820,37 @@ static void drain_dma_buffers(struct comedi_device *dev, unsigned int channel)
 
        if (channel)
                pci_addr_reg =
-                   priv(dev)->plx9080_iobase + PLX_DMA1_PCI_ADDRESS_REG;
+                   devpriv->plx9080_iobase + PLX_DMA1_PCI_ADDRESS_REG;
        else
                pci_addr_reg =
-                   priv(dev)->plx9080_iobase + PLX_DMA0_PCI_ADDRESS_REG;
+                   devpriv->plx9080_iobase + PLX_DMA0_PCI_ADDRESS_REG;
 
        /*  loop until we have read all the full buffers */
        j = 0;
        for (next_transfer_addr = readl(pci_addr_reg);
             (next_transfer_addr <
-             le32_to_cpu(priv(dev)->dma_desc[priv(dev)->dma_desc_index].
+             le32_to_cpu(devpriv->dma_desc[devpriv->dma_desc_index].
                          pci_start_addr)
              || next_transfer_addr >=
-             le32_to_cpu(priv(dev)->dma_desc[priv(dev)->dma_desc_index].
-                         pci_start_addr) + priv(dev)->block_size)
-            && j < priv(dev)->num_dma_descriptors; j++) {
+             le32_to_cpu(devpriv->dma_desc[devpriv->dma_desc_index].
+                         pci_start_addr) + devpriv->block_size)
+            && j < devpriv->num_dma_descriptors; j++) {
                /*  transfer data from dma buffer to comedi buffer */
-               num_samples = priv(dev)->block_size / sizeof(uint32_t);
+               num_samples = devpriv->block_size / sizeof(uint32_t);
                if (async->cmd.stop_src == TRIG_COUNT) {
-                       if (num_samples > priv(dev)->dio_count)
-                               num_samples = priv(dev)->dio_count;
-                       priv(dev)->dio_count -= num_samples;
+                       if (num_samples > devpriv->dio_count)
+                               num_samples = devpriv->dio_count;
+                       devpriv->dio_count -= num_samples;
                }
                cfc_write_array_to_buffer(dev->read_subdev,
-                                         priv(dev)->desc_dio_buffer[priv(dev)->
+                                         devpriv->desc_dio_buffer[devpriv->
                                                                     dma_desc_index],
                                          num_samples * sizeof(uint32_t));
-               priv(dev)->dma_desc_index++;
-               priv(dev)->dma_desc_index %= priv(dev)->num_dma_descriptors;
+               devpriv->dma_desc_index++;
+               devpriv->dma_desc_index %= devpriv->num_dma_descriptors;
 
                DEBUG_PRINT("next desc addr 0x%lx\n", (unsigned long)
-                           priv(dev)->dma_desc[priv(dev)->dma_desc_index].
+                           devpriv->dma_desc[devpriv->dma_desc_index].
                            next);
                DEBUG_PRINT("pci addr reg 0x%x\n", next_transfer_addr);
        }
@@ -927,6 +860,7 @@ static void drain_dma_buffers(struct comedi_device *dev, unsigned int channel)
 static irqreturn_t handle_interrupt(int irq, void *d)
 {
        struct comedi_device *dev = d;
+       struct hpdi_private *devpriv = dev->private;
        struct comedi_subdevice *s = dev->read_subdev;
        struct comedi_async *async = s->async;
        uint32_t hpdi_intr_status, hpdi_board_status;
@@ -938,26 +872,26 @@ static irqreturn_t handle_interrupt(int irq, void *d)
        if (!dev->attached)
                return IRQ_NONE;
 
-       plx_status = readl(priv(dev)->plx9080_iobase + PLX_INTRCS_REG);
+       plx_status = readl(devpriv->plx9080_iobase + PLX_INTRCS_REG);
        if ((plx_status & (ICS_DMA0_A | ICS_DMA1_A | ICS_LIA)) == 0)
                return IRQ_NONE;
 
-       hpdi_intr_status = readl(priv(dev)->hpdi_iobase + INTERRUPT_STATUS_REG);
-       hpdi_board_status = readl(priv(dev)->hpdi_iobase + BOARD_STATUS_REG);
+       hpdi_intr_status = readl(devpriv->hpdi_iobase + INTERRUPT_STATUS_REG);
+       hpdi_board_status = readl(devpriv->hpdi_iobase + BOARD_STATUS_REG);
 
        async->events = 0;
 
        if (hpdi_intr_status) {
                DEBUG_PRINT("hpdi: intr status 0x%x, ", hpdi_intr_status);
                writel(hpdi_intr_status,
-                      priv(dev)->hpdi_iobase + INTERRUPT_STATUS_REG);
+                      devpriv->hpdi_iobase + INTERRUPT_STATUS_REG);
        }
        /*  spin lock makes sure no one else changes plx dma control reg */
        spin_lock_irqsave(&dev->spinlock, flags);
-       dma0_status = readb(priv(dev)->plx9080_iobase + PLX_DMA0_CS_REG);
+       dma0_status = readb(devpriv->plx9080_iobase + PLX_DMA0_CS_REG);
        if (plx_status & ICS_DMA0_A) {  /*  dma chan 0 interrupt */
                writeb((dma0_status & PLX_DMA_EN_BIT) | PLX_CLEAR_DMA_INTR_BIT,
-                      priv(dev)->plx9080_iobase + PLX_DMA0_CS_REG);
+                      devpriv->plx9080_iobase + PLX_DMA0_CS_REG);
 
                DEBUG_PRINT("dma0 status 0x%x\n", dma0_status);
                if (dma0_status & PLX_DMA_EN_BIT)
@@ -968,10 +902,10 @@ static irqreturn_t handle_interrupt(int irq, void *d)
 
        /*  spin lock makes sure no one else changes plx dma control reg */
        spin_lock_irqsave(&dev->spinlock, flags);
-       dma1_status = readb(priv(dev)->plx9080_iobase + PLX_DMA1_CS_REG);
+       dma1_status = readb(devpriv->plx9080_iobase + PLX_DMA1_CS_REG);
        if (plx_status & ICS_DMA1_A) {  /*  XXX *//*  dma chan 1 interrupt */
                writeb((dma1_status & PLX_DMA_EN_BIT) | PLX_CLEAR_DMA_INTR_BIT,
-                      priv(dev)->plx9080_iobase + PLX_DMA1_CS_REG);
+                      devpriv->plx9080_iobase + PLX_DMA1_CS_REG);
                DEBUG_PRINT("dma1 status 0x%x\n", dma1_status);
 
                DEBUG_PRINT(" cleared dma ch1 interrupt\n");
@@ -980,8 +914,8 @@ static irqreturn_t handle_interrupt(int irq, void *d)
 
        /*  clear possible plx9080 interrupt sources */
        if (plx_status & ICS_LDIA) {    /*  clear local doorbell interrupt */
-               plx_bits = readl(priv(dev)->plx9080_iobase + PLX_DBR_OUT_REG);
-               writel(plx_bits, priv(dev)->plx9080_iobase + PLX_DBR_OUT_REG);
+               plx_bits = readl(devpriv->plx9080_iobase + PLX_DBR_OUT_REG);
+               writel(plx_bits, devpriv->plx9080_iobase + PLX_DBR_OUT_REG);
                DEBUG_PRINT(" cleared local doorbell bits 0x%x\n", plx_bits);
        }
 
@@ -989,7 +923,7 @@ static irqreturn_t handle_interrupt(int irq, void *d)
                comedi_error(dev, "rx fifo overrun");
                async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
                DEBUG_PRINT("dma0_status 0x%x\n",
-                           (int)readb(priv(dev)->plx9080_iobase +
+                           (int)readb(devpriv->plx9080_iobase +
                                       PLX_DMA0_CS_REG));
        }
 
@@ -998,7 +932,7 @@ static irqreturn_t handle_interrupt(int irq, void *d)
                async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
        }
 
-       if (priv(dev)->dio_count == 0)
+       if (devpriv->dio_count == 0)
                async->events |= COMEDI_CB_EOA;
 
        DEBUG_PRINT("board status 0x%x, ", hpdi_board_status);
@@ -1013,21 +947,24 @@ static irqreturn_t handle_interrupt(int irq, void *d)
 
 static void abort_dma(struct comedi_device *dev, unsigned int channel)
 {
+       struct hpdi_private *devpriv = dev->private;
        unsigned long flags;
 
        /*  spinlock for plx dma control/status reg */
        spin_lock_irqsave(&dev->spinlock, flags);
 
-       plx9080_abort_dma(priv(dev)->plx9080_iobase, channel);
+       plx9080_abort_dma(devpriv->plx9080_iobase, channel);
 
        spin_unlock_irqrestore(&dev->spinlock, flags);
 }
 
 static int hpdi_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+       struct hpdi_private *devpriv = dev->private;
+
        hpdi_writel(dev, 0, BOARD_CONTROL_REG);
 
-       writel(0, priv(dev)->hpdi_iobase + INTERRUPT_CONTROL_REG);
+       writel(0, devpriv->hpdi_iobase + INTERRUPT_CONTROL_REG);
 
        abort_dma(dev, 0);
 
index d696d4d51e2804bf8bea37cad76c814c663dc5de..51af903773e296978c0966b810121e5a9ace2a11 100644 (file)
@@ -502,13 +502,12 @@ static int icp_multi_attach_pci(struct comedi_device *dev,
        resource_size_t iobase;
        int ret;
 
-       comedi_set_hw_dev(dev, &pcidev->dev);
        dev->board_name = dev->driver->driver_name;
 
-       ret = alloc_private(dev, sizeof(*devpriv));
-       if (ret < 0)
-               return ret;
-       devpriv = dev->private;
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
+               return -ENOMEM;
+       dev->private = devpriv;
 
        ret = comedi_pci_enable(pcidev, dev->board_name);
        if (ret)
index 65ff1c9b973c1acd7ca9965463f0c23ae3a307f7..93584e2be35a50c8e97dbfec2a494e33e60cddae 100644 (file)
@@ -156,7 +156,6 @@ struct pci20xxx_private {
        union pci20xxx_subdev_private subdev_private[PCI20000_MODULES];
 };
 
-#define devpriv ((struct pci20xxx_private *)dev->private)
 #define CHAN (CR_CHAN(it->chanlist[0]))
 
 static int pci20006_init(struct comedi_device *dev, struct comedi_subdevice *s,
@@ -196,6 +195,7 @@ static int pci20xxx_dio_init(struct comedi_device *dev,
 static int pci20xxx_attach(struct comedi_device *dev,
                           struct comedi_devconfig *it)
 {
+       struct pci20xxx_private *devpriv;
        unsigned char i;
        int ret;
        int id;
@@ -206,22 +206,23 @@ static int pci20xxx_attach(struct comedi_device *dev,
        if (ret)
                return ret;
 
-       ret = alloc_private(dev, sizeof(struct pci20xxx_private));
-       if (ret < 0)
-               return ret;
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
+               return -ENOMEM;
+       dev->private = devpriv;
 
        devpriv->ioaddr = (void __iomem *)(unsigned long)it->options[0];
        dev->board_name = "pci20kc";
 
        /* Check PCI-20001 C-2A Carrier Board ID */
        if ((readb(devpriv->ioaddr) & PCI20000_ID) != PCI20000_ID) {
-               printk(KERN_WARNING "comedi%d: ii_pci20kc PCI-20001"
-                      " C-2A Carrier Board at base=0x%p not found !\n",
-                      dev->minor, devpriv->ioaddr);
+               dev_warn(dev->class_dev,
+                        "PCI-20001 C-2A Carrier Board at base=0x%p not found !\n",
+                        devpriv->ioaddr);
                return -EINVAL;
        }
-       printk(KERN_INFO "comedi%d: ii_pci20kc: PCI-20001 C-2A at base=0x%p\n",
-              dev->minor, devpriv->ioaddr);
+       dev_info(dev->class_dev, "PCI-20001 C-2A at base=0x%p\n",
+                devpriv->ioaddr);
 
        for (i = 0; i < PCI20000_MODULES; i++) {
                s = &dev->subdevices[i];
@@ -234,23 +235,21 @@ static int pci20xxx_attach(struct comedi_device *dev,
                            devpriv->ioaddr + (i + 1) * PCI20000_OFFSET;
                        pci20006_init(dev, s, it->options[2 * i + 2],
                                      it->options[2 * i + 3]);
-                       printk(KERN_INFO "comedi%d: "
-                              "ii_pci20kc PCI-20006 module in slot %d\n",
-                              dev->minor, i + 1);
+                       dev_info(dev->class_dev,
+                                "PCI-20006 module in slot %d\n", i + 1);
                        break;
                case PCI20341_ID:
                        sdp->pci20341.iobase =
                            devpriv->ioaddr + (i + 1) * PCI20000_OFFSET;
                        pci20341_init(dev, s, it->options[2 * i + 2],
                                      it->options[2 * i + 3]);
-                       printk(KERN_INFO "comedi%d: "
-                              "ii_pci20kc PCI-20341 module in slot %d\n",
-                              dev->minor, i + 1);
+                       dev_info(dev->class_dev,
+                                "PCI-20341 module in slot %d\n", i + 1);
                        break;
                default:
-                       printk(KERN_WARNING "ii_pci20kc: unknown module "
-                              "code 0x%02x in slot %d: module disabled\n",
-                              id, i); /* XXX this looks like a bug! i + 1 ?? */
+                       dev_warn(dev->class_dev,
+                                "unknown module code 0x%02x in slot %d: module disabled\n",
+                                id, i); /* XXX this looks like a bug! i + 1 ?? */
                        /* fall through */
                case PCI20xxx_EMPTY_ID:
                        s->type = COMEDI_SUBD_UNUSED;
@@ -346,8 +345,7 @@ static int pci20006_insn_write(struct comedi_device *dev,
                writeb(0x00, sdp->iobase + PCI20006_STROBE1);
                break;
        default:
-               printk(KERN_WARNING
-                      " comedi%d: pci20xxx: ao channel Error!\n", dev->minor);
+               dev_warn(dev->class_dev, "ao channel Error!\n");
                return -EINVAL;
        }
 
@@ -462,10 +460,8 @@ static int pci20341_insn_read(struct comedi_device *dev,
                        eoc = readb(sdp->iobase + PCI20341_STATUS_REG);
                }
                if (j >= 100) {
-                       printk(KERN_WARNING
-                              "comedi%d:  pci20xxx: "
-                              "AI interrupt channel %i polling exit !\n",
-                              dev->minor, i);
+                       dev_warn(dev->class_dev,
+                                "AI interrupt channel %i polling exit !\n", i);
                        return -EINVAL;
                }
                lo = readb(sdp->iobase + PCI20341_LDATA);
@@ -541,6 +537,7 @@ static int pci20xxx_dio_insn_bits(struct comedi_device *dev,
                                  struct comedi_subdevice *s,
                                  struct comedi_insn *insn, unsigned int *data)
 {
+       struct pci20xxx_private *devpriv = dev->private;
        unsigned int mask = data[0];
 
        s->state &= ~mask;
@@ -571,6 +568,7 @@ static int pci20xxx_dio_insn_bits(struct comedi_device *dev,
 static void pci20xxx_dio_config(struct comedi_device *dev,
                                struct comedi_subdevice *s)
 {
+       struct pci20xxx_private *devpriv = dev->private;
        unsigned char control_01;
        unsigned char control_23;
        unsigned char buffer;
@@ -627,6 +625,8 @@ static void pci20xxx_dio_config(struct comedi_device *dev,
 #if 0
 static void pci20xxx_do(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+       struct pci20xxx_private *devpriv = dev->private;
+
        /* XXX if the channel is configured for input, does this
           do bad things? */
        /* XXX it would be a good idea to only update the registers
@@ -641,9 +641,10 @@ static void pci20xxx_do(struct comedi_device *dev, struct comedi_subdevice *s)
 static unsigned int pci20xxx_di(struct comedi_device *dev,
                                struct comedi_subdevice *s)
 {
-       /* XXX same note as above */
+       struct pci20xxx_private *devpriv = dev->private;
        unsigned int bits;
 
+       /* XXX same note as above */
        bits = readb(devpriv->ioaddr + PCI20000_DIO_0);
        bits |= readb(devpriv->ioaddr + PCI20000_DIO_1) << 8;
        bits |= readb(devpriv->ioaddr + PCI20000_DIO_2) << 16;
index 4a108ea8a9aa15caf44ff4a48a349c1b2a321cbb..68400f13af0e08ae8fa35fc0fc078ec06f6705d5 100644 (file)
@@ -62,7 +62,7 @@ struct jr3_pci_dev_private {
 
        struct pci_dev *pci_dev;
        int pci_enabled;
-       volatile struct jr3_t *iobase;
+       struct jr3_t __iomem *iobase;
        int n_channels;
        struct timer_list timer;
 };
@@ -74,7 +74,7 @@ struct poll_delay_t {
 };
 
 struct jr3_pci_subdev_private {
-       volatile struct jr3_channel *channel;
+       struct jr3_channel __iomem *channel;
        unsigned long next_time_min;
        unsigned long next_time_max;
        enum { state_jr3_poll,
@@ -138,7 +138,7 @@ static struct poll_delay_t poll_delay_min_max(int min, int max)
        return result;
 }
 
-static int is_complete(volatile struct jr3_channel *channel)
+static int is_complete(struct jr3_channel __iomem *channel)
 {
        return get_s16(&channel->command_word0) == 0;
 }
@@ -150,7 +150,7 @@ struct transform_t {
        } link[8];
 };
 
-static void set_transforms(volatile struct jr3_channel *channel,
+static void set_transforms(struct jr3_channel __iomem *channel,
                           struct transform_t transf, short num)
 {
        int i;
@@ -169,18 +169,18 @@ static void set_transforms(volatile struct jr3_channel *channel,
        }
 }
 
-static void use_transform(volatile struct jr3_channel *channel,
+static void use_transform(struct jr3_channel __iomem *channel,
                          short transf_num)
 {
        set_s16(&channel->command_word0, 0x0500 + (transf_num & 0x000f));
 }
 
-static void use_offset(volatile struct jr3_channel *channel, short offset_num)
+static void use_offset(struct jr3_channel __iomem *channel, short offset_num)
 {
        set_s16(&channel->command_word0, 0x0600 + (offset_num & 0x000f));
 }
 
-static void set_offset(volatile struct jr3_channel *channel)
+static void set_offset(struct jr3_channel __iomem *channel)
 {
        set_s16(&channel->command_word0, 0x0700);
 }
@@ -194,7 +194,7 @@ struct six_axis_t {
        s16 mz;
 };
 
-static void set_full_scales(volatile struct jr3_channel *channel,
+static void set_full_scales(struct jr3_channel __iomem *channel,
                            struct six_axis_t full_scale)
 {
        printk("%d %d %d %d %d %d\n",
@@ -210,7 +210,7 @@ static void set_full_scales(volatile struct jr3_channel *channel,
        set_s16(&channel->command_word0, 0x0a00);
 }
 
-static struct six_axis_t get_min_full_scales(volatile struct jr3_channel
+static struct six_axis_t get_min_full_scales(struct jr3_channel __iomem
                                             *channel)
 {
        struct six_axis_t result;
@@ -223,7 +223,7 @@ static struct six_axis_t get_min_full_scales(volatile struct jr3_channel
        return result;
 }
 
-static struct six_axis_t get_max_full_scales(volatile struct jr3_channel
+static struct six_axis_t get_max_full_scales(struct jr3_channel __iomem
                                             *channel)
 {
        struct six_axis_t result;
@@ -492,7 +492,7 @@ static struct poll_delay_t jr3_pci_poll_subdevice(struct comedi_subdevice *s)
        int i;
 
        if (p) {
-               volatile struct jr3_channel *channel = p->channel;
+               struct jr3_channel __iomem *channel = p->channel;
                int errors = get_u16(&channel->errors);
 
                if (errors != p->errors) {
@@ -607,7 +607,7 @@ static struct poll_delay_t jr3_pci_poll_subdevice(struct comedi_subdevice *s)
                                             is_complete(channel));
                                        result = poll_delay_min_max(20, 100);
                                } else {
-                                       volatile struct force_array *full_scale;
+                                       struct force_array __iomem *full_scale;
 
                                        /*  Use ranges in kN or we will overflow arount 2000N! */
                                        full_scale = &channel->full_scale;
@@ -762,11 +762,12 @@ static int jr3_pci_attach(struct comedi_device *dev,
                return -EINVAL;
        }
 
-       result = alloc_private(dev, sizeof(struct jr3_pci_dev_private));
-       if (result < 0)
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
                return -ENOMEM;
+       dev->private = devpriv;
+
        card = NULL;
-       devpriv = dev->private;
        init_timer(&devpriv->timer);
        while (1) {
                card = pci_get_device(PCI_VENDOR_ID_JR3, PCI_ANY_ID, card);
@@ -849,8 +850,8 @@ static int jr3_pci_attach(struct comedi_device *dev,
                        p->channel = &devpriv->iobase->channel[i].data;
                        dev_dbg(dev->class_dev, "p->channel %p %p (%tx)\n",
                                p->channel, devpriv->iobase,
-                               ((char *)(p->channel) -
-                                (char *)(devpriv->iobase)));
+                               ((char __iomem *)p->channel -
+                                (char __iomem *)devpriv->iobase));
                        p->channel_no = i;
                        for (j = 0; j < 8; j++) {
                                int k;
@@ -941,7 +942,7 @@ static void jr3_pci_detach(struct comedi_device *dev)
                                kfree(dev->subdevices[i].private);
                }
                if (devpriv->iobase)
-                       iounmap((void *)devpriv->iobase);
+                       iounmap(devpriv->iobase);
                if (devpriv->pci_enabled)
                        comedi_pci_disable(devpriv->pci_dev);
                if (devpriv->pci_dev)
index 9c42653d8f18f4c0f724d767e57883623930ae90..3317f7a04c480418c51bd2491b6a9e24a4564c8c 100644 (file)
@@ -2,22 +2,22 @@
  * is 16 bits, but aligned on a 32 bit PCI boundary
  */
 
-static inline u16 get_u16(volatile const u32 * p)
+static inline u16 get_u16(const u32 __iomem *p)
 {
-       return (u16) readl(p);
+       return (u16)readl(p);
 }
 
-static inline void set_u16(volatile u32 * p, u16 val)
+static inline void set_u16(u32 __iomem *p, u16 val)
 {
        writel(val, p);
 }
 
-static inline s16 get_s16(volatile const s32 * p)
+static inline s16 get_s16(const s32 __iomem *p)
 {
-       return (s16) readl(p);
+       return (s16)readl(p);
 }
 
-static inline void set_s16(volatile s32 * p, s16 val)
+static inline void set_s16(s32 __iomem *p, s16 val)
 {
        writel(val, p);
 }
index e867b720f666697f44e78450e1550afdd682e4e6..355af553ed53f5159e20da37a1b46b5ff5be3ab9 100644 (file)
@@ -36,28 +36,9 @@ Kolter Electronic PCI Counter Card.
 
 #include "../comedidev.h"
 
-#define CNT_DRIVER_NAME         "ke_counter"
 #define PCI_VENDOR_ID_KOLTER    0x1001
 #define CNT_CARD_DEVICE_ID      0x0014
 
-/*-- board specification structure ------------------------------------------*/
-
-struct cnt_board_struct {
-
-       const char *name;
-       int device_id;
-       int cnt_channel_nbr;
-       int cnt_bits;
-};
-
-static const struct cnt_board_struct cnt_boards[] = {
-       {
-        .name = CNT_DRIVER_NAME,
-        .device_id = CNT_CARD_DEVICE_ID,
-        .cnt_channel_nbr = 3,
-        .cnt_bits = 24}
-};
-
 /*-- counter write ----------------------------------------------------------*/
 
 /* This should be used only for resetting the counters; maybe it is better
@@ -107,34 +88,13 @@ static int cnt_rinsn(struct comedi_device *dev,
        return 1;
 }
 
-static const void *cnt_find_boardinfo(struct comedi_device *dev,
-                                     struct pci_dev *pcidev)
-{
-       const struct cnt_board_struct *board;
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(cnt_boards); i++) {
-               board = &cnt_boards[i];
-               if (board->device_id == pcidev->device)
-                       return board;
-       }
-       return NULL;
-}
-
 static int cnt_attach_pci(struct comedi_device *dev,
                          struct pci_dev *pcidev)
 {
-       const struct cnt_board_struct *board;
        struct comedi_subdevice *s;
        int ret;
 
-       comedi_set_hw_dev(dev, &pcidev->dev);
-
-       board = cnt_find_boardinfo(dev, pcidev);
-       if (!board)
-               return -ENODEV;
-       dev->board_ptr = board;
-       dev->board_name = board->name;
+       dev->board_name = dev->driver->driver_name;
 
        ret = comedi_pci_enable(pcidev, dev->board_name);
        if (ret)
@@ -150,8 +110,8 @@ static int cnt_attach_pci(struct comedi_device *dev,
 
        s->type = COMEDI_SUBD_COUNTER;
        s->subdev_flags = SDF_READABLE /* | SDF_COMMON */ ;
-       s->n_chan = board->cnt_channel_nbr;
-       s->maxdata = (1 << board->cnt_bits) - 1;
+       s->n_chan = 3;
+       s->maxdata = 0x00ffffff;
        s->insn_read = cnt_rinsn;
        s->insn_write = cnt_winsn;
 
index 22db35d091f89e600d9853e96ada2799e3314fa1..ba7fd9d53d1955c88062fbbf7b1e5a03854fef0d 100644 (file)
@@ -1578,18 +1578,16 @@ static int me4000_attach_pci(struct comedi_device *dev,
        struct comedi_subdevice *s;
        int result;
 
-       comedi_set_hw_dev(dev, &pcidev->dev);
-
        thisboard = me4000_find_boardinfo(dev, pcidev);
        if (!thisboard)
                return -ENODEV;
        dev->board_ptr = thisboard;
        dev->board_name = thisboard->name;
 
-       result = alloc_private(dev, sizeof(*info));
-       if (result)
-               return result;
-       info = dev->private;
+       info = kzalloc(sizeof(*info), GFP_KERNEL);
+       if (!info)
+               return -ENOMEM;
+       dev->private = info;
 
        result = comedi_pci_enable(pcidev, dev->board_name);
        if (result)
index 2ce0b14af589ccca2d4eb5d7417a2a7b2734960b..271db1cb6070868f21fa43c61202ecb163a7848f 100644 (file)
@@ -234,8 +234,6 @@ struct me_private_data {
        int ao_readback[4];     /* Mirror of analog output data */
 };
 
-#define dev_private ((struct me_private_data *)dev->private)
-
 /*
  * ------------------------------------------------------------------
  *
@@ -260,6 +258,7 @@ static int me_dio_insn_config(struct comedi_device *dev,
                              struct comedi_subdevice *s,
                              struct comedi_insn *insn, unsigned int *data)
 {
+       struct me_private_data *dev_private = dev->private;
        int bits;
        int mask = 1 << CR_CHAN(insn->chanspec);
 
@@ -297,7 +296,9 @@ static int me_dio_insn_bits(struct comedi_device *dev,
                            struct comedi_subdevice *s,
                            struct comedi_insn *insn, unsigned int *data)
 {
+       struct me_private_data *dev_private = dev->private;
        unsigned int mask = data[0];
+
        s->state &= ~mask;
        s->state |= (mask & data[1]);
 
@@ -334,6 +335,7 @@ static int me_ai_insn_read(struct comedi_device *dev,
                           struct comedi_subdevice *s,
                           struct comedi_insn *insn, unsigned int *data)
 {
+       struct me_private_data *dev_private = dev->private;
        unsigned short value;
        int chan = CR_CHAN((&insn->chanspec)[0]);
        int rang = CR_RANGE((&insn->chanspec)[0]);
@@ -384,8 +386,7 @@ static int me_ai_insn_read(struct comedi_device *dev,
                    (readw(dev_private->me_regbase +
                           ME_READ_AD_FIFO) ^ 0x800) & 0x0FFF;
        } else {
-               printk(KERN_ERR "comedi%d: Cannot get single value\n",
-                      dev->minor);
+               dev_err(dev->class_dev, "Cannot get single value\n");
                return -EIO;
        }
 
@@ -407,6 +408,8 @@ static int me_ai_insn_read(struct comedi_device *dev,
 /* Cancel analog input autoscan */
 static int me_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+       struct me_private_data *dev_private = dev->private;
+
        /* disable interrupts */
 
        /* stop any running conversion */
@@ -443,6 +446,7 @@ static int me_ao_insn_write(struct comedi_device *dev,
                            struct comedi_subdevice *s,
                            struct comedi_insn *insn, unsigned int *data)
 {
+       struct me_private_data *dev_private = dev->private;
        int chan;
        int rang;
        int i;
@@ -494,6 +498,7 @@ static int me_ao_insn_read(struct comedi_device *dev,
                           struct comedi_subdevice *s, struct comedi_insn *insn,
                           unsigned int *data)
 {
+       struct me_private_data *dev_private = dev->private;
        int i;
 
        for (i = 0; i < insn->n; i++) {
@@ -516,6 +521,7 @@ static int me_ao_insn_read(struct comedi_device *dev,
 static int me2600_xilinx_download(struct comedi_device *dev,
                                  const u8 *data, size_t size)
 {
+       struct me_private_data *dev_private = dev->private;
        unsigned int value;
        unsigned int file_length;
        unsigned int i;
@@ -566,8 +572,7 @@ static int me2600_xilinx_download(struct comedi_device *dev,
        if (value & 0x20) {
                /* Disable interrupt */
                writel(0x00, dev_private->plx_regbase + PLX_INTCSR);
-               printk(KERN_ERR "comedi%d: Xilinx download failed\n",
-                      dev->minor);
+               dev_err(dev->class_dev, "Xilinx download failed\n");
                return -EIO;
        }
 
@@ -599,6 +604,8 @@ static int me2600_upload_firmware(struct comedi_device *dev)
 /* Reset device */
 static int me_reset(struct comedi_device *dev)
 {
+       struct me_private_data *dev_private = dev->private;
+
        /* Reset board */
        writew(0x00, dev_private->me_regbase + ME_CONTROL_1);
        writew(0x00, dev_private->me_regbase + ME_CONTROL_2);
@@ -630,6 +637,7 @@ static const void *me_find_boardinfo(struct comedi_device *dev,
 static int me_attach_pci(struct comedi_device *dev, struct pci_dev *pcidev)
 {
        const struct me_board *board;
+       struct me_private_data *dev_private;
        struct comedi_subdevice *s;
        resource_size_t plx_regbase_tmp;
        unsigned long plx_regbase_size_tmp;
@@ -640,22 +648,21 @@ static int me_attach_pci(struct comedi_device *dev, struct pci_dev *pcidev)
        resource_size_t regbase_tmp;
        int result, error;
 
-       comedi_set_hw_dev(dev, &pcidev->dev);
-
        board = me_find_boardinfo(dev, pcidev);
        if (!board)
                return -ENODEV;
        dev->board_ptr = board;
        dev->board_name = board->name;
 
-       /* Allocate private memory */
-       if (alloc_private(dev, sizeof(struct me_private_data)) < 0)
+       dev_private = kzalloc(sizeof(*dev_private), GFP_KERNEL);
+       if (!dev_private)
                return -ENOMEM;
+       dev->private = dev_private;
 
        /* Enable PCI device and request PCI regions */
        if (comedi_pci_enable(pcidev, dev->board_name) < 0) {
-               printk(KERN_ERR "comedi%d: Failed to enable PCI device and "
-                      "request regions\n", dev->minor);
+               dev_err(dev->class_dev,
+                       "Failed to enable PCI device and request regions\n");
                return -EIO;
        }
 
@@ -666,7 +673,7 @@ static int me_attach_pci(struct comedi_device *dev, struct pci_dev *pcidev)
            ioremap(plx_regbase_tmp, plx_regbase_size_tmp);
        dev_private->plx_regbase_size = plx_regbase_size_tmp;
        if (!dev_private->plx_regbase) {
-               printk("comedi%d: Failed to remap I/O memory\n", dev->minor);
+               dev_err(dev->class_dev, "Failed to remap I/O memory\n");
                return -ENOMEM;
        }
 
@@ -676,11 +683,11 @@ static int me_attach_pci(struct comedi_device *dev, struct pci_dev *pcidev)
        swap_regbase_size_tmp = pci_resource_len(pcidev, 5);
 
        if (!swap_regbase_tmp)
-               printk(KERN_ERR "comedi%d: Swap not present\n", dev->minor);
+               dev_err(dev->class_dev, "Swap not present\n");
 
        /*---------------------------------------------- Workaround start ---*/
        if (plx_regbase_tmp & 0x0080) {
-               printk(KERN_ERR "comedi%d: PLX-Bug detected\n", dev->minor);
+               dev_err(dev->class_dev, "PLX-Bug detected\n");
 
                if (swap_regbase_tmp) {
                        regbase_tmp = plx_regbase_tmp;
@@ -716,8 +723,7 @@ static int me_attach_pci(struct comedi_device *dev, struct pci_dev *pcidev)
        dev_private->me_regbase_size = me_regbase_size_tmp;
        dev_private->me_regbase = ioremap(me_regbase_tmp, me_regbase_size_tmp);
        if (!dev_private->me_regbase) {
-               printk(KERN_ERR "comedi%d: Failed to remap I/O memory\n",
-                      dev->minor);
+               dev_err(dev->class_dev, "Failed to remap I/O memory\n");
                return -ENOMEM;
        }
 
@@ -775,6 +781,7 @@ static int me_attach_pci(struct comedi_device *dev, struct pci_dev *pcidev)
 static void me_detach(struct comedi_device *dev)
 {
        struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+       struct me_private_data *dev_private = dev->private;
 
        if (dev_private) {
                if (dev_private->me_regbase) {
index f8b7faefc961160de4e3054425300a515dc3c37b..67dc5ad81b0d883334c6ad51d479bfa749e87895 100644 (file)
@@ -122,13 +122,12 @@ Configuration Options:
 #define MPC624_SPEED_6_875_Hz \
        (MPC624_OSR4 | MPC624_OSR3 | MPC624_OSR2 | MPC624_OSR1 | MPC624_OSR0)
 /* -------------------------------------------------------------------------- */
-struct skel_private {
+struct mpc624_private {
 
        /*  set by mpc624_attach() from driver's parameters */
        unsigned long int ulConvertionRate;
 };
 
-#define devpriv ((struct skel_private *)dev->private)
 /* -------------------------------------------------------------------------- */
 static const struct comedi_lrange range_mpc624_bipolar1 = {
        1,
@@ -155,6 +154,7 @@ static int mpc624_ai_rinsn(struct comedi_device *dev,
                           struct comedi_subdevice *s, struct comedi_insn *insn,
                           unsigned int *data)
 {
+       struct mpc624_private *devpriv = dev->private;
        int n, i;
        unsigned long int data_in, data_out;
        unsigned char ucPort;
@@ -283,6 +283,7 @@ static int mpc624_ai_rinsn(struct comedi_device *dev,
 
 static int mpc624_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
+       struct mpc624_private *devpriv;
        struct comedi_subdevice *s;
        unsigned long iobase;
        int ret;
@@ -297,9 +298,10 @@ static int mpc624_attach(struct comedi_device *dev, struct comedi_devconfig *it)
        dev->iobase = iobase;
        dev->board_name = "mpc624";
 
-       /*  Private structure initialization */
-       if (alloc_private(dev, sizeof(struct skel_private)) < 0)
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
                return -ENOMEM;
+       dev->private = devpriv;
 
        switch (it->options[1]) {
        case 0:
diff --git a/drivers/staging/comedi/drivers/mpc8260cpm.c b/drivers/staging/comedi/drivers/mpc8260cpm.c
deleted file mode 100644 (file)
index c0c3329..0000000
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
-    comedi/drivers/mpc8260.c
-    driver for digital I/O pins on the MPC 8260 CPM module
-
-    COMEDI - Linux Control and Measurement Device Interface
-    Copyright (C) 2000,2001 David A. Schleef <ds@schleef.org>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-/*
-Driver: mpc8260cpm
-Description: MPC8260 CPM module generic digital I/O lines
-Devices: [Motorola] MPC8260 CPM (mpc8260cpm)
-Author: ds
-Status: experimental
-Updated: Sat, 16 Mar 2002 17:34:48 -0800
-
-This driver is specific to the Motorola MPC8260 processor, allowing
-you to access the processor's generic digital I/O lines.
-
-It is apparently missing some code.
-*/
-
-#include "../comedidev.h"
-
-extern unsigned long mpc8260_dio_reserved[4];
-
-struct mpc8260cpm_private {
-
-       int data;
-
-};
-
-#define devpriv ((struct mpc8260cpm_private *)dev->private)
-
-static unsigned long *cpm_pdat(int port)
-{
-       switch (port) {
-       case 0:
-               return &io->iop_pdata;
-       case 1:
-               return &io->iop_pdatb;
-       case 2:
-               return &io->iop_pdatc;
-       case 3:
-               return &io->iop_pdatd;
-       }
-}
-
-static int mpc8260cpm_dio_config(struct comedi_device *dev,
-                                struct comedi_subdevice *s,
-                                struct comedi_insn *insn, unsigned int *data)
-{
-       int n;
-       unsigned int d;
-       unsigned int mask;
-       int port;
-
-       port = (int)s->private;
-       mask = 1 << CR_CHAN(insn->chanspec);
-       if (mask & cpm_reserved_bits[port]) {
-               return -EINVAL;
-       }
-
-       switch (data[0]) {
-       case INSN_CONFIG_DIO_OUTPUT:
-               s->io_bits |= mask;
-               break;
-       case INSN_CONFIG_DIO_INPUT:
-               s->io_bits &= ~mask;
-               break;
-       case INSN_CONFIG_DIO_QUERY:
-               data[1] = (s->io_bits & mask) ? COMEDI_OUTPUT : COMEDI_INPUT;
-               return insn->n;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       switch (port) {
-       case 0:
-               return &io->iop_pdira;
-       case 1:
-               return &io->iop_pdirb;
-       case 2:
-               return &io->iop_pdirc;
-       case 3:
-               return &io->iop_pdird;
-       }
-
-       return 1;
-}
-
-static int mpc8260cpm_dio_bits(struct comedi_device *dev,
-                              struct comedi_subdevice *s,
-                              struct comedi_insn *insn, unsigned int *data)
-{
-       int port;
-       unsigned long *p;
-
-       p = cpm_pdat((int)s->private);
-
-       return insn->n;
-}
-
-static int mpc8260cpm_attach(struct comedi_device *dev,
-                            struct comedi_devconfig *it)
-{
-       struct comedi_subdevice *s;
-       int i;
-       int ret;
-
-       printk("comedi%d: mpc8260cpm: ", dev->minor);
-
-       dev->board_ptr = mpc8260cpm_boards + dev->board;
-
-       dev->board_name = thisboard->name;
-
-       if (alloc_private(dev, sizeof(struct mpc8260cpm_private)) < 0)
-               return -ENOMEM;
-
-       ret =comedi_alloc_subdevices(dev, 4);
-       if (ret)
-               return ret;
-
-       for (i = 0; i < 4; i++) {
-               s = &dev->subdevices[i];
-               s->type = COMEDI_SUBD_DIO;
-               s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
-               s->n_chan = 32;
-               s->maxdata = 1;
-               s->range_table = &range_digital;
-               s->insn_config = mpc8260cpm_dio_config;
-               s->insn_bits = mpc8260cpm_dio_bits;
-       }
-
-       return 1;
-}
-
-static void mpc8260cpm_detach(struct comedi_device *dev)
-{
-       /* Nothing to cleanup */
-}
-
-static struct comedi_driver mpc8260cpm_driver = {
-       .driver_name    = "mpc8260cpm",
-       .module         = THIS_MODULE,
-       .attach         = mpc8260cpm_attach,
-       .detach         = mpc8260cpm_detach,
-};
-module_comedi_driver(mpc8260cpm_driver);
index 4625cb4d07c6fbea5bd0596a5e78c4d1e92e8573..1f5f402f3d17245322c8387767c8ec7158cd3d6b 100644 (file)
@@ -86,7 +86,6 @@ Devices: [Quanser Consulting] MultiQ-3 (multiq3)
 struct multiq3_private {
        unsigned int ao_readback[2];
 };
-#define devpriv ((struct multiq3_private *)dev->private)
 
 static int multiq3_ai_insn_read(struct comedi_device *dev,
                                struct comedi_subdevice *s,
@@ -129,6 +128,7 @@ static int multiq3_ao_insn_read(struct comedi_device *dev,
                                struct comedi_subdevice *s,
                                struct comedi_insn *insn, unsigned int *data)
 {
+       struct multiq3_private *devpriv = dev->private;
        int i;
        int chan = CR_CHAN(insn->chanspec);
 
@@ -142,6 +142,7 @@ static int multiq3_ao_insn_write(struct comedi_device *dev,
                                 struct comedi_subdevice *s,
                                 struct comedi_insn *insn, unsigned int *data)
 {
+       struct multiq3_private *devpriv = dev->private;
        int i;
        int chan = CR_CHAN(insn->chanspec);
 
@@ -230,6 +231,7 @@ static void encoder_reset(struct comedi_device *dev)
 static int multiq3_attach(struct comedi_device *dev,
                          struct comedi_devconfig *it)
 {
+       struct multiq3_private *devpriv;
        int result = 0;
        unsigned long iobase;
        unsigned int irq;
@@ -256,9 +258,10 @@ static int multiq3_attach(struct comedi_device *dev,
        if (result)
                return result;
 
-       result = alloc_private(dev, sizeof(struct multiq3_private));
-       if (result < 0)
-               return result;
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
+               return -ENOMEM;
+       dev->private = devpriv;
 
        s = &dev->subdevices[0];
        /* ai subdevice */
index 51295f32ee895a5123b1e4a04a1a8ff96e9f33b4..d853e75be7910b798f0401d9fc7809f6c9c01e85 100644 (file)
@@ -112,12 +112,11 @@ struct ni6527_private {
        unsigned int filter_enable;
 };
 
-#define devpriv ((struct ni6527_private *)dev->private)
-
 static int ni6527_di_insn_config(struct comedi_device *dev,
                                 struct comedi_subdevice *s,
                                 struct comedi_insn *insn, unsigned int *data)
 {
+       struct ni6527_private *devpriv = dev->private;
        int chan = CR_CHAN(insn->chanspec);
        unsigned int interval;
 
@@ -164,6 +163,8 @@ static int ni6527_di_insn_bits(struct comedi_device *dev,
                               struct comedi_subdevice *s,
                               struct comedi_insn *insn, unsigned int *data)
 {
+       struct ni6527_private *devpriv = dev->private;
+
        data[1] = readb(devpriv->mite->daq_io_addr + Port_Register(0));
        data[1] |= readb(devpriv->mite->daq_io_addr + Port_Register(1)) << 8;
        data[1] |= readb(devpriv->mite->daq_io_addr + Port_Register(2)) << 16;
@@ -175,6 +176,8 @@ static int ni6527_do_insn_bits(struct comedi_device *dev,
                               struct comedi_subdevice *s,
                               struct comedi_insn *insn, unsigned int *data)
 {
+       struct ni6527_private *devpriv = dev->private;
+
        if (data[0]) {
                s->state &= ~data[0];
                s->state |= (data[0] & data[1]);
@@ -202,6 +205,7 @@ static int ni6527_do_insn_bits(struct comedi_device *dev,
 static irqreturn_t ni6527_interrupt(int irq, void *d)
 {
        struct comedi_device *dev = d;
+       struct ni6527_private *devpriv = dev->private;
        struct comedi_subdevice *s = &dev->subdevices[2];
        unsigned int status;
 
@@ -281,6 +285,7 @@ static int ni6527_intr_cmdtest(struct comedi_device *dev,
 static int ni6527_intr_cmd(struct comedi_device *dev,
                           struct comedi_subdevice *s)
 {
+       struct ni6527_private *devpriv = dev->private;
        /* struct comedi_cmd *cmd = &s->async->cmd; */
 
        writeb(ClrEdge | ClrOverflow,
@@ -295,6 +300,8 @@ static int ni6527_intr_cmd(struct comedi_device *dev,
 static int ni6527_intr_cancel(struct comedi_device *dev,
                              struct comedi_subdevice *s)
 {
+       struct ni6527_private *devpriv = dev->private;
+
        writeb(0x00, devpriv->mite->daq_io_addr + Master_Interrupt_Control);
 
        return 0;
@@ -312,6 +319,8 @@ static int ni6527_intr_insn_config(struct comedi_device *dev,
                                   struct comedi_subdevice *s,
                                   struct comedi_insn *insn, unsigned int *data)
 {
+       struct ni6527_private *devpriv = dev->private;
+
        if (insn->n < 1)
                return -EINVAL;
        if (data[0] != INSN_CONFIG_CHANGE_NOTIFY)
@@ -351,12 +360,14 @@ ni6527_find_boardinfo(struct pci_dev *pcidev)
 static int __devinit ni6527_attach_pci(struct comedi_device *dev,
                                       struct pci_dev *pcidev)
 {
+       struct ni6527_private *devpriv;
        struct comedi_subdevice *s;
        int ret;
 
-       ret = alloc_private(dev, sizeof(struct ni6527_private));
-       if (ret < 0)
-               return ret;
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
+               return -ENOMEM;
+       dev->private = devpriv;
 
        dev->board_ptr = ni6527_find_boardinfo(pcidev);
        if (!dev->board_ptr)
@@ -430,6 +441,8 @@ static int __devinit ni6527_attach_pci(struct comedi_device *dev,
 
 static void ni6527_detach(struct comedi_device *dev)
 {
+       struct ni6527_private *devpriv = dev->private;
+
        if (devpriv && devpriv->mite && devpriv->mite->daq_io_addr)
                writeb(0x00,
                       devpriv->mite->daq_io_addr + Master_Interrupt_Control);
index 2a73ff57a2fb84fb7159e98e5e3d17c80be2a2ab..19d5e8c96e8f72c6ba819766cd5ddc9d79049f91 100644 (file)
@@ -291,11 +291,6 @@ struct ni_65xx_private {
        unsigned short dio_direction[NI_65XX_MAX_NUM_PORTS];
 };
 
-static inline struct ni_65xx_private *private(struct comedi_device *dev)
-{
-       return dev->private;
-}
-
 struct ni_65xx_subdevice_private {
        unsigned base_port;
 };
@@ -319,6 +314,7 @@ static int ni_65xx_config_filter(struct comedi_device *dev,
                                 struct comedi_subdevice *s,
                                 struct comedi_insn *insn, unsigned int *data)
 {
+       struct ni_65xx_private *devpriv = dev->private;
        const unsigned chan = CR_CHAN(insn->chanspec);
        const unsigned port =
            sprivate(s)->base_port + ni_65xx_port_by_channel(chan);
@@ -335,22 +331,22 @@ static int ni_65xx_config_filter(struct comedi_device *dev,
                        interval = max_filter_interval;
                data[1] = interval * filter_resolution_ns;
 
-               if (interval != private(dev)->filter_interval) {
+               if (interval != devpriv->filter_interval) {
                        writeb(interval,
-                              private(dev)->mite->daq_io_addr +
+                              devpriv->mite->daq_io_addr +
                               Filter_Interval);
-                       private(dev)->filter_interval = interval;
+                       devpriv->filter_interval = interval;
                }
 
-               private(dev)->filter_enable[port] |=
+               devpriv->filter_enable[port] |=
                    1 << (chan % ni_65xx_channels_per_port);
        } else {
-               private(dev)->filter_enable[port] &=
+               devpriv->filter_enable[port] &=
                    ~(1 << (chan % ni_65xx_channels_per_port));
        }
 
-       writeb(private(dev)->filter_enable[port],
-              private(dev)->mite->daq_io_addr + Filter_Enable(port));
+       writeb(devpriv->filter_enable[port],
+              devpriv->mite->daq_io_addr + Filter_Enable(port));
 
        return 2;
 }
@@ -359,6 +355,7 @@ static int ni_65xx_dio_insn_config(struct comedi_device *dev,
                                   struct comedi_subdevice *s,
                                   struct comedi_insn *insn, unsigned int *data)
 {
+       struct ni_65xx_private *devpriv = dev->private;
        unsigned port;
 
        if (insn->n < 1)
@@ -372,21 +369,21 @@ static int ni_65xx_dio_insn_config(struct comedi_device *dev,
        case INSN_CONFIG_DIO_OUTPUT:
                if (s->type != COMEDI_SUBD_DIO)
                        return -EINVAL;
-               private(dev)->dio_direction[port] = COMEDI_OUTPUT;
-               writeb(0, private(dev)->mite->daq_io_addr + Port_Select(port));
+               devpriv->dio_direction[port] = COMEDI_OUTPUT;
+               writeb(0, devpriv->mite->daq_io_addr + Port_Select(port));
                return 1;
                break;
        case INSN_CONFIG_DIO_INPUT:
                if (s->type != COMEDI_SUBD_DIO)
                        return -EINVAL;
-               private(dev)->dio_direction[port] = COMEDI_INPUT;
-               writeb(1, private(dev)->mite->daq_io_addr + Port_Select(port));
+               devpriv->dio_direction[port] = COMEDI_INPUT;
+               writeb(1, devpriv->mite->daq_io_addr + Port_Select(port));
                return 1;
                break;
        case INSN_CONFIG_DIO_QUERY:
                if (s->type != COMEDI_SUBD_DIO)
                        return -EINVAL;
-               data[1] = private(dev)->dio_direction[port];
+               data[1] = devpriv->dio_direction[port];
                return insn->n;
                break;
        default:
@@ -399,6 +396,7 @@ static int ni_65xx_dio_insn_bits(struct comedi_device *dev,
                                 struct comedi_subdevice *s,
                                 struct comedi_insn *insn, unsigned int *data)
 {
+       struct ni_65xx_private *devpriv = dev->private;
        unsigned base_bitfield_channel;
        const unsigned max_ports_per_bitfield = 5;
        unsigned read_bits = 0;
@@ -432,18 +430,18 @@ static int ni_65xx_dio_insn_bits(struct comedi_device *dev,
                port_data &= 0xff;
                if (port_mask) {
                        unsigned bits;
-                       private(dev)->output_bits[port] &= ~port_mask;
-                       private(dev)->output_bits[port] |=
+                       devpriv->output_bits[port] &= ~port_mask;
+                       devpriv->output_bits[port] |=
                            port_data & port_mask;
-                       bits = private(dev)->output_bits[port];
+                       bits = devpriv->output_bits[port];
                        if (board(dev)->invert_outputs)
                                bits = ~bits;
                        writeb(bits,
-                              private(dev)->mite->daq_io_addr +
+                              devpriv->mite->daq_io_addr +
                               Port_Data(port));
                }
                port_read_bits =
-                   readb(private(dev)->mite->daq_io_addr + Port_Data(port));
+                   readb(devpriv->mite->daq_io_addr + Port_Data(port));
                if (s->type == COMEDI_SUBD_DO && board(dev)->invert_outputs) {
                        /* Outputs inverted, so invert value read back from
                         * DO subdevice.  (Does not apply to boards with DIO
@@ -464,17 +462,18 @@ static int ni_65xx_dio_insn_bits(struct comedi_device *dev,
 static irqreturn_t ni_65xx_interrupt(int irq, void *d)
 {
        struct comedi_device *dev = d;
+       struct ni_65xx_private *devpriv = dev->private;
        struct comedi_subdevice *s = &dev->subdevices[2];
        unsigned int status;
 
-       status = readb(private(dev)->mite->daq_io_addr + Change_Status);
+       status = readb(devpriv->mite->daq_io_addr + Change_Status);
        if ((status & MasterInterruptStatus) == 0)
                return IRQ_NONE;
        if ((status & EdgeStatus) == 0)
                return IRQ_NONE;
 
        writeb(ClrEdge | ClrOverflow,
-              private(dev)->mite->daq_io_addr + Clear_Register);
+              devpriv->mite->daq_io_addr + Clear_Register);
 
        comedi_buf_put(s->async, 0);
        s->async->events |= COMEDI_CB_EOS;
@@ -543,13 +542,14 @@ static int ni_65xx_intr_cmdtest(struct comedi_device *dev,
 static int ni_65xx_intr_cmd(struct comedi_device *dev,
                            struct comedi_subdevice *s)
 {
+       struct ni_65xx_private *devpriv = dev->private;
        /* struct comedi_cmd *cmd = &s->async->cmd; */
 
        writeb(ClrEdge | ClrOverflow,
-              private(dev)->mite->daq_io_addr + Clear_Register);
+              devpriv->mite->daq_io_addr + Clear_Register);
        writeb(FallingEdgeIntEnable | RisingEdgeIntEnable |
               MasterInterruptEnable | EdgeIntEnable,
-              private(dev)->mite->daq_io_addr + Master_Interrupt_Control);
+              devpriv->mite->daq_io_addr + Master_Interrupt_Control);
 
        return 0;
 }
@@ -557,8 +557,9 @@ static int ni_65xx_intr_cmd(struct comedi_device *dev,
 static int ni_65xx_intr_cancel(struct comedi_device *dev,
                               struct comedi_subdevice *s)
 {
-       writeb(0x00,
-              private(dev)->mite->daq_io_addr + Master_Interrupt_Control);
+       struct ni_65xx_private *devpriv = dev->private;
+
+       writeb(0x00, devpriv->mite->daq_io_addr + Master_Interrupt_Control);
 
        return 0;
 }
@@ -576,35 +577,37 @@ static int ni_65xx_intr_insn_config(struct comedi_device *dev,
                                    struct comedi_insn *insn,
                                    unsigned int *data)
 {
+       struct ni_65xx_private *devpriv = dev->private;
+
        if (insn->n < 1)
                return -EINVAL;
        if (data[0] != INSN_CONFIG_CHANGE_NOTIFY)
                return -EINVAL;
 
        writeb(data[1],
-              private(dev)->mite->daq_io_addr +
+              devpriv->mite->daq_io_addr +
               Rising_Edge_Detection_Enable(0));
        writeb(data[1] >> 8,
-              private(dev)->mite->daq_io_addr +
+              devpriv->mite->daq_io_addr +
               Rising_Edge_Detection_Enable(0x10));
        writeb(data[1] >> 16,
-              private(dev)->mite->daq_io_addr +
+              devpriv->mite->daq_io_addr +
               Rising_Edge_Detection_Enable(0x20));
        writeb(data[1] >> 24,
-              private(dev)->mite->daq_io_addr +
+              devpriv->mite->daq_io_addr +
               Rising_Edge_Detection_Enable(0x30));
 
        writeb(data[2],
-              private(dev)->mite->daq_io_addr +
+              devpriv->mite->daq_io_addr +
               Falling_Edge_Detection_Enable(0));
        writeb(data[2] >> 8,
-              private(dev)->mite->daq_io_addr +
+              devpriv->mite->daq_io_addr +
               Falling_Edge_Detection_Enable(0x10));
        writeb(data[2] >> 16,
-              private(dev)->mite->daq_io_addr +
+              devpriv->mite->daq_io_addr +
               Falling_Edge_Detection_Enable(0x20));
        writeb(data[2] >> 24,
-              private(dev)->mite->daq_io_addr +
+              devpriv->mite->daq_io_addr +
               Falling_Edge_Detection_Enable(0x30));
 
        return 2;
@@ -627,32 +630,34 @@ ni_65xx_find_boardinfo(struct pci_dev *pcidev)
 static int __devinit ni_65xx_attach_pci(struct comedi_device *dev,
                                        struct pci_dev *pcidev)
 {
+       struct ni_65xx_private *devpriv;
        struct comedi_subdevice *s;
        unsigned i;
        int ret;
 
-       ret = alloc_private(dev, sizeof(struct ni_65xx_private));
-       if (ret < 0)
-               return ret;
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
+               return -ENOMEM;
+       dev->private = devpriv;
 
        dev->board_ptr = ni_65xx_find_boardinfo(pcidev);
        if (!dev->board_ptr)
                return -ENODEV;
 
-       private(dev)->mite = mite_alloc(pcidev);
-       if (!private(dev)->mite)
+       devpriv->mite = mite_alloc(pcidev);
+       if (!devpriv->mite)
                return -ENOMEM;
 
-       ret = mite_setup(private(dev)->mite);
+       ret = mite_setup(devpriv->mite);
        if (ret < 0) {
                dev_warn(dev->class_dev, "error setting up mite\n");
                return ret;
        }
 
        dev->board_name = board(dev)->name;
-       dev->irq = mite_irq(private(dev)->mite);
+       dev->irq = mite_irq(devpriv->mite);
        dev_info(dev->class_dev, "board: %s, ID=0x%02x", dev->board_name,
-              readb(private(dev)->mite->daq_io_addr + ID_Register));
+              readb(devpriv->mite->daq_io_addr + ID_Register));
 
        ret = comedi_alloc_subdevices(dev, 4);
        if (ret)
@@ -710,7 +715,7 @@ static int __devinit ni_65xx_attach_pci(struct comedi_device *dev,
                for (i = 0; i < board(dev)->num_dio_ports; ++i) {
                        /*  configure all ports for input */
                        writeb(0x1,
-                              private(dev)->mite->daq_io_addr +
+                              devpriv->mite->daq_io_addr +
                               Port_Select(i));
                }
        } else {
@@ -732,21 +737,21 @@ static int __devinit ni_65xx_attach_pci(struct comedi_device *dev,
 
        for (i = 0; i < ni_65xx_total_num_ports(board(dev)); ++i) {
                writeb(0x00,
-                      private(dev)->mite->daq_io_addr + Filter_Enable(i));
+                      devpriv->mite->daq_io_addr + Filter_Enable(i));
                if (board(dev)->invert_outputs)
                        writeb(0x01,
-                              private(dev)->mite->daq_io_addr + Port_Data(i));
+                              devpriv->mite->daq_io_addr + Port_Data(i));
                else
                        writeb(0x00,
-                              private(dev)->mite->daq_io_addr + Port_Data(i));
+                              devpriv->mite->daq_io_addr + Port_Data(i));
        }
        writeb(ClrEdge | ClrOverflow,
-              private(dev)->mite->daq_io_addr + Clear_Register);
+              devpriv->mite->daq_io_addr + Clear_Register);
        writeb(0x00,
-              private(dev)->mite->daq_io_addr + Master_Interrupt_Control);
+              devpriv->mite->daq_io_addr + Master_Interrupt_Control);
 
        /* Set filter interval to 0  (32bit reg) */
-       writeb(0x00000000, private(dev)->mite->daq_io_addr + Filter_Interval);
+       writeb(0x00000000, devpriv->mite->daq_io_addr + Filter_Interval);
 
        ret = request_irq(dev->irq, ni_65xx_interrupt, IRQF_SHARED,
                          "ni_65xx", dev);
@@ -760,15 +765,16 @@ static int __devinit ni_65xx_attach_pci(struct comedi_device *dev,
 
 static void ni_65xx_detach(struct comedi_device *dev)
 {
-       if (private(dev) && private(dev)->mite
-           && private(dev)->mite->daq_io_addr) {
+       struct ni_65xx_private *devpriv = dev->private;
+
+       if (devpriv && devpriv->mite && devpriv->mite->daq_io_addr) {
                writeb(0x00,
-                      private(dev)->mite->daq_io_addr +
+                      devpriv->mite->daq_io_addr +
                       Master_Interrupt_Control);
        }
        if (dev->irq)
                free_irq(dev->irq, dev);
-       if (private(dev)) {
+       if (devpriv) {
                struct comedi_subdevice *s;
                unsigned i;
 
@@ -777,9 +783,9 @@ static void ni_65xx_detach(struct comedi_device *dev)
                        kfree(s->private);
                        s->private = NULL;
                }
-               if (private(dev)->mite) {
-                       mite_unsetup(private(dev)->mite);
-                       mite_free(private(dev)->mite);
+               if (devpriv->mite) {
+                       mite_unsetup(devpriv->mite);
+                       mite_free(devpriv->mite);
                }
        }
 }
index df2f3b0bab4843201bb37c0cbda38f7395e56041..318057546485af43bbdf1ea0fb5bddaa73037dac 100644 (file)
@@ -419,16 +419,6 @@ static const struct ni_660x_board ni_660x_boards[] = {
 #define NI_660X_MAX_NUM_CHIPS 2
 #define NI_660X_MAX_NUM_COUNTERS (NI_660X_MAX_NUM_CHIPS * counters_per_chip)
 
-static DEFINE_PCI_DEVICE_TABLE(ni_660x_pci_table) = {
-       {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2c60)},
-       {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1310)},
-       {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1360)},
-       {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2cc0)},
-       {0}
-};
-
-MODULE_DEVICE_TABLE(pci, ni_660x_pci_table);
-
 struct ni_660x_private {
        struct mite_struct *mite;
        struct ni_gpct_device *counter_dev;
@@ -443,78 +433,11 @@ struct ni_660x_private {
        unsigned short pfi_output_selects[NUM_PFI_CHANNELS];
 };
 
-static inline struct ni_660x_private *private(struct comedi_device *dev)
-{
-       return dev->private;
-}
-
-/* initialized in ni_660x_attach_pci() */
-static inline const struct ni_660x_board *board(struct comedi_device *dev)
-{
-       return dev->board_ptr;
-}
-
-static int ni_660x_attach_pci(struct comedi_device *dev,
-                             struct pci_dev *pcidev);
-static void ni_660x_detach(struct comedi_device *dev);
-static void init_tio_chip(struct comedi_device *dev, int chipset);
-static void ni_660x_select_pfi_output(struct comedi_device *dev,
-                                     unsigned pfi_channel,
-                                     unsigned output_select);
-
-static struct comedi_driver ni_660x_driver = {
-       .driver_name = "ni_660x",
-       .module = THIS_MODULE,
-       .attach_pci = ni_660x_attach_pci,
-       .detach = ni_660x_detach,
-};
-
-static int __devinit ni_660x_pci_probe(struct pci_dev *dev,
-                                      const struct pci_device_id *ent)
-{
-       return comedi_pci_auto_config(dev, &ni_660x_driver);
-}
-
-static void __devexit ni_660x_pci_remove(struct pci_dev *dev)
-{
-       comedi_pci_auto_unconfig(dev);
-}
-
-static struct pci_driver ni_660x_pci_driver = {
-       .name = "ni_660x",
-       .id_table = ni_660x_pci_table,
-       .probe = ni_660x_pci_probe,
-       .remove = __devexit_p(ni_660x_pci_remove)
-};
-module_comedi_pci_driver(ni_660x_driver, ni_660x_pci_driver);
-
-static int ni_660x_set_pfi_routing(struct comedi_device *dev, unsigned chan,
-                                  unsigned source);
-
-/* Possible instructions for a GPCT */
-static int ni_660x_GPCT_rinsn(struct comedi_device *dev,
-                             struct comedi_subdevice *s,
-                             struct comedi_insn *insn, unsigned int *data);
-static int ni_660x_GPCT_insn_config(struct comedi_device *dev,
-                                   struct comedi_subdevice *s,
-                                   struct comedi_insn *insn,
-                                   unsigned int *data);
-static int ni_660x_GPCT_winsn(struct comedi_device *dev,
-                             struct comedi_subdevice *s,
-                             struct comedi_insn *insn, unsigned int *data);
-
-/* Possible instructions for Digital IO */
-static int ni_660x_dio_insn_config(struct comedi_device *dev,
-                                  struct comedi_subdevice *s,
-                                  struct comedi_insn *insn,
-                                  unsigned int *data);
-static int ni_660x_dio_insn_bits(struct comedi_device *dev,
-                                struct comedi_subdevice *s,
-                                struct comedi_insn *insn, unsigned int *data);
-
 static inline unsigned ni_660x_num_counters(struct comedi_device *dev)
 {
-       return board(dev)->n_chips * counters_per_chip;
+       const struct ni_660x_board *board = comedi_board(dev);
+
+       return board->n_chips * counters_per_chip;
 }
 
 static enum NI_660x_Register ni_gpct_to_660x_register(enum ni_gpct_register reg)
@@ -737,8 +660,9 @@ static inline void ni_660x_write_register(struct comedi_device *dev,
                                          unsigned chip_index, unsigned bits,
                                          enum NI_660x_Register reg)
 {
+       struct ni_660x_private *devpriv = dev->private;
        void __iomem *write_address =
-           private(dev)->mite->daq_io_addr + GPCT_OFFSET[chip_index] +
+           devpriv->mite->daq_io_addr + GPCT_OFFSET[chip_index] +
            registerData[reg].offset;
 
        switch (registerData[reg].size) {
@@ -758,8 +682,9 @@ static inline unsigned ni_660x_read_register(struct comedi_device *dev,
                                             unsigned chip_index,
                                             enum NI_660x_Register reg)
 {
+       struct ni_660x_private *devpriv = dev->private;
        void __iomem *read_address =
-           private(dev)->mite->daq_io_addr + GPCT_OFFSET[chip_index] +
+           devpriv->mite->daq_io_addr + GPCT_OFFSET[chip_index] +
            registerData[reg].offset;
 
        switch (registerData[reg].size) {
@@ -806,54 +731,56 @@ static inline void ni_660x_set_dma_channel(struct comedi_device *dev,
                                           unsigned mite_channel,
                                           struct ni_gpct *counter)
 {
+       struct ni_660x_private *devpriv = dev->private;
        unsigned long flags;
-       spin_lock_irqsave(&private(dev)->soft_reg_copy_lock, flags);
-       private(dev)->dma_configuration_soft_copies[counter->chip_index] &=
+
+       spin_lock_irqsave(&devpriv->soft_reg_copy_lock, flags);
+       devpriv->dma_configuration_soft_copies[counter->chip_index] &=
            ~dma_select_mask(mite_channel);
-       private(dev)->dma_configuration_soft_copies[counter->chip_index] |=
+       devpriv->dma_configuration_soft_copies[counter->chip_index] |=
            dma_select_bits(mite_channel,
                            dma_selection_counter(counter->counter_index));
        ni_660x_write_register(dev, counter->chip_index,
-                              private(dev)->
-                              dma_configuration_soft_copies
+                              devpriv->dma_configuration_soft_copies
                               [counter->chip_index] |
                               dma_reset_bit(mite_channel), DMAConfigRegister);
        mmiowb();
-       spin_unlock_irqrestore(&private(dev)->soft_reg_copy_lock, flags);
+       spin_unlock_irqrestore(&devpriv->soft_reg_copy_lock, flags);
 }
 
 static inline void ni_660x_unset_dma_channel(struct comedi_device *dev,
                                             unsigned mite_channel,
                                             struct ni_gpct *counter)
 {
+       struct ni_660x_private *devpriv = dev->private;
        unsigned long flags;
-       spin_lock_irqsave(&private(dev)->soft_reg_copy_lock, flags);
-       private(dev)->dma_configuration_soft_copies[counter->chip_index] &=
+
+       spin_lock_irqsave(&devpriv->soft_reg_copy_lock, flags);
+       devpriv->dma_configuration_soft_copies[counter->chip_index] &=
            ~dma_select_mask(mite_channel);
-       private(dev)->dma_configuration_soft_copies[counter->chip_index] |=
+       devpriv->dma_configuration_soft_copies[counter->chip_index] |=
            dma_select_bits(mite_channel, dma_selection_none);
        ni_660x_write_register(dev, counter->chip_index,
-                              private(dev)->
-                              dma_configuration_soft_copies
+                              devpriv->dma_configuration_soft_copies
                               [counter->chip_index], DMAConfigRegister);
        mmiowb();
-       spin_unlock_irqrestore(&private(dev)->soft_reg_copy_lock, flags);
+       spin_unlock_irqrestore(&devpriv->soft_reg_copy_lock, flags);
 }
 
 static int ni_660x_request_mite_channel(struct comedi_device *dev,
                                        struct ni_gpct *counter,
                                        enum comedi_io_direction direction)
 {
+       struct ni_660x_private *devpriv = dev->private;
        unsigned long flags;
        struct mite_channel *mite_chan;
 
-       spin_lock_irqsave(&private(dev)->mite_channel_lock, flags);
+       spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
        BUG_ON(counter->mite_chan);
-       mite_chan =
-           mite_request_channel(private(dev)->mite, mite_ring(private(dev),
-                                                              counter));
+       mite_chan = mite_request_channel(devpriv->mite,
+                                        mite_ring(devpriv, counter));
        if (mite_chan == NULL) {
-               spin_unlock_irqrestore(&private(dev)->mite_channel_lock, flags);
+               spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
                comedi_error(dev,
                             "failed to reserve mite dma channel for counter.");
                return -EBUSY;
@@ -861,16 +788,17 @@ static int ni_660x_request_mite_channel(struct comedi_device *dev,
        mite_chan->dir = direction;
        ni_tio_set_mite_channel(counter, mite_chan);
        ni_660x_set_dma_channel(dev, mite_chan->channel, counter);
-       spin_unlock_irqrestore(&private(dev)->mite_channel_lock, flags);
+       spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
        return 0;
 }
 
 static void ni_660x_release_mite_channel(struct comedi_device *dev,
                                         struct ni_gpct *counter)
 {
+       struct ni_660x_private *devpriv = dev->private;
        unsigned long flags;
 
-       spin_lock_irqsave(&private(dev)->mite_channel_lock, flags);
+       spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
        if (counter->mite_chan) {
                struct mite_channel *mite_chan = counter->mite_chan;
 
@@ -878,7 +806,7 @@ static void ni_660x_release_mite_channel(struct comedi_device *dev,
                ni_tio_set_mite_channel(counter, NULL);
                mite_release_channel(mite_chan);
        }
-       spin_unlock_irqrestore(&private(dev)->mite_channel_lock, flags);
+       spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
 }
 
 static int ni_660x_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
@@ -947,6 +875,7 @@ static void ni_660x_handle_gpct_interrupt(struct comedi_device *dev,
 static irqreturn_t ni_660x_interrupt(int irq, void *d)
 {
        struct comedi_device *dev = d;
+       struct ni_660x_private *devpriv = dev->private;
        struct comedi_subdevice *s;
        unsigned i;
        unsigned long flags;
@@ -954,24 +883,26 @@ static irqreturn_t ni_660x_interrupt(int irq, void *d)
        if (dev->attached == 0)
                return IRQ_NONE;
        /* lock to avoid race with comedi_poll */
-       spin_lock_irqsave(&private(dev)->interrupt_lock, flags);
+       spin_lock_irqsave(&devpriv->interrupt_lock, flags);
        smp_mb();
        for (i = 0; i < ni_660x_num_counters(dev); ++i) {
                s = &dev->subdevices[NI_660X_GPCT_SUBDEV(i)];
                ni_660x_handle_gpct_interrupt(dev, s);
        }
-       spin_unlock_irqrestore(&private(dev)->interrupt_lock, flags);
+       spin_unlock_irqrestore(&devpriv->interrupt_lock, flags);
        return IRQ_HANDLED;
 }
 
 static int ni_660x_input_poll(struct comedi_device *dev,
                              struct comedi_subdevice *s)
 {
+       struct ni_660x_private *devpriv = dev->private;
        unsigned long flags;
+
        /* lock to avoid race with comedi_poll */
-       spin_lock_irqsave(&private(dev)->interrupt_lock, flags);
+       spin_lock_irqsave(&devpriv->interrupt_lock, flags);
        mite_sync_input_dma(subdev_to_counter(s)->mite_chan, s->async);
-       spin_unlock_irqrestore(&private(dev)->interrupt_lock, flags);
+       spin_unlock_irqrestore(&devpriv->interrupt_lock, flags);
        return comedi_buf_read_n_available(s->async);
 }
 
@@ -979,9 +910,10 @@ static int ni_660x_buf_change(struct comedi_device *dev,
                              struct comedi_subdevice *s,
                              unsigned long new_size)
 {
+       struct ni_660x_private *devpriv = dev->private;
        int ret;
 
-       ret = mite_buf_change(mite_ring(private(dev), subdev_to_counter(s)),
+       ret = mite_buf_change(mite_ring(devpriv, subdev_to_counter(s)),
                              s->async);
        if (ret < 0)
                return ret;
@@ -991,32 +923,35 @@ static int ni_660x_buf_change(struct comedi_device *dev,
 
 static int ni_660x_allocate_private(struct comedi_device *dev)
 {
-       int retval;
+       struct ni_660x_private *devpriv;
        unsigned i;
 
-       retval = alloc_private(dev, sizeof(struct ni_660x_private));
-       if (retval < 0)
-               return retval;
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
+               return -ENOMEM;
+       dev->private = devpriv;
 
-       spin_lock_init(&private(dev)->mite_channel_lock);
-       spin_lock_init(&private(dev)->interrupt_lock);
-       spin_lock_init(&private(dev)->soft_reg_copy_lock);
+       spin_lock_init(&devpriv->mite_channel_lock);
+       spin_lock_init(&devpriv->interrupt_lock);
+       spin_lock_init(&devpriv->soft_reg_copy_lock);
        for (i = 0; i < NUM_PFI_CHANNELS; ++i)
-               private(dev)->pfi_output_selects[i] = pfi_output_select_counter;
+               devpriv->pfi_output_selects[i] = pfi_output_select_counter;
 
        return 0;
 }
 
 static int ni_660x_alloc_mite_rings(struct comedi_device *dev)
 {
+       const struct ni_660x_board *board = comedi_board(dev);
+       struct ni_660x_private *devpriv = dev->private;
        unsigned i;
        unsigned j;
 
-       for (i = 0; i < board(dev)->n_chips; ++i) {
+       for (i = 0; i < board->n_chips; ++i) {
                for (j = 0; j < counters_per_chip; ++j) {
-                       private(dev)->mite_rings[i][j] =
-                           mite_alloc_ring(private(dev)->mite);
-                       if (private(dev)->mite_rings[i][j] == NULL)
+                       devpriv->mite_rings[i][j] =
+                           mite_alloc_ring(devpriv->mite);
+                       if (devpriv->mite_rings[i][j] == NULL)
                                return -ENOMEM;
                }
        }
@@ -1025,12 +960,14 @@ static int ni_660x_alloc_mite_rings(struct comedi_device *dev)
 
 static void ni_660x_free_mite_rings(struct comedi_device *dev)
 {
+       const struct ni_660x_board *board = comedi_board(dev);
+       struct ni_660x_private *devpriv = dev->private;
        unsigned i;
        unsigned j;
 
-       for (i = 0; i < board(dev)->n_chips; ++i) {
+       for (i = 0; i < board->n_chips; ++i) {
                for (j = 0; j < counters_per_chip; ++j)
-                       mite_free_ring(private(dev)->mite_rings[i][j]);
+                       mite_free_ring(devpriv->mite_rings[i][j]);
        }
 }
 
@@ -1048,145 +985,6 @@ ni_660x_find_boardinfo(struct pci_dev *pcidev)
        return NULL;
 }
 
-static int __devinit ni_660x_attach_pci(struct comedi_device *dev,
-                                       struct pci_dev *pcidev)
-{
-       struct comedi_subdevice *s;
-       int ret;
-       unsigned i;
-       unsigned global_interrupt_config_bits;
-
-       ret = ni_660x_allocate_private(dev);
-       if (ret < 0)
-               return ret;
-       dev->board_ptr = ni_660x_find_boardinfo(pcidev);
-       if (!dev->board_ptr)
-               return -ENODEV;
-       private(dev)->mite = mite_alloc(pcidev);
-       if (!private(dev)->mite)
-               return -ENOMEM;
-
-       dev->board_name = board(dev)->name;
-
-       ret = mite_setup2(private(dev)->mite, 1);
-       if (ret < 0) {
-               dev_warn(dev->class_dev, "error setting up mite\n");
-               return ret;
-       }
-       comedi_set_hw_dev(dev, &private(dev)->mite->pcidev->dev);
-       ret = ni_660x_alloc_mite_rings(dev);
-       if (ret < 0)
-               return ret;
-
-       ret = comedi_alloc_subdevices(dev, 2 + NI_660X_MAX_NUM_COUNTERS);
-       if (ret)
-               return ret;
-
-       s = &dev->subdevices[0];
-       /* Old GENERAL-PURPOSE COUNTER/TIME (GPCT) subdevice, no longer used */
-       s->type = COMEDI_SUBD_UNUSED;
-
-       s = &dev->subdevices[NI_660X_DIO_SUBDEV];
-       /* DIGITAL I/O SUBDEVICE */
-       s->type = COMEDI_SUBD_DIO;
-       s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
-       s->n_chan = NUM_PFI_CHANNELS;
-       s->maxdata = 1;
-       s->range_table = &range_digital;
-       s->insn_bits = ni_660x_dio_insn_bits;
-       s->insn_config = ni_660x_dio_insn_config;
-       s->io_bits = 0;         /* all bits default to input */
-       /*  we use the ioconfig registers to control dio direction, so zero
-       output enables in stc dio control reg */
-       ni_660x_write_register(dev, 0, 0, STCDIOControl);
-
-       private(dev)->counter_dev = ni_gpct_device_construct(dev,
-                                                    &ni_gpct_write_register,
-                                                    &ni_gpct_read_register,
-                                                    ni_gpct_variant_660x,
-                                                    ni_660x_num_counters
-                                                    (dev));
-       if (private(dev)->counter_dev == NULL)
-               return -ENOMEM;
-       for (i = 0; i < NI_660X_MAX_NUM_COUNTERS; ++i) {
-               s = &dev->subdevices[NI_660X_GPCT_SUBDEV(i)];
-               if (i < ni_660x_num_counters(dev)) {
-                       s->type = COMEDI_SUBD_COUNTER;
-                       s->subdev_flags =
-                           SDF_READABLE | SDF_WRITABLE | SDF_LSAMPL |
-                           SDF_CMD_READ /* | SDF_CMD_WRITE */ ;
-                       s->n_chan = 3;
-                       s->maxdata = 0xffffffff;
-                       s->insn_read = ni_660x_GPCT_rinsn;
-                       s->insn_write = ni_660x_GPCT_winsn;
-                       s->insn_config = ni_660x_GPCT_insn_config;
-                       s->do_cmd = &ni_660x_cmd;
-                       s->len_chanlist = 1;
-                       s->do_cmdtest = &ni_660x_cmdtest;
-                       s->cancel = &ni_660x_cancel;
-                       s->poll = &ni_660x_input_poll;
-                       s->async_dma_dir = DMA_BIDIRECTIONAL;
-                       s->buf_change = &ni_660x_buf_change;
-                       s->private = &private(dev)->counter_dev->counters[i];
-
-                       private(dev)->counter_dev->counters[i].chip_index =
-                           i / counters_per_chip;
-                       private(dev)->counter_dev->counters[i].counter_index =
-                           i % counters_per_chip;
-               } else {
-                       s->type = COMEDI_SUBD_UNUSED;
-               }
-       }
-       for (i = 0; i < board(dev)->n_chips; ++i)
-               init_tio_chip(dev, i);
-
-       for (i = 0; i < ni_660x_num_counters(dev); ++i)
-               ni_tio_init_counter(&private(dev)->counter_dev->counters[i]);
-
-       for (i = 0; i < NUM_PFI_CHANNELS; ++i) {
-               if (i < min_counter_pfi_chan)
-                       ni_660x_set_pfi_routing(dev, i, pfi_output_select_do);
-               else
-                       ni_660x_set_pfi_routing(dev, i,
-                                               pfi_output_select_counter);
-               ni_660x_select_pfi_output(dev, i, pfi_output_select_high_Z);
-       }
-       /* to be safe, set counterswap bits on tio chips after all the counter
-          outputs have been set to high impedance mode */
-       for (i = 0; i < board(dev)->n_chips; ++i)
-               set_tio_counterswap(dev, i);
-
-       ret = request_irq(mite_irq(private(dev)->mite), ni_660x_interrupt,
-                         IRQF_SHARED, "ni_660x", dev);
-       if (ret < 0) {
-               dev_warn(dev->class_dev, " irq not available\n");
-               return ret;
-       }
-       dev->irq = mite_irq(private(dev)->mite);
-       global_interrupt_config_bits = Global_Int_Enable_Bit;
-       if (board(dev)->n_chips > 1)
-               global_interrupt_config_bits |= Cascade_Int_Enable_Bit;
-       ni_660x_write_register(dev, 0, global_interrupt_config_bits,
-                              GlobalInterruptConfigRegister);
-       dev_info(dev->class_dev, "ni_660x: %s attached\n", dev->board_name);
-       return 0;
-}
-
-static void ni_660x_detach(struct comedi_device *dev)
-{
-       if (dev->irq)
-               free_irq(dev->irq, dev);
-       if (dev->private) {
-               if (private(dev)->counter_dev)
-                       ni_gpct_device_destroy(private(dev)->counter_dev);
-               if (private(dev)->mite) {
-                       ni_660x_free_mite_rings(dev);
-                       mite_unsetup(private(dev)->mite);
-                       mite_free(private(dev)->mite);
-               }
-       }
-}
-
 static int
 ni_660x_GPCT_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
                   struct comedi_insn *insn, unsigned int *data)
@@ -1196,17 +994,17 @@ ni_660x_GPCT_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
 
 static void init_tio_chip(struct comedi_device *dev, int chipset)
 {
+       struct ni_660x_private *devpriv = dev->private;
        unsigned i;
 
        /*  init dma configuration register */
-       private(dev)->dma_configuration_soft_copies[chipset] = 0;
+       devpriv->dma_configuration_soft_copies[chipset] = 0;
        for (i = 0; i < MAX_DMA_CHANNEL; ++i) {
-               private(dev)->dma_configuration_soft_copies[chipset] |=
+               devpriv->dma_configuration_soft_copies[chipset] |=
                    dma_select_bits(i, dma_selection_none) & dma_select_mask(i);
        }
        ni_660x_write_register(dev, chipset,
-                              private(dev)->
-                              dma_configuration_soft_copies[chipset],
+                              devpriv->dma_configuration_soft_copies[chipset],
                               DMAConfigRegister);
        for (i = 0; i < NUM_PFI_CHANNELS; ++i)
                ni_660x_write_register(dev, chipset, 0, IOConfigReg(i));
@@ -1251,6 +1049,7 @@ static void ni_660x_select_pfi_output(struct comedi_device *dev,
                                      unsigned pfi_channel,
                                      unsigned output_select)
 {
+       const struct ni_660x_board *board = comedi_board(dev);
        static const unsigned counter_4_7_first_pfi = 8;
        static const unsigned counter_4_7_last_pfi = 23;
        unsigned active_chipset = 0;
@@ -1258,7 +1057,7 @@ static void ni_660x_select_pfi_output(struct comedi_device *dev,
        unsigned active_bits;
        unsigned idle_bits;
 
-       if (board(dev)->n_chips > 1) {
+       if (board->n_chips > 1) {
                if (output_select == pfi_output_select_counter &&
                    pfi_channel >= counter_4_7_first_pfi &&
                    pfi_channel <= counter_4_7_last_pfi) {
@@ -1294,6 +1093,8 @@ static void ni_660x_select_pfi_output(struct comedi_device *dev,
 static int ni_660x_set_pfi_routing(struct comedi_device *dev, unsigned chan,
                                   unsigned source)
 {
+       struct ni_660x_private *devpriv = dev->private;
+
        if (source > num_pfi_output_selects)
                return -EINVAL;
        if (source == pfi_output_select_high_Z)
@@ -1305,76 +1106,248 @@ static int ni_660x_set_pfi_routing(struct comedi_device *dev, unsigned chan,
                if (source == pfi_output_select_do)
                        return -EINVAL;
        }
-       BUG_ON(chan >= NUM_PFI_CHANNELS);
 
-       private(dev)->pfi_output_selects[chan] = source;
-       if (private(dev)->pfi_direction_bits & (((uint64_t) 1) << chan))
+       devpriv->pfi_output_selects[chan] = source;
+       if (devpriv->pfi_direction_bits & (((uint64_t) 1) << chan))
                ni_660x_select_pfi_output(dev, chan,
-                                         private(dev)->
-                                         pfi_output_selects[chan]);
+                                         devpriv->pfi_output_selects[chan]);
        return 0;
 }
 
-static unsigned ni_660x_get_pfi_routing(struct comedi_device *dev,
-                                       unsigned chan)
-{
-       BUG_ON(chan >= NUM_PFI_CHANNELS);
-       return private(dev)->pfi_output_selects[chan];
-}
-
-static void ni660x_config_filter(struct comedi_device *dev,
-                                unsigned pfi_channel,
-                                enum ni_gpct_filter_select filter)
-{
-       unsigned bits = ni_660x_read_register(dev, 0, IOConfigReg(pfi_channel));
-       bits &= ~pfi_input_select_mask(pfi_channel);
-       bits |= pfi_input_select_bits(pfi_channel, filter);
-       ni_660x_write_register(dev, 0, bits, IOConfigReg(pfi_channel));
-}
-
 static int ni_660x_dio_insn_config(struct comedi_device *dev,
                                   struct comedi_subdevice *s,
-                                  struct comedi_insn *insn, unsigned int *data)
+                                  struct comedi_insn *insn,
+                                  unsigned int *data)
 {
-       int chan = CR_CHAN(insn->chanspec);
-
-       /* The input or output configuration of each digital line is
-        * configured by a special insn_config instruction.  chanspec
-        * contains the channel to be changed, and data[0] contains the
-        * value COMEDI_INPUT or COMEDI_OUTPUT. */
+       struct ni_660x_private *devpriv = dev->private;
+       unsigned int chan = CR_CHAN(insn->chanspec);
+       uint64_t bit = 1ULL << chan;
+       unsigned int val;
+       int ret;
 
        switch (data[0]) {
        case INSN_CONFIG_DIO_OUTPUT:
-               private(dev)->pfi_direction_bits |= ((uint64_t) 1) << chan;
+               devpriv->pfi_direction_bits |= bit;
                ni_660x_select_pfi_output(dev, chan,
-                                         private(dev)->
-                                         pfi_output_selects[chan]);
+                                         devpriv->pfi_output_selects[chan]);
                break;
+
        case INSN_CONFIG_DIO_INPUT:
-               private(dev)->pfi_direction_bits &= ~(((uint64_t) 1) << chan);
+               devpriv->pfi_direction_bits &= ~bit;
                ni_660x_select_pfi_output(dev, chan, pfi_output_select_high_Z);
                break;
+
        case INSN_CONFIG_DIO_QUERY:
-               data[1] =
-                   (private(dev)->pfi_direction_bits &
-                    (((uint64_t) 1) << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT;
-               return 0;
+               data[1] = (devpriv->pfi_direction_bits & bit) ? COMEDI_OUTPUT
+                                                             : COMEDI_INPUT;
+               break;
+
        case INSN_CONFIG_SET_ROUTING:
-               return ni_660x_set_pfi_routing(dev, chan, data[1]);
+               ret = ni_660x_set_pfi_routing(dev, chan, data[1]);
+               if (ret)
+                       return ret;
                break;
+
        case INSN_CONFIG_GET_ROUTING:
-               data[1] = ni_660x_get_pfi_routing(dev, chan);
+               data[1] = devpriv->pfi_output_selects[chan];
                break;
+
        case INSN_CONFIG_FILTER:
-               ni660x_config_filter(dev, chan, data[1]);
+               val = ni_660x_read_register(dev, 0, IOConfigReg(chan));
+               val &= ~pfi_input_select_mask(chan);
+               val |= pfi_input_select_bits(chan, data[1]);
+               ni_660x_write_register(dev, 0, val, IOConfigReg(chan));
                break;
+
        default:
                return -EINVAL;
-               break;
        }
+
+       return insn->n;
+}
+
+static int __devinit ni_660x_attach_pci(struct comedi_device *dev,
+                                       struct pci_dev *pcidev)
+{
+       const struct ni_660x_board *board;
+       struct ni_660x_private *devpriv;
+       struct comedi_subdevice *s;
+       int ret;
+       unsigned i;
+       unsigned global_interrupt_config_bits;
+
+       ret = ni_660x_allocate_private(dev);
+       if (ret < 0)
+               return ret;
+       devpriv = dev->private;
+
+       dev->board_ptr = ni_660x_find_boardinfo(pcidev);
+       if (!dev->board_ptr)
+               return -ENODEV;
+       board = comedi_board(dev);
+
+       devpriv->mite = mite_alloc(pcidev);
+       if (!devpriv->mite)
+               return -ENOMEM;
+
+       dev->board_name = board->name;
+
+       ret = mite_setup2(devpriv->mite, 1);
+       if (ret < 0) {
+               dev_warn(dev->class_dev, "error setting up mite\n");
+               return ret;
+       }
+
+       ret = ni_660x_alloc_mite_rings(dev);
+       if (ret < 0)
+               return ret;
+
+       ret = comedi_alloc_subdevices(dev, 2 + NI_660X_MAX_NUM_COUNTERS);
+       if (ret)
+               return ret;
+
+       s = &dev->subdevices[0];
+       /* Old GENERAL-PURPOSE COUNTER/TIME (GPCT) subdevice, no longer used */
+       s->type = COMEDI_SUBD_UNUSED;
+
+       s = &dev->subdevices[NI_660X_DIO_SUBDEV];
+       /* DIGITAL I/O SUBDEVICE */
+       s->type = COMEDI_SUBD_DIO;
+       s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
+       s->n_chan = NUM_PFI_CHANNELS;
+       s->maxdata = 1;
+       s->range_table = &range_digital;
+       s->insn_bits = ni_660x_dio_insn_bits;
+       s->insn_config = ni_660x_dio_insn_config;
+       s->io_bits = 0;         /* all bits default to input */
+       /*  we use the ioconfig registers to control dio direction, so zero
+       output enables in stc dio control reg */
+       ni_660x_write_register(dev, 0, 0, STCDIOControl);
+
+       devpriv->counter_dev = ni_gpct_device_construct(dev,
+                                                    &ni_gpct_write_register,
+                                                    &ni_gpct_read_register,
+                                                    ni_gpct_variant_660x,
+                                                    ni_660x_num_counters
+                                                    (dev));
+       if (devpriv->counter_dev == NULL)
+               return -ENOMEM;
+       for (i = 0; i < NI_660X_MAX_NUM_COUNTERS; ++i) {
+               s = &dev->subdevices[NI_660X_GPCT_SUBDEV(i)];
+               if (i < ni_660x_num_counters(dev)) {
+                       s->type = COMEDI_SUBD_COUNTER;
+                       s->subdev_flags =
+                           SDF_READABLE | SDF_WRITABLE | SDF_LSAMPL |
+                           SDF_CMD_READ /* | SDF_CMD_WRITE */ ;
+                       s->n_chan = 3;
+                       s->maxdata = 0xffffffff;
+                       s->insn_read = ni_660x_GPCT_rinsn;
+                       s->insn_write = ni_660x_GPCT_winsn;
+                       s->insn_config = ni_660x_GPCT_insn_config;
+                       s->do_cmd = &ni_660x_cmd;
+                       s->len_chanlist = 1;
+                       s->do_cmdtest = &ni_660x_cmdtest;
+                       s->cancel = &ni_660x_cancel;
+                       s->poll = &ni_660x_input_poll;
+                       s->async_dma_dir = DMA_BIDIRECTIONAL;
+                       s->buf_change = &ni_660x_buf_change;
+                       s->private = &devpriv->counter_dev->counters[i];
+
+                       devpriv->counter_dev->counters[i].chip_index =
+                           i / counters_per_chip;
+                       devpriv->counter_dev->counters[i].counter_index =
+                           i % counters_per_chip;
+               } else {
+                       s->type = COMEDI_SUBD_UNUSED;
+               }
+       }
+       for (i = 0; i < board->n_chips; ++i)
+               init_tio_chip(dev, i);
+
+       for (i = 0; i < ni_660x_num_counters(dev); ++i)
+               ni_tio_init_counter(&devpriv->counter_dev->counters[i]);
+
+       for (i = 0; i < NUM_PFI_CHANNELS; ++i) {
+               if (i < min_counter_pfi_chan)
+                       ni_660x_set_pfi_routing(dev, i, pfi_output_select_do);
+               else
+                       ni_660x_set_pfi_routing(dev, i,
+                                               pfi_output_select_counter);
+               ni_660x_select_pfi_output(dev, i, pfi_output_select_high_Z);
+       }
+       /* to be safe, set counterswap bits on tio chips after all the counter
+          outputs have been set to high impedance mode */
+       for (i = 0; i < board->n_chips; ++i)
+               set_tio_counterswap(dev, i);
+
+       ret = request_irq(mite_irq(devpriv->mite), ni_660x_interrupt,
+                         IRQF_SHARED, "ni_660x", dev);
+       if (ret < 0) {
+               dev_warn(dev->class_dev, " irq not available\n");
+               return ret;
+       }
+       dev->irq = mite_irq(devpriv->mite);
+       global_interrupt_config_bits = Global_Int_Enable_Bit;
+       if (board->n_chips > 1)
+               global_interrupt_config_bits |= Cascade_Int_Enable_Bit;
+       ni_660x_write_register(dev, 0, global_interrupt_config_bits,
+                              GlobalInterruptConfigRegister);
+       dev_info(dev->class_dev, "ni_660x: %s attached\n", dev->board_name);
        return 0;
 }
 
+static void ni_660x_detach(struct comedi_device *dev)
+{
+       struct ni_660x_private *devpriv = dev->private;
+
+       if (dev->irq)
+               free_irq(dev->irq, dev);
+       if (devpriv) {
+               if (devpriv->counter_dev)
+                       ni_gpct_device_destroy(devpriv->counter_dev);
+               if (devpriv->mite) {
+                       ni_660x_free_mite_rings(dev);
+                       mite_unsetup(devpriv->mite);
+                       mite_free(devpriv->mite);
+               }
+       }
+}
+
+static struct comedi_driver ni_660x_driver = {
+       .driver_name    = "ni_660x",
+       .module         = THIS_MODULE,
+       .attach_pci     = ni_660x_attach_pci,
+       .detach         = ni_660x_detach,
+};
+
+static int __devinit ni_660x_pci_probe(struct pci_dev *dev,
+                                      const struct pci_device_id *ent)
+{
+       return comedi_pci_auto_config(dev, &ni_660x_driver);
+}
+
+static void __devexit ni_660x_pci_remove(struct pci_dev *dev)
+{
+       comedi_pci_auto_unconfig(dev);
+}
+
+static DEFINE_PCI_DEVICE_TABLE(ni_660x_pci_table) = {
+       {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2c60)},
+       {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1310)},
+       {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1360)},
+       {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2cc0)},
+       {0}
+};
+MODULE_DEVICE_TABLE(pci, ni_660x_pci_table);
+
+static struct pci_driver ni_660x_pci_driver = {
+       .name           = "ni_660x",
+       .id_table       = ni_660x_pci_table,
+       .probe          = ni_660x_pci_probe,
+       .remove         = __devexit_p(ni_660x_pci_remove),
+};
+module_comedi_pci_driver(ni_660x_driver, ni_660x_pci_driver);
+
 MODULE_AUTHOR("Comedi http://www.comedi.org");
 MODULE_DESCRIPTION("Comedi low-level driver");
 MODULE_LICENSE("GPL");
index eac6dc047bb0a56d3004d822feaa5a7fa8f84681..2cf4907c366acc4f6ad5ac1f803994d9ece32dc9 100644 (file)
@@ -210,10 +210,11 @@ static int __devinit ni_670x_attach_pci(struct comedi_device *dev,
        int ret;
        int i;
 
-       ret = alloc_private(dev, sizeof(*devpriv));
-       if (ret < 0)
-               return ret;
-       devpriv = dev->private;
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
+               return -ENOMEM;
+       dev->private = devpriv;
+
        dev->board_ptr = ni_670x_find_boardinfo(pcidev);
        if (!dev->board_ptr)
                return -ENODEV;
index 83950807b672a4bcbe08a3f0a957ad49a4e6352c..0222def373c2f881248ce5eea3b5af0756576328 100644 (file)
@@ -169,8 +169,6 @@ struct a2150_private {
        int config_bits;        /*  config register bits */
 };
 
-#define devpriv ((struct a2150_private *)dev->private)
-
 static int a2150_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
 
 static int a2150_get_timing(struct comedi_device *dev, unsigned int *period,
@@ -182,6 +180,8 @@ static int a2150_set_chanlist(struct comedi_device *dev,
 
 static void ni_dump_regs(struct comedi_device *dev)
 {
+       struct a2150_private *devpriv = dev->private;
+
        printk("config bits 0x%x\n", devpriv->config_bits);
        printk("irq dma bits 0x%x\n", devpriv->irq_dma_bits);
        printk("status bits 0x%x\n", inw(dev->iobase + STATUS_REG));
@@ -196,6 +196,7 @@ static irqreturn_t a2150_interrupt(int irq, void *d)
        int status;
        unsigned long flags;
        struct comedi_device *dev = d;
+       struct a2150_private *devpriv = dev->private;
        struct comedi_subdevice *s = dev->read_subdev;
        struct comedi_async *async;
        struct comedi_cmd *cmd;
@@ -300,6 +301,8 @@ static irqreturn_t a2150_interrupt(int irq, void *d)
 
 static int a2150_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+       struct a2150_private *devpriv = dev->private;
+
        /*  disable dma on card */
        devpriv->irq_dma_bits &= ~DMA_INTR_EN_BIT & ~DMA_EN_BIT;
        outw(devpriv->irq_dma_bits, dev->iobase + IRQ_DMA_CNTRL_REG);
@@ -425,6 +428,7 @@ static int a2150_ai_cmdtest(struct comedi_device *dev,
 
 static int a2150_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+       struct a2150_private *devpriv = dev->private;
        struct comedi_async *async = s->async;
        struct comedi_cmd *cmd = &async->cmd;
        unsigned long lock_flags;
@@ -536,6 +540,7 @@ static int a2150_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 static int a2150_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
                          struct comedi_insn *insn, unsigned int *data)
 {
+       struct a2150_private *devpriv = dev->private;
        unsigned int i, n;
        static const int timeout = 100000;
        static const int filter_delay = 36;
@@ -615,6 +620,7 @@ static int a2150_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
 static int a2150_get_timing(struct comedi_device *dev, unsigned int *period,
                            int flags)
 {
+       struct a2150_private *devpriv = dev->private;
        int lub, glb, temp;
        int lub_divisor_shift, lub_index, glb_divisor_shift, glb_index;
        int i, j;
@@ -689,6 +695,8 @@ static int a2150_set_chanlist(struct comedi_device *dev,
                              unsigned int start_channel,
                              unsigned int num_channels)
 {
+       struct a2150_private *devpriv = dev->private;
+
        if (start_channel + num_channels > 4)
                return -1;
 
@@ -727,6 +735,7 @@ static int a2150_probe(struct comedi_device *dev)
 
 static int a2150_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
+       struct a2150_private *devpriv;
        struct comedi_subdevice *s;
        unsigned long iobase = it->options[0];
        unsigned int irq = it->options[1];
@@ -749,9 +758,10 @@ static int a2150_attach(struct comedi_device *dev, struct comedi_devconfig *it)
        }
        printk("\n");
 
-       /* allocate and initialize dev->private */
-       if (alloc_private(dev, sizeof(struct a2150_private)) < 0)
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
                return -ENOMEM;
+       dev->private = devpriv;
 
        if (iobase == 0) {
                printk(" io base address required\n");
@@ -855,6 +865,8 @@ static int a2150_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 
 static void a2150_detach(struct comedi_device *dev)
 {
+       struct a2150_private *devpriv = dev->private;
+
        if (dev->iobase) {
                outw(APD_BIT | DPD_BIT, dev->iobase + CONFIG_REG);
                release_region(dev->iobase, A2150_SIZE);
index 93938cec93e789043a07f59c31e5aea9beac167f..907f65cdbdc0bc60a5504941f457f24370f737cf 100644 (file)
@@ -167,10 +167,10 @@ struct atao_private {
        unsigned int ao_readback[10];
 };
 
-#define devpriv ((struct atao_private *)dev->private)
-
 static void atao_reset(struct comedi_device *dev)
 {
+       struct atao_private *devpriv = dev->private;
+
        /* This is the reset sequence described in the manual */
 
        devpriv->cfg1 = 0;
@@ -202,6 +202,7 @@ static void atao_reset(struct comedi_device *dev)
 static int atao_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
                         struct comedi_insn *insn, unsigned int *data)
 {
+       struct atao_private *devpriv = dev->private;
        int i;
        int chan = CR_CHAN(insn->chanspec);
        short bits;
@@ -226,6 +227,7 @@ static int atao_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
 static int atao_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
                         struct comedi_insn *insn, unsigned int *data)
 {
+       struct atao_private *devpriv = dev->private;
        int i;
        int chan = CR_CHAN(insn->chanspec);
 
@@ -254,6 +256,7 @@ static int atao_dio_insn_config(struct comedi_device *dev,
                                struct comedi_subdevice *s,
                                struct comedi_insn *insn, unsigned int *data)
 {
+       struct atao_private *devpriv = dev->private;
        int chan = CR_CHAN(insn->chanspec);
        unsigned int mask, bit;
 
@@ -309,6 +312,7 @@ static int atao_calib_insn_write(struct comedi_device *dev,
                                 struct comedi_subdevice *s,
                                 struct comedi_insn *insn, unsigned int *data)
 {
+       struct atao_private *devpriv = dev->private;
        unsigned int bitstring, bit;
        unsigned int chan = CR_CHAN(insn->chanspec);
 
@@ -331,6 +335,7 @@ static int atao_calib_insn_write(struct comedi_device *dev,
 static int atao_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
        const struct atao_board *board = comedi_board(dev);
+       struct atao_private *devpriv;
        struct comedi_subdevice *s;
        unsigned long iobase;
        int ao_unipolar;
@@ -351,8 +356,10 @@ static int atao_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 
        dev->board_name = board->name;
 
-       if (alloc_private(dev, sizeof(struct atao_private)) < 0)
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
                return -ENOMEM;
+       dev->private = devpriv;
 
        ret = comedi_alloc_subdevices(dev, 4);
        if (ret)
index cac25572f6bb436b94a45186986de1af331f2c28..2cc29965e157c44a28aed0aac14e0cc0ae73ca7c 100644 (file)
@@ -284,8 +284,6 @@ struct ni_private {
 
 };
 
-#define devpriv ((struct ni_private *)dev->private)
-
 /* How we access registers */
 
 #define ni_writel(a, b)                (outl((a), (b)+dev->iobase))
@@ -303,6 +301,7 @@ struct ni_private {
 
 static void ni_atmio_win_out(struct comedi_device *dev, uint16_t data, int addr)
 {
+       struct ni_private *devpriv = dev->private;
        unsigned long flags;
 
        spin_lock_irqsave(&devpriv->window_lock, flags);
@@ -317,6 +316,7 @@ static void ni_atmio_win_out(struct comedi_device *dev, uint16_t data, int addr)
 
 static uint16_t ni_atmio_win_in(struct comedi_device *dev, int addr)
 {
+       struct ni_private *devpriv = dev->private;
        unsigned long flags;
        uint16_t ret;
 
@@ -406,16 +406,17 @@ static int ni_getboardtype(struct comedi_device *dev)
 static int ni_atmio_attach(struct comedi_device *dev,
                           struct comedi_devconfig *it)
 {
+       struct ni_private *devpriv;
        struct pnp_dev *isapnp_dev;
        int ret;
        unsigned long iobase;
        int board;
        unsigned int irq;
 
-       /* allocate private area */
        ret = ni_alloc_private(dev);
-       if (ret < 0)
+       if (ret)
                return ret;
+       devpriv = dev->private;
 
        devpriv->stc_writew = &ni_atmio_win_out;
        devpriv->stc_readw = &ni_atmio_win_in;
@@ -499,6 +500,8 @@ static int ni_atmio_attach(struct comedi_device *dev,
 
 static void ni_atmio_detach(struct comedi_device *dev)
 {
+       struct ni_private *devpriv = dev->private;
+
        mio_common_detach(dev);
        if (dev->iobase)
                release_region(dev->iobase, NI_SIZE);
index e91a620f9db314d3864170c8033351e958b868d1..a3884b4d90c699a72e53060fd3c2b135631573cf 100644 (file)
@@ -102,7 +102,6 @@ Devices: [National Instruments] AT-MIO-16 (atmio16), AT-MIO-16D (atmio16d)
 #define CLOCK_100_HZ   0x8F25
 /* Other miscellaneous defines */
 #define ATMIO16D_SIZE  32      /* bus address range */
-#define devpriv ((struct atmio16d_private *)dev->private)
 #define ATMIO16D_TIMEOUT 10
 
 struct atmio16_board_t {
@@ -202,6 +201,7 @@ static void reset_counters(struct comedi_device *dev)
 
 static void reset_atmio16d(struct comedi_device *dev)
 {
+       struct atmio16d_private *devpriv = dev->private;
        int i;
 
        /* now we need to initialize the board */
@@ -327,6 +327,7 @@ static int atmio16d_ai_cmdtest(struct comedi_device *dev,
 static int atmio16d_ai_cmd(struct comedi_device *dev,
                           struct comedi_subdevice *s)
 {
+       struct atmio16d_private *devpriv = dev->private;
        struct comedi_cmd *cmd = &s->async->cmd;
        unsigned int timer, base_clock;
        unsigned int sample_count, tmp, chan, gain;
@@ -486,6 +487,7 @@ static int atmio16d_ai_insn_read(struct comedi_device *dev,
                                 struct comedi_subdevice *s,
                                 struct comedi_insn *insn, unsigned int *data)
 {
+       struct atmio16d_private *devpriv = dev->private;
        int i, t;
        int chan;
        int gain;
@@ -539,6 +541,7 @@ static int atmio16d_ao_insn_read(struct comedi_device *dev,
                                 struct comedi_subdevice *s,
                                 struct comedi_insn *insn, unsigned int *data)
 {
+       struct atmio16d_private *devpriv = dev->private;
        int i;
 
        for (i = 0; i < insn->n; i++)
@@ -550,6 +553,7 @@ static int atmio16d_ao_insn_write(struct comedi_device *dev,
                                  struct comedi_subdevice *s,
                                  struct comedi_insn *insn, unsigned int *data)
 {
+       struct atmio16d_private *devpriv = dev->private;
        int i;
        int chan;
        int d;
@@ -596,6 +600,7 @@ static int atmio16d_dio_insn_config(struct comedi_device *dev,
                                    struct comedi_insn *insn,
                                    unsigned int *data)
 {
+       struct atmio16d_private *devpriv = dev->private;
        int i;
        int mask;
 
@@ -651,6 +656,7 @@ static int atmio16d_attach(struct comedi_device *dev,
                           struct comedi_devconfig *it)
 {
        const struct atmio16_board_t *board = comedi_board(dev);
+       struct atmio16d_private *devpriv;
        unsigned int irq;
        unsigned long iobase;
        int ret;
@@ -672,9 +678,10 @@ static int atmio16d_attach(struct comedi_device *dev,
        if (ret)
                return ret;
 
-       ret = alloc_private(dev, sizeof(struct atmio16d_private));
-       if (ret < 0)
-               return ret;
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
+               return -ENOMEM;
+       dev->private = devpriv;
 
        /* reset the atmio16d hardware */
        reset_atmio16d(dev);
index 2ba0ade45c6484b940b1ed9559a4bd85f96e5a84..68d7c6a5db7dac901fd2f208f923106930c3553f 100644 (file)
@@ -95,7 +95,7 @@ static int daq700_dio_insn_bits(struct comedi_device *dev,
        }
 
        data[1] = s->state & 0xff;
-       data[1] |= inb(dev->iobase + DIO_R);
+       data[1] |= inb(dev->iobase + DIO_R) << 8;
 
        return insn->n;
 }
index 0ca222bbcbe6bb3100966a1522ebb4d951435ce0..7b333353c5d9707baee59322036ce8e25ae9d6c2 100644 (file)
@@ -96,8 +96,6 @@ struct dio24_private {
        int data;               /* number of data points left to be taken */
 };
 
-#define devpriv ((struct dio24_private *)dev->private)
-
 static struct comedi_driver driver_dio24 = {
        .driver_name = "ni_daq_dio24",
        .module = THIS_MODULE,
@@ -110,6 +108,7 @@ static struct comedi_driver driver_dio24 = {
 
 static int dio24_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
+       struct dio24_private *devpriv;
        struct comedi_subdevice *s;
        unsigned long iobase = 0;
 #ifdef incomplete
@@ -118,9 +117,10 @@ static int dio24_attach(struct comedi_device *dev, struct comedi_devconfig *it)
        struct pcmcia_device *link;
        int ret;
 
-       /* allocate and initialize dev->private */
-       if (alloc_private(dev, sizeof(struct dio24_private)) < 0)
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
                return -ENOMEM;
+       dev->private = devpriv;
 
        /*  get base address, irq etc. based on bustype */
        switch (thisboard->bustype) {
@@ -202,7 +202,7 @@ static int dio24_cs_attach(struct pcmcia_device *link)
 {
        struct local_info_t *local;
 
-       printk(KERN_INFO "ni_daq_dio24: HOLA SOY YO - CS-attach!\n");
+       dev_info(&link->dev, "ni_daq_dio24: HOLA SOY YO - CS-attach!\n");
 
        dev_dbg(&link->dev, "dio24_cs_attach()\n");
 
@@ -242,7 +242,7 @@ static void dio24_config(struct pcmcia_device *link)
 {
        int ret;
 
-       printk(KERN_INFO "ni_daq_dio24: HOLA SOY YO! - config\n");
+       dev_info(&link->dev, "ni_daq_dio24: HOLA SOY YO! - config\n");
 
        dev_dbg(&link->dev, "dio24_config\n");
 
@@ -265,7 +265,7 @@ static void dio24_config(struct pcmcia_device *link)
        return;
 
 failed:
-       printk(KERN_INFO "Fallo");
+       dev_info(&link->dev, "Fallo");
        dio24_release(link);
 
 }                              /* dio24_config */
index 28b91a6c378908ba2f30b01b88a11d819b3dd9f7..ab51c2678b9d425762d182951d6a183ba0cb585f 100644 (file)
@@ -487,8 +487,6 @@ static const int dma_buffer_size = 0xff00;
 /* 2 bytes per sample */
 static const int sample_size = 2;
 
-#define devpriv ((struct labpc_private *)dev->private)
-
 static inline int labpc_counter_load(struct comedi_device *dev,
                                     unsigned long base_address,
                                     unsigned int counter_number,
@@ -504,6 +502,7 @@ static inline int labpc_counter_load(struct comedi_device *dev,
 int labpc_common_attach(struct comedi_device *dev, unsigned long iobase,
                        unsigned int irq, unsigned int dma_chan)
 {
+       struct labpc_private *devpriv = dev->private;
        struct comedi_subdevice *s;
        int i;
        unsigned long isr_flags;
@@ -700,15 +699,19 @@ labpc_pci_find_boardinfo(struct pci_dev *pcidev)
 static int __devinit labpc_attach_pci(struct comedi_device *dev,
                                      struct pci_dev *pcidev)
 {
+       struct labpc_private *devpriv;
        unsigned long iobase;
        unsigned int irq;
        int ret;
 
        if (!IS_ENABLED(CONFIG_COMEDI_PCI_DRIVERS))
                return -ENODEV;
-       ret = alloc_private(dev, sizeof(struct labpc_private));
-       if (ret < 0)
-               return ret;
+
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
+               return -ENOMEM;
+       dev->private = devpriv;
+
        dev->board_ptr = labpc_pci_find_boardinfo(pcidev);
        if (!dev->board_ptr)
                return -ENODEV;
@@ -725,13 +728,15 @@ static int __devinit labpc_attach_pci(struct comedi_device *dev,
 
 static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
+       struct labpc_private *devpriv;
        unsigned long iobase = 0;
        unsigned int irq = 0;
        unsigned int dma_chan = 0;
 
-       /* allocate and initialize dev->private */
-       if (alloc_private(dev, sizeof(struct labpc_private)) < 0)
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
                return -ENOMEM;
+       dev->private = devpriv;
 
        /* get base address, irq etc. based on bustype */
        switch (thisboard->bustype) {
@@ -770,8 +775,11 @@ static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 
 void labpc_common_detach(struct comedi_device *dev)
 {
+       struct labpc_private *devpriv = dev->private;
        struct comedi_subdevice *s;
 
+       if (!thisboard)
+               return;
        if (dev->subdevices) {
                s = &dev->subdevices[2];
                subdev_8255_cleanup(dev, s);
@@ -797,6 +805,8 @@ EXPORT_SYMBOL_GPL(labpc_common_detach);
 
 static void labpc_clear_adc_fifo(const struct comedi_device *dev)
 {
+       struct labpc_private *devpriv = dev->private;
+
        devpriv->write_byte(0x1, dev->iobase + ADC_CLEAR_REG);
        devpriv->read_byte(dev->iobase + ADC_FIFO_REG);
        devpriv->read_byte(dev->iobase + ADC_FIFO_REG);
@@ -804,6 +814,7 @@ static void labpc_clear_adc_fifo(const struct comedi_device *dev)
 
 static int labpc_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+       struct labpc_private *devpriv = dev->private;
        unsigned long flags;
 
        spin_lock_irqsave(&dev->spinlock, flags);
@@ -1096,6 +1107,7 @@ static int labpc_ai_cmdtest(struct comedi_device *dev,
 
 static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+       struct labpc_private *devpriv = dev->private;
        int channel, range, aref;
 #ifdef CONFIG_ISA_DMA_API
        unsigned long irq_flags;
@@ -1363,6 +1375,7 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 static irqreturn_t labpc_interrupt(int irq, void *d)
 {
        struct comedi_device *dev = d;
+       struct labpc_private *devpriv = dev->private;
        struct comedi_subdevice *s = dev->read_subdev;
        struct comedi_async *async;
        struct comedi_cmd *cmd;
@@ -1451,6 +1464,7 @@ static irqreturn_t labpc_interrupt(int irq, void *d)
 /* read all available samples from ai fifo */
 static int labpc_drain_fifo(struct comedi_device *dev)
 {
+       struct labpc_private *devpriv = dev->private;
        unsigned int lsb, msb;
        short data;
        struct comedi_async *async = dev->read_subdev->async;
@@ -1486,6 +1500,7 @@ static int labpc_drain_fifo(struct comedi_device *dev)
 #ifdef CONFIG_ISA_DMA_API
 static void labpc_drain_dma(struct comedi_device *dev)
 {
+       struct labpc_private *devpriv = dev->private;
        struct comedi_subdevice *s = dev->read_subdev;
        struct comedi_async *async = s->async;
        int status;
@@ -1539,6 +1554,8 @@ static void labpc_drain_dma(struct comedi_device *dev)
 
 static void handle_isa_dma(struct comedi_device *dev)
 {
+       struct labpc_private *devpriv = dev->private;
+
        labpc_drain_dma(dev);
 
        enable_dma(devpriv->dma_chan);
@@ -1553,6 +1570,8 @@ static void handle_isa_dma(struct comedi_device *dev)
 static void labpc_drain_dregs(struct comedi_device *dev)
 {
 #ifdef CONFIG_ISA_DMA_API
+       struct labpc_private *devpriv = dev->private;
+
        if (devpriv->current_transfer == isa_dma_transfer)
                labpc_drain_dma(dev);
 #endif
@@ -1563,6 +1582,7 @@ static void labpc_drain_dregs(struct comedi_device *dev)
 static int labpc_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
                          struct comedi_insn *insn, unsigned int *data)
 {
+       struct labpc_private *devpriv = dev->private;
        int i, n;
        int chan, range;
        int lsb, msb;
@@ -1652,6 +1672,7 @@ static int labpc_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
 static int labpc_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
                          struct comedi_insn *insn, unsigned int *data)
 {
+       struct labpc_private *devpriv = dev->private;
        int channel, range;
        unsigned long flags;
        int lsb, msb;
@@ -1693,6 +1714,8 @@ static int labpc_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
 static int labpc_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
                          struct comedi_insn *insn, unsigned int *data)
 {
+       struct labpc_private *devpriv = dev->private;
+
        data[0] = devpriv->ao_value[CR_CHAN(insn->chanspec)];
 
        return 1;
@@ -1702,6 +1725,8 @@ static int labpc_calib_read_insn(struct comedi_device *dev,
                                 struct comedi_subdevice *s,
                                 struct comedi_insn *insn, unsigned int *data)
 {
+       struct labpc_private *devpriv = dev->private;
+
        data[0] = devpriv->caldac[CR_CHAN(insn->chanspec)];
 
        return 1;
@@ -1721,6 +1746,8 @@ static int labpc_eeprom_read_insn(struct comedi_device *dev,
                                  struct comedi_subdevice *s,
                                  struct comedi_insn *insn, unsigned int *data)
 {
+       struct labpc_private *devpriv = dev->private;
+
        data[0] = devpriv->eeprom_data[CR_CHAN(insn->chanspec)];
 
        return 1;
@@ -1777,6 +1804,7 @@ static unsigned int labpc_suggest_transfer_size(const struct comedi_cmd *cmd)
 static void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd,
                             enum scan_mode mode)
 {
+       struct labpc_private *devpriv = dev->private;
        /* max value for 16 bit counter in mode 2 */
        const int max_counter_value = 0x10000;
        /* min value for 16 bit counter in mode 2 */
@@ -1883,6 +1911,7 @@ static int labpc_dio_mem_callback(int dir, int port, int data,
 static void labpc_serial_out(struct comedi_device *dev, unsigned int value,
                             unsigned int value_width)
 {
+       struct labpc_private *devpriv = dev->private;
        int i;
 
        for (i = 1; i <= value_width; i++) {
@@ -1907,6 +1936,7 @@ static void labpc_serial_out(struct comedi_device *dev, unsigned int value,
 /* lowlevel read from eeprom */
 static unsigned int labpc_serial_in(struct comedi_device *dev)
 {
+       struct labpc_private *devpriv = dev->private;
        unsigned int value = 0;
        int i;
        const int value_width = 8;      /*  number of bits wide values are */
@@ -1936,6 +1966,7 @@ static unsigned int labpc_serial_in(struct comedi_device *dev)
 static unsigned int labpc_eeprom_read(struct comedi_device *dev,
                                      unsigned int address)
 {
+       struct labpc_private *devpriv = dev->private;
        unsigned int value;
        /*  bits to tell eeprom to expect a read */
        const int read_instruction = 0x3;
@@ -1968,6 +1999,7 @@ static unsigned int labpc_eeprom_read(struct comedi_device *dev,
 static int labpc_eeprom_write(struct comedi_device *dev,
                                unsigned int address, unsigned int value)
 {
+       struct labpc_private *devpriv = dev->private;
        const int write_enable_instruction = 0x6;
        const int write_instruction = 0x2;
        const int write_length = 8;     /*  8 bit write lengths to eeprom */
@@ -2025,6 +2057,7 @@ static int labpc_eeprom_write(struct comedi_device *dev,
 
 static unsigned int labpc_eeprom_read_status(struct comedi_device *dev)
 {
+       struct labpc_private *devpriv = dev->private;
        unsigned int value;
        const int read_status_instruction = 0x5;
        const int write_length = 8;     /*  8 bit write lengths to eeprom */
@@ -2054,6 +2087,8 @@ static unsigned int labpc_eeprom_read_status(struct comedi_device *dev)
 static void write_caldac(struct comedi_device *dev, unsigned int channel,
                         unsigned int value)
 {
+       struct labpc_private *devpriv = dev->private;
+
        if (value == devpriv->caldac[channel])
                return;
        devpriv->caldac[channel] = value;
index eb0417eb6d7da993798bf2f2d3d74507822eb1e8..bfe19fa7d66f6206919a8c5856682f4e71b237e7 100644 (file)
@@ -127,13 +127,15 @@ static struct comedi_driver driver_labpc_cs = {
 
 static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
+       struct labpc_private *devpriv;
        unsigned long iobase = 0;
        unsigned int irq = 0;
        struct pcmcia_device *link;
 
-       /* allocate and initialize dev->private */
-       if (alloc_private(dev, sizeof(struct labpc_private)) < 0)
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
                return -ENOMEM;
+       dev->private = devpriv;
 
        /*  get base address, irq etc. based on bustype */
        switch (thisboard->bustype) {
index 3e5fdae93163b16c525cc2a591fc0faabd3e96ad..743a9016e076015369d6692f25eac1ba19b34349 100644 (file)
@@ -410,6 +410,7 @@ static void get_last_sample_6143(struct comedi_device *dev);
 static inline void ni_set_bitfield(struct comedi_device *dev, int reg,
                                   unsigned bit_mask, unsigned bit_values)
 {
+       struct ni_private *devpriv = dev->private;
        unsigned long flags;
 
        spin_lock_irqsave(&devpriv->soft_reg_copy_lock, flags);
@@ -506,6 +507,7 @@ static inline void ni_set_gpct_dma_channel(struct comedi_device *dev,
 static inline void ni_set_cdo_dma_channel(struct comedi_device *dev,
                                          int mite_channel)
 {
+       struct ni_private *devpriv = dev->private;
        unsigned long flags;
 
        spin_lock_irqsave(&devpriv->soft_reg_copy_lock, flags);
@@ -525,6 +527,7 @@ static inline void ni_set_cdo_dma_channel(struct comedi_device *dev,
 
 static int ni_request_ai_mite_channel(struct comedi_device *dev)
 {
+       struct ni_private *devpriv = dev->private;
        unsigned long flags;
 
        spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
@@ -545,6 +548,7 @@ static int ni_request_ai_mite_channel(struct comedi_device *dev)
 
 static int ni_request_ao_mite_channel(struct comedi_device *dev)
 {
+       struct ni_private *devpriv = dev->private;
        unsigned long flags;
 
        spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
@@ -567,6 +571,7 @@ static int ni_request_gpct_mite_channel(struct comedi_device *dev,
                                        unsigned gpct_index,
                                        enum comedi_io_direction direction)
 {
+       struct ni_private *devpriv = dev->private;
        unsigned long flags;
        struct mite_channel *mite_chan;
 
@@ -595,6 +600,7 @@ static int ni_request_gpct_mite_channel(struct comedi_device *dev,
 static int ni_request_cdo_mite_channel(struct comedi_device *dev)
 {
 #ifdef PCIDMA
+       struct ni_private *devpriv = dev->private;
        unsigned long flags;
 
        spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
@@ -617,6 +623,7 @@ static int ni_request_cdo_mite_channel(struct comedi_device *dev)
 static void ni_release_ai_mite_channel(struct comedi_device *dev)
 {
 #ifdef PCIDMA
+       struct ni_private *devpriv = dev->private;
        unsigned long flags;
 
        spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
@@ -632,6 +639,7 @@ static void ni_release_ai_mite_channel(struct comedi_device *dev)
 static void ni_release_ao_mite_channel(struct comedi_device *dev)
 {
 #ifdef PCIDMA
+       struct ni_private *devpriv = dev->private;
        unsigned long flags;
 
        spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
@@ -648,6 +656,7 @@ static void ni_release_ao_mite_channel(struct comedi_device *dev)
 static void ni_release_gpct_mite_channel(struct comedi_device *dev,
                                         unsigned gpct_index)
 {
+       struct ni_private *devpriv = dev->private;
        unsigned long flags;
 
        BUG_ON(gpct_index >= NUM_GPCT);
@@ -669,6 +678,7 @@ static void ni_release_gpct_mite_channel(struct comedi_device *dev,
 static void ni_release_cdo_mite_channel(struct comedi_device *dev)
 {
 #ifdef PCIDMA
+       struct ni_private *devpriv = dev->private;
        unsigned long flags;
 
        spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
@@ -686,6 +696,8 @@ static void ni_release_cdo_mite_channel(struct comedi_device *dev)
 static void ni_e_series_enable_second_irq(struct comedi_device *dev,
                                          unsigned gpct_index, short enable)
 {
+       struct ni_private *devpriv = dev->private;
+
        if (boardtype.reg_type & ni_reg_m_series_mask)
                return;
        switch (gpct_index) {
@@ -716,6 +728,8 @@ static void ni_e_series_enable_second_irq(struct comedi_device *dev,
 
 static void ni_clear_ai_fifo(struct comedi_device *dev)
 {
+       struct ni_private *devpriv = dev->private;
+
        if (boardtype.reg_type == ni_reg_6143) {
                /*  Flush the 6143 data FIFO */
                ni_writel(0x10, AIFIFO_Control_6143);   /*  Flush fifo */
@@ -742,13 +756,17 @@ static void ni_clear_ai_fifo(struct comedi_device *dev)
 
 static void win_out2(struct comedi_device *dev, uint32_t data, int reg)
 {
+       struct ni_private *devpriv = dev->private;
+
        devpriv->stc_writew(dev, data >> 16, reg);
        devpriv->stc_writew(dev, data & 0xffff, reg + 1);
 }
 
 static uint32_t win_in2(struct comedi_device *dev, int reg)
 {
+       struct ni_private *devpriv = dev->private;
        uint32_t bits;
+
        bits = devpriv->stc_readw(dev, reg) << 16;
        bits |= devpriv->stc_readw(dev, reg + 1);
        return bits;
@@ -758,6 +776,7 @@ static uint32_t win_in2(struct comedi_device *dev, int reg)
 static inline void ni_ao_win_outw(struct comedi_device *dev, uint16_t data,
                                  int addr)
 {
+       struct ni_private *devpriv = dev->private;
        unsigned long flags;
 
        spin_lock_irqsave(&devpriv->window_lock, flags);
@@ -769,6 +788,7 @@ static inline void ni_ao_win_outw(struct comedi_device *dev, uint16_t data,
 static inline void ni_ao_win_outl(struct comedi_device *dev, uint32_t data,
                                  int addr)
 {
+       struct ni_private *devpriv = dev->private;
        unsigned long flags;
 
        spin_lock_irqsave(&devpriv->window_lock, flags);
@@ -779,6 +799,7 @@ static inline void ni_ao_win_outl(struct comedi_device *dev, uint32_t data,
 
 static inline unsigned short ni_ao_win_inw(struct comedi_device *dev, int addr)
 {
+       struct ni_private *devpriv = dev->private;
        unsigned long flags;
        unsigned short data;
 
@@ -814,6 +835,7 @@ static inline void ni_set_bits(struct comedi_device *dev, int reg,
 static irqreturn_t ni_E_interrupt(int irq, void *d)
 {
        struct comedi_device *dev = d;
+       struct ni_private *devpriv = dev->private;
        unsigned short a_status;
        unsigned short b_status;
        unsigned int ai_mite_status = 0;
@@ -872,6 +894,7 @@ static irqreturn_t ni_E_interrupt(int irq, void *d)
 #ifdef PCIDMA
 static void ni_sync_ai_dma(struct comedi_device *dev)
 {
+       struct ni_private *devpriv = dev->private;
        struct comedi_subdevice *s = &dev->subdevices[NI_AI_SUBDEV];
        unsigned long flags;
 
@@ -884,6 +907,7 @@ static void ni_sync_ai_dma(struct comedi_device *dev)
 static void mite_handle_b_linkc(struct mite_struct *mite,
                                struct comedi_device *dev)
 {
+       struct ni_private *devpriv = dev->private;
        struct comedi_subdevice *s = &dev->subdevices[NI_AO_SUBDEV];
        unsigned long flags;
 
@@ -896,6 +920,7 @@ static void mite_handle_b_linkc(struct mite_struct *mite,
 
 static int ni_ao_wait_for_dma_load(struct comedi_device *dev)
 {
+       struct ni_private *devpriv = dev->private;
        static const int timeout = 10000;
        int i;
        for (i = 0; i < timeout; i++) {
@@ -918,6 +943,8 @@ static int ni_ao_wait_for_dma_load(struct comedi_device *dev)
 #endif /* PCIDMA */
 static void ni_handle_eos(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+       struct ni_private *devpriv = dev->private;
+
        if (devpriv->aimode == AIMODE_SCAN) {
 #ifdef PCIDMA
                static const int timeout = 10;
@@ -984,6 +1011,7 @@ static void handle_gpct_interrupt(struct comedi_device *dev,
                                  unsigned short counter_index)
 {
 #ifdef PCIDMA
+       struct ni_private *devpriv = dev->private;
        struct comedi_subdevice *s;
 
        s = &dev->subdevices[NI_GPCT_SUBDEV(counter_index)];
@@ -997,6 +1025,7 @@ static void handle_gpct_interrupt(struct comedi_device *dev,
 
 static void ack_a_interrupt(struct comedi_device *dev, unsigned short a_status)
 {
+       struct ni_private *devpriv = dev->private;
        unsigned short ack = 0;
 
        if (a_status & AI_SC_TC_St) {
@@ -1019,6 +1048,7 @@ static void ack_a_interrupt(struct comedi_device *dev, unsigned short a_status)
 static void handle_a_interrupt(struct comedi_device *dev, unsigned short status,
                               unsigned ai_mite_status)
 {
+       struct ni_private *devpriv = dev->private;
        struct comedi_subdevice *s = &dev->subdevices[NI_AI_SUBDEV];
 
        /* 67xx boards don't have ai subdevice, but their gpct0 might generate an a interrupt */
@@ -1122,7 +1152,9 @@ static void handle_a_interrupt(struct comedi_device *dev, unsigned short status,
 
 static void ack_b_interrupt(struct comedi_device *dev, unsigned short b_status)
 {
+       struct ni_private *devpriv = dev->private;
        unsigned short ack = 0;
+
        if (b_status & AO_BC_TC_St) {
                ack |= AO_BC_TC_Interrupt_Ack;
        }
@@ -1151,8 +1183,10 @@ static void ack_b_interrupt(struct comedi_device *dev, unsigned short b_status)
 static void handle_b_interrupt(struct comedi_device *dev,
                               unsigned short b_status, unsigned ao_mite_status)
 {
+       struct ni_private *devpriv = dev->private;
        struct comedi_subdevice *s = &dev->subdevices[NI_AO_SUBDEV];
        /* unsigned short ack=0; */
+
 #ifdef DEBUG_INTERRUPT
        printk("ni_mio_common: interrupt: b_status=%04x m1_status=%08x\n",
               b_status, ao_mite_status);
@@ -1340,6 +1374,7 @@ static int ni_ao_fifo_half_empty(struct comedi_device *dev,
 static int ni_ao_prep_fifo(struct comedi_device *dev,
                           struct comedi_subdevice *s)
 {
+       struct ni_private *devpriv = dev->private;
        int n;
 
        /* reset fifo */
@@ -1364,6 +1399,7 @@ static int ni_ao_prep_fifo(struct comedi_device *dev,
 static void ni_ai_fifo_read(struct comedi_device *dev,
                            struct comedi_subdevice *s, int n)
 {
+       struct ni_private *devpriv = dev->private;
        struct comedi_async *async = s->async;
        int i;
 
@@ -1434,6 +1470,7 @@ static void ni_handle_fifo_half_full(struct comedi_device *dev)
 #ifdef PCIDMA
 static int ni_ai_drain_dma(struct comedi_device *dev)
 {
+       struct ni_private *devpriv = dev->private;
        int i;
        static const int timeout = 10000;
        unsigned long flags;
@@ -1471,6 +1508,7 @@ static int ni_ai_drain_dma(struct comedi_device *dev)
 */
 static void ni_handle_fifo_dregs(struct comedi_device *dev)
 {
+       struct ni_private *devpriv = dev->private;
        struct comedi_subdevice *s = &dev->subdevices[NI_AI_SUBDEV];
        short data[2];
        u32 dl;
@@ -1535,6 +1573,7 @@ static void ni_handle_fifo_dregs(struct comedi_device *dev)
 
 static void get_last_sample_611x(struct comedi_device *dev)
 {
+       struct ni_private *devpriv __maybe_unused = dev->private;
        struct comedi_subdevice *s = &dev->subdevices[NI_AI_SUBDEV];
        short data;
        u32 dl;
@@ -1552,6 +1591,7 @@ static void get_last_sample_611x(struct comedi_device *dev)
 
 static void get_last_sample_6143(struct comedi_device *dev)
 {
+       struct ni_private *devpriv __maybe_unused = dev->private;
        struct comedi_subdevice *s = &dev->subdevices[NI_AI_SUBDEV];
        short data;
        u32 dl;
@@ -1574,11 +1614,13 @@ static void ni_ai_munge(struct comedi_device *dev, struct comedi_subdevice *s,
                        void *data, unsigned int num_bytes,
                        unsigned int chan_index)
 {
+       struct ni_private *devpriv = dev->private;
        struct comedi_async *async = s->async;
        unsigned int i;
        unsigned int length = num_bytes / bytes_per_sample(s);
        short *array = data;
        unsigned int *larray = data;
+
        for (i = 0; i < length; i++) {
 #ifdef PCIDMA
                if (s->subdev_flags & SDF_LSAMPL)
@@ -1599,6 +1641,7 @@ static void ni_ai_munge(struct comedi_device *dev, struct comedi_subdevice *s,
 
 static int ni_ai_setup_MITE_dma(struct comedi_device *dev)
 {
+       struct ni_private *devpriv = dev->private;
        struct comedi_subdevice *s = &dev->subdevices[NI_AI_SUBDEV];
        int retval;
        unsigned long flags;
@@ -1638,6 +1681,7 @@ static int ni_ai_setup_MITE_dma(struct comedi_device *dev)
 
 static int ni_ao_setup_MITE_dma(struct comedi_device *dev)
 {
+       struct ni_private *devpriv = dev->private;
        struct comedi_subdevice *s = &dev->subdevices[NI_AO_SUBDEV];
        int retval;
        unsigned long flags;
@@ -1676,6 +1720,8 @@ static int ni_ao_setup_MITE_dma(struct comedi_device *dev)
 
 static int ni_ai_reset(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+       struct ni_private *devpriv = dev->private;
+
        ni_release_ai_mite_channel(dev);
        /* ai configuration */
        devpriv->stc_writew(dev, AI_Configuration_Start | AI_Reset,
@@ -1786,6 +1832,7 @@ static int ni_ai_insn_read(struct comedi_device *dev,
                           struct comedi_subdevice *s, struct comedi_insn *insn,
                           unsigned int *data)
 {
+       struct ni_private *devpriv = dev->private;
        int i, n;
        const unsigned int mask = (1 << boardtype.adbits) - 1;
        unsigned signbits;
@@ -1881,7 +1928,9 @@ static int ni_ai_insn_read(struct comedi_device *dev,
 
 static void ni_prime_channelgain_list(struct comedi_device *dev)
 {
+       struct ni_private *devpriv = dev->private;
        int i;
+
        devpriv->stc_writew(dev, AI_CONVERT_Pulse, AI_Command_1_Register);
        for (i = 0; i < NI_TIMEOUT; ++i) {
                if (!(devpriv->stc_readw(dev,
@@ -1899,6 +1948,7 @@ static void ni_m_series_load_channelgain_list(struct comedi_device *dev,
                                              unsigned int n_chan,
                                              unsigned int *list)
 {
+       struct ni_private *devpriv = dev->private;
        unsigned int chan, range, aref;
        unsigned int i;
        unsigned offset;
@@ -2004,6 +2054,7 @@ static void ni_m_series_load_channelgain_list(struct comedi_device *dev,
 static void ni_load_channelgain_list(struct comedi_device *dev,
                                     unsigned int n_chan, unsigned int *list)
 {
+       struct ni_private *devpriv = dev->private;
        unsigned int chan, range, aref;
        unsigned int i;
        unsigned int hi, lo;
@@ -2122,7 +2173,9 @@ static void ni_load_channelgain_list(struct comedi_device *dev,
 static int ni_ns_to_timer(const struct comedi_device *dev, unsigned nanosec,
                          int round_mode)
 {
+       struct ni_private *devpriv = dev->private;
        int divider;
+
        switch (round_mode) {
        case TRIG_ROUND_NEAREST:
        default:
@@ -2140,6 +2193,8 @@ static int ni_ns_to_timer(const struct comedi_device *dev, unsigned nanosec,
 
 static unsigned ni_timer_to_ns(const struct comedi_device *dev, int timer)
 {
+       struct ni_private *devpriv = dev->private;
+
        return devpriv->clock_ns * (timer + 1);
 }
 
@@ -2162,6 +2217,7 @@ static unsigned ni_min_ai_scan_period_ns(struct comedi_device *dev,
 static int ni_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
                         struct comedi_cmd *cmd)
 {
+       struct ni_private *devpriv = dev->private;
        int err = 0;
        int tmp;
        unsigned int sources;
@@ -2356,6 +2412,7 @@ static int ni_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
 
 static int ni_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+       struct ni_private *devpriv = dev->private;
        const struct comedi_cmd *cmd = &s->async->cmd;
        int timer;
        int mode1 = 0;          /* mode1 is needed for both stop and convert */
@@ -2662,6 +2719,8 @@ static int ni_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 static int ni_ai_inttrig(struct comedi_device *dev, struct comedi_subdevice *s,
                         unsigned int trignum)
 {
+       struct ni_private *devpriv = dev->private;
+
        if (trignum != 0)
                return -EINVAL;
 
@@ -2681,6 +2740,8 @@ static int ni_ai_insn_config(struct comedi_device *dev,
                             struct comedi_subdevice *s,
                             struct comedi_insn *insn, unsigned int *data)
 {
+       struct ni_private *devpriv = dev->private;
+
        if (insn->n < 1)
                return -EINVAL;
 
@@ -2734,6 +2795,7 @@ static int ni_ai_config_analog_trig(struct comedi_device *dev,
                                    struct comedi_insn *insn,
                                    unsigned int *data)
 {
+       struct ni_private *devpriv = dev->private;
        unsigned int a, b, modebits;
        int err = 0;
 
@@ -2857,6 +2919,7 @@ static int ni_m_series_ao_config_chanlist(struct comedi_device *dev,
                                          unsigned int chanspec[],
                                          unsigned int n_chans, int timed)
 {
+       struct ni_private *devpriv = dev->private;
        unsigned int range;
        unsigned int chan;
        unsigned int conf;
@@ -2928,6 +2991,7 @@ static int ni_old_ao_config_chanlist(struct comedi_device *dev,
                                     unsigned int chanspec[],
                                     unsigned int n_chans)
 {
+       struct ni_private *devpriv = dev->private;
        unsigned int range;
        unsigned int chan;
        unsigned int conf;
@@ -2984,6 +3048,8 @@ static int ni_ao_insn_read(struct comedi_device *dev,
                           struct comedi_subdevice *s, struct comedi_insn *insn,
                           unsigned int *data)
 {
+       struct ni_private *devpriv = dev->private;
+
        data[0] = devpriv->ao[CR_CHAN(insn->chanspec)];
 
        return 1;
@@ -2993,6 +3059,7 @@ static int ni_ao_insn_write(struct comedi_device *dev,
                            struct comedi_subdevice *s,
                            struct comedi_insn *insn, unsigned int *data)
 {
+       struct ni_private *devpriv = dev->private;
        unsigned int chan = CR_CHAN(insn->chanspec);
        unsigned int invert;
 
@@ -3013,6 +3080,7 @@ static int ni_ao_insn_write_671x(struct comedi_device *dev,
                                 struct comedi_subdevice *s,
                                 struct comedi_insn *insn, unsigned int *data)
 {
+       struct ni_private *devpriv = dev->private;
        unsigned int chan = CR_CHAN(insn->chanspec);
        unsigned int invert;
 
@@ -3031,6 +3099,8 @@ static int ni_ao_insn_config(struct comedi_device *dev,
                             struct comedi_subdevice *s,
                             struct comedi_insn *insn, unsigned int *data)
 {
+       struct ni_private *devpriv = dev->private;
+
        switch (data[0]) {
        case INSN_CONFIG_GET_HARDWARE_BUFFER_SIZE:
                switch (data[1]) {
@@ -3057,6 +3127,7 @@ static int ni_ao_insn_config(struct comedi_device *dev,
 static int ni_ao_inttrig(struct comedi_device *dev, struct comedi_subdevice *s,
                         unsigned int trignum)
 {
+       struct ni_private *devpriv = dev->private;
        int ret;
        int interrupt_b_bits;
        int i;
@@ -3126,6 +3197,7 @@ static int ni_ao_inttrig(struct comedi_device *dev, struct comedi_subdevice *s,
 
 static int ni_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+       struct ni_private *devpriv = dev->private;
        const struct comedi_cmd *cmd = &s->async->cmd;
        int bits;
        int i;
@@ -3330,6 +3402,7 @@ static int ni_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 static int ni_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
                         struct comedi_cmd *cmd)
 {
+       struct ni_private *devpriv = dev->private;
        int err = 0;
        int tmp;
 
@@ -3438,6 +3511,8 @@ static int ni_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
 
 static int ni_ao_reset(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+       struct ni_private *devpriv = dev->private;
+
        /* devpriv->ao0p=0x0000; */
        /* ni_writew(devpriv->ao0p,AO_Configuration); */
 
@@ -3491,6 +3566,8 @@ static int ni_dio_insn_config(struct comedi_device *dev,
                              struct comedi_subdevice *s,
                              struct comedi_insn *insn, unsigned int *data)
 {
+       struct ni_private *devpriv = dev->private;
+
 #ifdef DEBUG_DIO
        printk("ni_dio_insn_config() chan=%d io=%d\n",
               CR_CHAN(insn->chanspec), data[0]);
@@ -3524,6 +3601,8 @@ static int ni_dio_insn_bits(struct comedi_device *dev,
                            struct comedi_subdevice *s,
                            struct comedi_insn *insn, unsigned int *data)
 {
+       struct ni_private *devpriv = dev->private;
+
 #ifdef DEBUG_DIO
        printk("ni_dio_insn_bits() mask=0x%x bits=0x%x\n", data[0], data[1]);
 #endif
@@ -3552,6 +3631,8 @@ static int ni_m_series_dio_insn_config(struct comedi_device *dev,
                                       struct comedi_insn *insn,
                                       unsigned int *data)
 {
+       struct ni_private *devpriv __maybe_unused = dev->private;
+
 #ifdef DEBUG_DIO
        printk("ni_m_series_dio_insn_config() chan=%d io=%d\n",
               CR_CHAN(insn->chanspec), data[0]);
@@ -3584,6 +3665,8 @@ static int ni_m_series_dio_insn_bits(struct comedi_device *dev,
                                     struct comedi_insn *insn,
                                     unsigned int *data)
 {
+       struct ni_private *devpriv __maybe_unused = dev->private;
+
 #ifdef DEBUG_DIO
        printk("ni_m_series_dio_insn_bits() mask=0x%x bits=0x%x\n", data[0],
               data[1]);
@@ -3680,6 +3763,7 @@ static int ni_cdio_cmdtest(struct comedi_device *dev,
 
 static int ni_cdio_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+       struct ni_private *devpriv __maybe_unused = dev->private;
        const struct comedi_cmd *cmd = &s->async->cmd;
        unsigned cdo_mode_bits = CDO_FIFO_Mode_Bit | CDO_Halt_On_Error_Bit;
        int retval;
@@ -3719,6 +3803,7 @@ static int ni_cdo_inttrig(struct comedi_device *dev, struct comedi_subdevice *s,
                          unsigned int trignum)
 {
 #ifdef PCIDMA
+       struct ni_private *devpriv = dev->private;
        unsigned long flags;
 #endif
        int retval = 0;
@@ -3766,6 +3851,8 @@ static int ni_cdo_inttrig(struct comedi_device *dev, struct comedi_subdevice *s,
 
 static int ni_cdio_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+       struct ni_private *devpriv __maybe_unused = dev->private;
+
        ni_writel(CDO_Disarm_Bit | CDO_Error_Interrupt_Enable_Clear_Bit |
                  CDO_Empty_FIFO_Interrupt_Enable_Clear_Bit |
                  CDO_FIFO_Request_Interrupt_Enable_Clear_Bit,
@@ -3781,6 +3868,7 @@ static int ni_cdio_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
 
 static void handle_cdio_interrupt(struct comedi_device *dev)
 {
+       struct ni_private *devpriv __maybe_unused = dev->private;
        unsigned cdio_status;
        struct comedi_subdevice *s = &dev->subdevices[NI_DIO_SUBDEV];
 #ifdef PCIDMA
@@ -3824,6 +3912,7 @@ static int ni_serial_insn_config(struct comedi_device *dev,
                                 struct comedi_subdevice *s,
                                 struct comedi_insn *insn, unsigned int *data)
 {
+       struct ni_private *devpriv = dev->private;
        int err = insn->n;
        unsigned char byte_out, byte_in = 0;
 
@@ -3920,6 +4009,7 @@ static int ni_serial_hw_readwrite8(struct comedi_device *dev,
                                   unsigned char data_out,
                                   unsigned char *data_in)
 {
+       struct ni_private *devpriv = dev->private;
        unsigned int status1;
        int err = 0, count = 20;
 
@@ -3978,6 +4068,7 @@ static int ni_serial_sw_readwrite8(struct comedi_device *dev,
                                   unsigned char data_out,
                                   unsigned char *data_in)
 {
+       struct ni_private *devpriv = dev->private;
        unsigned char mask, input = 0;
 
 #ifdef DEBUG_DIO
@@ -4031,9 +4122,10 @@ static int ni_serial_sw_readwrite8(struct comedi_device *dev,
 
 static void mio_common_detach(struct comedi_device *dev)
 {
+       struct ni_private *devpriv = dev->private;
        struct comedi_subdevice *s;
 
-       if (dev->private) {
+       if (devpriv) {
                if (devpriv->counter_dev) {
                        ni_gpct_device_destroy(devpriv->counter_dev);
                }
@@ -4151,6 +4243,7 @@ static void ni_gpct_write_register(struct ni_gpct *counter, unsigned bits,
                                   enum ni_gpct_register reg)
 {
        struct comedi_device *dev = counter->counter_dev->dev;
+       struct ni_private *devpriv = dev->private;
        unsigned stc_register;
        /* bits in the join reset register which are relevant to counters */
        static const unsigned gpct_joint_reset_mask = G0_Reset | G1_Reset;
@@ -4219,7 +4312,9 @@ static unsigned ni_gpct_read_register(struct ni_gpct *counter,
                                      enum ni_gpct_register reg)
 {
        struct comedi_device *dev = counter->counter_dev->dev;
+       struct ni_private *devpriv = dev->private;
        unsigned stc_register;
+
        switch (reg) {
                /* m-series only registers */
        case NITIO_G0_DMA_Status_Reg:
@@ -4251,6 +4346,8 @@ static int ni_freq_out_insn_read(struct comedi_device *dev,
                                 struct comedi_subdevice *s,
                                 struct comedi_insn *insn, unsigned int *data)
 {
+       struct ni_private *devpriv = dev->private;
+
        data[0] = devpriv->clock_and_fout & FOUT_Divider_mask;
        return 1;
 }
@@ -4259,6 +4356,8 @@ static int ni_freq_out_insn_write(struct comedi_device *dev,
                                  struct comedi_subdevice *s,
                                  struct comedi_insn *insn, unsigned int *data)
 {
+       struct ni_private *devpriv = dev->private;
+
        devpriv->clock_and_fout &= ~FOUT_Enable;
        devpriv->stc_writew(dev, devpriv->clock_and_fout,
                            Clock_and_FOUT_Register);
@@ -4273,6 +4372,8 @@ static int ni_freq_out_insn_write(struct comedi_device *dev,
 static int ni_set_freq_out_clock(struct comedi_device *dev,
                                 unsigned int clock_source)
 {
+       struct ni_private *devpriv = dev->private;
+
        switch (clock_source) {
        case NI_FREQ_OUT_TIMEBASE_1_DIV_2_CLOCK_SRC:
                devpriv->clock_and_fout &= ~FOUT_Timebase_Select;
@@ -4292,6 +4393,8 @@ static void ni_get_freq_out_clock(struct comedi_device *dev,
                                  unsigned int *clock_source,
                                  unsigned int *clock_period_ns)
 {
+       struct ni_private *devpriv = dev->private;
+
        if (devpriv->clock_and_fout & FOUT_Timebase_Select) {
                *clock_source = NI_FREQ_OUT_TIMEBASE_2_CLOCK_SRC;
                *clock_period_ns = TIMEBASE_2_NS;
@@ -4320,11 +4423,12 @@ static int ni_freq_out_insn_config(struct comedi_device *dev,
 
 static int ni_alloc_private(struct comedi_device *dev)
 {
-       int ret;
+       struct ni_private *devpriv;
 
-       ret = alloc_private(dev, sizeof(struct ni_private));
-       if (ret < 0)
-               return ret;
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
+               return -ENOMEM;
+       dev->private = devpriv;
 
        spin_lock_init(&devpriv->window_lock);
        spin_lock_init(&devpriv->soft_reg_copy_lock);
@@ -4335,6 +4439,7 @@ static int ni_alloc_private(struct comedi_device *dev)
 
 static int ni_E_init(struct comedi_device *dev)
 {
+       struct ni_private *devpriv = dev->private;
        struct comedi_subdevice *s;
        unsigned j;
        enum ni_gpct_variant counter_variant;
@@ -4661,6 +4766,7 @@ static int ni_E_init(struct comedi_device *dev)
 static int ni_8255_callback(int dir, int port, int data, unsigned long arg)
 {
        struct comedi_device *dev = (struct comedi_device *)arg;
+       struct ni_private *devpriv __maybe_unused = dev->private;
 
        if (dir) {
                ni_writeb(data, Port_A + 2 * port);
@@ -4689,6 +4795,7 @@ static int ni_eeprom_insn_read(struct comedi_device *dev,
 
 static int ni_read_eeprom(struct comedi_device *dev, int addr)
 {
+       struct ni_private *devpriv __maybe_unused = dev->private;
        int bit;
        int bitstring;
 
@@ -4716,6 +4823,8 @@ static int ni_m_series_eeprom_insn_read(struct comedi_device *dev,
                                        struct comedi_insn *insn,
                                        unsigned int *data)
 {
+       struct ni_private *devpriv = dev->private;
+
        data[0] = devpriv->eeprom_buffer[CR_CHAN(insn->chanspec)];
 
        return 1;
@@ -4723,6 +4832,8 @@ static int ni_m_series_eeprom_insn_read(struct comedi_device *dev,
 
 static int ni_get_pwm_config(struct comedi_device *dev, unsigned int *data)
 {
+       struct ni_private *devpriv = dev->private;
+
        data[1] = devpriv->pwm_up_count * devpriv->clock_ns;
        data[2] = devpriv->pwm_down_count * devpriv->clock_ns;
        return 3;
@@ -4732,7 +4843,9 @@ static int ni_m_series_pwm_config(struct comedi_device *dev,
                                  struct comedi_subdevice *s,
                                  struct comedi_insn *insn, unsigned int *data)
 {
+       struct ni_private *devpriv = dev->private;
        unsigned up_count, down_count;
+
        switch (data[0]) {
        case INSN_CONFIG_PWM_OUTPUT:
                switch (data[1]) {
@@ -4798,7 +4911,9 @@ static int ni_6143_pwm_config(struct comedi_device *dev,
                              struct comedi_subdevice *s,
                              struct comedi_insn *insn, unsigned int *data)
 {
+       struct ni_private *devpriv = dev->private;
        unsigned up_count, down_count;
+
        switch (data[0]) {
        case INSN_CONFIG_PWM_OUTPUT:
                switch (data[1]) {
@@ -4875,6 +4990,8 @@ static int ni_calib_insn_read(struct comedi_device *dev,
                              struct comedi_subdevice *s,
                              struct comedi_insn *insn, unsigned int *data)
 {
+       struct ni_private *devpriv = dev->private;
+
        data[0] = devpriv->caldacs[CR_CHAN(insn->chanspec)];
 
        return 1;
@@ -4905,6 +5022,7 @@ static struct caldac_struct caldacs[] = {
 
 static void caldac_setup(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+       struct ni_private *devpriv = dev->private;
        int i, j;
        int n_dacs;
        int n_chans = 0;
@@ -4958,6 +5076,7 @@ static void caldac_setup(struct comedi_device *dev, struct comedi_subdevice *s)
 
 static void ni_write_caldac(struct comedi_device *dev, int addr, int val)
 {
+       struct ni_private *devpriv = dev->private;
        unsigned int loadbit = 0, bits = 0, bit, bitstring = 0;
        int i;
        int type;
@@ -5211,8 +5330,10 @@ static int ni_gpct_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
 static int ni_m_series_set_pfi_routing(struct comedi_device *dev, unsigned chan,
                                       unsigned source)
 {
+       struct ni_private *devpriv = dev->private;
        unsigned pfi_reg_index;
        unsigned array_offset;
+
        if ((source & 0x1f) != source)
                return -EINVAL;
        pfi_reg_index = 1 + chan / 3;
@@ -5247,7 +5368,9 @@ static int ni_set_pfi_routing(struct comedi_device *dev, unsigned chan,
 static unsigned ni_m_series_get_pfi_routing(struct comedi_device *dev,
                                            unsigned chan)
 {
+       struct ni_private *devpriv = dev->private;
        const unsigned array_offset = chan / 3;
+
        return MSeries_PFI_Output_Select_Source(chan,
                                                devpriv->
                                                pfi_output_select_reg
@@ -5306,7 +5429,9 @@ static unsigned ni_get_pfi_routing(struct comedi_device *dev, unsigned chan)
 static int ni_config_filter(struct comedi_device *dev, unsigned pfi_channel,
                            enum ni_pfi_filter_select filter)
 {
+       struct ni_private *devpriv __maybe_unused = dev->private;
        unsigned bits;
+
        if ((boardtype.reg_type & ni_reg_m_series_mask) == 0) {
                return -ENOTSUPP;
        }
@@ -5321,6 +5446,8 @@ static int ni_pfi_insn_bits(struct comedi_device *dev,
                            struct comedi_subdevice *s,
                            struct comedi_insn *insn, unsigned int *data)
 {
+       struct ni_private *devpriv __maybe_unused = dev->private;
+
        if ((boardtype.reg_type & ni_reg_m_series_mask) == 0) {
                return -ENOTSUPP;
        }
@@ -5337,6 +5464,7 @@ static int ni_pfi_insn_config(struct comedi_device *dev,
                              struct comedi_subdevice *s,
                              struct comedi_insn *insn, unsigned int *data)
 {
+       struct ni_private *devpriv = dev->private;
        unsigned int chan;
 
        if (insn->n < 1)
@@ -5379,6 +5507,8 @@ static int ni_pfi_insn_config(struct comedi_device *dev,
  */
 static void ni_rtsi_init(struct comedi_device *dev)
 {
+       struct ni_private *devpriv = dev->private;
+
        /*  Initialises the RTSI bus signal switch to a default state */
 
        /*  Set clock mode to internal */
@@ -5480,6 +5610,7 @@ static inline unsigned num_configurable_rtsi_channels(struct comedi_device *dev)
 static int ni_mseries_set_pll_master_clock(struct comedi_device *dev,
                                           unsigned source, unsigned period_ns)
 {
+       struct ni_private *devpriv = dev->private;
        static const unsigned min_period_ns = 50;
        static const unsigned max_period_ns = 1000;
        static const unsigned timeout = 1000;
@@ -5488,6 +5619,7 @@ static int ni_mseries_set_pll_master_clock(struct comedi_device *dev,
        unsigned freq_multiplier;
        unsigned i;
        int retval;
+
        if (source == NI_MIO_PLL_PXI10_CLOCK)
                period_ns = 100;
        /*  these limits are somewhat arbitrary, but NI advertises 1 to 20MHz range so we'll use that */
@@ -5581,6 +5713,8 @@ static int ni_mseries_set_pll_master_clock(struct comedi_device *dev,
 static int ni_set_master_clock(struct comedi_device *dev, unsigned source,
                               unsigned period_ns)
 {
+       struct ni_private *devpriv = dev->private;
+
        if (source == NI_MIO_INTERNAL_CLOCK) {
                devpriv->rtsi_trig_direction_reg &= ~Use_RTSI_Clock_Bit;
                devpriv->stc_writew(dev, devpriv->rtsi_trig_direction_reg,
@@ -5666,6 +5800,8 @@ static int ni_valid_rtsi_output_source(struct comedi_device *dev, unsigned chan,
 static int ni_set_rtsi_routing(struct comedi_device *dev, unsigned chan,
                               unsigned source)
 {
+       struct ni_private *devpriv = dev->private;
+
        if (ni_valid_rtsi_output_source(dev, chan, source) == 0)
                return -EINVAL;
        if (chan < 4) {
@@ -5686,6 +5822,8 @@ static int ni_set_rtsi_routing(struct comedi_device *dev, unsigned chan,
 
 static unsigned ni_get_rtsi_routing(struct comedi_device *dev, unsigned chan)
 {
+       struct ni_private *devpriv = dev->private;
+
        if (chan < 4) {
                return RTSI_Trig_Output_Source(chan,
                                               devpriv->rtsi_trig_a_output_reg);
@@ -5704,7 +5842,9 @@ static int ni_rtsi_insn_config(struct comedi_device *dev,
                               struct comedi_subdevice *s,
                               struct comedi_insn *insn, unsigned int *data)
 {
+       struct ni_private *devpriv = dev->private;
        unsigned int chan = CR_CHAN(insn->chanspec);
+
        switch (data[0]) {
        case INSN_CONFIG_DIO_OUTPUT:
                if (chan < num_configurable_rtsi_channels(dev)) {
index ca4f8e06e75bafdf917f469407e6edff58cd82a1..b5b43e41f3f4c474bf31ba0ce4b5451822688032 100644 (file)
@@ -177,8 +177,6 @@ struct ni_private {
 
  NI_PRIVATE_COMMON};
 
-#define devpriv ((struct ni_private *)dev->private)
-
 /* How we access registers */
 
 #define ni_writel(a, b)                (outl((a), (b)+dev->iobase))
@@ -196,6 +194,7 @@ struct ni_private {
 
 static void mio_cs_win_out(struct comedi_device *dev, uint16_t data, int addr)
 {
+       struct ni_private *devpriv = dev->private;
        unsigned long flags;
 
        spin_lock_irqsave(&devpriv->window_lock, flags);
@@ -210,6 +209,7 @@ static void mio_cs_win_out(struct comedi_device *dev, uint16_t data, int addr)
 
 static uint16_t mio_cs_win_in(struct comedi_device *dev, int addr)
 {
+       struct ni_private *devpriv = dev->private;
        unsigned long flags;
        uint16_t ret;
 
@@ -324,6 +324,7 @@ static void mio_cs_config(struct pcmcia_device *link)
 
 static int mio_cs_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
+       struct ni_private *devpriv;
        struct pcmcia_device *link;
        unsigned int irq;
        int ret;
@@ -372,10 +373,10 @@ static int mio_cs_attach(struct comedi_device *dev, struct comedi_devconfig *it)
        }
        dev->irq = irq;
 
-       /* allocate private area */
        ret = ni_alloc_private(dev);
-       if (ret < 0)
+       if (ret)
                return ret;
+       devpriv = dev->private;
 
        devpriv->stc_writew = &mio_cs_win_out;
        devpriv->stc_readw = &mio_cs_win_in;
index bc9313ec985c9c8d90bec2bf5ad74387167f730a..0a556c7f9bc42bb8e92d080be23a4f846146976c 100644 (file)
@@ -310,7 +310,6 @@ struct nidio96_private {
        struct mite_dma_descriptor_ring *di_mite_ring;
        spinlock_t mite_channel_lock;
 };
-#define devpriv ((struct nidio96_private *)dev->private)
 
 static int ni_pcidio_cmdtest(struct comedi_device *dev,
                             struct comedi_subdevice *s,
@@ -332,6 +331,7 @@ static void ni_pcidio_print_status(unsigned int status);
 
 static int ni_pcidio_request_di_mite_channel(struct comedi_device *dev)
 {
+       struct nidio96_private *devpriv = dev->private;
        unsigned long flags;
 
        spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
@@ -355,6 +355,7 @@ static int ni_pcidio_request_di_mite_channel(struct comedi_device *dev)
 
 static void ni_pcidio_release_di_mite_channel(struct comedi_device *dev)
 {
+       struct nidio96_private *devpriv = dev->private;
        unsigned long flags;
 
        spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
@@ -384,6 +385,7 @@ static void ni_pcidio_event(struct comedi_device *dev,
 
 static int ni_pcidio_poll(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+       struct nidio96_private *devpriv = dev->private;
        unsigned long irq_flags;
        int count;
 
@@ -400,6 +402,7 @@ static int ni_pcidio_poll(struct comedi_device *dev, struct comedi_subdevice *s)
 static irqreturn_t nidio_interrupt(int irq, void *d)
 {
        struct comedi_device *dev = d;
+       struct nidio96_private *devpriv = dev->private;
        struct comedi_subdevice *s = &dev->subdevices[0];
        struct comedi_async *async = s->async;
        struct mite_struct *mite = devpriv->mite;
@@ -609,6 +612,7 @@ static void ni_pcidio_print_status(unsigned int flags)
 #ifdef unused
 static void debug_int(struct comedi_device *dev)
 {
+       struct nidio96_private *devpriv = dev->private;
        int a, b;
        static int n_int;
        struct timeval tv;
@@ -640,6 +644,8 @@ static int ni_pcidio_insn_config(struct comedi_device *dev,
                                 struct comedi_subdevice *s,
                                 struct comedi_insn *insn, unsigned int *data)
 {
+       struct nidio96_private *devpriv = dev->private;
+
        if (insn->n != 1)
                return -EINVAL;
        switch (data[0]) {
@@ -668,6 +674,8 @@ static int ni_pcidio_insn_bits(struct comedi_device *dev,
                               struct comedi_subdevice *s,
                               struct comedi_insn *insn, unsigned int *data)
 {
+       struct nidio96_private *devpriv = dev->private;
+
        if (data[0]) {
                s->state &= ~data[0];
                s->state |= (data[0] & data[1]);
@@ -793,6 +801,7 @@ static int ni_pcidio_ns_to_timer(int *nanosec, int round_mode)
 
 static int ni_pcidio_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+       struct nidio96_private *devpriv = dev->private;
        struct comedi_cmd *cmd = &s->async->cmd;
 
        /* XXX configure ports for input */
@@ -910,6 +919,7 @@ static int ni_pcidio_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 
 static int setup_mite_dma(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+       struct nidio96_private *devpriv = dev->private;
        int retval;
        unsigned long flags;
 
@@ -934,6 +944,8 @@ static int setup_mite_dma(struct comedi_device *dev, struct comedi_subdevice *s)
 static int ni_pcidio_inttrig(struct comedi_device *dev,
                             struct comedi_subdevice *s, unsigned int trignum)
 {
+       struct nidio96_private *devpriv = dev->private;
+
        if (trignum != 0)
                return -EINVAL;
 
@@ -946,6 +958,8 @@ static int ni_pcidio_inttrig(struct comedi_device *dev,
 static int ni_pcidio_cancel(struct comedi_device *dev,
                            struct comedi_subdevice *s)
 {
+       struct nidio96_private *devpriv = dev->private;
+
        writeb(0x00,
               devpriv->mite->daq_io_addr + Master_DMA_And_Interrupt_Control);
        ni_pcidio_release_di_mite_channel(dev);
@@ -956,6 +970,7 @@ static int ni_pcidio_cancel(struct comedi_device *dev,
 static int ni_pcidio_change(struct comedi_device *dev,
                            struct comedi_subdevice *s, unsigned long new_size)
 {
+       struct nidio96_private *devpriv = dev->private;
        int ret;
 
        ret = mite_buf_change(devpriv->di_mite_ring, s->async);
@@ -970,6 +985,7 @@ static int ni_pcidio_change(struct comedi_device *dev,
 static int pci_6534_load_fpga(struct comedi_device *dev, int fpga_index,
                              const u8 *data, size_t data_len)
 {
+       struct nidio96_private *devpriv = dev->private;
        static const int timeout = 1000;
        int i;
        size_t j;
@@ -1033,8 +1049,10 @@ static int pci_6534_reset_fpga(struct comedi_device *dev, int fpga_index)
 
 static int pci_6534_reset_fpgas(struct comedi_device *dev)
 {
+       struct nidio96_private *devpriv = dev->private;
        int ret;
        int i;
+
        writew(0x0, devpriv->mite->daq_io_addr + Firmware_Control_Register);
        for (i = 0; i < 3; ++i) {
                ret = pci_6534_reset_fpga(dev, i);
@@ -1047,6 +1065,8 @@ static int pci_6534_reset_fpgas(struct comedi_device *dev)
 
 static void pci_6534_init_main_fpga(struct comedi_device *dev)
 {
+       struct nidio96_private *devpriv = dev->private;
+
        writel(0, devpriv->mite->daq_io_addr + FPGA_Control1_Register);
        writel(0, devpriv->mite->daq_io_addr + FPGA_Control2_Register);
        writel(0, devpriv->mite->daq_io_addr + FPGA_SCALS_Counter_Register);
@@ -1057,6 +1077,7 @@ static void pci_6534_init_main_fpga(struct comedi_device *dev)
 
 static int pci_6534_upload_firmware(struct comedi_device *dev)
 {
+       struct nidio96_private *devpriv = dev->private;
        int ret;
        const struct firmware *fw;
        static const char *const fw_file[3] = {
@@ -1102,13 +1123,16 @@ nidio_find_boardinfo(struct pci_dev *pcidev)
 static int __devinit nidio_attach_pci(struct comedi_device *dev,
                                      struct pci_dev *pcidev)
 {
+       struct nidio96_private *devpriv;
        struct comedi_subdevice *s;
        int ret;
        unsigned int irq;
 
-       ret = alloc_private(dev, sizeof(struct nidio96_private));
-       if (ret < 0)
-               return ret;
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
+               return -ENOMEM;
+       dev->private = devpriv;
+
        spin_lock_init(&devpriv->mite_channel_lock);
 
        dev->board_ptr = nidio_find_boardinfo(pcidev);
@@ -1123,7 +1147,7 @@ static int __devinit nidio_attach_pci(struct comedi_device *dev,
                dev_warn(dev->class_dev, "error setting up mite\n");
                return ret;
        }
-       comedi_set_hw_dev(dev, &devpriv->mite->pcidev->dev);
+
        devpriv->di_mite_ring = mite_alloc_ring(devpriv->mite);
        if (devpriv->di_mite_ring == NULL)
                return -ENOMEM;
@@ -1184,6 +1208,8 @@ static int __devinit nidio_attach_pci(struct comedi_device *dev,
 
 static void nidio_detach(struct comedi_device *dev)
 {
+       struct nidio96_private *devpriv = dev->private;
+
        if (dev->irq)
                free_irq(dev->irq, dev);
        if (devpriv) {
index f284a90720ecef0cc455c9af0918d4bd236eab87..4adb4ba545caf439c3e41c8dfb539ba324ffa019 100644 (file)
@@ -1190,7 +1190,6 @@ static const struct ni_board_struct ni_boards[] = {
 
 struct ni_private {
 NI_PRIVATE_COMMON};
-#define devpriv ((struct ni_private *)dev->private)
 
 /* How we access registers */
 
@@ -1213,6 +1212,7 @@ NI_PRIVATE_COMMON};
 
 static void e_series_win_out(struct comedi_device *dev, uint16_t data, int reg)
 {
+       struct ni_private *devpriv = dev->private;
        unsigned long flags;
 
        spin_lock_irqsave(&devpriv->window_lock, flags);
@@ -1223,6 +1223,7 @@ static void e_series_win_out(struct comedi_device *dev, uint16_t data, int reg)
 
 static uint16_t e_series_win_in(struct comedi_device *dev, int reg)
 {
+       struct ni_private *devpriv = dev->private;
        unsigned long flags;
        uint16_t ret;
 
@@ -1237,7 +1238,9 @@ static uint16_t e_series_win_in(struct comedi_device *dev, int reg)
 static void m_series_stc_writew(struct comedi_device *dev, uint16_t data,
                                int reg)
 {
+       struct ni_private *devpriv = dev->private;
        unsigned offset;
+
        switch (reg) {
        case ADC_FIFO_Clear:
                offset = M_Offset_AI_FIFO_Clear;
@@ -1381,8 +1384,9 @@ static void m_series_stc_writew(struct comedi_device *dev, uint16_t data,
                /* FIXME: DIO_Output_Register (16 bit reg) is replaced by M_Offset_Static_Digital_Output (32 bit)
                   and M_Offset_SCXI_Serial_Data_Out (8 bit) */
        default:
-               printk(KERN_WARNING "%s: bug! unhandled register=0x%x in switch.\n",
-                      __func__, reg);
+               dev_warn(dev->class_dev,
+                        "%s: bug! unhandled register=0x%x in switch.\n",
+                        __func__, reg);
                BUG();
                return;
                break;
@@ -1392,7 +1396,9 @@ static void m_series_stc_writew(struct comedi_device *dev, uint16_t data,
 
 static uint16_t m_series_stc_readw(struct comedi_device *dev, int reg)
 {
+       struct ni_private *devpriv = dev->private;
        unsigned offset;
+
        switch (reg) {
        case AI_Status_1_Register:
                offset = M_Offset_AI_Status_1;
@@ -1416,8 +1422,9 @@ static uint16_t m_series_stc_readw(struct comedi_device *dev, int reg)
                offset = M_Offset_G01_Status;
                break;
        default:
-               printk(KERN_WARNING "%s: bug! unhandled register=0x%x in switch.\n",
-                      __func__, reg);
+               dev_warn(dev->class_dev,
+                        "%s: bug! unhandled register=0x%x in switch.\n",
+                        __func__, reg);
                BUG();
                return 0;
                break;
@@ -1428,7 +1435,9 @@ static uint16_t m_series_stc_readw(struct comedi_device *dev, int reg)
 static void m_series_stc_writel(struct comedi_device *dev, uint32_t data,
                                int reg)
 {
+       struct ni_private *devpriv = dev->private;
        unsigned offset;
+
        switch (reg) {
        case AI_SC_Load_A_Registers:
                offset = M_Offset_AI_SC_Load_A;
@@ -1458,8 +1467,9 @@ static void m_series_stc_writel(struct comedi_device *dev, uint32_t data,
                offset = M_Offset_G1_Load_B;
                break;
        default:
-               printk(KERN_WARNING "%s: bug! unhandled register=0x%x in switch.\n",
-                      __func__, reg);
+               dev_warn(dev->class_dev,
+                        "%s: bug! unhandled register=0x%x in switch.\n",
+                        __func__, reg);
                BUG();
                return;
                break;
@@ -1469,7 +1479,9 @@ static void m_series_stc_writel(struct comedi_device *dev, uint32_t data,
 
 static uint32_t m_series_stc_readl(struct comedi_device *dev, int reg)
 {
+       struct ni_private *devpriv = dev->private;
        unsigned offset;
+
        switch (reg) {
        case G_HW_Save_Register(0):
                offset = M_Offset_G0_HW_Save;
@@ -1484,8 +1496,9 @@ static uint32_t m_series_stc_readl(struct comedi_device *dev, int reg)
                offset = M_Offset_G1_Save;
                break;
        default:
-               printk(KERN_WARNING "%s: bug! unhandled register=0x%x in switch.\n",
-                      __func__, reg);
+               dev_warn(dev->class_dev,
+                        "%s: bug! unhandled register=0x%x in switch.\n",
+                        __func__, reg);
                BUG();
                return 0;
                break;
@@ -1516,6 +1529,7 @@ static int pcimio_dio_change(struct comedi_device *dev,
 
 static void m_series_init_eeprom_buffer(struct comedi_device *dev)
 {
+       struct ni_private *devpriv = dev->private;
        static const int Start_Cal_EEPROM = 0x400;
        static const unsigned window_size = 10;
        static const int serial_number_eeprom_offset = 0x4;
@@ -1553,6 +1567,8 @@ static void m_series_init_eeprom_buffer(struct comedi_device *dev)
 
 static void init_6143(struct comedi_device *dev)
 {
+       struct ni_private *devpriv = dev->private;
+
        /*  Disable interrupts */
        devpriv->stc_writew(dev, 0, Interrupt_Control_Register);
 
@@ -1572,10 +1588,12 @@ static void init_6143(struct comedi_device *dev)
 
 static void pcimio_detach(struct comedi_device *dev)
 {
+       struct ni_private *devpriv = dev->private;
+
        mio_common_detach(dev);
        if (dev->irq)
                free_irq(dev->irq, dev);
-       if (dev->private) {
+       if (devpriv) {
                mite_free_ring(devpriv->ai_mite_ring);
                mite_free_ring(devpriv->ao_mite_ring);
                mite_free_ring(devpriv->cdo_mite_ring);
@@ -1605,13 +1623,15 @@ pcimio_find_boardinfo(struct pci_dev *pcidev)
 static int __devinit pcimio_attach_pci(struct comedi_device *dev,
                                       struct pci_dev *pcidev)
 {
+       struct ni_private *devpriv;
        int ret;
 
        dev_info(dev->class_dev, "ni_pcimio: attach %s\n", pci_name(pcidev));
 
        ret = ni_alloc_private(dev);
-       if (ret < 0)
+       if (ret)
                return ret;
+       devpriv = dev->private;
 
        dev->board_ptr = pcimio_find_boardinfo(pcidev);
        if (!dev->board_ptr)
@@ -1641,7 +1661,7 @@ static int __devinit pcimio_attach_pci(struct comedi_device *dev,
                pr_warn("error setting up mite\n");
                return ret;
        }
-       comedi_set_hw_dev(dev, &devpriv->mite->pcidev->dev);
+
        devpriv->ai_mite_ring = mite_alloc_ring(devpriv->mite);
        if (devpriv->ai_mite_ring == NULL)
                return -ENOMEM;
@@ -1693,6 +1713,7 @@ static int __devinit pcimio_attach_pci(struct comedi_device *dev,
 static int pcimio_ai_change(struct comedi_device *dev,
                            struct comedi_subdevice *s, unsigned long new_size)
 {
+       struct ni_private *devpriv = dev->private;
        int ret;
 
        ret = mite_buf_change(devpriv->ai_mite_ring, s->async);
@@ -1705,6 +1726,7 @@ static int pcimio_ai_change(struct comedi_device *dev,
 static int pcimio_ao_change(struct comedi_device *dev,
                            struct comedi_subdevice *s, unsigned long new_size)
 {
+       struct ni_private *devpriv = dev->private;
        int ret;
 
        ret = mite_buf_change(devpriv->ao_mite_ring, s->async);
@@ -1718,6 +1740,7 @@ static int pcimio_gpct0_change(struct comedi_device *dev,
                               struct comedi_subdevice *s,
                               unsigned long new_size)
 {
+       struct ni_private *devpriv = dev->private;
        int ret;
 
        ret = mite_buf_change(devpriv->gpct_mite_ring[0], s->async);
@@ -1731,6 +1754,7 @@ static int pcimio_gpct1_change(struct comedi_device *dev,
                               struct comedi_subdevice *s,
                               unsigned long new_size)
 {
+       struct ni_private *devpriv = dev->private;
        int ret;
 
        ret = mite_buf_change(devpriv->gpct_mite_ring[1], s->async);
@@ -1743,6 +1767,7 @@ static int pcimio_gpct1_change(struct comedi_device *dev,
 static int pcimio_dio_change(struct comedi_device *dev,
                             struct comedi_subdevice *s, unsigned long new_size)
 {
+       struct ni_private *devpriv = dev->private;
        int ret;
 
        ret = mite_buf_change(devpriv->cdo_mite_ring, s->async);
index 89305a14eb5c0cbb9fc06519443e2218b162f8eb..f9c15aa45fea04a79bb44181d4b347889f01e3e9 100644 (file)
@@ -161,14 +161,13 @@ struct pcl711_private {
        unsigned int divisor2;
 };
 
-#define devpriv ((struct pcl711_private *)dev->private)
-
 static irqreturn_t pcl711_interrupt(int irq, void *d)
 {
        int lo, hi;
        int data;
        struct comedi_device *dev = d;
        const struct pcl711_board *board = comedi_board(dev);
+       struct pcl711_private *devpriv = dev->private;
        struct comedi_subdevice *s = &dev->subdevices[0];
 
        if (!dev->attached) {
@@ -264,6 +263,7 @@ ok:
 static int pcl711_ai_cmdtest(struct comedi_device *dev,
                             struct comedi_subdevice *s, struct comedi_cmd *cmd)
 {
+       struct pcl711_private *devpriv = dev->private;
        int tmp;
        int err = 0;
 
@@ -349,6 +349,7 @@ static int pcl711_ai_cmdtest(struct comedi_device *dev,
 
 static int pcl711_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+       struct pcl711_private *devpriv = dev->private;
        int timer1, timer2;
        struct comedi_cmd *cmd = &s->async->cmd;
 
@@ -398,6 +399,7 @@ static int pcl711_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 static int pcl711_ao_insn(struct comedi_device *dev, struct comedi_subdevice *s,
                          struct comedi_insn *insn, unsigned int *data)
 {
+       struct pcl711_private *devpriv = dev->private;
        int n;
        int chan = CR_CHAN(insn->chanspec);
 
@@ -417,6 +419,7 @@ static int pcl711_ao_insn_read(struct comedi_device *dev,
                               struct comedi_subdevice *s,
                               struct comedi_insn *insn, unsigned int *data)
 {
+       struct pcl711_private *devpriv = dev->private;
        int n;
        int chan = CR_CHAN(insn->chanspec);
 
@@ -460,6 +463,7 @@ static int pcl711_do_insn_bits(struct comedi_device *dev,
 static int pcl711_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
        const struct pcl711_board *board = comedi_board(dev);
+       struct pcl711_private *devpriv;
        int ret;
        unsigned long iobase;
        unsigned int irq;
@@ -499,9 +503,10 @@ static int pcl711_attach(struct comedi_device *dev, struct comedi_devconfig *it)
        if (ret)
                return ret;
 
-       ret = alloc_private(dev, sizeof(struct pcl711_private));
-       if (ret < 0)
-               return ret;
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
+               return -ENOMEM;
+       dev->private = devpriv;
 
        s = &dev->subdevices[0];
        /* AI subdevice */
index 07e72de982acd219bdced2759ea10defc2aaa618..50e01968f19c6ae445997ca43a5a61cf0056bd7f 100644 (file)
@@ -152,11 +152,10 @@ struct pcl726_private {
        unsigned int ao_readback[12];
 };
 
-#define devpriv ((struct pcl726_private *)dev->private)
-
 static int pcl726_ao_insn(struct comedi_device *dev, struct comedi_subdevice *s,
                          struct comedi_insn *insn, unsigned int *data)
 {
+       struct pcl726_private *devpriv = dev->private;
        int hi, lo;
        int n;
        int chan = CR_CHAN(insn->chanspec);
@@ -183,6 +182,7 @@ static int pcl726_ao_insn_read(struct comedi_device *dev,
                               struct comedi_subdevice *s,
                               struct comedi_insn *insn, unsigned int *data)
 {
+       struct pcl726_private *devpriv = dev->private;
        int chan = CR_CHAN(insn->chanspec);
        int n;
 
@@ -226,6 +226,7 @@ static int pcl726_do_insn_bits(struct comedi_device *dev,
 static int pcl726_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
        const struct pcl726_board *board = comedi_board(dev);
+       struct pcl726_private *devpriv;
        struct comedi_subdevice *s;
        unsigned long iobase;
        unsigned int iorange;
@@ -247,9 +248,10 @@ static int pcl726_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 
        dev->board_name = board->name;
 
-       ret = alloc_private(dev, sizeof(struct pcl726_private));
-       if (ret < 0)
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
                return -ENOMEM;
+       dev->private = devpriv;
 
        for (i = 0; i < 12; i++) {
                devpriv->bipolar[i] = 0;
index 3cf55ff9308383f07c8032b67222c05b4acc934f..d94c9dc78323326cb746afde3d12fc31c90cbb67 100644 (file)
@@ -369,8 +369,6 @@ struct pcl812_private {
        unsigned int ao_readback[2];    /*  data for AO readback */
 };
 
-#define devpriv ((struct pcl812_private *)dev->private)
-
 /*
 ==============================================================================
 */
@@ -388,6 +386,7 @@ static int pcl812_ai_insn_read(struct comedi_device *dev,
                               struct comedi_subdevice *s,
                               struct comedi_insn *insn, unsigned int *data)
 {
+       struct pcl812_private *devpriv = dev->private;
        int n;
        int timeout, hi;
 
@@ -465,6 +464,7 @@ static int pcl812_ao_insn_write(struct comedi_device *dev,
                                struct comedi_subdevice *s,
                                struct comedi_insn *insn, unsigned int *data)
 {
+       struct pcl812_private *devpriv = dev->private;
        int chan = CR_CHAN(insn->chanspec);
        int i;
 
@@ -486,6 +486,7 @@ static int pcl812_ao_insn_read(struct comedi_device *dev,
                               struct comedi_subdevice *s,
                               struct comedi_insn *insn, unsigned int *data)
 {
+       struct pcl812_private *devpriv = dev->private;
        int chan = CR_CHAN(insn->chanspec);
        int i;
 
@@ -533,6 +534,7 @@ static int pcl812_ai_cmdtest(struct comedi_device *dev,
                             struct comedi_subdevice *s, struct comedi_cmd *cmd)
 {
        const struct pcl812_board *board = comedi_board(dev);
+       struct pcl812_private *devpriv = dev->private;
        int err = 0;
        unsigned int flags;
        int tmp, divisor1, divisor2;
@@ -639,6 +641,7 @@ static int pcl812_ai_cmdtest(struct comedi_device *dev,
 static int pcl812_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
        const struct pcl812_board *board = comedi_board(dev);
+       struct pcl812_private *devpriv = dev->private;
        unsigned int divisor1 = 0, divisor2 = 0, i, dma_flags, bytes;
        struct comedi_cmd *cmd = &s->async->cmd;
 
@@ -789,6 +792,7 @@ static irqreturn_t interrupt_pcl812_ai_int(int irq, void *d)
        char err = 1;
        unsigned int mask, timeout;
        struct comedi_device *dev = d;
+       struct pcl812_private *devpriv = dev->private;
        struct comedi_subdevice *s = &dev->subdevices[0];
        unsigned int next_chan;
 
@@ -862,6 +866,7 @@ static void transfer_from_dma_buf(struct comedi_device *dev,
                                  struct comedi_subdevice *s, short *ptr,
                                  unsigned int bufptr, unsigned int len)
 {
+       struct pcl812_private *devpriv = dev->private;
        unsigned int i;
 
        s->async->events = 0;
@@ -892,6 +897,7 @@ static void transfer_from_dma_buf(struct comedi_device *dev,
 static irqreturn_t interrupt_pcl812_ai_dma(int irq, void *d)
 {
        struct comedi_device *dev = d;
+       struct pcl812_private *devpriv = dev->private;
        struct comedi_subdevice *s = &dev->subdevices[0];
        unsigned long dma_flags;
        int len, bufptr;
@@ -938,6 +944,7 @@ static irqreturn_t interrupt_pcl812_ai_dma(int irq, void *d)
 static irqreturn_t interrupt_pcl812(int irq, void *d)
 {
        struct comedi_device *dev = d;
+       struct pcl812_private *devpriv = dev->private;
 
        if (!dev->attached) {
                comedi_error(dev, "spurious interrupt");
@@ -954,6 +961,7 @@ static irqreturn_t interrupt_pcl812(int irq, void *d)
 */
 static int pcl812_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+       struct pcl812_private *devpriv = dev->private;
        unsigned long flags;
        unsigned int top1, top2, i;
 
@@ -1002,6 +1010,7 @@ static void setup_range_channel(struct comedi_device *dev,
                                struct comedi_subdevice *s,
                                unsigned int rangechan, char wait)
 {
+       struct pcl812_private *devpriv = dev->private;
        unsigned char chan_reg = CR_CHAN(rangechan);    /*  normal board */
                                                        /*  gain index */
        unsigned char gain_reg = CR_RANGE(rangechan) +
@@ -1063,8 +1072,9 @@ static void start_pacer(struct comedi_device *dev, int mode,
 static void free_resources(struct comedi_device *dev)
 {
        const struct pcl812_board *board = comedi_board(dev);
+       struct pcl812_private *devpriv = dev->private;
 
-       if (dev->private) {
+       if (devpriv) {
                if (devpriv->dmabuf[0])
                        free_pages(devpriv->dmabuf[0], devpriv->dmapages[0]);
                if (devpriv->dmabuf[1])
@@ -1084,6 +1094,8 @@ static void free_resources(struct comedi_device *dev)
 static int pcl812_ai_cancel(struct comedi_device *dev,
                            struct comedi_subdevice *s)
 {
+       struct pcl812_private *devpriv = dev->private;
+
        if (devpriv->ai_dma)
                disable_dma(devpriv->dma);
        outb(0, dev->iobase + PCL812_CLRINT);   /* clear INT request */
@@ -1100,6 +1112,7 @@ static int pcl812_ai_cancel(struct comedi_device *dev,
 static void pcl812_reset(struct comedi_device *dev)
 {
        const struct pcl812_board *board = comedi_board(dev);
+       struct pcl812_private *devpriv = dev->private;
 
        outb(0, dev->iobase + PCL812_MUX);
        outb(0 + devpriv->range_correction, dev->iobase + PCL812_GAIN);
@@ -1135,6 +1148,7 @@ static void pcl812_reset(struct comedi_device *dev)
 static int pcl812_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
        const struct pcl812_board *board = comedi_board(dev);
+       struct pcl812_private *devpriv;
        int ret, subdev;
        unsigned long iobase;
        unsigned int irq;
@@ -1153,11 +1167,12 @@ static int pcl812_attach(struct comedi_device *dev, struct comedi_devconfig *it)
        }
        dev->iobase = iobase;
 
-       ret = alloc_private(dev, sizeof(struct pcl812_private));
-       if (ret < 0) {
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv) {
                free_resources(dev);
-               return ret;     /* Can't alloc mem */
+               return -ENOMEM;
        }
+       dev->private = devpriv;
 
        dev->board_name = board->name;
 
index 0822de058e4d7fdb819f88ae91c08d14bfb07ead..858600a753b112d1ceb2dffddb14456ad969786a 100644 (file)
@@ -126,8 +126,6 @@ struct pcl816_board {
        int i8254_osc_base;     /*  1/frequency of on board oscilator in ns */
 };
 
-#define devpriv ((struct pcl816_private *)dev->private)
-
 #ifdef unused
 static int RTC_lock;   /* RTC lock */
 static int RTC_timer_lock;     /* RTC int lock */
@@ -259,6 +257,7 @@ static int pcl816_ai_insn_read(struct comedi_device *dev,
 static irqreturn_t interrupt_pcl816_ai_mode13_int(int irq, void *d)
 {
        struct comedi_device *dev = d;
+       struct pcl816_private *devpriv = dev->private;
        struct comedi_subdevice *s = &dev->subdevices[0];
        int low, hi;
        int timeout = 50;       /* wait max 50us */
@@ -315,6 +314,7 @@ static void transfer_from_dma_buf(struct comedi_device *dev,
                                  struct comedi_subdevice *s, short *ptr,
                                  unsigned int bufptr, unsigned int len)
 {
+       struct pcl816_private *devpriv = dev->private;
        int i;
 
        s->async->events = 0;
@@ -350,6 +350,7 @@ static void transfer_from_dma_buf(struct comedi_device *dev,
 static irqreturn_t interrupt_pcl816_ai_mode13_dma(int irq, void *d)
 {
        struct comedi_device *dev = d;
+       struct pcl816_private *devpriv = dev->private;
        struct comedi_subdevice *s = &dev->subdevices[0];
        int len, bufptr, this_dma_buf;
        unsigned long dma_flags;
@@ -398,6 +399,8 @@ static irqreturn_t interrupt_pcl816_ai_mode13_dma(int irq, void *d)
 static irqreturn_t interrupt_pcl816(int irq, void *d)
 {
        struct comedi_device *dev = d;
+       struct pcl816_private *devpriv = dev->private;
+
        DPRINTK("<I>");
 
        if (!dev->attached) {
@@ -554,6 +557,7 @@ static int pcl816_ai_cmdtest(struct comedi_device *dev,
 static int pcl816_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
        const struct pcl816_board *board = comedi_board(dev);
+       struct pcl816_private *devpriv = dev->private;
        unsigned int divisor1 = 0, divisor2 = 0, dma_flags, bytes, dmairq;
        struct comedi_cmd *cmd = &s->async->cmd;
        unsigned int seglen;
@@ -682,6 +686,7 @@ static int pcl816_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 
 static int pcl816_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+       struct pcl816_private *devpriv = dev->private;
        unsigned long flags;
        unsigned int top1, top2, i;
 
@@ -727,6 +732,8 @@ static int pcl816_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s)
 static int pcl816_ai_cancel(struct comedi_device *dev,
                            struct comedi_subdevice *s)
 {
+       struct pcl816_private *devpriv = dev->private;
+
 /* DEBUG(printk("pcl816_ai_cancel()\n");) */
 
        if (devpriv->irq_blocked > 0) {
@@ -932,6 +939,7 @@ setup_channel_list(struct comedi_device *dev,
                   struct comedi_subdevice *s, unsigned int *chanlist,
                   unsigned int seglen)
 {
+       struct pcl816_private *devpriv = dev->private;
        unsigned int i;
 
        devpriv->ai_act_chanlist_len = seglen;
@@ -991,6 +999,7 @@ static int set_rtc_irq_bit(unsigned char bit)
 static int pcl816_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
        const struct pcl816_board *board = comedi_board(dev);
+       struct pcl816_private *devpriv;
        int ret;
        unsigned long iobase;
        unsigned int irq, dma;
@@ -1015,9 +1024,10 @@ static int pcl816_attach(struct comedi_device *dev, struct comedi_devconfig *it)
                return -EIO;
        }
 
-       ret = alloc_private(dev, sizeof(struct pcl816_private));
-       if (ret < 0)
-               return ret;     /* Can't alloc mem */
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
+               return -ENOMEM;
+       dev->private = devpriv;
 
        dev->board_name = board->name;
 
@@ -1216,6 +1226,7 @@ case COMEDI_SUBD_DO:
 static void pcl816_detach(struct comedi_device *dev)
 {
        const struct pcl816_board *board = comedi_board(dev);
+       struct pcl816_private *devpriv = dev->private;
 
        if (dev->private) {
                pcl816_ai_cancel(dev, devpriv->sub_ai);
index d4b0859d81f216d6772a0fa02a89ac8aca7b5e76..c94f289e3f3acd18394d92c1a4543f9eb4b64644 100644 (file)
@@ -326,8 +326,6 @@ static const unsigned int muxonechan[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0
        0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff
 };
 
-#define devpriv ((struct pcl818_private *)dev->private)
-
 /*
 ==============================================================================
 */
@@ -406,6 +404,7 @@ static int pcl818_ao_insn_read(struct comedi_device *dev,
                               struct comedi_subdevice *s,
                               struct comedi_insn *insn, unsigned int *data)
 {
+       struct pcl818_private *devpriv = dev->private;
        int n;
        int chan = CR_CHAN(insn->chanspec);
 
@@ -419,6 +418,7 @@ static int pcl818_ao_insn_write(struct comedi_device *dev,
                                struct comedi_subdevice *s,
                                struct comedi_insn *insn, unsigned int *data)
 {
+       struct pcl818_private *devpriv = dev->private;
        int n;
        int chan = CR_CHAN(insn->chanspec);
 
@@ -478,6 +478,7 @@ static int pcl818_do_insn_bits(struct comedi_device *dev,
 static irqreturn_t interrupt_pcl818_ai_mode13_int(int irq, void *d)
 {
        struct comedi_device *dev = d;
+       struct pcl818_private *devpriv = dev->private;
        struct comedi_subdevice *s = &dev->subdevices[0];
        int low;
        int timeout = 50;       /* wait max 50us */
@@ -537,6 +538,7 @@ conv_finish:
 static irqreturn_t interrupt_pcl818_ai_mode13_dma(int irq, void *d)
 {
        struct comedi_device *dev = d;
+       struct pcl818_private *devpriv = dev->private;
        struct comedi_subdevice *s = &dev->subdevices[0];
        int i, len, bufptr;
        unsigned long flags;
@@ -616,6 +618,7 @@ static irqreturn_t interrupt_pcl818_ai_mode13_dma(int irq, void *d)
 static irqreturn_t interrupt_pcl818_ai_mode13_dma_rtc(int irq, void *d)
 {
        struct comedi_device *dev = d;
+       struct pcl818_private *devpriv = dev->private;
        struct comedi_subdevice *s = &dev->subdevices[0];
        unsigned long tmp;
        unsigned int top1, top2, i, bufptr;
@@ -721,6 +724,7 @@ static irqreturn_t interrupt_pcl818_ai_mode13_dma_rtc(int irq, void *d)
 static irqreturn_t interrupt_pcl818_ai_mode13_fifo(int irq, void *d)
 {
        struct comedi_device *dev = d;
+       struct pcl818_private *devpriv = dev->private;
        struct comedi_subdevice *s = &dev->subdevices[0];
        int i, len, lo;
 
@@ -795,6 +799,7 @@ static irqreturn_t interrupt_pcl818_ai_mode13_fifo(int irq, void *d)
 static irqreturn_t interrupt_pcl818(int irq, void *d)
 {
        struct comedi_device *dev = d;
+       struct pcl818_private *devpriv = dev->private;
 
        if (!dev->attached) {
                comedi_error(dev, "premature interrupt");
@@ -861,6 +866,7 @@ static irqreturn_t interrupt_pcl818(int irq, void *d)
 static void pcl818_ai_mode13dma_int(int mode, struct comedi_device *dev,
                                    struct comedi_subdevice *s)
 {
+       struct pcl818_private *devpriv = dev->private;
        unsigned int flags;
        unsigned int bytes;
 
@@ -902,6 +908,7 @@ static void pcl818_ai_mode13dma_int(int mode, struct comedi_device *dev,
 static void pcl818_ai_mode13dma_rtc(int mode, struct comedi_device *dev,
                                    struct comedi_subdevice *s)
 {
+       struct pcl818_private *devpriv = dev->private;
        unsigned int flags;
        short *pole;
 
@@ -943,6 +950,7 @@ static void pcl818_ai_mode13dma_rtc(int mode, struct comedi_device *dev,
 static int pcl818_ai_cmd_mode(int mode, struct comedi_device *dev,
                              struct comedi_subdevice *s)
 {
+       struct pcl818_private *devpriv = dev->private;
        struct comedi_cmd *cmd = &s->async->cmd;
        int divisor1 = 0, divisor2 = 0;
        unsigned int seglen;
@@ -1063,6 +1071,7 @@ static int pcl818_ai_cmd_mode(int mode, struct comedi_device *dev,
 static int pcl818_ao_mode13(int mode, struct comedi_device *dev,
                            struct comedi_subdevice *s, comedi_trig * it)
 {
+       struct pcl818_private *devpriv = dev->private;
        int divisor1 = 0, divisor2 = 0;
 
        if (!dev->irq) {
@@ -1222,6 +1231,7 @@ static void setup_channel_list(struct comedi_device *dev,
                               unsigned int *chanlist, unsigned int n_chan,
                               unsigned int seglen)
 {
+       struct pcl818_private *devpriv = dev->private;
        int i;
 
        devpriv->act_chanlist_len = seglen;
@@ -1259,6 +1269,7 @@ static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
                      struct comedi_cmd *cmd)
 {
        const struct pcl818_board *board = comedi_board(dev);
+       struct pcl818_private *devpriv = dev->private;
        int err = 0;
        int tmp, divisor1 = 0, divisor2 = 0;
 
@@ -1358,6 +1369,7 @@ static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
 */
 static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+       struct pcl818_private *devpriv = dev->private;
        struct comedi_cmd *cmd = &s->async->cmd;
        int retval;
 
@@ -1397,6 +1409,8 @@ static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 static int pcl818_ai_cancel(struct comedi_device *dev,
                            struct comedi_subdevice *s)
 {
+       struct pcl818_private *devpriv = dev->private;
+
        if (devpriv->irq_blocked > 0) {
                dev_dbg(dev->class_dev, "pcl818_ai_cancel()\n");
                devpriv->irq_was_now_closed = 1;
@@ -1482,6 +1496,7 @@ static int pcl818_check(unsigned long iobase)
 static void pcl818_reset(struct comedi_device *dev)
 {
        const struct pcl818_board *board = comedi_board(dev);
+       struct pcl818_private *devpriv = dev->private;
 
        if (devpriv->usefifo) { /*  FIFO shutdown */
                outb(0, dev->iobase + PCL818_FI_INTCLR);
@@ -1552,6 +1567,7 @@ static int set_rtc_irq_bit(unsigned char bit)
 static void rtc_dropped_irq(unsigned long data)
 {
        struct comedi_device *dev = (void *)data;
+       struct pcl818_private *devpriv = dev->private;
        unsigned long flags, tmp;
 
        switch (devpriv->int818_mode) {
@@ -1601,6 +1617,7 @@ static int rtc_setfreq_irq(int freq)
 static int pcl818_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
        const struct pcl818_board *board = comedi_board(dev);
+       struct pcl818_private *devpriv;
        int ret;
        unsigned long iobase;
        unsigned int irq;
@@ -1608,9 +1625,10 @@ static int pcl818_attach(struct comedi_device *dev, struct comedi_devconfig *it)
        unsigned long pages;
        struct comedi_subdevice *s;
 
-       ret = alloc_private(dev, sizeof(struct pcl818_private));
-       if (ret < 0)
-               return ret;     /* Can't alloc mem */
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
+               return -ENOMEM;
+       dev->private = devpriv;
 
        /* claim our I/O space */
        iobase = it->options[0];
@@ -1892,7 +1910,9 @@ no_dma:
 
 static void pcl818_detach(struct comedi_device *dev)
 {
-       if (dev->private) {
+       struct pcl818_private *devpriv = dev->private;
+
+       if (devpriv) {
                pcl818_ai_cancel(dev, devpriv->sub_ai);
                pcl818_reset(dev);
                if (devpriv->dma)
index 4102547dc6a8ed60f84a2a49688e7698504846d5..5f062df1ead4026bdc6310a5f80fcb3f780bce1c 100644 (file)
@@ -62,14 +62,6 @@ Copy/pasted/hacked from pcm724.c
 #define CR_A_MODE(a)   ((a)<<5)
 #define CR_CW          0x80
 
-struct pcm3724_board {
-       const char *name;       /*  driver name */
-       int dio;                /*  num of DIO */
-       int numofports;         /*  num of 8255 subdevices */
-       unsigned int IRQbits;   /*  allowed interrupts */
-       unsigned int io_range;  /*  len of IO space */
-};
-
 /* used to track configured dios */
 struct priv_pcm3724 {
        int dio_1;
@@ -156,13 +148,12 @@ static void do_3724_config(struct comedi_device *dev,
 static void enable_chan(struct comedi_device *dev, struct comedi_subdevice *s,
                        int chanspec)
 {
+       struct priv_pcm3724 *priv = dev->private;
        struct comedi_subdevice *s_dio1 = &dev->subdevices[0];
        unsigned int mask;
        int gatecfg;
-       struct priv_pcm3724 *priv;
 
        gatecfg = 0;
-       priv = dev->private;
 
        mask = 1 << CR_CHAN(chanspec);
        if (s == s_dio1)
@@ -233,36 +224,33 @@ static int subdev_3724_insn_config(struct comedi_device *dev,
 static int pcm3724_attach(struct comedi_device *dev,
                          struct comedi_devconfig *it)
 {
-       const struct pcm3724_board *board = comedi_board(dev);
+       struct priv_pcm3724 *priv;
        struct comedi_subdevice *s;
        unsigned long iobase;
        unsigned int iorange;
-       int ret, i, n_subdevices;
+       int ret, i;
+
+       dev->board_name = dev->driver->driver_name;
 
        iobase = it->options[0];
-       iorange = board->io_range;
+       iorange = PCM3724_SIZE;
 
-       ret = alloc_private(dev, sizeof(struct priv_pcm3724));
-       if (ret < 0)
+       priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+       if (!priv)
                return -ENOMEM;
-
-       ((struct priv_pcm3724 *)(dev->private))->dio_1 = 0;
-       ((struct priv_pcm3724 *)(dev->private))->dio_2 = 0;
+       dev->private = priv;
 
        printk(KERN_INFO "comedi%d: pcm3724: board=%s, 0x%03lx ", dev->minor,
-              board->name, iobase);
+              dev->board_name, iobase);
        if (!iobase || !request_region(iobase, iorange, "pcm3724")) {
                printk("I/O port conflict\n");
                return -EIO;
        }
 
        dev->iobase = iobase;
-       dev->board_name = board->name;
        printk(KERN_INFO "\n");
 
-       n_subdevices = board->numofports;
-
-       ret = comedi_alloc_subdevices(dev, n_subdevices);
+       ret = comedi_alloc_subdevices(dev, 2);
        if (ret)
                return ret;
 
@@ -277,7 +265,6 @@ static int pcm3724_attach(struct comedi_device *dev,
 
 static void pcm3724_detach(struct comedi_device *dev)
 {
-       const struct pcm3724_board *board = comedi_board(dev);
        struct comedi_subdevice *s;
        int i;
 
@@ -288,21 +275,14 @@ static void pcm3724_detach(struct comedi_device *dev)
                }
        }
        if (dev->iobase)
-               release_region(dev->iobase, board->io_range);
+               release_region(dev->iobase, PCM3724_SIZE);
 }
 
-static const struct pcm3724_board boardtypes[] = {
-       { "pcm3724", 48, 2, 0x00fc, PCM3724_SIZE, },
-};
-
 static struct comedi_driver pcm3724_driver = {
        .driver_name    = "pcm3724",
        .module         = THIS_MODULE,
        .attach         = pcm3724_attach,
        .detach         = pcm3724_detach,
-       .board_name     = &boardtypes[0].name,
-       .num_names      = ARRAY_SIZE(boardtypes),
-       .offset         = sizeof(struct pcm3724_board),
 };
 module_comedi_driver(pcm3724_driver);
 
index 5efeb9205c2e54e712d88b94717a0126316d2f5d..13e84215fac3254afcb242e75792fbca99d46002 100644 (file)
@@ -62,7 +62,6 @@ struct pcmad_priv_struct {
        int differential;
        int twos_comp;
 };
-#define devpriv ((struct pcmad_priv_struct *)dev->private)
 
 #define TIMEOUT        100
 
@@ -71,6 +70,7 @@ static int pcmad_ai_insn_read(struct comedi_device *dev,
                              struct comedi_insn *insn, unsigned int *data)
 {
        const struct pcmad_board_struct *board = comedi_board(dev);
+       struct pcmad_priv_struct *devpriv = dev->private;
        int i;
        int chan;
        int n;
@@ -104,6 +104,7 @@ static int pcmad_ai_insn_read(struct comedi_device *dev,
 static int pcmad_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
        const struct pcmad_board_struct *board = comedi_board(dev);
+       struct pcmad_priv_struct *devpriv;
        int ret;
        struct comedi_subdevice *s;
        unsigned long iobase;
@@ -121,9 +122,10 @@ static int pcmad_attach(struct comedi_device *dev, struct comedi_devconfig *it)
        if (ret)
                return ret;
 
-       ret = alloc_private(dev, sizeof(struct pcmad_priv_struct));
-       if (ret < 0)
-               return ret;
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
+               return -ENOMEM;
+       dev->private = devpriv;
 
        dev->board_name = board->name;
 
index 28af8f6873ebcff10721a7391a6d02f9411a63bc..0882dafaf57bf229730f373dfba40b0fdaa518f9 100644 (file)
@@ -64,13 +64,6 @@ Configuration Options:
 #define MSB_PORT(chan) (LSB_PORT(chan)+1)
 #define BITS 12
 
-/*
- * Bords
- */
-struct pcmda12_board {
-       const char *name;
-};
-
 /* note these have no effect and are merely here for reference..
    these are configured by jumpering the board! */
 static const struct comedi_lrange pcmda12_ranges = {
@@ -86,8 +79,6 @@ struct pcmda12_private {
        int simultaneous_xfer_mode;
 };
 
-#define devpriv ((struct pcmda12_private *)(dev->private))
-
 static void zero_chans(struct comedi_device *dev)
 {                              /* sets up an
                                   ASIC chip to defaults */
@@ -104,6 +95,7 @@ static void zero_chans(struct comedi_device *dev)
 static int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
                    struct comedi_insn *insn, unsigned int *data)
 {
+       struct pcmda12_private *devpriv = dev->private;
        int i;
        int chan = CR_CHAN(insn->chanspec);
 
@@ -146,6 +138,7 @@ static int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
 static int ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
                    struct comedi_insn *insn, unsigned int *data)
 {
+       struct pcmda12_private *devpriv = dev->private;
        int i;
        int chan = CR_CHAN(insn->chanspec);
 
@@ -162,7 +155,7 @@ static int ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
 static int pcmda12_attach(struct comedi_device *dev,
                          struct comedi_devconfig *it)
 {
-       const struct pcmda12_board *board = comedi_board(dev);
+       struct pcmda12_private *devpriv;
        struct comedi_subdevice *s;
        unsigned long iobase;
        int ret;
@@ -178,16 +171,12 @@ static int pcmda12_attach(struct comedi_device *dev,
        }
        dev->iobase = iobase;
 
-       dev->board_name = board->name;
+       dev->board_name = dev->driver->driver_name;
 
-/*
- * Allocate the private structure area.  alloc_private() is a
- * convenient macro defined in comedidev.h.
- */
-       if (alloc_private(dev, sizeof(struct pcmda12_private)) < 0) {
-               printk(KERN_ERR "cannot allocate private data structure\n");
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
                return -ENOMEM;
-       }
+       dev->private = devpriv;
 
        devpriv->simultaneous_xfer_mode = it->options[1];
 
@@ -218,20 +207,11 @@ static void pcmda12_detach(struct comedi_device *dev)
                release_region(dev->iobase, IOSIZE);
 }
 
-static const struct pcmda12_board pcmda12_boards[] = {
-       {
-               .name   = "pcmda12",
-       },
-};
-
 static struct comedi_driver pcmda12_driver = {
        .driver_name    = "pcmda12",
        .module         = THIS_MODULE,
        .attach         = pcmda12_attach,
        .detach         = pcmda12_detach,
-       .board_name     = &pcmda12_boards[0].name,
-       .offset         = sizeof(struct pcmda12_board),
-       .num_names      = ARRAY_SIZE(pcmda12_boards),
 };
 module_comedi_driver(pcmda12_driver);
 
index a10bf0a2987f99a6f878c60c85e539626d18c2c5..7522bfb6db0864fe45e643061d77e4f31bc156d0 100644 (file)
@@ -145,35 +145,6 @@ Configuration Options:
 #define PAGE_ENAB 2
 #define PAGE_INT_ID 3
 
-/*
- * Board descriptions for two imaginary boards.  Describing the
- * boards in this way is optional, and completely driver-dependent.
- * Some drivers use arrays such as this, other do not.
- */
-struct pcmmio_board {
-       const char *name;
-       const int dio_num_asics;
-       const int dio_num_ports;
-       const int total_iosize;
-       const int ai_bits;
-       const int ao_bits;
-       const int n_ai_chans;
-       const int n_ao_chans;
-       const struct comedi_lrange *ai_range_table, *ao_range_table;
-       int (*ai_rinsn) (struct comedi_device *dev,
-                       struct comedi_subdevice *s,
-                       struct comedi_insn *insn,
-                       unsigned int *data);
-       int (*ao_rinsn) (struct comedi_device *dev,
-                       struct comedi_subdevice *s,
-                       struct comedi_insn *insn,
-                       unsigned int *data);
-       int (*ao_winsn) (struct comedi_device *dev,
-                       struct comedi_subdevice *s,
-                       struct comedi_insn *insn,
-                       unsigned int *data);
-};
-
 static const struct comedi_lrange ranges_ai = {
        4, {RANGE(-5., 5.), RANGE(-10., 10.), RANGE(0., 5.), RANGE(0., 10.)}
 };
@@ -258,11 +229,6 @@ struct pcmmio_private {
        struct pcmmio_subdev_private *sprivs;
 };
 
-/*
- * most drivers define the following macro to make it easy to
- * access the private structure.
- */
-#define devpriv ((struct pcmmio_private *)dev->private)
 #define subpriv ((struct pcmmio_subdev_private *)s->private)
 
 /* DIO devices are slightly special.  Although it is possible to
@@ -416,9 +382,9 @@ static int pcmmio_dio_insn_config(struct comedi_device *dev,
 
 static void switch_page(struct comedi_device *dev, int asic, int page)
 {
-       const struct pcmmio_board *board = comedi_board(dev);
+       struct pcmmio_private *devpriv = dev->private;
 
-       if (asic < 0 || asic >= board->dio_num_asics)
+       if (asic < 0 || asic >= 1)
                return;         /* paranoia */
        if (page < 0 || page >= NUM_PAGES)
                return;         /* more paranoia */
@@ -434,10 +400,10 @@ static void switch_page(struct comedi_device *dev, int asic, int page)
 static void init_asics(struct comedi_device *dev)
 {                              /* sets up an
                                   ASIC chip to defaults */
-       const struct pcmmio_board *board = comedi_board(dev);
+       struct pcmmio_private *devpriv = dev->private;
        int asic;
 
-       for (asic = 0; asic < board->dio_num_asics; ++asic) {
+       for (asic = 0; asic < 1; ++asic) {
                int port, page;
                unsigned long baseaddr = devpriv->asics[asic].iobase;
 
@@ -472,9 +438,9 @@ static void init_asics(struct comedi_device *dev)
 #ifdef notused
 static void lock_port(struct comedi_device *dev, int asic, int port)
 {
-       const struct pcmmio_board *board = comedi_board(dev);
+       struct pcmmio_private *devpriv = dev->private;
 
-       if (asic < 0 || asic >= board->dio_num_asics)
+       if (asic < 0 || asic >= 1)
                return;         /* paranoia */
        if (port < 0 || port >= PORTS_PER_ASIC)
                return;         /* more paranoia */
@@ -488,9 +454,9 @@ static void lock_port(struct comedi_device *dev, int asic, int port)
 
 static void unlock_port(struct comedi_device *dev, int asic, int port)
 {
-       const struct pcmmio_board *board = comedi_board(dev);
+       struct pcmmio_private *devpriv = dev->private;
 
-       if (asic < 0 || asic >= board->dio_num_asics)
+       if (asic < 0 || asic >= 1)
                return;         /* paranoia */
        if (port < 0 || port >= PORTS_PER_ASIC)
                return;         /* more paranoia */
@@ -504,6 +470,7 @@ static void unlock_port(struct comedi_device *dev, int asic, int port)
 static void pcmmio_stop_intr(struct comedi_device *dev,
                             struct comedi_subdevice *s)
 {
+       struct pcmmio_private *devpriv = dev->private;
        int nports, firstport, asic, port;
 
        asic = subpriv->dio.intr.asic;
@@ -526,6 +493,7 @@ static irqreturn_t interrupt_pcmmio(int irq, void *d)
 {
        int asic, got1 = 0;
        struct comedi_device *dev = (struct comedi_device *)d;
+       struct pcmmio_private *devpriv = dev->private;
        int i;
 
        for (asic = 0; asic < MAX_ASICS; ++asic) {
@@ -685,6 +653,8 @@ static irqreturn_t interrupt_pcmmio(int irq, void *d)
 static int pcmmio_start_intr(struct comedi_device *dev,
                             struct comedi_subdevice *s)
 {
+       struct pcmmio_private *devpriv = dev->private;
+
        if (!subpriv->dio.intr.continuous && subpriv->dio.intr.stop_count == 0) {
                /* An empty acquisition! */
                s->async->events |= COMEDI_CB_EOA;
@@ -1012,7 +982,7 @@ static int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
 
 static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
-       const struct pcmmio_board *board = comedi_board(dev);
+       struct pcmmio_private *devpriv;
        struct comedi_subdevice *s;
        int sdev_no, chans_left, n_dio_subdevs, n_subdevs, port, asic,
            thisasic_chanct = 0;
@@ -1020,32 +990,25 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
        unsigned int irq[MAX_ASICS];
        int ret;
 
+       dev->board_name = dev->driver->driver_name;
+
        iobase = it->options[0];
        irq[0] = it->options[1];
 
        printk(KERN_INFO "comedi%d: %s: io: %lx attaching...\n", dev->minor,
-                       dev->driver->driver_name, iobase);
+                       dev->board_name, iobase);
 
        dev->iobase = iobase;
 
-       if (!iobase || !request_region(iobase,
-                                      board->total_iosize,
-                                      dev->driver->driver_name)) {
+       if (!iobase || !request_region(iobase, 32, dev->board_name)) {
                printk(KERN_ERR "comedi%d: I/O port conflict\n", dev->minor);
                return -EIO;
        }
 
-       dev->board_name = board->name;
-
-/*
- * Allocate the private structure area.  alloc_private() is a
- * convenient macro defined in comedidev.h.
- */
-       if (alloc_private(dev, sizeof(struct pcmmio_private)) < 0) {
-               printk(KERN_ERR "comedi%d: cannot allocate private data structure\n",
-                               dev->minor);
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
                return -ENOMEM;
-       }
+       dev->private = devpriv;
 
        for (asic = 0; asic < MAX_ASICS; ++asic) {
                devpriv->asics[asic].num = asic;
@@ -1059,7 +1022,7 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
                spin_lock_init(&devpriv->asics[asic].spinlock);
        }
 
-       chans_left = CHANS_PER_ASIC * board->dio_num_asics;
+       chans_left = CHANS_PER_ASIC * 1;
        n_dio_subdevs = CALC_N_DIO_SUBDEVS(chans_left);
        n_subdevs = n_dio_subdevs + 2;
        devpriv->sprivs =
@@ -1078,13 +1041,13 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
        /* First, AI */
        s = &dev->subdevices[0];
        s->private = &devpriv->sprivs[0];
-       s->maxdata = (1 << board->ai_bits) - 1;
-       s->range_table = board->ai_range_table;
+       s->maxdata = 0xffff;
+       s->range_table = &ranges_ai;
        s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF;
        s->type = COMEDI_SUBD_AI;
-       s->n_chan = board->n_ai_chans;
+       s->n_chan = 16;
        s->len_chanlist = s->n_chan;
-       s->insn_read = board->ai_rinsn;
+       s->insn_read = ai_rinsn;
        subpriv->iobase = dev->iobase + 0;
        /* initialize the resource enable register by clearing it */
        outb(0, subpriv->iobase + 3);
@@ -1093,14 +1056,14 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
        /* Next, AO */
        s = &dev->subdevices[1];
        s->private = &devpriv->sprivs[1];
-       s->maxdata = (1 << board->ao_bits) - 1;
-       s->range_table = board->ao_range_table;
+       s->maxdata = 0xffff;
+       s->range_table = &ranges_ao;
        s->subdev_flags = SDF_READABLE;
        s->type = COMEDI_SUBD_AO;
-       s->n_chan = board->n_ao_chans;
+       s->n_chan = 8;
        s->len_chanlist = s->n_chan;
-       s->insn_read = board->ao_rinsn;
-       s->insn_write = board->ao_winsn;
+       s->insn_read = ao_rinsn;
+       s->insn_write = ao_winsn;
        subpriv->iobase = dev->iobase + 8;
        /* initialize the resource enable register by clearing it */
        outb(0, subpriv->iobase + 3);
@@ -1180,7 +1143,7 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
        for (asic = 0; irq[0] && asic < MAX_ASICS; ++asic) {
                if (irq[asic]
                    && request_irq(irq[asic], interrupt_pcmmio,
-                                  IRQF_SHARED, board->name, dev)) {
+                                  IRQF_SHARED, dev->board_name, dev)) {
                        int i;
                        /* unroll the allocated irqs.. */
                        for (i = asic - 1; i >= 0; --i) {
@@ -1204,11 +1167,11 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 
 static void pcmmio_detach(struct comedi_device *dev)
 {
-       const struct pcmmio_board *board = comedi_board(dev);
+       struct pcmmio_private *devpriv = dev->private;
        int i;
 
        if (dev->iobase)
-               release_region(dev->iobase, board->total_iosize);
+               release_region(dev->iobase, 32);
        for (i = 0; i < MAX_ASICS; ++i) {
                if (devpriv && devpriv->asics[i].irq)
                        free_irq(devpriv->asics[i].irq, dev);
@@ -1217,32 +1180,11 @@ static void pcmmio_detach(struct comedi_device *dev)
                kfree(devpriv->sprivs);
 }
 
-static const struct pcmmio_board pcmmio_boards[] = {
-       {
-               .name           = "pcmmio",
-               .dio_num_asics  = 1,
-               .dio_num_ports  = 6,
-               .total_iosize   = 32,
-               .ai_bits        = 16,
-               .ao_bits        = 16,
-               .n_ai_chans     = 16,
-               .n_ao_chans     = 8,
-               .ai_range_table = &ranges_ai,
-               .ao_range_table = &ranges_ao,
-               .ai_rinsn       = ai_rinsn,
-               .ao_rinsn       = ao_rinsn,
-               .ao_winsn       = ao_winsn
-       },
-};
-
 static struct comedi_driver pcmmio_driver = {
        .driver_name    = "pcmmio",
        .module         = THIS_MODULE,
        .attach         = pcmmio_attach,
        .detach         = pcmmio_detach,
-       .board_name     = &pcmmio_boards[0].name,
-       .offset         = sizeof(struct pcmmio_board),
-       .num_names      = ARRAY_SIZE(pcmmio_boards),
 };
 module_comedi_driver(pcmmio_driver);
 
index 0e32119bc3f9a56af1cbbdb5607b9b9dd5d481c0..31ea20c2d39e1ebe39df58a845b86d70b3787d68 100644 (file)
@@ -194,11 +194,6 @@ struct pcmuio_private {
        struct pcmuio_subdev_private *sprivs;
 };
 
-/*
- * most drivers define the following macro to make it easy to
- * access the private structure.
- */
-#define devpriv ((struct pcmuio_private *)dev->private)
 #define subpriv ((struct pcmuio_subdev_private *)s->private)
 
 /* DIO devices are slightly special.  Although it is possible to
@@ -348,6 +343,7 @@ static int pcmuio_dio_insn_config(struct comedi_device *dev,
 static void switch_page(struct comedi_device *dev, int asic, int page)
 {
        const struct pcmuio_board *board = comedi_board(dev);
+       struct pcmuio_private *devpriv = dev->private;
 
        if (asic < 0 || asic >= board->num_asics)
                return;         /* paranoia */
@@ -404,6 +400,7 @@ static void init_asics(struct comedi_device *dev)
 static void lock_port(struct comedi_device *dev, int asic, int port)
 {
        const struct pcmuio_board *board = comedi_board(dev);
+       struct pcmuio_private *devpriv = dev->private;
 
        if (asic < 0 || asic >= board->num_asics)
                return;         /* paranoia */
@@ -419,6 +416,7 @@ static void lock_port(struct comedi_device *dev, int asic, int port)
 static void unlock_port(struct comedi_device *dev, int asic, int port)
 {
        const struct pcmuio_board *board = comedi_board(dev);
+       struct pcmuio_private *devpriv = dev->private;
 
        if (asic < 0 || asic >= board->num_asics)
                return;         /* paranoia */
@@ -435,6 +433,7 @@ static void pcmuio_stop_intr(struct comedi_device *dev,
                             struct comedi_subdevice *s)
 {
        int nports, firstport, asic, port;
+       struct pcmuio_private *devpriv = dev->private;
 
        asic = subpriv->intr.asic;
        if (asic < 0)
@@ -456,6 +455,7 @@ static irqreturn_t interrupt_pcmuio(int irq, void *d)
 {
        int asic, got1 = 0;
        struct comedi_device *dev = (struct comedi_device *)d;
+       struct pcmuio_private *devpriv = dev->private;
        int i;
 
        for (asic = 0; asic < MAX_ASICS; ++asic) {
@@ -607,6 +607,8 @@ static irqreturn_t interrupt_pcmuio(int irq, void *d)
 static int pcmuio_start_intr(struct comedi_device *dev,
                             struct comedi_subdevice *s)
 {
+       struct pcmuio_private *devpriv = dev->private;
+
        if (!subpriv->intr.continuous && subpriv->intr.stop_count == 0) {
                /* An empty acquisition! */
                s->async->events |= COMEDI_CB_EOA;
@@ -748,6 +750,7 @@ pcmuio_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
 static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
        const struct pcmuio_board *board = comedi_board(dev);
+       struct pcmuio_private *devpriv;
        struct comedi_subdevice *s;
        int sdev_no, chans_left, n_subdevs, port, asic, thisasic_chanct = 0;
        unsigned long iobase;
@@ -772,15 +775,10 @@ static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 
        dev->board_name = board->name;
 
-/*
- * Allocate the private structure area.  alloc_private() is a
- * convenient macro defined in comedidev.h.
- */
-       if (alloc_private(dev, sizeof(struct pcmuio_private)) < 0) {
-               dev_warn(dev->class_dev,
-                        "cannot allocate private data structure\n");
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
                return -ENOMEM;
-       }
+       dev->private = devpriv;
 
        for (asic = 0; asic < MAX_ASICS; ++asic) {
                devpriv->asics[asic].num = asic;
@@ -905,6 +903,7 @@ static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 static void pcmuio_detach(struct comedi_device *dev)
 {
        const struct pcmuio_board *board = comedi_board(dev);
+       struct pcmuio_private *devpriv = dev->private;
        int i;
 
        if (dev->iobase)
index 78dfe167b147d502ee1ee6c91b61dc22223acc57..d7842c95d9825bf765757b1b269334d53e30b037 100644 (file)
@@ -57,13 +57,18 @@ struct boarddef_struct {
        const struct comedi_lrange *range;
 };
 
+struct poc_private {
+       unsigned int ao_readback[32];
+};
+
 static int readback_insn(struct comedi_device *dev, struct comedi_subdevice *s,
                         struct comedi_insn *insn, unsigned int *data)
 {
+       struct poc_private *devpriv = dev->private;
        int chan;
 
        chan = CR_CHAN(insn->chanspec);
-       data[0] = ((unsigned int *)dev->private)[chan];
+       data[0] = devpriv->ao_readback[chan];
 
        return 1;
 }
@@ -75,12 +80,13 @@ static int readback_insn(struct comedi_device *dev, struct comedi_subdevice *s,
 static int dac02_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
                          struct comedi_insn *insn, unsigned int *data)
 {
+       struct poc_private *devpriv = dev->private;
        int temp;
        int chan;
        int output;
 
        chan = CR_CHAN(insn->chanspec);
-       ((unsigned int *)dev->private)[chan] = data[0];
+       devpriv->ao_readback[chan] = data[0];
        output = data[0];
 #ifdef wrong
        /*  convert to complementary binary if range is bipolar */
@@ -131,6 +137,7 @@ static int pcl734_insn_bits(struct comedi_device *dev,
 static int poc_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
        const struct boarddef_struct *board = comedi_board(dev);
+       struct poc_private *devpriv;
        struct comedi_subdevice *s;
        unsigned long iobase;
        unsigned int iosize;
@@ -160,8 +167,10 @@ static int poc_attach(struct comedi_device *dev, struct comedi_devconfig *it)
        if (ret)
                return ret;
 
-       if (alloc_private(dev, sizeof(unsigned int) * board->n_chan) < 0)
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
                return -ENOMEM;
+       dev->private = devpriv;
 
        /* analog output subdevice */
        s = &dev->subdevices[0];
index 3e276f7a33806d788c25fd0db6532f826529048a..d15bd8ac3d4f8ed32b66080a4be077b92e2199f0 100644 (file)
@@ -47,6 +47,8 @@ Status: works
 Devices: [Quatech] DAQP-208 (daqp), DAQP-308
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include "../comedidev.h"
 #include <linux/semaphore.h>
 
@@ -195,8 +197,8 @@ static struct comedi_driver driver_daqp = {
 
 static void daqp_dump(struct comedi_device *dev)
 {
-       printk(KERN_INFO "DAQP: status %02x; aux status %02x\n",
-              inb(dev->iobase + DAQP_STATUS), inb(dev->iobase + DAQP_AUX));
+       dev_info(dev->class_dev, "status %02x; aux status %02x\n",
+                inb(dev->iobase + DAQP_STATUS), inb(dev->iobase + DAQP_AUX));
 }
 
 static void hex_dump(char *str, void *ptr, int len)
@@ -255,33 +257,29 @@ static enum irqreturn daqp_interrupt(int irq, void *dev_id)
        int status;
 
        if (local == NULL) {
-               printk(KERN_WARNING
-                      "daqp_interrupt(): irq %d for unknown device.\n", irq);
+               pr_warn("irq %d for unknown device.\n", irq);
                return IRQ_NONE;
        }
 
        dev = local->dev;
        if (dev == NULL) {
-               printk(KERN_WARNING "daqp_interrupt(): NULL comedi_device.\n");
+               pr_warn("NULL comedi_device.\n");
                return IRQ_NONE;
        }
 
        if (!dev->attached) {
-               printk(KERN_WARNING
-                      "daqp_interrupt(): struct comedi_device not yet attached.\n");
+               pr_warn("struct comedi_device not yet attached.\n");
                return IRQ_NONE;
        }
 
        s = local->s;
        if (s == NULL) {
-               printk(KERN_WARNING
-                      "daqp_interrupt(): NULL comedi_subdevice.\n");
+               pr_warn("NULL comedi_subdevice.\n");
                return IRQ_NONE;
        }
 
        if ((struct local_info_t *)s->private != local) {
-               printk(KERN_WARNING
-                      "daqp_interrupt(): invalid comedi_subdevice.\n");
+               pr_warn("invalid comedi_subdevice.\n");
                return IRQ_NONE;
        }
 
@@ -331,8 +329,8 @@ static enum irqreturn daqp_interrupt(int irq, void *dev_id)
                }
 
                if (loop_limit <= 0) {
-                       printk(KERN_WARNING
-                              "loop_limit reached in daqp_interrupt()\n");
+                       dev_warn(dev->class_dev,
+                                "loop_limit reached in daqp_interrupt()\n");
                        daqp_ai_cancel(dev, s);
                        s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
                }
@@ -736,8 +734,8 @@ static int daqp_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
        while (--counter
               && (inb(dev->iobase + DAQP_STATUS) & DAQP_STATUS_EVENTS)) ;
        if (!counter) {
-               printk(KERN_ERR
-                      "daqp: couldn't clear interrupts in status register\n");
+               dev_err(dev->class_dev,
+                       "couldn't clear interrupts in status register\n");
                return -1;
        }
 
@@ -852,8 +850,8 @@ static int daqp_attach(struct comedi_device *dev, struct comedi_devconfig *it)
        if (ret)
                return ret;
 
-       printk(KERN_INFO "comedi%d: attaching daqp%d (io 0x%04lx)\n",
-              dev->minor, it->options[0], dev->iobase);
+       dev_info(dev->class_dev, "attaching daqp%d (io 0x%04lx)\n",
+                it->options[0], dev->iobase);
 
        s = &dev->subdevices[0];
        dev->read_subdev = s;
@@ -958,7 +956,7 @@ static int daqp_cs_attach(struct pcmcia_device *link)
                if (dev_table[i] == NULL)
                        break;
        if (i == MAX_DEV) {
-               printk(KERN_NOTICE "daqp_cs: no devices available\n");
+               dev_notice(&link->dev, "no devices available\n");
                return -ENODEV;
        }
 
index 41d24b08913b8c70f381c3fa19813e2c0fb6748d..0a91738eae330f0b3c7989ced1823c5a528ffaa6 100644 (file)
@@ -507,15 +507,14 @@ static int rtd520_probe_fifo_depth(struct comedi_device *dev)
                }
        }
        if (i == limit) {
-               printk(KERN_INFO "\ncomedi: %s: failed to probe fifo size.\n",
-                      DRV_NAME);
+               dev_info(dev->class_dev, "failed to probe fifo size.\n");
                return -EIO;
        }
        writel(0, devpriv->las0 + LAS0_ADC_FIFO_CLEAR);
        if (fifo_size != 0x400 && fifo_size != 0x2000) {
-               printk
-                   (KERN_INFO "\ncomedi: %s: unexpected fifo size of %i, expected 1024 or 8192.\n",
-                    DRV_NAME, fifo_size);
+               dev_info(dev->class_dev,
+                        "unexpected fifo size of %i, expected 1024 or 8192.\n",
+                        fifo_size);
                return -EIO;
        }
        return fifo_size;
@@ -1600,7 +1599,7 @@ static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it)
        int index;
 #endif
 
-       printk(KERN_INFO "comedi%d: rtd520 attaching.\n", dev->minor);
+       dev_info(dev->class_dev, "rtd520 attaching.\n");
 
 #if defined(CONFIG_COMEDI_DEBUG) && defined(USE_DMA)
        /* You can set this a load time: modprobe comedi comedi_debug=1 */
@@ -1608,13 +1607,10 @@ static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it)
                comedi_debug = 1;
 #endif
 
-       /*
-        * Allocate the private structure area.  alloc_private() is a
-        * convenient macro defined in comedidev.h.
-        */
-       if (alloc_private(dev, sizeof(struct rtdPrivate)) < 0)
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
                return -ENOMEM;
-       devpriv = dev->private;
+       dev->private = devpriv;
 
        pcidev = rtd_find_pci(dev, it);
        if (!pcidev)
@@ -1626,7 +1622,8 @@ static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 
        ret = comedi_pci_enable(pcidev, DRV_NAME);
        if (ret < 0) {
-               printk(KERN_INFO "Failed to enable PCI device and request regions.\n");
+               dev_info(dev->class_dev,
+                        "Failed to enable PCI device and request regions.\n");
                return ret;
        }
        dev->iobase = 1;        /* the "detach" needs this */
@@ -1653,8 +1650,9 @@ static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it)
                pci_read_config_byte(pcidev,
                                     PCI_LATENCY_TIMER, &pci_latency);
                if (pci_latency < 32) {
-                       printk(KERN_INFO "%s: PCI latency changed from %d to %d\n",
-                              dev->board_name, pci_latency, 32);
+                       dev_info(dev->class_dev,
+                                "PCI latency changed from %d to %d\n",
+                                pci_latency, 32);
                        pci_write_config_byte(pcidev,
                                              PCI_LATENCY_TIMER, 32);
                } else {
@@ -1675,7 +1673,7 @@ static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it)
        }
 
        /* Show board configuration */
-       printk(KERN_INFO "%s:", dev->board_name);
+       dev_info(dev->class_dev, "%s:", dev->board_name);
 
        ret = comedi_alloc_subdevices(dev, 4);
        if (ret)
@@ -1767,7 +1765,7 @@ static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it)
                return ret;
        }
        dev->irq = pcidev->irq;
-       printk(KERN_INFO "( irq=%u )", dev->irq);
+       dev_info(dev->class_dev, "( irq=%u )", dev->irq);
 
        ret = rtd520_probe_fifo_depth(dev);
        if (ret < 0)
@@ -1844,7 +1842,7 @@ static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it)
                /* set DMA trigger source */
                writel(DMAS_ADFIFO_HALF_FULL, devpriv->las0 + LAS0_DMA0_SRC);
        } else {
-               printk(KERN_INFO "( no IRQ->no DMA )");
+               dev_info(dev->class_dev, "( no IRQ->no DMA )");
        }
 #endif /* USE_DMA */
 
index 137885b1681ad045aa8fad64d40826aaa23d089a..7e577e444909211b192189cef3640ba278ab9083 100644 (file)
@@ -161,8 +161,6 @@ struct rti800_private {
        int muxgain_bits;
 };
 
-#define devpriv ((struct rti800_private *)dev->private)
-
 #define RTI800_TIMEOUT 100
 
 static irqreturn_t rti800_interrupt(int irq, void *dev)
@@ -177,6 +175,7 @@ static int rti800_ai_insn_read(struct comedi_device *dev,
                               struct comedi_subdevice *s,
                               struct comedi_insn *insn, unsigned int *data)
 {
+       struct rti800_private *devpriv = dev->private;
        int i, t;
        int status;
        int chan = CR_CHAN(insn->chanspec);
@@ -229,6 +228,7 @@ static int rti800_ao_insn_read(struct comedi_device *dev,
                               struct comedi_subdevice *s,
                               struct comedi_insn *insn, unsigned int *data)
 {
+       struct rti800_private *devpriv = dev->private;
        int i;
        int chan = CR_CHAN(insn->chanspec);
 
@@ -242,6 +242,7 @@ static int rti800_ao_insn_write(struct comedi_device *dev,
                                struct comedi_subdevice *s,
                                struct comedi_insn *insn, unsigned int *data)
 {
+       struct rti800_private *devpriv = dev->private;
        int chan = CR_CHAN(insn->chanspec);
        int d;
        int i;
@@ -303,6 +304,7 @@ static int rti800_do_insn_bits(struct comedi_device *dev,
 static int rti800_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
        const struct rti800_board *board = comedi_board(dev);
+       struct rti800_private *devpriv;
        unsigned int irq;
        unsigned long iobase;
        int ret;
@@ -347,9 +349,10 @@ static int rti800_attach(struct comedi_device *dev, struct comedi_devconfig *it)
        if (ret)
                return ret;
 
-       ret = alloc_private(dev, sizeof(struct rti800_private));
-       if (ret < 0)
-               return ret;
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
+               return -ENOMEM;
+       dev->private = devpriv;
 
        devpriv->adc_mux = it->options[2];
        devpriv->adc_range = it->options[3];
index 3f9d0278be50dccdf788066c5095b607ec2bfdac..2185ca1bcf020638914eb54621ad2c4696779544 100644 (file)
@@ -55,12 +55,11 @@ struct rti802_private {
        unsigned int ao_readback[8];
 };
 
-#define devpriv ((struct rti802_private *)dev->private)
-
 static int rti802_ao_insn_read(struct comedi_device *dev,
                               struct comedi_subdevice *s,
                               struct comedi_insn *insn, unsigned int *data)
 {
+       struct rti802_private *devpriv = dev->private;
        int i;
 
        for (i = 0; i < insn->n; i++)
@@ -73,6 +72,7 @@ static int rti802_ao_insn_write(struct comedi_device *dev,
                                struct comedi_subdevice *s,
                                struct comedi_insn *insn, unsigned int *data)
 {
+       struct rti802_private *devpriv = dev->private;
        int i, d;
        int chan = CR_CHAN(insn->chanspec);
 
@@ -89,6 +89,7 @@ static int rti802_ao_insn_write(struct comedi_device *dev,
 
 static int rti802_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
+       struct rti802_private *devpriv;
        struct comedi_subdevice *s;
        int i;
        unsigned long iobase;
@@ -104,8 +105,10 @@ static int rti802_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 
        dev->board_name = "rti802";
 
-       if (alloc_private(dev, sizeof(struct rti802_private)))
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
                return -ENOMEM;
+       dev->private = devpriv;
 
        ret = comedi_alloc_subdevices(dev, 1);
        if (ret)
index a1e256293bd670b5ebdacaf456041eb85c353a07..39232b359453395a98d08b771d809195827e57c1 100644 (file)
@@ -564,10 +564,10 @@ static int s526_attach(struct comedi_device *dev, struct comedi_devconfig *it)
        }
        dev->iobase = iobase;
 
-       ret = alloc_private(dev, sizeof(*devpriv));
-       if (ret)
-               return ret;
-       devpriv = dev->private;
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
+               return -ENOMEM;
+       dev->private = devpriv;
 
        ret = comedi_alloc_subdevices(dev, 4);
        if (ret)
index 551d68b7837cde3bd9e43229d06cec23c0f57582..15755325121dbb9174200532e93151484b4fb973 100644 (file)
@@ -161,7 +161,6 @@ static struct dio_private *dio_private_word[]={
 };
 */
 
-#define devpriv ((struct s626_private *)dev->private)
 #define diopriv ((struct dio_private *)s->private)
 
 /*  COUNTER OBJECT ------------------------------------------------ */
@@ -232,6 +231,8 @@ static const struct comedi_lrange s626_range_table = { 2, {
 /*  critical section. */
 static void DEBItransfer(struct comedi_device *dev)
 {
+       struct s626_private *devpriv = dev->private;
+
        /*  Initiate upload of shadow RAM to DEBI control register. */
        MC_ENABLE(P_MC2, MC2_UPLD_DEBI);
 
@@ -249,6 +250,7 @@ static void DEBItransfer(struct comedi_device *dev)
 
 static uint16_t DEBIread(struct comedi_device *dev, uint16_t addr)
 {
+       struct s626_private *devpriv = dev->private;
        uint16_t retval;
 
        /*  Set up DEBI control register value in shadow RAM. */
@@ -267,6 +269,7 @@ static uint16_t DEBIread(struct comedi_device *dev, uint16_t addr)
 /*  Write a value to a gate array register. */
 static void DEBIwrite(struct comedi_device *dev, uint16_t addr, uint16_t wdata)
 {
+       struct s626_private *devpriv = dev->private;
 
        /*  Set up DEBI control register value in shadow RAM. */
        WR7146(P_DEBICMD, DEBI_CMD_WRWORD | addr);
@@ -283,6 +286,7 @@ static void DEBIwrite(struct comedi_device *dev, uint16_t addr, uint16_t wdata)
 static void DEBIreplace(struct comedi_device *dev, uint16_t addr, uint16_t mask,
                        uint16_t wdata)
 {
+       struct s626_private *devpriv = dev->private;
 
        /*  Copy target gate array register into P_DEBIAD register. */
        WR7146(P_DEBICMD, DEBI_CMD_RDWORD | addr);
@@ -302,6 +306,8 @@ static void DEBIreplace(struct comedi_device *dev, uint16_t addr, uint16_t mask,
 
 static uint32_t I2Chandshake(struct comedi_device *dev, uint32_t val)
 {
+       struct s626_private *devpriv = dev->private;
+
        /*  Write I2C command to I2C Transfer Control shadow register. */
        WR7146(P_I2CCTRL, val);
 
@@ -324,6 +330,7 @@ static uint32_t I2Chandshake(struct comedi_device *dev, uint32_t val)
 /*  Read uint8_t from EEPROM. */
 static uint8_t I2Cread(struct comedi_device *dev, uint8_t addr)
 {
+       struct s626_private *devpriv = dev->private;
        uint8_t rtnval;
 
        /*  Send EEPROM target address. */
@@ -375,6 +382,7 @@ static uint8_t trimadrs[] = { 0x40, 0x41, 0x42, 0x50, 0x51, 0x52, 0x53, 0x60, 0x
  */
 static void SendDAC(struct comedi_device *dev, uint32_t val)
 {
+       struct s626_private *devpriv = dev->private;
 
        /* START THE SERIAL CLOCK RUNNING ------------- */
 
@@ -496,6 +504,7 @@ static void SendDAC(struct comedi_device *dev, uint32_t val)
 /*  Private helper function: Write setpoint to an application DAC channel. */
 static void SetDAC(struct comedi_device *dev, uint16_t chan, short dacdata)
 {
+       struct s626_private *devpriv = dev->private;
        register uint16_t signmask;
        register uint32_t WSImage;
 
@@ -553,6 +562,7 @@ static void SetDAC(struct comedi_device *dev, uint16_t chan, short dacdata)
 static void WriteTrimDAC(struct comedi_device *dev, uint8_t LogicalChan,
                         uint8_t DacData)
 {
+       struct s626_private *devpriv = dev->private;
        uint32_t chan;
 
        /*  Save the new setpoint in case the application needs to read it back later. */
@@ -735,6 +745,7 @@ static int s626_dio_clear_irq(struct comedi_device *dev)
 static irqreturn_t s626_irq_handler(int irq, void *d)
 {
        struct comedi_device *dev = d;
+       struct s626_private *devpriv = dev->private;
        struct comedi_subdevice *s;
        struct comedi_cmd *cmd;
        struct enc_private *k;
@@ -968,6 +979,7 @@ static irqreturn_t s626_irq_handler(int irq, void *d)
  */
 static void ResetADC(struct comedi_device *dev, uint8_t *ppl)
 {
+       struct s626_private *devpriv = dev->private;
        register uint32_t *pRPS;
        uint32_t JmpAdrs;
        uint16_t i;
@@ -1163,6 +1175,7 @@ static int s626_ai_insn_config(struct comedi_device *dev,
 
 /* static int s626_ai_rinsn(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data) */
 /* { */
+/*   struct s626_private *devpriv = dev->private; */
 /*   register uint8_t  i; */
 /*   register int32_t  *readaddr; */
 
@@ -1191,6 +1204,7 @@ static int s626_ai_insn_read(struct comedi_device *dev,
                             struct comedi_subdevice *s,
                             struct comedi_insn *insn, unsigned int *data)
 {
+       struct s626_private *devpriv = dev->private;
        uint16_t chan = CR_CHAN(insn->chanspec);
        uint16_t range = CR_RANGE(insn->chanspec);
        uint16_t AdcSpec = 0;
@@ -1302,6 +1316,8 @@ static int s626_ai_load_polllist(uint8_t *ppl, struct comedi_cmd *cmd)
 static int s626_ai_inttrig(struct comedi_device *dev,
                           struct comedi_subdevice *s, unsigned int trignum)
 {
+       struct s626_private *devpriv = dev->private;
+
        if (trignum != 0)
                return -EINVAL;
 
@@ -1378,7 +1394,7 @@ static void s626_timer_load(struct comedi_device *dev, struct enc_private *k,
 /*  TO COMPLETE  */
 static int s626_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
-
+       struct s626_private *devpriv = dev->private;
        uint8_t ppl[16];
        struct comedi_cmd *cmd = &s->async->cmd;
        struct enc_private *k;
@@ -1643,6 +1659,8 @@ static int s626_ai_cmdtest(struct comedi_device *dev,
 
 static int s626_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+       struct s626_private *devpriv = dev->private;
+
        /*  Stop RPS program in case it is currently running. */
        MC_DISABLE(P_MC1, MC1_ERPS1);
 
@@ -1657,7 +1675,7 @@ static int s626_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
 static int s626_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
                         struct comedi_insn *insn, unsigned int *data)
 {
-
+       struct s626_private *devpriv = dev->private;
        int i;
        uint16_t chan = CR_CHAN(insn->chanspec);
        int16_t dacdata;
@@ -1676,6 +1694,7 @@ static int s626_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
 static int s626_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
                         struct comedi_insn *insn, unsigned int *data)
 {
+       struct s626_private *devpriv = dev->private;
        int i;
 
        for (i = 0; i < insn->n; i++)
@@ -1974,6 +1993,7 @@ static uint16_t GetMode_B(struct comedi_device *dev, struct enc_private *k)
 static void SetMode_A(struct comedi_device *dev, struct enc_private *k,
                      uint16_t Setup, uint16_t DisableIntSrc)
 {
+       struct s626_private *devpriv = dev->private;
        register uint16_t cra;
        register uint16_t crb;
        register uint16_t setup = Setup;        /*  Cache the Standard Setup. */
@@ -2032,6 +2052,7 @@ static void SetMode_A(struct comedi_device *dev, struct enc_private *k,
 static void SetMode_B(struct comedi_device *dev, struct enc_private *k,
                      uint16_t Setup, uint16_t DisableIntSrc)
 {
+       struct s626_private *devpriv = dev->private;
        register uint16_t cra;
        register uint16_t crb;
        register uint16_t setup = Setup;        /*  Cache the Standard Setup. */
@@ -2165,6 +2186,8 @@ static uint16_t GetLoadTrig_B(struct comedi_device *dev, struct enc_private *k)
 static void SetIntSrc_A(struct comedi_device *dev, struct enc_private *k,
                        uint16_t IntSource)
 {
+       struct s626_private *devpriv = dev->private;
+
        /*  Reset any pending counter overflow or index captures. */
        DEBIreplace(dev, k->MyCRB, (uint16_t) (~CRBMSK_INTCTRL),
                    CRBMSK_INTRESETCMD | CRBMSK_INTRESET_A);
@@ -2182,6 +2205,7 @@ static void SetIntSrc_A(struct comedi_device *dev, struct enc_private *k,
 static void SetIntSrc_B(struct comedi_device *dev, struct enc_private *k,
                        uint16_t IntSource)
 {
+       struct s626_private *devpriv = dev->private;
        uint16_t crb;
 
        /*  Cache writeable CRB register image. */
@@ -2412,6 +2436,7 @@ static void CountersInit(struct comedi_device *dev)
 static int s626_allocate_dma_buffers(struct comedi_device *dev)
 {
        struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+       struct s626_private *devpriv = dev->private;
        void *addr;
        dma_addr_t appdma;
 
@@ -2432,6 +2457,7 @@ static int s626_allocate_dma_buffers(struct comedi_device *dev)
 
 static void s626_initialize(struct comedi_device *dev)
 {
+       struct s626_private *devpriv = dev->private;
        dma_addr_t pPhysBuf;
        uint16_t chan;
        int i;
@@ -2667,14 +2693,16 @@ static void s626_initialize(struct comedi_device *dev)
 
 static int s626_attach_pci(struct comedi_device *dev, struct pci_dev *pcidev)
 {
+       struct s626_private *devpriv;
        struct comedi_subdevice *s;
        int ret;
 
-       comedi_set_hw_dev(dev, &pcidev->dev);
        dev->board_name = dev->driver->driver_name;
 
-       if (alloc_private(dev, sizeof(struct s626_private)) < 0)
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
                return -ENOMEM;
+       dev->private = devpriv;
 
        ret = comedi_pci_enable(pcidev, dev->board_name);
        if (ret)
@@ -2794,6 +2822,7 @@ static int s626_attach_pci(struct comedi_device *dev, struct pci_dev *pcidev)
 static void s626_detach(struct comedi_device *dev)
 {
        struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+       struct s626_private *devpriv = dev->private;
 
        if (devpriv) {
                /* stop ai_command */
index 5bf84cfbdcebcb6715418ea132cce4ce1607bfd7..4b3b9b029476024f725afe904efbedcf10418cf6 100644 (file)
@@ -43,10 +43,6 @@ Status: in development
 #include <linux/serial.h>
 #include <linux/poll.h>
 
-struct serial2002_board {
-       const char *name;
-};
-
 struct serial2002_range_table_t {
 
        /*  HACK... */
@@ -68,12 +64,6 @@ struct serial2002_private {
        struct serial2002_range_table_t in_range[32], out_range[32];
 };
 
-/*
- * most drivers define the following macro to make it easy to
- * access the private structure.
- */
-#define devpriv ((struct serial2002_private *)dev->private)
-
 struct serial_data {
        enum { is_invalid, is_digital, is_channel } kind;
        int index;
@@ -348,6 +338,7 @@ static void serial_write(struct file *f, struct serial_data data)
 
 static int serial_2002_open(struct comedi_device *dev)
 {
+       struct serial2002_private *devpriv = dev->private;
        int result;
        char port[20];
 
@@ -655,6 +646,8 @@ err_alloc_configs:
 
 static void serial_2002_close(struct comedi_device *dev)
 {
+       struct serial2002_private *devpriv = dev->private;
+
        if (!IS_ERR(devpriv->tty) && devpriv->tty)
                filp_close(devpriv->tty, NULL);
 }
@@ -663,6 +656,7 @@ static int serial2002_di_rinsn(struct comedi_device *dev,
                               struct comedi_subdevice *s,
                               struct comedi_insn *insn, unsigned int *data)
 {
+       struct serial2002_private *devpriv = dev->private;
        int n;
        int chan;
 
@@ -685,6 +679,7 @@ static int serial2002_do_winsn(struct comedi_device *dev,
                               struct comedi_subdevice *s,
                               struct comedi_insn *insn, unsigned int *data)
 {
+       struct serial2002_private *devpriv = dev->private;
        int n;
        int chan;
 
@@ -704,6 +699,7 @@ static int serial2002_ai_rinsn(struct comedi_device *dev,
                               struct comedi_subdevice *s,
                               struct comedi_insn *insn, unsigned int *data)
 {
+       struct serial2002_private *devpriv = dev->private;
        int n;
        int chan;
 
@@ -726,6 +722,7 @@ static int serial2002_ao_winsn(struct comedi_device *dev,
                               struct comedi_subdevice *s,
                               struct comedi_insn *insn, unsigned int *data)
 {
+       struct serial2002_private *devpriv = dev->private;
        int n;
        int chan;
 
@@ -746,6 +743,7 @@ static int serial2002_ao_rinsn(struct comedi_device *dev,
                               struct comedi_subdevice *s,
                               struct comedi_insn *insn, unsigned int *data)
 {
+       struct serial2002_private *devpriv = dev->private;
        int n;
        int chan = CR_CHAN(insn->chanspec);
 
@@ -759,6 +757,7 @@ static int serial2002_ei_rinsn(struct comedi_device *dev,
                               struct comedi_subdevice *s,
                               struct comedi_insn *insn, unsigned int *data)
 {
+       struct serial2002_private *devpriv = dev->private;
        int n;
        int chan;
 
@@ -780,14 +779,18 @@ static int serial2002_ei_rinsn(struct comedi_device *dev,
 static int serial2002_attach(struct comedi_device *dev,
                             struct comedi_devconfig *it)
 {
-       const struct serial2002_board *board = comedi_board(dev);
+       struct serial2002_private *devpriv;
        struct comedi_subdevice *s;
        int ret;
 
        dev_dbg(dev->class_dev, "serial2002: attach\n");
-       dev->board_name = board->name;
-       if (alloc_private(dev, sizeof(struct serial2002_private)) < 0)
+       dev->board_name = dev->driver->driver_name;
+
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
                return -ENOMEM;
+       dev->private = devpriv;
+
        dev->open = serial_2002_open;
        dev->close = serial_2002_close;
        devpriv->port = it->options[0];
@@ -860,20 +863,11 @@ static void serial2002_detach(struct comedi_device *dev)
        }
 }
 
-static const struct serial2002_board serial2002_boards[] = {
-       {
-               .name   = "serial2002"
-       },
-};
-
 static struct comedi_driver serial2002_driver = {
        .driver_name    = "serial2002",
        .module         = THIS_MODULE,
        .attach         = serial2002_attach,
        .detach         = serial2002_detach,
-       .board_name     = &serial2002_boards[0].name,
-       .offset         = sizeof(struct serial2002_board),
-       .num_names      = ARRAY_SIZE(serial2002_boards),
 };
 module_comedi_driver(serial2002_driver);
 
index b70cdf300bbd74244eb1432e31db9dd44971e20e..f292d798f31ae7b189dbe0d355fab308c644be45 100644 (file)
@@ -145,12 +145,6 @@ struct skel_private {
        unsigned int ao_readback[2];
 };
 
-/*
- * most drivers define the following macro to make it easy to
- * access the private structure.
- */
-#define devpriv ((struct skel_private *)dev->private)
-
 /*
  * The struct comedi_driver structure tells the Comedi core module
  * which functions to call to configure/deconfigure (attach/detach)
@@ -211,6 +205,7 @@ static int skel_ns_to_timer(unsigned int *ns, int round);
  */
 static int skel_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
+       struct skel_private *devpriv;
        struct comedi_subdevice *s;
        int ret;
 
@@ -229,12 +224,11 @@ static int skel_attach(struct comedi_device *dev, struct comedi_devconfig *it)
  */
        dev->board_name = thisboard->name;
 
-/*
- * Allocate the private structure area.  alloc_private() is a
- * convenient macro defined in comedidev.h.
- */
-       if (alloc_private(dev, sizeof(struct skel_private)) < 0)
+       /* Allocate the private data */
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
                return -ENOMEM;
+       dev->private = devpriv;
 
        ret = comedi_alloc_subdevices(dev, 3);
        if (ret)
@@ -504,6 +498,7 @@ static int skel_ns_to_timer(unsigned int *ns, int round)
 static int skel_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
                         struct comedi_insn *insn, unsigned int *data)
 {
+       struct skel_private *devpriv = dev->private;
        int i;
        int chan = CR_CHAN(insn->chanspec);
 
@@ -525,6 +520,7 @@ static int skel_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
 static int skel_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
                         struct comedi_insn *insn, unsigned int *data)
 {
+       struct skel_private *devpriv = dev->private;
        int i;
        int chan = CR_CHAN(insn->chanspec);
 
index ae3aa1c5caef7c0b10ecda2af113ef317f5c5091..afa4016f906ae4d63f816140223dff43dc2fd3a9 100644 (file)
@@ -50,15 +50,6 @@ Status: unknown
 #define PCMR  0xa3             /* Port C Mode Register                      */
 #define PCDR  0xa7             /* Port C Data Register                      */
 
-/* This data structure holds information about the supported boards -------- */
-
-struct dnp_board {
-       const char *name;
-       int ai_chans;
-       int ai_bits;
-       int have_dio;
-};
-
 /* ------------------------------------------------------------------------- */
 /* The insn_bits interface allows packed reading/writing of DIO channels.    */
 /* The comedi core can convert between insn_bits and insn_read/write, so you */
@@ -173,11 +164,10 @@ static int dnp_dio_insn_config(struct comedi_device *dev,
 
 static int dnp_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
-       const struct dnp_board *board = comedi_board(dev);
        struct comedi_subdevice *s;
        int ret;
 
-       dev->board_name = board->name;
+       dev->board_name = dev->driver->driver_name;
 
        ret = comedi_alloc_subdevices(dev, 1);
        if (ret)
@@ -219,23 +209,11 @@ static void dnp_detach(struct comedi_device *dev)
        outb((inb(CSCDR) & 0xAA), CSCDR);
 }
 
-static const struct dnp_board dnp_boards[] = {
-       {
-               .name           = "dnp-1486",
-               .ai_chans       = 16,
-               .ai_bits        = 12,
-               .have_dio       = 1,
-       },
-};
-
 static struct comedi_driver dnp_driver = {
-       .driver_name    = "ssv_dnp",
+       .driver_name    = "dnp-1486",
        .module         = THIS_MODULE,
        .attach         = dnp_attach,
        .detach         = dnp_detach,
-       .board_name     = &dnp_boards[0].name,
-       .offset         = sizeof(struct dnp_board),
-       .num_names      = ARRAY_SIZE(dnp_boards),
 };
 module_comedi_driver(dnp_driver);
 
index 9f1fdec62dcbbc1a10bf56e8df579d2c845d4116..c9ded938314fc019c4588637488b53d16ae818e8 100644 (file)
@@ -42,6 +42,8 @@ Devices: [Fastwel] UNIOxx-5 (unioxx5),
 
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include "../comedidev.h"
 #include <linux/ioport.h>
 #include <linux/slab.h>
@@ -144,8 +146,7 @@ static int __unioxx5_digital_read(struct unioxx5_subd_priv *usp,
 
        channel_offset = __unioxx5_define_chan_offset(channel);
        if (channel_offset < 0) {
-               printk(KERN_ERR
-                      "comedi%d: undefined channel %d. channel range is 0 .. 23\n",
+               pr_err("comedi%d: undefined channel %d. channel range is 0 .. 23\n",
                       minor, channel);
                return 0;
        }
@@ -171,8 +172,7 @@ static int __unioxx5_analog_read(struct unioxx5_subd_priv *usp,
 
        /* defining if given module can work on input */
        if (usp->usp_module_type[module_no] & MODULE_OUTPUT_MASK) {
-               printk(KERN_ERR
-                      "comedi%d: module in position %d with id 0x%02x is for output only",
+               pr_err("comedi%d: module in position %d with id 0x%02x is for output only",
                       minor, module_no, usp->usp_module_type[module_no]);
                return 0;
        }
@@ -209,8 +209,7 @@ static int __unioxx5_digital_write(struct unioxx5_subd_priv *usp,
 
        channel_offset = __unioxx5_define_chan_offset(channel);
        if (channel_offset < 0) {
-               printk(KERN_ERR
-                      "comedi%d: undefined channel %d. channel range is 0 .. 23\n",
+               pr_err("comedi%d: undefined channel %d. channel range is 0 .. 23\n",
                       minor, channel);
                return 0;
        }
@@ -240,8 +239,7 @@ static int __unioxx5_analog_write(struct unioxx5_subd_priv *usp,
 
        /* defining if given module can work on output */
        if (!(usp->usp_module_type[module] & MODULE_OUTPUT_MASK)) {
-               printk(KERN_ERR
-                      "comedi%d: module in position %d with id 0x%0x is for input only!\n",
+               pr_err("comedi%d: module in position %d with id 0x%0x is for input only!\n",
                       minor, module, usp->usp_module_type[module]);
                return 0;
        }
@@ -323,17 +321,17 @@ static int unioxx5_insn_config(struct comedi_device *dev,
        type = usp->usp_module_type[channel / 2];
 
        if (type != MODULE_DIGITAL) {
-               printk(KERN_ERR
-                      "comedi%d: channel configuration accessible only for digital modules\n",
-                      dev->minor);
+               dev_err(dev->class_dev,
+                       "comedi%d: channel configuration accessible only for digital modules\n",
+                       dev->minor);
                return -1;
        }
 
        channel_offset = __unioxx5_define_chan_offset(channel);
        if (channel_offset < 0) {
-               printk(KERN_ERR
-                      "comedi%d: undefined channel %d. channel range is 0 .. 23\n",
-                      dev->minor, channel);
+               dev_err(dev->class_dev,
+                       "comedi%d: undefined channel %d. channel range is 0 .. 23\n",
+                       dev->minor, channel);
                return -1;
        }
 
@@ -348,7 +346,8 @@ static int unioxx5_insn_config(struct comedi_device *dev,
                flags |= mask;
                break;
        default:
-               printk(KERN_ERR "comedi%d: unknown flag\n", dev->minor);
+               dev_err(dev->class_dev,
+                       "comedi%d: unknown flag\n", dev->minor);
                return -1;
        }
 
@@ -375,19 +374,21 @@ static int __unioxx5_subdev_init(struct comedi_subdevice *subdev,
        int i, to, ndef_flag = 0;
 
        if (!request_region(subdev_iobase, UNIOXX5_SIZE, DRIVER_NAME)) {
-               printk(KERN_ERR "comedi%d: I/O port conflict\n", minor);
+               dev_err(subdev->class_dev,
+                       "comedi%d: I/O port conflict\n", minor);
                return -EIO;
        }
 
        usp = kzalloc(sizeof(*usp), GFP_KERNEL);
 
        if (usp == NULL) {
-               printk(KERN_ERR "comedi%d: error! --> out of memory!\n", minor);
+               dev_err(subdev->class_dev,
+                       "comedi%d: error! --> out of memory!\n", minor);
                return -1;
        }
 
        usp->usp_iobase = subdev_iobase;
-       printk(KERN_INFO "comedi%d: |", minor);
+       dev_info(subdev->class_dev, "comedi%d: |", minor);
 
        /* defining modules types */
        for (i = 0; i < 12; i++) {
@@ -433,8 +434,6 @@ static int __unioxx5_subdev_init(struct comedi_subdevice *subdev,
        /* for digital modules only!!! */
        subdev->insn_config = unioxx5_insn_config;
 
-       printk(KERN_INFO "subdevice configured\n");
-
        return 0;
 }
 
@@ -464,8 +463,8 @@ static int unioxx5_attach(struct comedi_device *dev,
 
        /* unioxx5 can has from two to four subdevices */
        if (n_subd < 2) {
-               printk(KERN_ERR
-                      "your card must has at least 2 'g01' subdevices\n");
+               dev_err(dev->class_dev,
+                       "your card must has at least 2 'g01' subdevices\n");
                return -1;
        }
 
@@ -480,7 +479,6 @@ static int unioxx5_attach(struct comedi_device *dev,
                        return -1;
        }
 
-       printk(KERN_INFO "attached\n");
        return 0;
 }
 
index b536bba74351178f6ae939f666ab4b7c4781bb78..e89f4e2927b68929a70b99e6b65649e4fd922fed 100644 (file)
@@ -2386,14 +2386,12 @@ static int usbdux_attach_usb(struct comedi_device *dev,
        down(&start_stop_sem);
        this_usbduxsub = usb_get_intfdata(uinterf);
        if (!this_usbduxsub || !this_usbduxsub->probed) {
-               printk(KERN_ERR
-                      "comedi%d: usbdux: error: attach_usb failed, not connected\n",
-                      dev->minor);
+               dev_err(dev->class_dev,
+                       "usbdux: error: attach_usb failed, not connected\n");
                ret = -ENODEV;
        } else if (this_usbduxsub->attached) {
-               printk(KERN_ERR
-                      "comedi%d: usbdux: error: attach_usb failed, already attached\n",
-                      dev->minor);
+               dev_err(dev->class_dev,
+                       "error: attach_usb failed, already attached\n");
                ret = -ENODEV;
        } else
                ret = usbdux_attach_common(dev, this_usbduxsub);
index 1154a7e2895d5aa944f7ca0befe5aa029d812ca1..060d853dc6519afa3e17a35b23cfe16e70709034 100644 (file)
@@ -37,6 +37,8 @@
  *       udev coldplug problem
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/firmware.h>
 #include <linux/module.h>
@@ -216,8 +218,9 @@ static int send_dux_commands(struct usbduxfastsub_s *udfs, int cmd_type)
                           usb_sndbulkpipe(udfs->usbdev, CHANNELLISTEP),
                           udfs->dux_commands, SIZEOFDUXBUFFER, &nsent, 10000);
        if (tmp < 0)
-               printk(KERN_ERR "comedi%d: could not transmit dux_commands to"
-                      "the usb-device, err=%d\n", udfs->comedidev->minor, tmp);
+               dev_err(&udfs->interface->dev,
+                       "could not transmit dux_commands to the usb-device, err=%d\n",
+                       tmp);
        return tmp;
 }
 
@@ -252,7 +255,7 @@ static int usbduxfast_ai_stop(struct usbduxfastsub_s *udfs, int do_unlink)
        int ret = 0;
 
        if (!udfs) {
-               printk(KERN_ERR "comedi?: usbduxfast_ai_stop: udfs=NULL!\n");
+               pr_err("%s: udfs=NULL!\n", __func__);
                return -EFAULT;
        }
 #ifdef CONFIG_COMEDI_DEBUG
@@ -284,7 +287,7 @@ static int usbduxfast_ai_cancel(struct comedi_device *dev,
 #endif
        udfs = dev->private;
        if (!udfs) {
-               printk(KERN_ERR "comedi: usbduxfast_ai_cancel: udfs=NULL\n");
+               dev_err(dev->class_dev, "%s: udfs=NULL\n", __func__);
                return -EFAULT;
        }
        down(&udfs->sem);
@@ -313,22 +316,19 @@ static void usbduxfastsub_ai_Irq(struct urb *urb)
 
        /* sanity checks - is the urb there? */
        if (!urb) {
-               printk(KERN_ERR "comedi_: usbduxfast_: ao int-handler called "
-                      "with urb=NULL!\n");
+               pr_err("ao int-handler called with urb=NULL!\n");
                return;
        }
        /* the context variable points to the subdevice */
        this_comedidev = urb->context;
        if (!this_comedidev) {
-               printk(KERN_ERR "comedi_: usbduxfast_: urb context is a NULL "
-                      "pointer!\n");
+               pr_err("urb context is a NULL pointer!\n");
                return;
        }
        /* the private structure of the subdevice is usbduxfastsub_s */
        udfs = this_comedidev->private;
        if (!udfs) {
-               printk(KERN_ERR "comedi_: usbduxfast_: private of comedi "
-                      "subdev is a NULL pointer!\n");
+               pr_err("private of comedi subdev is a NULL pointer!\n");
                return;
        }
        /* are we running a command? */
@@ -427,8 +427,8 @@ static void usbduxfastsub_ai_Irq(struct urb *urb)
        urb->status = 0;
        err = usb_submit_urb(urb, GFP_ATOMIC);
        if (err < 0) {
-               printk(KERN_ERR "comedi%d: usbduxfast: urb resubm failed: %d",
-                      udfs->comedidev->minor, err);
+               dev_err(&urb->dev->dev,
+                       "urb resubm failed: %d", err);
                s->async->events |= COMEDI_CB_EOA;
                s->async->events |= COMEDI_CB_ERROR;
                comedi_event(udfs->comedidev, s);
@@ -477,8 +477,8 @@ static int usbduxfastsub_stop(struct usbduxfastsub_s *udfs)
                              local_transfer_buffer, 1, /* Length */
                              EZTIMEOUT);       /* Timeout */
        if (ret < 0) {
-               printk(KERN_ERR "comedi_: usbduxfast: control msg failed "
-                      "(stop)\n");
+               dev_err(&udfs->interface->dev,
+                       "control msg failed (stop)\n");
                return ret;
        }
 
@@ -512,7 +512,7 @@ static int usbduxfastsub_upload(struct usbduxfastsub_s *udfs,
 #endif
 
        if (ret < 0) {
-               printk(KERN_ERR "comedi_: usbduxfast: uppload failed\n");
+               dev_err(&udfs->interface->dev, "uppload failed\n");
                return ret;
        }
 
@@ -538,8 +538,8 @@ static int usbduxfastsub_submit_InURBs(struct usbduxfastsub_s *udfs)
 #endif
        ret = usb_submit_urb(udfs->urbIn, GFP_ATOMIC);
        if (ret) {
-               printk(KERN_ERR "comedi_: usbduxfast: ai: usb_submit_urb error"
-                      " %d\n", ret);
+               dev_err(&udfs->interface->dev,
+                       "ai: usb_submit_urb error %d\n", ret);
                return ret;
        }
        return 0;
@@ -682,8 +682,7 @@ static int usbduxfast_ai_inttrig(struct comedi_device *dev,
 #endif
 
        if (trignum != 0) {
-               printk(KERN_ERR "comedi%d: usbduxfast_ai_inttrig: invalid"
-                      " trignum\n", dev->minor);
+               dev_err(dev->class_dev, "%s: invalid trignum\n", __func__);
                up(&udfs->sem);
                return -EINVAL;
        }
@@ -691,16 +690,16 @@ static int usbduxfast_ai_inttrig(struct comedi_device *dev,
                udfs->ai_cmd_running = 1;
                ret = usbduxfastsub_submit_InURBs(udfs);
                if (ret < 0) {
-                       printk(KERN_ERR "comedi%d: usbduxfast_ai_inttrig: "
-                              "urbSubmit: err=%d\n", dev->minor, ret);
+                       dev_err(dev->class_dev,
+                               "%s: urbSubmit: err=%d\n", __func__, ret);
                        udfs->ai_cmd_running = 0;
                        up(&udfs->sem);
                        return ret;
                }
                s->async->inttrig = NULL;
        } else {
-               printk(KERN_ERR "comedi%d: ai_inttrig but acqu is already"
-                      " running\n", dev->minor);
+               dev_err(dev->class_dev,
+                       "ai_inttrig but acqu is already running\n");
        }
        up(&udfs->sem);
        return 1;
@@ -738,8 +737,8 @@ static int usbduxfast_ai_cmd(struct comedi_device *dev,
                return -ENODEV;
        }
        if (udfs->ai_cmd_running) {
-               printk(KERN_ERR "comedi%d: ai_cmd not possible. Another ai_cmd"
-                      " is running.\n", dev->minor);
+               dev_err(dev->class_dev,
+                       "ai_cmd not possible. Another ai_cmd is running.\n");
                up(&udfs->sem);
                return -EBUSY;
        }
@@ -757,31 +756,29 @@ static int usbduxfast_ai_cmd(struct comedi_device *dev,
                for (i = 0; i < cmd->chanlist_len; ++i) {
                        chan = CR_CHAN(cmd->chanlist[i]);
                        if (chan != i) {
-                               printk(KERN_ERR "comedi%d: cmd is accepting "
-                                      "only consecutive channels.\n",
-                                      dev->minor);
+                               dev_err(dev->class_dev,
+                                       "cmd is accepting only consecutive channels.\n");
                                up(&udfs->sem);
                                return -EINVAL;
                        }
                        if ((gain != CR_RANGE(cmd->chanlist[i]))
                            && (cmd->chanlist_len > 3)) {
-                               printk(KERN_ERR "comedi%d: the gain must be"
-                                      " the same for all channels.\n",
-                                      dev->minor);
+                               dev_err(dev->class_dev,
+                                       "the gain must be the same for all channels.\n");
                                up(&udfs->sem);
                                return -EINVAL;
                        }
                        if (i >= NUMCHANNELS) {
-                               printk(KERN_ERR "comedi%d: channel list too"
-                                      " long\n", dev->minor);
+                               dev_err(dev->class_dev,
+                                       "channel list too long\n");
                                break;
                        }
                }
        }
        steps = 0;
        if (cmd->scan_begin_src == TRIG_TIMER) {
-               printk(KERN_ERR "comedi%d: usbduxfast: "
-                      "scan_begin_src==TRIG_TIMER not valid.\n", dev->minor);
+               dev_err(dev->class_dev,
+                       "scan_begin_src==TRIG_TIMER not valid.\n");
                up(&udfs->sem);
                return -EINVAL;
        }
@@ -789,22 +786,21 @@ static int usbduxfast_ai_cmd(struct comedi_device *dev,
                steps = (cmd->convert_arg * 30) / 1000;
 
        if ((steps < MIN_SAMPLING_PERIOD) && (cmd->chanlist_len != 1)) {
-               printk(KERN_ERR "comedi%d: usbduxfast: ai_cmd: steps=%ld, "
-                      "scan_begin_arg=%d. Not properly tested by cmdtest?\n",
-                      dev->minor, steps, cmd->scan_begin_arg);
+               dev_err(dev->class_dev,
+                       "ai_cmd: steps=%ld, scan_begin_arg=%d. Not properly tested by cmdtest?\n",
+                       steps, cmd->scan_begin_arg);
                up(&udfs->sem);
                return -EINVAL;
        }
        if (steps > MAX_SAMPLING_PERIOD) {
-               printk(KERN_ERR "comedi%d: usbduxfast: ai_cmd: sampling rate "
-                      "too low.\n", dev->minor);
+               dev_err(dev->class_dev, "ai_cmd: sampling rate too low.\n");
                up(&udfs->sem);
                return -EINVAL;
        }
        if ((cmd->start_src == TRIG_EXT) && (cmd->chanlist_len != 1)
            && (cmd->chanlist_len != 16)) {
-               printk(KERN_ERR "comedi%d: usbduxfast: ai_cmd: TRIG_EXT only"
-                      " with 1 or 16 channels possible.\n", dev->minor);
+               dev_err(dev->class_dev,
+                       "ai_cmd: TRIG_EXT only with 1 or 16 channels possible.\n");
                up(&udfs->sem);
                return -EINVAL;
        }
@@ -1121,8 +1117,7 @@ static int usbduxfast_ai_cmd(struct comedi_device *dev,
                break;
 
        default:
-               printk(KERN_ERR "comedi %d: unsupported combination of "
-                      "channels\n", dev->minor);
+               dev_err(dev->class_dev, "unsupported combination of channels\n");
                up(&udfs->sem);
                return -EFAULT;
        }
@@ -1134,17 +1129,16 @@ static int usbduxfast_ai_cmd(struct comedi_device *dev,
        /* 0 means that the AD commands are sent */
        result = send_dux_commands(udfs, SENDADCOMMANDS);
        if (result < 0) {
-               printk(KERN_ERR "comedi%d: adc command could not be submitted."
-                      "Aborting...\n", dev->minor);
+               dev_err(dev->class_dev,
+                       "adc command could not be submitted. Aborting...\n");
                up(&udfs->sem);
                return result;
        }
        if (cmd->stop_src == TRIG_COUNT) {
                udfs->ai_sample_count = cmd->stop_arg * cmd->scan_end_arg;
                if (udfs->ai_sample_count < 1) {
-                       printk(KERN_ERR "comedi%d: "
-                              "(cmd->stop_arg)*(cmd->scan_end_arg)<1, "
-                              "aborting.\n", dev->minor);
+                       dev_err(dev->class_dev,
+                               "(cmd->stop_arg)*(cmd->scan_end_arg)<1, aborting.\n");
                        up(&udfs->sem);
                        return -EFAULT;
                }
@@ -1193,8 +1187,7 @@ static int usbduxfast_ai_insn_read(struct comedi_device *dev,
 
        udfs = dev->private;
        if (!udfs) {
-               printk(KERN_ERR "comedi%d: ai_insn_read: no usb dev.\n",
-                      dev->minor);
+               dev_err(dev->class_dev, "%s: no usb dev.\n", __func__);
                return -ENODEV;
        }
 #ifdef CONFIG_COMEDI_DEBUG
@@ -1207,8 +1200,8 @@ static int usbduxfast_ai_insn_read(struct comedi_device *dev,
                return -ENODEV;
        }
        if (udfs->ai_cmd_running) {
-               printk(KERN_ERR "comedi%d: ai_insn_read not possible. Async "
-                      "Command is running.\n", dev->minor);
+               dev_err(dev->class_dev,
+                       "ai_insn_read not possible. Async Command is running.\n");
                up(&udfs->sem);
                return -EBUSY;
        }
@@ -1268,8 +1261,8 @@ static int usbduxfast_ai_insn_read(struct comedi_device *dev,
        /* 0 means that the AD commands are sent */
        err = send_dux_commands(udfs, SENDADCOMMANDS);
        if (err < 0) {
-               printk(KERN_ERR "comedi%d: adc command could not be submitted."
-                      "Aborting...\n", dev->minor);
+               dev_err(dev->class_dev,
+                       "adc command could not be submitted. Aborting...\n");
                up(&udfs->sem);
                return err;
        }
@@ -1284,8 +1277,7 @@ static int usbduxfast_ai_insn_read(struct comedi_device *dev,
                                   udfs->transfer_buffer, SIZEINBUF,
                                   &actual_length, 10000);
                if (err < 0) {
-                       printk(KERN_ERR "comedi%d: insn timeout. No data.\n",
-                              dev->minor);
+                       dev_err(dev->class_dev, "insn timeout. No data.\n");
                        up(&udfs->sem);
                        return err;
                }
@@ -1297,15 +1289,13 @@ static int usbduxfast_ai_insn_read(struct comedi_device *dev,
                                   udfs->transfer_buffer, SIZEINBUF,
                                   &actual_length, 10000);
                if (err < 0) {
-                       printk(KERN_ERR "comedi%d: insn data error: %d\n",
-                              dev->minor, err);
+                       dev_err(dev->class_dev, "insn data error: %d\n", err);
                        up(&udfs->sem);
                        return err;
                }
                n = actual_length / sizeof(uint16_t);
                if ((n % 16) != 0) {
-                       printk(KERN_ERR "comedi%d: insn data packet "
-                              "corrupted.\n", dev->minor);
+                       dev_err(dev->class_dev, "insn data packet corrupted.\n");
                        up(&udfs->sem);
                        return -EINVAL;
                }
@@ -1535,8 +1525,8 @@ static int usbduxfast_usb_probe(struct usb_interface *uinterf,
        int ret;
 
        if (udev->speed != USB_SPEED_HIGH) {
-               printk(KERN_ERR "comedi_: usbduxfast_: This driver needs"
-                      "USB 2.0 to operate. Aborting...\n");
+               dev_err(&uinterf->dev,
+                       "This driver needs USB 2.0 to operate. Aborting...\n");
                return -ENODEV;
        }
 #ifdef CONFIG_COMEDI_DEBUG
@@ -1555,7 +1545,8 @@ static int usbduxfast_usb_probe(struct usb_interface *uinterf,
 
        /* no more space */
        if (index == -1) {
-               printk(KERN_ERR "Too many usbduxfast-devices connected.\n");
+               dev_err(&uinterf->dev,
+                       "Too many usbduxfast-devices connected.\n");
                up(&start_stop_sem);
                return -EMFILE;
        }
@@ -1586,8 +1577,8 @@ static int usbduxfast_usb_probe(struct usb_interface *uinterf,
        usbduxfastsub[index].dux_commands = kmalloc(SIZEOFDUXBUFFER,
                                                    GFP_KERNEL);
        if (!usbduxfastsub[index].dux_commands) {
-               printk(KERN_ERR "comedi_: usbduxfast: error alloc space for "
-                      "dac commands\n");
+               dev_err(&uinterf->dev,
+                       "error alloc space for dac commands\n");
                tidy_up(&(usbduxfastsub[index]));
                up(&start_stop_sem);
                return -ENOMEM;
@@ -1595,8 +1586,8 @@ static int usbduxfast_usb_probe(struct usb_interface *uinterf,
        /* create space of the instruction buffer */
        usbduxfastsub[index].insnBuffer = kmalloc(SIZEINSNBUF, GFP_KERNEL);
        if (!usbduxfastsub[index].insnBuffer) {
-               printk(KERN_ERR "comedi_: usbduxfast: could not alloc space "
-                      "for insnBuffer\n");
+               dev_err(&uinterf->dev,
+                       "could not alloc space for insnBuffer\n");
                tidy_up(&(usbduxfastsub[index]));
                up(&start_stop_sem);
                return -ENOMEM;
@@ -1605,24 +1596,25 @@ static int usbduxfast_usb_probe(struct usb_interface *uinterf,
        i = usb_set_interface(usbduxfastsub[index].usbdev,
                              usbduxfastsub[index].ifnum, 1);
        if (i < 0) {
-               printk(KERN_ERR "comedi_: usbduxfast%d: could not switch to "
-                      "alternate setting 1.\n", index);
+               dev_err(&uinterf->dev,
+                       "usbduxfast%d: could not switch to alternate setting 1.\n",
+                       index);
                tidy_up(&(usbduxfastsub[index]));
                up(&start_stop_sem);
                return -ENODEV;
        }
        usbduxfastsub[index].urbIn = usb_alloc_urb(0, GFP_KERNEL);
        if (!usbduxfastsub[index].urbIn) {
-               printk(KERN_ERR "comedi_: usbduxfast%d: Could not alloc."
-                      "urb\n", index);
+               dev_err(&uinterf->dev,
+                       "usbduxfast%d: Could not alloc. urb\n", index);
                tidy_up(&(usbduxfastsub[index]));
                up(&start_stop_sem);
                return -ENOMEM;
        }
        usbduxfastsub[index].transfer_buffer = kmalloc(SIZEINBUF, GFP_KERNEL);
        if (!usbduxfastsub[index].transfer_buffer) {
-               printk(KERN_ERR "comedi_: usbduxfast%d: could not alloc. "
-                      "transb.\n", index);
+               dev_err(&uinterf->dev,
+                       "usbduxfast%d: could not alloc. transb.\n", index);
                tidy_up(&(usbduxfastsub[index]));
                up(&start_stop_sem);
                return -ENOMEM;
@@ -1640,12 +1632,12 @@ static int usbduxfast_usb_probe(struct usb_interface *uinterf,
                                      usbduxfast_firmware_request_complete_handler);
 
        if (ret) {
-               dev_err(&udev->dev, "could not load firmware (err=%d)\n", ret);
+               dev_err(&uinterf->dev, "could not load firmware (err=%d)\n", ret);
                return ret;
        }
 
-       printk(KERN_INFO "comedi_: usbduxfast%d has been successfully "
-              "initialized.\n", index);
+       dev_info(&uinterf->dev,
+                "usbduxfast%d has been successfully initialized.\n", index);
        /* success */
        return 0;
 }
@@ -1656,13 +1648,11 @@ static void usbduxfast_usb_disconnect(struct usb_interface *intf)
        struct usb_device *udev = interface_to_usbdev(intf);
 
        if (!udfs) {
-               printk(KERN_ERR "comedi_: usbduxfast: disconnect called with "
-                      "null pointer.\n");
+               dev_err(&intf->dev, "disconnect called with null pointer.\n");
                return;
        }
        if (udfs->usbdev != udev) {
-               printk(KERN_ERR "comedi_: usbduxfast: BUG! called with wrong "
-                      "ptr!!!\n");
+               dev_err(&intf->dev, "BUG! called with wrong ptr!!!\n");
                return;
        }
 
index df277aa591bbae2b7fbe29899ca0c2fcd2d21461..366490776c5a48ac9974bff8066a380796414438 100644 (file)
@@ -1371,12 +1371,11 @@ static int vmk80xx_usb_probe(struct usb_interface *intf,
 
        if (dev->board.model == VMK8061_MODEL) {
                vmk80xx_read_eeprom(dev, IC3_VERSION);
-               printk(KERN_INFO "comedi#: vmk80xx: %s\n", dev->fw.ic3_vers);
+               dev_info(&intf->dev, "%s\n", dev->fw.ic3_vers);
 
                if (vmk80xx_check_data_link(dev)) {
                        vmk80xx_read_eeprom(dev, IC6_VERSION);
-                       printk(KERN_INFO "comedi#: vmk80xx: %s\n",
-                              dev->fw.ic6_vers);
+                       dev_info(&intf->dev, "%s\n", dev->fw.ic6_vers);
                } else {
                        dbgcm("comedi#: vmk80xx: no conn. to CPU\n");
                }
@@ -1387,8 +1386,8 @@ static int vmk80xx_usb_probe(struct usb_interface *intf,
 
        dev->probed = 1;
 
-       printk(KERN_INFO "comedi#: vmk80xx: board #%d [%s] now attached\n",
-              dev->count, dev->board.name);
+       dev_info(&intf->dev, "board #%d [%s] now attached\n",
+                dev->count, dev->board.name);
 
        mutex_unlock(&glb_mutex);
 
@@ -1422,8 +1421,8 @@ static void vmk80xx_usb_disconnect(struct usb_interface *intf)
        kfree(dev->usb_rx_buf);
        kfree(dev->usb_tx_buf);
 
-       printk(KERN_INFO "comedi#: vmk80xx: board #%d [%s] now detached\n",
-              dev->count, dev->board.name);
+       dev_info(&intf->dev, "board #%d [%s] now detached\n",
+                dev->count, dev->board.name);
 
        up(&dev->limit_sem);
        mutex_unlock(&glb_mutex);
index 3f20ea55b8d0b45452bba1ed2dc4350cd6be007a..944ba9d718d9fbc69006a578fe0ff7e1ef7701d8 100644 (file)
@@ -95,7 +95,8 @@ static int comedi_do_insn(struct comedi_device *dev,
        s = &dev->subdevices[insn->subdev];
 
        if (s->type == COMEDI_SUBD_UNUSED) {
-               printk(KERN_ERR "%d not useable subdevice\n", insn->subdev);
+               dev_err(dev->class_dev,
+                       "%d not useable subdevice\n", insn->subdev);
                ret = -EIO;
                goto error;
        }
@@ -104,7 +105,7 @@ static int comedi_do_insn(struct comedi_device *dev,
 
        ret = comedi_check_chanlist(s, 1, &insn->chanspec);
        if (ret < 0) {
-               printk(KERN_ERR "bad chanspec\n");
+               dev_err(dev->class_dev, "bad chanspec\n");
                ret = -EINVAL;
                goto error;
        }
index 05fe78748dfcaf6b330c907443e5ac5b4e87c504..8b71131732d8ff5e45cb92d40e07e62ab138f27f 100644 (file)
@@ -308,9 +308,9 @@ static enum BC_STATUS bc_cproc_download_fw(struct crystalhd_cmd *ctx,
        sts = crystalhd_download_fw(ctx->adp, (uint8_t *)idata->add_cdata,
                                  idata->add_cdata_sz);
 
-       if (sts != BC_STS_SUCCESS) {
+       if (sts != BC_STS_SUCCESS)
                BCMLOG_ERR("Firmware Download Failure!! - %d\n", sts);
-       else
+       else
                ctx->state |= BC_LINK_INIT;
 
        return sts;
index f91a4bf4e68fb6f18c9c8890a7b5bc24d703c8e4..e203f606de33086be16e75165730926c905980a4 100644 (file)
@@ -9,7 +9,6 @@
 *****************************************************************************/
 
 #include <linux/kernel.h>
-#include <linux/version.h>
 #include <linux/kthread.h>
 #include <linux/module.h>
 #include <linux/freezer.h>
index 66973e93a6bc0e4c6ffd407920469fe4e44b3242..16635a9717b3a6aadd3378584c733a2f9f4a0068 100644 (file)
@@ -179,55 +179,6 @@ void CsrGlobalMutexLock(void);
  *----------------------------------------------------------------------------*/
 void CsrGlobalMutexUnlock(void);
 
-/*----------------------------------------------------------------------------*
- *  NAME
- *      CsrThreadCreate
- *
- *  DESCRIPTION
- *      Create thread function and return a handle to the created thread.
- *
- *  RETURNS
- *      Possible values:
- *          CSR_RESULT_SUCCESS           in case of success
- *          CSR_FE_RESULT_NO_MORE_THREADS   in case of out of thread resources
- *          CSR_FE_RESULT_INVALID_POINTER   in case one of the supplied pointers is invalid
- *
- *----------------------------------------------------------------------------*/
-CsrResult CsrThreadCreate(void (*threadFunction)(void *pointer), void *pointer,
-    u32 stackSize, u16 priority,
-    const char *threadName, CsrThreadHandle *threadHandle);
-
-/*----------------------------------------------------------------------------*
- *  NAME
- *      CsrThreadGetHandle
- *
- *  DESCRIPTION
- *      Return thread handle of calling thread.
- *
- *  RETURNS
- *      Possible values:
- *          CSR_RESULT_SUCCESS             in case of success
- *          CSR_FE_RESULT_INVALID_POINTER  in case the threadHandle pointer is invalid
- *
- *----------------------------------------------------------------------------*/
-CsrResult CsrThreadGetHandle(CsrThreadHandle *threadHandle);
-
-/*----------------------------------------------------------------------------*
- *  NAME
- *      CsrThreadEqual
- *
- *  DESCRIPTION
- *      Compare thread handles
- *
- *  RETURNS
- *      Possible values:
- *          CSR_RESULT_SUCCESS             in case thread handles are identical
- *          CSR_FE_RESULT_INVALID_POINTER  in case either threadHandle pointer is invalid
- *          CSR_RESULT_FAILURE             otherwise
- *
- *----------------------------------------------------------------------------*/
-CsrResult CsrThreadEqual(CsrThreadHandle *threadHandle1, CsrThreadHandle *threadHandle2);
-
 /*----------------------------------------------------------------------------*
  *  NAME
  *      CsrThreadSleep
index 57194ee911ead3cfc2070c90cfdad725e44c9067..cd1f8771922d0e02d16d519e96fa262afbbcb21d 100644 (file)
@@ -2,11 +2,11 @@
 #define CSR_FRAMEWORK_EXT_TYPES_H__
 /*****************************************************************************
 
-            (c) Cambridge Silicon Radio Limited 2010
-            All rights reserved and confidential information of CSR
+       (c) Cambridge Silicon Radio Limited 2010
+       All rights reserved and confidential information of CSR
 
-            Refer to LICENSE.txt included with this source for details
-            on the license terms.
+       Refer to LICENSE.txt included with this source for details
+       on the license terms.
 
 *****************************************************************************/
 
@@ -24,35 +24,25 @@ extern "C" {
 
 #ifdef __KERNEL__
 
-struct CsrThread
-{
-    struct task_struct *thread_task;
-    char                name[16];
-};
-
-struct CsrEvent
-{
-    /* wait_queue for waking the kernel thread */
-    wait_queue_head_t wakeup_q;
-    unsigned int      wakeup_flag;
+struct CsrEvent {
+       /* wait_queue for waking the kernel thread */
+       wait_queue_head_t wakeup_q;
+       unsigned int      wakeup_flag;
 };
 
 typedef struct CsrEvent CsrEventHandle;
 typedef struct semaphore CsrMutexHandle;
-typedef struct CsrThread CsrThreadHandle;
 
 #else /* __KERNEL __ */
 
-struct CsrEvent
-{
-    pthread_cond_t  event;
-    pthread_mutex_t mutex;
-    u32       eventBits;
+struct CsrEvent {
+       pthread_cond_t  event;
+       pthread_mutex_t mutex;
+       u32       eventBits;
 };
 
 typedef struct CsrEvent CsrEventHandle;
 typedef pthread_mutex_t CsrMutexHandle;
-typedef pthread_t CsrThreadHandle;
 
 #endif /* __KERNEL__ */
 
index b2808569f8de12d52ed088e90607636d1d8ca9ef..b619db69e1450d4ef3ddde6bae35dec566a5b87a 100644 (file)
@@ -201,7 +201,7 @@ void CsrLogTimedEventIn(u32 line,
     const char *file,
     CsrSchedQid task_id,
     CsrSchedTid tid,
-    CsrTime requested_delay,
+    u32 requested_delay,
     u16 fniarg,
     const void *fnvarg);
 
index 8842e4bf4611ba4ea801f2375fbd926fac2c7599..08fc0807cb7bfc4e3b57fe076c117aeb471e7af3 100644 (file)
@@ -2,13 +2,13 @@
 #define CSR_LOG_CONFIGURE_H__
 /*****************************************************************************
 
-            (c) Cambridge Silicon Radio Limited 2010
-            All rights reserved and confidential information of CSR
+  (c) Cambridge Silicon Radio Limited 2010
+  All rights reserved and confidential information of CSR
 
-            Refer to LICENSE.txt included with this source for details
-            on the license terms.
+  Refer to LICENSE.txt included with this source for details
+  on the license terms.
 
-*****************************************************************************/
+ *****************************************************************************/
 
 #include "csr_log.h"
 
@@ -37,7 +37,7 @@ void CsrLogLevelTaskSetAll(CsrLogLevelTask tasksLogLevelMask);
 
 /* Set the logging level for a given Task */
 /* This function can be used as a complement to CsrLogLevelTaskSetAll() to add more _or_ less log from a given task than what is set
-generally with CsrLogLevelTaskSetAll(). */
+   generally with CsrLogLevelTaskSetAll(). */
 void CsrLogLevelTaskSetSpecific(CsrSchedQid taskId, CsrLogLevelTask taskLogLevelMask);
 
 
@@ -81,51 +81,51 @@ void CsrLogLevelTextSetTaskSubOrigin(CsrLogTextTaskId taskId, u16 subOrigin, Csr
 
 /*******************************************************************************
 
-    NAME
-        CsrLogLevelTextSet
-
-    DESCRIPTION
-        Set the text logging level for a given origin and optionally sub origin
-        by name. If either string is NULL or zero length, it is interpreted as
-        all origins and/or all sub origins respectively. If originName is NULL
-        or zero length, subOriginName is ignored.
-
-        Passing NULL or zero length strings in both originName and subOriginName
-        is equivalent to calling CsrLogLevelTextSetAll, and overrides all
-        previous filter configurations for all origins and sub origins.
-
-        Passing NULL or a zero length string in subOriginName overrides all
-        previous filter configurations for all sub origins of the specified
-        origin.
-
-        Note: the supplied strings may be accessed after the function returns
-        and must remain valid and constant until CsrLogDeinit is called.
-
-        Note: when specifying an origin (originName is not NULL and not zero
-        length), this function can only be used for origins that use the
-        csr_log_text_2.h interface for registration and logging. Filtering for
-        origins that use the legacy csr_log_text.h interface must be be
-        configured using the legacy filter configuration functions that accept
-        a CsrLogTextTaskId as origin specifier. However, when not specifying an
-        origin this function also affects origins that have been registered with
-        the legacy csr_log_text.h interface. Furthermore, using this function
-        and the legacy filter configuration functions on the same origin is not
-        allowed.
-
-    PARAMETERS
-        originName - a string containing the name of the origin. Can be NULL or
-            zero length to set the log level for all origins. In this case, the
-            subOriginName parameter will be ignored.
-        subOriginName - a string containing the name of the sub origin. Can be
-            NULL or zero length to set the log level for all sub origins of the
-            specified origin.
-        warningLevelMask - The desired log level for the specified origin(s) and
-            sub origin(s).
-
-*******************************************************************************/
+  NAME
+  CsrLogLevelTextSet
+
+  DESCRIPTION
+  Set the text logging level for a given origin and optionally sub origin
+  by name. If either string is NULL or zero length, it is interpreted as
+  all origins and/or all sub origins respectively. If originName is NULL
+  or zero length, subOriginName is ignored.
+
+  Passing NULL or zero length strings in both originName and subOriginName
+  is equivalent to calling CsrLogLevelTextSetAll, and overrides all
+  previous filter configurations for all origins and sub origins.
+
+  Passing NULL or a zero length string in subOriginName overrides all
+  previous filter configurations for all sub origins of the specified
+  origin.
+
+Note: the supplied strings may be accessed after the function returns
+and must remain valid and constant until CsrLogDeinit is called.
+
+Note: when specifying an origin (originName is not NULL and not zero
+length), this function can only be used for origins that use the
+csr_log_text_2.h interface for registration and logging. Filtering for
+origins that use the legacy csr_log_text.h interface must be be
+configured using the legacy filter configuration functions that accept
+a CsrLogTextTaskId as origin specifier. However, when not specifying an
+origin this function also affects origins that have been registered with
+the legacy csr_log_text.h interface. Furthermore, using this function
+and the legacy filter configuration functions on the same origin is not
+allowed.
+
+PARAMETERS
+originName - a string containing the name of the origin. Can be NULL or
+zero length to set the log level for all origins. In this case, the
+subOriginName parameter will be ignored.
+subOriginName - a string containing the name of the sub origin. Can be
+NULL or zero length to set the log level for all sub origins of the
+specified origin.
+warningLevelMask - The desired log level for the specified origin(s) and
+sub origin(s).
+
+ *******************************************************************************/
 void CsrLogLevelTextSet(const char *originName,
-    const char *subOriginName,
-    CsrLogLevelText warningLevelMask);
+               const char *subOriginName,
+               CsrLogLevelText warningLevelMask);
 
 #ifdef __cplusplus
 }
index cc1b8bf6607993fc2e295b0591b9d09921e517f1..dc67a4a08552b97c6ef6c0345d1816c8829b02a1 100644 (file)
@@ -37,10 +37,10 @@ typedef CsrSchedIdentifier CsrSchedTid;
 typedef void (*schedEntryFunction_t)(void **inst);
 
 /* Time constants. */
-#define CSR_SCHED_TIME_MAX                ((CsrTime) 0xFFFFFFFF)
-#define CSR_SCHED_MILLISECOND             ((CsrTime) (1000))
-#define CSR_SCHED_SECOND                  ((CsrTime) (1000 * CSR_SCHED_MILLISECOND))
-#define CSR_SCHED_MINUTE                  ((CsrTime) (60 * CSR_SCHED_SECOND))
+#define CSR_SCHED_TIME_MAX                (0xFFFFFFFF)
+#define CSR_SCHED_MILLISECOND             (1000)
+#define CSR_SCHED_SECOND                  (1000 * CSR_SCHED_MILLISECOND)
+#define CSR_SCHED_MINUTE                  (60 * CSR_SCHED_SECOND)
 
 /* Queue and primitive that identifies the environment */
 #define CSR_SCHED_TASK_ID        0xFFFF
@@ -55,58 +55,6 @@ typedef u16 CsrSchedBgint;
 
 typedef void (*CsrSchedBgintHandler)(void *);
 
-/*----------------------------------------------------------------------------*
- *  NAME
- *      CsrSchedBgintReg
- *
- *  DESCRIPTION
- *      Register a background interrupt handler function with the scheduler.
- *        When CsrSchedBgint() is called from the foreground (e.g. an interrupt
- *        routine) the registered function is called.
- *
- *        If "cb" is null then the interrupt is effectively disabled. If a
- *        no bgints are available, CSR_SCHED_BGINT_INVALID is returned, otherwise
- *        a CsrSchedBgint value is returned to be used in subsequent calls to
- *        CsrSchedBgint().  id is a possibly NULL identifier used for logging
- *        purposes only.
- *
- *  RETURNS
- *      CsrSchedBgint -- CSR_SCHED_BGINT_INVALID denotes failure to obtain a CsrSchedBgintSet.
- *
- *----------------------------------------------------------------------------*/
-CsrSchedBgint CsrSchedBgintReg(CsrSchedBgintHandler cb,
-    void *context,
-    const char *id);
-
-/*----------------------------------------------------------------------------*
- *  NAME
- *      CsrSchedBgintUnreg
- *
- *  DESCRIPTION
- *      Unregister a background interrupt handler function.
- *
- *      ``irq'' is a background interrupt handle previously obtained
- *      from a call to CsrSchedBgintReg().
- *
- *  RETURNS
- *      void.
- *
- *----------------------------------------------------------------------------*/
-void CsrSchedBgintUnreg(CsrSchedBgint bgint);
-
-/*----------------------------------------------------------------------------*
- *  NAME
- *      CsrSchedBgintSet
- *
- *  DESCRIPTION
- *      Set background interrupt.
- *
- *  RETURNS
- *      void.
- *
- *----------------------------------------------------------------------------*/
-void CsrSchedBgintSet(CsrSchedBgint bgint);
-
 /*----------------------------------------------------------------------------*
  *  NAME
  *      CsrSchedMessagePut
@@ -176,25 +124,6 @@ void CsrSchedMessageBroadcast(u16 mi,
     void *msg_build_ptr);
 #endif
 
-/*----------------------------------------------------------------------------*
- *  NAME
- *      CsrSchedMessageGet
- *
- *  DESCRIPTION
- *      Obtains a message from the message queue belonging to the calling task.
- *      The message consists of one or both of a u16 and a void *.
- *
- *  RETURNS
- *      u8 - TRUE if a message has been obtained from the queue, else FALSE.
- *      If a message is taken from the queue, then "*pmi" and "*pmv" are set to
- *      the "mi" and "mv" passed to CsrSchedMessagePut() respectively.
- *
- *      "pmi" and "pmv" can be null, in which case the corresponding value from
- *      them message is discarded.
- *
- *----------------------------------------------------------------------------*/
-u8 CsrSchedMessageGet(u16 *pmi, void **pmv);
-
 /*----------------------------------------------------------------------------*
  *  NAME
  *      CsrSchedTimerSet
@@ -218,7 +147,7 @@ u8 CsrSchedMessageGet(u16 *pmi, void **pmv);
  *
  *----------------------------------------------------------------------------*/
 #if defined(CSR_LOG_ENABLE) && defined(CSR_LOG_INCLUDE_FILE_NAME_AND_LINE_NUMBER)
-CsrSchedTid CsrSchedTimerSetStringLog(CsrTime delay,
+CsrSchedTid CsrSchedTimerSetStringLog(u32 delay,
     void (*fn)(u16 mi, void *mv),
     u16 fniarg,
     void *fnvarg,
@@ -226,7 +155,7 @@ CsrSchedTid CsrSchedTimerSetStringLog(CsrTime delay,
     const char *file);
 #define CsrSchedTimerSet(d, fn, fni, fnv) CsrSchedTimerSetStringLog((d), (fn), (fni), (fnv), __LINE__, __FILE__)
 #else
-CsrSchedTid CsrSchedTimerSet(CsrTime delay,
+CsrSchedTid CsrSchedTimerSet(u32 delay,
     void (*fn)(u16 mi, void *mv),
     u16 fniarg,
     void *fnvarg);
@@ -271,20 +200,6 @@ u8 CsrSchedTimerCancel(CsrSchedTid eventid,
 CsrSchedQid CsrSchedTaskQueueGet(void);
 
 
-/*----------------------------------------------------------------------------*
- *  NAME
- *      CsrSchedTaskQueueGet
- *
- *  DESCRIPTION
- *      Return the queue identifier for the currently running queue
- *
- *  RETURNS
- *      char - The current task queue identifier, or 0xFFFF if not available.
- *
- *----------------------------------------------------------------------------*/
-char* CsrSchedTaskNameGet(CsrSchedQid );
-
-
 #ifdef __cplusplus
 }
 #endif
index 7b597f7622a26d6445f18d2c5d169bd8588cf247..f3f4a9c9c67a9b2e5c494582a1702311f328d367 100644 (file)
@@ -9,25 +9,24 @@
 *****************************************************************************/
 
 #include <linux/kernel.h>
-#include <linux/version.h>
 #include <linux/time.h>
 #include <linux/module.h>
 
 #include "csr_time.h"
 
-CsrTime CsrTimeGet(CsrTime *high)
+u32 CsrTimeGet(u32 *high)
 {
        struct timespec ts;
        u64 time;
-       CsrTime low;
+       u32 low;
 
        ts = current_kernel_time();
        time = (u64) ts.tv_sec * 1000000 + ts.tv_nsec / 1000;
 
        if (high != NULL)
-               *high = (CsrTime) ((time >> 32) & 0xFFFFFFFF);
+               *high = (u32) ((time >> 32) & 0xFFFFFFFF);
 
-       low = (CsrTime) (time & 0xFFFFFFFF);
+       low = (u32) (time & 0xFFFFFFFF);
 
        return low;
 }
index 2a45f3e4024d6c5fc32e4902b9f4ae81457cfbc9..5a1d859866ef6d0aac7c9313deef33d7167a0a6b 100644 (file)
@@ -2,11 +2,11 @@
 #define CSR_TIME_H__
 /*****************************************************************************
 
-            (c) Cambridge Silicon Radio Limited 2010
-            All rights reserved and confidential information of CSR
+(c) Cambridge Silicon Radio Limited 2010
+All rights reserved and confidential information of CSR
 
-            Refer to LICENSE.txt included with this source for details
-            on the license terms.
+Refer to LICENSE.txt included with this source for details
+on the license terms.
 
 *****************************************************************************/
 
@@ -18,61 +18,31 @@ extern "C" {
 
 /*******************************************************************************
 
-    NAME
-        CsrTime
+NAME
+       CsrTimeGet
 
-    DESCRIPTION
-        Type to hold a value describing the current system time, which is a
-        measure of time elapsed since some arbitrarily defined fixed time
-        reference, usually associated with system startup.
+DESCRIPTION
+       Returns the current system time in a low and a high part. The low part
+       is expressed in microseconds. The high part is incremented when the low
+       part wraps to provide an extended range.
 
-*******************************************************************************/
-typedef u32 CsrTime;
-
-
-/*******************************************************************************
-
-    NAME
-        CsrTimeUtc
-
-    DESCRIPTION
-        Type to hold a value describing a UTC wallclock time expressed in
-        seconds and milliseconds elapsed since midnight January 1st 1970.
-
-*******************************************************************************/
-typedef struct
-{
-    u32 sec;
-    u16 msec;
-} CsrTimeUtc;
-
-
-/*******************************************************************************
-
-    NAME
-        CsrTimeGet
-
-    DESCRIPTION
-        Returns the current system time in a low and a high part. The low part
-        is expressed in microseconds. The high part is incremented when the low
-        part wraps to provide an extended range.
-
-        The caller may provide a NULL pointer as the high parameter. In this case
-        the function just returns the low part and ignores the high parameter.
+       The caller may provide a NULL pointer as the high parameter.
+       In this case the function just returns the low part and ignores the
+       high parameter.
 
-        Although the time is expressed in microseconds the actual resolution is
-        platform dependent and can be less. It is recommended that the
-        resolution is at least 10 milliseconds.
+       Although the time is expressed in microseconds the actual resolution is
+       platform dependent and can be less. It is recommended that the
+       resolution is at least 10 milliseconds.
 
-    PARAMETERS
-        high - Pointer to variable that will receive the high part of the
-               current system time. Passing NULL is valid.
+PARAMETERS
+       high - Pointer to variable that will receive the high part of the
+              current system time. Passing NULL is valid.
 
-    RETURNS
-        Low part of current system time in microseconds.
+RETURNS
+       Low part of current system time in microseconds.
 
 *******************************************************************************/
-CsrTime CsrTimeGet(CsrTime *high);
+u32 CsrTimeGet(u32 *high);
 
 
 /*------------------------------------------------------------------*/
index d67b460e7a85db730cab0ef51880a972cda81ac2..f752359029194ffe7c11da7daef7faa03cee7126 100644 (file)
@@ -40,7 +40,7 @@
 typedef struct coredump_buf
 {
     u16  count;                       /* serial number of dump */
-    CsrTime    timestamp;                   /* host's system time at capture */
+    u32  timestamp;                   /* host's system time at capture */
     s16   requestor;                   /* request: 0=auto dump, 1=manual */
     u16  chip_ver;
     u32  fw_ver;
@@ -192,7 +192,7 @@ CsrResult unifi_coredump_capture(card_t *card, struct unifi_coredump_req *req)
 {
     CsrResult r = CSR_RESULT_SUCCESS;
     static u16 dump_seq_no = 1;
-    CsrTime time_of_capture;
+    u32 time_of_capture;
 
     func_enter();
 
index 5f841556bbef53e1264df1b3d9e8fe6c13d1b27a..ebe2f6d9ea8f0b3dee360ad646a7fa4ca1e661ef 100644 (file)
@@ -1,10 +1,10 @@
 /*****************************************************************************
 
-            (c) Cambridge Silicon Radio Limited 2011
-            All rights reserved and confidential information of CSR
+       (c) Cambridge Silicon Radio Limited 2011
+       All rights reserved and confidential information of CSR
 
-            Refer to LICENSE.txt included with this source for details
-            on the license terms.
+       Refer to LICENSE.txt included with this source for details
+       on the license terms.
 
 *****************************************************************************/
 
index 2923e2ef12f2a107175b9d5c92bc688a5060eddf..9042efac610a9ea7c346a0fc5bfb42bf7debb99b 100644 (file)
@@ -228,7 +228,7 @@ typedef struct unifi_coredump_req
     u32 chip_ver;                 /* Chip version */
     u32 fw_ver;                   /* Firmware version */
     s32  requestor;                /* Requestor: 0=auto dump, 1=manual */
-    CsrTime   timestamp;                /* time of capture by driver */
+    u32 timestamp;                /* time of capture by driver */
     u32 serial;                   /* capture serial number */
     s32  value;                    /* register value */
 } unifi_coredump_req_t;                 /* mini-coredumped reg value request */
index 33d92b698c59a686b786b51720639686f30a2441..99cf93061d1b5806985b8ae4e8f6fd05f578c7eb 100644 (file)
@@ -9,37 +9,38 @@
  *****************************************************************************/
 #include "csr_wifi_router_ctrl_sef.h"
 
-const CsrWifiRouterCtrlStateHandlerType CsrWifiRouterCtrlDownstreamStateHandlers[CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_COUNT] =
-{
-    /* 0x0000 */ CsrWifiRouterCtrlConfigurePowerModeReqHandler,
-    /* 0x0001 */ CsrWifiRouterCtrlHipReqHandler,
-    /* 0x0002 */ CsrWifiRouterCtrlMediaStatusReqHandler,
-    /* 0x0003 */ CsrWifiRouterCtrlMulticastAddressResHandler,
-    /* 0x0004 */ CsrWifiRouterCtrlPortConfigureReqHandler,
-    /* 0x0005 */ CsrWifiRouterCtrlQosControlReqHandler,
-    /* 0x0006 */ CsrWifiRouterCtrlSuspendResHandler,
-    /* 0x0007 */ CsrWifiRouterCtrlTclasAddReqHandler,
-    /* 0x0008 */ CsrWifiRouterCtrlResumeResHandler,
-    /* 0x0009 */ CsrWifiRouterCtrlRawSdioDeinitialiseReqHandler,
-    /* 0x000A */ CsrWifiRouterCtrlRawSdioInitialiseReqHandler,
-    /* 0x000B */ CsrWifiRouterCtrlTclasDelReqHandler,
-    /* 0x000C */ CsrWifiRouterCtrlTrafficClassificationReqHandler,
-    /* 0x000D */ CsrWifiRouterCtrlTrafficConfigReqHandler,
-    /* 0x000E */ CsrWifiRouterCtrlWifiOffReqHandler,
-    /* 0x000F */ CsrWifiRouterCtrlWifiOffResHandler,
-    /* 0x0010 */ CsrWifiRouterCtrlWifiOnReqHandler,
-    /* 0x0011 */ CsrWifiRouterCtrlWifiOnResHandler,
-    /* 0x0012 */ CsrWifiRouterCtrlM4TransmitReqHandler,
-    /* 0x0013 */ CsrWifiRouterCtrlModeSetReqHandler,
-    /* 0x0014 */ CsrWifiRouterCtrlPeerAddReqHandler,
-    /* 0x0015 */ CsrWifiRouterCtrlPeerDelReqHandler,
-    /* 0x0016 */ CsrWifiRouterCtrlPeerUpdateReqHandler,
-    /* 0x0017 */ CsrWifiRouterCtrlCapabilitiesReqHandler,
-    /* 0x0018 */ CsrWifiRouterCtrlBlockAckEnableReqHandler,
-    /* 0x0019 */ CsrWifiRouterCtrlBlockAckDisableReqHandler,
-    /* 0x001A */ CsrWifiRouterCtrlWapiRxPktReqHandler,
-    /* 0x001B */ CsrWifiRouterCtrlWapiMulticastFilterReqHandler,
-    /* 0x001C */ CsrWifiRouterCtrlWapiUnicastFilterReqHandler,
-    /* 0x001D */ CsrWifiRouterCtrlWapiUnicastTxPktReqHandler,
-    /* 0x001E */ CsrWifiRouterCtrlWapiFilterReqHandler,
+const CsrWifiRouterCtrlStateHandlerType
+       CsrWifiRouterCtrlDownstreamStateHandlers
+       [CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_COUNT] = {
+               /* 0x0000 */ CsrWifiRouterCtrlConfigurePowerModeReqHandler,
+               /* 0x0001 */ CsrWifiRouterCtrlHipReqHandler,
+               /* 0x0002 */ CsrWifiRouterCtrlMediaStatusReqHandler,
+               /* 0x0003 */ CsrWifiRouterCtrlMulticastAddressResHandler,
+               /* 0x0004 */ CsrWifiRouterCtrlPortConfigureReqHandler,
+               /* 0x0005 */ CsrWifiRouterCtrlQosControlReqHandler,
+               /* 0x0006 */ CsrWifiRouterCtrlSuspendResHandler,
+               /* 0x0007 */ CsrWifiRouterCtrlTclasAddReqHandler,
+               /* 0x0008 */ CsrWifiRouterCtrlResumeResHandler,
+               /* 0x0009 */ CsrWifiRouterCtrlRawSdioDeinitialiseReqHandler,
+               /* 0x000A */ CsrWifiRouterCtrlRawSdioInitialiseReqHandler,
+               /* 0x000B */ CsrWifiRouterCtrlTclasDelReqHandler,
+               /* 0x000C */ CsrWifiRouterCtrlTrafficClassificationReqHandler,
+               /* 0x000D */ CsrWifiRouterCtrlTrafficConfigReqHandler,
+               /* 0x000E */ CsrWifiRouterCtrlWifiOffReqHandler,
+               /* 0x000F */ CsrWifiRouterCtrlWifiOffResHandler,
+               /* 0x0010 */ CsrWifiRouterCtrlWifiOnReqHandler,
+               /* 0x0011 */ CsrWifiRouterCtrlWifiOnResHandler,
+               /* 0x0012 */ CsrWifiRouterCtrlM4TransmitReqHandler,
+               /* 0x0013 */ CsrWifiRouterCtrlModeSetReqHandler,
+               /* 0x0014 */ CsrWifiRouterCtrlPeerAddReqHandler,
+               /* 0x0015 */ CsrWifiRouterCtrlPeerDelReqHandler,
+               /* 0x0016 */ CsrWifiRouterCtrlPeerUpdateReqHandler,
+               /* 0x0017 */ CsrWifiRouterCtrlCapabilitiesReqHandler,
+               /* 0x0018 */ CsrWifiRouterCtrlBlockAckEnableReqHandler,
+               /* 0x0019 */ CsrWifiRouterCtrlBlockAckDisableReqHandler,
+               /* 0x001A */ CsrWifiRouterCtrlWapiRxPktReqHandler,
+               /* 0x001B */ CsrWifiRouterCtrlWapiMulticastFilterReqHandler,
+               /* 0x001C */ CsrWifiRouterCtrlWapiUnicastFilterReqHandler,
+               /* 0x001D */ CsrWifiRouterCtrlWapiUnicastTxPktReqHandler,
+               /* 0x001E */ CsrWifiRouterCtrlWapiFilterReqHandler,
 };
index de1086d7158d765b9715d2793ac97c43c09a11e7..4cd126338e27910cba3fc0ab5939da29739b66f6 100644 (file)
@@ -1,10 +1,10 @@
 /*****************************************************************************
 
-            (c) Cambridge Silicon Radio Limited 2011
-            All rights reserved and confidential information of CSR
+       (c) Cambridge Silicon Radio Limited 2011
+       All rights reserved and confidential information of CSR
 
-            Refer to LICENSE.txt included with this source for details
-            on the license terms.
+       Refer to LICENSE.txt included with this source for details
+       on the license terms.
 
 *****************************************************************************/
 
  *----------------------------------------------------------------------------*/
 void CsrWifiRouterFreeUpstreamMessageContents(u16 eventClass, void *message)
 {
-    if (eventClass != CSR_WIFI_ROUTER_PRIM)
-    {
-        return;
-    }
-    if (NULL == message)
-    {
-        return;
-    }
-
-    switch (*((CsrWifiRouterPrim *) message))
-    {
-        case CSR_WIFI_ROUTER_MA_PACKET_IND:
-        {
-            CsrWifiRouterMaPacketInd *p = (CsrWifiRouterMaPacketInd *)message;
-            kfree(p->frame);
-            p->frame = NULL;
-            break;
-        }
-
-        default:
-            break;
-    }
+       if (eventClass != CSR_WIFI_ROUTER_PRIM)
+               return;
+       if (NULL == message)
+               return;
+       switch (*((CsrWifiRouterPrim *) message)) {
+       case CSR_WIFI_ROUTER_MA_PACKET_IND:
+       {
+               CsrWifiRouterMaPacketInd *p =
+                       (CsrWifiRouterMaPacketInd *) message;
+               kfree(p->frame);
+               p->frame = NULL;
+               break;
+       }
+       default:
+               break;
+       }
 }
 
 
index c8741811b2e4f6d70104632a4c28656682e1369e..89650c7fb6fd3d326386ea28af864f7257b8c2ef 100644 (file)
@@ -1,10 +1,10 @@
 /*****************************************************************************
 
-            (c) Cambridge Silicon Radio Limited 2010
-            Confidential information of CSR
+       (c) Cambridge Silicon Radio Limited 2010
+       Confidential information of CSR
 
-            Refer to LICENSE.txt included with this source for details
-            on the license terms.
+       Refer to LICENSE.txt included with this source for details
+       on the license terms.
 
 *****************************************************************************/
 #ifndef CSR_WIFI_ROUTER_SEF_CSR_WIFI_SME_H__
 extern "C" {
 #endif
 
-typedef void (*CsrWifiSmeStateHandlerType)(void* drvpriv, CsrWifiFsmEvent* msg);
+typedef void (*CsrWifiSmeStateHandlerType)(void *drvpriv, CsrWifiFsmEvent *msg);
 
-extern const CsrWifiSmeStateHandlerType CsrWifiSmeUpstreamStateHandlers[CSR_WIFI_SME_PRIM_UPSTREAM_COUNT];
+extern const CsrWifiSmeStateHandlerType
+       CsrWifiSmeUpstreamStateHandlers[CSR_WIFI_SME_PRIM_UPSTREAM_COUNT];
 
 
-extern void CsrWifiSmeActivateCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeAdhocConfigGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeAdhocConfigSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeAssociationCompleteIndHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeAssociationStartIndHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeBlacklistCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeCalibrationDataGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeCalibrationDataSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeCcxConfigGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeCcxConfigSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeCoexConfigGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeCoexConfigSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeCoexInfoGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeConnectCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeConnectionConfigGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeConnectionInfoGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeConnectionQualityIndHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeConnectionStatsGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeDeactivateCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeDisconnectCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeEventMaskSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeHostConfigGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeHostConfigSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeIbssStationIndHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeKeyCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeLinkQualityGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeMediaStatusIndHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeMibConfigGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeMibConfigSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeMibGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeMibGetNextCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeMibSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeMicFailureIndHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeMulticastAddressCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmePacketFilterSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmePermanentMacAddressGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmePmkidCandidateListIndHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmePmkidCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmePowerConfigGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmePowerConfigSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeRegulatoryDomainInfoGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeRoamCompleteIndHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeRoamStartIndHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeRoamingConfigGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeRoamingConfigSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeScanConfigGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeScanConfigSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeScanFullCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeScanResultIndHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeScanResultsFlushCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeScanResultsGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeSmeStaConfigGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeSmeStaConfigSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeStationMacAddressGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeTspecIndHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeTspecCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeVersionsGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeWifiFlightmodeCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeWifiOffIndHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeWifiOffCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeWifiOnCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeCloakedSsidsSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeCloakedSsidsGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeWifiOnIndHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeSmeCommonConfigGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeSmeCommonConfigSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeGetInterfaceCapabilityCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeErrorIndHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeInfoIndHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeCoreDumpIndHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeAmpStatusChangeIndHandler(void* drvpriv, CsrWifiFsmEvent* msg);
+extern void CsrWifiSmeActivateCfmHandler(void *drvpriv, CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeAdhocConfigGetCfmHandler(void *drvpriv,
+       CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeAdhocConfigSetCfmHandler(void *drvpriv,
+       CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeAssociationCompleteIndHandler(void *drvpriv,
+       CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeAssociationStartIndHandler(void *drvpriv,
+       CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeBlacklistCfmHandler(void *drvpriv,
+       CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeCalibrationDataGetCfmHandler(void *drvpriv,
+       CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeCalibrationDataSetCfmHandler(void *drvpriv,
+       CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeCcxConfigGetCfmHandler(void *drvpriv,
+       CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeCcxConfigSetCfmHandler(void *drvpriv,
+       CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeCoexConfigGetCfmHandler(void *drvpriv,
+       CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeCoexConfigSetCfmHandler(void *drvpriv,
+       CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeCoexInfoGetCfmHandler(void *drvpriv,
+       CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeConnectCfmHandler(void *drvpriv, CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeConnectionConfigGetCfmHandler(void *drvpriv,
+       CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeConnectionInfoGetCfmHandler(void *drvpriv,
+       CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeConnectionQualityIndHandler(void *drvpriv,
+       CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeConnectionStatsGetCfmHandler(void *drvpriv,
+       CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeDeactivateCfmHandler(void *drvpriv, CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeDisconnectCfmHandler(void *drvpriv, CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeEventMaskSetCfmHandler(void *drvpriv,
+       CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeHostConfigGetCfmHandler(void *drvpriv,
+       CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeHostConfigSetCfmHandler(void *drvpriv,
+       CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeIbssStationIndHandler(void *drvpriv,
+       CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeKeyCfmHandler(void *drvpriv, CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeLinkQualityGetCfmHandler(void *drvpriv,
+       CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeMediaStatusIndHandler(void *drvpriv,
+       CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeMibConfigGetCfmHandler(void *drvpriv,
+       CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeMibConfigSetCfmHandler(void *drvpriv,
+       CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeMibGetCfmHandler(void *drvpriv, CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeMibGetNextCfmHandler(void *drvpriv, CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeMibSetCfmHandler(void *drvpriv, CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeMicFailureIndHandler(void *drvpriv, CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeMulticastAddressCfmHandler(void *drvpriv,
+       CsrWifiFsmEvent *msg);
+extern void CsrWifiSmePacketFilterSetCfmHandler(void *drvpriv,
+       CsrWifiFsmEvent *msg);
+extern void CsrWifiSmePermanentMacAddressGetCfmHandler(void *drvpriv,
+       CsrWifiFsmEvent *msg);
+extern void CsrWifiSmePmkidCandidateListIndHandler(void *drvpriv,
+       CsrWifiFsmEvent *msg);
+extern void CsrWifiSmePmkidCfmHandler(void *drvpriv, CsrWifiFsmEvent *msg);
+extern void CsrWifiSmePowerConfigGetCfmHandler(void *drvpriv,
+       CsrWifiFsmEvent *msg);
+extern void CsrWifiSmePowerConfigSetCfmHandler(void *drvpriv,
+       CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeRegulatoryDomainInfoGetCfmHandler(void *drvpriv,
+       CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeRoamCompleteIndHandler(void *drvpriv,
+       CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeRoamStartIndHandler(void *drvpriv, CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeRoamingConfigGetCfmHandler(void *drvpriv,
+       CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeRoamingConfigSetCfmHandler(void *drvpriv,
+       CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeScanConfigGetCfmHandler(void *drvpriv,
+       CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeScanConfigSetCfmHandler(void *drvpriv,
+       CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeScanFullCfmHandler(void *drvpriv, CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeScanResultIndHandler(void *drvpriv, CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeScanResultsFlushCfmHandler(void *drvpriv,
+       CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeScanResultsGetCfmHandler(void *drvpriv,
+       CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeSmeStaConfigGetCfmHandler(void *drvpriv,
+       CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeSmeStaConfigSetCfmHandler(void *drvpriv,
+       CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeStationMacAddressGetCfmHandler(void *drvpriv,
+       CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeTspecIndHandler(void *drvpriv, CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeTspecCfmHandler(void *drvpriv, CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeVersionsGetCfmHandler(void *drvpriv,
+       CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeWifiFlightmodeCfmHandler(void *drvpriv,
+       CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeWifiOffIndHandler(void *drvpriv, CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeWifiOffCfmHandler(void *drvpriv, CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeWifiOnCfmHandler(void *drvpriv, CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeCloakedSsidsSetCfmHandler(void *drvpriv,
+       CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeCloakedSsidsGetCfmHandler(void *drvpriv,
+       CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeWifiOnIndHandler(void *drvpriv, CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeSmeCommonConfigGetCfmHandler(void *drvpriv,
+       CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeSmeCommonConfigSetCfmHandler(void *drvpriv,
+       CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeGetInterfaceCapabilityCfmHandler(void *drvpriv,
+       CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeErrorIndHandler(void *drvpriv, CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeInfoIndHandler(void *drvpriv, CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeCoreDumpIndHandler(void *drvpriv, CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeAmpStatusChangeIndHandler(void *drvpriv,
+       CsrWifiFsmEvent *msg);
 
 #ifdef __cplusplus
 }
index 4f3af0a6be7c176af9dce4f0ca3f2d81effac2cf..e34ae66d2f5f7e42206f1a2d8aa83983f153a096 100644 (file)
@@ -1,10 +1,10 @@
 /*****************************************************************************
 
-            (c) Cambridge Silicon Radio Limited 2012
-            All rights reserved and confidential information of CSR
+       (c) Cambridge Silicon Radio Limited 2012
+       All rights reserved and confidential information of CSR
 
-            Refer to LICENSE.txt included with this source for details
-            on the license terms.
+       Refer to LICENSE.txt included with this source for details
+       on the license terms.
 
 *****************************************************************************/
 
@@ -32,13 +32,13 @@ extern void CsrWifiSmePfree(void *ptr);
 #define CsrWifiSmeAdhocConfigGetReqSizeof CsrWifiEventSizeof
 #define CsrWifiSmeAdhocConfigGetReqSerFree CsrWifiSmePfree
 
-extern u8CsrWifiSmeAdhocConfigSetReqSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeAdhocConfigSetReqDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeAdhocConfigSetReqSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeAdhocConfigSetReqDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeAdhocConfigSetReqSizeof(void *msg);
 #define CsrWifiSmeAdhocConfigSetReqSerFree CsrWifiSmePfree
 
-extern u8CsrWifiSmeBlacklistReqSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeBlacklistReqDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeBlacklistReqSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeBlacklistReqDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeBlacklistReqSizeof(void *msg);
 extern void CsrWifiSmeBlacklistReqSerFree(void *msg);
 
@@ -47,8 +47,8 @@ extern void CsrWifiSmeBlacklistReqSerFree(void *msg);
 #define CsrWifiSmeCalibrationDataGetReqSizeof CsrWifiEventSizeof
 #define CsrWifiSmeCalibrationDataGetReqSerFree CsrWifiSmePfree
 
-extern u8CsrWifiSmeCalibrationDataSetReqSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeCalibrationDataSetReqDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeCalibrationDataSetReqSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeCalibrationDataSetReqDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeCalibrationDataSetReqSizeof(void *msg);
 extern void CsrWifiSmeCalibrationDataSetReqSerFree(void *msg);
 
@@ -57,8 +57,8 @@ extern void CsrWifiSmeCalibrationDataSetReqSerFree(void *msg);
 #define CsrWifiSmeCcxConfigGetReqSizeof CsrWifiEventCsrUint16Sizeof
 #define CsrWifiSmeCcxConfigGetReqSerFree CsrWifiSmePfree
 
-extern u8CsrWifiSmeCcxConfigSetReqSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeCcxConfigSetReqDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeCcxConfigSetReqSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeCcxConfigSetReqDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeCcxConfigSetReqSizeof(void *msg);
 #define CsrWifiSmeCcxConfigSetReqSerFree CsrWifiSmePfree
 
@@ -67,8 +67,8 @@ extern size_t CsrWifiSmeCcxConfigSetReqSizeof(void *msg);
 #define CsrWifiSmeCoexConfigGetReqSizeof CsrWifiEventSizeof
 #define CsrWifiSmeCoexConfigGetReqSerFree CsrWifiSmePfree
 
-extern u8CsrWifiSmeCoexConfigSetReqSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeCoexConfigSetReqDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeCoexConfigSetReqSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeCoexConfigSetReqDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeCoexConfigSetReqSizeof(void *msg);
 #define CsrWifiSmeCoexConfigSetReqSerFree CsrWifiSmePfree
 
@@ -77,8 +77,8 @@ extern size_t CsrWifiSmeCoexConfigSetReqSizeof(void *msg);
 #define CsrWifiSmeCoexInfoGetReqSizeof CsrWifiEventSizeof
 #define CsrWifiSmeCoexInfoGetReqSerFree CsrWifiSmePfree
 
-extern u8CsrWifiSmeConnectReqSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeConnectReqDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeConnectReqSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeConnectReqDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeConnectReqSizeof(void *msg);
 extern void CsrWifiSmeConnectReqSerFree(void *msg);
 
@@ -117,13 +117,13 @@ extern void CsrWifiSmeConnectReqSerFree(void *msg);
 #define CsrWifiSmeHostConfigGetReqSizeof CsrWifiEventCsrUint16Sizeof
 #define CsrWifiSmeHostConfigGetReqSerFree CsrWifiSmePfree
 
-extern u8CsrWifiSmeHostConfigSetReqSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeHostConfigSetReqDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeHostConfigSetReqSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeHostConfigSetReqDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeHostConfigSetReqSizeof(void *msg);
 #define CsrWifiSmeHostConfigSetReqSerFree CsrWifiSmePfree
 
-extern u8CsrWifiSmeKeyReqSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeKeyReqDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeKeyReqSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeKeyReqDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeKeyReqSizeof(void *msg);
 #define CsrWifiSmeKeyReqSerFree CsrWifiSmePfree
 
@@ -137,33 +137,33 @@ extern size_t CsrWifiSmeKeyReqSizeof(void *msg);
 #define CsrWifiSmeMibConfigGetReqSizeof CsrWifiEventSizeof
 #define CsrWifiSmeMibConfigGetReqSerFree CsrWifiSmePfree
 
-extern u8CsrWifiSmeMibConfigSetReqSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeMibConfigSetReqDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeMibConfigSetReqSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeMibConfigSetReqDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeMibConfigSetReqSizeof(void *msg);
 #define CsrWifiSmeMibConfigSetReqSerFree CsrWifiSmePfree
 
-extern u8CsrWifiSmeMibGetNextReqSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeMibGetNextReqDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeMibGetNextReqSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeMibGetNextReqDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeMibGetNextReqSizeof(void *msg);
 extern void CsrWifiSmeMibGetNextReqSerFree(void *msg);
 
-extern u8CsrWifiSmeMibGetReqSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeMibGetReqDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeMibGetReqSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeMibGetReqDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeMibGetReqSizeof(void *msg);
 extern void CsrWifiSmeMibGetReqSerFree(void *msg);
 
-extern u8CsrWifiSmeMibSetReqSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeMibSetReqDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeMibSetReqSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeMibSetReqDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeMibSetReqSizeof(void *msg);
 extern void CsrWifiSmeMibSetReqSerFree(void *msg);
 
-extern u8CsrWifiSmeMulticastAddressReqSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeMulticastAddressReqDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeMulticastAddressReqSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeMulticastAddressReqDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeMulticastAddressReqSizeof(void *msg);
 extern void CsrWifiSmeMulticastAddressReqSerFree(void *msg);
 
-extern u8CsrWifiSmePacketFilterSetReqSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmePacketFilterSetReqDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmePacketFilterSetReqSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmePacketFilterSetReqDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmePacketFilterSetReqSizeof(void *msg);
 extern void CsrWifiSmePacketFilterSetReqSerFree(void *msg);
 
@@ -172,8 +172,8 @@ extern void CsrWifiSmePacketFilterSetReqSerFree(void *msg);
 #define CsrWifiSmePermanentMacAddressGetReqSizeof CsrWifiEventSizeof
 #define CsrWifiSmePermanentMacAddressGetReqSerFree CsrWifiSmePfree
 
-extern u8CsrWifiSmePmkidReqSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmePmkidReqDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmePmkidReqSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmePmkidReqDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmePmkidReqSizeof(void *msg);
 extern void CsrWifiSmePmkidReqSerFree(void *msg);
 
@@ -182,8 +182,8 @@ extern void CsrWifiSmePmkidReqSerFree(void *msg);
 #define CsrWifiSmePowerConfigGetReqSizeof CsrWifiEventSizeof
 #define CsrWifiSmePowerConfigGetReqSerFree CsrWifiSmePfree
 
-extern u8CsrWifiSmePowerConfigSetReqSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmePowerConfigSetReqDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmePowerConfigSetReqSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmePowerConfigSetReqDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmePowerConfigSetReqSizeof(void *msg);
 #define CsrWifiSmePowerConfigSetReqSerFree CsrWifiSmePfree
 
@@ -197,8 +197,8 @@ extern size_t CsrWifiSmePowerConfigSetReqSizeof(void *msg);
 #define CsrWifiSmeRoamingConfigGetReqSizeof CsrWifiEventCsrUint16Sizeof
 #define CsrWifiSmeRoamingConfigGetReqSerFree CsrWifiSmePfree
 
-extern u8CsrWifiSmeRoamingConfigSetReqSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeRoamingConfigSetReqDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeRoamingConfigSetReqSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeRoamingConfigSetReqDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeRoamingConfigSetReqSizeof(void *msg);
 #define CsrWifiSmeRoamingConfigSetReqSerFree CsrWifiSmePfree
 
@@ -207,13 +207,13 @@ extern size_t CsrWifiSmeRoamingConfigSetReqSizeof(void *msg);
 #define CsrWifiSmeScanConfigGetReqSizeof CsrWifiEventSizeof
 #define CsrWifiSmeScanConfigGetReqSerFree CsrWifiSmePfree
 
-extern u8CsrWifiSmeScanConfigSetReqSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeScanConfigSetReqDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeScanConfigSetReqSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeScanConfigSetReqDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeScanConfigSetReqSizeof(void *msg);
 extern void CsrWifiSmeScanConfigSetReqSerFree(void *msg);
 
-extern u8CsrWifiSmeScanFullReqSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeScanFullReqDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeScanFullReqSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeScanFullReqDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeScanFullReqSizeof(void *msg);
 extern void CsrWifiSmeScanFullReqSerFree(void *msg);
 
@@ -232,8 +232,8 @@ extern void CsrWifiSmeScanFullReqSerFree(void *msg);
 #define CsrWifiSmeSmeStaConfigGetReqSizeof CsrWifiEventCsrUint16Sizeof
 #define CsrWifiSmeSmeStaConfigGetReqSerFree CsrWifiSmePfree
 
-extern u8CsrWifiSmeSmeStaConfigSetReqSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeSmeStaConfigSetReqDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeSmeStaConfigSetReqSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeSmeStaConfigSetReqDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeSmeStaConfigSetReqSizeof(void *msg);
 #define CsrWifiSmeSmeStaConfigSetReqSerFree CsrWifiSmePfree
 
@@ -242,8 +242,8 @@ extern size_t CsrWifiSmeSmeStaConfigSetReqSizeof(void *msg);
 #define CsrWifiSmeStationMacAddressGetReqSizeof CsrWifiEventSizeof
 #define CsrWifiSmeStationMacAddressGetReqSerFree CsrWifiSmePfree
 
-extern u8CsrWifiSmeTspecReqSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeTspecReqDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeTspecReqSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeTspecReqDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeTspecReqSizeof(void *msg);
 extern void CsrWifiSmeTspecReqSerFree(void *msg);
 
@@ -252,8 +252,8 @@ extern void CsrWifiSmeTspecReqSerFree(void *msg);
 #define CsrWifiSmeVersionsGetReqSizeof CsrWifiEventSizeof
 #define CsrWifiSmeVersionsGetReqSerFree CsrWifiSmePfree
 
-extern u8CsrWifiSmeWifiFlightmodeReqSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeWifiFlightmodeReqDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeWifiFlightmodeReqSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeWifiFlightmodeReqDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeWifiFlightmodeReqSizeof(void *msg);
 extern void CsrWifiSmeWifiFlightmodeReqSerFree(void *msg);
 
@@ -262,13 +262,13 @@ extern void CsrWifiSmeWifiFlightmodeReqSerFree(void *msg);
 #define CsrWifiSmeWifiOffReqSizeof CsrWifiEventSizeof
 #define CsrWifiSmeWifiOffReqSerFree CsrWifiSmePfree
 
-extern u8CsrWifiSmeWifiOnReqSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeWifiOnReqDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeWifiOnReqSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeWifiOnReqDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeWifiOnReqSizeof(void *msg);
 extern void CsrWifiSmeWifiOnReqSerFree(void *msg);
 
-extern u8CsrWifiSmeCloakedSsidsSetReqSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeCloakedSsidsSetReqDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeCloakedSsidsSetReqSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeCloakedSsidsSetReqDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeCloakedSsidsSetReqSizeof(void *msg);
 extern void CsrWifiSmeCloakedSsidsSetReqSerFree(void *msg);
 
@@ -282,8 +282,8 @@ extern void CsrWifiSmeCloakedSsidsSetReqSerFree(void *msg);
 #define CsrWifiSmeSmeCommonConfigGetReqSizeof CsrWifiEventSizeof
 #define CsrWifiSmeSmeCommonConfigGetReqSerFree CsrWifiSmePfree
 
-extern u8CsrWifiSmeSmeCommonConfigSetReqSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeSmeCommonConfigSetReqDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeSmeCommonConfigSetReqSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeSmeCommonConfigSetReqDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeSmeCommonConfigSetReqSizeof(void *msg);
 #define CsrWifiSmeSmeCommonConfigSetReqSerFree CsrWifiSmePfree
 
@@ -292,13 +292,13 @@ extern size_t CsrWifiSmeSmeCommonConfigSetReqSizeof(void *msg);
 #define CsrWifiSmeInterfaceCapabilityGetReqSizeof CsrWifiEventSizeof
 #define CsrWifiSmeInterfaceCapabilityGetReqSerFree CsrWifiSmePfree
 
-extern u8CsrWifiSmeWpsConfigurationReqSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeWpsConfigurationReqDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeWpsConfigurationReqSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeWpsConfigurationReqDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeWpsConfigurationReqSizeof(void *msg);
 extern void CsrWifiSmeWpsConfigurationReqSerFree(void *msg);
 
-extern u8CsrWifiSmeSetReqSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeSetReqDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeSetReqSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeSetReqDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeSetReqSizeof(void *msg);
 extern void CsrWifiSmeSetReqSerFree(void *msg);
 
@@ -307,8 +307,8 @@ extern void CsrWifiSmeSetReqSerFree(void *msg);
 #define CsrWifiSmeActivateCfmSizeof CsrWifiEventCsrUint16Sizeof
 #define CsrWifiSmeActivateCfmSerFree CsrWifiSmePfree
 
-extern u8CsrWifiSmeAdhocConfigGetCfmSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeAdhocConfigGetCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeAdhocConfigGetCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeAdhocConfigGetCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeAdhocConfigGetCfmSizeof(void *msg);
 #define CsrWifiSmeAdhocConfigGetCfmSerFree CsrWifiSmePfree
 
@@ -317,23 +317,23 @@ extern size_t CsrWifiSmeAdhocConfigGetCfmSizeof(void *msg);
 #define CsrWifiSmeAdhocConfigSetCfmSizeof CsrWifiEventCsrUint16Sizeof
 #define CsrWifiSmeAdhocConfigSetCfmSerFree CsrWifiSmePfree
 
-extern u8CsrWifiSmeAssociationCompleteIndSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeAssociationCompleteIndDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeAssociationCompleteIndSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeAssociationCompleteIndDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeAssociationCompleteIndSizeof(void *msg);
 extern void CsrWifiSmeAssociationCompleteIndSerFree(void *msg);
 
-extern u8CsrWifiSmeAssociationStartIndSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeAssociationStartIndDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeAssociationStartIndSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeAssociationStartIndDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeAssociationStartIndSizeof(void *msg);
 #define CsrWifiSmeAssociationStartIndSerFree CsrWifiSmePfree
 
-extern u8CsrWifiSmeBlacklistCfmSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeBlacklistCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeBlacklistCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeBlacklistCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeBlacklistCfmSizeof(void *msg);
 extern void CsrWifiSmeBlacklistCfmSerFree(void *msg);
 
-extern u8CsrWifiSmeCalibrationDataGetCfmSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeCalibrationDataGetCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeCalibrationDataGetCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeCalibrationDataGetCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeCalibrationDataGetCfmSizeof(void *msg);
 extern void CsrWifiSmeCalibrationDataGetCfmSerFree(void *msg);
 
@@ -342,18 +342,18 @@ extern void CsrWifiSmeCalibrationDataGetCfmSerFree(void *msg);
 #define CsrWifiSmeCalibrationDataSetCfmSizeof CsrWifiEventCsrUint16Sizeof
 #define CsrWifiSmeCalibrationDataSetCfmSerFree CsrWifiSmePfree
 
-extern u8CsrWifiSmeCcxConfigGetCfmSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeCcxConfigGetCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeCcxConfigGetCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeCcxConfigGetCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeCcxConfigGetCfmSizeof(void *msg);
 #define CsrWifiSmeCcxConfigGetCfmSerFree CsrWifiSmePfree
 
-extern u8CsrWifiSmeCcxConfigSetCfmSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeCcxConfigSetCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeCcxConfigSetCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeCcxConfigSetCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeCcxConfigSetCfmSizeof(void *msg);
 #define CsrWifiSmeCcxConfigSetCfmSerFree CsrWifiSmePfree
 
-extern u8CsrWifiSmeCoexConfigGetCfmSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeCoexConfigGetCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeCoexConfigGetCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeCoexConfigGetCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeCoexConfigGetCfmSizeof(void *msg);
 #define CsrWifiSmeCoexConfigGetCfmSerFree CsrWifiSmePfree
 
@@ -362,33 +362,33 @@ extern size_t CsrWifiSmeCoexConfigGetCfmSizeof(void *msg);
 #define CsrWifiSmeCoexConfigSetCfmSizeof CsrWifiEventCsrUint16Sizeof
 #define CsrWifiSmeCoexConfigSetCfmSerFree CsrWifiSmePfree
 
-extern u8CsrWifiSmeCoexInfoGetCfmSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeCoexInfoGetCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeCoexInfoGetCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeCoexInfoGetCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeCoexInfoGetCfmSizeof(void *msg);
 #define CsrWifiSmeCoexInfoGetCfmSerFree CsrWifiSmePfree
 
-extern u8CsrWifiSmeConnectCfmSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeConnectCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeConnectCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeConnectCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeConnectCfmSizeof(void *msg);
 #define CsrWifiSmeConnectCfmSerFree CsrWifiSmePfree
 
-extern u8CsrWifiSmeConnectionConfigGetCfmSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeConnectionConfigGetCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeConnectionConfigGetCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeConnectionConfigGetCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeConnectionConfigGetCfmSizeof(void *msg);
 extern void CsrWifiSmeConnectionConfigGetCfmSerFree(void *msg);
 
-extern u8CsrWifiSmeConnectionInfoGetCfmSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeConnectionInfoGetCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeConnectionInfoGetCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeConnectionInfoGetCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeConnectionInfoGetCfmSizeof(void *msg);
 extern void CsrWifiSmeConnectionInfoGetCfmSerFree(void *msg);
 
-extern u8CsrWifiSmeConnectionQualityIndSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeConnectionQualityIndDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeConnectionQualityIndSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeConnectionQualityIndDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeConnectionQualityIndSizeof(void *msg);
 #define CsrWifiSmeConnectionQualityIndSerFree CsrWifiSmePfree
 
-extern u8CsrWifiSmeConnectionStatsGetCfmSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeConnectionStatsGetCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeConnectionStatsGetCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeConnectionStatsGetCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeConnectionStatsGetCfmSizeof(void *msg);
 #define CsrWifiSmeConnectionStatsGetCfmSerFree CsrWifiSmePfree
 
@@ -397,8 +397,8 @@ extern size_t CsrWifiSmeConnectionStatsGetCfmSizeof(void *msg);
 #define CsrWifiSmeDeactivateCfmSizeof CsrWifiEventCsrUint16Sizeof
 #define CsrWifiSmeDeactivateCfmSerFree CsrWifiSmePfree
 
-extern u8CsrWifiSmeDisconnectCfmSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeDisconnectCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeDisconnectCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeDisconnectCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeDisconnectCfmSizeof(void *msg);
 #define CsrWifiSmeDisconnectCfmSerFree CsrWifiSmePfree
 
@@ -407,38 +407,38 @@ extern size_t CsrWifiSmeDisconnectCfmSizeof(void *msg);
 #define CsrWifiSmeEventMaskSetCfmSizeof CsrWifiEventCsrUint16Sizeof
 #define CsrWifiSmeEventMaskSetCfmSerFree CsrWifiSmePfree
 
-extern u8CsrWifiSmeHostConfigGetCfmSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeHostConfigGetCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeHostConfigGetCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeHostConfigGetCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeHostConfigGetCfmSizeof(void *msg);
 #define CsrWifiSmeHostConfigGetCfmSerFree CsrWifiSmePfree
 
-extern u8CsrWifiSmeHostConfigSetCfmSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeHostConfigSetCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeHostConfigSetCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeHostConfigSetCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeHostConfigSetCfmSizeof(void *msg);
 #define CsrWifiSmeHostConfigSetCfmSerFree CsrWifiSmePfree
 
-extern u8CsrWifiSmeIbssStationIndSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeIbssStationIndDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeIbssStationIndSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeIbssStationIndDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeIbssStationIndSizeof(void *msg);
 #define CsrWifiSmeIbssStationIndSerFree CsrWifiSmePfree
 
-extern u8CsrWifiSmeKeyCfmSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeKeyCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeKeyCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeKeyCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeKeyCfmSizeof(void *msg);
 #define CsrWifiSmeKeyCfmSerFree CsrWifiSmePfree
 
-extern u8CsrWifiSmeLinkQualityGetCfmSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeLinkQualityGetCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeLinkQualityGetCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeLinkQualityGetCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeLinkQualityGetCfmSizeof(void *msg);
 #define CsrWifiSmeLinkQualityGetCfmSerFree CsrWifiSmePfree
 
-extern u8CsrWifiSmeMediaStatusIndSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeMediaStatusIndDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeMediaStatusIndSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeMediaStatusIndDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeMediaStatusIndSizeof(void *msg);
 extern void CsrWifiSmeMediaStatusIndSerFree(void *msg);
 
-extern u8CsrWifiSmeMibConfigGetCfmSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeMibConfigGetCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeMibConfigGetCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeMibConfigGetCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeMibConfigGetCfmSizeof(void *msg);
 #define CsrWifiSmeMibConfigGetCfmSerFree CsrWifiSmePfree
 
@@ -447,13 +447,13 @@ extern size_t CsrWifiSmeMibConfigGetCfmSizeof(void *msg);
 #define CsrWifiSmeMibConfigSetCfmSizeof CsrWifiEventCsrUint16Sizeof
 #define CsrWifiSmeMibConfigSetCfmSerFree CsrWifiSmePfree
 
-extern u8CsrWifiSmeMibGetCfmSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeMibGetCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeMibGetCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeMibGetCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeMibGetCfmSizeof(void *msg);
 extern void CsrWifiSmeMibGetCfmSerFree(void *msg);
 
-extern u8CsrWifiSmeMibGetNextCfmSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeMibGetNextCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeMibGetNextCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeMibGetNextCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeMibGetNextCfmSizeof(void *msg);
 extern void CsrWifiSmeMibGetNextCfmSerFree(void *msg);
 
@@ -462,38 +462,39 @@ extern void CsrWifiSmeMibGetNextCfmSerFree(void *msg);
 #define CsrWifiSmeMibSetCfmSizeof CsrWifiEventCsrUint16Sizeof
 #define CsrWifiSmeMibSetCfmSerFree CsrWifiSmePfree
 
-extern u8CsrWifiSmeMicFailureIndSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeMicFailureIndDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeMicFailureIndSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeMicFailureIndDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeMicFailureIndSizeof(void *msg);
 #define CsrWifiSmeMicFailureIndSerFree CsrWifiSmePfree
 
-extern u8CsrWifiSmeMulticastAddressCfmSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeMulticastAddressCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeMulticastAddressCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeMulticastAddressCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeMulticastAddressCfmSizeof(void *msg);
 extern void CsrWifiSmeMulticastAddressCfmSerFree(void *msg);
 
-extern u8CsrWifiSmePacketFilterSetCfmSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmePacketFilterSetCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmePacketFilterSetCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmePacketFilterSetCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmePacketFilterSetCfmSizeof(void *msg);
 #define CsrWifiSmePacketFilterSetCfmSerFree CsrWifiSmePfree
 
-extern u8* CsrWifiSmePermanentMacAddressGetCfmSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmePermanentMacAddressGetCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmePermanentMacAddressGetCfmSer(u8 *ptr, size_t *len,
+       void *msg);
+extern void *CsrWifiSmePermanentMacAddressGetCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmePermanentMacAddressGetCfmSizeof(void *msg);
 #define CsrWifiSmePermanentMacAddressGetCfmSerFree CsrWifiSmePfree
 
-extern u8CsrWifiSmePmkidCandidateListIndSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmePmkidCandidateListIndDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmePmkidCandidateListIndSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmePmkidCandidateListIndDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmePmkidCandidateListIndSizeof(void *msg);
 extern void CsrWifiSmePmkidCandidateListIndSerFree(void *msg);
 
-extern u8CsrWifiSmePmkidCfmSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmePmkidCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmePmkidCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmePmkidCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmePmkidCfmSizeof(void *msg);
 extern void CsrWifiSmePmkidCfmSerFree(void *msg);
 
-extern u8CsrWifiSmePowerConfigGetCfmSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmePowerConfigGetCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmePowerConfigGetCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmePowerConfigGetCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmePowerConfigGetCfmSizeof(void *msg);
 #define CsrWifiSmePowerConfigGetCfmSerFree CsrWifiSmePfree
 
@@ -502,33 +503,34 @@ extern size_t CsrWifiSmePowerConfigGetCfmSizeof(void *msg);
 #define CsrWifiSmePowerConfigSetCfmSizeof CsrWifiEventCsrUint16Sizeof
 #define CsrWifiSmePowerConfigSetCfmSerFree CsrWifiSmePfree
 
-extern u8* CsrWifiSmeRegulatoryDomainInfoGetCfmSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeRegulatoryDomainInfoGetCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeRegulatoryDomainInfoGetCfmSer(u8 *ptr, size_t *len,
+       void *msg);
+extern void *CsrWifiSmeRegulatoryDomainInfoGetCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeRegulatoryDomainInfoGetCfmSizeof(void *msg);
 #define CsrWifiSmeRegulatoryDomainInfoGetCfmSerFree CsrWifiSmePfree
 
-extern u8CsrWifiSmeRoamCompleteIndSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeRoamCompleteIndDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeRoamCompleteIndSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeRoamCompleteIndDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeRoamCompleteIndSizeof(void *msg);
 #define CsrWifiSmeRoamCompleteIndSerFree CsrWifiSmePfree
 
-extern u8CsrWifiSmeRoamStartIndSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeRoamStartIndDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeRoamStartIndSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeRoamStartIndDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeRoamStartIndSizeof(void *msg);
 #define CsrWifiSmeRoamStartIndSerFree CsrWifiSmePfree
 
-extern u8CsrWifiSmeRoamingConfigGetCfmSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeRoamingConfigGetCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeRoamingConfigGetCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeRoamingConfigGetCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeRoamingConfigGetCfmSizeof(void *msg);
 #define CsrWifiSmeRoamingConfigGetCfmSerFree CsrWifiSmePfree
 
-extern u8CsrWifiSmeRoamingConfigSetCfmSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeRoamingConfigSetCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeRoamingConfigSetCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeRoamingConfigSetCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeRoamingConfigSetCfmSizeof(void *msg);
 #define CsrWifiSmeRoamingConfigSetCfmSerFree CsrWifiSmePfree
 
-extern u8CsrWifiSmeScanConfigGetCfmSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeScanConfigGetCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeScanConfigGetCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeScanConfigGetCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeScanConfigGetCfmSizeof(void *msg);
 extern void CsrWifiSmeScanConfigGetCfmSerFree(void *msg);
 
@@ -542,8 +544,8 @@ extern void CsrWifiSmeScanConfigGetCfmSerFree(void *msg);
 #define CsrWifiSmeScanFullCfmSizeof CsrWifiEventCsrUint16Sizeof
 #define CsrWifiSmeScanFullCfmSerFree CsrWifiSmePfree
 
-extern u8CsrWifiSmeScanResultIndSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeScanResultIndDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeScanResultIndSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeScanResultIndDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeScanResultIndSizeof(void *msg);
 extern void CsrWifiSmeScanResultIndSerFree(void *msg);
 
@@ -552,38 +554,39 @@ extern void CsrWifiSmeScanResultIndSerFree(void *msg);
 #define CsrWifiSmeScanResultsFlushCfmSizeof CsrWifiEventCsrUint16Sizeof
 #define CsrWifiSmeScanResultsFlushCfmSerFree CsrWifiSmePfree
 
-extern u8CsrWifiSmeScanResultsGetCfmSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeScanResultsGetCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeScanResultsGetCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeScanResultsGetCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeScanResultsGetCfmSizeof(void *msg);
 extern void CsrWifiSmeScanResultsGetCfmSerFree(void *msg);
 
-extern u8CsrWifiSmeSmeStaConfigGetCfmSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeSmeStaConfigGetCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeSmeStaConfigGetCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeSmeStaConfigGetCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeSmeStaConfigGetCfmSizeof(void *msg);
 #define CsrWifiSmeSmeStaConfigGetCfmSerFree CsrWifiSmePfree
 
-extern u8CsrWifiSmeSmeStaConfigSetCfmSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeSmeStaConfigSetCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeSmeStaConfigSetCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeSmeStaConfigSetCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeSmeStaConfigSetCfmSizeof(void *msg);
 #define CsrWifiSmeSmeStaConfigSetCfmSerFree CsrWifiSmePfree
 
-extern u8* CsrWifiSmeStationMacAddressGetCfmSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeStationMacAddressGetCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeStationMacAddressGetCfmSer(u8 *ptr, size_t *len,
+       void *msg);
+extern void *CsrWifiSmeStationMacAddressGetCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeStationMacAddressGetCfmSizeof(void *msg);
 #define CsrWifiSmeStationMacAddressGetCfmSerFree CsrWifiSmePfree
 
-extern u8CsrWifiSmeTspecIndSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeTspecIndDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeTspecIndSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeTspecIndDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeTspecIndSizeof(void *msg);
 extern void CsrWifiSmeTspecIndSerFree(void *msg);
 
-extern u8CsrWifiSmeTspecCfmSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeTspecCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeTspecCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeTspecCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeTspecCfmSizeof(void *msg);
 extern void CsrWifiSmeTspecCfmSerFree(void *msg);
 
-extern u8CsrWifiSmeVersionsGetCfmSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeVersionsGetCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeVersionsGetCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeVersionsGetCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeVersionsGetCfmSizeof(void *msg);
 extern void CsrWifiSmeVersionsGetCfmSerFree(void *msg);
 
@@ -612,18 +615,18 @@ extern void CsrWifiSmeVersionsGetCfmSerFree(void *msg);
 #define CsrWifiSmeCloakedSsidsSetCfmSizeof CsrWifiEventCsrUint16Sizeof
 #define CsrWifiSmeCloakedSsidsSetCfmSerFree CsrWifiSmePfree
 
-extern u8CsrWifiSmeCloakedSsidsGetCfmSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeCloakedSsidsGetCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeCloakedSsidsGetCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeCloakedSsidsGetCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeCloakedSsidsGetCfmSizeof(void *msg);
 extern void CsrWifiSmeCloakedSsidsGetCfmSerFree(void *msg);
 
-extern u8CsrWifiSmeWifiOnIndSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeWifiOnIndDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeWifiOnIndSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeWifiOnIndDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeWifiOnIndSizeof(void *msg);
 #define CsrWifiSmeWifiOnIndSerFree CsrWifiSmePfree
 
-extern u8CsrWifiSmeSmeCommonConfigGetCfmSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeSmeCommonConfigGetCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeSmeCommonConfigGetCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeSmeCommonConfigGetCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeSmeCommonConfigGetCfmSizeof(void *msg);
 #define CsrWifiSmeSmeCommonConfigGetCfmSerFree CsrWifiSmePfree
 
@@ -632,23 +635,24 @@ extern size_t CsrWifiSmeSmeCommonConfigGetCfmSizeof(void *msg);
 #define CsrWifiSmeSmeCommonConfigSetCfmSizeof CsrWifiEventCsrUint16Sizeof
 #define CsrWifiSmeSmeCommonConfigSetCfmSerFree CsrWifiSmePfree
 
-extern u8* CsrWifiSmeInterfaceCapabilityGetCfmSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeInterfaceCapabilityGetCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeInterfaceCapabilityGetCfmSer(u8 *ptr, size_t *len,
+       void *msg);
+extern void *CsrWifiSmeInterfaceCapabilityGetCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeInterfaceCapabilityGetCfmSizeof(void *msg);
 #define CsrWifiSmeInterfaceCapabilityGetCfmSerFree CsrWifiSmePfree
 
-extern u8CsrWifiSmeErrorIndSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeErrorIndDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeErrorIndSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeErrorIndDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeErrorIndSizeof(void *msg);
 extern void CsrWifiSmeErrorIndSerFree(void *msg);
 
-extern u8CsrWifiSmeInfoIndSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeInfoIndDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeInfoIndSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeInfoIndDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeInfoIndSizeof(void *msg);
 extern void CsrWifiSmeInfoIndSerFree(void *msg);
 
-extern u8CsrWifiSmeCoreDumpIndSer(u8 *ptr, size_t *len, void *msg);
-extern voidCsrWifiSmeCoreDumpIndDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeCoreDumpIndSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeCoreDumpIndDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeCoreDumpIndSizeof(void *msg);
 extern void CsrWifiSmeCoreDumpIndSerFree(void *msg);
 
index 0f725e454939b74116185bc841f00ec17e0231e6..a94fe88fa41cbcc383e39d6b1fdb82d89e6952fd 100644 (file)
@@ -1,10 +1,10 @@
 /*****************************************************************************
 
-            (c) Cambridge Silicon Radio Limited 2011
-            All rights reserved and confidential information of CSR
+       (c) Cambridge Silicon Radio Limited 2011
+       All rights reserved and confidential information of CSR
 
-            Refer to LICENSE.txt included with this source for details
-            on the license terms.
+       Refer to LICENSE.txt included with this source for details
+       on the license terms.
 
 *****************************************************************************/
 
index 8ed7a7845cc64ae34ad4b2da49eaa6149e1269d1..9e3d8b8ab02cb7d6bcdde7b1c45fbf57d28678c1 100644 (file)
 int
 uf_verify_m4(unifi_priv_t *priv, const unsigned char *packet, unsigned int length)
 {
-    const unsigned char *p = packet;
-    u16 keyinfo;
+       const unsigned char *p = packet;
+       u16 keyinfo;
 
 
-    if (length < (4 + 5 + 8 + 32 + 16 + 8 + 8 + 16 + 1 + 8)) {
-        return 1;
-    }
+       if (length < (4 + 5 + 8 + 32 + 16 + 8 + 8 + 16 + 1 + 8))
+               return 1;
 
-    p += 8;
-    keyinfo = p[5] << 8 | p[6]; /* big-endian */
-    if (
-          (p[0] == 1 || p[0] == 2) /* protocol version 802.1X-2001 (WPA) or -2004 (WPA2) */ &&
-          p[1] == 3 /* EAPOL-Key */ &&
-          /* don't bother checking p[2] p[3] (hh ll, packet body length) */
-          (p[4] == 254 || p[4] == 2) /* descriptor type P802.1i-D3.0 (WPA) or 802.11i-2004 (WPA2) */ &&
-          ((keyinfo & 0x0007) == 1 || (keyinfo & 0x0007) == 2) /* key descriptor version */ &&
-         (keyinfo & ~0x0207U) == 0x0108 && /* key info for 4/4 or 4/2 -- ignore key desc version and sec bit (since varies in WPA 4/4) */
-          (p[4 + 5 + 8 + 32 + 16 + 8 + 8 + 16 + 0] == 0 && /* key data length (2 octets) 0 for 4/4 only */
-           p[4 + 5 + 8 + 32 + 16 + 8 + 8 + 16 + 1] == 0)
-        ) {
-        unifi_trace(priv, UDBG1, "uf_verify_m4: M4 detected \n");
-        return 0;
-    }
-    else
-    {
-        return 1;
-    }
+       p += 8;
+       keyinfo = p[5] << 8 | p[6]; /* big-endian */
+       if (
+         (p[0] == 1 || p[0] == 2) /* protocol version 802.1X-2001 (WPA) or -2004 (WPA2) */ &&
+         p[1] == 3 /* EAPOL-Key */ &&
+         /* don't bother checking p[2] p[3] (hh ll, packet body length) */
+         (p[4] == 254 || p[4] == 2) /* descriptor type P802.1i-D3.0 (WPA) or 802.11i-2004 (WPA2) */ &&
+         ((keyinfo & 0x0007) == 1 || (keyinfo & 0x0007) == 2) /* key descriptor version */ &&
+        (keyinfo & ~0x0207U) == 0x0108 && /* key info for 4/4 or 4/2 -- ignore key desc version and sec bit (since varies in WPA 4/4) */
+         (p[4 + 5 + 8 + 32 + 16 + 8 + 8 + 16 + 0] == 0 && /* key data length (2 octets) 0 for 4/4 only */
+          p[4 + 5 + 8 + 32 + 16 + 8 + 8 + 16 + 1] == 0)
+       ) {
+               unifi_trace(priv, UDBG1, "uf_verify_m4: M4 detected\n");
+               return 0;
+       } else {
+               return 1;
+       }
 }
 
 /*
index caf48e3120caedad6eaeb2a24ee26f550150116a..5206cbafff745dae0202fb3f98667332da399944 100644 (file)
@@ -31,7 +31,6 @@
  * ---------------------------------------------------------------------------
  */
 #include <linux/proc_fs.h>
-#include <linux/version.h>
 
 #include "csr_wifi_hip_unifi.h"
 #include "csr_wifi_hip_unifiversion.h"
index 7c524a18958efc96360756fa0e8101b0dd0ca591..7b76f07ff332e9424a3cf4696afc07693f047a11 100644 (file)
@@ -10,7 +10,6 @@
  * ---------------------------------------------------------------------------
  */
 
-#include <linux/version.h>
 #include "unifi_priv.h"
 
 #ifdef UNIFI_SNIFF_ARPHRD
index 9a52ab408e1ae2768bbba8e456ec740787767b60..113f2c189a67aa12e6e4cc3febfb6425f3bdc1ec 100644 (file)
@@ -47,7 +47,6 @@
 #include <linux/etherdevice.h>
 #include <linux/mutex.h>
 #include <linux/semaphore.h>
-#include <linux/version.h>
 #include <linux/vmalloc.h>
 #include "csr_wifi_hip_unifi.h"
 #include "csr_wifi_hip_conversions.h"
@@ -3247,8 +3246,8 @@ static void check_ba_frame_age_timeout( unifi_priv_t *priv,
                                         netInterface_priv_t *interfacePriv,
                                         ba_session_rx_struct *ba_session)
 {
-    CsrTime now;
-    CsrTime age;
+    u32 now;
+    u32 age;
     u8 i, j;
     u16 sn_temp;
 
@@ -3283,11 +3282,11 @@ static void check_ba_frame_age_timeout( unifi_priv_t *priv,
                 if (ba_session->buffer[i].recv_time > now)
                 {
                     /* timer wrap */
-                    age = CsrTimeAdd((CsrTime)CsrTimeSub(CSR_SCHED_TIME_MAX, ba_session->buffer[i].recv_time), now);
+                    age = CsrTimeAdd((u32)CsrTimeSub(CSR_SCHED_TIME_MAX, ba_session->buffer[i].recv_time), now);
                 }
                 else
                 {
-                    age = (CsrTime)CsrTimeSub(now, ba_session->buffer[i].recv_time);
+                    age = (u32)CsrTimeSub(now, ba_session->buffer[i].recv_time);
                 }
 
                 if (age >= CSR_WIFI_BA_MPDU_FRAME_AGE_TIMEOUT)
index af3e40bb5010c04ebf740775aa9b21dd3a116844..6b96df11baafcd99800b9f4c2fd5c66e447ff7ce 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/kernel.h>
 #include <linux/mutex.h>
 #include <linux/gfp.h>
-#include <linux/version.h>
 #include <linux/mmc/core.h>
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
index d7a5125d9a8eaf04c9fbdca2b881fda090399552..26f10bcbe0397212d7e022e2571c0ead402b7029 100644 (file)
@@ -12,7 +12,6 @@
  */
 
 #include <linux/netdevice.h>
-#include <linux/version.h>
 #include "unifi_priv.h"
 #include "csr_wifi_hip_unifi.h"
 #include "csr_wifi_hip_conversions.h"
index 5b26c41c01f6c95216b888c6d0cefc1b2c78048a..9c5ca3a9261f139ac684a14bbad3f64ce93ee3ec 100644 (file)
@@ -14,7 +14,6 @@
  * ---------------------------------------------------------------------------
  */
 
-#include <linux/version.h>
 #include "csr_wifi_hip_unifiversion.h"
 #include "unifi_priv.h"
 #include "csr_wifi_hip_conversions.h"
@@ -2102,7 +2101,7 @@ static int peer_add_new_record(unifi_priv_t *priv,CsrWifiRouterCtrlPeerAddReq *r
     u8 freeSlotFound = FALSE;
     CsrWifiRouterCtrlStaInfo_t *newRecord = NULL;
     netInterface_priv_t *interfacePriv = priv->interfacePriv[req->interfaceTag];
-    CsrTime currentTime, currentTimeHi;
+    u32 currentTime, currentTimeHi;
     unsigned long lock_flags;
 
     if (req->interfaceTag >= CSR_WIFI_NUM_INTERFACES) {
@@ -2296,8 +2295,8 @@ static void check_inactivity_timer_expire_func(unsigned long data)
     struct unifi_priv *priv;
     CsrWifiRouterCtrlStaInfo_t *sta_record = NULL;
     u8 i = 0;
-    CsrTime now;
-    CsrTime inactive_time;
+    u32 now;
+    u32 inactive_time;
     netInterface_priv_t *interfacePriv = (netInterface_priv_t *) data;
 
     if (!interfacePriv)
@@ -2329,11 +2328,11 @@ static void check_inactivity_timer_expire_func(unsigned long data)
             if (sta_record->lastActivity > now)
             {
                 /* simple timer wrap (for 1 wrap) */
-                inactive_time = CsrTimeAdd((CsrTime)CsrTimeSub(CSR_SCHED_TIME_MAX, sta_record->lastActivity), now);
+                inactive_time = CsrTimeAdd((u32)CsrTimeSub(CSR_SCHED_TIME_MAX, sta_record->lastActivity), now);
             }
             else
             {
-                inactive_time = (CsrTime)CsrTimeSub(now, sta_record->lastActivity);
+                inactive_time = (u32)CsrTimeSub(now, sta_record->lastActivity);
             }
 
             if (inactive_time >= STA_INACTIVE_TIMEOUT_VAL)
index 7816b15b4b5da518755314b21d3460fa49bb6544..ebe371c732b2c0916f8bcca4415abdf85ea12812 100644 (file)
@@ -32,7 +32,7 @@ int uf_sme_queue_message(unifi_priv_t *priv, u8 *buffer, int length);
 #include "csr_wifi_sme_lib.h"
 
 void CsrWifiRouterTransportInit(unifi_priv_t *priv);
-void CsrWifiRouterTransportRecv(unifi_priv_t *priv, u8buffer, size_t bufferLength);
+void CsrWifiRouterTransportRecv(unifi_priv_t *priv, u8 *buffer, size_t bufferLength);
 void CsrWifiRouterTransportDeInit(unifi_priv_t *priv);
 
 #endif /* __LINUX_SME_USERSPACE_H__ */
index 4013d021ebbf62a78c5d170656df0bd9f57abae5..0fae6f48f79b9e81345fcd835237909662ff6f8d 100644 (file)
@@ -12,7 +12,6 @@
  *
  * ***************************************************************************
  */
-#include <linux/version.h>
 #include "csr_wifi_hip_unifi.h"
 #include "csr_wifi_hip_conversions.h"
 #include "unifi_priv.h"
index ae7c8fc94092ca7ca9cad5512688d1c3e387377f..8f21d98dff2d622515b5056cc95880b02107418c 100644 (file)
@@ -14,7 +14,6 @@
  * ---------------------------------------------------------------------------
  */
 
-#include <linux/version.h>
 #include <linux/types.h>
 #include <linux/etherdevice.h>
 #include <linux/vmalloc.h>
@@ -1117,8 +1116,8 @@ void uf_process_ma_pkt_cfm_for_ap(unifi_priv_t *priv,u16 interfaceTag, const CSR
             staRecord->nullDataHostTag = INVALID_HOST_TAG;
 
             if(pkt_cfm->TransmissionStatus == CSR_TX_RETRY_LIMIT){
-                CsrTime now;
-                CsrTime inactive_time;
+                u32 now;
+                u32 inactive_time;
 
                 unifi_trace(priv, UDBG1, "Nulldata to probe STA ALIVE Failed with retry limit\n");
                 /* Recheck if there is some activity after null data is sent.
@@ -1134,12 +1133,12 @@ void uf_process_ma_pkt_cfm_for_ap(unifi_priv_t *priv,u16 interfaceTag, const CSR
                 if (staRecord->lastActivity > now)
                 {
                     /* simple timer wrap (for 1 wrap) */
-                    inactive_time = CsrTimeAdd((CsrTime)CsrTimeSub(CSR_SCHED_TIME_MAX, staRecord->lastActivity),
+                    inactive_time = CsrTimeAdd((u32)CsrTimeSub(CSR_SCHED_TIME_MAX, staRecord->lastActivity),
                                                now);
                 }
                 else
                 {
-                    inactive_time = (CsrTime)CsrTimeSub(now, staRecord->lastActivity);
+                    inactive_time = (u32)CsrTimeSub(now, staRecord->lastActivity);
                 }
 
                 if (inactive_time >= STA_INACTIVE_TIMEOUT_VAL)
@@ -3492,11 +3491,11 @@ CsrWifiRouterCtrlStaInfo_t * CsrWifiRouterCtrlGetStationRecordFromHandle(unifi_p
 }
 
 /* Function to do inactivity */
-void uf_check_inactivity(unifi_priv_t *priv, u16 interfaceTag, CsrTime currentTime)
+void uf_check_inactivity(unifi_priv_t *priv, u16 interfaceTag, u32 currentTime)
 {
     u32 i;
     CsrWifiRouterCtrlStaInfo_t *staInfo;
-    CsrTime elapsedTime;    /* Time in microseconds */
+    u32 elapsedTime;    /* Time in microseconds */
     netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag];
     CsrWifiMacAddress peerMacAddress;
     unsigned long lock_flags;
@@ -3543,8 +3542,8 @@ void uf_check_inactivity(unifi_priv_t *priv, u16 interfaceTag, CsrTime currentTi
 /* Function to update activity of a station */
 void uf_update_sta_activity(unifi_priv_t *priv, u16 interfaceTag, const u8 *peerMacAddress)
 {
-    CsrTime elapsedTime, currentTime;    /* Time in microseconds */
-    CsrTime timeHi;         /* Not used - Time in microseconds */
+    u32 elapsedTime, currentTime;    /* Time in microseconds */
+    u32 timeHi;         /* Not used - Time in microseconds */
     CsrWifiRouterCtrlStaInfo_t *staInfo;
     netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag];
     unsigned long lock_flags;
index aec8e28fb60dfbf836077e08ffab2da5edc0cda4..d20d74ce56cbb42f28e5401f78fa1c53ee0efd3a 100644 (file)
@@ -17,7 +17,6 @@
 #ifndef __LINUX_UNIFI_PRIV_H__
 #define __LINUX_UNIFI_PRIV_H__ 1
 
-#include <linux/version.h>
 #include <linux/module.h>
 #include <linux/string.h>
 #include <linux/errno.h>
@@ -313,7 +312,7 @@ typedef struct CsrWifiRouterCtrlStaInfo_t {
     CSR_CLIENT_TAG nullDataHostTag;
 
     /* Activity timestamps for the station */
-    CsrTime lastActivity;
+    u32 lastActivity;
 
     /* during m/c transmission sp suspended */
     u8 uspSuspend;
@@ -653,7 +652,7 @@ typedef struct {
     bulk_data_param_t bulkdata;
     CSR_SIGNAL signal;
     u16 sn;
-    CsrTime recv_time;
+    u32 recv_time;
 } frame_desc_struct;
 
 typedef struct {
@@ -736,7 +735,7 @@ typedef struct netInterface_priv
     u8 sta_activity_check_enabled;
 
     /* Timestamp when the last inactivity check was done */
-    CsrTime last_inactivity_check;
+    u32 last_inactivity_check;
 
     /*number of multicast or borad cast packets  queued*/
     u16 noOfbroadcastPktQueued;
index 6834c43abfbbb123285adf67c54e3c4715cf967f..beba089e2e350ed5c794ceccae728fe2dda5ac2f 100644 (file)
@@ -16,7 +16,6 @@
 #define __LINUX_UNIFI_WEXT_H__ 1
 
 #include <linux/kernel.h>
-#include <linux/version.h>
 #include <net/iw_handler.h>
 #include "csr_wifi_sme_prim.h"
 
index 39f4bb65ec83ac83076a7d69dc2771ae1de1bfcb..7d378c27f230b0ffdfb0abf436cf4a776197443a 100644 (file)
@@ -2,6 +2,7 @@ config DGRP
        tristate "Digi Realport driver"
        default n
        depends on SYSFS
+       depends on BROKEN
        ---help---
        Support for Digi Realport devices.  These devices allow you to
        access remote serial ports as if they are local tty devices.  This
index 49e670915e5ca4aec40a1afb96f0a1bfe48cb17d..021cca498f2c510ccb6bcd63a23582e39b094f16 100644 (file)
@@ -387,7 +387,7 @@ static long dgrp_dpa_ioctl(struct file *file, unsigned int cmd,
 
                port = getchan.ch_port;
 
-               if (port < 0 || port > nd->nd_chan_count)
+               if (port > nd->nd_chan_count)
                        return -EINVAL;
 
                ch = nd->nd_chan + port;
index 268dcb95204b1501901a7eb0baf20c563bed4cd7..4792d056a36532b179968dda51f73b37ce56cb95 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/sched.h>
 #include <asm/unaligned.h>
 #include <linux/proc_fs.h>
+#include <linux/uaccess.h>
 
 #include "dgrp_common.h"
 
index ab839ea3b44cb2f4e69186f82b6efe537cbe2f25..067d975554463b0f63768a0e5ac97b324df12250 100644 (file)
@@ -1671,6 +1671,9 @@ static int dgrp_send(struct nd_struct *nd, long tmax)
                                 * do the job.
                                 */
 
+                               /* FIXME: jiffies - ch->ch_waketime can never
+                                  be < 0. Someone needs to work out what is
+                                  actually intended here */
                                if (ch->ch_pun.un_open_count &&
                                    (ch->ch_pun.un_flag &
                                    (UN_EMPTY|UN_TIME|UN_LOW|UN_PWAIT)) != 0) {
index 28f5c9ab6b4349200f65062e0dc2a5adb275afc3..24327c3bad83427c208a03c231504f5fa42b0510 100644 (file)
@@ -39,6 +39,7 @@
 #include <linux/proc_fs.h>
 #include <linux/ctype.h>
 #include <linux/seq_file.h>
+#include <linux/uaccess.h>
 #include <linux/vmalloc.h>
 
 #include "dgrp_common.h"
@@ -228,6 +229,9 @@ static void register_proc_table(struct dgrp_proc_entry *table,
        int len;
        mode_t mode;
 
+       if (table == NULL)
+               return;
+
        for (; table->id; table++) {
                /* Can't do anything without a proc name. */
                if (!table->name)
@@ -296,6 +300,9 @@ static void unregister_proc_table(struct dgrp_proc_entry *table,
        struct proc_dir_entry *de;
        struct nd_struct *tmp;
 
+       if (table == NULL)
+               return;
+
        list_for_each_entry(tmp, &nd_struct_list, list) {
                if ((table == dgrp_net_table) && (tmp->nd_net_de)) {
                        unregister_dgrp_device(tmp->nd_net_de);
index e5a3c88d016e03210d6e77348674f9c57226e64d..43ab9f4d9349d6db20a2e1a53d7790950e7a5b9f 100644 (file)
@@ -17,7 +17,6 @@
 #include "dgrp_common.h"
 
 #include <linux/kernel.h>
-#include <linux/version.h>
 #include <linux/module.h>
 #include <linux/ctype.h>
 #include <linux/string.h>
@@ -177,7 +176,7 @@ static ssize_t dgrp_node_description_show(struct device *c,
        if (!nd)
                return 0;
 
-       if (nd->nd_state == NS_READY && nd->nd_ps_desc)
+       if (nd->nd_state == NS_READY)
                return snprintf(buf, PAGE_SIZE, "%s\n", nd->nd_ps_desc);
        return 0;
 }
index 7d7de873870c68d6b0965a5fbc51784963836388..e125b03598d73e5b40815cad70887793162802c5 100644 (file)
@@ -40,6 +40,7 @@
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
 #include <linux/sched.h>
+#include <linux/uaccess.h>
 
 #include "dgrp_common.h"
 
@@ -3172,6 +3173,9 @@ dgrp_tty_init(struct nd_struct *nd)
         */
 
        nd->nd_serial_ttdriver = alloc_tty_driver(CHAN_MAX);
+       if (!nd->nd_serial_ttdriver)
+               return -ENOMEM;
+
        sprintf(nd->nd_serial_name,  "tty_dgrp_%s_", id);
 
        nd->nd_serial_ttdriver->owner = THIS_MODULE;
@@ -3231,6 +3235,9 @@ dgrp_tty_init(struct nd_struct *nd)
        }
 
        nd->nd_callout_ttdriver = alloc_tty_driver(CHAN_MAX);
+       if (!nd->nd_callout_ttdriver)
+               return -ENOMEM;
+
        sprintf(nd->nd_callout_name, "cu_dgrp_%s_",  id);
 
        nd->nd_callout_ttdriver->owner = THIS_MODULE;
@@ -3268,6 +3275,9 @@ dgrp_tty_init(struct nd_struct *nd)
 
 
        nd->nd_xprint_ttdriver = alloc_tty_driver(CHAN_MAX);
+       if (!nd->nd_xprint_ttdriver)
+               return -ENOMEM;
+
        sprintf(nd->nd_xprint_name,  "pr_dgrp_%s_", id);
 
        nd->nd_xprint_ttdriver->owner = THIS_MODULE;
index 413da0d6b9f6821fc74a1ef1782812b75559b8d1..70fe33b57817b83b7f0cc0f6d0175b45a39cc099 100644 (file)
@@ -176,20 +176,13 @@ MODULE_DESCRIPTION("10/100/1000 Base-T Ethernet Driver for the ET1310 by Agere S
 #define PARM_DMA_CACHE_DEF      0
 
 /* RX defines */
-#define USE_FBR0 1
 #define FBR_CHUNKS 32
 #define MAX_DESC_PER_RING_RX         1024
 
 /* number of RFDs - default and min */
-#ifdef USE_FBR0
 #define RFD_LOW_WATER_MARK     40
 #define NIC_DEFAULT_NUM_RFD    1024
 #define NUM_FBRS               2
-#else
-#define RFD_LOW_WATER_MARK     20
-#define NIC_DEFAULT_NUM_RFD    256
-#define NUM_FBRS               1
-#endif
 
 #define NIC_MIN_NUM_RFD                64
 #define NUM_PACKETS_HANDLED    256
@@ -299,11 +292,10 @@ struct fbr_lookup {
        dma_addr_t       ring_physaddr;
        void            *mem_virtaddrs[MAX_DESC_PER_RING_RX / FBR_CHUNKS];
        dma_addr_t       mem_physaddrs[MAX_DESC_PER_RING_RX / FBR_CHUNKS];
-       u64              real_physaddr;
-       u64              offset;
+       dma_addr_t       offset;
        u32              local_full;
        u32              num_entries;
-       u32              buffsize;
+       dma_addr_t       buffsize;
 };
 
 /*
@@ -872,7 +864,7 @@ static void et131x_rx_dma_enable(struct et131x_adapter *adapter)
                csr |= 0x1000;
        else if (adapter->rx_ring.fbr[0]->buffsize == 16384)
                csr |= 0x1800;
-#ifdef USE_FBR0
+
        csr |= 0x0400;          /* FBR0 enable */
        if (adapter->rx_ring.fbr[1]->buffsize == 256)
                csr |= 0x0100;
@@ -880,7 +872,6 @@ static void et131x_rx_dma_enable(struct et131x_adapter *adapter)
                csr |= 0x0200;
        else if (adapter->rx_ring.fbr[1]->buffsize == 1024)
                csr |= 0x0300;
-#endif
        writel(csr, &adapter->regs->rxdma.csr);
 
        csr = readl(&adapter->regs->rxdma.csr);
@@ -1860,25 +1851,17 @@ static void et131x_config_rx_dma_regs(struct et131x_adapter *adapter)
        /* Halt RXDMA to perform the reconfigure.  */
        et131x_rx_dma_disable(adapter);
 
-       /* Load the completion writeback physical address
-        *
-        * NOTE : dma_alloc_coherent(), used above to alloc DMA regions,
-        * ALWAYS returns SAC (32-bit) addresses. If DAC (64-bit) addresses
-        * are ever returned, make sure the high part is retrieved here
-        * before storing the adjusted address.
-        */
-       writel((u32) ((u64)rx_local->rx_status_bus >> 32),
-              &rx_dma->dma_wb_base_hi);
-       writel((u32) rx_local->rx_status_bus, &rx_dma->dma_wb_base_lo);
+       /* Load the completion writeback physical address */
+       writel(upper_32_bits(rx_local->rx_status_bus), &rx_dma->dma_wb_base_hi);
+       writel(lower_32_bits(rx_local->rx_status_bus), &rx_dma->dma_wb_base_lo);
 
        memset(rx_local->rx_status_block, 0, sizeof(struct rx_status_block));
 
        /* Set the address and parameters of the packet status ring into the
         * 1310's registers
         */
-       writel((u32) ((u64)rx_local->ps_ring_physaddr >> 32),
-              &rx_dma->psr_base_hi);
-       writel((u32) rx_local->ps_ring_physaddr, &rx_dma->psr_base_lo);
+       writel(upper_32_bits(rx_local->ps_ring_physaddr), &rx_dma->psr_base_hi);
+       writel(lower_32_bits(rx_local->ps_ring_physaddr), &rx_dma->psr_base_lo);
        writel(rx_local->psr_num_entries - 1, &rx_dma->psr_num_des);
        writel(0, &rx_dma->psr_full_offset);
 
@@ -1903,9 +1886,10 @@ static void et131x_config_rx_dma_regs(struct et131x_adapter *adapter)
        /* Set the address and parameters of Free buffer ring 1 (and 0 if
         * required) into the 1310's registers
         */
-       writel((u32) (rx_local->fbr[0]->real_physaddr >> 32),
+       writel(upper_32_bits(rx_local->fbr[0]->ring_physaddr),
               &rx_dma->fbr1_base_hi);
-       writel((u32) rx_local->fbr[0]->real_physaddr, &rx_dma->fbr1_base_lo);
+       writel(lower_32_bits(rx_local->fbr[0]->ring_physaddr),
+              &rx_dma->fbr1_base_lo);
        writel(rx_local->fbr[0]->num_entries - 1, &rx_dma->fbr1_num_des);
        writel(ET_DMA10_WRAP, &rx_dma->fbr1_full_offset);
 
@@ -1917,7 +1901,6 @@ static void et131x_config_rx_dma_regs(struct et131x_adapter *adapter)
           ((rx_local->fbr[0]->num_entries * LO_MARK_PERCENT_FOR_RX) / 100) - 1,
           &rx_dma->fbr1_min_des);
 
-#ifdef USE_FBR0
        /* Now's the best time to initialize FBR0 contents */
        fbr_entry = (struct fbr_desc *) rx_local->fbr[1]->ring_virtaddr;
        for (entry = 0; entry < rx_local->fbr[1]->num_entries; entry++) {
@@ -1927,9 +1910,10 @@ static void et131x_config_rx_dma_regs(struct et131x_adapter *adapter)
                fbr_entry++;
        }
 
-       writel((u32) (rx_local->fbr[1]->real_physaddr >> 32),
+       writel(upper_32_bits(rx_local->fbr[1]->ring_physaddr),
               &rx_dma->fbr0_base_hi);
-       writel((u32) rx_local->fbr[1]->real_physaddr, &rx_dma->fbr0_base_lo);
+       writel(lower_32_bits(rx_local->fbr[1]->ring_physaddr),
+              &rx_dma->fbr0_base_lo);
        writel(rx_local->fbr[1]->num_entries - 1, &rx_dma->fbr0_num_des);
        writel(ET_DMA10_WRAP, &rx_dma->fbr0_full_offset);
 
@@ -1940,7 +1924,6 @@ static void et131x_config_rx_dma_regs(struct et131x_adapter *adapter)
        writel(
           ((rx_local->fbr[1]->num_entries * LO_MARK_PERCENT_FOR_RX) / 100) - 1,
           &rx_dma->fbr0_min_des);
-#endif
 
        /* Program the number of packets we will receive before generating an
         * interrupt.
@@ -1971,18 +1954,19 @@ static void et131x_config_tx_dma_regs(struct et131x_adapter *adapter)
        struct txdma_regs __iomem *txdma = &adapter->regs->txdma;
 
        /* Load the hardware with the start of the transmit descriptor ring. */
-       writel((u32) ((u64)adapter->tx_ring.tx_desc_ring_pa >> 32),
+       writel(upper_32_bits(adapter->tx_ring.tx_desc_ring_pa),
               &txdma->pr_base_hi);
-       writel((u32) adapter->tx_ring.tx_desc_ring_pa,
+       writel(lower_32_bits(adapter->tx_ring.tx_desc_ring_pa),
               &txdma->pr_base_lo);
 
        /* Initialise the transmit DMA engine */
        writel(NUM_DESC_PER_RING_TX - 1, &txdma->pr_num_des);
 
        /* Load the completion writeback physical address */
-       writel((u32)((u64)adapter->tx_ring.tx_status_pa >> 32),
-                                               &txdma->dma_wb_base_hi);
-       writel((u32)adapter->tx_ring.tx_status_pa, &txdma->dma_wb_base_lo);
+       writel(upper_32_bits(adapter->tx_ring.tx_status_pa),
+              &txdma->dma_wb_base_hi);
+       writel(lower_32_bits(adapter->tx_ring.tx_status_pa),
+              &txdma->dma_wb_base_lo);
 
        *adapter->tx_ring.tx_status = 0;
 
@@ -2274,7 +2258,7 @@ static inline u32 bump_free_buff_ring(u32 *free_buff_ring, u32 limit)
  * @mask: correct mask
  */
 static void et131x_align_allocated_memory(struct et131x_adapter *adapter,
-                                         u64 *phys_addr, u64 *offset,
+                                         dma_addr_t *phys_addr, dma_addr_t *offset,
                                          u64 mask)
 {
        u64 new_addr = *phys_addr & ~mask;
@@ -2311,9 +2295,7 @@ static int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter)
        rx_ring = &adapter->rx_ring;
 
        /* Alloc memory for the lookup table */
-#ifdef USE_FBR0
        rx_ring->fbr[1] = kmalloc(sizeof(struct fbr_lookup), GFP_KERNEL);
-#endif
        rx_ring->fbr[0] = kmalloc(sizeof(struct fbr_lookup), GFP_KERNEL);
 
        /* The first thing we will do is configure the sizes of the buffer
@@ -2335,35 +2317,25 @@ static int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter)
         */
 
        if (adapter->registry_jumbo_packet < 2048) {
-#ifdef USE_FBR0
                rx_ring->fbr[1]->buffsize = 256;
                rx_ring->fbr[1]->num_entries = 512;
-#endif
                rx_ring->fbr[0]->buffsize = 2048;
                rx_ring->fbr[0]->num_entries = 512;
        } else if (adapter->registry_jumbo_packet < 4096) {
-#ifdef USE_FBR0
                rx_ring->fbr[1]->buffsize = 512;
                rx_ring->fbr[1]->num_entries = 1024;
-#endif
                rx_ring->fbr[0]->buffsize = 4096;
                rx_ring->fbr[0]->num_entries = 512;
        } else {
-#ifdef USE_FBR0
                rx_ring->fbr[1]->buffsize = 1024;
                rx_ring->fbr[1]->num_entries = 768;
-#endif
                rx_ring->fbr[0]->buffsize = 16384;
                rx_ring->fbr[0]->num_entries = 128;
        }
 
-#ifdef USE_FBR0
        adapter->rx_ring.psr_num_entries =
                                adapter->rx_ring.fbr[1]->num_entries +
                                adapter->rx_ring.fbr[0]->num_entries;
-#else
-       adapter->rx_ring.psr_num_entries = adapter->rx_ring.fbr[0]->num_entries;
-#endif
 
        /* Allocate an area of memory for Free Buffer Ring 1 */
        bufsize = (sizeof(struct fbr_desc) * rx_ring->fbr[0]->num_entries) +
@@ -2378,25 +2350,15 @@ static int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter)
                return -ENOMEM;
        }
 
-       /* Save physical address
-        *
-        * NOTE: dma_alloc_coherent(), used above to alloc DMA regions,
-        * ALWAYS returns SAC (32-bit) addresses. If DAC (64-bit) addresses
-        * are ever returned, make sure the high part is retrieved here
-        * before storing the adjusted address.
-        */
-       rx_ring->fbr[0]->real_physaddr = rx_ring->fbr[0]->ring_physaddr;
-
        /* Align Free Buffer Ring 1 on a 4K boundary */
        et131x_align_allocated_memory(adapter,
-                                     &rx_ring->fbr[0]->real_physaddr,
+                                     &rx_ring->fbr[0]->ring_physaddr,
                                      &rx_ring->fbr[0]->offset, 0x0FFF);
 
        rx_ring->fbr[0]->ring_virtaddr =
                        (void *)((u8 *) rx_ring->fbr[0]->ring_virtaddr +
                        rx_ring->fbr[0]->offset);
 
-#ifdef USE_FBR0
        /* Allocate an area of memory for Free Buffer Ring 0 */
        bufsize = (sizeof(struct fbr_desc) * rx_ring->fbr[1]->num_entries) +
                                                                        0xfff;
@@ -2410,27 +2372,18 @@ static int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter)
                return -ENOMEM;
        }
 
-       /* Save physical address
-        *
-        * NOTE: dma_alloc_coherent(), used above to alloc DMA regions,
-        * ALWAYS returns SAC (32-bit) addresses. If DAC (64-bit) addresses
-        * are ever returned, make sure the high part is retrieved here before
-        * storing the adjusted address.
-        */
-       rx_ring->fbr[1]->real_physaddr = rx_ring->fbr[1]->ring_physaddr;
-
        /* Align Free Buffer Ring 0 on a 4K boundary */
        et131x_align_allocated_memory(adapter,
-                                     &rx_ring->fbr[1]->real_physaddr,
+                                     &rx_ring->fbr[1]->ring_physaddr,
                                      &rx_ring->fbr[1]->offset, 0x0FFF);
 
        rx_ring->fbr[1]->ring_virtaddr =
                        (void *)((u8 *) rx_ring->fbr[1]->ring_virtaddr +
                        rx_ring->fbr[1]->offset);
-#endif
+
        for (i = 0; i < (rx_ring->fbr[0]->num_entries / FBR_CHUNKS); i++) {
-               u64 fbr1_tmp_physaddr;
-               u64 fbr1_offset;
+               dma_addr_t fbr1_tmp_physaddr;
+               dma_addr_t fbr1_offset;
                u32 fbr1_align;
 
                /* This code allocates an area of memory big enough for N
@@ -2479,24 +2432,23 @@ static int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter)
                         * so the device can access it
                         */
                        rx_ring->fbr[0]->bus_high[index] =
-                           (u32) (fbr1_tmp_physaddr >> 32);
+                                       upper_32_bits(fbr1_tmp_physaddr);
                        rx_ring->fbr[0]->bus_low[index] =
-                           (u32) fbr1_tmp_physaddr;
+                                       lower_32_bits(fbr1_tmp_physaddr);
 
                        fbr1_tmp_physaddr += rx_ring->fbr[0]->buffsize;
 
                        rx_ring->fbr[0]->buffer1[index] =
-                           rx_ring->fbr[0]->virt[index];
+                                       rx_ring->fbr[0]->virt[index];
                        rx_ring->fbr[0]->buffer2[index] =
-                           rx_ring->fbr[0]->virt[index] - 4;
+                                       rx_ring->fbr[0]->virt[index] - 4;
                }
        }
 
-#ifdef USE_FBR0
        /* Same for FBR0 (if in use) */
        for (i = 0; i < (rx_ring->fbr[1]->num_entries / FBR_CHUNKS); i++) {
-               u64 fbr0_tmp_physaddr;
-               u64 fbr0_offset;
+               dma_addr_t fbr0_tmp_physaddr;
+               dma_addr_t fbr0_offset;
 
                fbr_chunksize =
                    ((FBR_CHUNKS + 1) * rx_ring->fbr[1]->buffsize) - 1;
@@ -2527,19 +2479,18 @@ static int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter)
                            (j * rx_ring->fbr[1]->buffsize) + fbr0_offset;
 
                        rx_ring->fbr[1]->bus_high[index] =
-                           (u32) (fbr0_tmp_physaddr >> 32);
+                                       upper_32_bits(fbr0_tmp_physaddr);
                        rx_ring->fbr[1]->bus_low[index] =
-                           (u32) fbr0_tmp_physaddr;
+                                       lower_32_bits(fbr0_tmp_physaddr);
 
                        fbr0_tmp_physaddr += rx_ring->fbr[1]->buffsize;
 
                        rx_ring->fbr[1]->buffer1[index] =
-                           rx_ring->fbr[1]->virt[index];
+                                       rx_ring->fbr[1]->virt[index];
                        rx_ring->fbr[1]->buffer2[index] =
-                           rx_ring->fbr[1]->virt[index] - 4;
+                                       rx_ring->fbr[1]->virt[index] - 4;
                }
        }
-#endif
 
        /* Allocate an area of memory for FIFO of Packet Status ring entries */
        pktstat_ringsize =
@@ -2668,7 +2619,6 @@ static void et131x_rx_dma_memory_free(struct et131x_adapter *adapter)
                rx_ring->fbr[0]->ring_virtaddr = NULL;
        }
 
-#ifdef USE_FBR0
        /* Now the same for Free Buffer Ring 0 */
        if (rx_ring->fbr[1]->ring_virtaddr) {
                /* First the packet memory */
@@ -2703,7 +2653,6 @@ static void et131x_rx_dma_memory_free(struct et131x_adapter *adapter)
 
                rx_ring->fbr[1]->ring_virtaddr = NULL;
        }
-#endif
 
        /* Free Packet Status Ring */
        if (rx_ring->ps_ring_virtaddr) {
@@ -2733,10 +2682,7 @@ static void et131x_rx_dma_memory_free(struct et131x_adapter *adapter)
        }
 
        /* Free the FBR Lookup Table */
-#ifdef USE_FBR0
        kfree(rx_ring->fbr[1]);
-#endif
-
        kfree(rx_ring->fbr[0]);
 
        /* Reset Counters */
@@ -2832,9 +2778,7 @@ static void nic_return_rfd(struct et131x_adapter *adapter, struct rfd *rfd)
         * need to clean up OOB data
         */
        if (
-#ifdef USE_FBR0
            (ring_index == 0 && buff_index < rx_local->fbr[1]->num_entries) ||
-#endif
            (ring_index == 1 && buff_index < rx_local->fbr[0]->num_entries)) {
                spin_lock_irqsave(&adapter->fbr_lock, flags);
 
@@ -2855,9 +2799,7 @@ static void nic_return_rfd(struct et131x_adapter *adapter, struct rfd *rfd)
                                        &rx_local->fbr[0]->local_full,
                                        rx_local->fbr[0]->num_entries - 1),
                                        &rx_dma->fbr1_full_offset);
-               }
-#ifdef USE_FBR0
-               else {
+               } else {
                        struct fbr_desc *next = (struct fbr_desc *)
                                rx_local->fbr[1]->ring_virtaddr +
                                    INDEX10(rx_local->fbr[1]->local_full);
@@ -2875,7 +2817,6 @@ static void nic_return_rfd(struct et131x_adapter *adapter, struct rfd *rfd)
                                        rx_local->fbr[1]->num_entries - 1),
                               &rx_dma->fbr0_full_offset);
                }
-#endif
                spin_unlock_irqrestore(&adapter->fbr_lock, flags);
        } else {
                dev_err(&adapter->pdev->dev,
@@ -2958,20 +2899,11 @@ static struct rfd *nic_rx_pkts(struct et131x_adapter *adapter)
        writel(rx_local->local_psr_full,
               &adapter->regs->rxdma.psr_full_offset);
 
-#ifndef USE_FBR0
-       if (ring_index != 1)
-               return NULL;
-#endif
-
-#ifdef USE_FBR0
        if (ring_index > 1 ||
-               (ring_index == 0 &&
-               buff_index > rx_local->fbr[1]->num_entries - 1) ||
-               (ring_index == 1 &&
-               buff_index > rx_local->fbr[0]->num_entries - 1)) {
-#else
-       if (ring_index != 1 || buff_index > rx_local->fbr[0]->num_entries - 1) {
-#endif
+                       (ring_index == 0 &&
+                       buff_index > rx_local->fbr[1]->num_entries - 1) ||
+                       (ring_index == 1 &&
+                       buff_index > rx_local->fbr[0]->num_entries - 1)) {
                /* Illegal buffer or ring index cannot be used by S/W*/
                dev_err(&adapter->pdev->dev,
                          "NICRxPkts PSR Entry %d indicates "
@@ -3285,6 +3217,7 @@ static int nic_send_packet(struct et131x_adapter *adapter, struct tcb *tcb)
        struct skb_frag_struct *frags = &skb_shinfo(skb)->frags[0];
        unsigned long flags;
        struct phy_device *phydev = adapter->phydev;
+       dma_addr_t dma_addr;
 
        /* Part of the optimizations of this send routine restrict us to
         * sending 24 fragments at a pass.  In practice we should never see
@@ -3313,85 +3246,47 @@ static int nic_send_packet(struct et131x_adapter *adapter, struct tcb *tcb)
                         * This will work until we determine why the hardware
                         * doesn't seem to like large fragments.
                         */
-                       if ((skb->len - skb->data_len) <= 1514) {
-                               desc[frag].addr_hi = 0;
+                       if (skb_headlen(skb) <= 1514) {
                                /* Low 16bits are length, high is vlan and
                                   unused currently so zero */
-                               desc[frag].len_vlan =
-                                       skb->len - skb->data_len;
-
-                               /* NOTE: Here, the dma_addr_t returned from
-                                * dma_map_single() is implicitly cast as a
-                                * u32. Although dma_addr_t can be
-                                * 64-bit, the address returned by
-                                * dma_map_single() is always 32-bit
-                                * addressable (as defined by the pci/dma
-                                * subsystem)
-                                */
-                               desc[frag++].addr_lo =
-                                   dma_map_single(&adapter->pdev->dev,
-                                                  skb->data,
-                                                  skb->len -
-                                                  skb->data_len,
-                                                  DMA_TO_DEVICE);
+                               desc[frag].len_vlan = skb_headlen(skb);
+                               dma_addr = dma_map_single(&adapter->pdev->dev,
+                                                         skb->data,
+                                                         skb_headlen(skb),
+                                                         DMA_TO_DEVICE);
+                               desc[frag].addr_lo = lower_32_bits(dma_addr);
+                               desc[frag].addr_hi = upper_32_bits(dma_addr);
+                               frag++;
                        } else {
-                               desc[frag].addr_hi = 0;
-                               desc[frag].len_vlan =
-                                   (skb->len - skb->data_len) / 2;
-
-                               /* NOTE: Here, the dma_addr_t returned from
-                                * dma_map_single() is implicitly cast as a
-                                * u32. Although dma_addr_t can be
-                                * 64-bit, the address returned by
-                                * dma_map_single() is always 32-bit
-                                * addressable (as defined by the pci/dma
-                                * subsystem)
-                                */
-                               desc[frag++].addr_lo =
-                                   dma_map_single(&adapter->pdev->dev,
-                                                  skb->data,
-                                                  ((skb->len -
-                                                    skb->data_len) / 2),
-                                                  DMA_TO_DEVICE);
-                               desc[frag].addr_hi = 0;
-
-                               desc[frag].len_vlan =
-                                   (skb->len - skb->data_len) / 2;
-
-                               /* NOTE: Here, the dma_addr_t returned from
-                                * dma_map_single() is implicitly cast as a
-                                * u32. Although dma_addr_t can be
-                                * 64-bit, the address returned by
-                                * dma_map_single() is always 32-bit
-                                * addressable (as defined by the pci/dma
-                                * subsystem)
-                                */
-                               desc[frag++].addr_lo =
-                                   dma_map_single(&adapter->pdev->dev,
-                                                  skb->data +
-                                                  ((skb->len -
-                                                    skb->data_len) / 2),
-                                                  ((skb->len -
-                                                    skb->data_len) / 2),
-                                                  DMA_TO_DEVICE);
+                               desc[frag].len_vlan = skb_headlen(skb) / 2;
+                               dma_addr = dma_map_single(&adapter->pdev->dev,
+                                                         skb->data,
+                                                         (skb_headlen(skb) / 2),
+                                                         DMA_TO_DEVICE);
+                               desc[frag].addr_lo = lower_32_bits(dma_addr);
+                               desc[frag].addr_hi = upper_32_bits(dma_addr);
+                               frag++;
+
+                               desc[frag].len_vlan = skb_headlen(skb) / 2;
+                               dma_addr = dma_map_single(&adapter->pdev->dev,
+                                                         skb->data +
+                                                         (skb_headlen(skb) / 2),
+                                                         (skb_headlen(skb) / 2),
+                                                         DMA_TO_DEVICE);
+                               desc[frag].addr_lo = lower_32_bits(dma_addr);
+                               desc[frag].addr_hi = upper_32_bits(dma_addr);
+                               frag++;
                        }
                } else {
-                       desc[frag].addr_hi = 0;
-                       desc[frag].len_vlan =
-                                       frags[i - 1].size;
-
-                       /* NOTE: Here, the dma_addr_t returned from
-                        * dma_map_page() is implicitly cast as a u32.
-                        * Although dma_addr_t can be 64-bit, the address
-                        * returned by dma_map_page() is always 32-bit
-                        * addressable (as defined by the pci/dma subsystem)
-                        */
-                       desc[frag++].addr_lo = skb_frag_dma_map(
-                                                       &adapter->pdev->dev,
-                                                       &frags[i - 1],
-                                                       0,
-                                                       frags[i - 1].size,
-                                                       DMA_TO_DEVICE);
+                       desc[frag].len_vlan = frags[i - 1].size;
+                       dma_addr = skb_frag_dma_map(&adapter->pdev->dev,
+                                                   &frags[i - 1],
+                                                   0,
+                                                   frags[i - 1].size,
+                                                   DMA_TO_DEVICE);
+                       desc[frag].addr_lo = lower_32_bits(dma_addr);
+                       desc[frag].addr_hi = upper_32_bits(dma_addr);
+                       frag++;
                }
        }
 
@@ -3521,7 +3416,7 @@ static int send_packet(struct sk_buff *skb, struct et131x_adapter *adapter)
 
        tcb->skb = skb;
 
-       if (skb->data != NULL && skb->len - skb->data_len >= 6) {
+       if (skb->data != NULL && skb_headlen(skb) >= 6) {
                shbufva = (u16 *) skb->data;
 
                if ((shbufva[0] == 0xffff) &&
@@ -3618,6 +3513,7 @@ static inline void free_send_packet(struct et131x_adapter *adapter,
        unsigned long flags;
        struct tx_desc *desc = NULL;
        struct net_device_stats *stats = &adapter->net_stats;
+       u64  dma_addr;
 
        if (tcb->flags & fMP_DEST_BROAD)
                atomic_inc(&adapter->stats.broadcast_pkts_xmtd);
@@ -3638,8 +3534,11 @@ static inline void free_send_packet(struct et131x_adapter *adapter,
                                    (adapter->tx_ring.tx_desc_ring +
                                                INDEX10(tcb->index_start));
 
+                       dma_addr = desc->addr_lo;
+                       dma_addr |= (u64)desc->addr_hi << 32;
+
                        dma_unmap_single(&adapter->pdev->dev,
-                                        desc->addr_lo,
+                                        dma_addr,
                                         desc->len_vlan, DMA_TO_DEVICE);
 
                        add_10bit(&tcb->index_start, 1);
index 6cb810701a3e87b31733555b97dbae60ea7673f3..dad6fd3e0a7f58cd35ab905c95b9a2954fdae72b 100644 (file)
@@ -170,7 +170,10 @@ static void dump_eth_packet(const char *title, u8 *data, int len)
        if (!(data[0] == 0xff && data[1] == 0xff)) {
                if (protocol == ETH_P_IP) {
                        printk(KERN_DEBUG "     src=%u.%u.%u.%u\n",
-                               NIPQUAD(ih->saddr));
+                               ((unsigned char *)&(ih->saddr))[0],
+                               ((unsigned char *)&(ih->saddr))[1],
+                               ((unsigned char *)&(ih->saddr))[2],
+                               ((unsigned char *)&(ih->saddr))[3]);
                } else if (protocol == ETH_P_IPV6) {
                        #ifdef NIP6
                        printk(KERN_DEBUG "     src=%x:%x:%x:%x:%x:%x:%x:%x\n",
index 65624bca8b3ab354f0cfb312bff1f69229a59357..38feb1acd8e06c845d9da13b4824d0c9dbb99713 100644 (file)
 #include <linux/mmc/card.h>
 #include <linux/mmc/sdio_func.h>
 
+#include <linux/firmware.h>
+
 #include "gdm_sdio.h"
 
 #define TYPE_A_HEADER_SIZE     4
 #define TYPE_A_LOOKAHEAD_SIZE   16
-#define YMEM0_SIZE                     0x8000  /* 32kbytes */
+#define YMEM0_SIZE             0x8000  /* 32kbytes */
 #define DOWNLOAD_SIZE          (YMEM0_SIZE - TYPE_A_HEADER_SIZE)
 
-#define KRN_PATH       "/lib/firmware/gdm72xx/gdmskrn.bin"
-#define RFS_PATH       "/lib/firmware/gdm72xx/gdmsrfs.bin"
+#define FW_DIR                 "gdm72xx/"
+#define FW_KRN                 "gdmskrn.bin"
+#define FW_RFS                 "gdmsrfs.bin"
 
 static u8 *tx_buf;
 
@@ -52,57 +55,57 @@ static int ack_ready(struct sdio_func *func)
        return 0;
 }
 
-static int download_image(struct sdio_func *func, char *img_name)
+static int download_image(struct sdio_func *func, const char *img_name)
 {
-       int ret = 0, len, size, pno;
-       struct file *filp = NULL;
-       struct inode *inode = NULL;
+       int ret = 0, len, pno;
        u8 *buf = tx_buf;
        loff_t pos = 0;
-
-       filp = filp_open(img_name, O_RDONLY | O_LARGEFILE, 0);
-       if (IS_ERR(filp)) {
-               printk(KERN_ERR "Can't find %s.\n", img_name);
-               return -ENOENT;
+       int img_len;
+       const struct firmware *firm;
+
+       ret = request_firmware(&firm, img_name, &func->dev);
+       if (ret < 0) {
+               printk(KERN_ERR
+                      "requesting firmware %s failed with error %d\n",
+                       img_name, ret);
+               return ret;
        }
 
-       inode = filp->f_dentry->d_inode;
-       if (!S_ISREG(inode->i_mode)) {
-               printk(KERN_ERR "Invalid file type: %s\n", img_name);
-               ret = -EINVAL;
-               goto out;
+       buf = kmalloc(DOWNLOAD_SIZE + TYPE_A_HEADER_SIZE, GFP_KERNEL);
+       if (buf == NULL) {
+               printk(KERN_ERR "Error: kmalloc\n");
+               return -ENOMEM;
        }
 
-       size = i_size_read(inode->i_mapping->host);
-       if (size <= 0) {
-               printk(KERN_ERR "Unable to find file size: %s\n", img_name);
-               ret = size;
+       img_len = firm->size;
+
+       if (img_len <= 0) {
+               ret = -1;
                goto out;
        }
 
        pno = 0;
-       while ((len = filp->f_op->read(filp, buf + TYPE_A_HEADER_SIZE,
-                                       DOWNLOAD_SIZE, &pos))) {
-               if (len < 0) {
-                       ret = -1;
-                       goto out;
+       while (img_len > 0) {
+               if (img_len > DOWNLOAD_SIZE) {
+                       len = DOWNLOAD_SIZE;
+                       buf[3] = 0;
+               } else {
+                       len = img_len; /* the last packet */
+                       buf[3] = 2;
                }
 
                buf[0] = len & 0xff;
                buf[1] = (len >> 8) & 0xff;
                buf[2] = (len >> 16) & 0xff;
 
-               if (pos >= size)        /* The last packet */
-                       buf[3] = 2;
-               else
-                       buf[3] = 0;
-
+               memcpy(buf+TYPE_A_HEADER_SIZE, firm->data + pos, len);
                ret = sdio_memcpy_toio(func, 0, buf, len + TYPE_A_HEADER_SIZE);
                if (ret < 0) {
                        printk(KERN_ERR "gdmwm: send image error: "
                                "packet number = %d ret = %d\n", pno, ret);
                        goto out;
                }
+
                if (buf[3] == 2)        /* The last packet */
                        break;
                if (!ack_ready(func)) {
@@ -119,17 +122,21 @@ static int download_image(struct sdio_func *func, char *img_name)
                sdio_writeb(func, 0x01, 0x13, &ret);
                sdio_writeb(func, 0x00, 0x10, &ret);    /* PCRRT */
 
+               img_len -= DOWNLOAD_SIZE;
+               pos += DOWNLOAD_SIZE;
                pno++;
        }
+
 out:
-       filp_close(filp, NULL);
+       kfree(buf);
        return ret;
 }
 
 int sdio_boot(struct sdio_func *func)
 {
-       static mm_segment_t fs;
        int ret;
+       const char *krn_name = FW_DIR FW_KRN;
+       const char *rfs_name = FW_DIR FW_RFS;
 
        tx_buf = kmalloc(YMEM0_SIZE, GFP_KERNEL);
        if (tx_buf == NULL) {
@@ -137,21 +144,17 @@ int sdio_boot(struct sdio_func *func)
                return -ENOMEM;
        }
 
-       fs = get_fs();
-       set_fs(get_ds());
-
-       ret = download_image(func, KRN_PATH);
+       ret = download_image(func, krn_name);
        if (ret)
                goto restore_fs;
        printk(KERN_INFO "GCT: Kernel download success.\n");
 
-       ret = download_image(func, RFS_PATH);
+       ret = download_image(func, rfs_name);
        if (ret)
                goto restore_fs;
        printk(KERN_INFO "GCT: Filesystem download success.\n");
 
 restore_fs:
-       set_fs(fs);
        kfree(tx_buf);
        return ret;
 }
index 8e37d6e04277663d7b7d135a5dd653f050a16785..d2a203a583afe6360dbbd2ea434d16edbf8fbe96 100644 (file)
@@ -310,30 +310,32 @@ static int adis16201_read_raw(struct iio_dev *indio_dev,
        case IIO_CHAN_INFO_SCALE:
                switch (chan->type) {
                case IIO_VOLTAGE:
-                       *val = 0;
-                       if (chan->channel == 0)
-                               *val2 = 1220;
-                       else
-                               *val2 = 610;
+                       if (chan->channel == 0) {
+                               *val = 1;
+                               *val2 = 220000; /* 1.22 mV */
+                       } else {
+                               *val = 0;
+                               *val2 = 610000; /* 0.610 mV */
+                       }
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_TEMP:
-                       *val = 0;
-                       *val2 = -470000;
+                       *val = -470; /* 0.47 C */
+                       *val2 = 0;
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_ACCEL:
                        *val = 0;
-                       *val2 = 462500;
-                       return IIO_VAL_INT_PLUS_MICRO;
+                       *val2 = IIO_G_TO_M_S_2(462400); /* 0.4624 mg */
+                       return IIO_VAL_INT_PLUS_NANO;
                case IIO_INCLI:
                        *val = 0;
-                       *val2 = 100000;
+                       *val2 = 100000; /* 0.1 degree */
                        return IIO_VAL_INT_PLUS_MICRO;
                default:
                        return -EINVAL;
                }
                break;
        case IIO_CHAN_INFO_OFFSET:
-               *val = 25;
+               *val = 25000 / -470 - 1278; /* 25 C = 1278 */
                return IIO_VAL_INT;
        case IIO_CHAN_INFO_CALIBBIAS:
                switch (chan->type) {
@@ -345,7 +347,7 @@ static int adis16201_read_raw(struct iio_dev *indio_dev,
                        break;
                default:
                        return -EINVAL;
-               };
+               }
                mutex_lock(&indio_dev->mlock);
                addr = adis16201_addresses[chan->address][1];
                ret = adis16201_spi_read_reg_16(indio_dev, addr, &val16);
@@ -382,7 +384,7 @@ static int adis16201_write_raw(struct iio_dev *indio_dev,
                        break;
                default:
                        return -EINVAL;
-               };
+               }
                val16 = val & ((1 << bits) - 1);
                addr = adis16201_addresses[chan->address][1];
                return adis16201_spi_write_reg_16(indio_dev, addr, val16);
index 002fa9dfc3756ee5052c9039dd7bb2af48473168..7d7c4d28f6f080675455decad901ccb62f329af1 100644 (file)
@@ -21,8 +21,6 @@
 
 #include "adis16203.h"
 
-#define DRIVER_NAME            "adis16203"
-
 /**
  * adis16203_spi_write_reg_8() - write single byte to a register
  * @indio_dev: iio device associated with child of actual device
@@ -316,25 +314,27 @@ static int adis16203_read_raw(struct iio_dev *indio_dev,
        case IIO_CHAN_INFO_SCALE:
                switch (chan->type) {
                case IIO_VOLTAGE:
-                       *val = 0;
-                       if (chan->channel == 0)
-                               *val2 = 1220;
-                       else
-                               *val2 = 610;
+                       if (chan->channel == 0) {
+                               *val = 1;
+                               *val2 = 220000; /* 1.22 mV */
+                       } else {
+                               *val = 0;
+                               *val2 = 610000; /* 0.61 mV */
+                       }
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_TEMP:
-                       *val = 0;
-                       *val2 = -470000;
+                       *val = -470; /* -0.47 C */
+                       *val2 = 0;
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_INCLI:
                        *val = 0;
-                       *val2 = 25000;
+                       *val2 = 25000; /* 0.025 degree */
                        return IIO_VAL_INT_PLUS_MICRO;
                default:
                        return -EINVAL;
                }
        case IIO_CHAN_INFO_OFFSET:
-               *val = 25;
+               *val = 25000 / -470 - 1278; /* 25 C = 1278 */
                return IIO_VAL_INT;
        case IIO_CHAN_INFO_CALIBBIAS:
                bits = 14;
index 05bdb7c2c8e3f100953c8b0fde872ae367f26c45..9b75a2bc8cbe1fa0fe80eba36ffb4a606714633c 100644 (file)
@@ -24,8 +24,6 @@
 
 #include "adis16204.h"
 
-#define DRIVER_NAME            "adis16204"
-
 /**
  * adis16204_spi_write_reg_8() - write single byte to a register
  * @dev: device associated with child of actual device (iio_dev or iio_trig)
@@ -317,26 +315,28 @@ static int adis16204_read_raw(struct iio_dev *indio_dev,
        case IIO_CHAN_INFO_SCALE:
                switch (chan->type) {
                case IIO_VOLTAGE:
-                       *val = 0;
-                       if (chan->channel == 0)
-                               *val2 = 1220;
-                       else
-                               *val2 = 610;
+                       if (chan->channel == 0) {
+                               *val = 1;
+                               *val2 = 220000; /* 1.22 mV */
+                       } else {
+                               *val = 0;
+                               *val2 = 610000; /* 0.61 mV */
+                       }
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_TEMP:
-                       *val = 0;
-                       *val2 = -470000;
+                       *val = -470; /* 0.47 C */
+                       *val2 = 0;
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_ACCEL:
                        *val = 0;
                        switch (chan->channel2) {
                        case IIO_MOD_X:
                        case IIO_MOD_ROOT_SUM_SQUARED_X_Y:
-                               *val2 = 17125;
+                               *val2 = IIO_G_TO_M_S_2(17125); /* 17.125 mg */
                                break;
                        case IIO_MOD_Y:
                        case IIO_MOD_Z:
-                               *val2 = 8407;
+                               *val2 = IIO_G_TO_M_S_2(8407); /* 8.407 mg */
                                break;
                        }
                        return IIO_VAL_INT_PLUS_MICRO;
@@ -345,7 +345,7 @@ static int adis16204_read_raw(struct iio_dev *indio_dev,
                }
                break;
        case IIO_CHAN_INFO_OFFSET:
-               *val = 25;
+               *val = 25000 / -470 - 1278; /* 25 C = 1278 */
                return IIO_VAL_INT;
        case IIO_CHAN_INFO_CALIBBIAS:
        case IIO_CHAN_INFO_PEAK:
@@ -389,7 +389,7 @@ static int adis16204_write_raw(struct iio_dev *indio_dev,
                        break;
                default:
                        return -EINVAL;
-               };
+               }
                val16 = val & ((1 << bits) - 1);
                addr = adis16204_addresses[chan->address][1];
                return adis16204_spi_write_reg_16(indio_dev, addr, val16);
index b7333bfe0b2f1312a51548a731e73f2f41bd36ba..b7a0d5c2bbd40d764a13d56c86b0c7e78c43f88a 100644 (file)
@@ -22,8 +22,6 @@
 
 #include "adis16209.h"
 
-#define DRIVER_NAME            "adis16209"
-
 /**
  * adis16209_spi_write_reg_8() - write single byte to a register
  * @indio_dev: iio device associated with actual device
@@ -295,7 +293,7 @@ static int adis16209_write_raw(struct iio_dev *indio_dev,
                        break;
                default:
                        return -EINVAL;
-               };
+               }
                val16 = val & ((1 << bits) - 1);
                addr = adis16209_addresses[chan->address][1];
                return adis16209_spi_write_reg_16(indio_dev, addr, val16);
@@ -343,28 +341,29 @@ static int adis16209_read_raw(struct iio_dev *indio_dev,
                case IIO_VOLTAGE:
                        *val = 0;
                        if (chan->channel == 0)
-                               *val2 = 305180;
+                               *val2 = 305180; /* 0.30518 mV */
                        else
-                               *val2 = 610500;
+                               *val2 = 610500; /* 0.6105 mV */
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_TEMP:
-                       *val = 0;
-                       *val2 = -470000;
+                       *val = -470; /* -0.47 C */
+                       *val2 = 0;
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_ACCEL:
                        *val = 0;
-                       *val2 = 2394;
-                       return IIO_VAL_INT_PLUS_MICRO;
+                       *val2 = IIO_G_TO_M_S_2(244140); /* 0.244140 mg */
+                       return IIO_VAL_INT_PLUS_NANO;
                case IIO_INCLI:
+               case IIO_ROT:
                        *val = 0;
-                       *val2 = 436;
+                       *val2 = 25000; /* 0.025 degree */
                        return IIO_VAL_INT_PLUS_MICRO;
                default:
                        return -EINVAL;
                }
                break;
        case IIO_CHAN_INFO_OFFSET:
-               *val = 25;
+               *val = 25000 / -470 - 0x4FE; /* 25 C = 0x4FE */
                return IIO_VAL_INT;
        case IIO_CHAN_INFO_CALIBBIAS:
                switch (chan->type) {
@@ -373,7 +372,7 @@ static int adis16209_read_raw(struct iio_dev *indio_dev,
                        break;
                default:
                        return -EINVAL;
-               };
+               }
                mutex_lock(&indio_dev->mlock);
                addr = adis16209_addresses[chan->address][1];
                ret = adis16209_spi_read_reg_16(indio_dev, addr, &val16);
@@ -491,6 +490,7 @@ static const struct iio_chan_spec adis16209_channels[] = {
                .modified = 1,
                .channel2 = IIO_MOD_X,
                .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
+               IIO_CHAN_INFO_SCALE_SHARED_BIT,
                .address = rot,
                .scan_index = ADIS16209_SCAN_ROT,
                .scan_type = {
index 2ad93dcaf40dd958dc0cb5caca627a32d67e374a..112280346eb64d0424c7c095f08c94cc9facd32f 100644 (file)
@@ -7,15 +7,6 @@
 #include <linux/iio/trigger.h>
 #include "adis16209.h"
 
-/**
- * adis16209_data_rdy_trig_poll() the event handler for the data rdy trig
- **/
-static irqreturn_t adis16209_data_rdy_trig_poll(int irq, void *trig)
-{
-       iio_trigger_poll(trig, iio_get_time_ns());
-       return IRQ_HANDLED;
-}
-
 /**
  * adis16209_data_rdy_trigger_set_state() set datardy interrupt state
  **/
@@ -45,7 +36,7 @@ int adis16209_probe_trigger(struct iio_dev *indio_dev)
        }
 
        ret = request_irq(st->us->irq,
-                         adis16209_data_rdy_trig_poll,
+                         iio_trigger_generic_data_rdy_poll,
                          IRQF_TRIGGER_RISING,
                          "adis16209",
                          st->trig);
index c755089c711715802ce6e90818a35bae41941acb..22807ac8e8f88892fbe2a196e3b7af4f8aaabc3e 100644 (file)
@@ -20,8 +20,6 @@
 
 #include "adis16220.h"
 
-#define DRIVER_NAME            "adis16220"
-
 /**
  * adis16220_spi_write_reg_8() - write single byte to a register
  * @indio_dev: iio device associated with child of actual device
@@ -486,7 +484,7 @@ static int adis16220_read_raw(struct iio_dev *indio_dev,
                break;
        case IIO_CHAN_INFO_OFFSET:
                if (chan->type == IIO_TEMP) {
-                       *val = 25;
+                       *val = 25000 / -470 - 1278; /* 25 C = 1278 */
                        return IIO_VAL_INT;
                }
                addrind = 1;
@@ -495,19 +493,22 @@ static int adis16220_read_raw(struct iio_dev *indio_dev,
                addrind = 2;
                break;
        case IIO_CHAN_INFO_SCALE:
-               *val = 0;
                switch (chan->type) {
                case IIO_TEMP:
-                       *val2 = -470000;
+                       *val = -470; /* -0.47 C */
+                       *val2 = 0;
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_ACCEL:
-                       *val2 = 1887042;
+                       *val2 = IIO_G_TO_M_S_2(19073); /* 19.073 g */
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_VOLTAGE:
-                       if (chan->channel == 0)
-                               *val2 = 0012221;
-                       else /* Should really be dependent on VDD */
-                               *val2 = 305;
+                       if (chan->channel == 0) {
+                               *val = 1;
+                               *val2 = 220700; /* 1.2207 mV */
+                       } else {
+                               /* Should really be dependent on VDD */
+                               *val2 = 305180; /* 305.18 uV */
+                       }
                        return IIO_VAL_INT_PLUS_MICRO;
                default:
                        return -EINVAL;
index 0fc26a49d681abbb4ece13156771e429db9aee2f..289f81963c82d00a8a5ca223e2b71465082d8a91 100644 (file)
@@ -25,8 +25,6 @@
 
 #include "adis16240.h"
 
-#define DRIVER_NAME            "adis16240"
-
 static int adis16240_check_status(struct iio_dev *indio_dev);
 
 /**
@@ -373,30 +371,31 @@ static int adis16240_read_raw(struct iio_dev *indio_dev,
        case IIO_CHAN_INFO_SCALE:
                switch (chan->type) {
                case IIO_VOLTAGE:
-                       *val = 0;
-                       if (chan->channel == 0)
-                               *val2 = 4880;
-                       else
+                       if (chan->channel == 0) {
+                               *val = 4;
+                               *val2 = 880000; /* 4.88 mV */
+                               return IIO_VAL_INT_PLUS_MICRO;
+                       } else {
                                return -EINVAL;
-                       return IIO_VAL_INT_PLUS_MICRO;
+                       }
                case IIO_TEMP:
-                       *val = 0;
-                       *val2 = 244000;
+                       *val = 244; /* 0.244 C */
+                       *val2 = 0;
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_ACCEL:
                        *val = 0;
-                       *val2 = 504062;
+                       *val2 = IIO_G_TO_M_S_2(51400); /* 51.4 mg */
                        return IIO_VAL_INT_PLUS_MICRO;
                default:
                        return -EINVAL;
                }
                break;
        case IIO_CHAN_INFO_PEAK_SCALE:
-               *val = 6;
-               *val2 = 629295;
+               *val = 0;
+               *val2 = IIO_G_TO_M_S_2(51400); /* 51.4 mg */
                return IIO_VAL_INT_PLUS_MICRO;
        case IIO_CHAN_INFO_OFFSET:
-               *val = 25;
+               *val = 25000 / 244 - 0x133; /* 25 C = 0x133 */
                return IIO_VAL_INT;
        case IIO_CHAN_INFO_CALIBBIAS:
                bits = 10;
index fa90a22b143e7c23121e8ec1afea564ae77e8cfa..f3caf09dcb89913dfc6d58ffef9983288b91a193 100644 (file)
@@ -7,15 +7,6 @@
 #include <linux/iio/trigger.h>
 #include "adis16240.h"
 
-/**
- * adis16240_data_rdy_trig_poll() the event handler for the data rdy trig
- **/
-static irqreturn_t adis16240_data_rdy_trig_poll(int irq, void *trig)
-{
-       iio_trigger_poll(trig, iio_get_time_ns());
-       return IRQ_HANDLED;
-}
-
 /**
  * adis16240_data_rdy_trigger_set_state() set datardy interrupt state
  **/
@@ -45,7 +36,7 @@ int adis16240_probe_trigger(struct iio_dev *indio_dev)
        }
 
        ret = request_irq(st->us->irq,
-                         adis16240_data_rdy_trig_poll,
+                         iio_trigger_generic_data_rdy_poll,
                          IRQF_TRIGGER_RISING,
                          "adis16240",
                          st->trig);
index fdd5fbded660ead0d4b9990774c7f840ef32eafd..e8e6e3fbcec0cb392ea4b882c34a43bbd6031619 100644 (file)
@@ -171,7 +171,7 @@ static int kxsd9_read_raw(struct iio_dev *indio_dev,
                *val2 = kxsd9_micro_scales[ret & KXSD9_FS_MASK];
                ret = IIO_VAL_INT_PLUS_MICRO;
                break;
-       };
+       }
 
 error_ret:
        return ret;
index f9bcd41f7188854a94bbb4c7ff37dab68bf70c89..2bac7221837c0ceefeaaa01127d2af9defcd5e6f 100644 (file)
@@ -158,6 +158,7 @@ struct lis3l02dq_state {
        struct spi_device               *us;
        struct iio_trigger              *trig;
        struct mutex                    buf_lock;
+       int                             gpio;
        bool                            trigger_on;
 
        u8      tx[LIS3L02DQ_MAX_RX] ____cacheline_aligned;
index 21b0469f8bc27f03f394ad726bc1a20e66d32244..d13c7e98978db2866433f9956df41fc19563daa0 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/gpio.h>
+#include <linux/of_gpio.h>
 #include <linux/mutex.h>
 #include <linux/device.h>
 #include <linux/kernel.h>
@@ -690,6 +691,7 @@ static int __devinit lis3l02dq_probe(struct spi_device *spi)
        spi_set_drvdata(spi, indio_dev);
 
        st->us = spi;
+       st->gpio = of_get_gpio(spi->dev.of_node, 0);
        mutex_init(&st->buf_lock);
        indio_dev->name = spi->dev.driver->name;
        indio_dev->dev.parent = &spi->dev;
@@ -711,7 +713,7 @@ static int __devinit lis3l02dq_probe(struct spi_device *spi)
                goto error_unreg_buffer_funcs;
        }
 
-       if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)) > 0) {
+       if (spi->irq) {
                ret = request_threaded_irq(st->us->irq,
                                           &lis3l02dq_th,
                                           &lis3l02dq_event_handler,
@@ -738,10 +740,10 @@ static int __devinit lis3l02dq_probe(struct spi_device *spi)
        return 0;
 
 error_remove_trigger:
-       if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)))
+       if (spi->irq)
                lis3l02dq_remove_trigger(indio_dev);
 error_free_interrupt:
-       if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)) > 0)
+       if (spi->irq)
                free_irq(st->us->irq, indio_dev);
 error_uninitialize_buffer:
        iio_buffer_unregister(indio_dev);
@@ -790,7 +792,7 @@ static int __devexit lis3l02dq_remove(struct spi_device *spi)
        lis3l02dq_disable_all_events(indio_dev);
        lis3l02dq_stop_device(indio_dev);
 
-       if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)) > 0)
+       if (spi->irq)
                free_irq(st->us->irq, indio_dev);
 
        lis3l02dq_remove_trigger(indio_dev);
index fa4190d9624753c51cc639175ede157862ff58c5..246352716537cf363cf456fd6dd802aa03e779b4 100644 (file)
@@ -237,7 +237,7 @@ static int lis3l02dq_data_rdy_trigger_set_state(struct iio_trigger *trig,
        u8 t;
 
        __lis3l02dq_write_data_ready_config(indio_dev, state);
-       if (state == false) {
+       if (!state) {
                /*
                 * A possible quirk with the handler is currently worked around
                 * by ensuring outstanding read events are cleared.
@@ -263,7 +263,7 @@ static int lis3l02dq_trig_try_reen(struct iio_trigger *trig)
        /* If gpio still high (or high again)
         * In theory possible we will need to do this several times */
        for (i = 0; i < 5; i++)
-               if (gpio_get_value(irq_to_gpio(st->us->irq)))
+               if (gpio_get_value(st->gpio))
                        lis3l02dq_read_all(indio_dev, NULL);
                else
                        break;
index 7e9bd0001cc7f9d1c239faf578e8b557d7c2cb01..10c59622671f3702fc7bd1a284a8968c3ac886de 100644 (file)
@@ -150,7 +150,7 @@ static int __devinit lpc32xx_adc_probe(struct platform_device *pdev)
 
        info = iio_priv(iodev);
 
-       info->adc_base = ioremap(res->start, res->end - res->start + 1);
+       info->adc_base = ioremap(res->start, resource_size(res));
        if (!info->adc_base) {
                dev_err(&pdev->dev, "failed mapping memory\n");
                retval = -EBUSY;
index ca7c1fa88e717b4c809a5fa50d00ed9246e8cef2..df5bba284b73055d3b821e7d86eade25749db86b 100644 (file)
@@ -351,7 +351,7 @@ static int mxs_lradc_buffer_preenable(struct iio_dev *iio)
                writel(chan_value, lradc->base + LRADC_CH(ofs));
                enable |= 1 << ofs;
                ofs++;
-       };
+       }
 
        writel(LRADC_DELAY_TRIGGER_LRADCS_MASK | LRADC_DELAY_KICK,
                lradc->base + LRADC_DELAY(0) + STMP_OFFSET_REG_CLR);
index 6a4041417d4e26e89aa30f7cd26c0d70c4beac88..c72a6c074b466de8a23232f9aeca8ea930efb35f 100644 (file)
@@ -156,7 +156,7 @@ static int ad7150_read_event_config(struct iio_dev *indio_dev, u64 event_code)
                        return !adaptive && (threshtype == 0x1);
                else
                        return !adaptive && (threshtype == 0x0);
-       };
+       }
        return -EINVAL;
 }
 
@@ -194,7 +194,7 @@ static int ad7150_write_event_params(struct iio_dev *indio_dev, u64 event_code)
                break;
        default:
                return -EINVAL;
-       };
+       }
        ret = i2c_smbus_write_byte_data(chip->client,
                                        ad7150_addresses[chan][4],
                                        sens);
@@ -257,7 +257,7 @@ static int ad7150_write_event_config(struct iio_dev *indio_dev,
        default:
                ret = -EINVAL;
                goto error_ret;
-       };
+       }
 
        cfg |= (!adaptive << 7) | (thresh_type << 5);
 
@@ -327,7 +327,7 @@ static int ad7150_write_event_value(struct iio_dev *indio_dev,
        default:
                ret = -EINVAL;
                goto error_ret;
-       };
+       }
 
        /* write back if active */
        ret = ad7150_write_event_params(indio_dev, event_code);
@@ -360,7 +360,7 @@ static ssize_t ad7150_show_timeout(struct device *dev,
                break;
        default:
                return -EINVAL;
-       };
+       }
 
        return sprintf(buf, "%d\n", value);
 }
@@ -394,7 +394,7 @@ static ssize_t ad7150_store_timeout(struct device *dev,
        default:
                ret = -EINVAL;
                goto error_ret;
-       };
+       }
 
        ret = ad7150_write_event_params(indio_dev, this_attr->address);
 error_ret:
index 98c3015116aa3d7801460804d1708866991f7bd5..288b33e8dadde7db5a11f062ade8ebe7407d994b 100644 (file)
@@ -405,7 +405,7 @@ static int ad7152_read_raw(struct iio_dev *indio_dev,
                break;
        default:
                ret = -EINVAL;
-       };
+       }
 out:
        mutex_unlock(&indio_dev->mlock);
        return ret;
index 754e11e871931e2481bf5e9cc40ec4894b9fe031..e6c11d934adac194f102a4701adb439a2cba7a62 100644 (file)
@@ -677,7 +677,7 @@ static int ad7746_read_raw(struct iio_dev *indio_dev,
                break;
        default:
                ret = -EINVAL;
-       };
+       }
 out:
        mutex_unlock(&indio_dev->mlock);
        return ret;
index 9571c03aa4cc976346d17bcb27f41d4dc4319060..e822460502be4b665674360f62a277e67f05febd 100644 (file)
@@ -24,8 +24,6 @@
 
 #include "adis16260.h"
 
-#define DRIVER_NAME            "adis16260"
-
 static int adis16260_check_status(struct iio_dev *indio_dev);
 
 /**
@@ -498,28 +496,33 @@ static int adis16260_read_raw(struct iio_dev *indio_dev,
                switch (chan->type) {
                case IIO_ANGL_VEL:
                        *val = 0;
-                       if (spi_get_device_id(st->us)->driver_data)
-                               *val2 = 320;
-                       else
-                               *val2 = 1278;
+                       if (spi_get_device_id(st->us)->driver_data) {
+                               /* 0.01832 degree / sec */
+                               *val2 = IIO_DEGREE_TO_RAD(18320);
+                       } else {
+                               /* 0.07326 degree / sec */
+                               *val2 = IIO_DEGREE_TO_RAD(73260);
+                       }
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_VOLTAGE:
-                       *val = 0;
-                       if (chan->channel == 0)
-                               *val2 = 18315;
-                       else
-                               *val2 = 610500;
+                       if (chan->channel == 0) {
+                               *val = 1;
+                               *val2 = 831500; /* 1.8315 mV */
+                       } else {
+                               *val = 0;
+                               *val2 = 610500; /* 610.5 uV */
+                       }
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_TEMP:
-                       *val = 0;
-                       *val2 = 145300;
+                       *val = 145;
+                       *val2 = 300000; /* 0.1453 C */
                        return IIO_VAL_INT_PLUS_MICRO;
                default:
                        return -EINVAL;
                }
                break;
        case IIO_CHAN_INFO_OFFSET:
-               *val = 25;
+               *val = 250000 / 1453; /* 25 C = 0x00 */
                return IIO_VAL_INT;
        case IIO_CHAN_INFO_CALIBBIAS:
                switch (chan->type) {
@@ -528,7 +531,7 @@ static int adis16260_read_raw(struct iio_dev *indio_dev,
                        break;
                default:
                        return -EINVAL;
-               };
+               }
                mutex_lock(&indio_dev->mlock);
                addr = adis16260_addresses[chan->address][1];
                ret = adis16260_spi_read_reg_16(indio_dev, addr, &val16);
@@ -548,7 +551,7 @@ static int adis16260_read_raw(struct iio_dev *indio_dev,
                        break;
                default:
                        return -EINVAL;
-               };
+               }
                mutex_lock(&indio_dev->mlock);
                addr = adis16260_addresses[chan->address][2];
                ret = adis16260_spi_read_reg_16(indio_dev, addr, &val16);
index 74e24e8aa8768d40cbdfc8f93810056e23548dec..132d278c5010b3e0945d543140a9fb12f44dfefa 100644 (file)
@@ -108,7 +108,7 @@ int iio_dummy_evgen_get_irq(void)
 
        mutex_lock(&iio_evgen->lock);
        for (i = 0; i < IIO_EVENTGEN_NO; i++)
-               if (iio_evgen->inuse[i] == false) {
+               if (!iio_evgen->inuse[i]) {
                        ret = iio_evgen->base + i;
                        iio_evgen->inuse[i] = true;
                        break;
index d59d7ac856a9db8bb3c0bff7ccf1811d97917539..77c601da184603c6391cecc1b10d887cb38ffb70 100644 (file)
@@ -139,6 +139,8 @@ struct adis16400_chip_info {
        const long flags;
        unsigned int gyro_scale_micro;
        unsigned int accel_scale_micro;
+       int temp_scale_nano;
+       int temp_offset;
        unsigned long default_scan_mask;
 };
 
index b302c9ba271260e2f31476e51420af68fbbd28db..baec6a1f23a0bb7d17e5c16ab3d93a1cb46eaf85 100644 (file)
@@ -553,10 +553,13 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_VOLTAGE:
                        *val = 0;
-                       if (chan->channel == 0)
-                               *val2 = 2418;
-                       else
-                               *val2 = 806;
+                       if (chan->channel == 0) {
+                               *val = 2;
+                               *val2 = 418000; /* 2.418 mV */
+                       } else {
+                               *val = 0;
+                               *val2 = 805800; /* 805.8 uV */
+                       }
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_ACCEL:
                        *val = 0;
@@ -564,11 +567,11 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_MAGN:
                        *val = 0;
-                       *val2 = 500;
+                       *val2 = 500; /* 0.5 mgauss */
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_TEMP:
-                       *val = 0;
-                       *val2 = 140000;
+                       *val = st->variant->temp_scale_nano / 1000000;
+                       *val2 = (st->variant->temp_scale_nano % 1000000);
                        return IIO_VAL_INT_PLUS_MICRO;
                default:
                        return -EINVAL;
@@ -586,9 +589,8 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
                return IIO_VAL_INT;
        case IIO_CHAN_INFO_OFFSET:
                /* currently only temperature */
-               *val = 198;
-               *val2 = 160000;
-               return IIO_VAL_INT_PLUS_MICRO;
+               *val = st->variant->temp_offset;
+               return IIO_VAL_INT;
        case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
                mutex_lock(&indio_dev->mlock);
                /* Need both the number of taps and the sampling frequency */
@@ -622,7 +624,7 @@ static const struct iio_chan_spec adis16400_channels[] = {
                IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
                .address = in_supply,
                .scan_index = ADIS16400_SCAN_SUPPLY,
-               .scan_type = IIO_ST('u', 14, 16, 0)
+               .scan_type = IIO_ST('u', 14, 16, 0),
        }, {
                .type = IIO_ANGL_VEL,
                .modified = 1,
@@ -633,7 +635,7 @@ static const struct iio_chan_spec adis16400_channels[] = {
                IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
                .address = gyro_x,
                .scan_index = ADIS16400_SCAN_GYRO_X,
-               .scan_type = IIO_ST('s', 14, 16, 0)
+               .scan_type = IIO_ST('s', 14, 16, 0),
        }, {
                .type = IIO_ANGL_VEL,
                .modified = 1,
@@ -752,7 +754,7 @@ static const struct iio_chan_spec adis16350_channels[] = {
                IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
                .address = in_supply,
                .scan_index = ADIS16400_SCAN_SUPPLY,
-               .scan_type = IIO_ST('u', 12, 16, 0)
+               .scan_type = IIO_ST('u', 12, 16, 0),
        }, {
                .type = IIO_ANGL_VEL,
                .modified = 1,
@@ -763,7 +765,7 @@ static const struct iio_chan_spec adis16350_channels[] = {
                IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
                .address = gyro_x,
                .scan_index = ADIS16400_SCAN_GYRO_X,
-               .scan_type = IIO_ST('s', 14, 16, 0)
+               .scan_type = IIO_ST('s', 14, 16, 0),
        }, {
                .type = IIO_ANGL_VEL,
                .modified = 1,
@@ -877,7 +879,7 @@ static const struct iio_chan_spec adis16300_channels[] = {
                IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
                .address = in_supply,
                .scan_index = ADIS16400_SCAN_SUPPLY,
-               .scan_type = IIO_ST('u', 12, 16, 0)
+               .scan_type = IIO_ST('u', 12, 16, 0),
        }, {
                .type = IIO_ANGL_VEL,
                .modified = 1,
@@ -1035,7 +1037,7 @@ static const struct iio_chan_spec adis16334_channels[] = {
                .indexed = 1,
                .channel = 0,
                .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-               IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
+               IIO_CHAN_INFO_OFFSET_SEPARATE_BIT |
                IIO_CHAN_INFO_SCALE_SHARED_BIT,
                .address = temp0,
                .scan_index = ADIS16400_SCAN_TEMP,
@@ -1058,8 +1060,10 @@ static struct adis16400_chip_info adis16400_chips[] = {
        [ADIS16300] = {
                .channels = adis16300_channels,
                .num_channels = ARRAY_SIZE(adis16300_channels),
-               .gyro_scale_micro = 873,
+               .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
                .accel_scale_micro = 5884,
+               .temp_scale_nano = 140000000, /* 0.14 C */
+               .temp_offset = 25000000 / 140000, /* 25 C = 0x00 */
                .default_scan_mask = (1 << ADIS16400_SCAN_SUPPLY) |
                (1 << ADIS16400_SCAN_GYRO_X) | (1 << ADIS16400_SCAN_ACC_X) |
                (1 << ADIS16400_SCAN_ACC_Y) | (1 << ADIS16400_SCAN_ACC_Z) |
@@ -1070,8 +1074,10 @@ static struct adis16400_chip_info adis16400_chips[] = {
        [ADIS16334] = {
                .channels = adis16334_channels,
                .num_channels = ARRAY_SIZE(adis16334_channels),
-               .gyro_scale_micro = 873,
-               .accel_scale_micro = 981,
+               .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
+               .accel_scale_micro = IIO_G_TO_M_S_2(1000), /* 1 mg */
+               .temp_scale_nano = 67850000, /* 0.06785 C */
+               .temp_offset = 25000000 / 67850, /* 25 C = 0x00 */
                .default_scan_mask = (1 << ADIS16400_SCAN_GYRO_X) |
                (1 << ADIS16400_SCAN_GYRO_Y) | (1 << ADIS16400_SCAN_GYRO_Z) |
                (1 << ADIS16400_SCAN_ACC_X) | (1 << ADIS16400_SCAN_ACC_Y) |
@@ -1080,8 +1086,10 @@ static struct adis16400_chip_info adis16400_chips[] = {
        [ADIS16350] = {
                .channels = adis16350_channels,
                .num_channels = ARRAY_SIZE(adis16350_channels),
-               .gyro_scale_micro = 872664,
-               .accel_scale_micro = 24732,
+               .gyro_scale_micro = IIO_DEGREE_TO_RAD(73260), /* 0.07326 deg/s */
+               .accel_scale_micro = IIO_G_TO_M_S_2(2522), /* 0.002522 g */
+               .temp_scale_nano = 145300000, /* 0.1453 C */
+               .temp_offset = 25000000 / 145300, /* 25 C = 0x00 */
                .default_scan_mask = 0x7FF,
                .flags = ADIS16400_NO_BURST,
        },
@@ -1090,8 +1098,10 @@ static struct adis16400_chip_info adis16400_chips[] = {
                .num_channels = ARRAY_SIZE(adis16350_channels),
                .flags = ADIS16400_HAS_PROD_ID,
                .product_id = 0x3FE8,
-               .gyro_scale_micro = 1279,
-               .accel_scale_micro = 24732,
+               .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
+               .accel_scale_micro = IIO_G_TO_M_S_2(3333), /* 3.333 mg */
+               .temp_scale_nano = 136000000, /* 0.136 C */
+               .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */
                .default_scan_mask = 0x7FF,
        },
        [ADIS16362] = {
@@ -1099,8 +1109,10 @@ static struct adis16400_chip_info adis16400_chips[] = {
                .num_channels = ARRAY_SIZE(adis16350_channels),
                .flags = ADIS16400_HAS_PROD_ID,
                .product_id = 0x3FEA,
-               .gyro_scale_micro = 1279,
-               .accel_scale_micro = 24732,
+               .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
+               .accel_scale_micro = IIO_G_TO_M_S_2(333), /* 0.333 mg */
+               .temp_scale_nano = 136000000, /* 0.136 C */
+               .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */
                .default_scan_mask = 0x7FF,
        },
        [ADIS16364] = {
@@ -1108,8 +1120,10 @@ static struct adis16400_chip_info adis16400_chips[] = {
                .num_channels = ARRAY_SIZE(adis16350_channels),
                .flags = ADIS16400_HAS_PROD_ID,
                .product_id = 0x3FEC,
-               .gyro_scale_micro = 1279,
-               .accel_scale_micro = 24732,
+               .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
+               .accel_scale_micro = IIO_G_TO_M_S_2(1000), /* 1 mg */
+               .temp_scale_nano = 136000000, /* 0.136 C */
+               .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */
                .default_scan_mask = 0x7FF,
        },
        [ADIS16365] = {
@@ -1117,8 +1131,10 @@ static struct adis16400_chip_info adis16400_chips[] = {
                .num_channels = ARRAY_SIZE(adis16350_channels),
                .flags = ADIS16400_HAS_PROD_ID,
                .product_id = 0x3FED,
-               .gyro_scale_micro = 1279,
-               .accel_scale_micro = 24732,
+               .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
+               .accel_scale_micro = IIO_G_TO_M_S_2(1000), /* 1 mg */
+               .temp_scale_nano = 136000000, /* 0.136 C */
+               .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */
                .default_scan_mask = 0x7FF,
        },
        [ADIS16400] = {
@@ -1126,9 +1142,11 @@ static struct adis16400_chip_info adis16400_chips[] = {
                .num_channels = ARRAY_SIZE(adis16400_channels),
                .flags = ADIS16400_HAS_PROD_ID,
                .product_id = 0x4015,
-               .gyro_scale_micro = 873,
-               .accel_scale_micro = 32656,
+               .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
+               .accel_scale_micro = IIO_G_TO_M_S_2(3333), /* 3.333 mg */
                .default_scan_mask = 0xFFF,
+               .temp_scale_nano = 140000000, /* 0.14 C */
+               .temp_offset = 25000000 / 140000, /* 25 C = 0x00 */
        }
 };
 
index 10e095486e549af7b637535d86ab79228a1322b9..f7edf69a3bc4af28d8fb7dfb27119b924585061a 100644 (file)
@@ -555,7 +555,7 @@ static int hmc5843_read_raw(struct iio_dev *indio_dev,
                *val = 0;
                *val2 = data->variant->regval_to_nanoscale[data->range];
                return IIO_VAL_INT_PLUS_NANO;
-       };
+       }
        return -EINVAL;
 }
 
index 3f059d3d9392c9611693d0943cc152b890940061..a9d93cc1c414dc0826f348208aae0ef285b8ccb0 100644 (file)
@@ -55,8 +55,6 @@
 #define ADE7753_SPI_BURST      (u32)(1000 * 1000)
 #define ADE7753_SPI_FAST       (u32)(2000 * 1000)
 
-#define DRIVER_NAME            "ade7753"
-
 /**
  * struct ade7753_state - device instance specific data
  * @us:                        actual spi_device
index 6121125520f6bbcadf66d0a8e82ef07a40e51e24..e42ffc387a1468ecb6a375d0620c0b1f4bbb1624 100644 (file)
@@ -73,8 +73,6 @@
 #define ADE7754_SPI_BURST      (u32)(1000 * 1000)
 #define ADE7754_SPI_FAST       (u32)(2000 * 1000)
 
-#define DRIVER_NAME            "ade7754"
-
 /**
  * struct ade7754_state - device instance specific data
  * @us:                        actual spi_device
index 1e11ad5ae5a462c47b13bfb8739bd5d05605297a..07318203a836e86155760c7ec16c595094b37489 100644 (file)
 #define AD7758_APP_PWR         4
 #define AD7758_WT(p, w)                (((w) << 2) | (p))
 
-#define DRIVER_NAME            "ade7758"
-
-
 /**
  * struct ade7758_state - device instance specific data
  * @us:                        actual spi_device
index c81d23d730d2dde6efd969e6d88bf53d43bd8772..f9ff1f8e7372ca83e5987e57172f7faad4d961b1 100644 (file)
@@ -36,8 +36,6 @@
 #define ADE7759_SPI_BURST      (u32)(1000 * 1000)
 #define ADE7759_SPI_FAST       (u32)(2000 * 1000)
 
-#define DRIVER_NAME            "ade7759"
-
 /**
  * struct ade7759_state - device instance specific data
  * @us:                        actual spi_device
index 2c96e8695d572fc4f84b05a16b255d82ba73ab96..06534577f6c38455876be00e936e922a4fe6c232 100644 (file)
 #define ADE7854_SPI_BURST      (u32)(1000 * 1000)
 #define ADE7854_SPI_FAST       (u32)(2000 * 1000)
 
-#define DRIVER_NAME            "ade7854"
-
 /**
  * struct ade7854_state - device instance specific data
  * @spi:                       actual spi_device
index 4cf47066140c7b93182c8c820e70759a92d2b50f..5cf43b3364ebfd1082de3fb83f976f88949dfa60 100644 (file)
@@ -6,15 +6,18 @@ menuconfig IPACK_BUS
        tristate "IndustryPack bus support"
        depends on HAS_IOMEM
        ---help---
-         If you say Y here you get support for the IndustryPack Framework
-         for drivers for many types of boards that support this industrial
-         bus. The IndustryPack Framework is a virtual bus allowing to
-         communicate between carrier and mezzanine cards connected through
-         this bus.
+         This option provides support for the IndustryPack framework.  There
+         are IndustryPack carrier boards, which interface another bus (such as
+         PCI) to an IndustryPack bus, and IndustryPack modules, that are
+         hosted on these buses.  While IndustryPack modules can provide a
+         large variety of functionality, they are most often found in
+         industrial control applications.
+
+         Say N if unsure.
 
 if IPACK_BUS
 
-source "drivers/staging/ipack/bridges/Kconfig"
+source "drivers/staging/ipack/carriers/Kconfig"
 
 source "drivers/staging/ipack/devices/Kconfig"
 
index 85ff223616fdbe2304d95fcbec75c1e64a167d45..6f14ade0f8f3b02df35efd56d993b5e37c08afdc 100644 (file)
@@ -3,4 +3,4 @@
 #
 obj-$(CONFIG_IPACK_BUS)                += ipack.o
 obj-y                          += devices/
-obj-y                          += bridges/
+obj-y                          += carriers/
diff --git a/drivers/staging/ipack/bridges/Kconfig b/drivers/staging/ipack/bridges/Kconfig
deleted file mode 100644 (file)
index 97c837e..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-config BOARD_TPCI200
-       tristate "TEWS TPCI-200 support for IndustryPack bus"
-       depends on IPACK_BUS
-       depends on PCI
-       help
-         This driver supports the TEWS TPCI200 device for the IndustryPack bus.
-       default n
-
diff --git a/drivers/staging/ipack/carriers/Kconfig b/drivers/staging/ipack/carriers/Kconfig
new file mode 100644 (file)
index 0000000..922ff5c
--- /dev/null
@@ -0,0 +1,7 @@
+config BOARD_TPCI200
+       tristate "Support for the TEWS TPCI-200 IndustryPack carrier board"
+       depends on IPACK_BUS
+       depends on PCI
+       help
+         This driver adds support for the TEWS TPCI200 IndustryPack carrier board.
+       default n
similarity index 68%
rename from drivers/staging/ipack/bridges/tpci200.c
rename to drivers/staging/ipack/carriers/tpci200.c
index bb8aa70281cd9da9aa55edf89850b08f1b848a2c..24e8e6d63f27f577cd66ac35d59cb3e8226b17fd 100644 (file)
  */
 
 #include <linux/module.h>
+#include <linux/slab.h>
 #include "tpci200.h"
 
-static u16 tpci200_status_timeout[] = {
+static const u16 tpci200_status_timeout[] = {
        TPCI200_A_TIMEOUT,
        TPCI200_B_TIMEOUT,
        TPCI200_C_TIMEOUT,
        TPCI200_D_TIMEOUT,
 };
 
-static u16 tpci200_status_error[] = {
+static const u16 tpci200_status_error[] = {
        TPCI200_A_ERROR,
        TPCI200_B_ERROR,
        TPCI200_C_ERROR,
        TPCI200_D_ERROR,
 };
 
+static const size_t tpci200_space_size[IPACK_SPACE_COUNT] = {
+       [IPACK_IO_SPACE]    = TPCI200_IO_SPACE_SIZE,
+       [IPACK_ID_SPACE]    = TPCI200_ID_SPACE_SIZE,
+       [IPACK_INT_SPACE]   = TPCI200_INT_SPACE_SIZE,
+       [IPACK_MEM8_SPACE]  = TPCI200_MEM8_SPACE_SIZE,
+       [IPACK_MEM16_SPACE] = TPCI200_MEM16_SPACE_SIZE,
+};
+
+static const size_t tpci200_space_interval[IPACK_SPACE_COUNT] = {
+       [IPACK_IO_SPACE]    = TPCI200_IO_SPACE_INTERVAL,
+       [IPACK_ID_SPACE]    = TPCI200_ID_SPACE_INTERVAL,
+       [IPACK_INT_SPACE]   = TPCI200_INT_SPACE_INTERVAL,
+       [IPACK_MEM8_SPACE]  = TPCI200_MEM8_SPACE_INTERVAL,
+       [IPACK_MEM16_SPACE] = TPCI200_MEM16_SPACE_INTERVAL,
+};
+
 static struct tpci200_board *check_slot(struct ipack_device *dev)
 {
        struct tpci200_board *tpci200;
@@ -46,7 +63,7 @@ static struct tpci200_board *check_slot(struct ipack_device *dev)
        if (dev->slot >= TPCI200_NB_SLOT) {
                dev_info(&dev->dev,
                         "Slot [%d:%d] doesn't exist! Last tpci200 slot is %d.\n",
-                        dev->bus_nr, dev->slot, TPCI200_NB_SLOT-1);
+                        dev->bus->bus_nr, dev->slot, TPCI200_NB_SLOT-1);
                return NULL;
        }
 
@@ -73,33 +90,19 @@ static void tpci200_set_mask(struct tpci200_board *tpci200,
 
 static void tpci200_unregister(struct tpci200_board *tpci200)
 {
-       int i;
-
        free_irq(tpci200->info->pdev->irq, (void *) tpci200);
 
        pci_iounmap(tpci200->info->pdev, tpci200->info->interface_regs);
-       pci_iounmap(tpci200->info->pdev, tpci200->info->ioidint_space);
-       pci_iounmap(tpci200->info->pdev, tpci200->info->mem8_space);
        pci_iounmap(tpci200->info->pdev, tpci200->info->cfg_regs);
 
        pci_release_region(tpci200->info->pdev, TPCI200_IP_INTERFACE_BAR);
        pci_release_region(tpci200->info->pdev, TPCI200_IO_ID_INT_SPACES_BAR);
+       pci_release_region(tpci200->info->pdev, TPCI200_MEM16_SPACE_BAR);
        pci_release_region(tpci200->info->pdev, TPCI200_MEM8_SPACE_BAR);
        pci_release_region(tpci200->info->pdev, TPCI200_CFG_MEM_BAR);
 
        pci_disable_device(tpci200->info->pdev);
        pci_dev_put(tpci200->info->pdev);
-
-       for (i = 0; i < TPCI200_NB_SLOT; i++) {
-               tpci200->slots[i].io_phys.address = NULL;
-               tpci200->slots[i].io_phys.size = 0;
-               tpci200->slots[i].id_phys.address = NULL;
-               tpci200->slots[i].id_phys.size = 0;
-               tpci200->slots[i].int_phys.address = NULL;
-               tpci200->slots[i].int_phys.size = 0;
-               tpci200->slots[i].mem_phys.address = NULL;
-               tpci200->slots[i].mem_phys.size = 0;
-       }
 }
 
 static void tpci200_enable_irq(struct tpci200_board *tpci200,
@@ -206,7 +209,7 @@ static int tpci200_request_irq(struct ipack_device *dev,
 
        if (tpci200->slots[dev->slot].irq != NULL) {
                dev_err(&dev->dev,
-                       "Slot [%d:%d] IRQ already registered !\n", dev->bus_nr,
+                       "Slot [%d:%d] IRQ already registered !\n", dev->bus->bus_nr,
                        dev->slot);
                res = -EINVAL;
                goto out_unlock;
@@ -216,7 +219,7 @@ static int tpci200_request_irq(struct ipack_device *dev,
        if (slot_irq == NULL) {
                dev_err(&dev->dev,
                        "Slot [%d:%d] unable to allocate memory for IRQ !\n",
-                       dev->bus_nr, dev->slot);
+                       dev->bus->bus_nr, dev->slot);
                res = -ENOMEM;
                goto out_unlock;
        }
@@ -243,8 +246,7 @@ static int tpci200_register(struct tpci200_board *tpci200)
 {
        int i;
        int res;
-       unsigned long ioidint_base;
-       unsigned long mem_base;
+       phys_addr_t ioidint_base;
        unsigned short slot_ctrl;
 
        if (pci_enable_device(tpci200->info->pdev) < 0)
@@ -273,38 +275,49 @@ static int tpci200_register(struct tpci200_board *tpci200)
                goto out_release_ip_space;
        }
 
-       /* Request MEM space (Bar 4) */
+       /* Request MEM8 space (Bar 5) */
        res = pci_request_region(tpci200->info->pdev, TPCI200_MEM8_SPACE_BAR,
-                                "Carrier MEM space");
+                                "Carrier MEM8 space");
        if (res) {
                dev_err(&tpci200->info->pdev->dev,
-                       "(bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 4!",
+                       "(bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 5!",
                        tpci200->info->pdev->bus->number,
                        tpci200->info->pdev->devfn);
                goto out_release_ioid_int_space;
        }
 
+       /* Request MEM16 space (Bar 4) */
+       res = pci_request_region(tpci200->info->pdev, TPCI200_MEM16_SPACE_BAR,
+                                "Carrier MEM16 space");
+       if (res) {
+               dev_err(&tpci200->info->pdev->dev,
+                       "(bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 4!",
+                       tpci200->info->pdev->bus->number,
+                       tpci200->info->pdev->devfn);
+               goto out_release_mem8_space;
+       }
+
        /* Map internal tpci200 driver user space */
        tpci200->info->interface_regs =
                ioremap_nocache(pci_resource_start(tpci200->info->pdev,
                                           TPCI200_IP_INTERFACE_BAR),
                        TPCI200_IFACE_SIZE);
-       tpci200->info->ioidint_space =
-               ioremap_nocache(pci_resource_start(tpci200->info->pdev,
-                                          TPCI200_IO_ID_INT_SPACES_BAR),
-                       TPCI200_IOIDINT_SIZE);
-       tpci200->info->mem8_space =
-               ioremap_nocache(pci_resource_start(tpci200->info->pdev,
-                                          TPCI200_MEM8_SPACE_BAR),
-                       TPCI200_MEM8_SIZE);
 
        /* Initialize lock that protects interface_regs */
        spin_lock_init(&tpci200->regs_lock);
 
        ioidint_base = pci_resource_start(tpci200->info->pdev,
                                          TPCI200_IO_ID_INT_SPACES_BAR);
-       mem_base = pci_resource_start(tpci200->info->pdev,
-                                     TPCI200_MEM8_SPACE_BAR);
+       tpci200->mod_mem[IPACK_IO_SPACE] = ioidint_base + TPCI200_IO_SPACE_OFF;
+       tpci200->mod_mem[IPACK_ID_SPACE] = ioidint_base + TPCI200_ID_SPACE_OFF;
+       tpci200->mod_mem[IPACK_INT_SPACE] =
+               ioidint_base + TPCI200_INT_SPACE_OFF;
+       tpci200->mod_mem[IPACK_MEM8_SPACE] =
+               pci_resource_start(tpci200->info->pdev,
+                                  TPCI200_MEM8_SPACE_BAR);
+       tpci200->mod_mem[IPACK_MEM16_SPACE] =
+               pci_resource_start(tpci200->info->pdev,
+                                  TPCI200_MEM16_SPACE_BAR);
 
        /* Set the default parameters of the slot
         * INT0 disabled, level sensitive
@@ -315,30 +328,8 @@ static int tpci200_register(struct tpci200_board *tpci200)
         * clock rate 8 MHz
         */
        slot_ctrl = 0;
-
-       /* Set all slot physical address space */
-       for (i = 0; i < TPCI200_NB_SLOT; i++) {
-               tpci200->slots[i].io_phys.address =
-                       (void __iomem *)ioidint_base +
-                       TPCI200_IO_SPACE_OFF + TPCI200_IO_SPACE_GAP*i;
-               tpci200->slots[i].io_phys.size = TPCI200_IO_SPACE_SIZE;
-
-               tpci200->slots[i].id_phys.address =
-                       (void __iomem *)ioidint_base +
-                       TPCI200_ID_SPACE_OFF + TPCI200_ID_SPACE_GAP*i;
-               tpci200->slots[i].id_phys.size = TPCI200_ID_SPACE_SIZE;
-
-               tpci200->slots[i].int_phys.address =
-                       (void __iomem *)ioidint_base +
-                       TPCI200_INT_SPACE_OFF + TPCI200_INT_SPACE_GAP * i;
-               tpci200->slots[i].int_phys.size = TPCI200_INT_SPACE_SIZE;
-
-               tpci200->slots[i].mem_phys.address =
-                       (void __iomem *)mem_base + TPCI200_MEM8_GAP*i;
-               tpci200->slots[i].mem_phys.size = TPCI200_MEM8_SIZE;
-
+       for (i = 0; i < TPCI200_NB_SLOT; i++)
                writew(slot_ctrl, &tpci200->info->interface_regs->control[i]);
-       }
 
        res = request_irq(tpci200->info->pdev->irq,
                          tpci200_interrupt, IRQF_SHARED,
@@ -353,6 +344,8 @@ static int tpci200_register(struct tpci200_board *tpci200)
 
        return 0;
 
+out_release_mem8_space:
+       pci_release_region(tpci200->info->pdev, TPCI200_MEM8_SPACE_BAR);
 out_release_ioid_int_space:
        pci_release_region(tpci200->info->pdev, TPCI200_IO_ID_INT_SPACES_BAR);
 out_release_ip_space:
@@ -362,166 +355,6 @@ out_disable_pci:
        return res;
 }
 
-static int tpci200_slot_unmap_space(struct ipack_device *dev, int space)
-{
-       struct ipack_addr_space *virt_addr_space;
-       struct tpci200_board *tpci200;
-
-       tpci200 = check_slot(dev);
-       if (tpci200 == NULL)
-               return -EINVAL;
-
-       if (mutex_lock_interruptible(&tpci200->mutex))
-               return -ERESTARTSYS;
-
-       switch (space) {
-       case IPACK_IO_SPACE:
-               if (dev->io_space.address == NULL) {
-                       dev_info(&dev->dev,
-                                "Slot [%d:%d] IO space not mapped !\n",
-                                dev->bus_nr, dev->slot);
-                       goto out_unlock;
-               }
-               virt_addr_space = &dev->io_space;
-               break;
-       case IPACK_ID_SPACE:
-               if (dev->id_space.address == NULL) {
-                       dev_info(&dev->dev,
-                                "Slot [%d:%d] ID space not mapped !\n",
-                                dev->bus_nr, dev->slot);
-                       goto out_unlock;
-               }
-               virt_addr_space = &dev->id_space;
-               break;
-       case IPACK_INT_SPACE:
-               if (dev->int_space.address == NULL) {
-                       dev_info(&dev->dev,
-                                "Slot [%d:%d] INT space not mapped !\n",
-                                dev->bus_nr, dev->slot);
-                       goto out_unlock;
-               }
-               virt_addr_space = &dev->int_space;
-               break;
-       case IPACK_MEM_SPACE:
-               if (dev->mem_space.address == NULL) {
-                       dev_info(&dev->dev,
-                                "Slot [%d:%d] MEM space not mapped !\n",
-                                dev->bus_nr, dev->slot);
-                       goto out_unlock;
-               }
-               virt_addr_space = &dev->mem_space;
-               break;
-       default:
-               dev_err(&dev->dev,
-                       "Slot [%d:%d] space number %d doesn't exist !\n",
-                       dev->bus_nr, dev->slot, space);
-               mutex_unlock(&tpci200->mutex);
-               return -EINVAL;
-       }
-
-       iounmap(virt_addr_space->address);
-
-       virt_addr_space->address = NULL;
-       virt_addr_space->size = 0;
-out_unlock:
-       mutex_unlock(&tpci200->mutex);
-       return 0;
-}
-
-static int tpci200_slot_map_space(struct ipack_device *dev,
-                                 unsigned int memory_size, int space)
-{
-       int res = 0;
-       unsigned int size_to_map;
-       void __iomem *phys_address;
-       struct ipack_addr_space *virt_addr_space;
-       struct tpci200_board *tpci200;
-
-       tpci200 = check_slot(dev);
-       if (tpci200 == NULL)
-               return -EINVAL;
-
-       if (mutex_lock_interruptible(&tpci200->mutex))
-               return -ERESTARTSYS;
-
-       switch (space) {
-       case IPACK_IO_SPACE:
-               if (dev->io_space.address != NULL) {
-                       dev_err(&dev->dev,
-                               "Slot [%d:%d] IO space already mapped !\n",
-                               tpci200->number, dev->slot);
-                       res = -EINVAL;
-                       goto out_unlock;
-               }
-               virt_addr_space = &dev->io_space;
-
-               phys_address = tpci200->slots[dev->slot].io_phys.address;
-               size_to_map = tpci200->slots[dev->slot].io_phys.size;
-               break;
-       case IPACK_ID_SPACE:
-               if (dev->id_space.address != NULL) {
-                       dev_err(&dev->dev,
-                               "Slot [%d:%d] ID space already mapped !\n",
-                               tpci200->number, dev->slot);
-                       res = -EINVAL;
-                       goto out_unlock;
-               }
-               virt_addr_space = &dev->id_space;
-
-               phys_address = tpci200->slots[dev->slot].id_phys.address;
-               size_to_map = tpci200->slots[dev->slot].id_phys.size;
-               break;
-       case IPACK_INT_SPACE:
-               if (dev->int_space.address != NULL) {
-                       dev_err(&dev->dev,
-                               "Slot [%d:%d] INT space already mapped !\n",
-                               tpci200->number, dev->slot);
-                       res = -EINVAL;
-                       goto out_unlock;
-               }
-               virt_addr_space = &dev->int_space;
-
-               phys_address = tpci200->slots[dev->slot].int_phys.address;
-               size_to_map = tpci200->slots[dev->slot].int_phys.size;
-               break;
-       case IPACK_MEM_SPACE:
-               if (dev->mem_space.address != NULL) {
-                       dev_err(&dev->dev,
-                               "Slot [%d:%d] MEM space already mapped !\n",
-                               tpci200->number, dev->slot);
-                       res = -EINVAL;
-                       goto out_unlock;
-               }
-               virt_addr_space = &dev->mem_space;
-
-               if (memory_size > tpci200->slots[dev->slot].mem_phys.size) {
-                       dev_err(&dev->dev,
-                               "Slot [%d:%d] request is 0x%X memory, only 0x%X available !\n",
-                               dev->bus_nr, dev->slot, memory_size,
-                               tpci200->slots[dev->slot].mem_phys.size);
-                       res = -EINVAL;
-                       goto out_unlock;
-               }
-
-               phys_address = tpci200->slots[dev->slot].mem_phys.address;
-               size_to_map = memory_size;
-               break;
-       default:
-               dev_err(&dev->dev, "Slot [%d:%d] space %d doesn't exist !\n",
-                       tpci200->number, dev->slot, space);
-               res = -EINVAL;
-               goto out_unlock;
-       }
-
-       virt_addr_space->size = size_to_map;
-       virt_addr_space->address =
-               ioremap_nocache((unsigned long)phys_address, size_to_map);
-
-out_unlock:
-       mutex_unlock(&tpci200->mutex);
-       return res;
-}
-
 static int tpci200_get_clockrate(struct ipack_device *dev)
 {
        struct tpci200_board *tpci200 = check_slot(dev);
@@ -609,8 +442,6 @@ static void tpci200_uninstall(struct tpci200_board *tpci200)
 }
 
 static const struct ipack_bus_ops tpci200_bus_ops = {
-       .map_space = tpci200_slot_map_space,
-       .unmap_space = tpci200_slot_unmap_space,
        .request_irq = tpci200_request_irq,
        .free_irq = tpci200_free_irq,
        .get_clockrate = tpci200_get_clockrate,
@@ -640,6 +471,31 @@ static int tpci200_install(struct tpci200_board *tpci200)
        return 0;
 }
 
+static void tpci200_release_device(struct ipack_device *dev)
+{
+       kfree(dev);
+}
+
+static int tpci200_create_device(struct tpci200_board *tpci200, int i)
+{
+       enum ipack_space space;
+       struct ipack_device *dev =
+               kzalloc(sizeof(struct ipack_device), GFP_KERNEL);
+       if (!dev)
+               return -ENOMEM;
+       dev->slot = i;
+       dev->bus = tpci200->info->ipack_bus;
+       dev->release = tpci200_release_device;
+
+       for (space = 0; space < IPACK_SPACE_COUNT; space++) {
+               dev->region[space].start =
+                       tpci200->mod_mem[space]
+                       + tpci200_space_interval[space] * i;
+               dev->region[space].size = tpci200_space_size[space];
+       }
+       return ipack_device_register(dev);
+}
+
 static int tpci200_pci_probe(struct pci_dev *pdev,
                             const struct pci_device_id *id)
 {
@@ -715,7 +571,7 @@ static int tpci200_pci_probe(struct pci_dev *pdev,
        dev_set_drvdata(&pdev->dev, tpci200);
 
        for (i = 0; i < TPCI200_NB_SLOT; i++)
-               ipack_device_register(tpci200->info->ipack_bus, i);
+               tpci200_create_device(tpci200, i);
        return 0;
 
 out_err_bus_register:
@@ -763,17 +619,7 @@ static struct pci_driver tpci200_pci_drv = {
        .remove = __devexit_p(tpci200_pci_remove),
 };
 
-static int __init tpci200_drvr_init_module(void)
-{
-       return pci_register_driver(&tpci200_pci_drv);
-}
-
-static void __exit tpci200_drvr_exit_module(void)
-{
-       pci_unregister_driver(&tpci200_pci_drv);
-}
+module_pci_driver(tpci200_pci_drv);
 
 MODULE_DESCRIPTION("TEWS TPCI-200 device driver");
 MODULE_LICENSE("GPL");
-module_init(tpci200_drvr_init_module);
-module_exit(tpci200_drvr_exit_module);
similarity index 89%
rename from drivers/staging/ipack/bridges/tpci200.h
rename to drivers/staging/ipack/carriers/tpci200.h
index 235d1fe4f48c96bac520e9eed486a4ac00650f90..982f31920af59f610007e0b76e4e73baff9e61de 100644 (file)
@@ -49,20 +49,20 @@ struct tpci200_regs {
 #define TPCI200_IFACE_SIZE            0x100
 
 #define TPCI200_IO_SPACE_OFF          0x0000
-#define TPCI200_IO_SPACE_GAP          0x0100
+#define TPCI200_IO_SPACE_INTERVAL     0x0100
 #define TPCI200_IO_SPACE_SIZE         0x0080
 #define TPCI200_ID_SPACE_OFF          0x0080
-#define TPCI200_ID_SPACE_GAP          0x0100
+#define TPCI200_ID_SPACE_INTERVAL     0x0100
 #define TPCI200_ID_SPACE_SIZE         0x0040
 #define TPCI200_INT_SPACE_OFF         0x00C0
-#define TPCI200_INT_SPACE_GAP         0x0100
+#define TPCI200_INT_SPACE_INTERVAL    0x0100
 #define TPCI200_INT_SPACE_SIZE        0x0040
 #define TPCI200_IOIDINT_SIZE          0x0400
 
-#define TPCI200_MEM8_GAP              0x00400000
-#define TPCI200_MEM8_SIZE             0x00400000
-#define TPCI200_MEM16_GAP             0x00800000
-#define TPCI200_MEM16_SIZE            0x00800000
+#define TPCI200_MEM8_SPACE_INTERVAL   0x00400000
+#define TPCI200_MEM8_SPACE_SIZE       0x00400000
+#define TPCI200_MEM16_SPACE_INTERVAL  0x00800000
+#define TPCI200_MEM16_SPACE_SIZE      0x00800000
 
 /* control field in tpci200_regs */
 #define TPCI200_INT0_EN               0x0040
@@ -137,11 +137,7 @@ struct slot_irq {
  *
  */
 struct tpci200_slot {
-       struct slot_irq         *irq;
-       struct ipack_addr_space io_phys;
-       struct ipack_addr_space id_phys;
-       struct ipack_addr_space int_phys;
-       struct ipack_addr_space mem_phys;
+       struct slot_irq     *irq;
 };
 
 /**
@@ -156,8 +152,6 @@ struct tpci200_infos {
        struct pci_dev                  *pdev;
        struct pci_device_id            *id_table;
        struct tpci200_regs __iomem     *interface_regs;
-       void __iomem                    *ioidint_space;
-       void __iomem                    *mem8_space;
        void __iomem                    *cfg_regs;
        struct ipack_bus_device         *ipack_bus;
 };
@@ -167,6 +161,7 @@ struct tpci200_board {
        spinlock_t              regs_lock;
        struct tpci200_slot     *slots;
        struct tpci200_infos    *info;
+       phys_addr_t             mod_mem[IPACK_SPACE_COUNT];
 };
 
 #endif /* _TPCI200_H_ */
index 39f71888a584059a474ec1eb61f56f19d8f2f192..0b82fdc198c042d3ac6eeb4ea5f3a7880436c5df 100644 (file)
@@ -4,4 +4,3 @@ config SERIAL_IPOCTAL
        help
          This driver supports the IPOCTAL serial port device for the IndustryPack bus.
        default n
-
index d751edfda8397c1c1d5791b34b7a38d0009d7866..b6a72e6c10614714e2f4c4d57110362d9a5b52ed 100644 (file)
@@ -53,6 +53,8 @@ struct ipoctal {
        struct ipoctal_channel          channel[NR_CHANNELS];
        unsigned char                   write;
        struct tty_driver               *tty_drv;
+       u8 __iomem                      *mem8_space;
+       u8 __iomem                      *int_space;
 };
 
 static int ipoctal_port_activate(struct tty_port *port, struct tty_struct *tty)
@@ -252,35 +254,12 @@ static irqreturn_t ipoctal_irq_handler(void *arg)
                ipoctal_irq_channel(&ipoctal->channel[i]);
 
        /* Clear the IPack device interrupt */
-       readw(ipoctal->dev->int_space.address + ACK_INT_REQ0);
-       readw(ipoctal->dev->int_space.address + ACK_INT_REQ1);
+       readw(ipoctal->int_space + ACK_INT_REQ0);
+       readw(ipoctal->int_space + ACK_INT_REQ1);
 
        return IRQ_HANDLED;
 }
 
-static int ipoctal_check_model(struct ipack_device *dev, unsigned char *id)
-{
-       unsigned char manufacturerID;
-       unsigned char board_id;
-
-
-       manufacturerID = ioread8(dev->id_space.address + IPACK_IDPROM_OFFSET_MANUFACTURER_ID);
-       if (manufacturerID != IPACK1_VENDOR_ID_SBS)
-               return -ENODEV;
-       board_id = ioread8(dev->id_space.address + IPACK_IDPROM_OFFSET_MODEL);
-       switch (board_id) {
-       case IPACK1_DEVICE_ID_SBS_OCTAL_232:
-       case IPACK1_DEVICE_ID_SBS_OCTAL_422:
-       case IPACK1_DEVICE_ID_SBS_OCTAL_485:
-               *id = board_id;
-               break;
-       default:
-               return -ENODEV;
-       }
-
-       return 0;
-}
-
 static const struct tty_port_operations ipoctal_tty_port_ops = {
        .dtr_rts = NULL,
        .activate = ipoctal_port_activate,
@@ -289,64 +268,55 @@ static const struct tty_port_operations ipoctal_tty_port_ops = {
 static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr,
                             unsigned int slot)
 {
-       int res = 0;
+       int res;
        int i;
        struct tty_driver *tty;
        char name[20];
-       unsigned char board_id;
        struct ipoctal_channel *channel;
+       struct ipack_region *region;
+       void __iomem *addr;
        union scc2698_channel __iomem *chan_regs;
        union scc2698_block __iomem *block_regs;
 
-       res = ipoctal->dev->bus->ops->map_space(ipoctal->dev, 0,
-                                               IPACK_ID_SPACE);
-       if (res) {
-               dev_err(&ipoctal->dev->dev,
-                       "Unable to map slot [%d:%d] ID space!\n",
-                       bus_nr, slot);
-               return res;
-       }
+       ipoctal->board_id = ipoctal->dev->id_device;
 
-       res = ipoctal_check_model(ipoctal->dev, &board_id);
-       if (res) {
-               ipoctal->dev->bus->ops->unmap_space(ipoctal->dev,
-                                                   IPACK_ID_SPACE);
-               goto out_unregister_id_space;
-       }
-       ipoctal->board_id = board_id;
-
-       res = ipoctal->dev->bus->ops->map_space(ipoctal->dev, 0,
-                                               IPACK_IO_SPACE);
-       if (res) {
+       region = &ipoctal->dev->region[IPACK_IO_SPACE];
+       addr = devm_ioremap_nocache(&ipoctal->dev->dev,
+                                   region->start, region->size);
+       if (!addr) {
                dev_err(&ipoctal->dev->dev,
                        "Unable to map slot [%d:%d] IO space!\n",
                        bus_nr, slot);
-               goto out_unregister_id_space;
+               return -EADDRNOTAVAIL;
        }
+       /* Save the virtual address to access the registers easily */
+       chan_regs =
+               (union scc2698_channel __iomem *) addr;
+       block_regs =
+               (union scc2698_block __iomem *) addr;
 
-       res = ipoctal->dev->bus->ops->map_space(ipoctal->dev, 0,
-                                               IPACK_INT_SPACE);
-       if (res) {
+       region = &ipoctal->dev->region[IPACK_INT_SPACE];
+       ipoctal->int_space =
+               devm_ioremap_nocache(&ipoctal->dev->dev,
+                                    region->start, region->size);
+       if (!ipoctal->int_space) {
                dev_err(&ipoctal->dev->dev,
                        "Unable to map slot [%d:%d] INT space!\n",
                        bus_nr, slot);
-               goto out_unregister_io_space;
+               return -EADDRNOTAVAIL;
        }
 
-       res = ipoctal->dev->bus->ops->map_space(ipoctal->dev,
-                                          0x8000, IPACK_MEM_SPACE);
-       if (res) {
+       region = &ipoctal->dev->region[IPACK_MEM8_SPACE];
+       ipoctal->mem8_space =
+               devm_ioremap_nocache(&ipoctal->dev->dev,
+                                    region->start, 0x8000);
+       if (!addr) {
                dev_err(&ipoctal->dev->dev,
-                       "Unable to map slot [%d:%d] MEM space!\n",
+                       "Unable to map slot [%d:%d] MEM8 space!\n",
                        bus_nr, slot);
-               goto out_unregister_int_space;
+               return -EADDRNOTAVAIL;
        }
 
-       /* Save the virtual address to access the registers easily */
-       chan_regs =
-               (union scc2698_channel __iomem *) ipoctal->dev->io_space.address;
-       block_regs =
-               (union scc2698_block __iomem *) ipoctal->dev->io_space.address;
 
        /* Disable RX and TX before touching anything */
        for (i = 0; i < NR_CHANNELS ; i++) {
@@ -389,17 +359,15 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr,
        ipoctal->dev->bus->ops->request_irq(ipoctal->dev,
                                       ipoctal_irq_handler, ipoctal);
        /* Dummy write */
-       iowrite8(1, ipoctal->dev->mem_space.address + 1);
+       iowrite8(1, ipoctal->mem8_space + 1);
 
        /* Register the TTY device */
 
        /* Each IP-OCTAL channel is a TTY port */
        tty = alloc_tty_driver(NR_CHANNELS);
 
-       if (!tty) {
-               res = -ENOMEM;
-               goto out_unregister_slot_unmap;
-       }
+       if (!tty)
+               return -ENOMEM;
 
        /* Fill struct tty_driver with ipoctal data */
        tty->owner = THIS_MODULE;
@@ -422,7 +390,7 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr,
        if (res) {
                dev_err(&ipoctal->dev->dev, "Can't register tty driver.\n");
                put_tty_driver(tty);
-               goto out_unregister_slot_unmap;
+               return res;
        }
 
        /* Save struct tty_driver for use it when uninstalling the device */
@@ -458,16 +426,6 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr,
        }
 
        return 0;
-
-out_unregister_slot_unmap:
-       ipoctal->dev->bus->ops->unmap_space(ipoctal->dev, IPACK_ID_SPACE);
-out_unregister_int_space:
-       ipoctal->dev->bus->ops->unmap_space(ipoctal->dev, IPACK_INT_SPACE);
-out_unregister_io_space:
-       ipoctal->dev->bus->ops->unmap_space(ipoctal->dev, IPACK_IO_SPACE);
-out_unregister_id_space:
-       ipoctal->dev->bus->ops->unmap_space(ipoctal->dev, IPACK_MEM_SPACE);
-       return res;
 }
 
 static inline int ipoctal_copy_write_buffer(struct ipoctal_channel *channel,
@@ -719,7 +677,7 @@ static int ipoctal_probe(struct ipack_device *dev)
                return -ENOMEM;
 
        ipoctal->dev = dev;
-       res = ipoctal_inst_slot(ipoctal, dev->bus_nr, dev->slot);
+       res = ipoctal_inst_slot(ipoctal, dev->bus->bus_nr, dev->slot);
        if (res)
                goto out_uninst;
 
@@ -745,10 +703,6 @@ static void __ipoctal_remove(struct ipoctal *ipoctal)
 
        tty_unregister_driver(ipoctal->tty_drv);
        put_tty_driver(ipoctal->tty_drv);
-       ipoctal->dev->bus->ops->unmap_space(ipoctal->dev, IPACK_MEM_SPACE);
-       ipoctal->dev->bus->ops->unmap_space(ipoctal->dev, IPACK_INT_SPACE);
-       ipoctal->dev->bus->ops->unmap_space(ipoctal->dev, IPACK_IO_SPACE);
-       ipoctal->dev->bus->ops->unmap_space(ipoctal->dev, IPACK_ID_SPACE);
        kfree(ipoctal);
 }
 
index d1e0651592a2f7a2ea0225c2e6e2ff5ba4e65d70..75bfecfe3620c26511e7ce5b7659257e1849d2cf 100644 (file)
@@ -24,7 +24,7 @@ static void ipack_device_release(struct device *dev)
 {
        struct ipack_device *device = to_ipack_dev(dev);
        kfree(device->id);
-       kfree(device);
+       device->release(device);
 }
 
 static inline const struct ipack_device_id *
@@ -234,7 +234,7 @@ static int ipack_unregister_bus_member(struct device *dev, void *data)
        struct ipack_device *idev = to_ipack_dev(dev);
        struct ipack_bus_device *bus = data;
 
-       if (idev->bus_nr == bus->bus_nr)
+       if (idev->bus == bus)
                ipack_device_unregister(idev);
 
        return 1;
@@ -351,12 +351,12 @@ static int ipack_device_read_id(struct ipack_device *dev)
        int i;
        int ret = 0;
 
-       ret = dev->bus->ops->map_space(dev, 0, IPACK_ID_SPACE);
-       if (ret) {
+       idmem = ioremap(dev->region[IPACK_ID_SPACE].start,
+                       dev->region[IPACK_ID_SPACE].size);
+       if (!idmem) {
                dev_err(&dev->dev, "error mapping memory\n");
-               return ret;
+               return -ENOMEM;
        }
-       idmem = dev->id_space.address;
 
        /* Determine ID PROM Data Format.  If we find the ids "IPAC" or "IPAH"
         * we are dealing with a IndustryPack  format 1 device.  If we detect
@@ -421,57 +421,44 @@ static int ipack_device_read_id(struct ipack_device *dev)
        }
 
 out:
-       dev->bus->ops->unmap_space(dev, IPACK_ID_SPACE);
+       iounmap(idmem);
 
        return ret;
 }
 
-struct ipack_device *ipack_device_register(struct ipack_bus_device *bus,
-                                          int slot)
+int ipack_device_register(struct ipack_device *dev)
 {
        int ret;
-       struct ipack_device *dev;
-
-       dev = kzalloc(sizeof(struct ipack_device), GFP_KERNEL);
-       if (!dev)
-               return NULL;
 
        dev->dev.bus = &ipack_bus_type;
        dev->dev.release = ipack_device_release;
-       dev->dev.parent = bus->parent;
-       dev->slot = slot;
-       dev->bus_nr = bus->bus_nr;
-       dev->bus = bus;
+       dev->dev.parent = dev->bus->parent;
        dev_set_name(&dev->dev,
-                    "ipack-dev.%u.%u", dev->bus_nr, dev->slot);
+                    "ipack-dev.%u.%u", dev->bus->bus_nr, dev->slot);
 
-       if (bus->ops->set_clockrate(dev, 8))
+       if (dev->bus->ops->set_clockrate(dev, 8))
                dev_warn(&dev->dev, "failed to switch to 8 MHz operation for reading of device ID.\n");
-       if (bus->ops->reset_timeout(dev))
+       if (dev->bus->ops->reset_timeout(dev))
                dev_warn(&dev->dev, "failed to reset potential timeout.");
 
        ret = ipack_device_read_id(dev);
        if (ret < 0) {
                dev_err(&dev->dev, "error reading device id section.\n");
-               kfree(dev);
-               return NULL;
+               return ret;
        }
 
        /* if the device supports 32 MHz operation, use it. */
        if (dev->speed_32mhz) {
-               ret = bus->ops->set_clockrate(dev, 32);
+               ret = dev->bus->ops->set_clockrate(dev, 32);
                if (ret < 0)
                        dev_err(&dev->dev, "failed to switch to 32 MHz operation.\n");
        }
 
        ret = device_register(&dev->dev);
-       if (ret < 0) {
+       if (ret < 0)
                kfree(dev->id);
-               kfree(dev);
-               return NULL;
-       }
 
-       return dev;
+       return ret;
 }
 EXPORT_SYMBOL_GPL(ipack_device_register);
 
index d8e3bb6feac85df763449d904e672686dae23352..7ca8789459e96066d84b05b6df0163183b1d5a48 100644 (file)
@@ -33,26 +33,25 @@ struct ipack_driver;
 
 enum ipack_space {
        IPACK_IO_SPACE    = 0,
-       IPACK_ID_SPACE    = 1,
-       IPACK_MEM_SPACE   = 2,
+       IPACK_ID_SPACE,
        IPACK_INT_SPACE,
+       IPACK_MEM8_SPACE,
+       IPACK_MEM16_SPACE,
+       /* Dummy for counting the number of entries.  Must remain the last
+        * entry */
+       IPACK_SPACE_COUNT,
 };
 
 /**
- *     struct ipack_addr_space - Virtual address space mapped for a specified type.
- *
- *     @address: virtual address
- *     @size: size of the mapped space
  */
-struct ipack_addr_space {
-       void __iomem *address;
-       unsigned int size;
+struct ipack_region {
+       phys_addr_t start;
+       size_t      size;
 };
 
 /**
  *     struct ipack_device
  *
- *     @bus_nr: IP bus number where the device is plugged
  *     @slot: Slot where the device is plugged in the carrier board
  *     @bus: ipack_bus_device where the device is plugged to.
  *     @id_space: Virtual address to ID space.
@@ -65,14 +64,11 @@ struct ipack_addr_space {
  * by the carrier board throught bus->ops.
  */
 struct ipack_device {
-       unsigned int bus_nr;
        unsigned int slot;
        struct ipack_bus_device *bus;
-       struct ipack_addr_space id_space;
-       struct ipack_addr_space io_space;
-       struct ipack_addr_space int_space;
-       struct ipack_addr_space mem_space;
        struct device dev;
+       void (*release) (struct ipack_device *dev);
+       struct ipack_region      region[IPACK_SPACE_COUNT];
        u8                      *id;
        size_t                   id_avail;
        u32                      id_vendor;
@@ -84,10 +80,11 @@ struct ipack_device {
 };
 
 /**
- *     struct ipack_driver_ops -- callbacks to mezzanine driver for installing/removing one device
+ * struct ipack_driver_ops -- Callbacks to IPack device driver
  *
- *     @probe: Probe function
- *     @remove: tell the driver that the carrier board wants to remove one device
+ * @probe:  Probe function
+ * @remove: Prepare imminent removal of the device.  Services provided by the
+ *          device should be revoked.
  */
 
 struct ipack_driver_ops {
@@ -96,10 +93,10 @@ struct ipack_driver_ops {
 };
 
 /**
- *     struct ipack_driver -- Specific data to each ipack board driver
+ * struct ipack_driver -- Specific data to each ipack device driver
  *
- *     @driver: Device driver kernel representation
- *     @ops: Mezzanine driver operations specific for the ipack bus.
+ * @driver: Device driver kernel representation
+ * @ops:    Callbacks provided by the IPack device driver
  */
 struct ipack_driver {
        struct device_driver driver;
@@ -125,8 +122,6 @@ struct ipack_driver {
  *     @reset_timeout: Resets the state returned by get_timeout.
  */
 struct ipack_bus_ops {
-       int (*map_space) (struct ipack_device *dev, unsigned int memory_size, int space);
-       int (*unmap_space) (struct ipack_device *dev, int space);
        int (*request_irq) (struct ipack_device *dev,
                            irqreturn_t (*handler)(void *), void *arg);
        int (*free_irq) (struct ipack_device *dev);
@@ -171,7 +166,7 @@ struct ipack_bus_device *ipack_bus_register(struct device *parent, int slots,
 int ipack_bus_unregister(struct ipack_bus_device *bus);
 
 /**
- *     ipack_driver_register -- Register a new driver
+ * ipack_driver_register -- Register a new ipack device driver
  *
  * Called by a ipack driver to register itself as a driver
  * that can manage ipack devices.
@@ -181,15 +176,18 @@ int ipack_driver_register(struct ipack_driver *edrv, struct module *owner,
 void ipack_driver_unregister(struct ipack_driver *edrv);
 
 /**
- *     ipack_device_register -- register a new mezzanine device
+ *     ipack_device_register -- register an IPack device with the kernel
+ *     @dev: the new device to register.
  *
- * @bus: ipack bus device it is plugged to.
- * @slot: slot position in the bus device.
+ *     Register a new IPack device ("module" in IndustryPack jargon). The call
+ *     is done by the carrier driver.  The carrier should populate the fields
+ *     bus and slot as well as the region array of @dev prior to calling this
+ *     function.  The rest of the fields will be allocated and populated
+ *     during registration.
  *
- * Register a new ipack device (mezzanine device). The call is done by
- * the carrier device driver.
+ *     Return zero on success or error code on failure.
  */
-struct ipack_device *ipack_device_register(struct ipack_bus_device *bus, int slot);
+int ipack_device_register(struct ipack_device *dev);
 void ipack_device_unregister(struct ipack_device *dev);
 
 /**
index 8e7398393a592d1491aa64867f727ecedce748d5..a92e21f7d55b83bb1b537e48259b1202271699fa 100644 (file)
 #include "driver.h"
 #include "audio.h"
 
-static int line6_index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
-static char *line6_id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
-
 /*
        Initialize the Line6 USB audio system.
 */
 int line6_init_audio(struct usb_line6 *line6)
 {
-       static int dev;
        struct snd_card *card;
        int err;
 
-       err = snd_card_create(line6_index[dev], line6_id[dev], THIS_MODULE, 0,
-                             &card);
+       err = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
+                             THIS_MODULE, 0, &card);
        if (err < 0)
                return err;
 
index b8358ca71bdd33e4a1280ca92af45c32253ba4e5..ac11a3bd1bbe99fe9f41538e1a6afe78a5c1a935 100644 (file)
@@ -96,8 +96,6 @@ static const char line6_request_version[] = {
        0xf0, 0x7e, 0x7f, 0x06, 0x01, 0xf7
 };
 
-struct usb_line6 *line6_devices[LINE6_MAX_DEVICES];
-
 /**
         Class for asynchronous messages.
 */
@@ -740,7 +738,6 @@ static int line6_probe(struct usb_interface *interface,
        struct usb_device *usbdev;
        struct usb_line6 *line6;
        const struct line6_properties *properties;
-       int devnum;
        int interface_number, alternate = 0;
        int product;
        int size = 0;
@@ -774,16 +771,6 @@ static int line6_probe(struct usb_interface *interface,
                goto err_put;
        }
 
-       /* find free slot in device table: */
-       for (devnum = 0; devnum < LINE6_MAX_DEVICES; ++devnum)
-               if (line6_devices[devnum] == NULL)
-                       break;
-
-       if (devnum == LINE6_MAX_DEVICES) {
-               ret = -ENODEV;
-               goto err_put;
-       }
-
        /* initialize device info: */
        properties = &line6_properties_table[devtype];
        dev_info(&interface->dev, "Line6 %s found\n", properties->name);
@@ -1112,7 +1099,6 @@ static int line6_probe(struct usb_interface *interface,
 
        dev_info(&interface->dev, "Line6 %s now attached\n",
                 line6->properties->name);
-       line6_devices[devnum] = line6;
 
        switch (product) {
        case LINE6_DEVID_PODX3:
@@ -1141,7 +1127,7 @@ static void line6_disconnect(struct usb_interface *interface)
 {
        struct usb_line6 *line6;
        struct usb_device *usbdev;
-       int interface_number, i;
+       int interface_number;
 
        if (interface == NULL)
                return;
@@ -1214,10 +1200,6 @@ static void line6_disconnect(struct usb_interface *interface)
 
                dev_info(&interface->dev, "Line6 %s now disconnected\n",
                         line6->properties->name);
-
-               for (i = LINE6_MAX_DEVICES; i--;)
-                       if (line6_devices[i] == line6)
-                               line6_devices[i] = NULL;
        }
 
        line6_destruct(interface);
index a3029eb223d6f9a0c6e5e4df01d171b951d779d1..35246cfcd91f6217c837cb778ff06a2f8317b0a1 100644 (file)
@@ -25,7 +25,6 @@
 #endif
 
 #define LINE6_TIMEOUT 1
-#define LINE6_MAX_DEVICES 8
 #define LINE6_BUFSIZE_LISTEN 32
 #define LINE6_MESSAGE_MAXLEN 256
 
@@ -78,7 +77,6 @@ do {                                  \
 } while (0)
 
 extern const unsigned char line6_midi_id[3];
-extern struct usb_line6 *line6_devices[LINE6_MAX_DEVICES];
 
 static const int SYSEX_DATA_OFS = sizeof(line6_midi_id) + 3;
 static const int SYSEX_EXTRA_SIZE = sizeof(line6_midi_id) + 4;
index 094fdc366f30a21d767107303b902294cd26358f..97cdf0856aed6fd0b18f912cadd1846a32331aad 100644 (file)
@@ -39,7 +39,6 @@
 #include <linux/workqueue.h>
 
 #include <mach/clk.h>
-#include <mach/iomap.h>
 
 #include "nvec.h"
 
index d49c32a956901938c1593eb4417a0ac8e0d77e74..3fe209ca38cb3ffff839d2c7ea2e8139baa439ac 100644 (file)
 static ushort resumeline = 898;
 module_param(resumeline, ushort, 0444);
 
-/* Default off since it doesn't work on DCON ASIC in B-test OLPC board */
-static int useaa = 1;
-module_param(useaa, int, 0444);
-
 static struct dcon_platform_data *pdata;
 
 /* I2C structures */
@@ -50,8 +46,6 @@ static struct dcon_platform_data *pdata;
 /* Platform devices */
 static struct platform_device *dcon_device;
 
-static DECLARE_WAIT_QUEUE_HEAD(dcon_wait_queue);
-
 static unsigned short normal_i2c[] = { 0x0d, I2C_CLIENT_END };
 
 static s32 dcon_write(struct dcon_priv *dcon, u8 reg, u16 val)
@@ -103,9 +97,7 @@ static int dcon_hw_init(struct dcon_priv *dcon, int is_init)
        /* Colour swizzle, AA, no passthrough, backlight */
        if (is_init) {
                dcon->disp_mode = MODE_PASSTHRU | MODE_BL_ENABLE |
-                               MODE_CSWIZZLE;
-               if (useaa)
-                       dcon->disp_mode |= MODE_COL_AA;
+                               MODE_CSWIZZLE | MODE_COL_AA;
        }
        dcon_write(dcon, DCON_REG_MODE, dcon->disp_mode);
 
@@ -191,9 +183,7 @@ static int dcon_set_mono_mode(struct dcon_priv *dcon, bool enable_mono)
                dcon->disp_mode |= MODE_MONO_LUMA;
        } else {
                dcon->disp_mode &= ~(MODE_MONO_LUMA);
-               dcon->disp_mode |= MODE_CSWIZZLE;
-               if (useaa)
-                       dcon->disp_mode |= MODE_COL_AA;
+               dcon->disp_mode |= MODE_CSWIZZLE | MODE_COL_AA;
        }
 
        dcon_write(dcon, DCON_REG_MODE, dcon->disp_mode);
@@ -288,7 +278,6 @@ static void dcon_source_switch(struct work_struct *work)
 {
        struct dcon_priv *dcon = container_of(work, struct dcon_priv,
                        switch_source);
-       DECLARE_WAITQUEUE(wait, current);
        int source = dcon->pending_src;
 
        if (dcon->curr_src == source)
@@ -305,11 +294,9 @@ static void dcon_source_switch(struct work_struct *work)
                if (dcon_write(dcon, DCON_REG_MODE,
                                dcon->disp_mode | MODE_SCAN_INT))
                        pr_err("couldn't enable scanline interrupt!\n");
-               else {
+               else
                        /* Wait up to one second for the scanline interrupt */
-                       wait_event_timeout(dcon_wait_queue,
-                                          dcon->switched == true, HZ);
-               }
+                       wait_event_timeout(dcon->waitq, dcon->switched, HZ);
 
                if (!dcon->switched)
                        pr_err("Timeout entering CPU mode; expect a screen glitch.\n");
@@ -340,21 +327,15 @@ static void dcon_source_switch(struct work_struct *work)
                break;
        case DCON_SOURCE_DCON:
        {
-               int t;
                struct timespec delta_t;
 
                pr_info("dcon_source_switch to DCON\n");
 
-               add_wait_queue(&dcon_wait_queue, &wait);
-               set_current_state(TASK_UNINTERRUPTIBLE);
-
                /* Clear DCONLOAD - this implies that the DCON is in control */
                pdata->set_dconload(0);
                getnstimeofday(&dcon->load_time);
 
-               t = schedule_timeout(HZ/2);
-               remove_wait_queue(&dcon_wait_queue, &wait);
-               set_current_state(TASK_RUNNING);
+               wait_event_timeout(dcon->waitq, dcon->switched, HZ/2);
 
                if (!dcon->switched) {
                        pr_err("Timeout entering DCON mode; expect a screen glitch.\n");
@@ -539,6 +520,10 @@ static int dcon_bl_update(struct backlight_device *dev)
        if (level != dcon->bl_val)
                dcon_set_backlight(dcon, level);
 
+       /* power down the DCON when the screen is blanked */
+       if (!dcon->ignore_fb_events)
+               dcon_sleep(dcon, !!(dev->props.state & BL_CORE_FBBLANK));
+
        return 0;
 }
 
@@ -584,24 +569,6 @@ static struct notifier_block dcon_panic_nb = {
        .notifier_call = unfreeze_on_panic,
 };
 
-/*
- * When the framebuffer sleeps due to external sources (e.g. user idle), power
- * down the DCON as well.  Power it back up when the fb comes back to life.
- */
-static int dcon_fb_notifier(struct notifier_block *self,
-                               unsigned long event, void *data)
-{
-       struct fb_event *evdata = data;
-       struct dcon_priv *dcon = container_of(self, struct dcon_priv,
-                       fbevent_nb);
-       int *blank = (int *)evdata->data;
-       if (((event != FB_EVENT_BLANK) && (event != FB_EVENT_CONBLANK)) ||
-                       dcon->ignore_fb_events)
-               return 0;
-       dcon_sleep(dcon, *blank ? true : false);
-       return 0;
-}
-
 static int dcon_detect(struct i2c_client *client, struct i2c_board_info *info)
 {
        strlcpy(info->type, "olpc_dcon", I2C_NAME_SIZE);
@@ -622,10 +589,10 @@ static int dcon_probe(struct i2c_client *client, const struct i2c_device_id *id)
                return -ENOMEM;
 
        dcon->client = client;
+       init_waitqueue_head(&dcon->waitq);
        INIT_WORK(&dcon->switch_source, dcon_source_switch);
        dcon->reboot_nb.notifier_call = dcon_reboot_notify;
        dcon->reboot_nb.priority = -1;
-       dcon->fbevent_nb.notifier_call = dcon_fb_notifier;
 
        i2c_set_clientdata(client, dcon);
 
@@ -680,7 +647,6 @@ static int dcon_probe(struct i2c_client *client, const struct i2c_device_id *id)
 
        register_reboot_notifier(&dcon->reboot_nb);
        atomic_notifier_chain_register(&panic_notifier_list, &dcon_panic_nb);
-       fb_register_client(&dcon->fbevent_nb);
 
        return 0;
 
@@ -701,7 +667,6 @@ static int dcon_remove(struct i2c_client *client)
 {
        struct dcon_priv *dcon = i2c_get_clientdata(client);
 
-       fb_unregister_client(&dcon->fbevent_nb);
        unregister_reboot_notifier(&dcon->reboot_nb);
        atomic_notifier_chain_unregister(&panic_notifier_list, &dcon_panic_nb);
 
@@ -720,8 +685,9 @@ static int dcon_remove(struct i2c_client *client)
 }
 
 #ifdef CONFIG_PM
-static int dcon_suspend(struct i2c_client *client, pm_message_t state)
+static int dcon_suspend(struct device *dev)
 {
+       struct i2c_client *client = to_i2c_client(dev);
        struct dcon_priv *dcon = i2c_get_clientdata(client);
 
        if (!dcon->asleep) {
@@ -732,8 +698,9 @@ static int dcon_suspend(struct i2c_client *client, pm_message_t state)
        return 0;
 }
 
-static int dcon_resume(struct i2c_client *client)
+static int dcon_resume(struct device *dev)
 {
+       struct i2c_client *client = to_i2c_client(dev);
        struct dcon_priv *dcon = i2c_get_clientdata(client);
 
        if (!dcon->asleep) {
@@ -744,7 +711,12 @@ static int dcon_resume(struct i2c_client *client)
        return 0;
 }
 
-#endif
+#else
+
+#define dcon_suspend NULL
+#define dcon_resume NULL
+
+#endif /* CONFIG_PM */
 
 
 irqreturn_t dcon_interrupt(int irq, void *id)
@@ -764,7 +736,7 @@ irqreturn_t dcon_interrupt(int irq, void *id)
        case 1: /* switch to CPU mode */
                dcon->switched = true;
                getnstimeofday(&dcon->irq_time);
-               wake_up(&dcon_wait_queue);
+               wake_up(&dcon->waitq);
                break;
 
        case 0:
@@ -778,7 +750,7 @@ irqreturn_t dcon_interrupt(int irq, void *id)
                if (dcon->curr_src != dcon->pending_src && !dcon->switched) {
                        dcon->switched = true;
                        getnstimeofday(&dcon->irq_time);
-                       wake_up(&dcon_wait_queue);
+                       wake_up(&dcon->waitq);
                        pr_debug("switching w/ status 0/0\n");
                } else {
                        pr_debug("scanline interrupt w/CPU\n");
@@ -788,16 +760,21 @@ irqreturn_t dcon_interrupt(int irq, void *id)
        return IRQ_HANDLED;
 }
 
+static const struct dev_pm_ops dcon_pm_ops = {
+       .suspend = dcon_suspend,
+       .resume = dcon_resume,
+};
+
 static const struct i2c_device_id dcon_idtable[] = {
        { "olpc_dcon",  0 },
        { }
 };
-
 MODULE_DEVICE_TABLE(i2c, dcon_idtable);
 
 struct i2c_driver dcon_driver = {
        .driver = {
                .name   = "olpc_dcon",
+               .pm = &dcon_pm_ops,
        },
        .class = I2C_CLASS_DDC | I2C_CLASS_HWMON,
        .id_table = dcon_idtable,
@@ -805,10 +782,6 @@ struct i2c_driver dcon_driver = {
        .remove = __devexit_p(dcon_remove),
        .detect = dcon_detect,
        .address_list = normal_i2c,
-#ifdef CONFIG_PM
-       .suspend = dcon_suspend,
-       .resume = dcon_resume,
-#endif
 };
 
 static int __init olpc_dcon_init(void)
index 167a41778be61ef3dd11474e615143ac90f987e8..997bded2949f2ccffe7cc6c0f1be50df4865a58b 100644 (file)
@@ -52,9 +52,9 @@ struct dcon_priv {
        struct fb_info *fbinfo;
        struct backlight_device *bl_dev;
 
+       wait_queue_head_t waitq;
        struct work_struct switch_source;
        struct notifier_block reboot_nb;
-       struct notifier_block fbevent_nb;
 
        /* Shadow register for the DCON_REG_MODE register */
        u8 disp_mode;
index 352dd3db01320cf82633388f41ddb26f83bbaf55..6a4d379c16a340775606f14f2ae604c90cbb4968 100644 (file)
@@ -10,7 +10,6 @@
 
 #include <linux/acpi.h>
 #include <linux/delay.h>
-#include <linux/pci.h>
 #include <linux/gpio.h>
 #include <asm/olpc.h>
 
@@ -62,33 +61,6 @@ static int dcon_was_irq(void)
 static int dcon_init_xo_1_5(struct dcon_priv *dcon)
 {
        unsigned int irq;
-       u_int8_t tmp;
-       struct pci_dev *pdev;
-
-       pdev = pci_get_device(PCI_VENDOR_ID_VIA,
-                             PCI_DEVICE_ID_VIA_VX855, NULL);
-       if (!pdev) {
-               pr_err("cannot find VX855 PCI ID\n");
-               return 1;
-       }
-
-       pci_read_config_byte(pdev, 0x95, &tmp);
-       pci_write_config_byte(pdev, 0x95, tmp|0x0c);
-
-       /* Set GPIO8 to GPIO mode, not SSPICLK */
-       pci_read_config_byte(pdev, 0xe3, &tmp);
-       pci_write_config_byte(pdev, 0xe3, tmp | 0x04);
-
-       /* Set GPI10/GPI11 to GPI mode, not SSPISDI/SSPISS */
-       pci_read_config_byte(pdev, 0xe4, &tmp);
-       pci_write_config_byte(pdev, 0xe4, tmp|0x08);
-
-       /* clear PMU_RxE1[6] to select SCI on GPIO12 */
-       /* clear PMU_RxE0[6] to choose falling edge */
-       pci_read_config_byte(pdev, 0xe1, &tmp);
-       pci_write_config_byte(pdev, 0xe1, tmp & ~BIT_GPIO12);
-       pci_read_config_byte(pdev, 0xe0, &tmp);
-       pci_write_config_byte(pdev, 0xe0, tmp & ~BIT_GPIO12);
 
        dcon_clear_irq();
 
@@ -101,8 +73,6 @@ static int dcon_init_xo_1_5(struct dcon_priv *dcon)
                        DCON_SOURCE_CPU : DCON_SOURCE_DCON;
        dcon->pending_src = dcon->curr_src;
 
-       pci_dev_put(pdev);
-
        /* we're sharing the IRQ with ACPI */
        irq = acpi_gbl_FADT.sci_interrupt;
        if (request_irq(irq, &dcon_interrupt, IRQF_SHARED, "DCON", dcon)) {
index 5c0c203b887f41d5d4d6bdf4709ccd7244640072..788f64f2f4674864f071a0ba42df7800fc874766 100644 (file)
@@ -270,7 +270,7 @@ int omap_thermal_expose_sensor(struct omap_bandgap *bg_ptr, int id,
        /* Create thermal zone */
        data->omap_thermal = thermal_zone_device_register(domain,
                                OMAP_TRIP_NUMBER, 0, data, &omap_thermal_ops,
-                               FAST_TEMP_MONITORING_RATE,
+                               NULL, FAST_TEMP_MONITORING_RATE,
                                FAST_TEMP_MONITORING_RATE);
        if (IS_ERR_OR_NULL(data->omap_thermal)) {
                dev_err(bg_ptr->dev, "thermal zone device is NULL\n");
index 732f2ad34036a27654d30270acd9d1fc0f189d7f..5249223290355cc5f93406ea62d0d5f4e241de14 100644 (file)
@@ -19,7 +19,7 @@
 
 #include "omap_drv.h"
 
-#include "drm_mode.h"
+#include <drm/drm_mode.h>
 #include "drm_crtc.h"
 #include "drm_crtc_helper.h"
 
index 08b22e9f0ed7e855cbe18920ef180034d03f2bcc..273ec12c028abd13f3257cbdc7bb24628b156bf1 100644 (file)
@@ -141,8 +141,7 @@ struct refill_engine {
        /* only one trans per engine for now */
        struct dmm_txn txn;
 
-       /* offset to lut associated with container */
-       u32 *lut_offset;
+       bool async;
 
        wait_queue_head_t wait_for_refill;
 
@@ -161,10 +160,11 @@ struct dmm {
        dma_addr_t refill_pa;
 
        /* refill engines */
-       struct semaphore engine_sem;
+       wait_queue_head_t engine_queue;
        struct list_head idle_head;
        struct refill_engine *engines;
        int num_engines;
+       atomic_t engine_counter;
 
        /* container information */
        int container_width;
@@ -176,9 +176,6 @@ struct dmm {
        /* array of LUT - TCM containers */
        struct tcm **tcm;
 
-       /* LUT table storage */
-       u32 *lut;
-
        /* allocation list and lock */
        struct list_head alloc_head;
 };
index 3ae39554df1874662ff7f032186d966e51c7d8d2..4d138df369b305c065a03803c86fa1dfbe6a4902 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/mm.h>
 #include <linux/time.h>
 #include <linux/list.h>
-#include <linux/semaphore.h>
 
 #include "omap_dmm_tiler.h"
 #include "omap_dmm_priv.h"
@@ -120,6 +119,18 @@ static int wait_status(struct refill_engine *engine, uint32_t wait_mask)
        return 0;
 }
 
+static void release_engine(struct refill_engine *engine)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&list_lock, flags);
+       list_add(&engine->idle_node, &omap_dmm->idle_head);
+       spin_unlock_irqrestore(&list_lock, flags);
+
+       atomic_inc(&omap_dmm->engine_counter);
+       wake_up_interruptible(&omap_dmm->engine_queue);
+}
+
 static irqreturn_t omap_dmm_irq_handler(int irq, void *arg)
 {
        struct dmm *dmm = arg;
@@ -130,9 +141,13 @@ static irqreturn_t omap_dmm_irq_handler(int irq, void *arg)
        writel(status, dmm->base + DMM_PAT_IRQSTATUS);
 
        for (i = 0; i < dmm->num_engines; i++) {
-               if (status & DMM_IRQSTAT_LST)
+               if (status & DMM_IRQSTAT_LST) {
                        wake_up_interruptible(&dmm->engines[i].wait_for_refill);
 
+                       if (dmm->engines[i].async)
+                               release_engine(&dmm->engines[i]);
+               }
+
                status >>= 8;
        }
 
@@ -146,17 +161,24 @@ static struct dmm_txn *dmm_txn_init(struct dmm *dmm, struct tcm *tcm)
 {
        struct dmm_txn *txn = NULL;
        struct refill_engine *engine = NULL;
+       int ret;
+       unsigned long flags;
 
-       down(&dmm->engine_sem);
+
+       /* wait until an engine is available */
+       ret = wait_event_interruptible(omap_dmm->engine_queue,
+               atomic_add_unless(&omap_dmm->engine_counter, -1, 0));
+       if (ret)
+               return ERR_PTR(ret);
 
        /* grab an idle engine */
-       spin_lock(&list_lock);
+       spin_lock_irqsave(&list_lock, flags);
        if (!list_empty(&dmm->idle_head)) {
                engine = list_entry(dmm->idle_head.next, struct refill_engine,
                                        idle_node);
                list_del(&engine->idle_node);
        }
-       spin_unlock(&list_lock);
+       spin_unlock_irqrestore(&list_lock, flags);
 
        BUG_ON(!engine);
 
@@ -174,7 +196,7 @@ static struct dmm_txn *dmm_txn_init(struct dmm *dmm, struct tcm *tcm)
  * Add region to DMM transaction.  If pages or pages[i] is NULL, then the
  * corresponding slot is cleared (ie. dummy_pa is programmed)
  */
-static int dmm_txn_append(struct dmm_txn *txn, struct pat_area *area,
+static void dmm_txn_append(struct dmm_txn *txn, struct pat_area *area,
                struct page **pages, uint32_t npages, uint32_t roll)
 {
        dma_addr_t pat_pa = 0;
@@ -184,9 +206,6 @@ static int dmm_txn_append(struct dmm_txn *txn, struct pat_area *area,
        int columns = (1 + area->x1 - area->x0);
        int rows = (1 + area->y1 - area->y0);
        int i = columns*rows;
-       u32 *lut = omap_dmm->lut + (engine->tcm->lut_id * omap_dmm->lut_width *
-                       omap_dmm->lut_height) +
-                       (area->y0 * omap_dmm->lut_width) + area->x0;
 
        pat = alloc_dma(txn, sizeof(struct pat), &pat_pa);
 
@@ -209,13 +228,9 @@ static int dmm_txn_append(struct dmm_txn *txn, struct pat_area *area,
                        page_to_phys(pages[n]) : engine->dmm->dummy_pa;
        }
 
-       /* fill in lut with new addresses */
-       for (i = 0; i < rows; i++, lut += omap_dmm->lut_width)
-               memcpy(lut, &data[i*columns], columns * sizeof(u32));
-
        txn->last_pat = pat;
 
-       return 0;
+       return;
 }
 
 /**
@@ -245,6 +260,9 @@ static int dmm_txn_commit(struct dmm_txn *txn, bool wait)
                goto cleanup;
        }
 
+       /* mark whether it is async to denote list management in IRQ handler */
+       engine->async = wait ? false : true;
+
        /* kick reload */
        writel(engine->refill_pa,
                dmm->base + reg[PAT_DESCR][engine->id]);
@@ -259,11 +277,10 @@ static int dmm_txn_commit(struct dmm_txn *txn, bool wait)
        }
 
 cleanup:
-       spin_lock(&list_lock);
-       list_add(&engine->idle_node, &dmm->idle_head);
-       spin_unlock(&list_lock);
+       /* only place engine back on list if we are done with it */
+       if (ret || wait)
+               release_engine(engine);
 
-       up(&omap_dmm->engine_sem);
        return ret;
 }
 
@@ -287,16 +304,13 @@ static int fill(struct tcm_area *area, struct page **pages,
                                .x1 = slice.p1.x,  .y1 = slice.p1.y,
                };
 
-               ret = dmm_txn_append(txn, &p_area, pages, npages, roll);
-               if (ret)
-                       goto fail;
+               dmm_txn_append(txn, &p_area, pages, npages, roll);
 
                roll += tcm_sizeof(slice);
        }
 
        ret = dmm_txn_commit(txn, wait);
 
-fail:
        return ret;
 }
 
@@ -333,6 +347,7 @@ struct tiler_block *tiler_reserve_2d(enum tiler_fmt fmt, uint16_t w,
        struct tiler_block *block = kzalloc(sizeof(*block), GFP_KERNEL);
        u32 min_align = 128;
        int ret;
+       unsigned long flags;
 
        BUG_ON(!validfmt(fmt));
 
@@ -354,9 +369,9 @@ struct tiler_block *tiler_reserve_2d(enum tiler_fmt fmt, uint16_t w,
        }
 
        /* add to allocation list */
-       spin_lock(&list_lock);
+       spin_lock_irqsave(&list_lock, flags);
        list_add(&block->alloc_node, &omap_dmm->alloc_head);
-       spin_unlock(&list_lock);
+       spin_unlock_irqrestore(&list_lock, flags);
 
        return block;
 }
@@ -365,6 +380,7 @@ struct tiler_block *tiler_reserve_1d(size_t size)
 {
        struct tiler_block *block = kzalloc(sizeof(*block), GFP_KERNEL);
        int num_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+       unsigned long flags;
 
        if (!block)
                return ERR_PTR(-ENOMEM);
@@ -377,9 +393,9 @@ struct tiler_block *tiler_reserve_1d(size_t size)
                return ERR_PTR(-ENOMEM);
        }
 
-       spin_lock(&list_lock);
+       spin_lock_irqsave(&list_lock, flags);
        list_add(&block->alloc_node, &omap_dmm->alloc_head);
-       spin_unlock(&list_lock);
+       spin_unlock_irqrestore(&list_lock, flags);
 
        return block;
 }
@@ -388,13 +404,14 @@ struct tiler_block *tiler_reserve_1d(size_t size)
 int tiler_release(struct tiler_block *block)
 {
        int ret = tcm_free(&block->area);
+       unsigned long flags;
 
        if (block->area.tcm)
                dev_err(omap_dmm->dev, "failed to release block\n");
 
-       spin_lock(&list_lock);
+       spin_lock_irqsave(&list_lock, flags);
        list_del(&block->alloc_node);
-       spin_unlock(&list_lock);
+       spin_unlock_irqrestore(&list_lock, flags);
 
        kfree(block);
        return ret;
@@ -505,7 +522,7 @@ size_t tiler_vsize(enum tiler_fmt fmt, uint16_t w, uint16_t h)
        return round_up(geom[fmt].cpp * w, PAGE_SIZE) * h;
 }
 
-bool dmm_is_initialized(void)
+bool dmm_is_available(void)
 {
        return omap_dmm ? true : false;
 }
@@ -514,16 +531,17 @@ static int omap_dmm_remove(struct platform_device *dev)
 {
        struct tiler_block *block, *_block;
        int i;
+       unsigned long flags;
 
        if (omap_dmm) {
                /* free all area regions */
-               spin_lock(&list_lock);
+               spin_lock_irqsave(&list_lock, flags);
                list_for_each_entry_safe(block, _block, &omap_dmm->alloc_head,
                                        alloc_node) {
                        list_del(&block->alloc_node);
                        kfree(block);
                }
-               spin_unlock(&list_lock);
+               spin_unlock_irqrestore(&list_lock, flags);
 
                for (i = 0; i < omap_dmm->num_lut; i++)
                        if (omap_dmm->tcm && omap_dmm->tcm[i])
@@ -532,15 +550,13 @@ static int omap_dmm_remove(struct platform_device *dev)
 
                kfree(omap_dmm->engines);
                if (omap_dmm->refill_va)
-                       dma_free_coherent(omap_dmm->dev,
+                       dma_free_writecombine(omap_dmm->dev,
                                REFILL_BUFFER_SIZE * omap_dmm->num_engines,
                                omap_dmm->refill_va,
                                omap_dmm->refill_pa);
                if (omap_dmm->dummy_page)
                        __free_page(omap_dmm->dummy_page);
 
-               vfree(omap_dmm->lut);
-
                if (omap_dmm->irq > 0)
                        free_irq(omap_dmm->irq, omap_dmm);
 
@@ -556,7 +572,7 @@ static int omap_dmm_probe(struct platform_device *dev)
 {
        int ret = -EFAULT, i;
        struct tcm_area area = {0};
-       u32 hwinfo, pat_geom, lut_table_size;
+       u32 hwinfo, pat_geom;
        struct resource *mem;
 
        omap_dmm = kzalloc(sizeof(*omap_dmm), GFP_KERNEL);
@@ -569,6 +585,8 @@ static int omap_dmm_probe(struct platform_device *dev)
        INIT_LIST_HEAD(&omap_dmm->alloc_head);
        INIT_LIST_HEAD(&omap_dmm->idle_head);
 
+       init_waitqueue_head(&omap_dmm->engine_queue);
+
        /* lookup hwmod data - base address and irq */
        mem = platform_get_resource(dev, IORESOURCE_MEM, 0);
        if (!mem) {
@@ -597,6 +615,8 @@ static int omap_dmm_probe(struct platform_device *dev)
        omap_dmm->container_width = 256;
        omap_dmm->container_height = 128;
 
+       atomic_set(&omap_dmm->engine_counter, omap_dmm->num_engines);
+
        /* read out actual LUT width and height */
        pat_geom = readl(omap_dmm->base + DMM_PAT_GEOMETRY);
        omap_dmm->lut_width = ((pat_geom >> 16) & 0xF) << 5;
@@ -628,16 +648,6 @@ static int omap_dmm_probe(struct platform_device *dev)
         */
        writel(0x7e7e7e7e, omap_dmm->base + DMM_PAT_IRQENABLE_SET);
 
-       lut_table_size = omap_dmm->lut_width * omap_dmm->lut_height *
-                       omap_dmm->num_lut;
-
-       omap_dmm->lut = vmalloc(lut_table_size * sizeof(*omap_dmm->lut));
-       if (!omap_dmm->lut) {
-               dev_err(&dev->dev, "could not allocate lut table\n");
-               ret = -ENOMEM;
-               goto fail;
-       }
-
        omap_dmm->dummy_page = alloc_page(GFP_KERNEL | __GFP_DMA32);
        if (!omap_dmm->dummy_page) {
                dev_err(&dev->dev, "could not allocate dummy page\n");
@@ -652,7 +662,7 @@ static int omap_dmm_probe(struct platform_device *dev)
        omap_dmm->dummy_pa = page_to_phys(omap_dmm->dummy_page);
 
        /* alloc refill memory */
-       omap_dmm->refill_va = dma_alloc_coherent(&dev->dev,
+       omap_dmm->refill_va = dma_alloc_writecombine(&dev->dev,
                                REFILL_BUFFER_SIZE * omap_dmm->num_engines,
                                &omap_dmm->refill_pa, GFP_KERNEL);
        if (!omap_dmm->refill_va) {
@@ -670,7 +680,6 @@ static int omap_dmm_probe(struct platform_device *dev)
                goto fail;
        }
 
-       sema_init(&omap_dmm->engine_sem, omap_dmm->num_engines);
        for (i = 0; i < omap_dmm->num_engines; i++) {
                omap_dmm->engines[i].id = i;
                omap_dmm->engines[i].dmm = omap_dmm;
@@ -720,9 +729,6 @@ static int omap_dmm_probe(struct platform_device *dev)
                .p1.y = omap_dmm->container_height - 1,
        };
 
-       for (i = 0; i < lut_table_size; i++)
-               omap_dmm->lut[i] = omap_dmm->dummy_pa;
-
        /* initialize all LUTs to dummy page entries */
        for (i = 0; i < omap_dmm->num_lut; i++) {
                area.tcm = omap_dmm->tcm[i];
index 740911df5fc3d9842de401aec53d6dae1482bf09..c0271a2ac877d458e540230816992d5a81ef3d2d 100644 (file)
@@ -107,7 +107,7 @@ uint32_t tiler_stride(enum tiler_fmt fmt, uint32_t orient);
 size_t tiler_size(enum tiler_fmt fmt, uint16_t w, uint16_t h);
 size_t tiler_vsize(enum tiler_fmt fmt, uint16_t w, uint16_t h);
 void tiler_align(enum tiler_fmt fmt, uint16_t *w, uint16_t *h);
-bool dmm_is_initialized(void);
+bool dmm_is_available(void);
 
 extern struct platform_driver omap_dmm_driver;
 
@@ -139,9 +139,4 @@ static inline bool validfmt(enum tiler_fmt fmt)
        }
 }
 
-static inline int dmm_is_available(void)
-{
-       return cpu_is_omap44xx();
-}
-
 #endif
index 446801d63007d7621da0b1227178b4b47d955206..75d2ff1bf8ad18fabf3f711c29a61e5e589b5d7e 100644 (file)
@@ -253,6 +253,7 @@ int omap_framebuffer_replace(struct drm_framebuffer *a,
        int ret = 0, i, na, nb;
        struct omap_framebuffer *ofba = to_omap_framebuffer(a);
        struct omap_framebuffer *ofbb = to_omap_framebuffer(b);
+       uint32_t pinned_mask = 0;
 
        na = a ? drm_format_num_planes(a->pixel_format) : 0;
        nb = b ? drm_format_num_planes(b->pixel_format) : 0;
@@ -263,25 +264,24 @@ int omap_framebuffer_replace(struct drm_framebuffer *a,
                pa = (i < na) ? &ofba->planes[i] : NULL;
                pb = (i < nb) ? &ofbb->planes[i] : NULL;
 
-               if (pa) {
+               if (pa)
                        unpin(arg, pa->bo);
-                       pa->paddr = 0;
-               }
 
                if (pb && !ret) {
                        ret = omap_gem_get_paddr(pb->bo, &pb->paddr, true);
-                       if (!ret)
+                       if (!ret) {
                                omap_gem_dma_sync(pb->bo, DMA_TO_DEVICE);
+                               pinned_mask |= (1 << i);
+                       }
                }
        }
 
        if (ret) {
                /* something went wrong.. unpin what has been pinned */
                for (i = 0; i < nb; i++) {
-                       struct plane *pb = &ofba->planes[i];
-                       if (pb->paddr) {
+                       if (pinned_mask & (1 << i)) {
+                               struct plane *pb = &ofba->planes[i];
                                unpin(arg, pb->bo);
-                               pb->paddr = 0;
                        }
                }
        }
index 3434e6ec01426677ff576de960ffbf65440af8d6..8a9b1cee0f77486b1f928d0d789088865ed10c38 100644 (file)
@@ -246,7 +246,7 @@ static int omap_gem_attach_pages(struct drm_gem_object *obj)
         * DSS, GPU, etc. are not cache coherent:
         */
        if (omap_obj->flags & (OMAP_BO_WC|OMAP_BO_UNCACHED)) {
-               addrs = kmalloc(npages * sizeof(addrs), GFP_KERNEL);
+               addrs = kmalloc(npages * sizeof(*addrs), GFP_KERNEL);
                if (!addrs) {
                        ret = -ENOMEM;
                        goto free_pages;
@@ -257,7 +257,7 @@ static int omap_gem_attach_pages(struct drm_gem_object *obj)
                                        0, PAGE_SIZE, DMA_BIDIRECTIONAL);
                }
        } else {
-               addrs = kzalloc(npages * sizeof(addrs), GFP_KERNEL);
+               addrs = kzalloc(npages * sizeof(*addrs), GFP_KERNEL);
                if (!addrs) {
                        ret = -ENOMEM;
                        goto free_pages;
@@ -1435,7 +1435,7 @@ void omap_gem_init(struct drm_device *dev)
        };
        int i, j;
 
-       if (!dmm_is_initialized()) {
+       if (!dmm_is_available()) {
                /* DMM only supported on OMAP4 and later, so this isn't fatal */
                dev_warn(dev->dev, "DMM not available, disable DMM support\n");
                return;
index 843c54101438fa1aa30aafe564016d45aa3ba10d..3abf6619dace58319beee2be2fba640d02f059d2 100644 (file)
@@ -18,6 +18,7 @@ config ZCACHE2
 config RAMSTER
        bool "Cross-machine RAM capacity sharing, aka peer-to-peer tmem"
        depends on CONFIGFS_FS=y && SYSFS=y && !HIGHMEM && ZCACHE2=y
+       depends on NET
        # must ensure struct page is 8-byte aligned
        select HAVE_ALIGNED_STRUCT_PAGE if !64_BIT
        default n
index 13f45c3125cea39dca829cb45d8400111b502de0..502bfdbcc84ba0dd2dfff085c567830f7effe36d 100644 (file)
@@ -235,7 +235,10 @@ enum       _ReasonCode{
 
 
 
-#define aSifsTime       ((priv->ieee80211->current_network.mode == IEEE_A)||(priv->ieee80211->current_network.mode == IEEE_N_24G)||(priv->ieee80211->current_network.mode == IEEE_N_5G))? 16 : 10
+#define aSifsTime ((priv->ieee80211->current_network.mode == IEEE_A || \
+                   priv->ieee80211->current_network.mode == IEEE_N_24G || \
+                   priv->ieee80211->current_network.mode == IEEE_N_5G) ? \
+                  16 : 10)
 
 #define MGMT_QUEUE_NUM 5
 
index c9a6a7fbb89c53d0946f0b3c1910bd8324955018..3a6479064519aafea0cce74b53e6b156451e7c47 100644 (file)
@@ -2110,10 +2110,10 @@ static int r871x_wps_start(struct net_device *dev,
        struct iw_point *pdata = &wrqu->data;
        u32   u32wps_start = 0;
 
-       if (copy_from_user((void *)&u32wps_start, pdata->pointer, 4))
-               return -EFAULT;
        if ((padapter->bDriverStopped) || (pdata == NULL))
                return -EINVAL;
+       if (copy_from_user((void *)&u32wps_start, pdata->pointer, 4))
+               return -EFAULT;
        if (u32wps_start == 0)
                u32wps_start = *extra;
        if (u32wps_start == 1) /* WPS Start */
index 82b8958e8d31b6b8b813921227639781fb16e157..75dd31224e62e35aa250e8595d90d8b71150ae86 100644 (file)
 # Makefile for the RTS51xx USB Card Reader drivers.
 #
 
-TARGET_MODULE := rts5139
+obj-$(CONFIG_RTS5139) := rts5139.o
 
-EXTRA_CFLAGS := -Idrivers/scsi -I$(PWD)
+ccflags-y := -Idrivers/scsi
 
-obj-m += $(TARGET_MODULE).o
-
-common-obj := rts51x_transport.o rts51x_scsi.o rts51x_fop.o
-
-$(TARGET_MODULE)-objs := $(common-obj) rts51x.o rts51x_chip.o rts51x_card.o \
-               xd.o sd.o ms.o sd_cprm.o ms_mg.o
+rts5139-y :=                           \
+               rts51x_transport.o      \
+               rts51x_scsi.o           \
+               rts51x_fop.o            \
+               rts51x.o                \
+               rts51x_chip.o           \
+               rts51x_card.o           \
+               xd.o                    \
+               sd.o                    \
+               ms.o                    \
+               sd_cprm.o               \
+               ms_mg.o
index 6eef33b03f553b817098e0eea19517b0ba971186..a27f7e224e032e9749582b6d748aa45b7e7784d9 100644 (file)
@@ -160,7 +160,7 @@ int ms_transfer_data(struct rts51x_chip *chip, u8 trans_mode, u8 tpc,
                rts51x_add_cmd(chip, WRITE_REG_CMD, MS_CFG, MS_2K_SECTOR_MODE,
                               0);
 
-       trans_dma_enable(dir, chip, sec_cnt * 512, DMA_512);
+       rts51x_trans_dma_enable(dir, chip, sec_cnt * 512, DMA_512);
 
        rts51x_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER, 0xFF,
                       MS_TRANSFER_START | trans_mode);
@@ -602,7 +602,7 @@ static int ms_prepare_reset(struct rts51x_chip *chip)
        if (!chip->option.FT2_fast_mode) {
                wait_timeout(250);
 
-               card_power_on(chip, MS_CARD);
+               rts51x_card_power_on(chip, MS_CARD);
                wait_timeout(150);
 
 #ifdef SUPPORT_OCP
@@ -872,7 +872,7 @@ static int msxc_change_power(struct rts51x_chip *chip, u8 mode)
        int retval;
        u8 buf[6];
 
-       ms_cleanup_work(chip);
+       rts51x_ms_cleanup_work(chip);
 
        /* Set Parameter Register */
        retval = ms_set_rw_reg_addr(chip, 0, 0, Pro_DataCount1, 6);
@@ -2600,14 +2600,14 @@ BUILD_FAIL:
        return STATUS_FAIL;
 }
 
-int reset_ms_card(struct rts51x_chip *chip)
+int rts51x_reset_ms_card(struct rts51x_chip *chip)
 {
        struct ms_info *ms_card = &(chip->ms_card);
        int retval;
 
        memset(ms_card, 0, sizeof(struct ms_info));
 
-       enable_card_clock(chip, MS_CARD);
+       rts51x_enable_card_clock(chip, MS_CARD);
 
        retval = rts51x_select_card(chip, MS_CARD);
        if (retval != STATUS_SUCCESS)
@@ -2936,7 +2936,7 @@ static int mspro_read_format_progress(struct rts51x_chip *chip,
        return STATUS_SUCCESS;
 }
 
-void mspro_polling_format_status(struct rts51x_chip *chip)
+void rts51x_mspro_polling_format_status(struct rts51x_chip *chip)
 {
        struct ms_info *ms_card = &(chip->ms_card);
        int i;
@@ -2952,25 +2952,25 @@ void mspro_polling_format_status(struct rts51x_chip *chip)
        return;
 }
 
-void mspro_format_sense(struct rts51x_chip *chip, unsigned int lun)
+void rts51x_mspro_format_sense(struct rts51x_chip *chip, unsigned int lun)
 {
        struct ms_info *ms_card = &(chip->ms_card);
 
        if (CHK_FORMAT_STATUS(ms_card, FORMAT_SUCCESS)) {
-               set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE);
                ms_card->pro_under_formatting = 0;
                ms_card->progress = 0;
        } else if (CHK_FORMAT_STATUS(ms_card, FORMAT_IN_PROGRESS)) {
-               set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x04, 0x04,
+               rts51x_set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x04, 0x04,
                               0, (u16) (ms_card->progress));
        } else {
-               set_sense_type(chip, lun, SENSE_TYPE_FORMAT_CMD_FAILED);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_FORMAT_CMD_FAILED);
                ms_card->pro_under_formatting = 0;
                ms_card->progress = 0;
        }
 }
 
-int mspro_format(struct scsi_cmnd *srb, struct rts51x_chip *chip,
+int rts51x_mspro_format(struct scsi_cmnd *srb, struct rts51x_chip *chip,
                 int short_data_len, int quick_format)
 {
        struct ms_info *ms_card = &(chip->ms_card);
@@ -3035,7 +3035,7 @@ int mspro_format(struct scsi_cmnd *srb, struct rts51x_chip *chip,
                ms_card->pro_under_formatting = 0;
                ms_card->progress = 0;
                ms_card->format_status = FORMAT_SUCCESS;
-               set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_NO_SENSE);
+               rts51x_set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_NO_SENSE);
                return STATUS_SUCCESS;
        }
 
@@ -3103,7 +3103,7 @@ static int ms_read_multiple_pages(struct rts51x_chip *chip, u16 phy_blk,
        rts51x_add_cmd(chip, WRITE_REG_CMD, MS_SECTOR_CNT_H, 0xFF, 0);
        rts51x_add_cmd(chip, WRITE_REG_CMD, MS_TPC, 0xFF, READ_PAGE_DATA);
 
-       trans_dma_enable(DMA_FROM_DEVICE, chip, 512 * page_cnt, DMA_512);
+       rts51x_trans_dma_enable(DMA_FROM_DEVICE, chip, 512 * page_cnt, DMA_512);
 
        rts51x_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER, 0xFF,
                       MS_TRANSFER_START | MS_TM_MULTI_READ);
@@ -3307,7 +3307,7 @@ static int ms_write_multiple_pages(struct rts51x_chip *chip, u16 old_blk,
        rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01,
                       RING_BUFFER);
 
-       trans_dma_enable(DMA_TO_DEVICE, chip, 512 * page_cnt, DMA_512);
+       rts51x_trans_dma_enable(DMA_TO_DEVICE, chip, 512 * page_cnt, DMA_512);
 
        rts51x_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER, 0xFF,
                       MS_TRANSFER_START | MS_TM_MULTI_WRITE);
@@ -3467,7 +3467,7 @@ static int ms_read_multiple_pages(struct rts51x_chip *chip, u16 phy_blk,
                rts51x_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF,
                               trans_cfg);
 
-               trans_dma_enable(DMA_FROM_DEVICE, chip, 512, DMA_512);
+               rts51x_trans_dma_enable(DMA_FROM_DEVICE, chip, 512, DMA_512);
 
                rts51x_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER, 0xFF,
                               MS_TRANSFER_START | MS_TM_NORMAL_READ);
@@ -3670,7 +3670,7 @@ static int ms_write_multiple_pages(struct rts51x_chip *chip, u16 old_blk,
                rts51x_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF,
                               WAIT_INT);
 
-               trans_dma_enable(DMA_TO_DEVICE, chip, 512, DMA_512);
+               rts51x_trans_dma_enable(DMA_TO_DEVICE, chip, 512, DMA_512);
 
                rts51x_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER, 0xFF,
                               MS_TRANSFER_START | MS_TM_NORMAL_WRITE);
@@ -3803,10 +3803,10 @@ static int ms_prepare_write(struct rts51x_chip *chip, u16 old_blk, u16 new_blk,
        return STATUS_SUCCESS;
 }
 
-int ms_delay_write(struct rts51x_chip *chip)
+int rts51x_ms_delay_write(struct rts51x_chip *chip)
 {
        struct ms_info *ms_card = &(chip->ms_card);
-       struct ms_delay_write_tag *delay_write = &(ms_card->delay_write);
+       struct rts51x_ms_delay_write_tag *delay_write = &(ms_card->delay_write);
        int retval;
 
        if (delay_write->delay_write_flag) {
@@ -3827,16 +3827,16 @@ int ms_delay_write(struct rts51x_chip *chip)
        return STATUS_SUCCESS;
 }
 
-static inline void ms_rw_fail(struct scsi_cmnd *srb, struct rts51x_chip *chip)
+static inline void rts51x_ms_rw_fail(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 {
        if (srb->sc_data_direction == DMA_FROM_DEVICE)
-               set_sense_type(chip, SCSI_LUN(srb),
+               rts51x_set_sense_type(chip, SCSI_LUN(srb),
                               SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
        else
-               set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
+               rts51x_set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
 }
 
-static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rts51x_chip *chip,
+static int rts51x_ms_rw_multi_sector(struct scsi_cmnd *srb, struct rts51x_chip *chip,
                              u32 start_sector, u16 sector_cnt)
 {
        struct ms_info *ms_card = &(chip->ms_card);
@@ -3847,7 +3847,7 @@ static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rts51x_chip *chip,
        u8 start_page, end_page = 0, page_cnt;
        u8 *buf;
        void *ptr = NULL;
-       struct ms_delay_write_tag *delay_write = &(ms_card->delay_write);
+       struct rts51x_ms_delay_write_tag *delay_write = &(ms_card->delay_write);
 
        ms_set_err_code(chip, MS_NO_ERROR);
 
@@ -3857,7 +3857,7 @@ static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rts51x_chip *chip,
 
        retval = ms_switch_clock(chip);
        if (retval != STATUS_SUCCESS) {
-               ms_rw_fail(srb, chip);
+               rts51x_ms_rw_fail(srb, chip);
                TRACE_RET(chip, retval);
        }
 
@@ -3873,7 +3873,7 @@ static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rts51x_chip *chip,
                retval = ms_build_l2p_tbl(chip, seg_no);
                if (retval != STATUS_SUCCESS) {
                        chip->card_fail |= MS_CARD;
-                       set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+                       rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
                        TRACE_RET(chip, retval);
                }
        }
@@ -3898,7 +3898,7 @@ static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rts51x_chip *chip,
                                              start_page);
 #endif
                        if (retval != STATUS_SUCCESS) {
-                               set_sense_type(chip, lun,
+                               rts51x_set_sense_type(chip, lun,
                                               SENSE_TYPE_MEDIA_WRITE_ERR);
                                TRACE_RET(chip, retval);
                        }
@@ -3911,9 +3911,9 @@ static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rts51x_chip *chip,
                        old_blk = delay_write->old_phyblock;
                        new_blk = delay_write->new_phyblock;
                } else {
-                       retval = ms_delay_write(chip);
+                       retval = rts51x_ms_delay_write(chip);
                        if (retval != STATUS_SUCCESS) {
-                               set_sense_type(chip, lun,
+                               rts51x_set_sense_type(chip, lun,
                                               SENSE_TYPE_MEDIA_WRITE_ERR);
                                TRACE_RET(chip, retval);
                        }
@@ -3922,7 +3922,7 @@ static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rts51x_chip *chip,
                                           log_blk - ms_start_idx[seg_no]);
                        new_blk = ms_get_unused_block(chip, seg_no);
                        if ((old_blk == 0xFFFF) || (new_blk == 0xFFFF)) {
-                               set_sense_type(chip, lun,
+                               rts51x_set_sense_type(chip, lun,
                                               SENSE_TYPE_MEDIA_WRITE_ERR);
                                TRACE_RET(chip, STATUS_FAIL);
                        }
@@ -3933,26 +3933,26 @@ static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rts51x_chip *chip,
                        if (retval != STATUS_SUCCESS) {
                                if (monitor_card_cd(chip, MS_CARD) ==
                                    CD_NOT_EXIST) {
-                                       set_sense_type(chip, lun,
+                                       rts51x_set_sense_type(chip, lun,
                                                SENSE_TYPE_MEDIA_NOT_PRESENT);
                                        TRACE_RET(chip, STATUS_FAIL);
                                }
 
-                               set_sense_type(chip, lun,
+                               rts51x_set_sense_type(chip, lun,
                                               SENSE_TYPE_MEDIA_WRITE_ERR);
                                TRACE_RET(chip, retval);
                        }
                }
        } else {
-               retval = ms_delay_write(chip);
+               retval = rts51x_ms_delay_write(chip);
                if (retval != STATUS_SUCCESS) {
                        if (monitor_card_cd(chip, MS_CARD) == CD_NOT_EXIST) {
-                               set_sense_type(chip, lun,
+                               rts51x_set_sense_type(chip, lun,
                                               SENSE_TYPE_MEDIA_NOT_PRESENT);
                                TRACE_RET(chip, STATUS_FAIL);
                        }
 
-                       set_sense_type(chip, lun,
+                       rts51x_set_sense_type(chip, lun,
                                       SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
                        TRACE_RET(chip, retval);
                }
@@ -3960,7 +3960,7 @@ static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rts51x_chip *chip,
                    ms_get_l2p_tbl(chip, seg_no,
                                   log_blk - ms_start_idx[seg_no]);
                if (old_blk == 0xFFFF) {
-                       set_sense_type(chip, lun,
+                       rts51x_set_sense_type(chip, lun,
                                       SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
                        TRACE_RET(chip, STATUS_FAIL);
                }
@@ -3993,12 +3993,12 @@ static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rts51x_chip *chip,
 
                if (retval != STATUS_SUCCESS) {
                        if (monitor_card_cd(chip, MS_CARD) == CD_NOT_EXIST) {
-                               set_sense_type(chip, lun,
+                               rts51x_set_sense_type(chip, lun,
                                               SENSE_TYPE_MEDIA_NOT_PRESENT);
                                TRACE_RET(chip, STATUS_FAIL);
                        }
 
-                       ms_rw_fail(srb, chip);
+                       rts51x_ms_rw_fail(srb, chip);
                        TRACE_RET(chip, retval);
                }
                /* Update L2P table if need */
@@ -4030,7 +4030,7 @@ static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rts51x_chip *chip,
                        retval = ms_build_l2p_tbl(chip, seg_no);
                        if (retval != STATUS_SUCCESS) {
                                chip->card_fail |= MS_CARD;
-                               set_sense_type(chip, lun,
+                               rts51x_set_sense_type(chip, lun,
                                               SENSE_TYPE_MEDIA_NOT_PRESENT);
                                TRACE_RET(chip, retval);
                        }
@@ -4040,14 +4040,14 @@ static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rts51x_chip *chip,
                    ms_get_l2p_tbl(chip, seg_no,
                                   log_blk - ms_start_idx[seg_no]);
                if (old_blk == 0xFFFF) {
-                       ms_rw_fail(srb, chip);
+                       rts51x_ms_rw_fail(srb, chip);
                        TRACE_RET(chip, STATUS_FAIL);
                }
 
                if (srb->sc_data_direction == DMA_TO_DEVICE) {
                        new_blk = ms_get_unused_block(chip, seg_no);
                        if (new_blk == 0xFFFF) {
-                               ms_rw_fail(srb, chip);
+                               rts51x_ms_rw_fail(srb, chip);
                                TRACE_RET(chip, STATUS_FAIL);
                        }
                }
@@ -4073,7 +4073,7 @@ static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rts51x_chip *chip,
        return STATUS_SUCCESS;
 }
 
-int ms_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
+int rts51x_ms_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
          u16 sector_cnt)
 {
        struct ms_info *ms_card = &(chip->ms_card);
@@ -4084,12 +4084,12 @@ int ms_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
                    mspro_rw_multi_sector(srb, chip, start_sector, sector_cnt);
        else
                retval =
-                   ms_rw_multi_sector(srb, chip, start_sector, sector_cnt);
+                   rts51x_ms_rw_multi_sector(srb, chip, start_sector, sector_cnt);
 
        return retval;
 }
 
-void ms_free_l2p_tbl(struct rts51x_chip *chip)
+void rts51x_ms_free_l2p_tbl(struct rts51x_chip *chip)
 {
        struct ms_info *ms_card = &(chip->ms_card);
        int i = 0;
@@ -4110,7 +4110,7 @@ void ms_free_l2p_tbl(struct rts51x_chip *chip)
        }
 }
 
-void ms_cleanup_work(struct rts51x_chip *chip)
+void rts51x_ms_cleanup_work(struct rts51x_chip *chip)
 {
        struct ms_info *ms_card = &(chip->ms_card);
 
@@ -4130,7 +4130,7 @@ void ms_cleanup_work(struct rts51x_chip *chip)
        } else if ((!CHK_MSPRO(ms_card))
                   && ms_card->delay_write.delay_write_flag) {
                RTS51X_DEBUGP("MS: delay write\n");
-               ms_delay_write(chip);
+               rts51x_ms_delay_write(chip);
                ms_card->counter = 0;
        }
 }
@@ -4161,12 +4161,12 @@ static int ms_power_off_card3v3(struct rts51x_chip *chip)
        return STATUS_SUCCESS;
 }
 
-int release_ms_card(struct rts51x_chip *chip)
+int rts51x_release_ms_card(struct rts51x_chip *chip)
 {
        struct ms_info *ms_card = &(chip->ms_card);
        int retval;
 
-       RTS51X_DEBUGP("release_ms_card\n");
+       RTS51X_DEBUGP("rts51x_release_ms_card\n");
 
        ms_card->delay_write.delay_write_flag = 0;
        ms_card->pro_under_formatting = 0;
@@ -4175,7 +4175,7 @@ int release_ms_card(struct rts51x_chip *chip)
        chip->card_fail &= ~MS_CARD;
        chip->card_wp &= ~MS_CARD;
 
-       ms_free_l2p_tbl(chip);
+       rts51x_ms_free_l2p_tbl(chip);
 
        rts51x_write_register(chip, SFSM_ED, HW_CMD_STOP, HW_CMD_STOP);
 
index 0321d06e776dba3377f43cbd559cf504735a43e1..857c1974ef240e50a6188e78830525ba958e1bbc 100644 (file)
        (((retval) != STATUS_SUCCESS) || \
        (chip->rsp_buf[0] & MS_TRANSFER_ERR))
 
-void mspro_polling_format_status(struct rts51x_chip *chip);
-void mspro_format_sense(struct rts51x_chip *chip, unsigned int lun);
+void rts51x_mspro_polling_format_status(struct rts51x_chip *chip);
+void rts51x_mspro_format_sense(struct rts51x_chip *chip, unsigned int lun);
 
-int reset_ms_card(struct rts51x_chip *chip);
-int ms_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
+int rts51x_reset_ms_card(struct rts51x_chip *chip);
+int rts51x_ms_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
          u16 sector_cnt);
-int mspro_format(struct scsi_cmnd *srb, struct rts51x_chip *chip,
+int rts51x_mspro_format(struct scsi_cmnd *srb, struct rts51x_chip *chip,
                 int short_data_len, int quick_format);
-void ms_free_l2p_tbl(struct rts51x_chip *chip);
-void ms_cleanup_work(struct rts51x_chip *chip);
-int release_ms_card(struct rts51x_chip *chip);
-int ms_delay_write(struct rts51x_chip *chip);
+void rts51x_ms_free_l2p_tbl(struct rts51x_chip *chip);
+void rts51x_ms_cleanup_work(struct rts51x_chip *chip);
+int rts51x_release_ms_card(struct rts51x_chip *chip);
+int rts51x_ms_delay_write(struct rts51x_chip *chip);
 
 #ifdef SUPPORT_MAGIC_GATE
 
index 057d96c1a937173c6c85bc20f1c37699df79842c..54cfd85259a9254b207a8b2205f003a7ecb8f834 100644 (file)
@@ -119,7 +119,7 @@ int mg_set_tpc_para_sub(struct rts51x_chip *chip, int type, u8 mg_entry_num)
   * 2. send SET_ID TPC command to medium with Leaf ID released by host
   * in this SCSI CMD.
   */
-int mg_set_leaf_id(struct scsi_cmnd *srb, struct rts51x_chip *chip)
+int rts51x_mg_set_leaf_id(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 {
        int retval;
        int i;
@@ -129,10 +129,10 @@ int mg_set_leaf_id(struct scsi_cmnd *srb, struct rts51x_chip *chip)
        RTS51X_DEBUGP("--%s--\n", __func__);
 
        if (scsi_bufflen(srb) < 12) {
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
                TRACE_RET(chip, STATUS_FAIL);
        }
-       ms_cleanup_work(chip);
+       rts51x_ms_cleanup_work(chip);
 
        retval = ms_switch_clock(chip);
        if (retval != STATUS_SUCCESS)
@@ -140,7 +140,7 @@ int mg_set_leaf_id(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 
        retval = mg_send_ex_cmd(chip, MG_SET_LID, 0);
        if (retval != STATUS_SUCCESS) {
-               set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
                TRACE_RET(chip, retval);
        }
 
@@ -151,12 +151,12 @@ int mg_set_leaf_id(struct scsi_cmnd *srb, struct rts51x_chip *chip)
        retval =
            ms_write_bytes(chip, PRO_WRITE_SHORT_DATA, 32, WAIT_INT, buf1, 32);
        if (retval != STATUS_SUCCESS) {
-               set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
                TRACE_RET(chip, retval);
        }
        retval = mg_check_int_error(chip);
        if (retval != STATUS_SUCCESS) {
-               set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
                TRACE_RET(chip, retval);
        }
 
@@ -170,7 +170,7 @@ int mg_set_leaf_id(struct scsi_cmnd *srb, struct rts51x_chip *chip)
   * data(1536 bytes totally) from medium by using READ_LONG_DATA TPC
   * for 3 times, and report data to host with data-length is 1052 bytes.
   */
-int mg_get_local_EKB(struct scsi_cmnd *srb, struct rts51x_chip *chip)
+int rts51x_mg_get_local_EKB(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 {
        int retval = STATUS_FAIL;
        int bufflen;
@@ -179,7 +179,7 @@ int mg_get_local_EKB(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 
        RTS51X_DEBUGP("--%s--\n", __func__);
 
-       ms_cleanup_work(chip);
+       rts51x_ms_cleanup_work(chip);
 
        retval = ms_switch_clock(chip);
        if (retval != STATUS_SUCCESS)
@@ -196,21 +196,21 @@ int mg_get_local_EKB(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 
        retval = mg_send_ex_cmd(chip, MG_GET_LEKB, 0);
        if (retval != STATUS_SUCCESS) {
-               set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
                TRACE_GOTO(chip, GetEKBFinish);
        }
 
        retval = ms_transfer_data(chip, MS_TM_AUTO_READ, PRO_READ_LONG_DATA,
                                  3, WAIT_INT, 0, 0, buf + 4, 1536);
        if (retval != STATUS_SUCCESS) {
-               set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
                rts51x_write_register(chip, CARD_STOP, MS_STOP | MS_CLR_ERR,
                                      MS_STOP | MS_CLR_ERR);
                TRACE_GOTO(chip, GetEKBFinish);
        }
        retval = mg_check_int_error(chip);
        if (retval != STATUS_SUCCESS) {
-               set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
                TRACE_GOTO(chip, GetEKBFinish);
        }
 
@@ -229,7 +229,7 @@ GetEKBFinish:
   * TPC commands to the medium for writing 8-bytes data as challenge
   * by host within a short data packet.
   */
-int mg_chg(struct scsi_cmnd *srb, struct rts51x_chip *chip)
+int rts51x_mg_chg(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 {
        struct ms_info *ms_card = &(chip->ms_card);
        int retval;
@@ -240,7 +240,7 @@ int mg_chg(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 
        RTS51X_DEBUGP("--%s--\n", __func__);
 
-       ms_cleanup_work(chip);
+       rts51x_ms_cleanup_work(chip);
 
        retval = ms_switch_clock(chip);
        if (retval != STATUS_SUCCESS)
@@ -248,19 +248,19 @@ int mg_chg(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 
        retval = mg_send_ex_cmd(chip, MG_GET_ID, 0);
        if (retval != STATUS_SUCCESS) {
-               set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
                TRACE_RET(chip, retval);
        }
 
        retval =
            ms_read_bytes(chip, PRO_READ_SHORT_DATA, 32, WAIT_INT, buf, 32);
        if (retval != STATUS_SUCCESS) {
-               set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
                TRACE_RET(chip, retval);
        }
        retval = mg_check_int_error(chip);
        if (retval != STATUS_SUCCESS) {
-               set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
                TRACE_RET(chip, retval);
        }
 
@@ -276,13 +276,13 @@ int mg_chg(struct scsi_cmnd *srb, struct rts51x_chip *chip)
        }
 
        if (i == 2500) {
-               set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
                TRACE_RET(chip, STATUS_FAIL);
        }
 
        retval = mg_send_ex_cmd(chip, MG_SET_RD, 0);
        if (retval != STATUS_SUCCESS) {
-               set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
                TRACE_RET(chip, retval);
        }
 
@@ -296,12 +296,12 @@ int mg_chg(struct scsi_cmnd *srb, struct rts51x_chip *chip)
        retval =
            ms_write_bytes(chip, PRO_WRITE_SHORT_DATA, 32, WAIT_INT, buf, 32);
        if (retval != STATUS_SUCCESS) {
-               set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
                TRACE_RET(chip, retval);
        }
        retval = mg_check_int_error(chip);
        if (retval != STATUS_SUCCESS) {
-               set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
                TRACE_RET(chip, retval);
        }
 
@@ -320,7 +320,7 @@ int mg_chg(struct scsi_cmnd *srb, struct rts51x_chip *chip)
   * The paremeter MagicGateID is the one that adapter has obtained from
   * the medium by TPC commands in Set Leaf ID command phase previously.
   */
-int mg_get_rsp_chg(struct scsi_cmnd *srb, struct rts51x_chip *chip)
+int rts51x_mg_get_rsp_chg(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 {
        struct ms_info *ms_card = &(chip->ms_card);
        int retval, i;
@@ -330,7 +330,7 @@ int mg_get_rsp_chg(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 
        RTS51X_DEBUGP("--%s--\n", __func__);
 
-       ms_cleanup_work(chip);
+       rts51x_ms_cleanup_work(chip);
 
        retval = ms_switch_clock(chip);
        if (retval != STATUS_SUCCESS)
@@ -338,19 +338,19 @@ int mg_get_rsp_chg(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 
        retval = mg_send_ex_cmd(chip, MG_MAKE_RMS, 0);
        if (retval != STATUS_SUCCESS) {
-               set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
                TRACE_RET(chip, retval);
        }
 
        retval =
            ms_read_bytes(chip, PRO_READ_SHORT_DATA, 32, WAIT_INT, buf1, 32);
        if (retval != STATUS_SUCCESS) {
-               set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
                TRACE_RET(chip, retval);
        }
        retval = mg_check_int_error(chip);
        if (retval != STATUS_SUCCESS) {
-               set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
                TRACE_RET(chip, retval);
        }
 
@@ -375,7 +375,7 @@ int mg_get_rsp_chg(struct scsi_cmnd *srb, struct rts51x_chip *chip)
        }
 
        if (i == 2500) {
-               set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
                TRACE_RET(chip, STATUS_FAIL);
        }
 
@@ -389,7 +389,7 @@ int mg_get_rsp_chg(struct scsi_cmnd *srb, struct rts51x_chip *chip)
   * issues TPC commands to the medium for writing 8-bytes data as
   * challenge by host within a short data packet.
   */
-int mg_rsp(struct scsi_cmnd *srb, struct rts51x_chip *chip)
+int rts51x_mg_rsp(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 {
        struct ms_info *ms_card = &(chip->ms_card);
        int retval;
@@ -400,7 +400,7 @@ int mg_rsp(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 
        RTS51X_DEBUGP("--%s--\n", __func__);
 
-       ms_cleanup_work(chip);
+       rts51x_ms_cleanup_work(chip);
 
        retval = ms_switch_clock(chip);
        if (retval != STATUS_SUCCESS)
@@ -408,7 +408,7 @@ int mg_rsp(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 
        retval = mg_send_ex_cmd(chip, MG_MAKE_KSE, 0);
        if (retval != STATUS_SUCCESS) {
-               set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
                TRACE_RET(chip, retval);
        }
 
@@ -422,12 +422,12 @@ int mg_rsp(struct scsi_cmnd *srb, struct rts51x_chip *chip)
        retval =
            ms_write_bytes(chip, PRO_WRITE_SHORT_DATA, 32, WAIT_INT, buf, 32);
        if (retval != STATUS_SUCCESS) {
-               set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
                TRACE_RET(chip, retval);
        }
        retval = mg_check_int_error(chip);
        if (retval != STATUS_SUCCESS) {
-               set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
                TRACE_RET(chip, retval);
        }
 
@@ -447,7 +447,7 @@ int mg_rsp(struct scsi_cmnd *srb, struct rts51x_chip *chip)
   * precedes data transmission from medium to Ring buffer by DMA mechanism
   * in order to get maximum performance and minimum code size simultaneously.
   */
-int mg_get_ICV(struct scsi_cmnd *srb, struct rts51x_chip *chip)
+int rts51x_mg_get_ICV(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 {
        struct ms_info *ms_card = &(chip->ms_card);
        int retval;
@@ -457,7 +457,7 @@ int mg_get_ICV(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 
        RTS51X_DEBUGP("--%s--\n", __func__);
 
-       ms_cleanup_work(chip);
+       rts51x_ms_cleanup_work(chip);
 
        retval = ms_switch_clock(chip);
        if (retval != STATUS_SUCCESS)
@@ -474,21 +474,21 @@ int mg_get_ICV(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 
        retval = mg_send_ex_cmd(chip, MG_GET_IBD, ms_card->mg_entry_num);
        if (retval != STATUS_SUCCESS) {
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
                TRACE_GOTO(chip, GetICVFinish);
        }
 
        retval = ms_transfer_data(chip, MS_TM_AUTO_READ, PRO_READ_LONG_DATA,
                                  2, WAIT_INT, 0, 0, buf + 4, 1024);
        if (retval != STATUS_SUCCESS) {
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
                rts51x_write_register(chip, CARD_STOP, MS_STOP | MS_CLR_ERR,
                                      MS_STOP | MS_CLR_ERR);
                TRACE_GOTO(chip, GetICVFinish);
        }
        retval = mg_check_int_error(chip);
        if (retval != STATUS_SUCCESS) {
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
                TRACE_GOTO(chip, GetICVFinish);
        }
 
@@ -511,7 +511,7 @@ GetICVFinish:
   * that sent by host, and it should be skipped by shifting DMA pointer
   * before writing 1024 bytes to medium.
   */
-int mg_set_ICV(struct scsi_cmnd *srb, struct rts51x_chip *chip)
+int rts51x_mg_set_ICV(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 {
        struct ms_info *ms_card = &(chip->ms_card);
        int retval;
@@ -524,7 +524,7 @@ int mg_set_ICV(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 
        RTS51X_DEBUGP("--%s--\n", __func__);
 
-       ms_cleanup_work(chip);
+       rts51x_ms_cleanup_work(chip);
 
        retval = ms_switch_clock(chip);
        if (retval != STATUS_SUCCESS)
@@ -541,13 +541,13 @@ int mg_set_ICV(struct scsi_cmnd *srb, struct rts51x_chip *chip)
        if (retval != STATUS_SUCCESS) {
                if (ms_card->mg_auth == 0) {
                        if ((buf[5] & 0xC0) != 0)
-                               set_sense_type(chip, lun,
+                               rts51x_set_sense_type(chip, lun,
                                        SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
                        else
-                               set_sense_type(chip, lun,
+                               rts51x_set_sense_type(chip, lun,
                                        SENSE_TYPE_MG_WRITE_ERR);
                } else {
-                       set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR);
+                       rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR);
                }
                TRACE_GOTO(chip, SetICVFinish);
        }
@@ -563,7 +563,7 @@ int mg_set_ICV(struct scsi_cmnd *srb, struct rts51x_chip *chip)
                rts51x_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF,
                               WAIT_INT);
 
-               trans_dma_enable(DMA_TO_DEVICE, chip, 512, DMA_512);
+               rts51x_trans_dma_enable(DMA_TO_DEVICE, chip, 512, DMA_512);
 
                rts51x_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER, 0xFF,
                               MS_TRANSFER_START | MS_TM_NORMAL_WRITE);
@@ -572,7 +572,7 @@ int mg_set_ICV(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 
                retval = rts51x_send_cmd(chip, MODE_CDOR, 100);
                if (retval != STATUS_SUCCESS) {
-                       set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR);
+                       rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR);
                        TRACE_GOTO(chip, SetICVFinish);
                }
 
@@ -583,13 +583,13 @@ int mg_set_ICV(struct scsi_cmnd *srb, struct rts51x_chip *chip)
                        rts51x_clear_ms_error(chip);
                        if (ms_card->mg_auth == 0) {
                                if ((buf[5] & 0xC0) != 0)
-                                       set_sense_type(chip, lun,
+                                       rts51x_set_sense_type(chip, lun,
                                                SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
                                else
-                                       set_sense_type(chip, lun,
+                                       rts51x_set_sense_type(chip, lun,
                                                SENSE_TYPE_MG_WRITE_ERR);
                        } else {
-                               set_sense_type(chip, lun,
+                               rts51x_set_sense_type(chip, lun,
                                               SENSE_TYPE_MG_WRITE_ERR);
                        }
                        retval = STATUS_FAIL;
@@ -602,13 +602,13 @@ int mg_set_ICV(struct scsi_cmnd *srb, struct rts51x_chip *chip)
                        rts51x_clear_ms_error(chip);
                        if (ms_card->mg_auth == 0) {
                                if ((buf[5] & 0xC0) != 0)
-                                       set_sense_type(chip, lun,
+                                       rts51x_set_sense_type(chip, lun,
                                                SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
                                else
-                                       set_sense_type(chip, lun,
+                                       rts51x_set_sense_type(chip, lun,
                                                SENSE_TYPE_MG_WRITE_ERR);
                        } else {
-                               set_sense_type(chip, lun,
+                               rts51x_set_sense_type(chip, lun,
                                               SENSE_TYPE_MG_WRITE_ERR);
                        }
                        retval = STATUS_FAIL;
@@ -622,13 +622,13 @@ int mg_set_ICV(struct scsi_cmnd *srb, struct rts51x_chip *chip)
                rts51x_clear_ms_error(chip);
                if (ms_card->mg_auth == 0) {
                        if ((buf[5] & 0xC0) != 0)
-                               set_sense_type(chip, lun,
+                               rts51x_set_sense_type(chip, lun,
                                        SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
                        else
-                               set_sense_type(chip, lun,
+                               rts51x_set_sense_type(chip, lun,
                                        SENSE_TYPE_MG_WRITE_ERR);
                } else {
-                       set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR);
+                       rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR);
                }
                TRACE_GOTO(chip, SetICVFinish);
        }
index e2ca55085f97dc03910c474d5b45a6f34304c4f0..d15733a992ae5f17295ac4461a0cbf868323f9d5 100644 (file)
 #include "rts51x_chip.h"
 #include "ms.h"
 
-int mg_set_leaf_id(struct scsi_cmnd *srb, struct rts51x_chip *chip);
-int mg_get_local_EKB(struct scsi_cmnd *srb, struct rts51x_chip *chip);
-int mg_chg(struct scsi_cmnd *srb, struct rts51x_chip *chip);
-int mg_get_rsp_chg(struct scsi_cmnd *srb, struct rts51x_chip *chip);
-int mg_rsp(struct scsi_cmnd *srb, struct rts51x_chip *chip);
-int mg_get_ICV(struct scsi_cmnd *srb, struct rts51x_chip *chip);
-int mg_set_ICV(struct scsi_cmnd *srb, struct rts51x_chip *chip);
+int rts51x_mg_set_leaf_id(struct scsi_cmnd *srb, struct rts51x_chip *chip);
+int rts51x_mg_get_local_EKB(struct scsi_cmnd *srb, struct rts51x_chip *chip);
+int rts51x_mg_chg(struct scsi_cmnd *srb, struct rts51x_chip *chip);
+int rts51x_mg_get_rsp_chg(struct scsi_cmnd *srb, struct rts51x_chip *chip);
+int rts51x_mg_rsp(struct scsi_cmnd *srb, struct rts51x_chip *chip);
+int rts51x_mg_get_ICV(struct scsi_cmnd *srb, struct rts51x_chip *chip);
+int rts51x_mg_set_ICV(struct scsi_cmnd *srb, struct rts51x_chip *chip);
 
 #endif /* __RTS51X_MS_MG_H */
index c3fe7dda1f4e9231a4b0cb4d93bc9acc71d267fc..04213463123e5ffe74ef8ed9c5ce119a1a3a6de0 100644 (file)
@@ -306,7 +306,7 @@ static int rts51x_control_thread(void *__chip)
 
                /* we've got a command, let's do it! */
                else {
-                       RTS51X_DEBUG(scsi_show_command(chip->srb));
+                       RTS51X_DEBUG(rts51x_scsi_show_command(chip->srb));
                        rts51x_invoke_transport(chip->srb, chip);
                }
 
@@ -397,7 +397,7 @@ static int rts51x_polling_thread(void *__chip)
                }
 #endif
 
-               mspro_polling_format_status(chip);
+               rts51x_mspro_polling_format_status(chip);
 
                /* lock the device pointers */
                mutex_lock(&(chip->usb->dev_mutex));
@@ -478,7 +478,7 @@ static void rts51x_init_options(struct rts51x_chip *chip)
 {
        struct rts51x_option *option = &(chip->option);
 
-       option->mspro_formatter_enable = 1;
+       option->rts51x_mspro_formatter_enable = 1;
 
        option->fpga_sd_sdr104_clk = CLK_100;
        option->fpga_sd_sdr50_clk = CLK_100;
@@ -510,7 +510,7 @@ static void rts51x_init_options(struct rts51x_chip *chip)
 
        option->FT2_fast_mode = 0;
        option->pwr_delay = 800;
-       option->xd_rw_step = 0;
+       option->rts51x_xd_rw_step = 0;
        option->D3318_off_delay = 50;
        option->delink_delay = 100;
        option->rts5129_D3318_off_enable = 0;
@@ -518,7 +518,7 @@ static void rts51x_init_options(struct rts51x_chip *chip)
        option->reset_or_rw_fail_set_pad_drive = 1;
        option->debounce_num = 2;
        option->led_toggle_interval = 6;
-       option->xd_rwn_step = 0;
+       option->rts51x_xd_rwn_step = 0;
        option->sd_send_status_en = 0;
        option->sdr50_tx_phase = 0x01;
        option->sdr50_rx_phase = 0x05;
index 50be42ac592b9c42a83d5f03a884e243292af529..509d83e623a5f4e468cf5449d8eb13f3beb3dccc 100644 (file)
@@ -41,7 +41,7 @@
 #include "sd.h"
 #include "ms.h"
 
-void do_remaining_work(struct rts51x_chip *chip)
+void rts51x_do_remaining_work(struct rts51x_chip *chip)
 {
        struct sd_info *sd_card = &(chip->sd_card);
        struct xd_info *xd_card = &(chip->xd_card);
@@ -84,27 +84,27 @@ void do_remaining_work(struct rts51x_chip *chip)
        }
 
        if (sd_card->counter > POLLING_WAIT_CNT)
-               sd_cleanup_work(chip);
+               rts51x_sd_cleanup_work(chip);
 
        if (xd_card->counter > POLLING_WAIT_CNT)
-               xd_cleanup_work(chip);
+               rts51x_xd_cleanup_work(chip);
 
        if (ms_card->counter > POLLING_WAIT_CNT)
-               ms_cleanup_work(chip);
+               rts51x_ms_cleanup_work(chip);
 }
 
-static void do_reset_xd_card(struct rts51x_chip *chip)
+static void do_rts51x_reset_xd_card(struct rts51x_chip *chip)
 {
        int retval;
 
        if (chip->card2lun[XD_CARD] >= MAX_ALLOWED_LUN_CNT)
                return;
 
-       retval = reset_xd_card(chip);
+       retval = rts51x_reset_xd_card(chip);
        if (retval == STATUS_SUCCESS) {
                chip->card_ready |= XD_CARD;
                chip->card_fail &= ~XD_CARD;
-               chip->rw_card[chip->card2lun[XD_CARD]] = xd_rw;
+               chip->rw_card[chip->card2lun[XD_CARD]] = rts51x_xd_rw;
        } else {
                chip->card_ready &= ~XD_CARD;
                chip->card_fail |= XD_CARD;
@@ -120,18 +120,18 @@ static void do_reset_xd_card(struct rts51x_chip *chip)
        }
 }
 
-void do_reset_sd_card(struct rts51x_chip *chip)
+void rts51x_do_rts51x_reset_sd_card(struct rts51x_chip *chip)
 {
        int retval;
 
        if (chip->card2lun[SD_CARD] >= MAX_ALLOWED_LUN_CNT)
                return;
 
-       retval = reset_sd_card(chip);
+       retval = rts51x_reset_sd_card(chip);
        if (retval == STATUS_SUCCESS) {
                chip->card_ready |= SD_CARD;
                chip->card_fail &= ~SD_CARD;
-               chip->rw_card[chip->card2lun[SD_CARD]] = sd_rw;
+               chip->rw_card[chip->card2lun[SD_CARD]] = rts51x_sd_rw;
        } else {
                chip->card_ready &= ~SD_CARD;
                chip->card_fail |= SD_CARD;
@@ -147,18 +147,18 @@ void do_reset_sd_card(struct rts51x_chip *chip)
        }
 }
 
-static void do_reset_ms_card(struct rts51x_chip *chip)
+static void do_rts51x_reset_ms_card(struct rts51x_chip *chip)
 {
        int retval;
 
        if (chip->card2lun[MS_CARD] >= MAX_ALLOWED_LUN_CNT)
                return;
 
-       retval = reset_ms_card(chip);
+       retval = rts51x_reset_ms_card(chip);
        if (retval == STATUS_SUCCESS) {
                chip->card_ready |= MS_CARD;
                chip->card_fail &= ~MS_CARD;
-               chip->rw_card[chip->card2lun[MS_CARD]] = ms_rw;
+               chip->rw_card[chip->card2lun[MS_CARD]] = rts51x_ms_rw;
        } else {
                chip->card_ready &= ~MS_CARD;
                chip->card_fail |= MS_CARD;
@@ -301,7 +301,7 @@ void rts51x_init_cards(struct rts51x_chip *chip)
                        chip->card_exist &= ~XD_CARD;
                        chip->card_ejected = 0;
                        if (chip->card_ready & XD_CARD) {
-                               release_xd_card(chip);
+                               rts51x_release_xd_card(chip);
                                chip->rw_card[chip->card2lun[XD_CARD]] = NULL;
                                clear_bit(chip->card2lun[XD_CARD],
                                          &(chip->lun_mc));
@@ -312,7 +312,7 @@ void rts51x_init_cards(struct rts51x_chip *chip)
                        chip->card_exist &= ~SD_CARD;
                        chip->card_ejected = 0;
                        if (chip->card_ready & SD_CARD) {
-                               release_sd_card(chip);
+                               rts51x_release_sd_card(chip);
                                chip->rw_card[chip->card2lun[SD_CARD]] = NULL;
                                clear_bit(chip->card2lun[SD_CARD],
                                          &(chip->lun_mc));
@@ -323,7 +323,7 @@ void rts51x_init_cards(struct rts51x_chip *chip)
                        chip->card_exist &= ~MS_CARD;
                        chip->card_ejected = 0;
                        if (chip->card_ready & MS_CARD) {
-                               release_ms_card(chip);
+                               rts51x_release_ms_card(chip);
                                chip->rw_card[chip->card2lun[MS_CARD]] = NULL;
                                clear_bit(chip->card2lun[MS_CARD],
                                          &(chip->lun_mc));
@@ -339,13 +339,13 @@ void rts51x_init_cards(struct rts51x_chip *chip)
 
                if (need_reset & XD_CARD) {
                        chip->card_exist |= XD_CARD;
-                       do_reset_xd_card(chip);
+                       do_rts51x_reset_xd_card(chip);
                } else if (need_reset & SD_CARD) {
                        chip->card_exist |= SD_CARD;
-                       do_reset_sd_card(chip);
+                       rts51x_do_rts51x_reset_sd_card(chip);
                } else if (need_reset & MS_CARD) {
                        chip->card_exist |= MS_CARD;
-                       do_reset_ms_card(chip);
+                       do_rts51x_reset_ms_card(chip);
                }
        }
 }
@@ -353,20 +353,20 @@ void rts51x_init_cards(struct rts51x_chip *chip)
 void rts51x_release_cards(struct rts51x_chip *chip)
 {
        if (chip->card_ready & SD_CARD) {
-               sd_cleanup_work(chip);
-               release_sd_card(chip);
+               rts51x_sd_cleanup_work(chip);
+               rts51x_release_sd_card(chip);
                chip->card_ready &= ~SD_CARD;
        }
 
        if (chip->card_ready & XD_CARD) {
-               xd_cleanup_work(chip);
-               release_xd_card(chip);
+               rts51x_xd_cleanup_work(chip);
+               rts51x_release_xd_card(chip);
                chip->card_ready &= ~XD_CARD;
        }
 
        if (chip->card_ready & MS_CARD) {
-               ms_cleanup_work(chip);
-               release_ms_card(chip);
+               rts51x_ms_cleanup_work(chip);
+               rts51x_release_ms_card(chip);
                chip->card_ready &= ~MS_CARD;
        }
 }
@@ -376,7 +376,7 @@ static inline u8 double_depth(u8 depth)
        return ((depth > 1) ? (depth - 1) : depth);
 }
 
-int switch_ssc_clock(struct rts51x_chip *chip, int clk)
+int rts51x_switch_ssc_clock(struct rts51x_chip *chip, int clk)
 {
        struct sd_info *sd_card = &(chip->sd_card);
        struct ms_info *ms_card = &(chip->ms_card);
@@ -513,7 +513,7 @@ int switch_ssc_clock(struct rts51x_chip *chip, int clk)
        return STATUS_SUCCESS;
 }
 
-int switch_normal_clock(struct rts51x_chip *chip, int clk)
+int rts51x_switch_normal_clock(struct rts51x_chip *chip, int clk)
 {
        int retval;
        u8 sel, div, mcu_cnt;
@@ -653,7 +653,7 @@ int switch_normal_clock(struct rts51x_chip *chip, int clk)
        return STATUS_SUCCESS;
 }
 
-int card_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 sec_addr,
+int rts51x_card_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 sec_addr,
            u16 sec_cnt)
 {
        int retval;
@@ -688,7 +688,7 @@ int card_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 sec_addr,
        return retval;
 }
 
-u8 get_lun_card(struct rts51x_chip *chip, unsigned int lun)
+u8 rts51x_get_lun_card(struct rts51x_chip *chip, unsigned int lun)
 {
        if ((chip->card_ready & chip->lun2card[lun]) == XD_CARD)
                return (u8) XD_CARD;
@@ -744,24 +744,24 @@ int rts51x_select_card(struct rts51x_chip *chip, int card)
        return STATUS_SUCCESS;
 }
 
-void eject_card(struct rts51x_chip *chip, unsigned int lun)
+void rts51x_eject_card(struct rts51x_chip *chip, unsigned int lun)
 {
        RTS51X_DEBUGP("eject card\n");
        RTS51X_SET_STAT(chip, STAT_RUN);
-       do_remaining_work(chip);
+       rts51x_do_remaining_work(chip);
 
        if ((chip->card_ready & chip->lun2card[lun]) == SD_CARD) {
-               release_sd_card(chip);
+               rts51x_release_sd_card(chip);
                chip->card_ejected |= SD_CARD;
                chip->card_ready &= ~SD_CARD;
                chip->capacity[lun] = 0;
        } else if ((chip->card_ready & chip->lun2card[lun]) == XD_CARD) {
-               release_xd_card(chip);
+               rts51x_release_xd_card(chip);
                chip->card_ejected |= XD_CARD;
                chip->card_ready &= ~XD_CARD;
                chip->capacity[lun] = 0;
        } else if ((chip->card_ready & chip->lun2card[lun]) == MS_CARD) {
-               release_ms_card(chip);
+               rts51x_release_ms_card(chip);
                chip->card_ejected |= MS_CARD;
                chip->card_ready &= ~MS_CARD;
                chip->capacity[lun] = 0;
@@ -770,7 +770,7 @@ void eject_card(struct rts51x_chip *chip, unsigned int lun)
                              XD_INT | MS_INT | SD_INT);
 }
 
-void trans_dma_enable(enum dma_data_direction dir, struct rts51x_chip *chip,
+void rts51x_trans_dma_enable(enum dma_data_direction dir, struct rts51x_chip *chip,
                      u32 byte_cnt, u8 pack_size)
 {
        if (pack_size > DMA_1024)
@@ -798,7 +798,7 @@ void trans_dma_enable(enum dma_data_direction dir, struct rts51x_chip *chip,
        }
 }
 
-int enable_card_clock(struct rts51x_chip *chip, u8 card)
+int rts51x_enable_card_clock(struct rts51x_chip *chip, u8 card)
 {
        u8 clk_en = 0;
 
@@ -814,7 +814,7 @@ int enable_card_clock(struct rts51x_chip *chip, u8 card)
        return STATUS_SUCCESS;
 }
 
-int card_power_on(struct rts51x_chip *chip, u8 card)
+int rts51x_card_power_on(struct rts51x_chip *chip, u8 card)
 {
        u8 mask, val1, val2;
 
@@ -863,7 +863,7 @@ int monitor_card_cd(struct rts51x_chip *chip, u8 card)
        return CD_NOT_EXIST;
 }
 
-int toggle_gpio(struct rts51x_chip *chip, u8 gpio)
+int rts51x_toggle_gpio(struct rts51x_chip *chip, u8 gpio)
 {
        int retval;
        u8 temp_reg;
@@ -898,7 +898,7 @@ int toggle_gpio(struct rts51x_chip *chip, u8 gpio)
        return STATUS_SUCCESS;
 }
 
-int turn_on_led(struct rts51x_chip *chip, u8 gpio)
+int rts51x_turn_on_led(struct rts51x_chip *chip, u8 gpio)
 {
        int retval;
        u8 gpio_oe[4] = {
@@ -917,7 +917,7 @@ int turn_on_led(struct rts51x_chip *chip, u8 gpio)
        return STATUS_SUCCESS;
 }
 
-int turn_off_led(struct rts51x_chip *chip, u8 gpio)
+int rts51x_turn_off_led(struct rts51x_chip *chip, u8 gpio)
 {
        int retval;
        u8 gpio_output[4] = {
index c5c03cce98bd6d4bdf9d6030fe18daa4b779ecb4..e62b25c314134d1e67827647fbe681ab37fb0fc8 100644 (file)
 
 int monitor_card_cd(struct rts51x_chip *chip, u8 card);
 
-void do_remaining_work(struct rts51x_chip *chip);
-void do_reset_sd_card(struct rts51x_chip *chip);
+void rts51x_do_remaining_work(struct rts51x_chip *chip);
+void rts51x_do_rts51x_reset_sd_card(struct rts51x_chip *chip);
 void rts51x_init_cards(struct rts51x_chip *chip);
 void rts51x_release_cards(struct rts51x_chip *chip);
-int switch_ssc_clock(struct rts51x_chip *chip, int clk);
-int switch_normal_clock(struct rts51x_chip *chip, int clk);
-int card_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 sec_addr,
+int rts51x_switch_ssc_clock(struct rts51x_chip *chip, int clk);
+int rts51x_switch_normal_clock(struct rts51x_chip *chip, int clk);
+int rts51x_card_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 sec_addr,
            u16 sec_cnt);
-u8 get_lun_card(struct rts51x_chip *chip, unsigned int lun);
+u8 rts51x_get_lun_card(struct rts51x_chip *chip, unsigned int lun);
 int rts51x_select_card(struct rts51x_chip *chip, int card);
-void eject_card(struct rts51x_chip *chip, unsigned int lun);
-void trans_dma_enable(enum dma_data_direction dir, struct rts51x_chip *chip,
+void rts51x_eject_card(struct rts51x_chip *chip, unsigned int lun);
+void rts51x_trans_dma_enable(enum dma_data_direction dir, struct rts51x_chip *chip,
                      u32 byte_cnt, u8 pack_size);
-int enable_card_clock(struct rts51x_chip *chip, u8 card);
-int card_power_on(struct rts51x_chip *chip, u8 card);
-int toggle_gpio(struct rts51x_chip *chip, u8 gpio);
-int turn_on_led(struct rts51x_chip *chip, u8 gpio);
-int turn_off_led(struct rts51x_chip *chip, u8 gpio);
+int rts51x_enable_card_clock(struct rts51x_chip *chip, u8 card);
+int rts51x_card_power_on(struct rts51x_chip *chip, u8 card);
+int rts51x_toggle_gpio(struct rts51x_chip *chip, u8 gpio);
+int rts51x_turn_on_led(struct rts51x_chip *chip, u8 gpio);
+int rts51x_turn_off_led(struct rts51x_chip *chip, u8 gpio);
 
 static inline int check_card_ready(struct rts51x_chip *chip, unsigned int lun)
 {
@@ -830,9 +830,9 @@ static inline int switch_clock(struct rts51x_chip *chip, int clk)
        int retval = 0;
 
        if (chip->asic_code)
-               retval = switch_ssc_clock(chip, clk);
+               retval = rts51x_switch_ssc_clock(chip, clk);
        else
-               retval = switch_normal_clock(chip, clk);
+               retval = rts51x_switch_normal_clock(chip, clk);
 
        return retval;
 }
index 08dcae8db63e6edf46a230eef7124810368f8e1c..7d7510de170cefc008fab0e60960912b30278fa0 100644 (file)
@@ -132,7 +132,7 @@ int rts51x_reset_chip(struct rts51x_chip *chip)
        }
 #endif
        if (chip->option.FT2_fast_mode) {
-               card_power_on(chip, SD_CARD | MS_CARD | XD_CARD);
+               rts51x_card_power_on(chip, SD_CARD | MS_CARD | XD_CARD);
                wait_timeout(10);
        }
 
@@ -212,8 +212,8 @@ int rts51x_init_chip(struct rts51x_chip *chip)
 
 int rts51x_release_chip(struct rts51x_chip *chip)
 {
-       xd_free_l2p_tbl(chip);
-       ms_free_l2p_tbl(chip);
+       rts51x_xd_free_l2p_tbl(chip);
+       rts51x_ms_free_l2p_tbl(chip);
        chip->card_ready = 0;
        return STATUS_SUCCESS;
 }
@@ -227,7 +227,7 @@ static inline void rts51x_blink_led(struct rts51x_chip *chip)
                        chip->led_toggle_counter++;
                } else {
                        chip->led_toggle_counter = 0;
-                       toggle_gpio(chip, LED_GPIO);
+                       rts51x_toggle_gpio(chip, LED_GPIO);
                }
        }
 }
@@ -325,14 +325,14 @@ void rts51x_polling_func(struct rts51x_chip *chip)
                            && (chip->card_exist &
                                (SD_CARD | MS_CARD | XD_CARD))
                            && (!chip->card_ejected)) {
-                               turn_on_led(chip, LED_GPIO);
+                               rts51x_turn_on_led(chip, LED_GPIO);
                        } else {
                                if (chip->rts5179) {
                                        rts51x_ep0_write_register(chip,
                                                                  CARD_GPIO,
                                                                  0x03, 0x00);
                                } else {
-                                       turn_off_led(chip, LED_GPIO);
+                                       rts51x_turn_off_led(chip, LED_GPIO);
                                }
 
                        }
@@ -353,7 +353,7 @@ void rts51x_polling_func(struct rts51x_chip *chip)
        switch (RTS51X_GET_STAT(chip)) {
        case STAT_RUN:
                rts51x_blink_led(chip);
-               do_remaining_work(chip);
+               rts51x_do_remaining_work(chip);
                break;
 
        case STAT_IDLE:
@@ -707,7 +707,7 @@ void rts51x_do_before_power_down(struct rts51x_chip *chip)
        if (chip->rts5179)
                rts51x_ep0_write_register(chip, CARD_GPIO, 0x03, 0x00);
        else
-               turn_off_led(chip, LED_GPIO);
+               rts51x_turn_off_led(chip, LED_GPIO);
 
        chip->cur_clk = 0;
        chip->card_exist = 0;
@@ -797,7 +797,7 @@ void rts51x_pp_status(struct rts51x_chip *chip, unsigned int lun, u8 *status,
 {
        struct sd_info *sd_card = &(chip->sd_card);
        struct ms_info *ms_card = &(chip->ms_card);
-       u8 card = get_lun_card(chip, lun);
+       u8 card = rts51x_get_lun_card(chip, lun);
 #ifdef SUPPORT_OC
        u8 oc_now_mask = 0, oc_ever_mask = 0;
 #endif
@@ -958,9 +958,9 @@ void rts51x_read_status(struct rts51x_chip *chip, unsigned int lun,
                rts51x_status[12] = 0;
 
        /* Detailed Type */
-       if (get_lun_card(chip, lun) == XD_CARD) {
+       if (rts51x_get_lun_card(chip, lun) == XD_CARD) {
                rts51x_status[13] = 0x40;
-       } else if (get_lun_card(chip, lun) == SD_CARD) {
+       } else if (rts51x_get_lun_card(chip, lun) == SD_CARD) {
                struct sd_info *sd_card = &(chip->sd_card);
 
                rts51x_status[13] = 0x20;
@@ -976,7 +976,7 @@ void rts51x_read_status(struct rts51x_chip *chip, unsigned int lun,
                        if (CHK_MMC_SECTOR_MODE(sd_card))
                                rts51x_status[13] |= 0x04; /* Hi capacity */
                }
-       } else if (get_lun_card(chip, lun) == MS_CARD) {
+       } else if (rts51x_get_lun_card(chip, lun) == MS_CARD) {
                struct ms_info *ms_card = &(chip->ms_card);
 
                if (CHK_MSPRO(ms_card)) {
index 64257caf2f304a1044ac2fe4b4e18c9b33a19232..12deb24cfbbed9956587646183c7722a127387f6 100644 (file)
@@ -253,7 +253,7 @@ struct sense_data_t {
 #define SUPPORT_UHS50_MMC44            0x40
 
 struct rts51x_option {
-       int mspro_formatter_enable;
+       int rts51x_mspro_formatter_enable;
 
        /* card clock expected by user for fpga platform */
        int fpga_sd_sdr104_clk;
@@ -308,7 +308,7 @@ struct rts51x_option {
         * add for config delay between 1/4 PMOS and 3/4 PMOS */
        int pwr_delay;
 
-       int xd_rw_step;         /* add to tune xd tRP */
+       int rts51x_xd_rw_step;          /* add to tune xd tRP */
        int D3318_off_delay;    /* add to tune D3318 off delay time */
        int delink_delay;       /* add to tune delink delay time */
        /* add for rts5129 to enable/disable D3318 off */
@@ -320,7 +320,7 @@ struct rts51x_option {
 
        u8 debounce_num;        /* debounce number */
        u8 led_toggle_interval; /* used to control led toggle speed */
-       int xd_rwn_step;
+       int rts51x_xd_rwn_step;
        u8 sd_send_status_en;
        /* used to store default phase which is
         * used when phase tune all pass. */
@@ -337,11 +337,11 @@ struct rts51x_option {
        u8 dv18_voltage;        /* add to tune dv18 voltage */
 };
 
-#define MS_FORMATTER_ENABLED(chip)     ((chip)->option.mspro_formatter_enable)
+#define MS_FORMATTER_ENABLED(chip)     ((chip)->option.rts51x_mspro_formatter_enable)
 
 struct rts51x_chip;
 
-typedef int (*card_rw_func) (struct scsi_cmnd *srb, struct rts51x_chip *chip,
+typedef int (*rts51x_card_rw_func) (struct scsi_cmnd *srb, struct rts51x_chip *chip,
                             u32 sec_addr, u16 sec_cnt);
 
 /* For MS Card */
@@ -564,7 +564,7 @@ struct sd_info {
 #define CHK_MS8BIT(ms_card)    (((ms_card)->ms_type & MS_8BIT))
 #define CHK_MS4BIT(ms_card)    (((ms_card)->ms_type & MS_4BIT))
 
-struct ms_delay_write_tag {
+struct rts51x_ms_delay_write_tag {
        u16 old_phyblock;
        u16 new_phyblock;
        u16 logblock;
@@ -605,7 +605,7 @@ struct ms_info {
        u32 total_sec_cnt;
        u8 last_rw_int;
 
-       struct ms_delay_write_tag delay_write;
+       struct rts51x_ms_delay_write_tag delay_write;
 
        int counter;
 
@@ -671,7 +671,7 @@ struct rts51x_chip {
        u32 capacity[MAX_ALLOWED_LUN_CNT];
 
        /* read/write card function pointer */
-       card_rw_func rw_card[MAX_ALLOWED_LUN_CNT];
+       rts51x_card_rw_func rw_card[MAX_ALLOWED_LUN_CNT];
        /* read/write capacity, used for GPIO Toggle */
        u32 rw_cap[MAX_ALLOWED_LUN_CNT];
        /* card to lun mapping table */
index bf1a9e64e8744f5d5b648407ba46173b5b74502d..dee7d8af564e3e2492b90e491aa800a7e3823d1c 100644 (file)
@@ -70,7 +70,7 @@ static int rts51x_sd_direct_cmnd(struct rts51x_chip *chip,
        switch (dir) {
        case 0:
                /* No data */
-               retval = ext_sd_execute_no_data(chip, chip->card2lun[SD_CARD],
+               retval = ext_rts51x_sd_execute_no_data(chip, chip->card2lun[SD_CARD],
                                                cmd_idx, standby, acmd,
                                                rsp_code, arg);
                if (retval != TRANSPORT_GOOD)
@@ -83,7 +83,7 @@ static int rts51x_sd_direct_cmnd(struct rts51x_chip *chip,
                if (!buf)
                        TRACE_RET(chip, STATUS_NOMEM);
 
-               retval = ext_sd_execute_read_data(chip, chip->card2lun[SD_CARD],
+               retval = ext_rts51x_sd_execute_read_data(chip, chip->card2lun[SD_CARD],
                                                  cmd_idx, cmd12, standby, acmd,
                                                  rsp_code, arg, len, buf,
                                                  cmnd->buf_len, 0);
@@ -117,7 +117,7 @@ static int rts51x_sd_direct_cmnd(struct rts51x_chip *chip,
                }
 
                retval =
-                   ext_sd_execute_write_data(chip, chip->card2lun[SD_CARD],
+                   ext_rts51x_sd_execute_write_data(chip, chip->card2lun[SD_CARD],
                                              cmd_idx, cmd12, standby, acmd,
                                              rsp_code, arg, len, buf,
                                              cmnd->buf_len, 0);
index e07a1f4f58cfa57838be883e1ca045050bb2c238..052911c931037a855c634685f4467b395494568f 100644 (file)
@@ -44,7 +44,7 @@
 #include "ms_mg.h"
 #include "trace.h"
 
-void scsi_show_command(struct scsi_cmnd *srb)
+void rts51x_scsi_show_command(struct scsi_cmnd *srb)
 {
        char *what = NULL;
        int i, unknown_cmd = 0;
@@ -333,72 +333,72 @@ void scsi_show_command(struct scsi_cmnd *srb)
        }
 }
 
-void set_sense_type(struct rts51x_chip *chip, unsigned int lun, int sense_type)
+void rts51x_set_sense_type(struct rts51x_chip *chip, unsigned int lun, int sense_type)
 {
        switch (sense_type) {
        case SENSE_TYPE_MEDIA_CHANGE:
-               set_sense_data(chip, lun, CUR_ERR, 0x06, 0, 0x28, 0, 0, 0);
+               rts51x_set_sense_data(chip, lun, CUR_ERR, 0x06, 0, 0x28, 0, 0, 0);
                break;
 
        case SENSE_TYPE_MEDIA_NOT_PRESENT:
-               set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x3A, 0, 0, 0);
+               rts51x_set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x3A, 0, 0, 0);
                break;
 
        case SENSE_TYPE_MEDIA_LBA_OVER_RANGE:
-               set_sense_data(chip, lun, CUR_ERR, 0x05, 0, 0x21, 0, 0, 0);
+               rts51x_set_sense_data(chip, lun, CUR_ERR, 0x05, 0, 0x21, 0, 0, 0);
                break;
 
        case SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT:
-               set_sense_data(chip, lun, CUR_ERR, 0x05, 0, 0x25, 0, 0, 0);
+               rts51x_set_sense_data(chip, lun, CUR_ERR, 0x05, 0, 0x25, 0, 0, 0);
                break;
 
        case SENSE_TYPE_MEDIA_WRITE_PROTECT:
-               set_sense_data(chip, lun, CUR_ERR, 0x07, 0, 0x27, 0, 0, 0);
+               rts51x_set_sense_data(chip, lun, CUR_ERR, 0x07, 0, 0x27, 0, 0, 0);
                break;
 
        case SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR:
-               set_sense_data(chip, lun, CUR_ERR, 0x03, 0, 0x11, 0, 0, 0);
+               rts51x_set_sense_data(chip, lun, CUR_ERR, 0x03, 0, 0x11, 0, 0, 0);
                break;
 
        case SENSE_TYPE_MEDIA_WRITE_ERR:
-               set_sense_data(chip, lun, CUR_ERR, 0x03, 0, 0x0C, 0x02, 0, 0);
+               rts51x_set_sense_data(chip, lun, CUR_ERR, 0x03, 0, 0x0C, 0x02, 0, 0);
                break;
 
        case SENSE_TYPE_MEDIA_INVALID_CMD_FIELD:
-               set_sense_data(chip, lun, CUR_ERR, ILGAL_REQ, 0,
+               rts51x_set_sense_data(chip, lun, CUR_ERR, ILGAL_REQ, 0,
                               ASC_INVLD_CDB, ASCQ_INVLD_CDB, CDB_ILLEGAL, 1);
                break;
 
        case SENSE_TYPE_FORMAT_CMD_FAILED:
-               set_sense_data(chip, lun, CUR_ERR, 0x03, 0, 0x31, 0x01, 0, 0);
+               rts51x_set_sense_data(chip, lun, CUR_ERR, 0x03, 0, 0x31, 0x01, 0, 0);
                break;
 
 #ifdef SUPPORT_MAGIC_GATE
        case SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB:
-               set_sense_data(chip, lun, CUR_ERR, 0x05, 0, 0x6F, 0x02, 0, 0);
+               rts51x_set_sense_data(chip, lun, CUR_ERR, 0x05, 0, 0x6F, 0x02, 0, 0);
                break;
 
        case SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN:
-               set_sense_data(chip, lun, CUR_ERR, 0x05, 0, 0x6F, 0x00, 0, 0);
+               rts51x_set_sense_data(chip, lun, CUR_ERR, 0x05, 0, 0x6F, 0x00, 0, 0);
                break;
 
        case SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM:
-               set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x30, 0x00, 0, 0);
+               rts51x_set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x30, 0x00, 0, 0);
                break;
 
        case SENSE_TYPE_MG_WRITE_ERR:
-               set_sense_data(chip, lun, CUR_ERR, 0x03, 0, 0x0C, 0x00, 0, 0);
+               rts51x_set_sense_data(chip, lun, CUR_ERR, 0x03, 0, 0x0C, 0x00, 0, 0);
                break;
 #endif
 
        case SENSE_TYPE_NO_SENSE:
        default:
-               set_sense_data(chip, lun, CUR_ERR, 0, 0, 0, 0, 0, 0);
+               rts51x_set_sense_data(chip, lun, CUR_ERR, 0, 0, 0, 0, 0, 0);
                break;
        }
 }
 
-void set_sense_data(struct rts51x_chip *chip, unsigned int lun, u8 err_code,
+void rts51x_set_sense_data(struct rts51x_chip *chip, unsigned int lun, u8 err_code,
                    u8 sense_key, u32 info, u8 asc, u8 ascq, u8 sns_key_info0,
                    u16 sns_key_info1)
 {
@@ -428,13 +428,13 @@ static int test_unit_ready(struct scsi_cmnd *srb, struct rts51x_chip *chip)
        rts51x_init_cards(chip);
 
        if (!check_card_ready(chip, lun)) {
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
                return TRANSPORT_FAILED;
        }
 
        if (!check_lun_mc(chip, lun)) {
                set_lun_mc(chip, lun);
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
                return TRANSPORT_FAILED;
        }
 
@@ -457,7 +457,7 @@ static int inquiry(struct scsi_cmnd *srb, struct rts51x_chip *chip)
        char *inquiry_string;
        unsigned char sendbytes;
        unsigned char *buf;
-       u8 card = get_lun_card(chip, lun);
+       u8 card = rts51x_get_lun_card(chip, lun);
        int pro_formatter_flag = 0;
        unsigned char inquiry_buf[] = {
                QULIFIRE | DRCT_ACCESS_DEV,
@@ -532,7 +532,7 @@ static int start_stop_unit(struct scsi_cmnd *srb, struct rts51x_chip *chip)
        case UNLOAD_MEDIUM:
                /* Media shall be unload */
                if (check_card_ready(chip, lun))
-                       eject_card(chip, lun);
+                       rts51x_eject_card(chip, lun);
                return TRANSPORT_GOOD;
 
        case MAKE_MEDIUM_READY:
@@ -540,7 +540,7 @@ static int start_stop_unit(struct scsi_cmnd *srb, struct rts51x_chip *chip)
                if (check_card_ready(chip, lun)) {
                        return TRANSPORT_GOOD;
                } else {
-                       set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+                       rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
                        TRACE_RET(chip, TRANSPORT_FAILED);
                }
 
@@ -559,7 +559,7 @@ static int allow_medium_removal(struct scsi_cmnd *srb, struct rts51x_chip *chip)
        scsi_set_resid(srb, 0);
 
        if (prevent) {
-               set_sense_type(chip, SCSI_LUN(srb),
+               rts51x_set_sense_type(chip, SCSI_LUN(srb),
                               SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
                TRACE_RET(chip, TRANSPORT_FAILED);
        }
@@ -663,10 +663,10 @@ static int mode_sense(struct scsi_cmnd *srb, struct rts51x_chip *chip)
        int status;
        int pro_formatter_flag;
        unsigned char pageCode, *buf;
-       u8 card = get_lun_card(chip, lun);
+       u8 card = rts51x_get_lun_card(chip, lun);
 
        if (!check_card_ready(chip, lun)) {
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
                scsi_set_resid(srb, scsi_bufflen(srb));
                TRACE_RET(chip, TRANSPORT_FAILED);
        }
@@ -678,7 +678,7 @@ static int mode_sense(struct scsi_cmnd *srb, struct rts51x_chip *chip)
        if ((get_lun2card(chip, lun) & MS_CARD)) {
                if (!card || (card == MS_CARD)) {
                        dataSize = 108;
-                       if (chip->option.mspro_formatter_enable)
+                       if (chip->option.rts51x_mspro_formatter_enable)
                                pro_formatter_flag = 1;
                }
        }
@@ -725,7 +725,7 @@ static int mode_sense(struct scsi_cmnd *srb, struct rts51x_chip *chip)
                }
                status = TRANSPORT_GOOD;
        } else {
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
                scsi_set_resid(srb, scsi_bufflen(srb));
                status = TRANSPORT_FAILED;
        }
@@ -749,9 +749,9 @@ static int request_sense(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 
        sense = &(chip->sense_buffer[lun]);
 
-       if ((get_lun_card(chip, lun) == MS_CARD)
+       if ((rts51x_get_lun_card(chip, lun) == MS_CARD)
            && PRO_UNDER_FORMATTING(ms_card)) {
-               mspro_format_sense(chip, lun);
+               rts51x_mspro_format_sense(chip, lun);
        }
 
        buf = vmalloc(scsi_bufflen(srb));
@@ -766,7 +766,7 @@ static int request_sense(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 
        scsi_set_resid(srb, 0);
        /* Reset Sense Data */
-       set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE);
+       rts51x_set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE);
        return TRANSPORT_GOOD;
 }
 
@@ -778,13 +778,13 @@ static int read_write(struct scsi_cmnd *srb, struct rts51x_chip *chip)
        u16 sec_cnt;
 
        if (!check_card_ready(chip, lun) || (chip->capacity[lun] == 0)) {
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
                TRACE_RET(chip, TRANSPORT_FAILED);
        }
 
        if (!check_lun_mc(chip, lun)) {
                set_lun_mc(chip, lun);
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
                return TRANSPORT_FAILED;
        }
 
@@ -812,13 +812,13 @@ static int read_write(struct scsi_cmnd *srb, struct rts51x_chip *chip)
                        ((u32) srb->cmnd[7]);
                sec_cnt = ((u16) (srb->cmnd[9]) << 8) | srb->cmnd[10];
        } else {
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
                TRACE_RET(chip, TRANSPORT_FAILED);
        }
 
        if ((start_sec > chip->capacity[lun]) ||
            ((start_sec + sec_cnt) > chip->capacity[lun])) {
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LBA_OVER_RANGE);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LBA_OVER_RANGE);
                TRACE_RET(chip, TRANSPORT_FAILED);
        }
 
@@ -830,17 +830,17 @@ static int read_write(struct scsi_cmnd *srb, struct rts51x_chip *chip)
        if ((srb->sc_data_direction == DMA_TO_DEVICE)
            && check_card_wp(chip, lun)) {
                RTS51X_DEBUGP("Write protected card!\n");
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_PROTECT);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_PROTECT);
                TRACE_RET(chip, TRANSPORT_FAILED);
        }
 
-       retval = card_rw(srb, chip, start_sec, sec_cnt);
+       retval = rts51x_card_rw(srb, chip, start_sec, sec_cnt);
        if (retval != STATUS_SUCCESS) {
                if (srb->sc_data_direction == DMA_FROM_DEVICE) {
-                       set_sense_type(chip, lun,
+                       rts51x_set_sense_type(chip, lun,
                                       SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
                } else {
-                       set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
+                       rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
                }
                TRACE_RET(chip, TRANSPORT_FAILED);
        }
@@ -855,13 +855,13 @@ static int read_format_capacity(struct scsi_cmnd *srb, struct rts51x_chip *chip)
        unsigned char *buf;
        unsigned int lun = SCSI_LUN(srb);
        unsigned int buf_len;
-       u8 card = get_lun_card(chip, lun);
+       u8 card = rts51x_get_lun_card(chip, lun);
        int desc_cnt;
        int i = 0;
 
        if (!check_card_ready(chip, lun)) {
-               if (!chip->option.mspro_formatter_enable) {
-                       set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+               if (!chip->option.rts51x_mspro_formatter_enable) {
+                       rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
                        TRACE_RET(chip, TRANSPORT_FAILED);
                }
        }
@@ -877,7 +877,7 @@ static int read_format_capacity(struct scsi_cmnd *srb, struct rts51x_chip *chip)
        buf[i++] = 0;
 
        /* Capacity List Length */
-       if ((buf_len > 12) && chip->option.mspro_formatter_enable &&
+       if ((buf_len > 12) && chip->option.rts51x_mspro_formatter_enable &&
            (chip->lun2card[lun] & MS_CARD) && (!card || (card == MS_CARD))) {
                buf[i++] = 0x10;
                desc_cnt = 2;
@@ -933,13 +933,13 @@ static int read_capacity(struct scsi_cmnd *srb, struct rts51x_chip *chip)
        unsigned int lun = SCSI_LUN(srb);
 
        if (!check_card_ready(chip, lun)) {
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
                TRACE_RET(chip, TRANSPORT_FAILED);
        }
 
        if (!check_lun_mc(chip, lun)) {
                set_lun_mc(chip, lun);
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
                return TRANSPORT_FAILED;
        }
 
@@ -1021,7 +1021,7 @@ static int read_mem(struct scsi_cmnd *srb, struct rts51x_chip *chip)
                retval = rts51x_ep0_read_register(chip, addr + i, buf + i);
                if (retval != STATUS_SUCCESS) {
                        vfree(buf);
-                       set_sense_type(chip, lun,
+                       rts51x_set_sense_type(chip, lun,
                                       SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
                        TRACE_RET(chip, TRANSPORT_FAILED);
                }
@@ -1066,7 +1066,7 @@ static int write_mem(struct scsi_cmnd *srb, struct rts51x_chip *chip)
                    rts51x_ep0_write_register(chip, addr + i, 0xFF, buf[i]);
                if (retval != STATUS_SUCCESS) {
                        vfree(buf);
-                       set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
+                       rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
                        TRACE_RET(chip, TRANSPORT_FAILED);
                }
        }
@@ -1083,12 +1083,12 @@ static int get_sd_csd(struct scsi_cmnd *srb, struct rts51x_chip *chip)
        unsigned int lun = SCSI_LUN(srb);
 
        if (!check_card_ready(chip, lun)) {
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
                TRACE_RET(chip, TRANSPORT_FAILED);
        }
 
-       if (get_lun_card(chip, lun) != SD_CARD) {
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
+       if (rts51x_get_lun_card(chip, lun) != SD_CARD) {
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
                TRACE_RET(chip, TRANSPORT_FAILED);
        }
 
@@ -1120,7 +1120,7 @@ static int read_phy_register(struct scsi_cmnd *srb, struct rts51x_chip *chip)
                            rts51x_read_phy_register(chip, addr + i, buf + i);
                        if (retval != STATUS_SUCCESS) {
                                vfree(buf);
-                               set_sense_type(chip, SCSI_LUN(srb),
+                               rts51x_set_sense_type(chip, SCSI_LUN(srb),
                                        SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
                                TRACE_RET(chip, TRANSPORT_FAILED);
                        }
@@ -1163,7 +1163,7 @@ static int write_phy_register(struct scsi_cmnd *srb, struct rts51x_chip *chip)
                            rts51x_write_phy_register(chip, addr + i, buf[i]);
                        if (retval != STATUS_SUCCESS) {
                                vfree(buf);
-                               set_sense_type(chip, SCSI_LUN(srb),
+                               rts51x_set_sense_type(chip, SCSI_LUN(srb),
                                               SENSE_TYPE_MEDIA_WRITE_ERR);
                                TRACE_RET(chip, TRANSPORT_FAILED);
                        }
@@ -1181,15 +1181,15 @@ static int get_card_bus_width(struct scsi_cmnd *srb, struct rts51x_chip *chip)
        u8 card, bus_width;
 
        if (!check_card_ready(chip, lun)) {
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
                TRACE_RET(chip, TRANSPORT_FAILED);
        }
 
-       card = get_lun_card(chip, lun);
+       card = rts51x_get_lun_card(chip, lun);
        if ((card == SD_CARD) || (card == MS_CARD)) {
                bus_width = chip->card_bus_width[lun];
        } else {
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
                TRACE_RET(chip, TRANSPORT_FAILED);
        }
 
@@ -1211,7 +1211,7 @@ static int trace_msg_cmd(struct scsi_cmnd *srb, struct rts51x_chip *chip)
            ((2 + MSG_FUNC_LEN + MSG_FILE_LEN + TIME_VAL_LEN) * TRACE_ITEM_CNT);
 
        if ((scsi_bufflen(srb) < buf_len) || (scsi_sglist(srb) == NULL)) {
-               set_sense_type(chip, SCSI_LUN(srb),
+               rts51x_set_sense_type(chip, SCSI_LUN(srb),
                               SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
                TRACE_RET(chip, TRANSPORT_FAILED);
        }
@@ -1251,7 +1251,7 @@ static int rw_mem_cmd_buf(struct scsi_cmnd *srb, struct rts51x_chip *chip)
        case ADD_BATCHCMD:
                cmd_type = srb->cmnd[4];
                if (cmd_type > 2) {
-                       set_sense_type(chip, lun,
+                       rts51x_set_sense_type(chip, lun,
                                       SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
                        TRACE_RET(chip, TRANSPORT_FAILED);
                }
@@ -1274,13 +1274,13 @@ static int rw_mem_cmd_buf(struct scsi_cmnd *srb, struct rts51x_chip *chip)
                                                                          [9]);
                retval = rts51x_send_cmd(chip, mode, 1000);
                if (retval != STATUS_SUCCESS) {
-                       set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
+                       rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
                        TRACE_RET(chip, TRANSPORT_FAILED);
                }
                if (mode & STAGE_R) {
                        retval = rts51x_get_rsp(chip, len, timeout);
                        if (retval != STATUS_SUCCESS) {
-                               set_sense_type(chip, lun,
+                               rts51x_set_sense_type(chip, lun,
                                        SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
                                TRACE_RET(chip, TRANSPORT_FAILED);
                        }
@@ -1291,7 +1291,7 @@ static int rw_mem_cmd_buf(struct scsi_cmnd *srb, struct rts51x_chip *chip)
                idx = srb->cmnd[4];
                value = chip->rsp_buf[idx];
                if (scsi_bufflen(srb) < 1) {
-                       set_sense_type(chip, lun,
+                       rts51x_set_sense_type(chip, lun,
                                       SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
                        TRACE_RET(chip, TRANSPORT_FAILED);
                }
@@ -1300,12 +1300,12 @@ static int rw_mem_cmd_buf(struct scsi_cmnd *srb, struct rts51x_chip *chip)
                break;
 
        default:
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
                TRACE_RET(chip, TRANSPORT_FAILED);
        }
 
        if (retval != STATUS_SUCCESS) {
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
                TRACE_RET(chip, TRANSPORT_FAILED);
        }
 
@@ -1357,7 +1357,7 @@ static int app_cmd(struct scsi_cmnd *srb, struct rts51x_chip *chip)
                break;
 
        default:
-               set_sense_type(chip, SCSI_LUN(srb),
+               rts51x_set_sense_type(chip, SCSI_LUN(srb),
                               SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
                TRACE_RET(chip, TRANSPORT_FAILED);
        }
@@ -1401,7 +1401,7 @@ static int vendor_cmnd(struct scsi_cmnd *srb, struct rts51x_chip *chip)
                break;
 
        default:
-               set_sense_type(chip, SCSI_LUN(srb),
+               rts51x_set_sense_type(chip, SCSI_LUN(srb),
                               SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
                TRACE_RET(chip, TRANSPORT_FAILED);
        }
@@ -1415,15 +1415,15 @@ static int ms_format_cmnd(struct scsi_cmnd *srb, struct rts51x_chip *chip)
        unsigned int lun = SCSI_LUN(srb);
        int retval, quick_format;
 
-       if (get_lun_card(chip, lun) != MS_CARD) {
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
+       if (rts51x_get_lun_card(chip, lun) != MS_CARD) {
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
                TRACE_RET(chip, TRANSPORT_FAILED);
        }
 
        if ((srb->cmnd[3] != 0x4D) || (srb->cmnd[4] != 0x47)
            || (srb->cmnd[5] != 0x66) || (srb->cmnd[6] != 0x6D)
            || (srb->cmnd[7] != 0x74)) {
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
                TRACE_RET(chip, TRANSPORT_FAILED);
        }
 
@@ -1433,26 +1433,26 @@ static int ms_format_cmnd(struct scsi_cmnd *srb, struct rts51x_chip *chip)
                quick_format = 1;
 
        if (!(chip->card_ready & MS_CARD)) {
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
                TRACE_RET(chip, TRANSPORT_FAILED);
        }
 
        if (chip->card_wp & MS_CARD) {
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_PROTECT);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_PROTECT);
                TRACE_RET(chip, TRANSPORT_FAILED);
        }
 
        if (!CHK_MSPRO(ms_card)) {
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
                TRACE_RET(chip, TRANSPORT_FAILED);
        }
 
        rts51x_prepare_run(chip);
        RTS51X_SET_STAT(chip, STAT_RUN);
 
-       retval = mspro_format(srb, chip, MS_SHORT_DATA_LEN, quick_format);
+       retval = rts51x_mspro_format(srb, chip, MS_SHORT_DATA_LEN, quick_format);
        if (retval != STATUS_SUCCESS) {
-               set_sense_type(chip, lun, SENSE_TYPE_FORMAT_CMD_FAILED);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_FORMAT_CMD_FAILED);
                TRACE_RET(chip, TRANSPORT_FAILED);
        }
 
@@ -1471,18 +1471,18 @@ static int get_ms_information(struct scsi_cmnd *srb, struct rts51x_chip *chip)
        int i;
 
        if (!check_card_ready(chip, lun)) {
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
                TRACE_RET(chip, TRANSPORT_FAILED);
        }
-       if ((get_lun_card(chip, lun) != MS_CARD)) {
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
+       if ((rts51x_get_lun_card(chip, lun) != MS_CARD)) {
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
                TRACE_RET(chip, TRANSPORT_FAILED);
        }
 
        if ((srb->cmnd[2] != 0xB0) || (srb->cmnd[4] != 0x4D) ||
            (srb->cmnd[5] != 0x53) || (srb->cmnd[6] != 0x49) ||
            (srb->cmnd[7] != 0x44)) {
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
                TRACE_RET(chip, TRANSPORT_FAILED);
        }
 
@@ -1490,7 +1490,7 @@ static int get_ms_information(struct scsi_cmnd *srb, struct rts51x_chip *chip)
        if ((CHK_MSXC(ms_card) && (dev_info_id == 0x10)) ||
            (!CHK_MSXC(ms_card) && (dev_info_id == 0x13)) ||
            !CHK_MSPRO(ms_card)) {
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
                TRACE_RET(chip, TRANSPORT_FAILED);
        }
 
@@ -1576,44 +1576,44 @@ static int sd_extention_cmnd(struct scsi_cmnd *srb, struct rts51x_chip *chip)
        rts51x_prepare_run(chip);
        RTS51X_SET_STAT(chip, STAT_RUN);
 
-       sd_cleanup_work(chip);
+       rts51x_sd_cleanup_work(chip);
 
        if (!check_card_ready(chip, lun)) {
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
                TRACE_RET(chip, TRANSPORT_FAILED);
        }
-       if ((get_lun_card(chip, lun) != SD_CARD)) {
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
+       if ((rts51x_get_lun_card(chip, lun) != SD_CARD)) {
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
                TRACE_RET(chip, TRANSPORT_FAILED);
        }
 
        switch (srb->cmnd[0]) {
        case SD_PASS_THRU_MODE:
-               result = sd_pass_thru_mode(srb, chip);
+               result = rts51x_sd_pass_thru_mode(srb, chip);
                break;
 
        case SD_EXECUTE_NO_DATA:
-               result = sd_execute_no_data(srb, chip);
+               result = rts51x_sd_execute_no_data(srb, chip);
                break;
 
        case SD_EXECUTE_READ:
-               result = sd_execute_read_data(srb, chip);
+               result = rts51x_sd_execute_read_data(srb, chip);
                break;
 
        case SD_EXECUTE_WRITE:
-               result = sd_execute_write_data(srb, chip);
+               result = rts51x_sd_execute_write_data(srb, chip);
                break;
 
        case SD_GET_RSP:
-               result = sd_get_cmd_rsp(srb, chip);
+               result = rts51x_sd_get_cmd_rsp(srb, chip);
                break;
 
        case SD_HW_RST:
-               result = sd_hw_rst(srb, chip);
+               result = rts51x_sd_hw_rst(srb, chip);
                break;
 
        default:
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
                TRACE_RET(chip, TRANSPORT_FAILED);
        }
 
@@ -1632,24 +1632,24 @@ static int mg_report_key(struct scsi_cmnd *srb, struct rts51x_chip *chip)
        rts51x_prepare_run(chip);
        RTS51X_SET_STAT(chip, STAT_RUN);
 
-       ms_cleanup_work(chip);
+       rts51x_ms_cleanup_work(chip);
 
        if (!check_card_ready(chip, lun)) {
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
                TRACE_RET(chip, TRANSPORT_FAILED);
        }
-       if ((get_lun_card(chip, lun) != MS_CARD)) {
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
+       if ((rts51x_get_lun_card(chip, lun) != MS_CARD)) {
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
                TRACE_RET(chip, TRANSPORT_FAILED);
        }
 
        if (srb->cmnd[7] != KC_MG_R_PRO) {
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
                TRACE_RET(chip, TRANSPORT_FAILED);
        }
 
        if (!CHK_MSPRO(ms_card)) {
-               set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
                TRACE_RET(chip, TRANSPORT_FAILED);
        }
 
@@ -1659,11 +1659,11 @@ static int mg_report_key(struct scsi_cmnd *srb, struct rts51x_chip *chip)
        case KF_GET_LOC_EKB:
                if ((scsi_bufflen(srb) == 0x41C) &&
                    (srb->cmnd[8] == 0x04) && (srb->cmnd[9] == 0x1C)) {
-                       retval = mg_get_local_EKB(srb, chip);
+                       retval = rts51x_mg_get_local_EKB(srb, chip);
                        if (retval != STATUS_SUCCESS)
                                TRACE_RET(chip, TRANSPORT_FAILED);
                } else {
-                       set_sense_type(chip, lun,
+                       rts51x_set_sense_type(chip, lun,
                                       SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
                        TRACE_RET(chip, TRANSPORT_FAILED);
                }
@@ -1672,11 +1672,11 @@ static int mg_report_key(struct scsi_cmnd *srb, struct rts51x_chip *chip)
        case KF_RSP_CHG:
                if ((scsi_bufflen(srb) == 0x24) &&
                    (srb->cmnd[8] == 0x00) && (srb->cmnd[9] == 0x24)) {
-                       retval = mg_get_rsp_chg(srb, chip);
+                       retval = rts51x_mg_get_rsp_chg(srb, chip);
                        if (retval != STATUS_SUCCESS)
                                TRACE_RET(chip, TRANSPORT_FAILED);
                } else {
-                       set_sense_type(chip, lun,
+                       rts51x_set_sense_type(chip, lun,
                                       SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
                        TRACE_RET(chip, TRANSPORT_FAILED);
                }
@@ -1690,18 +1690,18 @@ static int mg_report_key(struct scsi_cmnd *srb, struct rts51x_chip *chip)
                    (srb->cmnd[2] == 0x00) &&
                    (srb->cmnd[3] == 0x00) &&
                    (srb->cmnd[4] == 0x00) && (srb->cmnd[5] < 32)) {
-                       retval = mg_get_ICV(srb, chip);
+                       retval = rts51x_mg_get_ICV(srb, chip);
                        if (retval != STATUS_SUCCESS)
                                TRACE_RET(chip, TRANSPORT_FAILED);
                } else {
-                       set_sense_type(chip, lun,
+                       rts51x_set_sense_type(chip, lun,
                                       SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
                        TRACE_RET(chip, TRANSPORT_FAILED);
                }
                break;
 
        default:
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
                TRACE_RET(chip, TRANSPORT_FAILED);
        }
 
@@ -1719,28 +1719,28 @@ static int mg_send_key(struct scsi_cmnd *srb, struct rts51x_chip *chip)
        rts51x_prepare_run(chip);
        RTS51X_SET_STAT(chip, STAT_RUN);
 
-       ms_cleanup_work(chip);
+       rts51x_ms_cleanup_work(chip);
 
        if (!check_card_ready(chip, lun)) {
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
                TRACE_RET(chip, TRANSPORT_FAILED);
        }
        if (check_card_wp(chip, lun)) {
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_PROTECT);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_PROTECT);
                TRACE_RET(chip, TRANSPORT_FAILED);
        }
-       if ((get_lun_card(chip, lun) != MS_CARD)) {
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
+       if ((rts51x_get_lun_card(chip, lun) != MS_CARD)) {
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
                TRACE_RET(chip, TRANSPORT_FAILED);
        }
 
        if (srb->cmnd[7] != KC_MG_R_PRO) {
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
                TRACE_RET(chip, TRANSPORT_FAILED);
        }
 
        if (!CHK_MSPRO(ms_card)) {
-               set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
                TRACE_RET(chip, TRANSPORT_FAILED);
        }
 
@@ -1750,11 +1750,11 @@ static int mg_send_key(struct scsi_cmnd *srb, struct rts51x_chip *chip)
        case KF_SET_LEAF_ID:
                if ((scsi_bufflen(srb) == 0x0C) &&
                    (srb->cmnd[8] == 0x00) && (srb->cmnd[9] == 0x0C)) {
-                       retval = mg_set_leaf_id(srb, chip);
+                       retval = rts51x_mg_set_leaf_id(srb, chip);
                        if (retval != STATUS_SUCCESS)
                                TRACE_RET(chip, TRANSPORT_FAILED);
                } else {
-                       set_sense_type(chip, lun,
+                       rts51x_set_sense_type(chip, lun,
                                       SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
                        TRACE_RET(chip, TRANSPORT_FAILED);
                }
@@ -1763,11 +1763,11 @@ static int mg_send_key(struct scsi_cmnd *srb, struct rts51x_chip *chip)
        case KF_CHG_HOST:
                if ((scsi_bufflen(srb) == 0x0C) &&
                    (srb->cmnd[8] == 0x00) && (srb->cmnd[9] == 0x0C)) {
-                       retval = mg_chg(srb, chip);
+                       retval = rts51x_mg_chg(srb, chip);
                        if (retval != STATUS_SUCCESS)
                                TRACE_RET(chip, TRANSPORT_FAILED);
                } else {
-                       set_sense_type(chip, lun,
+                       rts51x_set_sense_type(chip, lun,
                                       SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
                        TRACE_RET(chip, TRANSPORT_FAILED);
                }
@@ -1776,11 +1776,11 @@ static int mg_send_key(struct scsi_cmnd *srb, struct rts51x_chip *chip)
        case KF_RSP_HOST:
                if ((scsi_bufflen(srb) == 0x0C) &&
                    (srb->cmnd[8] == 0x00) && (srb->cmnd[9] == 0x0C)) {
-                       retval = mg_rsp(srb, chip);
+                       retval = rts51x_mg_rsp(srb, chip);
                        if (retval != STATUS_SUCCESS)
                                TRACE_RET(chip, TRANSPORT_FAILED);
                } else {
-                       set_sense_type(chip, lun,
+                       rts51x_set_sense_type(chip, lun,
                                       SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
                        TRACE_RET(chip, TRANSPORT_FAILED);
                }
@@ -1794,18 +1794,18 @@ static int mg_send_key(struct scsi_cmnd *srb, struct rts51x_chip *chip)
                    (srb->cmnd[2] == 0x00) &&
                    (srb->cmnd[3] == 0x00) &&
                    (srb->cmnd[4] == 0x00) && (srb->cmnd[5] < 32)) {
-                       retval = mg_set_ICV(srb, chip);
+                       retval = rts51x_mg_set_ICV(srb, chip);
                        if (retval != STATUS_SUCCESS)
                                TRACE_RET(chip, TRANSPORT_FAILED);
                } else {
-                       set_sense_type(chip, lun,
+                       rts51x_set_sense_type(chip, lun,
                                       SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
                        TRACE_RET(chip, TRANSPORT_FAILED);
                }
                break;
 
        default:
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
                TRACE_RET(chip, TRANSPORT_FAILED);
        }
 
@@ -1820,12 +1820,12 @@ int rts51x_scsi_handler(struct scsi_cmnd *srb, struct rts51x_chip *chip)
        unsigned int lun = SCSI_LUN(srb);
        int result = TRANSPORT_GOOD;
 
-       if ((get_lun_card(chip, lun) == MS_CARD) &&
+       if ((rts51x_get_lun_card(chip, lun) == MS_CARD) &&
            (ms_card->format_status == FORMAT_IN_PROGRESS)) {
                if ((srb->cmnd[0] != REQUEST_SENSE)
                    && (srb->cmnd[0] != INQUIRY)) {
                        /* Logical Unit Not Ready Format in Progress */
-                       set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x04, 0x04,
+                       rts51x_set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x04, 0x04,
                                       0, (u16) (ms_card->progress));
                        TRACE_RET(chip, TRANSPORT_FAILED);
                }
@@ -1908,7 +1908,7 @@ int rts51x_scsi_handler(struct scsi_cmnd *srb, struct rts51x_chip *chip)
                break;
 
        default:
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
                result = TRANSPORT_FAILED;
        }
 
index 9042bc98a9a0b7ed5cb595f5f7e1afa955068dad..cdfe550371cec9cb58c7e91ed1c6ddd494b07bc3 100644 (file)
@@ -133,9 +133,9 @@ struct rts51x_chip;
 
 #define SCSI                    0x00   /* Interface ID                     */
 
-void scsi_show_command(struct scsi_cmnd *srb);
-void set_sense_type(struct rts51x_chip *chip, unsigned int lun, int sense_type);
-void set_sense_data(struct rts51x_chip *chip, unsigned int lun, u8 err_code,
+void rts51x_scsi_show_command(struct scsi_cmnd *srb);
+void rts51x_set_sense_type(struct rts51x_chip *chip, unsigned int lun, int sense_type);
+void rts51x_set_sense_data(struct rts51x_chip *chip, unsigned int lun, u8 err_code,
                    u8 sense_key, u32 info, u8 asc, u8 ascq, u8 sns_key_info0,
                    u16 sns_key_info1);
 
index b739f26f78cc79da353f61dc5d78eb436ceb90f8..4283b0917f2460bd7ba0bb59e2951a347c288533 100644 (file)
@@ -680,7 +680,7 @@ static int sd_set_init_para(struct rts51x_chip *chip)
        return STATUS_SUCCESS;
 }
 
-int sd_select_card(struct rts51x_chip *chip, int select)
+int rts51x_sd_select_card(struct rts51x_chip *chip, int select)
 {
        struct sd_info *sd_card = &(chip->sd_card);
        int retval;
@@ -1747,7 +1747,7 @@ static int mmc_ddr_tuning(struct rts51x_chip *chip)
        return STATUS_SUCCESS;
 }
 
-int sd_switch_clock(struct rts51x_chip *chip)
+int rts51x_sd_switch_clock(struct rts51x_chip *chip)
 {
        struct sd_info *sd_card = &(chip->sd_card);
        int retval;
@@ -1913,7 +1913,7 @@ static int sd_init_power(struct rts51x_chip *chip)
 #endif
 
                /* Power on card */
-               retval = card_power_on(chip, SD_CARD);
+               retval = rts51x_card_power_on(chip, SD_CARD);
                if (retval != STATUS_SUCCESS)
                        TRACE_RET(chip, retval);
 
@@ -2139,7 +2139,7 @@ RTY_CMD55:
        if (retval != STATUS_SUCCESS)
                TRACE_RET(chip, retval);
        /* Select SD card */
-       retval = sd_select_card(chip, 1);
+       retval = rts51x_sd_select_card(chip, 1);
        if (retval != STATUS_SUCCESS)
                TRACE_RET(chip, retval);
 
@@ -2656,7 +2656,7 @@ RTY_MMC_RST:
        spec_ver = (sd_card->raw_csd[0] & 0x3C) >> 2;
 
        /* Select MMC card */
-       retval = sd_select_card(chip, 1);
+       retval = rts51x_sd_select_card(chip, 1);
        if (retval != STATUS_SUCCESS)
                TRACE_RET(chip, retval);
 
@@ -2748,7 +2748,7 @@ RTY_MMC_RST:
        return STATUS_SUCCESS;
 }
 
-int reset_sd_card(struct rts51x_chip *chip)
+int rts51x_reset_sd_card(struct rts51x_chip *chip)
 {
        struct sd_info *sd_card = &(chip->sd_card);
        int retval;
@@ -2764,7 +2764,7 @@ int reset_sd_card(struct rts51x_chip *chip)
        sd_card->sd_switch_fail = 0;
 
        sd_clear_reset_fail(chip);
-       enable_card_clock(chip, SD_CARD);
+       rts51x_enable_card_clock(chip, SD_CARD);
 
        sd_init_power(chip);
 
@@ -2891,7 +2891,7 @@ static void sd_stop_seq_mode(struct rts51x_chip *chip)
        int retval;
 
        if (sd_card->seq_mode) {
-               retval = sd_switch_clock(chip);
+               retval = rts51x_sd_switch_clock(chip);
                if (retval != STATUS_SUCCESS)
                        return;
 
@@ -2923,14 +2923,14 @@ static inline int sd_auto_tune_clock(struct rts51x_chip *chip)
                        sd_card->sd_clock = CLK_50;
        }
 
-       retval = sd_switch_clock(chip);
+       retval = rts51x_sd_switch_clock(chip);
        if (retval != STATUS_SUCCESS)
                TRACE_RET(chip, retval);
 
        return STATUS_SUCCESS;
 }
 
-int sd_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
+int rts51x_sd_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
          u16 sector_cnt)
 {
        struct sd_info *sd_card = &(chip->sd_card);
@@ -2947,11 +2947,11 @@ int sd_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
        else
                data_addr = start_sector;
 
-       RTS51X_DEBUGP("sd_rw, data_addr = 0x%x\n", data_addr);
+       RTS51X_DEBUGP("rts51x_sd_rw, data_addr = 0x%x\n", data_addr);
 
        sd_clr_err_code(chip);
 
-       retval = sd_switch_clock(chip);
+       retval = rts51x_sd_switch_clock(chip);
        if (retval != STATUS_SUCCESS)
                TRACE_RET(chip, retval);
 
@@ -3020,7 +3020,7 @@ int sd_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
                               SD_NO_WAIT_BUSY_END | SD_NO_CHECK_CRC7 |
                               SD_RSP_LEN_0);
 
-               trans_dma_enable(srb->sc_data_direction, chip, sector_cnt * 512,
+               rts51x_trans_dma_enable(srb->sc_data_direction, chip, sector_cnt * 512,
                                 DMA_512);
 
                if (srb->sc_data_direction == DMA_FROM_DEVICE) {
@@ -3058,7 +3058,7 @@ int sd_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
                                       SD_NO_WAIT_BUSY_END | SD_CHECK_CRC7 |
                                       SD_RSP_LEN_6);
 
-                       trans_dma_enable(srb->sc_data_direction, chip,
+                       rts51x_trans_dma_enable(srb->sc_data_direction, chip,
                                         sector_cnt * 512, DMA_512);
 
                        rts51x_add_cmd(chip, WRITE_REG_CMD, SD_TRANSFER, 0xFF,
@@ -3099,7 +3099,7 @@ int sd_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
                                       SD_NO_WAIT_BUSY_END | SD_NO_CHECK_CRC7 |
                                       SD_RSP_LEN_0);
 
-                       trans_dma_enable(srb->sc_data_direction, chip,
+                       rts51x_trans_dma_enable(srb->sc_data_direction, chip,
                                         sector_cnt * 512, DMA_512);
 
                        rts51x_add_cmd(chip, WRITE_REG_CMD, SD_TRANSFER, 0xFF,
@@ -3168,7 +3168,7 @@ int sd_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
        return STATUS_SUCCESS;
 }
 
-void sd_cleanup_work(struct rts51x_chip *chip)
+void rts51x_sd_cleanup_work(struct rts51x_chip *chip)
 {
        struct sd_info *sd_card = &(chip->sd_card);
 
@@ -3220,12 +3220,12 @@ static int sd_power_off_card3v3(struct rts51x_chip *chip)
        return STATUS_SUCCESS;
 }
 
-int release_sd_card(struct rts51x_chip *chip)
+int rts51x_release_sd_card(struct rts51x_chip *chip)
 {
        struct sd_info *sd_card = &(chip->sd_card);
        int retval;
 
-       RTS51X_DEBUGP("release_sd_card\n");
+       RTS51X_DEBUGP("rts51x_release_sd_card\n");
 
        chip->card_ready &= ~SD_CARD;
        chip->card_fail &= ~SD_CARD;
index de155d8e682d98f55203712991be078c058a6fd5..7dd943f54c7492cfc96c756a742a1f95f7cd0ce9 100644 (file)
@@ -256,13 +256,13 @@ struct timing_phase_path {
        int len;
 };
 
-int sd_select_card(struct rts51x_chip *chip, int select);
-int reset_sd_card(struct rts51x_chip *chip);
-int sd_switch_clock(struct rts51x_chip *chip);
-int sd_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
+int rts51x_sd_select_card(struct rts51x_chip *chip, int select);
+int rts51x_reset_sd_card(struct rts51x_chip *chip);
+int rts51x_sd_switch_clock(struct rts51x_chip *chip);
+int rts51x_sd_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
          u16 sector_cnt);
-void sd_cleanup_work(struct rts51x_chip *chip);
-int release_sd_card(struct rts51x_chip *chip);
+void rts51x_sd_cleanup_work(struct rts51x_chip *chip);
+int rts51x_release_sd_card(struct rts51x_chip *chip);
 
 #ifdef SUPPORT_CPRM
 extern int reset_sd(struct rts51x_chip *chip);
index 0167f7f35c20f2deb7f16e16f09f49779a6b57d6..d4689839e15ab95a441c81b7f95b0b58bf8e0987 100644 (file)
@@ -269,7 +269,7 @@ static int ext_sd_get_rsp(struct rts51x_chip *chip, int len,
        return STATUS_SUCCESS;
 }
 
-int ext_sd_execute_no_data(struct rts51x_chip *chip, unsigned int lun,
+int ext_rts51x_sd_execute_no_data(struct rts51x_chip *chip, unsigned int lun,
                           u8 cmd_idx, u8 standby, u8 acmd, u8 rsp_code,
                           u32 arg)
 {
@@ -277,30 +277,30 @@ int ext_sd_execute_no_data(struct rts51x_chip *chip, unsigned int lun,
        int retval, rsp_len;
        u8 rsp_type;
 
-       retval = sd_switch_clock(chip);
+       retval = rts51x_sd_switch_clock(chip);
        if (retval != STATUS_SUCCESS)
                TRACE_RET(chip, TRANSPORT_FAILED);
 
        if (sd_card->pre_cmd_err) {
                sd_card->pre_cmd_err = 0;
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
                TRACE_RET(chip, TRANSPORT_FAILED);
        }
        retval = get_rsp_type(rsp_code, &rsp_type, &rsp_len);
        if (retval != STATUS_SUCCESS) {
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
                TRACE_RET(chip, TRANSPORT_FAILED);
        }
        sd_card->last_rsp_type = rsp_type;
 
-       retval = sd_switch_clock(chip);
+       retval = rts51x_sd_switch_clock(chip);
        if (retval != STATUS_SUCCESS)
                TRACE_RET(chip, TRANSPORT_FAILED);
        /* Set H/W SD/MMC Bus Width */
        rts51x_write_register(chip, SD_CFG1, 0x03, SD_BUS_WIDTH_4);
 
        if (standby) {
-               retval = sd_select_card(chip, 0);
+               retval = rts51x_sd_select_card(chip, 0);
                if (retval != STATUS_SUCCESS)
                        TRACE_GOTO(chip, SD_Execute_Cmd_Failed);
        }
@@ -319,7 +319,7 @@ int ext_sd_execute_no_data(struct rts51x_chip *chip, unsigned int lun,
                TRACE_GOTO(chip, SD_Execute_Cmd_Failed);
 
        if (standby) {
-               retval = sd_select_card(chip, 1);
+               retval = rts51x_sd_select_card(chip, 1);
                if (retval != STATUS_SUCCESS)
                        TRACE_GOTO(chip, SD_Execute_Cmd_Failed);
        }
@@ -328,16 +328,16 @@ int ext_sd_execute_no_data(struct rts51x_chip *chip, unsigned int lun,
 
 SD_Execute_Cmd_Failed:
        sd_card->pre_cmd_err = 1;
-       set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE);
-       release_sd_card(chip);
-       do_reset_sd_card(chip);
+       rts51x_set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE);
+       rts51x_release_sd_card(chip);
+       rts51x_do_rts51x_reset_sd_card(chip);
        if (!(chip->card_ready & SD_CARD))
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
 
        TRACE_RET(chip, TRANSPORT_FAILED);
 }
 
-int ext_sd_execute_read_data(struct rts51x_chip *chip, unsigned int lun,
+int ext_rts51x_sd_execute_read_data(struct rts51x_chip *chip, unsigned int lun,
                             u8 cmd_idx, u8 cmd12, u8 standby,
                             u8 acmd, u8 rsp_code, u32 arg, u32 data_len,
                             void *data_buf, unsigned int buf_len, int use_sg)
@@ -349,21 +349,21 @@ int ext_sd_execute_read_data(struct rts51x_chip *chip, unsigned int lun,
 
        if (sd_card->pre_cmd_err) {
                sd_card->pre_cmd_err = 0;
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
                TRACE_RET(chip, TRANSPORT_FAILED);
        }
 
-       retval = sd_switch_clock(chip);
+       retval = rts51x_sd_switch_clock(chip);
        if (retval != STATUS_SUCCESS)
                TRACE_RET(chip, STATUS_FAIL);
        retval = get_rsp_type(rsp_code, &rsp_type, &rsp_len);
        if (retval != STATUS_SUCCESS) {
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
                TRACE_RET(chip, TRANSPORT_FAILED);
        }
        sd_card->last_rsp_type = rsp_type;
 
-       retval = sd_switch_clock(chip);
+       retval = rts51x_sd_switch_clock(chip);
        if (retval != STATUS_SUCCESS)
                TRACE_RET(chip, TRANSPORT_FAILED);
        bus_width = SD_BUS_WIDTH_4;
@@ -376,7 +376,7 @@ int ext_sd_execute_read_data(struct rts51x_chip *chip, unsigned int lun,
        }
 
        if (standby) {
-               retval = sd_select_card(chip, 0);
+               retval = rts51x_sd_select_card(chip, 0);
                if (retval != STATUS_SUCCESS)
                        TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
        }
@@ -448,7 +448,7 @@ int ext_sd_execute_read_data(struct rts51x_chip *chip, unsigned int lun,
                rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CMD4, 0xFF, (u8) arg);
                rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CFG1, 0x03, bus_width);
                rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CFG2, 0xFF, rsp_type);
-               trans_dma_enable(DMA_FROM_DEVICE, chip, data_len, DMA_512);
+               rts51x_trans_dma_enable(DMA_FROM_DEVICE, chip, data_len, DMA_512);
                rts51x_add_cmd(chip, WRITE_REG_CMD, SD_TRANSFER, 0xFF,
                               SD_TM_AUTO_READ_2 | SD_TRANSFER_START);
                rts51x_add_cmd(chip, CHECK_REG_CMD, SD_TRANSFER,
@@ -490,7 +490,7 @@ int ext_sd_execute_read_data(struct rts51x_chip *chip, unsigned int lun,
                TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
 
        if (standby) {
-               retval = sd_select_card(chip, 1);
+               retval = rts51x_sd_select_card(chip, 1);
                if (retval != STATUS_SUCCESS)
                        TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
        }
@@ -531,18 +531,18 @@ int ext_sd_execute_read_data(struct rts51x_chip *chip, unsigned int lun,
 
 SD_Execute_Read_Cmd_Failed:
        sd_card->pre_cmd_err = 1;
-       set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE);
+       rts51x_set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE);
        if (read_err)
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
-       release_sd_card(chip);
-       do_reset_sd_card(chip);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
+       rts51x_release_sd_card(chip);
+       rts51x_do_rts51x_reset_sd_card(chip);
        if (!(chip->card_ready & SD_CARD))
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
 
        TRACE_RET(chip, TRANSPORT_FAILED);
 }
 
-int ext_sd_execute_write_data(struct rts51x_chip *chip, unsigned int lun,
+int ext_rts51x_sd_execute_write_data(struct rts51x_chip *chip, unsigned int lun,
                              u8 cmd_idx, u8 cmd12, u8 standby, u8 acmd,
                              u8 rsp_code, u32 arg, u32 data_len,
                              void *data_buf, unsigned int buf_len, int use_sg)
@@ -555,22 +555,22 @@ int ext_sd_execute_write_data(struct rts51x_chip *chip, unsigned int lun,
 
        if (sd_card->pre_cmd_err) {
                sd_card->pre_cmd_err = 0;
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
                TRACE_RET(chip, TRANSPORT_FAILED);
        }
 
-       retval = sd_switch_clock(chip);
+       retval = rts51x_sd_switch_clock(chip);
        if (retval != STATUS_SUCCESS)
                TRACE_RET(chip, STATUS_FAIL);
 
        retval = get_rsp_type(rsp_code, &rsp_type, &rsp_len);
        if (retval != STATUS_SUCCESS) {
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
                TRACE_RET(chip, TRANSPORT_FAILED);
        }
        sd_card->last_rsp_type = rsp_type;
 
-       retval = sd_switch_clock(chip);
+       retval = rts51x_sd_switch_clock(chip);
        if (retval != STATUS_SUCCESS)
                TRACE_RET(chip, TRANSPORT_FAILED);
        rts51x_write_register(chip, SD_CFG1, 0x03, SD_BUS_WIDTH_4);
@@ -583,7 +583,7 @@ int ext_sd_execute_write_data(struct rts51x_chip *chip, unsigned int lun,
        }
 
        if (standby) {
-               retval = sd_select_card(chip, 0);
+               retval = rts51x_sd_select_card(chip, 0);
                if (retval != STATUS_SUCCESS)
                        TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
        }
@@ -690,7 +690,7 @@ int ext_sd_execute_write_data(struct rts51x_chip *chip, unsigned int lun,
                rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BLOCK_CNT_L,
                               0xFF, (u8) ((data_len & 0x0001FE00) >> 9));
 
-               trans_dma_enable(DMA_TO_DEVICE, chip, data_len, DMA_512);
+               rts51x_trans_dma_enable(DMA_TO_DEVICE, chip, data_len, DMA_512);
 
                rts51x_add_cmd(chip, WRITE_REG_CMD, SD_TRANSFER, 0xFF,
                               SD_TM_AUTO_WRITE_3 | SD_TRANSFER_START);
@@ -724,7 +724,7 @@ int ext_sd_execute_write_data(struct rts51x_chip *chip, unsigned int lun,
        }
 
        if (standby) {
-               retval = sd_select_card(chip, 1);
+               retval = rts51x_sd_select_card(chip, 1);
                if (retval != STATUS_SUCCESS)
                        TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
        }
@@ -767,18 +767,18 @@ int ext_sd_execute_write_data(struct rts51x_chip *chip, unsigned int lun,
 
 SD_Execute_Write_Cmd_Failed:
        sd_card->pre_cmd_err = 1;
-       set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE);
+       rts51x_set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE);
        if (write_err)
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
-       release_sd_card(chip);
-       do_reset_sd_card(chip);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
+       rts51x_release_sd_card(chip);
+       rts51x_do_rts51x_reset_sd_card(chip);
        if (!(chip->card_ready & SD_CARD))
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
 
        TRACE_RET(chip, TRANSPORT_FAILED);
 }
 
-int sd_pass_thru_mode(struct scsi_cmnd *srb, struct rts51x_chip *chip)
+int rts51x_sd_pass_thru_mode(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 {
        struct sd_info *sd_card = &(chip->sd_card);
        unsigned int lun = SCSI_LUN(srb);
@@ -808,7 +808,7 @@ int sd_pass_thru_mode(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 
        if (!(CHK_BIT(chip->lun_mc, lun))) {
                SET_BIT(chip->lun_mc, lun);
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
                TRACE_RET(chip, TRANSPORT_FAILED);
        }
 
@@ -816,7 +816,7 @@ int sd_pass_thru_mode(struct scsi_cmnd *srb, struct rts51x_chip *chip)
            || (0x20 != srb->cmnd[4]) || (0x43 != srb->cmnd[5])
            || (0x61 != srb->cmnd[6]) || (0x72 != srb->cmnd[7])
            || (0x64 != srb->cmnd[8])) {
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
                TRACE_RET(chip, TRANSPORT_FAILED);
        }
 
@@ -830,7 +830,7 @@ int sd_pass_thru_mode(struct scsi_cmnd *srb, struct rts51x_chip *chip)
                break;
 
        default:
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
                TRACE_RET(chip, TRANSPORT_FAILED);
        }
 
@@ -850,7 +850,7 @@ int sd_pass_thru_mode(struct scsi_cmnd *srb, struct rts51x_chip *chip)
        return TRANSPORT_GOOD;
 }
 
-int sd_execute_no_data(struct scsi_cmnd *srb, struct rts51x_chip *chip)
+int rts51x_sd_execute_no_data(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 {
        struct sd_info *sd_card = &(chip->sd_card);
        unsigned int lun = SCSI_LUN(srb);
@@ -860,7 +860,7 @@ int sd_execute_no_data(struct scsi_cmnd *srb, struct rts51x_chip *chip)
        u32 arg;
 
        if (!sd_card->sd_pass_thru_en) {
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
                TRACE_RET(chip, TRANSPORT_FAILED);
        }
 
@@ -876,13 +876,13 @@ int sd_execute_no_data(struct scsi_cmnd *srb, struct rts51x_chip *chip)
        rsp_code = srb->cmnd[10];
 
        retval =
-           ext_sd_execute_no_data(chip, lun, cmd_idx, standby, acmd, rsp_code,
+           ext_rts51x_sd_execute_no_data(chip, lun, cmd_idx, standby, acmd, rsp_code,
                                   arg);
        scsi_set_resid(srb, 0);
        return retval;
 }
 
-int sd_execute_read_data(struct scsi_cmnd *srb, struct rts51x_chip *chip)
+int rts51x_sd_execute_read_data(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 {
        struct sd_info *sd_card = &(chip->sd_card);
        int retval;
@@ -891,7 +891,7 @@ int sd_execute_read_data(struct scsi_cmnd *srb, struct rts51x_chip *chip)
        u32 arg, data_len;
 
        if (!sd_card->sd_pass_thru_en) {
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
                TRACE_RET(chip, TRANSPORT_FAILED);
        }
 
@@ -912,7 +912,7 @@ int sd_execute_read_data(struct scsi_cmnd *srb, struct rts51x_chip *chip)
        rsp_code = srb->cmnd[10];
 
        retval =
-           ext_sd_execute_read_data(chip, lun, cmd_idx, send_cmd12, standby,
+           ext_rts51x_sd_execute_read_data(chip, lun, cmd_idx, send_cmd12, standby,
                                     acmd, rsp_code, arg, data_len,
                                     scsi_sglist(srb), scsi_bufflen(srb),
                                     scsi_sg_count(srb));
@@ -920,7 +920,7 @@ int sd_execute_read_data(struct scsi_cmnd *srb, struct rts51x_chip *chip)
        return retval;
 }
 
-int sd_execute_write_data(struct scsi_cmnd *srb, struct rts51x_chip *chip)
+int rts51x_sd_execute_write_data(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 {
        struct sd_info *sd_card = &(chip->sd_card);
        int retval;
@@ -929,7 +929,7 @@ int sd_execute_write_data(struct scsi_cmnd *srb, struct rts51x_chip *chip)
        u32 data_len, arg;
 
        if (!sd_card->sd_pass_thru_en) {
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
                TRACE_RET(chip, TRANSPORT_FAILED);
        }
 
@@ -950,7 +950,7 @@ int sd_execute_write_data(struct scsi_cmnd *srb, struct rts51x_chip *chip)
        rsp_code = srb->cmnd[10];
 
        retval =
-           ext_sd_execute_write_data(chip, lun, cmd_idx, send_cmd12, standby,
+           ext_rts51x_sd_execute_write_data(chip, lun, cmd_idx, send_cmd12, standby,
                                      acmd, rsp_code, arg, data_len,
                                      scsi_sglist(srb), scsi_bufflen(srb),
                                      scsi_sg_count(srb));
@@ -958,7 +958,7 @@ int sd_execute_write_data(struct scsi_cmnd *srb, struct rts51x_chip *chip)
        return retval;
 }
 
-int sd_get_cmd_rsp(struct scsi_cmnd *srb, struct rts51x_chip *chip)
+int rts51x_sd_get_cmd_rsp(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 {
        struct sd_info *sd_card = &(chip->sd_card);
        unsigned int lun = SCSI_LUN(srb);
@@ -966,20 +966,20 @@ int sd_get_cmd_rsp(struct scsi_cmnd *srb, struct rts51x_chip *chip)
        u16 data_len;
 
        if (!sd_card->sd_pass_thru_en) {
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
                TRACE_RET(chip, TRANSPORT_FAILED);
        }
 
        if (sd_card->pre_cmd_err) {
                sd_card->pre_cmd_err = 0;
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
                TRACE_RET(chip, TRANSPORT_FAILED);
        }
 
        data_len = ((u16) srb->cmnd[7] << 8) | srb->cmnd[8];
 
        if (sd_card->last_rsp_type == SD_RSP_TYPE_R0) {
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
                TRACE_RET(chip, TRANSPORT_FAILED);
        } else if (sd_card->last_rsp_type == SD_RSP_TYPE_R2) {
                count = (data_len < 17) ? data_len : 17;
@@ -997,20 +997,20 @@ int sd_get_cmd_rsp(struct scsi_cmnd *srb, struct rts51x_chip *chip)
        return TRANSPORT_GOOD;
 }
 
-int sd_hw_rst(struct scsi_cmnd *srb, struct rts51x_chip *chip)
+int rts51x_sd_hw_rst(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 {
        struct sd_info *sd_card = &(chip->sd_card);
        unsigned int lun = SCSI_LUN(srb);
        int retval;
 
        if (!sd_card->sd_pass_thru_en) {
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
                TRACE_RET(chip, TRANSPORT_FAILED);
        }
 
        if (sd_card->pre_cmd_err) {
                sd_card->pre_cmd_err = 0;
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
                TRACE_RET(chip, TRANSPORT_FAILED);
        }
 
@@ -1018,16 +1018,16 @@ int sd_hw_rst(struct scsi_cmnd *srb, struct rts51x_chip *chip)
            || (0x20 != srb->cmnd[4]) || (0x43 != srb->cmnd[5])
            || (0x61 != srb->cmnd[6]) || (0x72 != srb->cmnd[7])
            || (0x64 != srb->cmnd[8])) {
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
                TRACE_RET(chip, TRANSPORT_FAILED);
        }
 
        switch (srb->cmnd[1] & 0x0F) {
        case 0:
                /* SD Card Power Off -> ON and Initialization */
-               retval = reset_sd_card(chip);
+               retval = rts51x_reset_sd_card(chip);
                if (retval != STATUS_SUCCESS) {
-                       set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+                       rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
                        sd_card->pre_cmd_err = 1;
                        TRACE_RET(chip, TRANSPORT_FAILED);
                }
@@ -1038,14 +1038,14 @@ int sd_hw_rst(struct scsi_cmnd *srb, struct rts51x_chip *chip)
                 * (without SD Card Power Off -> ON) */
                retval = reset_sd(chip);
                if (retval != STATUS_SUCCESS) {
-                       set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+                       rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
                        sd_card->pre_cmd_err = 1;
                        TRACE_RET(chip, TRANSPORT_FAILED);
                }
                break;
 
        default:
-               set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+               rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
                TRACE_RET(chip, TRANSPORT_FAILED);
        }
 
index 75e263b6594cbf3b77b1cd66c07269777959b4d3..79dfd27db41a8c4450133b6830576e0b518cc52a 100644 (file)
 #include "sd.h"
 
 #ifdef SUPPORT_CPRM
-int ext_sd_execute_no_data(struct rts51x_chip *chip, unsigned int lun,
+int ext_rts51x_sd_execute_no_data(struct rts51x_chip *chip, unsigned int lun,
                           u8 cmd_idx, u8 standby, u8 acmd, u8 rsp_code,
                           u32 arg);
-int ext_sd_execute_read_data(struct rts51x_chip *chip, unsigned int lun,
+int ext_rts51x_sd_execute_read_data(struct rts51x_chip *chip, unsigned int lun,
                             u8 cmd_idx, u8 cmd12, u8 standby, u8 acmd,
                             u8 rsp_code, u32 arg, u32 data_len, void *data_buf,
                             unsigned int buf_len, int use_sg);
-int ext_sd_execute_write_data(struct rts51x_chip *chip, unsigned int lun,
+int ext_rts51x_sd_execute_write_data(struct rts51x_chip *chip, unsigned int lun,
                              u8 cmd_idx, u8 cmd12, u8 standby, u8 acmd,
                              u8 rsp_code, u32 arg, u32 data_len,
                              void *data_buf, unsigned int buf_len, int use_sg);
 
-int sd_pass_thru_mode(struct scsi_cmnd *srb, struct rts51x_chip *chip);
-int sd_execute_no_data(struct scsi_cmnd *srb, struct rts51x_chip *chip);
-int sd_execute_read_data(struct scsi_cmnd *srb, struct rts51x_chip *chip);
-int sd_execute_write_data(struct scsi_cmnd *srb, struct rts51x_chip *chip);
-int sd_get_cmd_rsp(struct scsi_cmnd *srb, struct rts51x_chip *chip);
-int sd_hw_rst(struct scsi_cmnd *srb, struct rts51x_chip *chip);
+int rts51x_sd_pass_thru_mode(struct scsi_cmnd *srb, struct rts51x_chip *chip);
+int rts51x_sd_execute_no_data(struct scsi_cmnd *srb, struct rts51x_chip *chip);
+int rts51x_sd_execute_read_data(struct scsi_cmnd *srb, struct rts51x_chip *chip);
+int rts51x_sd_execute_write_data(struct scsi_cmnd *srb, struct rts51x_chip *chip);
+int rts51x_sd_get_cmd_rsp(struct scsi_cmnd *srb, struct rts51x_chip *chip);
+int rts51x_sd_hw_rst(struct scsi_cmnd *srb, struct rts51x_chip *chip);
 #endif
 
 #endif /* __RTS51X_SD_CPRM_H */
index 58f8ba24caedb6fd6d00e80f38689cc5cb603e4a..10fea7e16ace00dedfd9c4a6573d4643246c2ce9 100644 (file)
@@ -425,7 +425,7 @@ static int reset_xd(struct rts51x_chip *chip)
                }
 #endif
 
-               retval = card_power_on(chip, XD_CARD);
+               retval = rts51x_card_power_on(chip, XD_CARD);
                if (retval != STATUS_SUCCESS)
                        TRACE_RET(chip, retval);
 #ifdef SUPPORT_OCP
@@ -472,8 +472,8 @@ static int reset_xd(struct rts51x_chip *chip)
                rts51x_init_cmd(chip);
                rts51x_add_cmd(chip, WRITE_REG_CMD, XD_DTCTL, 0xFF,
                        XD_TIME_SETUP_STEP * 3 + XD_TIME_RW_STEP *
-                       (2 + i + chip->option.xd_rw_step)
-                       + XD_TIME_RWN_STEP * (i + chip->option.xd_rwn_step));
+                       (2 + i + chip->option.rts51x_xd_rw_step)
+                       + XD_TIME_RWN_STEP * (i + chip->option.rts51x_xd_rwn_step));
                rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CATCTL, 0xFF,
                        XD_TIME_SETUP_STEP * 3 + XD_TIME_RW_STEP * (4 +
                        i) + XD_TIME_RWN_STEP * (3 + i));
@@ -905,7 +905,7 @@ static u32 xd_get_l2p_tbl(struct rts51x_chip *chip, int zone_no, u16 log_off)
        return (u32) zone->l2p_table[log_off] + ((u32) (zone_no) << 10);
 }
 
-int reset_xd_card(struct rts51x_chip *chip)
+int rts51x_reset_xd_card(struct rts51x_chip *chip)
 {
        struct xd_info *xd_card = &(chip->xd_card);
        int retval;
@@ -920,7 +920,7 @@ int reset_xd_card(struct rts51x_chip *chip)
        xd_card->cis_block = 0xFFFF;
        xd_card->delay_write.delay_write_flag = 0;
 
-       enable_card_clock(chip, XD_CARD);
+       rts51x_enable_card_clock(chip, XD_CARD);
 
        retval = reset_xd(chip);
        if (retval != STATUS_SUCCESS) {
@@ -1526,7 +1526,7 @@ static int xd_read_multiple_pages(struct rts51x_chip *chip, u32 phy_blk,
        rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CHK_DATA_STATUS,
                       XD_AUTO_CHK_DATA_STATUS, XD_AUTO_CHK_DATA_STATUS);
 
-       trans_dma_enable(chip->srb->sc_data_direction, chip, page_cnt * 512,
+       rts51x_trans_dma_enable(chip->srb->sc_data_direction, chip, page_cnt * 512,
                         DMA_512);
 
        rts51x_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF,
@@ -1745,7 +1745,7 @@ static int xd_write_multiple_pages(struct rts51x_chip *chip, u32 old_blk,
        rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01,
                       RING_BUFFER);
 
-       trans_dma_enable(chip->srb->sc_data_direction, chip, page_cnt * 512,
+       rts51x_trans_dma_enable(chip->srb->sc_data_direction, chip, page_cnt * 512,
                         DMA_512);
 
        rts51x_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF,
@@ -1842,7 +1842,7 @@ static int xd_delay_write(struct rts51x_chip *chip)
        return STATUS_SUCCESS;
 }
 
-int xd_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
+int rts51x_xd_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
          u16 sector_cnt)
 {
        struct xd_info *xd_card = &(chip->xd_card);
@@ -1860,7 +1860,7 @@ int xd_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
 
        xd_card->counter = 0;
 
-       RTS51X_DEBUGP("xd_rw: scsi_bufflen = %d, scsi_sg_count = %d\n",
+       RTS51X_DEBUGP("rts51x_xd_rw: scsi_bufflen = %d, scsi_sg_count = %d\n",
                       scsi_bufflen(srb), scsi_sg_count(srb));
        RTS51X_DEBUGP("Data direction: %s\n",
                       (srb->sc_data_direction ==
@@ -1883,7 +1883,7 @@ int xd_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
                retval = xd_build_l2p_tbl(chip, zone_no);
                if (retval != STATUS_SUCCESS) {
                        chip->card_fail |= XD_CARD;
-                       set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+                       rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
                        TRACE_RET(chip, retval);
                }
        }
@@ -1900,7 +1900,7 @@ int xd_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
                                                      delay_write->pageoff,
                                                      start_page);
                                if (retval != STATUS_SUCCESS) {
-                                       set_sense_type(chip, lun,
+                                       rts51x_set_sense_type(chip, lun,
                                                SENSE_TYPE_MEDIA_WRITE_ERR);
                                        TRACE_RET(chip, retval);
                                }
@@ -1916,7 +1916,7 @@ int xd_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
                } else {
                        retval = xd_delay_write(chip);
                        if (retval != STATUS_SUCCESS) {
-                               set_sense_type(chip, lun,
+                               rts51x_set_sense_type(chip, lun,
                                               SENSE_TYPE_MEDIA_WRITE_ERR);
                                TRACE_RET(chip, retval);
                        }
@@ -1924,7 +1924,7 @@ int xd_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
                        new_blk = xd_get_unused_block(chip, zone_no);
                        if ((old_blk == BLK_NOT_FOUND)
                            || (new_blk == BLK_NOT_FOUND)) {
-                               set_sense_type(chip, lun,
+                               rts51x_set_sense_type(chip, lun,
                                               SENSE_TYPE_MEDIA_WRITE_ERR);
                                TRACE_RET(chip, retval);
                        }
@@ -1935,11 +1935,11 @@ int xd_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
                        if (retval != STATUS_SUCCESS) {
                                if (monitor_card_cd(chip, XD_CARD) ==
                                    CD_NOT_EXIST) {
-                                       set_sense_type(chip, lun,
+                                       rts51x_set_sense_type(chip, lun,
                                                SENSE_TYPE_MEDIA_NOT_PRESENT);
                                        TRACE_RET(chip, STATUS_FAIL);
                                }
-                               set_sense_type(chip, lun,
+                               rts51x_set_sense_type(chip, lun,
                                               SENSE_TYPE_MEDIA_WRITE_ERR);
                                TRACE_RET(chip, retval);
                        }
@@ -1948,18 +1948,18 @@ int xd_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
                retval = xd_delay_write(chip);
                if (retval != STATUS_SUCCESS) {
                        if (monitor_card_cd(chip, XD_CARD) == CD_NOT_EXIST) {
-                               set_sense_type(chip, lun,
+                               rts51x_set_sense_type(chip, lun,
                                               SENSE_TYPE_MEDIA_NOT_PRESENT);
                                TRACE_RET(chip, STATUS_FAIL);
                        }
-                       set_sense_type(chip, lun,
+                       rts51x_set_sense_type(chip, lun,
                                       SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
                        TRACE_RET(chip, retval);
                }
 
                old_blk = xd_get_l2p_tbl(chip, zone_no, log_off);
                if (old_blk == BLK_NOT_FOUND) {
-                       set_sense_type(chip, lun,
+                       rts51x_set_sense_type(chip, lun,
                                       SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
                        TRACE_RET(chip, STATUS_FAIL);
                }
@@ -1980,7 +1980,7 @@ int xd_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
                                                        start_page, end_page,
                                                        buf, &ptr, &offset);
                        if (retval != STATUS_SUCCESS) {
-                               set_sense_type(chip, lun,
+                               rts51x_set_sense_type(chip, lun,
                                        SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
                                TRACE_RET(chip, STATUS_FAIL);
                        }
@@ -1991,7 +1991,7 @@ int xd_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
                                                    end_page, buf, &ptr,
                                                    &offset);
                        if (retval != STATUS_SUCCESS) {
-                               set_sense_type(chip, lun,
+                               rts51x_set_sense_type(chip, lun,
                                               SENSE_TYPE_MEDIA_WRITE_ERR);
                                TRACE_RET(chip, STATUS_FAIL);
                        }
@@ -2010,7 +2010,7 @@ int xd_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
                        retval = xd_build_l2p_tbl(chip, zone_no);
                        if (retval != STATUS_SUCCESS) {
                                chip->card_fail |= XD_CARD;
-                               set_sense_type(chip, lun,
+                               rts51x_set_sense_type(chip, lun,
                                               SENSE_TYPE_MEDIA_NOT_PRESENT);
                                TRACE_RET(chip, retval);
                        }
@@ -2019,10 +2019,10 @@ int xd_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
                old_blk = xd_get_l2p_tbl(chip, zone_no, log_off);
                if (old_blk == BLK_NOT_FOUND) {
                        if (srb->sc_data_direction == DMA_FROM_DEVICE) {
-                               set_sense_type(chip, lun,
+                               rts51x_set_sense_type(chip, lun,
                                        SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
                        } else {
-                               set_sense_type(chip, lun,
+                               rts51x_set_sense_type(chip, lun,
                                               SENSE_TYPE_MEDIA_WRITE_ERR);
                        }
                        TRACE_RET(chip, STATUS_FAIL);
@@ -2031,7 +2031,7 @@ int xd_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
                if (srb->sc_data_direction == DMA_TO_DEVICE) {
                        new_blk = xd_get_unused_block(chip, zone_no);
                        if (new_blk == BLK_NOT_FOUND) {
-                               set_sense_type(chip, lun,
+                               rts51x_set_sense_type(chip, lun,
                                               SENSE_TYPE_MEDIA_WRITE_ERR);
                                TRACE_RET(chip, STATUS_FAIL);
                        }
@@ -2054,7 +2054,7 @@ int xd_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
        return STATUS_SUCCESS;
 }
 
-void xd_free_l2p_tbl(struct rts51x_chip *chip)
+void rts51x_xd_free_l2p_tbl(struct rts51x_chip *chip)
 {
        struct xd_info *xd_card = &(chip->xd_card);
        int i = 0;
@@ -2075,7 +2075,7 @@ void xd_free_l2p_tbl(struct rts51x_chip *chip)
        }
 }
 
-void xd_cleanup_work(struct rts51x_chip *chip)
+void rts51x_xd_cleanup_work(struct rts51x_chip *chip)
 {
        struct xd_info *xd_card = &(chip->xd_card);
 
@@ -2115,12 +2115,12 @@ static int xd_power_off_card3v3(struct rts51x_chip *chip)
        return STATUS_SUCCESS;
 }
 
-int release_xd_card(struct rts51x_chip *chip)
+int rts51x_release_xd_card(struct rts51x_chip *chip)
 {
        struct xd_info *xd_card = &(chip->xd_card);
        int retval;
 
-       RTS51X_DEBUGP("release_xd_card\n");
+       RTS51X_DEBUGP("rts51x_release_xd_card\n");
 
        chip->card_ready &= ~XD_CARD;
        chip->card_fail &= ~XD_CARD;
@@ -2128,7 +2128,7 @@ int release_xd_card(struct rts51x_chip *chip)
 
        xd_card->delay_write.delay_write_flag = 0;
 
-       xd_free_l2p_tbl(chip);
+       rts51x_xd_free_l2p_tbl(chip);
 
        rts51x_write_register(chip, SFSM_ED, HW_CMD_STOP, HW_CMD_STOP);
 
index 55e4205e23faaae3a5749490537c8b6e20f8a3ad..695a0b4d7e52ff49e973724684fa9b83acbb6752 100644 (file)
 #define        CIS1_8                  (256 + 8)
 #define        CIS1_9                  (256 + 9)
 
-int reset_xd_card(struct rts51x_chip *chip);
-int xd_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
+int rts51x_reset_xd_card(struct rts51x_chip *chip);
+int rts51x_xd_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
          u16 sector_cnt);
-void xd_free_l2p_tbl(struct rts51x_chip *chip);
-void xd_cleanup_work(struct rts51x_chip *chip);
-int release_xd_card(struct rts51x_chip *chip);
+void rts51x_xd_free_l2p_tbl(struct rts51x_chip *chip);
+void rts51x_xd_cleanup_work(struct rts51x_chip *chip);
+int rts51x_release_xd_card(struct rts51x_chip *chip);
 
 #endif /* __RTS51X_XD_H */
index cc2b54d52b1b1d043ca2210a678090df401f0044..27365f9bc0b035a6b894e2317dd7da4d6385b001 100644 (file)
@@ -338,7 +338,7 @@ void cpld_set_fractional_mode(struct channel *sc, u32 mode,
                           SBE_2T3E3_CPLD_VAL_FRACTIONAL_MODE_2);
                break;
        default:
-               printk(KERN_ERR "wrong mode in set_fractional_mode\n");
+               netdev_err(sc->dev, "wrong mode in set_fractional_mode\n");
                return;
        }
 
index f3dbef6b0eef24cf8855615c3adb34b640412d24..c8e039860dc4257051aac56d14e9a89ab8961f50 100644 (file)
@@ -135,9 +135,10 @@ void t3e3_read_card_serial_number(struct channel *sc)
        for (i = 0; i < 3; i++)
                sc->ether.card_serial_number[i] = t3e3_eeprom_read_word(sc, 10 + i);
 
-       printk(KERN_INFO "SBE wanPMC-2T3E3 serial number: %04X%04X%04X\n",
-              sc->ether.card_serial_number[0], sc->ether.card_serial_number[1],
-              sc->ether.card_serial_number[2]);
+       netdev_info(sc->dev, "SBE wanPMC-2T3E3 serial number: %04X%04X%04X\n",
+                   sc->ether.card_serial_number[0],
+                   sc->ether.card_serial_number[1],
+                   sc->ether.card_serial_number[2]);
 }
 
 /*
index 8adb17816ad9c44f37388fe433d8086e0208707e..8e1a043b6b9fb4a9e11d53f9262da93858393b49 100644 (file)
@@ -10,6 +10,8 @@
  * This code is based on a driver written by SBE Inc.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
@@ -66,7 +68,7 @@ static int __devinit t3e3_init_channel(struct channel *channel, struct pci_dev *
 
        dev = alloc_hdlcdev(channel);
        if (!dev) {
-               printk(KERN_ERR "SBE 2T3E3" ": Out of memory\n");
+               pr_err("Out of memory\n");
                err = -ENOMEM;
                goto free_regions;
        }
@@ -96,7 +98,8 @@ static int __devinit t3e3_init_channel(struct channel *channel, struct pci_dev *
 
        err = request_irq(dev->irq, &t3e3_intr, IRQF_SHARED, dev->name, dev);
        if (err) {
-               printk(KERN_WARNING "%s: could not get irq: %d\n", dev->name, dev->irq);
+               netdev_warn(channel->dev, "%s: could not get irq: %d\n",
+                           dev->name, dev->irq);
                goto unregister_dev;
        }
 
@@ -144,7 +147,7 @@ static int __devinit t3e3_init_card(struct pci_dev *pdev, const struct pci_devic
                                break; /* found the second channel */
 
                if (!pdev1) {
-                       printk(KERN_ERR "SBE 2T3E3" ": Can't find the second channel\n");
+                       dev_err(&pdev->dev, "Can't find the second channel\n");
                        return -EFAULT;
                }
                channels = 2;
@@ -153,7 +156,7 @@ static int __devinit t3e3_init_card(struct pci_dev *pdev, const struct pci_devic
 
        card = kzalloc(sizeof(struct card) + channels * sizeof(struct channel), GFP_KERNEL);
        if (!card) {
-               printk(KERN_ERR "SBE 2T3E3" ": Out of memory\n");
+               dev_err(&pdev->dev, "Out of memory\n");
                return -ENOBUFS;
        }
 
index 180c96327b9adc89f6f7e7030d3b16be92ddb948..1f5088b3c10b59ab479cb1aedc9483f3fe3df535 100644 (file)
@@ -57,7 +57,7 @@ static int t3e3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
        return 0;
 }
 
-static struct net_device_statst3e3_get_stats(struct net_device *dev)
+static struct net_device_stats *t3e3_get_stats(struct net_device *dev)
 {
        struct net_device_stats *nstats = &dev->stats;
        struct channel *sc = dev_to_priv(dev);
@@ -134,7 +134,8 @@ int setup_device(struct net_device *dev, struct channel *sc)
        dev->tx_queue_len = 100;
        hdlc->xmit = t3e3_if_start_xmit;
        hdlc->attach = t3e3_attach;
-       if ((retval = register_hdlc_device(dev))) {
+       retval = register_hdlc_device(dev);
+       if (retval) {
                dev_err(&sc->pdev->dev, "error registering HDLC device\n");
                return retval;
        }
index 3cfd0516adfa5ea6e7e8986b0150eb09711081c2..f579f143f85fc5045ed6e9047fcd819fdf342b82 100644 (file)
@@ -5454,8 +5454,6 @@ static void if_scan_init(void)
                        dev->ethtool_ops->get_drvinfo(dev, &drvinfo);
                } else
                        continue;
-               if (!drvinfo.bus_info)
-                       continue;
                if (!strcmp(drvinfo.bus_info, "N/A"))
                        continue;
                memcpy(&cbuf, drvinfo.bus_info, 32);
@@ -7703,13 +7701,8 @@ get_bypass_slave_pfs(char *page, char **start, off_t off, int count,
                return len;
        }
        net_slave_dev = pbp_device_block_slave->ndev;
-       if (net_slave_dev) {
-               if (net_slave_dev)
-                       len = sprintf(page, "%s\n", net_slave_dev->name);
-               else
-                       len = sprintf(page, "fail\n");
-
-       }
+       if (net_slave_dev)
+               len = sprintf(page, "%s\n", net_slave_dev->name);
 
        *eof = 1;
        return len;
index 6ad4b27472e4d44b188de35db42adc5d5494e5e2..a01ca97b76650326e9ff86f4b13f95ec1a6453cb 100644 (file)
 /*                                                                            */
 /******************************************************************************/
 
-#include <linux/version.h>
-#if defined(CONFIG_SMP) && ! defined(__SMP__)
+#if defined(CONFIG_SMP) && !defined(__SMP__)
 #define __SMP__
 #endif
 
 #include <linux/proc_fs.h>
 #include <linux/netdevice.h>
 #include <asm/uaccess.h>
-//#include <linux/smp_lock.h>
+/* #include <linux/smp_lock.h> */
 #include "bp_mod.h"
 
 #define BP_PROC_DIR "bypass"
-//#define BYPASS_SUPPORT "bypass"
+/* #define BYPASS_SUPPORT "bypass" */
 
-#ifdef  BYPASS_SUPPORT
+#ifdef BYPASS_SUPPORT
 
 #define GPIO6_SET_ENTRY_SD           "gpio6_set"
 #define GPIO6_CLEAR_ENTRY_SD         "gpio6_clear"
@@ -70,7 +69,7 @@
 #define DISC_CHANGE_ENTRY_SD      "disc_change"
 #define DIS_DISC_ENTRY_SD         "dis_disc"
 #define DISC_PWUP_ENTRY_SD        "disc_pwup"
-#endif                         //bypass_support
+
 static struct proc_dir_entry *bp_procfs_dir;
 
 static struct proc_dir_entry *proc_getdir(char *name,
@@ -86,20 +85,17 @@ static struct proc_dir_entry *proc_getdir(char *name,
        if (pde == (struct proc_dir_entry *)0) {
                /* create the directory */
                pde = create_proc_entry(name, S_IFDIR, proc_dir);
-               if (pde == (struct proc_dir_entry *)0) {
-                       return (pde);
-               }
+               if (pde == (struct proc_dir_entry *)0)
+                       return pde;
        }
-       return (pde);
+       return pde;
 }
 
-#ifdef BYPASS_SUPPORT
-
 int
 bypass_proc_create_entry_sd(struct pfs_unit *pfs_unit_curr,
                            char *proc_name,
-                           write_proc_t * write_proc,
-                           read_proc_t * read_proc,
+                           write_proc_t *write_proc,
+                           read_proc_t *read_proc,
                            struct proc_dir_entry *parent_pfs, void *data)
 {
        strcpy(pfs_unit_curr->proc_name, proc_name);
@@ -107,10 +103,8 @@ bypass_proc_create_entry_sd(struct pfs_unit *pfs_unit_curr,
                                                      S_IFREG | S_IRUSR |
                                                      S_IWUSR | S_IRGRP |
                                                      S_IROTH, parent_pfs);
-       if (pfs_unit_curr->proc_entry == 0) {
-
+       if (pfs_unit_curr->proc_entry == 0)
                return -1;
-       }
 
        pfs_unit_curr->proc_entry->read_proc = read_proc;
        pfs_unit_curr->proc_entry->write_proc = write_proc;
@@ -207,9 +201,8 @@ set_bypass_pfs(struct file *file, const char *buffer,
        if (count > (sizeof(kbuf) - 1))
                return -1;
 
-       if (copy_from_user(&kbuf, buffer, count)) {
+       if (copy_from_user(&kbuf, buffer, count))
                return -1;
-       }
 
        kbuf[count] = '\0';
        length = strlen(kbuf);
@@ -239,9 +232,8 @@ set_tap_pfs(struct file *file, const char *buffer,
        if (count > (sizeof(kbuf) - 1))
                return -1;
 
-       if (copy_from_user(&kbuf, buffer, count)) {
+       if (copy_from_user(&kbuf, buffer, count))
                return -1;
-       }
 
        kbuf[count] = '\0';
        length = strlen(kbuf);
@@ -271,9 +263,8 @@ set_disc_pfs(struct file *file, const char *buffer,
        if (count > (sizeof(kbuf) - 1))
                return -1;
 
-       if (copy_from_user(&kbuf, buffer, count)) {
+       if (copy_from_user(&kbuf, buffer, count))
                return -1;
-       }
 
        kbuf[count] = '\0';
        length = strlen(kbuf);
@@ -421,9 +412,8 @@ set_bypass_wd_pfs(struct file *file, const char *buffer,
        unsigned int timeout = 0;
        char *timeout_ptr = kbuf;
 
-       if (copy_from_user(&kbuf, buffer, count)) {
+       if (copy_from_user(&kbuf, buffer, count))
                return -1;
-       }
 
        timeout_ptr = kbuf;
        timeout = atoi(&timeout_ptr);
@@ -570,9 +560,8 @@ set_dis_bypass_pfs(struct file *file, const char *buffer,
 
        int bypass_param = 0, length = 0;
 
-       if (copy_from_user(&kbuf, buffer, count)) {
+       if (copy_from_user(&kbuf, buffer, count))
                return -1;
-       }
 
        kbuf[count] = '\0';
        length = strlen(kbuf);
@@ -599,9 +588,8 @@ set_dis_tap_pfs(struct file *file, const char *buffer,
 
        int tap_param = 0, length = 0;
 
-       if (copy_from_user(&kbuf, buffer, count)) {
+       if (copy_from_user(&kbuf, buffer, count))
                return -1;
-       }
 
        kbuf[count] = '\0';
        length = strlen(kbuf);
@@ -628,9 +616,8 @@ set_dis_disc_pfs(struct file *file, const char *buffer,
 
        int tap_param = 0, length = 0;
 
-       if (copy_from_user(&kbuf, buffer, count)) {
+       if (copy_from_user(&kbuf, buffer, count))
                return -1;
-       }
 
        kbuf[count] = '\0';
        length = strlen(kbuf);
@@ -717,9 +704,8 @@ set_bypass_pwup_pfs(struct file *file, const char *buffer,
 
        int bypass_param = 0, length = 0;
 
-       if (copy_from_user(&kbuf, buffer, count)) {
+       if (copy_from_user(&kbuf, buffer, count))
                return -1;
-       }
 
        kbuf[count] = '\0';
        length = strlen(kbuf);
@@ -746,9 +732,8 @@ set_bypass_pwoff_pfs(struct file *file, const char *buffer,
 
        int bypass_param = 0, length = 0;
 
-       if (copy_from_user(&kbuf, buffer, count)) {
+       if (copy_from_user(&kbuf, buffer, count))
                return -1;
-       }
 
        kbuf[count] = '\0';
        length = strlen(kbuf);
@@ -775,9 +760,8 @@ set_tap_pwup_pfs(struct file *file, const char *buffer,
 
        int tap_param = 0, length = 0;
 
-       if (copy_from_user(&kbuf, buffer, count)) {
+       if (copy_from_user(&kbuf, buffer, count))
                return -1;
-       }
 
        kbuf[count] = '\0';
        length = strlen(kbuf);
@@ -804,9 +788,8 @@ set_disc_pwup_pfs(struct file *file, const char *buffer,
 
        int tap_param = 0, length = 0;
 
-       if (copy_from_user(&kbuf, buffer, count)) {
+       if (copy_from_user(&kbuf, buffer, count))
                return -1;
-       }
 
        kbuf[count] = '\0';
        length = strlen(kbuf);
@@ -913,9 +896,8 @@ set_std_nic_pfs(struct file *file, const char *buffer,
 
        int bypass_param = 0, length = 0;
 
-       if (copy_from_user(&kbuf, buffer, count)) {
+       if (copy_from_user(&kbuf, buffer, count))
                return -1;
-       }
 
        kbuf[count] = '\0';
        length = strlen(kbuf);
@@ -988,9 +970,8 @@ set_wd_exp_mode_pfs(struct file *file, const char *buffer,
        if (count > (sizeof(kbuf) - 1))
                return -1;
 
-       if (copy_from_user(&kbuf, buffer, count)) {
+       if (copy_from_user(&kbuf, buffer, count))
                return -1;
-       }
 
        kbuf[count] = '\0';
        length = strlen(kbuf);
@@ -1036,9 +1017,8 @@ set_wd_autoreset_pfs(struct file *file, const char *buffer,
        u32 timeout = 0;
        char *timeout_ptr = kbuf;
 
-       if (copy_from_user(&kbuf, buffer, count)) {
+       if (copy_from_user(&kbuf, buffer, count))
                return -1;
-       }
 
        timeout_ptr = kbuf;
        timeout = atoi(&timeout_ptr);
@@ -1061,9 +1041,8 @@ set_tpl_pfs(struct file *file, const char *buffer,
        if (count > (sizeof(kbuf) - 1))
                return -1;
 
-       if (copy_from_user(&kbuf, buffer, count)) {
+       if (copy_from_user(&kbuf, buffer, count))
                return -1;
-       }
 
        kbuf[count] = '\0';
        length = strlen(kbuf);
@@ -1094,9 +1073,8 @@ set_wait_at_pwup_pfs(struct file *file, const char *buffer,
        if (count > (sizeof(kbuf) - 1))
                return -1;
 
-       if (copy_from_user(&kbuf, buffer, count)) {
+       if (copy_from_user(&kbuf, buffer, count))
                return -1;
-       }
 
        kbuf[count] = '\0';
        length = strlen(kbuf);
@@ -1126,9 +1104,8 @@ set_hw_reset_pfs(struct file *file, const char *buffer,
        if (count > (sizeof(kbuf) - 1))
                return -1;
 
-       if (copy_from_user(&kbuf, buffer, count)) {
+       if (copy_from_user(&kbuf, buffer, count))
                return -1;
-       }
 
        kbuf[count] = '\0';
        length = strlen(kbuf);
@@ -1147,10 +1124,10 @@ set_hw_reset_pfs(struct file *file, const char *buffer,
 
 #endif                         /*PMC_FIX_FLAG */
 
-int bypass_proc_create_dev_sd(bpctl_dev_t * pbp_device_block)
+int bypass_proc_create_dev_sd(bpctl_dev_t *pbp_device_block)
 {
        struct bypass_pfs_sd *current_pfs = &(pbp_device_block->bypass_pfs_set);
-       static struct proc_dir_entry *procfs_dir = NULL;
+       static struct proc_dir_entry *procfs_dir;
        int ret = 0;
 
        sprintf(current_pfs->dir_name, "bypass_%s", dev->name);
@@ -1327,7 +1304,7 @@ int bypass_proc_create_dev_sd(bpctl_dev_t * pbp_device_block)
        return ret;
 }
 
-int bypass_proc_remove_dev_sd(bpctl_dev_t * pbp_device_block)
+int bypass_proc_remove_dev_sd(bpctl_dev_t *pbp_device_block)
 {
 
        struct bypass_pfs_sd *current_pfs = &pbp_device_block->bypass_pfs_set;
index a1c85eec02f078b87b5944d35b6b65da5378b659..e9db2d114ba1ea4f4217d9ce8564521095a63081 100644 (file)
@@ -15,6 +15,7 @@
 
 #include "bp_ioctl.h"
 #include "libbp_sd.h"
+#include <linux/version.h>
 
 #define IF_NAME            "eth"
 #define SILICOM_VID        0x1374
index 527829d5813370a9b2782b59986cbf7dc00ffdae..95a1f1815d9072f9fa10c37cef89d2cfe97c6259 100644 (file)
@@ -11,7 +11,6 @@
 /*                                                                            */
 /******************************************************************************/
 
-#include <linux/version.h>
 #if defined(CONFIG_SMP) && ! defined(__SMP__)
 #define __SMP__
 #endif
index cd920dad85cdefb881b6ca25ddd62c5400125e12..f08f4593b186ff873dc4df4116019ce0772f534d 100644 (file)
@@ -142,39 +142,12 @@ static DEFINE_PCI_DEVICE_TABLE(slic_pci_tbl) = {
 
 MODULE_DEVICE_TABLE(pci, slic_pci_tbl);
 
-#ifdef ASSERT
-#undef ASSERT
-#endif
-
-static void slic_assert_fail(void)
-{
-       u32 cpuid;
-       u32 curr_pid;
-       cpuid = smp_processor_id();
-       curr_pid = current->pid;
-
-       printk(KERN_ERR "%s CPU # %d ---- PID # %d\n",
-              __func__, cpuid, curr_pid);
-}
-
-#ifndef ASSERT
-#define ASSERT(a) do {                                                 \
-       if (!(a)) {                                                     \
-               printk(KERN_ERR "slicoss ASSERT() Failure: function %s" \
-                       "line %d\n", __func__, __LINE__);               \
-               slic_assert_fail();                                     \
-       }                                                               \
-} while (0)
-#endif
-
-
 #define SLIC_GET_SLIC_HANDLE(_adapter, _pslic_handle)                   \
 {                                                                       \
     spin_lock_irqsave(&_adapter->handle_lock.lock,                      \
                        _adapter->handle_lock.flags);                   \
     _pslic_handle  =  _adapter->pfree_slic_handles;                     \
     if (_pslic_handle) {                                                \
-       ASSERT(_pslic_handle->type == SLIC_HANDLE_FREE);                \
        _adapter->pfree_slic_handles = _pslic_handle->next;             \
     }                                                                   \
     spin_unlock_irqrestore(&_adapter->handle_lock.lock,                 \
@@ -325,11 +298,8 @@ static void slic_timer_ping(ulong dev)
        struct adapter *adapter;
        struct sliccard *card;
 
-       ASSERT(dev);
        adapter = netdev_priv((struct net_device *)dev);
-       ASSERT(adapter);
        card = adapter->card;
-       ASSERT(card);
 
        adapter->pingtimer.expires = jiffies + (PING_TIMER_INTERVAL * HZ);
        add_timer(&adapter->pingtimer);
@@ -361,9 +331,6 @@ static void slic_link_config(struct adapter *adapter,
        if (adapter->state != ADAPT_UP)
                return;
 
-       ASSERT((adapter->devid == SLIC_1GB_DEVICE_ID)
-              || (adapter->devid == SLIC_2GB_DEVICE_ID));
-
        if (linkspeed > LINK_1000MB)
                linkspeed = LINK_AUTOSPEED;
        if (linkduplex > LINK_AUTOD)
@@ -593,8 +560,7 @@ static int slic_card_download(struct adapter *adapter)
                file = "slicoss/gbdownload.sys";
                break;
        default:
-               ASSERT(0);
-               break;
+               return -ENOENT;
        }
        ret = request_firmware(&fw, file, &adapter->pcidev->dev);
        if (ret) {
@@ -604,7 +570,6 @@ static int slic_card_download(struct adapter *adapter)
        }
        numsects = *(u32 *)(fw->data + index);
        index += 4;
-       ASSERT(numsects <= 3);
        for (i = 0; i < numsects; i++) {
                sectsize[i] = *(u32 *)(fw->data + index);
                index += 4;
@@ -1060,8 +1025,6 @@ static void slic_upr_start(struct adapter *adapter)
        case SLIC_UPR_PING:
                slic_reg32_write(&slic_regs->slic_ping, 1, FLUSH);
                break;
-       default:
-               ASSERT(0);
        }
 }
 
@@ -1116,9 +1079,6 @@ static void slic_link_upr_complete(struct adapter *adapter, u32 isr)
        if (adapter->state != ADAPT_UP)
                return;
 
-       ASSERT((adapter->devid == SLIC_1GB_DEVICE_ID)
-              || (adapter->devid == SLIC_2GB_DEVICE_ID));
-
        linkup = linkstatus & GIG_LINKUP ? LINK_UP : LINK_DOWN;
        if (linkstatus & GIG_SPEED_1000)
                linkspeed = LINK_1000MB;
@@ -1170,7 +1130,6 @@ static void slic_upr_request_complete(struct adapter *adapter, u32 isr)
        spin_lock_irqsave(&adapter->upr_lock.lock, adapter->upr_lock.flags);
        upr = adapter->upr_list;
        if (!upr) {
-               ASSERT(0);
                spin_unlock_irqrestore(&adapter->upr_lock.lock,
                                        adapter->upr_lock.flags);
                return;
@@ -1178,7 +1137,6 @@ static void slic_upr_request_complete(struct adapter *adapter, u32 isr)
        adapter->upr_list = upr->next;
        upr->next = NULL;
        adapter->upr_busy = 0;
-       ASSERT(adapter->port == upr->adapter);
        switch (upr->upr_request) {
        case SLIC_UPR_STATS:
                {
@@ -1260,23 +1218,9 @@ static void slic_upr_request_complete(struct adapter *adapter, u32 isr)
                break;
        case SLIC_UPR_RCONFIG:
                break;
-       case SLIC_UPR_RPHY:
-               ASSERT(0);
-               break;
-       case SLIC_UPR_ENLB:
-               ASSERT(0);
-               break;
-       case SLIC_UPR_ENCT:
-               ASSERT(0);
-               break;
-       case SLIC_UPR_PDWN:
-               ASSERT(0);
-               break;
        case SLIC_UPR_PING:
                card->pingstatus |= (isr & ISR_PINGDSMASK);
                break;
-       default:
-               ASSERT(0);
        }
        kfree(upr);
        slic_upr_start(adapter);
@@ -1292,7 +1236,6 @@ static void slic_config_get(struct adapter *adapter, u32 config,
        status = slic_upr_request(adapter,
                                  SLIC_UPR_RCONFIG,
                                  (u32) config, (u32) config_h, 0, 0);
-       ASSERT(status == 0);
 }
 
 /*
@@ -1422,7 +1365,6 @@ static int slic_rspqueue_init(struct adapter *adapter)
        __iomem struct slic_regs *slic_regs = adapter->slic_regs;
        u32 paddrh = 0;
 
-       ASSERT(adapter->state == ADAPT_DOWN);
        memset(rspq, 0, sizeof(struct slic_rspqueue));
 
        rspq->num_pages = SLIC_RSPQ_PAGES_GB;
@@ -1439,14 +1381,6 @@ static int slic_rspqueue_init(struct adapter *adapter)
                }
                /* FIXME:
                 * do we really need this assertions (4K PAGE_SIZE aligned addr)? */
-#if 0
-#ifndef CONFIG_X86_64
-               ASSERT(((u32) rspq->vaddr[i] & 0xFFFFF000) ==
-                      (u32) rspq->vaddr[i]);
-               ASSERT(((u32) rspq->paddr[i] & 0xFFFFF000) ==
-                      (u32) rspq->paddr[i]);
-#endif
-#endif
                memset(rspq->vaddr[i], 0, PAGE_SIZE);
 
                if (paddrh == 0) {
@@ -1475,18 +1409,9 @@ static struct slic_rspbuf *slic_rspqueue_getnext(struct adapter *adapter)
                return NULL;
 
        buf = rspq->rspbuf;
-#if BITS_PER_LONG == 32
-       ASSERT((buf->status & 0xFFFFFFE0) == 0);
-#endif
-       ASSERT(buf->hosthandle);
        if (++rspq->offset < SLIC_RSPQ_BUFSINPAGE) {
                rspq->rspbuf++;
-#if BITS_PER_LONG == 32
-               ASSERT(((u32) rspq->rspbuf & 0xFFFFFFE0) ==
-                      (u32) rspq->rspbuf);
-#endif
        } else {
-               ASSERT(rspq->offset == SLIC_RSPQ_BUFSINPAGE);
                slic_reg64_write(adapter, &adapter->slic_regs->slic_rbar64,
                        (rspq->paddr[rspq->pageindex] | SLIC_RSPQ_BUFSINPAGE),
                        &adapter->slic_regs->slic_addr_upper, 0, DONT_FLUSH);
@@ -1494,22 +1419,9 @@ static struct slic_rspbuf *slic_rspqueue_getnext(struct adapter *adapter)
                rspq->offset = 0;
                rspq->rspbuf = (struct slic_rspbuf *)
                                                rspq->vaddr[rspq->pageindex];
-#if BITS_PER_LONG == 32
-               ASSERT(((u32) rspq->rspbuf & 0xFFFFF000) ==
-                      (u32) rspq->rspbuf);
-#endif
        }
-#if BITS_PER_LONG == 32
-       ASSERT(((u32) buf & 0xFFFFFFE0) == (u32) buf);
-#endif
-       return buf;
-}
 
-static void slic_cmdqmem_init(struct adapter *adapter)
-{
-       struct slic_cmdqmem *cmdqmem = &adapter->cmdqmem;
-
-       memset(cmdqmem, 0, sizeof(struct slic_cmdqmem));
+       return buf;
 }
 
 static void slic_cmdqmem_free(struct adapter *adapter)
@@ -1540,9 +1452,7 @@ static u32 *slic_cmdqmem_addpage(struct adapter *adapter)
                                        &cmdqmem->dma_pages[cmdqmem->pagecnt]);
        if (!pageaddr)
                return NULL;
-#if BITS_PER_LONG == 32
-       ASSERT(((u32) pageaddr & 0xFFFFF000) == (u32) pageaddr);
-#endif
+
        cmdqmem->pages[cmdqmem->pagecnt] = pageaddr;
        cmdqmem->pagecnt++;
        return pageaddr;
@@ -1598,11 +1508,6 @@ static void slic_cmdq_addcmdpage(struct adapter *adapter, u32 *page)
               (adapter->slic_handle_ix < 256)) {
                /* Allocate and initialize a SLIC_HANDLE for this command */
                SLIC_GET_SLIC_HANDLE(adapter, pslic_handle);
-               if (pslic_handle == NULL)
-                       ASSERT(0);
-               ASSERT(pslic_handle ==
-                      &adapter->slic_handles[pslic_handle->token.
-                                             handle_index]);
                pslic_handle->type = SLIC_HANDLE_CMD;
                pslic_handle->address = (void *) cmd;
                pslic_handle->offset = (ushort) adapter->slic_handle_ix++;
@@ -1641,20 +1546,16 @@ static int slic_cmdq_init(struct adapter *adapter)
        int i;
        u32 *pageaddr;
 
-       ASSERT(adapter->state == ADAPT_DOWN);
        memset(&adapter->cmdq_all, 0, sizeof(struct slic_cmdqueue));
        memset(&adapter->cmdq_free, 0, sizeof(struct slic_cmdqueue));
        memset(&adapter->cmdq_done, 0, sizeof(struct slic_cmdqueue));
        spin_lock_init(&adapter->cmdq_all.lock.lock);
        spin_lock_init(&adapter->cmdq_free.lock.lock);
        spin_lock_init(&adapter->cmdq_done.lock.lock);
-       slic_cmdqmem_init(adapter);
+       memset(&adapter->cmdqmem, 0, sizeof(struct slic_cmdqmem));
        adapter->slic_handle_ix = 1;
        for (i = 0; i < SLIC_CMDQ_INITPAGES; i++) {
                pageaddr = slic_cmdqmem_addpage(adapter);
-#if BITS_PER_LONG == 32
-               ASSERT(((u32) pageaddr & 0xFFFFF000) == (u32) pageaddr);
-#endif
                if (!pageaddr) {
                        slic_cmdq_free(adapter);
                        return -ENOMEM;
@@ -1682,7 +1583,6 @@ static void slic_cmdq_reset(struct adapter *adapter)
        while (hcmd) {
                if (hcmd->busy) {
                        skb = hcmd->skb;
-                       ASSERT(skb);
                        hcmd->busy = 0;
                        hcmd->skb = NULL;
                        dev_kfree_skb_irq(skb);
@@ -1718,7 +1618,6 @@ static void slic_cmdq_getdone(struct adapter *adapter)
        struct slic_cmdqueue *done_cmdq = &adapter->cmdq_done;
        struct slic_cmdqueue *free_cmdq = &adapter->cmdq_free;
 
-       ASSERT(free_cmdq->head == NULL);
        spin_lock_irqsave(&done_cmdq->lock.lock, done_cmdq->lock.flags);
 
        free_cmdq->head = done_cmdq->head;
@@ -1884,7 +1783,6 @@ static int slic_rcvqueue_init(struct adapter *adapter)
        int i, count;
        struct slic_rcvqueue *rcvq = &adapter->rcvqueue;
 
-       ASSERT(adapter->state == ADAPT_DOWN);
        rcvq->tail = NULL;
        rcvq->head = NULL;
        rcvq->size = SLIC_RCVQ_ENTRIES;
@@ -1913,7 +1811,6 @@ static struct sk_buff *slic_rcvqueue_getnext(struct adapter *adapter)
        if (rcvq->count) {
                skb = rcvq->head;
                rcvbuf = (struct slic_rcvbuf *)skb->head;
-               ASSERT(rcvbuf);
 
                if (rcvbuf->status & IRHDDR_SVALID) {
                        rcvq->head = rcvq->head->next;
@@ -1946,8 +1843,6 @@ static u32 slic_rcvqueue_reinsert(struct adapter *adapter, struct sk_buff *skb)
        struct slic_rcvbuf *rcvbuf = (struct slic_rcvbuf *)skb->head;
        struct device *dev;
 
-       ASSERT(skb->len == SLIC_RCVBUF_HEADSIZE);
-
        paddr = (void *)pci_map_single(adapter->pcidev, skb->head,
                                  SLIC_RCVQ_RCVBUFSIZE, PCI_DMA_FROMDEVICE);
        rcvbuf->status = 0;
@@ -2019,7 +1914,6 @@ static int slic_debug_card_show(struct seq_file *seq, void *v)
                    card->adapters_activated);
        seq_printf(seq, "     Allocated           : %d\n",
                    card->adapters_allocated);
-       ASSERT(card->card_size <= SLIC_NBR_MACS);
        for (i = 0; i < card->card_size; i++) {
                seq_printf(seq,
                           "     MAC%d : %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n",
@@ -2460,7 +2354,6 @@ static void slic_link_event_handler(struct adapter *adapter)
                (u32) &pshmem->linkstatus,      /* no 4GB wrap guaranteed */
                                  0, 0, 0);
 #endif
-       ASSERT(status == 0);
 }
 
 static void slic_init_cleanup(struct adapter *adapter)
@@ -2524,8 +2417,6 @@ static void slic_mcast_set_list(struct net_device *dev)
        char *addresses;
        struct netdev_hw_addr *ha;
 
-       ASSERT(adapter);
-
        netdev_for_each_mc_addr(ha, dev) {
                addresses = (char *) &ha->addr;
                status = slic_mcast_add_list(adapter, addresses);
@@ -2612,8 +2503,6 @@ static void slic_xmit_fail(struct adapter *adapter,
                                "xmit_start skb[%p] type[%x] No host commands "
                                "available\n", skb, skb->pkt_type);
                        break;
-               default:
-                       ASSERT(0);
                }
        }
        dev_kfree_skb(skb);
@@ -2725,7 +2614,6 @@ static void slic_rcv_handler(struct adapter *adapter)
        while ((skb = slic_rcvqueue_getnext(adapter))) {
                u32 rx_bytes;
 
-               ASSERT(skb->head);
                rcvbuf = (struct slic_rcvbuf *)skb->head;
                adapter->card->events++;
                if (rcvbuf->status & IRHDDR_ERR) {
@@ -2781,16 +2669,11 @@ static void slic_xmit_complete(struct adapter *adapter)
                 Get the complete host command buffer
                */
                slic_handle_word.handle_token = rspbuf->hosthandle;
-               ASSERT(slic_handle_word.handle_index);
-               ASSERT(slic_handle_word.handle_index <= SLIC_CMDQ_MAXCMDS);
                hcmd =
                    (struct slic_hostcmd *)
                        adapter->slic_handles[slic_handle_word.handle_index].
                                                                        address;
 /*      hcmd = (struct slic_hostcmd *) rspbuf->hosthandle; */
-               ASSERT(hcmd);
-               ASSERT(hcmd->pslic_handle ==
-                      &adapter->slic_handles[slic_handle_word.handle_index]);
                if (hcmd->type == SLIC_CMD_DUMB) {
                        if (hcmd->skb)
                                dev_kfree_skb_irq(hcmd->skb);
@@ -2884,9 +2767,6 @@ static irqreturn_t slic_interrupt(int irq, void *dev_id)
                                slic_upr_request_complete(adapter, isr);
                        }
                        break;
-
-               default:
-                       break;
                }
 
                adapter->isrcopy = 0;
@@ -2911,7 +2791,6 @@ static netdev_tx_t slic_xmit_start(struct sk_buff *skb, struct net_device *dev)
        void *offloadcmd = NULL;
 
        card = adapter->card;
-       ASSERT(card);
        if ((adapter->linkstate != LINK_UP) ||
            (adapter->state != ADAPT_UP) || (card->state != CARD_UP)) {
                status = XMIT_FAIL_LINK_STATE;
@@ -2929,9 +2808,6 @@ static netdev_tx_t slic_xmit_start(struct sk_buff *skb, struct net_device *dev)
                        status = XMIT_FAIL_HOSTCMD_FAIL;
                        goto xmit_fail;
                }
-               ASSERT(hcmd->pslic_handle);
-               ASSERT(hcmd->cmd64.hosthandle ==
-                      hcmd->pslic_handle->token.handle_token);
                hcmd->skb = skb;
                hcmd->busy = 1;
                hcmd->type = SLIC_CMD_DUMB;
@@ -3024,8 +2900,6 @@ static int slic_if_init(struct adapter *adapter)
        struct slic_shmem *pshmem;
        int rc;
 
-       ASSERT(card);
-
        /* adapter should be down at this point */
        if (adapter->state != ADAPT_DOWN) {
                dev_err(&dev->dev, "%s: adapter->state != ADAPT_DOWN\n",
@@ -3033,7 +2907,6 @@ static int slic_if_init(struct adapter *adapter)
                rc = -EIO;
                goto err;
        }
-       ASSERT(adapter->linkstate == LINK_DOWN);
 
        adapter->devflags_prev = dev->flags;
        adapter->macopts = MAC_DIRECTED;
@@ -3133,9 +3006,6 @@ static int slic_entry_open(struct net_device *dev)
        struct sliccard *card = adapter->card;
        int status;
 
-       ASSERT(adapter);
-       ASSERT(card);
-
        netif_stop_queue(adapter->netdev);
 
        spin_lock_irqsave(&slic_global.driver_lock.lock,
@@ -3202,9 +3072,7 @@ static void __devexit slic_entry_remove(struct pci_dev *pcidev)
                mlist = mlist->next;
                kfree(mcaddr);
        }
-       ASSERT(adapter->card);
        card = adapter->card;
-       ASSERT(card->adapters_allocated);
        card->adapters_allocated--;
        adapter->allocated = 0;
        if (!card->adapters_allocated) {
@@ -3214,10 +3082,8 @@ static void __devexit slic_entry_remove(struct pci_dev *pcidev)
                } else {
                        while (curr_card->next != card)
                                curr_card = curr_card->next;
-                       ASSERT(curr_card);
                        curr_card->next = card->next;
                }
-               ASSERT(slic_global.num_slic_cards);
                slic_global.num_slic_cards--;
                slic_card_cleanup(card);
        }
@@ -3234,14 +3100,12 @@ static int slic_entry_halt(struct net_device *dev)
 
        spin_lock_irqsave(&slic_global.driver_lock.lock,
                                slic_global.driver_lock.flags);
-       ASSERT(card);
        netif_stop_queue(adapter->netdev);
        adapter->state = ADAPT_DOWN;
        adapter->linkstate = LINK_DOWN;
        adapter->upr_list = NULL;
        adapter->upr_busy = 0;
        adapter->devflags_prev = 0;
-       ASSERT(card->adapter[adapter->cardindex] == adapter);
        slic_reg32_write(&slic_regs->slic_icr, ICR_INT_OFF, FLUSH);
        adapter->all_reg_writes++;
        adapter->icr_reg_writes++;
@@ -3273,7 +3137,6 @@ static struct net_device_stats *slic_get_stats(struct net_device *dev)
 {
        struct adapter *adapter = netdev_priv(dev);
 
-       ASSERT(adapter);
        dev->stats.collisions = adapter->slic_stats.iface.xmit_collisions;
        dev->stats.rx_errors = adapter->slic_stats.iface.rcv_errors;
        dev->stats.tx_errors = adapter->slic_stats.iface.xmt_errors;
@@ -3296,7 +3159,6 @@ static int slic_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
        u32 data[7];
        u32 intagg;
 
-       ASSERT(rq);
        switch (cmd) {
        case SIOCSLICSETINTAGG:
                if (copy_from_user(data, rq->ifr_data, 28))
@@ -3342,7 +3204,6 @@ static int slic_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                }
 #endif
        case SIOCETHTOOL:
-               ASSERT(adapter);
                if (copy_from_user(&ecmd, rq->ifr_data, sizeof(ecmd)))
                        return -EFAULT;
 
@@ -3682,7 +3543,6 @@ static void slic_init_adapter(struct net_device *netdev,
        /*
          Initialize slic_handle array
        */
-       ASSERT(SLIC_CMDQ_MAXCMDS <= 0xFFFF);
        /*
         Start with 1.  0 is an invalid host handle.
        */
@@ -3699,8 +3559,6 @@ static void slic_init_adapter(struct net_device *netdev,
                                        sizeof(struct slic_shmem),
                                        &adapter->
                                        phys_shmem);
-       ASSERT(adapter->pshmem);
-
        if (adapter->pshmem)
                memset(adapter->pshmem, 0, sizeof(struct slic_shmem));
 }
@@ -3775,11 +3633,9 @@ static u32 slic_card_locate(struct adapter *adapter)
                }
        }
 
-       ASSERT(card);
        if (!card)
                return -ENXIO;
        /* Put the adapter in the card's adapter list */
-       ASSERT(card->adapter[adapter->port] == NULL);
        if (!card->adapter[adapter->port]) {
                card->adapter[adapter->port] = adapter;
                adapter->card = card;
@@ -3794,7 +3650,6 @@ static u32 slic_card_locate(struct adapter *adapter)
                        else
                                break;
                }
-               ASSERT(i != SLIC_MAX_PORTS);
                if (physcard->adapter[i]->slotnumber == adapter->slotnumber)
                        break;
                physcard = physcard->next;
@@ -3802,7 +3657,8 @@ static u32 slic_card_locate(struct adapter *adapter)
        if (!physcard) {
                /* no structure allocated for this physical card yet */
                physcard = kzalloc(sizeof(struct physcard), GFP_ATOMIC);
-               ASSERT(physcard);
+               if (!physcard)
+                       return -ENOMEM;
 
                physcard->next = slic_global.phys_card;
                slic_global.phys_card = physcard;
@@ -3813,7 +3669,6 @@ static u32 slic_card_locate(struct adapter *adapter)
        /* Note - this is ZERO relative */
        adapter->physport = physcard->adapters_allocd - 1;
 
-       ASSERT(physcard->adapter[adapter->physport] == NULL);
        physcard->adapter[adapter->physport] = adapter;
        adapter->physcard = physcard;
 
index 277491a877eaec8a1678858b2caa2d2b47c9492a..37d19c696ea942cfb9a665f7b588e59eeefe29c7 100644 (file)
@@ -1143,30 +1143,8 @@ static struct i2c_driver synaptics_rmi4_driver = {
        .remove         =       __devexit_p(synaptics_rmi4_remove),
        .id_table       =       synaptics_rmi4_id_table,
 };
-/**
- * synaptics_rmi4_init() - Initialize the touchscreen driver
- *
- * This function uses to initializes the synaptics
- * touchscreen driver and returns integer.
- */
-static int __init synaptics_rmi4_init(void)
-{
-       return i2c_add_driver(&synaptics_rmi4_driver);
-}
-/**
- * synaptics_rmi4_exit() - De-initialize the touchscreen driver
- *
- * This function uses to de-initialize the synaptics
- * touchscreen driver and returns none.
- */
-static void __exit synaptics_rmi4_exit(void)
-{
-       i2c_del_driver(&synaptics_rmi4_driver);
-}
-
 
-module_init(synaptics_rmi4_init);
-module_exit(synaptics_rmi4_exit);
+module_i2c_driver(synaptics_rmi4_driver);
 
 MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("naveen.gaddipati@stericsson.com, js.ha@stericsson.com");
index c8d79a7f0e0e3aa91e2af71b8855322add6b168c..79298d068636a7a9e4d19ff73994e41479b74687 100644 (file)
@@ -18,6 +18,7 @@
  */
 
 #include <linux/device.h>
+#include <linux/file.h>
 #include <linux/kthread.h>
 #include <linux/module.h>
 
@@ -203,7 +204,7 @@ static void stub_shutdown_connection(struct usbip_device *ud)
         * not touch NULL socket.
         */
        if (ud->tcp_socket) {
-               sock_release(ud->tcp_socket);
+               fput(ud->tcp_socket->file);
                ud->tcp_socket = NULL;
        }
 
@@ -477,19 +478,17 @@ static void stub_disconnect(struct usb_interface *interface)
        /* get stub_device */
        if (!sdev) {
                dev_err(&interface->dev, "could not get device");
-               /* BUG(); */
                return;
        }
 
        usb_set_intfdata(interface, NULL);
 
        /*
-        * NOTE:
-        * rx/tx threads are invoked for each usb_device.
+        * NOTE: rx/tx threads are invoked for each usb_device.
         */
        stub_remove_files(&interface->dev);
 
-       /*If usb reset called from event handler*/
+       /* If usb reset is called from event handler */
        if (busid_priv->sdev->ud.eh == current) {
                busid_priv->interf_count--;
                return;
@@ -504,13 +503,13 @@ static void stub_disconnect(struct usb_interface *interface)
 
        busid_priv->interf_count = 0;
 
-       /* 1. shutdown the current connection */
+       /* shutdown the current connection */
        shutdown_busid(busid_priv);
 
        usb_put_dev(sdev->udev);
        usb_put_intf(interface);
 
-       /* 3. free sdev */
+       /* free sdev */
        busid_priv->sdev = NULL;
        stub_device_free(sdev);
 
index 694cfd7596f39d9f6b025dacd6c8cb4f1e06990e..0572a15242b5a7c85efb5dafff64645e6693d6da 100644 (file)
@@ -164,7 +164,6 @@ static int tweak_set_configuration_cmd(struct urb *urb)
                 config, dev_name(&urb->dev->dev));
 
        return 0;
-       /* return usb_driver_set_configuration(urb->dev, config); */
 }
 
 static int tweak_reset_device_cmd(struct urb *urb)
@@ -480,7 +479,7 @@ static void stub_recv_cmd_submit(struct stub_device *sdev,
                return;
        }
 
-       /* set priv->urb->transfer_buffer */
+       /* allocate urb transfer buffer, if needed */
        if (pdu->u.cmd_submit.transfer_buffer_length > 0) {
                priv->urb->transfer_buffer =
                        kzalloc(pdu->u.cmd_submit.transfer_buffer_length,
@@ -492,7 +491,7 @@ static void stub_recv_cmd_submit(struct stub_device *sdev,
                }
        }
 
-       /* set priv->urb->setup_packet */
+       /* copy urb setup packet */
        priv->urb->setup_packet = kmemdup(&pdu->u.cmd_submit.setup, 8,
                                          GFP_KERNEL);
        if (!priv->urb->setup_packet) {
index 023fda305be292a89be270b146da9321d43eeba8..513961fef0551e517d270c8bf60f8d6537e94b4d 100644 (file)
@@ -166,7 +166,7 @@ static int stub_send_ret_submit(struct stub_device *sdev)
                int ret;
                struct urb *urb = priv->urb;
                struct usbip_header pdu_header;
-               void *iso_buffer = NULL;
+               struct usbip_iso_packet_descriptor *iso_buffer = NULL;
                struct kvec *iov = NULL;
                int iovnum = 0;
 
@@ -192,7 +192,6 @@ static int stub_send_ret_submit(struct stub_device *sdev)
                setup_ret_submit_pdu(&pdu_header, urb);
                usbip_dbg_stub_tx("setup txdata seqnum: %d urb: %p\n",
                                  pdu_header.base.seqnum, urb);
-               /*usbip_dump_header(pdu_header);*/
                usbip_header_correct_endian(&pdu_header, 1);
 
                iov[iovnum].iov_base = &pdu_header;
index 57f11f9cd8a583517cf4b16b2ddc722b6e84d967..75189feac380c5cba44e7264811a94e40c3b46ae 100644 (file)
@@ -413,8 +413,10 @@ struct socket *sockfd_to_socket(unsigned int sockfd)
 
        inode = file->f_dentry->d_inode;
 
-       if (!inode || !S_ISSOCK(inode->i_mode))
+       if (!inode || !S_ISSOCK(inode->i_mode)) {
+               fput(file);
                return NULL;
+       }
 
        socket = SOCKET_I(inode);
 
@@ -439,7 +441,6 @@ static void usbip_pack_cmd_submit(struct usbip_header *pdu, struct urb *urb,
         * will be discussed when usbip is ported to other operating systems.
         */
        if (pack) {
-               /* vhci_tx.c */
                spdu->transfer_flags =
                        tweak_transfer_flags(urb->transfer_flags);
                spdu->transfer_buffer_length    = urb->transfer_buffer_length;
@@ -447,9 +448,7 @@ static void usbip_pack_cmd_submit(struct usbip_header *pdu, struct urb *urb,
                spdu->number_of_packets         = urb->number_of_packets;
                spdu->interval                  = urb->interval;
        } else  {
-               /* stub_rx.c */
                urb->transfer_flags         = spdu->transfer_flags;
-
                urb->transfer_buffer_length = spdu->transfer_buffer_length;
                urb->start_frame            = spdu->start_frame;
                urb->number_of_packets      = spdu->number_of_packets;
@@ -463,16 +462,12 @@ static void usbip_pack_ret_submit(struct usbip_header *pdu, struct urb *urb,
        struct usbip_header_ret_submit *rpdu = &pdu->u.ret_submit;
 
        if (pack) {
-               /* stub_tx.c */
-
                rpdu->status            = urb->status;
                rpdu->actual_length     = urb->actual_length;
                rpdu->start_frame       = urb->start_frame;
                rpdu->number_of_packets = urb->number_of_packets;
                rpdu->error_count       = urb->error_count;
        } else {
-               /* vhci_rx.c */
-
                urb->status             = rpdu->status;
                urb->actual_length      = rpdu->actual_length;
                urb->start_frame        = rpdu->start_frame;
@@ -639,28 +634,26 @@ static void usbip_pack_iso(struct usbip_iso_packet_descriptor *iso,
 }
 
 /* must free buffer */
-void *usbip_alloc_iso_desc_pdu(struct urb *urb, ssize_t *bufflen)
+struct usbip_iso_packet_descriptor*
+usbip_alloc_iso_desc_pdu(struct urb *urb, ssize_t *bufflen)
 {
-       void *buff;
        struct usbip_iso_packet_descriptor *iso;
        int np = urb->number_of_packets;
        ssize_t size = np * sizeof(*iso);
        int i;
 
-       buff = kzalloc(size, GFP_KERNEL);
-       if (!buff)
+       iso = kzalloc(size, GFP_KERNEL);
+       if (!iso)
                return NULL;
 
        for (i = 0; i < np; i++) {
-               iso = buff + (i * sizeof(*iso));
-
-               usbip_pack_iso(iso, &urb->iso_frame_desc[i], 1);
-               usbip_iso_packet_correct_endian(iso, 1);
+               usbip_pack_iso(&iso[i], &urb->iso_frame_desc[i], 1);
+               usbip_iso_packet_correct_endian(&iso[i], 1);
        }
 
        *bufflen = size;
 
-       return buff;
+       return iso;
 }
 EXPORT_SYMBOL_GPL(usbip_alloc_iso_desc_pdu);
 
@@ -680,8 +673,6 @@ int usbip_recv_iso(struct usbip_device *ud, struct urb *urb)
 
        /* my Bluetooth dongle gets ISO URBs which are np = 0 */
        if (np == 0) {
-               /* pr_info("iso np == 0\n"); */
-               /* usbip_dump_urb(urb); */
                return 0;
        }
 
@@ -703,11 +694,10 @@ int usbip_recv_iso(struct usbip_device *ud, struct urb *urb)
                return -EPIPE;
        }
 
+       iso = (struct usbip_iso_packet_descriptor *) buff;
        for (i = 0; i < np; i++) {
-               iso = buff + (i * sizeof(*iso));
-
-               usbip_iso_packet_correct_endian(iso, 0);
-               usbip_pack_iso(iso, &urb->iso_frame_desc[i], 0);
+               usbip_iso_packet_correct_endian(&iso[i], 0);
+               usbip_pack_iso(&iso[i], &urb->iso_frame_desc[i], 0);
                total_length += urb->iso_frame_desc[i].actual_length;
        }
 
@@ -754,7 +744,7 @@ void usbip_pad_iso(struct usbip_device *ud, struct urb *urb)
        /*
         * if actual_length is transfer_buffer_length then no padding is
         * present.
-       */
+        */
        if (urb->actual_length == urb->transfer_buffer_length)
                return;
 
@@ -778,14 +768,12 @@ int usbip_recv_xbuff(struct usbip_device *ud, struct urb *urb)
        int size;
 
        if (ud->side == USBIP_STUB) {
-               /* stub_rx.c */
                /* the direction of urb must be OUT. */
                if (usb_pipein(urb->pipe))
                        return 0;
 
                size = urb->transfer_buffer_length;
        } else {
-               /* vhci_rx.c */
                /* the direction of urb must be IN. */
                if (usb_pipeout(urb->pipe))
                        return 0;
index 5d89c0fd6f7bb2f79a4b068bc94f10b814ca50ca..7e6c5436d972f6201a19cbc691e3a4cbfac6f528 100644 (file)
@@ -320,7 +320,9 @@ void usbip_pack_pdu(struct usbip_header *pdu, struct urb *urb, int cmd,
                    int pack);
 void usbip_header_correct_endian(struct usbip_header *pdu, int send);
 
-void *usbip_alloc_iso_desc_pdu(struct urb *urb, ssize_t *bufflen);
+struct usbip_iso_packet_descriptor*
+usbip_alloc_iso_desc_pdu(struct urb *urb, ssize_t *bufflen);
+
 /* some members of urb must be substituted before. */
 int usbip_recv_iso(struct usbip_device *ud, struct urb *urb);
 void usbip_pad_iso(struct usbip_device *ud, struct urb *urb);
index c66b8b3f97b40c43b7b07c184934fc44409a9f2a..5dddc4d4b6a566ab0bb224ad85918c7669e25db3 100644 (file)
@@ -99,7 +99,6 @@ extern const struct attribute_group dev_attr_group;
 
 /* vhci_hcd.c */
 void rh_port_connect(int rhport, enum usb_device_speed speed);
-void rh_port_disconnect(int rhport);
 
 /* vhci_rx.c */
 struct urb *pickup_urb_and_free_priv(struct vhci_device *vdev, __u32 seqnum);
index 620d1beb4587cf7ec308cc262e31b6dd009d115a..7dc8bbaee18f6d417e401bd2e7825a779884f198 100644 (file)
@@ -18,6 +18,7 @@
  */
 
 #include <linux/init.h>
+#include <linux/file.h>
 #include <linux/kernel.h>
 #include <linux/kthread.h>
 #include <linux/module.h>
@@ -140,32 +141,23 @@ void rh_port_connect(int rhport, enum usb_device_speed speed)
                break;
        }
 
-       /* spin_lock(&the_controller->vdev[rhport].ud.lock);
-        * the_controller->vdev[rhport].ud.status = VDEV_CONNECT;
-        * spin_unlock(&the_controller->vdev[rhport].ud.lock); */
-
        spin_unlock_irqrestore(&the_controller->lock, flags);
 
        usb_hcd_poll_rh_status(vhci_to_hcd(the_controller));
 }
 
-void rh_port_disconnect(int rhport)
+static void rh_port_disconnect(int rhport)
 {
        unsigned long flags;
 
        usbip_dbg_vhci_rh("rh_port_disconnect %d\n", rhport);
 
        spin_lock_irqsave(&the_controller->lock, flags);
-       /* stop_activity(dum, driver); */
+
        the_controller->port_status[rhport] &= ~USB_PORT_STAT_CONNECTION;
        the_controller->port_status[rhport] |=
                                        (1 << USB_PORT_FEAT_C_CONNECTION);
 
-       /* not yet complete the disconnection
-        * spin_lock(&vdev->ud.lock);
-        * vdev->ud.status = VHC_ST_DISCONNECT;
-        * spin_unlock(&vdev->ud.lock); */
-
        spin_unlock_irqrestore(&the_controller->lock, flags);
        usb_hcd_poll_rh_status(vhci_to_hcd(the_controller));
 }
@@ -228,7 +220,6 @@ done:
        return changed ? retval : 0;
 }
 
-/* See hub_configure in hub.c */
 static inline void hub_descriptor(struct usb_hub_descriptor *desc)
 {
        memset(desc, 0, sizeof(*desc));
@@ -292,8 +283,6 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
                        usbip_dbg_vhci_rh(" ClearPortFeature: "
                                          "USB_PORT_FEAT_POWER\n");
                        dum->port_status[rhport] = 0;
-                       /* dum->address = 0; */
-                       /* dum->hdev = 0; */
                        dum->resuming = 0;
                        break;
                case USB_PORT_FEAT_C_RESET:
@@ -333,11 +322,11 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
                        retval = -EPIPE;
                }
 
-               /* we do no care of resume. */
+               /* we do not care about resume. */
 
                /* whoever resets or resumes must GetPortStatus to
                 * complete it!!
-                *                                   */
+                */
                if (dum->resuming && time_after(jiffies, dum->re_timeout)) {
                        dum->port_status[rhport] |=
                                (1 << USB_PORT_FEAT_C_SUSPEND);
@@ -345,11 +334,6 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
                                ~(1 << USB_PORT_FEAT_SUSPEND);
                        dum->resuming = 0;
                        dum->re_timeout = 0;
-                       /* if (dum->driver && dum->driver->resume) {
-                        *      spin_unlock (&dum->lock);
-                        *      dum->driver->resume (&dum->gadget);
-                        *      spin_lock (&dum->lock);
-                        * } */
                }
 
                if ((dum->port_status[rhport] & (1 << USB_PORT_FEAT_RESET)) !=
@@ -411,9 +395,6 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
 
        default:
                pr_err("default: no such request\n");
-               /* dev_dbg (hardware,
-                *              "hub control req%04x v%04x i%04x l%d\n",
-                *              typeReq, wValue, wIndex, wLength); */
 
                /* "protocol stall" on error */
                retval = -EPIPE;
@@ -456,7 +437,6 @@ static void vhci_tx_urb(struct urb *urb)
 
        if (!vdev) {
                pr_err("could not get virtual device");
-               /* BUG(); */
                return;
        }
 
@@ -813,7 +793,7 @@ static void vhci_shutdown_connection(struct usbip_device *ud)
                kernel_sock_shutdown(ud->tcp_socket, SHUT_RDWR);
        }
 
-       /* kill threads related to this sdev, if v.c. exists */
+       /* kill threads related to this sdev */
        if (vdev->ud.tcp_rx) {
                kthread_stop_put(vdev->ud.tcp_rx);
                vdev->ud.tcp_rx = NULL;
@@ -825,8 +805,8 @@ static void vhci_shutdown_connection(struct usbip_device *ud)
        pr_info("stop threads\n");
 
        /* active connection is closed */
-       if (vdev->ud.tcp_socket != NULL) {
-               sock_release(vdev->ud.tcp_socket);
+       if (vdev->ud.tcp_socket) {
+               fput(vdev->ud.tcp_socket->file);
                vdev->ud.tcp_socket = NULL;
        }
        pr_info("release socket\n");
@@ -872,7 +852,10 @@ static void vhci_device_reset(struct usbip_device *ud)
                usb_put_dev(vdev->udev);
        vdev->udev = NULL;
 
-       ud->tcp_socket = NULL;
+       if (ud->tcp_socket) {
+               fput(ud->tcp_socket->file);
+               ud->tcp_socket = NULL;
+       }
        ud->status = VDEV_ST_NULL;
 
        spin_unlock(&ud->lock);
@@ -928,7 +911,6 @@ static int vhci_start(struct usb_hcd *hcd)
        spin_lock_init(&vhci->lock);
 
        hcd->power_budget = 0; /* no limit */
-       hcd->state  = HC_STATE_RUNNING;
        hcd->uses_new_polling = 1;
 
        /* vhci_hcd is now ready to be controlled through sysfs */
@@ -976,8 +958,6 @@ static int vhci_bus_suspend(struct usb_hcd *hcd)
        dev_dbg(&hcd->self.root_hub->dev, "%s\n", __func__);
 
        spin_lock_irq(&vhci->lock);
-       /* vhci->rh_state = DUMMY_RH_SUSPENDED;
-        * set_link_state(vhci); */
        hcd->state = HC_STATE_SUSPENDED;
        spin_unlock_irq(&vhci->lock);
 
@@ -995,10 +975,6 @@ static int vhci_bus_resume(struct usb_hcd *hcd)
        if (!HCD_HW_ACCESSIBLE(hcd)) {
                rc = -ESHUTDOWN;
        } else {
-               /* vhci->rh_state = DUMMY_RH_RUNNING;
-                * set_link_state(vhci);
-                * if (!list_empty(&vhci->urbp_list))
-                *      mod_timer(&vhci->timer, jiffies); */
                hcd->state = HC_STATE_RUNNING;
        }
        spin_unlock_irq(&vhci->lock);
@@ -1175,7 +1151,6 @@ static struct platform_device the_pdev = {
        .name = (char *) driver_name,
        .id = -1,
        .dev = {
-               /* .driver = &vhci_driver, */
                .release = the_pdev_release,
        },
 };
index f0eaf04fa25b36fafa4a79e74b08d54b42ddf4a4..ba5f1c079b69511bb206289a722076e4089ffa3f 100644 (file)
@@ -167,7 +167,7 @@ static void vhci_recv_ret_unlink(struct vhci_device *vdev,
        } else {
                usbip_dbg_vhci_rx("now giveback urb %p\n", urb);
 
-               /* If unlink is succeed, status is -ECONNRESET */
+               /* If unlink is successful, status is -ECONNRESET */
                urb->status = pdu->u.ret_unlink.status;
                pr_info("urb->status %d\n", urb->status);
 
index 7ce9c2f7e442929b28370f1f816fcb31ea583aa6..c66e9c05c76b70bab213fc9c912c7c328a1b7171 100644 (file)
@@ -18,6 +18,7 @@
  */
 
 #include <linux/kthread.h>
+#include <linux/file.h>
 #include <linux/net.h>
 
 #include "usbip_common.h"
@@ -189,7 +190,8 @@ static ssize_t store_attach(struct device *dev, struct device_attribute *attr,
        if (valid_args(rhport, speed) < 0)
                return -EINVAL;
 
-       /* check sockfd */
+       /* Extract socket from fd. */
+       /* The correct way to clean this up is to fput(socket->file). */
        socket = sockfd_to_socket(sockfd);
        if (!socket)
                return -EINVAL;
@@ -206,6 +208,8 @@ static ssize_t store_attach(struct device *dev, struct device_attribute *attr,
                spin_unlock(&vdev->ud.lock);
                spin_unlock(&the_controller->lock);
 
+               fput(socket->file);
+
                dev_err(dev, "port %d already used\n", rhport);
                return -EINVAL;
        }
index 9b437e7ef1a764032a6c63e23852a1e62440d8ae..b1f0dcd68f5592c28dd57997d7604c37ebf409c3 100644 (file)
@@ -76,7 +76,7 @@ static int vhci_send_cmd_submit(struct vhci_device *vdev)
                int ret;
                struct urb *urb = priv->urb;
                struct usbip_header pdu_header;
-               void *iso_buffer = NULL;
+               struct usbip_iso_packet_descriptor *iso_buffer = NULL;
 
                txsize = 0;
                memset(&pdu_header, 0, sizeof(pdu_header));
index 67b1b88b1b89d365a4cc8f75cba1d20f1318928a..5f13890cf1241af033949988b437b284b23c8a4c 100644 (file)
@@ -596,9 +596,9 @@ static int hostap_set_encryption(PSDevice pDevice,
 
        if (param->u.crypt.seq) {
            memcpy(&abySeq, param->u.crypt.seq, 8);
-               for (ii = 0 ; ii < 8 ; ii++) {
-                KeyRSC |= (abySeq[ii] << (ii * 8));
-               }
+               for (ii = 0 ; ii < 8 ; ii++)
+                       KeyRSC |= (unsigned long)abySeq[ii] << (ii * 8);
+
                dwKeyIndex |= 1 << 29;
                pMgmt->sNodeDBTable[iNodeIndex].KeyRSC = KeyRSC;
        }
index 4972e57845c228834d3540c6745d6eda5e436b7d..875ee4442386c834b96e88b9e70cf9c29ca936ef 100644 (file)
@@ -242,7 +242,7 @@ s_vFillTxKey (
         }
         // Append IV after Mac Header
         *pdwIV &= WEP_IV_MASK;//00000000 11111111 11111111 11111111
-        *pdwIV |= (byKeyIndex << 30);
+        *pdwIV |= (unsigned long)byKeyIndex << 30;
         *pdwIV = cpu_to_le32(*pdwIV);
         pDevice->dwIVCounter++;
         if (pDevice->dwIVCounter > WEP_IV_MASK) {
index 94bd1fc42c9313e77e0c6b1ac727e9d5d02ba18b..6d0b87a14267b66b2e1c92a1f6d0ba91024d48fd 100644 (file)
@@ -412,6 +412,7 @@ vCommandTimer (
                if (!is_channel_valid(pMgmt->uScanChannel)) {
                     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Invalid channel pMgmt->uScanChannel = %d \n",pMgmt->uScanChannel);
                     s_bCommandComplete(pDevice);
+                    spin_unlock_irq(&pDevice->lock);
                     return;
                 }
 //printk("chester-pMgmt->uScanChannel=%d,pDevice->byMaxChannel=%d\n",pMgmt->uScanChannel,pDevice->byMaxChannel);
index 6370d1039103d3d36027947e014d1643a9f3d1ea..8d9b9c1a2d50e72f8ebfd81801b051b1faf66d82 100644 (file)
@@ -418,7 +418,6 @@ typedef struct __device_info {
     struct net_device*          dev;
     struct net_device_stats     stats;
 
-    const struct firmware      *firmware;
 
     OPTIONS                     sOpts;
 
index 8c8126a3540b426a69756872968664dadad38aba..8831ea03c00152864ca4336980624ac16dcef769 100644 (file)
@@ -61,28 +61,24 @@ FIRMWAREbDownload(
      PSDevice pDevice
     )
 {
+       struct device *dev = &pDevice->usb->dev;
        const struct firmware *fw;
        int NdisStatus;
        void *pBuffer = NULL;
        BOOL result = FALSE;
        u16 wLength;
-       int ii;
+       int ii, rc;
+
 
        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->Download firmware\n");
        spin_unlock_irq(&pDevice->lock);
 
-       if (!pDevice->firmware) {
-               struct device *dev = &pDevice->usb->dev;
-               int rc;
-
-               rc = request_firmware(&pDevice->firmware, FIRMWARE_NAME, dev);
-               if (rc) {
-                       dev_err(dev, "firmware file %s request failed (%d)\n",
-                               FIRMWARE_NAME, rc);
+       rc = request_firmware(&fw, FIRMWARE_NAME, dev);
+       if (rc) {
+               dev_err(dev, "firmware file %s request failed (%d)\n",
+                       FIRMWARE_NAME, rc);
                        goto out;
-               }
        }
-       fw = pDevice->firmware;
 
        pBuffer = kmalloc(FIRMWARE_CHUNK_SIZE, GFP_KERNEL);
        if (!pBuffer)
@@ -103,10 +99,12 @@ FIRMWAREbDownload(
                DBG_PRT(MSG_LEVEL_DEBUG,
                        KERN_INFO"Download firmware...%d %zu\n", ii, fw->size);
                if (NdisStatus != STATUS_SUCCESS)
-                       goto out;
+                       goto free_fw;
         }
 
        result = TRUE;
+free_fw:
+       release_firmware(fw);
 
 out:
        kfree(pBuffer);
index 0a73d4060ee19348122a1e036d2c604374f75d41..26a7d0e4b0487aa118d85e9e665238ccb6ade802 100644 (file)
@@ -542,9 +542,9 @@ static int hostap_set_encryption(PSDevice pDevice,
 
        if (param->u.crypt.seq) {
            memcpy(&abySeq, param->u.crypt.seq, 8);
-               for (ii = 0 ; ii < 8 ; ii++) {
-                KeyRSC |= (abySeq[ii] << (ii * 8));
-               }
+               for (ii = 0 ; ii < 8 ; ii++)
+                       KeyRSC |= (unsigned long)abySeq[ii] << (ii * 8);
+
                dwKeyIndex |= 1 << 29;
                pMgmt->sNodeDBTable[iNodeIndex].KeyRSC = KeyRSC;
        }
index ad422dea702badae6888a5d19235e1c7e39bea92..d402df9161e100e259b463cf27994bfa214568d0 100644 (file)
@@ -1219,7 +1219,6 @@ static void __devexit vt6656_disconnect(struct usb_interface *intf)
        }
 
        device_release_WPADEV(device);
-       release_firmware(device->firmware);
 
        usb_set_intfdata(intf, NULL);
        usb_put_dev(interface_to_usbdev(intf));
index 593cdc713b0e21413e6044f1fd70a2801c099ada..74c0598e37b7c4b03742b06375a56adc10f34994 100644 (file)
@@ -769,6 +769,9 @@ BYTE    byPwr = pDevice->byCCKPwr;
         return TRUE;
     }
 
+       if (uCH == 0)
+               return -EINVAL;
+
     switch (uRATE) {
     case RATE_1M:
     case RATE_2M:
index 3390838798833943f7c34c2989d01f52909de3a8..a54c0c1de2e8351f5d5862a8149f6ac54a6a9dce 100644 (file)
@@ -355,7 +355,7 @@ s_vFillTxKey (
         }
         // Append IV after Mac Header
         *pdwIV &= WEP_IV_MASK;//00000000 11111111 11111111 11111111
-        *pdwIV |= (pDevice->byKeyIndex << 30);
+        *pdwIV |= (unsigned long)pDevice->byKeyIndex << 30;
         *pdwIV = cpu_to_le32(*pdwIV);
         pDevice->dwIVCounter++;
         if (pDevice->dwIVCounter > WEP_IV_MASK) {
index 609e8fa10b982dd5527f6b041c285cd08992867c..b5259db6e36a17584447bf578d5a1e85ba208191 100644 (file)
@@ -660,6 +660,7 @@ PIPEnsSendBulkOut(
        if (status != 0)
        {
                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Submit Tx URB failed %d\n", status);
+               pContext->bBoolInUse = FALSE;
                return STATUS_FAILURE;
        }
         return STATUS_PENDING;
index 1b8b8ace39e0b5a733e80cb03814e2f40b718a77..43990e87d6416bdbfff4010df38ae496281481ff 100644 (file)
@@ -315,7 +315,7 @@ static void Mds_HeaderCopy(struct wbsoft_priv *adapter, struct wb35_descriptor *
 
        pT00->T00_tx_packet_id = pDes->Descriptor_ID; /* Set packet ID */
        pT00->T00_header_length = 24; /* Set header length */
-       pT01->T01_retry_abort_ebable = 1; /* 921013 931130.5.h */
+       pT01->T01_retry_abort_enable = 1; /* 921013 931130.5.h */
 
        /* Key ID setup */
        pT01->T01_wep_id = 0;
index 39e84a0d9729863457a9b439f987608b243a9955..289ee549146df7c7ae19e30399ac5fb8e442403e 100644 (file)
@@ -226,11 +226,11 @@ struct T01_descriptor {
                        u32     T01_add_challenge_text:1;
                        u32     T01_inhibit_crc:1;
                        u32     T01_loop_back_wep_mode:1;
-                       u32     T01_retry_abort_ebable:1;
+                       u32     T01_retry_abort_enable:1;
                };
 #else
                struct {
-                       u32     T01_retry_abort_ebable:1;
+                       u32     T01_retry_abort_enable:1;
                        u32     T01_loop_back_wep_mode:1;
                        u32     T01_inhibit_crc:1;
                        u32     T01_add_challenge_text:1;
index a345885307405ce6f5f9db82a6d8eef4c5eb7693..37df9987918388da038ab84f3f13c280c8a07817 100644 (file)
@@ -108,7 +108,7 @@ with the I/O base address and MAC address used by the card.
  \- Card power management
  \- Support for Hermes-II & Hermes-II.5 based PCMCIA, Mini PCI, and CardBus cards
  \- Wired Equivalent Privacy (WEP)
- \- WPA-PSK support (EXPERIMENTAL)
+ \- WPA-PSK support
  \- Driver utility interface (UIL)
  \- Wireless Extensions
  \- Software AP mode
index 13d9bc25797dd23f14fd8ef7356dc747700331bd..392b29d8f134bf212340181b9fc93727ddbfd33f 100644 (file)
@@ -1,4 +1,4 @@
-This drivers still need a lot of work. I can list all cleanups to do but it's
+This drivers still needs a lot of work. I can list all cleanups to do but it's
 going to be long. So, I'm writing "cleanups" and not the list.
 
 Arnaud
index e95a1655a6ce6e3a23e0f73078b31e61d88bd9bb..c8561a0b386d50eca565b66d5f236b19f23c2d38 100644 (file)
@@ -2501,7 +2501,7 @@ static void XGI_GetVBInfo(unsigned short ModeNo, unsigned short ModeIdIndex,
                } else {
                        temp = 0x017C;
                }
-       } else { /* 3nd party chip */
+       } else { /* 3rd party chip */
                temp = SetCRT2ToLCD;
        }
 
@@ -4390,7 +4390,7 @@ static void XGI_SetLCDRegs(unsigned short ModeNo, unsigned short ModeIdIndex,
        xgifb_reg_and_or(pVBInfo->Part2Port, 0x17, 0xFB, 0x00);
        xgifb_reg_and_or(pVBInfo->Part2Port, 0x18, 0xDF, 0x00);
 
-       /* Customized LCDB Des no add */
+       /* Customized LCDB Does not add */
        tempbx = 5;
        LCDBDesPtr = XGI_GetLcdPtr(tempbx, ModeNo, ModeIdIndex,
                                   RefreshRateTableIndex, pVBInfo);
index 653b074035f7b165d04d1587d428097ecfac780a..6edefde23722b436641166f5b678291d6648c6b2 100644 (file)
@@ -223,8 +223,13 @@ static int zram_bvec_read(struct zram *zram, struct bio_vec *bvec,
        cmem = zs_map_object(zram->mem_pool, zram->table[index].handle,
                                ZS_MM_RO);
 
-       ret = lzo1x_decompress_safe(cmem, zram->table[index].size,
+       if (zram->table[index].size == PAGE_SIZE) {
+               memcpy(uncmem, cmem, PAGE_SIZE);
+               ret = LZO_E_OK;
+       } else {
+               ret = lzo1x_decompress_safe(cmem, zram->table[index].size,
                                    uncmem, &clen);
+       }
 
        if (is_partial_io(bvec)) {
                memcpy(user_mem + bvec->bv_offset, uncmem + offset,
@@ -342,8 +347,11 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index,
                goto out;
        }
 
-       if (unlikely(clen > max_zpage_size))
+       if (unlikely(clen > max_zpage_size)) {
                zram_stat_inc(&zram->stats.bad_compress);
+               src = uncmem;
+               clen = PAGE_SIZE;
+       }
 
        handle = zs_malloc(zram->mem_pool, clen);
        if (!handle) {
index 572c0b1551d4bb2dd6c0cb9940988a57ed40ebce..df2eec407db64b6b29f562ba94946e56fb24317e 100644 (file)
@@ -39,8 +39,8 @@ static const size_t max_zpage_size = PAGE_SIZE / 4 * 3;
 
 /*
  * NOTE: max_zpage_size must be less than or equal to:
- *   ZS_MAX_ALLOC_SIZE - sizeof(struct zobj_header)
- * otherwise, xv_malloc() would always return failure.
+ *   ZS_MAX_ALLOC_SIZE. Otherwise, zs_malloc() would
+ * always return failure.
  */
 
 /*-- End of configurable params */
index 90b740048f26ee7151eda956b092e12fad74e70c..1bf7432bfcbc659f8b27dc15400016b31173add3 100644 (file)
@@ -1432,6 +1432,7 @@ static struct iscsi_param *iscsi_check_key(
                        break;
                case PHASE_OPERATIONAL:
                        pr_debug("Operational phase.\n");
+                       break;
                default:
                        pr_debug("Unknown phase.\n");
                }
index e1cb6bd75f60335517dc26d50d7b5726205da41a..266c15eb89ea747a80b03805cb69cd672aaa30e7 100644 (file)
@@ -55,3 +55,52 @@ config EXYNOS_THERMAL
        help
          If you say yes here you get support for TMU (Thermal Managment
          Unit) on SAMSUNG EXYNOS series of SoC.
+
+config FAIR_SHARE
+       bool "Fair-share thermal governor"
+       depends on THERMAL
+       help
+         Enable this to manage platform thermals using fair-share governor.
+
+config STEP_WISE
+       bool "Step_wise thermal governor"
+       depends on THERMAL
+       help
+         Enable this to manage platform thermals using a simple linear
+
+config USER_SPACE
+       bool "User_space thermal governor"
+       depends on THERMAL
+       help
+         Enable this to let the user space manage the platform thermals.
+
+choice
+       prompt "Default Thermal governor"
+       depends on THERMAL
+       default THERMAL_DEFAULT_GOV_STEP_WISE
+       help
+         This option sets which thermal governor shall be loaded at
+         startup. If in doubt, select 'step_wise'.
+
+config THERMAL_DEFAULT_GOV_STEP_WISE
+       bool "step_wise"
+       select STEP_WISE
+       help
+         Use the step_wise governor as default. This throttles the
+         devices one step at a time.
+
+config THERMAL_DEFAULT_GOV_FAIR_SHARE
+       bool "fair_share"
+       select FAIR_SHARE
+       help
+         Use the fair_share governor as default. This throttles the
+         devices based on their 'contribution' to a zone. The
+         contribution should be provided through platform data.
+
+config THERMAL_DEFAULT_GOV_USER_SPACE
+       bool "user_space"
+       select USER_SPACE
+       help
+         Select this if you want to let the user space manage the
+         platform thermals.
+endchoice
index 885550dc64b7f741a984836941b0be5d4c23d2c8..e5f79747fa943bd480cb9ec2bf3b30fc0c8c2004 100644 (file)
@@ -7,3 +7,6 @@ obj-$(CONFIG_CPU_THERMAL)               += cpu_cooling.o
 obj-$(CONFIG_SPEAR_THERMAL)            += spear_thermal.o
 obj-$(CONFIG_RCAR_THERMAL)     += rcar_thermal.o
 obj-$(CONFIG_EXYNOS_THERMAL)           += exynos_thermal.o
+obj-$(CONFIG_FAIR_SHARE)               += fair_share.o
+obj-$(CONFIG_STEP_WISE)                        += step_wise.o
+obj-$(CONFIG_USER_SPACE)               += user_space.o
index fd03e8581afc2a8e86ed354c03c06e84a1b604cc..7772d160376930ef417da581fc92482d93c01aec 100644 (file)
@@ -451,7 +451,7 @@ static int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf)
        th_zone->cool_dev_size++;
 
        th_zone->therm_dev = thermal_zone_device_register(sensor_conf->name,
-                       EXYNOS_ZONE_COUNT, 0, NULL, &exynos_dev_ops, 0,
+                       EXYNOS_ZONE_COUNT, 0, NULL, &exynos_dev_ops, NULL, 0,
                        IDLE_INTERVAL);
 
        if (IS_ERR(th_zone->therm_dev)) {
@@ -815,7 +815,7 @@ static struct platform_device_id exynos_tmu_driver_ids[] = {
        },
        { },
 };
-MODULE_DEVICE_TABLE(platform, exynos4_tmu_driver_ids);
+MODULE_DEVICE_TABLE(platform, exynos_tmu_driver_ids);
 
 static inline struct  exynos_tmu_platform_data *exynos_get_driver_data(
                        struct platform_device *pdev)
diff --git a/drivers/thermal/fair_share.c b/drivers/thermal/fair_share.c
new file mode 100644 (file)
index 0000000..792479f
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ *  fair_share.c - A simple weight based Thermal governor
+ *
+ *  Copyright (C) 2012 Intel Corp
+ *  Copyright (C) 2012 Durgadoss R <durgadoss.r@intel.com>
+ *
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/thermal.h>
+
+#include "thermal_core.h"
+
+/**
+ * get_trip_level: - obtains the current trip level for a zone
+ * @tz:                thermal zone device
+ */
+static int get_trip_level(struct thermal_zone_device *tz)
+{
+       int count = 0;
+       unsigned long trip_temp;
+
+       if (tz->trips == 0 || !tz->ops->get_trip_temp)
+               return 0;
+
+       for (count = 0; count < tz->trips; count++) {
+               tz->ops->get_trip_temp(tz, count, &trip_temp);
+               if (tz->temperature < trip_temp)
+                       break;
+       }
+       return count;
+}
+
+static long get_target_state(struct thermal_zone_device *tz,
+               struct thermal_cooling_device *cdev, int weight, int level)
+{
+       unsigned long max_state;
+
+       cdev->ops->get_max_state(cdev, &max_state);
+
+       return (long)(weight * level * max_state) / (100 * tz->trips);
+}
+
+/**
+ * fair_share_throttle - throttles devices asscciated with the given zone
+ * @tz - thermal_zone_device
+ *
+ * Throttling Logic: This uses three parameters to calculate the new
+ * throttle state of the cooling devices associated with the given zone.
+ *
+ * Parameters used for Throttling:
+ * P1. max_state: Maximum throttle state exposed by the cooling device.
+ * P2. weight[i]/100:
+ *     How 'effective' the 'i'th device is, in cooling the given zone.
+ * P3. cur_trip_level/max_no_of_trips:
+ *     This describes the extent to which the devices should be throttled.
+ *     We do not want to throttle too much when we trip a lower temperature,
+ *     whereas the throttling is at full swing if we trip critical levels.
+ *     (Heavily assumes the trip points are in ascending order)
+ * new_state of cooling device = P3 * P2 * P1
+ */
+static int fair_share_throttle(struct thermal_zone_device *tz, int trip)
+{
+       const struct thermal_zone_params *tzp;
+       struct thermal_cooling_device *cdev;
+       struct thermal_instance *instance;
+       int i;
+       int cur_trip_level = get_trip_level(tz);
+
+       if (!tz->tzp || !tz->tzp->tbp)
+               return -EINVAL;
+
+       tzp = tz->tzp;
+
+       for (i = 0; i < tzp->num_tbps; i++) {
+               if (!tzp->tbp[i].cdev)
+                       continue;
+
+               cdev = tzp->tbp[i].cdev;
+               instance = get_thermal_instance(tz, cdev, trip);
+               if (!instance)
+                       continue;
+
+               instance->target = get_target_state(tz, cdev,
+                                       tzp->tbp[i].weight, cur_trip_level);
+
+               instance->cdev->updated = false;
+               thermal_cdev_update(cdev);
+       }
+       return 0;
+}
+
+static struct thermal_governor thermal_gov_fair_share = {
+       .name           = "fair_share",
+       .throttle       = fair_share_throttle,
+       .owner          = THIS_MODULE,
+};
+
+static int __init thermal_gov_fair_share_init(void)
+{
+       return thermal_register_governor(&thermal_gov_fair_share);
+}
+
+static void __exit thermal_gov_fair_share_exit(void)
+{
+       thermal_unregister_governor(&thermal_gov_fair_share);
+}
+
+/* This should load after thermal framework */
+fs_initcall(thermal_gov_fair_share_init);
+module_exit(thermal_gov_fair_share_exit);
+
+MODULE_AUTHOR("Durgadoss R");
+MODULE_DESCRIPTION("A simple weight based thermal throttling governor");
+MODULE_LICENSE("GPL");
index d4452716aaab1a7dbec7e3df53ec0abbed43aabd..b13fe5d910b015d3646102fabfb44891063fa891 100644 (file)
@@ -211,7 +211,7 @@ static int rcar_thermal_probe(struct platform_device *pdev)
        }
 
        zone = thermal_zone_device_register("rcar_thermal", 0, priv,
-                                           &rcar_thermal_zone_ops, 0, 0);
+                                   &rcar_thermal_zone_ops, NULL, 0, 0);
        if (IS_ERR(zone)) {
                dev_err(&pdev->dev, "thermal zone device is NULL\n");
                ret = PTR_ERR(zone);
index 9bc969261d011225f603971ed3a0b9a44b64b2a2..6b2d8b21aaee03b5a723249cea6773f96c5adf19 100644 (file)
@@ -147,7 +147,7 @@ static int spear_thermal_probe(struct platform_device *pdev)
        writel_relaxed(stdev->flags, stdev->thermal_base);
 
        spear_thermal = thermal_zone_device_register("spear_thermal", 0, 0,
-                               stdev, &ops, 0, 0);
+                               stdev, &ops, NULL, 0, 0);
        if (IS_ERR(spear_thermal)) {
                dev_err(&pdev->dev, "thermal zone device is NULL\n");
                ret = PTR_ERR(spear_thermal);
diff --git a/drivers/thermal/step_wise.c b/drivers/thermal/step_wise.c
new file mode 100644 (file)
index 0000000..1242cff
--- /dev/null
@@ -0,0 +1,194 @@
+/*
+ *  step_wise.c - A step-by-step Thermal throttling governor
+ *
+ *  Copyright (C) 2012 Intel Corp
+ *  Copyright (C) 2012 Durgadoss R <durgadoss.r@intel.com>
+ *
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/thermal.h>
+
+#include "thermal_core.h"
+
+/*
+ * If the temperature is higher than a trip point,
+ *    a. if the trend is THERMAL_TREND_RAISING, use higher cooling
+ *       state for this trip point
+ *    b. if the trend is THERMAL_TREND_DROPPING, use lower cooling
+ *       state for this trip point
+ */
+static unsigned long get_target_state(struct thermal_instance *instance,
+                                       enum thermal_trend trend)
+{
+       struct thermal_cooling_device *cdev = instance->cdev;
+       unsigned long cur_state;
+
+       cdev->ops->get_cur_state(cdev, &cur_state);
+
+       if (trend == THERMAL_TREND_RAISING) {
+               cur_state = cur_state < instance->upper ?
+                           (cur_state + 1) : instance->upper;
+       } else if (trend == THERMAL_TREND_DROPPING) {
+               cur_state = cur_state > instance->lower ?
+                           (cur_state - 1) : instance->lower;
+       }
+
+       return cur_state;
+}
+
+static void update_passive_instance(struct thermal_zone_device *tz,
+                               enum thermal_trip_type type, int value)
+{
+       /*
+        * If value is +1, activate a passive instance.
+        * If value is -1, deactivate a passive instance.
+        */
+       if (type == THERMAL_TRIP_PASSIVE || type == THERMAL_TRIPS_NONE)
+               tz->passive += value;
+}
+
+static void update_instance_for_throttle(struct thermal_zone_device *tz,
+                               int trip, enum thermal_trip_type trip_type,
+                               enum thermal_trend trend)
+{
+       struct thermal_instance *instance;
+
+       list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
+               if (instance->trip != trip)
+                       continue;
+
+               instance->target = get_target_state(instance, trend);
+
+               /* Activate a passive thermal instance */
+               if (instance->target == THERMAL_NO_TARGET)
+                       update_passive_instance(tz, trip_type, 1);
+
+               instance->cdev->updated = false; /* cdev needs update */
+       }
+}
+
+static void update_instance_for_dethrottle(struct thermal_zone_device *tz,
+                               int trip, enum thermal_trip_type trip_type)
+{
+       struct thermal_instance *instance;
+       struct thermal_cooling_device *cdev;
+       unsigned long cur_state;
+
+       list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
+               if (instance->trip != trip ||
+                       instance->target == THERMAL_NO_TARGET)
+                       continue;
+
+               cdev = instance->cdev;
+               cdev->ops->get_cur_state(cdev, &cur_state);
+
+               instance->target = cur_state > instance->lower ?
+                           (cur_state - 1) : THERMAL_NO_TARGET;
+
+               /* Deactivate a passive thermal instance */
+               if (instance->target == THERMAL_NO_TARGET)
+                       update_passive_instance(tz, trip_type, -1);
+
+               cdev->updated = false; /* cdev needs update */
+       }
+}
+
+static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip)
+{
+       long trip_temp;
+       enum thermal_trip_type trip_type;
+       enum thermal_trend trend;
+
+       if (trip == THERMAL_TRIPS_NONE) {
+               trip_temp = tz->forced_passive;
+               trip_type = THERMAL_TRIPS_NONE;
+       } else {
+               tz->ops->get_trip_temp(tz, trip, &trip_temp);
+               tz->ops->get_trip_type(tz, trip, &trip_type);
+       }
+
+       trend = get_tz_trend(tz, trip);
+
+       mutex_lock(&tz->lock);
+
+       if (tz->temperature >= trip_temp)
+               update_instance_for_throttle(tz, trip, trip_type, trend);
+       else
+               update_instance_for_dethrottle(tz, trip, trip_type);
+
+       mutex_unlock(&tz->lock);
+}
+
+/**
+ * step_wise_throttle - throttles devices asscciated with the given zone
+ * @tz - thermal_zone_device
+ * @trip - the trip point
+ * @trip_type - type of the trip point
+ *
+ * Throttling Logic: This uses the trend of the thermal zone to throttle.
+ * If the thermal zone is 'heating up' this throttles all the cooling
+ * devices associated with the zone and its particular trip point, by one
+ * step. If the zone is 'cooling down' it brings back the performance of
+ * the devices by one step.
+ */
+static int step_wise_throttle(struct thermal_zone_device *tz, int trip)
+{
+       struct thermal_instance *instance;
+
+       thermal_zone_trip_update(tz, trip);
+
+       if (tz->forced_passive)
+               thermal_zone_trip_update(tz, THERMAL_TRIPS_NONE);
+
+       mutex_lock(&tz->lock);
+
+       list_for_each_entry(instance, &tz->thermal_instances, tz_node)
+               thermal_cdev_update(instance->cdev);
+
+       mutex_unlock(&tz->lock);
+
+       return 0;
+}
+
+static struct thermal_governor thermal_gov_step_wise = {
+       .name           = DEFAULT_THERMAL_GOVERNOR,
+       .throttle       = step_wise_throttle,
+       .owner          = THIS_MODULE,
+};
+
+static int __init thermal_gov_step_wise_init(void)
+{
+       return thermal_register_governor(&thermal_gov_step_wise);
+}
+
+static void __exit thermal_gov_step_wise_exit(void)
+{
+       thermal_unregister_governor(&thermal_gov_step_wise);
+}
+
+/* This should load after thermal framework */
+fs_initcall(thermal_gov_step_wise_init);
+module_exit(thermal_gov_step_wise_exit);
+
+MODULE_AUTHOR("Durgadoss R");
+MODULE_DESCRIPTION("A step-by-step thermal throttling governor");
+MODULE_LICENSE("GPL");
diff --git a/drivers/thermal/thermal_core.h b/drivers/thermal/thermal_core.h
new file mode 100644 (file)
index 0000000..0d3205a
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ *  thermal_core.h
+ *
+ *  Copyright (C) 2012  Intel Corp
+ *  Author: Durgadoss R <durgadoss.r@intel.com>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+#ifndef __THERMAL_CORE_H__
+#define __THERMAL_CORE_H__
+
+#include <linux/device.h>
+#include <linux/thermal.h>
+
+/* Initial state of a cooling device during binding */
+#define THERMAL_NO_TARGET -1UL
+
+/*
+ * This structure is used to describe the behavior of
+ * a certain cooling device on a certain trip point
+ * in a certain thermal zone
+ */
+struct thermal_instance {
+       int id;
+       char name[THERMAL_NAME_LENGTH];
+       struct thermal_zone_device *tz;
+       struct thermal_cooling_device *cdev;
+       int trip;
+       unsigned long upper;    /* Highest cooling state for this trip point */
+       unsigned long lower;    /* Lowest cooling state for this trip point */
+       unsigned long target;   /* expected cooling state */
+       char attr_name[THERMAL_NAME_LENGTH];
+       struct device_attribute attr;
+       struct list_head tz_node; /* node in tz->thermal_instances */
+       struct list_head cdev_node; /* node in cdev->thermal_instances */
+};
+
+#endif /* __THERMAL_CORE_H__ */
index 9ee42ca4d289754cb99b374a32eb8bdc59371e46..8f0f37bb2825992bb14ba400975a1d15f5583fa9 100644 (file)
 #include <net/netlink.h>
 #include <net/genetlink.h>
 
+#include "thermal_core.h"
+
 MODULE_AUTHOR("Zhang Rui");
 MODULE_DESCRIPTION("Generic thermal management sysfs support");
 MODULE_LICENSE("GPL");
 
-#define THERMAL_NO_TARGET -1UL
-/*
- * This structure is used to describe the behavior of
- * a certain cooling device on a certain trip point
- * in a certain thermal zone
- */
-struct thermal_instance {
-       int id;
-       char name[THERMAL_NAME_LENGTH];
-       struct thermal_zone_device *tz;
-       struct thermal_cooling_device *cdev;
-       int trip;
-       unsigned long upper;    /* Highest cooling state for this trip point */
-       unsigned long lower;    /* Lowest cooling state for this trip point */
-       unsigned long target;   /* expected cooling state */
-       char attr_name[THERMAL_NAME_LENGTH];
-       struct device_attribute attr;
-       struct list_head tz_node; /* node in tz->thermal_instances */
-       struct list_head cdev_node; /* node in cdev->thermal_instances */
-};
-
 static DEFINE_IDR(thermal_tz_idr);
 static DEFINE_IDR(thermal_cdev_idr);
 static DEFINE_MUTEX(thermal_idr_lock);
 
 static LIST_HEAD(thermal_tz_list);
 static LIST_HEAD(thermal_cdev_list);
+static LIST_HEAD(thermal_governor_list);
+
 static DEFINE_MUTEX(thermal_list_lock);
+static DEFINE_MUTEX(thermal_governor_lock);
+
+static struct thermal_governor *__find_governor(const char *name)
+{
+       struct thermal_governor *pos;
+
+       list_for_each_entry(pos, &thermal_governor_list, governor_list)
+               if (!strnicmp(name, pos->name, THERMAL_NAME_LENGTH))
+                       return pos;
+
+       return NULL;
+}
+
+int thermal_register_governor(struct thermal_governor *governor)
+{
+       int err;
+       const char *name;
+       struct thermal_zone_device *pos;
+
+       if (!governor)
+               return -EINVAL;
+
+       mutex_lock(&thermal_governor_lock);
+
+       err = -EBUSY;
+       if (__find_governor(governor->name) == NULL) {
+               err = 0;
+               list_add(&governor->governor_list, &thermal_governor_list);
+       }
+
+       mutex_lock(&thermal_list_lock);
+
+       list_for_each_entry(pos, &thermal_tz_list, node) {
+               if (pos->governor)
+                       continue;
+               if (pos->tzp)
+                       name = pos->tzp->governor_name;
+               else
+                       name = DEFAULT_THERMAL_GOVERNOR;
+               if (!strnicmp(name, governor->name, THERMAL_NAME_LENGTH))
+                       pos->governor = governor;
+       }
+
+       mutex_unlock(&thermal_list_lock);
+       mutex_unlock(&thermal_governor_lock);
+
+       return err;
+}
+EXPORT_SYMBOL_GPL(thermal_register_governor);
+
+void thermal_unregister_governor(struct thermal_governor *governor)
+{
+       struct thermal_zone_device *pos;
+
+       if (!governor)
+               return;
+
+       mutex_lock(&thermal_governor_lock);
+
+       if (__find_governor(governor->name) == NULL)
+               goto exit;
+
+       mutex_lock(&thermal_list_lock);
+
+       list_for_each_entry(pos, &thermal_tz_list, node) {
+               if (!strnicmp(pos->governor->name, governor->name,
+                                               THERMAL_NAME_LENGTH))
+                       pos->governor = NULL;
+       }
+
+       mutex_unlock(&thermal_list_lock);
+       list_del(&governor->governor_list);
+exit:
+       mutex_unlock(&thermal_governor_lock);
+       return;
+}
+EXPORT_SYMBOL_GPL(thermal_unregister_governor);
 
 static int get_idr(struct idr *idr, struct mutex *lock, int *id)
 {
@@ -101,6 +161,261 @@ static void release_idr(struct idr *idr, struct mutex *lock, int id)
                mutex_unlock(lock);
 }
 
+int get_tz_trend(struct thermal_zone_device *tz, int trip)
+{
+       enum thermal_trend trend;
+
+       if (!tz->ops->get_trend || tz->ops->get_trend(tz, trip, &trend)) {
+               if (tz->temperature > tz->last_temperature)
+                       trend = THERMAL_TREND_RAISING;
+               else if (tz->temperature < tz->last_temperature)
+                       trend = THERMAL_TREND_DROPPING;
+               else
+                       trend = THERMAL_TREND_STABLE;
+       }
+
+       return trend;
+}
+EXPORT_SYMBOL(get_tz_trend);
+
+struct thermal_instance *get_thermal_instance(struct thermal_zone_device *tz,
+                       struct thermal_cooling_device *cdev, int trip)
+{
+       struct thermal_instance *pos = NULL;
+       struct thermal_instance *target_instance = NULL;
+
+       mutex_lock(&tz->lock);
+       mutex_lock(&cdev->lock);
+
+       list_for_each_entry(pos, &tz->thermal_instances, tz_node) {
+               if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) {
+                       target_instance = pos;
+                       break;
+               }
+       }
+
+       mutex_unlock(&cdev->lock);
+       mutex_unlock(&tz->lock);
+
+       return target_instance;
+}
+EXPORT_SYMBOL(get_thermal_instance);
+
+static void print_bind_err_msg(struct thermal_zone_device *tz,
+                       struct thermal_cooling_device *cdev, int ret)
+{
+       dev_err(&tz->device, "binding zone %s with cdev %s failed:%d\n",
+                               tz->type, cdev->type, ret);
+}
+
+static void __bind(struct thermal_zone_device *tz, int mask,
+                       struct thermal_cooling_device *cdev)
+{
+       int i, ret;
+
+       for (i = 0; i < tz->trips; i++) {
+               if (mask & (1 << i)) {
+                       ret = thermal_zone_bind_cooling_device(tz, i, cdev,
+                                       THERMAL_NO_LIMIT, THERMAL_NO_LIMIT);
+                       if (ret)
+                               print_bind_err_msg(tz, cdev, ret);
+               }
+       }
+}
+
+static void __unbind(struct thermal_zone_device *tz, int mask,
+                       struct thermal_cooling_device *cdev)
+{
+       int i;
+
+       for (i = 0; i < tz->trips; i++)
+               if (mask & (1 << i))
+                       thermal_zone_unbind_cooling_device(tz, i, cdev);
+}
+
+static void bind_cdev(struct thermal_cooling_device *cdev)
+{
+       int i, ret;
+       const struct thermal_zone_params *tzp;
+       struct thermal_zone_device *pos = NULL;
+
+       mutex_lock(&thermal_list_lock);
+
+       list_for_each_entry(pos, &thermal_tz_list, node) {
+               if (!pos->tzp && !pos->ops->bind)
+                       continue;
+
+               if (!pos->tzp && pos->ops->bind) {
+                       ret = pos->ops->bind(pos, cdev);
+                       if (ret)
+                               print_bind_err_msg(pos, cdev, ret);
+               }
+
+               tzp = pos->tzp;
+               if (!tzp || !tzp->tbp)
+                       continue;
+
+               for (i = 0; i < tzp->num_tbps; i++) {
+                       if (tzp->tbp[i].cdev || !tzp->tbp[i].match)
+                               continue;
+                       if (tzp->tbp[i].match(pos, cdev))
+                               continue;
+                       tzp->tbp[i].cdev = cdev;
+                       __bind(pos, tzp->tbp[i].trip_mask, cdev);
+               }
+       }
+
+       mutex_unlock(&thermal_list_lock);
+}
+
+static void bind_tz(struct thermal_zone_device *tz)
+{
+       int i, ret;
+       struct thermal_cooling_device *pos = NULL;
+       const struct thermal_zone_params *tzp = tz->tzp;
+
+       if (!tzp && !tz->ops->bind)
+               return;
+
+       mutex_lock(&thermal_list_lock);
+
+       /* If there is no platform data, try to use ops->bind */
+       if (!tzp && tz->ops->bind) {
+               list_for_each_entry(pos, &thermal_cdev_list, node) {
+                       ret = tz->ops->bind(tz, pos);
+                       if (ret)
+                               print_bind_err_msg(tz, pos, ret);
+               }
+               goto exit;
+       }
+
+       if (!tzp || !tzp->tbp)
+               goto exit;
+
+       list_for_each_entry(pos, &thermal_cdev_list, node) {
+               for (i = 0; i < tzp->num_tbps; i++) {
+                       if (tzp->tbp[i].cdev || !tzp->tbp[i].match)
+                               continue;
+                       if (tzp->tbp[i].match(tz, pos))
+                               continue;
+                       tzp->tbp[i].cdev = pos;
+                       __bind(tz, tzp->tbp[i].trip_mask, pos);
+               }
+       }
+exit:
+       mutex_unlock(&thermal_list_lock);
+}
+
+static void thermal_zone_device_set_polling(struct thermal_zone_device *tz,
+                                           int delay)
+{
+       if (delay > 1000)
+               mod_delayed_work(system_freezable_wq, &tz->poll_queue,
+                                round_jiffies(msecs_to_jiffies(delay)));
+       else if (delay)
+               mod_delayed_work(system_freezable_wq, &tz->poll_queue,
+                                msecs_to_jiffies(delay));
+       else
+               cancel_delayed_work(&tz->poll_queue);
+}
+
+static void monitor_thermal_zone(struct thermal_zone_device *tz)
+{
+       mutex_lock(&tz->lock);
+
+       if (tz->passive)
+               thermal_zone_device_set_polling(tz, tz->passive_delay);
+       else if (tz->polling_delay)
+               thermal_zone_device_set_polling(tz, tz->polling_delay);
+       else
+               thermal_zone_device_set_polling(tz, 0);
+
+       mutex_unlock(&tz->lock);
+}
+
+static void handle_non_critical_trips(struct thermal_zone_device *tz,
+                       int trip, enum thermal_trip_type trip_type)
+{
+       tz->governor->throttle(tz, trip);
+}
+
+static void handle_critical_trips(struct thermal_zone_device *tz,
+                               int trip, enum thermal_trip_type trip_type)
+{
+       long trip_temp;
+
+       tz->ops->get_trip_temp(tz, trip, &trip_temp);
+
+       /* If we have not crossed the trip_temp, we do not care. */
+       if (tz->temperature < trip_temp)
+               return;
+
+       if (tz->ops->notify)
+               tz->ops->notify(tz, trip, trip_type);
+
+       if (trip_type == THERMAL_TRIP_CRITICAL) {
+               pr_emerg("Critical temperature reached(%d C),shutting down\n",
+                        tz->temperature / 1000);
+               orderly_poweroff(true);
+       }
+}
+
+static void handle_thermal_trip(struct thermal_zone_device *tz, int trip)
+{
+       enum thermal_trip_type type;
+
+       tz->ops->get_trip_type(tz, trip, &type);
+
+       if (type == THERMAL_TRIP_CRITICAL || type == THERMAL_TRIP_HOT)
+               handle_critical_trips(tz, trip, type);
+       else
+               handle_non_critical_trips(tz, trip, type);
+       /*
+        * Alright, we handled this trip successfully.
+        * So, start monitoring again.
+        */
+       monitor_thermal_zone(tz);
+}
+
+static void update_temperature(struct thermal_zone_device *tz)
+{
+       long temp;
+       int ret;
+
+       mutex_lock(&tz->lock);
+
+       ret = tz->ops->get_temp(tz, &temp);
+       if (ret) {
+               pr_warn("failed to read out thermal zone %d\n", tz->id);
+               goto exit;
+       }
+
+       tz->last_temperature = tz->temperature;
+       tz->temperature = temp;
+
+exit:
+       mutex_unlock(&tz->lock);
+}
+
+void thermal_zone_device_update(struct thermal_zone_device *tz)
+{
+       int count;
+
+       update_temperature(tz);
+
+       for (count = 0; count < tz->trips; count++)
+               handle_thermal_trip(tz, count);
+}
+EXPORT_SYMBOL(thermal_zone_device_update);
+
+static void thermal_zone_device_check(struct work_struct *work)
+{
+       struct thermal_zone_device *tz = container_of(work, struct
+                                                     thermal_zone_device,
+                                                     poll_queue.work);
+       thermal_zone_device_update(tz);
+}
+
 /* sys I/F for thermal zone */
 
 #define to_thermal_zone(_dev) \
@@ -354,10 +669,41 @@ passive_show(struct device *dev, struct device_attribute *attr,
        return sprintf(buf, "%d\n", tz->forced_passive);
 }
 
+static ssize_t
+policy_store(struct device *dev, struct device_attribute *attr,
+                   const char *buf, size_t count)
+{
+       int ret = -EINVAL;
+       struct thermal_zone_device *tz = to_thermal_zone(dev);
+       struct thermal_governor *gov;
+
+       mutex_lock(&thermal_governor_lock);
+
+       gov = __find_governor(buf);
+       if (!gov)
+               goto exit;
+
+       tz->governor = gov;
+       ret = count;
+
+exit:
+       mutex_unlock(&thermal_governor_lock);
+       return ret;
+}
+
+static ssize_t
+policy_show(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+       struct thermal_zone_device *tz = to_thermal_zone(dev);
+
+       return sprintf(buf, "%s\n", tz->governor->name);
+}
+
 static DEVICE_ATTR(type, 0444, type_show, NULL);
 static DEVICE_ATTR(temp, 0444, temp_show, NULL);
 static DEVICE_ATTR(mode, 0644, mode_show, mode_store);
 static DEVICE_ATTR(passive, S_IRUGO | S_IWUSR, passive_show, passive_store);
+static DEVICE_ATTR(policy, S_IRUGO | S_IWUSR, policy_show, policy_store);
 
 /* sys I/F for cooling device */
 #define to_cooling_device(_dev)        \
@@ -700,27 +1046,6 @@ thermal_remove_hwmon_sysfs(struct thermal_zone_device *tz)
 }
 #endif
 
-static void thermal_zone_device_set_polling(struct thermal_zone_device *tz,
-                                           int delay)
-{
-       if (delay > 1000)
-               mod_delayed_work(system_freezable_wq, &tz->poll_queue,
-                                round_jiffies(msecs_to_jiffies(delay)));
-       else if (delay)
-               mod_delayed_work(system_freezable_wq, &tz->poll_queue,
-                                msecs_to_jiffies(delay));
-       else
-               cancel_delayed_work(&tz->poll_queue);
-}
-
-static void thermal_zone_device_check(struct work_struct *work)
-{
-       struct thermal_zone_device *tz = container_of(work, struct
-                                                     thermal_zone_device,
-                                                     poll_queue.work);
-       thermal_zone_device_update(tz);
-}
-
 /**
  * thermal_zone_bind_cooling_device - bind a cooling device to a thermal zone
  * @tz:                thermal zone device
@@ -895,7 +1220,6 @@ thermal_cooling_device_register(char *type, void *devdata,
                                const struct thermal_cooling_device_ops *ops)
 {
        struct thermal_cooling_device *cdev;
-       struct thermal_zone_device *pos;
        int result;
 
        if (type && strlen(type) >= THERMAL_NAME_LENGTH)
@@ -945,20 +1269,15 @@ thermal_cooling_device_register(char *type, void *devdata,
        if (result)
                goto unregister;
 
+       /* Add 'this' new cdev to the global cdev list */
        mutex_lock(&thermal_list_lock);
        list_add(&cdev->node, &thermal_cdev_list);
-       list_for_each_entry(pos, &thermal_tz_list, node) {
-               if (!pos->ops->bind)
-                       continue;
-               result = pos->ops->bind(pos, cdev);
-               if (result)
-                       break;
-
-       }
        mutex_unlock(&thermal_list_lock);
 
-       if (!result)
-               return cdev;
+       /* Update binding information for 'this' new cdev */
+       bind_cdev(cdev);
+
+       return cdev;
 
 unregister:
        release_idr(&thermal_cdev_idr, &thermal_idr_lock, cdev->id);
@@ -974,10 +1293,10 @@ EXPORT_SYMBOL(thermal_cooling_device_register);
  * thermal_cooling_device_unregister() must be called when the device is no
  * longer needed.
  */
-void thermal_cooling_device_unregister(struct
-                                      thermal_cooling_device
-                                      *cdev)
+void thermal_cooling_device_unregister(struct thermal_cooling_device *cdev)
 {
+       int i;
+       const struct thermal_zone_params *tzp;
        struct thermal_zone_device *tz;
        struct thermal_cooling_device *pos = NULL;
 
@@ -994,12 +1313,28 @@ void thermal_cooling_device_unregister(struct
                return;
        }
        list_del(&cdev->node);
+
+       /* Unbind all thermal zones associated with 'this' cdev */
        list_for_each_entry(tz, &thermal_tz_list, node) {
-               if (!tz->ops->unbind)
+               if (tz->ops->unbind) {
+                       tz->ops->unbind(tz, cdev);
                        continue;
-               tz->ops->unbind(tz, cdev);
+               }
+
+               if (!tz->tzp || !tz->tzp->tbp)
+                       continue;
+
+               tzp = tz->tzp;
+               for (i = 0; i < tzp->num_tbps; i++) {
+                       if (tzp->tbp[i].cdev == cdev) {
+                               __unbind(tz, tzp->tbp[i].trip_mask, cdev);
+                               tzp->tbp[i].cdev = NULL;
+                       }
+               }
        }
+
        mutex_unlock(&thermal_list_lock);
+
        if (cdev->type[0])
                device_remove_file(&cdev->device, &dev_attr_cdev_type);
        device_remove_file(&cdev->device, &dev_attr_max_state);
@@ -1011,7 +1346,7 @@ void thermal_cooling_device_unregister(struct
 }
 EXPORT_SYMBOL(thermal_cooling_device_unregister);
 
-static void thermal_cdev_do_update(struct thermal_cooling_device *cdev)
+void thermal_cdev_update(struct thermal_cooling_device *cdev)
 {
        struct thermal_instance *instance;
        unsigned long target = 0;
@@ -1032,183 +1367,25 @@ static void thermal_cdev_do_update(struct thermal_cooling_device *cdev)
        cdev->ops->set_cur_state(cdev, target);
        cdev->updated = true;
 }
+EXPORT_SYMBOL(thermal_cdev_update);
 
-static void thermal_zone_do_update(struct thermal_zone_device *tz)
-{
-       struct thermal_instance *instance;
-
-       list_for_each_entry(instance, &tz->thermal_instances, tz_node)
-               thermal_cdev_do_update(instance->cdev);
-}
-
-/*
- * Cooling algorithm for both active and passive cooling
- *
- * 1. if the temperature is higher than a trip point,
- *    a. if the trend is THERMAL_TREND_RAISING, use higher cooling
- *       state for this trip point
- *    b. if the trend is THERMAL_TREND_DROPPING, use lower cooling
- *       state for this trip point
- *
- * 2. if the temperature is lower than a trip point, use lower
- *    cooling state for this trip point
- *
- * Note that this behaves the same as the previous passive cooling
- * algorithm.
- */
-
-static void thermal_zone_trip_update(struct thermal_zone_device *tz,
-                                    int trip, long temp)
-{
-       struct thermal_instance *instance;
-       struct thermal_cooling_device *cdev = NULL;
-       unsigned long cur_state, max_state;
-       long trip_temp;
-       enum thermal_trip_type trip_type;
-       enum thermal_trend trend;
-
-       if (trip == THERMAL_TRIPS_NONE) {
-               trip_temp = tz->forced_passive;
-               trip_type = THERMAL_TRIPS_NONE;
-       } else {
-               tz->ops->get_trip_temp(tz, trip, &trip_temp);
-               tz->ops->get_trip_type(tz, trip, &trip_type);
-       }
-
-       if (!tz->ops->get_trend || tz->ops->get_trend(tz, trip, &trend)) {
-               /*
-                * compare the current temperature and previous temperature
-                * to get the thermal trend, if no special requirement
-                */
-               if (tz->temperature > tz->last_temperature)
-                       trend = THERMAL_TREND_RAISING;
-               else if (tz->temperature < tz->last_temperature)
-                       trend = THERMAL_TREND_DROPPING;
-               else
-                       trend = THERMAL_TREND_STABLE;
-       }
-
-       if (temp >= trip_temp) {
-               list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
-                       if (instance->trip != trip)
-                               continue;
-
-                       cdev = instance->cdev;
-
-                       cdev->ops->get_cur_state(cdev, &cur_state);
-                       cdev->ops->get_max_state(cdev, &max_state);
-
-                       if (trend == THERMAL_TREND_RAISING) {
-                               cur_state = cur_state < instance->upper ?
-                                           (cur_state + 1) : instance->upper;
-                       } else if (trend == THERMAL_TREND_DROPPING) {
-                               cur_state = cur_state > instance->lower ?
-                                   (cur_state - 1) : instance->lower;
-                       }
-
-                       /* activate a passive thermal instance */
-                       if ((trip_type == THERMAL_TRIP_PASSIVE ||
-                            trip_type == THERMAL_TRIPS_NONE) &&
-                            instance->target == THERMAL_NO_TARGET)
-                               tz->passive++;
-
-                       instance->target = cur_state;
-                       cdev->updated = false; /* cooling device needs update */
-               }
-       } else {        /* below trip */
-               list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
-                       if (instance->trip != trip)
-                               continue;
-
-                       /* Do not use the inactive thermal instance */
-                       if (instance->target == THERMAL_NO_TARGET)
-                               continue;
-                       cdev = instance->cdev;
-                       cdev->ops->get_cur_state(cdev, &cur_state);
-
-                       cur_state = cur_state > instance->lower ?
-                                   (cur_state - 1) : THERMAL_NO_TARGET;
-
-                       /* deactivate a passive thermal instance */
-                       if ((trip_type == THERMAL_TRIP_PASSIVE ||
-                            trip_type == THERMAL_TRIPS_NONE) &&
-                            cur_state == THERMAL_NO_TARGET)
-                               tz->passive--;
-                       instance->target = cur_state;
-                       cdev->updated = false; /* cooling device needs update */
-               }
-       }
-
-       return;
-}
 /**
- * thermal_zone_device_update - force an update of a thermal zone's state
- * @ttz:       the thermal zone to update
+ * notify_thermal_framework - Sensor drivers use this API to notify framework
+ * @tz:                thermal zone device
+ * @trip:      indicates which trip point has been crossed
+ *
+ * This function handles the trip events from sensor drivers. It starts
+ * throttling the cooling devices according to the policy configured.
+ * For CRITICAL and HOT trip points, this notifies the respective drivers,
+ * and does actual throttling for other trip points i.e ACTIVE and PASSIVE.
+ * The throttling policy is based on the configured platform data; if no
+ * platform data is provided, this uses the step_wise throttling policy.
  */
-
-void thermal_zone_device_update(struct thermal_zone_device *tz)
+void notify_thermal_framework(struct thermal_zone_device *tz, int trip)
 {
-       int count, ret = 0;
-       long temp, trip_temp;
-       enum thermal_trip_type trip_type;
-
-       mutex_lock(&tz->lock);
-
-       if (tz->ops->get_temp(tz, &temp)) {
-               /* get_temp failed - retry it later */
-               pr_warn("failed to read out thermal zone %d\n", tz->id);
-               goto leave;
-       }
-
-       tz->last_temperature = tz->temperature;
-       tz->temperature = temp;
-
-       for (count = 0; count < tz->trips; count++) {
-               tz->ops->get_trip_type(tz, count, &trip_type);
-               tz->ops->get_trip_temp(tz, count, &trip_temp);
-
-               switch (trip_type) {
-               case THERMAL_TRIP_CRITICAL:
-                       if (temp >= trip_temp) {
-                               if (tz->ops->notify)
-                                       ret = tz->ops->notify(tz, count,
-                                                             trip_type);
-                               if (!ret) {
-                                       pr_emerg("Critical temperature reached (%ld C), shutting down\n",
-                                                temp/1000);
-                                       orderly_poweroff(true);
-                               }
-                       }
-                       break;
-               case THERMAL_TRIP_HOT:
-                       if (temp >= trip_temp)
-                               if (tz->ops->notify)
-                                       tz->ops->notify(tz, count, trip_type);
-                       break;
-               case THERMAL_TRIP_ACTIVE:
-                       thermal_zone_trip_update(tz, count, temp);
-                       break;
-               case THERMAL_TRIP_PASSIVE:
-                       if (temp >= trip_temp || tz->passive)
-                               thermal_zone_trip_update(tz, count, temp);
-                       break;
-               }
-       }
-
-       if (tz->forced_passive)
-               thermal_zone_trip_update(tz, THERMAL_TRIPS_NONE, temp);
-       thermal_zone_do_update(tz);
-
-leave:
-       if (tz->passive)
-               thermal_zone_device_set_polling(tz, tz->passive_delay);
-       else if (tz->polling_delay)
-               thermal_zone_device_set_polling(tz, tz->polling_delay);
-       else
-               thermal_zone_device_set_polling(tz, 0);
-       mutex_unlock(&tz->lock);
+       handle_thermal_trip(tz, trip);
 }
-EXPORT_SYMBOL(thermal_zone_device_update);
+EXPORT_SYMBOL(notify_thermal_framework);
 
 /**
  * create_trip_attrs - create attributes for trip points
@@ -1320,6 +1497,7 @@ static void remove_trip_attrs(struct thermal_zone_device *tz)
  * @mask:      a bit string indicating the writeablility of trip points
  * @devdata:   private device data
  * @ops:       standard thermal zone device callbacks
+ * @tzp:       thermal zone platform parameters
  * @passive_delay: number of milliseconds to wait between polls when
  *                performing passive cooling
  * @polling_delay: number of milliseconds to wait between polls when checking
@@ -1332,10 +1510,10 @@ static void remove_trip_attrs(struct thermal_zone_device *tz)
 struct thermal_zone_device *thermal_zone_device_register(const char *type,
        int trips, int mask, void *devdata,
        const struct thermal_zone_device_ops *ops,
+       const struct thermal_zone_params *tzp,
        int passive_delay, int polling_delay)
 {
        struct thermal_zone_device *tz;
-       struct thermal_cooling_device *pos;
        enum thermal_trip_type trip_type;
        int result;
        int count;
@@ -1365,6 +1543,7 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
 
        strcpy(tz->type, type ? : "");
        tz->ops = ops;
+       tz->tzp = tzp;
        tz->device.class = &thermal_class;
        tz->devdata = devdata;
        tz->trips = trips;
@@ -1406,27 +1585,38 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
                        passive = 1;
        }
 
-       if (!passive)
-               result = device_create_file(&tz->device,
-                                           &dev_attr_passive);
+       if (!passive) {
+               result = device_create_file(&tz->device, &dev_attr_passive);
+               if (result)
+                       goto unregister;
+       }
 
+       /* Create policy attribute */
+       result = device_create_file(&tz->device, &dev_attr_policy);
        if (result)
                goto unregister;
 
+       /* Update 'this' zone's governor information */
+       mutex_lock(&thermal_governor_lock);
+
+       if (tz->tzp)
+               tz->governor = __find_governor(tz->tzp->governor_name);
+       else
+               tz->governor = __find_governor(DEFAULT_THERMAL_GOVERNOR);
+
+       mutex_unlock(&thermal_governor_lock);
+
        result = thermal_add_hwmon_sysfs(tz);
        if (result)
                goto unregister;
 
        mutex_lock(&thermal_list_lock);
        list_add_tail(&tz->node, &thermal_tz_list);
-       if (ops->bind)
-               list_for_each_entry(pos, &thermal_cdev_list, node) {
-               result = ops->bind(tz, pos);
-               if (result)
-                       break;
-               }
        mutex_unlock(&thermal_list_lock);
 
+       /* Bind cooling devices for this zone */
+       bind_tz(tz);
+
        INIT_DELAYED_WORK(&(tz->poll_queue), thermal_zone_device_check);
 
        thermal_zone_device_update(tz);
@@ -1447,12 +1637,16 @@ EXPORT_SYMBOL(thermal_zone_device_register);
  */
 void thermal_zone_device_unregister(struct thermal_zone_device *tz)
 {
+       int i;
+       const struct thermal_zone_params *tzp;
        struct thermal_cooling_device *cdev;
        struct thermal_zone_device *pos = NULL;
 
        if (!tz)
                return;
 
+       tzp = tz->tzp;
+
        mutex_lock(&thermal_list_lock);
        list_for_each_entry(pos, &thermal_tz_list, node)
            if (pos == tz)
@@ -1463,9 +1657,25 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz)
                return;
        }
        list_del(&tz->node);
-       if (tz->ops->unbind)
-               list_for_each_entry(cdev, &thermal_cdev_list, node)
-                   tz->ops->unbind(tz, cdev);
+
+       /* Unbind all cdevs associated with 'this' thermal zone */
+       list_for_each_entry(cdev, &thermal_cdev_list, node) {
+               if (tz->ops->unbind) {
+                       tz->ops->unbind(tz, cdev);
+                       continue;
+               }
+
+               if (!tzp || !tzp->tbp)
+                       break;
+
+               for (i = 0; i < tzp->num_tbps; i++) {
+                       if (tzp->tbp[i].cdev == cdev) {
+                               __unbind(tz, tzp->tbp[i].trip_mask, cdev);
+                               tzp->tbp[i].cdev = NULL;
+                       }
+               }
+       }
+
        mutex_unlock(&thermal_list_lock);
 
        thermal_zone_device_set_polling(tz, 0);
@@ -1475,7 +1685,9 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz)
        device_remove_file(&tz->device, &dev_attr_temp);
        if (tz->ops->get_mode)
                device_remove_file(&tz->device, &dev_attr_mode);
+       device_remove_file(&tz->device, &dev_attr_policy);
        remove_trip_attrs(tz);
+       tz->governor = NULL;
 
        thermal_remove_hwmon_sysfs(tz);
        release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id);
diff --git a/drivers/thermal/user_space.c b/drivers/thermal/user_space.c
new file mode 100644 (file)
index 0000000..6bbb380
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ *  user_space.c - A simple user space Thermal events notifier
+ *
+ *  Copyright (C) 2012 Intel Corp
+ *  Copyright (C) 2012 Durgadoss R <durgadoss.r@intel.com>
+ *
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/thermal.h>
+
+#include "thermal_core.h"
+
+/**
+ * notify_user_space - Notifies user space about thermal events
+ * @tz - thermal_zone_device
+ *
+ * This function notifies the user space through UEvents.
+ */
+static int notify_user_space(struct thermal_zone_device *tz, int trip)
+{
+       mutex_lock(&tz->lock);
+       kobject_uevent(&tz->device.kobj, KOBJ_CHANGE);
+       mutex_unlock(&tz->lock);
+       return 0;
+}
+
+static struct thermal_governor thermal_gov_user_space = {
+       .name           = "user_space",
+       .throttle       = notify_user_space,
+       .owner          = THIS_MODULE,
+};
+
+static int __init thermal_gov_user_space_init(void)
+{
+       return thermal_register_governor(&thermal_gov_user_space);
+}
+
+static void __exit thermal_gov_user_space_exit(void)
+{
+       thermal_unregister_governor(&thermal_gov_user_space);
+}
+
+/* This should load after thermal framework */
+fs_initcall(thermal_gov_user_space_init);
+module_exit(thermal_gov_user_space_exit);
+
+MODULE_AUTHOR("Durgadoss R");
+MODULE_DESCRIPTION("A user space Thermal notifier");
+MODULE_LICENSE("GPL");
index d8e05eeab23213e503381422735f59fe7240281c..0ecf22b6a38e5c61a9d42670435ac60939ce82c4 100644 (file)
@@ -357,6 +357,7 @@ config TRACE_SINK
 config PPC_EPAPR_HV_BYTECHAN
        tristate "ePAPR hypervisor byte channel driver"
        depends on PPC
+       select EPAPR_PARAVIRT
        help
          This driver creates /dev entries for each ePAPR hypervisor byte
          channel, thereby allowing applications to communicate with byte
index cab5c7adf8e84314e9ee515465a0db07bb1687e5..744c3b8eea49dbfb141a90bf3a0ad09e2d8f320e 100644 (file)
@@ -1496,8 +1496,10 @@ static int __devinit hvcs_initialize(void)
                num_ttys_to_alloc = hvcs_parm_num_devs;
 
        hvcs_tty_driver = alloc_tty_driver(num_ttys_to_alloc);
-       if (!hvcs_tty_driver)
+       if (!hvcs_tty_driver) {
+               mutex_unlock(&hvcs_init_mutex);
                return -ENOMEM;
+       }
 
        if (hvcs_alloc_index_list(num_ttys_to_alloc)) {
                rc = -ENOMEM;
index 8c0b7b42319c44d7038892d0026582797acad95a..60b076cc4e20c28fb2c4e89a0445c61c0355925d 100644 (file)
 #define ECHO_OP_SET_CANON_COL 0x81
 #define ECHO_OP_ERASE_TAB 0x82
 
+struct n_tty_data {
+       unsigned int column;
+       unsigned long overrun_time;
+       int num_overrun;
+
+       unsigned char lnext:1, erasing:1, raw:1, real_raw:1, icanon:1;
+       unsigned char echo_overrun:1;
+
+       DECLARE_BITMAP(process_char_map, 256);
+       DECLARE_BITMAP(read_flags, N_TTY_BUF_SIZE);
+
+       char *read_buf;
+       int read_head;
+       int read_tail;
+       int read_cnt;
+
+       unsigned char *echo_buf;
+       unsigned int echo_pos;
+       unsigned int echo_cnt;
+
+       int canon_data;
+       unsigned long canon_head;
+       unsigned int canon_column;
+
+       struct mutex atomic_read_lock;
+       struct mutex output_lock;
+       struct mutex echo_lock;
+       spinlock_t read_lock;
+};
+
 static inline int tty_put_user(struct tty_struct *tty, unsigned char x,
                               unsigned char __user *ptr)
 {
-       tty_audit_add_data(tty, &x, 1);
+       struct n_tty_data *ldata = tty->disc_data;
+
+       tty_audit_add_data(tty, &x, 1, ldata->icanon);
        return put_user(x, ptr);
 }
 
@@ -92,17 +124,18 @@ static inline int tty_put_user(struct tty_struct *tty, unsigned char x,
 
 static void n_tty_set_room(struct tty_struct *tty)
 {
+       struct n_tty_data *ldata = tty->disc_data;
        int left;
        int old_left;
 
-       /* tty->read_cnt is not read locked ? */
+       /* ldata->read_cnt is not read locked ? */
        if (I_PARMRK(tty)) {
                /* Multiply read_cnt by 3, since each byte might take up to
                 * three times as many spaces when PARMRK is set (depending on
                 * its flags, e.g. parity error). */
-               left = N_TTY_BUF_SIZE - tty->read_cnt * 3 - 1;
+               left = N_TTY_BUF_SIZE - ldata->read_cnt * 3 - 1;
        } else
-               left = N_TTY_BUF_SIZE - tty->read_cnt - 1;
+               left = N_TTY_BUF_SIZE - ldata->read_cnt - 1;
 
        /*
         * If we are doing input canonicalization, and there are no
@@ -111,44 +144,47 @@ static void n_tty_set_room(struct tty_struct *tty)
         * characters will be beeped.
         */
        if (left <= 0)
-               left = tty->icanon && !tty->canon_data;
+               left = ldata->icanon && !ldata->canon_data;
        old_left = tty->receive_room;
        tty->receive_room = left;
 
        /* Did this open up the receive buffer? We may need to flip */
-       if (left && !old_left)
-               schedule_work(&tty->buf.work);
+       if (left && !old_left) {
+               WARN_RATELIMIT(tty->port->itty == NULL,
+                               "scheduling with invalid itty");
+               schedule_work(&tty->port->buf.work);
+       }
 }
 
-static void put_tty_queue_nolock(unsigned char c, struct tty_struct *tty)
+static void put_tty_queue_nolock(unsigned char c, struct n_tty_data *ldata)
 {
-       if (tty->read_cnt < N_TTY_BUF_SIZE) {
-               tty->read_buf[tty->read_head] = c;
-               tty->read_head = (tty->read_head + 1) & (N_TTY_BUF_SIZE-1);
-               tty->read_cnt++;
+       if (ldata->read_cnt < N_TTY_BUF_SIZE) {
+               ldata->read_buf[ldata->read_head] = c;
+               ldata->read_head = (ldata->read_head + 1) & (N_TTY_BUF_SIZE-1);
+               ldata->read_cnt++;
        }
 }
 
 /**
  *     put_tty_queue           -       add character to tty
  *     @c: character
- *     @tty: tty device
+ *     @ldata: n_tty data
  *
  *     Add a character to the tty read_buf queue. This is done under the
  *     read_lock to serialize character addition and also to protect us
  *     against parallel reads or flushes
  */
 
-static void put_tty_queue(unsigned char c, struct tty_struct *tty)
+static void put_tty_queue(unsigned char c, struct n_tty_data *ldata)
 {
        unsigned long flags;
        /*
         *      The problem of stomping on the buffers ends here.
         *      Why didn't anyone see this one coming? --AJK
        */
-       spin_lock_irqsave(&tty->read_lock, flags);
-       put_tty_queue_nolock(c, tty);
-       spin_unlock_irqrestore(&tty->read_lock, flags);
+       spin_lock_irqsave(&ldata->read_lock, flags);
+       put_tty_queue_nolock(c, ldata);
+       spin_unlock_irqrestore(&ldata->read_lock, flags);
 }
 
 /**
@@ -179,18 +215,19 @@ static void check_unthrottle(struct tty_struct *tty)
 
 static void reset_buffer_flags(struct tty_struct *tty)
 {
+       struct n_tty_data *ldata = tty->disc_data;
        unsigned long flags;
 
-       spin_lock_irqsave(&tty->read_lock, flags);
-       tty->read_head = tty->read_tail = tty->read_cnt = 0;
-       spin_unlock_irqrestore(&tty->read_lock, flags);
+       spin_lock_irqsave(&ldata->read_lock, flags);
+       ldata->read_head = ldata->read_tail = ldata->read_cnt = 0;
+       spin_unlock_irqrestore(&ldata->read_lock, flags);
 
-       mutex_lock(&tty->echo_lock);
-       tty->echo_pos = tty->echo_cnt = tty->echo_overrun = 0;
-       mutex_unlock(&tty->echo_lock);
+       mutex_lock(&ldata->echo_lock);
+       ldata->echo_pos = ldata->echo_cnt = ldata->echo_overrun = 0;
+       mutex_unlock(&ldata->echo_lock);
 
-       tty->canon_head = tty->canon_data = tty->erasing = 0;
-       memset(&tty->read_flags, 0, sizeof tty->read_flags);
+       ldata->canon_head = ldata->canon_data = ldata->erasing = 0;
+       bitmap_zero(ldata->read_flags, N_TTY_BUF_SIZE);
        n_tty_set_room(tty);
 }
 
@@ -235,18 +272,19 @@ static void n_tty_flush_buffer(struct tty_struct *tty)
 
 static ssize_t n_tty_chars_in_buffer(struct tty_struct *tty)
 {
+       struct n_tty_data *ldata = tty->disc_data;
        unsigned long flags;
        ssize_t n = 0;
 
-       spin_lock_irqsave(&tty->read_lock, flags);
-       if (!tty->icanon) {
-               n = tty->read_cnt;
-       } else if (tty->canon_data) {
-               n = (tty->canon_head > tty->read_tail) ?
-                       tty->canon_head - tty->read_tail :
-                       tty->canon_head + (N_TTY_BUF_SIZE - tty->read_tail);
+       spin_lock_irqsave(&ldata->read_lock, flags);
+       if (!ldata->icanon) {
+               n = ldata->read_cnt;
+       } else if (ldata->canon_data) {
+               n = (ldata->canon_head > ldata->read_tail) ?
+                       ldata->canon_head - ldata->read_tail :
+                       ldata->canon_head + (N_TTY_BUF_SIZE - ldata->read_tail);
        }
-       spin_unlock_irqrestore(&tty->read_lock, flags);
+       spin_unlock_irqrestore(&ldata->read_lock, flags);
        return n;
 }
 
@@ -301,6 +339,7 @@ static inline int is_continuation(unsigned char c, struct tty_struct *tty)
 
 static int do_output_char(unsigned char c, struct tty_struct *tty, int space)
 {
+       struct n_tty_data *ldata = tty->disc_data;
        int     spaces;
 
        if (!space)
@@ -309,48 +348,48 @@ static int do_output_char(unsigned char c, struct tty_struct *tty, int space)
        switch (c) {
        case '\n':
                if (O_ONLRET(tty))
-                       tty->column = 0;
+                       ldata->column = 0;
                if (O_ONLCR(tty)) {
                        if (space < 2)
                                return -1;
-                       tty->canon_column = tty->column = 0;
+                       ldata->canon_column = ldata->column = 0;
                        tty->ops->write(tty, "\r\n", 2);
                        return 2;
                }
-               tty->canon_column = tty->column;
+               ldata->canon_column = ldata->column;
                break;
        case '\r':
-               if (O_ONOCR(tty) && tty->column == 0)
+               if (O_ONOCR(tty) && ldata->column == 0)
                        return 0;
                if (O_OCRNL(tty)) {
                        c = '\n';
                        if (O_ONLRET(tty))
-                               tty->canon_column = tty->column = 0;
+                               ldata->canon_column = ldata->column = 0;
                        break;
                }
-               tty->canon_column = tty->column = 0;
+               ldata->canon_column = ldata->column = 0;
                break;
        case '\t':
-               spaces = 8 - (tty->column & 7);
+               spaces = 8 - (ldata->column & 7);
                if (O_TABDLY(tty) == XTABS) {
                        if (space < spaces)
                                return -1;
-                       tty->column += spaces;
+                       ldata->column += spaces;
                        tty->ops->write(tty, "        ", spaces);
                        return spaces;
                }
-               tty->column += spaces;
+               ldata->column += spaces;
                break;
        case '\b':
-               if (tty->column > 0)
-                       tty->column--;
+               if (ldata->column > 0)
+                       ldata->column--;
                break;
        default:
                if (!iscntrl(c)) {
                        if (O_OLCUC(tty))
                                c = toupper(c);
                        if (!is_continuation(c, tty))
-                               tty->column++;
+                               ldata->column++;
                }
                break;
        }
@@ -375,14 +414,15 @@ static int do_output_char(unsigned char c, struct tty_struct *tty, int space)
 
 static int process_output(unsigned char c, struct tty_struct *tty)
 {
+       struct n_tty_data *ldata = tty->disc_data;
        int     space, retval;
 
-       mutex_lock(&tty->output_lock);
+       mutex_lock(&ldata->output_lock);
 
        space = tty_write_room(tty);
        retval = do_output_char(c, tty, space);
 
-       mutex_unlock(&tty->output_lock);
+       mutex_unlock(&ldata->output_lock);
        if (retval < 0)
                return -1;
        else
@@ -411,15 +451,16 @@ static int process_output(unsigned char c, struct tty_struct *tty)
 static ssize_t process_output_block(struct tty_struct *tty,
                                    const unsigned char *buf, unsigned int nr)
 {
+       struct n_tty_data *ldata = tty->disc_data;
        int     space;
        int     i;
        const unsigned char *cp;
 
-       mutex_lock(&tty->output_lock);
+       mutex_lock(&ldata->output_lock);
 
        space = tty_write_room(tty);
        if (!space) {
-               mutex_unlock(&tty->output_lock);
+               mutex_unlock(&ldata->output_lock);
                return 0;
        }
        if (nr > space)
@@ -431,30 +472,30 @@ static ssize_t process_output_block(struct tty_struct *tty,
                switch (c) {
                case '\n':
                        if (O_ONLRET(tty))
-                               tty->column = 0;
+                               ldata->column = 0;
                        if (O_ONLCR(tty))
                                goto break_out;
-                       tty->canon_column = tty->column;
+                       ldata->canon_column = ldata->column;
                        break;
                case '\r':
-                       if (O_ONOCR(tty) && tty->column == 0)
+                       if (O_ONOCR(tty) && ldata->column == 0)
                                goto break_out;
                        if (O_OCRNL(tty))
                                goto break_out;
-                       tty->canon_column = tty->column = 0;
+                       ldata->canon_column = ldata->column = 0;
                        break;
                case '\t':
                        goto break_out;
                case '\b':
-                       if (tty->column > 0)
-                               tty->column--;
+                       if (ldata->column > 0)
+                               ldata->column--;
                        break;
                default:
                        if (!iscntrl(c)) {
                                if (O_OLCUC(tty))
                                        goto break_out;
                                if (!is_continuation(c, tty))
-                                       tty->column++;
+                                       ldata->column++;
                        }
                        break;
                }
@@ -462,7 +503,7 @@ static ssize_t process_output_block(struct tty_struct *tty,
 break_out:
        i = tty->ops->write(tty, buf, i);
 
-       mutex_unlock(&tty->output_lock);
+       mutex_unlock(&ldata->output_lock);
        return i;
 }
 
@@ -494,21 +535,22 @@ break_out:
 
 static void process_echoes(struct tty_struct *tty)
 {
+       struct n_tty_data *ldata = tty->disc_data;
        int     space, nr;
        unsigned char c;
        unsigned char *cp, *buf_end;
 
-       if (!tty->echo_cnt)
+       if (!ldata->echo_cnt)
                return;
 
-       mutex_lock(&tty->output_lock);
-       mutex_lock(&tty->echo_lock);
+       mutex_lock(&ldata->output_lock);
+       mutex_lock(&ldata->echo_lock);
 
        space = tty_write_room(tty);
 
-       buf_end = tty->echo_buf + N_TTY_BUF_SIZE;
-       cp = tty->echo_buf + tty->echo_pos;
-       nr = tty->echo_cnt;
+       buf_end = ldata->echo_buf + N_TTY_BUF_SIZE;
+       cp = ldata->echo_buf + ldata->echo_pos;
+       nr = ldata->echo_cnt;
        while (nr > 0) {
                c = *cp;
                if (c == ECHO_OP_START) {
@@ -545,7 +587,7 @@ static void process_echoes(struct tty_struct *tty)
                                 * Otherwise, tab spacing is normal.
                                 */
                                if (!(num_chars & 0x80))
-                                       num_chars += tty->canon_column;
+                                       num_chars += ldata->canon_column;
                                num_bs = 8 - (num_chars & 7);
 
                                if (num_bs > space) {
@@ -555,22 +597,22 @@ static void process_echoes(struct tty_struct *tty)
                                space -= num_bs;
                                while (num_bs--) {
                                        tty_put_char(tty, '\b');
-                                       if (tty->column > 0)
-                                               tty->column--;
+                                       if (ldata->column > 0)
+                                               ldata->column--;
                                }
                                cp += 3;
                                nr -= 3;
                                break;
 
                        case ECHO_OP_SET_CANON_COL:
-                               tty->canon_column = tty->column;
+                               ldata->canon_column = ldata->column;
                                cp += 2;
                                nr -= 2;
                                break;
 
                        case ECHO_OP_MOVE_BACK_COL:
-                               if (tty->column > 0)
-                                       tty->column--;
+                               if (ldata->column > 0)
+                                       ldata->column--;
                                cp += 2;
                                nr -= 2;
                                break;
@@ -582,7 +624,7 @@ static void process_echoes(struct tty_struct *tty)
                                        break;
                                }
                                tty_put_char(tty, ECHO_OP_START);
-                               tty->column++;
+                               ldata->column++;
                                space--;
                                cp += 2;
                                nr -= 2;
@@ -604,7 +646,7 @@ static void process_echoes(struct tty_struct *tty)
                                }
                                tty_put_char(tty, '^');
                                tty_put_char(tty, op ^ 0100);
-                               tty->column += 2;
+                               ldata->column += 2;
                                space -= 2;
                                cp += 2;
                                nr -= 2;
@@ -635,20 +677,20 @@ static void process_echoes(struct tty_struct *tty)
        }
 
        if (nr == 0) {
-               tty->echo_pos = 0;
-               tty->echo_cnt = 0;
-               tty->echo_overrun = 0;
+               ldata->echo_pos = 0;
+               ldata->echo_cnt = 0;
+               ldata->echo_overrun = 0;
        } else {
-               int num_processed = tty->echo_cnt - nr;
-               tty->echo_pos += num_processed;
-               tty->echo_pos &= N_TTY_BUF_SIZE - 1;
-               tty->echo_cnt = nr;
+               int num_processed = ldata->echo_cnt - nr;
+               ldata->echo_pos += num_processed;
+               ldata->echo_pos &= N_TTY_BUF_SIZE - 1;
+               ldata->echo_cnt = nr;
                if (num_processed > 0)
-                       tty->echo_overrun = 0;
+                       ldata->echo_overrun = 0;
        }
 
-       mutex_unlock(&tty->echo_lock);
-       mutex_unlock(&tty->output_lock);
+       mutex_unlock(&ldata->echo_lock);
+       mutex_unlock(&ldata->output_lock);
 
        if (tty->ops->flush_chars)
                tty->ops->flush_chars(tty);
@@ -657,72 +699,70 @@ static void process_echoes(struct tty_struct *tty)
 /**
  *     add_echo_byte   -       add a byte to the echo buffer
  *     @c: unicode byte to echo
- *     @tty: terminal device
+ *     @ldata: n_tty data
  *
  *     Add a character or operation byte to the echo buffer.
  *
  *     Should be called under the echo lock to protect the echo buffer.
  */
 
-static void add_echo_byte(unsigned char c, struct tty_struct *tty)
+static void add_echo_byte(unsigned char c, struct n_tty_data *ldata)
 {
        int     new_byte_pos;
 
-       if (tty->echo_cnt == N_TTY_BUF_SIZE) {
+       if (ldata->echo_cnt == N_TTY_BUF_SIZE) {
                /* Circular buffer is already at capacity */
-               new_byte_pos = tty->echo_pos;
+               new_byte_pos = ldata->echo_pos;
 
                /*
                 * Since the buffer start position needs to be advanced,
                 * be sure to step by a whole operation byte group.
                 */
-               if (tty->echo_buf[tty->echo_pos] == ECHO_OP_START) {
-                       if (tty->echo_buf[(tty->echo_pos + 1) &
+               if (ldata->echo_buf[ldata->echo_pos] == ECHO_OP_START) {
+                       if (ldata->echo_buf[(ldata->echo_pos + 1) &
                                          (N_TTY_BUF_SIZE - 1)] ==
                                                ECHO_OP_ERASE_TAB) {
-                               tty->echo_pos += 3;
-                               tty->echo_cnt -= 2;
+                               ldata->echo_pos += 3;
+                               ldata->echo_cnt -= 2;
                        } else {
-                               tty->echo_pos += 2;
-                               tty->echo_cnt -= 1;
+                               ldata->echo_pos += 2;
+                               ldata->echo_cnt -= 1;
                        }
                } else {
-                       tty->echo_pos++;
+                       ldata->echo_pos++;
                }
-               tty->echo_pos &= N_TTY_BUF_SIZE - 1;
+               ldata->echo_pos &= N_TTY_BUF_SIZE - 1;
 
-               tty->echo_overrun = 1;
+               ldata->echo_overrun = 1;
        } else {
-               new_byte_pos = tty->echo_pos + tty->echo_cnt;
+               new_byte_pos = ldata->echo_pos + ldata->echo_cnt;
                new_byte_pos &= N_TTY_BUF_SIZE - 1;
-               tty->echo_cnt++;
+               ldata->echo_cnt++;
        }
 
-       tty->echo_buf[new_byte_pos] = c;
+       ldata->echo_buf[new_byte_pos] = c;
 }
 
 /**
  *     echo_move_back_col      -       add operation to move back a column
- *     @tty: terminal device
+ *     @ldata: n_tty data
  *
  *     Add an operation to the echo buffer to move back one column.
  *
  *     Locking: echo_lock to protect the echo buffer
  */
 
-static void echo_move_back_col(struct tty_struct *tty)
+static void echo_move_back_col(struct n_tty_data *ldata)
 {
-       mutex_lock(&tty->echo_lock);
-
-       add_echo_byte(ECHO_OP_START, tty);
-       add_echo_byte(ECHO_OP_MOVE_BACK_COL, tty);
-
-       mutex_unlock(&tty->echo_lock);
+       mutex_lock(&ldata->echo_lock);
+       add_echo_byte(ECHO_OP_START, ldata);
+       add_echo_byte(ECHO_OP_MOVE_BACK_COL, ldata);
+       mutex_unlock(&ldata->echo_lock);
 }
 
 /**
  *     echo_set_canon_col      -       add operation to set the canon column
- *     @tty: terminal device
+ *     @ldata: n_tty data
  *
  *     Add an operation to the echo buffer to set the canon column
  *     to the current column.
@@ -730,21 +770,19 @@ static void echo_move_back_col(struct tty_struct *tty)
  *     Locking: echo_lock to protect the echo buffer
  */
 
-static void echo_set_canon_col(struct tty_struct *tty)
+static void echo_set_canon_col(struct n_tty_data *ldata)
 {
-       mutex_lock(&tty->echo_lock);
-
-       add_echo_byte(ECHO_OP_START, tty);
-       add_echo_byte(ECHO_OP_SET_CANON_COL, tty);
-
-       mutex_unlock(&tty->echo_lock);
+       mutex_lock(&ldata->echo_lock);
+       add_echo_byte(ECHO_OP_START, ldata);
+       add_echo_byte(ECHO_OP_SET_CANON_COL, ldata);
+       mutex_unlock(&ldata->echo_lock);
 }
 
 /**
  *     echo_erase_tab  -       add operation to erase a tab
  *     @num_chars: number of character columns already used
  *     @after_tab: true if num_chars starts after a previous tab
- *     @tty: terminal device
+ *     @ldata: n_tty data
  *
  *     Add an operation to the echo buffer to erase a tab.
  *
@@ -758,12 +796,12 @@ static void echo_set_canon_col(struct tty_struct *tty)
  */
 
 static void echo_erase_tab(unsigned int num_chars, int after_tab,
-                          struct tty_struct *tty)
+                          struct n_tty_data *ldata)
 {
-       mutex_lock(&tty->echo_lock);
+       mutex_lock(&ldata->echo_lock);
 
-       add_echo_byte(ECHO_OP_START, tty);
-       add_echo_byte(ECHO_OP_ERASE_TAB, tty);
+       add_echo_byte(ECHO_OP_START, ldata);
+       add_echo_byte(ECHO_OP_ERASE_TAB, ldata);
 
        /* We only need to know this modulo 8 (tab spacing) */
        num_chars &= 7;
@@ -772,9 +810,9 @@ static void echo_erase_tab(unsigned int num_chars, int after_tab,
        if (after_tab)
                num_chars |= 0x80;
 
-       add_echo_byte(num_chars, tty);
+       add_echo_byte(num_chars, ldata);
 
-       mutex_unlock(&tty->echo_lock);
+       mutex_unlock(&ldata->echo_lock);
 }
 
 /**
@@ -790,18 +828,16 @@ static void echo_erase_tab(unsigned int num_chars, int after_tab,
  *     Locking: echo_lock to protect the echo buffer
  */
 
-static void echo_char_raw(unsigned char c, struct tty_struct *tty)
+static void echo_char_raw(unsigned char c, struct n_tty_data *ldata)
 {
-       mutex_lock(&tty->echo_lock);
-
+       mutex_lock(&ldata->echo_lock);
        if (c == ECHO_OP_START) {
-               add_echo_byte(ECHO_OP_START, tty);
-               add_echo_byte(ECHO_OP_START, tty);
+               add_echo_byte(ECHO_OP_START, ldata);
+               add_echo_byte(ECHO_OP_START, ldata);
        } else {
-               add_echo_byte(c, tty);
+               add_echo_byte(c, ldata);
        }
-
-       mutex_unlock(&tty->echo_lock);
+       mutex_unlock(&ldata->echo_lock);
 }
 
 /**
@@ -820,30 +856,32 @@ static void echo_char_raw(unsigned char c, struct tty_struct *tty)
 
 static void echo_char(unsigned char c, struct tty_struct *tty)
 {
-       mutex_lock(&tty->echo_lock);
+       struct n_tty_data *ldata = tty->disc_data;
+
+       mutex_lock(&ldata->echo_lock);
 
        if (c == ECHO_OP_START) {
-               add_echo_byte(ECHO_OP_START, tty);
-               add_echo_byte(ECHO_OP_START, tty);
+               add_echo_byte(ECHO_OP_START, ldata);
+               add_echo_byte(ECHO_OP_START, ldata);
        } else {
                if (L_ECHOCTL(tty) && iscntrl(c) && c != '\t')
-                       add_echo_byte(ECHO_OP_START, tty);
-               add_echo_byte(c, tty);
+                       add_echo_byte(ECHO_OP_START, ldata);
+               add_echo_byte(c, ldata);
        }
 
-       mutex_unlock(&tty->echo_lock);
+       mutex_unlock(&ldata->echo_lock);
 }
 
 /**
  *     finish_erasing          -       complete erase
- *     @tty: tty doing the erase
+ *     @ldata: n_tty data
  */
 
-static inline void finish_erasing(struct tty_struct *tty)
+static inline void finish_erasing(struct n_tty_data *ldata)
 {
-       if (tty->erasing) {
-               echo_char_raw('/', tty);
-               tty->erasing = 0;
+       if (ldata->erasing) {
+               echo_char_raw('/', ldata);
+               ldata->erasing = 0;
        }
 }
 
@@ -861,12 +899,13 @@ static inline void finish_erasing(struct tty_struct *tty)
 
 static void eraser(unsigned char c, struct tty_struct *tty)
 {
+       struct n_tty_data *ldata = tty->disc_data;
        enum { ERASE, WERASE, KILL } kill_type;
        int head, seen_alnums, cnt;
        unsigned long flags;
 
        /* FIXME: locking needed ? */
-       if (tty->read_head == tty->canon_head) {
+       if (ldata->read_head == ldata->canon_head) {
                /* process_output('\a', tty); */ /* what do you think? */
                return;
        }
@@ -876,24 +915,24 @@ static void eraser(unsigned char c, struct tty_struct *tty)
                kill_type = WERASE;
        else {
                if (!L_ECHO(tty)) {
-                       spin_lock_irqsave(&tty->read_lock, flags);
-                       tty->read_cnt -= ((tty->read_head - tty->canon_head) &
+                       spin_lock_irqsave(&ldata->read_lock, flags);
+                       ldata->read_cnt -= ((ldata->read_head - ldata->canon_head) &
                                          (N_TTY_BUF_SIZE - 1));
-                       tty->read_head = tty->canon_head;
-                       spin_unlock_irqrestore(&tty->read_lock, flags);
+                       ldata->read_head = ldata->canon_head;
+                       spin_unlock_irqrestore(&ldata->read_lock, flags);
                        return;
                }
                if (!L_ECHOK(tty) || !L_ECHOKE(tty) || !L_ECHOE(tty)) {
-                       spin_lock_irqsave(&tty->read_lock, flags);
-                       tty->read_cnt -= ((tty->read_head - tty->canon_head) &
+                       spin_lock_irqsave(&ldata->read_lock, flags);
+                       ldata->read_cnt -= ((ldata->read_head - ldata->canon_head) &
                                          (N_TTY_BUF_SIZE - 1));
-                       tty->read_head = tty->canon_head;
-                       spin_unlock_irqrestore(&tty->read_lock, flags);
-                       finish_erasing(tty);
+                       ldata->read_head = ldata->canon_head;
+                       spin_unlock_irqrestore(&ldata->read_lock, flags);
+                       finish_erasing(ldata);
                        echo_char(KILL_CHAR(tty), tty);
                        /* Add a newline if ECHOK is on and ECHOKE is off. */
                        if (L_ECHOK(tty))
-                               echo_char_raw('\n', tty);
+                               echo_char_raw('\n', ldata);
                        return;
                }
                kill_type = KILL;
@@ -901,14 +940,14 @@ static void eraser(unsigned char c, struct tty_struct *tty)
 
        seen_alnums = 0;
        /* FIXME: Locking ?? */
-       while (tty->read_head != tty->canon_head) {
-               head = tty->read_head;
+       while (ldata->read_head != ldata->canon_head) {
+               head = ldata->read_head;
 
                /* erase a single possibly multibyte character */
                do {
                        head = (head - 1) & (N_TTY_BUF_SIZE-1);
-                       c = tty->read_buf[head];
-               } while (is_continuation(c, tty) && head != tty->canon_head);
+                       c = ldata->read_buf[head];
+               } while (is_continuation(c, tty) && head != ldata->canon_head);
 
                /* do not partially erase */
                if (is_continuation(c, tty))
@@ -921,30 +960,31 @@ static void eraser(unsigned char c, struct tty_struct *tty)
                        else if (seen_alnums)
                                break;
                }
-               cnt = (tty->read_head - head) & (N_TTY_BUF_SIZE-1);
-               spin_lock_irqsave(&tty->read_lock, flags);
-               tty->read_head = head;
-               tty->read_cnt -= cnt;
-               spin_unlock_irqrestore(&tty->read_lock, flags);
+               cnt = (ldata->read_head - head) & (N_TTY_BUF_SIZE-1);
+               spin_lock_irqsave(&ldata->read_lock, flags);
+               ldata->read_head = head;
+               ldata->read_cnt -= cnt;
+               spin_unlock_irqrestore(&ldata->read_lock, flags);
                if (L_ECHO(tty)) {
                        if (L_ECHOPRT(tty)) {
-                               if (!tty->erasing) {
-                                       echo_char_raw('\\', tty);
-                                       tty->erasing = 1;
+                               if (!ldata->erasing) {
+                                       echo_char_raw('\\', ldata);
+                                       ldata->erasing = 1;
                                }
                                /* if cnt > 1, output a multi-byte character */
                                echo_char(c, tty);
                                while (--cnt > 0) {
                                        head = (head+1) & (N_TTY_BUF_SIZE-1);
-                                       echo_char_raw(tty->read_buf[head], tty);
-                                       echo_move_back_col(tty);
+                                       echo_char_raw(ldata->read_buf[head],
+                                                       ldata);
+                                       echo_move_back_col(ldata);
                                }
                        } else if (kill_type == ERASE && !L_ECHOE(tty)) {
                                echo_char(ERASE_CHAR(tty), tty);
                        } else if (c == '\t') {
                                unsigned int num_chars = 0;
                                int after_tab = 0;
-                               unsigned long tail = tty->read_head;
+                               unsigned long tail = ldata->read_head;
 
                                /*
                                 * Count the columns used for characters
@@ -953,9 +993,9 @@ static void eraser(unsigned char c, struct tty_struct *tty)
                                 * This info is used to go back the correct
                                 * number of columns.
                                 */
-                               while (tail != tty->canon_head) {
+                               while (tail != ldata->canon_head) {
                                        tail = (tail-1) & (N_TTY_BUF_SIZE-1);
-                                       c = tty->read_buf[tail];
+                                       c = ldata->read_buf[tail];
                                        if (c == '\t') {
                                                after_tab = 1;
                                                break;
@@ -966,25 +1006,25 @@ static void eraser(unsigned char c, struct tty_struct *tty)
                                                num_chars++;
                                        }
                                }
-                               echo_erase_tab(num_chars, after_tab, tty);
+                               echo_erase_tab(num_chars, after_tab, ldata);
                        } else {
                                if (iscntrl(c) && L_ECHOCTL(tty)) {
-                                       echo_char_raw('\b', tty);
-                                       echo_char_raw(' ', tty);
-                                       echo_char_raw('\b', tty);
+                                       echo_char_raw('\b', ldata);
+                                       echo_char_raw(' ', ldata);
+                                       echo_char_raw('\b', ldata);
                                }
                                if (!iscntrl(c) || L_ECHOCTL(tty)) {
-                                       echo_char_raw('\b', tty);
-                                       echo_char_raw(' ', tty);
-                                       echo_char_raw('\b', tty);
+                                       echo_char_raw('\b', ldata);
+                                       echo_char_raw(' ', ldata);
+                                       echo_char_raw('\b', ldata);
                                }
                        }
                }
                if (kill_type == ERASE)
                        break;
        }
-       if (tty->read_head == tty->canon_head && L_ECHO(tty))
-               finish_erasing(tty);
+       if (ldata->read_head == ldata->canon_head && L_ECHO(tty))
+               finish_erasing(ldata);
 }
 
 /**
@@ -1023,6 +1063,8 @@ static inline void isig(int sig, struct tty_struct *tty, int flush)
 
 static inline void n_tty_receive_break(struct tty_struct *tty)
 {
+       struct n_tty_data *ldata = tty->disc_data;
+
        if (I_IGNBRK(tty))
                return;
        if (I_BRKINT(tty)) {
@@ -1030,10 +1072,10 @@ static inline void n_tty_receive_break(struct tty_struct *tty)
                return;
        }
        if (I_PARMRK(tty)) {
-               put_tty_queue('\377', tty);
-               put_tty_queue('\0', tty);
+               put_tty_queue('\377', ldata);
+               put_tty_queue('\0', ldata);
        }
-       put_tty_queue('\0', tty);
+       put_tty_queue('\0', ldata);
        wake_up_interruptible(&tty->read_wait);
 }
 
@@ -1052,16 +1094,17 @@ static inline void n_tty_receive_break(struct tty_struct *tty)
 
 static inline void n_tty_receive_overrun(struct tty_struct *tty)
 {
+       struct n_tty_data *ldata = tty->disc_data;
        char buf[64];
 
-       tty->num_overrun++;
-       if (time_before(tty->overrun_time, jiffies - HZ) ||
-                       time_after(tty->overrun_time, jiffies)) {
+       ldata->num_overrun++;
+       if (time_after(jiffies, ldata->overrun_time + HZ) ||
+                       time_after(ldata->overrun_time, jiffies)) {
                printk(KERN_WARNING "%s: %d input overrun(s)\n",
                        tty_name(tty, buf),
-                       tty->num_overrun);
-               tty->overrun_time = jiffies;
-               tty->num_overrun = 0;
+                       ldata->num_overrun);
+               ldata->overrun_time = jiffies;
+               ldata->num_overrun = 0;
        }
 }
 
@@ -1076,16 +1119,18 @@ static inline void n_tty_receive_overrun(struct tty_struct *tty)
 static inline void n_tty_receive_parity_error(struct tty_struct *tty,
                                              unsigned char c)
 {
+       struct n_tty_data *ldata = tty->disc_data;
+
        if (I_IGNPAR(tty))
                return;
        if (I_PARMRK(tty)) {
-               put_tty_queue('\377', tty);
-               put_tty_queue('\0', tty);
-               put_tty_queue(c, tty);
+               put_tty_queue('\377', ldata);
+               put_tty_queue('\0', ldata);
+               put_tty_queue(c, ldata);
        } else  if (I_INPCK(tty))
-               put_tty_queue('\0', tty);
+               put_tty_queue('\0', ldata);
        else
-               put_tty_queue(c, tty);
+               put_tty_queue(c, ldata);
        wake_up_interruptible(&tty->read_wait);
 }
 
@@ -1101,11 +1146,12 @@ static inline void n_tty_receive_parity_error(struct tty_struct *tty,
 
 static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
 {
+       struct n_tty_data *ldata = tty->disc_data;
        unsigned long flags;
        int parmrk;
 
-       if (tty->raw) {
-               put_tty_queue(c, tty);
+       if (ldata->raw) {
+               put_tty_queue(c, ldata);
                return;
        }
 
@@ -1115,7 +1161,7 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
                c = tolower(c);
 
        if (L_EXTPROC(tty)) {
-               put_tty_queue(c, tty);
+               put_tty_queue(c, ldata);
                return;
        }
 
@@ -1143,26 +1189,26 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
         * handle specially, do shortcut processing to speed things
         * up.
         */
-       if (!test_bit(c, tty->process_char_map) || tty->lnext) {
-               tty->lnext = 0;
+       if (!test_bit(c, ldata->process_char_map) || ldata->lnext) {
+               ldata->lnext = 0;
                parmrk = (c == (unsigned char) '\377' && I_PARMRK(tty)) ? 1 : 0;
-               if (tty->read_cnt >= (N_TTY_BUF_SIZE - parmrk - 1)) {
+               if (ldata->read_cnt >= (N_TTY_BUF_SIZE - parmrk - 1)) {
                        /* beep if no space */
                        if (L_ECHO(tty))
                                process_output('\a', tty);
                        return;
                }
                if (L_ECHO(tty)) {
-                       finish_erasing(tty);
+                       finish_erasing(ldata);
                        /* Record the column of first canon char. */
-                       if (tty->canon_head == tty->read_head)
-                               echo_set_canon_col(tty);
+                       if (ldata->canon_head == ldata->read_head)
+                               echo_set_canon_col(ldata);
                        echo_char(c, tty);
                        process_echoes(tty);
                }
                if (parmrk)
-                       put_tty_queue(c, tty);
-               put_tty_queue(c, tty);
+                       put_tty_queue(c, ldata);
+               put_tty_queue(c, ldata);
                return;
        }
 
@@ -1218,7 +1264,7 @@ send_signal:
        } else if (c == '\n' && I_INLCR(tty))
                c = '\r';
 
-       if (tty->icanon) {
+       if (ldata->icanon) {
                if (c == ERASE_CHAR(tty) || c == KILL_CHAR(tty) ||
                    (c == WERASE_CHAR(tty) && L_IEXTEN(tty))) {
                        eraser(c, tty);
@@ -1226,12 +1272,12 @@ send_signal:
                        return;
                }
                if (c == LNEXT_CHAR(tty) && L_IEXTEN(tty)) {
-                       tty->lnext = 1;
+                       ldata->lnext = 1;
                        if (L_ECHO(tty)) {
-                               finish_erasing(tty);
+                               finish_erasing(ldata);
                                if (L_ECHOCTL(tty)) {
-                                       echo_char_raw('^', tty);
-                                       echo_char_raw('\b', tty);
+                                       echo_char_raw('^', ldata);
+                                       echo_char_raw('\b', ldata);
                                        process_echoes(tty);
                                }
                        }
@@ -1239,34 +1285,34 @@ send_signal:
                }
                if (c == REPRINT_CHAR(tty) && L_ECHO(tty) &&
                    L_IEXTEN(tty)) {
-                       unsigned long tail = tty->canon_head;
+                       unsigned long tail = ldata->canon_head;
 
-                       finish_erasing(tty);
+                       finish_erasing(ldata);
                        echo_char(c, tty);
-                       echo_char_raw('\n', tty);
-                       while (tail != tty->read_head) {
-                               echo_char(tty->read_buf[tail], tty);
+                       echo_char_raw('\n', ldata);
+                       while (tail != ldata->read_head) {
+                               echo_char(ldata->read_buf[tail], tty);
                                tail = (tail+1) & (N_TTY_BUF_SIZE-1);
                        }
                        process_echoes(tty);
                        return;
                }
                if (c == '\n') {
-                       if (tty->read_cnt >= N_TTY_BUF_SIZE) {
+                       if (ldata->read_cnt >= N_TTY_BUF_SIZE) {
                                if (L_ECHO(tty))
                                        process_output('\a', tty);
                                return;
                        }
                        if (L_ECHO(tty) || L_ECHONL(tty)) {
-                               echo_char_raw('\n', tty);
+                               echo_char_raw('\n', ldata);
                                process_echoes(tty);
                        }
                        goto handle_newline;
                }
                if (c == EOF_CHAR(tty)) {
-                       if (tty->read_cnt >= N_TTY_BUF_SIZE)
+                       if (ldata->read_cnt >= N_TTY_BUF_SIZE)
                                return;
-                       if (tty->canon_head != tty->read_head)
+                       if (ldata->canon_head != ldata->read_head)
                                set_bit(TTY_PUSH, &tty->flags);
                        c = __DISABLED_CHAR;
                        goto handle_newline;
@@ -1275,7 +1321,7 @@ send_signal:
                    (c == EOL2_CHAR(tty) && L_IEXTEN(tty))) {
                        parmrk = (c == (unsigned char) '\377' && I_PARMRK(tty))
                                 ? 1 : 0;
-                       if (tty->read_cnt >= (N_TTY_BUF_SIZE - parmrk)) {
+                       if (ldata->read_cnt >= (N_TTY_BUF_SIZE - parmrk)) {
                                if (L_ECHO(tty))
                                        process_output('\a', tty);
                                return;
@@ -1285,8 +1331,8 @@ send_signal:
                         */
                        if (L_ECHO(tty)) {
                                /* Record the column of first canon char. */
-                               if (tty->canon_head == tty->read_head)
-                                       echo_set_canon_col(tty);
+                               if (ldata->canon_head == ldata->read_head)
+                                       echo_set_canon_col(ldata);
                                echo_char(c, tty);
                                process_echoes(tty);
                        }
@@ -1295,15 +1341,15 @@ send_signal:
                         * EOL_CHAR and EOL2_CHAR?
                         */
                        if (parmrk)
-                               put_tty_queue(c, tty);
+                               put_tty_queue(c, ldata);
 
 handle_newline:
-                       spin_lock_irqsave(&tty->read_lock, flags);
-                       set_bit(tty->read_head, tty->read_flags);
-                       put_tty_queue_nolock(c, tty);
-                       tty->canon_head = tty->read_head;
-                       tty->canon_data++;
-                       spin_unlock_irqrestore(&tty->read_lock, flags);
+                       spin_lock_irqsave(&ldata->read_lock, flags);
+                       set_bit(ldata->read_head, ldata->read_flags);
+                       put_tty_queue_nolock(c, ldata);
+                       ldata->canon_head = ldata->read_head;
+                       ldata->canon_data++;
+                       spin_unlock_irqrestore(&ldata->read_lock, flags);
                        kill_fasync(&tty->fasync, SIGIO, POLL_IN);
                        if (waitqueue_active(&tty->read_wait))
                                wake_up_interruptible(&tty->read_wait);
@@ -1312,29 +1358,29 @@ handle_newline:
        }
 
        parmrk = (c == (unsigned char) '\377' && I_PARMRK(tty)) ? 1 : 0;
-       if (tty->read_cnt >= (N_TTY_BUF_SIZE - parmrk - 1)) {
+       if (ldata->read_cnt >= (N_TTY_BUF_SIZE - parmrk - 1)) {
                /* beep if no space */
                if (L_ECHO(tty))
                        process_output('\a', tty);
                return;
        }
        if (L_ECHO(tty)) {
-               finish_erasing(tty);
+               finish_erasing(ldata);
                if (c == '\n')
-                       echo_char_raw('\n', tty);
+                       echo_char_raw('\n', ldata);
                else {
                        /* Record the column of first canon char. */
-                       if (tty->canon_head == tty->read_head)
-                               echo_set_canon_col(tty);
+                       if (ldata->canon_head == ldata->read_head)
+                               echo_set_canon_col(ldata);
                        echo_char(c, tty);
                }
                process_echoes(tty);
        }
 
        if (parmrk)
-               put_tty_queue(c, tty);
+               put_tty_queue(c, ldata);
 
-       put_tty_queue(c, tty);
+       put_tty_queue(c, ldata);
 }
 
 
@@ -1369,33 +1415,31 @@ static void n_tty_write_wakeup(struct tty_struct *tty)
 static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
                              char *fp, int count)
 {
+       struct n_tty_data *ldata = tty->disc_data;
        const unsigned char *p;
        char *f, flags = TTY_NORMAL;
        int     i;
        char    buf[64];
        unsigned long cpuflags;
 
-       if (!tty->read_buf)
-               return;
-
-       if (tty->real_raw) {
-               spin_lock_irqsave(&tty->read_lock, cpuflags);
-               i = min(N_TTY_BUF_SIZE - tty->read_cnt,
-                       N_TTY_BUF_SIZE - tty->read_head);
+       if (ldata->real_raw) {
+               spin_lock_irqsave(&ldata->read_lock, cpuflags);
+               i = min(N_TTY_BUF_SIZE - ldata->read_cnt,
+                       N_TTY_BUF_SIZE - ldata->read_head);
                i = min(count, i);
-               memcpy(tty->read_buf + tty->read_head, cp, i);
-               tty->read_head = (tty->read_head + i) & (N_TTY_BUF_SIZE-1);
-               tty->read_cnt += i;
+               memcpy(ldata->read_buf + ldata->read_head, cp, i);
+               ldata->read_head = (ldata->read_head + i) & (N_TTY_BUF_SIZE-1);
+               ldata->read_cnt += i;
                cp += i;
                count -= i;
 
-               i = min(N_TTY_BUF_SIZE - tty->read_cnt,
-                       N_TTY_BUF_SIZE - tty->read_head);
+               i = min(N_TTY_BUF_SIZE - ldata->read_cnt,
+                       N_TTY_BUF_SIZE - ldata->read_head);
                i = min(count, i);
-               memcpy(tty->read_buf + tty->read_head, cp, i);
-               tty->read_head = (tty->read_head + i) & (N_TTY_BUF_SIZE-1);
-               tty->read_cnt += i;
-               spin_unlock_irqrestore(&tty->read_lock, cpuflags);
+               memcpy(ldata->read_buf + ldata->read_head, cp, i);
+               ldata->read_head = (ldata->read_head + i) & (N_TTY_BUF_SIZE-1);
+               ldata->read_cnt += i;
+               spin_unlock_irqrestore(&ldata->read_lock, cpuflags);
        } else {
                for (i = count, p = cp, f = fp; i; i--, p++) {
                        if (f)
@@ -1426,7 +1470,7 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
 
        n_tty_set_room(tty);
 
-       if ((!tty->icanon && (tty->read_cnt >= tty->minimum_to_wake)) ||
+       if ((!ldata->icanon && (ldata->read_cnt >= tty->minimum_to_wake)) ||
                L_EXTPROC(tty)) {
                kill_fasync(&tty->fasync, SIGIO, POLL_IN);
                if (waitqueue_active(&tty->read_wait))
@@ -1470,25 +1514,25 @@ int is_ignored(int sig)
 
 static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
 {
+       struct n_tty_data *ldata = tty->disc_data;
        int canon_change = 1;
-       BUG_ON(!tty);
 
        if (old)
                canon_change = (old->c_lflag ^ tty->termios.c_lflag) & ICANON;
        if (canon_change) {
-               memset(&tty->read_flags, 0, sizeof tty->read_flags);
-               tty->canon_head = tty->read_tail;
-               tty->canon_data = 0;
-               tty->erasing = 0;
+               bitmap_zero(ldata->read_flags, N_TTY_BUF_SIZE);
+               ldata->canon_head = ldata->read_tail;
+               ldata->canon_data = 0;
+               ldata->erasing = 0;
        }
 
-       if (canon_change && !L_ICANON(tty) && tty->read_cnt)
+       if (canon_change && !L_ICANON(tty) && ldata->read_cnt)
                wake_up_interruptible(&tty->read_wait);
 
-       tty->icanon = (L_ICANON(tty) != 0);
+       ldata->icanon = (L_ICANON(tty) != 0);
        if (test_bit(TTY_HW_COOK_IN, &tty->flags)) {
-               tty->raw = 1;
-               tty->real_raw = 1;
+               ldata->raw = 1;
+               ldata->real_raw = 1;
                n_tty_set_room(tty);
                return;
        }
@@ -1496,51 +1540,51 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
            I_ICRNL(tty) || I_INLCR(tty) || L_ICANON(tty) ||
            I_IXON(tty) || L_ISIG(tty) || L_ECHO(tty) ||
            I_PARMRK(tty)) {
-               memset(tty->process_char_map, 0, 256/8);
+               bitmap_zero(ldata->process_char_map, 256);
 
                if (I_IGNCR(tty) || I_ICRNL(tty))
-                       set_bit('\r', tty->process_char_map);
+                       set_bit('\r', ldata->process_char_map);
                if (I_INLCR(tty))
-                       set_bit('\n', tty->process_char_map);
+                       set_bit('\n', ldata->process_char_map);
 
                if (L_ICANON(tty)) {
-                       set_bit(ERASE_CHAR(tty), tty->process_char_map);
-                       set_bit(KILL_CHAR(tty), tty->process_char_map);
-                       set_bit(EOF_CHAR(tty), tty->process_char_map);
-                       set_bit('\n', tty->process_char_map);
-                       set_bit(EOL_CHAR(tty), tty->process_char_map);
+                       set_bit(ERASE_CHAR(tty), ldata->process_char_map);
+                       set_bit(KILL_CHAR(tty), ldata->process_char_map);
+                       set_bit(EOF_CHAR(tty), ldata->process_char_map);
+                       set_bit('\n', ldata->process_char_map);
+                       set_bit(EOL_CHAR(tty), ldata->process_char_map);
                        if (L_IEXTEN(tty)) {
                                set_bit(WERASE_CHAR(tty),
-                                       tty->process_char_map);
+                                       ldata->process_char_map);
                                set_bit(LNEXT_CHAR(tty),
-                                       tty->process_char_map);
+                                       ldata->process_char_map);
                                set_bit(EOL2_CHAR(tty),
-                                       tty->process_char_map);
+                                       ldata->process_char_map);
                                if (L_ECHO(tty))
                                        set_bit(REPRINT_CHAR(tty),
-                                               tty->process_char_map);
+                                               ldata->process_char_map);
                        }
                }
                if (I_IXON(tty)) {
-                       set_bit(START_CHAR(tty), tty->process_char_map);
-                       set_bit(STOP_CHAR(tty), tty->process_char_map);
+                       set_bit(START_CHAR(tty), ldata->process_char_map);
+                       set_bit(STOP_CHAR(tty), ldata->process_char_map);
                }
                if (L_ISIG(tty)) {
-                       set_bit(INTR_CHAR(tty), tty->process_char_map);
-                       set_bit(QUIT_CHAR(tty), tty->process_char_map);
-                       set_bit(SUSP_CHAR(tty), tty->process_char_map);
+                       set_bit(INTR_CHAR(tty), ldata->process_char_map);
+                       set_bit(QUIT_CHAR(tty), ldata->process_char_map);
+                       set_bit(SUSP_CHAR(tty), ldata->process_char_map);
                }
-               clear_bit(__DISABLED_CHAR, tty->process_char_map);
-               tty->raw = 0;
-               tty->real_raw = 0;
+               clear_bit(__DISABLED_CHAR, ldata->process_char_map);
+               ldata->raw = 0;
+               ldata->real_raw = 0;
        } else {
-               tty->raw = 1;
+               ldata->raw = 1;
                if ((I_IGNBRK(tty) || (!I_BRKINT(tty) && !I_PARMRK(tty))) &&
                    (I_IGNPAR(tty) || !I_INPCK(tty)) &&
                    (tty->driver->flags & TTY_DRIVER_REAL_RAW))
-                       tty->real_raw = 1;
+                       ldata->real_raw = 1;
                else
-                       tty->real_raw = 0;
+                       ldata->real_raw = 0;
        }
        n_tty_set_room(tty);
        /* The termios change make the tty ready for I/O */
@@ -1560,15 +1604,13 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
 
 static void n_tty_close(struct tty_struct *tty)
 {
+       struct n_tty_data *ldata = tty->disc_data;
+
        n_tty_flush_buffer(tty);
-       if (tty->read_buf) {
-               kfree(tty->read_buf);
-               tty->read_buf = NULL;
-       }
-       if (tty->echo_buf) {
-               kfree(tty->echo_buf);
-               tty->echo_buf = NULL;
-       }
+       kfree(ldata->read_buf);
+       kfree(ldata->echo_buf);
+       kfree(ldata);
+       tty->disc_data = NULL;
 }
 
 /**
@@ -1583,37 +1625,50 @@ static void n_tty_close(struct tty_struct *tty)
 
 static int n_tty_open(struct tty_struct *tty)
 {
-       if (!tty)
-               return -EINVAL;
+       struct n_tty_data *ldata;
+
+       ldata = kzalloc(sizeof(*ldata), GFP_KERNEL);
+       if (!ldata)
+               goto err;
+
+       ldata->overrun_time = jiffies;
+       mutex_init(&ldata->atomic_read_lock);
+       mutex_init(&ldata->output_lock);
+       mutex_init(&ldata->echo_lock);
+       spin_lock_init(&ldata->read_lock);
 
        /* These are ugly. Currently a malloc failure here can panic */
-       if (!tty->read_buf) {
-               tty->read_buf = kzalloc(N_TTY_BUF_SIZE, GFP_KERNEL);
-               if (!tty->read_buf)
-                       return -ENOMEM;
-       }
-       if (!tty->echo_buf) {
-               tty->echo_buf = kzalloc(N_TTY_BUF_SIZE, GFP_KERNEL);
+       ldata->read_buf = kzalloc(N_TTY_BUF_SIZE, GFP_KERNEL);
+       ldata->echo_buf = kzalloc(N_TTY_BUF_SIZE, GFP_KERNEL);
+       if (!ldata->read_buf || !ldata->echo_buf)
+               goto err_free_bufs;
 
-               if (!tty->echo_buf)
-                       return -ENOMEM;
-       }
+       tty->disc_data = ldata;
        reset_buffer_flags(tty);
        tty_unthrottle(tty);
-       tty->column = 0;
+       ldata->column = 0;
        n_tty_set_termios(tty, NULL);
        tty->minimum_to_wake = 1;
        tty->closing = 0;
+
        return 0;
+err_free_bufs:
+       kfree(ldata->read_buf);
+       kfree(ldata->echo_buf);
+       kfree(ldata);
+err:
+       return -ENOMEM;
 }
 
 static inline int input_available_p(struct tty_struct *tty, int amt)
 {
+       struct n_tty_data *ldata = tty->disc_data;
+
        tty_flush_to_ldisc(tty);
-       if (tty->icanon && !L_EXTPROC(tty)) {
-               if (tty->canon_data)
+       if (ldata->icanon && !L_EXTPROC(tty)) {
+               if (ldata->canon_data)
                        return 1;
-       } else if (tty->read_cnt >= (amt ? amt : 1))
+       } else if (ldata->read_cnt >= (amt ? amt : 1))
                return 1;
 
        return 0;
@@ -1632,7 +1687,7 @@ static inline int input_available_p(struct tty_struct *tty, int amt)
  *     buffer, and once to drain the space from the (physical) beginning of
  *     the buffer to head pointer.
  *
- *     Called under the tty->atomic_read_lock sem
+ *     Called under the ldata->atomic_read_lock sem
  *
  */
 
@@ -1641,29 +1696,31 @@ static int copy_from_read_buf(struct tty_struct *tty,
                                      size_t *nr)
 
 {
+       struct n_tty_data *ldata = tty->disc_data;
        int retval;
        size_t n;
        unsigned long flags;
        bool is_eof;
 
        retval = 0;
-       spin_lock_irqsave(&tty->read_lock, flags);
-       n = min(tty->read_cnt, N_TTY_BUF_SIZE - tty->read_tail);
+       spin_lock_irqsave(&ldata->read_lock, flags);
+       n = min(ldata->read_cnt, N_TTY_BUF_SIZE - ldata->read_tail);
        n = min(*nr, n);
-       spin_unlock_irqrestore(&tty->read_lock, flags);
+       spin_unlock_irqrestore(&ldata->read_lock, flags);
        if (n) {
-               retval = copy_to_user(*b, &tty->read_buf[tty->read_tail], n);
+               retval = copy_to_user(*b, &ldata->read_buf[ldata->read_tail], n);
                n -= retval;
                is_eof = n == 1 &&
-                       tty->read_buf[tty->read_tail] == EOF_CHAR(tty);
-               tty_audit_add_data(tty, &tty->read_buf[tty->read_tail], n);
-               spin_lock_irqsave(&tty->read_lock, flags);
-               tty->read_tail = (tty->read_tail + n) & (N_TTY_BUF_SIZE-1);
-               tty->read_cnt -= n;
+                       ldata->read_buf[ldata->read_tail] == EOF_CHAR(tty);
+               tty_audit_add_data(tty, &ldata->read_buf[ldata->read_tail], n,
+                               ldata->icanon);
+               spin_lock_irqsave(&ldata->read_lock, flags);
+               ldata->read_tail = (ldata->read_tail + n) & (N_TTY_BUF_SIZE-1);
+               ldata->read_cnt -= n;
                /* Turn single EOF into zero-length read */
-               if (L_EXTPROC(tty) && tty->icanon && is_eof && !tty->read_cnt)
+               if (L_EXTPROC(tty) && ldata->icanon && is_eof && !ldata->read_cnt)
                        n = 0;
-               spin_unlock_irqrestore(&tty->read_lock, flags);
+               spin_unlock_irqrestore(&ldata->read_lock, flags);
                *b += n;
                *nr -= n;
        }
@@ -1730,6 +1787,7 @@ static int job_control(struct tty_struct *tty, struct file *file)
 static ssize_t n_tty_read(struct tty_struct *tty, struct file *file,
                         unsigned char __user *buf, size_t nr)
 {
+       struct n_tty_data *ldata = tty->disc_data;
        unsigned char __user *b = buf;
        DECLARE_WAITQUEUE(wait, current);
        int c;
@@ -1741,17 +1799,13 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file,
        int packet;
 
 do_it_again:
-
-       if (WARN_ON(!tty->read_buf))
-               return -EAGAIN;
-
        c = job_control(tty, file);
        if (c < 0)
                return c;
 
        minimum = time = 0;
        timeout = MAX_SCHEDULE_TIMEOUT;
-       if (!tty->icanon) {
+       if (!ldata->icanon) {
                time = (HZ / 10) * TIME_CHAR(tty);
                minimum = MIN_CHAR(tty);
                if (minimum) {
@@ -1774,10 +1828,10 @@ do_it_again:
         *      Internal serialization of reads.
         */
        if (file->f_flags & O_NONBLOCK) {
-               if (!mutex_trylock(&tty->atomic_read_lock))
+               if (!mutex_trylock(&ldata->atomic_read_lock))
                        return -EAGAIN;
        } else {
-               if (mutex_lock_interruptible(&tty->atomic_read_lock))
+               if (mutex_lock_interruptible(&ldata->atomic_read_lock))
                        return -ERESTARTSYS;
        }
        packet = tty->packet;
@@ -1830,7 +1884,6 @@ do_it_again:
                        /* FIXME: does n_tty_set_room need locking ? */
                        n_tty_set_room(tty);
                        timeout = schedule_timeout(timeout);
-                       BUG_ON(!tty->read_buf);
                        continue;
                }
                __set_current_state(TASK_RUNNING);
@@ -1845,45 +1898,45 @@ do_it_again:
                        nr--;
                }
 
-               if (tty->icanon && !L_EXTPROC(tty)) {
+               if (ldata->icanon && !L_EXTPROC(tty)) {
                        /* N.B. avoid overrun if nr == 0 */
-                       spin_lock_irqsave(&tty->read_lock, flags);
-                       while (nr && tty->read_cnt) {
+                       spin_lock_irqsave(&ldata->read_lock, flags);
+                       while (nr && ldata->read_cnt) {
                                int eol;
 
-                               eol = test_and_clear_bit(tty->read_tail,
-                                               tty->read_flags);
-                               c = tty->read_buf[tty->read_tail];
-                               tty->read_tail = ((tty->read_tail+1) &
+                               eol = test_and_clear_bit(ldata->read_tail,
+                                               ldata->read_flags);
+                               c = ldata->read_buf[ldata->read_tail];
+                               ldata->read_tail = ((ldata->read_tail+1) &
                                                  (N_TTY_BUF_SIZE-1));
-                               tty->read_cnt--;
+                               ldata->read_cnt--;
                                if (eol) {
                                        /* this test should be redundant:
                                         * we shouldn't be reading data if
                                         * canon_data is 0
                                         */
-                                       if (--tty->canon_data < 0)
-                                               tty->canon_data = 0;
+                                       if (--ldata->canon_data < 0)
+                                               ldata->canon_data = 0;
                                }
-                               spin_unlock_irqrestore(&tty->read_lock, flags);
+                               spin_unlock_irqrestore(&ldata->read_lock, flags);
 
                                if (!eol || (c != __DISABLED_CHAR)) {
                                        if (tty_put_user(tty, c, b++)) {
                                                retval = -EFAULT;
                                                b--;
-                                               spin_lock_irqsave(&tty->read_lock, flags);
+                                               spin_lock_irqsave(&ldata->read_lock, flags);
                                                break;
                                        }
                                        nr--;
                                }
                                if (eol) {
                                        tty_audit_push(tty);
-                                       spin_lock_irqsave(&tty->read_lock, flags);
+                                       spin_lock_irqsave(&ldata->read_lock, flags);
                                        break;
                                }
-                               spin_lock_irqsave(&tty->read_lock, flags);
+                               spin_lock_irqsave(&ldata->read_lock, flags);
                        }
-                       spin_unlock_irqrestore(&tty->read_lock, flags);
+                       spin_unlock_irqrestore(&ldata->read_lock, flags);
                        if (retval)
                                break;
                } else {
@@ -1915,7 +1968,7 @@ do_it_again:
                if (time)
                        timeout = time;
        }
-       mutex_unlock(&tty->atomic_read_lock);
+       mutex_unlock(&ldata->atomic_read_lock);
        remove_wait_queue(&tty->read_wait, &wait);
 
        if (!waitqueue_active(&tty->read_wait))
@@ -2076,19 +2129,19 @@ static unsigned int n_tty_poll(struct tty_struct *tty, struct file *file,
        return mask;
 }
 
-static unsigned long inq_canon(struct tty_struct *tty)
+static unsigned long inq_canon(struct n_tty_data *ldata)
 {
        int nr, head, tail;
 
-       if (!tty->canon_data)
+       if (!ldata->canon_data)
                return 0;
-       head = tty->canon_head;
-       tail = tty->read_tail;
+       head = ldata->canon_head;
+       tail = ldata->read_tail;
        nr = (head - tail) & (N_TTY_BUF_SIZE-1);
        /* Skip EOF-chars.. */
        while (head != tail) {
-               if (test_bit(tail, tty->read_flags) &&
-                   tty->read_buf[tail] == __DISABLED_CHAR)
+               if (test_bit(tail, ldata->read_flags) &&
+                   ldata->read_buf[tail] == __DISABLED_CHAR)
                        nr--;
                tail = (tail+1) & (N_TTY_BUF_SIZE-1);
        }
@@ -2098,6 +2151,7 @@ static unsigned long inq_canon(struct tty_struct *tty)
 static int n_tty_ioctl(struct tty_struct *tty, struct file *file,
                       unsigned int cmd, unsigned long arg)
 {
+       struct n_tty_data *ldata = tty->disc_data;
        int retval;
 
        switch (cmd) {
@@ -2105,9 +2159,9 @@ static int n_tty_ioctl(struct tty_struct *tty, struct file *file,
                return put_user(tty_chars_in_buffer(tty), (int __user *) arg);
        case TIOCINQ:
                /* FIXME: Locking */
-               retval = tty->read_cnt;
+               retval = ldata->read_cnt;
                if (L_ICANON(tty))
-                       retval = inq_canon(tty);
+                       retval = inq_canon(ldata);
                return put_user(retval, (unsigned int __user *) arg);
        default:
                return n_tty_ioctl_helper(tty, file, cmd, arg);
index a82b39939a9cab4fc02a6d6d0be13607284d68ce..4219f040adb8ff55f35109accc5eea5e55ef2366 100644 (file)
@@ -4,9 +4,6 @@
  *  Added support for a Unix98-style ptmx device.
  *    -- C. Scott Ananian <cananian@alumni.princeton.edu>, 14-Jan-1998
  *
- *  When reading this code see also fs/devpts. In particular note that the
- *  driver_data field is used by the devpts side as a binding to the devpts
- *  inode.
  */
 
 #include <linux/module.h>
@@ -59,7 +56,7 @@ static void pty_close(struct tty_struct *tty, struct file *filp)
 #ifdef CONFIG_UNIX98_PTYS
                if (tty->driver == ptm_driver) {
                        mutex_lock(&devpts_mutex);
-                       devpts_pty_kill(tty->link);
+                       devpts_pty_kill(tty->link->driver_data);
                        mutex_unlock(&devpts_mutex);
                }
 #endif
@@ -96,7 +93,7 @@ static void pty_unthrottle(struct tty_struct *tty)
 
 static int pty_space(struct tty_struct *to)
 {
-       int n = 8192 - to->buf.memory_used;
+       int n = 8192 - to->port->buf.memory_used;
        if (n < 0)
                return 0;
        return n;
@@ -348,6 +345,7 @@ static int pty_common_install(struct tty_driver *driver, struct tty_struct *tty,
        tty_port_init(ports[1]);
        o_tty->port = ports[0];
        tty->port = ports[1];
+       o_tty->port->itty = o_tty;
 
        tty_driver_kref_get(driver);
        tty->count++;
@@ -366,8 +364,15 @@ err:
        return retval;
 }
 
+/* this is called once with whichever end is closed last */
+static void pty_unix98_shutdown(struct tty_struct *tty)
+{
+       devpts_kill_index(tty->driver_data, tty->index);
+}
+
 static void pty_cleanup(struct tty_struct *tty)
 {
+       tty->port->itty = NULL;
        kfree(tty->port);
 }
 
@@ -547,7 +552,7 @@ static struct tty_struct *pts_unix98_lookup(struct tty_driver *driver,
        struct tty_struct *tty;
 
        mutex_lock(&devpts_mutex);
-       tty = devpts_get_tty(pts_inode, idx);
+       tty = devpts_get_priv(pts_inode);
        mutex_unlock(&devpts_mutex);
        /* Master must be open before slave */
        if (!tty)
@@ -581,6 +586,7 @@ static const struct tty_operations ptm_unix98_ops = {
        .set_termios = pty_set_termios,
        .ioctl = pty_unix98_ioctl,
        .resize = pty_resize,
+       .shutdown = pty_unix98_shutdown,
        .cleanup = pty_cleanup
 };
 
@@ -596,6 +602,7 @@ static const struct tty_operations pty_unix98_ops = {
        .chars_in_buffer = pty_chars_in_buffer,
        .unthrottle = pty_unthrottle,
        .set_termios = pty_set_termios,
+       .shutdown = pty_unix98_shutdown,
        .cleanup = pty_cleanup,
 };
 
@@ -614,6 +621,7 @@ static const struct tty_operations pty_unix98_ops = {
 static int ptmx_open(struct inode *inode, struct file *filp)
 {
        struct tty_struct *tty;
+       struct inode *slave_inode;
        int retval;
        int index;
 
@@ -650,15 +658,21 @@ static int ptmx_open(struct inode *inode, struct file *filp)
 
        tty_add_file(tty, filp);
 
-       retval = devpts_pty_new(inode, tty->link);
-       if (retval)
+       slave_inode = devpts_pty_new(inode,
+                       MKDEV(UNIX98_PTY_SLAVE_MAJOR, index), index,
+                       tty->link);
+       if (IS_ERR(slave_inode)) {
+               retval = PTR_ERR(slave_inode);
                goto err_release;
+       }
 
        retval = ptm_driver->ops->open(tty, filp);
        if (retval)
                goto err_release;
 
        tty_unlock(tty);
+       tty->driver_data = inode;
+       tty->link->driver_data = slave_inode;
        return 0;
 err_release:
        tty_unlock(tty);
index 3ba4234592bc8a7285b2d488ce9b0db010e2e018..5ccbd90540cfdf4bef3be26c15d2202393ced213 100644 (file)
@@ -2349,16 +2349,14 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
                        serial_port_out(port, UART_EFR, efr);
        }
 
-#ifdef CONFIG_ARCH_OMAP1
        /* Workaround to enable 115200 baud on OMAP1510 internal ports */
-       if (cpu_is_omap1510() && is_omap_port(up)) {
+       if (is_omap1510_8250(up)) {
                if (baud == 115200) {
                        quot = 1;
                        serial_port_out(port, UART_OMAP_OSC_12M_SEL, 1);
                } else
                        serial_port_out(port, UART_OMAP_OSC_12M_SEL, 0);
        }
-#endif
 
        /*
         * For NatSemi, switch to bank 2 not bank 1, to avoid resetting EXCR2,
@@ -2439,10 +2437,9 @@ static unsigned int serial8250_port_size(struct uart_8250_port *pt)
 {
        if (pt->port.iotype == UPIO_AU)
                return 0x1000;
-#ifdef CONFIG_ARCH_OMAP1
-       if (is_omap_port(pt))
+       if (is_omap1_8250(pt))
                return 0x16 << pt->port.regshift;
-#endif
+
        return 8 << pt->port.regshift;
 }
 
index 5a76f9c8d36b98d943ef574de25c4400579c0551..3b4ea84898c2e719dc233ecddde63dc3c421bd0d 100644 (file)
@@ -106,3 +106,39 @@ static inline int serial8250_pnp_init(void) { return 0; }
 static inline void serial8250_pnp_exit(void) { }
 #endif
 
+#ifdef CONFIG_ARCH_OMAP1
+static inline int is_omap1_8250(struct uart_8250_port *pt)
+{
+       int res;
+
+       switch (pt->port.mapbase) {
+       case OMAP1_UART1_BASE:
+       case OMAP1_UART2_BASE:
+       case OMAP1_UART3_BASE:
+               res = 1;
+               break;
+       default:
+               res = 0;
+               break;
+       }
+
+       return res;
+}
+
+static inline int is_omap1510_8250(struct uart_8250_port *pt)
+{
+       if (!cpu_is_omap1510())
+               return 0;
+
+       return is_omap1_8250(pt);
+}
+#else
+static inline int is_omap1_8250(struct uart_8250_port *pt)
+{
+       return 0;
+}
+static inline int is_omap1510_8250(struct uart_8250_port *pt)
+{
+       return 0;
+}
+#endif
index c3b2ec0c8c0b7f3a6749f41feedb38fe0af58ac2..b19b8c54780115172639265e3a9d42ca0297ec22 100644 (file)
@@ -161,6 +161,29 @@ static int __devexit dw8250_remove(struct platform_device *pdev)
        return 0;
 }
 
+#ifdef CONFIG_PM
+static int dw8250_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       struct dw8250_data *data = platform_get_drvdata(pdev);
+
+       serial8250_suspend_port(data->line);
+
+       return 0;
+}
+
+static int dw8250_resume(struct platform_device *pdev)
+{
+       struct dw8250_data *data = platform_get_drvdata(pdev);
+
+       serial8250_resume_port(data->line);
+
+       return 0;
+}
+#else
+#define dw8250_suspend NULL
+#define dw8250_resume NULL
+#endif /* CONFIG_PM */
+
 static const struct of_device_id dw8250_match[] = {
        { .compatible = "snps,dw-apb-uart" },
        { /* Sentinel */ }
@@ -175,6 +198,8 @@ static struct platform_driver dw8250_platform_driver = {
        },
        .probe                  = dw8250_probe,
        .remove                 = __devexit_p(dw8250_remove),
+       .suspend                = dw8250_suspend,
+       .resume                 = dw8250_resume,
 };
 
 module_platform_driver(dw8250_platform_driver);
index eaafb98debed89e2f1b2e5e83ac33cd79301792e..843a150ba1053dd84d547e15565599ab24791ea3 100644 (file)
@@ -140,7 +140,7 @@ static void __init init_port(struct early_serial8250_device *device)
        serial_out(port, UART_FCR, 0);          /* no fifo */
        serial_out(port, UART_MCR, 0x3);        /* DTR + RTS */
 
-       divisor = port->uartclk / (16 * device->baud);
+       divisor = DIV_ROUND_CLOSEST(port->uartclk, 16 * device->baud);
        c = serial_in(port, UART_LCR);
        serial_out(port, UART_LCR, c | UART_LCR_DLAB);
        serial_out(port, UART_DLL, divisor & 0xff);
index 8f1dd2cc00a8de79ac9538248271d2be376336aa..f3d0edf46644da2505db40ee0422b3bca2ee8234 100644 (file)
@@ -162,7 +162,7 @@ int __init hp300_setup_serial_console(void)
 static int __devinit hpdca_init_one(struct dio_dev *d,
                                const struct dio_device_id *ent)
 {
-       struct uart_port port;
+       struct uart_8250_port uart;
        int line;
 
 #ifdef CONFIG_SERIAL_8250_CONSOLE
@@ -174,19 +174,19 @@ static int __devinit hpdca_init_one(struct dio_dev *d,
        memset(&uart, 0, sizeof(uart));
 
        /* Memory mapped I/O */
-       port.iotype = UPIO_MEM;
-       port.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF;
-       port.irq = d->ipl;
-       port.uartclk = HPDCA_BAUD_BASE * 16;
-       port.mapbase = (d->resource.start + UART_OFFSET);
-       port.membase = (char *)(port.mapbase + DIO_VIRADDRBASE);
-       port.regshift = 1;
-       port.dev = &d->dev;
+       uart.port.iotype = UPIO_MEM;
+       uart.port.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF;
+       uart.port.irq = d->ipl;
+       uart.port.uartclk = HPDCA_BAUD_BASE * 16;
+       uart.port.mapbase = (d->resource.start + UART_OFFSET);
+       uart.port.membase = (char *)(uart.port.mapbase + DIO_VIRADDRBASE);
+       uart.port.regshift = 1;
+       uart.port.dev = &d->dev;
        line = serial8250_register_8250_port(&uart);
 
        if (line < 0) {
                printk(KERN_NOTICE "8250_hp300: register_serial() DCA scode %d"
-                      " irq %d failed\n", d->scode, port.irq);
+                      " irq %d failed\n", d->scode, uart.port.irq);
                return -ENOMEM;
        }
 
index 17b7d26abf416494aac36ddd66cfd47d9824d593..cec8852dd1b6e0e3ada0b558c4bf0f7987492d0b 100644 (file)
@@ -1068,7 +1068,7 @@ ce4100_serial_setup(struct serial_private *priv,
 {
        int ret;
 
-       ret = setup_port(priv, port, 0, 0, board->reg_shift);
+       ret = setup_port(priv, port, idx, 0, board->reg_shift);
        port->port.iotype = UPIO_MEM32;
        port->port.type = PORT_XSCALE;
        port->port.flags = (port->port.flags | UPF_FIXED_PORT | UPF_FIXED_TYPE);
@@ -2658,8 +2658,8 @@ static struct pciserial_board pci_boards[] __devinitdata = {
                .first_offset   = 0x1000,
        },
        [pbn_ce4100_1_115200] = {
-               .flags          = FL_BASE0,
-               .num_ports      = 1,
+               .flags          = FL_BASE_BARS,
+               .num_ports      = 2,
                .base_baud      = 921600,
                .reg_shift      = 2,
        },
index 233fbaaf25596ae4515f0d3e1890d4b62da617d6..2a53be5f010d9af3ee0ed1950f5951524e9a7cb3 100644 (file)
@@ -1150,7 +1150,7 @@ config SERIAL_SC26XX_CONSOLE
          Support for Console on SC2681/SC2692 serial ports.
 
 config SERIAL_SCCNXP
-       bool "SCCNXP serial port support"
+       tristate "SCCNXP serial port support"
        depends on !SERIAL_SC26XX
        select SERIAL_CORE
        default n
@@ -1162,7 +1162,7 @@ config SERIAL_SCCNXP
 
 config SERIAL_SCCNXP_CONSOLE
        bool "Console on SCCNXP serial port"
-       depends on SERIAL_SCCNXP
+       depends on SERIAL_SCCNXP=y
        select SERIAL_CORE_CONSOLE
        help
          Support for console on SCCNXP serial ports.
index 3d7e1ee2fa57a4a6db1deb0a7a173b90769298a3..65f891be12d1d6481849f93ce4d06e8ec6373a17 100644 (file)
@@ -39,6 +39,7 @@
 #include <linux/atmel_pdc.h>
 #include <linux/atmel_serial.h>
 #include <linux/uaccess.h>
+#include <linux/pinctrl/consumer.h>
 
 #include <asm/io.h>
 #include <asm/ioctls.h>
@@ -1773,6 +1774,7 @@ static int __devinit atmel_serial_probe(struct platform_device *pdev)
        struct atmel_uart_data *pdata = pdev->dev.platform_data;
        void *data;
        int ret = -ENODEV;
+       struct pinctrl *pinctrl;
 
        BUILD_BUG_ON(ATMEL_SERIAL_RINGSIZE & (ATMEL_SERIAL_RINGSIZE - 1));
 
@@ -1805,6 +1807,12 @@ static int __devinit atmel_serial_probe(struct platform_device *pdev)
 
        atmel_init_port(port, pdev);
 
+       pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+       if (IS_ERR(pinctrl)) {
+               ret = PTR_ERR(pinctrl);
+               goto err;
+       }
+
        if (!atmel_use_dma_rx(&port->uart)) {
                ret = -ENOMEM;
                data = kmalloc(sizeof(struct atmel_uart_char)
index d0f719fafc841f07022adb734b0d2187360e6d05..a0a6db5c32fe4c93b9d8ccad1dd4c98a62049b55 100644 (file)
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
 #if defined(CONFIG_SERIAL_CLPS711X_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
 #endif
 
 #include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/sysrq.h>
-#include <linux/spinlock.h>
 #include <linux/device.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
+#include <linux/console.h>
 #include <linux/serial_core.h>
 #include <linux/serial.h>
 #include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
 
 #include <mach/hardware.h>
-#include <asm/irq.h>
-
-#define UART_NR                2
-
-#define SERIAL_CLPS711X_MAJOR  204
-#define SERIAL_CLPS711X_MINOR  40
-#define SERIAL_CLPS711X_NR     UART_NR
-
-/*
- * We use the relevant SYSCON register as a base address for these ports.
- */
-#define UBRLCR(port)           ((port)->iobase + UBRLCR1 - SYSCON1)
-#define UARTDR(port)           ((port)->iobase + UARTDR1 - SYSCON1)
-#define SYSFLG(port)           ((port)->iobase + SYSFLG1 - SYSCON1)
-#define SYSCON(port)           ((port)->iobase + SYSCON1 - SYSCON1)
-
-#define TX_IRQ(port)           ((port)->irq)
-#define RX_IRQ(port)           ((port)->irq + 1)
 
-#define UART_ANY_ERR           (UARTDR_FRMERR | UARTDR_PARERR | UARTDR_OVERR)
-
-#define tx_enabled(port)       ((port)->unused[0])
+#define UART_CLPS711X_NAME     "uart-clps711x"
+#define UART_CLPS711X_NR       2
+#define UART_CLPS711X_MAJOR    204
+#define UART_CLPS711X_MINOR    40
+
+#define UBRLCR(port)           ((port)->line ? UBRLCR2 : UBRLCR1)
+#define UARTDR(port)           ((port)->line ? UARTDR2 : UARTDR1)
+#define SYSFLG(port)           ((port)->line ? SYSFLG2 : SYSFLG1)
+#define SYSCON(port)           ((port)->line ? SYSCON2 : SYSCON1)
+#define TX_IRQ(port)           ((port)->line ? IRQ_UTXINT2 : IRQ_UTXINT1)
+#define RX_IRQ(port)           ((port)->line ? IRQ_URXINT2 : IRQ_URXINT1)
+
+struct clps711x_port {
+       struct uart_driver      uart;
+       struct clk              *uart_clk;
+       struct uart_port        port[UART_CLPS711X_NR];
+       int                     tx_enabled[UART_CLPS711X_NR];
+#ifdef CONFIG_SERIAL_CLPS711X_CONSOLE
+       struct console          console;
+#endif
+};
 
-static void clps711xuart_stop_tx(struct uart_port *port)
+static void uart_clps711x_stop_tx(struct uart_port *port)
 {
-       if (tx_enabled(port)) {
+       struct clps711x_port *s = dev_get_drvdata(port->dev);
+
+       if (s->tx_enabled[port->line]) {
                disable_irq(TX_IRQ(port));
-               tx_enabled(port) = 0;
+               s->tx_enabled[port->line] = 0;
        }
 }
 
-static void clps711xuart_start_tx(struct uart_port *port)
+static void uart_clps711x_start_tx(struct uart_port *port)
 {
-       if (!tx_enabled(port)) {
+       struct clps711x_port *s = dev_get_drvdata(port->dev);
+
+       if (!s->tx_enabled[port->line]) {
                enable_irq(TX_IRQ(port));
-               tx_enabled(port) = 1;
+               s->tx_enabled[port->line] = 1;
        }
 }
 
-static void clps711xuart_stop_rx(struct uart_port *port)
+static void uart_clps711x_stop_rx(struct uart_port *port)
 {
        disable_irq(RX_IRQ(port));
 }
 
-static void clps711xuart_enable_ms(struct uart_port *port)
+static void uart_clps711x_enable_ms(struct uart_port *port)
 {
+       /* Do nothing */
 }
 
-static irqreturn_t clps711xuart_int_rx(int irq, void *dev_id)
+static irqreturn_t uart_clps711x_int_rx(int irq, void *dev_id)
 {
        struct uart_port *port = dev_id;
-       struct tty_struct *tty = port->state->port.tty;
+       struct tty_struct *tty = tty_port_tty_get(&port->state->port);
        unsigned int status, ch, flg;
 
-       status = clps_readl(SYSFLG(port));
-       while (!(status & SYSFLG_URXFE)) {
-               ch = clps_readl(UARTDR(port));
+       if (!tty)
+               return IRQ_HANDLED;
 
-               port->icount.rx++;
+       for (;;) {
+               status = clps_readl(SYSFLG(port));
+               if (status & SYSFLG_URXFE)
+                       break;
+
+               ch = clps_readw(UARTDR(port));
+               status = ch & (UARTDR_FRMERR | UARTDR_PARERR | UARTDR_OVERR);
+               ch &= 0xff;
 
+               port->icount.rx++;
                flg = TTY_NORMAL;
 
-               /*
-                * Note that the error handling code is
-                * out of the main execution path
-                */
-               if (unlikely(ch & UART_ANY_ERR)) {
-                       if (ch & UARTDR_PARERR)
+               if (unlikely(status)) {
+                       if (status & UARTDR_PARERR)
                                port->icount.parity++;
-                       else if (ch & UARTDR_FRMERR)
+                       else if (status & UARTDR_FRMERR)
                                port->icount.frame++;
-                       if (ch & UARTDR_OVERR)
+                       else if (status & UARTDR_OVERR)
                                port->icount.overrun++;
 
-                       ch &= port->read_status_mask;
+                       status &= port->read_status_mask;
 
-                       if (ch & UARTDR_PARERR)
+                       if (status & UARTDR_PARERR)
                                flg = TTY_PARITY;
-                       else if (ch & UARTDR_FRMERR)
+                       else if (status & UARTDR_FRMERR)
                                flg = TTY_FRAME;
-
-#ifdef SUPPORT_SYSRQ
-                       port->sysrq = 0;
-#endif
+                       else if (status & UARTDR_OVERR)
+                               flg = TTY_OVERRUN;
                }
 
                if (uart_handle_sysrq_char(port, ch))
-                       goto ignore_char;
+                       continue;
 
-               /*
-                * CHECK: does overrun affect the current character?
-                * ASSUMPTION: it does not.
-                */
-               uart_insert_char(port, ch, UARTDR_OVERR, ch, flg);
+               if (status & port->ignore_status_mask)
+                       continue;
 
-       ignore_char:
-               status = clps_readl(SYSFLG(port));
+               uart_insert_char(port, status, UARTDR_OVERR, ch, flg);
        }
+
        tty_flip_buffer_push(tty);
+
+       tty_kref_put(tty);
+
        return IRQ_HANDLED;
 }
 
-static irqreturn_t clps711xuart_int_tx(int irq, void *dev_id)
+static irqreturn_t uart_clps711x_int_tx(int irq, void *dev_id)
 {
        struct uart_port *port = dev_id;
+       struct clps711x_port *s = dev_get_drvdata(port->dev);
        struct circ_buf *xmit = &port->state->xmit;
-       int count;
 
        if (port->x_char) {
-               clps_writel(port->x_char, UARTDR(port));
+               clps_writew(port->x_char, UARTDR(port));
                port->icount.tx++;
                port->x_char = 0;
                return IRQ_HANDLED;
        }
 
-       if (uart_circ_empty(xmit) || uart_tx_stopped(port))
-               goto disable_tx_irq;
+       if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
+               disable_irq_nosync(TX_IRQ(port));
+               s->tx_enabled[port->line] = 0;
+               return IRQ_HANDLED;
+       }
 
-       count = port->fifosize >> 1;
-       do {
-               clps_writel(xmit->buf[xmit->tail], UARTDR(port));
+       while (!uart_circ_empty(xmit)) {
+               clps_writew(xmit->buf[xmit->tail], UARTDR(port));
                xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
                port->icount.tx++;
-               if (uart_circ_empty(xmit))
+               if (clps_readl(SYSFLG(port) & SYSFLG_UTXFF))
                        break;
-       } while (--count > 0);
+       }
 
        if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
                uart_write_wakeup(port);
 
-       if (uart_circ_empty(xmit)) {
-       disable_tx_irq:
-               disable_irq_nosync(TX_IRQ(port));
-               tx_enabled(port) = 0;
-       }
-
        return IRQ_HANDLED;
 }
 
-static unsigned int clps711xuart_tx_empty(struct uart_port *port)
+static unsigned int uart_clps711x_tx_empty(struct uart_port *port)
 {
-       unsigned int status = clps_readl(SYSFLG(port));
-       return status & SYSFLG_UBUSY ? 0 : TIOCSER_TEMT;
+       return (clps_readl(SYSFLG(port) & SYSFLG_UBUSY)) ? 0 : TIOCSER_TEMT;
 }
 
-static unsigned int clps711xuart_get_mctrl(struct uart_port *port)
+static unsigned int uart_clps711x_get_mctrl(struct uart_port *port)
 {
-       unsigned int port_addr;
-       unsigned int result = 0;
-       unsigned int status;
+       unsigned int status, result = 0;
 
-       port_addr = SYSFLG(port);
-       if (port_addr == SYSFLG1) {
+       if (port->line == 0) {
                status = clps_readl(SYSFLG1);
                if (status & SYSFLG1_DCD)
                        result |= TIOCM_CAR;
@@ -199,104 +187,86 @@ static unsigned int clps711xuart_get_mctrl(struct uart_port *port)
                        result |= TIOCM_DSR;
                if (status & SYSFLG1_CTS)
                        result |= TIOCM_CTS;
-       }
+       } else
+               result = TIOCM_DSR | TIOCM_CTS | TIOCM_CAR;
 
        return result;
 }
 
-static void
-clps711xuart_set_mctrl_null(struct uart_port *port, unsigned int mctrl)
+static void uart_clps711x_set_mctrl(struct uart_port *port, unsigned int mctrl)
 {
+       /* Do nothing */
 }
 
-static void clps711xuart_break_ctl(struct uart_port *port, int break_state)
+static void uart_clps711x_break_ctl(struct uart_port *port, int break_state)
 {
        unsigned long flags;
        unsigned int ubrlcr;
 
        spin_lock_irqsave(&port->lock, flags);
+
        ubrlcr = clps_readl(UBRLCR(port));
-       if (break_state == -1)
+       if (break_state)
                ubrlcr |= UBRLCR_BREAK;
        else
                ubrlcr &= ~UBRLCR_BREAK;
        clps_writel(ubrlcr, UBRLCR(port));
+
        spin_unlock_irqrestore(&port->lock, flags);
 }
 
-static int clps711xuart_startup(struct uart_port *port)
+static int uart_clps711x_startup(struct uart_port *port)
 {
-       unsigned int syscon;
-       int retval;
-
-       tx_enabled(port) = 1;
-
-       /*
-        * Allocate the IRQs
-        */
-       retval = request_irq(TX_IRQ(port), clps711xuart_int_tx, 0,
-                            "clps711xuart_tx", port);
-       if (retval)
-               return retval;
-
-       retval = request_irq(RX_IRQ(port), clps711xuart_int_rx, 0,
-                            "clps711xuart_rx", port);
-       if (retval) {
-               free_irq(TX_IRQ(port), port);
-               return retval;
+       struct clps711x_port *s = dev_get_drvdata(port->dev);
+       int ret;
+
+       s->tx_enabled[port->line] = 1;
+       /* Allocate the IRQs */
+       ret = devm_request_irq(port->dev, TX_IRQ(port), uart_clps711x_int_tx,
+                              0, UART_CLPS711X_NAME " TX", port);
+       if (ret)
+               return ret;
+
+       ret = devm_request_irq(port->dev, RX_IRQ(port), uart_clps711x_int_rx,
+                              0, UART_CLPS711X_NAME " RX", port);
+       if (ret) {
+               devm_free_irq(port->dev, TX_IRQ(port), port);
+               return ret;
        }
 
-       /*
-        * enable the port
-        */
-       syscon = clps_readl(SYSCON(port));
-       syscon |= SYSCON_UARTEN;
-       clps_writel(syscon, SYSCON(port));
+       /* Disable break */
+       clps_writel(clps_readl(UBRLCR(port)) & ~UBRLCR_BREAK, UBRLCR(port));
+
+       /* Enable the port */
+       clps_writel(clps_readl(SYSCON(port)) | SYSCON_UARTEN, SYSCON(port));
 
        return 0;
 }
 
-static void clps711xuart_shutdown(struct uart_port *port)
+static void uart_clps711x_shutdown(struct uart_port *port)
 {
-       unsigned int ubrlcr, syscon;
+       /* Free the interrupts */
+       devm_free_irq(port->dev, TX_IRQ(port), port);
+       devm_free_irq(port->dev, RX_IRQ(port), port);
 
-       /*
-        * Free the interrupt
-        */
-       free_irq(TX_IRQ(port), port);   /* TX interrupt */
-       free_irq(RX_IRQ(port), port);   /* RX interrupt */
-
-       /*
-        * disable the port
-        */
-       syscon = clps_readl(SYSCON(port));
-       syscon &= ~SYSCON_UARTEN;
-       clps_writel(syscon, SYSCON(port));
-
-       /*
-        * disable break condition and fifos
-        */
-       ubrlcr = clps_readl(UBRLCR(port));
-       ubrlcr &= ~(UBRLCR_FIFOEN | UBRLCR_BREAK);
-       clps_writel(ubrlcr, UBRLCR(port));
+       /* Disable the port */
+       clps_writel(clps_readl(SYSCON(port)) & ~SYSCON_UARTEN, SYSCON(port));
 }
 
-static void
-clps711xuart_set_termios(struct uart_port *port, struct ktermios *termios,
-                        struct ktermios *old)
+static void uart_clps711x_set_termios(struct uart_port *port,
+                                     struct ktermios *termios,
+                                     struct ktermios *old)
 {
        unsigned int ubrlcr, baud, quot;
        unsigned long flags;
 
-       /*
-        * We don't implement CREAD.
-        */
-       termios->c_cflag |= CREAD;
+       /* Mask termios capabilities we don't support */
+       termios->c_cflag &= ~CMSPAR;
+       termios->c_iflag &= ~(BRKINT | IGNBRK);
 
-       /*
-        * Ask the core to calculate the divisor for us.
-        */
-       baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); 
+       /* Ask the core to calculate the divisor for us */
+       baud = uart_get_baud_rate(port, termios, old, port->uartclk / 4096,
+                                                     port->uartclk / 16);
        quot = uart_get_divisor(port, baud);
 
        switch (termios->c_cflag & CSIZE) {
@@ -309,160 +279,117 @@ clps711xuart_set_termios(struct uart_port *port, struct ktermios *termios,
        case CS7:
                ubrlcr = UBRLCR_WRDLEN7;
                break;
-       default: // CS8
+       case CS8:
+       default:
                ubrlcr = UBRLCR_WRDLEN8;
                break;
        }
+
        if (termios->c_cflag & CSTOPB)
                ubrlcr |= UBRLCR_XSTOP;
+
        if (termios->c_cflag & PARENB) {
                ubrlcr |= UBRLCR_PRTEN;
                if (!(termios->c_cflag & PARODD))
                        ubrlcr |= UBRLCR_EVENPRT;
        }
-       if (port->fifosize > 1)
-               ubrlcr |= UBRLCR_FIFOEN;
 
-       spin_lock_irqsave(&port->lock, flags);
+       /* Enable FIFO */
+       ubrlcr |= UBRLCR_FIFOEN;
 
-       /*
-        * Update the per-port timeout.
-        */
-       uart_update_timeout(port, termios->c_cflag, baud);
+       spin_lock_irqsave(&port->lock, flags);
 
+       /* Set read status mask */
        port->read_status_mask = UARTDR_OVERR;
        if (termios->c_iflag & INPCK)
                port->read_status_mask |= UARTDR_PARERR | UARTDR_FRMERR;
 
-       /*
-        * Characters to ignore
-        */
+       /* Set status ignore mask */
        port->ignore_status_mask = 0;
-       if (termios->c_iflag & IGNPAR)
-               port->ignore_status_mask |= UARTDR_FRMERR | UARTDR_PARERR;
-       if (termios->c_iflag & IGNBRK) {
-               /*
-                * If we're ignoring parity and break indicators,
-                * ignore overruns to (for real raw support).
-                */
-               if (termios->c_iflag & IGNPAR)
-                       port->ignore_status_mask |= UARTDR_OVERR;
-       }
+       if (!(termios->c_cflag & CREAD))
+               port->ignore_status_mask |= UARTDR_OVERR | UARTDR_PARERR |
+                                           UARTDR_FRMERR;
 
-       quot -= 1;
+       uart_update_timeout(port, termios->c_cflag, baud);
 
-       clps_writel(ubrlcr | quot, UBRLCR(port));
+       clps_writel(ubrlcr | (quot - 1), UBRLCR(port));
 
        spin_unlock_irqrestore(&port->lock, flags);
 }
 
-static const char *clps711xuart_type(struct uart_port *port)
+static const char *uart_clps711x_type(struct uart_port *port)
 {
-       return port->type == PORT_CLPS711X ? "CLPS711x" : NULL;
+       return (port->type == PORT_CLPS711X) ? "CLPS711X" : NULL;
 }
 
-/*
- * Configure/autoconfigure the port.
- */
-static void clps711xuart_config_port(struct uart_port *port, int flags)
+static void uart_clps711x_config_port(struct uart_port *port, int flags)
 {
        if (flags & UART_CONFIG_TYPE)
                port->type = PORT_CLPS711X;
 }
 
-static void clps711xuart_release_port(struct uart_port *port)
+static void uart_clps711x_release_port(struct uart_port *port)
 {
+       /* Do nothing */
 }
 
-static int clps711xuart_request_port(struct uart_port *port)
+static int uart_clps711x_request_port(struct uart_port *port)
 {
+       /* Do nothing */
        return 0;
 }
 
-static struct uart_ops clps711x_pops = {
-       .tx_empty       = clps711xuart_tx_empty,
-       .set_mctrl      = clps711xuart_set_mctrl_null,
-       .get_mctrl      = clps711xuart_get_mctrl,
-       .stop_tx        = clps711xuart_stop_tx,
-       .start_tx       = clps711xuart_start_tx,
-       .stop_rx        = clps711xuart_stop_rx,
-       .enable_ms      = clps711xuart_enable_ms,
-       .break_ctl      = clps711xuart_break_ctl,
-       .startup        = clps711xuart_startup,
-       .shutdown       = clps711xuart_shutdown,
-       .set_termios    = clps711xuart_set_termios,
-       .type           = clps711xuart_type,
-       .config_port    = clps711xuart_config_port,
-       .release_port   = clps711xuart_release_port,
-       .request_port   = clps711xuart_request_port,
-};
-
-static struct uart_port clps711x_ports[UART_NR] = {
-       {
-               .iobase         = SYSCON1,
-               .irq            = IRQ_UTXINT1, /* IRQ_URXINT1, IRQ_UMSINT */
-               .uartclk        = 3686400,
-               .fifosize       = 16,
-               .ops            = &clps711x_pops,
-               .line           = 0,
-               .flags          = UPF_BOOT_AUTOCONF,
-       },
-       {
-               .iobase         = SYSCON2,
-               .irq            = IRQ_UTXINT2, /* IRQ_URXINT2 */
-               .uartclk        = 3686400,
-               .fifosize       = 16,
-               .ops            = &clps711x_pops,
-               .line           = 1,
-               .flags          = UPF_BOOT_AUTOCONF,
-       }
+static const struct uart_ops uart_clps711x_ops = {
+       .tx_empty       = uart_clps711x_tx_empty,
+       .set_mctrl      = uart_clps711x_set_mctrl,
+       .get_mctrl      = uart_clps711x_get_mctrl,
+       .stop_tx        = uart_clps711x_stop_tx,
+       .start_tx       = uart_clps711x_start_tx,
+       .stop_rx        = uart_clps711x_stop_rx,
+       .enable_ms      = uart_clps711x_enable_ms,
+       .break_ctl      = uart_clps711x_break_ctl,
+       .startup        = uart_clps711x_startup,
+       .shutdown       = uart_clps711x_shutdown,
+       .set_termios    = uart_clps711x_set_termios,
+       .type           = uart_clps711x_type,
+       .config_port    = uart_clps711x_config_port,
+       .release_port   = uart_clps711x_release_port,
+       .request_port   = uart_clps711x_request_port,
 };
 
 #ifdef CONFIG_SERIAL_CLPS711X_CONSOLE
-static void clps711xuart_console_putchar(struct uart_port *port, int ch)
+static void uart_clps711x_console_putchar(struct uart_port *port, int ch)
 {
        while (clps_readl(SYSFLG(port)) & SYSFLG_UTXFF)
                barrier();
-       clps_writel(ch, UARTDR(port));
+
+       clps_writew(ch, UARTDR(port));
 }
 
-/*
- *     Print a string to the serial port trying not to disturb
- *     any possible real use of the port...
- *
- *     The console_lock must be held when we get here.
- *
- *     Note that this is called with interrupts already disabled
- */
-static void
-clps711xuart_console_write(struct console *co, const char *s,
-                          unsigned int count)
+static void uart_clps711x_console_write(struct console *co, const char *c,
+                                       unsigned n)
 {
-       struct uart_port *port = clps711x_ports + co->index;
-       unsigned int status, syscon;
+       struct clps711x_port *s = (struct clps711x_port *)co->data;
+       struct uart_port *port = &s->port[co->index];
+       u32 syscon;
 
-       /*
-        *      Ensure that the port is enabled.
-        */
+       /* Ensure that the port is enabled */
        syscon = clps_readl(SYSCON(port));
        clps_writel(syscon | SYSCON_UARTEN, SYSCON(port));
 
-       uart_console_write(port, s, count, clps711xuart_console_putchar);
+       uart_console_write(port, c, n, uart_clps711x_console_putchar);
 
-       /*
-        *      Finally, wait for transmitter to become empty
-        *      and restore the uart state.
-        */
-       do {
-               status = clps_readl(SYSFLG(port));
-       } while (status & SYSFLG_UBUSY);
+       /* Wait for transmitter to become empty */
+       while (clps_readl(SYSFLG(port)) & SYSFLG_UBUSY)
+               barrier();
 
+       /* Restore the uart state */
        clps_writel(syscon, SYSCON(port));
 }
 
-static void __init
-clps711xuart_console_get_options(struct uart_port *port, int *baud,
-                                int *parity, int *bits)
+static void uart_clps711x_console_get_options(struct uart_port *port,
+                                             int *baud, int *parity,
+                                             int *bits)
 {
        if (clps_readl(SYSCON(port)) & SYSCON_UARTEN) {
                unsigned int ubrlcr, quot;
@@ -487,92 +414,124 @@ clps711xuart_console_get_options(struct uart_port *port, int *baud,
        }
 }
 
-static int __init clps711xuart_console_setup(struct console *co, char *options)
+static int uart_clps711x_console_setup(struct console *co, char *options)
 {
-       struct uart_port *port;
-       int baud = 38400;
-       int bits = 8;
-       int parity = 'n';
-       int flow = 'n';
-
-       /*
-        * Check whether an invalid uart number has been specified, and
-        * if so, search for the first available port that does have
-        * console support.
-        */
-       port = uart_get_console(clps711x_ports, UART_NR, co);
+       int baud = 38400, bits = 8, parity = 'n', flow = 'n';
+       struct clps711x_port *s = (struct clps711x_port *)co->data;
+       struct uart_port *port = &s->port[(co->index > 0) ? co->index : 0];
 
        if (options)
                uart_parse_options(options, &baud, &parity, &bits, &flow);
        else
-               clps711xuart_console_get_options(port, &baud, &parity, &bits);
+               uart_clps711x_console_get_options(port, &baud, &parity, &bits);
 
        return uart_set_options(port, co, baud, parity, bits, flow);
 }
+#endif
 
-static struct uart_driver clps711x_reg;
-static struct console clps711x_console = {
-       .name           = "ttyCL",
-       .write          = clps711xuart_console_write,
-       .device         = uart_console_device,
-       .setup          = clps711xuart_console_setup,
-       .flags          = CON_PRINTBUFFER,
-       .index          = -1,
-       .data           = &clps711x_reg,
-};
-
-static int __init clps711xuart_console_init(void)
+static int __devinit uart_clps711x_probe(struct platform_device *pdev)
 {
-       register_console(&clps711x_console);
-       return 0;
-}
-console_initcall(clps711xuart_console_init);
+       struct clps711x_port *s;
+       int ret, i;
+
+       s = devm_kzalloc(&pdev->dev, sizeof(struct clps711x_port), GFP_KERNEL);
+       if (!s) {
+               dev_err(&pdev->dev, "Error allocating port structure\n");
+               return -ENOMEM;
+       }
+       platform_set_drvdata(pdev, s);
 
-#define CLPS711X_CONSOLE       &clps711x_console
-#else
-#define CLPS711X_CONSOLE       NULL
+       s->uart_clk = devm_clk_get(&pdev->dev, "uart");
+       if (IS_ERR(s->uart_clk)) {
+               dev_err(&pdev->dev, "Can't get UART clocks\n");
+               ret = PTR_ERR(s->uart_clk);
+               goto err_out;
+       }
+
+       s->uart.owner           = THIS_MODULE;
+       s->uart.dev_name        = "ttyCL";
+       s->uart.major           = UART_CLPS711X_MAJOR;
+       s->uart.minor           = UART_CLPS711X_MINOR;
+       s->uart.nr              = UART_CLPS711X_NR;
+#ifdef CONFIG_SERIAL_CLPS711X_CONSOLE
+       s->uart.cons            = &s->console;
+       s->uart.cons->device    = uart_console_device;
+       s->uart.cons->write     = uart_clps711x_console_write;
+       s->uart.cons->setup     = uart_clps711x_console_setup;
+       s->uart.cons->flags     = CON_PRINTBUFFER;
+       s->uart.cons->index     = -1;
+       s->uart.cons->data      = s;
+       strcpy(s->uart.cons->name, "ttyCL");
 #endif
+       ret = uart_register_driver(&s->uart);
+       if (ret) {
+               dev_err(&pdev->dev, "Registering UART driver failed\n");
+               devm_clk_put(&pdev->dev, s->uart_clk);
+               goto err_out;
+       }
 
-static struct uart_driver clps711x_reg = {
-       .driver_name            = "ttyCL",
-       .dev_name               = "ttyCL",
-       .major                  = SERIAL_CLPS711X_MAJOR,
-       .minor                  = SERIAL_CLPS711X_MINOR,
-       .nr                     = UART_NR,
+       for (i = 0; i < UART_CLPS711X_NR; i++) {
+               s->port[i].line         = i;
+               s->port[i].dev          = &pdev->dev;
+               s->port[i].irq          = TX_IRQ(&s->port[i]);
+               s->port[i].iobase       = SYSCON(&s->port[i]);
+               s->port[i].type         = PORT_CLPS711X;
+               s->port[i].fifosize     = 16;
+               s->port[i].flags        = UPF_SKIP_TEST | UPF_FIXED_TYPE;
+               s->port[i].uartclk      = clk_get_rate(s->uart_clk);
+               s->port[i].ops          = &uart_clps711x_ops;
+               WARN_ON(uart_add_one_port(&s->uart, &s->port[i]));
+       }
 
-       .cons                   = CLPS711X_CONSOLE,
-};
+       return 0;
 
-static int __init clps711xuart_init(void)
-{
-       int ret, i;
+err_out:
+       platform_set_drvdata(pdev, NULL);
 
-       printk(KERN_INFO "Serial: CLPS711x driver\n");
+       return ret;
+}
 
-       ret = uart_register_driver(&clps711x_reg);
-       if (ret)
-               return ret;
+static int __devexit uart_clps711x_remove(struct platform_device *pdev)
+{
+       struct clps711x_port *s = platform_get_drvdata(pdev);
+       int i;
 
-       for (i = 0; i < UART_NR; i++)
-               uart_add_one_port(&clps711x_reg, &clps711x_ports[i]);
+       for (i = 0; i < UART_CLPS711X_NR; i++)
+               uart_remove_one_port(&s->uart, &s->port[i]);
+
+       devm_clk_put(&pdev->dev, s->uart_clk);
+       uart_unregister_driver(&s->uart);
+       platform_set_drvdata(pdev, NULL);
 
        return 0;
 }
 
-static void __exit clps711xuart_exit(void)
-{
-       int i;
+static struct platform_driver clps711x_uart_driver = {
+       .driver = {
+               .name   = UART_CLPS711X_NAME,
+               .owner  = THIS_MODULE,
+       },
+       .probe  = uart_clps711x_probe,
+       .remove = __devexit_p(uart_clps711x_remove),
+};
+module_platform_driver(clps711x_uart_driver);
 
-       for (i = 0; i < UART_NR; i++)
-               uart_remove_one_port(&clps711x_reg, &clps711x_ports[i]);
+static struct platform_device clps711x_uart_device = {
+       .name   = UART_CLPS711X_NAME,
+};
 
-       uart_unregister_driver(&clps711x_reg);
+static int __init uart_clps711x_init(void)
+{
+       return platform_device_register(&clps711x_uart_device);
 }
+module_init(uart_clps711x_init);
 
-module_init(clps711xuart_init);
-module_exit(clps711xuart_exit);
+static void __exit uart_clps711x_exit(void)
+{
+       platform_device_unregister(&clps711x_uart_device);
+}
+module_exit(uart_clps711x_exit);
 
 MODULE_AUTHOR("Deep Blue Solutions Ltd");
-MODULE_DESCRIPTION("CLPS-711x generic serial driver");
+MODULE_DESCRIPTION("CLPS711X serial driver");
 MODULE_LICENSE("GPL");
-MODULE_ALIAS_CHARDEV(SERIAL_CLPS711X_MAJOR, SERIAL_CLPS711X_MINOR);
index 6ede6fd92b4cd00e939dca479e0f3e3a0a0d923e..6d3d26a607b9fd26bc03cff7d50f62ccbf8a589b 100644 (file)
@@ -671,19 +671,19 @@ serial_omap_configure_xonxoff
 
        /*
         * IXON Flag:
-        * Flow control for OMAP.TX
-        * OMAP.RX should listen for XON/XOFF
+        * Enable XON/XOFF flow control on output.
+        * Transmit XON1, XOFF1
         */
        if (termios->c_iflag & IXON)
-               up->efr |= OMAP_UART_SW_RX;
+               up->efr |= OMAP_UART_SW_TX;
 
        /*
         * IXOFF Flag:
-        * Flow control for OMAP.RX
-        * OMAP.TX should send XON/XOFF
+        * Enable XON/XOFF flow control on input.
+        * Receiver compares XON1, XOFF1.
         */
        if (termios->c_iflag & IXOFF)
-               up->efr |= OMAP_UART_SW_TX;
+               up->efr |= OMAP_UART_SW_RX;
 
        serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);
        serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
index 9033fc6e0e4eb31a4fea337eca73634c8eec5109..2764828251f5bec273fd9f56cd6cf5764f4cb12a 100644 (file)
@@ -705,6 +705,57 @@ serial_pxa_console_write(struct console *co, const char *s, unsigned int count)
        clk_disable_unprepare(up->clk);
 }
 
+#ifdef CONFIG_CONSOLE_POLL
+/*
+ * Console polling routines for writing and reading from the uart while
+ * in an interrupt or debug context.
+ */
+
+static int serial_pxa_get_poll_char(struct uart_port *port)
+{
+       struct uart_pxa_port *up = (struct uart_pxa_port *)port;
+       unsigned char lsr = serial_in(up, UART_LSR);
+
+       while (!(lsr & UART_LSR_DR))
+               lsr = serial_in(up, UART_LSR);
+
+       return serial_in(up, UART_RX);
+}
+
+
+static void serial_pxa_put_poll_char(struct uart_port *port,
+                        unsigned char c)
+{
+       unsigned int ier;
+       struct uart_pxa_port *up = (struct uart_pxa_port *)port;
+
+       /*
+        *      First save the IER then disable the interrupts
+        */
+       ier = serial_in(up, UART_IER);
+       serial_out(up, UART_IER, UART_IER_UUE);
+
+       wait_for_xmitr(up);
+       /*
+        *      Send the character out.
+        *      If a LF, also do CR...
+        */
+       serial_out(up, UART_TX, c);
+       if (c == 10) {
+               wait_for_xmitr(up);
+               serial_out(up, UART_TX, 13);
+       }
+
+       /*
+        *      Finally, wait for transmitter to become empty
+        *      and restore the IER
+        */
+       wait_for_xmitr(up);
+       serial_out(up, UART_IER, ier);
+}
+
+#endif /* CONFIG_CONSOLE_POLL */
+
 static int __init
 serial_pxa_console_setup(struct console *co, char *options)
 {
@@ -759,6 +810,10 @@ struct uart_ops serial_pxa_pops = {
        .request_port   = serial_pxa_request_port,
        .config_port    = serial_pxa_config_port,
        .verify_port    = serial_pxa_verify_port,
+#ifdef CONFIG_CONSOLE_POLL
+       .poll_get_char = serial_pxa_get_poll_char,
+       .poll_put_char = serial_pxa_put_poll_char,
+#endif
 };
 
 static struct uart_driver serial_pxa_reg = {
index 7f04717176aa42c8ba6232719903eb547e673df3..740458ca62cca5e82a8fc579e61d69ab52b0074c 100644 (file)
@@ -530,16 +530,16 @@ static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level,
        switch (level) {
        case 3:
                if (!IS_ERR(ourport->baudclk))
-                       clk_disable(ourport->baudclk);
+                       clk_disable_unprepare(ourport->baudclk);
 
-               clk_disable(ourport->clk);
+               clk_disable_unprepare(ourport->clk);
                break;
 
        case 0:
-               clk_enable(ourport->clk);
+               clk_prepare_enable(ourport->clk);
 
                if (!IS_ERR(ourport->baudclk))
-                       clk_enable(ourport->baudclk);
+                       clk_prepare_enable(ourport->baudclk);
 
                break;
        default:
@@ -713,11 +713,11 @@ static void s3c24xx_serial_set_termios(struct uart_port *port,
                s3c24xx_serial_setsource(port, clk_sel);
 
                if (!IS_ERR(ourport->baudclk)) {
-                       clk_disable(ourport->baudclk);
+                       clk_disable_unprepare(ourport->baudclk);
                        ourport->baudclk = ERR_PTR(-EINVAL);
                }
 
-               clk_enable(clk);
+               clk_prepare_enable(clk);
 
                ourport->baudclk = clk;
                ourport->baudclk_rate = clk ? clk_get_rate(clk) : 0;
@@ -1287,9 +1287,9 @@ static int s3c24xx_serial_resume(struct device *dev)
        struct s3c24xx_uart_port *ourport = to_ourport(port);
 
        if (port) {
-               clk_enable(ourport->clk);
+               clk_prepare_enable(ourport->clk);
                s3c24xx_serial_resetport(port, s3c24xx_port_to_cfg(port));
-               clk_disable(ourport->clk);
+               clk_disable_unprepare(ourport->clk);
 
                uart_resume_port(&s3c24xx_uart_drv, port);
        }
index b7086d004f5f36cb47422d5225edf5540ad7d8b2..e821068cd95b0f798dc7a9bb39d6507c6733812c 100644 (file)
@@ -971,6 +971,7 @@ static const struct platform_device_id sccnxp_id_table[] = {
        { "sc28202",    SCCNXP_TYPE_SC28202 },
        { "sc68681",    SCCNXP_TYPE_SC68681 },
        { "sc68692",    SCCNXP_TYPE_SC68692 },
+       { },
 };
 MODULE_DEVICE_TABLE(platform, sccnxp_id_table);
 
index 205d4cf4a063bf404e126b97bcfb71c3d3ed3d87..4354fe565f641b96bdf0c11316b6bedfadeef871 100644 (file)
@@ -567,10 +567,6 @@ static int __devinit vt8500_serial_probe(struct platform_device *pdev)
        if (!mmres || !irqres)
                return -ENODEV;
 
-       vt8500_port = kzalloc(sizeof(struct vt8500_port), GFP_KERNEL);
-       if (!vt8500_port)
-               return -ENOMEM;
-
        if (np)
                port = of_alias_get_id(np, "serial");
                if (port > VT8500_MAX_PORTS)
@@ -593,6 +589,10 @@ static int __devinit vt8500_serial_probe(struct platform_device *pdev)
                return -EBUSY;
        }
 
+       vt8500_port = kzalloc(sizeof(struct vt8500_port), GFP_KERNEL);
+       if (!vt8500_port)
+               return -ENOMEM;
+
        vt8500_port->uart.type = PORT_VT8500;
        vt8500_port->uart.iotype = UPIO_MEM;
        vt8500_port->uart.mapbase = mmres->start;
index b0b39b823ccf16ec2e0b82264721a0be7e54005f..6953dc82850cb278fd99da209e560021d4d0c1e8 100644 (file)
@@ -23,7 +23,7 @@ struct tty_audit_buf {
 };
 
 static struct tty_audit_buf *tty_audit_buf_alloc(int major, int minor,
-                                                int icanon)
+                                                unsigned icanon)
 {
        struct tty_audit_buf *buf;
 
@@ -239,7 +239,8 @@ int tty_audit_push_task(struct task_struct *tsk, kuid_t loginuid, u32 sessionid)
  *     if TTY auditing is disabled or out of memory.  Otherwise, return a new
  *     reference to the buffer.
  */
-static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty)
+static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty,
+               unsigned icanon)
 {
        struct tty_audit_buf *buf, *buf2;
 
@@ -257,7 +258,7 @@ static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty)
 
        buf2 = tty_audit_buf_alloc(tty->driver->major,
                                   tty->driver->minor_start + tty->index,
-                                  tty->icanon);
+                                  icanon);
        if (buf2 == NULL) {
                audit_log_lost("out of memory in TTY auditing");
                return NULL;
@@ -287,7 +288,7 @@ static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty)
  *     Audit @data of @size from @tty, if necessary.
  */
 void tty_audit_add_data(struct tty_struct *tty, unsigned char *data,
-                       size_t size)
+                       size_t size, unsigned icanon)
 {
        struct tty_audit_buf *buf;
        int major, minor;
@@ -299,7 +300,7 @@ void tty_audit_add_data(struct tty_struct *tty, unsigned char *data,
            && tty->driver->subtype == PTY_TYPE_MASTER)
                return;
 
-       buf = tty_audit_buf_get(tty);
+       buf = tty_audit_buf_get(tty, icanon);
        if (!buf)
                return;
 
@@ -307,11 +308,11 @@ void tty_audit_add_data(struct tty_struct *tty, unsigned char *data,
        major = tty->driver->major;
        minor = tty->driver->minor_start + tty->index;
        if (buf->major != major || buf->minor != minor
-           || buf->icanon != tty->icanon) {
+           || buf->icanon != icanon) {
                tty_audit_buf_push_current(buf);
                buf->major = major;
                buf->minor = minor;
-               buf->icanon = tty->icanon;
+               buf->icanon = icanon;
        }
        do {
                size_t run;
index 91e326ffe7db826054c2607c1ea2688ed047bb81..6cf87d7afb7efb14264b7a20c7394a99adbb7946 100644 (file)
  *     Locking: none
  */
 
-void tty_buffer_free_all(struct tty_struct *tty)
+void tty_buffer_free_all(struct tty_port *port)
 {
+       struct tty_bufhead *buf = &port->buf;
        struct tty_buffer *thead;
-       while ((thead = tty->buf.head) != NULL) {
-               tty->buf.head = thead->next;
+
+       while ((thead = buf->head) != NULL) {
+               buf->head = thead->next;
                kfree(thead);
        }
-       while ((thead = tty->buf.free) != NULL) {
-               tty->buf.free = thead->next;
+       while ((thead = buf->free) != NULL) {
+               buf->free = thead->next;
                kfree(thead);
        }
-       tty->buf.tail = NULL;
-       tty->buf.memory_used = 0;
+       buf->tail = NULL;
+       buf->memory_used = 0;
 }
 
 /**
@@ -54,11 +56,11 @@ void tty_buffer_free_all(struct tty_struct *tty)
  *     Locking: Caller must hold tty->buf.lock
  */
 
-static struct tty_buffer *tty_buffer_alloc(struct tty_struct *tty, size_t size)
+static struct tty_buffer *tty_buffer_alloc(struct tty_port *port, size_t size)
 {
        struct tty_buffer *p;
 
-       if (tty->buf.memory_used + size > 65536)
+       if (port->buf.memory_used + size > 65536)
                return NULL;
        p = kmalloc(sizeof(struct tty_buffer) + 2 * size, GFP_ATOMIC);
        if (p == NULL)
@@ -70,7 +72,7 @@ static struct tty_buffer *tty_buffer_alloc(struct tty_struct *tty, size_t size)
        p->read = 0;
        p->char_buf_ptr = (char *)(p->data);
        p->flag_buf_ptr = (unsigned char *)p->char_buf_ptr + size;
-       tty->buf.memory_used += size;
+       port->buf.memory_used += size;
        return p;
 }
 
@@ -85,17 +87,19 @@ static struct tty_buffer *tty_buffer_alloc(struct tty_struct *tty, size_t size)
  *     Locking: Caller must hold tty->buf.lock
  */
 
-static void tty_buffer_free(struct tty_struct *tty, struct tty_buffer *b)
+static void tty_buffer_free(struct tty_port *port, struct tty_buffer *b)
 {
+       struct tty_bufhead *buf = &port->buf;
+
        /* Dumb strategy for now - should keep some stats */
-       tty->buf.memory_used -= b->size;
-       WARN_ON(tty->buf.memory_used < 0);
+       buf->memory_used -= b->size;
+       WARN_ON(buf->memory_used < 0);
 
        if (b->size >= 512)
                kfree(b);
        else {
-               b->next = tty->buf.free;
-               tty->buf.free = b;
+               b->next = buf->free;
+               buf->free = b;
        }
 }
 
@@ -110,15 +114,16 @@ static void tty_buffer_free(struct tty_struct *tty, struct tty_buffer *b)
  *     Locking: Caller must hold tty->buf.lock
  */
 
-static void __tty_buffer_flush(struct tty_struct *tty)
+static void __tty_buffer_flush(struct tty_port *port)
 {
+       struct tty_bufhead *buf = &port->buf;
        struct tty_buffer *thead;
 
-       while ((thead = tty->buf.head) != NULL) {
-               tty->buf.head = thead->next;
-               tty_buffer_free(tty, thead);
+       while ((thead = buf->head) != NULL) {
+               buf->head = thead->next;
+               tty_buffer_free(port, thead);
        }
-       tty->buf.tail = NULL;
+       buf->tail = NULL;
 }
 
 /**
@@ -134,21 +139,24 @@ static void __tty_buffer_flush(struct tty_struct *tty)
 
 void tty_buffer_flush(struct tty_struct *tty)
 {
+       struct tty_port *port = tty->port;
+       struct tty_bufhead *buf = &port->buf;
        unsigned long flags;
-       spin_lock_irqsave(&tty->buf.lock, flags);
+
+       spin_lock_irqsave(&buf->lock, flags);
 
        /* If the data is being pushed to the tty layer then we can't
           process it here. Instead set a flag and the flush_to_ldisc
           path will process the flush request before it exits */
-       if (test_bit(TTY_FLUSHING, &tty->flags)) {
-               set_bit(TTY_FLUSHPENDING, &tty->flags);
-               spin_unlock_irqrestore(&tty->buf.lock, flags);
+       if (test_bit(TTYP_FLUSHING, &port->iflags)) {
+               set_bit(TTYP_FLUSHPENDING, &port->iflags);
+               spin_unlock_irqrestore(&buf->lock, flags);
                wait_event(tty->read_wait,
-                               test_bit(TTY_FLUSHPENDING, &tty->flags) == 0);
+                               test_bit(TTYP_FLUSHPENDING, &port->iflags) == 0);
                return;
        } else
-               __tty_buffer_flush(tty);
-       spin_unlock_irqrestore(&tty->buf.lock, flags);
+               __tty_buffer_flush(port);
+       spin_unlock_irqrestore(&buf->lock, flags);
 }
 
 /**
@@ -163,9 +171,9 @@ void tty_buffer_flush(struct tty_struct *tty)
  *     Locking: Caller must hold tty->buf.lock
  */
 
-static struct tty_buffer *tty_buffer_find(struct tty_struct *tty, size_t size)
+static struct tty_buffer *tty_buffer_find(struct tty_port *port, size_t size)
 {
-       struct tty_buffer **tbh = &tty->buf.free;
+       struct tty_buffer **tbh = &port->buf.free;
        while ((*tbh) != NULL) {
                struct tty_buffer *t = *tbh;
                if (t->size >= size) {
@@ -174,14 +182,14 @@ static struct tty_buffer *tty_buffer_find(struct tty_struct *tty, size_t size)
                        t->used = 0;
                        t->commit = 0;
                        t->read = 0;
-                       tty->buf.memory_used += t->size;
+                       port->buf.memory_used += t->size;
                        return t;
                }
                tbh = &((*tbh)->next);
        }
        /* Round the buffer size out */
        size = (size + 0xFF) & ~0xFF;
-       return tty_buffer_alloc(tty, size);
+       return tty_buffer_alloc(port, size);
        /* Should possibly check if this fails for the largest buffer we
           have queued and recycle that ? */
 }
@@ -192,29 +200,31 @@ static struct tty_buffer *tty_buffer_find(struct tty_struct *tty, size_t size)
  *
  *     Make at least size bytes of linear space available for the tty
  *     buffer. If we fail return the size we managed to find.
- *      Locking: Caller must hold tty->buf.lock
+ *      Locking: Caller must hold port->buf.lock
  */
-static int __tty_buffer_request_room(struct tty_struct *tty, size_t size)
+static int __tty_buffer_request_room(struct tty_port *port, size_t size)
 {
+       struct tty_bufhead *buf = &port->buf;
        struct tty_buffer *b, *n;
        int left;
        /* OPTIMISATION: We could keep a per tty "zero" sized buffer to
           remove this conditional if its worth it. This would be invisible
           to the callers */
-       if ((b = tty->buf.tail) != NULL)
+       b = buf->tail;
+       if (b != NULL)
                left = b->size - b->used;
        else
                left = 0;
 
        if (left < size) {
                /* This is the slow path - looking for new buffers to use */
-               if ((n = tty_buffer_find(tty, size)) != NULL) {
+               if ((n = tty_buffer_find(port, size)) != NULL) {
                        if (b != NULL) {
                                b->next = n;
                                b->commit = b->used;
                        } else
-                               tty->buf.head = n;
-                       tty->buf.tail = n;
+                               buf->head = n;
+                       buf->tail = n;
                } else
                        size = left;
        }
@@ -231,16 +241,17 @@ static int __tty_buffer_request_room(struct tty_struct *tty, size_t size)
  *     Make at least size bytes of linear space available for the tty
  *     buffer. If we fail return the size we managed to find.
  *
- *     Locking: Takes tty->buf.lock
+ *     Locking: Takes port->buf.lock
  */
 int tty_buffer_request_room(struct tty_struct *tty, size_t size)
 {
+       struct tty_port *port = tty->port;
        unsigned long flags;
        int length;
 
-       spin_lock_irqsave(&tty->buf.lock, flags);
-       length = __tty_buffer_request_room(tty, size);
-       spin_unlock_irqrestore(&tty->buf.lock, flags);
+       spin_lock_irqsave(&port->buf.lock, flags);
+       length = __tty_buffer_request_room(port, size);
+       spin_unlock_irqrestore(&port->buf.lock, flags);
        return length;
 }
 EXPORT_SYMBOL_GPL(tty_buffer_request_room);
@@ -255,12 +266,13 @@ EXPORT_SYMBOL_GPL(tty_buffer_request_room);
  *     Queue a series of bytes to the tty buffering. All the characters
  *     passed are marked with the supplied flag. Returns the number added.
  *
- *     Locking: Called functions may take tty->buf.lock
+ *     Locking: Called functions may take port->buf.lock
  */
 
 int tty_insert_flip_string_fixed_flag(struct tty_struct *tty,
                const unsigned char *chars, char flag, size_t size)
 {
+       struct tty_bufhead *buf = &tty->port->buf;
        int copied = 0;
        do {
                int goal = min_t(size_t, size - copied, TTY_BUFFER_PAGE);
@@ -268,18 +280,18 @@ int tty_insert_flip_string_fixed_flag(struct tty_struct *tty,
                unsigned long flags;
                struct tty_buffer *tb;
 
-               spin_lock_irqsave(&tty->buf.lock, flags);
-               space = __tty_buffer_request_room(tty, goal);
-               tb = tty->buf.tail;
+               spin_lock_irqsave(&buf->lock, flags);
+               space = __tty_buffer_request_room(tty->port, goal);
+               tb = buf->tail;
                /* If there is no space then tb may be NULL */
                if (unlikely(space == 0)) {
-                       spin_unlock_irqrestore(&tty->buf.lock, flags);
+                       spin_unlock_irqrestore(&buf->lock, flags);
                        break;
                }
                memcpy(tb->char_buf_ptr + tb->used, chars, space);
                memset(tb->flag_buf_ptr + tb->used, flag, space);
                tb->used += space;
-               spin_unlock_irqrestore(&tty->buf.lock, flags);
+               spin_unlock_irqrestore(&buf->lock, flags);
                copied += space;
                chars += space;
                /* There is a small chance that we need to split the data over
@@ -300,12 +312,13 @@ EXPORT_SYMBOL(tty_insert_flip_string_fixed_flag);
  *     the flags array indicates the status of the character. Returns the
  *     number added.
  *
- *     Locking: Called functions may take tty->buf.lock
+ *     Locking: Called functions may take port->buf.lock
  */
 
 int tty_insert_flip_string_flags(struct tty_struct *tty,
                const unsigned char *chars, const char *flags, size_t size)
 {
+       struct tty_bufhead *buf = &tty->port->buf;
        int copied = 0;
        do {
                int goal = min_t(size_t, size - copied, TTY_BUFFER_PAGE);
@@ -313,18 +326,18 @@ int tty_insert_flip_string_flags(struct tty_struct *tty,
                unsigned long __flags;
                struct tty_buffer *tb;
 
-               spin_lock_irqsave(&tty->buf.lock, __flags);
-               space = __tty_buffer_request_room(tty, goal);
-               tb = tty->buf.tail;
+               spin_lock_irqsave(&buf->lock, __flags);
+               space = __tty_buffer_request_room(tty->port, goal);
+               tb = buf->tail;
                /* If there is no space then tb may be NULL */
                if (unlikely(space == 0)) {
-                       spin_unlock_irqrestore(&tty->buf.lock, __flags);
+                       spin_unlock_irqrestore(&buf->lock, __flags);
                        break;
                }
                memcpy(tb->char_buf_ptr + tb->used, chars, space);
                memcpy(tb->flag_buf_ptr + tb->used, flags, space);
                tb->used += space;
-               spin_unlock_irqrestore(&tty->buf.lock, __flags);
+               spin_unlock_irqrestore(&buf->lock, __flags);
                copied += space;
                chars += space;
                flags += space;
@@ -342,18 +355,23 @@ EXPORT_SYMBOL(tty_insert_flip_string_flags);
  *     Takes any pending buffers and transfers their ownership to the
  *     ldisc side of the queue. It then schedules those characters for
  *     processing by the line discipline.
+ *     Note that this function can only be used when the low_latency flag
+ *     is unset. Otherwise the workqueue won't be flushed.
  *
- *     Locking: Takes tty->buf.lock
+ *     Locking: Takes port->buf.lock
  */
 
 void tty_schedule_flip(struct tty_struct *tty)
 {
+       struct tty_bufhead *buf = &tty->port->buf;
        unsigned long flags;
-       spin_lock_irqsave(&tty->buf.lock, flags);
-       if (tty->buf.tail != NULL)
-               tty->buf.tail->commit = tty->buf.tail->used;
-       spin_unlock_irqrestore(&tty->buf.lock, flags);
-       schedule_work(&tty->buf.work);
+       WARN_ON(tty->low_latency);
+
+       spin_lock_irqsave(&buf->lock, flags);
+       if (buf->tail != NULL)
+               buf->tail->commit = buf->tail->used;
+       spin_unlock_irqrestore(&buf->lock, flags);
+       schedule_work(&buf->work);
 }
 EXPORT_SYMBOL(tty_schedule_flip);
 
@@ -369,26 +387,27 @@ EXPORT_SYMBOL(tty_schedule_flip);
  *     that need their own block copy routines into the buffer. There is no
  *     guarantee the buffer is a DMA target!
  *
- *     Locking: May call functions taking tty->buf.lock
+ *     Locking: May call functions taking port->buf.lock
  */
 
 int tty_prepare_flip_string(struct tty_struct *tty, unsigned char **chars,
-                                                               size_t size)
+               size_t size)
 {
+       struct tty_bufhead *buf = &tty->port->buf;
        int space;
        unsigned long flags;
        struct tty_buffer *tb;
 
-       spin_lock_irqsave(&tty->buf.lock, flags);
-       space = __tty_buffer_request_room(tty, size);
+       spin_lock_irqsave(&buf->lock, flags);
+       space = __tty_buffer_request_room(tty->port, size);
 
-       tb = tty->buf.tail;
+       tb = buf->tail;
        if (likely(space)) {
                *chars = tb->char_buf_ptr + tb->used;
                memset(tb->flag_buf_ptr + tb->used, TTY_NORMAL, space);
                tb->used += space;
        }
-       spin_unlock_irqrestore(&tty->buf.lock, flags);
+       spin_unlock_irqrestore(&buf->lock, flags);
        return space;
 }
 EXPORT_SYMBOL_GPL(tty_prepare_flip_string);
@@ -406,26 +425,27 @@ EXPORT_SYMBOL_GPL(tty_prepare_flip_string);
  *     that need their own block copy routines into the buffer. There is no
  *     guarantee the buffer is a DMA target!
  *
- *     Locking: May call functions taking tty->buf.lock
+ *     Locking: May call functions taking port->buf.lock
  */
 
 int tty_prepare_flip_string_flags(struct tty_struct *tty,
                        unsigned char **chars, char **flags, size_t size)
 {
+       struct tty_bufhead *buf = &tty->port->buf;
        int space;
        unsigned long __flags;
        struct tty_buffer *tb;
 
-       spin_lock_irqsave(&tty->buf.lock, __flags);
-       space = __tty_buffer_request_room(tty, size);
+       spin_lock_irqsave(&buf->lock, __flags);
+       space = __tty_buffer_request_room(tty->port, size);
 
-       tb = tty->buf.tail;
+       tb = buf->tail;
        if (likely(space)) {
                *chars = tb->char_buf_ptr + tb->used;
                *flags = tb->flag_buf_ptr + tb->used;
                tb->used += space;
        }
-       spin_unlock_irqrestore(&tty->buf.lock, __flags);
+       spin_unlock_irqrestore(&buf->lock, __flags);
        return space;
 }
 EXPORT_SYMBOL_GPL(tty_prepare_flip_string_flags);
@@ -446,20 +466,25 @@ EXPORT_SYMBOL_GPL(tty_prepare_flip_string_flags);
 
 static void flush_to_ldisc(struct work_struct *work)
 {
-       struct tty_struct *tty =
-               container_of(work, struct tty_struct, buf.work);
+       struct tty_port *port = container_of(work, struct tty_port, buf.work);
+       struct tty_bufhead *buf = &port->buf;
+       struct tty_struct *tty;
        unsigned long   flags;
        struct tty_ldisc *disc;
 
+       tty = port->itty;
+       if (WARN_RATELIMIT(tty == NULL, "tty is NULL"))
+               return;
+
        disc = tty_ldisc_ref(tty);
        if (disc == NULL)       /*  !TTY_LDISC */
                return;
 
-       spin_lock_irqsave(&tty->buf.lock, flags);
+       spin_lock_irqsave(&buf->lock, flags);
 
-       if (!test_and_set_bit(TTY_FLUSHING, &tty->flags)) {
+       if (!test_and_set_bit(TTYP_FLUSHING, &port->iflags)) {
                struct tty_buffer *head;
-               while ((head = tty->buf.head) != NULL) {
+               while ((head = buf->head) != NULL) {
                        int count;
                        char *char_buf;
                        unsigned char *flag_buf;
@@ -468,14 +493,14 @@ static void flush_to_ldisc(struct work_struct *work)
                        if (!count) {
                                if (head->next == NULL)
                                        break;
-                               tty->buf.head = head->next;
-                               tty_buffer_free(tty, head);
+                               buf->head = head->next;
+                               tty_buffer_free(port, head);
                                continue;
                        }
                        /* Ldisc or user is trying to flush the buffers
                           we are feeding to the ldisc, stop feeding the
                           line discipline as we want to empty the queue */
-                       if (test_bit(TTY_FLUSHPENDING, &tty->flags))
+                       if (test_bit(TTYP_FLUSHPENDING, &port->iflags))
                                break;
                        if (!tty->receive_room)
                                break;
@@ -484,22 +509,22 @@ static void flush_to_ldisc(struct work_struct *work)
                        char_buf = head->char_buf_ptr + head->read;
                        flag_buf = head->flag_buf_ptr + head->read;
                        head->read += count;
-                       spin_unlock_irqrestore(&tty->buf.lock, flags);
+                       spin_unlock_irqrestore(&buf->lock, flags);
                        disc->ops->receive_buf(tty, char_buf,
                                                        flag_buf, count);
-                       spin_lock_irqsave(&tty->buf.lock, flags);
+                       spin_lock_irqsave(&buf->lock, flags);
                }
-               clear_bit(TTY_FLUSHING, &tty->flags);
+               clear_bit(TTYP_FLUSHING, &port->iflags);
        }
 
        /* We may have a deferred request to flush the input buffer,
           if so pull the chain under the lock and empty the queue */
-       if (test_bit(TTY_FLUSHPENDING, &tty->flags)) {
-               __tty_buffer_flush(tty);
-               clear_bit(TTY_FLUSHPENDING, &tty->flags);
+       if (test_bit(TTYP_FLUSHPENDING, &port->iflags)) {
+               __tty_buffer_flush(port);
+               clear_bit(TTYP_FLUSHPENDING, &port->iflags);
                wake_up(&tty->read_wait);
        }
-       spin_unlock_irqrestore(&tty->buf.lock, flags);
+       spin_unlock_irqrestore(&buf->lock, flags);
 
        tty_ldisc_deref(disc);
 }
@@ -514,7 +539,8 @@ static void flush_to_ldisc(struct work_struct *work)
  */
 void tty_flush_to_ldisc(struct tty_struct *tty)
 {
-       flush_work(&tty->buf.work);
+       if (!tty->low_latency)
+               flush_work(&tty->port->buf.work);
 }
 
 /**
@@ -532,16 +558,18 @@ void tty_flush_to_ldisc(struct tty_struct *tty)
 
 void tty_flip_buffer_push(struct tty_struct *tty)
 {
+       struct tty_bufhead *buf = &tty->port->buf;
        unsigned long flags;
-       spin_lock_irqsave(&tty->buf.lock, flags);
-       if (tty->buf.tail != NULL)
-               tty->buf.tail->commit = tty->buf.tail->used;
-       spin_unlock_irqrestore(&tty->buf.lock, flags);
+
+       spin_lock_irqsave(&buf->lock, flags);
+       if (buf->tail != NULL)
+               buf->tail->commit = buf->tail->used;
+       spin_unlock_irqrestore(&buf->lock, flags);
 
        if (tty->low_latency)
-               flush_to_ldisc(&tty->buf.work);
+               flush_to_ldisc(&buf->work);
        else
-               schedule_work(&tty->buf.work);
+               schedule_work(&buf->work);
 }
 EXPORT_SYMBOL(tty_flip_buffer_push);
 
@@ -555,13 +583,15 @@ EXPORT_SYMBOL(tty_flip_buffer_push);
  *     Locking: none
  */
 
-void tty_buffer_init(struct tty_struct *tty)
+void tty_buffer_init(struct tty_port *port)
 {
-       spin_lock_init(&tty->buf.lock);
-       tty->buf.head = NULL;
-       tty->buf.tail = NULL;
-       tty->buf.free = NULL;
-       tty->buf.memory_used = 0;
-       INIT_WORK(&tty->buf.work, flush_to_ldisc);
+       struct tty_bufhead *buf = &port->buf;
+
+       spin_lock_init(&buf->lock);
+       buf->head = NULL;
+       buf->tail = NULL;
+       buf->free = NULL;
+       buf->memory_used = 0;
+       INIT_WORK(&buf->work, flush_to_ldisc);
 }
 
index 2ea176b2280e60f201aefec32af4beb8d7892702..a3eba7f359ed2b50ac3c3da6c7ec22384bd16732 100644 (file)
@@ -186,7 +186,6 @@ void free_tty_struct(struct tty_struct *tty)
        if (tty->dev)
                put_device(tty->dev);
        kfree(tty->write_buf);
-       tty_buffer_free_all(tty);
        tty->magic = 0xDEADDEAD;
        kfree(tty);
 }
@@ -1417,6 +1416,8 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx)
                        "%s: %s driver does not set tty->port. This will crash the kernel later. Fix the driver!\n",
                        __func__, tty->driver->name);
 
+       tty->port->itty = tty;
+
        /*
         * Structures all installed ... call the ldisc open routines.
         * If we fail here just call release_tty to clean up.  No need
@@ -1552,6 +1553,7 @@ static void release_tty(struct tty_struct *tty, int idx)
                tty->ops->shutdown(tty);
        tty_free_termios(tty);
        tty_driver_remove_tty(tty->driver, tty);
+       tty->port->itty = NULL;
 
        if (tty->link)
                tty_kref_put(tty->link);
@@ -1625,7 +1627,6 @@ int tty_release(struct inode *inode, struct file *filp)
        struct tty_struct *tty = file_tty(filp);
        struct tty_struct *o_tty;
        int     pty_master, tty_closing, o_tty_closing, do_sleep;
-       int     devpts;
        int     idx;
        char    buf[64];
 
@@ -1640,7 +1641,6 @@ int tty_release(struct inode *inode, struct file *filp)
        idx = tty->index;
        pty_master = (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
                      tty->driver->subtype == PTY_TYPE_MASTER);
-       devpts = (tty->driver->flags & TTY_DRIVER_DEVPTS_MEM) != 0;
        /* Review: parallel close */
        o_tty = tty->link;
 
@@ -1799,9 +1799,6 @@ int tty_release(struct inode *inode, struct file *filp)
        release_tty(tty, idx);
        mutex_unlock(&tty_mutex);
 
-       /* Make this pty number available for reallocation */
-       if (devpts)
-               devpts_kill_index(inode, idx);
        return 0;
 }
 
@@ -2937,19 +2934,13 @@ void initialize_tty_struct(struct tty_struct *tty,
        tty_ldisc_init(tty);
        tty->session = NULL;
        tty->pgrp = NULL;
-       tty->overrun_time = jiffies;
-       tty_buffer_init(tty);
        mutex_init(&tty->legacy_mutex);
        mutex_init(&tty->termios_mutex);
        mutex_init(&tty->ldisc_mutex);
        init_waitqueue_head(&tty->write_wait);
        init_waitqueue_head(&tty->read_wait);
        INIT_WORK(&tty->hangup_work, do_tty_hangup);
-       mutex_init(&tty->atomic_read_lock);
        mutex_init(&tty->atomic_write_lock);
-       mutex_init(&tty->output_lock);
-       mutex_init(&tty->echo_lock);
-       spin_lock_init(&tty->read_lock);
        spin_lock_init(&tty->ctrl_lock);
        INIT_LIST_HEAD(&tty->tty_files);
        INIT_WORK(&tty->SAK_work, do_SAK_work);
index 0f2a2c5e704c3560755069f1c102f6714e0ae4b6..c5782294e53261e701f13292b5732c231cfb9d14 100644 (file)
@@ -26,7 +26,7 @@
  *     callers who will do ldisc lookups and cannot sleep.
  */
 
-static DEFINE_SPINLOCK(tty_ldisc_lock);
+static DEFINE_RAW_SPINLOCK(tty_ldisc_lock);
 static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait);
 /* Line disc dispatch table */
 static struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS];
@@ -49,21 +49,21 @@ static void put_ldisc(struct tty_ldisc *ld)
         * If this is the last user, free the ldisc, and
         * release the ldisc ops.
         *
-        * We really want an "atomic_dec_and_lock_irqsave()",
+        * We really want an "atomic_dec_and_raw_lock_irqsave()",
         * but we don't have it, so this does it by hand.
         */
-       local_irq_save(flags);
-       if (atomic_dec_and_lock(&ld->users, &tty_ldisc_lock)) {
+       raw_spin_lock_irqsave(&tty_ldisc_lock, flags);
+       if (atomic_dec_and_test(&ld->users)) {
                struct tty_ldisc_ops *ldo = ld->ops;
 
                ldo->refcount--;
                module_put(ldo->owner);
-               spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+               raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags);
 
                kfree(ld);
                return;
        }
-       local_irq_restore(flags);
+       raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags);
        wake_up(&ld->wq_idle);
 }
 
@@ -88,11 +88,11 @@ int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc)
        if (disc < N_TTY || disc >= NR_LDISCS)
                return -EINVAL;
 
-       spin_lock_irqsave(&tty_ldisc_lock, flags);
+       raw_spin_lock_irqsave(&tty_ldisc_lock, flags);
        tty_ldiscs[disc] = new_ldisc;
        new_ldisc->num = disc;
        new_ldisc->refcount = 0;
-       spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+       raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags);
 
        return ret;
 }
@@ -118,12 +118,12 @@ int tty_unregister_ldisc(int disc)
        if (disc < N_TTY || disc >= NR_LDISCS)
                return -EINVAL;
 
-       spin_lock_irqsave(&tty_ldisc_lock, flags);
+       raw_spin_lock_irqsave(&tty_ldisc_lock, flags);
        if (tty_ldiscs[disc]->refcount)
                ret = -EBUSY;
        else
                tty_ldiscs[disc] = NULL;
-       spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+       raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags);
 
        return ret;
 }
@@ -134,7 +134,7 @@ static struct tty_ldisc_ops *get_ldops(int disc)
        unsigned long flags;
        struct tty_ldisc_ops *ldops, *ret;
 
-       spin_lock_irqsave(&tty_ldisc_lock, flags);
+       raw_spin_lock_irqsave(&tty_ldisc_lock, flags);
        ret = ERR_PTR(-EINVAL);
        ldops = tty_ldiscs[disc];
        if (ldops) {
@@ -144,7 +144,7 @@ static struct tty_ldisc_ops *get_ldops(int disc)
                        ret = ldops;
                }
        }
-       spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+       raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags);
        return ret;
 }
 
@@ -152,10 +152,10 @@ static void put_ldops(struct tty_ldisc_ops *ldops)
 {
        unsigned long flags;
 
-       spin_lock_irqsave(&tty_ldisc_lock, flags);
+       raw_spin_lock_irqsave(&tty_ldisc_lock, flags);
        ldops->refcount--;
        module_put(ldops->owner);
-       spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+       raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags);
 }
 
 /**
@@ -287,11 +287,11 @@ static struct tty_ldisc *tty_ldisc_try(struct tty_struct *tty)
        unsigned long flags;
        struct tty_ldisc *ld;
 
-       spin_lock_irqsave(&tty_ldisc_lock, flags);
+       raw_spin_lock_irqsave(&tty_ldisc_lock, flags);
        ld = NULL;
        if (test_bit(TTY_LDISC, &tty->flags))
                ld = get_ldisc(tty->ldisc);
-       spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+       raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags);
        return ld;
 }
 
@@ -512,7 +512,7 @@ static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old)
 static int tty_ldisc_halt(struct tty_struct *tty)
 {
        clear_bit(TTY_LDISC, &tty->flags);
-       return cancel_work_sync(&tty->buf.work);
+       return cancel_work_sync(&tty->port->buf.work);
 }
 
 /**
@@ -525,7 +525,7 @@ static void tty_ldisc_flush_works(struct tty_struct *tty)
 {
        flush_work(&tty->hangup_work);
        flush_work(&tty->SAK_work);
-       flush_work(&tty->buf.work);
+       flush_work(&tty->port->buf.work);
 }
 
 /**
@@ -704,9 +704,9 @@ enable:
        /* Restart the work queue in case no characters kick it off. Safe if
           already running */
        if (work)
-               schedule_work(&tty->buf.work);
+               schedule_work(&tty->port->buf.work);
        if (o_work)
-               schedule_work(&o_tty->buf.work);
+               schedule_work(&o_tty->port->buf.work);
        mutex_unlock(&tty->ldisc_mutex);
        tty_unlock(tty);
        return retval;
@@ -817,7 +817,7 @@ void tty_ldisc_hangup(struct tty_struct *tty)
         */
        clear_bit(TTY_LDISC, &tty->flags);
        tty_unlock(tty);
-       cancel_work_sync(&tty->buf.work);
+       cancel_work_sync(&tty->port->buf.work);
        mutex_unlock(&tty->ldisc_mutex);
 retry:
        tty_lock(tty);
@@ -897,6 +897,11 @@ int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty)
 
 static void tty_ldisc_kill(struct tty_struct *tty)
 {
+       /* There cannot be users from userspace now. But there still might be
+        * drivers holding a reference via tty_ldisc_ref. Do not steal them the
+        * ldisc until they are done. */
+       tty_ldisc_wait_idle(tty, MAX_SCHEDULE_TIMEOUT);
+
        mutex_lock(&tty->ldisc_mutex);
        /*
         * Now kill off the ldisc
index 67feac9e6ebbef7e224c47672bff95f7f511c5a2..2e41abebbcbaef923c38a4ea6c3cee56dd6fe9fd 100644 (file)
@@ -19,7 +19,7 @@ static void __lockfunc tty_lock_nested(struct tty_struct *tty,
                                       unsigned int subclass)
 {
        if (tty->magic != TTY_MAGIC) {
-               printk(KERN_ERR "L Bad %p\n", tty);
+               pr_err("L Bad %p\n", tty);
                WARN_ON(1);
                return;
        }
@@ -36,7 +36,7 @@ EXPORT_SYMBOL(tty_lock);
 void __lockfunc tty_unlock(struct tty_struct *tty)
 {
        if (tty->magic != TTY_MAGIC) {
-               printk(KERN_ERR "U Bad %p\n", tty);
+               pr_err("U Bad %p\n", tty);
                WARN_ON(1);
                return;
        }
index d7bdd8d0c23f0faa832aee87447af772958ceb13..416b42f7c346680067ea6eb8d4679421cf5596c8 100644 (file)
@@ -21,6 +21,7 @@
 void tty_port_init(struct tty_port *port)
 {
        memset(port, 0, sizeof(*port));
+       tty_buffer_init(port);
        init_waitqueue_head(&port->open_wait);
        init_waitqueue_head(&port->close_wait);
        init_waitqueue_head(&port->delta_msr_wait);
@@ -126,6 +127,7 @@ static void tty_port_destructor(struct kref *kref)
        struct tty_port *port = container_of(kref, struct tty_port, kref);
        if (port->xmit_buf)
                free_page((unsigned long)port->xmit_buf);
+       tty_buffer_free_all(port);
        if (port->ops->destruct)
                port->ops->destruct(port);
        else
index 8e9b4be97a2d202c4b1725ff44f97943627b132d..60b7b69260592e9b413b599dcf572117f8487450 100644 (file)
@@ -341,15 +341,11 @@ int paste_selection(struct tty_struct *tty)
        struct  tty_ldisc *ld;
        DECLARE_WAITQUEUE(wait, current);
 
-
        console_lock();
        poke_blanked_console();
        console_unlock();
 
-       /* FIXME: wtf is this supposed to achieve ? */
-       ld = tty_ldisc_ref(tty);
-       if (!ld)
-               ld = tty_ldisc_ref_wait(tty);
+       ld = tty_ldisc_ref_wait(tty);
 
        /* FIXME: this is completely unsafe */
        add_wait_queue(&vc->paste_wait, &wait);
@@ -361,8 +357,7 @@ int paste_selection(struct tty_struct *tty)
                }
                count = sel_buffer_lth - pasted;
                count = min(count, tty->receive_room);
-               tty->ldisc->ops->receive_buf(tty, sel_buffer + pasted,
-                                                               NULL, count);
+               ld->ops->receive_buf(tty, sel_buffer + pasted, NULL, count);
                pasted += count;
        }
        remove_wait_queue(&vc->paste_wait, &wait);
index 6f3ea9bbc818b3fc235ace278187341417dad32a..82e2b89d44803771c95e04b7a94fdb2a64e2db18 100644 (file)
@@ -44,6 +44,22 @@ config UIO_PDRV_GENIRQ
 
          If you don't know what to do here, say N.
 
+config UIO_DMEM_GENIRQ
+       tristate "Userspace platform driver with generic irq and dynamic memory"
+       help
+         Platform driver for Userspace I/O devices, including generic
+         interrupt handling code. Shared interrupts are not supported.
+
+         Memory regions can be specified with the same platform device
+         resources as the UIO_PDRV drivers, but dynamic regions can also
+         be specified.
+         The number and size of these regions is static,
+         but the memory allocation is not performed until
+         the associated device file is opened. The
+         memory is freed once the uio device is closed.
+
+         If you don't know what to do here, say N.
+
 config UIO_AEC
        tristate "AEC video timestamp device"
        depends on PCI
index d4dd9a5552f8ceb7c4c02acaeaff8e4299c05398..b354c539507ae0e43172c10ff55030b796bcbf68 100644 (file)
@@ -2,6 +2,7 @@ obj-$(CONFIG_UIO)       += uio.o
 obj-$(CONFIG_UIO_CIF)  += uio_cif.o
 obj-$(CONFIG_UIO_PDRV) += uio_pdrv.o
 obj-$(CONFIG_UIO_PDRV_GENIRQ)  += uio_pdrv_genirq.o
+obj-$(CONFIG_UIO_DMEM_GENIRQ)  += uio_dmem_genirq.o
 obj-$(CONFIG_UIO_AEC)  += uio_aec.o
 obj-$(CONFIG_UIO_SERCOS3)      += uio_sercos3.o
 obj-$(CONFIG_UIO_PCI_GENERIC)  += uio_pci_generic.o
diff --git a/drivers/uio/uio_dmem_genirq.c b/drivers/uio/uio_dmem_genirq.c
new file mode 100644 (file)
index 0000000..4d4dd00
--- /dev/null
@@ -0,0 +1,354 @@
+/*
+ * drivers/uio/uio_dmem_genirq.c
+ *
+ * Userspace I/O platform driver with generic IRQ handling code.
+ *
+ * Copyright (C) 2012 Damian Hobson-Garcia
+ *
+ * Based on uio_pdrv_genirq.c by Magnus Damm
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/uio_driver.h>
+#include <linux/spinlock.h>
+#include <linux/bitops.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/platform_data/uio_dmem_genirq.h>
+#include <linux/stringify.h>
+#include <linux/pm_runtime.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+
+#define DRIVER_NAME "uio_dmem_genirq"
+
+struct uio_dmem_genirq_platdata {
+       struct uio_info *uioinfo;
+       spinlock_t lock;
+       unsigned long flags;
+       struct platform_device *pdev;
+       unsigned int dmem_region_start;
+       unsigned int num_dmem_regions;
+       struct mutex alloc_lock;
+       unsigned int refcnt;
+};
+
+static int uio_dmem_genirq_open(struct uio_info *info, struct inode *inode)
+{
+       struct uio_dmem_genirq_platdata *priv = info->priv;
+       struct uio_mem *uiomem;
+       int ret = 0;
+
+       uiomem = &priv->uioinfo->mem[priv->dmem_region_start];
+
+       mutex_lock(&priv->alloc_lock);
+       while (!priv->refcnt && uiomem < &priv->uioinfo->mem[MAX_UIO_MAPS]) {
+               void *addr;
+               if (!uiomem->size)
+                       break;
+
+               addr = dma_alloc_coherent(&priv->pdev->dev, uiomem->size,
+                               (dma_addr_t *)&uiomem->addr, GFP_KERNEL);
+               if (!addr) {
+                       ret = -ENOMEM;
+                       break;
+               }
+
+               uiomem->internal_addr = addr;
+               ++uiomem;
+       }
+       priv->refcnt++;
+
+       mutex_unlock(&priv->alloc_lock);
+       /* Wait until the Runtime PM code has woken up the device */
+       pm_runtime_get_sync(&priv->pdev->dev);
+       return ret;
+}
+
+static int uio_dmem_genirq_release(struct uio_info *info, struct inode *inode)
+{
+       struct uio_dmem_genirq_platdata *priv = info->priv;
+       struct uio_mem *uiomem;
+
+       /* Tell the Runtime PM code that the device has become idle */
+       pm_runtime_put_sync(&priv->pdev->dev);
+
+       uiomem = &priv->uioinfo->mem[priv->dmem_region_start];
+
+       mutex_lock(&priv->alloc_lock);
+
+       priv->refcnt--;
+       while (!priv->refcnt && uiomem < &priv->uioinfo->mem[MAX_UIO_MAPS]) {
+               if (!uiomem->size)
+                       break;
+
+               dma_free_coherent(&priv->pdev->dev, uiomem->size,
+                               uiomem->internal_addr, uiomem->addr);
+               uiomem->addr = DMA_ERROR_CODE;
+               ++uiomem;
+       }
+
+       mutex_unlock(&priv->alloc_lock);
+       return 0;
+}
+
+static irqreturn_t uio_dmem_genirq_handler(int irq, struct uio_info *dev_info)
+{
+       struct uio_dmem_genirq_platdata *priv = dev_info->priv;
+
+       /* Just disable the interrupt in the interrupt controller, and
+        * remember the state so we can allow user space to enable it later.
+        */
+
+       if (!test_and_set_bit(0, &priv->flags))
+               disable_irq_nosync(irq);
+
+       return IRQ_HANDLED;
+}
+
+static int uio_dmem_genirq_irqcontrol(struct uio_info *dev_info, s32 irq_on)
+{
+       struct uio_dmem_genirq_platdata *priv = dev_info->priv;
+       unsigned long flags;
+
+       /* Allow user space to enable and disable the interrupt
+        * in the interrupt controller, but keep track of the
+        * state to prevent per-irq depth damage.
+        *
+        * Serialize this operation to support multiple tasks.
+        */
+
+       spin_lock_irqsave(&priv->lock, flags);
+       if (irq_on) {
+               if (test_and_clear_bit(0, &priv->flags))
+                       enable_irq(dev_info->irq);
+       } else {
+               if (!test_and_set_bit(0, &priv->flags))
+                       disable_irq(dev_info->irq);
+       }
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       return 0;
+}
+
+static int uio_dmem_genirq_probe(struct platform_device *pdev)
+{
+       struct uio_dmem_genirq_pdata *pdata = pdev->dev.platform_data;
+       struct uio_info *uioinfo = &pdata->uioinfo;
+       struct uio_dmem_genirq_platdata *priv;
+       struct uio_mem *uiomem;
+       int ret = -EINVAL;
+       int i;
+
+       if (!uioinfo) {
+               int irq;
+
+               /* alloc uioinfo for one device */
+               uioinfo = kzalloc(sizeof(*uioinfo), GFP_KERNEL);
+               if (!uioinfo) {
+                       ret = -ENOMEM;
+                       dev_err(&pdev->dev, "unable to kmalloc\n");
+                       goto bad2;
+               }
+               uioinfo->name = pdev->dev.of_node->name;
+               uioinfo->version = "devicetree";
+
+               /* Multiple IRQs are not supported */
+               irq = platform_get_irq(pdev, 0);
+               if (irq == -ENXIO)
+                       uioinfo->irq = UIO_IRQ_NONE;
+               else
+                       uioinfo->irq = irq;
+       }
+
+       if (!uioinfo || !uioinfo->name || !uioinfo->version) {
+               dev_err(&pdev->dev, "missing platform_data\n");
+               goto bad0;
+       }
+
+       if (uioinfo->handler || uioinfo->irqcontrol ||
+           uioinfo->irq_flags & IRQF_SHARED) {
+               dev_err(&pdev->dev, "interrupt configuration error\n");
+               goto bad0;
+       }
+
+       priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+       if (!priv) {
+               ret = -ENOMEM;
+               dev_err(&pdev->dev, "unable to kmalloc\n");
+               goto bad0;
+       }
+
+       dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
+
+       priv->uioinfo = uioinfo;
+       spin_lock_init(&priv->lock);
+       priv->flags = 0; /* interrupt is enabled to begin with */
+       priv->pdev = pdev;
+       mutex_init(&priv->alloc_lock);
+
+       if (!uioinfo->irq) {
+               ret = platform_get_irq(pdev, 0);
+               if (ret < 0) {
+                       dev_err(&pdev->dev, "failed to get IRQ\n");
+                       goto bad0;
+               }
+               uioinfo->irq = ret;
+       }
+       uiomem = &uioinfo->mem[0];
+
+       for (i = 0; i < pdev->num_resources; ++i) {
+               struct resource *r = &pdev->resource[i];
+
+               if (r->flags != IORESOURCE_MEM)
+                       continue;
+
+               if (uiomem >= &uioinfo->mem[MAX_UIO_MAPS]) {
+                       dev_warn(&pdev->dev, "device has more than "
+                                       __stringify(MAX_UIO_MAPS)
+                                       " I/O memory resources.\n");
+                       break;
+               }
+
+               uiomem->memtype = UIO_MEM_PHYS;
+               uiomem->addr = r->start;
+               uiomem->size = resource_size(r);
+               ++uiomem;
+       }
+
+       priv->dmem_region_start = i;
+       priv->num_dmem_regions = pdata->num_dynamic_regions;
+
+       for (i = 0; i < pdata->num_dynamic_regions; ++i) {
+               if (uiomem >= &uioinfo->mem[MAX_UIO_MAPS]) {
+                       dev_warn(&pdev->dev, "device has more than "
+                                       __stringify(MAX_UIO_MAPS)
+                                       " dynamic and fixed memory regions.\n");
+                       break;
+               }
+               uiomem->memtype = UIO_MEM_PHYS;
+               uiomem->addr = DMA_ERROR_CODE;
+               uiomem->size = pdata->dynamic_region_sizes[i];
+               ++uiomem;
+       }
+
+       while (uiomem < &uioinfo->mem[MAX_UIO_MAPS]) {
+               uiomem->size = 0;
+               ++uiomem;
+       }
+
+       /* This driver requires no hardware specific kernel code to handle
+        * interrupts. Instead, the interrupt handler simply disables the
+        * interrupt in the interrupt controller. User space is responsible
+        * for performing hardware specific acknowledge and re-enabling of
+        * the interrupt in the interrupt controller.
+        *
+        * Interrupt sharing is not supported.
+        */
+
+       uioinfo->handler = uio_dmem_genirq_handler;
+       uioinfo->irqcontrol = uio_dmem_genirq_irqcontrol;
+       uioinfo->open = uio_dmem_genirq_open;
+       uioinfo->release = uio_dmem_genirq_release;
+       uioinfo->priv = priv;
+
+       /* Enable Runtime PM for this device:
+        * The device starts in suspended state to allow the hardware to be
+        * turned off by default. The Runtime PM bus code should power on the
+        * hardware and enable clocks at open().
+        */
+       pm_runtime_enable(&pdev->dev);
+
+       ret = uio_register_device(&pdev->dev, priv->uioinfo);
+       if (ret) {
+               dev_err(&pdev->dev, "unable to register uio device\n");
+               goto bad1;
+       }
+
+       platform_set_drvdata(pdev, priv);
+       return 0;
+ bad1:
+       kfree(priv);
+       pm_runtime_disable(&pdev->dev);
+ bad0:
+       /* kfree uioinfo for OF */
+       if (pdev->dev.of_node)
+               kfree(uioinfo);
+ bad2:
+       return ret;
+}
+
+static int uio_dmem_genirq_remove(struct platform_device *pdev)
+{
+       struct uio_dmem_genirq_platdata *priv = platform_get_drvdata(pdev);
+
+       uio_unregister_device(priv->uioinfo);
+       pm_runtime_disable(&pdev->dev);
+
+       priv->uioinfo->handler = NULL;
+       priv->uioinfo->irqcontrol = NULL;
+
+       /* kfree uioinfo for OF */
+       if (pdev->dev.of_node)
+               kfree(priv->uioinfo);
+
+       kfree(priv);
+       return 0;
+}
+
+static int uio_dmem_genirq_runtime_nop(struct device *dev)
+{
+       /* Runtime PM callback shared between ->runtime_suspend()
+        * and ->runtime_resume(). Simply returns success.
+        *
+        * In this driver pm_runtime_get_sync() and pm_runtime_put_sync()
+        * are used at open() and release() time. This allows the
+        * Runtime PM code to turn off power to the device while the
+        * device is unused, ie before open() and after release().
+        *
+        * This Runtime PM callback does not need to save or restore
+        * any registers since user space is responsbile for hardware
+        * register reinitialization after open().
+        */
+       return 0;
+}
+
+static const struct dev_pm_ops uio_dmem_genirq_dev_pm_ops = {
+       .runtime_suspend = uio_dmem_genirq_runtime_nop,
+       .runtime_resume = uio_dmem_genirq_runtime_nop,
+};
+
+#ifdef CONFIG_OF
+static const struct of_device_id uio_of_genirq_match[] = {
+       { /* empty for now */ },
+};
+MODULE_DEVICE_TABLE(of, uio_of_genirq_match);
+#else
+# define uio_of_genirq_match NULL
+#endif
+
+static struct platform_driver uio_dmem_genirq = {
+       .probe = uio_dmem_genirq_probe,
+       .remove = uio_dmem_genirq_remove,
+       .driver = {
+               .name = DRIVER_NAME,
+               .owner = THIS_MODULE,
+               .pm = &uio_dmem_genirq_dev_pm_ops,
+               .of_match_table = uio_of_genirq_match,
+       },
+};
+
+module_platform_driver(uio_dmem_genirq);
+
+MODULE_AUTHOR("Damian Hobson-Garcia");
+MODULE_DESCRIPTION("Userspace I/O platform driver with dynamic memory.");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRIVER_NAME);
index 981f2132d1283c44234f4fa79466c4d11241c94e..6e49ec6f3adcaeae67898e53cc1c5eb6cd62b756 100644 (file)
@@ -817,10 +817,6 @@ static const __u32 acm_tty_speed[] = {
        2500000, 3000000, 3500000, 4000000
 };
 
-static const __u8 acm_tty_size[] = {
-       5, 6, 7, 8
-};
-
 static void acm_tty_set_termios(struct tty_struct *tty,
                                                struct ktermios *termios_old)
 {
@@ -834,7 +830,21 @@ static void acm_tty_set_termios(struct tty_struct *tty,
        newline.bParityType = termios->c_cflag & PARENB ?
                                (termios->c_cflag & PARODD ? 1 : 2) +
                                (termios->c_cflag & CMSPAR ? 2 : 0) : 0;
-       newline.bDataBits = acm_tty_size[(termios->c_cflag & CSIZE) >> 4];
+       switch (termios->c_cflag & CSIZE) {
+       case CS5:
+               newline.bDataBits = 5;
+               break;
+       case CS6:
+               newline.bDataBits = 6;
+               break;
+       case CS7:
+               newline.bDataBits = 7;
+               break;
+       case CS8:
+       default:
+               newline.bDataBits = 8;
+               break;
+       }
        /* FIXME: Needs to clear unsupported bits in the termios */
        acm->clocal = ((termios->c_cflag & CLOCAL) != 0);
 
@@ -1233,7 +1243,7 @@ made_compressed_probe:
 
                if (usb_endpoint_xfer_int(epwrite))
                        usb_fill_int_urb(snd->urb, usb_dev,
-                               usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress),
+                               usb_sndintpipe(usb_dev, epwrite->bEndpointAddress),
                                NULL, acm->writesize, acm_write_bulk, snd, epwrite->bInterval);
                else
                        usb_fill_bulk_urb(snd->urb, usb_dev,
index f460de31aceee80200ff9e91f514917bae9f7adc..cbacea933b18cbc9c6287acec62f465495569b1e 100644 (file)
@@ -591,16 +591,14 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes,
 
        /* Now look at all of this device's children. */
        usb_hub_for_each_child(usbdev, chix, childdev) {
-               if (childdev) {
-                       usb_lock_device(childdev);
-                       ret = usb_device_dump(buffer, nbytes, skip_bytes,
-                                             file_offset, childdev, bus,
-                                             level + 1, chix - 1, ++cnt);
-                       usb_unlock_device(childdev);
-                       if (ret == -EFAULT)
-                               return total_written;
-                       total_written += ret;
-               }
+               usb_lock_device(childdev);
+               ret = usb_device_dump(buffer, nbytes, skip_bytes,
+                                     file_offset, childdev, bus,
+                                     level + 1, chix - 1, ++cnt);
+               usb_unlock_device(childdev);
+               if (ret == -EFAULT)
+                       return total_written;
+               total_written += ret;
        }
        return total_written;
 }
index e0356cb859b5910eaaf5aa6e0b324808c56f4c0a..b78fbe222b72c2e3bc662973e9f9f08941ce2628 100644 (file)
@@ -1348,6 +1348,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
                                        ret = -EFAULT;
                                        goto error;
                                }
+                               uurb->buffer += u;
                        }
                        totlen -= u;
                }
index ddd820d25288b57da71336bf4eed397a4cc16410..6056db7af410fac833ed00d8c5f793773f628931 100644 (file)
@@ -367,6 +367,10 @@ static int usb_probe_interface(struct device *dev)
        intf->condition = USB_INTERFACE_UNBOUND;
        usb_cancel_queued_reset(intf);
 
+       /* If the LPM disable succeeded, balance the ref counts. */
+       if (!lpm_disable_error)
+               usb_unlocked_enable_lpm(udev);
+
        /* Unbound interfaces are always runtime-PM-disabled and -suspended */
        if (driver->supports_autosuspend)
                pm_runtime_disable(dev);
index 1e741bca02652e8f4ed2b027654abc3ac9d16a4f..eaa14514e173163bf46aba9dd65cddaa57fb85fd 100644 (file)
@@ -2039,8 +2039,9 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg)
        status = hcd->driver->bus_resume(hcd);
        clear_bit(HCD_FLAG_WAKEUP_PENDING, &hcd->flags);
        if (status == 0) {
-               /* TRSMRCY = 10 msec */
-               msleep(10);
+               struct usb_device *udev;
+               int port1;
+
                spin_lock_irq(&hcd_root_hub_lock);
                if (!HCD_DEAD(hcd)) {
                        usb_set_device_state(rhdev, rhdev->actconfig
@@ -2050,6 +2051,20 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg)
                        hcd->state = HC_STATE_RUNNING;
                }
                spin_unlock_irq(&hcd_root_hub_lock);
+
+               /*
+                * Check whether any of the enabled ports on the root hub are
+                * unsuspended.  If they are then a TRSMRCY delay is needed
+                * (this is what the USB-2 spec calls a "global resume").
+                * Otherwise we can skip the delay.
+                */
+               usb_hub_for_each_child(rhdev, port1, udev) {
+                       if (udev->state != USB_STATE_NOTATTACHED &&
+                                       !udev->port_is_suspended) {
+                               usleep_range(10000, 11000);     /* TRSMRCY */
+                               break;
+                       }
+               }
        } else {
                hcd->state = old_state;
                dev_dbg(&rhdev->dev, "bus %s fail, err %d\n",
index 673ee46962621e8013b102f2876c918bfa1d56f0..c585a188bb18ac6a8f0c574684d994b4501cc38f 100644 (file)
@@ -739,13 +739,16 @@ static void hub_tt_work(struct work_struct *work)
        int                     limit = 100;
 
        spin_lock_irqsave (&hub->tt.lock, flags);
-       while (--limit && !list_empty (&hub->tt.clear_list)) {
+       while (!list_empty(&hub->tt.clear_list)) {
                struct list_head        *next;
                struct usb_tt_clear     *clear;
                struct usb_device       *hdev = hub->hdev;
                const struct hc_driver  *drv;
                int                     status;
 
+               if (!hub->quiescing && --limit < 0)
+                       break;
+
                next = hub->tt.clear_list.next;
                clear = list_entry (next, struct usb_tt_clear, clear_list);
                list_del (&clear->clear_list);
@@ -1210,7 +1213,7 @@ static void hub_quiesce(struct usb_hub *hub, enum hub_quiescing_type type)
        if (hub->has_indicators)
                cancel_delayed_work_sync(&hub->leds);
        if (hub->tt.hub)
-               cancel_work_sync(&hub->tt.clear_work);
+               flush_work(&hub->tt.clear_work);
 }
 
 /* caller has locked the hub device */
@@ -2876,6 +2879,7 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
                                (PMSG_IS_AUTO(msg) ? "auto-" : ""),
                                udev->do_remote_wakeup);
                usb_set_device_state(udev, USB_STATE_SUSPENDED);
+               udev->port_is_suspended = 1;
                msleep(10);
        }
        usb_mark_last_busy(hub->hdev);
@@ -3040,6 +3044,7 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)
 
  SuspendCleared:
        if (status == 0) {
+               udev->port_is_suspended = 0;
                if (hub_is_superspeed(hub->hdev)) {
                        if (portchange & USB_PORT_STAT_C_LINK_STATE)
                                clear_port_feature(hub->hdev, port1,
@@ -3241,8 +3246,7 @@ static int usb_req_set_sel(struct usb_device *udev, enum usb3_link_state state)
                        (state == USB3_LPM_U2 &&
                         (u2_sel > USB3_LPM_MAX_U2_SEL_PEL ||
                          u2_pel > USB3_LPM_MAX_U2_SEL_PEL))) {
-               dev_dbg(&udev->dev, "Device-initiated %s disabled due "
-                               "to long SEL %llu ms or PEL %llu ms\n",
+               dev_dbg(&udev->dev, "Device-initiated %s disabled due to long SEL %llu us or PEL %llu us\n",
                                usb3_lpm_names[state], u1_sel, u1_pel);
                return -EINVAL;
        }
@@ -3319,16 +3323,6 @@ static int usb_set_device_initiated_lpm(struct usb_device *udev,
        }
 
        if (enable) {
-               /*
-                * First, let the device know about the exit latencies
-                * associated with the link state we're about to enable.
-                */
-               ret = usb_req_set_sel(udev, state);
-               if (ret < 0) {
-                       dev_warn(&udev->dev, "Set SEL for device-initiated "
-                                       "%s failed.\n", usb3_lpm_names[state]);
-                       return -EBUSY;
-               }
                /*
                 * Now send the control transfer to enable device-initiated LPM
                 * for either U1 or U2.
@@ -3414,7 +3408,28 @@ static int usb_set_lpm_timeout(struct usb_device *udev,
 static void usb_enable_link_state(struct usb_hcd *hcd, struct usb_device *udev,
                enum usb3_link_state state)
 {
-       int timeout;
+       int timeout, ret;
+       __u8 u1_mel = udev->bos->ss_cap->bU1devExitLat;
+       __le16 u2_mel = udev->bos->ss_cap->bU2DevExitLat;
+
+       /* If the device says it doesn't have *any* exit latency to come out of
+        * U1 or U2, it's probably lying.  Assume it doesn't implement that link
+        * state.
+        */
+       if ((state == USB3_LPM_U1 && u1_mel == 0) ||
+                       (state == USB3_LPM_U2 && u2_mel == 0))
+               return;
+
+       /*
+        * First, let the device know about the exit latencies
+        * associated with the link state we're about to enable.
+        */
+       ret = usb_req_set_sel(udev, state);
+       if (ret < 0) {
+               dev_warn(&udev->dev, "Set SEL for device-initiated %s failed.\n",
+                               usb3_lpm_names[state]);
+               return;
+       }
 
        /* We allow the host controller to set the U1/U2 timeout internally
         * first, so that it can change its schedule to account for the
index 9d912bfdcffe0e5a47f58c685688e0bcf31547bf..3662287e2f4feadd4876fad2d37072f70c065fce 100644 (file)
@@ -214,9 +214,25 @@ EXPORT_SYMBOL_GPL(usb_unanchor_urb);
  * urb->interval is modified to reflect the actual transfer period used
  * (normally some power of two units).  And for isochronous urbs,
  * urb->start_frame is modified to reflect when the URB's transfers were
- * scheduled to start.  Not all isochronous transfer scheduling policies
- * will work, but most host controller drivers should easily handle ISO
- * queues going from now until 10-200 msec into the future.
+ * scheduled to start.
+ *
+ * Not all isochronous transfer scheduling policies will work, but most
+ * host controller drivers should easily handle ISO queues going from now
+ * until 10-200 msec into the future.  Drivers should try to keep at
+ * least one or two msec of data in the queue; many controllers require
+ * that new transfers start at least 1 msec in the future when they are
+ * added.  If the driver is unable to keep up and the queue empties out,
+ * the behavior for new submissions is governed by the URB_ISO_ASAP flag.
+ * If the flag is set, or if the queue is idle, then the URB is always
+ * assigned to the first available (and not yet expired) slot in the
+ * endpoint's schedule.  If the flag is not set and the queue is active
+ * then the URB is always assigned to the next slot in the schedule
+ * following the end of the endpoint's previous URB, even if that slot is
+ * in the past.  When a packet is assigned in this way to a slot that has
+ * already expired, the packet is not transmitted and the corresponding
+ * usb_iso_packet_descriptor's status field will return -EXDEV.  If this
+ * would happen to all the packets in the URB, submission fails with a
+ * -EXDEV error code.
  *
  * For control endpoints, the synchronous usb_control_msg() call is
  * often used (in non-interrupt context) instead of this call.
index cd8fb44a3e164030ffe59a38a0af0baa42371051..7d3de09a82e4ae70a51173dbacbb7fe81e07fadb 100644 (file)
@@ -370,14 +370,14 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent,
                                 struct usb_bus *bus, unsigned port1)
 {
        struct usb_device *dev;
-       struct usb_hcd *usb_hcd = container_of(bus, struct usb_hcd, self);
+       struct usb_hcd *usb_hcd = bus_to_hcd(bus);
        unsigned root_hub = 0;
 
        dev = kzalloc(sizeof(*dev), GFP_KERNEL);
        if (!dev)
                return NULL;
 
-       if (!usb_get_hcd(bus_to_hcd(bus))) {
+       if (!usb_get_hcd(usb_hcd)) {
                kfree(dev);
                return NULL;
        }
index b415c0c859d3d2b3e990fc571b57d4e6e88f81fd..c14ebc975ba422028b663b4b90ac6e605c1c6115 100644 (file)
@@ -409,6 +409,10 @@ static void dwc3_core_exit(struct dwc3 *dwc)
 {
        dwc3_event_buffers_cleanup(dwc);
        dwc3_free_event_buffers(dwc);
+
+       usb_phy_shutdown(dwc->usb2_phy);
+       usb_phy_shutdown(dwc->usb3_phy);
+
 }
 
 #define DWC3_ALIGN_MASK                (16 - 1)
index c9e729a4bf6562876ba58b1776ce235ecc5ca5ed..7b7deddf6a52a264f02b7d47fa84d1916c461e6f 100644 (file)
@@ -1904,7 +1904,7 @@ static void dwc3_stop_active_transfer(struct dwc3 *dwc, u32 epnum)
        ret = dwc3_send_gadget_ep_cmd(dwc, dep->number, cmd, &params);
        WARN_ON_ONCE(ret);
        dep->resource_index = 0;
-
+       dep->flags &= ~DWC3_EP_BUSY;
        udelay(100);
 }
 
index dfb51a45496c10cbaa2d930ae6a6f45ffb9860a4..e0ff51b895296ab66988e509bd6b73d94a663701 100644 (file)
@@ -952,6 +952,7 @@ endif
 config USB_G_WEBCAM
        tristate "USB Webcam Gadget"
        depends on VIDEO_DEV
+       select USB_LIBCOMPOSITE
        help
          The Webcam Gadget acts as a composite USB Audio and Video Class
          device. It provides a userspace API to process UVC control requests
index f696fb9b136ded4b8c32ba8b360ef2550551f73d..21a9861dabf0a9660a3c1cf74f04d055fbb0b649 100644 (file)
@@ -2930,10 +2930,10 @@ static void vbus_work(struct work_struct *work)
 
                /* Get the VBUS status from the transceiver */
                value = i2c_smbus_read_byte_data(udc->isp1301_i2c_client,
-                                                ISP1301_I2C_OTG_CONTROL_2);
+                                                ISP1301_I2C_INTERRUPT_SOURCE);
 
                /* VBUS on or off? */
-               if (value & OTG_B_SESS_VLD)
+               if (value & INT_SESS_VLD)
                        udc->vbus = 1;
                else
                        udc->vbus = 0;
index 43ac7482fa9184dbd4748d42d6a6008e21f330ef..c009263a47e3250951fc1b16cab143ba0934eb86 100644 (file)
@@ -2069,8 +2069,10 @@ static irqreturn_t net2272_irq(int irq, void *_dev)
 #if defined(PLX_PCI_RDK2)
        /* see if PCI int for us by checking irqstat */
        intcsr = readl(dev->rdk2.fpga_base_addr + RDK2_IRQSTAT);
-       if (!intcsr & (1 << NET2272_PCI_IRQ))
+       if (!intcsr & (1 << NET2272_PCI_IRQ)) {
+               spin_unlock(&dev->lock);
                return IRQ_NONE;
+       }
        /* check dma interrupts */
 #endif
        /* Platform/devcice interrupt handler */
index 3f1431d37e1c836f88b32aff5b002fb9cf4efa0b..8cc06f054c6a3bfa32ebf1ee0af333849feb1b05 100644 (file)
@@ -215,9 +215,13 @@ config USB_W90X900_EHCI
                Enables support for the W90X900 USB controller
 
 config USB_CNS3XXX_EHCI
-       bool "Cavium CNS3XXX EHCI Module"
+       bool "Cavium CNS3XXX EHCI Module (DEPRECATED)"
        depends on USB_EHCI_HCD && ARCH_CNS3XXX
+       select USB_EHCI_HCD_PLATFORM
        ---help---
+         This option is deprecated now and the driver was removed, use
+         USB_EHCI_HCD_PLATFORM instead.
+
          Enable support for the CNS3XXX SOC's on-chip EHCI controller.
          It is needed for high-speed (480Mbit/sec) USB 2.0 device
          support.
@@ -333,16 +337,6 @@ config USB_OHCI_ATH79
          Enables support for the built-in OHCI controller present on the
          Atheros AR71XX/AR7240 SoCs.
 
-config USB_OHCI_HCD_PPC_SOC
-       bool "OHCI support for on-chip PPC USB controller"
-       depends on USB_OHCI_HCD && (STB03xxx || PPC_MPC52xx)
-       default y
-       select USB_OHCI_BIG_ENDIAN_DESC
-       select USB_OHCI_BIG_ENDIAN_MMIO
-       ---help---
-         Enables support for the USB controller on the MPC52xx or
-         STB03xxx processor chip.  If unsure, say Y.
-
 config USB_OHCI_HCD_PPC_OF_BE
        bool "OHCI support for OF platform bus (big endian)"
        depends on USB_OHCI_HCD && PPC_OF
@@ -393,9 +387,13 @@ config USB_OHCI_HCD_SSB
          If unsure, say N.
 
 config USB_OHCI_SH
-       bool "OHCI support for SuperH USB controller"
+       bool "OHCI support for SuperH USB controller (DEPRECATED)"
        depends on USB_OHCI_HCD && SUPERH
+       select USB_OHCI_HCD_PLATFORM
        ---help---
+         This option is deprecated now and the driver was removed, use
+         USB_OHCI_HCD_PLATFORM instead.
+
          Enables support for the on-chip OHCI controller on the SuperH.
          If you use the PCI OHCI controller, this option is not necessary.
 
@@ -406,9 +404,13 @@ config USB_OHCI_EXYNOS
         Enable support for the Samsung Exynos SOC's on-chip OHCI controller.
 
 config USB_CNS3XXX_OHCI
-       bool "Cavium CNS3XXX OHCI Module"
+       bool "Cavium CNS3XXX OHCI Module (DEPRECATED)"
        depends on USB_OHCI_HCD && ARCH_CNS3XXX
+       select USB_OHCI_HCD_PLATFORM
        ---help---
+         This option is deprecated now and the driver was removed, use
+         USB_OHCI_HCD_PLATFORM instead.
+
          Enable support for the CNS3XXX SOC's on-chip OHCI controller.
          It is needed for low-speed USB 1.0 device support.
 
index 9e0a89ced15cb3aa6d699aabd5be7a34df9e53c0..332ed897a6fbd4706d8101d5f013fe67c0e48b03 100644 (file)
@@ -40,6 +40,5 @@ obj-$(CONFIG_USB_HWA_HCD)     += hwa-hc.o
 obj-$(CONFIG_USB_IMX21_HCD)    += imx21-hcd.o
 obj-$(CONFIG_USB_FSL_MPH_DR_OF)        += fsl-mph-dr-of.o
 obj-$(CONFIG_USB_OCTEON2_COMMON) += octeon2-common.o
-obj-$(CONFIG_MIPS_ALCHEMY)     += alchemy-common.o
 obj-$(CONFIG_USB_HCD_BCMA)     += bcma-hcd.o
 obj-$(CONFIG_USB_HCD_SSB)      += ssb-hcd.o
diff --git a/drivers/usb/host/ehci-au1xxx.c b/drivers/usb/host/ehci-au1xxx.c
deleted file mode 100644 (file)
index 65c945e..0000000
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * EHCI HCD (Host Controller Driver) for USB.
- *
- * Bus Glue for AMD Alchemy Au1xxx
- *
- * Based on "ohci-au1xxx.c" by Matt Porter <mporter@kernel.crashing.org>
- *
- * Modified for AMD Alchemy Au1200 EHC
- *  by K.Boge <karsten.boge@amd.com>
- *
- * This file is licenced under the GPL.
- */
-
-#include <linux/platform_device.h>
-#include <asm/mach-au1x00/au1000.h>
-
-
-extern int usb_disabled(void);
-
-static int au1xxx_ehci_setup(struct usb_hcd *hcd)
-{
-       struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-       int ret;
-
-       ehci->caps = hcd->regs;
-       ret = ehci_setup(hcd);
-
-       ehci->need_io_watchdog = 0;
-       return ret;
-}
-
-static const struct hc_driver ehci_au1xxx_hc_driver = {
-       .description            = hcd_name,
-       .product_desc           = "Au1xxx EHCI",
-       .hcd_priv_size          = sizeof(struct ehci_hcd),
-
-       /*
-        * generic hardware linkage
-        */
-       .irq                    = ehci_irq,
-       .flags                  = HCD_MEMORY | HCD_USB2,
-
-       /*
-        * basic lifecycle operations
-        *
-        * FIXME -- ehci_init() doesn't do enough here.
-        * See ehci-ppc-soc for a complete implementation.
-        */
-       .reset                  = au1xxx_ehci_setup,
-       .start                  = ehci_run,
-       .stop                   = ehci_stop,
-       .shutdown               = ehci_shutdown,
-
-       /*
-        * managing i/o requests and associated device resources
-        */
-       .urb_enqueue            = ehci_urb_enqueue,
-       .urb_dequeue            = ehci_urb_dequeue,
-       .endpoint_disable       = ehci_endpoint_disable,
-       .endpoint_reset         = ehci_endpoint_reset,
-
-       /*
-        * scheduling support
-        */
-       .get_frame_number       = ehci_get_frame,
-
-       /*
-        * root hub support
-        */
-       .hub_status_data        = ehci_hub_status_data,
-       .hub_control            = ehci_hub_control,
-       .bus_suspend            = ehci_bus_suspend,
-       .bus_resume             = ehci_bus_resume,
-       .relinquish_port        = ehci_relinquish_port,
-       .port_handed_over       = ehci_port_handed_over,
-
-       .clear_tt_buffer_complete       = ehci_clear_tt_buffer_complete,
-};
-
-static int ehci_hcd_au1xxx_drv_probe(struct platform_device *pdev)
-{
-       struct usb_hcd *hcd;
-       struct resource *res;
-       int ret;
-
-       if (usb_disabled())
-               return -ENODEV;
-
-       if (pdev->resource[1].flags != IORESOURCE_IRQ) {
-               pr_debug("resource[1] is not IORESOURCE_IRQ");
-               return -ENOMEM;
-       }
-       hcd = usb_create_hcd(&ehci_au1xxx_hc_driver, &pdev->dev, "Au1xxx");
-       if (!hcd)
-               return -ENOMEM;
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       hcd->rsrc_start = res->start;
-       hcd->rsrc_len = resource_size(res);
-
-       hcd->regs = devm_request_and_ioremap(&pdev->dev, res);
-       if (!hcd->regs) {
-               pr_debug("devm_request_and_ioremap failed");
-               ret = -ENOMEM;
-               goto err1;
-       }
-
-       if (alchemy_usb_control(ALCHEMY_USB_EHCI0, 1)) {
-               printk(KERN_INFO "%s: controller init failed!\n", pdev->name);
-               ret = -ENODEV;
-               goto err1;
-       }
-
-       ret = usb_add_hcd(hcd, pdev->resource[1].start,
-                         IRQF_SHARED);
-       if (ret == 0) {
-               platform_set_drvdata(pdev, hcd);
-               return ret;
-       }
-
-       alchemy_usb_control(ALCHEMY_USB_EHCI0, 0);
-err1:
-       usb_put_hcd(hcd);
-       return ret;
-}
-
-static int ehci_hcd_au1xxx_drv_remove(struct platform_device *pdev)
-{
-       struct usb_hcd *hcd = platform_get_drvdata(pdev);
-
-       usb_remove_hcd(hcd);
-       alchemy_usb_control(ALCHEMY_USB_EHCI0, 0);
-       usb_put_hcd(hcd);
-       platform_set_drvdata(pdev, NULL);
-
-       return 0;
-}
-
-#ifdef CONFIG_PM
-static int ehci_hcd_au1xxx_drv_suspend(struct device *dev)
-{
-       struct usb_hcd *hcd = dev_get_drvdata(dev);
-       bool do_wakeup = device_may_wakeup(dev);
-       int rc;
-
-       rc = ehci_suspend(hcd, do_wakeup);
-       alchemy_usb_control(ALCHEMY_USB_EHCI0, 0);
-
-       return rc;
-}
-
-static int ehci_hcd_au1xxx_drv_resume(struct device *dev)
-{
-       struct usb_hcd *hcd = dev_get_drvdata(dev);
-
-       alchemy_usb_control(ALCHEMY_USB_EHCI0, 1);
-       ehci_resume(hcd, false);
-
-       return 0;
-}
-
-static const struct dev_pm_ops au1xxx_ehci_pmops = {
-       .suspend        = ehci_hcd_au1xxx_drv_suspend,
-       .resume         = ehci_hcd_au1xxx_drv_resume,
-};
-
-#define AU1XXX_EHCI_PMOPS &au1xxx_ehci_pmops
-
-#else
-#define AU1XXX_EHCI_PMOPS NULL
-#endif
-
-static struct platform_driver ehci_hcd_au1xxx_driver = {
-       .probe          = ehci_hcd_au1xxx_drv_probe,
-       .remove         = ehci_hcd_au1xxx_drv_remove,
-       .shutdown       = usb_hcd_platform_shutdown,
-       .driver = {
-               .name   = "au1xxx-ehci",
-               .owner  = THIS_MODULE,
-               .pm     = AU1XXX_EHCI_PMOPS,
-       }
-};
-
-MODULE_ALIAS("platform:au1xxx-ehci");
diff --git a/drivers/usb/host/ehci-cns3xxx.c b/drivers/usb/host/ehci-cns3xxx.c
deleted file mode 100644 (file)
index d91708d..0000000
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright 2008 Cavium Networks
- *
- * This file is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License, Version 2, as
- * published by the Free Software Foundation.
- */
-
-#include <linux/platform_device.h>
-#include <linux/atomic.h>
-#include <mach/cns3xxx.h>
-#include <mach/pm.h>
-
-static int cns3xxx_ehci_init(struct usb_hcd *hcd)
-{
-       struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-       int retval;
-
-       /*
-        * EHCI and OHCI share the same clock and power,
-        * resetting twice would cause the 1st controller been reset.
-        * Therefore only do power up  at the first up device, and
-        * power down at the last down device.
-        *
-        * Set USB AHB INCR length to 16
-        */
-       if (atomic_inc_return(&usb_pwr_ref) == 1) {
-               cns3xxx_pwr_power_up(1 << PM_PLL_HM_PD_CTRL_REG_OFFSET_PLL_USB);
-               cns3xxx_pwr_clk_en(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST);
-               cns3xxx_pwr_soft_rst(1 << PM_SOFT_RST_REG_OFFST_USB_HOST);
-               __raw_writel((__raw_readl(MISC_CHIP_CONFIG_REG) | (0X2 << 24)),
-                       MISC_CHIP_CONFIG_REG);
-       }
-
-       ehci->caps = hcd->regs;
-
-       hcd->has_tt = 0;
-
-       retval = ehci_setup(hcd);
-       if (retval)
-               return retval;
-
-       ehci_port_power(ehci, 0);
-
-       return retval;
-}
-
-static const struct hc_driver cns3xxx_ehci_hc_driver = {
-       .description            = hcd_name,
-       .product_desc           = "CNS3XXX EHCI Host Controller",
-       .hcd_priv_size          = sizeof(struct ehci_hcd),
-       .irq                    = ehci_irq,
-       .flags                  = HCD_MEMORY | HCD_USB2,
-       .reset                  = cns3xxx_ehci_init,
-       .start                  = ehci_run,
-       .stop                   = ehci_stop,
-       .shutdown               = ehci_shutdown,
-       .urb_enqueue            = ehci_urb_enqueue,
-       .urb_dequeue            = ehci_urb_dequeue,
-       .endpoint_disable       = ehci_endpoint_disable,
-       .endpoint_reset         = ehci_endpoint_reset,
-       .get_frame_number       = ehci_get_frame,
-       .hub_status_data        = ehci_hub_status_data,
-       .hub_control            = ehci_hub_control,
-#ifdef CONFIG_PM
-       .bus_suspend            = ehci_bus_suspend,
-       .bus_resume             = ehci_bus_resume,
-#endif
-       .relinquish_port        = ehci_relinquish_port,
-       .port_handed_over       = ehci_port_handed_over,
-
-       .clear_tt_buffer_complete       = ehci_clear_tt_buffer_complete,
-};
-
-static int cns3xxx_ehci_probe(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-       struct usb_hcd *hcd;
-       const struct hc_driver *driver = &cns3xxx_ehci_hc_driver;
-       struct resource *res;
-       int irq;
-       int retval;
-
-       if (usb_disabled())
-               return -ENODEV;
-
-       res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-       if (!res) {
-               dev_err(dev, "Found HC with no IRQ.\n");
-               return -ENODEV;
-       }
-       irq = res->start;
-
-       hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
-       if (!hcd)
-               return -ENOMEM;
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(dev, "Found HC with no register addr.\n");
-               retval = -ENODEV;
-               goto err1;
-       }
-
-       hcd->rsrc_start = res->start;
-       hcd->rsrc_len = resource_size(res);
-
-       hcd->regs = devm_request_and_ioremap(&pdev->dev, res);
-       if (hcd->regs == NULL) {
-               dev_dbg(dev, "error mapping memory\n");
-               retval = -EFAULT;
-               goto err1;
-       }
-
-       retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
-       if (retval == 0)
-               return retval;
-
-err1:
-       usb_put_hcd(hcd);
-
-       return retval;
-}
-
-static int cns3xxx_ehci_remove(struct platform_device *pdev)
-{
-       struct usb_hcd *hcd = platform_get_drvdata(pdev);
-
-       usb_remove_hcd(hcd);
-
-       /*
-        * EHCI and OHCI share the same clock and power,
-        * resetting twice would cause the 1st controller been reset.
-        * Therefore only do power up  at the first up device, and
-        * power down at the last down device.
-        */
-       if (atomic_dec_return(&usb_pwr_ref) == 0)
-               cns3xxx_pwr_clk_dis(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST);
-
-       usb_put_hcd(hcd);
-
-       platform_set_drvdata(pdev, NULL);
-
-       return 0;
-}
-
-MODULE_ALIAS("platform:cns3xxx-ehci");
-
-static struct platform_driver cns3xxx_ehci_driver = {
-       .probe = cns3xxx_ehci_probe,
-       .remove = cns3xxx_ehci_remove,
-       .driver = {
-               .name = "cns3xxx-ehci",
-       },
-};
index 1599806e3d47cddd7de228a4bb779b2a5e11fdd9..dfd3bf3aa4de2c35b965c32e792a44dfaf7c7ea8 100644 (file)
 
 /* this file is part of ehci-hcd.c */
 
-#define ehci_dbg(ehci, fmt, args...) \
-       dev_dbg (ehci_to_hcd(ehci)->self.controller , fmt , ## args )
-#define ehci_err(ehci, fmt, args...) \
-       dev_err (ehci_to_hcd(ehci)->self.controller , fmt , ## args )
-#define ehci_info(ehci, fmt, args...) \
-       dev_info (ehci_to_hcd(ehci)->self.controller , fmt , ## args )
-#define ehci_warn(ehci, fmt, args...) \
-       dev_warn (ehci_to_hcd(ehci)->self.controller , fmt , ## args )
-
-#ifdef VERBOSE_DEBUG
-#      define ehci_vdbg ehci_dbg
-#else
-       static inline void ehci_vdbg(struct ehci_hcd *ehci, ...) {}
-#endif
-
 #ifdef DEBUG
 
 /* check the values in the HCSPARAMS register
index 9bfde82078ecabde8236fc504aaf2a1794d25fb3..0d2f35ca93f1d5e7091cc77122e70b162f22679d 100644 (file)
@@ -222,7 +222,7 @@ static int ehci_fsl_setup_phy(struct usb_hcd *hcd,
 
        if (pdata->controller_ver < 0) {
                dev_warn(hcd->self.controller, "Could not get controller version\n");
-               return;
+               return -ENODEV;
        }
 
        portsc = ehci_readl(ehci, &ehci->regs->port_status[port_offset]);
index 6bf6c42481e8a6c645236ab27c170819c6f76024..9c2afb516fe5b37e372a97d3f6c01bdc140b78cc 100644 (file)
@@ -118,9 +118,34 @@ MODULE_PARM_DESC(hird, "host initiated resume duration, +1 for each 75us");
 /*-------------------------------------------------------------------------*/
 
 #include "ehci.h"
-#include "ehci-dbg.c"
 #include "pci-quirks.h"
 
+/*
+ * The MosChip MCS9990 controller updates its microframe counter
+ * a little before the frame counter, and occasionally we will read
+ * the invalid intermediate value.  Avoid problems by checking the
+ * microframe number (the low-order 3 bits); if they are 0 then
+ * re-read the register to get the correct value.
+ */
+static unsigned ehci_moschip_read_frame_index(struct ehci_hcd *ehci)
+{
+       unsigned uf;
+
+       uf = ehci_readl(ehci, &ehci->regs->frame_index);
+       if (unlikely((uf & 7) == 0))
+               uf = ehci_readl(ehci, &ehci->regs->frame_index);
+       return uf;
+}
+
+static inline unsigned ehci_read_frame_index(struct ehci_hcd *ehci)
+{
+       if (ehci->frame_index_bug)
+               return ehci_moschip_read_frame_index(ehci);
+       return ehci_readl(ehci, &ehci->regs->frame_index);
+}
+
+#include "ehci-dbg.c"
+
 /*-------------------------------------------------------------------------*/
 
 /*
@@ -503,7 +528,7 @@ static int ehci_init(struct usb_hcd *hcd)
 
        /* controllers may cache some of the periodic schedule ... */
        if (HCC_ISOC_CACHE(hcc_params))         // full frame cache
-               ehci->i_thresh = 2 + 8;
+               ehci->i_thresh = 0;
        else                                    // N microframes cached
                ehci->i_thresh = 2 + HCC_ISOC_THRES(hcc_params);
 
@@ -1219,11 +1244,6 @@ MODULE_LICENSE ("GPL");
 #define PLATFORM_DRIVER                ehci_hcd_sh_driver
 #endif
 
-#ifdef CONFIG_MIPS_ALCHEMY
-#include "ehci-au1xxx.c"
-#define        PLATFORM_DRIVER         ehci_hcd_au1xxx_driver
-#endif
-
 #ifdef CONFIG_USB_EHCI_HCD_OMAP
 #include "ehci-omap.c"
 #define        PLATFORM_DRIVER         ehci_hcd_omap_driver
@@ -1249,11 +1269,6 @@ MODULE_LICENSE ("GPL");
 #define        PLATFORM_DRIVER         ehci_orion_driver
 #endif
 
-#ifdef CONFIG_ARCH_IXP4XX
-#include "ehci-ixp4xx.c"
-#define        PLATFORM_DRIVER         ixp4xx_ehci_driver
-#endif
-
 #ifdef CONFIG_USB_W90X900_EHCI
 #include "ehci-w90x900.c"
 #define        PLATFORM_DRIVER         ehci_hcd_w90x900_driver
@@ -1269,11 +1284,6 @@ MODULE_LICENSE ("GPL");
 #define PLATFORM_DRIVER                ehci_octeon_driver
 #endif
 
-#ifdef CONFIG_USB_CNS3XXX_EHCI
-#include "ehci-cns3xxx.c"
-#define PLATFORM_DRIVER                cns3xxx_ehci_driver
-#endif
-
 #ifdef CONFIG_ARCH_VT8500
 #include "ehci-vt8500.c"
 #define        PLATFORM_DRIVER         vt8500_ehci_driver
@@ -1314,21 +1324,11 @@ MODULE_LICENSE ("GPL");
 #define PLATFORM_DRIVER                ehci_grlib_driver
 #endif
 
-#ifdef CONFIG_CPU_XLR
-#include "ehci-xls.c"
-#define PLATFORM_DRIVER                ehci_xls_driver
-#endif
-
 #ifdef CONFIG_USB_EHCI_MV
 #include "ehci-mv.c"
 #define        PLATFORM_DRIVER         ehci_mv_driver
 #endif
 
-#ifdef CONFIG_MACH_LOONGSON1
-#include "ehci-ls1x.c"
-#define PLATFORM_DRIVER                ehci_ls1x_driver
-#endif
-
 #ifdef CONFIG_MIPS_SEAD3
 #include "ehci-sead3.c"
 #define        PLATFORM_DRIVER         ehci_hcd_sead3_driver
index 914ce9370e70f4a1d9a956ccf50fae9b97973b21..a7ec827ca2ca697344418a58a9dc3d0c27aae316 100644 (file)
@@ -384,11 +384,24 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
        ehci_writel(ehci, ehci->command, &ehci->regs->command);
        ehci->rh_state = EHCI_RH_RUNNING;
 
-       /* Some controller/firmware combinations need a delay during which
-        * they set up the port statuses.  See Bugzilla #8190. */
-       spin_unlock_irq(&ehci->lock);
-       msleep(8);
-       spin_lock_irq(&ehci->lock);
+       /*
+        * According to Bugzilla #8190, the port status for some controllers
+        * will be wrong without a delay. At their wrong status, the port
+        * is enabled, but not suspended neither resumed.
+        */
+       i = HCS_N_PORTS(ehci->hcs_params);
+       while (i--) {
+               temp = ehci_readl(ehci, &ehci->regs->port_status[i]);
+               if ((temp & PORT_PE) &&
+                               !(temp & (PORT_SUSPEND | PORT_RESUME))) {
+                       ehci_dbg(ehci, "Port status(0x%x) is wrong\n", temp);
+                       spin_unlock_irq(&ehci->lock);
+                       msleep(8);
+                       spin_lock_irq(&ehci->lock);
+                       break;
+               }
+       }
+
        if (ehci->shutdown)
                goto shutdown;
 
diff --git a/drivers/usb/host/ehci-ixp4xx.c b/drivers/usb/host/ehci-ixp4xx.c
deleted file mode 100644 (file)
index f224c0a..0000000
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * IXP4XX EHCI Host Controller Driver
- *
- * Author: Vladimir Barinov <vbarinov@embeddedalley.com>
- *
- * Based on "ehci-fsl.c" by Randy Vinson <rvinson@mvista.com>
- *
- * 2007 (c) MontaVista Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-
-#include <linux/platform_device.h>
-
-static int ixp4xx_ehci_init(struct usb_hcd *hcd)
-{
-       struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-       int retval = 0;
-
-       ehci->big_endian_desc = 1;
-       ehci->big_endian_mmio = 1;
-
-       ehci->caps = hcd->regs + 0x100;
-
-       hcd->has_tt = 1;
-
-       retval = ehci_setup(hcd);
-       if (retval)
-               return retval;
-
-       ehci_port_power(ehci, 0);
-
-       return retval;
-}
-
-static const struct hc_driver ixp4xx_ehci_hc_driver = {
-       .description            = hcd_name,
-       .product_desc           = "IXP4XX EHCI Host Controller",
-       .hcd_priv_size          = sizeof(struct ehci_hcd),
-       .irq                    = ehci_irq,
-       .flags                  = HCD_MEMORY | HCD_USB2,
-       .reset                  = ixp4xx_ehci_init,
-       .start                  = ehci_run,
-       .stop                   = ehci_stop,
-       .shutdown               = ehci_shutdown,
-       .urb_enqueue            = ehci_urb_enqueue,
-       .urb_dequeue            = ehci_urb_dequeue,
-       .endpoint_disable       = ehci_endpoint_disable,
-       .endpoint_reset         = ehci_endpoint_reset,
-       .get_frame_number       = ehci_get_frame,
-       .hub_status_data        = ehci_hub_status_data,
-       .hub_control            = ehci_hub_control,
-#if defined(CONFIG_PM)
-       .bus_suspend            = ehci_bus_suspend,
-       .bus_resume             = ehci_bus_resume,
-#endif
-       .relinquish_port        = ehci_relinquish_port,
-       .port_handed_over       = ehci_port_handed_over,
-
-       .clear_tt_buffer_complete       = ehci_clear_tt_buffer_complete,
-};
-
-static int ixp4xx_ehci_probe(struct platform_device *pdev)
-{
-       struct usb_hcd *hcd;
-       const struct hc_driver *driver = &ixp4xx_ehci_hc_driver;
-       struct resource *res;
-       int irq;
-       int retval;
-
-       if (usb_disabled())
-               return -ENODEV;
-
-       res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-       if (!res) {
-               dev_err(&pdev->dev,
-                       "Found HC with no IRQ. Check %s setup!\n",
-                       dev_name(&pdev->dev));
-               return -ENODEV;
-       }
-       irq = res->start;
-
-       hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
-       if (!hcd) {
-               retval = -ENOMEM;
-               goto fail_create_hcd;
-       }
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(&pdev->dev,
-                       "Found HC with no register addr. Check %s setup!\n",
-                       dev_name(&pdev->dev));
-               retval = -ENODEV;
-               goto fail_request_resource;
-       }
-       hcd->rsrc_start = res->start;
-       hcd->rsrc_len = resource_size(res);
-
-       hcd->regs = devm_request_and_ioremap(&pdev->dev, res);
-       if (hcd->regs == NULL) {
-               dev_dbg(&pdev->dev, "error mapping memory\n");
-               retval = -EFAULT;
-               goto fail_request_resource;
-       }
-
-       retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
-       if (retval)
-               goto fail_request_resource;
-
-       return retval;
-
-fail_request_resource:
-       usb_put_hcd(hcd);
-fail_create_hcd:
-       dev_err(&pdev->dev, "init %s fail, %d\n", dev_name(&pdev->dev), retval);
-       return retval;
-}
-
-static int ixp4xx_ehci_remove(struct platform_device *pdev)
-{
-       struct usb_hcd *hcd = platform_get_drvdata(pdev);
-
-       usb_remove_hcd(hcd);
-       usb_put_hcd(hcd);
-
-       return 0;
-}
-
-MODULE_ALIAS("platform:ixp4xx-ehci");
-
-static struct platform_driver ixp4xx_ehci_driver = {
-       .probe = ixp4xx_ehci_probe,
-       .remove = ixp4xx_ehci_remove,
-       .driver = {
-               .name = "ixp4xx-ehci",
-       },
-};
index 2111627a19deefa935d4e724efe86965893dc168..6b092c1dff64c4e78035899304896296e82263e4 100644 (file)
@@ -17,8 +17,8 @@
 */
 
 /* this file is part of ehci-hcd.c */
-static int __maybe_unused ehci_lpm_set_da(struct ehci_hcd *ehci,
-       int dev_addr, int port_num)
+
+static int ehci_lpm_set_da(struct ehci_hcd *ehci, int dev_addr, int port_num)
 {
        u32 __iomem portsc;
 
@@ -38,7 +38,7 @@ static int __maybe_unused ehci_lpm_set_da(struct ehci_hcd *ehci,
  * this function is used to check if the device support LPM
  * if yes, mark the PORTSC register with PORT_LPM bit
  */
-static int __maybe_unused ehci_lpm_check(struct ehci_hcd *ehci, int port)
+static int ehci_lpm_check(struct ehci_hcd *ehci, int port)
 {
        u32 __iomem     *portsc ;
        u32 val32;
@@ -82,3 +82,20 @@ static int __maybe_unused ehci_lpm_check(struct ehci_hcd *ehci, int port)
 
        return retval;
 }
+
+static int __maybe_unused ehci_update_device(struct usb_hcd *hcd,
+               struct usb_device *udev)
+{
+       struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+       int rc = 0;
+
+       if (!udev->parent) /* udev is root hub itself, impossible */
+               rc = -1;
+       /* we only support lpm device connected to root hub yet */
+       if (ehci->has_lpm && !udev->parent->parent) {
+               rc = ehci_lpm_set_da(ehci, udev->devnum, udev->portnum);
+               if (!rc)
+                       rc = ehci_lpm_check(ehci, udev->portnum);
+       }
+       return rc;
+}
diff --git a/drivers/usb/host/ehci-ls1x.c b/drivers/usb/host/ehci-ls1x.c
deleted file mode 100644 (file)
index ca75965..0000000
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- *  Bus Glue for Loongson LS1X built-in EHCI controller.
- *
- *  Copyright (c) 2012 Zhang, Keguang <keguang.zhang@gmail.com>
- *
- *  This program is free software; you can redistribute it and/or modify it
- *  under the terms of the GNU General Public License version 2 as published
- *  by the Free Software Foundation.
- */
-
-
-#include <linux/platform_device.h>
-
-static int ehci_ls1x_reset(struct usb_hcd *hcd)
-{
-       struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-       int ret;
-
-       ehci->caps = hcd->regs;
-
-       ret = ehci_setup(hcd);
-       if (ret)
-               return ret;
-
-       ehci_port_power(ehci, 0);
-
-       return 0;
-}
-
-static const struct hc_driver ehci_ls1x_hc_driver = {
-       .description            = hcd_name,
-       .product_desc           = "LOONGSON1 EHCI",
-       .hcd_priv_size          = sizeof(struct ehci_hcd),
-
-       /*
-        * generic hardware linkage
-        */
-       .irq                    = ehci_irq,
-       .flags                  = HCD_MEMORY | HCD_USB2,
-
-       /*
-        * basic lifecycle operations
-        */
-       .reset                  = ehci_ls1x_reset,
-       .start                  = ehci_run,
-       .stop                   = ehci_stop,
-       .shutdown               = ehci_shutdown,
-
-       /*
-        * managing i/o requests and associated device resources
-        */
-       .urb_enqueue            = ehci_urb_enqueue,
-       .urb_dequeue            = ehci_urb_dequeue,
-       .endpoint_disable       = ehci_endpoint_disable,
-       .endpoint_reset         = ehci_endpoint_reset,
-
-       /*
-        * scheduling support
-        */
-       .get_frame_number       = ehci_get_frame,
-
-       /*
-        * root hub support
-        */
-       .hub_status_data        = ehci_hub_status_data,
-       .hub_control            = ehci_hub_control,
-       .relinquish_port        = ehci_relinquish_port,
-       .port_handed_over       = ehci_port_handed_over,
-
-       .clear_tt_buffer_complete       = ehci_clear_tt_buffer_complete,
-};
-
-static int ehci_hcd_ls1x_probe(struct platform_device *pdev)
-{
-       struct usb_hcd *hcd;
-       struct resource *res;
-       int irq;
-       int ret;
-
-       pr_debug("initializing loongson1 ehci USB Controller\n");
-
-       if (usb_disabled())
-               return -ENODEV;
-
-       res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-       if (!res) {
-               dev_err(&pdev->dev,
-                       "Found HC with no IRQ. Check %s setup!\n",
-                       dev_name(&pdev->dev));
-               return -ENODEV;
-       }
-       irq = res->start;
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(&pdev->dev,
-                       "Found HC with no register addr. Check %s setup!\n",
-                       dev_name(&pdev->dev));
-               return -ENODEV;
-       }
-
-       hcd = usb_create_hcd(&ehci_ls1x_hc_driver, &pdev->dev,
-                               dev_name(&pdev->dev));
-       if (!hcd)
-               return -ENOMEM;
-       hcd->rsrc_start = res->start;
-       hcd->rsrc_len   = resource_size(res);
-
-       hcd->regs = devm_request_and_ioremap(&pdev->dev, res);
-       if (hcd->regs == NULL) {
-               dev_dbg(&pdev->dev, "error mapping memory\n");
-               ret = -EFAULT;
-               goto err_put_hcd;
-       }
-
-       ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
-       if (ret)
-               goto err_put_hcd;
-
-       return ret;
-
-err_put_hcd:
-       usb_put_hcd(hcd);
-       return ret;
-}
-
-static int ehci_hcd_ls1x_remove(struct platform_device *pdev)
-{
-       struct usb_hcd *hcd = platform_get_drvdata(pdev);
-
-       usb_remove_hcd(hcd);
-       usb_put_hcd(hcd);
-
-       return 0;
-}
-
-static struct platform_driver ehci_ls1x_driver = {
-       .probe = ehci_hcd_ls1x_probe,
-       .remove = ehci_hcd_ls1x_remove,
-       .shutdown = usb_hcd_platform_shutdown,
-       .driver = {
-               .name = "ls1x-ehci",
-               .owner  = THIS_MODULE,
-       },
-};
-
-MODULE_ALIAS(PLATFORM_MODULE_PREFIX "ls1x-ehci");
index 4a08fc0b27c9e541da76b9598120b646ab7aa9a5..8e58a5fa19946282909eecf2a691ad5d546169c8 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/usb/ulpi.h>
 #include <linux/slab.h>
 
-#include <mach/hardware.h>
 #include <linux/platform_data/usb-ehci-mxc.h>
 
 #include <asm/mach-types.h>
index 8e7eca62f169fc204c6e1ef2034f26acdf2729dc..9c2717d66730ad74d9f99ef2aa0795b25c716a1b 100644 (file)
@@ -160,7 +160,7 @@ static const struct hc_driver ehci_orion_hc_driver = {
        .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
 };
 
-static void __init
+static void __devinit
 ehci_orion_conf_mbus_windows(struct usb_hcd *hcd,
                             const struct mbus_dram_target_info *dram)
 {
index 2cb7d370c4eff93ee39509f739e9669ff2cd3a0a..7880ba621f89552ee0d76fc4ae5b70a75d256d23 100644 (file)
@@ -103,7 +103,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
                }
                break;
        case PCI_VENDOR_ID_INTEL:
-               ehci->fs_i_thresh = 1;
                if (pdev->device == PCI_DEVICE_ID_INTEL_CE4100_USB)
                        hcd->has_tt = 1;
                break;
@@ -380,22 +379,6 @@ static int ehci_pci_resume(struct usb_hcd *hcd, bool hibernated)
 }
 #endif
 
-static int ehci_update_device(struct usb_hcd *hcd, struct usb_device *udev)
-{
-       struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-       int rc = 0;
-
-       if (!udev->parent) /* udev is root hub itself, impossible */
-               rc = -1;
-       /* we only support lpm device connected to root hub yet */
-       if (ehci->has_lpm && !udev->parent->parent) {
-               rc = ehci_lpm_set_da(ehci, udev->devnum, udev->portnum);
-               if (!rc)
-                       rc = ehci_lpm_check(ehci, udev->portnum);
-       }
-       return rc;
-}
-
 static const struct hc_driver ehci_pci_hc_driver = {
        .description =          hcd_name,
        .product_desc =         "EHCI Host Controller",
index 764e0100b6f438d82ab64057e8cb37abd638fa79..272728c48c9e6e2aa6b4cf7604a8d9280e195b0c 100644 (file)
@@ -38,6 +38,8 @@ static int ehci_platform_reset(struct usb_hcd *hcd)
        if (retval)
                return retval;
 
+       if (pdata->no_io_watchdog)
+               ehci->need_io_watchdog = 0;
        if (pdata->port_power_on)
                ehci_port_power(ehci, 1);
        if (pdata->port_power_off)
@@ -96,12 +98,12 @@ static int __devinit ehci_platform_probe(struct platform_device *dev)
 
        irq = platform_get_irq(dev, 0);
        if (irq < 0) {
-               pr_err("no irq provided");
+               dev_err(&dev->dev, "no irq provided");
                return irq;
        }
        res_mem = platform_get_resource(dev, IORESOURCE_MEM, 0);
        if (!res_mem) {
-               pr_err("no memory recourse provided");
+               dev_err(&dev->dev, "no memory resource provided");
                return -ENXIO;
        }
 
@@ -121,29 +123,19 @@ static int __devinit ehci_platform_probe(struct platform_device *dev)
        hcd->rsrc_start = res_mem->start;
        hcd->rsrc_len = resource_size(res_mem);
 
-       if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
-               pr_err("controller already in use");
-               err = -EBUSY;
-               goto err_put_hcd;
-       }
-
-       hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
+       hcd->regs = devm_request_and_ioremap(&dev->dev, res_mem);
        if (!hcd->regs) {
                err = -ENOMEM;
-               goto err_release_region;
+               goto err_put_hcd;
        }
        err = usb_add_hcd(hcd, irq, IRQF_SHARED);
        if (err)
-               goto err_iounmap;
+               goto err_put_hcd;
 
        platform_set_drvdata(dev, hcd);
 
        return err;
 
-err_iounmap:
-       iounmap(hcd->regs);
-err_release_region:
-       release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
 err_put_hcd:
        usb_put_hcd(hcd);
 err_power:
@@ -159,8 +151,6 @@ static int __devexit ehci_platform_remove(struct platform_device *dev)
        struct usb_ehci_pdata *pdata = dev->dev.platform_data;
 
        usb_remove_hcd(hcd);
-       iounmap(hcd->regs);
-       release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
        usb_put_hcd(hcd);
        platform_set_drvdata(dev, NULL);
 
index 85b74be202eb3b25a2c75dbde9386805dd9d6f79..abc178d21fe49fd3bbd504a913c7bae529f2d092 100644 (file)
@@ -136,7 +136,7 @@ static int __devinit s5p_ehci_probe(struct platform_device *pdev)
                goto fail_clk;
        }
 
-       err = clk_enable(s5p_ehci->clk);
+       err = clk_prepare_enable(s5p_ehci->clk);
        if (err)
                goto fail_clk;
 
@@ -183,7 +183,7 @@ static int __devinit s5p_ehci_probe(struct platform_device *pdev)
        return 0;
 
 fail_io:
-       clk_disable(s5p_ehci->clk);
+       clk_disable_unprepare(s5p_ehci->clk);
 fail_clk:
        usb_put_hcd(hcd);
        return err;
@@ -200,7 +200,7 @@ static int __devexit s5p_ehci_remove(struct platform_device *pdev)
        if (pdata && pdata->phy_exit)
                pdata->phy_exit(pdev, S5P_USB_PHY_HOST);
 
-       clk_disable(s5p_ehci->clk);
+       clk_disable_unprepare(s5p_ehci->clk);
 
        usb_put_hcd(hcd);
 
@@ -231,7 +231,7 @@ static int s5p_ehci_suspend(struct device *dev)
        if (pdata && pdata->phy_exit)
                pdata->phy_exit(pdev, S5P_USB_PHY_HOST);
 
-       clk_disable(s5p_ehci->clk);
+       clk_disable_unprepare(s5p_ehci->clk);
 
        return rc;
 }
@@ -243,7 +243,7 @@ static int s5p_ehci_resume(struct device *dev)
        struct platform_device *pdev = to_platform_device(dev);
        struct s5p_ehci_platdata *pdata = pdev->dev.platform_data;
 
-       clk_enable(s5p_ehci->clk);
+       clk_prepare_enable(s5p_ehci->clk);
 
        if (pdata && pdata->phy_init)
                pdata->phy_init(pdev, S5P_USB_PHY_HOST);
index 7cf3da7babf0009b6732302ecef280cc01429ff6..2e14714b359fa6b123f133af5d7133393c205895 100644 (file)
 
 static int ehci_get_frame (struct usb_hcd *hcd);
 
-#ifdef CONFIG_PCI
-
-static unsigned ehci_read_frame_index(struct ehci_hcd *ehci)
-{
-       unsigned uf;
-
-       /*
-        * The MosChip MCS9990 controller updates its microframe counter
-        * a little before the frame counter, and occasionally we will read
-        * the invalid intermediate value.  Avoid problems by checking the
-        * microframe number (the low-order 3 bits); if they are 0 then
-        * re-read the register to get the correct value.
-        */
-       uf = ehci_readl(ehci, &ehci->regs->frame_index);
-       if (unlikely(ehci->frame_index_bug && ((uf & 7) == 0)))
-               uf = ehci_readl(ehci, &ehci->regs->frame_index);
-       return uf;
-}
-
-#endif
-
-/*-------------------------------------------------------------------------*/
-
 /*
  * periodic_next_shadow - return "next" pointer on shadow list
  * @periodic: host pointer to qh/itd/sitd
@@ -1361,7 +1338,7 @@ sitd_slot_ok (
  * given EHCI_TUNE_FLS and the slop).  Or, write a smarter scheduler!
  */
 
-#define SCHEDULE_SLOP  80      /* microframes */
+#define SCHEDULING_DELAY       40      /* microframes */
 
 static int
 iso_stream_schedule (
@@ -1370,7 +1347,7 @@ iso_stream_schedule (
        struct ehci_iso_stream  *stream
 )
 {
-       u32                     now, next, start, period, span;
+       u32                     now, base, next, start, period, span;
        int                     status;
        unsigned                mod = ehci->periodic_size << 3;
        struct ehci_iso_sched   *sched = urb->hcpriv;
@@ -1382,62 +1359,72 @@ iso_stream_schedule (
                span <<= 3;
        }
 
-       if (span > mod - SCHEDULE_SLOP) {
-               ehci_dbg (ehci, "iso request %p too long\n", urb);
-               status = -EFBIG;
-               goto fail;
-       }
-
        now = ehci_read_frame_index(ehci) & (mod - 1);
 
        /* Typical case: reuse current schedule, stream is still active.
         * Hopefully there are no gaps from the host falling behind
-        * (irq delays etc), but if there are we'll take the next
-        * slot in the schedule, implicitly assuming URB_ISO_ASAP.
+        * (irq delays etc).  If there are, the behavior depends on
+        * whether URB_ISO_ASAP is set.
         */
        if (likely (!list_empty (&stream->td_list))) {
-               u32     excess;
 
-               /* For high speed devices, allow scheduling within the
-                * isochronous scheduling threshold.  For full speed devices
-                * and Intel PCI-based controllers, don't (work around for
-                * Intel ICH9 bug).
-                */
-               if (!stream->highspeed && ehci->fs_i_thresh)
-                       next = now + ehci->i_thresh;
+               /* Take the isochronous scheduling threshold into account */
+               if (ehci->i_thresh)
+                       next = now + ehci->i_thresh;    /* uframe cache */
                else
-                       next = now;
+                       next = (now + 2 + 7) & ~0x07;   /* full frame cache */
 
-               /* Fell behind (by up to twice the slop amount)?
-                * We decide based on the time of the last currently-scheduled
-                * slot, not the time of the next available slot.
+               /*
+                * Use ehci->last_iso_frame as the base.  There can't be any
+                * TDs scheduled for earlier than that.
                 */
-               excess = (stream->next_uframe - period - next) & (mod - 1);
-               if (excess >= mod - 2 * SCHEDULE_SLOP)
-                       start = next + excess - mod + period *
-                                       DIV_ROUND_UP(mod - excess, period);
-               else
-                       start = next + excess + period;
-               if (start - now >= mod) {
-                       ehci_dbg(ehci, "request %p would overflow (%d+%d >= %d)\n",
-                                       urb, start - now - period, period,
-                                       mod);
-                       status = -EFBIG;
+               base = ehci->last_iso_frame << 3;
+               next = (next - base) & (mod - 1);
+               start = (stream->next_uframe - base) & (mod - 1);
+
+               /* Is the schedule already full? */
+               if (unlikely(start < period)) {
+                       ehci_dbg(ehci, "iso sched full %p (%u-%u < %u mod %u)\n",
+                                       urb, stream->next_uframe, base,
+                                       period, mod);
+                       status = -ENOSPC;
                        goto fail;
                }
+
+               /* Behind the scheduling threshold? */
+               if (unlikely(start < next)) {
+
+                       /* USB_ISO_ASAP: Round up to the first available slot */
+                       if (urb->transfer_flags & URB_ISO_ASAP)
+                               start += (next - start + period - 1) & -period;
+
+                       /*
+                        * Not ASAP: Use the next slot in the stream.  If
+                        * the entire URB falls before the threshold, fail.
+                        */
+                       else if (start + span - period < next) {
+                               ehci_dbg(ehci, "iso urb late %p (%u+%u < %u)\n",
+                                               urb, start + base,
+                                               span - period, next + base);
+                               status = -EXDEV;
+                               goto fail;
+                       }
+               }
+
+               start += base;
        }
 
        /* need to schedule; when's the next (u)frame we could start?
         * this is bigger than ehci->i_thresh allows; scheduling itself
-        * isn't free, the slop should handle reasonably slow cpus.  it
+        * isn't free, the delay should handle reasonably slow cpus.  it
         * can also help high bandwidth if the dma and irq loads don't
         * jump until after the queue is primed.
         */
        else {
                int done = 0;
-               start = SCHEDULE_SLOP + (now & ~0x07);
 
-               /* NOTE:  assumes URB_ISO_ASAP, to limit complexity/bugs */
+               base = now & ~0x07;
+               start = base + SCHEDULING_DELAY;
 
                /* find a uframe slot with enough bandwidth.
                 * Early uframes are more precious because full-speed
@@ -1464,19 +1451,16 @@ iso_stream_schedule (
 
                /* no room in the schedule */
                if (!done) {
-                       ehci_dbg(ehci, "iso resched full %p (now %d max %d)\n",
-                               urb, now, now + mod);
+                       ehci_dbg(ehci, "iso sched full %p", urb);
                        status = -ENOSPC;
                        goto fail;
                }
        }
 
        /* Tried to schedule too far into the future? */
-       if (unlikely(start - now + span - period
-                               >= mod - 2 * SCHEDULE_SLOP)) {
-               ehci_dbg(ehci, "request %p would overflow (%d+%d >= %d)\n",
-                               urb, start - now, span - period,
-                               mod - 2 * SCHEDULE_SLOP);
+       if (unlikely(start - base + span - period >= mod)) {
+               ehci_dbg(ehci, "request %p would overflow (%u+%u >= %u)\n",
+                               urb, start - base, span - period, mod);
                status = -EFBIG;
                goto fail;
        }
@@ -1490,7 +1474,7 @@ iso_stream_schedule (
 
        /* Make sure scan_isoc() sees these */
        if (ehci->isoc_count == 0)
-               ehci->next_frame = now >> 3;
+               ehci->last_iso_frame = now >> 3;
        return 0;
 
  fail:
@@ -1708,7 +1692,7 @@ static bool itd_complete(struct ehci_hcd *ehci, struct ehci_itd *itd)
                        urb->actual_length += desc->actual_length;
                } else {
                        /* URB was too late */
-                       desc->status = -EXDEV;
+                       urb->error_count++;
                }
        }
 
@@ -2081,7 +2065,7 @@ static bool sitd_complete(struct ehci_hcd *ehci, struct ehci_sitd *sitd)
        t = hc32_to_cpup(ehci, &sitd->hw_results);
 
        /* report transfer status */
-       if (t & SITD_ERRS) {
+       if (unlikely(t & SITD_ERRS)) {
                urb->error_count++;
                if (t & SITD_STS_DBE)
                        desc->status = usb_pipein (urb->pipe)
@@ -2091,6 +2075,9 @@ static bool sitd_complete(struct ehci_hcd *ehci, struct ehci_sitd *sitd)
                        desc->status = -EOVERFLOW;
                else /* XACT, MMF, etc */
                        desc->status = -EPROTO;
+       } else if (unlikely(t & SITD_STS_ACTIVE)) {
+               /* URB was too late */
+               urb->error_count++;
        } else {
                desc->status = 0;
                desc->actual_length = desc->length - SITD_LENGTH(t);
@@ -2220,16 +2207,16 @@ static void scan_isoc(struct ehci_hcd *ehci)
                now_frame = (uf >> 3) & fmask;
                live = true;
        } else  {
-               now_frame = (ehci->next_frame - 1) & fmask;
+               now_frame = (ehci->last_iso_frame - 1) & fmask;
                live = false;
        }
        ehci->now_frame = now_frame;
 
-       frame = ehci->next_frame;
        for (;;) {
                union ehci_shadow       q, *q_p;
                __hc32                  type, *hw_p;
 
+               frame = ehci->last_iso_frame;
 restart:
                /* scan each element in frame's queue for completions */
                q_p = &ehci->pshadow [frame];
@@ -2334,7 +2321,6 @@ restart:
                /* Stop when we have reached the current frame */
                if (frame == now_frame)
                        break;
-               frame = (frame + 1) & fmask;
+               ehci->last_iso_frame = (frame + 1) & fmask;
        }
-       ehci->next_frame = now_frame;
 }
index 6223d1757848c6d43db7aa59d7042b1c8c736f02..2de089001ae98890c0cf70a74c647ece79582606 100644 (file)
 #include <linux/pm_runtime.h>
 
 #include <linux/usb/tegra_usb_phy.h>
-#include <mach/iomap.h>
+
+#define TEGRA_USB_BASE                 0xC5000000
+#define TEGRA_USB2_BASE                        0xC5004000
+#define TEGRA_USB3_BASE                        0xC5008000
 
 #define TEGRA_USB_DMA_ALIGN 32
 
index 96722bfebc84ba0bed49f6cd4c0aa3313f7f55dd..c6fe0bb619cb212499ba2b04b0c64c1f396d5da2 100644 (file)
 #include <linux/of.h>
 #include <linux/platform_device.h>
 
-static int ehci_update_device(struct usb_hcd *hcd, struct usb_device *udev)
-{
-       struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-       int rc = 0;
-
-       if (!udev->parent) /* udev is root hub itself, impossible */
-               rc = -1;
-       /* we only support lpm device connected to root hub yet */
-       if (ehci->has_lpm && !udev->parent->parent) {
-               rc = ehci_lpm_set_da(ehci, udev->devnum, udev->portnum);
-               if (!rc)
-                       rc = ehci_lpm_check(ehci, udev->portnum);
-       }
-       return rc;
-}
-
 static const struct hc_driver vt8500_ehci_hc_driver = {
        .description            = hcd_name,
        .product_desc           = "VT8500 EHCI",
@@ -85,6 +69,8 @@ static const struct hc_driver vt8500_ehci_hc_driver = {
        .clear_tt_buffer_complete       = ehci_clear_tt_buffer_complete,
 };
 
+static u64 vt8500_ehci_dma_mask = DMA_BIT_MASK(32);
+
 static int vt8500_ehci_drv_probe(struct platform_device *pdev)
 {
        struct usb_hcd *hcd;
@@ -95,6 +81,14 @@ static int vt8500_ehci_drv_probe(struct platform_device *pdev)
        if (usb_disabled())
                return -ENODEV;
 
+       /*
+        * Right now device-tree probed devices don't get dma_mask set.
+        * Since shared usb code relies on it, set it here for now.
+        * Once we have dma capability bindings this can go away.
+        */
+       if (!pdev->dev.dma_mask)
+               pdev->dev.dma_mask = &vt8500_ehci_dma_mask;
+
        if (pdev->resource[1].flags != IORESOURCE_IRQ) {
                pr_debug("resource[1] is not IORESOURCE_IRQ");
                return -ENOMEM;
index ec598082c14b09476f7de3369f75b0d04b3a6a69..fdd7c4873cf20361aed91c58910828eff9cdebf0 100644 (file)
@@ -13,7 +13,7 @@
 
 #include <linux/platform_device.h>
 
-/*ebable phy0 and phy1 for w90p910*/
+/* enable phy0 and phy1 for w90p910 */
 #define        ENPHY           (0x01<<8)
 #define PHY0_CTR       (0xA4)
 #define PHY1_CTR       (0xA8)
diff --git a/drivers/usb/host/ehci-xls.c b/drivers/usb/host/ehci-xls.c
deleted file mode 100644 (file)
index 8dc6a22..0000000
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * EHCI HCD for Netlogic XLS processors.
- *
- * (C) Copyright 2011 Netlogic Microsystems Inc.
- *
- *  Based on various ehci-*.c drivers
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive for
- * more details.
- */
-
-#include <linux/platform_device.h>
-
-static int ehci_xls_setup(struct usb_hcd *hcd)
-{
-       struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-
-       ehci->caps = hcd->regs;
-
-       return ehci_setup(hcd);
-}
-
-int ehci_xls_probe_internal(const struct hc_driver *driver,
-       struct platform_device *pdev)
-{
-       struct usb_hcd  *hcd;
-       struct resource *res;
-       int retval, irq;
-
-       /* Get our IRQ from an earlier registered Platform Resource */
-       irq = platform_get_irq(pdev, 0);
-       if (irq < 0) {
-               dev_err(&pdev->dev, "Found HC with no IRQ. Check %s setup!\n",
-                               dev_name(&pdev->dev));
-               return -ENODEV;
-       }
-
-       /* Get our Memory Handle */
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(&pdev->dev, "Error: MMIO Handle %s setup!\n",
-                               dev_name(&pdev->dev));
-               return -ENODEV;
-       }
-       hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
-       if (!hcd) {
-               retval = -ENOMEM;
-               goto err1;
-       }
-
-       hcd->rsrc_start = res->start;
-       hcd->rsrc_len = resource_size(res);
-
-       if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
-                               driver->description)) {
-               dev_dbg(&pdev->dev, "controller already in use\n");
-               retval = -EBUSY;
-               goto err2;
-       }
-       hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
-
-       if (hcd->regs == NULL) {
-               dev_dbg(&pdev->dev, "error mapping memory\n");
-               retval = -EFAULT;
-               goto err3;
-       }
-
-       retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
-       if (retval != 0)
-               goto err4;
-       return retval;
-
-err4:
-       iounmap(hcd->regs);
-err3:
-       release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-err2:
-       usb_put_hcd(hcd);
-err1:
-       dev_err(&pdev->dev, "init %s fail, %d\n", dev_name(&pdev->dev),
-                       retval);
-       return retval;
-}
-
-static struct hc_driver ehci_xls_hc_driver = {
-       .description    = hcd_name,
-       .product_desc   = "XLS EHCI Host Controller",
-       .hcd_priv_size  = sizeof(struct ehci_hcd),
-       .irq            = ehci_irq,
-       .flags          = HCD_USB2 | HCD_MEMORY,
-       .reset          = ehci_xls_setup,
-       .start          = ehci_run,
-       .stop           = ehci_stop,
-       .shutdown       = ehci_shutdown,
-
-       .urb_enqueue    = ehci_urb_enqueue,
-       .urb_dequeue    = ehci_urb_dequeue,
-       .endpoint_disable = ehci_endpoint_disable,
-       .endpoint_reset = ehci_endpoint_reset,
-
-       .get_frame_number = ehci_get_frame,
-
-       .hub_status_data = ehci_hub_status_data,
-       .hub_control    = ehci_hub_control,
-       .bus_suspend    = ehci_bus_suspend,
-       .bus_resume     = ehci_bus_resume,
-       .relinquish_port = ehci_relinquish_port,
-       .port_handed_over = ehci_port_handed_over,
-
-       .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
-};
-
-static int ehci_xls_probe(struct platform_device *pdev)
-{
-       if (usb_disabled())
-               return -ENODEV;
-
-       return ehci_xls_probe_internal(&ehci_xls_hc_driver, pdev);
-}
-
-static int ehci_xls_remove(struct platform_device *pdev)
-{
-       struct usb_hcd *hcd = platform_get_drvdata(pdev);
-
-       usb_remove_hcd(hcd);
-       iounmap(hcd->regs);
-       release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-       usb_put_hcd(hcd);
-       return 0;
-}
-
-MODULE_ALIAS("ehci-xls");
-
-static struct platform_driver ehci_xls_driver = {
-       .probe          = ehci_xls_probe,
-       .remove         = ehci_xls_remove,
-       .shutdown       = usb_hcd_platform_shutdown,
-       .driver         = {
-               .name = "ehci-xls",
-       },
-};
index da07d98f7d1de7780c578853e92b705c1231d316..ec948c3b1cea6faba93862fc33fe3c6f5234d800 100644 (file)
@@ -143,7 +143,7 @@ struct ehci_hcd {                   /* one per controller */
        struct ehci_qh          *intr_unlink_last;
        unsigned                intr_unlink_cycle;
        unsigned                now_frame;      /* frame from HC hardware */
-       unsigned                next_frame;     /* scan periodic, start here */
+       unsigned                last_iso_frame; /* last frame scanned for iso */
        unsigned                intr_count;     /* intr activity count */
        unsigned                isoc_count;     /* isoc activity count */
        unsigned                periodic_count; /* periodic activity count */
@@ -193,7 +193,6 @@ struct ehci_hcd {                   /* one per controller */
        unsigned                has_amcc_usb23:1;
        unsigned                need_io_watchdog:1;
        unsigned                amd_pll_fix:1;
-       unsigned                fs_i_thresh:1;  /* Intel iso scheduling */
        unsigned                use_dummy_qh:1; /* AMD Frame List table quirk*/
        unsigned                has_synopsys_hc_bug:1; /* Synopsys HC */
        unsigned                frame_index_bug:1; /* MosChip (AKA NetMos) */
@@ -762,22 +761,21 @@ static inline u32 hc32_to_cpup (const struct ehci_hcd *ehci, const __hc32 *x)
 
 /*-------------------------------------------------------------------------*/
 
-#ifdef CONFIG_PCI
-
-/* For working around the MosChip frame-index-register bug */
-static unsigned ehci_read_frame_index(struct ehci_hcd *ehci);
-
+#define ehci_dbg(ehci, fmt, args...) \
+       dev_dbg(ehci_to_hcd(ehci)->self.controller , fmt , ## args)
+#define ehci_err(ehci, fmt, args...) \
+       dev_err(ehci_to_hcd(ehci)->self.controller , fmt , ## args)
+#define ehci_info(ehci, fmt, args...) \
+       dev_info(ehci_to_hcd(ehci)->self.controller , fmt , ## args)
+#define ehci_warn(ehci, fmt, args...) \
+       dev_warn(ehci_to_hcd(ehci)->self.controller , fmt , ## args)
+
+#ifdef VERBOSE_DEBUG
+#      define ehci_vdbg ehci_dbg
 #else
-
-static inline unsigned ehci_read_frame_index(struct ehci_hcd *ehci)
-{
-       return ehci_readl(ehci, &ehci->regs->frame_index);
-}
-
+       static inline void ehci_vdbg(struct ehci_hcd *ehci, ...) {}
 #endif
 
-/*-------------------------------------------------------------------------*/
-
 #ifndef DEBUG
 #define STUB_DEBUG_FILES
 #endif /* DEBUG */
index 0bf72f943b00d392654fdc9613e4f397bfac2d32..908d84af1dd72bca08b80f40177dfdecc881bd00 100644 (file)
@@ -705,7 +705,7 @@ static int ohci_hcd_at91_drv_resume(struct platform_device *pdev)
        if (!clocked)
                at91_start_clock();
 
-       ohci_finish_controller_resume(hcd);
+       ohci_resume(hcd, false);
        return 0;
 }
 #else
diff --git a/drivers/usb/host/ohci-au1xxx.c b/drivers/usb/host/ohci-au1xxx.c
deleted file mode 100644 (file)
index c611699..0000000
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- * OHCI HCD (Host Controller Driver) for USB.
- *
- * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
- * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
- * (C) Copyright 2002 Hewlett-Packard Company
- *
- * Bus Glue for AMD Alchemy Au1xxx
- *
- * Written by Christopher Hoover <ch@hpl.hp.com>
- * Based on fragments of previous driver by Russell King et al.
- *
- * Modified for LH7A404 from ohci-sa1111.c
- *  by Durgesh Pattamatta <pattamattad@sharpsec.com>
- * Modified for AMD Alchemy Au1xxx
- *  by Matt Porter <mporter@kernel.crashing.org>
- *
- * This file is licenced under the GPL.
- */
-
-#include <linux/platform_device.h>
-#include <linux/signal.h>
-
-#include <asm/mach-au1x00/au1000.h>
-
-
-extern int usb_disabled(void);
-
-static int __devinit ohci_au1xxx_start(struct usb_hcd *hcd)
-{
-       struct ohci_hcd *ohci = hcd_to_ohci(hcd);
-       int ret;
-
-       ohci_dbg(ohci, "ohci_au1xxx_start, ohci:%p", ohci);
-
-       if ((ret = ohci_init(ohci)) < 0)
-               return ret;
-
-       if ((ret = ohci_run(ohci)) < 0) {
-               dev_err(hcd->self.controller, "can't start %s",
-                       hcd->self.bus_name);
-               ohci_stop(hcd);
-               return ret;
-       }
-
-       return 0;
-}
-
-static const struct hc_driver ohci_au1xxx_hc_driver = {
-       .description =          hcd_name,
-       .product_desc =         "Au1xxx OHCI",
-       .hcd_priv_size =        sizeof(struct ohci_hcd),
-
-       /*
-        * generic hardware linkage
-        */
-       .irq =                  ohci_irq,
-       .flags =                HCD_USB11 | HCD_MEMORY,
-
-       /*
-        * basic lifecycle operations
-        */
-       .start =                ohci_au1xxx_start,
-       .stop =                 ohci_stop,
-       .shutdown =             ohci_shutdown,
-
-       /*
-        * managing i/o requests and associated device resources
-        */
-       .urb_enqueue =          ohci_urb_enqueue,
-       .urb_dequeue =          ohci_urb_dequeue,
-       .endpoint_disable =     ohci_endpoint_disable,
-
-       /*
-        * scheduling support
-        */
-       .get_frame_number =     ohci_get_frame,
-
-       /*
-        * root hub support
-        */
-       .hub_status_data =      ohci_hub_status_data,
-       .hub_control =          ohci_hub_control,
-#ifdef CONFIG_PM
-       .bus_suspend =          ohci_bus_suspend,
-       .bus_resume =           ohci_bus_resume,
-#endif
-       .start_port_reset =     ohci_start_port_reset,
-};
-
-static int ohci_hcd_au1xxx_drv_probe(struct platform_device *pdev)
-{
-       int ret, unit;
-       struct usb_hcd *hcd;
-
-       if (usb_disabled())
-               return -ENODEV;
-
-       if (pdev->resource[1].flags != IORESOURCE_IRQ) {
-               pr_debug("resource[1] is not IORESOURCE_IRQ\n");
-               return -ENOMEM;
-       }
-
-       hcd = usb_create_hcd(&ohci_au1xxx_hc_driver, &pdev->dev, "au1xxx");
-       if (!hcd)
-               return -ENOMEM;
-
-       hcd->rsrc_start = pdev->resource[0].start;
-       hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1;
-
-       if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
-               pr_debug("request_mem_region failed\n");
-               ret = -EBUSY;
-               goto err1;
-       }
-
-       hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
-       if (!hcd->regs) {
-               pr_debug("ioremap failed\n");
-               ret = -ENOMEM;
-               goto err2;
-       }
-
-       unit = (hcd->rsrc_start == AU1300_USB_OHCI1_PHYS_ADDR) ?
-                       ALCHEMY_USB_OHCI1 : ALCHEMY_USB_OHCI0;
-       if (alchemy_usb_control(unit, 1)) {
-               printk(KERN_INFO "%s: controller init failed!\n", pdev->name);
-               ret = -ENODEV;
-               goto err3;
-       }
-
-       ohci_hcd_init(hcd_to_ohci(hcd));
-
-       ret = usb_add_hcd(hcd, pdev->resource[1].start,
-                         IRQF_SHARED);
-       if (ret == 0) {
-               platform_set_drvdata(pdev, hcd);
-               return ret;
-       }
-
-       alchemy_usb_control(unit, 0);
-err3:
-       iounmap(hcd->regs);
-err2:
-       release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-err1:
-       usb_put_hcd(hcd);
-       return ret;
-}
-
-static int ohci_hcd_au1xxx_drv_remove(struct platform_device *pdev)
-{
-       struct usb_hcd *hcd = platform_get_drvdata(pdev);
-       int unit;
-
-       unit = (hcd->rsrc_start == AU1300_USB_OHCI1_PHYS_ADDR) ?
-                       ALCHEMY_USB_OHCI1 : ALCHEMY_USB_OHCI0;
-       usb_remove_hcd(hcd);
-       alchemy_usb_control(unit, 0);
-       iounmap(hcd->regs);
-       release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-       usb_put_hcd(hcd);
-       platform_set_drvdata(pdev, NULL);
-
-       return 0;
-}
-
-#ifdef CONFIG_PM
-static int ohci_hcd_au1xxx_drv_suspend(struct device *dev)
-{
-       struct usb_hcd *hcd = dev_get_drvdata(dev);
-       struct ohci_hcd *ohci = hcd_to_ohci(hcd);
-       unsigned long flags;
-       int rc;
-
-       rc = 0;
-
-       /* Root hub was already suspended. Disable irq emission and
-        * mark HW unaccessible, bail out if RH has been resumed. Use
-        * the spinlock to properly synchronize with possible pending
-        * RH suspend or resume activity.
-        */
-       spin_lock_irqsave(&ohci->lock, flags);
-       if (ohci->rh_state != OHCI_RH_SUSPENDED) {
-               rc = -EINVAL;
-               goto bail;
-       }
-       ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
-       (void)ohci_readl(ohci, &ohci->regs->intrdisable);
-
-       clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
-
-       alchemy_usb_control(ALCHEMY_USB_OHCI0, 0);
-bail:
-       spin_unlock_irqrestore(&ohci->lock, flags);
-
-       return rc;
-}
-
-static int ohci_hcd_au1xxx_drv_resume(struct device *dev)
-{
-       struct usb_hcd *hcd = dev_get_drvdata(dev);
-
-       alchemy_usb_control(ALCHEMY_USB_OHCI0, 1);
-
-       set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
-       ohci_finish_controller_resume(hcd);
-
-       return 0;
-}
-
-static const struct dev_pm_ops au1xxx_ohci_pmops = {
-       .suspend        = ohci_hcd_au1xxx_drv_suspend,
-       .resume         = ohci_hcd_au1xxx_drv_resume,
-};
-
-#define AU1XXX_OHCI_PMOPS &au1xxx_ohci_pmops
-
-#else
-#define AU1XXX_OHCI_PMOPS NULL
-#endif
-
-static struct platform_driver ohci_hcd_au1xxx_driver = {
-       .probe          = ohci_hcd_au1xxx_drv_probe,
-       .remove         = ohci_hcd_au1xxx_drv_remove,
-       .shutdown       = usb_hcd_platform_shutdown,
-       .driver         = {
-               .name   = "au1xxx-ohci",
-               .owner  = THIS_MODULE,
-               .pm     = AU1XXX_OHCI_PMOPS,
-       },
-};
-
-MODULE_ALIAS("platform:au1xxx-ohci");
diff --git a/drivers/usb/host/ohci-cns3xxx.c b/drivers/usb/host/ohci-cns3xxx.c
deleted file mode 100644 (file)
index 2c9f233..0000000
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Copyright 2008 Cavium Networks
- *
- * This file is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License, Version 2, as
- * published by the Free Software Foundation.
- */
-
-#include <linux/platform_device.h>
-#include <linux/atomic.h>
-#include <mach/cns3xxx.h>
-#include <mach/pm.h>
-
-static int __devinit
-cns3xxx_ohci_start(struct usb_hcd *hcd)
-{
-       struct ohci_hcd *ohci = hcd_to_ohci(hcd);
-       int ret;
-
-       /*
-        * EHCI and OHCI share the same clock and power,
-        * resetting twice would cause the 1st controller been reset.
-        * Therefore only do power up  at the first up device, and
-        * power down at the last down device.
-        *
-        * Set USB AHB INCR length to 16
-        */
-       if (atomic_inc_return(&usb_pwr_ref) == 1) {
-               cns3xxx_pwr_power_up(1 << PM_PLL_HM_PD_CTRL_REG_OFFSET_PLL_USB);
-               cns3xxx_pwr_clk_en(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST);
-               cns3xxx_pwr_soft_rst(1 << PM_SOFT_RST_REG_OFFST_USB_HOST);
-               __raw_writel((__raw_readl(MISC_CHIP_CONFIG_REG) | (0X2 << 24)),
-                       MISC_CHIP_CONFIG_REG);
-       }
-
-       ret = ohci_init(ohci);
-       if (ret < 0)
-               return ret;
-
-       ohci->num_ports = 1;
-
-       ret = ohci_run(ohci);
-       if (ret < 0) {
-               dev_err(hcd->self.controller, "can't start %s\n",
-                       hcd->self.bus_name);
-               ohci_stop(hcd);
-               return ret;
-       }
-       return 0;
-}
-
-static const struct hc_driver cns3xxx_ohci_hc_driver = {
-       .description            = hcd_name,
-       .product_desc           = "CNS3XXX OHCI Host controller",
-       .hcd_priv_size          = sizeof(struct ohci_hcd),
-       .irq                    = ohci_irq,
-       .flags                  = HCD_USB11 | HCD_MEMORY,
-       .start                  = cns3xxx_ohci_start,
-       .stop                   = ohci_stop,
-       .shutdown               = ohci_shutdown,
-       .urb_enqueue            = ohci_urb_enqueue,
-       .urb_dequeue            = ohci_urb_dequeue,
-       .endpoint_disable       = ohci_endpoint_disable,
-       .get_frame_number       = ohci_get_frame,
-       .hub_status_data        = ohci_hub_status_data,
-       .hub_control            = ohci_hub_control,
-#ifdef CONFIG_PM
-       .bus_suspend            = ohci_bus_suspend,
-       .bus_resume             = ohci_bus_resume,
-#endif
-       .start_port_reset       = ohci_start_port_reset,
-};
-
-static int cns3xxx_ohci_probe(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-       struct usb_hcd *hcd;
-       const struct hc_driver *driver = &cns3xxx_ohci_hc_driver;
-       struct resource *res;
-       int irq;
-       int retval;
-
-       if (usb_disabled())
-               return -ENODEV;
-
-       res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-       if (!res) {
-               dev_err(dev, "Found HC with no IRQ.\n");
-               return -ENODEV;
-       }
-       irq = res->start;
-
-       hcd = usb_create_hcd(driver, dev, dev_name(dev));
-       if (!hcd)
-               return -ENOMEM;
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(dev, "Found HC with no register addr.\n");
-               retval = -ENODEV;
-               goto err1;
-       }
-       hcd->rsrc_start = res->start;
-       hcd->rsrc_len = resource_size(res);
-
-       if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
-                       driver->description)) {
-               dev_dbg(dev, "controller already in use\n");
-               retval = -EBUSY;
-               goto err1;
-       }
-
-       hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
-       if (!hcd->regs) {
-               dev_dbg(dev, "error mapping memory\n");
-               retval = -EFAULT;
-               goto err2;
-       }
-
-       ohci_hcd_init(hcd_to_ohci(hcd));
-
-       retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
-       if (retval == 0)
-               return retval;
-
-       iounmap(hcd->regs);
-err2:
-       release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-err1:
-       usb_put_hcd(hcd);
-       return retval;
-}
-
-static int cns3xxx_ohci_remove(struct platform_device *pdev)
-{
-       struct usb_hcd *hcd = platform_get_drvdata(pdev);
-
-       usb_remove_hcd(hcd);
-       iounmap(hcd->regs);
-       release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-
-       /*
-        * EHCI and OHCI share the same clock and power,
-        * resetting twice would cause the 1st controller been reset.
-        * Therefore only do power up  at the first up device, and
-        * power down at the last down device.
-        */
-       if (atomic_dec_return(&usb_pwr_ref) == 0)
-               cns3xxx_pwr_clk_dis(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST);
-
-       usb_put_hcd(hcd);
-
-       platform_set_drvdata(pdev, NULL);
-
-       return 0;
-}
-
-MODULE_ALIAS("platform:cns3xxx-ohci");
-
-static struct platform_driver ohci_hcd_cns3xxx_driver = {
-       .probe = cns3xxx_ohci_probe,
-       .remove = cns3xxx_ohci_remove,
-       .driver = {
-               .name = "cns3xxx-ohci",
-       },
-};
index dbfbd1dfd2e2f798aae4fc60456d2190e47d0428..a982f04ed78705b037af6e91037ebea20a84ab85 100644 (file)
@@ -194,7 +194,7 @@ static int ohci_hcd_ep93xx_drv_resume(struct platform_device *pdev)
 
        ep93xx_start_hc(&pdev->dev);
 
-       ohci_finish_controller_resume(hcd);
+       ohci_resume(hcd, false);
        return 0;
 }
 #endif
index 20a50081f9225d7111c7a9ddfe3d91dc1f8bde97..2f303295b428b0f10f867aaea5ac2daee4583e5e 100644 (file)
@@ -115,7 +115,7 @@ static int __devinit exynos_ohci_probe(struct platform_device *pdev)
        }
 
        exynos_ohci->hcd = hcd;
-       exynos_ohci->clk = clk_get(&pdev->dev, "usbhost");
+       exynos_ohci->clk = devm_clk_get(&pdev->dev, "usbhost");
 
        if (IS_ERR(exynos_ohci->clk)) {
                dev_err(&pdev->dev, "Failed to get usbhost clock\n");
@@ -123,9 +123,9 @@ static int __devinit exynos_ohci_probe(struct platform_device *pdev)
                goto fail_clk;
        }
 
-       err = clk_enable(exynos_ohci->clk);
+       err = clk_prepare_enable(exynos_ohci->clk);
        if (err)
-               goto fail_clken;
+               goto fail_clk;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!res) {
@@ -167,9 +167,7 @@ static int __devinit exynos_ohci_probe(struct platform_device *pdev)
        return 0;
 
 fail_io:
-       clk_disable(exynos_ohci->clk);
-fail_clken:
-       clk_put(exynos_ohci->clk);
+       clk_disable_unprepare(exynos_ohci->clk);
 fail_clk:
        usb_put_hcd(hcd);
        return err;
@@ -186,8 +184,7 @@ static int __devexit exynos_ohci_remove(struct platform_device *pdev)
        if (pdata && pdata->phy_exit)
                pdata->phy_exit(pdev, S5P_USB_PHY_HOST);
 
-       clk_disable(exynos_ohci->clk);
-       clk_put(exynos_ohci->clk);
+       clk_disable_unprepare(exynos_ohci->clk);
 
        usb_put_hcd(hcd);
 
@@ -232,7 +229,7 @@ static int exynos_ohci_suspend(struct device *dev)
        if (pdata && pdata->phy_exit)
                pdata->phy_exit(pdev, S5P_USB_PHY_HOST);
 
-       clk_disable(exynos_ohci->clk);
+       clk_disable_unprepare(exynos_ohci->clk);
 
 fail:
        spin_unlock_irqrestore(&ohci->lock, flags);
@@ -247,15 +244,12 @@ static int exynos_ohci_resume(struct device *dev)
        struct platform_device *pdev = to_platform_device(dev);
        struct exynos4_ohci_platdata *pdata = pdev->dev.platform_data;
 
-       clk_enable(exynos_ohci->clk);
+       clk_prepare_enable(exynos_ohci->clk);
 
        if (pdata && pdata->phy_init)
                pdata->phy_init(pdev, S5P_USB_PHY_HOST);
 
-       /* Mark hardware accessible again as we are out of D3 state by now */
-       set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
-
-       ohci_finish_controller_resume(hcd);
+       ohci_resume(hcd, false);
 
        return 0;
 }
index 4a1d64d92338e7653035b054decf6e714909a41f..180a2b01db56c9d496fb52388a324d2df2b4a931 100644 (file)
@@ -231,13 +231,41 @@ static int ohci_urb_enqueue (
                        frame &= ~(ed->interval - 1);
                        frame |= ed->branch;
                        urb->start_frame = frame;
+               }
+       } else if (ed->type == PIPE_ISOCHRONOUS) {
+               u16     next = ohci_frame_no(ohci) + 2;
+               u16     frame = ed->last_iso + ed->interval;
+
+               /* Behind the scheduling threshold? */
+               if (unlikely(tick_before(frame, next))) {
 
-                       /* yes, only URB_ISO_ASAP is supported, and
-                        * urb->start_frame is never used as input.
+                       /* USB_ISO_ASAP: Round up to the first available slot */
+                       if (urb->transfer_flags & URB_ISO_ASAP)
+                               frame += (next - frame + ed->interval - 1) &
+                                               -ed->interval;
+
+                       /*
+                        * Not ASAP: Use the next slot in the stream.  If
+                        * the entire URB falls before the threshold, fail.
                         */
+                       else if (tick_before(frame + ed->interval *
+                                       (urb->number_of_packets - 1), next)) {
+                               retval = -EXDEV;
+                               usb_hcd_unlink_urb_from_ep(hcd, urb);
+                               goto fail;
+                       }
+
+                       /*
+                        * Some OHCI hardware doesn't handle late TDs
+                        * correctly.  After retiring them it proceeds to
+                        * the next ED instead of the next TD.  Therefore
+                        * we have to omit the late TDs entirely.
+                        */
+                       urb_priv->td_cnt = DIV_ROUND_UP(next - frame,
+                                       ed->interval);
                }
-       } else if (ed->type == PIPE_ISOCHRONOUS)
-               urb->start_frame = ed->last_iso + ed->interval;
+               urb->start_frame = frame;
+       }
 
        /* fill the TDs and link them to the ed; and
         * enable that part of the schedule, if needed
@@ -983,6 +1011,79 @@ static int ohci_restart (struct ohci_hcd *ohci)
 
 #endif
 
+#ifdef CONFIG_PM
+
+static int __maybe_unused ohci_suspend(struct usb_hcd *hcd, bool do_wakeup)
+{
+       struct ohci_hcd *ohci = hcd_to_ohci (hcd);
+       unsigned long   flags;
+
+       /* Disable irq emission and mark HW unaccessible. Use
+        * the spinlock to properly synchronize with possible pending
+        * RH suspend or resume activity.
+        */
+       spin_lock_irqsave (&ohci->lock, flags);
+       ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
+       (void)ohci_readl(ohci, &ohci->regs->intrdisable);
+
+       clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+       spin_unlock_irqrestore (&ohci->lock, flags);
+
+       return 0;
+}
+
+
+static int __maybe_unused ohci_resume(struct usb_hcd *hcd, bool hibernated)
+{
+       struct ohci_hcd         *ohci = hcd_to_ohci(hcd);
+       int                     port;
+       bool                    need_reinit = false;
+
+       set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+
+       /* Make sure resume from hibernation re-enumerates everything */
+       if (hibernated)
+               ohci_usb_reset(ohci);
+
+       /* See if the controller is already running or has been reset */
+       ohci->hc_control = ohci_readl(ohci, &ohci->regs->control);
+       if (ohci->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) {
+               need_reinit = true;
+       } else {
+               switch (ohci->hc_control & OHCI_CTRL_HCFS) {
+               case OHCI_USB_OPER:
+               case OHCI_USB_RESET:
+                       need_reinit = true;
+               }
+       }
+
+       /* If needed, reinitialize and suspend the root hub */
+       if (need_reinit) {
+               spin_lock_irq(&ohci->lock);
+               ohci_rh_resume(ohci);
+               ohci_rh_suspend(ohci, 0);
+               spin_unlock_irq(&ohci->lock);
+       }
+
+       /* Normally just turn on port power and enable interrupts */
+       else {
+               ohci_dbg(ohci, "powerup ports\n");
+               for (port = 0; port < ohci->num_ports; port++)
+                       ohci_writel(ohci, RH_PS_PPS,
+                                       &ohci->regs->roothub.portstatus[port]);
+
+               ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrenable);
+               ohci_readl(ohci, &ohci->regs->intrenable);
+               msleep(20);
+       }
+
+       usb_hcd_resume_root_hub(hcd);
+
+       return 0;
+}
+
+#endif
+
 /*-------------------------------------------------------------------------*/
 
 MODULE_AUTHOR (DRIVER_AUTHOR);
@@ -1029,21 +1130,6 @@ MODULE_LICENSE ("GPL");
 #define PLATFORM_DRIVER                ohci_hcd_ep93xx_driver
 #endif
 
-#ifdef CONFIG_MIPS_ALCHEMY
-#include "ohci-au1xxx.c"
-#define PLATFORM_DRIVER                ohci_hcd_au1xxx_driver
-#endif
-
-#ifdef CONFIG_PNX8550
-#include "ohci-pnx8550.c"
-#define PLATFORM_DRIVER                ohci_hcd_pnx8550_driver
-#endif
-
-#ifdef CONFIG_USB_OHCI_HCD_PPC_SOC
-#include "ohci-ppc-soc.c"
-#define PLATFORM_DRIVER                ohci_hcd_ppc_soc_driver
-#endif
-
 #ifdef CONFIG_ARCH_AT91
 #include "ohci-at91.c"
 #define PLATFORM_DRIVER                ohci_hcd_at91_driver
@@ -1059,11 +1145,6 @@ MODULE_LICENSE ("GPL");
 #define PLATFORM_DRIVER                ohci_hcd_da8xx_driver
 #endif
 
-#ifdef CONFIG_USB_OHCI_SH
-#include "ohci-sh.c"
-#define PLATFORM_DRIVER                ohci_hcd_sh_driver
-#endif
-
 
 #ifdef CONFIG_USB_OHCI_HCD_PPC_OF
 #include "ohci-ppc-of.c"
@@ -1105,16 +1186,6 @@ MODULE_LICENSE ("GPL");
 #define PLATFORM_DRIVER                ohci_hcd_tilegx_driver
 #endif
 
-#ifdef CONFIG_USB_CNS3XXX_OHCI
-#include "ohci-cns3xxx.c"
-#define PLATFORM_DRIVER                ohci_hcd_cns3xxx_driver
-#endif
-
-#ifdef CONFIG_CPU_XLR
-#include "ohci-xls.c"
-#define PLATFORM_DRIVER                ohci_xls_driver
-#endif
-
 #ifdef CONFIG_USB_OHCI_HCD_PLATFORM
 #include "ohci-platform.c"
 #define PLATFORM_DRIVER                ohci_platform_driver
index 2f3619eefefa9bca87189e5da44dd6bbb0cd8191..db09dae7b557a18063d424a3ffc58c1edb8ccca8 100644 (file)
@@ -316,48 +316,6 @@ static int ohci_bus_resume (struct usb_hcd *hcd)
        return rc;
 }
 
-/* Carry out the final steps of resuming the controller device */
-static void __maybe_unused ohci_finish_controller_resume(struct usb_hcd *hcd)
-{
-       struct ohci_hcd         *ohci = hcd_to_ohci(hcd);
-       int                     port;
-       bool                    need_reinit = false;
-
-       /* See if the controller is already running or has been reset */
-       ohci->hc_control = ohci_readl(ohci, &ohci->regs->control);
-       if (ohci->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) {
-               need_reinit = true;
-       } else {
-               switch (ohci->hc_control & OHCI_CTRL_HCFS) {
-               case OHCI_USB_OPER:
-               case OHCI_USB_RESET:
-                       need_reinit = true;
-               }
-       }
-
-       /* If needed, reinitialize and suspend the root hub */
-       if (need_reinit) {
-               spin_lock_irq(&ohci->lock);
-               ohci_rh_resume(ohci);
-               ohci_rh_suspend(ohci, 0);
-               spin_unlock_irq(&ohci->lock);
-       }
-
-       /* Normally just turn on port power and enable interrupts */
-       else {
-               ohci_dbg(ohci, "powerup ports\n");
-               for (port = 0; port < ohci->num_ports; port++)
-                       ohci_writel(ohci, RH_PS_PPS,
-                                       &ohci->regs->roothub.portstatus[port]);
-
-               ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrenable);
-               ohci_readl(ohci, &ohci->regs->intrenable);
-               msleep(20);
-       }
-
-       usb_hcd_resume_root_hub(hcd);
-}
-
 /* Carry out polling-, autostop-, and autoresume-related state changes */
 static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
                int any_connected, int rhsc_status)
index 4531d03503c32371f4b1c5cd505ac38243dafe13..733c77c36355ac95082ec08cc3ceb4e3c7d9d881 100644 (file)
@@ -530,7 +530,7 @@ static int ohci_omap_resume(struct platform_device *dev)
        ohci->next_statechange = jiffies;
 
        omap_ohci_clock_power(1);
-       ohci_finish_controller_resume(hcd);
+       ohci_resume(hcd, false);
        return 0;
 }
 
index 1843bb68ac7ceefc73afcc2ed9f3a2f7fa8de1db..6afa7dc4e4c39a3f4ec5374915819b8483e74a9f 100644 (file)
@@ -296,49 +296,6 @@ static int __devinit ohci_pci_start (struct usb_hcd *hcd)
        return ret;
 }
 
-#ifdef CONFIG_PM
-
-static int ohci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
-{
-       struct ohci_hcd *ohci = hcd_to_ohci (hcd);
-       unsigned long   flags;
-       int             rc = 0;
-
-       /* Root hub was already suspended. Disable irq emission and
-        * mark HW unaccessible, bail out if RH has been resumed. Use
-        * the spinlock to properly synchronize with possible pending
-        * RH suspend or resume activity.
-        */
-       spin_lock_irqsave (&ohci->lock, flags);
-       if (ohci->rh_state != OHCI_RH_SUSPENDED) {
-               rc = -EINVAL;
-               goto bail;
-       }
-       ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
-       (void)ohci_readl(ohci, &ohci->regs->intrdisable);
-
-       clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
- bail:
-       spin_unlock_irqrestore (&ohci->lock, flags);
-
-       return rc;
-}
-
-
-static int ohci_pci_resume(struct usb_hcd *hcd, bool hibernated)
-{
-       set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
-
-       /* Make sure resume from hibernation re-enumerates everything */
-       if (hibernated)
-               ohci_usb_reset(hcd_to_ohci(hcd));
-
-       ohci_finish_controller_resume(hcd);
-       return 0;
-}
-
-#endif /* CONFIG_PM */
-
 
 /*-------------------------------------------------------------------------*/
 
@@ -362,8 +319,8 @@ static const struct hc_driver ohci_pci_hc_driver = {
        .shutdown =             ohci_shutdown,
 
 #ifdef CONFIG_PM
-       .pci_suspend =          ohci_pci_suspend,
-       .pci_resume =           ohci_pci_resume,
+       .pci_suspend =          ohci_suspend,
+       .pci_resume =           ohci_resume,
 #endif
 
        /*
index e24ec9f79164afc9e6563a147cb76d4c0f3c96c3..bda4e0bb8ab3c14a0b4e02e8e40b2bd2b9306359 100644 (file)
@@ -31,6 +31,10 @@ static int ohci_platform_reset(struct usb_hcd *hcd)
                ohci->flags |= OHCI_QUIRK_FRAME_NO;
 
        ohci_hcd_init(ohci);
+
+       if (pdata->num_ports)
+               ohci->num_ports = pdata->num_ports;
+
        err = ohci_init(ohci);
 
        return err;
@@ -97,13 +101,13 @@ static int __devinit ohci_platform_probe(struct platform_device *dev)
 
        irq = platform_get_irq(dev, 0);
        if (irq < 0) {
-               pr_err("no irq provided");
+               dev_err(&dev->dev, "no irq provided");
                return irq;
        }
 
        res_mem = platform_get_resource(dev, IORESOURCE_MEM, 0);
        if (!res_mem) {
-               pr_err("no memory recourse provided");
+               dev_err(&dev->dev, "no memory resource provided");
                return -ENXIO;
        }
 
@@ -123,29 +127,19 @@ static int __devinit ohci_platform_probe(struct platform_device *dev)
        hcd->rsrc_start = res_mem->start;
        hcd->rsrc_len = resource_size(res_mem);
 
-       if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
-               pr_err("controller already in use");
-               err = -EBUSY;
-               goto err_put_hcd;
-       }
-
-       hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
+       hcd->regs = devm_request_and_ioremap(&dev->dev, res_mem);
        if (!hcd->regs) {
                err = -ENOMEM;
-               goto err_release_region;
+               goto err_put_hcd;
        }
        err = usb_add_hcd(hcd, irq, IRQF_SHARED);
        if (err)
-               goto err_iounmap;
+               goto err_put_hcd;
 
        platform_set_drvdata(dev, hcd);
 
        return err;
 
-err_iounmap:
-       iounmap(hcd->regs);
-err_release_region:
-       release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
 err_put_hcd:
        usb_put_hcd(hcd);
 err_power:
@@ -161,8 +155,6 @@ static int __devexit ohci_platform_remove(struct platform_device *dev)
        struct usb_ohci_pdata *pdata = dev->dev.platform_data;
 
        usb_remove_hcd(hcd);
-       iounmap(hcd->regs);
-       release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
        usb_put_hcd(hcd);
        platform_set_drvdata(dev, NULL);
 
@@ -199,7 +191,7 @@ static int ohci_platform_resume(struct device *dev)
                        return err;
        }
 
-       ohci_finish_controller_resume(hcd);
+       ohci_resume(hcd, false);
        return 0;
 }
 
diff --git a/drivers/usb/host/ohci-pnx8550.c b/drivers/usb/host/ohci-pnx8550.c
deleted file mode 100644 (file)
index 148d27d..0000000
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
- * OHCI HCD (Host Controller Driver) for USB.
- *
- * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
- * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
- * (C) Copyright 2002 Hewlett-Packard Company
- * (C) Copyright 2005 Embedded Alley Solutions, Inc.
- *
- * Bus Glue for PNX8550
- *
- * Written by Christopher Hoover <ch@hpl.hp.com>
- * Based on fragments of previous driver by Russell King et al.
- *
- * Modified for LH7A404 from ohci-sa1111.c
- *  by Durgesh Pattamatta <pattamattad@sharpsec.com>
- *
- * Modified for PNX8550 from ohci-sa1111.c and sa-omap.c
- *  by Vitaly Wool <vitalywool@gmail.com>
- *
- * This file is licenced under the GPL.
- */
-
-#include <linux/device.h>
-#include <linux/platform_device.h>
-#include <asm/mach-pnx8550/usb.h>
-#include <asm/mach-pnx8550/int.h>
-#include <asm/mach-pnx8550/pci.h>
-
-#ifndef CONFIG_PNX8550
-#error "This file is PNX8550 bus glue.  CONFIG_PNX8550 must be defined."
-#endif
-
-extern int usb_disabled(void);
-
-/*-------------------------------------------------------------------------*/
-
-static void pnx8550_start_hc(struct platform_device *dev)
-{
-       /*
-        * Set register CLK48CTL to enable and 48MHz
-        */
-       outl(0x00000003, PCI_BASE | 0x0004770c);
-
-       /*
-        * Set register CLK12CTL to enable and 48MHz
-        */
-       outl(0x00000003, PCI_BASE | 0x00047710);
-
-       udelay(100);
-}
-
-static void pnx8550_stop_hc(struct platform_device *dev)
-{
-       udelay(10);
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-/* configure so an HC device and id are always provided */
-/* always called with process context; sleeping is OK */
-
-
-/**
- * usb_hcd_pnx8550_probe - initialize pnx8550-based HCDs
- * Context: !in_interrupt()
- *
- * Allocates basic resources for this USB host controller, and
- * then invokes the start() method for the HCD associated with it
- * through the hotplug entry's driver_data.
- *
- */
-int usb_hcd_pnx8550_probe (const struct hc_driver *driver,
-                         struct platform_device *dev)
-{
-       int retval;
-       struct usb_hcd *hcd;
-
-       if (dev->resource[0].flags != IORESOURCE_MEM ||
-                       dev->resource[1].flags != IORESOURCE_IRQ) {
-               dev_err (&dev->dev,"invalid resource type\n");
-               return -ENOMEM;
-       }
-
-       hcd = usb_create_hcd (driver, &dev->dev, "pnx8550");
-       if (!hcd)
-               return -ENOMEM;
-       hcd->rsrc_start = dev->resource[0].start;
-       hcd->rsrc_len = dev->resource[0].end - dev->resource[0].start + 1;
-
-       if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
-               dev_err(&dev->dev, "request_mem_region [0x%08llx, 0x%08llx] "
-                               "failed\n", hcd->rsrc_start, hcd->rsrc_len);
-               retval = -EBUSY;
-               goto err1;
-       }
-
-       hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
-       if (!hcd->regs) {
-               dev_err(&dev->dev, "ioremap [[0x%08llx, 0x%08llx] failed\n",
-                               hcd->rsrc_start, hcd->rsrc_len);
-               retval = -ENOMEM;
-               goto err2;
-       }
-
-       pnx8550_start_hc(dev);
-
-       ohci_hcd_init(hcd_to_ohci(hcd));
-
-       retval = usb_add_hcd(hcd, dev->resource[1].start, 0);
-       if (retval == 0)
-               return retval;
-
-       pnx8550_stop_hc(dev);
-       iounmap(hcd->regs);
- err2:
-       release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
- err1:
-       usb_put_hcd(hcd);
-       return retval;
-}
-
-
-/* may be called without controller electrically present */
-/* may be called with controller, bus, and devices active */
-
-/**
- * usb_hcd_pnx8550_remove - shutdown processing for pnx8550-based HCDs
- * @dev: USB Host Controller being removed
- * Context: !in_interrupt()
- *
- * Reverses the effect of usb_hcd_pnx8550_probe(), first invoking
- * the HCD's stop() method.  It is always called from a thread
- * context, normally "rmmod", "apmd", or something similar.
- *
- */
-void usb_hcd_pnx8550_remove (struct usb_hcd *hcd, struct platform_device *dev)
-{
-       usb_remove_hcd(hcd);
-       pnx8550_stop_hc(dev);
-       iounmap(hcd->regs);
-       release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-       usb_put_hcd(hcd);
-}
-
-/*-------------------------------------------------------------------------*/
-
-static int __devinit
-ohci_pnx8550_start (struct usb_hcd *hcd)
-{
-       struct ohci_hcd *ohci = hcd_to_ohci (hcd);
-       int             ret;
-
-       ohci_dbg (ohci, "ohci_pnx8550_start, ohci:%p", ohci);
-
-       if ((ret = ohci_init(ohci)) < 0)
-               return ret;
-
-       if ((ret = ohci_run (ohci)) < 0) {
-               dev_err(hcd->self.controller, "can't start %s",
-                       hcd->self.bus_name);
-               ohci_stop (hcd);
-               return ret;
-       }
-
-       return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static const struct hc_driver ohci_pnx8550_hc_driver = {
-       .description =          hcd_name,
-       .product_desc =         "PNX8550 OHCI",
-       .hcd_priv_size =        sizeof(struct ohci_hcd),
-
-       /*
-        * generic hardware linkage
-        */
-       .irq =                  ohci_irq,
-       .flags =                HCD_USB11 | HCD_MEMORY,
-
-       /*
-        * basic lifecycle operations
-        */
-       .start =                ohci_pnx8550_start,
-       .stop =                 ohci_stop,
-
-       /*
-        * managing i/o requests and associated device resources
-        */
-       .urb_enqueue =          ohci_urb_enqueue,
-       .urb_dequeue =          ohci_urb_dequeue,
-       .endpoint_disable =     ohci_endpoint_disable,
-
-       /*
-        * scheduling support
-        */
-       .get_frame_number =     ohci_get_frame,
-
-       /*
-        * root hub support
-        */
-       .hub_status_data =      ohci_hub_status_data,
-       .hub_control =          ohci_hub_control,
-#ifdef CONFIG_PM
-       .bus_suspend =          ohci_bus_suspend,
-       .bus_resume =           ohci_bus_resume,
-#endif
-       .start_port_reset =     ohci_start_port_reset,
-};
-
-/*-------------------------------------------------------------------------*/
-
-static int ohci_hcd_pnx8550_drv_probe(struct platform_device *pdev)
-{
-       int ret;
-
-       if (usb_disabled())
-               return -ENODEV;
-
-       ret = usb_hcd_pnx8550_probe(&ohci_pnx8550_hc_driver, pdev);
-       return ret;
-}
-
-static int ohci_hcd_pnx8550_drv_remove(struct platform_device *pdev)
-{
-       struct usb_hcd *hcd = platform_get_drvdata(pdev);
-
-       usb_hcd_pnx8550_remove(hcd, pdev);
-       return 0;
-}
-
-MODULE_ALIAS("platform:pnx8550-ohci");
-
-static struct platform_driver ohci_hcd_pnx8550_driver = {
-       .driver = {
-               .name   = "pnx8550-ohci",
-               .owner  = THIS_MODULE,
-       },
-       .probe          = ohci_hcd_pnx8550_drv_probe,
-       .remove         = ohci_hcd_pnx8550_drv_remove,
-};
-
diff --git a/drivers/usb/host/ohci-ppc-soc.c b/drivers/usb/host/ohci-ppc-soc.c
deleted file mode 100644 (file)
index 185c39e..0000000
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * OHCI HCD (Host Controller Driver) for USB.
- *
- * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
- * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
- * (C) Copyright 2002 Hewlett-Packard Company
- * (C) Copyright 2003-2005 MontaVista Software Inc.
- *
- * Bus Glue for PPC On-Chip OHCI driver
- * Tested on Freescale MPC5200 and IBM STB04xxx
- *
- * Modified by Dale Farnsworth <dale@farnsworth.org> from ohci-sa1111.c
- *
- * This file is licenced under the GPL.
- */
-
-#include <linux/platform_device.h>
-#include <linux/signal.h>
-
-/* configure so an HC device and id are always provided */
-/* always called with process context; sleeping is OK */
-
-/**
- * usb_hcd_ppc_soc_probe - initialize On-Chip HCDs
- * Context: !in_interrupt()
- *
- * Allocates basic resources for this USB host controller.
- *
- * Store this function in the HCD's struct pci_driver as probe().
- */
-static int usb_hcd_ppc_soc_probe(const struct hc_driver *driver,
-                         struct platform_device *pdev)
-{
-       int retval;
-       struct usb_hcd *hcd;
-       struct ohci_hcd *ohci;
-       struct resource *res;
-       int irq;
-
-       pr_debug("initializing PPC-SOC USB Controller\n");
-
-       res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-       if (!res) {
-               pr_debug("%s: no irq\n", __FILE__);
-               return -ENODEV;
-       }
-       irq = res->start;
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               pr_debug("%s: no reg addr\n", __FILE__);
-               return -ENODEV;
-       }
-
-       hcd = usb_create_hcd(driver, &pdev->dev, "PPC-SOC USB");
-       if (!hcd)
-               return -ENOMEM;
-       hcd->rsrc_start = res->start;
-       hcd->rsrc_len = resource_size(res);
-
-       if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
-               pr_debug("%s: request_mem_region failed\n", __FILE__);
-               retval = -EBUSY;
-               goto err1;
-       }
-
-       hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
-       if (!hcd->regs) {
-               pr_debug("%s: ioremap failed\n", __FILE__);
-               retval = -ENOMEM;
-               goto err2;
-       }
-
-       ohci = hcd_to_ohci(hcd);
-       ohci->flags |= OHCI_QUIRK_BE_MMIO | OHCI_QUIRK_BE_DESC;
-
-#ifdef CONFIG_PPC_MPC52xx
-       /* MPC52xx doesn't need frame_no shift */
-       ohci->flags |= OHCI_QUIRK_FRAME_NO;
-#endif
-       ohci_hcd_init(ohci);
-
-       retval = usb_add_hcd(hcd, irq, 0);
-       if (retval == 0)
-               return retval;
-
-       pr_debug("Removing PPC-SOC USB Controller\n");
-
-       iounmap(hcd->regs);
- err2:
-       release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
- err1:
-       usb_put_hcd(hcd);
-       return retval;
-}
-
-
-/* may be called without controller electrically present */
-/* may be called with controller, bus, and devices active */
-
-/**
- * usb_hcd_ppc_soc_remove - shutdown processing for On-Chip HCDs
- * @pdev: USB Host Controller being removed
- * Context: !in_interrupt()
- *
- * Reverses the effect of usb_hcd_ppc_soc_probe().
- * It is always called from a thread
- * context, normally "rmmod", "apmd", or something similar.
- *
- */
-static void usb_hcd_ppc_soc_remove(struct usb_hcd *hcd,
-               struct platform_device *pdev)
-{
-       usb_remove_hcd(hcd);
-
-       pr_debug("stopping PPC-SOC USB Controller\n");
-
-       iounmap(hcd->regs);
-       release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-       usb_put_hcd(hcd);
-}
-
-static int __devinit
-ohci_ppc_soc_start(struct usb_hcd *hcd)
-{
-       struct ohci_hcd *ohci = hcd_to_ohci(hcd);
-       int             ret;
-
-       if ((ret = ohci_init(ohci)) < 0)
-               return ret;
-
-       if ((ret = ohci_run(ohci)) < 0) {
-               dev_err(hcd->self.controller, "can't start %s\n",
-                       hcd->self.bus_name);
-               ohci_stop(hcd);
-               return ret;
-       }
-
-       return 0;
-}
-
-static const struct hc_driver ohci_ppc_soc_hc_driver = {
-       .description =          hcd_name,
-       .hcd_priv_size =        sizeof(struct ohci_hcd),
-
-       /*
-        * generic hardware linkage
-        */
-       .irq =                  ohci_irq,
-       .flags =                HCD_USB11 | HCD_MEMORY,
-
-       /*
-        * basic lifecycle operations
-        */
-       .start =                ohci_ppc_soc_start,
-       .stop =                 ohci_stop,
-       .shutdown =             ohci_shutdown,
-
-       /*
-        * managing i/o requests and associated device resources
-        */
-       .urb_enqueue =          ohci_urb_enqueue,
-       .urb_dequeue =          ohci_urb_dequeue,
-       .endpoint_disable =     ohci_endpoint_disable,
-
-       /*
-        * scheduling support
-        */
-       .get_frame_number =     ohci_get_frame,
-
-       /*
-        * root hub support
-        */
-       .hub_status_data =      ohci_hub_status_data,
-       .hub_control =          ohci_hub_control,
-#ifdef CONFIG_PM
-       .bus_suspend =          ohci_bus_suspend,
-       .bus_resume =           ohci_bus_resume,
-#endif
-       .start_port_reset =     ohci_start_port_reset,
-};
-
-static int ohci_hcd_ppc_soc_drv_probe(struct platform_device *pdev)
-{
-       int ret;
-
-       if (usb_disabled())
-               return -ENODEV;
-
-       ret = usb_hcd_ppc_soc_probe(&ohci_ppc_soc_hc_driver, pdev);
-       return ret;
-}
-
-static int ohci_hcd_ppc_soc_drv_remove(struct platform_device *pdev)
-{
-       struct usb_hcd *hcd = platform_get_drvdata(pdev);
-
-       usb_hcd_ppc_soc_remove(hcd, pdev);
-       return 0;
-}
-
-static struct platform_driver ohci_hcd_ppc_soc_driver = {
-       .probe          = ohci_hcd_ppc_soc_drv_probe,
-       .remove         = ohci_hcd_ppc_soc_drv_remove,
-       .shutdown       = usb_hcd_platform_shutdown,
-#ifdef CONFIG_PM
-       /*.suspend      = ohci_hcd_ppc_soc_drv_suspend,*/
-       /*.resume       = ohci_hcd_ppc_soc_drv_resume,*/
-#endif
-       .driver         = {
-               .name   = "ppc-soc-ohci",
-               .owner  = THIS_MODULE,
-       },
-};
-
-MODULE_ALIAS("platform:ppc-soc-ohci");
index 2bf11440b010443290f2cbd6795cf22ddf561b0d..156d289d3bb51112b6aad220291101ceafe5e4ff 100644 (file)
@@ -591,7 +591,7 @@ static int ohci_hcd_pxa27x_drv_resume(struct device *dev)
        /* Select Power Management Mode */
        pxa27x_ohci_select_pmm(ohci, inf->port_mode);
 
-       ohci_finish_controller_resume(hcd);
+       ohci_resume(hcd, false);
        return 0;
 }
 
index c5a1ea9145faec6e65809ddf1fdbb7046f6897cc..177a213790d47f6d9abe059c15e8043230f690c8 100644 (file)
@@ -596,7 +596,6 @@ static void td_submit_urb (
                urb_priv->ed->hwHeadP &= ~cpu_to_hc32 (ohci, ED_C);
        }
 
-       urb_priv->td_cnt = 0;
        list_add (&urb_priv->pending, &ohci->pending);
 
        if (data_len)
@@ -672,7 +671,8 @@ static void td_submit_urb (
         * we could often reduce the number of TDs here.
         */
        case PIPE_ISOCHRONOUS:
-               for (cnt = 0; cnt < urb->number_of_packets; cnt++) {
+               for (cnt = urb_priv->td_cnt; cnt < urb->number_of_packets;
+                               cnt++) {
                        int     frame = urb->start_frame;
 
                        // FIXME scheduling should handle frame counter
index 0d2309ca471eeb9fff1be06da36081f4878bd42c..e84190f25c6b7b6995d32f53d7e1818f1f6608bc 100644 (file)
@@ -323,8 +323,6 @@ usb_hcd_s3c2410_remove(struct usb_hcd *hcd, struct platform_device *dev)
 {
        usb_remove_hcd(hcd);
        s3c2410_stop_hc(dev);
-       iounmap(hcd->regs);
-       release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
        usb_put_hcd(hcd);
 }
 
@@ -353,35 +351,29 @@ static int usb_hcd_s3c2410_probe(const struct hc_driver *driver,
        hcd->rsrc_start = dev->resource[0].start;
        hcd->rsrc_len   = resource_size(&dev->resource[0]);
 
-       if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
-               dev_err(&dev->dev, "request_mem_region failed\n");
-               retval = -EBUSY;
+       hcd->regs = devm_request_and_ioremap(&dev->dev, &dev->resource[0]);
+       if (!hcd->regs) {
+               dev_err(&dev->dev, "devm_request_and_ioremap failed\n");
+               retval = -ENOMEM;
                goto err_put;
        }
 
-       clk = clk_get(&dev->dev, "usb-host");
+       clk = devm_clk_get(&dev->dev, "usb-host");
        if (IS_ERR(clk)) {
                dev_err(&dev->dev, "cannot get usb-host clock\n");
                retval = PTR_ERR(clk);
-               goto err_mem;
+               goto err_put;
        }
 
-       usb_clk = clk_get(&dev->dev, "usb-bus-host");
+       usb_clk = devm_clk_get(&dev->dev, "usb-bus-host");
        if (IS_ERR(usb_clk)) {
                dev_err(&dev->dev, "cannot get usb-bus-host clock\n");
                retval = PTR_ERR(usb_clk);
-               goto err_clk;
+               goto err_put;
        }
 
        s3c2410_start_hc(dev, hcd);
 
-       hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
-       if (!hcd->regs) {
-               dev_err(&dev->dev, "ioremap failed\n");
-               retval = -ENOMEM;
-               goto err_ioremap;
-       }
-
        ohci_hcd_init(hcd_to_ohci(hcd));
 
        retval = usb_add_hcd(hcd, dev->resource[1].start, 0);
@@ -392,14 +384,6 @@ static int usb_hcd_s3c2410_probe(const struct hc_driver *driver,
 
  err_ioremap:
        s3c2410_stop_hc(dev);
-       iounmap(hcd->regs);
-       clk_put(usb_clk);
-
- err_clk:
-       clk_put(clk);
-
- err_mem:
-       release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
 
  err_put:
        usb_put_hcd(hcd);
@@ -524,8 +508,7 @@ static int ohci_hcd_s3c2410_drv_resume(struct device *dev)
 
        s3c2410_start_hc(pdev, hcd);
 
-       set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
-       ohci_finish_controller_resume(hcd);
+       ohci_resume(hcd, false);
 
        return 0;
 }
diff --git a/drivers/usb/host/ohci-sh.c b/drivers/usb/host/ohci-sh.c
deleted file mode 100644 (file)
index 76a20c2..0000000
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * OHCI HCD (Host Controller Driver) for USB.
- *
- * Copyright (C) 2008 Renesas Solutions Corp.
- *
- * Author : Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- *
- */
-
-#include <linux/platform_device.h>
-
-static int ohci_sh_start(struct usb_hcd *hcd)
-{
-       struct ohci_hcd *ohci = hcd_to_ohci(hcd);
-
-       ohci_hcd_init(ohci);
-       ohci_init(ohci);
-       ohci_run(ohci);
-       return 0;
-}
-
-static const struct hc_driver ohci_sh_hc_driver = {
-       .description =          hcd_name,
-       .product_desc =         "SuperH OHCI",
-       .hcd_priv_size =        sizeof(struct ohci_hcd),
-
-       /*
-        * generic hardware linkage
-        */
-       .irq =                  ohci_irq,
-       .flags =                HCD_USB11 | HCD_MEMORY,
-
-       /*
-        * basic lifecycle operations
-        */
-       .start =                ohci_sh_start,
-       .stop =                 ohci_stop,
-       .shutdown =             ohci_shutdown,
-
-       /*
-        * managing i/o requests and associated device resources
-        */
-       .urb_enqueue =          ohci_urb_enqueue,
-       .urb_dequeue =          ohci_urb_dequeue,
-       .endpoint_disable =     ohci_endpoint_disable,
-
-       /*
-        * scheduling support
-        */
-       .get_frame_number =     ohci_get_frame,
-
-       /*
-        * root hub support
-        */
-       .hub_status_data =      ohci_hub_status_data,
-       .hub_control =          ohci_hub_control,
-#ifdef CONFIG_PM
-       .bus_suspend =          ohci_bus_suspend,
-       .bus_resume =           ohci_bus_resume,
-#endif
-       .start_port_reset =     ohci_start_port_reset,
-};
-
-/*-------------------------------------------------------------------------*/
-
-static int ohci_hcd_sh_probe(struct platform_device *pdev)
-{
-       struct resource *res = NULL;
-       struct usb_hcd *hcd = NULL;
-       int irq = -1;
-       int ret;
-
-       if (usb_disabled())
-               return -ENODEV;
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(&pdev->dev, "platform_get_resource error.\n");
-               return -ENODEV;
-       }
-
-       irq = platform_get_irq(pdev, 0);
-       if (irq < 0) {
-               dev_err(&pdev->dev, "platform_get_irq error.\n");
-               return -ENODEV;
-       }
-
-       /* initialize hcd */
-       hcd = usb_create_hcd(&ohci_sh_hc_driver, &pdev->dev, (char *)hcd_name);
-       if (!hcd) {
-               dev_err(&pdev->dev, "Failed to create hcd\n");
-               return -ENOMEM;
-       }
-
-       hcd->regs = (void __iomem *)res->start;
-       hcd->rsrc_start = res->start;
-       hcd->rsrc_len = resource_size(res);
-       ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
-       if (ret != 0) {
-               dev_err(&pdev->dev, "Failed to add hcd\n");
-               usb_put_hcd(hcd);
-               return ret;
-       }
-
-       return ret;
-}
-
-static int ohci_hcd_sh_remove(struct platform_device *pdev)
-{
-       struct usb_hcd *hcd = platform_get_drvdata(pdev);
-
-       usb_remove_hcd(hcd);
-       usb_put_hcd(hcd);
-
-       return 0;
-}
-
-static struct platform_driver ohci_hcd_sh_driver = {
-       .probe          = ohci_hcd_sh_probe,
-       .remove         = ohci_hcd_sh_remove,
-       .shutdown       = usb_hcd_platform_shutdown,
-       .driver         = {
-               .name   = "sh_ohci",
-               .owner  = THIS_MODULE,
-       },
-};
-
-MODULE_ALIAS("platform:sh_ohci");
index 5596ac2ba1ca55851c21b1f3044d0bfef0e17085..3b5b908fd47b29e25f0f90198c85607182152fef 100644 (file)
@@ -238,7 +238,7 @@ static int ohci_sm501_resume(struct platform_device *pdev)
        ohci->next_statechange = jiffies;
 
        sm501_unit_power(dev->parent, SM501_GATE_USB_HOST, 1);
-       ohci_finish_controller_resume(hcd);
+       ohci_resume(hcd, false);
        return 0;
 }
 #else
index fc7305ee3c9cd465ecdb68c64b140e9f9da10fc9..d607be33c03c865a6a6abcd5245deee02e8b3a03 100644 (file)
@@ -231,7 +231,7 @@ static int spear_ohci_hcd_drv_resume(struct platform_device *dev)
        ohci->next_statechange = jiffies;
 
        spear_start_ohci(ohci_p);
-       ohci_finish_controller_resume(hcd);
+       ohci_resume(hcd, false);
        return 0;
 }
 #endif
index 60c2b0722f2e16280f32db0ada071260e9ef30d4..2c9ab8f126d456df6ce02e7cccd771e651b4b3e6 100644 (file)
@@ -352,7 +352,7 @@ static int ohci_hcd_tmio_drv_resume(struct platform_device *dev)
 
        spin_unlock_irqrestore(&tmio->lock, flags);
 
-       ohci_finish_controller_resume(hcd);
+       ohci_resume(hcd, false);
 
        return 0;
 }
diff --git a/drivers/usb/host/ohci-xls.c b/drivers/usb/host/ohci-xls.c
deleted file mode 100644 (file)
index 84201cd..0000000
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * OHCI HCD for Netlogic XLS processors.
- *
- * (C) Copyright 2011 Netlogic Microsystems Inc.
- *
- *  Based on ohci-au1xxx.c, and other Linux OHCI drivers.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive for
- * more details.
- */
-
-#include <linux/platform_device.h>
-#include <linux/signal.h>
-
-static int ohci_xls_probe_internal(const struct hc_driver *driver,
-                       struct platform_device *dev)
-{
-       struct resource *res;
-       struct usb_hcd *hcd;
-       int retval, irq;
-
-       /* Get our IRQ from an earlier registered Platform Resource */
-       irq = platform_get_irq(dev, 0);
-       if (irq < 0) {
-               dev_err(&dev->dev, "Found HC with no IRQ\n");
-               return -ENODEV;
-       }
-
-       /* Get our Memory Handle */
-       res = platform_get_resource(dev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(&dev->dev, "MMIO Handle incorrect!\n");
-               return -ENODEV;
-       }
-
-       hcd = usb_create_hcd(driver, &dev->dev, "XLS");
-       if (!hcd) {
-               retval = -ENOMEM;
-               goto err1;
-       }
-       hcd->rsrc_start = res->start;
-       hcd->rsrc_len = resource_size(res);
-
-       if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
-                       driver->description)) {
-               dev_dbg(&dev->dev, "Controller already in use\n");
-               retval = -EBUSY;
-               goto err2;
-       }
-
-       hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
-       if (hcd->regs == NULL) {
-               dev_dbg(&dev->dev, "error mapping memory\n");
-               retval = -EFAULT;
-               goto err3;
-       }
-
-       retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
-       if (retval != 0)
-               goto err4;
-       return retval;
-
-err4:
-       iounmap(hcd->regs);
-err3:
-       release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-err2:
-       usb_put_hcd(hcd);
-err1:
-       dev_err(&dev->dev, "init fail, %d\n", retval);
-       return retval;
-}
-
-static int ohci_xls_reset(struct usb_hcd *hcd)
-{
-       struct ohci_hcd *ohci = hcd_to_ohci(hcd);
-
-       ohci_hcd_init(ohci);
-       return ohci_init(ohci);
-}
-
-static int __devinit ohci_xls_start(struct usb_hcd *hcd)
-{
-       struct ohci_hcd *ohci;
-       int ret;
-
-       ohci = hcd_to_ohci(hcd);
-       ret = ohci_run(ohci);
-       if (ret < 0) {
-               dev_err(hcd->self.controller, "can't start %s\n",
-                       hcd->self.bus_name);
-               ohci_stop(hcd);
-               return ret;
-       }
-       return 0;
-}
-
-static struct hc_driver ohci_xls_hc_driver = {
-       .description    = hcd_name,
-       .product_desc   = "XLS OHCI Host Controller",
-       .hcd_priv_size  = sizeof(struct ohci_hcd),
-       .irq            = ohci_irq,
-       .flags          = HCD_MEMORY | HCD_USB11,
-       .reset          = ohci_xls_reset,
-       .start          = ohci_xls_start,
-       .stop           = ohci_stop,
-       .shutdown       = ohci_shutdown,
-       .urb_enqueue    = ohci_urb_enqueue,
-       .urb_dequeue    = ohci_urb_dequeue,
-       .endpoint_disable = ohci_endpoint_disable,
-       .get_frame_number = ohci_get_frame,
-       .hub_status_data = ohci_hub_status_data,
-       .hub_control    = ohci_hub_control,
-#ifdef CONFIG_PM
-       .bus_suspend    = ohci_bus_suspend,
-       .bus_resume     = ohci_bus_resume,
-#endif
-       .start_port_reset = ohci_start_port_reset,
-};
-
-static int ohci_xls_probe(struct platform_device *dev)
-{
-       int ret;
-
-       pr_debug("In ohci_xls_probe");
-       if (usb_disabled())
-               return -ENODEV;
-       ret = ohci_xls_probe_internal(&ohci_xls_hc_driver, dev);
-       return ret;
-}
-
-static int ohci_xls_remove(struct platform_device *dev)
-{
-       struct usb_hcd *hcd = platform_get_drvdata(dev);
-
-       usb_remove_hcd(hcd);
-       iounmap(hcd->regs);
-       release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-       usb_put_hcd(hcd);
-       return 0;
-}
-
-static struct platform_driver ohci_xls_driver = {
-       .probe          = ohci_xls_probe,
-       .remove         = ohci_xls_remove,
-       .shutdown       = usb_hcd_platform_shutdown,
-       .driver         = {
-               .name   = "ohci-xls-0",
-               .owner  = THIS_MODULE,
-       },
-};
index fcc09e5ec0addc9cd9661086b1e18165bd5f8ba4..b3eea0ba97a936b9743245971d0a94a1e6b2e45e 100644 (file)
@@ -2036,10 +2036,8 @@ static void collect_usb_address_map(struct usb_device *udev, unsigned long *map)
            udev->parent->descriptor.bDeviceClass == USB_CLASS_HUB)
                map[udev->devnum/32] |= (1 << (udev->devnum % 32));
 
-       usb_hub_for_each_child(udev, chix, childdev) {
-               if (childdev)
-                       collect_usb_address_map(childdev, map);
-       }
+       usb_hub_for_each_child(udev, chix, childdev)
+               collect_usb_address_map(childdev, map);
 }
 
 /* this function must be called with interrupt disabled */
index e4780491df4a8255de5f5196ca0813be6f44c681..68ebf20e15192f954eaf1a1e69735fadc878bd68 100644 (file)
@@ -60,6 +60,7 @@ static const struct hc_driver uhci_platform_hc_driver = {
        .hub_control =          uhci_hub_control,
 };
 
+static u64 platform_uhci_dma_mask = DMA_BIT_MASK(32);
 
 static int __devinit uhci_hcd_platform_probe(struct platform_device *pdev)
 {
@@ -71,6 +72,14 @@ static int __devinit uhci_hcd_platform_probe(struct platform_device *pdev)
        if (usb_disabled())
                return -ENODEV;
 
+       /*
+        * Right now device-tree probed devices don't get dma_mask set.
+        * Since shared usb code relies on it, set it here for now.
+        * Once we have dma capability bindings this can go away.
+        */
+       if (!pdev->dev.dma_mask)
+               pdev->dev.dma_mask = &platform_uhci_dma_mask;
+
        hcd = usb_create_hcd(&uhci_platform_hc_driver, &pdev->dev,
                        pdev->name);
        if (!hcd)
index d2c6f5ac4626af6c0297ab1348b9a14b18f77605..15921fd55048614de4940dabbdfb95564a129392 100644 (file)
@@ -1256,7 +1256,8 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb,
                struct uhci_qh *qh)
 {
        struct uhci_td *td = NULL;      /* Since urb->number_of_packets > 0 */
-       int i, frame;
+       int i;
+       unsigned frame, next;
        unsigned long destination, status;
        struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv;
 
@@ -1265,37 +1266,29 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb,
                        urb->number_of_packets >= UHCI_NUMFRAMES)
                return -EFBIG;
 
+       uhci_get_current_frame_number(uhci);
+
        /* Check the period and figure out the starting frame number */
        if (!qh->bandwidth_reserved) {
                qh->period = urb->interval;
-               if (urb->transfer_flags & URB_ISO_ASAP) {
-                       qh->phase = -1;         /* Find the best phase */
-                       i = uhci_check_bandwidth(uhci, qh);
-                       if (i)
-                               return i;
-
-                       /* Allow a little time to allocate the TDs */
-                       uhci_get_current_frame_number(uhci);
-                       frame = uhci->frame_number + 10;
-
-                       /* Move forward to the first frame having the
-                        * correct phase */
-                       urb->start_frame = frame + ((qh->phase - frame) &
-                                       (qh->period - 1));
-               } else {
-                       i = urb->start_frame - uhci->last_iso_frame;
-                       if (i <= 0 || i >= UHCI_NUMFRAMES)
-                               return -EINVAL;
-                       qh->phase = urb->start_frame & (qh->period - 1);
-                       i = uhci_check_bandwidth(uhci, qh);
-                       if (i)
-                               return i;
-               }
+               qh->phase = -1;         /* Find the best phase */
+               i = uhci_check_bandwidth(uhci, qh);
+               if (i)
+                       return i;
+
+               /* Allow a little time to allocate the TDs */
+               next = uhci->frame_number + 10;
+               frame = qh->phase;
+
+               /* Round up to the first available slot */
+               frame += (next - frame + qh->period - 1) & -qh->period;
 
        } else if (qh->period != urb->interval) {
                return -EINVAL;         /* Can't change the period */
 
        } else {
+               next = uhci->frame_number + 2;
+
                /* Find the next unused frame */
                if (list_empty(&qh->queue)) {
                        frame = qh->iso_frame;
@@ -1308,25 +1301,31 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb,
                                        lurb->number_of_packets *
                                        lurb->interval;
                }
-               if (urb->transfer_flags & URB_ISO_ASAP) {
-                       /* Skip some frames if necessary to insure
-                        * the start frame is in the future.
+
+               /* Fell behind? */
+               if (uhci_frame_before_eq(frame, next)) {
+
+                       /* USB_ISO_ASAP: Round up to the first available slot */
+                       if (urb->transfer_flags & URB_ISO_ASAP)
+                               frame += (next - frame + qh->period - 1) &
+                                               -qh->period;
+
+                       /*
+                        * Not ASAP: Use the next slot in the stream.  If
+                        * the entire URB falls before the threshold, fail.
                         */
-                       uhci_get_current_frame_number(uhci);
-                       if (uhci_frame_before_eq(frame, uhci->frame_number)) {
-                               frame = uhci->frame_number + 1;
-                               frame += ((qh->phase - frame) &
-                                       (qh->period - 1));
-                       }
-               }       /* Otherwise pick up where the last URB leaves off */
-               urb->start_frame = frame;
+                       else if (!uhci_frame_before_eq(next,
+                                       frame + (urb->number_of_packets - 1) *
+                                               qh->period))
+                               return -EXDEV;
+               }
        }
 
        /* Make sure we won't have to go too far into the future */
        if (uhci_frame_before_eq(uhci->last_iso_frame + UHCI_NUMFRAMES,
-                       urb->start_frame + urb->number_of_packets *
-                               urb->interval))
+                       frame + urb->number_of_packets * urb->interval))
                return -EFBIG;
+       urb->start_frame = frame;
 
        status = TD_CTRL_ACTIVE | TD_CTRL_IOS;
        destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe);
index aa90ad4d4fd53b2f70288641dcd13942355ca875..a686cf4905bb80ae3e4c7b206c05d7cd2b960920 100644 (file)
@@ -151,9 +151,8 @@ static void xhci_usb3_hub_descriptor(struct usb_hcd *hcd, struct xhci_hcd *xhci,
                if (portsc & PORT_DEV_REMOVE)
                        port_removable |= 1 << (i + 1);
        }
-       memset(&desc->u.ss.DeviceRemovable,
-                       (__force __u16) cpu_to_le16(port_removable),
-                       sizeof(__u16));
+
+       desc->u.ss.DeviceRemovable = cpu_to_le16(port_removable);
 }
 
 static void xhci_hub_descriptor(struct usb_hcd *hcd, struct xhci_hcd *xhci,
@@ -809,11 +808,13 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
                        temp = xhci_readl(xhci, port_array[wIndex]);
                        xhci_dbg(xhci, "set port power, actual port %d status  = 0x%x\n", wIndex, temp);
 
+                       spin_unlock_irqrestore(&xhci->lock, flags);
                        temp = usb_acpi_power_manageable(hcd->self.root_hub,
                                        wIndex);
                        if (temp)
                                usb_acpi_set_power_state(hcd->self.root_hub,
                                                wIndex, true);
+                       spin_lock_irqsave(&xhci->lock, flags);
                        break;
                case USB_PORT_FEAT_RESET:
                        temp = (temp | PORT_RESET);
@@ -917,11 +918,13 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
                        xhci_writel(xhci, temp & ~PORT_POWER,
                                port_array[wIndex]);
 
+                       spin_unlock_irqrestore(&xhci->lock, flags);
                        temp = usb_acpi_power_manageable(hcd->self.root_hub,
                                        wIndex);
                        if (temp)
                                usb_acpi_set_power_state(hcd->self.root_hub,
                                                wIndex, false);
+                       spin_lock_irqsave(&xhci->lock, flags);
                        break;
                default:
                        goto error;
index 8d7fcbbe6ade92df9dab163402be686544ae7f84..9ec939646b42f97e809eca4401ca7d3a91a7ad22 100644 (file)
@@ -479,7 +479,8 @@ static bool compliance_mode_recovery_timer_quirk_check(void)
 
        if (strstr(dmi_product_name, "Z420") ||
                        strstr(dmi_product_name, "Z620") ||
-                       strstr(dmi_product_name, "Z820"))
+                       strstr(dmi_product_name, "Z820") ||
+                       strstr(dmi_product_name, "Z1"))
                return true;
 
        return false;
@@ -4020,7 +4021,7 @@ int xhci_update_device(struct usb_hcd *hcd, struct usb_device *udev)
 static unsigned long long xhci_service_interval_to_ns(
                struct usb_endpoint_descriptor *desc)
 {
-       return (1 << (desc->bInterval - 1)) * 125 * 1000;
+       return (1ULL << (desc->bInterval - 1)) * 125 * 1000;
 }
 
 static u16 xhci_get_timeout_no_hub_lpm(struct usb_device *udev,
@@ -4141,7 +4142,7 @@ static u16 xhci_calculate_intel_u2_timeout(struct usb_device *udev,
                        (xhci_service_interval_to_ns(desc) > timeout_ns))
                timeout_ns = xhci_service_interval_to_ns(desc);
 
-       u2_del_ns = udev->bos->ss_cap->bU2DevExitLat * 1000;
+       u2_del_ns = le16_to_cpu(udev->bos->ss_cap->bU2DevExitLat) * 1000ULL;
        if (u2_del_ns > timeout_ns)
                timeout_ns = u2_del_ns;
 
index 4223d761223d3440a243a87150d4283537e89a4b..e712afed947c0743dffa1a099ca91832288eeb89 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/usb.h>
 #include <linux/firmware.h>
 #include <linux/ihex.h>
+#include <linux/usb/ezusb.h>
 
 struct ezusb_fx_type {
        /* EZ-USB Control and Status Register.  Bit 0 controls 8051 reset */
@@ -22,21 +23,16 @@ struct ezusb_fx_type {
        unsigned short max_internal_adress;
 };
 
-struct ezusb_fx_type ezusb_fx1 = {
+static struct ezusb_fx_type ezusb_fx1 = {
        .cpucs_reg = 0x7F92,
        .max_internal_adress = 0x1B3F,
 };
 
-struct ezusb_fx_type ezusb_fx2 = {
-       .cpucs_reg = 0xE600,
-       .max_internal_adress = 0x3FFF,
-};
-
 /* Commands for writing to memory */
 #define WRITE_INT_RAM 0xA0
 #define WRITE_EXT_RAM 0xA3
 
-int ezusb_writememory(struct usb_device *dev, int address,
+static int ezusb_writememory(struct usb_device *dev, int address,
                                unsigned char *data, int length, __u8 request)
 {
        int result;
@@ -58,10 +54,9 @@ int ezusb_writememory(struct usb_device *dev, int address,
        kfree(transfer_buffer);
        return result;
 }
-EXPORT_SYMBOL_GPL(ezusb_writememory);
 
-int ezusb_set_reset(struct usb_device *dev, unsigned short cpucs_reg,
-                        unsigned char reset_bit)
+static int ezusb_set_reset(struct usb_device *dev, unsigned short cpucs_reg,
+                          unsigned char reset_bit)
 {
        int response = ezusb_writememory(dev, cpucs_reg, &reset_bit, 1, WRITE_INT_RAM);
        if (response < 0)
@@ -76,12 +71,6 @@ int ezusb_fx1_set_reset(struct usb_device *dev, unsigned char reset_bit)
 }
 EXPORT_SYMBOL_GPL(ezusb_fx1_set_reset);
 
-int ezusb_fx2_set_reset(struct usb_device *dev, unsigned char reset_bit)
-{
-       return ezusb_set_reset(dev, ezusb_fx2.cpucs_reg, reset_bit);
-}
-EXPORT_SYMBOL_GPL(ezusb_fx2_set_reset);
-
 static int ezusb_ihex_firmware_download(struct usb_device *dev,
                                        struct ezusb_fx_type fx,
                                        const char *firmware_path)
@@ -151,10 +140,28 @@ int ezusb_fx1_ihex_firmware_download(struct usb_device *dev,
 }
 EXPORT_SYMBOL_GPL(ezusb_fx1_ihex_firmware_download);
 
+#if 0
+/*
+ * Once someone one needs these fx2 functions, uncomment them
+ * and add them to ezusb.h and all should be good.
+ */
+static struct ezusb_fx_type ezusb_fx2 = {
+       .cpucs_reg = 0xE600,
+       .max_internal_adress = 0x3FFF,
+};
+
+int ezusb_fx2_set_reset(struct usb_device *dev, unsigned char reset_bit)
+{
+       return ezusb_set_reset(dev, ezusb_fx2.cpucs_reg, reset_bit);
+}
+EXPORT_SYMBOL_GPL(ezusb_fx2_set_reset);
+
 int ezusb_fx2_ihex_firmware_download(struct usb_device *dev,
                                     const char *firmware_path)
 {
        return ezusb_ihex_firmware_download(dev, ezusb_fx2, firmware_path);
 }
 EXPORT_SYMBOL_GPL(ezusb_fx2_ihex_firmware_download);
+#endif
 
+MODULE_LICENSE("GPL");
index 457f25e62c519a33be80e39dcbb8b222cee8de12..c964d6af178bd0196e20a80bd482529c38369900 100644 (file)
@@ -305,6 +305,12 @@ static irqreturn_t am35x_musb_interrupt(int irq, void *hci)
                ret = IRQ_HANDLED;
        }
 
+       /* Drop spurious RX and TX if device is disconnected */
+       if (musb->int_usb & MUSB_INTR_DISCONNECT) {
+               musb->int_tx = 0;
+               musb->int_rx = 0;
+       }
+
        if (musb->int_tx || musb->int_rx || musb->int_usb)
                ret |= musb_interrupt(musb);
 
index 444346e1e10d768086b1e10487f6b6428c892897..ff5f112053d28f114e4d90844b7aa2172f3856d4 100644 (file)
@@ -458,11 +458,11 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id)
        struct platform_device  *musb;
        struct resource *res;
        struct resource resources[2];
-       char res_name[10];
+       char res_name[11];
        int ret, musbid;
 
        /* get memory resource */
-       sprintf(res_name, "musb%d", id);
+       snprintf(res_name, sizeof(res_name), "musb%d", id);
        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, res_name);
        if (!res) {
                dev_err(dev, "%s get mem resource failed\n", res_name);
@@ -473,7 +473,7 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id)
        resources[0] = *res;
 
        /* get irq resource */
-       sprintf(res_name, "musb%d-irq", id);
+       snprintf(res_name, sizeof(res_name), "musb%d-irq", id);
        res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, res_name);
        if (!res) {
                dev_err(dev, "%s get irq resource failed\n", res_name);
@@ -530,7 +530,7 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id)
 
                of_property_read_u32(np, "num-eps", (u32 *)&config->num_eps);
                of_property_read_u32(np, "ram-bits", (u32 *)&config->ram_bits);
-               sprintf(res_name, "port%d-mode", id);
+               snprintf(res_name, sizeof(res_name), "port%d-mode", id);
                of_property_read_u32(np, res_name, (u32 *)&pdata->mode);
                of_property_read_u32(np, "power", (u32 *)&pdata->power);
                config->multipoint = of_property_read_bool(np, "multipoint");
index 987116f9efcdec0fc7693725f3d315850f5f9eb8..9d13c81754e0cd0d2b38299dcb6143847ad380b2 100644 (file)
@@ -29,7 +29,9 @@
 #include <linux/usb/ulpi.h>
 #include <asm/mach-types.h>
 #include <linux/usb/tegra_usb_phy.h>
-#include <mach/iomap.h>
+
+#define TEGRA_USB_BASE         0xC5000000
+#define TEGRA_USB_SIZE         SZ_16K
 
 #define ULPI_VIEWPORT          0x170
 
index 143c4e9e1be45cc24c0a612d38e590a5ad136be9..c021b202c0f3fe05894d3a94075c55bea8dd1a66 100644 (file)
@@ -795,6 +795,7 @@ static void xfer_work(struct work_struct *work)
        dev_dbg(dev, "  %s %d (%d/ %d)\n",
                fifo->name, usbhs_pipe_number(pipe), pkt->length, pkt->zero);
 
+       usbhs_pipe_enable(pipe);
        usbhsf_dma_start(pipe, fifo);
        dma_async_issue_pending(chan);
 }
index 35c5208f32494d7c55f4fd98fa79cf517425ca46..61933a90e5bfdbe41fed1679979977e6ff849b4b 100644 (file)
@@ -273,9 +273,9 @@ static irqreturn_t usbhs_interrupt(int irq, void *data)
        usbhs_write(priv, INTSTS0, ~irq_state.intsts0 & INTSTS0_MAGIC);
        usbhs_write(priv, INTSTS1, ~irq_state.intsts1 & INTSTS1_MAGIC);
 
-       usbhs_write(priv, BRDYSTS, 0);
-       usbhs_write(priv, NRDYSTS, 0);
-       usbhs_write(priv, BEMPSTS, 0);
+       usbhs_write(priv, BRDYSTS, ~irq_state.brdysts);
+       usbhs_write(priv, NRDYSTS, ~irq_state.nrdysts);
+       usbhs_write(priv, BEMPSTS, ~irq_state.bempsts);
 
        /*
         * call irq callback functions
index 9b69a132329474052486e0483649b6c64a746a4f..069cd765400cbf51f649564d5ed8490d90cd8259 100644 (file)
@@ -334,6 +334,11 @@ static void usbhsh_pipe_detach(struct usbhsh_hpriv *hpriv,
        struct device *dev = usbhs_priv_to_dev(priv);
        unsigned long flags;
 
+       if (unlikely(!uep)) {
+               dev_err(dev, "no uep\n");
+               return;
+       }
+
        /********************  spin lock ********************/
        usbhs_lock(priv, flags);
 
index 08786c06dcf1d21f0784ea6d02553c381a11dfd0..3d80c7b1fd1b4ba15133e2ffcd3c5db7be2e9933 100644 (file)
@@ -54,7 +54,7 @@ struct usbhs_pipe_info {
  * pipe list
  */
 #define __usbhs_for_each_pipe(start, pos, info, i)     \
-       for (i = start, pos = (info)->pipe;             \
+       for (i = start, pos = (info)->pipe + i;         \
             i < (info)->size;                          \
             i++, pos = (info)->pipe + i)
 
index cf2522c397d3957c0477a591d20f59d108496aa2..bd50a8a41a0f583a589c06586d09765ae2c13a27 100644 (file)
@@ -125,9 +125,6 @@ static inline int calc_divisor(int bps)
 
 static int ark3116_attach(struct usb_serial *serial)
 {
-       struct usb_serial_port *port = serial->port[0];
-       struct ark3116_private *priv;
-
        /* make sure we have our end-points */
        if ((serial->num_bulk_in == 0) ||
            (serial->num_bulk_out == 0) ||
@@ -142,8 +139,15 @@ static int ark3116_attach(struct usb_serial *serial)
                return -EINVAL;
        }
 
-       priv = kzalloc(sizeof(struct ark3116_private),
-                      GFP_KERNEL);
+       return 0;
+}
+
+static int ark3116_port_probe(struct usb_serial_port *port)
+{
+       struct usb_serial *serial = port->serial;
+       struct ark3116_private *priv;
+
+       priv = kzalloc(sizeof(*priv), GFP_KERNEL);
        if (!priv)
                return -ENOMEM;
 
@@ -198,18 +202,15 @@ static int ark3116_attach(struct usb_serial *serial)
        return 0;
 }
 
-static void ark3116_release(struct usb_serial *serial)
+static int ark3116_port_remove(struct usb_serial_port *port)
 {
-       struct usb_serial_port *port = serial->port[0];
        struct ark3116_private *priv = usb_get_serial_port_data(port);
 
        /* device is closed, so URBs and DMA should be down */
-
-       usb_set_serial_port_data(port, NULL);
-
        mutex_destroy(&priv->hw_lock);
-
        kfree(priv);
+
+       return 0;
 }
 
 static void ark3116_init_termios(struct tty_struct *tty)
@@ -723,7 +724,8 @@ static struct usb_serial_driver ark3116_device = {
        .id_table =             id_table,
        .num_ports =            1,
        .attach =               ark3116_attach,
-       .release =              ark3116_release,
+       .port_probe =           ark3116_port_probe,
+       .port_remove =          ark3116_port_remove,
        .set_termios =          ark3116_set_termios,
        .init_termios =         ark3116_init_termios,
        .ioctl =                ark3116_ioctl,
index 99449424193f7295f5e3e5160e7993542080bda1..ea29556f0d7222a87475afa34e6fe683f6b4e513 100644 (file)
@@ -45,8 +45,8 @@
 #define DRIVER_DESC "USB Belkin Serial converter driver"
 
 /* function prototypes for a Belkin USB Serial Adapter F5U103 */
-static int  belkin_sa_startup(struct usb_serial *serial);
-static void belkin_sa_release(struct usb_serial *serial);
+static int belkin_sa_port_probe(struct usb_serial_port *port);
+static int belkin_sa_port_remove(struct usb_serial_port *port);
 static int  belkin_sa_open(struct tty_struct *tty,
                        struct usb_serial_port *port);
 static void belkin_sa_close(struct usb_serial_port *port);
@@ -88,8 +88,8 @@ static struct usb_serial_driver belkin_device = {
        .break_ctl =            belkin_sa_break_ctl,
        .tiocmget =             belkin_sa_tiocmget,
        .tiocmset =             belkin_sa_tiocmset,
-       .attach =               belkin_sa_startup,
-       .release =              belkin_sa_release,
+       .port_probe =           belkin_sa_port_probe,
+       .port_remove =          belkin_sa_port_remove,
 };
 
 static struct usb_serial_driver * const serial_drivers[] = {
@@ -118,17 +118,15 @@ struct belkin_sa_private {
                                            (c), BELKIN_SA_SET_REQUEST_TYPE, \
                                            (v), 0, NULL, 0, WDR_TIMEOUT)
 
-/* do some startup allocations not currently performed by usb_serial_probe() */
-static int belkin_sa_startup(struct usb_serial *serial)
+static int belkin_sa_port_probe(struct usb_serial_port *port)
 {
-       struct usb_device *dev = serial->dev;
+       struct usb_device *dev = port->serial->dev;
        struct belkin_sa_private *priv;
 
-       /* allocate the private data structure */
        priv = kmalloc(sizeof(struct belkin_sa_private), GFP_KERNEL);
        if (!priv)
-               return -1; /* error */
-       /* set initial values for control structures */
+               return -ENOMEM;
+
        spin_lock_init(&priv->lock);
        priv->control_state = 0;
        priv->last_lsr = 0;
@@ -140,18 +138,19 @@ static int belkin_sa_startup(struct usb_serial *serial)
                                        le16_to_cpu(dev->descriptor.bcdDevice),
                                        priv->bad_flow_control);
 
-       init_waitqueue_head(&serial->port[0]->write_wait);
-       usb_set_serial_port_data(serial->port[0], priv);
+       usb_set_serial_port_data(port, priv);
 
        return 0;
 }
 
-static void belkin_sa_release(struct usb_serial *serial)
+static int belkin_sa_port_remove(struct usb_serial_port *port)
 {
-       int i;
+       struct belkin_sa_private *priv;
 
-       for (i = 0; i < serial->num_ports; ++i)
-               kfree(usb_get_serial_port_data(serial->port[i]));
+       priv = usb_get_serial_port_data(port);
+       kfree(priv);
+
+       return 0;
 }
 
 static int belkin_sa_open(struct tty_struct *tty,
index 28af5acc3360c57beaad356f1b4aa016fc221810..eb033fc92a156bf3c8f43e94a248ead38f695642 100644 (file)
@@ -162,7 +162,7 @@ static const struct usb_device_id id_table[] = {
 
 MODULE_DEVICE_TABLE(usb, id_table);
 
-struct cp210x_port_private {
+struct cp210x_serial_private {
        __u8                    bInterfaceNumber;
 };
 
@@ -276,7 +276,7 @@ static int cp210x_get_config(struct usb_serial_port *port, u8 request,
                unsigned int *data, int size)
 {
        struct usb_serial *serial = port->serial;
-       struct cp210x_port_private *port_priv = usb_get_serial_port_data(port);
+       struct cp210x_serial_private *spriv = usb_get_serial_data(serial);
        __le32 *buf;
        int result, i, length;
 
@@ -292,7 +292,7 @@ static int cp210x_get_config(struct usb_serial_port *port, u8 request,
        /* Issue the request, attempting to read 'size' bytes */
        result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
                                request, REQTYPE_INTERFACE_TO_HOST, 0x0000,
-                               port_priv->bInterfaceNumber, buf, size,
+                               spriv->bInterfaceNumber, buf, size,
                                USB_CTRL_GET_TIMEOUT);
 
        /* Convert data into an array of integers */
@@ -323,7 +323,7 @@ static int cp210x_set_config(struct usb_serial_port *port, u8 request,
                unsigned int *data, int size)
 {
        struct usb_serial *serial = port->serial;
-       struct cp210x_port_private *port_priv = usb_get_serial_port_data(port);
+       struct cp210x_serial_private *spriv = usb_get_serial_data(serial);
        __le32 *buf;
        int result, i, length;
 
@@ -345,13 +345,13 @@ static int cp210x_set_config(struct usb_serial_port *port, u8 request,
                result = usb_control_msg(serial->dev,
                                usb_sndctrlpipe(serial->dev, 0),
                                request, REQTYPE_HOST_TO_INTERFACE, 0x0000,
-                               port_priv->bInterfaceNumber, buf, size,
+                               spriv->bInterfaceNumber, buf, size,
                                USB_CTRL_SET_TIMEOUT);
        } else {
                result = usb_control_msg(serial->dev,
                                usb_sndctrlpipe(serial->dev, 0),
                                request, REQTYPE_HOST_TO_INTERFACE, data[0],
-                               port_priv->bInterfaceNumber, NULL, 0,
+                               spriv->bInterfaceNumber, NULL, 0,
                                USB_CTRL_SET_TIMEOUT);
        }
 
@@ -845,36 +845,30 @@ static void cp210x_break_ctl (struct tty_struct *tty, int break_state)
 
 static int cp210x_startup(struct usb_serial *serial)
 {
-       struct cp210x_port_private *port_priv;
-       int i;
+       struct usb_host_interface *cur_altsetting;
+       struct cp210x_serial_private *spriv;
 
        /* cp210x buffers behave strangely unless device is reset */
        usb_reset_device(serial->dev);
 
-       for (i = 0; i < serial->num_ports; i++) {
-               port_priv = kzalloc(sizeof(*port_priv), GFP_KERNEL);
-               if (!port_priv)
-                       return -ENOMEM;
+       spriv = kzalloc(sizeof(*spriv), GFP_KERNEL);
+       if (!spriv)
+               return -ENOMEM;
 
-               port_priv->bInterfaceNumber =
-                   serial->interface->cur_altsetting->desc.bInterfaceNumber;
+       cur_altsetting = serial->interface->cur_altsetting;
+       spriv->bInterfaceNumber = cur_altsetting->desc.bInterfaceNumber;
 
-               usb_set_serial_port_data(serial->port[i], port_priv);
-       }
+       usb_set_serial_data(serial, spriv);
 
        return 0;
 }
 
 static void cp210x_release(struct usb_serial *serial)
 {
-       struct cp210x_port_private *port_priv;
-       int i;
+       struct cp210x_serial_private *spriv;
 
-       for (i = 0; i < serial->num_ports; i++) {
-               port_priv = usb_get_serial_port_data(serial->port[i]);
-               kfree(port_priv);
-               usb_set_serial_port_data(serial->port[i], NULL);
-       }
+       spriv = usb_get_serial_data(serial);
+       kfree(spriv);
 }
 
 module_usb_serial_driver(serial_drivers, id_table);
index 2a7aecc72237ccaac68b2c922093182c878acbda..4ee77dcbe690dc73e95f79ebf2d3d75e2784326b 100644 (file)
@@ -55,9 +55,9 @@
 #define CYBERJACK_PRODUCT_ID   0x0100
 
 /* Function prototypes */
-static int cyberjack_startup(struct usb_serial *serial);
 static void cyberjack_disconnect(struct usb_serial *serial);
-static void cyberjack_release(struct usb_serial *serial);
+static int cyberjack_port_probe(struct usb_serial_port *port);
+static int cyberjack_port_remove(struct usb_serial_port *port);
 static int  cyberjack_open(struct tty_struct *tty,
        struct usb_serial_port *port);
 static void cyberjack_close(struct usb_serial_port *port);
@@ -83,9 +83,9 @@ static struct usb_serial_driver cyberjack_device = {
        .description =          "Reiner SCT Cyberjack USB card reader",
        .id_table =             id_table,
        .num_ports =            1,
-       .attach =               cyberjack_startup,
        .disconnect =           cyberjack_disconnect,
-       .release =              cyberjack_release,
+       .port_probe =           cyberjack_port_probe,
+       .port_remove =          cyberjack_port_remove,
        .open =                 cyberjack_open,
        .close =                cyberjack_close,
        .write =                cyberjack_write,
@@ -107,56 +107,45 @@ struct cyberjack_private {
        short           wrsent;         /* Data already sent */
 };
 
-/* do some startup allocations not currently performed by usb_serial_probe() */
-static int cyberjack_startup(struct usb_serial *serial)
+static int cyberjack_port_probe(struct usb_serial_port *port)
 {
        struct cyberjack_private *priv;
-       int i;
+       int result;
 
-       /* allocate the private data structure */
        priv = kmalloc(sizeof(struct cyberjack_private), GFP_KERNEL);
        if (!priv)
                return -ENOMEM;
 
-       /* set initial values */
        spin_lock_init(&priv->lock);
        priv->rdtodo = 0;
        priv->wrfilled = 0;
        priv->wrsent = 0;
-       usb_set_serial_port_data(serial->port[0], priv);
 
-       init_waitqueue_head(&serial->port[0]->write_wait);
+       usb_set_serial_port_data(port, priv);
 
-       for (i = 0; i < serial->num_ports; ++i) {
-               int result;
-               result = usb_submit_urb(serial->port[i]->interrupt_in_urb,
-                                       GFP_KERNEL);
-               if (result)
-                       dev_err(&serial->dev->dev,
-                               "usb_submit_urb(read int) failed\n");
-               dev_dbg(&serial->dev->dev, "%s - usb_submit_urb(int urb)\n",
-                       __func__);
-       }
+       result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
+       if (result)
+               dev_err(&port->dev, "usb_submit_urb(read int) failed\n");
 
        return 0;
 }
 
-static void cyberjack_disconnect(struct usb_serial *serial)
+static int cyberjack_port_remove(struct usb_serial_port *port)
 {
-       int i;
+       struct cyberjack_private *priv;
 
-       for (i = 0; i < serial->num_ports; ++i)
-               usb_kill_urb(serial->port[i]->interrupt_in_urb);
+       priv = usb_get_serial_port_data(port);
+       kfree(priv);
+
+       return 0;
 }
 
-static void cyberjack_release(struct usb_serial *serial)
+static void cyberjack_disconnect(struct usb_serial *serial)
 {
        int i;
 
-       for (i = 0; i < serial->num_ports; ++i) {
-               /* My special items, the standard routines free my urbs */
-               kfree(usb_get_serial_port_data(serial->port[i]));
-       }
+       for (i = 0; i < serial->num_ports; ++i)
+               usb_kill_urb(serial->port[i]->interrupt_in_urb);
 }
 
 static int  cyberjack_open(struct tty_struct *tty,
index 1befce21e1734df489e940e49023a9b8a3c37d95..f0da1279c11410ece644a5fd4f4cf9e4532588c8 100644 (file)
@@ -123,10 +123,10 @@ struct cypress_private {
 };
 
 /* function prototypes for the Cypress USB to serial device */
-static int  cypress_earthmate_startup(struct usb_serial *serial);
-static int  cypress_hidcom_startup(struct usb_serial *serial);
-static int  cypress_ca42v2_startup(struct usb_serial *serial);
-static void cypress_release(struct usb_serial *serial);
+static int  cypress_earthmate_port_probe(struct usb_serial_port *port);
+static int  cypress_hidcom_port_probe(struct usb_serial_port *port);
+static int  cypress_ca42v2_port_probe(struct usb_serial_port *port);
+static int  cypress_port_remove(struct usb_serial_port *port);
 static int  cypress_open(struct tty_struct *tty, struct usb_serial_port *port);
 static void cypress_close(struct usb_serial_port *port);
 static void cypress_dtr_rts(struct usb_serial_port *port, int on);
@@ -156,8 +156,8 @@ static struct usb_serial_driver cypress_earthmate_device = {
        .description =                  "DeLorme Earthmate USB",
        .id_table =                     id_table_earthmate,
        .num_ports =                    1,
-       .attach =                       cypress_earthmate_startup,
-       .release =                      cypress_release,
+       .port_probe =                   cypress_earthmate_port_probe,
+       .port_remove =                  cypress_port_remove,
        .open =                         cypress_open,
        .close =                        cypress_close,
        .dtr_rts =                      cypress_dtr_rts,
@@ -182,8 +182,8 @@ static struct usb_serial_driver cypress_hidcom_device = {
        .description =                  "HID->COM RS232 Adapter",
        .id_table =                     id_table_cyphidcomrs232,
        .num_ports =                    1,
-       .attach =                       cypress_hidcom_startup,
-       .release =                      cypress_release,
+       .port_probe =                   cypress_hidcom_port_probe,
+       .port_remove =                  cypress_port_remove,
        .open =                         cypress_open,
        .close =                        cypress_close,
        .dtr_rts =                      cypress_dtr_rts,
@@ -208,8 +208,8 @@ static struct usb_serial_driver cypress_ca42v2_device = {
        .description =                  "Nokia CA-42 V2 Adapter",
        .id_table =                     id_table_nokiaca42v2,
        .num_ports =                    1,
-       .attach =                       cypress_ca42v2_startup,
-       .release =                      cypress_release,
+       .port_probe =                   cypress_ca42v2_port_probe,
+       .port_remove =                  cypress_port_remove,
        .open =                         cypress_open,
        .close =                        cypress_close,
        .dtr_rts =                      cypress_dtr_rts,
@@ -438,10 +438,10 @@ static void cypress_set_dead(struct usb_serial_port *port)
  *****************************************************************************/
 
 
-static int generic_startup(struct usb_serial *serial)
+static int cypress_generic_port_probe(struct usb_serial_port *port)
 {
+       struct usb_serial *serial = port->serial;
        struct cypress_private *priv;
-       struct usb_serial_port *port = serial->port[0];
 
        priv = kzalloc(sizeof(struct cypress_private), GFP_KERNEL);
        if (!priv)
@@ -490,14 +490,16 @@ static int generic_startup(struct usb_serial *serial)
 }
 
 
-static int cypress_earthmate_startup(struct usb_serial *serial)
+static int cypress_earthmate_port_probe(struct usb_serial_port *port)
 {
+       struct usb_serial *serial = port->serial;
        struct cypress_private *priv;
-       struct usb_serial_port *port = serial->port[0];
+       int ret;
 
-       if (generic_startup(serial)) {
+       ret = cypress_generic_port_probe(port);
+       if (ret) {
                dev_dbg(&port->dev, "%s - Failed setting up port\n", __func__);
-               return 1;
+               return ret;
        }
 
        priv = usb_get_serial_port_data(port);
@@ -518,56 +520,53 @@ static int cypress_earthmate_startup(struct usb_serial *serial)
        }
 
        return 0;
-} /* cypress_earthmate_startup */
-
+}
 
-static int cypress_hidcom_startup(struct usb_serial *serial)
+static int cypress_hidcom_port_probe(struct usb_serial_port *port)
 {
        struct cypress_private *priv;
-       struct usb_serial_port *port = serial->port[0];
+       int ret;
 
-       if (generic_startup(serial)) {
+       ret = cypress_generic_port_probe(port);
+       if (ret) {
                dev_dbg(&port->dev, "%s - Failed setting up port\n", __func__);
-               return 1;
+               return ret;
        }
 
        priv = usb_get_serial_port_data(port);
        priv->chiptype = CT_CYPHIDCOM;
 
        return 0;
-} /* cypress_hidcom_startup */
-
+}
 
-static int cypress_ca42v2_startup(struct usb_serial *serial)
+static int cypress_ca42v2_port_probe(struct usb_serial_port *port)
 {
        struct cypress_private *priv;
-       struct usb_serial_port *port = serial->port[0];
+       int ret;
 
-       if (generic_startup(serial)) {
+       ret = cypress_generic_port_probe(port);
+       if (ret) {
                dev_dbg(&port->dev, "%s - Failed setting up port\n", __func__);
-               return 1;
+               return ret;
        }
 
        priv = usb_get_serial_port_data(port);
        priv->chiptype = CT_CA42V2;
 
        return 0;
-} /* cypress_ca42v2_startup */
-
+}
 
-static void cypress_release(struct usb_serial *serial)
+static int cypress_port_remove(struct usb_serial_port *port)
 {
        struct cypress_private *priv;
 
-       /* all open ports are closed at this point */
-       priv = usb_get_serial_port_data(serial->port[0]);
+       priv = usb_get_serial_port_data(port);
 
-       if (priv) {
-               kfifo_free(&priv->write_fifo);
-               kfree(priv);
-       }
-}
+       kfifo_free(&priv->write_fifo);
+       kfree(priv);
 
+       return 0;
+}
 
 static int cypress_open(struct tty_struct *tty, struct usb_serial_port *port)
 {
index 244477107e2f1f1b9a13e0d26349eac502563c0a..6e4eb57d0177406c5eb8f9d30c83f0551dd159f7 100644 (file)
@@ -318,39 +318,30 @@ static int f81232_ioctl(struct tty_struct *tty,
        return -ENOIOCTLCMD;
 }
 
-static int f81232_startup(struct usb_serial *serial)
+static int f81232_port_probe(struct usb_serial_port *port)
 {
        struct f81232_private *priv;
-       int i;
 
-       for (i = 0; i < serial->num_ports; ++i) {
-               priv = kzalloc(sizeof(struct f81232_private), GFP_KERNEL);
-               if (!priv)
-                       goto cleanup;
-               spin_lock_init(&priv->lock);
-               init_waitqueue_head(&priv->delta_msr_wait);
-               usb_set_serial_port_data(serial->port[i], priv);
-       }
-       return 0;
+       priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
 
-cleanup:
-       for (--i; i >= 0; --i) {
-               priv = usb_get_serial_port_data(serial->port[i]);
-               kfree(priv);
-               usb_set_serial_port_data(serial->port[i], NULL);
-       }
-       return -ENOMEM;
+       spin_lock_init(&priv->lock);
+       init_waitqueue_head(&priv->delta_msr_wait);
+
+       usb_set_serial_port_data(port, priv);
+
+       return 0;
 }
 
-static void f81232_release(struct usb_serial *serial)
+static int f81232_port_remove(struct usb_serial_port *port)
 {
-       int i;
        struct f81232_private *priv;
 
-       for (i = 0; i < serial->num_ports; ++i) {
-               priv = usb_get_serial_port_data(serial->port[i]);
-               kfree(priv);
-       }
+       priv = usb_get_serial_port_data(port);
+       kfree(priv);
+
+       return 0;
 }
 
 static struct usb_serial_driver f81232_device = {
@@ -373,8 +364,8 @@ static struct usb_serial_driver f81232_device = {
        .tiocmset =             f81232_tiocmset,
        .process_read_urb =     f81232_process_read_urb,
        .read_int_callback =    f81232_read_int_callback,
-       .attach =               f81232_startup,
-       .release =              f81232_release,
+       .port_probe =           f81232_port_probe,
+       .port_remove =          f81232_port_remove,
 };
 
 static struct usb_serial_driver * const serial_drivers[] = {
index 3ee92648c02dd589a75dc7d29125f26d3aa1f9ff..203358d7e7bc6ed23d78bf0a35cbf797e3e4f4bb 100644 (file)
@@ -1405,11 +1405,10 @@ static void timeout_handler(unsigned long data)
 
 
 
-static int garmin_attach(struct usb_serial *serial)
+static int garmin_port_probe(struct usb_serial_port *port)
 {
-       int status = 0;
-       struct usb_serial_port *port = serial->port[0];
-       struct garmin_data *garmin_data_p = NULL;
+       int status;
+       struct garmin_data *garmin_data_p;
 
        garmin_data_p = kzalloc(sizeof(struct garmin_data), GFP_KERNEL);
        if (garmin_data_p == NULL) {
@@ -1434,22 +1433,14 @@ static int garmin_attach(struct usb_serial *serial)
 }
 
 
-static void garmin_disconnect(struct usb_serial *serial)
+static int garmin_port_remove(struct usb_serial_port *port)
 {
-       struct usb_serial_port *port = serial->port[0];
        struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
 
        usb_kill_urb(port->interrupt_in_urb);
        del_timer_sync(&garmin_data_p->timer);
-}
-
-
-static void garmin_release(struct usb_serial *serial)
-{
-       struct usb_serial_port *port = serial->port[0];
-       struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
-
        kfree(garmin_data_p);
+       return 0;
 }
 
 
@@ -1466,9 +1457,8 @@ static struct usb_serial_driver garmin_device = {
        .close               = garmin_close,
        .throttle            = garmin_throttle,
        .unthrottle          = garmin_unthrottle,
-       .attach              = garmin_attach,
-       .disconnect          = garmin_disconnect,
-       .release             = garmin_release,
+       .port_probe             = garmin_port_probe,
+       .port_remove            = garmin_port_remove,
        .write               = garmin_write,
        .write_room          = garmin_write_room,
        .write_bulk_callback = garmin_write_bulk_callback,
index 8e6faaf3580cb102abaea73be8d3636446dba7b6..5acc0d13864a400344a012400f20bc989fa23574 100644 (file)
@@ -225,6 +225,8 @@ static int  edge_get_icount(struct tty_struct *tty,
 static int  edge_startup(struct usb_serial *serial);
 static void edge_disconnect(struct usb_serial *serial);
 static void edge_release(struct usb_serial *serial);
+static int edge_port_probe(struct usb_serial_port *port);
+static int edge_port_remove(struct usb_serial_port *port);
 
 #include "io_tables.h" /* all of the devices that this driver supports */
 
@@ -2875,10 +2877,9 @@ static void load_application_firmware(struct edgeport_serial *edge_serial)
 static int edge_startup(struct usb_serial *serial)
 {
        struct edgeport_serial *edge_serial;
-       struct edgeport_port *edge_port;
        struct usb_device *dev;
        struct device *ddev = &serial->dev->dev;
-       int i, j;
+       int i;
        int response;
        bool interrupt_in_found;
        bool bulk_in_found;
@@ -2961,25 +2962,6 @@ static int edge_startup(struct usb_serial *serial)
        /* we set up the pointers to the endpoints in the edge_open function,
         * as the structures aren't created yet. */
 
-       /* set up our port private structures */
-       for (i = 0; i < serial->num_ports; ++i) {
-               edge_port = kzalloc(sizeof(struct edgeport_port), GFP_KERNEL);
-               if (edge_port == NULL) {
-                       dev_err(ddev, "%s - Out of memory\n", __func__);
-                       for (j = 0; j < i; ++j) {
-                               kfree(usb_get_serial_port_data(serial->port[j]));
-                               usb_set_serial_port_data(serial->port[j],
-                                                                       NULL);
-                       }
-                       usb_set_serial_data(serial, NULL);
-                       kfree(edge_serial);
-                       return -ENOMEM;
-               }
-               spin_lock_init(&edge_port->ep_lock);
-               edge_port->port = serial->port[i];
-               usb_set_serial_port_data(serial->port[i], edge_port);
-       }
-
        response = 0;
 
        if (edge_serial->is_epic) {
@@ -3120,14 +3102,36 @@ static void edge_disconnect(struct usb_serial *serial)
 static void edge_release(struct usb_serial *serial)
 {
        struct edgeport_serial *edge_serial = usb_get_serial_data(serial);
-       int i;
-
-       for (i = 0; i < serial->num_ports; ++i)
-               kfree(usb_get_serial_port_data(serial->port[i]));
 
        kfree(edge_serial);
 }
 
+static int edge_port_probe(struct usb_serial_port *port)
+{
+       struct edgeport_port *edge_port;
+
+       edge_port = kzalloc(sizeof(*edge_port), GFP_KERNEL);
+       if (!edge_port)
+               return -ENOMEM;
+
+       spin_lock_init(&edge_port->ep_lock);
+       edge_port->port = port;
+
+       usb_set_serial_port_data(port, edge_port);
+
+       return 0;
+}
+
+static int edge_port_remove(struct usb_serial_port *port)
+{
+       struct edgeport_port *edge_port;
+
+       edge_port = usb_get_serial_port_data(port);
+       kfree(edge_port);
+
+       return 0;
+}
+
 module_usb_serial_driver(serial_drivers, id_table_combined);
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
index 350afddb55ba8c1fd276068518de05c78ac280ee..1511dd0ad3242650e6da605d316b2d7165b1fb2d 100644 (file)
@@ -110,6 +110,8 @@ static struct usb_serial_driver edgeport_2port_device = {
        .attach                 = edge_startup,
        .disconnect             = edge_disconnect,
        .release                = edge_release,
+       .port_probe             = edge_port_probe,
+       .port_remove            = edge_port_remove,
        .ioctl                  = edge_ioctl,
        .set_termios            = edge_set_termios,
        .tiocmget               = edge_tiocmget,
@@ -139,6 +141,8 @@ static struct usb_serial_driver edgeport_4port_device = {
        .attach                 = edge_startup,
        .disconnect             = edge_disconnect,
        .release                = edge_release,
+       .port_probe             = edge_port_probe,
+       .port_remove            = edge_port_remove,
        .ioctl                  = edge_ioctl,
        .set_termios            = edge_set_termios,
        .tiocmget               = edge_tiocmget,
@@ -168,6 +172,8 @@ static struct usb_serial_driver edgeport_8port_device = {
        .attach                 = edge_startup,
        .disconnect             = edge_disconnect,
        .release                = edge_release,
+       .port_probe             = edge_port_probe,
+       .port_remove            = edge_port_remove,
        .ioctl                  = edge_ioctl,
        .set_termios            = edge_set_termios,
        .tiocmget               = edge_tiocmget,
@@ -197,6 +203,8 @@ static struct usb_serial_driver epic_device = {
        .attach                 = edge_startup,
        .disconnect             = edge_disconnect,
        .release                = edge_release,
+       .port_probe             = edge_port_probe,
+       .port_remove            = edge_port_remove,
        .ioctl                  = edge_ioctl,
        .set_termios            = edge_set_termios,
        .tiocmget               = edge_tiocmget,
index a2209cd4509396d3827d4a0627c59f42b5d713be..60023c2d2a317008d7aab0c78bd5120f77b1597c 100644 (file)
@@ -2532,12 +2532,7 @@ static void edge_break(struct tty_struct *tty, int break_state)
 static int edge_startup(struct usb_serial *serial)
 {
        struct edgeport_serial *edge_serial;
-       struct edgeport_port *edge_port;
-       struct usb_device *dev;
        int status;
-       int i;
-
-       dev = serial->dev;
 
        /* create our private serial structure */
        edge_serial = kzalloc(sizeof(struct edgeport_serial), GFP_KERNEL);
@@ -2555,40 +2550,7 @@ static int edge_startup(struct usb_serial *serial)
                return status;
        }
 
-       /* set up our port private structures */
-       for (i = 0; i < serial->num_ports; ++i) {
-               edge_port = kzalloc(sizeof(struct edgeport_port), GFP_KERNEL);
-               if (edge_port == NULL) {
-                       dev_err(&serial->dev->dev, "%s - Out of memory\n",
-                                                               __func__);
-                       goto cleanup;
-               }
-               spin_lock_init(&edge_port->ep_lock);
-               if (kfifo_alloc(&edge_port->write_fifo, EDGE_OUT_BUF_SIZE,
-                                                               GFP_KERNEL)) {
-                       dev_err(&serial->dev->dev, "%s - Out of memory\n",
-                                                               __func__);
-                       kfree(edge_port);
-                       goto cleanup;
-               }
-               edge_port->port = serial->port[i];
-               edge_port->edge_serial = edge_serial;
-               usb_set_serial_port_data(serial->port[i], edge_port);
-               edge_port->bUartMode = default_uart_mode;
-       }
-
        return 0;
-
-cleanup:
-       for (--i; i >= 0; --i) {
-               edge_port = usb_get_serial_port_data(serial->port[i]);
-               kfifo_free(&edge_port->write_fifo);
-               kfree(edge_port);
-               usb_set_serial_port_data(serial->port[i], NULL);
-       }
-       kfree(edge_serial);
-       usb_set_serial_data(serial, NULL);
-       return -ENOMEM;
 }
 
 static void edge_disconnect(struct usb_serial *serial)
@@ -2597,17 +2559,54 @@ static void edge_disconnect(struct usb_serial *serial)
 
 static void edge_release(struct usb_serial *serial)
 {
-       int i;
+       kfree(usb_get_serial_data(serial));
+}
+
+static int edge_port_probe(struct usb_serial_port *port)
+{
        struct edgeport_port *edge_port;
+       int ret;
 
-       for (i = 0; i < serial->num_ports; ++i) {
-               edge_port = usb_get_serial_port_data(serial->port[i]);
+       edge_port = kzalloc(sizeof(*edge_port), GFP_KERNEL);
+       if (!edge_port)
+               return -ENOMEM;
+
+       ret = kfifo_alloc(&edge_port->write_fifo, EDGE_OUT_BUF_SIZE,
+                                                               GFP_KERNEL);
+       if (ret) {
+               kfree(edge_port);
+               return -ENOMEM;
+       }
+
+       spin_lock_init(&edge_port->ep_lock);
+       edge_port->port = port;
+       edge_port->edge_serial = usb_get_serial_data(port->serial);
+       edge_port->bUartMode = default_uart_mode;
+
+       usb_set_serial_port_data(port, edge_port);
+
+       ret = edge_create_sysfs_attrs(port);
+       if (ret) {
                kfifo_free(&edge_port->write_fifo);
                kfree(edge_port);
+               return ret;
        }
-       kfree(usb_get_serial_data(serial));
+
+       return 0;
 }
 
+static int edge_port_remove(struct usb_serial_port *port)
+{
+       struct edgeport_port *edge_port;
+
+       edge_port = usb_get_serial_port_data(port);
+
+       edge_remove_sysfs_attrs(port);
+       kfifo_free(&edge_port->write_fifo);
+       kfree(edge_port);
+
+       return 0;
+}
 
 /* Sysfs Attributes */
 
@@ -2667,8 +2666,8 @@ static struct usb_serial_driver edgeport_1port_device = {
        .attach                 = edge_startup,
        .disconnect             = edge_disconnect,
        .release                = edge_release,
-       .port_probe             = edge_create_sysfs_attrs,
-       .port_remove            = edge_remove_sysfs_attrs,
+       .port_probe             = edge_port_probe,
+       .port_remove            = edge_port_remove,
        .ioctl                  = edge_ioctl,
        .set_termios            = edge_set_termios,
        .tiocmget               = edge_tiocmget,
@@ -2698,8 +2697,8 @@ static struct usb_serial_driver edgeport_2port_device = {
        .attach                 = edge_startup,
        .disconnect             = edge_disconnect,
        .release                = edge_release,
-       .port_probe             = edge_create_sysfs_attrs,
-       .port_remove            = edge_remove_sysfs_attrs,
+       .port_probe             = edge_port_probe,
+       .port_remove            = edge_port_remove,
        .ioctl                  = edge_ioctl,
        .set_termios            = edge_set_termios,
        .tiocmget               = edge_tiocmget,
index 01da3ea36e89d5363a8890339eac6165dec0e14c..cd5533e81de7e113d77898795996346ce036378a 100644 (file)
@@ -53,6 +53,8 @@ static int iuu_cardout;
 static bool xmas;
 static int vcc_default = 5;
 
+static int iuu_create_sysfs_attrs(struct usb_serial_port *port);
+static int iuu_remove_sysfs_attrs(struct usb_serial_port *port);
 static void read_rxcmd_callback(struct urb *urb);
 
 struct iuu_private {
@@ -72,63 +74,55 @@ struct iuu_private {
        u32 clk;
 };
 
-
-static void iuu_free_buf(struct iuu_private *priv)
-{
-       kfree(priv->buf);
-       kfree(priv->writebuf);
-}
-
-static int iuu_alloc_buf(struct usb_serial *serial, struct iuu_private *priv)
-{
-       priv->buf = kzalloc(256, GFP_KERNEL);
-       priv->writebuf = kzalloc(256, GFP_KERNEL);
-       if (!priv->buf || !priv->writebuf) {
-               iuu_free_buf(priv);
-               dev_dbg(&serial->dev->dev, "%s problem allocation buffer\n", __func__);
-               return -ENOMEM;
-       }
-       dev_dbg(&serial->dev->dev, "%s - Privates buffers allocation success\n", __func__);
-       return 0;
-}
-
-static int iuu_startup(struct usb_serial *serial)
+static int iuu_port_probe(struct usb_serial_port *port)
 {
        struct iuu_private *priv;
+       int ret;
 
        priv = kzalloc(sizeof(struct iuu_private), GFP_KERNEL);
-       dev_dbg(&serial->dev->dev, "%s- priv allocation success\n", __func__);
        if (!priv)
                return -ENOMEM;
-       if (iuu_alloc_buf(serial, priv)) {
+
+       priv->buf = kzalloc(256, GFP_KERNEL);
+       if (!priv->buf) {
+               kfree(priv);
+               return -ENOMEM;
+       }
+
+       priv->writebuf = kzalloc(256, GFP_KERNEL);
+       if (!priv->writebuf) {
+               kfree(priv->buf);
                kfree(priv);
                return -ENOMEM;
        }
+
        priv->vcc = vcc_default;
        spin_lock_init(&priv->lock);
        init_waitqueue_head(&priv->delta_msr_wait);
-       usb_set_serial_port_data(serial->port[0], priv);
+
+       usb_set_serial_port_data(port, priv);
+
+       ret = iuu_create_sysfs_attrs(port);
+       if (ret) {
+               kfree(priv->writebuf);
+               kfree(priv->buf);
+               kfree(priv);
+               return ret;
+       }
+
        return 0;
 }
 
-/* Release function */
-static void iuu_release(struct usb_serial *serial)
+static int iuu_port_remove(struct usb_serial_port *port)
 {
-       struct usb_serial_port *port = serial->port[0];
        struct iuu_private *priv = usb_get_serial_port_data(port);
-       if (!port)
-               return;
 
-       if (priv) {
-               iuu_free_buf(priv);
-               dev_dbg(&port->dev, "%s - I will free all\n", __func__);
-               usb_set_serial_port_data(port, NULL);
-
-               dev_dbg(&port->dev, "%s - priv is not anymore in port structure\n", __func__);
-               kfree(priv);
+       iuu_remove_sysfs_attrs(port);
+       kfree(priv->writebuf);
+       kfree(priv->buf);
+       kfree(priv);
 
-               dev_dbg(&port->dev, "%s priv is now kfree\n", __func__);
-       }
+       return 0;
 }
 
 static int iuu_tiocmset(struct tty_struct *tty,
@@ -1215,8 +1209,6 @@ static struct usb_serial_driver iuu_device = {
        .num_ports = 1,
        .bulk_in_size = 512,
        .bulk_out_size = 512,
-       .port_probe = iuu_create_sysfs_attrs,
-       .port_remove = iuu_remove_sysfs_attrs,
        .open = iuu_open,
        .close = iuu_close,
        .write = iuu_uart_write,
@@ -1225,8 +1217,8 @@ static struct usb_serial_driver iuu_device = {
        .tiocmset = iuu_tiocmset,
        .set_termios = iuu_set_termios,
        .init_termios = iuu_init_termios,
-       .attach = iuu_startup,
-       .release = iuu_release,
+       .port_probe = iuu_port_probe,
+       .port_remove = iuu_port_remove,
 };
 
 static struct usb_serial_driver * const serial_drivers[] = {
index ca43ecb4a2bdd494e997a36ecd591b3a410132d2..bb87e29c4ac29645804b05a9e52455f8125ff05c 100644 (file)
@@ -713,29 +713,33 @@ MODULE_FIRMWARE("keyspan_pda/keyspan_pda.fw");
 MODULE_FIRMWARE("keyspan_pda/xircom_pgs.fw");
 #endif
 
-static int keyspan_pda_startup(struct usb_serial *serial)
+static int keyspan_pda_port_probe(struct usb_serial_port *port)
 {
 
        struct keyspan_pda_private *priv;
 
-       /* allocate the private data structures for all ports. Well, for all
-          one ports. */
-
        priv = kmalloc(sizeof(struct keyspan_pda_private), GFP_KERNEL);
        if (!priv)
-               return 1; /* error */
-       usb_set_serial_port_data(serial->port[0], priv);
-       init_waitqueue_head(&serial->port[0]->write_wait);
+               return -ENOMEM;
+
        INIT_WORK(&priv->wakeup_work, keyspan_pda_wakeup_write);
        INIT_WORK(&priv->unthrottle_work, keyspan_pda_request_unthrottle);
-       priv->serial = serial;
-       priv->port = serial->port[0];
+       priv->serial = port->serial;
+       priv->port = port;
+
+       usb_set_serial_port_data(port, priv);
+
        return 0;
 }
 
-static void keyspan_pda_release(struct usb_serial *serial)
+static int keyspan_pda_port_remove(struct usb_serial_port *port)
 {
-       kfree(usb_get_serial_port_data(serial->port[0]));
+       struct keyspan_pda_private *priv;
+
+       priv = usb_get_serial_port_data(port);
+       kfree(priv);
+
+       return 0;
 }
 
 #ifdef KEYSPAN
@@ -786,8 +790,8 @@ static struct usb_serial_driver keyspan_pda_device = {
        .break_ctl =            keyspan_pda_break_ctl,
        .tiocmget =             keyspan_pda_tiocmget,
        .tiocmset =             keyspan_pda_tiocmset,
-       .attach =               keyspan_pda_startup,
-       .release =              keyspan_pda_release,
+       .port_probe =           keyspan_pda_port_probe,
+       .port_remove =          keyspan_pda_port_remove,
 };
 
 static struct usb_serial_driver * const serial_drivers[] = {
index 3f6d7376c02d48e5a145449d79fe5ed4a3f01b3d..1f4517864cd25cd6bdf665bce9d154f0c708f99d 100644 (file)
@@ -60,8 +60,8 @@
 /*
  * Function prototypes
  */
-static int  klsi_105_startup(struct usb_serial *serial);
-static void klsi_105_release(struct usb_serial *serial);
+static int klsi_105_port_probe(struct usb_serial_port *port);
+static int klsi_105_port_remove(struct usb_serial_port *port);
 static int  klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port);
 static void klsi_105_close(struct usb_serial_port *port);
 static void klsi_105_set_termios(struct tty_struct *tty,
@@ -99,8 +99,8 @@ static struct usb_serial_driver kl5kusb105d_device = {
        /*.break_ctl =          klsi_105_break_ctl,*/
        .tiocmget =             klsi_105_tiocmget,
        .tiocmset =             klsi_105_tiocmset,
-       .attach =               klsi_105_startup,
-       .release =              klsi_105_release,
+       .port_probe =           klsi_105_port_probe,
+       .port_remove =          klsi_105_port_remove,
        .throttle =             usb_serial_generic_throttle,
        .unthrottle =           usb_serial_generic_unthrottle,
        .process_read_urb =     klsi_105_process_read_urb,
@@ -223,60 +223,40 @@ static int klsi_105_get_line_state(struct usb_serial_port *port,
  * Driver's tty interface functions
  */
 
-static int klsi_105_startup(struct usb_serial *serial)
+static int klsi_105_port_probe(struct usb_serial_port *port)
 {
        struct klsi_105_private *priv;
-       int i;
 
-       /* check if we support the product id (see keyspan.c)
-        * FIXME
-        */
+       priv = kmalloc(sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
 
-       /* allocate the private data structure */
-       for (i = 0; i < serial->num_ports; i++) {
-               priv = kmalloc(sizeof(struct klsi_105_private),
-                                                  GFP_KERNEL);
-               if (!priv) {
-                       dev_dbg(&serial->interface->dev,
-                               "%s - kmalloc for klsi_105_private failed.\n",
-                               __func__);
-                       i--;
-                       goto err_cleanup;
-               }
-               /* set initial values for control structures */
-               priv->cfg.pktlen    = 5;
-               priv->cfg.baudrate  = kl5kusb105a_sio_b9600;
-               priv->cfg.databits  = kl5kusb105a_dtb_8;
-               priv->cfg.unknown1  = 0;
-               priv->cfg.unknown2  = 1;
+       /* set initial values for control structures */
+       priv->cfg.pktlen    = 5;
+       priv->cfg.baudrate  = kl5kusb105a_sio_b9600;
+       priv->cfg.databits  = kl5kusb105a_dtb_8;
+       priv->cfg.unknown1  = 0;
+       priv->cfg.unknown2  = 1;
 
-               priv->line_state    = 0;
+       priv->line_state    = 0;
 
-               usb_set_serial_port_data(serial->port[i], priv);
+       spin_lock_init(&priv->lock);
 
-               spin_lock_init(&priv->lock);
+       /* priv->termios is left uninitialized until port opening */
 
-               /* priv->termios is left uninitialized until port opening */
-               init_waitqueue_head(&serial->port[i]->write_wait);
-       }
+       usb_set_serial_port_data(port, priv);
 
        return 0;
-
-err_cleanup:
-       for (; i >= 0; i--) {
-               priv = usb_get_serial_port_data(serial->port[i]);
-               kfree(priv);
-               usb_set_serial_port_data(serial->port[i], NULL);
-       }
-       return -ENOMEM;
 }
 
-static void klsi_105_release(struct usb_serial *serial)
+static int klsi_105_port_remove(struct usb_serial_port *port)
 {
-       int i;
+       struct klsi_105_private *priv;
+
+       priv = usb_get_serial_port_data(port);
+       kfree(priv);
 
-       for (i = 0; i < serial->num_ports; ++i)
-               kfree(usb_get_serial_port_data(serial->port[i]));
+       return 0;
 }
 
 static int  klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port)
index 5c4d2fbd4e11892e7c40479b322c3f56e74e7294..c9ca7a5b12e09c883f08562ca93a8fbede32e82b 100644 (file)
@@ -54,8 +54,8 @@
 
 
 /* Function prototypes */
-static int  kobil_startup(struct usb_serial *serial);
-static void kobil_release(struct usb_serial *serial);
+static int kobil_port_probe(struct usb_serial_port *probe);
+static int kobil_port_remove(struct usb_serial_port *probe);
 static int  kobil_open(struct tty_struct *tty, struct usb_serial_port *port);
 static void kobil_close(struct usb_serial_port *port);
 static int  kobil_write(struct tty_struct *tty, struct usb_serial_port *port,
@@ -89,8 +89,8 @@ static struct usb_serial_driver kobil_device = {
        .description =          "KOBIL USB smart card terminal",
        .id_table =             id_table,
        .num_ports =            1,
-       .attach =               kobil_startup,
-       .release =              kobil_release,
+       .port_probe =           kobil_port_probe,
+       .port_remove =          kobil_port_remove,
        .ioctl =                kobil_ioctl,
        .set_termios =          kobil_set_termios,
        .init_termios =         kobil_init_termios,
@@ -117,9 +117,10 @@ struct kobil_private {
 };
 
 
-static int kobil_startup(struct usb_serial *serial)
+static int kobil_port_probe(struct usb_serial_port *port)
 {
        int i;
+       struct usb_serial *serial = port->serial;
        struct kobil_private *priv;
        struct usb_device *pdev;
        struct usb_host_config *actconfig;
@@ -149,7 +150,7 @@ static int kobil_startup(struct usb_serial *serial)
                dev_dbg(&serial->dev->dev, "KOBIL KAAN SIM detected\n");
                break;
        }
-       usb_set_serial_port_data(serial->port[0], priv);
+       usb_set_serial_port_data(port, priv);
 
        /* search for the necessary endpoints */
        pdev = serial->dev;
@@ -179,12 +180,14 @@ static int kobil_startup(struct usb_serial *serial)
 }
 
 
-static void kobil_release(struct usb_serial *serial)
+static int kobil_port_remove(struct usb_serial_port *port)
 {
-       int i;
+       struct kobil_private *priv;
 
-       for (i = 0; i < serial->num_ports; ++i)
-               kfree(usb_get_serial_port_data(serial->port[i]));
+       priv = usb_get_serial_port_data(port);
+       kfree(priv);
+
+       return 0;
 }
 
 static void kobil_init_termios(struct tty_struct *tty)
index 30cff03e9f012ffee6ecc2548477f8b1020c66f6..54d4148d01d120a6d5c2085eb3d884328405a109 100644 (file)
@@ -503,11 +503,19 @@ static const struct option_blacklist_info net_intf5_blacklist = {
        .reserved = BIT(5),
 };
 
+static const struct option_blacklist_info net_intf6_blacklist = {
+       .reserved = BIT(6),
+};
+
 static const struct option_blacklist_info zte_mf626_blacklist = {
        .sendsetup = BIT(0) | BIT(1),
        .reserved = BIT(4),
 };
 
+static const struct option_blacklist_info zte_1255_blacklist = {
+       .reserved = BIT(3) | BIT(4),
+};
+
 static const struct usb_device_id option_ids[] = {
        { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
        { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
@@ -853,13 +861,19 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0113, 0xff, 0xff, 0xff),
                .driver_info = (kernel_ulong_t)&net_intf5_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0117, 0xff, 0xff, 0xff) },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0118, 0xff, 0xff, 0xff) },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0121, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0118, 0xff, 0xff, 0xff),
+               .driver_info = (kernel_ulong_t)&net_intf5_blacklist },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0121, 0xff, 0xff, 0xff),
+               .driver_info = (kernel_ulong_t)&net_intf5_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0122, 0xff, 0xff, 0xff) },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0123, 0xff, 0xff, 0xff) },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0124, 0xff, 0xff, 0xff) },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0125, 0xff, 0xff, 0xff) },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0126, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0123, 0xff, 0xff, 0xff),
+               .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0124, 0xff, 0xff, 0xff),
+               .driver_info = (kernel_ulong_t)&net_intf5_blacklist },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0125, 0xff, 0xff, 0xff),
+               .driver_info = (kernel_ulong_t)&net_intf6_blacklist },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0126, 0xff, 0xff, 0xff),
+               .driver_info = (kernel_ulong_t)&net_intf5_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0128, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0142, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0143, 0xff, 0xff, 0xff) },
@@ -872,7 +886,8 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0156, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0157, 0xff, 0xff, 0xff),
          .driver_info = (kernel_ulong_t)&net_intf5_blacklist },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0158, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0158, 0xff, 0xff, 0xff),
+         .driver_info = (kernel_ulong_t)&net_intf3_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0159, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0161, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0162, 0xff, 0xff, 0xff) },
@@ -880,13 +895,22 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0165, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0167, 0xff, 0xff, 0xff),
          .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0191, 0xff, 0xff, 0xff), /* ZTE EuFi890 */
+         .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0199, 0xff, 0xff, 0xff), /* ZTE MF820S */
+         .driver_info = (kernel_ulong_t)&net_intf1_blacklist },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0257, 0xff, 0xff, 0xff), /* ZTE MF821 */
+         .driver_info = (kernel_ulong_t)&net_intf3_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0326, 0xff, 0xff, 0xff),
          .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1008, 0xff, 0xff, 0xff),
          .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1010, 0xff, 0xff, 0xff),
          .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1012, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1012, 0xff, 0xff, 0xff),
+         .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1021, 0xff, 0xff, 0xff),
+         .driver_info = (kernel_ulong_t)&net_intf2_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1057, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1058, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1059, 0xff, 0xff, 0xff) },
@@ -1002,18 +1026,24 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1169, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1170, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1244, 0xff, 0xff, 0xff) },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1245, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1245, 0xff, 0xff, 0xff),
+         .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1246, 0xff, 0xff, 0xff) },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1247, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1247, 0xff, 0xff, 0xff),
+         .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1248, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1249, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1250, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1251, 0xff, 0xff, 0xff) },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1252, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1252, 0xff, 0xff, 0xff),
+         .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1253, 0xff, 0xff, 0xff) },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1254, 0xff, 0xff, 0xff) },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1255, 0xff, 0xff, 0xff) },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1256, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1254, 0xff, 0xff, 0xff),
+         .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1255, 0xff, 0xff, 0xff),
+         .driver_info = (kernel_ulong_t)&zte_1255_blacklist },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1256, 0xff, 0xff, 0xff),
+         .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1257, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1258, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1259, 0xff, 0xff, 0xff) },
@@ -1058,8 +1088,16 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1298, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1299, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1300, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1401, 0xff, 0xff, 0xff),
+               .driver_info = (kernel_ulong_t)&net_intf2_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1402, 0xff, 0xff, 0xff),
                .driver_info = (kernel_ulong_t)&net_intf2_blacklist },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1424, 0xff, 0xff, 0xff),
+               .driver_info = (kernel_ulong_t)&net_intf2_blacklist },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1425, 0xff, 0xff, 0xff),
+               .driver_info = (kernel_ulong_t)&net_intf2_blacklist },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1426, 0xff, 0xff, 0xff),  /* ZTE MF91 */
+               .driver_info = (kernel_ulong_t)&net_intf2_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2002, 0xff,
          0xff, 0xff), .driver_info = (kernel_ulong_t)&zte_k3765_z_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2003, 0xff, 0xff, 0xff) },
@@ -1071,15 +1109,21 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0070, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0073, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0094, 0xff, 0xff, 0xff) },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0130, 0xff, 0xff, 0xff) },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0133, 0xff, 0xff, 0xff) },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0141, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0130, 0xff, 0xff, 0xff),
+               .driver_info = (kernel_ulong_t)&net_intf1_blacklist },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0133, 0xff, 0xff, 0xff),
+               .driver_info = (kernel_ulong_t)&net_intf3_blacklist },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0141, 0xff, 0xff, 0xff),
+               .driver_info = (kernel_ulong_t)&net_intf5_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0147, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0152, 0xff, 0xff, 0xff) },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0168, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0168, 0xff, 0xff, 0xff),
+               .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0170, 0xff, 0xff, 0xff) },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0176, 0xff, 0xff, 0xff) },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0178, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0176, 0xff, 0xff, 0xff),
+               .driver_info = (kernel_ulong_t)&net_intf3_blacklist },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0178, 0xff, 0xff, 0xff),
+               .driver_info = (kernel_ulong_t)&net_intf3_blacklist },
 
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC8710, 0xff, 0xff, 0xff) },
index 933241f03fd8382f9e1dcd6f9fee38c8d1b89298..cee9a52ca891cd0857b324fba5f99933b03771f0 100644 (file)
@@ -137,8 +137,8 @@ static int oti6858_chars_in_buffer(struct tty_struct *tty);
 static int oti6858_tiocmget(struct tty_struct *tty);
 static int oti6858_tiocmset(struct tty_struct *tty,
                                unsigned int set, unsigned int clear);
-static int oti6858_startup(struct usb_serial *serial);
-static void oti6858_release(struct usb_serial *serial);
+static int oti6858_port_probe(struct usb_serial_port *port);
+static int oti6858_port_remove(struct usb_serial_port *port);
 
 /* device info */
 static struct usb_serial_driver oti6858_device = {
@@ -161,8 +161,8 @@ static struct usb_serial_driver oti6858_device = {
        .write_bulk_callback =  oti6858_write_bulk_callback,
        .write_room =           oti6858_write_room,
        .chars_in_buffer =      oti6858_chars_in_buffer,
-       .attach =               oti6858_startup,
-       .release =              oti6858_release,
+       .port_probe =           oti6858_port_probe,
+       .port_remove =          oti6858_port_remove,
 };
 
 static struct usb_serial_driver * const serial_drivers[] = {
@@ -331,36 +331,33 @@ static void send_data(struct work_struct *work)
        usb_serial_port_softint(port);
 }
 
-static int oti6858_startup(struct usb_serial *serial)
+static int oti6858_port_probe(struct usb_serial_port *port)
 {
-       struct usb_serial_port *port = serial->port[0];
        struct oti6858_private *priv;
-       int i;
-
-       for (i = 0; i < serial->num_ports; ++i) {
-               priv = kzalloc(sizeof(struct oti6858_private), GFP_KERNEL);
-               if (!priv)
-                       break;
-
-               spin_lock_init(&priv->lock);
-               init_waitqueue_head(&priv->intr_wait);
-/*             INIT_WORK(&priv->setup_work, setup_line, serial->port[i]); */
-/*             INIT_WORK(&priv->write_work, send_data, serial->port[i]); */
-               priv->port = port;
-               INIT_DELAYED_WORK(&priv->delayed_setup_work, setup_line);
-               INIT_DELAYED_WORK(&priv->delayed_write_work, send_data);
-
-               usb_set_serial_port_data(serial->port[i], priv);
-       }
-       if (i == serial->num_ports)
-               return 0;
 
-       for (--i; i >= 0; --i) {
-               priv = usb_get_serial_port_data(serial->port[i]);
-               kfree(priv);
-               usb_set_serial_port_data(serial->port[i], NULL);
-       }
-       return -ENOMEM;
+       priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       spin_lock_init(&priv->lock);
+       init_waitqueue_head(&priv->intr_wait);
+       priv->port = port;
+       INIT_DELAYED_WORK(&priv->delayed_setup_work, setup_line);
+       INIT_DELAYED_WORK(&priv->delayed_write_work, send_data);
+
+       usb_set_serial_port_data(port, priv);
+
+       return 0;
+}
+
+static int oti6858_port_remove(struct usb_serial_port *port)
+{
+       struct oti6858_private *priv;
+
+       priv = usb_get_serial_port_data(port);
+       kfree(priv);
+
+       return 0;
 }
 
 static int oti6858_write(struct tty_struct *tty, struct usb_serial_port *port,
@@ -709,15 +706,6 @@ static int oti6858_ioctl(struct tty_struct *tty,
        return -ENOIOCTLCMD;
 }
 
-
-static void oti6858_release(struct usb_serial *serial)
-{
-       int i;
-
-       for (i = 0; i < serial->num_ports; ++i)
-               kfree(usb_get_serial_port_data(serial->port[i]));
-}
-
 static void oti6858_read_int_callback(struct urb *urb)
 {
        struct usb_serial_port *port =  urb->context;
index 892ebdc7a364b29572a908453c37443374965513..600241901361e62458d0d002e22261e1e5c0bc5f 100644 (file)
@@ -133,12 +133,15 @@ enum pl2303_type {
        HX,             /* HX version of the pl2303 chip */
 };
 
+struct pl2303_serial_private {
+       enum pl2303_type type;
+};
+
 struct pl2303_private {
        spinlock_t lock;
        wait_queue_head_t delta_msr_wait;
        u8 line_control;
        u8 line_status;
-       enum pl2303_type type;
 };
 
 static int pl2303_vendor_read(__u16 value, __u16 index,
@@ -167,14 +170,19 @@ static int pl2303_vendor_write(__u16 value, __u16 index,
 
 static int pl2303_startup(struct usb_serial *serial)
 {
-       struct pl2303_private *priv;
+       struct pl2303_serial_private *spriv;
        enum pl2303_type type = type_0;
        unsigned char *buf;
-       int i;
+
+       spriv = kzalloc(sizeof(*spriv), GFP_KERNEL);
+       if (!spriv)
+               return -ENOMEM;
 
        buf = kmalloc(10, GFP_KERNEL);
-       if (buf == NULL)
+       if (!buf) {
+               kfree(spriv);
                return -ENOMEM;
+       }
 
        if (serial->dev->descriptor.bDeviceClass == 0x02)
                type = type_0;
@@ -186,15 +194,8 @@ static int pl2303_startup(struct usb_serial *serial)
                type = type_1;
        dev_dbg(&serial->interface->dev, "device type: %d\n", type);
 
-       for (i = 0; i < serial->num_ports; ++i) {
-               priv = kzalloc(sizeof(struct pl2303_private), GFP_KERNEL);
-               if (!priv)
-                       goto cleanup;
-               spin_lock_init(&priv->lock);
-               init_waitqueue_head(&priv->delta_msr_wait);
-               priv->type = type;
-               usb_set_serial_port_data(serial->port[i], priv);
-       }
+       spriv->type = type;
+       usb_set_serial_data(serial, spriv);
 
        pl2303_vendor_read(0x8484, 0, serial, buf);
        pl2303_vendor_write(0x0404, 0, serial);
@@ -213,15 +214,40 @@ static int pl2303_startup(struct usb_serial *serial)
 
        kfree(buf);
        return 0;
+}
 
-cleanup:
-       kfree(buf);
-       for (--i; i >= 0; --i) {
-               priv = usb_get_serial_port_data(serial->port[i]);
-               kfree(priv);
-               usb_set_serial_port_data(serial->port[i], NULL);
-       }
-       return -ENOMEM;
+static void pl2303_release(struct usb_serial *serial)
+{
+       struct pl2303_serial_private *spriv;
+
+       spriv = usb_get_serial_data(serial);
+       kfree(spriv);
+}
+
+static int pl2303_port_probe(struct usb_serial_port *port)
+{
+       struct pl2303_private *priv;
+
+       priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       spin_lock_init(&priv->lock);
+       init_waitqueue_head(&priv->delta_msr_wait);
+
+       usb_set_serial_port_data(port, priv);
+
+       return 0;
+}
+
+static int pl2303_port_remove(struct usb_serial_port *port)
+{
+       struct pl2303_private *priv;
+
+       priv = usb_get_serial_port_data(port);
+       kfree(priv);
+
+       return 0;
 }
 
 static int set_control_lines(struct usb_device *dev, u8 value)
@@ -240,6 +266,7 @@ static void pl2303_set_termios(struct tty_struct *tty,
                struct usb_serial_port *port, struct ktermios *old_termios)
 {
        struct usb_serial *serial = port->serial;
+       struct pl2303_serial_private *spriv = usb_get_serial_data(serial);
        struct pl2303_private *priv = usb_get_serial_port_data(port);
        unsigned long flags;
        unsigned int cflag;
@@ -323,7 +350,7 @@ static void pl2303_set_termios(struct tty_struct *tty,
                }
                if (baud > 1228800) {
                        /* type_0, type_1 only support up to 1228800 baud */
-                       if (priv->type != HX)
+                       if (spriv->type != HX)
                                baud = 1228800;
                        else if (baud > 6000000)
                                baud = 6000000;
@@ -426,7 +453,7 @@ static void pl2303_set_termios(struct tty_struct *tty,
             buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
 
        if (cflag & CRTSCTS) {
-               if (priv->type == HX)
+               if (spriv->type == HX)
                        pl2303_vendor_write(0x0, 0x61, serial);
                else
                        pl2303_vendor_write(0x0, 0x41, serial);
@@ -468,10 +495,10 @@ static int pl2303_open(struct tty_struct *tty, struct usb_serial_port *port)
 {
        struct ktermios tmp_termios;
        struct usb_serial *serial = port->serial;
-       struct pl2303_private *priv = usb_get_serial_port_data(port);
+       struct pl2303_serial_private *spriv = usb_get_serial_data(serial);
        int result;
 
-       if (priv->type != HX) {
+       if (spriv->type != HX) {
                usb_clear_halt(serial->dev, port->write_urb->pipe);
                usb_clear_halt(serial->dev, port->read_urb->pipe);
        } else {
@@ -655,17 +682,6 @@ static void pl2303_break_ctl(struct tty_struct *tty, int break_state)
                dev_err(&port->dev, "error sending break = %d\n", result);
 }
 
-static void pl2303_release(struct usb_serial *serial)
-{
-       int i;
-       struct pl2303_private *priv;
-
-       for (i = 0; i < serial->num_ports; ++i) {
-               priv = usb_get_serial_port_data(serial->port[i]);
-               kfree(priv);
-       }
-}
-
 static void pl2303_update_line_status(struct usb_serial_port *port,
                                      unsigned char *data,
                                      unsigned int actual_length)
@@ -827,6 +843,8 @@ static struct usb_serial_driver pl2303_device = {
        .read_int_callback =    pl2303_read_int_callback,
        .attach =               pl2303_startup,
        .release =              pl2303_release,
+       .port_probe =           pl2303_port_probe,
+       .port_remove =          pl2303_port_remove,
 };
 
 static struct usb_serial_driver * const serial_drivers[] = {
index 01d882cf3775a2523662e4ab40f917a91eac5099..76ef95bcbbf272599f9516636b913921e07e3ae2 100644 (file)
@@ -959,6 +959,7 @@ static void sierra_release(struct usb_serial *serial)
                        continue;
                kfree(portdata);
        }
+       kfree(serial->private);
 }
 
 #ifdef CONFIG_PM
index 9716efe92955bdd26d2aa7d5d5a3ea3ebdf9f540..769c137f8975689fd9a798e12fda23bf27036728 100644 (file)
@@ -157,13 +157,10 @@ struct spcp8x5_private {
        u8                      line_status;
 };
 
-/* desc : when device plug in,this function would be called.
- * thanks to usb_serial subsystem,then do almost every things for us. And what
- * we should do just alloc the buffer */
-static int spcp8x5_startup(struct usb_serial *serial)
+static int spcp8x5_port_probe(struct usb_serial_port *port)
 {
+       struct usb_serial *serial = port->serial;
        struct spcp8x5_private *priv;
-       int i;
        enum spcp8x5_type type = SPCP825_007_TYPE;
        u16 product = le16_to_cpu(serial->dev->descriptor.idProduct);
 
@@ -180,34 +177,27 @@ static int spcp8x5_startup(struct usb_serial *serial)
                type = SPCP825_PHILIP_TYPE;
        dev_dbg(&serial->dev->dev, "device type = %d\n", (int)type);
 
-       for (i = 0; i < serial->num_ports; ++i) {
-               priv = kzalloc(sizeof(struct spcp8x5_private), GFP_KERNEL);
-               if (!priv)
-                       goto cleanup;
+       priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
 
-               spin_lock_init(&priv->lock);
-               init_waitqueue_head(&priv->delta_msr_wait);
-               priv->type = type;
-               usb_set_serial_port_data(serial->port[i] , priv);
-       }
+       spin_lock_init(&priv->lock);
+       init_waitqueue_head(&priv->delta_msr_wait);
+       priv->type = type;
+
+       usb_set_serial_port_data(port , priv);
 
        return 0;
-cleanup:
-       for (--i; i >= 0; --i) {
-               priv = usb_get_serial_port_data(serial->port[i]);
-               kfree(priv);
-               usb_set_serial_port_data(serial->port[i] , NULL);
-       }
-       return -ENOMEM;
 }
 
-/* call when the device plug out. free all the memory alloced by probe */
-static void spcp8x5_release(struct usb_serial *serial)
+static int spcp8x5_port_remove(struct usb_serial_port *port)
 {
-       int i;
+       struct spcp8x5_private *priv;
 
-       for (i = 0; i < serial->num_ports; i++)
-               kfree(usb_get_serial_port_data(serial->port[i]));
+       priv = usb_get_serial_port_data(port);
+       kfree(priv);
+
+       return 0;
 }
 
 /* set the modem control line of the device.
@@ -649,8 +639,8 @@ static struct usb_serial_driver spcp8x5_device = {
        .ioctl                  = spcp8x5_ioctl,
        .tiocmget               = spcp8x5_tiocmget,
        .tiocmset               = spcp8x5_tiocmset,
-       .attach                 = spcp8x5_startup,
-       .release                = spcp8x5_release,
+       .port_probe             = spcp8x5_port_probe,
+       .port_remove            = spcp8x5_port_remove,
        .process_read_urb       = spcp8x5_process_read_urb,
 };
 
index 015810b3785bb72938d60691b81433a918583750..868d1e6852e2ab6086a354cd62a352a241cb51c7 100644 (file)
@@ -67,13 +67,6 @@ struct ssu100_port_private {
        struct async_icount icount;
 };
 
-static void ssu100_release(struct usb_serial *serial)
-{
-       struct ssu100_port_private *priv = usb_get_serial_port_data(*serial->port);
-
-       kfree(priv);
-}
-
 static inline int ssu100_control_msg(struct usb_device *dev,
                                     u8 request, u16 data, u16 index)
 {
@@ -441,22 +434,34 @@ static int ssu100_ioctl(struct tty_struct *tty,
 }
 
 static int ssu100_attach(struct usb_serial *serial)
+{
+       return ssu100_initdevice(serial->dev);
+}
+
+static int ssu100_port_probe(struct usb_serial_port *port)
 {
        struct ssu100_port_private *priv;
-       struct usb_serial_port *port = *serial->port;
 
        priv = kzalloc(sizeof(*priv), GFP_KERNEL);
-       if (!priv) {
-               dev_err(&port->dev, "%s- kmalloc(%Zd) failed.\n", __func__,
-                       sizeof(*priv));
+       if (!priv)
                return -ENOMEM;
-       }
 
        spin_lock_init(&priv->status_lock);
        init_waitqueue_head(&priv->delta_msr_wait);
+
        usb_set_serial_port_data(port, priv);
 
-       return ssu100_initdevice(serial->dev);
+       return 0;
+}
+
+static int ssu100_port_remove(struct usb_serial_port *port)
+{
+       struct ssu100_port_private *priv;
+
+       priv = usb_get_serial_port_data(port);
+       kfree(priv);
+
+       return 0;
 }
 
 static int ssu100_tiocmget(struct tty_struct *tty)
@@ -647,7 +652,8 @@ static struct usb_serial_driver ssu100_device = {
        .open                = ssu100_open,
        .close               = ssu100_close,
        .attach              = ssu100_attach,
-       .release             = ssu100_release,
+       .port_probe          = ssu100_port_probe,
+       .port_remove         = ssu100_port_remove,
        .dtr_rts             = ssu100_dtr_rts,
        .process_read_urb    = ssu100_process_read_urb,
        .tiocmget            = ssu100_tiocmget,
index 6f49392cda5bdb889192a118c94a0573b48348a8..f2530d2ef3c42af788e75c1db2554a95642c6207 100644 (file)
@@ -97,6 +97,8 @@ struct ti_device {
 
 static int ti_startup(struct usb_serial *serial);
 static void ti_release(struct usb_serial *serial);
+static int ti_port_probe(struct usb_serial_port *port);
+static int ti_port_remove(struct usb_serial_port *port);
 static int ti_open(struct tty_struct *tty, struct usb_serial_port *port);
 static void ti_close(struct usb_serial_port *port);
 static int ti_write(struct tty_struct *tty, struct usb_serial_port *port,
@@ -221,6 +223,8 @@ static struct usb_serial_driver ti_1port_device = {
        .num_ports              = 1,
        .attach                 = ti_startup,
        .release                = ti_release,
+       .port_probe             = ti_port_probe,
+       .port_remove            = ti_port_remove,
        .open                   = ti_open,
        .close                  = ti_close,
        .write                  = ti_write,
@@ -249,6 +253,8 @@ static struct usb_serial_driver ti_2port_device = {
        .num_ports              = 2,
        .attach                 = ti_startup,
        .release                = ti_release,
+       .port_probe             = ti_port_probe,
+       .port_remove            = ti_port_remove,
        .open                   = ti_open,
        .close                  = ti_close,
        .write                  = ti_write,
@@ -347,11 +353,8 @@ module_exit(ti_exit);
 static int ti_startup(struct usb_serial *serial)
 {
        struct ti_device *tdev;
-       struct ti_port *tport;
        struct usb_device *dev = serial->dev;
        int status;
-       int i;
-
 
        dev_dbg(&dev->dev,
                "%s - product 0x%4X, num configurations %d, configuration value %d",
@@ -399,42 +402,8 @@ static int ti_startup(struct usb_serial *serial)
                goto free_tdev;
        }
 
-       /* set up port structures */
-       for (i = 0; i < serial->num_ports; ++i) {
-               tport = kzalloc(sizeof(struct ti_port), GFP_KERNEL);
-               if (tport == NULL) {
-                       dev_err(&dev->dev, "%s - out of memory\n", __func__);
-                       status = -ENOMEM;
-                       goto free_tports;
-               }
-               spin_lock_init(&tport->tp_lock);
-               tport->tp_uart_base_addr = (i == 0 ?
-                               TI_UART1_BASE_ADDR : TI_UART2_BASE_ADDR);
-               tport->tp_closing_wait = closing_wait;
-               init_waitqueue_head(&tport->tp_msr_wait);
-               init_waitqueue_head(&tport->tp_write_wait);
-               if (kfifo_alloc(&tport->write_fifo, TI_WRITE_BUF_SIZE,
-                                                               GFP_KERNEL)) {
-                       dev_err(&dev->dev, "%s - out of memory\n", __func__);
-                       kfree(tport);
-                       status = -ENOMEM;
-                       goto free_tports;
-               }
-               tport->tp_port = serial->port[i];
-               tport->tp_tdev = tdev;
-               usb_set_serial_port_data(serial->port[i], tport);
-               tport->tp_uart_mode = 0;        /* default is RS232 */
-       }
-
        return 0;
 
-free_tports:
-       for (--i; i >= 0; --i) {
-               tport = usb_get_serial_port_data(serial->port[i]);
-               kfifo_free(&tport->write_fifo);
-               kfree(tport);
-               usb_set_serial_port_data(serial->port[i], NULL);
-       }
 free_tdev:
        kfree(tdev);
        usb_set_serial_data(serial, NULL);
@@ -444,21 +413,50 @@ free_tdev:
 
 static void ti_release(struct usb_serial *serial)
 {
-       int i;
        struct ti_device *tdev = usb_get_serial_data(serial);
+
+       kfree(tdev);
+}
+
+static int ti_port_probe(struct usb_serial_port *port)
+{
        struct ti_port *tport;
 
-       for (i = 0; i < serial->num_ports; ++i) {
-               tport = usb_get_serial_port_data(serial->port[i]);
-               if (tport) {
-                       kfifo_free(&tport->write_fifo);
-                       kfree(tport);
-               }
+       tport = kzalloc(sizeof(*tport), GFP_KERNEL);
+       if (!tport)
+               return -ENOMEM;
+
+       spin_lock_init(&tport->tp_lock);
+       if (port == port->serial->port[0])
+               tport->tp_uart_base_addr = TI_UART1_BASE_ADDR;
+       else
+               tport->tp_uart_base_addr = TI_UART2_BASE_ADDR;
+       tport->tp_closing_wait = closing_wait;
+       init_waitqueue_head(&tport->tp_msr_wait);
+       init_waitqueue_head(&tport->tp_write_wait);
+       if (kfifo_alloc(&tport->write_fifo, TI_WRITE_BUF_SIZE, GFP_KERNEL)) {
+               kfree(tport);
+               return -ENOMEM;
        }
+       tport->tp_port = port;
+       tport->tp_tdev = usb_get_serial_data(port->serial);
+       tport->tp_uart_mode = 0;        /* default is RS232 */
 
-       kfree(tdev);
+       usb_set_serial_port_data(port, tport);
+
+       return 0;
 }
 
+static int ti_port_remove(struct usb_serial_port *port)
+{
+       struct ti_port *tport;
+
+       tport = usb_get_serial_port_data(port);
+       kfifo_free(&tport->write_fifo);
+       kfree(tport);
+
+       return 0;
+}
 
 static int ti_open(struct tty_struct *tty, struct usb_serial_port *port)
 {
index 779cd954abcbd26d1fc935650d102dc524b8ca5a..d305a5aa3a5d7683a5bcd1c2e60c4a0262f35f65 100644 (file)
@@ -1004,6 +1004,12 @@ UNUSUAL_DEV( 0x07cf, 0x1001, 0x1000, 0x9999,
                USB_SC_8070, USB_PR_CB, NULL,
                US_FL_NEED_OVERRIDE | US_FL_FIX_INQUIRY ),
 
+/* Submitted by Oleksandr Chumachenko <ledest@gmail.com> */
+UNUSUAL_DEV( 0x07cf, 0x1167, 0x0100, 0x0100,
+               "Casio",
+               "EX-N1 DigitalCamera",
+               USB_SC_8070, USB_PR_DEVICE, NULL, 0),
+
 /* Submitted by Hartmut Wahl <hwahl@hwahl.de>*/
 UNUSUAL_DEV( 0x0839, 0x000a, 0x0001, 0x0001,
                "Samsung",
index 0616f235bd6b512ecf54769cfc346e12180febd7..ce310170829fdc66442a8c7b629fc028152c96af 100644 (file)
@@ -105,20 +105,15 @@ static int skel_open(struct inode *inode, struct file *file)
                goto exit;
        }
 
-       /* increment our usage count for the device */
-       kref_get(&dev->kref);
-
-       /* lock the device to allow correctly handling errors
-        * in resumption */
-       mutex_lock(&dev->io_mutex);
-
        retval = usb_autopm_get_interface(interface);
        if (retval)
-               goto out_err;
+               goto exit;
+
+       /* increment our usage count for the device */
+       kref_get(&dev->kref);
 
        /* save our object in the file's private structure */
        file->private_data = dev;
-       mutex_unlock(&dev->io_mutex);
 
 exit:
        return retval;
index 231009af65a3a05712dfd34d8484a7b0a02da18e..1d365316960cdad1a0a020d6d2757a0e5f73f85e 100644 (file)
@@ -847,19 +847,6 @@ static void wusb_dev_bos_rm(struct wusb_dev *wusb_dev)
        wusb_dev->wusb_cap_descr = NULL;
 };
 
-static struct usb_wireless_cap_descriptor wusb_cap_descr_default = {
-       .bLength = sizeof(wusb_cap_descr_default),
-       .bDescriptorType = USB_DT_DEVICE_CAPABILITY,
-       .bDevCapabilityType = USB_CAP_TYPE_WIRELESS_USB,
-
-       .bmAttributes = USB_WIRELESS_BEACON_NONE,
-       .wPHYRates = cpu_to_le16(USB_WIRELESS_PHY_53),
-       .bmTFITXPowerInfo = 0,
-       .bmFFITXPowerInfo = 0,
-       .bmBandGroup = cpu_to_le16(0x0001),     /* WUSB1.0[7.4.1] bottom */
-       .bReserved = 0
-};
-
 /*
  * USB stack's device addition Notifier Callback
  *
index c6915c6c3cd1e5fc3941a8a3e6fe242fa9db0310..585949b570550fd5e681b23a2564f8f65eb8f83a 100644 (file)
@@ -206,11 +206,11 @@ static ssize_t lm3639_bled_mode_store(struct device *dev,
 
 out:
        dev_err(pchip->dev, "%s:i2c access fail to register\n", __func__);
-       return size;
+       return ret;
 
 out_input:
        dev_err(pchip->dev, "%s:input conversion fail\n", __func__);
-       return size;
+       return ret;
 
 }
 
index cf2688de083244c2ab25da05638c6edb2d7e3a47..e501dbc966b3b2a3976d17956fc9bd9f387cec29 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/math64.h>
 
 #include <linux/platform_data/video-imxfb.h>
-#include <mach/hardware.h>
 
 /*
  * Complain if VAR is out of range.
@@ -53,8 +52,8 @@
 #define LCDC_SIZE      0x04
 #define SIZE_XMAX(x)   ((((x) >> 4) & 0x3f) << 20)
 
-#define YMAX_MASK       (cpu_is_mx1() ? 0x1ff : 0x3ff)
-#define SIZE_YMAX(y)   ((y) & YMAX_MASK)
+#define YMAX_MASK_IMX1 0x1ff
+#define YMAX_MASK_IMX21        0x3ff
 
 #define LCDC_VPW       0x08
 #define VPW_VPW(x)     ((x) & 0x3ff)
@@ -128,12 +127,18 @@ struct imxfb_rgb {
        struct fb_bitfield      transp;
 };
 
+enum imxfb_type {
+       IMX1_FB,
+       IMX21_FB,
+};
+
 struct imxfb_info {
        struct platform_device  *pdev;
        void __iomem            *regs;
        struct clk              *clk_ipg;
        struct clk              *clk_ahb;
        struct clk              *clk_per;
+       enum imxfb_type         devtype;
 
        /*
         * These are the addresses we mapped
@@ -168,6 +173,24 @@ struct imxfb_info {
        void (*backlight_power)(int);
 };
 
+static struct platform_device_id imxfb_devtype[] = {
+       {
+               .name = "imx1-fb",
+               .driver_data = IMX1_FB,
+       }, {
+               .name = "imx21-fb",
+               .driver_data = IMX21_FB,
+       }, {
+               /* sentinel */
+       }
+};
+MODULE_DEVICE_TABLE(platform, imxfb_devtype);
+
+static inline int is_imx1_fb(struct imxfb_info *fbi)
+{
+       return fbi->devtype == IMX1_FB;
+}
+
 #define IMX_NAME       "IMX"
 
 /*
@@ -366,7 +389,7 @@ static int imxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
                break;
        case 16:
        default:
-               if (cpu_is_mx1())
+               if (is_imx1_fb(fbi))
                        pcr |= PCR_BPIX_12;
                else
                        pcr |= PCR_BPIX_16;
@@ -596,6 +619,7 @@ static struct fb_ops imxfb_ops = {
 static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *info)
 {
        struct imxfb_info *fbi = info->par;
+       u32 ymax_mask = is_imx1_fb(fbi) ? YMAX_MASK_IMX1 : YMAX_MASK_IMX21;
 
        pr_debug("var: xres=%d hslen=%d lm=%d rm=%d\n",
                var->xres, var->hsync_len,
@@ -617,7 +641,7 @@ static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *inf
        if (var->right_margin > 255)
                printk(KERN_ERR "%s: invalid right_margin %d\n",
                        info->fix.id, var->right_margin);
-       if (var->yres < 1 || var->yres > YMAX_MASK)
+       if (var->yres < 1 || var->yres > ymax_mask)
                printk(KERN_ERR "%s: invalid yres %d\n",
                        info->fix.id, var->yres);
        if (var->vsync_len > 100)
@@ -645,7 +669,7 @@ static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *inf
                VCR_V_WAIT_2(var->upper_margin),
                fbi->regs + LCDC_VCR);
 
-       writel(SIZE_XMAX(var->xres) | SIZE_YMAX(var->yres),
+       writel(SIZE_XMAX(var->xres) | (var->yres & ymax_mask),
                        fbi->regs + LCDC_SIZE);
 
        writel(fbi->pcr, fbi->regs + LCDC_PCR);
@@ -765,6 +789,7 @@ static int __init imxfb_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        fbi = info->par;
+       fbi->devtype = pdev->id_entry->driver_data;
 
        if (!fb_mode)
                fb_mode = pdata->mode[0].mode.name;
@@ -939,6 +964,7 @@ static struct platform_driver imxfb_driver = {
        .driver         = {
                .name   = DRIVER_NAME,
        },
+       .id_table       = imxfb_devtype,
 };
 
 static int imxfb_setup(void)
index ce1d452464ed5171d537346bdd1a0132a7d321d1..73688720857445ddb18096a90a80fc22f2f63499 100644 (file)
 #include <linux/console.h>
 #include <linux/clk.h>
 #include <linux/mutex.h>
+#include <linux/dma/ipu-dma.h>
 
 #include <linux/platform_data/dma-imx.h>
-#include <mach/hardware.h>
-#include <mach/ipu.h>
 #include <linux/platform_data/video-mx3fb.h>
 
 #include <asm/io.h>
index 2dcdbc9364d8802ed26154f18097a8995b5c5271..99ebdde590f8266dc1b734c9c827fd40693d227f 100644 (file)
@@ -15,6 +15,7 @@ if VIRT_DRIVERS
 config FSL_HV_MANAGER
        tristate "Freescale hypervisor management driver"
        depends on FSL_SOC
+       select EPAPR_PARAVIRT
        help
           The Freescale hypervisor management driver provides several services
          to drivers and applications related to the Freescale hypervisor:
index 6b1b7e1849396d8183c6ae326b0ab1dc4c66ead2..5a0e1d32ce133a5c7305b966cddcfdc701edbe53 100644 (file)
@@ -225,7 +225,7 @@ static void vm_notify(struct virtqueue *vq)
 
        /* We write the queue's selector into the notification register to
         * signal the other end */
-       writel(virtqueue_get_queue_index(vq), vm_dev->base + VIRTIO_MMIO_QUEUE_NOTIFY);
+       writel(vq->index, vm_dev->base + VIRTIO_MMIO_QUEUE_NOTIFY);
 }
 
 /* Notify all virtqueues on an interrupt. */
@@ -266,7 +266,7 @@ static void vm_del_vq(struct virtqueue *vq)
        struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vq->vdev);
        struct virtio_mmio_vq_info *info = vq->priv;
        unsigned long flags, size;
-       unsigned int index = virtqueue_get_queue_index(vq);
+       unsigned int index = vq->index;
 
        spin_lock_irqsave(&vm_dev->lock, flags);
        list_del(&info->node);
index c33aea36598aa2b6133147756956439f65a84f7f..e3ecc94591ad29defa2b572d54eab60a223cb3aa 100644 (file)
@@ -203,8 +203,7 @@ static void vp_notify(struct virtqueue *vq)
 
        /* we write the queue's selector into the notification register to
         * signal the other end */
-       iowrite16(virtqueue_get_queue_index(vq),
-                 vp_dev->ioaddr + VIRTIO_PCI_QUEUE_NOTIFY);
+       iowrite16(vq->index, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_NOTIFY);
 }
 
 /* Handle a configuration change: Tell driver if it wants to know. */
@@ -479,8 +478,7 @@ static void vp_del_vq(struct virtqueue *vq)
        list_del(&info->node);
        spin_unlock_irqrestore(&vp_dev->lock, flags);
 
-       iowrite16(virtqueue_get_queue_index(vq),
-               vp_dev->ioaddr + VIRTIO_PCI_QUEUE_SEL);
+       iowrite16(vq->index, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_SEL);
 
        if (vp_dev->msix_enabled) {
                iowrite16(VIRTIO_MSI_NO_VECTOR,
@@ -830,16 +828,4 @@ static struct pci_driver virtio_pci_driver = {
 #endif
 };
 
-static int __init virtio_pci_init(void)
-{
-       return pci_register_driver(&virtio_pci_driver);
-}
-
-module_init(virtio_pci_init);
-
-static void __exit virtio_pci_exit(void)
-{
-       pci_unregister_driver(&virtio_pci_driver);
-}
-
-module_exit(virtio_pci_exit);
+module_pci_driver(virtio_pci_driver);
index e639584b2dbd1c24e36017db1978009b73f8e33f..ffd7e7da5d3b1753316f633fbbb38935e5dc27de 100644 (file)
@@ -93,8 +93,6 @@ struct vring_virtqueue
        /* Host publishes avail event idx */
        bool event;
 
-       /* Number of free buffers */
-       unsigned int num_free;
        /* Head of free buffer list. */
        unsigned int free_head;
        /* Number we've added since last sync. */
@@ -106,9 +104,6 @@ struct vring_virtqueue
        /* How to notify other side. FIXME: commonalize hcalls! */
        void (*notify)(struct virtqueue *vq);
 
-       /* Index of the queue */
-       int queue_index;
-
 #ifdef DEBUG
        /* They're supposed to lock for us. */
        unsigned int in_use;
@@ -135,6 +130,13 @@ static int vring_add_indirect(struct vring_virtqueue *vq,
        unsigned head;
        int i;
 
+       /*
+        * We require lowmem mappings for the descriptors because
+        * otherwise virt_to_phys will give us bogus addresses in the
+        * virtqueue.
+        */
+       gfp &= ~(__GFP_HIGHMEM | __GFP_HIGH);
+
        desc = kmalloc((out + in) * sizeof(struct vring_desc), gfp);
        if (!desc)
                return -ENOMEM;
@@ -160,7 +162,7 @@ static int vring_add_indirect(struct vring_virtqueue *vq,
        desc[i-1].next = 0;
 
        /* We're about to use a buffer */
-       vq->num_free--;
+       vq->vq.num_free--;
 
        /* Use a single buffer which doesn't continue */
        head = vq->free_head;
@@ -174,13 +176,6 @@ static int vring_add_indirect(struct vring_virtqueue *vq,
        return head;
 }
 
-int virtqueue_get_queue_index(struct virtqueue *_vq)
-{
-       struct vring_virtqueue *vq = to_vvq(_vq);
-       return vq->queue_index;
-}
-EXPORT_SYMBOL_GPL(virtqueue_get_queue_index);
-
 /**
  * virtqueue_add_buf - expose buffer to other end
  * @vq: the struct virtqueue we're talking about.
@@ -193,10 +188,7 @@ EXPORT_SYMBOL_GPL(virtqueue_get_queue_index);
  * Caller must ensure we don't call this with other virtqueue operations
  * at the same time (except where noted).
  *
- * Returns remaining capacity of queue or a negative error
- * (ie. ENOSPC).  Note that it only really makes sense to treat all
- * positive return values as "available": indirect buffers mean that
- * we can put an entire sg[] array inside a single queue entry.
+ * Returns zero or a negative error (ie. ENOSPC, ENOMEM).
  */
 int virtqueue_add_buf(struct virtqueue *_vq,
                      struct scatterlist sg[],
@@ -228,7 +220,7 @@ int virtqueue_add_buf(struct virtqueue *_vq,
 
        /* If the host supports indirect descriptor tables, and we have multiple
         * buffers, then go indirect. FIXME: tune this threshold */
-       if (vq->indirect && (out + in) > 1 && vq->num_free) {
+       if (vq->indirect && (out + in) > 1 && vq->vq.num_free) {
                head = vring_add_indirect(vq, sg, out, in, gfp);
                if (likely(head >= 0))
                        goto add_head;
@@ -237,9 +229,9 @@ int virtqueue_add_buf(struct virtqueue *_vq,
        BUG_ON(out + in > vq->vring.num);
        BUG_ON(out + in == 0);
 
-       if (vq->num_free < out + in) {
+       if (vq->vq.num_free < out + in) {
                pr_debug("Can't add buf len %i - avail = %i\n",
-                        out + in, vq->num_free);
+                        out + in, vq->vq.num_free);
                /* FIXME: for historical reasons, we force a notify here if
                 * there are outgoing parts to the buffer.  Presumably the
                 * host should service the ring ASAP. */
@@ -250,7 +242,7 @@ int virtqueue_add_buf(struct virtqueue *_vq,
        }
 
        /* We're about to use some buffers from the free list. */
-       vq->num_free -= out + in;
+       vq->vq.num_free -= out + in;
 
        head = vq->free_head;
        for (i = vq->free_head; out; i = vq->vring.desc[i].next, out--) {
@@ -296,7 +288,7 @@ add_head:
        pr_debug("Added buffer head %i to %p\n", head, vq);
        END_USE(vq);
 
-       return vq->num_free;
+       return 0;
 }
 EXPORT_SYMBOL_GPL(virtqueue_add_buf);
 
@@ -393,13 +385,13 @@ static void detach_buf(struct vring_virtqueue *vq, unsigned int head)
 
        while (vq->vring.desc[i].flags & VRING_DESC_F_NEXT) {
                i = vq->vring.desc[i].next;
-               vq->num_free++;
+               vq->vq.num_free++;
        }
 
        vq->vring.desc[i].next = vq->free_head;
        vq->free_head = head;
        /* Plus final descriptor */
-       vq->num_free++;
+       vq->vq.num_free++;
 }
 
 static inline bool more_used(const struct vring_virtqueue *vq)
@@ -599,7 +591,7 @@ void *virtqueue_detach_unused_buf(struct virtqueue *_vq)
                return buf;
        }
        /* That should have freed everything. */
-       BUG_ON(vq->num_free != vq->vring.num);
+       BUG_ON(vq->vq.num_free != vq->vring.num);
 
        END_USE(vq);
        return NULL;
@@ -653,12 +645,13 @@ struct virtqueue *vring_new_virtqueue(unsigned int index,
        vq->vq.callback = callback;
        vq->vq.vdev = vdev;
        vq->vq.name = name;
+       vq->vq.num_free = num;
+       vq->vq.index = index;
        vq->notify = notify;
        vq->weak_barriers = weak_barriers;
        vq->broken = false;
        vq->last_used_idx = 0;
        vq->num_added = 0;
-       vq->queue_index = index;
        list_add_tail(&vq->vq.list, &vdev->vqs);
 #ifdef DEBUG
        vq->in_use = false;
@@ -673,7 +666,6 @@ struct virtqueue *vring_new_virtqueue(unsigned int index,
                vq->vring.avail->flags |= VRING_AVAIL_F_NO_INTERRUPT;
 
        /* Put everything in free lists. */
-       vq->num_free = num;
        vq->free_head = 0;
        for (i = 0; i < num-1; i++) {
                vq->vring.desc[i].next = i+1;
index c8c5c8032bcb61f763517cb688b37de98a6deb68..eb44b036f92894a73ee7ea29fdb208e56d4a68ad 100644 (file)
@@ -208,7 +208,7 @@ static int __devinit davinci_wdt_probe(struct platform_device *pdev)
        if (WARN_ON(IS_ERR(wdt_clk)))
                return PTR_ERR(wdt_clk);
 
-       clk_enable(wdt_clk);
+       clk_prepare_enable(wdt_clk);
 
        if (heartbeat < 1 || heartbeat > MAX_HEARTBEAT)
                heartbeat = DEFAULT_HEARTBEAT;
@@ -256,7 +256,7 @@ static int __devexit davinci_wdt_remove(struct platform_device *pdev)
                wdt_mem = NULL;
        }
 
-       clk_disable(wdt_clk);
+       clk_disable_unprepare(wdt_clk);
        clk_put(wdt_clk);
 
        return 0;
index bcfab2b00ad20ae5c1e72fbf0e2809aa02cfdf2d..9a45d0294cf48f21397f43909680f2f9349c6d86 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/uaccess.h>
 #include <linux/timer.h>
 #include <linux/jiffies.h>
-#include <mach/hardware.h>
 
 #define DRIVER_NAME "imx2-wdt"
 
index d4dffcd528730330a0d4cff238dcf0b56e3f318b..126d8ce591ce5fc7e69348f746e91e60b04bc4ee 100644 (file)
@@ -3,6 +3,7 @@ menu "Xen driver support"
 
 config XEN_BALLOON
        bool "Xen memory balloon driver"
+       depends on !ARM
        default y
        help
          The balloon driver allows the Xen domain to request more memory from
@@ -145,6 +146,7 @@ config SWIOTLB_XEN
 
 config XEN_TMEM
        bool
+       depends on !ARM
        default y if (CLEANCACHE || FRONTSWAP)
        help
          Shim to interface in-kernel Transcendent Memory hooks
index 31ab82fda38a264cd045c4b52c117eb375f8e80e..d6886d90ccfd53eed62773a755ee282e9553a55f 100644 (file)
@@ -55,7 +55,6 @@
 #include <asm/pgalloc.h>
 #include <asm/pgtable.h>
 #include <asm/tlb.h>
-#include <asm/e820.h>
 
 #include <asm/xen/hypervisor.h>
 #include <asm/xen/hypercall.h>
@@ -88,7 +87,7 @@ struct balloon_stats balloon_stats;
 EXPORT_SYMBOL_GPL(balloon_stats);
 
 /* We increase/decrease in batches which fit in a page */
-static unsigned long frame_list[PAGE_SIZE / sizeof(unsigned long)];
+static xen_pfn_t frame_list[PAGE_SIZE / sizeof(unsigned long)];
 
 #ifdef CONFIG_HIGHMEM
 #define inc_totalhigh_pages() (totalhigh_pages++)
index 4dcfced107f50e41c518405b28747064d62d78bc..a797359968e38e7e1fc4f2d37cd8f067bd8df95a 100644 (file)
@@ -100,7 +100,8 @@ static int __init setup_vcpu_hotplug_event(void)
        static struct notifier_block xsn_cpu = {
                .notifier_call = setup_cpu_watcher };
 
-       if (!xen_pv_domain())
+       /* PVH TBD/FIXME: future work */
+       if (!xen_pv_domain() || xen_pvh_domain())
                return -ENODEV;
 
        register_xenstore_notifier(&xsn_cpu);
index 42569c77ccc8886d38b924a457489819d0dd53c4..f3ccc80a455f54c0abd15c1018f2fc79c7a0332a 100644 (file)
@@ -8,7 +8,9 @@
 
 static int xen_dbgp_op(struct usb_hcd *hcd, int op)
 {
+#ifdef CONFIG_PCI
        const struct device *ctrlr = hcd_to_bus(hcd)->controller;
+#endif
        struct physdev_dbgp_op dbgp;
 
        if (!xen_initial_domain())
index 59e10a1286d53ff73aa3e0a6c91a5aed9033de9e..912ac81b6dbff5e2b9f48c2b2662083bf00ce476 100644 (file)
@@ -115,7 +115,9 @@ struct irq_info {
 #define PIRQ_SHAREABLE (1 << 1)
 
 static int *evtchn_to_irq;
+#ifdef CONFIG_X86
 static unsigned long *pirq_eoi_map;
+#endif
 static bool (*pirq_needs_eoi)(unsigned irq);
 
 static DEFINE_PER_CPU(unsigned long [NR_EVENT_CHANNELS/BITS_PER_LONG],
@@ -277,10 +279,12 @@ static unsigned int cpu_from_evtchn(unsigned int evtchn)
        return ret;
 }
 
+#ifdef CONFIG_X86
 static bool pirq_check_eoi_map(unsigned irq)
 {
        return test_bit(pirq_from_irq(irq), pirq_eoi_map);
 }
+#endif
 
 static bool pirq_needs_eoi_flag(unsigned irq)
 {
index b2b0a375b3484b162b0c2ebc6cd09d5584f8ec60..444091e40dd1325ee926f87e39b1aa88e3917a4f 100644 (file)
@@ -38,7 +38,6 @@
 #include <linux/vmalloc.h>
 #include <linux/uaccess.h>
 #include <linux/io.h>
-#include <linux/delay.h>
 #include <linux/hardirq.h>
 
 #include <xen/xen.h>
@@ -84,7 +83,7 @@ struct gnttab_ops {
         * nr_gframes is the number of frames to map grant table. Returning
         * GNTST_okay means success and negative value means failure.
         */
-       int (*map_frames)(unsigned long *frames, unsigned int nr_gframes);
+       int (*map_frames)(xen_pfn_t *frames, unsigned int nr_gframes);
        /*
         * Release a list of frames which are mapped in map_frames for grant
         * entry status.
@@ -824,52 +823,6 @@ unsigned int gnttab_max_grant_frames(void)
 }
 EXPORT_SYMBOL_GPL(gnttab_max_grant_frames);
 
-/* Handling of paged out grant targets (GNTST_eagain) */
-#define MAX_DELAY 256
-static inline void
-gnttab_retry_eagain_gop(unsigned int cmd, void *gop, int16_t *status,
-                                               const char *func)
-{
-       unsigned delay = 1;
-
-       do {
-               BUG_ON(HYPERVISOR_grant_table_op(cmd, gop, 1));
-               if (*status == GNTST_eagain)
-                       msleep(delay++);
-       } while ((*status == GNTST_eagain) && (delay < MAX_DELAY));
-
-       if (delay >= MAX_DELAY) {
-               printk(KERN_ERR "%s: %s eagain grant\n", func, current->comm);
-               *status = GNTST_bad_page;
-       }
-}
-
-void gnttab_batch_map(struct gnttab_map_grant_ref *batch, unsigned count)
-{
-       struct gnttab_map_grant_ref *op;
-
-       if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, batch, count))
-               BUG();
-       for (op = batch; op < batch + count; op++)
-               if (op->status == GNTST_eagain)
-                       gnttab_retry_eagain_gop(GNTTABOP_map_grant_ref, op,
-                                               &op->status, __func__);
-}
-EXPORT_SYMBOL_GPL(gnttab_batch_map);
-
-void gnttab_batch_copy(struct gnttab_copy *batch, unsigned count)
-{
-       struct gnttab_copy *op;
-
-       if (HYPERVISOR_grant_table_op(GNTTABOP_copy, batch, count))
-               BUG();
-       for (op = batch; op < batch + count; op++)
-               if (op->status == GNTST_eagain)
-                       gnttab_retry_eagain_gop(GNTTABOP_copy, op,
-                                               &op->status, __func__);
-}
-EXPORT_SYMBOL_GPL(gnttab_batch_copy);
-
 int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
                    struct gnttab_map_grant_ref *kmap_ops,
                    struct page **pages, unsigned int count)
@@ -883,12 +836,6 @@ int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
        if (ret)
                return ret;
 
-       /* Retry eagain maps */
-       for (i = 0; i < count; i++)
-               if (map_ops[i].status == GNTST_eagain)
-                       gnttab_retry_eagain_gop(GNTTABOP_map_grant_ref, map_ops + i,
-                                               &map_ops[i].status, __func__);
-
        if (xen_feature(XENFEAT_auto_translated_physmap))
                return ret;
 
@@ -960,7 +907,7 @@ static unsigned nr_status_frames(unsigned nr_grant_frames)
        return (nr_grant_frames * GREFS_PER_GRANT_FRAME + SPP - 1) / SPP;
 }
 
-static int gnttab_map_frames_v1(unsigned long *frames, unsigned int nr_gframes)
+static int gnttab_map_frames_v1(xen_pfn_t *frames, unsigned int nr_gframes)
 {
        int rc;
 
@@ -977,7 +924,7 @@ static void gnttab_unmap_frames_v1(void)
        arch_gnttab_unmap(gnttab_shared.addr, nr_grant_frames);
 }
 
-static int gnttab_map_frames_v2(unsigned long *frames, unsigned int nr_gframes)
+static int gnttab_map_frames_v2(xen_pfn_t *frames, unsigned int nr_gframes)
 {
        uint64_t *sframes;
        unsigned int nr_sframes;
@@ -1029,7 +976,7 @@ static void gnttab_unmap_frames_v2(void)
 static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
 {
        struct gnttab_setup_table setup;
-       unsigned long *frames;
+       xen_pfn_t *frames;
        unsigned int nr_gframes = end_idx + 1;
        int rc;
 
index 5e5ad7e2885832f64f2131aa43aead50548cae0a..96453f8a85c5543f506ecc128f22e91b3d2dbdbb 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/kobject.h>
+#include <linux/err.h>
 
 #include <asm/xen/hypervisor.h>
 #include <asm/xen/hypercall.h>
@@ -284,7 +285,8 @@ static ssize_t virtual_start_show(struct hyp_sysfs_attr *attr, char *buffer)
                ret = HYPERVISOR_xen_version(XENVER_platform_parameters,
                                             parms);
                if (!ret)
-                       ret = sprintf(buffer, "%lx\n", parms->virt_start);
+                       ret = sprintf(buffer, "%"PRI_xen_ulong"\n",
+                                     parms->virt_start);
                kfree(parms);
        }
 
index 46d140baebd8770463b9d37399f5149220920532..0f478ac483cd418e1a8a0b84fdb1b35651ce6404 100644 (file)
@@ -89,9 +89,15 @@ static int __xen_pcibk_add_pci_dev(struct xen_pcibk_device *pdev,
 
        mutex_lock(&vpci_dev->lock);
 
-       /* Keep multi-function devices together on the virtual PCI bus */
-       for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
-               if (!list_empty(&vpci_dev->dev_list[slot])) {
+       /*
+        * Keep multi-function devices together on the virtual PCI bus, except
+        * virtual functions.
+        */
+       if (!dev->is_virtfn) {
+               for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
+                       if (list_empty(&vpci_dev->dev_list[slot]))
+                               continue;
+
                        t = list_entry(list_first(&vpci_dev->dev_list[slot]),
                                       struct pci_dev_entry, list);
 
@@ -116,7 +122,7 @@ static int __xen_pcibk_add_pci_dev(struct xen_pcibk_device *pdev,
                               pci_name(dev), slot);
                        list_add_tail(&dev_entry->list,
                                      &vpci_dev->dev_list[slot]);
-                       func = PCI_FUNC(dev->devfn);
+                       func = dev->is_virtfn ? 0 : PCI_FUNC(dev->devfn);
                        goto unlock;
                }
        }
index bcf3ba4a6ec1543a7500ef0de36269dec1ff728d..b3e146edb51d947b3bb7d22b63e52fac32adcbc3 100644 (file)
@@ -490,7 +490,8 @@ static int xenbus_map_ring_valloc_pv(struct xenbus_device *dev,
 
        op.host_addr = arbitrary_virt_to_machine(pte).maddr;
 
-       gnttab_batch_map(&op, 1);
+       if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
+               BUG();
 
        if (op.status != GNTST_okay) {
                free_vm_area(area);
@@ -571,7 +572,8 @@ int xenbus_map_ring(struct xenbus_device *dev, int gnt_ref,
        gnttab_set_map_op(&op, (unsigned long)vaddr, GNTMAP_host_map, gnt_ref,
                          dev->otherend_id);
 
-       gnttab_batch_map(&op, 1);
+       if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
+               BUG();
 
        if (op.status != GNTST_okay) {
                xenbus_dev_fatal(dev, op.status,
index 48220e129f854435292065c5e928f95d982a4ad3..acedeabe589c94eaecd5ab5d478f7e7b3bfbe4af 100644 (file)
@@ -625,8 +625,9 @@ static struct xenbus_watch *find_watch(const char *token)
  * so if we are running on anything older than 4 do not attempt to read
  * control/platform-feature-xs_reset_watches.
  */
-static bool xen_strict_xenbus_quirk()
+static bool xen_strict_xenbus_quirk(void)
 {
+#ifdef CONFIG_X86
        uint32_t eax, ebx, ecx, edx, base;
 
        base = xen_cpuid_base();
@@ -634,6 +635,7 @@ static bool xen_strict_xenbus_quirk()
 
        if ((eax >> 16) < 4)
                return true;
+#endif
        return false;
 
 }
index f95ae3a027f38dd3173d5c766eeeb0ecda58d2be..6afe87482155adf2f93f6885988fc954450d82c8 100644 (file)
@@ -68,16 +68,6 @@ source "fs/quota/Kconfig"
 source "fs/autofs4/Kconfig"
 source "fs/fuse/Kconfig"
 
-config CUSE
-       tristate "Character device in Userspace support"
-       depends on FUSE_FS
-       help
-         This FUSE extension allows character devices to be
-         implemented in userspace.
-
-         If you want to develop or use userspace character device
-         based on CUSE, answer Y or M.
-
 config GENERIC_ACL
        bool
        select FS_POSIX_ACL
index 3f152b92a94ad2824876fd99c9fbfdd05098d0cf..afc2bb6917806e85ee916d8b2c25cb2183890055 100644 (file)
@@ -471,9 +471,19 @@ static int exact_lock(dev_t dev, void *data)
  */
 int cdev_add(struct cdev *p, dev_t dev, unsigned count)
 {
+       int error;
+
        p->dev = dev;
        p->count = count;
-       return kobj_map(cdev_map, dev, count, NULL, exact_match, exact_lock, p);
+
+       error = kobj_map(cdev_map, dev, count, NULL,
+                        exact_match, exact_lock, p);
+       if (error)
+               return error;
+
+       kobject_get(p->kobj.parent);
+
+       return 0;
 }
 
 static void cdev_unmap(dev_t dev, unsigned count)
@@ -498,14 +508,20 @@ void cdev_del(struct cdev *p)
 static void cdev_default_release(struct kobject *kobj)
 {
        struct cdev *p = container_of(kobj, struct cdev, kobj);
+       struct kobject *parent = kobj->parent;
+
        cdev_purge(p);
+       kobject_put(parent);
 }
 
 static void cdev_dynamic_release(struct kobject *kobj)
 {
        struct cdev *p = container_of(kobj, struct cdev, kobj);
+       struct kobject *parent = kobj->parent;
+
        cdev_purge(p);
        kfree(p);
+       kobject_put(parent);
 }
 
 static struct kobj_type ktype_cdev_default = {
index fc783e264420a890751aa81e819fc8b53aaa1a81..ad8ca0e5751e2ae333f822311a29808f280042f4 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/string.h>
 #include <linux/keyctl.h>
 #include <linux/key-type.h>
+#include <linux/moduleparam.h>
 #include <keys/user-type.h>
 #include "cifspdu.h"
 #include "cifsglob.h"
@@ -42,135 +43,32 @@ static const struct cifs_sid sid_authusers = {
 /* group users */
 static const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {} };
 
-const struct cred *root_cred;
+static const struct cred *root_cred;
 
-static void
-shrink_idmap_tree(struct rb_root *root, int nr_to_scan, int *nr_rem,
-                       int *nr_del)
-{
-       struct rb_node *node;
-       struct rb_node *tmp;
-       struct cifs_sid_id *psidid;
-
-       node = rb_first(root);
-       while (node) {
-               tmp = node;
-               node = rb_next(tmp);
-               psidid = rb_entry(tmp, struct cifs_sid_id, rbnode);
-               if (nr_to_scan == 0 || *nr_del == nr_to_scan)
-                       ++(*nr_rem);
-               else {
-                       if (time_after(jiffies, psidid->time + SID_MAP_EXPIRE)
-                                               && psidid->refcount == 0) {
-                               rb_erase(tmp, root);
-                               ++(*nr_del);
-                       } else
-                               ++(*nr_rem);
-               }
-       }
-}
-
-/*
- * Run idmap cache shrinker.
- */
-static int
-cifs_idmap_shrinker(struct shrinker *shrink, struct shrink_control *sc)
-{
-       int nr_to_scan = sc->nr_to_scan;
-       int nr_del = 0;
-       int nr_rem = 0;
-       struct rb_root *root;
-
-       root = &uidtree;
-       spin_lock(&siduidlock);
-       shrink_idmap_tree(root, nr_to_scan, &nr_rem, &nr_del);
-       spin_unlock(&siduidlock);
-
-       root = &gidtree;
-       spin_lock(&sidgidlock);
-       shrink_idmap_tree(root, nr_to_scan, &nr_rem, &nr_del);
-       spin_unlock(&sidgidlock);
-
-       root = &siduidtree;
-       spin_lock(&uidsidlock);
-       shrink_idmap_tree(root, nr_to_scan, &nr_rem, &nr_del);
-       spin_unlock(&uidsidlock);
-
-       root = &sidgidtree;
-       spin_lock(&gidsidlock);
-       shrink_idmap_tree(root, nr_to_scan, &nr_rem, &nr_del);
-       spin_unlock(&gidsidlock);
-
-       return nr_rem;
-}
-
-static void
-sid_rb_insert(struct rb_root *root, unsigned long cid,
-               struct cifs_sid_id **psidid, char *typestr)
-{
-       char *strptr;
-       struct rb_node *node = root->rb_node;
-       struct rb_node *parent = NULL;
-       struct rb_node **linkto = &(root->rb_node);
-       struct cifs_sid_id *lsidid;
-
-       while (node) {
-               lsidid = rb_entry(node, struct cifs_sid_id, rbnode);
-               parent = node;
-               if (cid > lsidid->id) {
-                       linkto = &(node->rb_left);
-                       node = node->rb_left;
-               }
-               if (cid < lsidid->id) {
-                       linkto = &(node->rb_right);
-                       node = node->rb_right;
-               }
-       }
-
-       (*psidid)->id = cid;
-       (*psidid)->time = jiffies - (SID_MAP_RETRY + 1);
-       (*psidid)->refcount = 0;
-
-       sprintf((*psidid)->sidstr, "%s", typestr);
-       strptr = (*psidid)->sidstr + strlen((*psidid)->sidstr);
-       sprintf(strptr, "%ld", cid);
-
-       clear_bit(SID_ID_PENDING, &(*psidid)->state);
-       clear_bit(SID_ID_MAPPED, &(*psidid)->state);
-
-       rb_link_node(&(*psidid)->rbnode, parent, linkto);
-       rb_insert_color(&(*psidid)->rbnode, root);
-}
-
-static struct cifs_sid_id *
-sid_rb_search(struct rb_root *root, unsigned long cid)
-{
-       struct rb_node *node = root->rb_node;
-       struct cifs_sid_id *lsidid;
-
-       while (node) {
-               lsidid = rb_entry(node, struct cifs_sid_id, rbnode);
-               if (cid > lsidid->id)
-                       node = node->rb_left;
-               else if (cid < lsidid->id)
-                       node = node->rb_right;
-               else /* node found */
-                       return lsidid;
-       }
-
-       return NULL;
-}
-
-static struct shrinker cifs_shrinker = {
-       .shrink = cifs_idmap_shrinker,
-       .seeks = DEFAULT_SEEKS,
-};
+static unsigned int cifs_idmap_cache_timeout = 600;
+module_param(cifs_idmap_cache_timeout, uint, 0644);
+MODULE_PARM_DESC(cifs_idmap_cache_timeout, "Number of seconds that ID mappings "
+                       "stay in cache. (default=600)");
 
 static int
 cifs_idmap_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
 {
        char *payload;
 
+       /*
+        * If the payload is less than or equal to the size of a pointer, then
+        * an allocation here is wasteful. Just copy the data directly to the
+        * payload.value union member instead.
+        *
+        * With this however, you must check the datalen before trying to
+        * dereference payload.data!
+        */
+       if (prep->datalen <= sizeof(void *)) {
+               key->payload.value = 0;
+               memcpy(&key->payload.value, prep->data, prep->datalen);
+               key->datalen = prep->datalen;
+               return 0;
+       }
        payload = kmalloc(prep->datalen, GFP_KERNEL);
        if (!payload)
                return -ENOMEM;
@@ -184,10 +82,11 @@ cifs_idmap_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
 static inline void
 cifs_idmap_key_destroy(struct key *key)
 {
-       kfree(key->payload.data);
+       if (key->datalen > sizeof(void *))
+               kfree(key->payload.data);
 }
 
-struct key_type cifs_idmap_key_type = {
+static struct key_type cifs_idmap_key_type = {
        .name        = "cifs.idmap",
        .instantiate = cifs_idmap_key_instantiate,
        .destroy     = cifs_idmap_key_destroy,
@@ -195,214 +94,153 @@ struct key_type cifs_idmap_key_type = {
        .match       = user_match,
 };
 
-static void
-sid_to_str(struct cifs_sid *sidptr, char *sidstr)
+static char *
+sid_to_key_str(struct cifs_sid *sidptr, unsigned int type)
 {
-       int i;
-       unsigned long saval;
-       char *strptr;
-
-       strptr = sidstr;
+       int i, len;
+       unsigned int saval;
+       char *sidstr, *strptr;
 
-       sprintf(strptr, "%s", "S");
-       strptr = sidstr + strlen(sidstr);
+       /* 3 bytes for prefix */
+       sidstr = kmalloc(3 + SID_STRING_BASE_SIZE +
+                        (SID_STRING_SUBAUTH_SIZE * sidptr->num_subauth),
+                        GFP_KERNEL);
+       if (!sidstr)
+               return sidstr;
 
-       sprintf(strptr, "-%d", sidptr->revision);
-       strptr = sidstr + strlen(sidstr);
+       strptr = sidstr;
+       len = sprintf(strptr, "%cs:S-%hhu", type == SIDOWNER ? 'o' : 'g',
+                       sidptr->revision);
+       strptr += len;
 
-       for (i = 0; i < 6; ++i) {
+       for (i = 0; i < NUM_AUTHS; ++i) {
                if (sidptr->authority[i]) {
-                       sprintf(strptr, "-%d", sidptr->authority[i]);
-                       strptr = sidstr + strlen(sidstr);
+                       len = sprintf(strptr, "-%hhu", sidptr->authority[i]);
+                       strptr += len;
                }
        }
 
        for (i = 0; i < sidptr->num_subauth; ++i) {
                saval = le32_to_cpu(sidptr->sub_auth[i]);
-               sprintf(strptr, "-%ld", saval);
-               strptr = sidstr + strlen(sidstr);
+               len = sprintf(strptr, "-%u", saval);
+               strptr += len;
        }
+
+       return sidstr;
 }
 
-static void
-id_rb_insert(struct rb_root *root, struct cifs_sid *sidptr,
-               struct cifs_sid_id **psidid, char *typestr)
+/*
+ * if the two SIDs (roughly equivalent to a UUID for a user or group) are
+ * the same returns zero, if they do not match returns non-zero.
+ */
+static int
+compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid)
 {
-       int rc;
-       char *strptr;
-       struct rb_node *node = root->rb_node;
-       struct rb_node *parent = NULL;
-       struct rb_node **linkto = &(root->rb_node);
-       struct cifs_sid_id *lsidid;
-
-       while (node) {
-               lsidid = rb_entry(node, struct cifs_sid_id, rbnode);
-               parent = node;
-               rc = compare_sids(sidptr, &((lsidid)->sid));
-               if (rc > 0) {
-                       linkto = &(node->rb_left);
-                       node = node->rb_left;
-               } else if (rc < 0) {
-                       linkto = &(node->rb_right);
-                       node = node->rb_right;
-               }
-       }
-
-       memcpy(&(*psidid)->sid, sidptr, sizeof(struct cifs_sid));
-       (*psidid)->time = jiffies - (SID_MAP_RETRY + 1);
-       (*psidid)->refcount = 0;
+       int i;
+       int num_subauth, num_sat, num_saw;
 
-       sprintf((*psidid)->sidstr, "%s", typestr);
-       strptr = (*psidid)->sidstr + strlen((*psidid)->sidstr);
-       sid_to_str(&(*psidid)->sid, strptr);
+       if ((!ctsid) || (!cwsid))
+               return 1;
 
-       clear_bit(SID_ID_PENDING, &(*psidid)->state);
-       clear_bit(SID_ID_MAPPED, &(*psidid)->state);
+       /* compare the revision */
+       if (ctsid->revision != cwsid->revision) {
+               if (ctsid->revision > cwsid->revision)
+                       return 1;
+               else
+                       return -1;
+       }
 
-       rb_link_node(&(*psidid)->rbnode, parent, linkto);
-       rb_insert_color(&(*psidid)->rbnode, root);
-}
+       /* compare all of the six auth values */
+       for (i = 0; i < NUM_AUTHS; ++i) {
+               if (ctsid->authority[i] != cwsid->authority[i]) {
+                       if (ctsid->authority[i] > cwsid->authority[i])
+                               return 1;
+                       else
+                               return -1;
+               }
+       }
 
-static struct cifs_sid_id *
-id_rb_search(struct rb_root *root, struct cifs_sid *sidptr)
-{
-       int rc;
-       struct rb_node *node = root->rb_node;
-       struct cifs_sid_id *lsidid;
-
-       while (node) {
-               lsidid = rb_entry(node, struct cifs_sid_id, rbnode);
-               rc = compare_sids(sidptr, &((lsidid)->sid));
-               if (rc > 0) {
-                       node = node->rb_left;
-               } else if (rc < 0) {
-                       node = node->rb_right;
-               } else /* node found */
-                       return lsidid;
+       /* compare all of the subauth values if any */
+       num_sat = ctsid->num_subauth;
+       num_saw = cwsid->num_subauth;
+       num_subauth = num_sat < num_saw ? num_sat : num_saw;
+       if (num_subauth) {
+               for (i = 0; i < num_subauth; ++i) {
+                       if (ctsid->sub_auth[i] != cwsid->sub_auth[i]) {
+                               if (le32_to_cpu(ctsid->sub_auth[i]) >
+                                       le32_to_cpu(cwsid->sub_auth[i]))
+                                       return 1;
+                               else
+                                       return -1;
+                       }
+               }
        }
 
-       return NULL;
+       return 0; /* sids compare/match */
 }
 
-static int
-sidid_pending_wait(void *unused)
+static void
+cifs_copy_sid(struct cifs_sid *dst, const struct cifs_sid *src)
 {
-       schedule();
-       return signal_pending(current) ? -ERESTARTSYS : 0;
+       int i;
+
+       dst->revision = src->revision;
+       dst->num_subauth = min_t(u8, src->num_subauth, SID_MAX_SUB_AUTHORITIES);
+       for (i = 0; i < NUM_AUTHS; ++i)
+               dst->authority[i] = src->authority[i];
+       for (i = 0; i < dst->num_subauth; ++i)
+               dst->sub_auth[i] = src->sub_auth[i];
 }
 
 static int
-id_to_sid(unsigned long cid, uint sidtype, struct cifs_sid *ssid)
+id_to_sid(unsigned int cid, uint sidtype, struct cifs_sid *ssid)
 {
-       int rc = 0;
+       int rc;
        struct key *sidkey;
+       struct cifs_sid *ksid;
+       unsigned int ksid_size;
+       char desc[3 + 10 + 1]; /* 3 byte prefix + 10 bytes for value + NULL */
        const struct cred *saved_cred;
-       struct cifs_sid *lsid;
-       struct cifs_sid_id *psidid, *npsidid;
-       struct rb_root *cidtree;
-       spinlock_t *cidlock;
-
-       if (sidtype == SIDOWNER) {
-               cidlock = &siduidlock;
-               cidtree = &uidtree;
-       } else if (sidtype == SIDGROUP) {
-               cidlock = &sidgidlock;
-               cidtree = &gidtree;
-       } else
-               return -EINVAL;
 
-       spin_lock(cidlock);
-       psidid = sid_rb_search(cidtree, cid);
-
-       if (!psidid) { /* node does not exist, allocate one & attempt adding */
-               spin_unlock(cidlock);
-               npsidid = kzalloc(sizeof(struct cifs_sid_id), GFP_KERNEL);
-               if (!npsidid)
-                       return -ENOMEM;
-
-               npsidid->sidstr = kmalloc(SIDLEN, GFP_KERNEL);
-               if (!npsidid->sidstr) {
-                       kfree(npsidid);
-                       return -ENOMEM;
-               }
-
-               spin_lock(cidlock);
-               psidid = sid_rb_search(cidtree, cid);
-               if (psidid) { /* node happened to get inserted meanwhile */
-                       ++psidid->refcount;
-                       spin_unlock(cidlock);
-                       kfree(npsidid->sidstr);
-                       kfree(npsidid);
-               } else {
-                       psidid = npsidid;
-                       sid_rb_insert(cidtree, cid, &psidid,
-                                       sidtype == SIDOWNER ? "oi:" : "gi:");
-                       ++psidid->refcount;
-                       spin_unlock(cidlock);
-               }
-       } else {
-               ++psidid->refcount;
-               spin_unlock(cidlock);
-       }
-
-       /*
-        * If we are here, it is safe to access psidid and its fields
-        * since a reference was taken earlier while holding the spinlock.
-        * A reference on the node is put without holding the spinlock
-        * and it is OK to do so in this case, shrinker will not erase
-        * this node until all references are put and we do not access
-        * any fields of the node after a reference is put .
-        */
-       if (test_bit(SID_ID_MAPPED, &psidid->state)) {
-               memcpy(ssid, &psidid->sid, sizeof(struct cifs_sid));
-               psidid->time = jiffies; /* update ts for accessing */
-               goto id_sid_out;
-       }
+       rc = snprintf(desc, sizeof(desc), "%ci:%u",
+                       sidtype == SIDOWNER ? 'o' : 'g', cid);
+       if (rc >= sizeof(desc))
+               return -EINVAL;
 
-       if (time_after(psidid->time + SID_MAP_RETRY, jiffies)) {
+       rc = 0;
+       saved_cred = override_creds(root_cred);
+       sidkey = request_key(&cifs_idmap_key_type, desc, "");
+       if (IS_ERR(sidkey)) {
                rc = -EINVAL;
-               goto id_sid_out;
+               cFYI(1, "%s: Can't map %cid %u to a SID", __func__,
+                       sidtype == SIDOWNER ? 'u' : 'g', cid);
+               goto out_revert_creds;
+       } else if (sidkey->datalen < CIFS_SID_BASE_SIZE) {
+               rc = -EIO;
+               cFYI(1, "%s: Downcall contained malformed key "
+                       "(datalen=%hu)", __func__, sidkey->datalen);
+               goto invalidate_key;
        }
 
-       if (!test_and_set_bit(SID_ID_PENDING, &psidid->state)) {
-               saved_cred = override_creds(root_cred);
-               sidkey = request_key(&cifs_idmap_key_type, psidid->sidstr, "");
-               if (IS_ERR(sidkey)) {
-                       rc = -EINVAL;
-                       cFYI(1, "%s: Can't map and id to a SID", __func__);
-               } else {
-                       lsid = (struct cifs_sid *)sidkey->payload.data;
-                       memcpy(&psidid->sid, lsid,
-                               sidkey->datalen < sizeof(struct cifs_sid) ?
-                               sidkey->datalen : sizeof(struct cifs_sid));
-                       memcpy(ssid, &psidid->sid,
-                               sidkey->datalen < sizeof(struct cifs_sid) ?
-                               sidkey->datalen : sizeof(struct cifs_sid));
-                       set_bit(SID_ID_MAPPED, &psidid->state);
-                       key_put(sidkey);
-                       kfree(psidid->sidstr);
-               }
-               psidid->time = jiffies; /* update ts for accessing */
-               revert_creds(saved_cred);
-               clear_bit(SID_ID_PENDING, &psidid->state);
-               wake_up_bit(&psidid->state, SID_ID_PENDING);
-       } else {
-               rc = wait_on_bit(&psidid->state, SID_ID_PENDING,
-                               sidid_pending_wait, TASK_INTERRUPTIBLE);
-               if (rc) {
-                       cFYI(1, "%s: sidid_pending_wait interrupted %d",
-                                       __func__, rc);
-                       --psidid->refcount;
-                       return rc;
-               }
-               if (test_bit(SID_ID_MAPPED, &psidid->state))
-                       memcpy(ssid, &psidid->sid, sizeof(struct cifs_sid));
-               else
-                       rc = -EINVAL;
+       ksid = (struct cifs_sid *)sidkey->payload.data;
+       ksid_size = CIFS_SID_BASE_SIZE + (ksid->num_subauth * sizeof(__le32));
+       if (ksid_size > sidkey->datalen) {
+               rc = -EIO;
+               cFYI(1, "%s: Downcall contained malformed key (datalen=%hu, "
+                       "ksid_size=%u)", __func__, sidkey->datalen, ksid_size);
+               goto invalidate_key;
        }
-id_sid_out:
-       --psidid->refcount;
+       cifs_copy_sid(ssid, ksid);
+       key_set_timeout(sidkey, cifs_idmap_cache_timeout);
+out_key_put:
+       key_put(sidkey);
+out_revert_creds:
+       revert_creds(saved_cred);
        return rc;
+
+invalidate_key:
+       key_invalidate(sidkey);
+       goto out_key_put;
 }
 
 static int
@@ -410,111 +248,68 @@ sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,
                struct cifs_fattr *fattr, uint sidtype)
 {
        int rc;
-       unsigned long cid;
-       struct key *idkey;
+       struct key *sidkey;
+       char *sidstr;
        const struct cred *saved_cred;
-       struct cifs_sid_id *psidid, *npsidid;
-       struct rb_root *cidtree;
-       spinlock_t *cidlock;
-
-       if (sidtype == SIDOWNER) {
-               cid = cifs_sb->mnt_uid; /* default uid, in case upcall fails */
-               cidlock = &siduidlock;
-               cidtree = &uidtree;
-       } else if (sidtype == SIDGROUP) {
-               cid = cifs_sb->mnt_gid; /* default gid, in case upcall fails */
-               cidlock = &sidgidlock;
-               cidtree = &gidtree;
-       } else
-               return -ENOENT;
-
-       spin_lock(cidlock);
-       psidid = id_rb_search(cidtree, psid);
-
-       if (!psidid) { /* node does not exist, allocate one & attempt adding */
-               spin_unlock(cidlock);
-               npsidid = kzalloc(sizeof(struct cifs_sid_id), GFP_KERNEL);
-               if (!npsidid)
-                       return -ENOMEM;
-
-               npsidid->sidstr = kmalloc(SIDLEN, GFP_KERNEL);
-               if (!npsidid->sidstr) {
-                       kfree(npsidid);
-                       return -ENOMEM;
-               }
-
-               spin_lock(cidlock);
-               psidid = id_rb_search(cidtree, psid);
-               if (psidid) { /* node happened to get inserted meanwhile */
-                       ++psidid->refcount;
-                       spin_unlock(cidlock);
-                       kfree(npsidid->sidstr);
-                       kfree(npsidid);
-               } else {
-                       psidid = npsidid;
-                       id_rb_insert(cidtree, psid, &psidid,
-                                       sidtype == SIDOWNER ? "os:" : "gs:");
-                       ++psidid->refcount;
-                       spin_unlock(cidlock);
-               }
-       } else {
-               ++psidid->refcount;
-               spin_unlock(cidlock);
-       }
+       uid_t fuid = cifs_sb->mnt_uid;
+       gid_t fgid = cifs_sb->mnt_gid;
 
        /*
-        * If we are here, it is safe to access psidid and its fields
-        * since a reference was taken earlier while holding the spinlock.
-        * A reference on the node is put without holding the spinlock
-        * and it is OK to do so in this case, shrinker will not erase
-        * this node until all references are put and we do not access
-        * any fields of the node after a reference is put .
+        * If we have too many subauthorities, then something is really wrong.
+        * Just return an error.
         */
-       if (test_bit(SID_ID_MAPPED, &psidid->state)) {
-               cid = psidid->id;
-               psidid->time = jiffies; /* update ts for accessing */
-               goto sid_to_id_out;
+       if (unlikely(psid->num_subauth > SID_MAX_SUB_AUTHORITIES)) {
+               cFYI(1, "%s: %u subauthorities is too many!", __func__,
+                       psid->num_subauth);
+               return -EIO;
        }
 
-       if (time_after(psidid->time + SID_MAP_RETRY, jiffies))
-               goto sid_to_id_out;
-
-       if (!test_and_set_bit(SID_ID_PENDING, &psidid->state)) {
-               saved_cred = override_creds(root_cred);
-               idkey = request_key(&cifs_idmap_key_type, psidid->sidstr, "");
-               if (IS_ERR(idkey))
-                       cFYI(1, "%s: Can't map SID to an id", __func__);
-               else {
-                       cid = *(unsigned long *)idkey->payload.value;
-                       psidid->id = cid;
-                       set_bit(SID_ID_MAPPED, &psidid->state);
-                       key_put(idkey);
-                       kfree(psidid->sidstr);
-               }
-               revert_creds(saved_cred);
-               psidid->time = jiffies; /* update ts for accessing */
-               clear_bit(SID_ID_PENDING, &psidid->state);
-               wake_up_bit(&psidid->state, SID_ID_PENDING);
-       } else {
-               rc = wait_on_bit(&psidid->state, SID_ID_PENDING,
-                               sidid_pending_wait, TASK_INTERRUPTIBLE);
-               if (rc) {
-                       cFYI(1, "%s: sidid_pending_wait interrupted %d",
-                                       __func__, rc);
-                       --psidid->refcount; /* decremented without spinlock */
-                       return rc;
-               }
-               if (test_bit(SID_ID_MAPPED, &psidid->state))
-                       cid = psidid->id;
+       sidstr = sid_to_key_str(psid, sidtype);
+       if (!sidstr)
+               return -ENOMEM;
+
+       saved_cred = override_creds(root_cred);
+       sidkey = request_key(&cifs_idmap_key_type, sidstr, "");
+       if (IS_ERR(sidkey)) {
+               rc = -EINVAL;
+               cFYI(1, "%s: Can't map SID %s to a %cid", __func__, sidstr,
+                       sidtype == SIDOWNER ? 'u' : 'g');
+               goto out_revert_creds;
+       }
+
+       /*
+        * FIXME: Here we assume that uid_t and gid_t are same size. It's
+        * probably a safe assumption but might be better to check based on
+        * sidtype.
+        */
+       if (sidkey->datalen != sizeof(uid_t)) {
+               rc = -EIO;
+               cFYI(1, "%s: Downcall contained malformed key "
+                       "(datalen=%hu)", __func__, sidkey->datalen);
+               key_invalidate(sidkey);
+               goto out_key_put;
        }
 
-sid_to_id_out:
-       --psidid->refcount; /* decremented without spinlock */
        if (sidtype == SIDOWNER)
-               fattr->cf_uid = cid;
+               fuid = (uid_t)sidkey->payload.value;
        else
-               fattr->cf_gid = cid;
+               fgid = (gid_t)sidkey->payload.value;
+
+       key_set_timeout(sidkey, cifs_idmap_cache_timeout);
+out_key_put:
+       key_put(sidkey);
+out_revert_creds:
+       revert_creds(saved_cred);
+       kfree(sidstr);
 
+       /*
+        * Note that we return 0 here unconditionally. If the mapping
+        * fails then we just fall back to using the mnt_uid/mnt_gid.
+        */
+       if (sidtype == SIDOWNER)
+               fattr->cf_uid = fuid;
+       else
+               fattr->cf_gid = fgid;
        return 0;
 }
 
@@ -537,19 +332,15 @@ init_cifs_idmap(void)
        if (!cred)
                return -ENOMEM;
 
-       keyring = key_alloc(&key_type_keyring, ".cifs_idmap", 0, 0, cred,
-                           (KEY_POS_ALL & ~KEY_POS_SETATTR) |
-                           KEY_USR_VIEW | KEY_USR_READ,
-                           KEY_ALLOC_NOT_IN_QUOTA);
+       keyring = keyring_alloc(".cifs_idmap", 0, 0, cred,
+                               (KEY_POS_ALL & ~KEY_POS_SETATTR) |
+                               KEY_USR_VIEW | KEY_USR_READ,
+                               KEY_ALLOC_NOT_IN_QUOTA, NULL);
        if (IS_ERR(keyring)) {
                ret = PTR_ERR(keyring);
                goto failed_put_cred;
        }
 
-       ret = key_instantiate_and_link(keyring, NULL, 0, NULL, NULL);
-       if (ret < 0)
-               goto failed_put_key;
-
        ret = register_key_type(&cifs_idmap_key_type);
        if (ret < 0)
                goto failed_put_key;
@@ -561,17 +352,6 @@ init_cifs_idmap(void)
        cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING;
        root_cred = cred;
 
-       spin_lock_init(&siduidlock);
-       uidtree = RB_ROOT;
-       spin_lock_init(&sidgidlock);
-       gidtree = RB_ROOT;
-
-       spin_lock_init(&uidsidlock);
-       siduidtree = RB_ROOT;
-       spin_lock_init(&gidsidlock);
-       sidgidtree = RB_ROOT;
-       register_shrinker(&cifs_shrinker);
-
        cFYI(1, "cifs idmap keyring: %d", key_serial(keyring));
        return 0;
 
@@ -588,95 +368,13 @@ exit_cifs_idmap(void)
        key_revoke(root_cred->thread_keyring);
        unregister_key_type(&cifs_idmap_key_type);
        put_cred(root_cred);
-       unregister_shrinker(&cifs_shrinker);
        cFYI(1, "Unregistered %s key type", cifs_idmap_key_type.name);
 }
 
-void
-cifs_destroy_idmaptrees(void)
-{
-       struct rb_root *root;
-       struct rb_node *node;
-
-       root = &uidtree;
-       spin_lock(&siduidlock);
-       while ((node = rb_first(root)))
-               rb_erase(node, root);
-       spin_unlock(&siduidlock);
-
-       root = &gidtree;
-       spin_lock(&sidgidlock);
-       while ((node = rb_first(root)))
-               rb_erase(node, root);
-       spin_unlock(&sidgidlock);
-
-       root = &siduidtree;
-       spin_lock(&uidsidlock);
-       while ((node = rb_first(root)))
-               rb_erase(node, root);
-       spin_unlock(&uidsidlock);
-
-       root = &sidgidtree;
-       spin_lock(&gidsidlock);
-       while ((node = rb_first(root)))
-               rb_erase(node, root);
-       spin_unlock(&gidsidlock);
-}
-
-/* if the two SIDs (roughly equivalent to a UUID for a user or group) are
-   the same returns 1, if they do not match returns 0 */
-int compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid)
-{
-       int i;
-       int num_subauth, num_sat, num_saw;
-
-       if ((!ctsid) || (!cwsid))
-               return 1;
-
-       /* compare the revision */
-       if (ctsid->revision != cwsid->revision) {
-               if (ctsid->revision > cwsid->revision)
-                       return 1;
-               else
-                       return -1;
-       }
-
-       /* compare all of the six auth values */
-       for (i = 0; i < 6; ++i) {
-               if (ctsid->authority[i] != cwsid->authority[i]) {
-                       if (ctsid->authority[i] > cwsid->authority[i])
-                               return 1;
-                       else
-                               return -1;
-               }
-       }
-
-       /* compare all of the subauth values if any */
-       num_sat = ctsid->num_subauth;
-       num_saw = cwsid->num_subauth;
-       num_subauth = num_sat < num_saw ? num_sat : num_saw;
-       if (num_subauth) {
-               for (i = 0; i < num_subauth; ++i) {
-                       if (ctsid->sub_auth[i] != cwsid->sub_auth[i]) {
-                               if (le32_to_cpu(ctsid->sub_auth[i]) >
-                                       le32_to_cpu(cwsid->sub_auth[i]))
-                                       return 1;
-                               else
-                                       return -1;
-                       }
-               }
-       }
-
-       return 0; /* sids compare/match */
-}
-
-
 /* copy ntsd, owner sid, and group sid from a security descriptor to another */
 static void copy_sec_desc(const struct cifs_ntsd *pntsd,
                                struct cifs_ntsd *pnntsd, __u32 sidsoffset)
 {
-       int i;
-
        struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
        struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr;
 
@@ -692,26 +390,14 @@ static void copy_sec_desc(const struct cifs_ntsd *pntsd,
        owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
                                le32_to_cpu(pntsd->osidoffset));
        nowner_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset);
-
-       nowner_sid_ptr->revision = owner_sid_ptr->revision;
-       nowner_sid_ptr->num_subauth = owner_sid_ptr->num_subauth;
-       for (i = 0; i < 6; i++)
-               nowner_sid_ptr->authority[i] = owner_sid_ptr->authority[i];
-       for (i = 0; i < 5; i++)
-               nowner_sid_ptr->sub_auth[i] = owner_sid_ptr->sub_auth[i];
+       cifs_copy_sid(nowner_sid_ptr, owner_sid_ptr);
 
        /* copy group sid */
        group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
                                le32_to_cpu(pntsd->gsidoffset));
        ngroup_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset +
                                        sizeof(struct cifs_sid));
-
-       ngroup_sid_ptr->revision = group_sid_ptr->revision;
-       ngroup_sid_ptr->num_subauth = group_sid_ptr->num_subauth;
-       for (i = 0; i < 6; i++)
-               ngroup_sid_ptr->authority[i] = group_sid_ptr->authority[i];
-       for (i = 0; i < 5; i++)
-               ngroup_sid_ptr->sub_auth[i] = group_sid_ptr->sub_auth[i];
+       cifs_copy_sid(ngroup_sid_ptr, group_sid_ptr);
 
        return;
 }
@@ -818,7 +504,7 @@ static __u16 fill_ace_for_sid(struct cifs_ace *pntace,
 
        pntace->sid.revision = psid->revision;
        pntace->sid.num_subauth = psid->num_subauth;
-       for (i = 0; i < 6; i++)
+       for (i = 0; i < NUM_AUTHS; i++)
                pntace->sid.authority[i] = psid->authority[i];
        for (i = 0; i < psid->num_subauth; i++)
                pntace->sid.sub_auth[i] = psid->sub_auth[i];
@@ -994,8 +680,8 @@ static int parse_sid(struct cifs_sid *psid, char *end_of_acl)
                return -EINVAL;
        }
 
-       if (psid->num_subauth) {
 #ifdef CONFIG_CIFS_DEBUG2
+       if (psid->num_subauth) {
                int i;
                cFYI(1, "SID revision %d num_auth %d",
                        psid->revision, psid->num_subauth);
@@ -1009,8 +695,8 @@ static int parse_sid(struct cifs_sid *psid, char *end_of_acl)
                        num auths and therefore go off the end */
                cFYI(1, "RID 0x%x",
                        le32_to_cpu(psid->sub_auth[psid->num_subauth-1]));
-#endif
        }
+#endif
 
        return 0;
 }
@@ -1120,8 +806,7 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
                                kfree(nowner_sid_ptr);
                                return rc;
                        }
-                       memcpy(owner_sid_ptr, nowner_sid_ptr,
-                                       sizeof(struct cifs_sid));
+                       cifs_copy_sid(owner_sid_ptr, nowner_sid_ptr);
                        kfree(nowner_sid_ptr);
                        *aclflag = CIFS_ACL_OWNER;
                }
@@ -1139,8 +824,7 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
                                kfree(ngroup_sid_ptr);
                                return rc;
                        }
-                       memcpy(group_sid_ptr, ngroup_sid_ptr,
-                                       sizeof(struct cifs_sid));
+                       cifs_copy_sid(group_sid_ptr, ngroup_sid_ptr);
                        kfree(ngroup_sid_ptr);
                        *aclflag = CIFS_ACL_GROUP;
                }
@@ -1316,42 +1000,39 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode,
 
        /* Get the security descriptor */
        pntsd = get_cifs_acl(CIFS_SB(inode->i_sb), inode, path, &secdesclen);
-
-       /* Add three ACEs for owner, group, everyone getting rid of
-          other ACEs as chmod disables ACEs and set the security descriptor */
-
        if (IS_ERR(pntsd)) {
                rc = PTR_ERR(pntsd);
                cERROR(1, "%s: error %d getting sec desc", __func__, rc);
-       } else {
-               /* allocate memory for the smb header,
-                  set security descriptor request security descriptor
-                  parameters, and secuirty descriptor itself */
-
-               secdesclen = secdesclen < DEFSECDESCLEN ?
-                                       DEFSECDESCLEN : secdesclen;
-               pnntsd = kmalloc(secdesclen, GFP_KERNEL);
-               if (!pnntsd) {
-                       cERROR(1, "Unable to allocate security descriptor");
-                       kfree(pntsd);
-                       return -ENOMEM;
-               }
+               goto out;
+       }
 
-               rc = build_sec_desc(pntsd, pnntsd, secdesclen, nmode, uid, gid,
-                                       &aclflag);
+       /*
+        * Add three ACEs for owner, group, everyone getting rid of other ACEs
+        * as chmod disables ACEs and set the security descriptor. Allocate
+        * memory for the smb header, set security descriptor request security
+        * descriptor parameters, and secuirty descriptor itself
+        */
+       secdesclen = max_t(u32, secdesclen, DEFSECDESCLEN);
+       pnntsd = kmalloc(secdesclen, GFP_KERNEL);
+       if (!pnntsd) {
+               cERROR(1, "Unable to allocate security descriptor");
+               kfree(pntsd);
+               return -ENOMEM;
+       }
 
-               cFYI(DBG2, "build_sec_desc rc: %d", rc);
+       rc = build_sec_desc(pntsd, pnntsd, secdesclen, nmode, uid, gid,
+                               &aclflag);
 
-               if (!rc) {
-                       /* Set the security descriptor */
-                       rc = set_cifs_acl(pnntsd, secdesclen, inode,
-                                               path, aclflag);
-                       cFYI(DBG2, "set_cifs_acl rc: %d", rc);
-               }
+       cFYI(DBG2, "build_sec_desc rc: %d", rc);
 
-               kfree(pnntsd);
-               kfree(pntsd);
+       if (!rc) {
+               /* Set the security descriptor */
+               rc = set_cifs_acl(pnntsd, secdesclen, inode, path, aclflag);
+               cFYI(DBG2, "set_cifs_acl rc: %d", rc);
        }
 
+       kfree(pnntsd);
+       kfree(pntsd);
+out:
        return rc;
 }
index 5c902c7ce5247a8df78db13072c0c7941e964086..46cd444ea2f26038d64ad23fa7e3615b2f4eadcf 100644 (file)
@@ -23,8 +23,8 @@
 #define _CIFSACL_H
 
 
-#define NUM_AUTHS 6 /* number of authority fields */
-#define NUM_SUBAUTHS 5 /* number of sub authority fields */
+#define NUM_AUTHS (6)  /* number of authority fields */
+#define SID_MAX_SUB_AUTHORITIES (15) /* max number of sub authority fields */
 #define NUM_WK_SIDS 7 /* number of well known sids */
 #define SIDNAMELENGTH 20 /* long enough for the ones we care about */
 #define DEFSECDESCLEN 192 /* sec desc len contaiting a dacl with three aces */
 
 #define SIDOWNER 1
 #define SIDGROUP 2
-#define SIDLEN 150 /* S- 1 revision- 6 authorities- max 5 sub authorities */
 
-#define SID_ID_MAPPED 0
-#define SID_ID_PENDING 1
-#define SID_MAP_EXPIRE (3600 * HZ) /* map entry expires after one hour */
-#define SID_MAP_RETRY (300 * HZ)   /* wait 5 minutes for next attempt to map */
+/*
+ * Maximum size of a string representation of a SID:
+ *
+ * The fields are unsigned values in decimal. So:
+ *
+ * u8:  max 3 bytes in decimal
+ * u32: max 10 bytes in decimal
+ *
+ * "S-" + 3 bytes for version field + 4 bytes for each authority field (3 bytes
+ * per number + 1 for '-') + NULL terminator.
+ *
+ * Add 11 bytes for each subauthority field (10 bytes each + 1 for '-')
+ */
+#define SID_STRING_BASE_SIZE (2 + 3 + (4 * NUM_AUTHS) + 1)
+#define SID_STRING_SUBAUTH_SIZE (11) /* size of a single subauth string */
 
 struct cifs_ntsd {
        __le16 revision; /* revision level */
@@ -60,10 +70,13 @@ struct cifs_ntsd {
 struct cifs_sid {
        __u8 revision; /* revision level */
        __u8 num_subauth;
-       __u8 authority[6];
-       __le32 sub_auth[5]; /* sub_auth[num_subauth] */
+       __u8 authority[NUM_AUTHS];
+       __le32 sub_auth[SID_MAX_SUB_AUTHORITIES]; /* sub_auth[num_subauth] */
 } __attribute__((packed));
 
+/* size of a struct cifs_sid, sans sub_auth array */
+#define CIFS_SID_BASE_SIZE (1 + 1 + NUM_AUTHS)
+
 struct cifs_acl {
        __le16 revision; /* revision level */
        __le16 size;
@@ -78,26 +91,4 @@ struct cifs_ace {
        struct cifs_sid sid; /* ie UUID of user or group who gets these perms */
 } __attribute__((packed));
 
-struct cifs_wksid {
-       struct cifs_sid cifssid;
-       char sidname[SIDNAMELENGTH];
-} __attribute__((packed));
-
-struct cifs_sid_id {
-       unsigned int refcount; /* increment with spinlock, decrement without */
-       unsigned long id;
-       unsigned long time;
-       unsigned long state;
-       char *sidstr;
-       struct rb_node rbnode;
-       struct cifs_sid sid;
-};
-
-#ifdef __KERNEL__
-extern struct key_type cifs_idmap_key_type;
-extern const struct cred *root_cred;
-#endif /* KERNEL */
-
-extern int compare_sids(const struct cifs_sid *, const struct cifs_sid *);
-
 #endif /* _CIFSACL_H */
index e7931cc55d0c96f7a4edde39d5fbd78fa24f82af..5e62f441267289dd497ae5e35707bc06782e2fbe 100644 (file)
@@ -64,24 +64,23 @@ unsigned int global_secflags = CIFSSEC_DEF;
 unsigned int sign_CIFS_PDUs = 1;
 static const struct super_operations cifs_super_ops;
 unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE;
-module_param(CIFSMaxBufSize, int, 0);
+module_param(CIFSMaxBufSize, uint, 0);
 MODULE_PARM_DESC(CIFSMaxBufSize, "Network buffer size (not including header). "
                                 "Default: 16384 Range: 8192 to 130048");
 unsigned int cifs_min_rcv = CIFS_MIN_RCV_POOL;
-module_param(cifs_min_rcv, int, 0);
+module_param(cifs_min_rcv, uint, 0);
 MODULE_PARM_DESC(cifs_min_rcv, "Network buffers in pool. Default: 4 Range: "
                                "1 to 64");
 unsigned int cifs_min_small = 30;
-module_param(cifs_min_small, int, 0);
+module_param(cifs_min_small, uint, 0);
 MODULE_PARM_DESC(cifs_min_small, "Small network buffers in pool. Default: 30 "
                                 "Range: 2 to 256");
 unsigned int cifs_max_pending = CIFS_MAX_REQ;
-module_param(cifs_max_pending, int, 0444);
+module_param(cifs_max_pending, uint, 0444);
 MODULE_PARM_DESC(cifs_max_pending, "Simultaneous requests to server. "
                                   "Default: 32767 Range: 2 to 32767.");
 module_param(enable_oplocks, bool, 0644);
-MODULE_PARM_DESC(enable_oplocks, "Enable or disable oplocks (bool). Default:"
-                                "y/Y/1");
+MODULE_PARM_DESC(enable_oplocks, "Enable or disable oplocks. Default: y/Y/1");
 
 extern mempool_t *cifs_sm_req_poolp;
 extern mempool_t *cifs_req_poolp;
@@ -1205,7 +1204,6 @@ exit_cifs(void)
        unregister_filesystem(&cifs_fs_type);
        cifs_dfs_release_automount_timer();
 #ifdef CONFIG_CIFS_ACL
-       cifs_destroy_idmaptrees();
        exit_cifs_idmap();
 #endif
 #ifdef CONFIG_CIFS_UPCALL
index 5144e9fbeb8cc9d58682dac81b66da81a81a3329..2d2ae6958658988bc49fc717c2a66b65aee0ef10 100644 (file)
@@ -58,7 +58,6 @@ do {                                                          \
 } while (0)
 extern int init_cifs_idmap(void);
 extern void exit_cifs_idmap(void);
-extern void cifs_destroy_idmaptrees(void);
 extern char *build_path_from_dentry(struct dentry *);
 extern char *build_wildcard_path_from_dentry(struct dentry *direntry);
 extern char *cifs_compose_mount_options(const char *sb_mountdata,
index afdff79651f1362c697d8f5d755aa4d3a6c66655..ed6208ff85a770771841a0fe54da82dff26bdfa3 100644 (file)
@@ -1791,11 +1791,12 @@ int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry,
        stat->ino = CIFS_I(inode)->uniqueid;
 
        /*
-        * If on a multiuser mount without unix extensions, and the admin hasn't
-        * overridden them, set the ownership to the fsuid/fsgid of the current
-        * process.
+        * If on a multiuser mount without unix extensions or cifsacl being
+        * enabled, and the admin hasn't overridden them, set the ownership
+        * to the fsuid/fsgid of the current process.
         */
        if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) &&
+           !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
            !tcon->unix_ext) {
                if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID))
                        stat->uid = current_fsuid();
index f9b5d3d6cf33461081f4945d61a5d604fe2ef468..96fe44b480af68c8d12762cb1b9af84b1a0b9b59 100644 (file)
@@ -134,6 +134,16 @@ cifs_fill_common_info(struct cifs_fattr *fattr, struct cifs_sb_info *cifs_sb)
        if (fattr->cf_cifsattrs & ATTR_READONLY)
                fattr->cf_mode &= ~S_IWUGO;
 
+       /*
+        * We of course don't get ACL info in FIND_FIRST/NEXT results, so
+        * mark it for revalidation so that "ls -l" will look right. It might
+        * be super-slow, but if we don't do this then the ownership of files
+        * may look wrong since the inodes may not have timed out by the time
+        * "ls" does a stat() call on them.
+        */
+       if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL)
+               fattr->cf_flags |= CIFS_FATTR_NEED_REVAL;
+
        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL &&
            fattr->cf_cifsattrs & ATTR_SYSTEM) {
                if (fattr->cf_eof == 0)  {
index 14afbabe65464e226549894404ec1af9d1a3f747..472e6befc54d3640d4ca8f7b3a6458aeb7eddce6 100644 (file)
@@ -545,37 +545,38 @@ void devpts_kill_index(struct inode *ptmx_inode, int idx)
        mutex_unlock(&allocated_ptys_lock);
 }
 
-int devpts_pty_new(struct inode *ptmx_inode, struct tty_struct *tty)
+/**
+ * devpts_pty_new -- create a new inode in /dev/pts/
+ * @ptmx_inode: inode of the master
+ * @device: major+minor of the node to be created
+ * @index: used as a name of the node
+ * @priv: what's given back by devpts_get_priv
+ *
+ * The created inode is returned. Remove it from /dev/pts/ by devpts_pty_kill.
+ */
+struct inode *devpts_pty_new(struct inode *ptmx_inode, dev_t device, int index,
+               void *priv)
 {
-       /* tty layer puts index from devpts_new_index() in here */
-       int number = tty->index;
-       struct tty_driver *driver = tty->driver;
-       dev_t device = MKDEV(driver->major, driver->minor_start+number);
        struct dentry *dentry;
        struct super_block *sb = pts_sb_from_inode(ptmx_inode);
-       struct inode *inode = new_inode(sb);
+       struct inode *inode;
        struct dentry *root = sb->s_root;
        struct pts_fs_info *fsi = DEVPTS_SB(sb);
        struct pts_mount_opts *opts = &fsi->mount_opts;
-       int ret = 0;
        char s[12];
 
-       /* We're supposed to be given the slave end of a pty */
-       BUG_ON(driver->type != TTY_DRIVER_TYPE_PTY);
-       BUG_ON(driver->subtype != PTY_TYPE_SLAVE);
-
+       inode = new_inode(sb);
        if (!inode)
-               return -ENOMEM;
+               return ERR_PTR(-ENOMEM);
 
-       inode->i_ino = number + 3;
+       inode->i_ino = index + 3;
        inode->i_uid = opts->setuid ? opts->uid : current_fsuid();
        inode->i_gid = opts->setgid ? opts->gid : current_fsgid();
        inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
        init_special_inode(inode, S_IFCHR|opts->mode, device);
-       inode->i_private = tty;
-       tty->driver_data = inode;
+       inode->i_private = priv;
 
-       sprintf(s, "%d", number);
+       sprintf(s, "%d", index);
 
        mutex_lock(&root->d_inode->i_mutex);
 
@@ -585,18 +586,24 @@ int devpts_pty_new(struct inode *ptmx_inode, struct tty_struct *tty)
                fsnotify_create(root->d_inode, dentry);
        } else {
                iput(inode);
-               ret = -ENOMEM;
+               inode = ERR_PTR(-ENOMEM);
        }
 
        mutex_unlock(&root->d_inode->i_mutex);
 
-       return ret;
+       return inode;
 }
 
-struct tty_struct *devpts_get_tty(struct inode *pts_inode, int number)
+/**
+ * devpts_get_priv -- get private data for a slave
+ * @pts_inode: inode of the slave
+ *
+ * Returns whatever was passed as priv in devpts_pty_new for a given inode.
+ */
+void *devpts_get_priv(struct inode *pts_inode)
 {
        struct dentry *dentry;
-       struct tty_struct *tty;
+       void *priv = NULL;
 
        BUG_ON(pts_inode->i_rdev == MKDEV(TTYAUX_MAJOR, PTMX_MINOR));
 
@@ -605,18 +612,22 @@ struct tty_struct *devpts_get_tty(struct inode *pts_inode, int number)
        if (!dentry)
                return NULL;
 
-       tty = NULL;
        if (pts_inode->i_sb->s_magic == DEVPTS_SUPER_MAGIC)
-               tty = (struct tty_struct *)pts_inode->i_private;
+               priv = pts_inode->i_private;
 
        dput(dentry);
 
-       return tty;
+       return priv;
 }
 
-void devpts_pty_kill(struct tty_struct *tty)
+/**
+ * devpts_pty_kill -- remove inode form /dev/pts/
+ * @inode: inode of the slave to be removed
+ *
+ * This is an inverse operation of devpts_pty_new.
+ */
+void devpts_pty_kill(struct inode *inode)
 {
-       struct inode *inode = tty->driver_data;
        struct super_block *sb = pts_sb_from_inode(inode);
        struct dentry *root = sb->s_root;
        struct dentry *dentry;
index 1b5089067d018d581c68242f39fcf522a8fee55d..cf1821784a16bff41349319400940c7e4218fa5a 100644 (file)
@@ -174,8 +174,7 @@ void ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
                ext4_free_inodes_set(sb, gdp, 0);
                ext4_itable_unused_set(sb, gdp, 0);
                memset(bh->b_data, 0xff, sb->s_blocksize);
-               ext4_block_bitmap_csum_set(sb, block_group, gdp, bh,
-                                          EXT4_BLOCKS_PER_GROUP(sb) / 8);
+               ext4_block_bitmap_csum_set(sb, block_group, gdp, bh);
                return;
        }
        memset(bh->b_data, 0, sb->s_blocksize);
@@ -212,8 +211,7 @@ void ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
         */
        ext4_mark_bitmap_end(num_clusters_in_group(sb, block_group),
                             sb->s_blocksize * 8, bh->b_data);
-       ext4_block_bitmap_csum_set(sb, block_group, gdp, bh,
-                                  EXT4_BLOCKS_PER_GROUP(sb) / 8);
+       ext4_block_bitmap_csum_set(sb, block_group, gdp, bh);
        ext4_group_desc_csum_set(sb, block_group, gdp);
 }
 
@@ -350,7 +348,7 @@ void ext4_validate_block_bitmap(struct super_block *sb,
                return;
        }
        if (unlikely(!ext4_block_bitmap_csum_verify(sb, block_group,
-                       desc, bh, EXT4_BLOCKS_PER_GROUP(sb) / 8))) {
+                       desc, bh))) {
                ext4_unlock_group(sb, block_group);
                ext4_error(sb, "bg %u: bad block bitmap checksum", block_group);
                return;
index 5c2d1813ebe919188d53dac74de8b512a7f02965..3285aa5a706af3f97c6a182a12304c7478177d9d 100644 (file)
@@ -58,11 +58,12 @@ void ext4_inode_bitmap_csum_set(struct super_block *sb, ext4_group_t group,
 
 int ext4_block_bitmap_csum_verify(struct super_block *sb, ext4_group_t group,
                                  struct ext4_group_desc *gdp,
-                                 struct buffer_head *bh, int sz)
+                                 struct buffer_head *bh)
 {
        __u32 hi;
        __u32 provided, calculated;
        struct ext4_sb_info *sbi = EXT4_SB(sb);
+       int sz = EXT4_CLUSTERS_PER_GROUP(sb) / 8;
 
        if (!EXT4_HAS_RO_COMPAT_FEATURE(sb,
                                        EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
@@ -84,8 +85,9 @@ int ext4_block_bitmap_csum_verify(struct super_block *sb, ext4_group_t group,
 
 void ext4_block_bitmap_csum_set(struct super_block *sb, ext4_group_t group,
                                struct ext4_group_desc *gdp,
-                               struct buffer_head *bh, int sz)
+                               struct buffer_head *bh)
 {
+       int sz = EXT4_CLUSTERS_PER_GROUP(sb) / 8;
        __u32 csum;
        struct ext4_sb_info *sbi = EXT4_SB(sb);
 
index 3ab2539b7b2eb477222a3dbb7dd8b51cea3cca84..3c20de1d59d0d44586199ade586864758e2ce204 100644 (file)
@@ -1882,10 +1882,10 @@ int ext4_inode_bitmap_csum_verify(struct super_block *sb, ext4_group_t group,
                                  struct buffer_head *bh, int sz);
 void ext4_block_bitmap_csum_set(struct super_block *sb, ext4_group_t group,
                                struct ext4_group_desc *gdp,
-                               struct buffer_head *bh, int sz);
+                               struct buffer_head *bh);
 int ext4_block_bitmap_csum_verify(struct super_block *sb, ext4_group_t group,
                                  struct ext4_group_desc *gdp,
-                                 struct buffer_head *bh, int sz);
+                                 struct buffer_head *bh);
 
 /* balloc.c */
 extern void ext4_validate_block_bitmap(struct super_block *sb,
@@ -2063,8 +2063,7 @@ extern int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count);
 extern int ext4_calculate_overhead(struct super_block *sb);
 extern int ext4_superblock_csum_verify(struct super_block *sb,
                                       struct ext4_super_block *es);
-extern void ext4_superblock_csum_set(struct super_block *sb,
-                                    struct ext4_super_block *es);
+extern void ext4_superblock_csum_set(struct super_block *sb);
 extern void *ext4_kvmalloc(size_t size, gfp_t flags);
 extern void *ext4_kvzalloc(size_t size, gfp_t flags);
 extern void ext4_kvfree(void *ptr);
index bfa65b49d4243d75a5c73456fc2ee4e3698537f4..b4323ba846b52ad09fe0740699ea2d82ff92ba65 100644 (file)
@@ -143,17 +143,13 @@ int __ext4_handle_dirty_super(const char *where, unsigned int line,
        struct buffer_head *bh = EXT4_SB(sb)->s_sbh;
        int err = 0;
 
+       ext4_superblock_csum_set(sb);
        if (ext4_handle_valid(handle)) {
-               ext4_superblock_csum_set(sb,
-                               (struct ext4_super_block *)bh->b_data);
                err = jbd2_journal_dirty_metadata(handle, bh);
                if (err)
                        ext4_journal_abort_handle(where, line, __func__,
                                                  bh, handle, err);
-       } else {
-               ext4_superblock_csum_set(sb,
-                               (struct ext4_super_block *)bh->b_data);
+       } else
                mark_buffer_dirty(bh);
-       }
        return err;
 }
index 1c94cca35ed1a12ce42ce39bddea7c9dd23111cf..7011ac967208e941272f09a07e3292d72ef576f9 100644 (file)
@@ -52,6 +52,9 @@
 #define EXT4_EXT_MARK_UNINIT1  0x2  /* mark first half uninitialized */
 #define EXT4_EXT_MARK_UNINIT2  0x4  /* mark second half uninitialized */
 
+#define EXT4_EXT_DATA_VALID1   0x8  /* first half contains valid data */
+#define EXT4_EXT_DATA_VALID2   0x10 /* second half contains valid data */
+
 static __le32 ext4_extent_block_csum(struct inode *inode,
                                     struct ext4_extent_header *eh)
 {
@@ -2914,6 +2917,9 @@ static int ext4_split_extent_at(handle_t *handle,
        unsigned int ee_len, depth;
        int err = 0;
 
+       BUG_ON((split_flag & (EXT4_EXT_DATA_VALID1 | EXT4_EXT_DATA_VALID2)) ==
+              (EXT4_EXT_DATA_VALID1 | EXT4_EXT_DATA_VALID2));
+
        ext_debug("ext4_split_extents_at: inode %lu, logical"
                "block %llu\n", inode->i_ino, (unsigned long long)split);
 
@@ -2972,7 +2978,14 @@ static int ext4_split_extent_at(handle_t *handle,
 
        err = ext4_ext_insert_extent(handle, inode, path, &newex, flags);
        if (err == -ENOSPC && (EXT4_EXT_MAY_ZEROOUT & split_flag)) {
-               err = ext4_ext_zeroout(inode, &orig_ex);
+               if (split_flag & (EXT4_EXT_DATA_VALID1|EXT4_EXT_DATA_VALID2)) {
+                       if (split_flag & EXT4_EXT_DATA_VALID1)
+                               err = ext4_ext_zeroout(inode, ex2);
+                       else
+                               err = ext4_ext_zeroout(inode, ex);
+               } else
+                       err = ext4_ext_zeroout(inode, &orig_ex);
+
                if (err)
                        goto fix_extent_len;
                /* update the extent length and mark as initialized */
@@ -3025,12 +3038,13 @@ static int ext4_split_extent(handle_t *handle,
        uninitialized = ext4_ext_is_uninitialized(ex);
 
        if (map->m_lblk + map->m_len < ee_block + ee_len) {
-               split_flag1 = split_flag & EXT4_EXT_MAY_ZEROOUT ?
-                             EXT4_EXT_MAY_ZEROOUT : 0;
+               split_flag1 = split_flag & EXT4_EXT_MAY_ZEROOUT;
                flags1 = flags | EXT4_GET_BLOCKS_PRE_IO;
                if (uninitialized)
                        split_flag1 |= EXT4_EXT_MARK_UNINIT1 |
                                       EXT4_EXT_MARK_UNINIT2;
+               if (split_flag & EXT4_EXT_DATA_VALID2)
+                       split_flag1 |= EXT4_EXT_DATA_VALID1;
                err = ext4_split_extent_at(handle, inode, path,
                                map->m_lblk + map->m_len, split_flag1, flags1);
                if (err)
@@ -3043,8 +3057,8 @@ static int ext4_split_extent(handle_t *handle,
                return PTR_ERR(path);
 
        if (map->m_lblk >= ee_block) {
-               split_flag1 = split_flag & EXT4_EXT_MAY_ZEROOUT ?
-                             EXT4_EXT_MAY_ZEROOUT : 0;
+               split_flag1 = split_flag & (EXT4_EXT_MAY_ZEROOUT |
+                                           EXT4_EXT_DATA_VALID2);
                if (uninitialized)
                        split_flag1 |= EXT4_EXT_MARK_UNINIT1;
                if (split_flag & EXT4_EXT_MARK_UNINIT2)
@@ -3323,26 +3337,47 @@ static int ext4_split_unwritten_extents(handle_t *handle,
 
        split_flag |= ee_block + ee_len <= eof_block ? EXT4_EXT_MAY_ZEROOUT : 0;
        split_flag |= EXT4_EXT_MARK_UNINIT2;
-
+       if (flags & EXT4_GET_BLOCKS_CONVERT)
+               split_flag |= EXT4_EXT_DATA_VALID2;
        flags |= EXT4_GET_BLOCKS_PRE_IO;
        return ext4_split_extent(handle, inode, path, map, split_flag, flags);
 }
 
 static int ext4_convert_unwritten_extents_endio(handle_t *handle,
-                                             struct inode *inode,
-                                             struct ext4_ext_path *path)
+                                               struct inode *inode,
+                                               struct ext4_map_blocks *map,
+                                               struct ext4_ext_path *path)
 {
        struct ext4_extent *ex;
+       ext4_lblk_t ee_block;
+       unsigned int ee_len;
        int depth;
        int err = 0;
 
        depth = ext_depth(inode);
        ex = path[depth].p_ext;
+       ee_block = le32_to_cpu(ex->ee_block);
+       ee_len = ext4_ext_get_actual_len(ex);
 
        ext_debug("ext4_convert_unwritten_extents_endio: inode %lu, logical"
                "block %llu, max_blocks %u\n", inode->i_ino,
-               (unsigned long long)le32_to_cpu(ex->ee_block),
-               ext4_ext_get_actual_len(ex));
+                 (unsigned long long)ee_block, ee_len);
+
+       /* If extent is larger than requested then split is required */
+       if (ee_block != map->m_lblk || ee_len > map->m_len) {
+               err = ext4_split_unwritten_extents(handle, inode, map, path,
+                                                  EXT4_GET_BLOCKS_CONVERT);
+               if (err < 0)
+                       goto out;
+               ext4_ext_drop_refs(path);
+               path = ext4_ext_find_extent(inode, map->m_lblk, path);
+               if (IS_ERR(path)) {
+                       err = PTR_ERR(path);
+                       goto out;
+               }
+               depth = ext_depth(inode);
+               ex = path[depth].p_ext;
+       }
 
        err = ext4_ext_get_access(handle, inode, path + depth);
        if (err)
@@ -3652,7 +3687,7 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode,
        }
        /* IO end_io complete, convert the filled extent to written */
        if ((flags & EXT4_GET_BLOCKS_CONVERT)) {
-               ret = ext4_convert_unwritten_extents_endio(handle, inode,
+               ret = ext4_convert_unwritten_extents_endio(handle, inode, map,
                                                        path);
                if (ret >= 0) {
                        ext4_update_inode_fsync_trans(handle, inode, 1);
@@ -4428,6 +4463,9 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
         */
        if (len <= EXT_UNINIT_MAX_LEN << blkbits)
                flags |= EXT4_GET_BLOCKS_NO_NORMALIZE;
+
+       /* Prevent race condition between unwritten */
+       ext4_flush_unwritten_io(inode);
 retry:
        while (ret >= 0 && ret < max_blocks) {
                map.m_lblk = map.m_lblk + ret;
index fa36372f3fdf827ed2557a3ecf5ccceab9e2cfe1..4facdd29a350f1d8250d17373e94c44a393ab78f 100644 (file)
@@ -762,9 +762,7 @@ got:
                        ext4_free_group_clusters_set(sb, gdp,
                                ext4_free_clusters_after_init(sb, group, gdp));
                        ext4_block_bitmap_csum_set(sb, group, gdp,
-                                                  block_bitmap_bh,
-                                                  EXT4_BLOCKS_PER_GROUP(sb) /
-                                                  8);
+                                                  block_bitmap_bh);
                        ext4_group_desc_csum_set(sb, group, gdp);
                }
                ext4_unlock_group(sb, group);
index f8b27bf80acaf45a3b9ce9aa872d2bed48b2f27d..526e55358606c83a548657449907cd94eed3c155 100644 (file)
@@ -2805,8 +2805,7 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
        }
        len = ext4_free_group_clusters(sb, gdp) - ac->ac_b_ex.fe_len;
        ext4_free_group_clusters_set(sb, gdp, len);
-       ext4_block_bitmap_csum_set(sb, ac->ac_b_ex.fe_group, gdp, bitmap_bh,
-                                  EXT4_BLOCKS_PER_GROUP(sb) / 8);
+       ext4_block_bitmap_csum_set(sb, ac->ac_b_ex.fe_group, gdp, bitmap_bh);
        ext4_group_desc_csum_set(sb, ac->ac_b_ex.fe_group, gdp);
 
        ext4_unlock_group(sb, ac->ac_b_ex.fe_group);
@@ -4666,8 +4665,7 @@ do_more:
 
        ret = ext4_free_group_clusters(sb, gdp) + count_clusters;
        ext4_free_group_clusters_set(sb, gdp, ret);
-       ext4_block_bitmap_csum_set(sb, block_group, gdp, bitmap_bh,
-                                  EXT4_BLOCKS_PER_GROUP(sb) / 8);
+       ext4_block_bitmap_csum_set(sb, block_group, gdp, bitmap_bh);
        ext4_group_desc_csum_set(sb, block_group, gdp);
        ext4_unlock_group(sb, block_group);
        percpu_counter_add(&sbi->s_freeclusters_counter, count_clusters);
@@ -4811,8 +4809,7 @@ int ext4_group_add_blocks(handle_t *handle, struct super_block *sb,
        mb_free_blocks(NULL, &e4b, bit, count);
        blk_free_count = blocks_freed + ext4_free_group_clusters(sb, desc);
        ext4_free_group_clusters_set(sb, desc, blk_free_count);
-       ext4_block_bitmap_csum_set(sb, block_group, desc, bitmap_bh,
-                                  EXT4_BLOCKS_PER_GROUP(sb) / 8);
+       ext4_block_bitmap_csum_set(sb, block_group, desc, bitmap_bh);
        ext4_group_desc_csum_set(sb, block_group, desc);
        ext4_unlock_group(sb, block_group);
        percpu_counter_add(&sbi->s_freeclusters_counter,
@@ -4993,8 +4990,9 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range)
        minlen = EXT4_NUM_B2C(EXT4_SB(sb),
                              range->minlen >> sb->s_blocksize_bits);
 
-       if (unlikely(minlen > EXT4_CLUSTERS_PER_GROUP(sb)) ||
-           unlikely(start >= max_blks))
+       if (minlen > EXT4_CLUSTERS_PER_GROUP(sb) ||
+           start >= max_blks ||
+           range->len < sb->s_blocksize)
                return -EINVAL;
        if (end >= max_blks)
                end = max_blks - 1;
index 7a75e1086961eedb674b8c2bf1bb84e657f4dfa2..47bf06a2765ddcbbd37eb84e693680278ea96fb9 100644 (file)
@@ -1212,8 +1212,7 @@ static int ext4_set_bitmap_checksums(struct super_block *sb,
        bh = ext4_get_bitmap(sb, group_data->block_bitmap);
        if (!bh)
                return -EIO;
-       ext4_block_bitmap_csum_set(sb, group, gdp, bh,
-                                  EXT4_BLOCKS_PER_GROUP(sb) / 8);
+       ext4_block_bitmap_csum_set(sb, group, gdp, bh);
        brelse(bh);
 
        return 0;
index 7265a0367476a87f0355b17c22b2488f65ec9a5f..80928f716850924cb34e7a591367cadf115fb95a 100644 (file)
@@ -143,9 +143,10 @@ int ext4_superblock_csum_verify(struct super_block *sb,
        return es->s_checksum == ext4_superblock_csum(sb, es);
 }
 
-void ext4_superblock_csum_set(struct super_block *sb,
-                             struct ext4_super_block *es)
+void ext4_superblock_csum_set(struct super_block *sb)
 {
+       struct ext4_super_block *es = EXT4_SB(sb)->s_es;
+
        if (!EXT4_HAS_RO_COMPAT_FEATURE(sb,
                EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
                return;
@@ -1963,7 +1964,7 @@ static int ext4_fill_flex_info(struct super_block *sb)
                sbi->s_log_groups_per_flex = 0;
                return 1;
        }
-       groups_per_flex = 1 << sbi->s_log_groups_per_flex;
+       groups_per_flex = 1U << sbi->s_log_groups_per_flex;
 
        err = ext4_alloc_flex_bg_array(sb, sbi->s_groups_count);
        if (err)
@@ -4381,7 +4382,7 @@ static int ext4_commit_super(struct super_block *sb, int sync)
                cpu_to_le32(percpu_counter_sum_positive(
                                &EXT4_SB(sb)->s_freeinodes_counter));
        BUFFER_TRACE(sbh, "marking dirty");
-       ext4_superblock_csum_set(sb, es);
+       ext4_superblock_csum_set(sb);
        mark_buffer_dirty(sbh);
        if (sync) {
                error = sync_dirty_buffer(sbh);
index 0cf160a94eda06afe6055d3c9e0aa806337121e3..1b2f6c2c3aaff697d2909cb88953e61b9d57b82b 100644 (file)
@@ -4,12 +4,24 @@ config FUSE_FS
          With FUSE it is possible to implement a fully functional filesystem
          in a userspace program.
 
-         There's also companion library: libfuse.  This library along with
-         utilities is available from the FUSE homepage:
+         There's also a companion library: libfuse2.  This library is available
+         from the FUSE homepage:
          <http://fuse.sourceforge.net/>
+         although chances are your distribution already has that library
+         installed if you've installed the "fuse" package itself.
 
          See <file:Documentation/filesystems/fuse.txt> for more information.
          See <file:Documentation/Changes> for needed library/utility version.
 
          If you want to develop a userspace FS, or if you want to use
          a filesystem based on FUSE, answer Y or M.
+
+config CUSE
+       tristate "Character device in Userspace support"
+       depends on FUSE_FS
+       help
+         This FUSE extension allows character devices to be
+         implemented in userspace.
+
+         If you want to develop or use a userspace character device
+         based on CUSE, answer Y or M.
index 8c23fa7a91e65cb46ad3907432e4418c7f96ad2d..4137559573e0dfbf5114e81db7b06d7bdc5a885c 100644 (file)
@@ -491,6 +491,25 @@ void fuse_request_send_background_locked(struct fuse_conn *fc,
        fuse_request_send_nowait_locked(fc, req);
 }
 
+void fuse_force_forget(struct file *file, u64 nodeid)
+{
+       struct inode *inode = file->f_path.dentry->d_inode;
+       struct fuse_conn *fc = get_fuse_conn(inode);
+       struct fuse_req *req;
+       struct fuse_forget_in inarg;
+
+       memset(&inarg, 0, sizeof(inarg));
+       inarg.nlookup = 1;
+       req = fuse_get_req_nofail(fc, file);
+       req->in.h.opcode = FUSE_FORGET;
+       req->in.h.nodeid = nodeid;
+       req->in.numargs = 1;
+       req->in.args[0].size = sizeof(inarg);
+       req->in.args[0].value = &inarg;
+       req->isreply = 0;
+       fuse_request_send_nowait(fc, req);
+}
+
 /*
  * Lock the request.  Up to the next unlock_request() there mustn't be
  * anything that could cause a page-fault.  If the request was already
index 324bc085053447665eccaacdc8fcf169cb418413..0994180d297315682728e1920315d23ae6483979 100644 (file)
@@ -1155,6 +1155,143 @@ static int parse_dirfile(char *buf, size_t nbytes, struct file *file,
        return 0;
 }
 
+static int fuse_direntplus_link(struct file *file,
+                               struct fuse_direntplus *direntplus,
+                               u64 attr_version)
+{
+       int err;
+       struct fuse_entry_out *o = &direntplus->entry_out;
+       struct fuse_dirent *dirent = &direntplus->dirent;
+       struct dentry *parent = file->f_path.dentry;
+       struct qstr name = QSTR_INIT(dirent->name, dirent->namelen);
+       struct dentry *dentry;
+       struct dentry *alias;
+       struct inode *dir = parent->d_inode;
+       struct fuse_conn *fc;
+       struct inode *inode;
+
+       if (!o->nodeid) {
+               /*
+                * Unlike in the case of fuse_lookup, zero nodeid does not mean
+                * ENOENT. Instead, it only means the userspace filesystem did
+                * not want to return attributes/handle for this entry.
+                *
+                * So do nothing.
+                */
+               return 0;
+       }
+
+       if (name.name[0] == '.') {
+               /*
+                * We could potentially refresh the attributes of the directory
+                * and its parent?
+                */
+               if (name.len == 1)
+                       return 0;
+               if (name.name[1] == '.' && name.len == 2)
+                       return 0;
+       }
+       fc = get_fuse_conn(dir);
+
+       name.hash = full_name_hash(name.name, name.len);
+       dentry = d_lookup(parent, &name);
+       if (dentry && dentry->d_inode) {
+               inode = dentry->d_inode;
+               if (get_node_id(inode) == o->nodeid) {
+                       struct fuse_inode *fi;
+                       fi = get_fuse_inode(inode);
+                       spin_lock(&fc->lock);
+                       fi->nlookup++;
+                       spin_unlock(&fc->lock);
+
+                       /*
+                        * The other branch to 'found' comes via fuse_iget()
+                        * which bumps nlookup inside
+                        */
+                       goto found;
+               }
+               err = d_invalidate(dentry);
+               if (err)
+                       goto out;
+               dput(dentry);
+               dentry = NULL;
+       }
+
+       dentry = d_alloc(parent, &name);
+       err = -ENOMEM;
+       if (!dentry)
+               goto out;
+
+       inode = fuse_iget(dir->i_sb, o->nodeid, o->generation,
+                         &o->attr, entry_attr_timeout(o), attr_version);
+       if (!inode)
+               goto out;
+
+       alias = d_materialise_unique(dentry, inode);
+       err = PTR_ERR(alias);
+       if (IS_ERR(alias))
+               goto out;
+       if (alias) {
+               dput(dentry);
+               dentry = alias;
+       }
+
+found:
+       fuse_change_attributes(inode, &o->attr, entry_attr_timeout(o),
+                              attr_version);
+
+       fuse_change_entry_timeout(dentry, o);
+
+       err = 0;
+out:
+       if (dentry)
+               dput(dentry);
+       return err;
+}
+
+static int parse_dirplusfile(char *buf, size_t nbytes, struct file *file,
+                            void *dstbuf, filldir_t filldir, u64 attr_version)
+{
+       struct fuse_direntplus *direntplus;
+       struct fuse_dirent *dirent;
+       size_t reclen;
+       int over = 0;
+       int ret;
+
+       while (nbytes >= FUSE_NAME_OFFSET_DIRENTPLUS) {
+               direntplus = (struct fuse_direntplus *) buf;
+               dirent = &direntplus->dirent;
+               reclen = FUSE_DIRENTPLUS_SIZE(direntplus);
+
+               if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX)
+                       return -EIO;
+               if (reclen > nbytes)
+                       break;
+
+               if (!over) {
+                       /* We fill entries into dstbuf only as much as
+                          it can hold. But we still continue iterating
+                          over remaining entries to link them. If not,
+                          we need to send a FORGET for each of those
+                          which we did not link.
+                       */
+                       over = filldir(dstbuf, dirent->name, dirent->namelen,
+                                      file->f_pos, dirent->ino,
+                                      dirent->type);
+                       file->f_pos = dirent->off;
+               }
+
+               buf += reclen;
+               nbytes -= reclen;
+
+               ret = fuse_direntplus_link(file, direntplus, attr_version);
+               if (ret)
+                       fuse_force_forget(file, direntplus->entry_out.nodeid);
+       }
+
+       return 0;
+}
+
 static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir)
 {
        int err;
@@ -1163,6 +1300,7 @@ static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir)
        struct inode *inode = file->f_path.dentry->d_inode;
        struct fuse_conn *fc = get_fuse_conn(inode);
        struct fuse_req *req;
+       u64 attr_version = 0;
 
        if (is_bad_inode(inode))
                return -EIO;
@@ -1179,14 +1317,28 @@ static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir)
        req->out.argpages = 1;
        req->num_pages = 1;
        req->pages[0] = page;
-       fuse_read_fill(req, file, file->f_pos, PAGE_SIZE, FUSE_READDIR);
+       if (fc->do_readdirplus) {
+               attr_version = fuse_get_attr_version(fc);
+               fuse_read_fill(req, file, file->f_pos, PAGE_SIZE,
+                              FUSE_READDIRPLUS);
+       } else {
+               fuse_read_fill(req, file, file->f_pos, PAGE_SIZE,
+                              FUSE_READDIR);
+       }
        fuse_request_send(fc, req);
        nbytes = req->out.args[0].size;
        err = req->out.h.error;
        fuse_put_request(fc, req);
-       if (!err)
-               err = parse_dirfile(page_address(page), nbytes, file, dstbuf,
-                                   filldir);
+       if (!err) {
+               if (fc->do_readdirplus) {
+                       err = parse_dirplusfile(page_address(page), nbytes,
+                                               file, dstbuf, filldir,
+                                               attr_version);
+               } else {
+                       err = parse_dirfile(page_address(page), nbytes, file,
+                                           dstbuf, filldir);
+               }
+       }
 
        __free_page(page);
        fuse_invalidate_attr(inode); /* atime changed */
index e24dd74e3068d130545ee58f918519d4ca2ee620..82f1045f59a724f4ec85350a3eaebad9681c867b 100644 (file)
@@ -487,6 +487,9 @@ struct fuse_conn {
        /** Use enhanced/automatic page cache invalidation. */
        unsigned auto_inval_data:1;
 
+       /** Does the filesystem support readdir-plus? */
+       unsigned do_readdirplus:1;
+
        /** The number of requests waiting for completion */
        atomic_t num_waiting;
 
@@ -578,6 +581,9 @@ void fuse_queue_forget(struct fuse_conn *fc, struct fuse_forget_link *forget,
 
 struct fuse_forget_link *fuse_alloc_forget(void);
 
+/* Used by READDIRPLUS */
+void fuse_force_forget(struct file *file, u64 nodeid);
+
 /**
  * Initialize READ or READDIR request
  */
index f0eda124cffb7714daf51c475dcabc8c955056e0..11c08189d06b733330830a32f720584cdaeb8ec2 100644 (file)
@@ -859,6 +859,8 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
                                fc->dont_mask = 1;
                        if (arg->flags & FUSE_AUTO_INVAL_DATA)
                                fc->auto_inval_data = 1;
+                       if (arg->flags & FUSE_DO_READDIRPLUS)
+                               fc->do_readdirplus = 1;
                } else {
                        ra_pages = fc->max_read / PAGE_CACHE_SIZE;
                        fc->no_lock = 1;
@@ -885,7 +887,8 @@ static void fuse_send_init(struct fuse_conn *fc, struct fuse_req *req)
        arg->flags |= FUSE_ASYNC_READ | FUSE_POSIX_LOCKS | FUSE_ATOMIC_O_TRUNC |
                FUSE_EXPORT_SUPPORT | FUSE_BIG_WRITES | FUSE_DONT_MASK |
                FUSE_SPLICE_WRITE | FUSE_SPLICE_MOVE | FUSE_SPLICE_READ |
-               FUSE_FLOCK_LOCKS | FUSE_IOCTL_DIR | FUSE_AUTO_INVAL_DATA;
+               FUSE_FLOCK_LOCKS | FUSE_IOCTL_DIR | FUSE_AUTO_INVAL_DATA |
+               FUSE_DO_READDIRPLUS;
        req->in.h.opcode = FUSE_INIT;
        req->in.numargs = 1;
        req->in.args[0].size = sizeof(*arg);
index 0def0504afc1816ae40b55de02c07aa68cc3a003..377a68dbd066f4b318d8b61472869c270eb7198b 100644 (file)
@@ -677,10 +677,8 @@ static ssize_t gfs2_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
        size_t writesize = iov_length(iov, nr_segs);
        struct dentry *dentry = file->f_dentry;
        struct gfs2_inode *ip = GFS2_I(dentry->d_inode);
-       struct gfs2_sbd *sdp;
        int ret;
 
-       sdp = GFS2_SB(file->f_mapping->host);
        ret = gfs2_rs_alloc(ip);
        if (ret)
                return ret;
index e6c2fd53cab252da56fab66b3ca2749ef7ed1f44..e543871ec82fb0a18358295ad39346efc19290d7 100644 (file)
@@ -55,8 +55,6 @@ struct gfs2_glock_iter {
 
 typedef void (*glock_examiner) (struct gfs2_glock * gl);
 
-static int __dump_glock(struct seq_file *seq, const struct gfs2_glock *gl);
-#define GLOCK_BUG_ON(gl,x) do { if (unlikely(x)) { __dump_glock(NULL, gl); BUG(); } } while(0)
 static void do_xmote(struct gfs2_glock *gl, struct gfs2_holder *gh, unsigned int target);
 
 static struct dentry *gfs2_root;
@@ -1013,7 +1011,7 @@ trap_recursive:
        printk(KERN_ERR "pid: %d\n", pid_nr(gh->gh_owner_pid));
        printk(KERN_ERR "lock type: %d req lock state : %d\n",
               gh->gh_gl->gl_name.ln_type, gh->gh_state);
-       __dump_glock(NULL, gl);
+       gfs2_dump_glock(NULL, gl);
        BUG();
 }
 
@@ -1508,7 +1506,7 @@ static int dump_glock(struct seq_file *seq, struct gfs2_glock *gl)
 {
        int ret;
        spin_lock(&gl->gl_spin);
-       ret = __dump_glock(seq, gl);
+       ret = gfs2_dump_glock(seq, gl);
        spin_unlock(&gl->gl_spin);
        return ret;
 }
@@ -1655,7 +1653,7 @@ static const char *gflags2str(char *buf, const struct gfs2_glock *gl)
 }
 
 /**
- * __dump_glock - print information about a glock
+ * gfs2_dump_glock - print information about a glock
  * @seq: The seq_file struct
  * @gl: the glock
  *
@@ -1672,7 +1670,7 @@ static const char *gflags2str(char *buf, const struct gfs2_glock *gl)
  * Returns: 0 on success, -ENOBUFS when we run out of space
  */
 
-static int __dump_glock(struct seq_file *seq, const struct gfs2_glock *gl)
+int gfs2_dump_glock(struct seq_file *seq, const struct gfs2_glock *gl)
 {
        const struct gfs2_glock_operations *glops = gl->gl_ops;
        unsigned long long dtime;
index 307ac31df781ea80ac8f77e01bfe5f4970710cb3..fd580b7861d5b940170092a719ddf4fe15cf3a26 100644 (file)
@@ -178,33 +178,33 @@ static inline struct address_space *gfs2_glock2aspace(struct gfs2_glock *gl)
        return NULL;
 }
 
-int gfs2_glock_get(struct gfs2_sbd *sdp,
-                  u64 number, const struct gfs2_glock_operations *glops,
-                  int create, struct gfs2_glock **glp);
-void gfs2_glock_hold(struct gfs2_glock *gl);
-void gfs2_glock_put_nolock(struct gfs2_glock *gl);
-void gfs2_glock_put(struct gfs2_glock *gl);
-void gfs2_holder_init(struct gfs2_glock *gl, unsigned int state, unsigned flags,
-                     struct gfs2_holder *gh);
-void gfs2_holder_reinit(unsigned int state, unsigned flags,
-                       struct gfs2_holder *gh);
-void gfs2_holder_uninit(struct gfs2_holder *gh);
-int gfs2_glock_nq(struct gfs2_holder *gh);
-int gfs2_glock_poll(struct gfs2_holder *gh);
-int gfs2_glock_wait(struct gfs2_holder *gh);
-void gfs2_glock_dq(struct gfs2_holder *gh);
-void gfs2_glock_dq_wait(struct gfs2_holder *gh);
-
-void gfs2_glock_dq_uninit(struct gfs2_holder *gh);
-int gfs2_glock_nq_num(struct gfs2_sbd *sdp,
-                     u64 number, const struct gfs2_glock_operations *glops,
-                     unsigned int state, int flags, struct gfs2_holder *gh);
-
-int gfs2_glock_nq_m(unsigned int num_gh, struct gfs2_holder *ghs);
-void gfs2_glock_dq_m(unsigned int num_gh, struct gfs2_holder *ghs);
-void gfs2_glock_dq_uninit_m(unsigned int num_gh, struct gfs2_holder *ghs);
-
-__printf(2, 3)
+extern int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
+                         const struct gfs2_glock_operations *glops,
+                         int create, struct gfs2_glock **glp);
+extern void gfs2_glock_hold(struct gfs2_glock *gl);
+extern void gfs2_glock_put_nolock(struct gfs2_glock *gl);
+extern void gfs2_glock_put(struct gfs2_glock *gl);
+extern void gfs2_holder_init(struct gfs2_glock *gl, unsigned int state,
+                            unsigned flags, struct gfs2_holder *gh);
+extern void gfs2_holder_reinit(unsigned int state, unsigned flags,
+                              struct gfs2_holder *gh);
+extern void gfs2_holder_uninit(struct gfs2_holder *gh);
+extern int gfs2_glock_nq(struct gfs2_holder *gh);
+extern int gfs2_glock_poll(struct gfs2_holder *gh);
+extern int gfs2_glock_wait(struct gfs2_holder *gh);
+extern void gfs2_glock_dq(struct gfs2_holder *gh);
+extern void gfs2_glock_dq_wait(struct gfs2_holder *gh);
+extern void gfs2_glock_dq_uninit(struct gfs2_holder *gh);
+extern int gfs2_glock_nq_num(struct gfs2_sbd *sdp, u64 number,
+                            const struct gfs2_glock_operations *glops,
+                            unsigned int state, int flags,
+                            struct gfs2_holder *gh);
+extern int gfs2_glock_nq_m(unsigned int num_gh, struct gfs2_holder *ghs);
+extern void gfs2_glock_dq_m(unsigned int num_gh, struct gfs2_holder *ghs);
+extern void gfs2_glock_dq_uninit_m(unsigned int num_gh, struct gfs2_holder *ghs);
+extern int gfs2_dump_glock(struct seq_file *seq, const struct gfs2_glock *gl);
+#define GLOCK_BUG_ON(gl,x) do { if (unlikely(x)) { gfs2_dump_glock(NULL, gl); BUG(); } } while(0)
+extern __printf(2, 3)
 void gfs2_print_dbg(struct seq_file *seq, const char *fmt, ...);
 
 /**
index 32cc4fde975c2d74aa19d7134f61ed712a1599fa..0a3e7c7e26c140c61a55fb57c4eb3eb3c6785ea2 100644 (file)
@@ -74,7 +74,7 @@ static void __gfs2_ail_flush(struct gfs2_glock *gl, bool fsync)
 
                gfs2_trans_add_revoke(sdp, bd);
        }
-       BUG_ON(!fsync && atomic_read(&gl->gl_ail_count));
+       GLOCK_BUG_ON(gl, !fsync && atomic_read(&gl->gl_ail_count));
        spin_unlock(&sdp->sd_ail_lock);
        gfs2_log_unlock(sdp);
 }
@@ -96,7 +96,7 @@ static void gfs2_ail_empty_gl(struct gfs2_glock *gl)
        tr.tr_ip = (unsigned long)__builtin_return_address(0);
        sb_start_intwrite(sdp->sd_vfs);
        gfs2_log_reserve(sdp, tr.tr_reserved);
-       BUG_ON(current->journal_info);
+       WARN_ON_ONCE(current->journal_info);
        current->journal_info = &tr;
 
        __gfs2_ail_flush(gl, 0);
@@ -139,7 +139,7 @@ static void rgrp_go_sync(struct gfs2_glock *gl)
 
        if (!test_and_clear_bit(GLF_DIRTY, &gl->gl_flags))
                return;
-       BUG_ON(gl->gl_state != LM_ST_EXCLUSIVE);
+       GLOCK_BUG_ON(gl, gl->gl_state != LM_ST_EXCLUSIVE);
 
        gfs2_log_flush(gl->gl_sbd, gl);
        filemap_fdatawrite(metamapping);
@@ -168,7 +168,7 @@ static void rgrp_go_inval(struct gfs2_glock *gl, int flags)
 {
        struct address_space *mapping = gfs2_glock2aspace(gl);
 
-       BUG_ON(!(flags & DIO_METADATA));
+       WARN_ON_ONCE(!(flags & DIO_METADATA));
        gfs2_assert_withdraw(gl->gl_sbd, !atomic_read(&gl->gl_ail_count));
        truncate_inode_pages(mapping, 0);
 
@@ -197,7 +197,7 @@ static void inode_go_sync(struct gfs2_glock *gl)
        if (!test_and_clear_bit(GLF_DIRTY, &gl->gl_flags))
                return;
 
-       BUG_ON(gl->gl_state != LM_ST_EXCLUSIVE);
+       GLOCK_BUG_ON(gl, gl->gl_state != LM_ST_EXCLUSIVE);
 
        gfs2_log_flush(gl->gl_sbd, gl);
        filemap_fdatawrite(metamapping);
index 3d469d37345ebfad798578830b9d768a59c6a35c..24bb0b857860fbf2a0778d309edb85bf17c50a86 100644 (file)
@@ -621,6 +621,7 @@ struct gfs2_sbd {
        u32 sd_hash_bsize_shift;
        u32 sd_hash_ptrs;       /* Number of pointers in a hash block */
        u32 sd_qc_per_block;
+       u32 sd_blocks_per_bitmap;
        u32 sd_max_dirres;      /* Max blocks needed to add a directory entry */
        u32 sd_max_height;      /* Max height of a file's metadata tree */
        u64 sd_heightsize[GFS2_MAX_META_HEIGHT + 1];
index 8ff95a2d54ee7dae3de7a9ad6945b5a6c0f17b13..01e444b5b2bd4495f5b82f85e1c1cb9cc61cad99 100644 (file)
@@ -621,7 +621,6 @@ static void revoke_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)
 
 static void revoke_lo_before_commit(struct gfs2_sbd *sdp)
 {
-       struct gfs2_log_descriptor *ld;
        struct gfs2_meta_header *mh;
        unsigned int offset;
        struct list_head *head = &sdp->sd_log_le_revoke;
@@ -634,7 +633,6 @@ static void revoke_lo_before_commit(struct gfs2_sbd *sdp)
 
        length = gfs2_struct2blk(sdp, sdp->sd_log_num_revoke, sizeof(u64));
        page = gfs2_get_log_desc(sdp, GFS2_LOG_DESC_REVOKE, length, sdp->sd_log_num_revoke);
-       ld = page_address(page);
        offset = sizeof(struct gfs2_log_descriptor);
 
        list_for_each_entry(bd, head, bd_list) {
index e443966c810697e50f71b37afb807db62828335f..0e3554edb8f25d2f5d82932294eca6b5b4d54020 100644 (file)
@@ -278,6 +278,9 @@ static int gfs2_read_sb(struct gfs2_sbd *sdp, int silent)
        sdp->sd_qc_per_block = (sdp->sd_sb.sb_bsize -
                                sizeof(struct gfs2_meta_header)) /
                                sizeof(struct gfs2_quota_change);
+       sdp->sd_blocks_per_bitmap = (sdp->sd_sb.sb_bsize -
+                                    sizeof(struct gfs2_meta_header))
+               * GFS2_NBBY; /* not the rgrp bitmap, subsequent bitmaps only */
 
        /* Compute maximum reservation required to add a entry to a directory */
 
index 40c4b0d42fa8fea10b73102b4fd7d155ebf8daa0..c5af8e18f27af8a3b0c899ce1fe5404fede93831 100644 (file)
@@ -497,8 +497,11 @@ int gfs2_quota_hold(struct gfs2_inode *ip, u32 uid, u32 gid)
        struct gfs2_quota_data **qd;
        int error;
 
-       if (ip->i_res == NULL)
-               gfs2_rs_alloc(ip);
+       if (ip->i_res == NULL) {
+               error = gfs2_rs_alloc(ip);
+               if (error)
+                       return error;
+       }
 
        qd = ip->i_res->rs_qa_qd;
 
index 3cc402ce6fea6b3957e82646851e9646fa7cd26b..669b89b95ccc35b3794bd78301bcf9f741cf429b 100644 (file)
@@ -251,22 +251,25 @@ static u32 gfs2_bitfit(const u8 *buf, const unsigned int len,
 static int gfs2_rbm_from_block(struct gfs2_rbm *rbm, u64 block)
 {
        u64 rblock = block - rbm->rgd->rd_data0;
-       u32 goal = (u32)rblock;
-       int x;
+       u32 x;
 
        if (WARN_ON_ONCE(rblock > UINT_MAX))
                return -EINVAL;
        if (block >= rbm->rgd->rd_data0 + rbm->rgd->rd_data)
                return -E2BIG;
 
-       for (x = 0; x < rbm->rgd->rd_length; x++) {
-               rbm->bi = rbm->rgd->rd_bits + x;
-               if (goal < (rbm->bi->bi_start + rbm->bi->bi_len) * GFS2_NBBY) {
-                       rbm->offset = goal - (rbm->bi->bi_start * GFS2_NBBY);
-                       break;
-               }
-       }
+       rbm->bi = rbm->rgd->rd_bits;
+       rbm->offset = (u32)(rblock);
+       /* Check if the block is within the first block */
+       if (rbm->offset < (rbm->bi->bi_start + rbm->bi->bi_len) * GFS2_NBBY)
+               return 0;
 
+       /* Adjust for the size diff between gfs2_meta_header and gfs2_rgrp */
+       rbm->offset += (sizeof(struct gfs2_rgrp) -
+                       sizeof(struct gfs2_meta_header)) * GFS2_NBBY;
+       x = rbm->offset / rbm->rgd->rd_sbd->sd_blocks_per_bitmap;
+       rbm->offset -= x * rbm->rgd->rd_sbd->sd_blocks_per_bitmap;
+       rbm->bi += x;
        return 0;
 }
 
@@ -553,7 +556,6 @@ void gfs2_free_clones(struct gfs2_rgrpd *rgd)
  */
 int gfs2_rs_alloc(struct gfs2_inode *ip)
 {
-       int error = 0;
        struct gfs2_blkreserv *res;
 
        if (ip->i_res)
@@ -561,7 +563,7 @@ int gfs2_rs_alloc(struct gfs2_inode *ip)
 
        res = kmem_cache_zalloc(gfs2_rsrv_cachep, GFP_NOFS);
        if (!res)
-               error = -ENOMEM;
+               return -ENOMEM;
 
        RB_CLEAR_NODE(&res->rs_node);
 
@@ -571,7 +573,7 @@ int gfs2_rs_alloc(struct gfs2_inode *ip)
        else
                ip->i_res = res;
        up_write(&ip->i_rw_mutex);
-       return error;
+       return 0;
 }
 
 static void dump_rs(struct seq_file *seq, const struct gfs2_blkreserv *rs)
@@ -1263,7 +1265,9 @@ int gfs2_fitrim(struct file *filp, void __user *argp)
        int ret = 0;
        u64 amt;
        u64 trimmed = 0;
+       u64 start, end, minlen;
        unsigned int x;
+       unsigned bs_shift = sdp->sd_sb.sb_bsize_shift;
 
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
@@ -1271,19 +1275,25 @@ int gfs2_fitrim(struct file *filp, void __user *argp)
        if (!blk_queue_discard(q))
                return -EOPNOTSUPP;
 
-       if (argp == NULL) {
-               r.start = 0;
-               r.len = ULLONG_MAX;
-               r.minlen = 0;
-       } else if (copy_from_user(&r, argp, sizeof(r)))
+       if (copy_from_user(&r, argp, sizeof(r)))
                return -EFAULT;
 
        ret = gfs2_rindex_update(sdp);
        if (ret)
                return ret;
 
-       rgd = gfs2_blk2rgrpd(sdp, r.start, 0);
-       rgd_end = gfs2_blk2rgrpd(sdp, r.start + r.len, 0);
+       start = r.start >> bs_shift;
+       end = start + (r.len >> bs_shift);
+       minlen = max_t(u64, r.minlen,
+                      q->limits.discard_granularity) >> bs_shift;
+
+       rgd = gfs2_blk2rgrpd(sdp, start, 0);
+       rgd_end = gfs2_blk2rgrpd(sdp, end - 1, 0);
+
+       if (end <= start ||
+           minlen > sdp->sd_max_rg_data ||
+           start > rgd_end->rd_data0 + rgd_end->rd_data)
+               return -EINVAL;
 
        while (1) {
 
@@ -1295,7 +1305,9 @@ int gfs2_fitrim(struct file *filp, void __user *argp)
                        /* Trim each bitmap in the rgrp */
                        for (x = 0; x < rgd->rd_length; x++) {
                                struct gfs2_bitmap *bi = rgd->rd_bits + x;
-                               ret = gfs2_rgrp_send_discards(sdp, rgd->rd_data0, NULL, bi, r.minlen, &amt);
+                               ret = gfs2_rgrp_send_discards(sdp,
+                                               rgd->rd_data0, NULL, bi, minlen,
+                                               &amt);
                                if (ret) {
                                        gfs2_glock_dq_uninit(&gh);
                                        goto out;
@@ -1324,7 +1336,7 @@ int gfs2_fitrim(struct file *filp, void __user *argp)
 
 out:
        r.len = trimmed << 9;
-       if (argp && copy_to_user(argp, &r, sizeof(r)))
+       if (copy_to_user(argp, &r, sizeof(r)))
                return -EFAULT;
 
        return ret;
index 60ef3fb707ffbfc6a77f1257efc82544cf0f9489..1506673c087e11ae820245baadc8ae74cb9f01b2 100644 (file)
@@ -138,33 +138,39 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
        struct page *pg;
        struct inode *inode = mapping->host;
        struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
+       struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
+       struct jffs2_raw_inode ri;
+       uint32_t alloc_len = 0;
        pgoff_t index = pos >> PAGE_CACHE_SHIFT;
        uint32_t pageofs = index << PAGE_CACHE_SHIFT;
        int ret = 0;
 
+       jffs2_dbg(1, "%s()\n", __func__);
+
+       if (pageofs > inode->i_size) {
+               ret = jffs2_reserve_space(c, sizeof(ri), &alloc_len,
+                                         ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
+               if (ret)
+                       return ret;
+       }
+
+       mutex_lock(&f->sem);
        pg = grab_cache_page_write_begin(mapping, index, flags);
-       if (!pg)
+       if (!pg) {
+               if (alloc_len)
+                       jffs2_complete_reservation(c);
+               mutex_unlock(&f->sem);
                return -ENOMEM;
+       }
        *pagep = pg;
 
-       jffs2_dbg(1, "%s()\n", __func__);
-
-       if (pageofs > inode->i_size) {
+       if (alloc_len) {
                /* Make new hole frag from old EOF to new page */
-               struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
-               struct jffs2_raw_inode ri;
                struct jffs2_full_dnode *fn;
-               uint32_t alloc_len;
 
                jffs2_dbg(1, "Writing new hole frag 0x%x-0x%x between current EOF and new page\n",
                          (unsigned int)inode->i_size, pageofs);
 
-               ret = jffs2_reserve_space(c, sizeof(ri), &alloc_len,
-                                         ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
-               if (ret)
-                       goto out_page;
-
-               mutex_lock(&f->sem);
                memset(&ri, 0, sizeof(ri));
 
                ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
@@ -191,7 +197,6 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
                if (IS_ERR(fn)) {
                        ret = PTR_ERR(fn);
                        jffs2_complete_reservation(c);
-                       mutex_unlock(&f->sem);
                        goto out_page;
                }
                ret = jffs2_add_full_dnode_to_inode(c, f, fn);
@@ -206,12 +211,10 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
                        jffs2_mark_node_obsolete(c, fn->raw);
                        jffs2_free_full_dnode(fn);
                        jffs2_complete_reservation(c);
-                       mutex_unlock(&f->sem);
                        goto out_page;
                }
                jffs2_complete_reservation(c);
                inode->i_size = pageofs;
-               mutex_unlock(&f->sem);
        }
 
        /*
@@ -220,18 +223,18 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
         * case of a short-copy.
         */
        if (!PageUptodate(pg)) {
-               mutex_lock(&f->sem);
                ret = jffs2_do_readpage_nolock(inode, pg);
-               mutex_unlock(&f->sem);
                if (ret)
                        goto out_page;
        }
+       mutex_unlock(&f->sem);
        jffs2_dbg(1, "end write_begin(). pg->flags %lx\n", pg->flags);
        return ret;
 
 out_page:
        unlock_page(pg);
        page_cache_release(pg);
+       mutex_unlock(&f->sem);
        return ret;
 }
 
index 9947563e41750223035daa3aeeaba785a9baf82c..dfcd5030455933bcfbc795c251bc3f0b6fa8e36a 100644 (file)
@@ -83,7 +83,7 @@ int jfs_ioc_trim(struct inode *ip, struct fstrim_range *range)
        struct bmap *bmp = JFS_SBI(ip->i_sb)->bmap;
        struct super_block *sb = ipbmap->i_sb;
        int agno, agno_end;
-       s64 start, end, minlen;
+       u64 start, end, minlen;
        u64 trimmed = 0;
 
        /**
@@ -93,15 +93,19 @@ int jfs_ioc_trim(struct inode *ip, struct fstrim_range *range)
         * minlen:      minimum extent length in Bytes
         */
        start = range->start >> sb->s_blocksize_bits;
-       if (start < 0)
-               start = 0;
        end = start + (range->len >> sb->s_blocksize_bits) - 1;
-       if (end >= bmp->db_mapsize)
-               end = bmp->db_mapsize - 1;
        minlen = range->minlen >> sb->s_blocksize_bits;
-       if (minlen <= 0)
+       if (minlen == 0)
                minlen = 1;
 
+       if (minlen > bmp->db_agsize ||
+           start >= bmp->db_mapsize ||
+           range->len < sb->s_blocksize)
+               return -EINVAL;
+
+       if (end >= bmp->db_mapsize)
+               end = bmp->db_mapsize - 1;
+
        /**
         * we trim all ag's within the range
         */
index 13ad1539fbf2479cd7f69a45611cd3d6a460688f..00ec0b9c94d116fd513e356e6616a4142ef10a94 100644 (file)
@@ -64,10 +64,6 @@ static void nlm4_compute_offsets(const struct nlm_lock *lock,
 {
        const struct file_lock *fl = &lock->fl;
 
-       BUG_ON(fl->fl_start > NLM4_OFFSET_MAX);
-       BUG_ON(fl->fl_end > NLM4_OFFSET_MAX &&
-                               fl->fl_end != OFFSET_MAX);
-
        *l_offset = loff_t_to_s64(fl->fl_start);
        if (fl->fl_end == OFFSET_MAX)
                *l_len = 0;
@@ -122,7 +118,6 @@ static void encode_netobj(struct xdr_stream *xdr,
 {
        __be32 *p;
 
-       BUG_ON(length > XDR_MAX_NETOBJ);
        p = xdr_reserve_space(xdr, 4 + length);
        xdr_encode_opaque(p, data, length);
 }
@@ -156,7 +151,6 @@ out_overflow:
 static void encode_cookie(struct xdr_stream *xdr,
                          const struct nlm_cookie *cookie)
 {
-       BUG_ON(cookie->len > NLM_MAXCOOKIELEN);
        encode_netobj(xdr, (u8 *)&cookie->data, cookie->len);
 }
 
@@ -198,7 +192,6 @@ out_overflow:
  */
 static void encode_fh(struct xdr_stream *xdr, const struct nfs_fh *fh)
 {
-       BUG_ON(fh->size > NFS3_FHSIZE);
        encode_netobj(xdr, (u8 *)&fh->data, fh->size);
 }
 
@@ -336,7 +329,6 @@ static void encode_caller_name(struct xdr_stream *xdr, const char *name)
        u32 length = strlen(name);
        __be32 *p;
 
-       BUG_ON(length > NLM_MAXSTRLEN);
        p = xdr_reserve_space(xdr, 4 + length);
        xdr_encode_opaque(p, name, length);
 }
index 05d29124c6ab4150c9a5381cbc98b9a472c65b25..54f9e6ce0430ae88d742709bc47499c0d1b71731 100644 (file)
@@ -141,7 +141,7 @@ static void nlmclnt_setlockargs(struct nlm_rqst *req, struct file_lock *fl)
 
 static void nlmclnt_release_lockargs(struct nlm_rqst *req)
 {
-       BUG_ON(req->a_args.lock.fl.fl_ops != NULL);
+       WARN_ON_ONCE(req->a_args.lock.fl.fl_ops != NULL);
 }
 
 /**
@@ -465,7 +465,6 @@ static const struct file_lock_operations nlmclnt_lock_ops = {
 
 static void nlmclnt_locks_init_private(struct file_lock *fl, struct nlm_host *host)
 {
-       BUG_ON(fl->fl_ops != NULL);
        fl->fl_u.nfs_fl.state = 0;
        fl->fl_u.nfs_fl.owner = nlm_find_lockowner(host, fl->fl_owner);
        INIT_LIST_HEAD(&fl->fl_u.nfs_fl.list);
index d269ada7670e155c7544a2aa01ea0697e98f3991..9a55797a1cd420ac6b5fa051ebfc9d5780f2ccca 100644 (file)
@@ -60,10 +60,6 @@ static void nlm_compute_offsets(const struct nlm_lock *lock,
 {
        const struct file_lock *fl = &lock->fl;
 
-       BUG_ON(fl->fl_start > NLM_OFFSET_MAX);
-       BUG_ON(fl->fl_end > NLM_OFFSET_MAX &&
-                               fl->fl_end != OFFSET_MAX);
-
        *l_offset = loff_t_to_s32(fl->fl_start);
        if (fl->fl_end == OFFSET_MAX)
                *l_len = 0;
@@ -119,7 +115,6 @@ static void encode_netobj(struct xdr_stream *xdr,
 {
        __be32 *p;
 
-       BUG_ON(length > XDR_MAX_NETOBJ);
        p = xdr_reserve_space(xdr, 4 + length);
        xdr_encode_opaque(p, data, length);
 }
@@ -153,7 +148,6 @@ out_overflow:
 static void encode_cookie(struct xdr_stream *xdr,
                          const struct nlm_cookie *cookie)
 {
-       BUG_ON(cookie->len > NLM_MAXCOOKIELEN);
        encode_netobj(xdr, (u8 *)&cookie->data, cookie->len);
 }
 
@@ -195,7 +189,6 @@ out_overflow:
  */
 static void encode_fh(struct xdr_stream *xdr, const struct nfs_fh *fh)
 {
-       BUG_ON(fh->size != NFS2_FHSIZE);
        encode_netobj(xdr, (u8 *)&fh->data, NFS2_FHSIZE);
 }
 
@@ -223,7 +216,7 @@ static void encode_nlm_stat(struct xdr_stream *xdr,
 {
        __be32 *p;
 
-       BUG_ON(be32_to_cpu(stat) > NLM_LCK_DENIED_GRACE_PERIOD);
+       WARN_ON_ONCE(be32_to_cpu(stat) > NLM_LCK_DENIED_GRACE_PERIOD);
        p = xdr_reserve_space(xdr, 4);
        *p = stat;
 }
@@ -330,7 +323,6 @@ static void encode_caller_name(struct xdr_stream *xdr, const char *name)
        u32 length = strlen(name);
        __be32 *p;
 
-       BUG_ON(length > NLM_MAXSTRLEN);
        p = xdr_reserve_space(xdr, 4 + length);
        xdr_encode_opaque(p, name, length);
 }
index f9b22e58f78f053a05fffa2ec11feaa32bc2518a..0e17090c310f100f00573590f5653e8e93bab88a 100644 (file)
@@ -177,9 +177,6 @@ static void nlm_destroy_host_locked(struct nlm_host *host)
 
        dprintk("lockd: destroy host %s\n", host->h_name);
 
-       BUG_ON(!list_empty(&host->h_lockowners));
-       BUG_ON(atomic_read(&host->h_count));
-
        hlist_del_init(&host->h_hash);
 
        nsm_unmonitor(host);
@@ -289,13 +286,12 @@ void nlmclnt_release_host(struct nlm_host *host)
 
        dprintk("lockd: release client host %s\n", host->h_name);
 
-       BUG_ON(atomic_read(&host->h_count) < 0);
-       BUG_ON(host->h_server);
+       WARN_ON_ONCE(host->h_server);
 
        if (atomic_dec_and_test(&host->h_count)) {
-               BUG_ON(!list_empty(&host->h_lockowners));
-               BUG_ON(!list_empty(&host->h_granted));
-               BUG_ON(!list_empty(&host->h_reclaim));
+               WARN_ON_ONCE(!list_empty(&host->h_lockowners));
+               WARN_ON_ONCE(!list_empty(&host->h_granted));
+               WARN_ON_ONCE(!list_empty(&host->h_reclaim));
 
                mutex_lock(&nlm_host_mutex);
                nlm_destroy_host_locked(host);
@@ -412,8 +408,7 @@ void nlmsvc_release_host(struct nlm_host *host)
 
        dprintk("lockd: release server host %s\n", host->h_name);
 
-       BUG_ON(atomic_read(&host->h_count) < 0);
-       BUG_ON(!host->h_server);
+       WARN_ON_ONCE(!host->h_server);
        atomic_dec(&host->h_count);
 }
 
index e4fb3ba5a58a3d50eb11a0f9533ca58ae5150283..3c2cfc6836315c288e9a0a367d03f235235ebbee 100644 (file)
@@ -85,29 +85,38 @@ static struct rpc_clnt *nsm_create(struct net *net)
        return rpc_create(&args);
 }
 
+static struct rpc_clnt *nsm_client_set(struct lockd_net *ln,
+               struct rpc_clnt *clnt)
+{
+       spin_lock(&ln->nsm_clnt_lock);
+       if (ln->nsm_users == 0) {
+               if (clnt == NULL)
+                       goto out;
+               ln->nsm_clnt = clnt;
+       }
+       clnt = ln->nsm_clnt;
+       ln->nsm_users++;
+out:
+       spin_unlock(&ln->nsm_clnt_lock);
+       return clnt;
+}
+
 static struct rpc_clnt *nsm_client_get(struct net *net)
 {
-       static DEFINE_MUTEX(nsm_create_mutex);
-       struct rpc_clnt *clnt;
+       struct rpc_clnt *clnt, *new;
        struct lockd_net *ln = net_generic(net, lockd_net_id);
 
-       spin_lock(&ln->nsm_clnt_lock);
-       if (ln->nsm_users) {
-               ln->nsm_users++;
-               clnt = ln->nsm_clnt;
-               spin_unlock(&ln->nsm_clnt_lock);
+       clnt = nsm_client_set(ln, NULL);
+       if (clnt != NULL)
                goto out;
-       }
-       spin_unlock(&ln->nsm_clnt_lock);
 
-       mutex_lock(&nsm_create_mutex);
-       clnt = nsm_create(net);
-       if (!IS_ERR(clnt)) {
-               ln->nsm_clnt = clnt;
-               smp_wmb();
-               ln->nsm_users = 1;
-       }
-       mutex_unlock(&nsm_create_mutex);
+       clnt = new = nsm_create(net);
+       if (IS_ERR(clnt))
+               goto out;
+
+       clnt = nsm_client_set(ln, new);
+       if (clnt != new)
+               rpc_shutdown_client(new);
 out:
        return clnt;
 }
@@ -115,18 +124,16 @@ out:
 static void nsm_client_put(struct net *net)
 {
        struct lockd_net *ln = net_generic(net, lockd_net_id);
-       struct rpc_clnt *clnt = ln->nsm_clnt;
-       int shutdown = 0;
+       struct rpc_clnt *clnt = NULL;
 
        spin_lock(&ln->nsm_clnt_lock);
-       if (ln->nsm_users) {
-               if (--ln->nsm_users)
-                       ln->nsm_clnt = NULL;
-               shutdown = !ln->nsm_users;
+       ln->nsm_users--;
+       if (ln->nsm_users == 0) {
+               clnt = ln->nsm_clnt;
+               ln->nsm_clnt = NULL;
        }
        spin_unlock(&ln->nsm_clnt_lock);
-
-       if (shutdown)
+       if (clnt != NULL)
                rpc_shutdown_client(clnt);
 }
 
@@ -147,8 +154,6 @@ static int nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res,
                .rpc_resp       = res,
        };
 
-       BUG_ON(clnt == NULL);
-
        memset(res, 0, sizeof(*res));
 
        msg.rpc_proc = &clnt->cl_procinfo[proc];
@@ -459,7 +464,6 @@ static void encode_nsm_string(struct xdr_stream *xdr, const char *string)
        const u32 len = strlen(string);
        __be32 *p;
 
-       BUG_ON(len > SM_MAXSTRLEN);
        p = xdr_reserve_space(xdr, 4 + len);
        xdr_encode_opaque(p, string, len);
 }
index 3009a365e082e37764ea817d070165c3b828146b..21171f0c6477560d7a5f6deb3e336e6c98581f96 100644 (file)
@@ -68,7 +68,8 @@ nlmsvc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,
 
        /* Obtain file pointer. Not used by FREE_ALL call. */
        if (filp != NULL) {
-               if ((error = nlm_lookup_file(rqstp, &file, &lock->fh)) != 0)
+               error = cast_status(nlm_lookup_file(rqstp, &file, &lock->fh));
+               if (error != 0)
                        goto no_locks;
                *filp = file;
 
index 9c501449450dc9be6891e5d9c1a035ca31b5687b..427bb73e298f197d4cfc73b17baeffdd1c848c5d 100644 (file)
@@ -245,8 +245,8 @@ static int logfs_mtd_can_write_buf(struct super_block *sb, u64 ofs)
                goto out;
        if (memchr_inv(buf, 0xff, super->s_writesize))
                err = -EIO;
-       kfree(buf);
 out:
+       kfree(buf);
        return err;
 }
 
index dded2636811182497c5c78d24f51e81577d7aad5..862a2f16db64b7335453ef88ed7bea6e153cfa91 100644 (file)
@@ -118,7 +118,6 @@ int nfs_cache_register_sb(struct super_block *sb, struct cache_detail *cd)
        struct dentry *dir;
 
        dir = rpc_d_lookup_sb(sb, "cache");
-       BUG_ON(dir == NULL);
        ret = sunrpc_cache_register_pipefs(dir, cd->name, 0600, cd);
        dput(dir);
        return ret;
index 9a521fb3986955aab3f32e755bdef94e9c313aa2..5088b57b078a729d09ced36b3e491c01cba9cf4c 100644 (file)
@@ -241,7 +241,7 @@ static int nfs_callback_start_svc(int minorversion, struct rpc_xprt *xprt,
                svc_exit_thread(cb_info->rqst);
                cb_info->rqst = NULL;
                cb_info->task = NULL;
-               return PTR_ERR(cb_info->task);
+               return ret;
        }
        dprintk("nfs_callback_up: service started\n");
        return 0;
index 76b4a7a3e55931e0f9cc79d08c248048cbfaa961..0be08b964f387e3ee7a093214969b54aa506dd02 100644 (file)
@@ -216,7 +216,6 @@ static u32 initiate_bulk_draining(struct nfs_client *clp,
                        }
                        pnfs_get_layout_hdr(lo);
                        spin_unlock(&ino->i_lock);
-                       BUG_ON(!list_empty(&lo->plh_bulk_recall));
                        list_add(&lo->plh_bulk_recall, &recall_list);
                }
        }
index 8b39a42ac35ee5d8c081f205e631b6b2458b4be1..c285e0a117e4a577b7bc930c058c7db5faf6d99d 100644 (file)
@@ -277,7 +277,7 @@ void nfs_put_client(struct nfs_client *clp)
                nfs_cb_idr_remove_locked(clp);
                spin_unlock(&nn->nfs_client_lock);
 
-               BUG_ON(!list_empty(&clp->cl_superblocks));
+               WARN_ON_ONCE(!list_empty(&clp->cl_superblocks));
 
                clp->rpc_ops->free_client(clp);
        }
@@ -1061,10 +1061,6 @@ struct nfs_server *nfs_create_server(struct nfs_mount_info *mount_info,
        if (error < 0)
                goto error;
 
-       BUG_ON(!server->nfs_client);
-       BUG_ON(!server->nfs_client->rpc_ops);
-       BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops);
-
        /* Probe the root fh to retrieve its FSID */
        error = nfs_probe_fsinfo(server, mount_info->mntfh, fattr);
        if (error < 0)
index 9cc4a3fbf4b0d4ab3106b7584ba756776005e6f8..bc3968fa81e53c1164b9ebb93c7f122303731143 100644 (file)
@@ -193,19 +193,15 @@ static int nfs_idmap_init_keyring(void)
        if (!cred)
                return -ENOMEM;
 
-       keyring = key_alloc(&key_type_keyring, ".id_resolver", 0, 0, cred,
-                            (KEY_POS_ALL & ~KEY_POS_SETATTR) |
-                            KEY_USR_VIEW | KEY_USR_READ,
-                            KEY_ALLOC_NOT_IN_QUOTA);
+       keyring = keyring_alloc(".id_resolver", 0, 0, cred,
+                               (KEY_POS_ALL & ~KEY_POS_SETATTR) |
+                               KEY_USR_VIEW | KEY_USR_READ,
+                               KEY_ALLOC_NOT_IN_QUOTA, NULL);
        if (IS_ERR(keyring)) {
                ret = PTR_ERR(keyring);
                goto failed_put_cred;
        }
 
-       ret = key_instantiate_and_link(keyring, NULL, 0, NULL, NULL);
-       if (ret < 0)
-               goto failed_put_key;
-
        ret = register_key_type(&key_type_id_resolver);
        if (ret < 0)
                goto failed_put_key;
index 5c7325c5c5e66b23beacd6fb7485fda5a640dcd9..3967be22c7f85804fcc5dbcb2e7b14c4406af0af 100644 (file)
@@ -112,8 +112,8 @@ void nfs_clear_inode(struct inode *inode)
        /*
         * The following should never happen...
         */
-       BUG_ON(nfs_have_writebacks(inode));
-       BUG_ON(!list_empty(&NFS_I(inode)->open_files));
+       WARN_ON_ONCE(nfs_have_writebacks(inode));
+       WARN_ON_ONCE(!list_empty(&NFS_I(inode)->open_files));
        nfs_zap_acl_cache(inode);
        nfs_access_zap_cache(inode);
        nfs_fscache_release_inode_cookie(inode);
index 8e65c7f1f87c526707959c0e691e36532406d1fa..03262331571ed561ad0986128140144f56c93219 100644 (file)
@@ -169,6 +169,9 @@ int nfs_mount(struct nfs_mount_request *info)
                (info->hostname ? info->hostname : "server"),
                        info->dirpath);
 
+       if (strlen(info->dirpath) > MNTPATHLEN)
+               return -ENAMETOOLONG;
+
        if (info->noresvport)
                args.flags |= RPC_CLNT_CREATE_NONPRIVPORT;
 
@@ -242,6 +245,9 @@ void nfs_umount(const struct nfs_mount_request *info)
        struct rpc_clnt *clnt;
        int status;
 
+       if (strlen(info->dirpath) > MNTPATHLEN)
+               return;
+
        if (info->noresvport)
                args.flags |= RPC_CLNT_CREATE_NONPRIVPORT;
 
@@ -283,7 +289,6 @@ static void encode_mntdirpath(struct xdr_stream *xdr, const char *pathname)
        const u32 pathname_len = strlen(pathname);
        __be32 *p;
 
-       BUG_ON(pathname_len > MNTPATHLEN);
        p = xdr_reserve_space(xdr, 4 + pathname_len);
        xdr_encode_opaque(p, pathname, pathname_len);
 }
index d04f0df7be553db3aa89ce5637ff3c8ef3044d07..06b9df49f7f7773fa62ad1b7215b2ffcdfee852a 100644 (file)
@@ -195,7 +195,6 @@ static void encode_fhandle(struct xdr_stream *xdr, const struct nfs_fh *fh)
 {
        __be32 *p;
 
-       BUG_ON(fh->size != NFS2_FHSIZE);
        p = xdr_reserve_space(xdr, NFS2_FHSIZE);
        memcpy(p, fh->data, NFS2_FHSIZE);
 }
@@ -388,7 +387,7 @@ static void encode_filename(struct xdr_stream *xdr,
 {
        __be32 *p;
 
-       BUG_ON(length > NFS2_MAXNAMLEN);
+       WARN_ON_ONCE(length > NFS2_MAXNAMLEN);
        p = xdr_reserve_space(xdr, 4 + length);
        xdr_encode_opaque(p, name, length);
 }
@@ -428,7 +427,6 @@ static void encode_path(struct xdr_stream *xdr, struct page **pages, u32 length)
 {
        __be32 *p;
 
-       BUG_ON(length > NFS2_MAXPATHLEN);
        p = xdr_reserve_space(xdr, 4);
        *p = cpu_to_be32(length);
        xdr_write_pages(xdr, pages, 0, length);
index 6cbe89400dfcc134b9af58d6ad16ecf42bab911a..bffc32406fbf81b764d43a298e12489b5fa37faf 100644 (file)
@@ -198,7 +198,7 @@ static void encode_filename3(struct xdr_stream *xdr,
 {
        __be32 *p;
 
-       BUG_ON(length > NFS3_MAXNAMLEN);
+       WARN_ON_ONCE(length > NFS3_MAXNAMLEN);
        p = xdr_reserve_space(xdr, 4 + length);
        xdr_encode_opaque(p, name, length);
 }
@@ -238,7 +238,6 @@ out_overflow:
 static void encode_nfspath3(struct xdr_stream *xdr, struct page **pages,
                            const u32 length)
 {
-       BUG_ON(length > NFS3_MAXPATHLEN);
        encode_uint32(xdr, length);
        xdr_write_pages(xdr, pages, 0, length);
 }
@@ -388,7 +387,6 @@ out_overflow:
  */
 static void encode_ftype3(struct xdr_stream *xdr, const u32 type)
 {
-       BUG_ON(type > NF3FIFO);
        encode_uint32(xdr, type);
 }
 
@@ -443,7 +441,7 @@ static void encode_nfs_fh3(struct xdr_stream *xdr, const struct nfs_fh *fh)
 {
        __be32 *p;
 
-       BUG_ON(fh->size > NFS3_FHSIZE);
+       WARN_ON_ONCE(fh->size > NFS3_FHSIZE);
        p = xdr_reserve_space(xdr, 4 + fh->size);
        xdr_encode_opaque(p, fh->data, fh->size);
 }
@@ -1339,6 +1337,7 @@ static void nfs3_xdr_enc_setacl3args(struct rpc_rqst *req,
        error = nfsacl_encode(xdr->buf, base, args->inode,
                            (args->mask & NFS_ACL) ?
                            args->acl_access : NULL, 1, 0);
+       /* FIXME: this is just broken */
        BUG_ON(error < 0);
        error = nfsacl_encode(xdr->buf, base + error, args->inode,
                            (args->mask & NFS_DFACL) ?
index a525fdefccdeb475edb9468c1467e6196db20246..53112a1147c82e891baa8e2556134e8a11ae0bf8 100644 (file)
@@ -280,6 +280,7 @@ static inline int nfs4_setup_sequence(const struct nfs_server *server,
                struct nfs4_sequence_args *args, struct nfs4_sequence_res *res,
                struct rpc_task *task)
 {
+       rpc_call_start(task);
        return 0;
 }
 
index 6bacfde1319a76945a9ab9634e453f8a61def8ce..72717e67b34e72ba1941743245fa31b243fa619a 100644 (file)
@@ -713,10 +713,6 @@ static int nfs4_server_common_setup(struct nfs_server *server,
        struct nfs_fattr *fattr;
        int error;
 
-       BUG_ON(!server->nfs_client);
-       BUG_ON(!server->nfs_client->rpc_ops);
-       BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops);
-
        /* data servers support only a subset of NFSv4.1 */
        if (is_ds_only_client(server->nfs_client))
                return -EPROTONOSUPPORT;
index afddd6639afb1bd5242e95c5b659fa2b86174181..e7699308364acf6f84fcf62e5f815ed2c74c2b5c 100644 (file)
@@ -20,7 +20,6 @@ nfs4_file_open(struct inode *inode, struct file *filp)
        struct iattr attr;
        int err;
 
-       BUG_ON(inode != dentry->d_inode);
        /*
         * If no cached dentry exists or if it's negative, NFSv4 handled the
         * opens in ->lookup() or ->create().
index 52d8472120663de91855690fa0996cdf03e4a8a4..63d5d42187fb876763d8231c67af48b06da9423d 100644 (file)
@@ -122,12 +122,21 @@ static void filelayout_reset_read(struct nfs_read_data *data)
        }
 }
 
+static void filelayout_fenceme(struct inode *inode, struct pnfs_layout_hdr *lo)
+{
+       if (!test_and_clear_bit(NFS_LAYOUT_RETURN, &lo->plh_flags))
+               return;
+       clear_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(inode)->flags);
+       pnfs_return_layout(inode);
+}
+
 static int filelayout_async_handle_error(struct rpc_task *task,
                                         struct nfs4_state *state,
                                         struct nfs_client *clp,
                                         struct pnfs_layout_segment *lseg)
 {
-       struct inode *inode = lseg->pls_layout->plh_inode;
+       struct pnfs_layout_hdr *lo = lseg->pls_layout;
+       struct inode *inode = lo->plh_inode;
        struct nfs_server *mds_server = NFS_SERVER(inode);
        struct nfs4_deviceid_node *devid = FILELAYOUT_DEVID_NODE(lseg);
        struct nfs_client *mds_client = mds_server->nfs_client;
@@ -204,10 +213,8 @@ static int filelayout_async_handle_error(struct rpc_task *task,
                dprintk("%s DS connection error %d\n", __func__,
                        task->tk_status);
                nfs4_mark_deviceid_unavailable(devid);
-               clear_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(inode)->flags);
-               _pnfs_return_layout(inode);
+               set_bit(NFS_LAYOUT_RETURN, &lo->plh_flags);
                rpc_wake_up(&tbl->slot_tbl_waitq);
-               nfs4_ds_disconnect(clp);
                /* fall through */
        default:
 reset:
@@ -299,12 +306,8 @@ static void filelayout_read_prepare(struct rpc_task *task, void *data)
        }
        rdata->read_done_cb = filelayout_read_done_cb;
 
-       if (nfs41_setup_sequence(rdata->ds_clp->cl_session,
-                               &rdata->args.seq_args, &rdata->res.seq_res,
-                               task))
-               return;
-
-       rpc_call_start(task);
+       nfs41_setup_sequence(rdata->ds_clp->cl_session, &rdata->args.seq_args,
+                       &rdata->res.seq_res, task);
 }
 
 static void filelayout_read_call_done(struct rpc_task *task, void *data)
@@ -331,7 +334,9 @@ static void filelayout_read_count_stats(struct rpc_task *task, void *data)
 static void filelayout_read_release(void *data)
 {
        struct nfs_read_data *rdata = data;
+       struct pnfs_layout_hdr *lo = rdata->header->lseg->pls_layout;
 
+       filelayout_fenceme(lo->plh_inode, lo);
        nfs_put_client(rdata->ds_clp);
        rdata->header->mds_ops->rpc_release(data);
 }
@@ -399,12 +404,8 @@ static void filelayout_write_prepare(struct rpc_task *task, void *data)
                rpc_exit(task, 0);
                return;
        }
-       if (nfs41_setup_sequence(wdata->ds_clp->cl_session,
-                               &wdata->args.seq_args, &wdata->res.seq_res,
-                               task))
-               return;
-
-       rpc_call_start(task);
+       nfs41_setup_sequence(wdata->ds_clp->cl_session, &wdata->args.seq_args,
+                       &wdata->res.seq_res, task);
 }
 
 static void filelayout_write_call_done(struct rpc_task *task, void *data)
@@ -429,7 +430,9 @@ static void filelayout_write_count_stats(struct rpc_task *task, void *data)
 static void filelayout_write_release(void *data)
 {
        struct nfs_write_data *wdata = data;
+       struct pnfs_layout_hdr *lo = wdata->header->lseg->pls_layout;
 
+       filelayout_fenceme(lo->plh_inode, lo);
        nfs_put_client(wdata->ds_clp);
        wdata->header->mds_ops->rpc_release(data);
 }
@@ -438,12 +441,8 @@ static void filelayout_commit_prepare(struct rpc_task *task, void *data)
 {
        struct nfs_commit_data *wdata = data;
 
-       if (nfs41_setup_sequence(wdata->ds_clp->cl_session,
-                               &wdata->args.seq_args, &wdata->res.seq_res,
-                               task))
-               return;
-
-       rpc_call_start(task);
+       nfs41_setup_sequence(wdata->ds_clp->cl_session, &wdata->args.seq_args,
+                       &wdata->res.seq_res, task);
 }
 
 static void filelayout_write_commit_done(struct rpc_task *task, void *data)
@@ -501,7 +500,6 @@ filelayout_read_pagelist(struct nfs_read_data *data)
        loff_t offset = data->args.offset;
        u32 j, idx;
        struct nfs_fh *fh;
-       int status;
 
        dprintk("--> %s ino %lu pgbase %u req %Zu@%llu\n",
                __func__, hdr->inode->i_ino,
@@ -527,9 +525,8 @@ filelayout_read_pagelist(struct nfs_read_data *data)
        data->mds_offset = offset;
 
        /* Perform an asynchronous read to ds */
-       status = nfs_initiate_read(ds->ds_clp->cl_rpcclient, data,
+       nfs_initiate_read(ds->ds_clp->cl_rpcclient, data,
                                  &filelayout_read_call_ops, RPC_TASK_SOFTCONN);
-       BUG_ON(status != 0);
        return PNFS_ATTEMPTED;
 }
 
@@ -543,7 +540,6 @@ filelayout_write_pagelist(struct nfs_write_data *data, int sync)
        loff_t offset = data->args.offset;
        u32 j, idx;
        struct nfs_fh *fh;
-       int status;
 
        /* Retrieve the correct rpc_client for the byte range */
        j = nfs4_fl_calc_j_index(lseg, offset);
@@ -568,10 +564,9 @@ filelayout_write_pagelist(struct nfs_write_data *data, int sync)
        data->args.offset = filelayout_get_dserver_offset(lseg, offset);
 
        /* Perform an asynchronous write */
-       status = nfs_initiate_write(ds->ds_clp->cl_rpcclient, data,
+       nfs_initiate_write(ds->ds_clp->cl_rpcclient, data,
                                    &filelayout_write_call_ops, sync,
                                    RPC_TASK_SOFTCONN);
-       BUG_ON(status != 0);
        return PNFS_ATTEMPTED;
 }
 
@@ -739,7 +734,7 @@ filelayout_decode_layout(struct pnfs_layout_hdr *flo,
                goto out_err;
 
        if (fl->num_fh > 0) {
-               fl->fh_array = kzalloc(fl->num_fh * sizeof(struct nfs_fh *),
+               fl->fh_array = kcalloc(fl->num_fh, sizeof(fl->fh_array[0]),
                                       gfp_flags);
                if (!fl->fh_array)
                        goto out_err;
@@ -898,7 +893,7 @@ static void
 filelayout_pg_init_read(struct nfs_pageio_descriptor *pgio,
                        struct nfs_page *req)
 {
-       BUG_ON(pgio->pg_lseg != NULL);
+       WARN_ON_ONCE(pgio->pg_lseg != NULL);
 
        if (req->wb_offset != req->wb_pgbase) {
                /*
@@ -928,7 +923,7 @@ filelayout_pg_init_write(struct nfs_pageio_descriptor *pgio,
        struct nfs_commit_info cinfo;
        int status;
 
-       BUG_ON(pgio->pg_lseg != NULL);
+       WARN_ON_ONCE(pgio->pg_lseg != NULL);
 
        if (req->wb_offset != req->wb_pgbase)
                goto out_mds;
@@ -1176,7 +1171,6 @@ static void filelayout_recover_commit_reqs(struct list_head *dst,
         */
        for (i = 0, b = cinfo->ds->buckets; i < cinfo->ds->nbuckets; i++, b++) {
                if (transfer_commit_list(&b->written, dst, cinfo, 0)) {
-                       BUG_ON(!list_empty(&b->written));
                        pnfs_put_lseg(b->wlseg);
                        b->wlseg = NULL;
                }
index dca47d78671026810c67b139763cd1b27548d42d..8c07241fe52b0ac86c7d1ef241923f20f0d56a1e 100644 (file)
@@ -149,6 +149,5 @@ extern void nfs4_fl_put_deviceid(struct nfs4_file_layout_dsaddr *dsaddr);
 extern void nfs4_fl_free_deviceid(struct nfs4_file_layout_dsaddr *dsaddr);
 struct nfs4_file_layout_dsaddr *
 filelayout_get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id, gfp_t gfp_flags);
-void nfs4_ds_disconnect(struct nfs_client *clp);
 
 #endif /* FS_NFS_NFS4FILELAYOUT_H */
index 3336d5eaf879adc07a2e95f64b512835935763a6..93e2530d7098708833ec336127f3e64f3a4662a2 100644 (file)
@@ -148,28 +148,6 @@ _data_server_lookup_locked(const struct list_head *dsaddrs)
        return NULL;
 }
 
-/*
- * Lookup DS by nfs_client pointer. Zero data server client pointer
- */
-void nfs4_ds_disconnect(struct nfs_client *clp)
-{
-       struct nfs4_pnfs_ds *ds;
-       struct nfs_client *found = NULL;
-
-       dprintk("%s clp %p\n", __func__, clp);
-       spin_lock(&nfs4_ds_cache_lock);
-       list_for_each_entry(ds, &nfs4_data_server_cache, ds_node)
-               if (ds->ds_clp && ds->ds_clp == clp) {
-                       found = ds->ds_clp;
-                       ds->ds_clp = NULL;
-               }
-       spin_unlock(&nfs4_ds_cache_lock);
-       if (found) {
-               set_bit(NFS_CS_STOP_RENEW, &clp->cl_res_state);
-               nfs_put_client(clp);
-       }
-}
-
 /*
  * Create an rpc connection to the nfs4_pnfs_ds data server
  * Currently only supports IPv4 and IPv6 addresses
@@ -184,8 +162,6 @@ nfs4_ds_connect(struct nfs_server *mds_srv, struct nfs4_pnfs_ds *ds)
        dprintk("--> %s DS %s au_flavor %d\n", __func__, ds->ds_remotestr,
                mds_srv->nfs_client->cl_rpcclient->cl_auth->au_flavor);
 
-       BUG_ON(list_empty(&ds->ds_addrs));
-
        list_for_each_entry(da, &ds->ds_addrs, da_node) {
                dprintk("%s: DS %s: trying address %s\n",
                        __func__, ds->ds_remotestr, da->da_remotestr);
index 6a83780e0ce6b9a9888ce51dfd303ca454b54ea8..549462e5b9b0633239a1b2766ce17433446874dc 100644 (file)
@@ -5,6 +5,7 @@
 
 #include <linux/nfs_fs.h>
 #include "nfs4_fs.h"
+#include "internal.h"
 
 #define NFSDBG_FACILITY                NFSDBG_CLIENT
 
index 68b21d81b7acfa79bef010023195c1f45023c82b..8b04d14617f565387369a686956a6c18a76164ec 100644 (file)
@@ -206,7 +206,6 @@ static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dent
 {
        __be32 *start, *p;
 
-       BUG_ON(readdir->count < 80);
        if (cookie > 2) {
                readdir->cookie = cookie;
                memcpy(&readdir->verifier, verifier, sizeof(readdir->verifier));
@@ -416,7 +415,6 @@ static void renew_lease(const struct nfs_server *server, unsigned long timestamp
 static void
 nfs4_free_slot(struct nfs4_slot_table *tbl, u32 slotid)
 {
-       BUG_ON(slotid >= NFS4_MAX_SLOT_TABLE);
        /* clear used bit in bitmap */
        __clear_bit(slotid, tbl->used_slots);
 
@@ -607,7 +605,7 @@ int nfs41_setup_sequence(struct nfs4_session *session,
        dprintk("--> %s\n", __func__);
        /* slot already allocated? */
        if (res->sr_slot != NULL)
-               return 0;
+               goto out_success;
 
        tbl = &session->fc_slot_table;
 
@@ -654,6 +652,8 @@ int nfs41_setup_sequence(struct nfs4_session *session,
         * set to 1 if an rpc level failure occurs.
         */
        res->sr_status = 1;
+out_success:
+       rpc_call_start(task);
        return 0;
 }
 EXPORT_SYMBOL_GPL(nfs41_setup_sequence);
@@ -666,8 +666,10 @@ int nfs4_setup_sequence(const struct nfs_server *server,
        struct nfs4_session *session = nfs4_get_session(server);
        int ret = 0;
 
-       if (session == NULL)
+       if (session == NULL) {
+               rpc_call_start(task);
                goto out;
+       }
 
        dprintk("--> %s clp %p session %p sr_slot %td\n",
                __func__, session->clp, session, res->sr_slot ?
@@ -688,13 +690,11 @@ struct nfs41_call_sync_data {
 static void nfs41_call_sync_prepare(struct rpc_task *task, void *calldata)
 {
        struct nfs41_call_sync_data *data = calldata;
+       struct nfs4_session *session = nfs4_get_session(data->seq_server);
 
        dprintk("--> %s data->seq_server %p\n", __func__, data->seq_server);
 
-       if (nfs4_setup_sequence(data->seq_server, data->seq_args,
-                               data->seq_res, task))
-               return;
-       rpc_call_start(task);
+       nfs41_setup_sequence(session, data->seq_args, data->seq_res, task);
 }
 
 static void nfs41_call_priv_sync_prepare(struct rpc_task *task, void *calldata)
@@ -1570,11 +1570,8 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata)
                nfs_copy_fh(&data->o_res.fh, data->o_arg.fh);
        }
        data->timestamp = jiffies;
-       if (nfs4_setup_sequence(data->o_arg.server,
-                               &data->o_arg.seq_args,
-                               &data->o_res.seq_res, task))
-               return;
-       rpc_call_start(task);
+       nfs4_setup_sequence(data->o_arg.server, &data->o_arg.seq_args,
+                       &data->o_res.seq_res, task);
        return;
 unlock_no_action:
        rcu_read_unlock();
@@ -2293,12 +2290,8 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
 
        nfs_fattr_init(calldata->res.fattr);
        calldata->timestamp = jiffies;
-       if (nfs4_setup_sequence(NFS_SERVER(inode),
-                               &calldata->arg.seq_args,
-                               &calldata->res.seq_res,
-                               task))
-               goto out;
-       rpc_call_start(task);
+       nfs4_setup_sequence(NFS_SERVER(inode), &calldata->arg.seq_args,
+                       &calldata->res.seq_res, task);
 out:
        dprintk("%s: done!\n", __func__);
 }
@@ -2531,7 +2524,8 @@ static int nfs4_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle,
        rpc_authflavor_t flav_array[NFS_MAX_SECFLAVORS];
 
        len = rpcauth_list_flavors(flav_array, ARRAY_SIZE(flav_array));
-       BUG_ON(len < 0);
+       if (len < 0)
+               return len;
 
        for (i = 0; i < len; i++) {
                /* AUTH_UNIX is the default flavor if none was specified,
@@ -3036,12 +3030,8 @@ static void nfs4_proc_unlink_setup(struct rpc_message *msg, struct inode *dir)
 
 static void nfs4_proc_unlink_rpc_prepare(struct rpc_task *task, struct nfs_unlinkdata *data)
 {
-       if (nfs4_setup_sequence(NFS_SERVER(data->dir),
-                               &data->args.seq_args,
-                               &data->res.seq_res,
-                               task))
-               return;
-       rpc_call_start(task);
+       nfs4_setup_sequence(NFS_SERVER(data->dir), &data->args.seq_args,
+                       &data->res.seq_res, task);
 }
 
 static int nfs4_proc_unlink_done(struct rpc_task *task, struct inode *dir)
@@ -3069,12 +3059,8 @@ static void nfs4_proc_rename_setup(struct rpc_message *msg, struct inode *dir)
 
 static void nfs4_proc_rename_rpc_prepare(struct rpc_task *task, struct nfs_renamedata *data)
 {
-       if (nfs4_setup_sequence(NFS_SERVER(data->old_dir),
-                               &data->args.seq_args,
-                               &data->res.seq_res,
-                               task))
-               return;
-       rpc_call_start(task);
+       nfs4_setup_sequence(NFS_SERVER(data->old_dir), &data->args.seq_args,
+                       &data->res.seq_res, task);
 }
 
 static int nfs4_proc_rename_done(struct rpc_task *task, struct inode *old_dir,
@@ -3360,9 +3346,6 @@ static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry,
        int mode = sattr->ia_mode;
        int status = -ENOMEM;
 
-       BUG_ON(!(sattr->ia_valid & ATTR_MODE));
-       BUG_ON(!S_ISFIFO(mode) && !S_ISBLK(mode) && !S_ISCHR(mode) && !S_ISSOCK(mode));
-
        data = nfs4_alloc_createdata(dir, &dentry->d_name, sattr, NF4SOCK);
        if (data == NULL)
                goto out;
@@ -3378,10 +3361,13 @@ static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry,
                data->arg.ftype = NF4CHR;
                data->arg.u.device.specdata1 = MAJOR(rdev);
                data->arg.u.device.specdata2 = MINOR(rdev);
+       } else if (!S_ISSOCK(mode)) {
+               status = -EINVAL;
+               goto out_free;
        }
        
        status = nfs4_do_create(dir, dentry, data);
-
+out_free:
        nfs4_free_createdata(data);
 out:
        return status;
@@ -3563,12 +3549,8 @@ static void nfs4_proc_read_setup(struct nfs_read_data *data, struct rpc_message
 
 static void nfs4_proc_read_rpc_prepare(struct rpc_task *task, struct nfs_read_data *data)
 {
-       if (nfs4_setup_sequence(NFS_SERVER(data->header->inode),
-                               &data->args.seq_args,
-                               &data->res.seq_res,
-                               task))
-               return;
-       rpc_call_start(task);
+       nfs4_setup_sequence(NFS_SERVER(data->header->inode),
+                       &data->args.seq_args, &data->res.seq_res, task);
 }
 
 static int nfs4_write_done_cb(struct rpc_task *task, struct nfs_write_data *data)
@@ -3629,22 +3611,14 @@ static void nfs4_proc_write_setup(struct nfs_write_data *data, struct rpc_messag
 
 static void nfs4_proc_write_rpc_prepare(struct rpc_task *task, struct nfs_write_data *data)
 {
-       if (nfs4_setup_sequence(NFS_SERVER(data->header->inode),
-                               &data->args.seq_args,
-                               &data->res.seq_res,
-                               task))
-               return;
-       rpc_call_start(task);
+       nfs4_setup_sequence(NFS_SERVER(data->header->inode),
+                       &data->args.seq_args, &data->res.seq_res, task);
 }
 
 static void nfs4_proc_commit_rpc_prepare(struct rpc_task *task, struct nfs_commit_data *data)
 {
-       if (nfs4_setup_sequence(NFS_SERVER(data->inode),
-                               &data->args.seq_args,
-                               &data->res.seq_res,
-                               task))
-               return;
-       rpc_call_start(task);
+       nfs4_setup_sequence(NFS_SERVER(data->inode), &data->args.seq_args,
+                       &data->res.seq_res, task);
 }
 
 static int nfs4_commit_done_cb(struct rpc_task *task, struct nfs_commit_data *data)
@@ -4291,11 +4265,8 @@ static void nfs4_delegreturn_prepare(struct rpc_task *task, void *data)
 
        d_data = (struct nfs4_delegreturndata *)data;
 
-       if (nfs4_setup_sequence(d_data->res.server,
-                               &d_data->args.seq_args,
-                               &d_data->res.seq_res, task))
-               return;
-       rpc_call_start(task);
+       nfs4_setup_sequence(d_data->res.server, &d_data->args.seq_args,
+                       &d_data->res.seq_res, task);
 }
 #endif /* CONFIG_NFS_V4_1 */
 
@@ -4543,11 +4514,8 @@ static void nfs4_locku_prepare(struct rpc_task *task, void *data)
                return;
        }
        calldata->timestamp = jiffies;
-       if (nfs4_setup_sequence(calldata->server,
-                               &calldata->arg.seq_args,
-                               &calldata->res.seq_res, task))
-               return;
-       rpc_call_start(task);
+       nfs4_setup_sequence(calldata->server, &calldata->arg.seq_args,
+                       &calldata->res.seq_res, task);
 }
 
 static const struct rpc_call_ops nfs4_locku_ops = {
@@ -4699,11 +4667,8 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata)
        } else
                data->arg.new_lock_owner = 0;
        data->timestamp = jiffies;
-       if (nfs4_setup_sequence(data->server,
-                               &data->arg.seq_args,
-                               &data->res.seq_res, task))
-               return;
-       rpc_call_start(task);
+       nfs4_setup_sequence(data->server, &data->arg.seq_args,
+                       &data->res.seq_res, task);
        dprintk("%s: done!, ret = %d\n", __func__, data->rpc_status);
 }
 
@@ -5347,7 +5312,6 @@ int nfs4_proc_bind_conn_to_session(struct nfs_client *clp, struct rpc_cred *cred
        };
 
        dprintk("--> %s\n", __func__);
-       BUG_ON(clp == NULL);
 
        res.session = kzalloc(sizeof(struct nfs4_session), GFP_NOFS);
        if (unlikely(res.session == NULL)) {
@@ -5559,7 +5523,6 @@ struct nfs4_get_lease_time_data {
 static void nfs4_get_lease_time_prepare(struct rpc_task *task,
                                        void *calldata)
 {
-       int ret;
        struct nfs4_get_lease_time_data *data =
                        (struct nfs4_get_lease_time_data *)calldata;
 
@@ -5567,12 +5530,8 @@ static void nfs4_get_lease_time_prepare(struct rpc_task *task,
        rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED);
        /* just setup sequence, do not trigger session recovery
           since we're invoked within one */
-       ret = nfs41_setup_sequence(data->clp->cl_session,
-                                  &data->args->la_seq_args,
-                                  &data->res->lr_seq_res, task);
-
-       BUG_ON(ret == -EAGAIN);
-       rpc_call_start(task);
+       nfs41_setup_sequence(data->clp->cl_session, &data->args->la_seq_args,
+                       &data->res->lr_seq_res, task);
        dprintk("<-- %s\n", __func__);
 }
 
@@ -6123,9 +6082,7 @@ static void nfs41_sequence_prepare(struct rpc_task *task, void *data)
        args = task->tk_msg.rpc_argp;
        res = task->tk_msg.rpc_resp;
 
-       if (nfs41_setup_sequence(clp->cl_session, args, res, task))
-               return;
-       rpc_call_start(task);
+       nfs41_setup_sequence(clp->cl_session, args, res, task);
 }
 
 static const struct rpc_call_ops nfs41_sequence_ops = {
@@ -6215,12 +6172,9 @@ static void nfs4_reclaim_complete_prepare(struct rpc_task *task, void *data)
        struct nfs4_reclaim_complete_data *calldata = data;
 
        rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED);
-       if (nfs41_setup_sequence(calldata->clp->cl_session,
-                               &calldata->arg.seq_args,
-                               &calldata->res.seq_res, task))
-               return;
-
-       rpc_call_start(task);
+       nfs41_setup_sequence(calldata->clp->cl_session,
+                       &calldata->arg.seq_args, &calldata->res.seq_res,
+                       task);
 }
 
 static int nfs41_reclaim_complete_handle_errors(struct rpc_task *task, struct nfs_client *clp)
@@ -6320,6 +6274,7 @@ nfs4_layoutget_prepare(struct rpc_task *task, void *calldata)
 {
        struct nfs4_layoutget *lgp = calldata;
        struct nfs_server *server = NFS_SERVER(lgp->args.inode);
+       struct nfs4_session *session = nfs4_get_session(server);
 
        dprintk("--> %s\n", __func__);
        /* Note the is a race here, where a CB_LAYOUTRECALL can come in
@@ -6327,16 +6282,14 @@ nfs4_layoutget_prepare(struct rpc_task *task, void *calldata)
         * However, that is not so catastrophic, and there seems
         * to be no way to prevent it completely.
         */
-       if (nfs4_setup_sequence(server, &lgp->args.seq_args,
+       if (nfs41_setup_sequence(session, &lgp->args.seq_args,
                                &lgp->res.seq_res, task))
                return;
        if (pnfs_choose_layoutget_stateid(&lgp->args.stateid,
                                          NFS_I(lgp->args.inode)->layout,
                                          lgp->args.ctx->state)) {
                rpc_exit(task, NFS4_OK);
-               return;
        }
-       rpc_call_start(task);
 }
 
 static void nfs4_layoutget_done(struct rpc_task *task, void *calldata)
@@ -6349,7 +6302,7 @@ static void nfs4_layoutget_done(struct rpc_task *task, void *calldata)
 
        dprintk("--> %s\n", __func__);
 
-       if (!nfs4_sequence_done(task, &lgp->res.seq_res))
+       if (!nfs41_sequence_done(task, &lgp->res.seq_res))
                goto out;
 
        switch (task->tk_status) {
@@ -6500,10 +6453,8 @@ nfs4_layoutreturn_prepare(struct rpc_task *task, void *calldata)
        struct nfs4_layoutreturn *lrp = calldata;
 
        dprintk("--> %s\n", __func__);
-       if (nfs41_setup_sequence(lrp->clp->cl_session, &lrp->args.seq_args,
-                               &lrp->res.seq_res, task))
-               return;
-       rpc_call_start(task);
+       nfs41_setup_sequence(lrp->clp->cl_session, &lrp->args.seq_args,
+                       &lrp->res.seq_res, task);
 }
 
 static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata)
@@ -6513,7 +6464,7 @@ static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata)
 
        dprintk("--> %s\n", __func__);
 
-       if (!nfs4_sequence_done(task, &lrp->res.seq_res))
+       if (!nfs41_sequence_done(task, &lrp->res.seq_res))
                return;
 
        server = NFS_SERVER(lrp->args.inode);
@@ -6662,11 +6613,10 @@ static void nfs4_layoutcommit_prepare(struct rpc_task *task, void *calldata)
 {
        struct nfs4_layoutcommit_data *data = calldata;
        struct nfs_server *server = NFS_SERVER(data->args.inode);
+       struct nfs4_session *session = nfs4_get_session(server);
 
-       if (nfs4_setup_sequence(server, &data->args.seq_args,
-                               &data->res.seq_res, task))
-               return;
-       rpc_call_start(task);
+       nfs41_setup_sequence(session, &data->args.seq_args,
+                       &data->res.seq_res, task);
 }
 
 static void
@@ -6675,7 +6625,7 @@ nfs4_layoutcommit_done(struct rpc_task *task, void *calldata)
        struct nfs4_layoutcommit_data *data = calldata;
        struct nfs_server *server = NFS_SERVER(data->args.inode);
 
-       if (!nfs4_sequence_done(task, &data->res.seq_res))
+       if (!nfs41_sequence_done(task, &data->res.seq_res))
                return;
 
        switch (task->tk_status) { /* Just ignore these failures */
index c351e6b398388f7c1b4b09a6240d4ad6c2559295..e0a28dffd29dc20ee472fa634a4165208873c8aa 100644 (file)
@@ -1086,7 +1086,6 @@ void nfs_free_seqid(struct nfs_seqid *seqid)
  */
 static void nfs_increment_seqid(int status, struct nfs_seqid *seqid)
 {
-       BUG_ON(list_first_entry(&seqid->sequence->list, struct nfs_seqid, list) != seqid);
        switch (status) {
                case 0:
                        break;
index 40836ee5dc3a87849b9dc2fc1f1946f4acbe45b6..672d9b0ef2c58e86ad331636377667ea7296a397 100644 (file)
@@ -936,7 +936,7 @@ static void encode_compound_hdr(struct xdr_stream *xdr,
         * but this is not required as a MUST for the server to do so. */
        hdr->replen = RPC_REPHDRSIZE + auth->au_rslack + 3 + hdr->taglen;
 
-       BUG_ON(hdr->taglen > NFS4_MAXTAGLEN);
+       WARN_ON_ONCE(hdr->taglen > NFS4_MAXTAGLEN);
        encode_string(xdr, hdr->taglen, hdr->tag);
        p = reserve_space(xdr, 8);
        *p++ = cpu_to_be32(hdr->minorversion);
@@ -955,7 +955,7 @@ static void encode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 op,
 
 static void encode_nops(struct compound_hdr *hdr)
 {
-       BUG_ON(hdr->nops > NFS4_MAX_OPS);
+       WARN_ON_ONCE(hdr->nops > NFS4_MAX_OPS);
        *hdr->nops_p = htonl(hdr->nops);
 }
 
@@ -1403,7 +1403,6 @@ static void encode_opentype(struct xdr_stream *xdr, const struct nfs_openargs *a
                *p = cpu_to_be32(NFS4_OPEN_NOCREATE);
                break;
        default:
-               BUG_ON(arg->claim != NFS4_OPEN_CLAIM_NULL);
                *p = cpu_to_be32(NFS4_OPEN_CREATE);
                encode_createmode(xdr, arg);
        }
@@ -1621,7 +1620,6 @@ encode_setacl(struct xdr_stream *xdr, struct nfs_setaclargs *arg, struct compoun
        p = reserve_space(xdr, 2*4);
        *p++ = cpu_to_be32(1);
        *p = cpu_to_be32(FATTR4_WORD0_ACL);
-       BUG_ON(arg->acl_len % 4);
        p = reserve_space(xdr, 4);
        *p = cpu_to_be32(arg->acl_len);
        xdr_write_pages(xdr, arg->acl_pages, arg->acl_pgbase, arg->acl_len);
index be731e6b7b9cc1781a0a1776f49f7e5aa8219a89..c6f990656f8905ed4911b471f7334e1a1a40582e 100644 (file)
@@ -369,7 +369,7 @@ void objio_free_result(struct objlayout_io_res *oir)
        kfree(objios);
 }
 
-enum pnfs_osd_errno osd_pri_2_pnfs_err(enum osd_err_priority oep)
+static enum pnfs_osd_errno osd_pri_2_pnfs_err(enum osd_err_priority oep)
 {
        switch (oep) {
        case OSD_ERR_PRI_NO_ERROR:
@@ -574,7 +574,7 @@ static bool objio_pg_test(struct nfs_pageio_descriptor *pgio,
                        (unsigned long)pgio->pg_layout_private;
 }
 
-void objio_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *req)
+static void objio_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *req)
 {
        pnfs_generic_pg_init_read(pgio, req);
        if (unlikely(pgio->pg_lseg == NULL))
@@ -604,7 +604,7 @@ static bool aligned_on_raid_stripe(u64 offset, struct ore_layout *layout,
        return false;
 }
 
-void objio_init_write(struct nfs_pageio_descriptor *pgio, struct nfs_page *req)
+static void objio_init_write(struct nfs_pageio_descriptor *pgio, struct nfs_page *req)
 {
        unsigned long stripe_end = 0;
        u64 wb_size;
index 8746135453011dc70d30ebbd5b70e2b813f7b15d..a9ebd817278b7beb301c222cb3e7abd1c183c3b4 100644 (file)
@@ -148,17 +148,6 @@ end_offset(u64 start, u64 len)
        return end >= start ? end : NFS4_MAX_UINT64;
 }
 
-/* last octet in a range */
-static inline u64
-last_byte_offset(u64 start, u64 len)
-{
-       u64 end;
-
-       BUG_ON(!len);
-       end = start + len;
-       return end > start ? end - 1 : NFS4_MAX_UINT64;
-}
-
 static void _fix_verify_io_params(struct pnfs_layout_segment *lseg,
                           struct page ***p_pages, unsigned *p_pgbase,
                           u64 offset, unsigned long count)
index fe624c91bd006ef11f839f61cab54f833286edfa..778c7faad498e20e1885d7709635b1a149aa0faf 100644 (file)
@@ -369,17 +369,6 @@ end_offset(u64 start, u64 len)
        return end >= start ? end : NFS4_MAX_UINT64;
 }
 
-/* last octet in a range */
-static inline u64
-last_byte_offset(u64 start, u64 len)
-{
-       u64 end;
-
-       BUG_ON(!len);
-       end = start + len;
-       return end > start ? end - 1 : NFS4_MAX_UINT64;
-}
-
 /*
  * is l2 fully contained in l1?
  *   start1                             end1
@@ -645,7 +634,6 @@ send_layoutget(struct pnfs_layout_hdr *lo,
 
        dprintk("--> %s\n", __func__);
 
-       BUG_ON(ctx == NULL);
        lgp = kzalloc(sizeof(*lgp), gfp_flags);
        if (lgp == NULL)
                return NULL;
@@ -1126,7 +1114,6 @@ pnfs_update_layout(struct inode *ino,
                 * chance of a CB_LAYOUTRECALL(FILE) coming in.
                 */
                spin_lock(&clp->cl_lock);
-               BUG_ON(!list_empty(&lo->plh_layouts));
                list_add_tail(&lo->plh_layouts, &server->layouts);
                spin_unlock(&clp->cl_lock);
        }
@@ -1222,7 +1209,7 @@ pnfs_generic_pg_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *r
 {
        u64 rd_size = req->wb_bytes;
 
-       BUG_ON(pgio->pg_lseg != NULL);
+       WARN_ON_ONCE(pgio->pg_lseg != NULL);
 
        if (req->wb_offset != req->wb_pgbase) {
                nfs_pageio_reset_read_mds(pgio);
@@ -1251,7 +1238,7 @@ void
 pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *pgio,
                           struct nfs_page *req, u64 wb_size)
 {
-       BUG_ON(pgio->pg_lseg != NULL);
+       WARN_ON_ONCE(pgio->pg_lseg != NULL);
 
        if (req->wb_offset != req->wb_pgbase) {
                nfs_pageio_reset_write_mds(pgio);
index 2d722dba111181377e6f599adae06a8d341abe09..dbf7bba52da04086c0c0a2bbb8b4283b309b8758 100644 (file)
@@ -62,6 +62,7 @@ enum {
        NFS_LAYOUT_RW_FAILED,           /* get rw layout failed stop trying */
        NFS_LAYOUT_BULK_RECALL,         /* bulk recall affecting layout */
        NFS_LAYOUT_ROC,                 /* some lseg had roc bit set */
+       NFS_LAYOUT_RETURN,              /* Return this layout ASAP */
 };
 
 enum layoutdriver_policy_flags {
index 9347ab7c9574fa3b2468a54449d85d366aaf6b61..f5bc8e11713ba82f8861b9727e5ade4aedbe68ac 100644 (file)
@@ -239,21 +239,18 @@ int nfs_congestion_kb;
 #define NFS_CONGESTION_OFF_THRESH      \
        (NFS_CONGESTION_ON_THRESH - (NFS_CONGESTION_ON_THRESH >> 2))
 
-static int nfs_set_page_writeback(struct page *page)
+static void nfs_set_page_writeback(struct page *page)
 {
+       struct nfs_server *nfss = NFS_SERVER(page_file_mapping(page)->host);
        int ret = test_set_page_writeback(page);
 
-       if (!ret) {
-               struct inode *inode = page_file_mapping(page)->host;
-               struct nfs_server *nfss = NFS_SERVER(inode);
+       WARN_ON_ONCE(ret != 0);
 
-               if (atomic_long_inc_return(&nfss->writeback) >
-                               NFS_CONGESTION_ON_THRESH) {
-                       set_bdi_congested(&nfss->backing_dev_info,
-                                               BLK_RW_ASYNC);
-               }
+       if (atomic_long_inc_return(&nfss->writeback) >
+                       NFS_CONGESTION_ON_THRESH) {
+               set_bdi_congested(&nfss->backing_dev_info,
+                                       BLK_RW_ASYNC);
        }
-       return ret;
 }
 
 static void nfs_end_page_writeback(struct page *page)
@@ -315,10 +312,10 @@ static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio,
        if (IS_ERR(req))
                goto out;
 
-       ret = nfs_set_page_writeback(page);
-       BUG_ON(ret != 0);
-       BUG_ON(test_bit(PG_CLEAN, &req->wb_flags));
+       nfs_set_page_writeback(page);
+       WARN_ON_ONCE(test_bit(PG_CLEAN, &req->wb_flags));
 
+       ret = 0;
        if (!nfs_pageio_add_request(pgio, req)) {
                nfs_redirty_request(req);
                ret = pgio->pg_error;
@@ -451,8 +448,6 @@ static void nfs_inode_remove_request(struct nfs_page *req)
        struct inode *inode = req->wb_context->dentry->d_inode;
        struct nfs_inode *nfsi = NFS_I(inode);
 
-       BUG_ON (!NFS_WBACK_BUSY(req));
-
        spin_lock(&inode->i_lock);
        if (likely(!PageSwapCache(req->wb_page))) {
                set_page_private(req->wb_page, 0);
@@ -1727,7 +1722,6 @@ int nfs_wb_page_cancel(struct inode *inode, struct page *page)
        struct nfs_page *req;
        int ret = 0;
 
-       BUG_ON(!PageLocked(page));
        for (;;) {
                wait_on_page_writeback(page);
                req = nfs_page_find_request(page);
index 3344bdd5506e3f06259efb7f176e0263764fc2dd..08b886f119ce49cd0232f954b775be71e76ae736 100644 (file)
@@ -201,7 +201,7 @@ void dnotify_flush(struct file *filp, fl_owner_t id)
 
        /* nothing else could have found us thanks to the dnotify_mark_mutex */
        if (dn_mark->dn == NULL)
-               fsnotify_destroy_mark(fsn_mark);
+               fsnotify_destroy_mark(fsn_mark, dnotify_group);
 
        mutex_unlock(&dnotify_mark_mutex);
 
@@ -385,7 +385,7 @@ out:
        spin_unlock(&fsn_mark->lock);
 
        if (destroy)
-               fsnotify_destroy_mark(fsn_mark);
+               fsnotify_destroy_mark(fsn_mark, dnotify_group);
 
        mutex_unlock(&dnotify_mark_mutex);
        fsnotify_put_mark(fsn_mark);
index f35794b97e8e5cb5cc396af28206d69ca1202935..aeb5b5abbd4fcb9036b1b9e7391541c20d8b8d3c 100644 (file)
@@ -18,6 +18,12 @@ static bool should_merge(struct fsnotify_event *old, struct fsnotify_event *new)
            old->tgid == new->tgid) {
                switch (old->data_type) {
                case (FSNOTIFY_EVENT_PATH):
+#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
+                       /* dont merge two permission events */
+                       if ((old->mask & FAN_ALL_PERM_EVENTS) &&
+                           (new->mask & FAN_ALL_PERM_EVENTS))
+                               return false;
+#endif
                        if ((old->path.mnt == new->path.mnt) &&
                            (old->path.dentry == new->path.dentry))
                                return true;
index 721d692fa8d4a20dd5bf593d3f732d8b3f913261..9437ad1785e94269bf759ace466afb01225c01ed 100644 (file)
@@ -395,8 +395,12 @@ static int fanotify_release(struct inode *ignored, struct file *file)
 
        wake_up(&group->fanotify_data.access_waitq);
 #endif
+
+       if (file->f_flags & FASYNC)
+               fsnotify_fasync(-1, file, 0);
+
        /* matches the fanotify_init->fsnotify_alloc_group */
-       fsnotify_put_group(group);
+       fsnotify_destroy_group(group);
 
        return 0;
 }
@@ -490,7 +494,8 @@ out:
 
 static __u32 fanotify_mark_remove_from_mask(struct fsnotify_mark *fsn_mark,
                                            __u32 mask,
-                                           unsigned int flags)
+                                           unsigned int flags,
+                                           int *destroy)
 {
        __u32 oldmask;
 
@@ -504,8 +509,7 @@ static __u32 fanotify_mark_remove_from_mask(struct fsnotify_mark *fsn_mark,
        }
        spin_unlock(&fsn_mark->lock);
 
-       if (!(oldmask & ~mask))
-               fsnotify_destroy_mark(fsn_mark);
+       *destroy = !(oldmask & ~mask);
 
        return mask & oldmask;
 }
@@ -516,12 +520,17 @@ static int fanotify_remove_vfsmount_mark(struct fsnotify_group *group,
 {
        struct fsnotify_mark *fsn_mark = NULL;
        __u32 removed;
+       int destroy_mark;
 
        fsn_mark = fsnotify_find_vfsmount_mark(group, mnt);
        if (!fsn_mark)
                return -ENOENT;
 
-       removed = fanotify_mark_remove_from_mask(fsn_mark, mask, flags);
+       removed = fanotify_mark_remove_from_mask(fsn_mark, mask, flags,
+                                                &destroy_mark);
+       if (destroy_mark)
+               fsnotify_destroy_mark(fsn_mark, group);
+
        fsnotify_put_mark(fsn_mark);
        if (removed & real_mount(mnt)->mnt_fsnotify_mask)
                fsnotify_recalc_vfsmount_mask(mnt);
@@ -535,12 +544,16 @@ static int fanotify_remove_inode_mark(struct fsnotify_group *group,
 {
        struct fsnotify_mark *fsn_mark = NULL;
        __u32 removed;
+       int destroy_mark;
 
        fsn_mark = fsnotify_find_inode_mark(group, inode);
        if (!fsn_mark)
                return -ENOENT;
 
-       removed = fanotify_mark_remove_from_mask(fsn_mark, mask, flags);
+       removed = fanotify_mark_remove_from_mask(fsn_mark, mask, flags,
+                                                &destroy_mark);
+       if (destroy_mark)
+               fsnotify_destroy_mark(fsn_mark, group);
        /* matches the fsnotify_find_inode_mark() */
        fsnotify_put_mark(fsn_mark);
        if (removed & inode->i_fsnotify_mask)
@@ -707,13 +720,13 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
                break;
        default:
                fd = -EINVAL;
-               goto out_put_group;
+               goto out_destroy_group;
        }
 
        if (flags & FAN_UNLIMITED_QUEUE) {
                fd = -EPERM;
                if (!capable(CAP_SYS_ADMIN))
-                       goto out_put_group;
+                       goto out_destroy_group;
                group->max_events = UINT_MAX;
        } else {
                group->max_events = FANOTIFY_DEFAULT_MAX_EVENTS;
@@ -722,7 +735,7 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
        if (flags & FAN_UNLIMITED_MARKS) {
                fd = -EPERM;
                if (!capable(CAP_SYS_ADMIN))
-                       goto out_put_group;
+                       goto out_destroy_group;
                group->fanotify_data.max_marks = UINT_MAX;
        } else {
                group->fanotify_data.max_marks = FANOTIFY_DEFAULT_MAX_MARKS;
@@ -730,12 +743,12 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
 
        fd = anon_inode_getfd("[fanotify]", &fanotify_fops, group, f_flags);
        if (fd < 0)
-               goto out_put_group;
+               goto out_destroy_group;
 
        return fd;
 
-out_put_group:
-       fsnotify_put_group(group);
+out_destroy_group:
+       fsnotify_destroy_group(group);
        return fd;
 }
 
index 63fc294a469268d06d9ae1cc9f3d19f3ba95f695..bd2625bd88b47a7b2961ec0d43b77f5675a80ad6 100644 (file)
@@ -33,9 +33,6 @@
  */
 void fsnotify_final_destroy_group(struct fsnotify_group *group)
 {
-       /* clear the notification queue of all events */
-       fsnotify_flush_notify(group);
-
        if (group->ops->free_group_priv)
                group->ops->free_group_priv(group);
 
@@ -43,23 +40,30 @@ void fsnotify_final_destroy_group(struct fsnotify_group *group)
 }
 
 /*
- * Trying to get rid of a group.  We need to first get rid of any outstanding
- * allocations and then free the group.  Remember that fsnotify_clear_marks_by_group
- * could miss marks that are being freed by inode and those marks could still
- * hold a reference to this group (via group->num_marks)  If we get into that
- * situtation, the fsnotify_final_destroy_group will get called when that final
- * mark is freed.
+ * Trying to get rid of a group. Remove all marks, flush all events and release
+ * the group reference.
+ * Note that another thread calling fsnotify_clear_marks_by_group() may still
+ * hold a ref to the group.
  */
-static void fsnotify_destroy_group(struct fsnotify_group *group)
+void fsnotify_destroy_group(struct fsnotify_group *group)
 {
        /* clear all inode marks for this group */
        fsnotify_clear_marks_by_group(group);
 
        synchronize_srcu(&fsnotify_mark_srcu);
 
-       /* past the point of no return, matches the initial value of 1 */
-       if (atomic_dec_and_test(&group->num_marks))
-               fsnotify_final_destroy_group(group);
+       /* clear the notification queue of all events */
+       fsnotify_flush_notify(group);
+
+       fsnotify_put_group(group);
+}
+
+/*
+ * Get reference to a group.
+ */
+void fsnotify_get_group(struct fsnotify_group *group)
+{
+       atomic_inc(&group->refcnt);
 }
 
 /*
@@ -68,7 +72,7 @@ static void fsnotify_destroy_group(struct fsnotify_group *group)
 void fsnotify_put_group(struct fsnotify_group *group)
 {
        if (atomic_dec_and_test(&group->refcnt))
-               fsnotify_destroy_group(group);
+               fsnotify_final_destroy_group(group);
 }
 
 /*
@@ -84,21 +88,24 @@ struct fsnotify_group *fsnotify_alloc_group(const struct fsnotify_ops *ops)
 
        /* set to 0 when there a no external references to this group */
        atomic_set(&group->refcnt, 1);
-       /*
-        * hits 0 when there are no external references AND no marks for
-        * this group
-        */
-       atomic_set(&group->num_marks, 1);
+       atomic_set(&group->num_marks, 0);
 
        mutex_init(&group->notification_mutex);
        INIT_LIST_HEAD(&group->notification_list);
        init_waitqueue_head(&group->notification_waitq);
        group->max_events = UINT_MAX;
 
-       spin_lock_init(&group->mark_lock);
+       mutex_init(&group->mark_mutex);
        INIT_LIST_HEAD(&group->marks_list);
 
        group->ops = ops;
 
        return group;
 }
+
+int fsnotify_fasync(int fd, struct file *file, int on)
+{
+       struct fsnotify_group *group = file->private_data;
+
+       return fasync_helper(fd, file, on, &group->fsn_fa) >= 0 ? 0 : -EIO;
+}
index b13c00ac48eb377086f1928d8ff0cffae3b8cc44..21230209c9579c2ed88a9f9cdfcf30a7dd54d6bd 100644 (file)
@@ -63,8 +63,8 @@ void fsnotify_destroy_inode_mark(struct fsnotify_mark *mark)
 {
        struct inode *inode = mark->i.inode;
 
+       BUG_ON(!mutex_is_locked(&mark->group->mark_mutex));
        assert_spin_locked(&mark->lock);
-       assert_spin_locked(&mark->group->mark_lock);
 
        spin_lock(&inode->i_lock);
 
@@ -99,8 +99,16 @@ void fsnotify_clear_marks_by_inode(struct inode *inode)
        spin_unlock(&inode->i_lock);
 
        list_for_each_entry_safe(mark, lmark, &free_list, i.free_i_list) {
-               fsnotify_destroy_mark(mark);
+               struct fsnotify_group *group;
+
+               spin_lock(&mark->lock);
+               fsnotify_get_group(mark->group);
+               group = mark->group;
+               spin_unlock(&mark->lock);
+
+               fsnotify_destroy_mark(mark, group);
                fsnotify_put_mark(mark);
+               fsnotify_put_group(group);
        }
 }
 
@@ -191,8 +199,8 @@ int fsnotify_add_inode_mark(struct fsnotify_mark *mark,
 
        mark->flags |= FSNOTIFY_MARK_FLAG_INODE;
 
+       BUG_ON(!mutex_is_locked(&group->mark_mutex));
        assert_spin_locked(&mark->lock);
-       assert_spin_locked(&group->mark_lock);
 
        spin_lock(&inode->i_lock);
 
index e3cbd746f64a5eb4ac9359cf8a3f271a6da8a332..871569c7d609360688c229e1357d3610e44841d0 100644 (file)
@@ -118,6 +118,7 @@ static int inotify_handle_event(struct fsnotify_group *group,
 
        fsn_event_priv = &event_priv->fsnotify_event_priv_data;
 
+       fsnotify_get_group(group);
        fsn_event_priv->group = group;
        event_priv->wd = wd;
 
@@ -131,7 +132,7 @@ static int inotify_handle_event(struct fsnotify_group *group,
        }
 
        if (inode_mark->mask & IN_ONESHOT)
-               fsnotify_destroy_mark(inode_mark);
+               fsnotify_destroy_mark(inode_mark, group);
 
        return ret;
 }
@@ -210,6 +211,7 @@ void inotify_free_event_priv(struct fsnotify_event_private_data *fsn_event_priv)
        event_priv = container_of(fsn_event_priv, struct inotify_event_private_data,
                                  fsnotify_event_priv_data);
 
+       fsnotify_put_group(fsn_event_priv->group);
        kmem_cache_free(event_priv_cachep, event_priv);
 }
 
index c311dda054a31efc1cb6d7e1f75f938857a5b604..d42ea9bd5727f6b50420c43218c0c4ffeb30e46c 100644 (file)
@@ -264,7 +264,7 @@ static ssize_t inotify_read(struct file *file, char __user *buf,
                ret = -EAGAIN;
                if (file->f_flags & O_NONBLOCK)
                        break;
-               ret = -EINTR;
+               ret = -ERESTARTSYS;
                if (signal_pending(current))
                        break;
 
@@ -280,23 +280,17 @@ static ssize_t inotify_read(struct file *file, char __user *buf,
        return ret;
 }
 
-static int inotify_fasync(int fd, struct file *file, int on)
-{
-       struct fsnotify_group *group = file->private_data;
-
-       return fasync_helper(fd, file, on, &group->inotify_data.fa) >= 0 ? 0 : -EIO;
-}
-
 static int inotify_release(struct inode *ignored, struct file *file)
 {
        struct fsnotify_group *group = file->private_data;
 
        pr_debug("%s: group=%p\n", __func__, group);
 
-       fsnotify_clear_marks_by_group(group);
+       if (file->f_flags & FASYNC)
+               fsnotify_fasync(-1, file, 0);
 
        /* free this group, matching get was inotify_init->fsnotify_obtain_group */
-       fsnotify_put_group(group);
+       fsnotify_destroy_group(group);
 
        return 0;
 }
@@ -337,7 +331,7 @@ static long inotify_ioctl(struct file *file, unsigned int cmd,
 static const struct file_operations inotify_fops = {
        .poll           = inotify_poll,
        .read           = inotify_read,
-       .fasync         = inotify_fasync,
+       .fasync         = fsnotify_fasync,
        .release        = inotify_release,
        .unlocked_ioctl = inotify_ioctl,
        .compat_ioctl   = inotify_ioctl,
@@ -519,13 +513,13 @@ void inotify_ignored_and_remove_idr(struct fsnotify_mark *fsn_mark,
        struct fsnotify_event_private_data *fsn_event_priv;
        int ret;
 
+       i_mark = container_of(fsn_mark, struct inotify_inode_mark, fsn_mark);
+
        ignored_event = fsnotify_create_event(NULL, FS_IN_IGNORED, NULL,
                                              FSNOTIFY_EVENT_NONE, NULL, 0,
                                              GFP_NOFS);
        if (!ignored_event)
-               return;
-
-       i_mark = container_of(fsn_mark, struct inotify_inode_mark, fsn_mark);
+               goto skip_send_ignore;
 
        event_priv = kmem_cache_alloc(event_priv_cachep, GFP_NOFS);
        if (unlikely(!event_priv))
@@ -533,6 +527,7 @@ void inotify_ignored_and_remove_idr(struct fsnotify_mark *fsn_mark,
 
        fsn_event_priv = &event_priv->fsnotify_event_priv_data;
 
+       fsnotify_get_group(group);
        fsn_event_priv->group = group;
        event_priv->wd = i_mark->wd;
 
@@ -546,9 +541,9 @@ void inotify_ignored_and_remove_idr(struct fsnotify_mark *fsn_mark,
        }
 
 skip_send_ignore:
-
        /* matches the reference taken when the event was created */
-       fsnotify_put_event(ignored_event);
+       if (ignored_event)
+               fsnotify_put_event(ignored_event);
 
        /* remove this mark from the idr */
        inotify_remove_from_idr(group, i_mark);
@@ -707,12 +702,11 @@ static struct fsnotify_group *inotify_new_group(unsigned int max_events)
        spin_lock_init(&group->inotify_data.idr_lock);
        idr_init(&group->inotify_data.idr);
        group->inotify_data.last_wd = 0;
-       group->inotify_data.fa = NULL;
        group->inotify_data.user = get_current_user();
 
        if (atomic_inc_return(&group->inotify_data.user->inotify_devs) >
            inotify_max_user_instances) {
-               fsnotify_put_group(group);
+               fsnotify_destroy_group(group);
                return ERR_PTR(-EMFILE);
        }
 
@@ -741,7 +735,7 @@ SYSCALL_DEFINE1(inotify_init1, int, flags)
        ret = anon_inode_getfd("inotify", &inotify_fops, group,
                                  O_RDONLY | flags);
        if (ret < 0)
-               fsnotify_put_group(group);
+               fsnotify_destroy_group(group);
 
        return ret;
 }
@@ -817,7 +811,7 @@ SYSCALL_DEFINE2(inotify_rm_watch, int, fd, __s32, wd)
 
        ret = 0;
 
-       fsnotify_destroy_mark(&i_mark->fsn_mark);
+       fsnotify_destroy_mark(&i_mark->fsn_mark, group);
 
        /* match ref taken by inotify_idr_find */
        fsnotify_put_mark(&i_mark->fsn_mark);
index f104d565b6823aa75ab39c5c0717e9e3fd9382f3..fc6b49bf73600c2aad93e802865512b692a7cc24 100644 (file)
@@ -109,8 +109,11 @@ void fsnotify_get_mark(struct fsnotify_mark *mark)
 
 void fsnotify_put_mark(struct fsnotify_mark *mark)
 {
-       if (atomic_dec_and_test(&mark->refcnt))
+       if (atomic_dec_and_test(&mark->refcnt)) {
+               if (mark->group)
+                       fsnotify_put_group(mark->group);
                mark->free_mark(mark);
+       }
 }
 
 /*
@@ -118,14 +121,14 @@ void fsnotify_put_mark(struct fsnotify_mark *mark)
  * The caller had better be holding a reference to this mark so we don't actually
  * do the final put under the mark->lock
  */
-void fsnotify_destroy_mark(struct fsnotify_mark *mark)
+void fsnotify_destroy_mark_locked(struct fsnotify_mark *mark,
+                                 struct fsnotify_group *group)
 {
-       struct fsnotify_group *group;
        struct inode *inode = NULL;
 
-       spin_lock(&mark->lock);
+       BUG_ON(!mutex_is_locked(&group->mark_mutex));
 
-       group = mark->group;
+       spin_lock(&mark->lock);
 
        /* something else already called this function on this mark */
        if (!(mark->flags & FSNOTIFY_MARK_FLAG_ALIVE)) {
@@ -135,8 +138,6 @@ void fsnotify_destroy_mark(struct fsnotify_mark *mark)
 
        mark->flags &= ~FSNOTIFY_MARK_FLAG_ALIVE;
 
-       spin_lock(&group->mark_lock);
-
        if (mark->flags & FSNOTIFY_MARK_FLAG_INODE) {
                inode = mark->i.inode;
                fsnotify_destroy_inode_mark(mark);
@@ -147,13 +148,22 @@ void fsnotify_destroy_mark(struct fsnotify_mark *mark)
 
        list_del_init(&mark->g_list);
 
-       spin_unlock(&group->mark_lock);
        spin_unlock(&mark->lock);
 
+       if (inode && (mark->flags & FSNOTIFY_MARK_FLAG_OBJECT_PINNED))
+               iput(inode);
+       /* release lock temporarily */
+       mutex_unlock(&group->mark_mutex);
+
        spin_lock(&destroy_lock);
        list_add(&mark->destroy_list, &destroy_list);
        spin_unlock(&destroy_lock);
        wake_up(&destroy_waitq);
+       /*
+        * We don't necessarily have a ref on mark from caller so the above destroy
+        * may have actually freed it, unless this group provides a 'freeing_mark'
+        * function which must be holding a reference.
+        */
 
        /*
         * Some groups like to know that marks are being freed.  This is a
@@ -175,21 +185,17 @@ void fsnotify_destroy_mark(struct fsnotify_mark *mark)
         * is just a lazy update (and could be a perf win...)
         */
 
-       if (inode && (mark->flags & FSNOTIFY_MARK_FLAG_OBJECT_PINNED))
-               iput(inode);
+       atomic_dec(&group->num_marks);
 
-       /*
-        * We don't necessarily have a ref on mark from caller so the above iput
-        * may have already destroyed it.  Don't touch from now on.
-        */
+       mutex_lock_nested(&group->mark_mutex, SINGLE_DEPTH_NESTING);
+}
 
-       /*
-        * it's possible that this group tried to destroy itself, but this
-        * this mark was simultaneously being freed by inode.  If that's the
-        * case, we finish freeing the group here.
-        */
-       if (unlikely(atomic_dec_and_test(&group->num_marks)))
-               fsnotify_final_destroy_group(group);
+void fsnotify_destroy_mark(struct fsnotify_mark *mark,
+                          struct fsnotify_group *group)
+{
+       mutex_lock_nested(&group->mark_mutex, SINGLE_DEPTH_NESTING);
+       fsnotify_destroy_mark_locked(mark, group);
+       mutex_unlock(&group->mark_mutex);
 }
 
 void fsnotify_set_mark_mask_locked(struct fsnotify_mark *mark, __u32 mask)
@@ -214,26 +220,26 @@ void fsnotify_set_mark_ignored_mask_locked(struct fsnotify_mark *mark, __u32 mas
  * These marks may be used for the fsnotify backend to determine which
  * event types should be delivered to which group.
  */
-int fsnotify_add_mark(struct fsnotify_mark *mark,
-                     struct fsnotify_group *group, struct inode *inode,
-                     struct vfsmount *mnt, int allow_dups)
+int fsnotify_add_mark_locked(struct fsnotify_mark *mark,
+                            struct fsnotify_group *group, struct inode *inode,
+                            struct vfsmount *mnt, int allow_dups)
 {
        int ret = 0;
 
        BUG_ON(inode && mnt);
        BUG_ON(!inode && !mnt);
+       BUG_ON(!mutex_is_locked(&group->mark_mutex));
 
        /*
         * LOCKING ORDER!!!!
+        * group->mark_mutex
         * mark->lock
-        * group->mark_lock
         * inode->i_lock
         */
        spin_lock(&mark->lock);
-       spin_lock(&group->mark_lock);
-
        mark->flags |= FSNOTIFY_MARK_FLAG_ALIVE;
 
+       fsnotify_get_group(group);
        mark->group = group;
        list_add(&mark->g_list, &group->marks_list);
        atomic_inc(&group->num_marks);
@@ -251,11 +257,8 @@ int fsnotify_add_mark(struct fsnotify_mark *mark,
                BUG();
        }
 
-       spin_unlock(&group->mark_lock);
-
        /* this will pin the object if appropriate */
        fsnotify_set_mark_mask_locked(mark, mark->mask);
-
        spin_unlock(&mark->lock);
 
        if (inode)
@@ -265,10 +268,10 @@ int fsnotify_add_mark(struct fsnotify_mark *mark,
 err:
        mark->flags &= ~FSNOTIFY_MARK_FLAG_ALIVE;
        list_del_init(&mark->g_list);
+       fsnotify_put_group(group);
        mark->group = NULL;
        atomic_dec(&group->num_marks);
 
-       spin_unlock(&group->mark_lock);
        spin_unlock(&mark->lock);
 
        spin_lock(&destroy_lock);
@@ -279,6 +282,16 @@ err:
        return ret;
 }
 
+int fsnotify_add_mark(struct fsnotify_mark *mark, struct fsnotify_group *group,
+                     struct inode *inode, struct vfsmount *mnt, int allow_dups)
+{
+       int ret;
+       mutex_lock(&group->mark_mutex);
+       ret = fsnotify_add_mark_locked(mark, group, inode, mnt, allow_dups);
+       mutex_unlock(&group->mark_mutex);
+       return ret;
+}
+
 /*
  * clear any marks in a group in which mark->flags & flags is true
  */
@@ -286,22 +299,16 @@ void fsnotify_clear_marks_by_group_flags(struct fsnotify_group *group,
                                         unsigned int flags)
 {
        struct fsnotify_mark *lmark, *mark;
-       LIST_HEAD(free_list);
 
-       spin_lock(&group->mark_lock);
+       mutex_lock_nested(&group->mark_mutex, SINGLE_DEPTH_NESTING);
        list_for_each_entry_safe(mark, lmark, &group->marks_list, g_list) {
                if (mark->flags & flags) {
-                       list_add(&mark->free_g_list, &free_list);
-                       list_del_init(&mark->g_list);
                        fsnotify_get_mark(mark);
+                       fsnotify_destroy_mark_locked(mark, group);
+                       fsnotify_put_mark(mark);
                }
        }
-       spin_unlock(&group->mark_lock);
-
-       list_for_each_entry_safe(mark, lmark, &free_list, free_g_list) {
-               fsnotify_destroy_mark(mark);
-               fsnotify_put_mark(mark);
-       }
+       mutex_unlock(&group->mark_mutex);
 }
 
 /*
@@ -317,6 +324,8 @@ void fsnotify_duplicate_mark(struct fsnotify_mark *new, struct fsnotify_mark *ol
        assert_spin_locked(&old->lock);
        new->i.inode = old->i.inode;
        new->m.mnt = old->m.mnt;
+       if (old->group)
+               fsnotify_get_group(old->group);
        new->group = old->group;
        new->mask = old->mask;
        new->free_mark = old->free_mark;
index c887b1378f7ed5087eca0df3ca745e15d9a88cc6..b3963d8c998846207eb8a0c48590c14d566630f4 100644 (file)
@@ -225,6 +225,7 @@ alloc_holder:
        mutex_unlock(&group->notification_mutex);
 
        wake_up(&group->notification_waitq);
+       kill_fasync(&group->fsn_fa, SIGIO, POLL_IN);
        return return_event;
 }
 
index b7b4b0e8554fb1e8ab6948f2efd35704ed156e56..4df58b8ea64a97d562f0701f4061152ed0f02fc2 100644 (file)
@@ -46,8 +46,16 @@ void fsnotify_clear_marks_by_mount(struct vfsmount *mnt)
        spin_unlock(&mnt->mnt_root->d_lock);
 
        list_for_each_entry_safe(mark, lmark, &free_list, m.free_m_list) {
-               fsnotify_destroy_mark(mark);
+               struct fsnotify_group *group;
+
+               spin_lock(&mark->lock);
+               fsnotify_get_group(mark->group);
+               group = mark->group;
+               spin_unlock(&mark->lock);
+
+               fsnotify_destroy_mark(mark, group);
                fsnotify_put_mark(mark);
+               fsnotify_put_group(group);
        }
 }
 
@@ -88,8 +96,8 @@ void fsnotify_destroy_vfsmount_mark(struct fsnotify_mark *mark)
 {
        struct vfsmount *mnt = mark->m.mnt;
 
+       BUG_ON(!mutex_is_locked(&mark->group->mark_mutex));
        assert_spin_locked(&mark->lock);
-       assert_spin_locked(&mark->group->mark_lock);
 
        spin_lock(&mnt->mnt_root->d_lock);
 
@@ -151,8 +159,8 @@ int fsnotify_add_vfsmount_mark(struct fsnotify_mark *mark,
 
        mark->flags |= FSNOTIFY_MARK_FLAG_VFSMOUNT;
 
+       BUG_ON(!mutex_is_locked(&group->mark_mutex));
        assert_spin_locked(&mark->lock);
-       assert_spin_locked(&group->mark_lock);
 
        spin_lock(&mnt->mnt_root->d_lock);
 
index f7c648d7d6bf1b0ecbc88cb6edaf79553eade538..ff753bbe296c8827ab296e9185bdbcf5e6a71bd9 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/time.h>
 #include <linux/debugfs.h>
 #include <linux/slab.h>
+#include <linux/bitmap.h>
 
 #include "heartbeat.h"
 #include "tcp.h"
@@ -282,15 +283,6 @@ struct o2hb_bio_wait_ctxt {
        int               wc_error;
 };
 
-static int o2hb_pop_count(void *map, int count)
-{
-       int i = -1, pop = 0;
-
-       while ((i = find_next_bit(map, count, i + 1)) < count)
-               pop++;
-       return pop;
-}
-
 static void o2hb_write_timeout(struct work_struct *work)
 {
        int failed, quorum;
@@ -307,9 +299,9 @@ static void o2hb_write_timeout(struct work_struct *work)
                spin_lock_irqsave(&o2hb_live_lock, flags);
                if (test_bit(reg->hr_region_num, o2hb_quorum_region_bitmap))
                        set_bit(reg->hr_region_num, o2hb_failed_region_bitmap);
-               failed = o2hb_pop_count(&o2hb_failed_region_bitmap,
+               failed = bitmap_weight(o2hb_failed_region_bitmap,
                                        O2NM_MAX_REGIONS);
-               quorum = o2hb_pop_count(&o2hb_quorum_region_bitmap,
+               quorum = bitmap_weight(o2hb_quorum_region_bitmap,
                                        O2NM_MAX_REGIONS);
                spin_unlock_irqrestore(&o2hb_live_lock, flags);
 
@@ -771,7 +763,7 @@ static void o2hb_set_quorum_device(struct o2hb_region *reg)
         * If global heartbeat active, unpin all regions if the
         * region count > CUT_OFF
         */
-       if (o2hb_pop_count(&o2hb_quorum_region_bitmap,
+       if (bitmap_weight(o2hb_quorum_region_bitmap,
                           O2NM_MAX_REGIONS) > O2HB_PIN_CUT_OFF)
                o2hb_region_unpin(NULL);
 unlock:
@@ -956,23 +948,9 @@ out:
        return changed;
 }
 
-/* This could be faster if we just implmented a find_last_bit, but I
- * don't think the circumstances warrant it. */
-static int o2hb_highest_node(unsigned long *nodes,
-                            int numbits)
+static int o2hb_highest_node(unsigned long *nodes, int numbits)
 {
-       int highest, node;
-
-       highest = numbits;
-       node = -1;
-       while ((node = find_next_bit(nodes, numbits, node + 1)) != -1) {
-               if (node >= numbits)
-                       break;
-
-               highest = node;
-       }
-
-       return highest;
+       return find_last_bit(nodes, numbits);
 }
 
 static int o2hb_do_disk_heartbeat(struct o2hb_region *reg)
@@ -1833,7 +1811,7 @@ static ssize_t o2hb_region_dev_write(struct o2hb_region *reg,
        live_threshold = O2HB_LIVE_THRESHOLD;
        if (o2hb_global_heartbeat_active()) {
                spin_lock(&o2hb_live_lock);
-               if (o2hb_pop_count(&o2hb_region_bitmap, O2NM_MAX_REGIONS) == 1)
+               if (bitmap_weight(o2hb_region_bitmap, O2NM_MAX_REGIONS) == 1)
                        live_threshold <<= 1;
                spin_unlock(&o2hb_live_lock);
        }
@@ -2184,7 +2162,7 @@ static void o2hb_heartbeat_group_drop_item(struct config_group *group,
        if (!o2hb_dependent_users)
                goto unlock;
 
-       if (o2hb_pop_count(&o2hb_quorum_region_bitmap,
+       if (bitmap_weight(o2hb_quorum_region_bitmap,
                           O2NM_MAX_REGIONS) <= O2HB_PIN_CUT_OFF)
                o2hb_region_pin(NULL);
 
@@ -2478,7 +2456,7 @@ static int o2hb_region_inc_user(const char *region_uuid)
        if (o2hb_dependent_users > 1)
                goto unlock;
 
-       if (o2hb_pop_count(&o2hb_quorum_region_bitmap,
+       if (bitmap_weight(o2hb_quorum_region_bitmap,
                           O2NM_MAX_REGIONS) <= O2HB_PIN_CUT_OFF)
                ret = o2hb_region_pin(NULL);
 
index baa2b9ef7eef90094dbd3ef8d76f6a6e1df64224..2260fb9e650831fef349ce2c6f6dcd878ffa45d2 100644 (file)
@@ -199,7 +199,8 @@ extern struct mlog_bits mlog_and_bits, mlog_not_bits;
 #define mlog_errno(st) do {                                            \
        int _st = (st);                                                 \
        if (_st != -ERESTARTSYS && _st != -EINTR &&                     \
-           _st != AOP_TRUNCATED_PAGE && _st != -ENOSPC)                \
+           _st != AOP_TRUNCATED_PAGE && _st != -ENOSPC &&              \
+           _st != -EDQUOT)                                             \
                mlog(ML_ERROR, "status = %lld\n", (long long)_st);      \
 } while (0)
 
index 005261c333b090f5f53f376bd5bbed55b8e16ba7..3d09a940c015d4e0304aaf2d3c98baeb3c0b80f8 100644 (file)
@@ -1888,8 +1888,10 @@ ok:
                         * up nodes that this node contacted */
                        while ((nn = find_next_bit (mle->response_map, O2NM_MAX_NODES,
                                                    nn+1)) < O2NM_MAX_NODES) {
-                               if (nn != dlm->node_num && nn != assert->node_idx)
+                               if (nn != dlm->node_num && nn != assert->node_idx) {
                                        master_request = 1;
+                                       break;
+                               }
                        }
                }
                mle->master = assert->node_idx;
@@ -2020,7 +2022,7 @@ int dlm_dispatch_assert_master(struct dlm_ctxt *dlm,
                               int ignore_higher, u8 request_from, u32 flags)
 {
        struct dlm_work_item *item;
-       item = kzalloc(sizeof(*item), GFP_NOFS);
+       item = kzalloc(sizeof(*item), GFP_ATOMIC);
        if (!item)
                return -ENOMEM;
 
@@ -2357,6 +2359,10 @@ static int dlm_is_lockres_migrateable(struct dlm_ctxt *dlm,
 
        assert_spin_locked(&res->spinlock);
 
+       /* delay migration when the lockres is in MIGRATING state */
+       if (res->state & DLM_LOCK_RES_MIGRATING)
+               return 0;
+
        if (res->owner != dlm->node_num)
                return 0;
 
index 01ebfd0bdad72264b99345378f0c6febe246503d..15d81adb8d772845fad5b8fd00da547c5c22cd38 100644 (file)
@@ -1887,6 +1887,13 @@ static int dlm_process_recovery_data(struct dlm_ctxt *dlm,
 
                if (ml->type == LKM_NLMODE)
                        goto skip_lvb;
+               
+               /*
+                * If the lock is in the blocked list it can't have a valid lvb,
+                * so skip it
+                */
+               if (ml->list == DLM_BLOCKED_LIST)
+                       goto skip_lvb;
 
                if (!dlm_lvb_is_empty(mres->lvb)) {
                        if (lksb->flags & DLM_LKSB_PUT_LVB) {
index f1fbb4b552ad3649238becdd9c21d4b138d5c8d7..66edce7ecfd78f807451bdbf724cfabc071dbd5a 100644 (file)
@@ -57,7 +57,7 @@
 static int ocfs2_fast_symlink_readpage(struct file *unused, struct page *page)
 {
        struct inode *inode = page->mapping->host;
-       struct buffer_head *bh;
+       struct buffer_head *bh = NULL;
        int status = ocfs2_read_inode_block(inode, &bh);
        struct ocfs2_dinode *fe;
        const char *link;
index cceaab07ad549caaa124b71e3db01f126052ef59..43973b084abf25649fdb12e16ad3d169c0e29c9e 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/sched.h>
 #include <linux/proc_fs.h>
 struct  ctl_table_header;
+struct  mempolicy;
 
 extern struct proc_dir_entry proc_root;
 #ifdef CONFIG_PROC_SYSCTL
@@ -74,6 +75,9 @@ struct proc_maps_private {
 #ifdef CONFIG_MMU
        struct vm_area_struct *tail_vma;
 #endif
+#ifdef CONFIG_NUMA
+       struct mempolicy *task_mempolicy;
+#endif
 };
 
 void proc_init_inodecache(void);
index 64c3b3172367abbd1c1464b9372f33ee4efa7acb..e296572c73ed651dd7d81cc33eb3dd1b64de5d0d 100644 (file)
@@ -45,10 +45,13 @@ static cputime64_t get_iowait_time(int cpu)
 
 static u64 get_idle_time(int cpu)
 {
-       u64 idle, idle_time = get_cpu_idle_time_us(cpu, NULL);
+       u64 idle, idle_time = -1ULL;
+
+       if (cpu_online(cpu))
+               idle_time = get_cpu_idle_time_us(cpu, NULL);
 
        if (idle_time == -1ULL)
-               /* !NO_HZ so we can rely on cpustat.idle */
+               /* !NO_HZ or cpu offline so we can rely on cpustat.idle */
                idle = kcpustat_cpu(cpu).cpustat[CPUTIME_IDLE];
        else
                idle = usecs_to_cputime64(idle_time);
@@ -58,10 +61,13 @@ static u64 get_idle_time(int cpu)
 
 static u64 get_iowait_time(int cpu)
 {
-       u64 iowait, iowait_time = get_cpu_iowait_time_us(cpu, NULL);
+       u64 iowait, iowait_time = -1ULL;
+
+       if (cpu_online(cpu))
+               iowait_time = get_cpu_iowait_time_us(cpu, NULL);
 
        if (iowait_time == -1ULL)
-               /* !NO_HZ so we can rely on cpustat.iowait */
+               /* !NO_HZ or cpu offline so we can rely on cpustat.iowait */
                iowait = kcpustat_cpu(cpu).cpustat[CPUTIME_IOWAIT];
        else
                iowait = usecs_to_cputime64(iowait_time);
index 14df8806ff294e22ebfda54f4d35d08c30c5a6c3..90c63f9392a595318c5d1e03e1d69305bf9413fa 100644 (file)
@@ -90,10 +90,55 @@ static void pad_len_spaces(struct seq_file *m, int len)
        seq_printf(m, "%*c", len, ' ');
 }
 
+#ifdef CONFIG_NUMA
+/*
+ * These functions are for numa_maps but called in generic **maps seq_file
+ * ->start(), ->stop() ops.
+ *
+ * numa_maps scans all vmas under mmap_sem and checks their mempolicy.
+ * Each mempolicy object is controlled by reference counting. The problem here
+ * is how to avoid accessing dead mempolicy object.
+ *
+ * Because we're holding mmap_sem while reading seq_file, it's safe to access
+ * each vma's mempolicy, no vma objects will never drop refs to mempolicy.
+ *
+ * A task's mempolicy (task->mempolicy) has different behavior. task->mempolicy
+ * is set and replaced under mmap_sem but unrefed and cleared under task_lock().
+ * So, without task_lock(), we cannot trust get_vma_policy() because we cannot
+ * gurantee the task never exits under us. But taking task_lock() around
+ * get_vma_plicy() causes lock order problem.
+ *
+ * To access task->mempolicy without lock, we hold a reference count of an
+ * object pointed by task->mempolicy and remember it. This will guarantee
+ * that task->mempolicy points to an alive object or NULL in numa_maps accesses.
+ */
+static void hold_task_mempolicy(struct proc_maps_private *priv)
+{
+       struct task_struct *task = priv->task;
+
+       task_lock(task);
+       priv->task_mempolicy = task->mempolicy;
+       mpol_get(priv->task_mempolicy);
+       task_unlock(task);
+}
+static void release_task_mempolicy(struct proc_maps_private *priv)
+{
+       mpol_put(priv->task_mempolicy);
+}
+#else
+static void hold_task_mempolicy(struct proc_maps_private *priv)
+{
+}
+static void release_task_mempolicy(struct proc_maps_private *priv)
+{
+}
+#endif
+
 static void vma_stop(struct proc_maps_private *priv, struct vm_area_struct *vma)
 {
        if (vma && vma != priv->tail_vma) {
                struct mm_struct *mm = vma->vm_mm;
+               release_task_mempolicy(priv);
                up_read(&mm->mmap_sem);
                mmput(mm);
        }
@@ -132,7 +177,7 @@ static void *m_start(struct seq_file *m, loff_t *pos)
 
        tail_vma = get_gate_vma(priv->task->mm);
        priv->tail_vma = tail_vma;
-
+       hold_task_mempolicy(priv);
        /* Start with last addr hint */
        vma = find_vma(mm, last_addr);
        if (last_addr && vma) {
@@ -159,6 +204,7 @@ out:
        if (vma)
                return vma;
 
+       release_task_mempolicy(priv);
        /* End of vmas has been reached */
        m->version = (tail_vma != NULL)? 0: -1UL;
        up_read(&mm->mmap_sem);
@@ -1178,11 +1224,9 @@ static int show_numa_map(struct seq_file *m, void *v, int is_pid)
        walk.private = md;
        walk.mm = mm;
 
-       task_lock(task);
        pol = get_vma_policy(task, vma, vma->vm_start);
        mpol_to_str(buffer, sizeof(buffer), pol, 0);
        mpol_cond_put(pol);
-       task_unlock(task);
 
        seq_printf(m, "%08lx %s", vma->vm_start, buffer);
 
index 28ec13af28d91c360c89c68f7af0f1957e79477a..4b0b8b4082b61c33428878beb35990ebdd459afa 100644 (file)
@@ -681,8 +681,9 @@ int ubifs_find_free_leb_for_idx(struct ubifs_info *c)
        if (!lprops) {
                lprops = ubifs_fast_find_freeable(c);
                if (!lprops) {
-                       ubifs_assert(c->freeable_cnt == 0);
-                       if (c->lst.empty_lebs - c->lst.taken_empty_lebs > 0) {
+                       if (c->in_a_category_cnt != c->main_lebs ||
+                           c->lst.empty_lebs - c->lst.taken_empty_lebs > 0) {
+                               ubifs_assert(c->freeable_cnt == 0);
                                lprops = scan_for_leb_for_idx(c);
                                if (IS_ERR(lprops)) {
                                        err = PTR_ERR(lprops);
index e5a2a35a46dcc1fc3fb9178704cec947458bda2e..46190a7c42a6c113bcffe4f170800b98a22eaf01 100644 (file)
@@ -300,8 +300,11 @@ void ubifs_add_to_cat(struct ubifs_info *c, struct ubifs_lprops *lprops,
        default:
                ubifs_assert(0);
        }
+
        lprops->flags &= ~LPROPS_CAT_MASK;
        lprops->flags |= cat;
+       c->in_a_category_cnt += 1;
+       ubifs_assert(c->in_a_category_cnt <= c->main_lebs);
 }
 
 /**
@@ -334,6 +337,9 @@ static void ubifs_remove_from_cat(struct ubifs_info *c,
        default:
                ubifs_assert(0);
        }
+
+       c->in_a_category_cnt -= 1;
+       ubifs_assert(c->in_a_category_cnt >= 0);
 }
 
 /**
index 5486346d0a3f9ec63ce10f9296ee0fbdec8732f1..d133c276fe05d526c647756c704ef37a8438612e 100644 (file)
@@ -1183,6 +1183,8 @@ struct ubifs_debug_info;
  * @freeable_list: list of freeable non-index LEBs (free + dirty == @leb_size)
  * @frdi_idx_list: list of freeable index LEBs (free + dirty == @leb_size)
  * @freeable_cnt: number of freeable LEBs in @freeable_list
+ * @in_a_category_cnt: count of lprops which are in a certain category, which
+ *                     basically meants that they were loaded from the flash
  *
  * @ltab_lnum: LEB number of LPT's own lprops table
  * @ltab_offs: offset of LPT's own lprops table
@@ -1412,6 +1414,7 @@ struct ubifs_info {
        struct list_head freeable_list;
        struct list_head frdi_idx_list;
        int freeable_cnt;
+       int in_a_category_cnt;
 
        int ltab_lnum;
        int ltab_offs;
index d2bf974b1a2f68db6a47901cebd060bb49518bd1..e65357bb3dc641ac9b880935d35c67e373102169 100644 (file)
@@ -39,7 +39,7 @@ xfs-y                         += xfs_aops.o \
                                   xfs_fsops.o \
                                   xfs_fs_subr.o \
                                   xfs_globals.o \
-                                  xfs_iget.o \
+                                  xfs_icache.o \
                                   xfs_ioctl.o \
                                   xfs_iomap.o \
                                   xfs_iops.o \
@@ -47,7 +47,6 @@ xfs-y                         += xfs_aops.o \
                                   xfs_message.o \
                                   xfs_mru_cache.o \
                                   xfs_super.o \
-                                  xfs_sync.o \
                                   xfs_xattr.o \
                                   xfs_rename.o \
                                   xfs_utils.o \
index 4f33c32affe3d2eb4bec9c5ca8d71a33bbc5032a..335206a9c6985fde106d164543efee515bba1433 100644 (file)
@@ -1866,6 +1866,7 @@ xfs_alloc_fix_freelist(
        /*
         * Initialize the args structure.
         */
+       memset(&targs, 0, sizeof(targs));
        targs.tp = tp;
        targs.mp = mp;
        targs.agbp = agbp;
@@ -2207,7 +2208,7 @@ xfs_alloc_read_agf(
  * group or loop over the allocation groups to find the result.
  */
 int                            /* error */
-__xfs_alloc_vextent(
+xfs_alloc_vextent(
        xfs_alloc_arg_t *args)  /* allocation argument structure */
 {
        xfs_agblock_t   agsize; /* allocation group size */
@@ -2417,46 +2418,6 @@ error0:
        return error;
 }
 
-static void
-xfs_alloc_vextent_worker(
-       struct work_struct      *work)
-{
-       struct xfs_alloc_arg    *args = container_of(work,
-                                               struct xfs_alloc_arg, work);
-       unsigned long           pflags;
-
-       /* we are in a transaction context here */
-       current_set_flags_nested(&pflags, PF_FSTRANS);
-
-       args->result = __xfs_alloc_vextent(args);
-       complete(args->done);
-
-       current_restore_flags_nested(&pflags, PF_FSTRANS);
-}
-
-/*
- * Data allocation requests often come in with little stack to work on. Push
- * them off to a worker thread so there is lots of stack to use. Metadata
- * requests, OTOH, are generally from low stack usage paths, so avoid the
- * context switch overhead here.
- */
-int
-xfs_alloc_vextent(
-       struct xfs_alloc_arg    *args)
-{
-       DECLARE_COMPLETION_ONSTACK(done);
-
-       if (!args->userdata)
-               return __xfs_alloc_vextent(args);
-
-
-       args->done = &done;
-       INIT_WORK_ONSTACK(&args->work, xfs_alloc_vextent_worker);
-       queue_work(xfs_alloc_wq, &args->work);
-       wait_for_completion(&done);
-       return args->result;
-}
-
 /*
  * Free an extent.
  * Just break up the extent address and hand off to xfs_free_ag_extent
index 93be4a667ca1692648aec03195b5747bac4239f2..feacb061bab78bb3492ee0ff37eed5cc0fb95894 100644 (file)
@@ -120,9 +120,6 @@ typedef struct xfs_alloc_arg {
        char            isfl;           /* set if is freelist blocks - !acctg */
        char            userdata;       /* set if this is user data */
        xfs_fsblock_t   firstblock;     /* io first block allocated */
-       struct completion *done;
-       struct work_struct work;
-       int             result;
 } xfs_alloc_arg_t;
 
 /*
index 848ffa77707b98bf272f61fc162f6e361504926e..83d0cf3df930794c307c4adcb33dceb8a5415f7e 100644 (file)
@@ -2437,6 +2437,7 @@ xfs_bmap_btalloc(
         * Normal allocation, done through xfs_alloc_vextent.
         */
        tryagain = isaligned = 0;
+       memset(&args, 0, sizeof(args));
        args.tp = ap->tp;
        args.mp = mp;
        args.fsbno = ap->blkno;
@@ -3082,6 +3083,7 @@ xfs_bmap_extents_to_btree(
         * Convert to a btree with two levels, one record in root.
         */
        XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_BTREE);
+       memset(&args, 0, sizeof(args));
        args.tp = tp;
        args.mp = mp;
        args.firstblock = *firstblock;
@@ -3237,6 +3239,7 @@ xfs_bmap_local_to_extents(
                xfs_buf_t       *bp;    /* buffer for extent block */
                xfs_bmbt_rec_host_t *ep;/* extent record pointer */
 
+               memset(&args, 0, sizeof(args));
                args.tp = tp;
                args.mp = ip->i_mount;
                args.firstblock = *firstblock;
@@ -4616,12 +4619,11 @@ xfs_bmapi_delay(
 
 
 STATIC int
-xfs_bmapi_allocate(
-       struct xfs_bmalloca     *bma,
-       int                     flags)
+__xfs_bmapi_allocate(
+       struct xfs_bmalloca     *bma)
 {
        struct xfs_mount        *mp = bma->ip->i_mount;
-       int                     whichfork = (flags & XFS_BMAPI_ATTRFORK) ?
+       int                     whichfork = (bma->flags & XFS_BMAPI_ATTRFORK) ?
                                                XFS_ATTR_FORK : XFS_DATA_FORK;
        struct xfs_ifork        *ifp = XFS_IFORK_PTR(bma->ip, whichfork);
        int                     tmp_logflags = 0;
@@ -4654,24 +4656,27 @@ xfs_bmapi_allocate(
         * Indicate if this is the first user data in the file, or just any
         * user data.
         */
-       if (!(flags & XFS_BMAPI_METADATA)) {
+       if (!(bma->flags & XFS_BMAPI_METADATA)) {
                bma->userdata = (bma->offset == 0) ?
                        XFS_ALLOC_INITIAL_USER_DATA : XFS_ALLOC_USERDATA;
        }
 
-       bma->minlen = (flags & XFS_BMAPI_CONTIG) ? bma->length : 1;
+       bma->minlen = (bma->flags & XFS_BMAPI_CONTIG) ? bma->length : 1;
 
        /*
         * Only want to do the alignment at the eof if it is userdata and
         * allocation length is larger than a stripe unit.
         */
        if (mp->m_dalign && bma->length >= mp->m_dalign &&
-           !(flags & XFS_BMAPI_METADATA) && whichfork == XFS_DATA_FORK) {
+           !(bma->flags & XFS_BMAPI_METADATA) && whichfork == XFS_DATA_FORK) {
                error = xfs_bmap_isaeof(bma, whichfork);
                if (error)
                        return error;
        }
 
+       if (bma->flags & XFS_BMAPI_STACK_SWITCH)
+               bma->stack_switch = 1;
+
        error = xfs_bmap_alloc(bma);
        if (error)
                return error;
@@ -4706,7 +4711,7 @@ xfs_bmapi_allocate(
         * A wasdelay extent has been initialized, so shouldn't be flagged
         * as unwritten.
         */
-       if (!bma->wasdel && (flags & XFS_BMAPI_PREALLOC) &&
+       if (!bma->wasdel && (bma->flags & XFS_BMAPI_PREALLOC) &&
            xfs_sb_version_hasextflgbit(&mp->m_sb))
                bma->got.br_state = XFS_EXT_UNWRITTEN;
 
@@ -4734,6 +4739,45 @@ xfs_bmapi_allocate(
        return 0;
 }
 
+static void
+xfs_bmapi_allocate_worker(
+       struct work_struct      *work)
+{
+       struct xfs_bmalloca     *args = container_of(work,
+                                               struct xfs_bmalloca, work);
+       unsigned long           pflags;
+
+       /* we are in a transaction context here */
+       current_set_flags_nested(&pflags, PF_FSTRANS);
+
+       args->result = __xfs_bmapi_allocate(args);
+       complete(args->done);
+
+       current_restore_flags_nested(&pflags, PF_FSTRANS);
+}
+
+/*
+ * Some allocation requests often come in with little stack to work on. Push
+ * them off to a worker thread so there is lots of stack to use. Otherwise just
+ * call directly to avoid the context switch overhead here.
+ */
+int
+xfs_bmapi_allocate(
+       struct xfs_bmalloca     *args)
+{
+       DECLARE_COMPLETION_ONSTACK(done);
+
+       if (!args->stack_switch)
+               return __xfs_bmapi_allocate(args);
+
+
+       args->done = &done;
+       INIT_WORK_ONSTACK(&args->work, xfs_bmapi_allocate_worker);
+       queue_work(xfs_alloc_wq, &args->work);
+       wait_for_completion(&done);
+       return args->result;
+}
+
 STATIC int
 xfs_bmapi_convert_unwritten(
        struct xfs_bmalloca     *bma,
@@ -4919,6 +4963,7 @@ xfs_bmapi_write(
                        bma.conv = !!(flags & XFS_BMAPI_CONVERT);
                        bma.wasdel = wasdelay;
                        bma.offset = bno;
+                       bma.flags = flags;
 
                        /*
                         * There's a 32/64 bit type mismatch between the
@@ -4934,7 +4979,7 @@ xfs_bmapi_write(
 
                        ASSERT(len > 0);
                        ASSERT(bma.length > 0);
-                       error = xfs_bmapi_allocate(&bma, flags);
+                       error = xfs_bmapi_allocate(&bma);
                        if (error)
                                goto error0;
                        if (bma.blkno == NULLFSBLOCK)
index 803b56d7ce16a97b7e5eb8075ba4e7853e4b8d30..5f469c3516ebc28bf836e86c974feb8c61373a4c 100644 (file)
@@ -77,6 +77,7 @@ typedef       struct xfs_bmap_free
  * from written to unwritten, otherwise convert from unwritten to written.
  */
 #define XFS_BMAPI_CONVERT      0x040
+#define XFS_BMAPI_STACK_SWITCH 0x080
 
 #define XFS_BMAPI_FLAGS \
        { XFS_BMAPI_ENTIRE,     "ENTIRE" }, \
@@ -85,7 +86,8 @@ typedef       struct xfs_bmap_free
        { XFS_BMAPI_PREALLOC,   "PREALLOC" }, \
        { XFS_BMAPI_IGSTATE,    "IGSTATE" }, \
        { XFS_BMAPI_CONTIG,     "CONTIG" }, \
-       { XFS_BMAPI_CONVERT,    "CONVERT" }
+       { XFS_BMAPI_CONVERT,    "CONVERT" }, \
+       { XFS_BMAPI_STACK_SWITCH, "STACK_SWITCH" }
 
 
 static inline int xfs_bmapi_aflag(int w)
@@ -133,6 +135,11 @@ typedef struct xfs_bmalloca {
        char                    userdata;/* set if is user data */
        char                    aeof;   /* allocated space at eof */
        char                    conv;   /* overwriting unwritten extents */
+       char                    stack_switch;
+       int                     flags;
+       struct completion       *done;
+       struct work_struct      work;
+       int                     result;
 } xfs_bmalloca_t;
 
 /*
index 8c6d1d70278cc6e71dbc093cbbfc5f2c5d44df19..a83611849cee292d6731d8a782778d6ebb2bf048 100644 (file)
@@ -29,6 +29,7 @@
 #include "xfs_inode.h"
 #include "xfs_inode_item.h"
 #include "xfs_trace.h"
+#include "xfs_icache.h"
 
 /*
  * Note that we only accept fileids which are long enough rather than allow
index aa473fa640a2dd16f56ae76abfb72c1f204ba43b..daf4066c24b26639093061fb752d6caa13979109 100644 (file)
@@ -728,16 +728,17 @@ xfs_file_buffered_aio_write(
 write_retry:
        trace_xfs_file_buffered_write(ip, count, iocb->ki_pos, 0);
        ret = generic_file_buffered_write(iocb, iovp, nr_segs,
-                       pos, &iocb->ki_pos, count, ret);
+                       pos, &iocb->ki_pos, count, 0);
+
        /*
-        * if we just got an ENOSPC, flush the inode now we aren't holding any
-        * page locks and retry *once*
+        * If we just got an ENOSPC, try to write back all dirty inodes to
+        * convert delalloc space to free up some of the excess reserved
+        * metadata space.
         */
        if (ret == -ENOSPC && !enospc) {
                enospc = 1;
-               ret = -xfs_flush_pages(ip, 0, -1, 0, FI_NONE);
-               if (!ret)
-                       goto write_retry;
+               xfs_flush_inodes(ip->i_mount);
+               goto write_retry;
        }
 
        current->backing_dev_info = NULL;
index 445bf1aef31c16d9e6bd17a8b91e78d7f1763c05..c5c4ef4f2bdbec16d9eb07ff0188921f677384ff 100644 (file)
@@ -250,6 +250,7 @@ xfs_ialloc_ag_alloc(
                                        /* boundary */
        struct xfs_perag *pag;
 
+       memset(&args, 0, sizeof(args));
        args.tp = tp;
        args.mp = tp->t_mountp;
 
similarity index 64%
rename from fs/xfs/xfs_sync.c
rename to fs/xfs/xfs_icache.c
index 9500caf15acf6c355cde32cb0e692a3a58a6a990..9c8703b5cd72819610a12c37aecf2c8e329fa25d 100644 (file)
@@ -19,6 +19,7 @@
 #include "xfs_fs.h"
 #include "xfs_types.h"
 #include "xfs_log.h"
+#include "xfs_log_priv.h"
 #include "xfs_inum.h"
 #include "xfs_trans.h"
 #include "xfs_trans_priv.h"
 #include "xfs_quota.h"
 #include "xfs_trace.h"
 #include "xfs_fsops.h"
+#include "xfs_icache.h"
 
 #include <linux/kthread.h>
 #include <linux/freezer.h>
 
-struct workqueue_struct        *xfs_syncd_wq;  /* sync workqueue */
+STATIC void __xfs_inode_clear_reclaim_tag(struct xfs_mount *mp,
+                               struct xfs_perag *pag, struct xfs_inode *ip);
+
+/*
+ * Allocate and initialise an xfs_inode.
+ */
+STATIC struct xfs_inode *
+xfs_inode_alloc(
+       struct xfs_mount        *mp,
+       xfs_ino_t               ino)
+{
+       struct xfs_inode        *ip;
+
+       /*
+        * if this didn't occur in transactions, we could use
+        * KM_MAYFAIL and return NULL here on ENOMEM. Set the
+        * code up to do this anyway.
+        */
+       ip = kmem_zone_alloc(xfs_inode_zone, KM_SLEEP);
+       if (!ip)
+               return NULL;
+       if (inode_init_always(mp->m_super, VFS_I(ip))) {
+               kmem_zone_free(xfs_inode_zone, ip);
+               return NULL;
+       }
+
+       ASSERT(atomic_read(&ip->i_pincount) == 0);
+       ASSERT(!spin_is_locked(&ip->i_flags_lock));
+       ASSERT(!xfs_isiflocked(ip));
+       ASSERT(ip->i_ino == 0);
+
+       mrlock_init(&ip->i_iolock, MRLOCK_BARRIER, "xfsio", ip->i_ino);
+
+       /* initialise the xfs inode */
+       ip->i_ino = ino;
+       ip->i_mount = mp;
+       memset(&ip->i_imap, 0, sizeof(struct xfs_imap));
+       ip->i_afp = NULL;
+       memset(&ip->i_df, 0, sizeof(xfs_ifork_t));
+       ip->i_flags = 0;
+       ip->i_delayed_blks = 0;
+       memset(&ip->i_d, 0, sizeof(xfs_icdinode_t));
+
+       return ip;
+}
+
+STATIC void
+xfs_inode_free_callback(
+       struct rcu_head         *head)
+{
+       struct inode            *inode = container_of(head, struct inode, i_rcu);
+       struct xfs_inode        *ip = XFS_I(inode);
+
+       kmem_zone_free(xfs_inode_zone, ip);
+}
+
+STATIC void
+xfs_inode_free(
+       struct xfs_inode        *ip)
+{
+       switch (ip->i_d.di_mode & S_IFMT) {
+       case S_IFREG:
+       case S_IFDIR:
+       case S_IFLNK:
+               xfs_idestroy_fork(ip, XFS_DATA_FORK);
+               break;
+       }
+
+       if (ip->i_afp)
+               xfs_idestroy_fork(ip, XFS_ATTR_FORK);
+
+       if (ip->i_itemp) {
+               ASSERT(!(ip->i_itemp->ili_item.li_flags & XFS_LI_IN_AIL));
+               xfs_inode_item_destroy(ip);
+               ip->i_itemp = NULL;
+       }
+
+       /* asserts to verify all state is correct here */
+       ASSERT(atomic_read(&ip->i_pincount) == 0);
+       ASSERT(!spin_is_locked(&ip->i_flags_lock));
+       ASSERT(!xfs_isiflocked(ip));
+
+       /*
+        * Because we use RCU freeing we need to ensure the inode always
+        * appears to be reclaimed with an invalid inode number when in the
+        * free state. The ip->i_flags_lock provides the barrier against lookup
+        * races.
+        */
+       spin_lock(&ip->i_flags_lock);
+       ip->i_flags = XFS_IRECLAIM;
+       ip->i_ino = 0;
+       spin_unlock(&ip->i_flags_lock);
+
+       call_rcu(&VFS_I(ip)->i_rcu, xfs_inode_free_callback);
+}
+
+/*
+ * Check the validity of the inode we just found it the cache
+ */
+static int
+xfs_iget_cache_hit(
+       struct xfs_perag        *pag,
+       struct xfs_inode        *ip,
+       xfs_ino_t               ino,
+       int                     flags,
+       int                     lock_flags) __releases(RCU)
+{
+       struct inode            *inode = VFS_I(ip);
+       struct xfs_mount        *mp = ip->i_mount;
+       int                     error;
+
+       /*
+        * check for re-use of an inode within an RCU grace period due to the
+        * radix tree nodes not being updated yet. We monitor for this by
+        * setting the inode number to zero before freeing the inode structure.
+        * If the inode has been reallocated and set up, then the inode number
+        * will not match, so check for that, too.
+        */
+       spin_lock(&ip->i_flags_lock);
+       if (ip->i_ino != ino) {
+               trace_xfs_iget_skip(ip);
+               XFS_STATS_INC(xs_ig_frecycle);
+               error = EAGAIN;
+               goto out_error;
+       }
+
+
+       /*
+        * If we are racing with another cache hit that is currently
+        * instantiating this inode or currently recycling it out of
+        * reclaimabe state, wait for the initialisation to complete
+        * before continuing.
+        *
+        * XXX(hch): eventually we should do something equivalent to
+        *           wait_on_inode to wait for these flags to be cleared
+        *           instead of polling for it.
+        */
+       if (ip->i_flags & (XFS_INEW|XFS_IRECLAIM)) {
+               trace_xfs_iget_skip(ip);
+               XFS_STATS_INC(xs_ig_frecycle);
+               error = EAGAIN;
+               goto out_error;
+       }
+
+       /*
+        * If lookup is racing with unlink return an error immediately.
+        */
+       if (ip->i_d.di_mode == 0 && !(flags & XFS_IGET_CREATE)) {
+               error = ENOENT;
+               goto out_error;
+       }
+
+       /*
+        * If IRECLAIMABLE is set, we've torn down the VFS inode already.
+        * Need to carefully get it back into useable state.
+        */
+       if (ip->i_flags & XFS_IRECLAIMABLE) {
+               trace_xfs_iget_reclaim(ip);
+
+               /*
+                * We need to set XFS_IRECLAIM to prevent xfs_reclaim_inode
+                * from stomping over us while we recycle the inode.  We can't
+                * clear the radix tree reclaimable tag yet as it requires
+                * pag_ici_lock to be held exclusive.
+                */
+               ip->i_flags |= XFS_IRECLAIM;
+
+               spin_unlock(&ip->i_flags_lock);
+               rcu_read_unlock();
+
+               error = -inode_init_always(mp->m_super, inode);
+               if (error) {
+                       /*
+                        * Re-initializing the inode failed, and we are in deep
+                        * trouble.  Try to re-add it to the reclaim list.
+                        */
+                       rcu_read_lock();
+                       spin_lock(&ip->i_flags_lock);
+
+                       ip->i_flags &= ~(XFS_INEW | XFS_IRECLAIM);
+                       ASSERT(ip->i_flags & XFS_IRECLAIMABLE);
+                       trace_xfs_iget_reclaim_fail(ip);
+                       goto out_error;
+               }
+
+               spin_lock(&pag->pag_ici_lock);
+               spin_lock(&ip->i_flags_lock);
+
+               /*
+                * Clear the per-lifetime state in the inode as we are now
+                * effectively a new inode and need to return to the initial
+                * state before reuse occurs.
+                */
+               ip->i_flags &= ~XFS_IRECLAIM_RESET_FLAGS;
+               ip->i_flags |= XFS_INEW;
+               __xfs_inode_clear_reclaim_tag(mp, pag, ip);
+               inode->i_state = I_NEW;
+
+               ASSERT(!rwsem_is_locked(&ip->i_iolock.mr_lock));
+               mrlock_init(&ip->i_iolock, MRLOCK_BARRIER, "xfsio", ip->i_ino);
+
+               spin_unlock(&ip->i_flags_lock);
+               spin_unlock(&pag->pag_ici_lock);
+       } else {
+               /* If the VFS inode is being torn down, pause and try again. */
+               if (!igrab(inode)) {
+                       trace_xfs_iget_skip(ip);
+                       error = EAGAIN;
+                       goto out_error;
+               }
+
+               /* We've got a live one. */
+               spin_unlock(&ip->i_flags_lock);
+               rcu_read_unlock();
+               trace_xfs_iget_hit(ip);
+       }
+
+       if (lock_flags != 0)
+               xfs_ilock(ip, lock_flags);
+
+       xfs_iflags_clear(ip, XFS_ISTALE | XFS_IDONTCACHE);
+       XFS_STATS_INC(xs_ig_found);
+
+       return 0;
+
+out_error:
+       spin_unlock(&ip->i_flags_lock);
+       rcu_read_unlock();
+       return error;
+}
+
+
+static int
+xfs_iget_cache_miss(
+       struct xfs_mount        *mp,
+       struct xfs_perag        *pag,
+       xfs_trans_t             *tp,
+       xfs_ino_t               ino,
+       struct xfs_inode        **ipp,
+       int                     flags,
+       int                     lock_flags)
+{
+       struct xfs_inode        *ip;
+       int                     error;
+       xfs_agino_t             agino = XFS_INO_TO_AGINO(mp, ino);
+       int                     iflags;
+
+       ip = xfs_inode_alloc(mp, ino);
+       if (!ip)
+               return ENOMEM;
+
+       error = xfs_iread(mp, tp, ip, flags);
+       if (error)
+               goto out_destroy;
+
+       trace_xfs_iget_miss(ip);
+
+       if ((ip->i_d.di_mode == 0) && !(flags & XFS_IGET_CREATE)) {
+               error = ENOENT;
+               goto out_destroy;
+       }
+
+       /*
+        * Preload the radix tree so we can insert safely under the
+        * write spinlock. Note that we cannot sleep inside the preload
+        * region. Since we can be called from transaction context, don't
+        * recurse into the file system.
+        */
+       if (radix_tree_preload(GFP_NOFS)) {
+               error = EAGAIN;
+               goto out_destroy;
+       }
+
+       /*
+        * Because the inode hasn't been added to the radix-tree yet it can't
+        * be found by another thread, so we can do the non-sleeping lock here.
+        */
+       if (lock_flags) {
+               if (!xfs_ilock_nowait(ip, lock_flags))
+                       BUG();
+       }
+
+       /*
+        * These values must be set before inserting the inode into the radix
+        * tree as the moment it is inserted a concurrent lookup (allowed by the
+        * RCU locking mechanism) can find it and that lookup must see that this
+        * is an inode currently under construction (i.e. that XFS_INEW is set).
+        * The ip->i_flags_lock that protects the XFS_INEW flag forms the
+        * memory barrier that ensures this detection works correctly at lookup
+        * time.
+        */
+       iflags = XFS_INEW;
+       if (flags & XFS_IGET_DONTCACHE)
+               iflags |= XFS_IDONTCACHE;
+       ip->i_udquot = ip->i_gdquot = NULL;
+       xfs_iflags_set(ip, iflags);
+
+       /* insert the new inode */
+       spin_lock(&pag->pag_ici_lock);
+       error = radix_tree_insert(&pag->pag_ici_root, agino, ip);
+       if (unlikely(error)) {
+               WARN_ON(error != -EEXIST);
+               XFS_STATS_INC(xs_ig_dup);
+               error = EAGAIN;
+               goto out_preload_end;
+       }
+       spin_unlock(&pag->pag_ici_lock);
+       radix_tree_preload_end();
+
+       *ipp = ip;
+       return 0;
+
+out_preload_end:
+       spin_unlock(&pag->pag_ici_lock);
+       radix_tree_preload_end();
+       if (lock_flags)
+               xfs_iunlock(ip, lock_flags);
+out_destroy:
+       __destroy_inode(VFS_I(ip));
+       xfs_inode_free(ip);
+       return error;
+}
+
+/*
+ * Look up an inode by number in the given file system.
+ * The inode is looked up in the cache held in each AG.
+ * If the inode is found in the cache, initialise the vfs inode
+ * if necessary.
+ *
+ * If it is not in core, read it in from the file system's device,
+ * add it to the cache and initialise the vfs inode.
+ *
+ * The inode is locked according to the value of the lock_flags parameter.
+ * This flag parameter indicates how and if the inode's IO lock and inode lock
+ * should be taken.
+ *
+ * mp -- the mount point structure for the current file system.  It points
+ *       to the inode hash table.
+ * tp -- a pointer to the current transaction if there is one.  This is
+ *       simply passed through to the xfs_iread() call.
+ * ino -- the number of the inode desired.  This is the unique identifier
+ *        within the file system for the inode being requested.
+ * lock_flags -- flags indicating how to lock the inode.  See the comment
+ *              for xfs_ilock() for a list of valid values.
+ */
+int
+xfs_iget(
+       xfs_mount_t     *mp,
+       xfs_trans_t     *tp,
+       xfs_ino_t       ino,
+       uint            flags,
+       uint            lock_flags,
+       xfs_inode_t     **ipp)
+{
+       xfs_inode_t     *ip;
+       int             error;
+       xfs_perag_t     *pag;
+       xfs_agino_t     agino;
+
+       /*
+        * xfs_reclaim_inode() uses the ILOCK to ensure an inode
+        * doesn't get freed while it's being referenced during a
+        * radix tree traversal here.  It assumes this function
+        * aqcuires only the ILOCK (and therefore it has no need to
+        * involve the IOLOCK in this synchronization).
+        */
+       ASSERT((lock_flags & (XFS_IOLOCK_EXCL | XFS_IOLOCK_SHARED)) == 0);
+
+       /* reject inode numbers outside existing AGs */
+       if (!ino || XFS_INO_TO_AGNO(mp, ino) >= mp->m_sb.sb_agcount)
+               return EINVAL;
+
+       /* get the perag structure and ensure that it's inode capable */
+       pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ino));
+       agino = XFS_INO_TO_AGINO(mp, ino);
+
+again:
+       error = 0;
+       rcu_read_lock();
+       ip = radix_tree_lookup(&pag->pag_ici_root, agino);
+
+       if (ip) {
+               error = xfs_iget_cache_hit(pag, ip, ino, flags, lock_flags);
+               if (error)
+                       goto out_error_or_again;
+       } else {
+               rcu_read_unlock();
+               XFS_STATS_INC(xs_ig_missed);
+
+               error = xfs_iget_cache_miss(mp, pag, tp, ino, &ip,
+                                                       flags, lock_flags);
+               if (error)
+                       goto out_error_or_again;
+       }
+       xfs_perag_put(pag);
+
+       *ipp = ip;
+
+       /*
+        * If we have a real type for an on-disk inode, we can set ops(&unlock)
+        * now.  If it's a new inode being created, xfs_ialloc will handle it.
+        */
+       if (xfs_iflags_test(ip, XFS_INEW) && ip->i_d.di_mode != 0)
+               xfs_setup_inode(ip);
+       return 0;
+
+out_error_or_again:
+       if (error == EAGAIN) {
+               delay(1);
+               goto again;
+       }
+       xfs_perag_put(pag);
+       return error;
+}
 
 /*
  * The inode lookup is done in batches to keep the amount of lock traffic and
@@ -215,224 +630,21 @@ xfs_inode_ag_iterator(
        return XFS_ERROR(last_error);
 }
 
-STATIC int
-xfs_sync_inode_data(
-       struct xfs_inode        *ip,
-       struct xfs_perag        *pag,
-       int                     flags)
-{
-       struct inode            *inode = VFS_I(ip);
-       struct address_space *mapping = inode->i_mapping;
-       int                     error = 0;
-
-       if (!mapping_tagged(mapping, PAGECACHE_TAG_DIRTY))
-               return 0;
-
-       if (!xfs_ilock_nowait(ip, XFS_IOLOCK_SHARED)) {
-               if (flags & SYNC_TRYLOCK)
-                       return 0;
-               xfs_ilock(ip, XFS_IOLOCK_SHARED);
-       }
-
-       error = xfs_flush_pages(ip, 0, -1, (flags & SYNC_WAIT) ?
-                               0 : XBF_ASYNC, FI_NONE);
-       xfs_iunlock(ip, XFS_IOLOCK_SHARED);
-       return error;
-}
-
-/*
- * Write out pagecache data for the whole filesystem.
- */
-STATIC int
-xfs_sync_data(
-       struct xfs_mount        *mp,
-       int                     flags)
-{
-       int                     error;
-
-       ASSERT((flags & ~(SYNC_TRYLOCK|SYNC_WAIT)) == 0);
-
-       error = xfs_inode_ag_iterator(mp, xfs_sync_inode_data, flags);
-       if (error)
-               return XFS_ERROR(error);
-
-       xfs_log_force(mp, (flags & SYNC_WAIT) ? XFS_LOG_SYNC : 0);
-       return 0;
-}
-
-STATIC int
-xfs_sync_fsdata(
-       struct xfs_mount        *mp)
-{
-       struct xfs_buf          *bp;
-       int                     error;
-
-       /*
-        * If the buffer is pinned then push on the log so we won't get stuck
-        * waiting in the write for someone, maybe ourselves, to flush the log.
-        *
-        * Even though we just pushed the log above, we did not have the
-        * superblock buffer locked at that point so it can become pinned in
-        * between there and here.
-        */
-       bp = xfs_getsb(mp, 0);
-       if (xfs_buf_ispinned(bp))
-               xfs_log_force(mp, 0);
-       error = xfs_bwrite(bp);
-       xfs_buf_relse(bp);
-       return error;
-}
-
-/*
- * When remounting a filesystem read-only or freezing the filesystem, we have
- * two phases to execute. This first phase is syncing the data before we
- * quiesce the filesystem, and the second is flushing all the inodes out after
- * we've waited for all the transactions created by the first phase to
- * complete. The second phase ensures that the inodes are written to their
- * location on disk rather than just existing in transactions in the log. This
- * means after a quiesce there is no log replay required to write the inodes to
- * disk (this is the main difference between a sync and a quiesce).
- */
-/*
- * First stage of freeze - no writers will make progress now we are here,
- * so we flush delwri and delalloc buffers here, then wait for all I/O to
- * complete.  Data is frozen at that point. Metadata is not frozen,
- * transactions can still occur here so don't bother emptying the AIL
- * because it'll just get dirty again.
- */
-int
-xfs_quiesce_data(
-       struct xfs_mount        *mp)
-{
-       int                     error, error2 = 0;
-
-       /* force out the log */
-       xfs_log_force(mp, XFS_LOG_SYNC);
-
-       /* write superblock and hoover up shutdown errors */
-       error = xfs_sync_fsdata(mp);
-
-       /* mark the log as covered if needed */
-       if (xfs_log_need_covered(mp))
-               error2 = xfs_fs_log_dummy(mp);
-
-       return error ? error : error2;
-}
-
-/*
- * Second stage of a quiesce. The data is already synced, now we have to take
- * care of the metadata. New transactions are already blocked, so we need to
- * wait for any remaining transactions to drain out before proceeding.
- */
-void
-xfs_quiesce_attr(
-       struct xfs_mount        *mp)
-{
-       int     error = 0;
-
-       /* wait for all modifications to complete */
-       while (atomic_read(&mp->m_active_trans) > 0)
-               delay(100);
-
-       /* reclaim inodes to do any IO before the freeze completes */
-       xfs_reclaim_inodes(mp, 0);
-       xfs_reclaim_inodes(mp, SYNC_WAIT);
-
-       /* flush all pending changes from the AIL */
-       xfs_ail_push_all_sync(mp->m_ail);
-
-       /*
-        * Just warn here till VFS can correctly support
-        * read-only remount without racing.
-        */
-       WARN_ON(atomic_read(&mp->m_active_trans) != 0);
-
-       /* Push the superblock and write an unmount record */
-       error = xfs_log_sbcount(mp);
-       if (error)
-               xfs_warn(mp, "xfs_attr_quiesce: failed to log sb changes. "
-                               "Frozen image may not be consistent.");
-       xfs_log_unmount_write(mp);
-
-       /*
-        * At this point we might have modified the superblock again and thus
-        * added an item to the AIL, thus flush it again.
-        */
-       xfs_ail_push_all_sync(mp->m_ail);
-
-       /*
-        * The superblock buffer is uncached and xfsaild_push() will lock and
-        * set the XBF_ASYNC flag on the buffer. We cannot do xfs_buf_iowait()
-        * here but a lock on the superblock buffer will block until iodone()
-        * has completed.
-        */
-       xfs_buf_lock(mp->m_sb_bp);
-       xfs_buf_unlock(mp->m_sb_bp);
-}
-
-static void
-xfs_syncd_queue_sync(
-       struct xfs_mount        *mp)
-{
-       queue_delayed_work(xfs_syncd_wq, &mp->m_sync_work,
-                               msecs_to_jiffies(xfs_syncd_centisecs * 10));
-}
-
-/*
- * Every sync period we need to unpin all items, reclaim inodes and sync
- * disk quotas.  We might need to cover the log to indicate that the
- * filesystem is idle and not frozen.
- */
-STATIC void
-xfs_sync_worker(
-       struct work_struct *work)
-{
-       struct xfs_mount *mp = container_of(to_delayed_work(work),
-                                       struct xfs_mount, m_sync_work);
-       int             error;
-
-       /*
-        * We shouldn't write/force the log if we are in the mount/unmount
-        * process or on a read only filesystem. The workqueue still needs to be
-        * active in both cases, however, because it is used for inode reclaim
-        * during these times.  Use the MS_ACTIVE flag to avoid doing anything
-        * during mount.  Doing work during unmount is avoided by calling
-        * cancel_delayed_work_sync on this work queue before tearing down
-        * the ail and the log in xfs_log_unmount.
-        */
-       if (!(mp->m_super->s_flags & MS_ACTIVE) &&
-           !(mp->m_flags & XFS_MOUNT_RDONLY)) {
-               /* dgc: errors ignored here */
-               if (mp->m_super->s_writers.frozen == SB_UNFROZEN &&
-                   xfs_log_need_covered(mp))
-                       error = xfs_fs_log_dummy(mp);
-               else
-                       xfs_log_force(mp, 0);
-
-               /* start pushing all the metadata that is currently
-                * dirty */
-               xfs_ail_push_all(mp->m_ail);
-       }
-
-       /* queue us up again */
-       xfs_syncd_queue_sync(mp);
-}
-
 /*
  * Queue a new inode reclaim pass if there are reclaimable inodes and there
  * isn't a reclaim pass already in progress. By default it runs every 5s based
- * on the xfs syncd work default of 30s. Perhaps this should have it's own
+ * on the xfs periodic sync default of 30s. Perhaps this should have it's own
  * tunable, but that can be done if this method proves to be ineffective or too
  * aggressive.
  */
 static void
-xfs_syncd_queue_reclaim(
+xfs_reclaim_work_queue(
        struct xfs_mount        *mp)
 {
 
        rcu_read_lock();
        if (radix_tree_tagged(&mp->m_perag_tree, XFS_ICI_RECLAIM_TAG)) {
-               queue_delayed_work(xfs_syncd_wq, &mp->m_reclaim_work,
+               queue_delayed_work(mp->m_reclaim_workqueue, &mp->m_reclaim_work,
                        msecs_to_jiffies(xfs_syncd_centisecs / 6 * 10));
        }
        rcu_read_unlock();
@@ -445,7 +657,7 @@ xfs_syncd_queue_reclaim(
  * goes low. It scans as quickly as possible avoiding locked inodes or those
  * already being flushed, and once done schedules a future pass.
  */
-STATIC void
+void
 xfs_reclaim_worker(
        struct work_struct *work)
 {
@@ -453,65 +665,10 @@ xfs_reclaim_worker(
                                        struct xfs_mount, m_reclaim_work);
 
        xfs_reclaim_inodes(mp, SYNC_TRYLOCK);
-       xfs_syncd_queue_reclaim(mp);
+       xfs_reclaim_work_queue(mp);
 }
 
-/*
- * Flush delayed allocate data, attempting to free up reserved space
- * from existing allocations.  At this point a new allocation attempt
- * has failed with ENOSPC and we are in the process of scratching our
- * heads, looking about for more room.
- *
- * Queue a new data flush if there isn't one already in progress and
- * wait for completion of the flush. This means that we only ever have one
- * inode flush in progress no matter how many ENOSPC events are occurring and
- * so will prevent the system from bogging down due to every concurrent
- * ENOSPC event scanning all the active inodes in the system for writeback.
- */
-void
-xfs_flush_inodes(
-       struct xfs_inode        *ip)
-{
-       struct xfs_mount        *mp = ip->i_mount;
-
-       queue_work(xfs_syncd_wq, &mp->m_flush_work);
-       flush_work(&mp->m_flush_work);
-}
-
-STATIC void
-xfs_flush_worker(
-       struct work_struct *work)
-{
-       struct xfs_mount *mp = container_of(work,
-                                       struct xfs_mount, m_flush_work);
-
-       xfs_sync_data(mp, SYNC_TRYLOCK);
-       xfs_sync_data(mp, SYNC_TRYLOCK | SYNC_WAIT);
-}
-
-int
-xfs_syncd_init(
-       struct xfs_mount        *mp)
-{
-       INIT_WORK(&mp->m_flush_work, xfs_flush_worker);
-       INIT_DELAYED_WORK(&mp->m_sync_work, xfs_sync_worker);
-       INIT_DELAYED_WORK(&mp->m_reclaim_work, xfs_reclaim_worker);
-
-       xfs_syncd_queue_sync(mp);
-
-       return 0;
-}
-
-void
-xfs_syncd_stop(
-       struct xfs_mount        *mp)
-{
-       cancel_delayed_work_sync(&mp->m_sync_work);
-       cancel_delayed_work_sync(&mp->m_reclaim_work);
-       cancel_work_sync(&mp->m_flush_work);
-}
-
-void
+static void
 __xfs_inode_set_reclaim_tag(
        struct xfs_perag        *pag,
        struct xfs_inode        *ip)
@@ -529,7 +686,7 @@ __xfs_inode_set_reclaim_tag(
                spin_unlock(&ip->i_mount->m_perag_lock);
 
                /* schedule periodic background inode reclaim */
-               xfs_syncd_queue_reclaim(ip->i_mount);
+               xfs_reclaim_work_queue(ip->i_mount);
 
                trace_xfs_perag_set_reclaim(ip->i_mount, pag->pag_agno,
                                                        -1, _RET_IP_);
@@ -577,7 +734,7 @@ __xfs_inode_clear_reclaim(
        }
 }
 
-void
+STATIC void
 __xfs_inode_clear_reclaim_tag(
        xfs_mount_t     *mp,
        xfs_perag_t     *pag,
@@ -787,9 +944,9 @@ out:
        /*
         * We could return EAGAIN here to make reclaim rescan the inode tree in
         * a short while. However, this just burns CPU time scanning the tree
-        * waiting for IO to complete and xfssyncd never goes back to the idle
-        * state. Instead, return 0 to let the next scheduled background reclaim
-        * attempt to reclaim the inode again.
+        * waiting for IO to complete and the reclaim work never goes back to
+        * the idle state. Instead, return 0 to let the next scheduled
+        * background reclaim attempt to reclaim the inode again.
         */
        return 0;
 }
@@ -800,7 +957,7 @@ out:
  * then a shut down during filesystem unmount reclaim walk leak all the
  * unreclaimed inodes.
  */
-int
+STATIC int
 xfs_reclaim_inodes_ag(
        struct xfs_mount        *mp,
        int                     flags,
@@ -945,7 +1102,7 @@ xfs_reclaim_inodes_nr(
        int                     nr_to_scan)
 {
        /* kick background reclaimer and push the AIL */
-       xfs_syncd_queue_reclaim(mp);
+       xfs_reclaim_work_queue(mp);
        xfs_ail_push_all(mp->m_ail);
 
        xfs_reclaim_inodes_ag(mp, SYNC_TRYLOCK | SYNC_WAIT, &nr_to_scan);
similarity index 73%
rename from fs/xfs/xfs_sync.h
rename to fs/xfs/xfs_icache.h
index 941202e7ac6e594e2c423c19bc89248397e39516..222e22f16b4ac9c97583aa69cff15c54393200f8 100644 (file)
@@ -24,24 +24,16 @@ struct xfs_perag;
 #define SYNC_WAIT              0x0001  /* wait for i/o to complete */
 #define SYNC_TRYLOCK           0x0002  /* only try to lock inodes */
 
-extern struct workqueue_struct *xfs_syncd_wq;  /* sync workqueue */
+int xfs_iget(struct xfs_mount *mp, struct xfs_trans *tp, xfs_ino_t ino,
+            uint flags, uint lock_flags, xfs_inode_t **ipp);
 
-int xfs_syncd_init(struct xfs_mount *mp);
-void xfs_syncd_stop(struct xfs_mount *mp);
-
-int xfs_quiesce_data(struct xfs_mount *mp);
-void xfs_quiesce_attr(struct xfs_mount *mp);
-
-void xfs_flush_inodes(struct xfs_inode *ip);
+void xfs_reclaim_worker(struct work_struct *work);
 
 int xfs_reclaim_inodes(struct xfs_mount *mp, int mode);
 int xfs_reclaim_inodes_count(struct xfs_mount *mp);
 void xfs_reclaim_inodes_nr(struct xfs_mount *mp, int nr_to_scan);
 
 void xfs_inode_set_reclaim_tag(struct xfs_inode *ip);
-void __xfs_inode_set_reclaim_tag(struct xfs_perag *pag, struct xfs_inode *ip);
-void __xfs_inode_clear_reclaim_tag(struct xfs_mount *mp, struct xfs_perag *pag,
-                               struct xfs_inode *ip);
 
 int xfs_sync_inode_grab(struct xfs_inode *ip);
 int xfs_inode_ag_iterator(struct xfs_mount *mp,
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c
deleted file mode 100644 (file)
index 784a803..0000000
+++ /dev/null
@@ -1,705 +0,0 @@
-/*
- * Copyright (c) 2000-2005 Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-#include "xfs.h"
-#include "xfs_fs.h"
-#include "xfs_types.h"
-#include "xfs_acl.h"
-#include "xfs_log.h"
-#include "xfs_inum.h"
-#include "xfs_trans.h"
-#include "xfs_sb.h"
-#include "xfs_ag.h"
-#include "xfs_mount.h"
-#include "xfs_bmap_btree.h"
-#include "xfs_alloc_btree.h"
-#include "xfs_ialloc_btree.h"
-#include "xfs_dinode.h"
-#include "xfs_inode.h"
-#include "xfs_btree.h"
-#include "xfs_ialloc.h"
-#include "xfs_quota.h"
-#include "xfs_utils.h"
-#include "xfs_trans_priv.h"
-#include "xfs_inode_item.h"
-#include "xfs_bmap.h"
-#include "xfs_trace.h"
-
-
-/*
- * Allocate and initialise an xfs_inode.
- */
-STATIC struct xfs_inode *
-xfs_inode_alloc(
-       struct xfs_mount        *mp,
-       xfs_ino_t               ino)
-{
-       struct xfs_inode        *ip;
-
-       /*
-        * if this didn't occur in transactions, we could use
-        * KM_MAYFAIL and return NULL here on ENOMEM. Set the
-        * code up to do this anyway.
-        */
-       ip = kmem_zone_alloc(xfs_inode_zone, KM_SLEEP);
-       if (!ip)
-               return NULL;
-       if (inode_init_always(mp->m_super, VFS_I(ip))) {
-               kmem_zone_free(xfs_inode_zone, ip);
-               return NULL;
-       }
-
-       ASSERT(atomic_read(&ip->i_pincount) == 0);
-       ASSERT(!spin_is_locked(&ip->i_flags_lock));
-       ASSERT(!xfs_isiflocked(ip));
-       ASSERT(ip->i_ino == 0);
-
-       mrlock_init(&ip->i_iolock, MRLOCK_BARRIER, "xfsio", ip->i_ino);
-
-       /* initialise the xfs inode */
-       ip->i_ino = ino;
-       ip->i_mount = mp;
-       memset(&ip->i_imap, 0, sizeof(struct xfs_imap));
-       ip->i_afp = NULL;
-       memset(&ip->i_df, 0, sizeof(xfs_ifork_t));
-       ip->i_flags = 0;
-       ip->i_delayed_blks = 0;
-       memset(&ip->i_d, 0, sizeof(xfs_icdinode_t));
-
-       return ip;
-}
-
-STATIC void
-xfs_inode_free_callback(
-       struct rcu_head         *head)
-{
-       struct inode            *inode = container_of(head, struct inode, i_rcu);
-       struct xfs_inode        *ip = XFS_I(inode);
-
-       kmem_zone_free(xfs_inode_zone, ip);
-}
-
-void
-xfs_inode_free(
-       struct xfs_inode        *ip)
-{
-       switch (ip->i_d.di_mode & S_IFMT) {
-       case S_IFREG:
-       case S_IFDIR:
-       case S_IFLNK:
-               xfs_idestroy_fork(ip, XFS_DATA_FORK);
-               break;
-       }
-
-       if (ip->i_afp)
-               xfs_idestroy_fork(ip, XFS_ATTR_FORK);
-
-       if (ip->i_itemp) {
-               ASSERT(!(ip->i_itemp->ili_item.li_flags & XFS_LI_IN_AIL));
-               xfs_inode_item_destroy(ip);
-               ip->i_itemp = NULL;
-       }
-
-       /* asserts to verify all state is correct here */
-       ASSERT(atomic_read(&ip->i_pincount) == 0);
-       ASSERT(!spin_is_locked(&ip->i_flags_lock));
-       ASSERT(!xfs_isiflocked(ip));
-
-       /*
-        * Because we use RCU freeing we need to ensure the inode always
-        * appears to be reclaimed with an invalid inode number when in the
-        * free state. The ip->i_flags_lock provides the barrier against lookup
-        * races.
-        */
-       spin_lock(&ip->i_flags_lock);
-       ip->i_flags = XFS_IRECLAIM;
-       ip->i_ino = 0;
-       spin_unlock(&ip->i_flags_lock);
-
-       call_rcu(&VFS_I(ip)->i_rcu, xfs_inode_free_callback);
-}
-
-/*
- * Check the validity of the inode we just found it the cache
- */
-static int
-xfs_iget_cache_hit(
-       struct xfs_perag        *pag,
-       struct xfs_inode        *ip,
-       xfs_ino_t               ino,
-       int                     flags,
-       int                     lock_flags) __releases(RCU)
-{
-       struct inode            *inode = VFS_I(ip);
-       struct xfs_mount        *mp = ip->i_mount;
-       int                     error;
-
-       /*
-        * check for re-use of an inode within an RCU grace period due to the
-        * radix tree nodes not being updated yet. We monitor for this by
-        * setting the inode number to zero before freeing the inode structure.
-        * If the inode has been reallocated and set up, then the inode number
-        * will not match, so check for that, too.
-        */
-       spin_lock(&ip->i_flags_lock);
-       if (ip->i_ino != ino) {
-               trace_xfs_iget_skip(ip);
-               XFS_STATS_INC(xs_ig_frecycle);
-               error = EAGAIN;
-               goto out_error;
-       }
-
-
-       /*
-        * If we are racing with another cache hit that is currently
-        * instantiating this inode or currently recycling it out of
-        * reclaimabe state, wait for the initialisation to complete
-        * before continuing.
-        *
-        * XXX(hch): eventually we should do something equivalent to
-        *           wait_on_inode to wait for these flags to be cleared
-        *           instead of polling for it.
-        */
-       if (ip->i_flags & (XFS_INEW|XFS_IRECLAIM)) {
-               trace_xfs_iget_skip(ip);
-               XFS_STATS_INC(xs_ig_frecycle);
-               error = EAGAIN;
-               goto out_error;
-       }
-
-       /*
-        * If lookup is racing with unlink return an error immediately.
-        */
-       if (ip->i_d.di_mode == 0 && !(flags & XFS_IGET_CREATE)) {
-               error = ENOENT;
-               goto out_error;
-       }
-
-       /*
-        * If IRECLAIMABLE is set, we've torn down the VFS inode already.
-        * Need to carefully get it back into useable state.
-        */
-       if (ip->i_flags & XFS_IRECLAIMABLE) {
-               trace_xfs_iget_reclaim(ip);
-
-               /*
-                * We need to set XFS_IRECLAIM to prevent xfs_reclaim_inode
-                * from stomping over us while we recycle the inode.  We can't
-                * clear the radix tree reclaimable tag yet as it requires
-                * pag_ici_lock to be held exclusive.
-                */
-               ip->i_flags |= XFS_IRECLAIM;
-
-               spin_unlock(&ip->i_flags_lock);
-               rcu_read_unlock();
-
-               error = -inode_init_always(mp->m_super, inode);
-               if (error) {
-                       /*
-                        * Re-initializing the inode failed, and we are in deep
-                        * trouble.  Try to re-add it to the reclaim list.
-                        */
-                       rcu_read_lock();
-                       spin_lock(&ip->i_flags_lock);
-
-                       ip->i_flags &= ~(XFS_INEW | XFS_IRECLAIM);
-                       ASSERT(ip->i_flags & XFS_IRECLAIMABLE);
-                       trace_xfs_iget_reclaim_fail(ip);
-                       goto out_error;
-               }
-
-               spin_lock(&pag->pag_ici_lock);
-               spin_lock(&ip->i_flags_lock);
-
-               /*
-                * Clear the per-lifetime state in the inode as we are now
-                * effectively a new inode and need to return to the initial
-                * state before reuse occurs.
-                */
-               ip->i_flags &= ~XFS_IRECLAIM_RESET_FLAGS;
-               ip->i_flags |= XFS_INEW;
-               __xfs_inode_clear_reclaim_tag(mp, pag, ip);
-               inode->i_state = I_NEW;
-
-               ASSERT(!rwsem_is_locked(&ip->i_iolock.mr_lock));
-               mrlock_init(&ip->i_iolock, MRLOCK_BARRIER, "xfsio", ip->i_ino);
-
-               spin_unlock(&ip->i_flags_lock);
-               spin_unlock(&pag->pag_ici_lock);
-       } else {
-               /* If the VFS inode is being torn down, pause and try again. */
-               if (!igrab(inode)) {
-                       trace_xfs_iget_skip(ip);
-                       error = EAGAIN;
-                       goto out_error;
-               }
-
-               /* We've got a live one. */
-               spin_unlock(&ip->i_flags_lock);
-               rcu_read_unlock();
-               trace_xfs_iget_hit(ip);
-       }
-
-       if (lock_flags != 0)
-               xfs_ilock(ip, lock_flags);
-
-       xfs_iflags_clear(ip, XFS_ISTALE | XFS_IDONTCACHE);
-       XFS_STATS_INC(xs_ig_found);
-
-       return 0;
-
-out_error:
-       spin_unlock(&ip->i_flags_lock);
-       rcu_read_unlock();
-       return error;
-}
-
-
-static int
-xfs_iget_cache_miss(
-       struct xfs_mount        *mp,
-       struct xfs_perag        *pag,
-       xfs_trans_t             *tp,
-       xfs_ino_t               ino,
-       struct xfs_inode        **ipp,
-       int                     flags,
-       int                     lock_flags)
-{
-       struct xfs_inode        *ip;
-       int                     error;
-       xfs_agino_t             agino = XFS_INO_TO_AGINO(mp, ino);
-       int                     iflags;
-
-       ip = xfs_inode_alloc(mp, ino);
-       if (!ip)
-               return ENOMEM;
-
-       error = xfs_iread(mp, tp, ip, flags);
-       if (error)
-               goto out_destroy;
-
-       trace_xfs_iget_miss(ip);
-
-       if ((ip->i_d.di_mode == 0) && !(flags & XFS_IGET_CREATE)) {
-               error = ENOENT;
-               goto out_destroy;
-       }
-
-       /*
-        * Preload the radix tree so we can insert safely under the
-        * write spinlock. Note that we cannot sleep inside the preload
-        * region. Since we can be called from transaction context, don't
-        * recurse into the file system.
-        */
-       if (radix_tree_preload(GFP_NOFS)) {
-               error = EAGAIN;
-               goto out_destroy;
-       }
-
-       /*
-        * Because the inode hasn't been added to the radix-tree yet it can't
-        * be found by another thread, so we can do the non-sleeping lock here.
-        */
-       if (lock_flags) {
-               if (!xfs_ilock_nowait(ip, lock_flags))
-                       BUG();
-       }
-
-       /*
-        * These values must be set before inserting the inode into the radix
-        * tree as the moment it is inserted a concurrent lookup (allowed by the
-        * RCU locking mechanism) can find it and that lookup must see that this
-        * is an inode currently under construction (i.e. that XFS_INEW is set).
-        * The ip->i_flags_lock that protects the XFS_INEW flag forms the
-        * memory barrier that ensures this detection works correctly at lookup
-        * time.
-        */
-       iflags = XFS_INEW;
-       if (flags & XFS_IGET_DONTCACHE)
-               iflags |= XFS_IDONTCACHE;
-       ip->i_udquot = ip->i_gdquot = NULL;
-       xfs_iflags_set(ip, iflags);
-
-       /* insert the new inode */
-       spin_lock(&pag->pag_ici_lock);
-       error = radix_tree_insert(&pag->pag_ici_root, agino, ip);
-       if (unlikely(error)) {
-               WARN_ON(error != -EEXIST);
-               XFS_STATS_INC(xs_ig_dup);
-               error = EAGAIN;
-               goto out_preload_end;
-       }
-       spin_unlock(&pag->pag_ici_lock);
-       radix_tree_preload_end();
-
-       *ipp = ip;
-       return 0;
-
-out_preload_end:
-       spin_unlock(&pag->pag_ici_lock);
-       radix_tree_preload_end();
-       if (lock_flags)
-               xfs_iunlock(ip, lock_flags);
-out_destroy:
-       __destroy_inode(VFS_I(ip));
-       xfs_inode_free(ip);
-       return error;
-}
-
-/*
- * Look up an inode by number in the given file system.
- * The inode is looked up in the cache held in each AG.
- * If the inode is found in the cache, initialise the vfs inode
- * if necessary.
- *
- * If it is not in core, read it in from the file system's device,
- * add it to the cache and initialise the vfs inode.
- *
- * The inode is locked according to the value of the lock_flags parameter.
- * This flag parameter indicates how and if the inode's IO lock and inode lock
- * should be taken.
- *
- * mp -- the mount point structure for the current file system.  It points
- *       to the inode hash table.
- * tp -- a pointer to the current transaction if there is one.  This is
- *       simply passed through to the xfs_iread() call.
- * ino -- the number of the inode desired.  This is the unique identifier
- *        within the file system for the inode being requested.
- * lock_flags -- flags indicating how to lock the inode.  See the comment
- *              for xfs_ilock() for a list of valid values.
- */
-int
-xfs_iget(
-       xfs_mount_t     *mp,
-       xfs_trans_t     *tp,
-       xfs_ino_t       ino,
-       uint            flags,
-       uint            lock_flags,
-       xfs_inode_t     **ipp)
-{
-       xfs_inode_t     *ip;
-       int             error;
-       xfs_perag_t     *pag;
-       xfs_agino_t     agino;
-
-       /*
-        * xfs_reclaim_inode() uses the ILOCK to ensure an inode
-        * doesn't get freed while it's being referenced during a
-        * radix tree traversal here.  It assumes this function
-        * aqcuires only the ILOCK (and therefore it has no need to
-        * involve the IOLOCK in this synchronization).
-        */
-       ASSERT((lock_flags & (XFS_IOLOCK_EXCL | XFS_IOLOCK_SHARED)) == 0);
-
-       /* reject inode numbers outside existing AGs */
-       if (!ino || XFS_INO_TO_AGNO(mp, ino) >= mp->m_sb.sb_agcount)
-               return EINVAL;
-
-       /* get the perag structure and ensure that it's inode capable */
-       pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ino));
-       agino = XFS_INO_TO_AGINO(mp, ino);
-
-again:
-       error = 0;
-       rcu_read_lock();
-       ip = radix_tree_lookup(&pag->pag_ici_root, agino);
-
-       if (ip) {
-               error = xfs_iget_cache_hit(pag, ip, ino, flags, lock_flags);
-               if (error)
-                       goto out_error_or_again;
-       } else {
-               rcu_read_unlock();
-               XFS_STATS_INC(xs_ig_missed);
-
-               error = xfs_iget_cache_miss(mp, pag, tp, ino, &ip,
-                                                       flags, lock_flags);
-               if (error)
-                       goto out_error_or_again;
-       }
-       xfs_perag_put(pag);
-
-       *ipp = ip;
-
-       /*
-        * If we have a real type for an on-disk inode, we can set ops(&unlock)
-        * now.  If it's a new inode being created, xfs_ialloc will handle it.
-        */
-       if (xfs_iflags_test(ip, XFS_INEW) && ip->i_d.di_mode != 0)
-               xfs_setup_inode(ip);
-       return 0;
-
-out_error_or_again:
-       if (error == EAGAIN) {
-               delay(1);
-               goto again;
-       }
-       xfs_perag_put(pag);
-       return error;
-}
-
-/*
- * This is a wrapper routine around the xfs_ilock() routine
- * used to centralize some grungy code.  It is used in places
- * that wish to lock the inode solely for reading the extents.
- * The reason these places can't just call xfs_ilock(SHARED)
- * is that the inode lock also guards to bringing in of the
- * extents from disk for a file in b-tree format.  If the inode
- * is in b-tree format, then we need to lock the inode exclusively
- * until the extents are read in.  Locking it exclusively all
- * the time would limit our parallelism unnecessarily, though.
- * What we do instead is check to see if the extents have been
- * read in yet, and only lock the inode exclusively if they
- * have not.
- *
- * The function returns a value which should be given to the
- * corresponding xfs_iunlock_map_shared().  This value is
- * the mode in which the lock was actually taken.
- */
-uint
-xfs_ilock_map_shared(
-       xfs_inode_t     *ip)
-{
-       uint    lock_mode;
-
-       if ((ip->i_d.di_format == XFS_DINODE_FMT_BTREE) &&
-           ((ip->i_df.if_flags & XFS_IFEXTENTS) == 0)) {
-               lock_mode = XFS_ILOCK_EXCL;
-       } else {
-               lock_mode = XFS_ILOCK_SHARED;
-       }
-
-       xfs_ilock(ip, lock_mode);
-
-       return lock_mode;
-}
-
-/*
- * This is simply the unlock routine to go with xfs_ilock_map_shared().
- * All it does is call xfs_iunlock() with the given lock_mode.
- */
-void
-xfs_iunlock_map_shared(
-       xfs_inode_t     *ip,
-       unsigned int    lock_mode)
-{
-       xfs_iunlock(ip, lock_mode);
-}
-
-/*
- * The xfs inode contains 2 locks: a multi-reader lock called the
- * i_iolock and a multi-reader lock called the i_lock.  This routine
- * allows either or both of the locks to be obtained.
- *
- * The 2 locks should always be ordered so that the IO lock is
- * obtained first in order to prevent deadlock.
- *
- * ip -- the inode being locked
- * lock_flags -- this parameter indicates the inode's locks
- *       to be locked.  It can be:
- *             XFS_IOLOCK_SHARED,
- *             XFS_IOLOCK_EXCL,
- *             XFS_ILOCK_SHARED,
- *             XFS_ILOCK_EXCL,
- *             XFS_IOLOCK_SHARED | XFS_ILOCK_SHARED,
- *             XFS_IOLOCK_SHARED | XFS_ILOCK_EXCL,
- *             XFS_IOLOCK_EXCL | XFS_ILOCK_SHARED,
- *             XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL
- */
-void
-xfs_ilock(
-       xfs_inode_t             *ip,
-       uint                    lock_flags)
-{
-       /*
-        * You can't set both SHARED and EXCL for the same lock,
-        * and only XFS_IOLOCK_SHARED, XFS_IOLOCK_EXCL, XFS_ILOCK_SHARED,
-        * and XFS_ILOCK_EXCL are valid values to set in lock_flags.
-        */
-       ASSERT((lock_flags & (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL)) !=
-              (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL));
-       ASSERT((lock_flags & (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)) !=
-              (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL));
-       ASSERT((lock_flags & ~(XFS_LOCK_MASK | XFS_LOCK_DEP_MASK)) == 0);
-
-       if (lock_flags & XFS_IOLOCK_EXCL)
-               mrupdate_nested(&ip->i_iolock, XFS_IOLOCK_DEP(lock_flags));
-       else if (lock_flags & XFS_IOLOCK_SHARED)
-               mraccess_nested(&ip->i_iolock, XFS_IOLOCK_DEP(lock_flags));
-
-       if (lock_flags & XFS_ILOCK_EXCL)
-               mrupdate_nested(&ip->i_lock, XFS_ILOCK_DEP(lock_flags));
-       else if (lock_flags & XFS_ILOCK_SHARED)
-               mraccess_nested(&ip->i_lock, XFS_ILOCK_DEP(lock_flags));
-
-       trace_xfs_ilock(ip, lock_flags, _RET_IP_);
-}
-
-/*
- * This is just like xfs_ilock(), except that the caller
- * is guaranteed not to sleep.  It returns 1 if it gets
- * the requested locks and 0 otherwise.  If the IO lock is
- * obtained but the inode lock cannot be, then the IO lock
- * is dropped before returning.
- *
- * ip -- the inode being locked
- * lock_flags -- this parameter indicates the inode's locks to be
- *       to be locked.  See the comment for xfs_ilock() for a list
- *      of valid values.
- */
-int
-xfs_ilock_nowait(
-       xfs_inode_t             *ip,
-       uint                    lock_flags)
-{
-       /*
-        * You can't set both SHARED and EXCL for the same lock,
-        * and only XFS_IOLOCK_SHARED, XFS_IOLOCK_EXCL, XFS_ILOCK_SHARED,
-        * and XFS_ILOCK_EXCL are valid values to set in lock_flags.
-        */
-       ASSERT((lock_flags & (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL)) !=
-              (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL));
-       ASSERT((lock_flags & (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)) !=
-              (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL));
-       ASSERT((lock_flags & ~(XFS_LOCK_MASK | XFS_LOCK_DEP_MASK)) == 0);
-
-       if (lock_flags & XFS_IOLOCK_EXCL) {
-               if (!mrtryupdate(&ip->i_iolock))
-                       goto out;
-       } else if (lock_flags & XFS_IOLOCK_SHARED) {
-               if (!mrtryaccess(&ip->i_iolock))
-                       goto out;
-       }
-       if (lock_flags & XFS_ILOCK_EXCL) {
-               if (!mrtryupdate(&ip->i_lock))
-                       goto out_undo_iolock;
-       } else if (lock_flags & XFS_ILOCK_SHARED) {
-               if (!mrtryaccess(&ip->i_lock))
-                       goto out_undo_iolock;
-       }
-       trace_xfs_ilock_nowait(ip, lock_flags, _RET_IP_);
-       return 1;
-
- out_undo_iolock:
-       if (lock_flags & XFS_IOLOCK_EXCL)
-               mrunlock_excl(&ip->i_iolock);
-       else if (lock_flags & XFS_IOLOCK_SHARED)
-               mrunlock_shared(&ip->i_iolock);
- out:
-       return 0;
-}
-
-/*
- * xfs_iunlock() is used to drop the inode locks acquired with
- * xfs_ilock() and xfs_ilock_nowait().  The caller must pass
- * in the flags given to xfs_ilock() or xfs_ilock_nowait() so
- * that we know which locks to drop.
- *
- * ip -- the inode being unlocked
- * lock_flags -- this parameter indicates the inode's locks to be
- *       to be unlocked.  See the comment for xfs_ilock() for a list
- *      of valid values for this parameter.
- *
- */
-void
-xfs_iunlock(
-       xfs_inode_t             *ip,
-       uint                    lock_flags)
-{
-       /*
-        * You can't set both SHARED and EXCL for the same lock,
-        * and only XFS_IOLOCK_SHARED, XFS_IOLOCK_EXCL, XFS_ILOCK_SHARED,
-        * and XFS_ILOCK_EXCL are valid values to set in lock_flags.
-        */
-       ASSERT((lock_flags & (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL)) !=
-              (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL));
-       ASSERT((lock_flags & (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)) !=
-              (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL));
-       ASSERT((lock_flags & ~(XFS_LOCK_MASK | XFS_LOCK_DEP_MASK)) == 0);
-       ASSERT(lock_flags != 0);
-
-       if (lock_flags & XFS_IOLOCK_EXCL)
-               mrunlock_excl(&ip->i_iolock);
-       else if (lock_flags & XFS_IOLOCK_SHARED)
-               mrunlock_shared(&ip->i_iolock);
-
-       if (lock_flags & XFS_ILOCK_EXCL)
-               mrunlock_excl(&ip->i_lock);
-       else if (lock_flags & XFS_ILOCK_SHARED)
-               mrunlock_shared(&ip->i_lock);
-
-       trace_xfs_iunlock(ip, lock_flags, _RET_IP_);
-}
-
-/*
- * give up write locks.  the i/o lock cannot be held nested
- * if it is being demoted.
- */
-void
-xfs_ilock_demote(
-       xfs_inode_t             *ip,
-       uint                    lock_flags)
-{
-       ASSERT(lock_flags & (XFS_IOLOCK_EXCL|XFS_ILOCK_EXCL));
-       ASSERT((lock_flags & ~(XFS_IOLOCK_EXCL|XFS_ILOCK_EXCL)) == 0);
-
-       if (lock_flags & XFS_ILOCK_EXCL)
-               mrdemote(&ip->i_lock);
-       if (lock_flags & XFS_IOLOCK_EXCL)
-               mrdemote(&ip->i_iolock);
-
-       trace_xfs_ilock_demote(ip, lock_flags, _RET_IP_);
-}
-
-#ifdef DEBUG
-int
-xfs_isilocked(
-       xfs_inode_t             *ip,
-       uint                    lock_flags)
-{
-       if (lock_flags & (XFS_ILOCK_EXCL|XFS_ILOCK_SHARED)) {
-               if (!(lock_flags & XFS_ILOCK_SHARED))
-                       return !!ip->i_lock.mr_writer;
-               return rwsem_is_locked(&ip->i_lock.mr_lock);
-       }
-
-       if (lock_flags & (XFS_IOLOCK_EXCL|XFS_IOLOCK_SHARED)) {
-               if (!(lock_flags & XFS_IOLOCK_SHARED))
-                       return !!ip->i_iolock.mr_writer;
-               return rwsem_is_locked(&ip->i_iolock.mr_lock);
-       }
-
-       ASSERT(0);
-       return 0;
-}
-#endif
-
-void
-__xfs_iflock(
-       struct xfs_inode        *ip)
-{
-       wait_queue_head_t *wq = bit_waitqueue(&ip->i_flags, __XFS_IFLOCK_BIT);
-       DEFINE_WAIT_BIT(wait, &ip->i_flags, __XFS_IFLOCK_BIT);
-
-       do {
-               prepare_to_wait_exclusive(wq, &wait.wait, TASK_UNINTERRUPTIBLE);
-               if (xfs_isiflocked(ip))
-                       io_schedule();
-       } while (!xfs_iflock_nowait(ip));
-
-       finish_wait(wq, &wait.wait);
-}
index 2778258fcfa239e07dbc79edf6cb4750b7e13dd8..bba8f37525b3867576aea0acaf3adddbadbe7f2b 100644 (file)
@@ -45,6 +45,7 @@
 #include "xfs_filestream.h"
 #include "xfs_vnodeops.h"
 #include "xfs_trace.h"
+#include "xfs_icache.h"
 
 kmem_zone_t *xfs_ifork_zone;
 kmem_zone_t *xfs_inode_zone;
@@ -74,6 +75,256 @@ xfs_get_extsz_hint(
        return 0;
 }
 
+/*
+ * This is a wrapper routine around the xfs_ilock() routine used to centralize
+ * some grungy code.  It is used in places that wish to lock the inode solely
+ * for reading the extents.  The reason these places can't just call
+ * xfs_ilock(SHARED) is that the inode lock also guards to bringing in of the
+ * extents from disk for a file in b-tree format.  If the inode is in b-tree
+ * format, then we need to lock the inode exclusively until the extents are read
+ * in.  Locking it exclusively all the time would limit our parallelism
+ * unnecessarily, though.  What we do instead is check to see if the extents
+ * have been read in yet, and only lock the inode exclusively if they have not.
+ *
+ * The function returns a value which should be given to the corresponding
+ * xfs_iunlock_map_shared().  This value is the mode in which the lock was
+ * actually taken.
+ */
+uint
+xfs_ilock_map_shared(
+       xfs_inode_t     *ip)
+{
+       uint    lock_mode;
+
+       if ((ip->i_d.di_format == XFS_DINODE_FMT_BTREE) &&
+           ((ip->i_df.if_flags & XFS_IFEXTENTS) == 0)) {
+               lock_mode = XFS_ILOCK_EXCL;
+       } else {
+               lock_mode = XFS_ILOCK_SHARED;
+       }
+
+       xfs_ilock(ip, lock_mode);
+
+       return lock_mode;
+}
+
+/*
+ * This is simply the unlock routine to go with xfs_ilock_map_shared().
+ * All it does is call xfs_iunlock() with the given lock_mode.
+ */
+void
+xfs_iunlock_map_shared(
+       xfs_inode_t     *ip,
+       unsigned int    lock_mode)
+{
+       xfs_iunlock(ip, lock_mode);
+}
+
+/*
+ * The xfs inode contains 2 locks: a multi-reader lock called the
+ * i_iolock and a multi-reader lock called the i_lock.  This routine
+ * allows either or both of the locks to be obtained.
+ *
+ * The 2 locks should always be ordered so that the IO lock is
+ * obtained first in order to prevent deadlock.
+ *
+ * ip -- the inode being locked
+ * lock_flags -- this parameter indicates the inode's locks
+ *       to be locked.  It can be:
+ *             XFS_IOLOCK_SHARED,
+ *             XFS_IOLOCK_EXCL,
+ *             XFS_ILOCK_SHARED,
+ *             XFS_ILOCK_EXCL,
+ *             XFS_IOLOCK_SHARED | XFS_ILOCK_SHARED,
+ *             XFS_IOLOCK_SHARED | XFS_ILOCK_EXCL,
+ *             XFS_IOLOCK_EXCL | XFS_ILOCK_SHARED,
+ *             XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL
+ */
+void
+xfs_ilock(
+       xfs_inode_t             *ip,
+       uint                    lock_flags)
+{
+       trace_xfs_ilock(ip, lock_flags, _RET_IP_);
+
+       /*
+        * You can't set both SHARED and EXCL for the same lock,
+        * and only XFS_IOLOCK_SHARED, XFS_IOLOCK_EXCL, XFS_ILOCK_SHARED,
+        * and XFS_ILOCK_EXCL are valid values to set in lock_flags.
+        */
+       ASSERT((lock_flags & (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL)) !=
+              (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL));
+       ASSERT((lock_flags & (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)) !=
+              (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL));
+       ASSERT((lock_flags & ~(XFS_LOCK_MASK | XFS_LOCK_DEP_MASK)) == 0);
+
+       if (lock_flags & XFS_IOLOCK_EXCL)
+               mrupdate_nested(&ip->i_iolock, XFS_IOLOCK_DEP(lock_flags));
+       else if (lock_flags & XFS_IOLOCK_SHARED)
+               mraccess_nested(&ip->i_iolock, XFS_IOLOCK_DEP(lock_flags));
+
+       if (lock_flags & XFS_ILOCK_EXCL)
+               mrupdate_nested(&ip->i_lock, XFS_ILOCK_DEP(lock_flags));
+       else if (lock_flags & XFS_ILOCK_SHARED)
+               mraccess_nested(&ip->i_lock, XFS_ILOCK_DEP(lock_flags));
+}
+
+/*
+ * This is just like xfs_ilock(), except that the caller
+ * is guaranteed not to sleep.  It returns 1 if it gets
+ * the requested locks and 0 otherwise.  If the IO lock is
+ * obtained but the inode lock cannot be, then the IO lock
+ * is dropped before returning.
+ *
+ * ip -- the inode being locked
+ * lock_flags -- this parameter indicates the inode's locks to be
+ *       to be locked.  See the comment for xfs_ilock() for a list
+ *      of valid values.
+ */
+int
+xfs_ilock_nowait(
+       xfs_inode_t             *ip,
+       uint                    lock_flags)
+{
+       trace_xfs_ilock_nowait(ip, lock_flags, _RET_IP_);
+
+       /*
+        * You can't set both SHARED and EXCL for the same lock,
+        * and only XFS_IOLOCK_SHARED, XFS_IOLOCK_EXCL, XFS_ILOCK_SHARED,
+        * and XFS_ILOCK_EXCL are valid values to set in lock_flags.
+        */
+       ASSERT((lock_flags & (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL)) !=
+              (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL));
+       ASSERT((lock_flags & (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)) !=
+              (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL));
+       ASSERT((lock_flags & ~(XFS_LOCK_MASK | XFS_LOCK_DEP_MASK)) == 0);
+
+       if (lock_flags & XFS_IOLOCK_EXCL) {
+               if (!mrtryupdate(&ip->i_iolock))
+                       goto out;
+       } else if (lock_flags & XFS_IOLOCK_SHARED) {
+               if (!mrtryaccess(&ip->i_iolock))
+                       goto out;
+       }
+       if (lock_flags & XFS_ILOCK_EXCL) {
+               if (!mrtryupdate(&ip->i_lock))
+                       goto out_undo_iolock;
+       } else if (lock_flags & XFS_ILOCK_SHARED) {
+               if (!mrtryaccess(&ip->i_lock))
+                       goto out_undo_iolock;
+       }
+       return 1;
+
+ out_undo_iolock:
+       if (lock_flags & XFS_IOLOCK_EXCL)
+               mrunlock_excl(&ip->i_iolock);
+       else if (lock_flags & XFS_IOLOCK_SHARED)
+               mrunlock_shared(&ip->i_iolock);
+ out:
+       return 0;
+}
+
+/*
+ * xfs_iunlock() is used to drop the inode locks acquired with
+ * xfs_ilock() and xfs_ilock_nowait().  The caller must pass
+ * in the flags given to xfs_ilock() or xfs_ilock_nowait() so
+ * that we know which locks to drop.
+ *
+ * ip -- the inode being unlocked
+ * lock_flags -- this parameter indicates the inode's locks to be
+ *       to be unlocked.  See the comment for xfs_ilock() for a list
+ *      of valid values for this parameter.
+ *
+ */
+void
+xfs_iunlock(
+       xfs_inode_t             *ip,
+       uint                    lock_flags)
+{
+       /*
+        * You can't set both SHARED and EXCL for the same lock,
+        * and only XFS_IOLOCK_SHARED, XFS_IOLOCK_EXCL, XFS_ILOCK_SHARED,
+        * and XFS_ILOCK_EXCL are valid values to set in lock_flags.
+        */
+       ASSERT((lock_flags & (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL)) !=
+              (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL));
+       ASSERT((lock_flags & (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)) !=
+              (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL));
+       ASSERT((lock_flags & ~(XFS_LOCK_MASK | XFS_LOCK_DEP_MASK)) == 0);
+       ASSERT(lock_flags != 0);
+
+       if (lock_flags & XFS_IOLOCK_EXCL)
+               mrunlock_excl(&ip->i_iolock);
+       else if (lock_flags & XFS_IOLOCK_SHARED)
+               mrunlock_shared(&ip->i_iolock);
+
+       if (lock_flags & XFS_ILOCK_EXCL)
+               mrunlock_excl(&ip->i_lock);
+       else if (lock_flags & XFS_ILOCK_SHARED)
+               mrunlock_shared(&ip->i_lock);
+
+       trace_xfs_iunlock(ip, lock_flags, _RET_IP_);
+}
+
+/*
+ * give up write locks.  the i/o lock cannot be held nested
+ * if it is being demoted.
+ */
+void
+xfs_ilock_demote(
+       xfs_inode_t             *ip,
+       uint                    lock_flags)
+{
+       ASSERT(lock_flags & (XFS_IOLOCK_EXCL|XFS_ILOCK_EXCL));
+       ASSERT((lock_flags & ~(XFS_IOLOCK_EXCL|XFS_ILOCK_EXCL)) == 0);
+
+       if (lock_flags & XFS_ILOCK_EXCL)
+               mrdemote(&ip->i_lock);
+       if (lock_flags & XFS_IOLOCK_EXCL)
+               mrdemote(&ip->i_iolock);
+
+       trace_xfs_ilock_demote(ip, lock_flags, _RET_IP_);
+}
+
+#ifdef DEBUG
+int
+xfs_isilocked(
+       xfs_inode_t             *ip,
+       uint                    lock_flags)
+{
+       if (lock_flags & (XFS_ILOCK_EXCL|XFS_ILOCK_SHARED)) {
+               if (!(lock_flags & XFS_ILOCK_SHARED))
+                       return !!ip->i_lock.mr_writer;
+               return rwsem_is_locked(&ip->i_lock.mr_lock);
+       }
+
+       if (lock_flags & (XFS_IOLOCK_EXCL|XFS_IOLOCK_SHARED)) {
+               if (!(lock_flags & XFS_IOLOCK_SHARED))
+                       return !!ip->i_iolock.mr_writer;
+               return rwsem_is_locked(&ip->i_iolock.mr_lock);
+       }
+
+       ASSERT(0);
+       return 0;
+}
+#endif
+
+void
+__xfs_iflock(
+       struct xfs_inode        *ip)
+{
+       wait_queue_head_t *wq = bit_waitqueue(&ip->i_flags, __XFS_IFLOCK_BIT);
+       DEFINE_WAIT_BIT(wait, &ip->i_flags, __XFS_IFLOCK_BIT);
+
+       do {
+               prepare_to_wait_exclusive(wq, &wait.wait, TASK_UNINTERRUPTIBLE);
+               if (xfs_isiflocked(ip))
+                       io_schedule();
+       } while (!xfs_iflock_nowait(ip));
+
+       finish_wait(wq, &wait.wait);
+}
+
 #ifdef DEBUG
 /*
  * Make sure that the extents in the given memory buffer
index 94b32f906e7903a32cc1e1474f3d4a6fed267f93..1fc2065e010b4ddf3bbd8889735a979588a4a857 100644 (file)
@@ -496,11 +496,10 @@ static inline int xfs_isiflocked(struct xfs_inode *ip)
        (((pip)->i_mount->m_flags & XFS_MOUNT_GRPID) || \
         ((pip)->i_d.di_mode & S_ISGID))
 
+
 /*
- * xfs_iget.c prototypes.
+ * xfs_inode.c prototypes.
  */
-int            xfs_iget(struct xfs_mount *, struct xfs_trans *, xfs_ino_t,
-                        uint, uint, xfs_inode_t **);
 void           xfs_ilock(xfs_inode_t *, uint);
 int            xfs_ilock_nowait(xfs_inode_t *, uint);
 void           xfs_iunlock(xfs_inode_t *, uint);
@@ -508,11 +507,6 @@ void               xfs_ilock_demote(xfs_inode_t *, uint);
 int            xfs_isilocked(xfs_inode_t *, uint);
 uint           xfs_ilock_map_shared(xfs_inode_t *);
 void           xfs_iunlock_map_shared(xfs_inode_t *, uint);
-void           xfs_inode_free(struct xfs_inode *ip);
-
-/*
- * xfs_inode.c prototypes.
- */
 int            xfs_ialloc(struct xfs_trans *, xfs_inode_t *, umode_t,
                           xfs_nlink_t, xfs_dev_t, prid_t, int,
                           struct xfs_buf **, xfs_inode_t **);
index 973dff6ad93526292871d3452d758e86b3f077ac..a066cf1766ab6a3963759b4e7e3268bc2a81f47b 100644 (file)
@@ -373,7 +373,7 @@ xfs_iomap_write_delay(
        xfs_extlen_t    extsz;
        int             nimaps;
        xfs_bmbt_irec_t imap[XFS_WRITE_IMAPS];
-       int             prealloc, flushed = 0;
+       int             prealloc;
        int             error;
 
        ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
@@ -434,26 +434,17 @@ retry:
        }
 
        /*
-        * If bmapi returned us nothing, we got either ENOSPC or EDQUOT.  For
-        * ENOSPC, * flush all other inodes with delalloc blocks to free up
-        * some of the excess reserved metadata space. For both cases, retry
+        * If bmapi returned us nothing, we got either ENOSPC or EDQUOT. Retry
         * without EOF preallocation.
         */
        if (nimaps == 0) {
                trace_xfs_delalloc_enospc(ip, offset, count);
-               if (flushed)
-                       return XFS_ERROR(error ? error : ENOSPC);
-
-               if (error == ENOSPC) {
-                       xfs_iunlock(ip, XFS_ILOCK_EXCL);
-                       xfs_flush_inodes(ip);
-                       xfs_ilock(ip, XFS_ILOCK_EXCL);
+               if (prealloc) {
+                       prealloc = 0;
+                       error = 0;
+                       goto retry;
                }
-
-               flushed = 1;
-               error = 0;
-               prealloc = 0;
-               goto retry;
+               return XFS_ERROR(error ? error : ENOSPC);
        }
 
        if (!(imap[0].br_startblock || XFS_IS_REALTIME_INODE(ip)))
@@ -584,7 +575,9 @@ xfs_iomap_write_allocate(
                         * pointer that the caller gave to us.
                         */
                        error = xfs_bmapi_write(tp, ip, map_start_fsb,
-                                               count_fsb, 0, &first_block, 1,
+                                               count_fsb,
+                                               XFS_BMAPI_STACK_SWITCH,
+                                               &first_block, 1,
                                                imap, &nimaps, &free_list);
                        if (error)
                                goto trans_cancel;
index 01d10a66e30243518d293f2c72a29b6135f7977b..3998fd2a7949475801898801e9009efbd5d4aeb9 100644 (file)
@@ -34,6 +34,7 @@
 #include "xfs_error.h"
 #include "xfs_btree.h"
 #include "xfs_trace.h"
+#include "xfs_icache.h"
 
 STATIC int
 xfs_internal_inum(
index 7f4f9370d0e7438df3820fab9b0026b37292623b..46b6986e39b0fd9c44384d9ed15cba3cb224dc70 100644 (file)
@@ -34,6 +34,7 @@
 #include "xfs_dinode.h"
 #include "xfs_inode.h"
 #include "xfs_trace.h"
+#include "xfs_fsops.h"
 
 kmem_zone_t    *xfs_log_ticket_zone;
 
@@ -679,25 +680,29 @@ out:
 }
 
 /*
- * Finish the recovery of the file system.  This is separate from
- * the xfs_log_mount() call, because it depends on the code in
- * xfs_mountfs() to read in the root and real-time bitmap inodes
- * between calling xfs_log_mount() and here.
+ * Finish the recovery of the file system.  This is separate from the
+ * xfs_log_mount() call, because it depends on the code in xfs_mountfs() to read
+ * in the root and real-time bitmap inodes between calling xfs_log_mount() and
+ * here.
  *
- * mp          - ubiquitous xfs mount point structure
+ * If we finish recovery successfully, start the background log work. If we are
+ * not doing recovery, then we have a RO filesystem and we don't need to start
+ * it.
  */
 int
 xfs_log_mount_finish(xfs_mount_t *mp)
 {
-       int     error;
+       int     error = 0;
 
-       if (!(mp->m_flags & XFS_MOUNT_NORECOVERY))
+       if (!(mp->m_flags & XFS_MOUNT_NORECOVERY)) {
                error = xlog_recover_finish(mp->m_log);
-       else {
-               error = 0;
+               if (!error)
+                       xfs_log_work_queue(mp);
+       } else {
                ASSERT(mp->m_flags & XFS_MOUNT_RDONLY);
        }
 
+
        return error;
 }
 
@@ -850,15 +855,49 @@ xfs_log_unmount_write(xfs_mount_t *mp)
 }      /* xfs_log_unmount_write */
 
 /*
- * Deallocate log structures for unmount/relocation.
+ * Empty the log for unmount/freeze.
+ *
+ * To do this, we first need to shut down the background log work so it is not
+ * trying to cover the log as we clean up. We then need to unpin all objects in
+ * the log so we can then flush them out. Once they have completed their IO and
+ * run the callbacks removing themselves from the AIL, we can write the unmount
+ * record.
+ */
+void
+xfs_log_quiesce(
+       struct xfs_mount        *mp)
+{
+       cancel_delayed_work_sync(&mp->m_log->l_work);
+       xfs_log_force(mp, XFS_LOG_SYNC);
+
+       /*
+        * The superblock buffer is uncached and while xfs_ail_push_all_sync()
+        * will push it, xfs_wait_buftarg() will not wait for it. Further,
+        * xfs_buf_iowait() cannot be used because it was pushed with the
+        * XBF_ASYNC flag set, so we need to use a lock/unlock pair to wait for
+        * the IO to complete.
+        */
+       xfs_ail_push_all_sync(mp->m_ail);
+       xfs_wait_buftarg(mp->m_ddev_targp);
+       xfs_buf_lock(mp->m_sb_bp);
+       xfs_buf_unlock(mp->m_sb_bp);
+
+       xfs_log_unmount_write(mp);
+}
+
+/*
+ * Shut down and release the AIL and Log.
  *
- * We need to stop the aild from running before we destroy
- * and deallocate the log as the aild references the log.
+ * During unmount, we need to ensure we flush all the dirty metadata objects
+ * from the AIL so that the log is empty before we write the unmount record to
+ * the log. Once this is done, we can tear down the AIL and the log.
  */
 void
-xfs_log_unmount(xfs_mount_t *mp)
+xfs_log_unmount(
+       struct xfs_mount        *mp)
 {
-       cancel_delayed_work_sync(&mp->m_sync_work);
+       xfs_log_quiesce(mp);
+
        xfs_trans_ail_destroy(mp);
        xlog_dealloc_log(mp->m_log);
 }
@@ -1161,6 +1200,40 @@ done:
 }      /* xlog_get_iclog_buffer_size */
 
 
+void
+xfs_log_work_queue(
+       struct xfs_mount        *mp)
+{
+       queue_delayed_work(mp->m_log_workqueue, &mp->m_log->l_work,
+                               msecs_to_jiffies(xfs_syncd_centisecs * 10));
+}
+
+/*
+ * Every sync period we need to unpin all items in the AIL and push them to
+ * disk. If there is nothing dirty, then we might need to cover the log to
+ * indicate that the filesystem is idle.
+ */
+void
+xfs_log_worker(
+       struct work_struct      *work)
+{
+       struct xlog             *log = container_of(to_delayed_work(work),
+                                               struct xlog, l_work);
+       struct xfs_mount        *mp = log->l_mp;
+
+       /* dgc: errors ignored - not fatal and nowhere to report them */
+       if (xfs_log_need_covered(mp))
+               xfs_fs_log_dummy(mp);
+       else
+               xfs_log_force(mp, 0);
+
+       /* start pushing all the metadata that is currently dirty */
+       xfs_ail_push_all(mp->m_ail);
+
+       /* queue us up again */
+       xfs_log_work_queue(mp);
+}
+
 /*
  * This routine initializes some of the log structure for a given mount point.
  * Its primary purpose is to fill in enough, so recovery can occur.  However,
@@ -1195,6 +1268,7 @@ xlog_alloc_log(
        log->l_logBBsize   = num_bblks;
        log->l_covered_state = XLOG_STATE_COVER_IDLE;
        log->l_flags       |= XLOG_ACTIVE_RECOVERY;
+       INIT_DELAYED_WORK(&log->l_work, xfs_log_worker);
 
        log->l_prev_block  = -1;
        /* log->l_tail_lsn = 0x100000000LL; cycle = 1; current block = 0 */
@@ -2387,14 +2461,27 @@ xlog_state_do_callback(
 
 
                                /*
-                                * update the last_sync_lsn before we drop the
+                                * Completion of a iclog IO does not imply that
+                                * a transaction has completed, as transactions
+                                * can be large enough to span many iclogs. We
+                                * cannot change the tail of the log half way
+                                * through a transaction as this may be the only
+                                * transaction in the log and moving th etail to
+                                * point to the middle of it will prevent
+                                * recovery from finding the start of the
+                                * transaction. Hence we should only update the
+                                * last_sync_lsn if this iclog contains
+                                * transaction completion callbacks on it.
+                                *
+                                * We have to do this before we drop the
                                 * icloglock to ensure we are the only one that
                                 * can update it.
                                 */
                                ASSERT(XFS_LSN_CMP(atomic64_read(&log->l_last_sync_lsn),
                                        be64_to_cpu(iclog->ic_header.h_lsn)) <= 0);
-                               atomic64_set(&log->l_last_sync_lsn,
-                                       be64_to_cpu(iclog->ic_header.h_lsn));
+                               if (iclog->ic_callback)
+                                       atomic64_set(&log->l_last_sync_lsn,
+                                               be64_to_cpu(iclog->ic_header.h_lsn));
 
                        } else
                                ioerrors++;
@@ -3700,3 +3787,4 @@ xlog_iclogs_empty(
        } while (iclog != log->l_iclog);
        return 1;
 }
+
index 748d312850e2fc7da07509971f9afbf7aa9cb6d4..5caee96059dfb3a9fe5a1f03cd84c868674626b0 100644 (file)
@@ -181,5 +181,9 @@ int xfs_log_commit_cil(struct xfs_mount *mp, struct xfs_trans *tp,
                                xfs_lsn_t *commit_lsn, int flags);
 bool   xfs_log_item_in_current_chkpt(struct xfs_log_item *lip);
 
+void   xfs_log_work_queue(struct xfs_mount *mp);
+void   xfs_log_worker(struct work_struct *work);
+void   xfs_log_quiesce(struct xfs_mount *mp);
+
 #endif
 #endif /* __XFS_LOG_H__ */
index 18a801d76a4234e550427a83b6d6a65b7092d670..9a4e0e5ec3225a3cf79a82fe2e3da51987aa3b2d 100644 (file)
@@ -495,6 +495,7 @@ struct xlog {
        struct xfs_buf          *l_xbuf;        /* extra buffer for log
                                                 * wrapping */
        struct xfs_buftarg      *l_targ;        /* buftarg of log */
+       struct delayed_work     l_work;         /* background flush work */
        uint                    l_flags;
        uint                    l_quotaoffs_flag; /* XFS_DQ_*, for QUOTAOFFs */
        struct list_head        *l_buf_cancel_table;
index 5da3ace352bffe6ca32d16ae76fc131291914a00..651c98859b045fd80bf40d463fc5ce9a908c8ad5 100644 (file)
@@ -42,6 +42,7 @@
 #include "xfs_quota.h"
 #include "xfs_utils.h"
 #include "xfs_trace.h"
+#include "xfs_icache.h"
 
 STATIC int
 xlog_find_zeroed(
index b2bd3a0e6376e1190e1bbb747435acdaca998bb6..6f1c997704cdc8c8065a907dc4e7096d256fe3b4 100644 (file)
@@ -42,6 +42,7 @@
 #include "xfs_fsops.h"
 #include "xfs_utils.h"
 #include "xfs_trace.h"
+#include "xfs_icache.h"
 
 
 #ifdef HAVE_PERCPU_SB
@@ -1450,20 +1451,15 @@ xfs_unmountfs(
 
        /*
         * And reclaim all inodes.  At this point there should be no dirty
-        * inode, and none should be pinned or locked, but use synchronous
-        * reclaim just to be sure.
+        * inodes and none should be pinned or locked, but use synchronous
+        * reclaim just to be sure. We can stop background inode reclaim
+        * here as well if it is still running.
         */
+       cancel_delayed_work_sync(&mp->m_reclaim_work);
        xfs_reclaim_inodes(mp, SYNC_WAIT);
 
        xfs_qm_unmount(mp);
 
-       /*
-        * Flush out the log synchronously so that we know for sure
-        * that nothing is pinned.  This is important because bflush()
-        * will skip pinned buffers.
-        */
-       xfs_log_force(mp, XFS_LOG_SYNC);
-
        /*
         * Unreserve any blocks we have so that when we unmount we don't account
         * the reserved free space as used. This is really only necessary for
@@ -1489,23 +1485,6 @@ xfs_unmountfs(
                xfs_warn(mp, "Unable to update superblock counters. "
                                "Freespace may not be correct on next mount.");
 
-       /*
-        * At this point we might have modified the superblock again and thus
-        * added an item to the AIL, thus flush it again.
-        */
-       xfs_ail_push_all_sync(mp->m_ail);
-       xfs_wait_buftarg(mp->m_ddev_targp);
-
-       /*
-        * The superblock buffer is uncached and xfsaild_push() will lock and
-        * set the XBF_ASYNC flag on the buffer. We cannot do xfs_buf_iowait()
-        * here but a lock on the superblock buffer will block until iodone()
-        * has completed.
-        */
-       xfs_buf_lock(mp->m_sb_bp);
-       xfs_buf_unlock(mp->m_sb_bp);
-
-       xfs_log_unmount_write(mp);
        xfs_log_unmount(mp);
        xfs_uuid_unmount(mp);
 
index deee09e534dcf35de23535bfa6ce94f6ffa750a6..a631ca3b9065469d39a688da1f906bc6a6063bf2 100644 (file)
@@ -51,8 +51,6 @@ typedef struct xfs_trans_reservations {
 
 #else /* __KERNEL__ */
 
-#include "xfs_sync.h"
-
 struct xlog;
 struct xfs_inode;
 struct xfs_mru_cache;
@@ -197,9 +195,7 @@ typedef struct xfs_mount {
        struct mutex            m_icsb_mutex;   /* balancer sync lock */
 #endif
        struct xfs_mru_cache    *m_filestream;  /* per-mount filestream data */
-       struct delayed_work     m_sync_work;    /* background sync work */
        struct delayed_work     m_reclaim_work; /* background inode reclaim */
-       struct work_struct      m_flush_work;   /* background inode flush */
        __int64_t               m_update_flags; /* sb flags we need to update
                                                   on the next remount,rw */
        struct shrinker         m_inode_shrink; /* inode reclaim shrinker */
@@ -209,6 +205,8 @@ typedef struct xfs_mount {
        struct workqueue_struct *m_data_workqueue;
        struct workqueue_struct *m_unwritten_workqueue;
        struct workqueue_struct *m_cil_workqueue;
+       struct workqueue_struct *m_reclaim_workqueue;
+       struct workqueue_struct *m_log_workqueue;
 } xfs_mount_t;
 
 /*
index 2e86fa0cfc0d660374b2d8860f7c30e059b94e2b..48c750b0e830444dffcf9404ada2c919115673b1 100644 (file)
@@ -40,6 +40,7 @@
 #include "xfs_utils.h"
 #include "xfs_qm.h"
 #include "xfs_trace.h"
+#include "xfs_icache.h"
 
 /*
  * The global quota manager. There is only one of these for the entire
index 858a3b186110ab74760ebebf0d6b8c1326a9ee5a..7a9071f8855fc85b09d324b4d9115eaad4e7da85 100644 (file)
@@ -40,6 +40,7 @@
 #include "xfs_utils.h"
 #include "xfs_qm.h"
 #include "xfs_trace.h"
+#include "xfs_icache.h"
 
 STATIC int     xfs_qm_log_quotaoff(xfs_mount_t *, xfs_qoff_logitem_t **, uint);
 STATIC int     xfs_qm_log_quotaoff_end(xfs_mount_t *, xfs_qoff_logitem_t *,
index ca28a4ba4b548f0c379291bfb0e716ac3a9ec54e..a69e0b4750a9ff8761f1096fd6473e3ab36509ed 100644 (file)
@@ -38,6 +38,7 @@
 #include "xfs_utils.h"
 #include "xfs_trace.h"
 #include "xfs_buf.h"
+#include "xfs_icache.h"
 
 
 /*
index 26a09bd7f975f1f344083034b15960e43e4663a6..3d9ea947e9f80d347518c98081be7c645799a8fa 100644 (file)
@@ -49,7 +49,7 @@
 #include "xfs_extfree_item.h"
 #include "xfs_mru_cache.h"
 #include "xfs_inode_item.h"
-#include "xfs_sync.h"
+#include "xfs_icache.h"
 #include "xfs_trace.h"
 
 #include <linux/namei.h>
@@ -863,8 +863,23 @@ xfs_init_mount_workqueues(
                        WQ_MEM_RECLAIM, 0, mp->m_fsname);
        if (!mp->m_cil_workqueue)
                goto out_destroy_unwritten;
+
+       mp->m_reclaim_workqueue = alloc_workqueue("xfs-reclaim/%s",
+                       WQ_NON_REENTRANT, 0, mp->m_fsname);
+       if (!mp->m_reclaim_workqueue)
+               goto out_destroy_cil;
+
+       mp->m_log_workqueue = alloc_workqueue("xfs-log/%s",
+                       WQ_NON_REENTRANT, 0, mp->m_fsname);
+       if (!mp->m_log_workqueue)
+               goto out_destroy_reclaim;
+
        return 0;
 
+out_destroy_reclaim:
+       destroy_workqueue(mp->m_reclaim_workqueue);
+out_destroy_cil:
+       destroy_workqueue(mp->m_cil_workqueue);
 out_destroy_unwritten:
        destroy_workqueue(mp->m_unwritten_workqueue);
 out_destroy_data_iodone_queue:
@@ -877,11 +892,31 @@ STATIC void
 xfs_destroy_mount_workqueues(
        struct xfs_mount        *mp)
 {
+       destroy_workqueue(mp->m_log_workqueue);
+       destroy_workqueue(mp->m_reclaim_workqueue);
        destroy_workqueue(mp->m_cil_workqueue);
        destroy_workqueue(mp->m_data_workqueue);
        destroy_workqueue(mp->m_unwritten_workqueue);
 }
 
+/*
+ * Flush all dirty data to disk. Must not be called while holding an XFS_ILOCK
+ * or a page lock. We use sync_inodes_sb() here to ensure we block while waiting
+ * for IO to complete so that we effectively throttle multiple callers to the
+ * rate at which IO is completing.
+ */
+void
+xfs_flush_inodes(
+       struct xfs_mount        *mp)
+{
+       struct super_block      *sb = mp->m_super;
+
+       if (down_read_trylock(&sb->s_umount)) {
+               sync_inodes_sb(sb);
+               up_read(&sb->s_umount);
+       }
+}
+
 /* Catch misguided souls that try to use this interface on XFS */
 STATIC struct inode *
 xfs_fs_alloc_inode(
@@ -1006,9 +1041,8 @@ xfs_fs_put_super(
        struct xfs_mount        *mp = XFS_M(sb);
 
        xfs_filestream_unmount(mp);
-       cancel_delayed_work_sync(&mp->m_sync_work);
        xfs_unmountfs(mp);
-       xfs_syncd_stop(mp);
+
        xfs_freesb(mp);
        xfs_icsb_destroy_counters(mp);
        xfs_destroy_mount_workqueues(mp);
@@ -1023,7 +1057,6 @@ xfs_fs_sync_fs(
        int                     wait)
 {
        struct xfs_mount        *mp = XFS_M(sb);
-       int                     error;
 
        /*
         * Doing anything during the async pass would be counterproductive.
@@ -1031,17 +1064,14 @@ xfs_fs_sync_fs(
        if (!wait)
                return 0;
 
-       error = xfs_quiesce_data(mp);
-       if (error)
-               return -error;
-
+       xfs_log_force(mp, XFS_LOG_SYNC);
        if (laptop_mode) {
                /*
                 * The disk must be active because we're syncing.
-                * We schedule xfssyncd now (now that the disk is
+                * We schedule log work now (now that the disk is
                 * active) instead of later (when it might not be).
                 */
-               flush_delayed_work(&mp->m_sync_work);
+               flush_delayed_work(&mp->m_log->l_work);
        }
 
        return 0;
@@ -1118,6 +1148,48 @@ xfs_restore_resvblks(struct xfs_mount *mp)
        xfs_reserve_blocks(mp, &resblks, NULL);
 }
 
+/*
+ * Trigger writeback of all the dirty metadata in the file system.
+ *
+ * This ensures that the metadata is written to their location on disk rather
+ * than just existing in transactions in the log. This means after a quiesce
+ * there is no log replay required to write the inodes to disk - this is the
+ * primary difference between a sync and a quiesce.
+ *
+ * Note: xfs_log_quiesce() stops background log work - the callers must ensure
+ * it is started again when appropriate.
+ */
+void
+xfs_quiesce_attr(
+       struct xfs_mount        *mp)
+{
+       int     error = 0;
+
+       /* wait for all modifications to complete */
+       while (atomic_read(&mp->m_active_trans) > 0)
+               delay(100);
+
+       /* force the log to unpin objects from the now complete transactions */
+       xfs_log_force(mp, XFS_LOG_SYNC);
+
+       /* reclaim inodes to do any IO before the freeze completes */
+       xfs_reclaim_inodes(mp, 0);
+       xfs_reclaim_inodes(mp, SYNC_WAIT);
+
+       /* Push the superblock and write an unmount record */
+       error = xfs_log_sbcount(mp);
+       if (error)
+               xfs_warn(mp, "xfs_attr_quiesce: failed to log sb changes. "
+                               "Frozen image may not be consistent.");
+       /*
+        * Just warn here till VFS can correctly support
+        * read-only remount without racing.
+        */
+       WARN_ON(atomic_read(&mp->m_active_trans) != 0);
+
+       xfs_log_quiesce(mp);
+}
+
 STATIC int
 xfs_fs_remount(
        struct super_block      *sb,
@@ -1198,20 +1270,18 @@ xfs_fs_remount(
                 * value if it is non-zero, otherwise go with the default.
                 */
                xfs_restore_resvblks(mp);
+               xfs_log_work_queue(mp);
        }
 
        /* rw -> ro */
        if (!(mp->m_flags & XFS_MOUNT_RDONLY) && (*flags & MS_RDONLY)) {
                /*
-                * After we have synced the data but before we sync the
-                * metadata, we need to free up the reserve block pool so that
-                * the used block count in the superblock on disk is correct at
-                * the end of the remount. Stash the current reserve pool size
-                * so that if we get remounted rw, we can return it to the same
-                * size.
+                * Before we sync the metadata, we need to free up the reserve
+                * block pool so that the used block count in the superblock on
+                * disk is correct at the end of the remount. Stash the current
+                * reserve pool size so that if we get remounted rw, we can
+                * return it to the same size.
                 */
-
-               xfs_quiesce_data(mp);
                xfs_save_resvblks(mp);
                xfs_quiesce_attr(mp);
                mp->m_flags |= XFS_MOUNT_RDONLY;
@@ -1243,6 +1313,7 @@ xfs_fs_unfreeze(
        struct xfs_mount        *mp = XFS_M(sb);
 
        xfs_restore_resvblks(mp);
+       xfs_log_work_queue(mp);
        return 0;
 }
 
@@ -1321,6 +1392,7 @@ xfs_fs_fill_super(
        spin_lock_init(&mp->m_sb_lock);
        mutex_init(&mp->m_growlock);
        atomic_set(&mp->m_active_trans, 0);
+       INIT_DELAYED_WORK(&mp->m_reclaim_work, xfs_reclaim_worker);
 
        mp->m_super = sb;
        sb->s_fs_info = mp;
@@ -1371,10 +1443,6 @@ xfs_fs_fill_super(
        /*
         * we must configure the block size in the superblock before we run the
         * full mount process as the mount process can lookup and cache inodes.
-        * For the same reason we must also initialise the syncd and register
-        * the inode cache shrinker so that inodes can be reclaimed during
-        * operations like a quotacheck that iterate all inodes in the
-        * filesystem.
         */
        sb->s_magic = XFS_SB_MAGIC;
        sb->s_blocksize = mp->m_sb.sb_blocksize;
@@ -1384,13 +1452,9 @@ xfs_fs_fill_super(
        sb->s_time_gran = 1;
        set_posix_acl_flag(sb);
 
-       error = xfs_syncd_init(mp);
-       if (error)
-               goto out_filestream_unmount;
-
        error = xfs_mountfs(mp);
        if (error)
-               goto out_syncd_stop;
+               goto out_filestream_unmount;
 
        root = igrab(VFS_I(mp->m_rootip));
        if (!root) {
@@ -1408,8 +1472,7 @@ xfs_fs_fill_super(
        }
 
        return 0;
- out_syncd_stop:
-       xfs_syncd_stop(mp);
+
  out_filestream_unmount:
        xfs_filestream_unmount(mp);
  out_free_sb:
@@ -1429,7 +1492,6 @@ out_destroy_workqueues:
  out_unmount:
        xfs_filestream_unmount(mp);
        xfs_unmountfs(mp);
-       xfs_syncd_stop(mp);
        goto out_free_sb;
 }
 
@@ -1624,16 +1686,6 @@ xfs_destroy_zones(void)
 STATIC int __init
 xfs_init_workqueues(void)
 {
-       /*
-        * We never want to the same work item to run twice, reclaiming inodes
-        * or idling the log is not going to get any faster by multiple CPUs
-        * competing for ressources.  Use the default large max_active value
-        * so that even lots of filesystems can perform these task in parallel.
-        */
-       xfs_syncd_wq = alloc_workqueue("xfssyncd", WQ_NON_REENTRANT, 0);
-       if (!xfs_syncd_wq)
-               return -ENOMEM;
-
        /*
         * The allocation workqueue can be used in memory reclaim situations
         * (writepage path), and parallelism is only limited by the number of
@@ -1642,20 +1694,15 @@ xfs_init_workqueues(void)
         */
        xfs_alloc_wq = alloc_workqueue("xfsalloc", WQ_MEM_RECLAIM, 0);
        if (!xfs_alloc_wq)
-               goto out_destroy_syncd;
+               return -ENOMEM;
 
        return 0;
-
-out_destroy_syncd:
-       destroy_workqueue(xfs_syncd_wq);
-       return -ENOMEM;
 }
 
 STATIC void
 xfs_destroy_workqueues(void)
 {
        destroy_workqueue(xfs_alloc_wq);
-       destroy_workqueue(xfs_syncd_wq);
 }
 
 STATIC int __init
index 9de4a920ba05962a655c81a87069254ebfbefc28..bbe3d15a7904d6185ab440c3b2a12533322e72a7 100644 (file)
@@ -74,6 +74,7 @@ struct block_device;
 
 extern __uint64_t xfs_max_file_offset(unsigned int);
 
+extern void xfs_flush_inodes(struct xfs_mount *mp);
 extern void xfs_blkdev_issue_flush(struct xfs_buftarg *);
 extern xfs_agnumber_t xfs_set_inode32(struct xfs_mount *);
 extern xfs_agnumber_t xfs_set_inode64(struct xfs_mount *);
index 2a5c637344b4f310cd28586eec082d38176cbfcb..2ee1f49da0aa70eed076c03d4ebfef78f172acef 100644 (file)
@@ -47,6 +47,7 @@
 #include "xfs_filestream.h"
 #include "xfs_vnodeops.h"
 #include "xfs_trace.h"
+#include "xfs_icache.h"
 
 /*
  * The maximum pathlen is 1024 bytes. Since the minimum file system
@@ -777,7 +778,7 @@ xfs_create(
                        XFS_TRANS_PERM_LOG_RES, log_count);
        if (error == ENOSPC) {
                /* flush outstanding delalloc blocks and retry */
-               xfs_flush_inodes(dp);
+               xfs_flush_inodes(mp);
                error = xfs_trans_reserve(tp, resblks, log_res, 0,
                                XFS_TRANS_PERM_LOG_RES, log_count);
        }
index 0daa0fbd865437ab12a756535e8c2432c363bf35..081fc31f3e13821ea890684c5be0707696e687aa 100644 (file)
@@ -144,12 +144,11 @@ struct acpi_device_flags {
        u32 bus_address:1;
        u32 removable:1;
        u32 ejectable:1;
-       u32 lockable:1;
        u32 suprise_removal_ok:1;
        u32 power_manageable:1;
        u32 performance_manageable:1;
        u32 eject_pending:1;
-       u32 reserved:23;
+       u32 reserved:24;
 };
 
 /* File System */
@@ -426,14 +425,18 @@ static inline int acpi_pm_device_sleep_state(struct device *d, int *p, int m)
 }
 #endif
 
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_PM_RUNTIME
 int acpi_pm_device_run_wake(struct device *, bool);
-int acpi_pm_device_sleep_wake(struct device *, bool);
 #else
 static inline int acpi_pm_device_run_wake(struct device *dev, bool enable)
 {
        return -ENODEV;
 }
+#endif
+
+#ifdef CONFIG_PM_SLEEP
+int acpi_pm_device_sleep_wake(struct device *, bool);
+#else
 static inline int acpi_pm_device_sleep_wake(struct device *dev, bool enable)
 {
        return -ENODEV;
index b36ce40bd1c6c929e8b408044440df4ce5931825..8ce9d4e59cc54ea87d3557f5c95d9d5019978938 100644 (file)
@@ -219,6 +219,10 @@ static inline int pmd_same(pmd_t pmd_a, pmd_t pmd_b)
 #define move_pte(pte, prot, old_addr, new_addr)        (pte)
 #endif
 
+#ifndef __HAVE_ARCH_PTE_ACCESSIBLE
+#define pte_accessible(pte)            pte_present(pte)
+#endif
+
 #ifndef flush_tlb_fix_spurious_fault
 #define flush_tlb_fix_spurious_fault(vma, address) flush_tlb_page(vma, address)
 #endif
index c4467c55df1e56a1cf22cf70a82dac467db1c711..6b700c7b2fe1cba3cd054a200eac450ac4bde7be 100644 (file)
@@ -56,6 +56,8 @@ typedef u64 vmac_t;
 struct vmac_ctx_t {
        struct crypto_cipher *child;
        struct vmac_ctx __vmac_ctx;
+       u8 partial[VMAC_NHBYTES];       /* partial block */
+       int partial_size;               /* size of the partial block */
 };
 
 #endif /* __CRYPTO_VMAC_H */
index 90be9898110202f918a3d75d72da9437bb249bc5..39955bdbf88083acbef566b70180738d16a82f87 100644 (file)
@@ -76,6 +76,14 @@ typedef int (*acpi_table_handler) (struct acpi_table_header *table);
 
 typedef int (*acpi_table_entry_handler) (struct acpi_subtable_header *header, const unsigned long end);
 
+#ifdef CONFIG_ACPI_INITRD_TABLE_OVERRIDE
+void acpi_initrd_override(void *data, size_t size);
+#else
+static inline void acpi_initrd_override(void *data, size_t size)
+{
+}
+#endif
+
 char * __acpi_map_table (unsigned long phys_addr, unsigned long size);
 void __acpi_unmap_table(char *map, unsigned long size);
 int early_acpi_boot_init(void);
@@ -257,10 +265,14 @@ int acpi_check_region(resource_size_t start, resource_size_t n,
 
 int acpi_resources_are_enforced(void);
 
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_HIBERNATION
 void __init acpi_no_s4_hw_signature(void);
+#endif
+
+#ifdef CONFIG_PM_SLEEP
 void __init acpi_old_suspend_ordering(void);
 void __init acpi_nvs_nosave(void);
+void __init acpi_nvs_nosave_s3(void);
 #endif /* CONFIG_PM_SLEEP */
 
 struct acpi_osc_context {
@@ -426,6 +438,14 @@ void acpi_os_set_prepare_sleep(int (*func)(u8 sleep_state,
 
 acpi_status acpi_os_prepare_sleep(u8 sleep_state,
                                  u32 pm1a_control, u32 pm1b_control);
+#ifdef CONFIG_X86
+void arch_reserve_mem_area(acpi_physical_address addr, size_t size);
+#else
+static inline void arch_reserve_mem_area(acpi_physical_address addr,
+                                         size_t size)
+{
+}
+#endif /* CONFIG_X86 */
 #else
 #define acpi_os_set_prepare_sleep(func, pm1a_ctrl, pm1b_ctrl) do { } while (0)
 #endif
index 5c3f4e4b9a239ceb01de3d5bc98b0534f28ea172..eed6982860ba3ceaef639436f6d2a5c6e6156188 100644 (file)
@@ -64,4 +64,6 @@ enum asn1_tag {
        ASN1_LONG_TAG   = 31    /* Long form tag */
 };
 
+#define ASN1_INDEFINITE_LENGTH 0x80
+
 #endif /* _LINUX_ASN1_H */
index 4180eb78d5752de3d16c3f836359039af09737e8..fd15d98297056f26381d8f7131e1ead8e0d0f868 100644 (file)
@@ -251,7 +251,7 @@ struct bcma_bus {
        u8 num;
 
        struct bcma_drv_cc drv_cc;
-       struct bcma_drv_pci drv_pci;
+       struct bcma_drv_pci drv_pci[2];
        struct bcma_drv_mips drv_mips;
        struct bcma_drv_gmac_cmn drv_gmac_cmn;
 
index 1cf1749440ac66dabd8b0f797e80690bbde9961d..145f3c56227f78932ed6cd8490d1b9c5828d63cc 100644 (file)
@@ -510,6 +510,7 @@ struct bcma_chipcommon_pmu {
 
 #ifdef CONFIG_BCMA_DRIVER_MIPS
 struct bcma_pflash {
+       bool present;
        u8 buswidth;
        u32 window;
        u32 window_size;
@@ -532,6 +533,7 @@ struct mtd_info;
 
 struct bcma_nflash {
        bool present;
+       bool boot;              /* This is the flash the SoC boots from */
 
        struct mtd_info *mtd;
 };
@@ -552,6 +554,7 @@ struct bcma_drv_cc {
        u32 capabilities;
        u32 capabilities_ext;
        u8 setup_done:1;
+       u8 early_setup_done:1;
        /* Fast Powerup Delay constant */
        u16 fast_pwrup_delay;
        struct bcma_chipcommon_pmu pmu;
@@ -583,6 +586,7 @@ struct bcma_drv_cc {
        bcma_cc_write32(cc, offset, (bcma_cc_read32(cc, offset) & (mask)) | (set))
 
 extern void bcma_core_chipcommon_init(struct bcma_drv_cc *cc);
+extern void bcma_core_chipcommon_early_init(struct bcma_drv_cc *cc);
 
 extern void bcma_chipco_suspend(struct bcma_drv_cc *cc);
 extern void bcma_chipco_resume(struct bcma_drv_cc *cc);
@@ -606,6 +610,7 @@ u32 bcma_chipco_gpio_polarity(struct bcma_drv_cc *cc, u32 mask, u32 value);
 
 /* PMU support */
 extern void bcma_pmu_init(struct bcma_drv_cc *cc);
+extern void bcma_pmu_early_init(struct bcma_drv_cc *cc);
 
 extern void bcma_chipco_pll_write(struct bcma_drv_cc *cc, u32 offset,
                                  u32 value);
index c0043645cdcb0f8f4cf4ab04de7f22c438336b98..0baf8a56b7947b7300e5bb2b1b0a8dd5ef188483 100644 (file)
@@ -35,13 +35,16 @@ struct bcma_device;
 struct bcma_drv_mips {
        struct bcma_device *core;
        u8 setup_done:1;
+       u8 early_setup_done:1;
        unsigned int assigned_irqs;
 };
 
 #ifdef CONFIG_BCMA_DRIVER_MIPS
 extern void bcma_core_mips_init(struct bcma_drv_mips *mcore);
+extern void bcma_core_mips_early_init(struct bcma_drv_mips *mcore);
 #else
 static inline void bcma_core_mips_init(struct bcma_drv_mips *mcore) { }
+static inline void bcma_core_mips_early_init(struct bcma_drv_mips *mcore) { }
 #endif
 
 extern u32 bcma_cpu_clock(struct bcma_drv_mips *mcore);
index 6c9cb93ae3de4bb3210f5037dbd3865fe18288d3..7e8104bb7a7eb11f412fb504df6552e6595ef40b 100644 (file)
@@ -85,6 +85,9 @@
                                                         * (2 ZettaBytes), high 32 bits
                                                         */
 
-#define BCMA_SFLASH                    0x1c000000
+#define BCMA_SOC_FLASH1                        0x1fc00000      /* MIPS Flash Region 1 */
+#define BCMA_SOC_FLASH1_SZ             0x00400000      /* MIPS Size of Flash Region 1 */
+#define BCMA_SOC_FLASH2                        0x1c000000      /* Flash Region 2 (region 1 shadowed here) */
+#define BCMA_SOC_FLASH2_SZ             0x02000000      /* Size of Flash Region 2 */
 
 #endif /* LINUX_BCMA_REGS_H_ */
index f8a030ced0c7f39297085eb346a989aff5b5d612..4cd1d0fd2542c147f67413dbaec3d37e2f7f558a 100644 (file)
@@ -34,7 +34,6 @@ extern int cgroup_lock_is_held(void);
 extern bool cgroup_lock_live_group(struct cgroup *cgrp);
 extern void cgroup_unlock(void);
 extern void cgroup_fork(struct task_struct *p);
-extern void cgroup_fork_callbacks(struct task_struct *p);
 extern void cgroup_post_fork(struct task_struct *p);
 extern void cgroup_exit(struct task_struct *p, int run_callbacks);
 extern int cgroupstats_build(struct cgroupstats *stats,
index 1775eb8acc03665d36bf8b094c440a41ba10764d..1d7399314a8933eab0516daf5ff4bf7f87777d88 100644 (file)
@@ -4,6 +4,7 @@
 #include <linux/types.h>
 #include <linux/mm.h>
 #include <linux/fs.h>
+#include <asm/siginfo.h>
 
 /*
  * These are the only things you should do on a core-file: use only these
index b60f6ba01d0c787225b626c5f4b4eef2cdca1e37..d03c219930524347b47d62009f2711e650f7ae47 100644 (file)
@@ -11,6 +11,7 @@
 #ifndef _LINUX_CPUFREQ_H
 #define _LINUX_CPUFREQ_H
 
+#include <asm/cputime.h>
 #include <linux/mutex.h>
 #include <linux/notifier.h>
 #include <linux/threads.h>
@@ -22,6 +23,8 @@
 #include <asm/div64.h>
 
 #define CPUFREQ_NAME_LEN 16
+/* Print length for names. Extra 1 space for accomodating '\n' in prints */
+#define CPUFREQ_NAME_PLEN (CPUFREQ_NAME_LEN + 1)
 
 
 /*********************************************************************
@@ -405,5 +408,9 @@ void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table,
 
 void cpufreq_frequency_table_put_attr(unsigned int cpu);
 
+/*********************************************************************
+ *                     Governor Helpers                                     *
+ *********************************************************************/
+cputime64_t get_cpu_idle_time(unsigned int cpu, cputime64_t *wall);
 
 #endif /* _LINUX_CPUFREQ_H */
index ebbed2ce66379bd986fbf83f11e7ae8c32bf6070..0142aacb70b7049583a1618c735c7410a6827d65 100644 (file)
@@ -76,21 +76,6 @@ extern int groups_search(const struct group_info *, kgid_t);
 extern int in_group_p(kgid_t);
 extern int in_egroup_p(kgid_t);
 
-/*
- * The common credentials for a thread group
- * - shared by CLONE_THREAD
- */
-#ifdef CONFIG_KEYS
-struct thread_group_cred {
-       atomic_t        usage;
-       pid_t           tgid;                   /* thread group process ID */
-       spinlock_t      lock;
-       struct key __rcu *session_keyring;      /* keyring inherited over fork */
-       struct key      *process_keyring;       /* keyring private to this process */
-       struct rcu_head rcu;                    /* RCU deletion hook */
-};
-#endif
-
 /*
  * The security context of a task
  *
@@ -139,6 +124,8 @@ struct cred {
 #ifdef CONFIG_KEYS
        unsigned char   jit_keyring;    /* default keyring to attach requested
                                         * keys to */
+       struct key __rcu *session_keyring; /* keyring inherited over fork */
+       struct key      *process_keyring; /* keyring private to this process */
        struct key      *thread_keyring; /* keyring private to this thread */
        struct key      *request_key_auth; /* assumed request_key authority */
        struct thread_group_cred *tgcred; /* thread-group shared credentials */
index 281c72a3b9d50d19161c0f6182d38f67991cce8f..7e2e2ea4a70f10693c6a146497726af1e9f4265b 100644 (file)
@@ -66,6 +66,8 @@ struct devfreq_dev_status {
  *                     explained above with "DEVFREQ_FLAG_*" macros.
  * @get_dev_status     The device should provide the current performance
  *                     status to devfreq, which is used by governors.
+ * @get_cur_freq       The device should provide the current frequency
+ *                     at which it is operating.
  * @exit               An optional callback that is called when devfreq
  *                     is removing the devfreq object due to error or
  *                     from devfreq_remove_device() call. If the user
@@ -79,6 +81,7 @@ struct devfreq_dev_profile {
        int (*target)(struct device *dev, unsigned long *freq, u32 flags);
        int (*get_dev_status)(struct device *dev,
                              struct devfreq_dev_status *stat);
+       int (*get_cur_freq)(struct device *dev, unsigned long *freq);
        void (*exit)(struct device *dev);
 };
 
@@ -91,25 +94,18 @@ struct devfreq_dev_profile {
  *                     status of the device (load = busy_time / total_time).
  *                     If no_central_polling is set, this callback is called
  *                     only with update_devfreq() notified by OPP.
- * @init               Called when the devfreq is being attached to a device
- * @exit               Called when the devfreq is being removed from a
- *                     device. Governor should stop any internal routines
- *                     before return because related data may be
- *                     freed after exit().
- * @no_central_polling Do not use devfreq's central polling mechanism.
- *                     When this is set, devfreq will not call
- *                     get_target_freq with devfreq_monitor(). However,
- *                     devfreq will call get_target_freq with
- *                     devfreq_update() notified by OPP framework.
+ * @event_handler       Callback for devfreq core framework to notify events
+ *                      to governors. Events include per device governor
+ *                      init and exit, opp changes out of devfreq, suspend
+ *                      and resume of per device devfreq during device idle.
  *
  * Note that the callbacks are called with devfreq->lock locked by devfreq.
  */
 struct devfreq_governor {
        const char name[DEVFREQ_NAME_LEN];
        int (*get_target_freq)(struct devfreq *this, unsigned long *freq);
-       int (*init)(struct devfreq *this);
-       void (*exit)(struct devfreq *this);
-       const bool no_central_polling;
+       int (*event_handler)(struct devfreq *devfreq,
+                               unsigned int event, void *data);
 };
 
 /**
@@ -124,18 +120,13 @@ struct devfreq_governor {
  * @nb         notifier block used to notify devfreq object that it should
  *             reevaluate operable frequencies. Devfreq users may use
  *             devfreq.nb to the corresponding register notifier call chain.
- * @polling_jiffies    interval in jiffies.
+ * @work       delayed work for load monitoring.
  * @previous_freq      previously configured frequency value.
- * @next_polling       the number of remaining jiffies to poll with
- *                     "devfreq_monitor" executions to reevaluate
- *                     frequency/voltage of the device. Set by
- *                     profile's polling_ms interval.
  * @data       Private data of the governor. The devfreq framework does not
  *             touch this.
- * @being_removed      a flag to mark that this object is being removed in
- *                     order to prevent trying to remove the object multiple times.
  * @min_freq   Limit minimum frequency requested by user (0: none)
  * @max_freq   Limit maximum frequency requested by user (0: none)
+ * @stop_polling        devfreq polling status of a device.
  *
  * This structure stores the devfreq information for a give device.
  *
@@ -153,17 +144,15 @@ struct devfreq {
        struct devfreq_dev_profile *profile;
        const struct devfreq_governor *governor;
        struct notifier_block nb;
+       struct delayed_work work;
 
-       unsigned long polling_jiffies;
        unsigned long previous_freq;
-       unsigned int next_polling;
 
        void *data; /* private data for governors */
 
-       bool being_removed;
-
        unsigned long min_freq;
        unsigned long max_freq;
+       bool stop_polling;
 };
 
 #if defined(CONFIG_PM_DEVFREQ)
@@ -172,6 +161,8 @@ extern struct devfreq *devfreq_add_device(struct device *dev,
                                  const struct devfreq_governor *governor,
                                  void *data);
 extern int devfreq_remove_device(struct devfreq *devfreq);
+extern int devfreq_suspend_device(struct devfreq *devfreq);
+extern int devfreq_resume_device(struct devfreq *devfreq);
 
 /* Helper functions for devfreq user device driver with OPP. */
 extern struct opp *devfreq_recommended_opp(struct device *dev,
@@ -225,6 +216,16 @@ static int devfreq_remove_device(struct devfreq *devfreq)
        return 0;
 }
 
+static int devfreq_suspend_device(struct devfreq *devfreq)
+{
+       return 0;
+}
+
+static int devfreq_resume_device(struct devfreq *devfreq)
+{
+       return 0;
+}
+
 static struct opp *devfreq_recommended_opp(struct device *dev,
                                           unsigned long *freq, u32 flags)
 {
index 5ce0e5fd712e0fe67d0e05b455fffbb85c16fb7c..251a2090a55444cec55ce4f04510b6ef83a69cfb 100644 (file)
 int devpts_new_index(struct inode *ptmx_inode);
 void devpts_kill_index(struct inode *ptmx_inode, int idx);
 /* mknod in devpts */
-int devpts_pty_new(struct inode *ptmx_inode, struct tty_struct *tty);
-/* get tty structure */
-struct tty_struct *devpts_get_tty(struct inode *pts_inode, int number);
+struct inode *devpts_pty_new(struct inode *ptmx_inode, dev_t device, int index,
+               void *priv);
+/* get private structure */
+void *devpts_get_priv(struct inode *pts_inode);
 /* unlink */
-void devpts_pty_kill(struct tty_struct *tty);
+void devpts_pty_kill(struct inode *inode);
 
 #else
 
 /* Dummy stubs in the no-pty case */
 static inline int devpts_new_index(struct inode *ptmx_inode) { return -EINVAL; }
 static inline void devpts_kill_index(struct inode *ptmx_inode, int idx) { }
-static inline int devpts_pty_new(struct inode *ptmx_inode,
-                               struct tty_struct *tty)
+static inline struct inode *devpts_pty_new(struct inode *ptmx_inode,
+               dev_t device, int index, void *priv)
 {
-       return -EINVAL;
+       return ERR_PTR(-EINVAL);
 }
-static inline struct tty_struct *devpts_get_tty(struct inode *pts_inode,
-               int number)
+static inline void *devpts_get_priv(struct inode *pts_inode)
 {
        return NULL;
 }
-static inline void devpts_pty_kill(struct tty_struct *tty) { }
+static inline void devpts_pty_kill(struct inode *inode) { }
 
 #endif
 
index 171ad8aedc835258e152b94b2bc92242045d9c3e..fc0e34ce038f4055eaf7160cb1eb7693b7cc7e5d 100644 (file)
@@ -39,6 +39,8 @@ extern void debug_dma_map_page(struct device *dev, struct page *page,
                               int direction, dma_addr_t dma_addr,
                               bool map_single);
 
+extern void debug_dma_mapping_error(struct device *dev, dma_addr_t dma_addr);
+
 extern void debug_dma_unmap_page(struct device *dev, dma_addr_t addr,
                                 size_t size, int direction, bool map_single);
 
@@ -105,6 +107,11 @@ static inline void debug_dma_map_page(struct device *dev, struct page *page,
 {
 }
 
+static inline void debug_dma_mapping_error(struct device *dev,
+                                         dma_addr_t dma_addr)
+{
+}
+
 static inline void debug_dma_unmap_page(struct device *dev, dma_addr_t addr,
                                        size_t size, int direction,
                                        bool map_single)
similarity index 97%
rename from arch/arm/plat-mxc/include/mach/ipu.h
rename to include/linux/dma/ipu-dma.h
index 539e559d18b2c6f1046f3909e22760d43eaea9b1..18031115c6684f6ca5681aa5e19efd4a546b61ee 100644 (file)
@@ -9,8 +9,8 @@
  * published by the Free Software Foundation.
  */
 
-#ifndef _IPU_H_
-#define _IPU_H_
+#ifndef __LINUX_DMA_IPU_DMA_H
+#define __LINUX_DMA_IPU_DMA_H
 
 #include <linux/types.h>
 #include <linux/dmaengine.h>
@@ -174,4 +174,4 @@ struct idmac_channel {
 #define to_tx_desc(tx) container_of(tx, struct idmac_tx_desc, txd)
 #define to_idmac_chan(c) container_of(c, struct idmac_channel, dma_chan)
 
-#endif
+#endif /* __LINUX_DMA_IPU_DMA_H */
diff --git a/include/linux/earlycpio.h b/include/linux/earlycpio.h
new file mode 100644 (file)
index 0000000..111f46d
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef _LINUX_EARLYCPIO_H
+#define _LINUX_EARLYCPIO_H
+
+#include <linux/types.h>
+
+#define MAX_CPIO_FILE_NAME 18
+
+struct cpio_data {
+       void *data;
+       size_t size;
+       char name[MAX_CPIO_FILE_NAME];
+};
+
+struct cpio_data find_cpio_data(const char *path, void *data, size_t len,
+                               long *offset);
+
+#endif /* _LINUX_EARLYCPIO_H */
index bab9f8473dc1c7673c7e900e73691d38ee35e737..4784213c819d1e9d96ee27d4a8b898cdad15dafb 100644 (file)
@@ -14,7 +14,6 @@
 
 #include <linux/atomic.h>
 #include <linux/device.h>
-#include <linux/kobject.h>
 #include <linux/completion.h>
 #include <linux/workqueue.h>
 #include <linux/debugfs.h>
@@ -533,6 +532,7 @@ struct csrow_info {
 
        u32 ue_count;           /* Uncorrectable Errors for this csrow */
        u32 ce_count;           /* Correctable Errors for this csrow */
+       u32 nr_pages;           /* combined pages count of all channels */
 
        struct mem_ctl_info *mci;       /* the parent */
 
@@ -667,6 +667,8 @@ struct mem_ctl_info {
        u32 fake_inject_ue;
        u16 fake_inject_count;
 #endif
+       __u8 csbased : 1,       /* csrow-based memory controller */
+            __resv  : 7;
 };
 
 #endif
index 7443a560c9d059d106e7ce18dcf8813b18502c65..2c26c14cd7100d79ff046b9187409e2f430571eb 100644 (file)
@@ -68,7 +68,7 @@ enum extcon_cable_name {
        EXTCON_VIDEO_OUT,
        EXTCON_MECHANICAL,
 };
-extern const char *extcon_cable_name[];
+extern const char extcon_cable_name[][CABLE_NAME_MAX + 1];
 
 struct extcon_cable;
 
index d09af4b67cf121ad91fd4ca02bec01560b6110fd..ee899329e65a6e43320ddfbedd38f427f6d39125 100644 (file)
@@ -75,28 +75,62 @@ static inline bool cgroup_freezing(struct task_struct *task)
  */
 
 
-/* Tell the freezer not to count the current task as freezable. */
+/**
+ * freezer_do_not_count - tell freezer to ignore %current
+ *
+ * Tell freezers to ignore the current task when determining whether the
+ * target frozen state is reached.  IOW, the current task will be
+ * considered frozen enough by freezers.
+ *
+ * The caller shouldn't do anything which isn't allowed for a frozen task
+ * until freezer_cont() is called.  Usually, freezer[_do_not]_count() pair
+ * wrap a scheduling operation and nothing much else.
+ */
 static inline void freezer_do_not_count(void)
 {
        current->flags |= PF_FREEZER_SKIP;
 }
 
-/*
- * Tell the freezer to count the current task as freezable again and try to
- * freeze it.
+/**
+ * freezer_count - tell freezer to stop ignoring %current
+ *
+ * Undo freezer_do_not_count().  It tells freezers that %current should be
+ * considered again and tries to freeze if freezing condition is already in
+ * effect.
  */
 static inline void freezer_count(void)
 {
        current->flags &= ~PF_FREEZER_SKIP;
+       /*
+        * If freezing is in progress, the following paired with smp_mb()
+        * in freezer_should_skip() ensures that either we see %true
+        * freezing() or freezer_should_skip() sees !PF_FREEZER_SKIP.
+        */
+       smp_mb();
        try_to_freeze();
 }
 
-/*
- * Check if the task should be counted as freezable by the freezer
+/**
+ * freezer_should_skip - whether to skip a task when determining frozen
+ *                      state is reached
+ * @p: task in quesion
+ *
+ * This function is used by freezers after establishing %true freezing() to
+ * test whether a task should be skipped when determining the target frozen
+ * state is reached.  IOW, if this function returns %true, @p is considered
+ * frozen enough.
  */
-static inline int freezer_should_skip(struct task_struct *p)
+static inline bool freezer_should_skip(struct task_struct *p)
 {
-       return !!(p->flags & PF_FREEZER_SKIP);
+       /*
+        * The following smp_mb() paired with the one in freezer_count()
+        * ensures that either freezer_count() sees %true freezing() or we
+        * see cleared %PF_FREEZER_SKIP and return %false.  This makes it
+        * impossible for a task to slip frozen state testing after
+        * clearing %PF_FREEZER_SKIP.
+        */
+       smp_mb();
+       return p->flags & PF_FREEZER_SKIP;
 }
 
 /*
index 63d966d5c2ea7a382c2f42cc664c7804dec86f73..d5b0910d49615ee01cf3255818d99e78241cb09f 100644 (file)
@@ -88,9 +88,10 @@ struct fsnotify_event_private_data;
  *             if the group is interested in this event.
  * handle_event - main call for a group to handle an fs event
  * free_group_priv - called when a group refcnt hits 0 to clean up the private union
- * freeing-mark - this means that a mark has been flagged to die when everything
- *             finishes using it.  The function is supplied with what must be a
- *             valid group and inode to use to clean up.
+ * freeing_mark - called when a mark is being destroyed for some reason.  The group
+ *             MUST be holding a reference on each mark and that reference must be
+ *             dropped in this function.  inotify uses this function to send
+ *             userspace messages that marks have been removed.
  */
 struct fsnotify_ops {
        bool (*should_send_event)(struct fsnotify_group *group, struct inode *inode,
@@ -141,12 +142,14 @@ struct fsnotify_group {
        unsigned int priority;
 
        /* stores all fastpath marks assoc with this group so they can be cleaned on unregister */
-       spinlock_t mark_lock;           /* protect marks_list */
+       struct mutex mark_mutex;        /* protect marks_list */
        atomic_t num_marks;             /* 1 for each mark and 1 for not being
                                         * past the point of no return when freeing
                                         * a group */
        struct list_head marks_list;    /* all inode marks for this group */
 
+       struct fasync_struct    *fsn_fa;    /* async notification */
+
        /* groups can define private fields here or use the void *private */
        union {
                void *private;
@@ -155,7 +158,6 @@ struct fsnotify_group {
                        spinlock_t      idr_lock;
                        struct idr      idr;
                        u32             last_wd;
-                       struct fasync_struct    *fa;    /* async notification */
                        struct user_struct      *user;
                } inotify_data;
 #endif
@@ -287,7 +289,6 @@ struct fsnotify_mark {
                struct fsnotify_inode_mark i;
                struct fsnotify_vfsmount_mark m;
        };
-       struct list_head free_g_list;   /* tmp list used when freeing this mark */
        __u32 ignored_mask;             /* events types to ignore */
 #define FSNOTIFY_MARK_FLAG_INODE               0x01
 #define FSNOTIFY_MARK_FLAG_VFSMOUNT            0x02
@@ -360,11 +361,16 @@ static inline void __fsnotify_d_instantiate(struct dentry *dentry, struct inode
 
 /* called from fsnotify listeners, such as fanotify or dnotify */
 
-/* get a reference to an existing or create a new group */
+/* create a new group */
 extern struct fsnotify_group *fsnotify_alloc_group(const struct fsnotify_ops *ops);
+/* get reference to a group */
+extern void fsnotify_get_group(struct fsnotify_group *group);
 /* drop reference on a group from fsnotify_alloc_group */
 extern void fsnotify_put_group(struct fsnotify_group *group);
-
+/* destroy group */
+extern void fsnotify_destroy_group(struct fsnotify_group *group);
+/* fasync handler function */
+extern int fsnotify_fasync(int fd, struct file *file, int on);
 /* take a reference to an event */
 extern void fsnotify_get_event(struct fsnotify_event *event);
 extern void fsnotify_put_event(struct fsnotify_event *event);
@@ -405,8 +411,13 @@ extern void fsnotify_set_mark_mask_locked(struct fsnotify_mark *mark, __u32 mask
 /* attach the mark to both the group and the inode */
 extern int fsnotify_add_mark(struct fsnotify_mark *mark, struct fsnotify_group *group,
                             struct inode *inode, struct vfsmount *mnt, int allow_dups);
-/* given a mark, flag it to be freed when all references are dropped */
-extern void fsnotify_destroy_mark(struct fsnotify_mark *mark);
+extern int fsnotify_add_mark_locked(struct fsnotify_mark *mark, struct fsnotify_group *group,
+                                   struct inode *inode, struct vfsmount *mnt, int allow_dups);
+/* given a group and a mark, flag mark to be freed when all references are dropped */
+extern void fsnotify_destroy_mark(struct fsnotify_mark *mark,
+                                 struct fsnotify_group *group);
+extern void fsnotify_destroy_mark_locked(struct fsnotify_mark *mark,
+                                        struct fsnotify_group *group);
 /* run all the marks in a group, and clear all of the vfsmount marks */
 extern void fsnotify_clear_vfsmount_marks_by_group(struct fsnotify_group *group);
 /* run all the marks in a group, and clear all of the inode marks */
index 271a770b47843934075c64ed8893144a0fd570d7..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1 +0,0 @@
-header-y += hsi_char.h
index b31cb7da03466b6550d9fa9fd0e4359c2540c957..4f0f948601388802d01b9c4b176df8431ace61e6 100644 (file)
@@ -159,6 +159,13 @@ static inline struct page *compound_trans_head(struct page *page)
        }
        return page;
 }
+
+extern bool pmd_numa(struct vm_area_struct *vma, pmd_t pmd);
+
+extern void do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma,
+                                 unsigned long address, pmd_t *pmd,
+                                 unsigned int flags, pmd_t orig_pmd);
+
 #else /* CONFIG_TRANSPARENT_HUGEPAGE */
 #define HPAGE_PMD_SHIFT ({ BUILD_BUG(); 0; })
 #define HPAGE_PMD_MASK ({ BUILD_BUG(); 0; })
@@ -195,6 +202,18 @@ static inline int pmd_trans_huge_lock(pmd_t *pmd,
 {
        return 0;
 }
+
+static inline bool pmd_numa(struct vm_area_struct *vma, pmd_t pmd)
+{
+       return false;
+}
+
+static inline void do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma,
+                                 unsigned long address, pmd_t *pmd,
+                                 unsigned int flags, pmd_t orig_pmd)
+{
+}
+
 #endif /* CONFIG_TRANSPARENT_HUGEPAGE */
 
 #endif /* _LINUX_HUGE_MM_H */
index 2385119f8bb016c003f5bf2b638b412a6ddde7f9..85764a9007313186f3695ced71f31ba9893ff6be 100644 (file)
@@ -1107,20 +1107,6 @@ struct ieee80211_ht_operation {
 #define WLAN_HT_SMPS_CONTROL_STATIC    1
 #define WLAN_HT_SMPS_CONTROL_DYNAMIC   3
 
-#define VHT_MCS_SUPPORTED_SET_SIZE      8
-
-struct ieee80211_vht_capabilities {
-       __le32 vht_capabilities_info;
-       u8 vht_supported_mcs_set[VHT_MCS_SUPPORTED_SET_SIZE];
-} __packed;
-
-struct ieee80211_vht_operation {
-       u8 vht_op_info_chwidth;
-       u8 vht_op_info_chan_center_freq_seg1_idx;
-       u8 vht_op_info_chan_center_freq_seg2_idx;
-       __le16 vht_basic_mcs_set;
-} __packed;
-
 /**
  * struct ieee80211_vht_mcs_info - VHT MCS information
  * @rx_mcs_map: RX MCS map 2 bits for each stream, total 8 streams
@@ -1141,6 +1127,37 @@ struct ieee80211_vht_mcs_info {
        __le16 tx_highest;
 } __packed;
 
+/**
+ * struct ieee80211_vht_cap - VHT capabilities
+ *
+ * This structure is the "VHT capabilities element" as
+ * described in 802.11ac D3.0 8.4.2.160
+ * @vht_cap_info: VHT capability info
+ * @supp_mcs: VHT MCS supported rates
+ */
+struct ieee80211_vht_cap {
+       __le32 vht_cap_info;
+       struct ieee80211_vht_mcs_info supp_mcs;
+} __packed;
+
+/**
+ * struct ieee80211_vht_operation - VHT operation IE
+ *
+ * This structure is the "VHT operation element" as
+ * described in 802.11ac D3.0 8.4.2.161
+ * @chan_width: Operating channel width
+ * @center_freq_seg1_idx: center freq segment 1 index
+ * @center_freq_seg2_idx: center freq segment 2 index
+ * @basic_mcs_set: VHT Basic MCS rate set
+ */
+struct ieee80211_vht_operation {
+       u8 chan_width;
+       u8 center_freq_seg1_idx;
+       u8 center_freq_seg2_idx;
+       __le16 basic_mcs_set;
+} __packed;
+
+
 #define IEEE80211_VHT_MCS_ZERO_TO_SEVEN_SUPPORT 0
 #define IEEE80211_VHT_MCS_ZERO_TO_EIGHT_SUPPORT 1
 #define IEEE80211_VHT_MCS_ZERO_TO_NINE_SUPPORT  2
@@ -1440,8 +1457,6 @@ enum ieee80211_eid {
 
        WLAN_EID_RSN = 48,
        WLAN_EID_MMIE = 76,
-       WLAN_EID_WPA = 221,
-       WLAN_EID_GENERIC = 221,
        WLAN_EID_VENDOR_SPECIFIC = 221,
        WLAN_EID_QOS_PARAMETER = 222,
 
index c0ae76ac4e0b87e905d358e846bd8459f0f10023..7806c24e5bc8173a004597a1dd266f8e14900de6 100644 (file)
@@ -618,4 +618,20 @@ static inline struct dentry *iio_get_debugfs_dentry(struct iio_dev *indio_dev)
 };
 #endif
 
+/**
+ * IIO_DEGREE_TO_RAD() - Convert degree to rad
+ * @deg: A value in degree
+ *
+ * Returns the given value converted from degree to rad
+ */
+#define IIO_DEGREE_TO_RAD(deg) (((deg) * 314159ULL + 9000000ULL) / 18000000ULL)
+
+/**
+ * IIO_G_TO_M_S_2() - Convert g to meter / second**2
+ * @g: A value in g
+ *
+ * Returns the given value converted from g to meter / second**2
+ */
+#define IIO_G_TO_M_S_2(g) ((g) * 980665ULL / 100000ULL)
+
 #endif /* _INDUSTRIAL_IO_H_ */
index 5c647ecfd5ba9216810b031da17e26ed601364bf..87b196a2d69839ac5a5e2b2cf40d44877bb42fa4 100644 (file)
@@ -58,5 +58,6 @@ enum iio_modifier {
 #define IIO_VAL_INT_PLUS_NANO 3
 #define IIO_VAL_INT_PLUS_MICRO_DB 4
 #define IIO_VAL_FRACTIONAL 10
+#define IIO_VAL_FRACTIONAL_LOG2 11
 
 #endif /* _IIO_TYPES_H_ */
index 2c7223d7e73b720de899756e3a0433a813c2640e..86c361e947b93b6be3fb6d55d81ff2054c2a5f02 100644 (file)
@@ -18,6 +18,7 @@ extern int ima_bprm_check(struct linux_binprm *bprm);
 extern int ima_file_check(struct file *file, int mask);
 extern void ima_file_free(struct file *file);
 extern int ima_file_mmap(struct file *file, unsigned long prot);
+extern int ima_module_check(struct file *file);
 
 #else
 static inline int ima_bprm_check(struct linux_binprm *bprm)
@@ -40,6 +41,11 @@ static inline int ima_file_mmap(struct file *file, unsigned long prot)
        return 0;
 }
 
+static inline int ima_module_check(struct file *file)
+{
+       return 0;
+}
+
 #endif /* CONFIG_IMA_H */
 
 #ifdef CONFIG_IMA_APPRAISE
index 6d087c5f57f79e5a22ffa9a440061b5079838f53..b4405b6077749900e1cc2fb9ff9b15b5ace4161b 100644 (file)
@@ -143,6 +143,13 @@ extern struct task_group root_task_group;
 
 #define INIT_TASK_COMM "swapper"
 
+#ifdef CONFIG_SCHED_NUMA
+# define INIT_TASK_NUMA(tsk)                                           \
+       .node = -1,
+#else
+# define INIT_TASK_NUMA(tsk)
+#endif
+
 /*
  *  INIT_TASK is used to set up the first task table, touch at
  * your own risk!. Base=0, limit=0x1fffff (=2MB)
@@ -210,6 +217,7 @@ extern struct task_group root_task_group;
        INIT_TRACE_RECURSION                                            \
        INIT_TASK_RCU_PREEMPT(tsk)                                      \
        INIT_CPUSET_SEQ                                                 \
+       INIT_TASK_NUMA(tsk)                                             \
 }
 
 
index 2393b1c040b695d69d3a2f700300d3b4cec296c5..4dfde1161c5e7878565d05ad7f5293e9e4d19cef 100644 (file)
@@ -265,6 +265,7 @@ extern int key_unlink(struct key *keyring,
 
 extern struct key *keyring_alloc(const char *description, kuid_t uid, kgid_t gid,
                                 const struct cred *cred,
+                                key_perm_t perm,
                                 unsigned long flags,
                                 struct key *dest);
 
index 93bfc9f9815c7fa178ad70b555e7a2afb86b3f02..6afc5be2615efa5f6312ce6a9ec3d30dbdf87031 100644 (file)
@@ -118,6 +118,7 @@ static inline bool is_error_page(struct page *page)
 #define KVM_REQ_IMMEDIATE_EXIT    15
 #define KVM_REQ_PMU               16
 #define KVM_REQ_PMI               17
+#define KVM_REQ_WATCHDOG          18
 
 #define KVM_USERSPACE_IRQ_SOURCE_ID            0
 #define KVM_IRQFD_RESAMPLE_IRQ_SOURCE_ID       1
@@ -582,7 +583,6 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id);
 int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu);
 void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu);
 
-int kvm_arch_vcpu_reset(struct kvm_vcpu *vcpu);
 int kvm_arch_hardware_enable(void *garbage);
 void kvm_arch_hardware_disable(void *garbage);
 int kvm_arch_hardware_setup(void);
index e5ccb9ddd90eeb634665e88afd13d56184fff241..d6b1ea13218647fe93be002ac1989bc83f5b87e7 100644 (file)
@@ -5,7 +5,6 @@
 #ifndef _LINUX_MEMPOLICY_H
 #define _LINUX_MEMPOLICY_H 1
 
-
 #include <linux/mmzone.h>
 #include <linux/slab.h>
 #include <linux/rbtree.h>
@@ -198,7 +197,9 @@ static inline int vma_migratable(struct vm_area_struct *vma)
        return 1;
 }
 
-#else
+extern int mpol_misplaced(struct page *, struct vm_area_struct *, unsigned long);
+
+#else /* CONFIG_NUMA */
 
 struct mempolicy {};
 
@@ -323,5 +324,11 @@ static inline int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol,
        return 0;
 }
 
+static inline int mpol_misplaced(struct page *page, struct vm_area_struct *vma,
+                                unsigned long address)
+{
+       return -1; /* no node preference */
+}
+
 #endif /* CONFIG_NUMA */
 #endif
index 1d28ae90384ed42e9c43a63a01d3a63c91a9c812..fe03b2d35d4f39178a9227a5eeeeeb7355e19192 100644 (file)
 #ifndef __LINUX_MFD_MAX77693_H
 #define __LINUX_MFD_MAX77693_H
 
+struct max77693_reg_data {
+       u8 addr;
+       u8 data;
+};
+
+struct max77693_muic_platform_data {
+       struct max77693_reg_data *init_data;
+       int num_init_data;
+};
+
 struct max77693_platform_data {
        int wakeup;
+
+       /* muic data */
+       struct max77693_muic_platform_data *muic_data;
 };
 #endif /* __LINUX_MFD_MAX77693_H */
index 6bc31d854626b26f62994f0810a143ee00027e17..804e280c1e1d9a2a18157b377bfef9f622834cc7 100644 (file)
 
 #include <linux/irq.h>
 
+/* TPS65090 Regulator ID */
+enum {
+       TPS65090_REGULATOR_DCDC1,
+       TPS65090_REGULATOR_DCDC2,
+       TPS65090_REGULATOR_DCDC3,
+       TPS65090_REGULATOR_FET1,
+       TPS65090_REGULATOR_FET2,
+       TPS65090_REGULATOR_FET3,
+       TPS65090_REGULATOR_FET4,
+       TPS65090_REGULATOR_FET5,
+       TPS65090_REGULATOR_FET6,
+       TPS65090_REGULATOR_FET7,
+       TPS65090_REGULATOR_LDO1,
+       TPS65090_REGULATOR_LDO2,
+
+       /* Last entry for maximum ID */
+       TPS65090_REGULATOR_MAX,
+};
+
 struct tps65090 {
        struct mutex            lock;
        struct device           *dev;
@@ -41,10 +60,26 @@ struct tps65090_subdev_info {
        void            *platform_data;
 };
 
+/*
+ * struct tps65090_regulator_plat_data
+ *
+ * @reg_init_data: The regulator init data.
+ * @enable_ext_control: Enable extrenal control or not. Only available for
+ *     DCDC1, DCDC2 and DCDC3.
+ * @gpio: Gpio number if external control is enabled and controlled through
+ *     gpio.
+ */
+struct tps65090_regulator_plat_data {
+       struct regulator_init_data *reg_init_data;
+       bool enable_ext_control;
+       int gpio;
+};
+
 struct tps65090_platform_data {
        int irq_base;
        int num_subdevs;
        struct tps65090_subdev_info *subdevs;
+       struct tps65090_regulator_plat_data *reg_pdata[TPS65090_REGULATOR_MAX];
 };
 
 /*
index fc87be4fdc2501a8106b18664102c793ccdb588b..8e21a094836d21566bec6f08c027ad5c765fa715 100644 (file)
@@ -176,6 +176,11 @@ struct wm8994_pdata {
         unsigned int lineout1fb:1;
         unsigned int lineout2fb:1;
 
+       /* Delay between detecting a jack and starting microphone
+        * detect (specified in ms)
+        */
+       int micdet_delay;
+
        /* IRQ for microphone detection if brought out directly as a
         * signal.
         */
index ce7e6671968b791194df3c35d180443dbd615869..9a5afeaedf80bf2e50fc26b6373020930232edf7 100644 (file)
@@ -30,6 +30,7 @@ extern int migrate_vmas(struct mm_struct *mm,
 extern void migrate_page_copy(struct page *newpage, struct page *page);
 extern int migrate_huge_page_move_mapping(struct address_space *mapping,
                                  struct page *newpage, struct page *page);
+extern int migrate_misplaced_page(struct page *page, int node);
 #else
 
 static inline void putback_lru_pages(struct list_head *l) {}
@@ -63,5 +64,11 @@ static inline int migrate_huge_page_move_mapping(struct address_space *mapping,
 #define migrate_page NULL
 #define fail_migrate_page NULL
 
+static inline
+int migrate_misplaced_page(struct page *page, int node)
+{
+       return -EAGAIN; /* can't migrate now */
+}
 #endif /* CONFIG_MIGRATION */
+
 #endif /* _LINUX_MIGRATE_H */
index ebf3d89a3919405ccd9a887178c65764a931a291..40b37dc103186abcb93f20f2ea73ee5ca18c6d4e 100644 (file)
@@ -6,11 +6,14 @@
  *     on most operations but not ->writepage as the potential stall time
  *     is too significant
  * MIGRATE_SYNC will block when migrating pages
+ * MIGRATE_FAULT called from the fault path to migrate-on-fault for mempolicy
+ *     this path has an extra reference count
  */
 enum migrate_mode {
        MIGRATE_ASYNC,
        MIGRATE_SYNC_LIGHT,
        MIGRATE_SYNC,
+       MIGRATE_FAULT,
 };
 
 #endif         /* MIGRATE_MODE_H_INCLUDED */
index fa068040273893c27d71461e459e2eb268739396..54b3094374be7f28e3b1e8c921a097f58517189f 100644 (file)
@@ -163,6 +163,19 @@ extern pgprot_t protection_map[16];
 #define FAULT_FLAG_KILLABLE    0x20    /* The fault task is in SIGKILL killable region */
 #define FAULT_FLAG_TRIED       0x40    /* second try */
 
+/*
+ * Some architectures (such as x86) may need to preserve certain pgprot
+ * bits, without complicating generic pgprot code.
+ *
+ * Most architectures don't care:
+ */
+#ifndef pgprot_modify
+static inline pgprot_t pgprot_modify(pgprot_t oldprot, pgprot_t newprot)
+{
+       return newprot;
+}
+#endif
+
 /*
  * vm_fault is filled by the the pagefault handler and passed to the vma's
  * ->fault function. The vma's ->fault is responsible for returning a bitmask
@@ -581,50 +594,11 @@ static inline pte_t maybe_mkwrite(pte_t pte, struct vm_area_struct *vma)
  * sets it, so none of the operations on it need to be atomic.
  */
 
-
-/*
- * page->flags layout:
- *
- * There are three possibilities for how page->flags get
- * laid out.  The first is for the normal case, without
- * sparsemem.  The second is for sparsemem when there is
- * plenty of space for node and section.  The last is when
- * we have run out of space and have to fall back to an
- * alternate (slower) way of determining the node.
- *
- * No sparsemem or sparsemem vmemmap: |       NODE     | ZONE | ... | FLAGS |
- * classic sparse with space for node:| SECTION | NODE | ZONE | ... | FLAGS |
- * classic sparse no space for node:  | SECTION |     ZONE    | ... | FLAGS |
- */
-#if defined(CONFIG_SPARSEMEM) && !defined(CONFIG_SPARSEMEM_VMEMMAP)
-#define SECTIONS_WIDTH         SECTIONS_SHIFT
-#else
-#define SECTIONS_WIDTH         0
-#endif
-
-#define ZONES_WIDTH            ZONES_SHIFT
-
-#if SECTIONS_WIDTH+ZONES_WIDTH+NODES_SHIFT <= BITS_PER_LONG - NR_PAGEFLAGS
-#define NODES_WIDTH            NODES_SHIFT
-#else
-#ifdef CONFIG_SPARSEMEM_VMEMMAP
-#error "Vmemmap: No space for nodes field in page flags"
-#endif
-#define NODES_WIDTH            0
-#endif
-
-/* Page flags: | [SECTION] | [NODE] | ZONE | ... | FLAGS | */
+/* Page flags: | [SECTION] | [NODE] | ZONE | [LAST_NID] | ... | FLAGS | */
 #define SECTIONS_PGOFF         ((sizeof(unsigned long)*8) - SECTIONS_WIDTH)
 #define NODES_PGOFF            (SECTIONS_PGOFF - NODES_WIDTH)
 #define ZONES_PGOFF            (NODES_PGOFF - ZONES_WIDTH)
-
-/*
- * We are going to use the flags for the page to node mapping if its in
- * there.  This includes the case where there is no node, so it is implicit.
- */
-#if !(NODES_WIDTH > 0 || NODES_SHIFT == 0)
-#define NODE_NOT_IN_PAGE_FLAGS
-#endif
+#define LAST_NID_PGOFF         (ZONES_PGOFF - LAST_NID_WIDTH)
 
 /*
  * Define the bit shifts to access each section.  For non-existent
@@ -634,6 +608,7 @@ static inline pte_t maybe_mkwrite(pte_t pte, struct vm_area_struct *vma)
 #define SECTIONS_PGSHIFT       (SECTIONS_PGOFF * (SECTIONS_WIDTH != 0))
 #define NODES_PGSHIFT          (NODES_PGOFF * (NODES_WIDTH != 0))
 #define ZONES_PGSHIFT          (ZONES_PGOFF * (ZONES_WIDTH != 0))
+#define LAST_NID_PGSHIFT       (LAST_NID_PGOFF * (LAST_NID_WIDTH != 0))
 
 /* NODE:ZONE or SECTION:ZONE is used to ID a zone for the buddy allocator */
 #ifdef NODE_NOT_IN_PAGE_FLAGS
@@ -655,6 +630,7 @@ static inline pte_t maybe_mkwrite(pte_t pte, struct vm_area_struct *vma)
 #define ZONES_MASK             ((1UL << ZONES_WIDTH) - 1)
 #define NODES_MASK             ((1UL << NODES_WIDTH) - 1)
 #define SECTIONS_MASK          ((1UL << SECTIONS_WIDTH) - 1)
+#define LAST_NID_MASK          ((1UL << LAST_NID_WIDTH) - 1)
 #define ZONEID_MASK            ((1UL << ZONEID_SHIFT) - 1)
 
 static inline enum zone_type page_zonenum(const struct page *page)
@@ -693,6 +669,51 @@ static inline int page_to_nid(const struct page *page)
 }
 #endif
 
+#ifdef CONFIG_SCHED_NUMA
+#ifdef LAST_NID_NOT_IN_PAGE_FLAGS
+static inline int page_xchg_last_nid(struct page *page, int nid)
+{
+       return xchg(&page->_last_nid, nid);
+}
+
+static inline int page_last_nid(struct page *page)
+{
+       return page->_last_nid;
+}
+#else
+static inline int page_xchg_last_nid(struct page *page, int nid)
+{
+       unsigned long old_flags, flags;
+       int last_nid;
+
+       do {
+               old_flags = flags = page->flags;
+               last_nid = (flags >> LAST_NID_PGSHIFT) & LAST_NID_MASK;
+
+               flags &= ~(LAST_NID_MASK << LAST_NID_PGSHIFT);
+               flags |= (nid & LAST_NID_MASK) << LAST_NID_PGSHIFT;
+       } while (unlikely(cmpxchg(&page->flags, old_flags, flags) != old_flags));
+
+       return last_nid;
+}
+
+static inline int page_last_nid(struct page *page)
+{
+       return (page->flags >> LAST_NID_PGSHIFT) & LAST_NID_MASK;
+}
+#endif /* LAST_NID_NOT_IN_PAGE_FLAGS */
+#else /* CONFIG_SCHED_NUMA */
+static inline int page_xchg_last_nid(struct page *page, int nid)
+{
+       return page_to_nid(page);
+}
+
+static inline int page_last_nid(struct page *page)
+{
+       return page_to_nid(page);
+}
+#endif /* CONFIG_SCHED_NUMA */
+
 static inline struct zone *page_zone(const struct page *page)
 {
        return &NODE_DATA(page_to_nid(page))->node_zones[page_zonenum(page)];
@@ -1078,6 +1099,9 @@ extern unsigned long move_page_tables(struct vm_area_struct *vma,
 extern unsigned long do_mremap(unsigned long addr,
                               unsigned long old_len, unsigned long new_len,
                               unsigned long flags, unsigned long new_addr);
+extern void change_protection(struct vm_area_struct *vma, unsigned long start,
+                             unsigned long end, pgprot_t newprot,
+                             int dirty_accountable);
 extern int mprotect_fixup(struct vm_area_struct *vma,
                          struct vm_area_struct **pprev, unsigned long start,
                          unsigned long end, unsigned long newflags);
@@ -1548,6 +1572,21 @@ static inline pgprot_t vm_get_page_prot(unsigned long vm_flags)
 }
 #endif
 
+static inline pgprot_t vma_prot_none(struct vm_area_struct *vma)
+{
+       /*
+        * obtain PROT_NONE by removing READ|WRITE|EXEC privs
+        */
+       vm_flags_t vmflags = vma->vm_flags & ~(VM_READ|VM_WRITE|VM_EXEC);
+       return pgprot_modify(vma->vm_page_prot, vm_get_page_prot(vmflags));
+}
+
+static inline void
+change_prot_none(struct vm_area_struct *vma, unsigned long start, unsigned long end)
+{
+       change_protection(vma, start, end, vma_prot_none(vma), 0);
+}
+
 struct vm_area_struct *find_extend_vma(struct mm_struct *, unsigned long addr);
 int remap_pfn_range(struct vm_area_struct *, unsigned long addr,
                        unsigned long pfn, unsigned long size, pgprot_t);
@@ -1569,6 +1608,7 @@ struct page *follow_page(struct vm_area_struct *, unsigned long address,
 #define FOLL_MLOCK     0x40    /* mark page as mlocked */
 #define FOLL_SPLIT     0x80    /* don't return transhuge pages, split them */
 #define FOLL_HWPOISON  0x100   /* check page is hwpoisoned */
+#define FOLL_NUMA      0x200   /* force NUMA hinting page fault */
 
 typedef int (*pte_fn_t)(pte_t *pte, pgtable_t token, unsigned long addr,
                        void *data);
index 31f8a3af7d942545562afd1fcacf11f52a4f82a0..77b268fef8429fa77e8e850ee37e6106d0b6567c 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/cpumask.h>
 #include <linux/page-debug-flags.h>
 #include <linux/uprobes.h>
+#include <linux/page-flags-layout.h>
 #include <asm/page.h>
 #include <asm/mmu.h>
 
@@ -128,10 +129,7 @@ struct page {
                };
 
                struct list_head list;  /* slobs list of pages */
-               struct {                /* slab fields */
-                       struct kmem_cache *slab_cache;
-                       struct slab *slab_page;
-               };
+               struct slab *slab_page; /* slab fields */
        };
 
        /* Remainder is not double word aligned */
@@ -146,7 +144,7 @@ struct page {
 #if USE_SPLIT_PTLOCKS
                spinlock_t ptl;
 #endif
-               struct kmem_cache *slab;        /* SLUB: Pointer to slab */
+               struct kmem_cache *slab_cache;  /* SL[AU]B: Pointer to slab */
                struct page *first_page;        /* Compound tail pages */
        };
 
@@ -175,6 +173,10 @@ struct page {
         */
        void *shadow;
 #endif
+
+#ifdef LAST_NID_NOT_IN_PAGE_FLAGS
+       int _last_nid;
+#endif
 }
 /*
  * The struct page can be forced to be double word aligned so that atomic ops
@@ -397,6 +399,11 @@ struct mm_struct {
 #endif
 #ifdef CONFIG_CPUMASK_OFFSTACK
        struct cpumask cpumask_allocation;
+#endif
+#ifdef CONFIG_SCHED_NUMA
+       unsigned long numa_next_scan;
+       unsigned long numa_scan_offset;
+       int numa_scan_seq;
 #endif
        struct uprobes_state uprobes_state;
 };
index 7c6a1139d8faf9ad54af671c68cd81ea3dcebf2f..31416760723c86f38ae75020fcc2879ebcc8fa9d 100644 (file)
@@ -186,7 +186,7 @@ struct dw_mci {
 
        struct regulator        *vmmc;  /* Power regulator */
        unsigned long           irq_flags; /* IRQ flags */
-       unsigned int            irq;
+       int                     irq;
 };
 
 /* DMA ops for Internal/External DMAC interface */
index 50aaca81f63d6db3914b7858f0209fed036a5971..c9fcd8f6618430458e8aca57f863a9151c1020f6 100644 (file)
@@ -15,7 +15,7 @@
 #include <linux/seqlock.h>
 #include <linux/nodemask.h>
 #include <linux/pageblock-flags.h>
-#include <generated/bounds.h>
+#include <linux/page-flags-layout.h>
 #include <linux/atomic.h>
 #include <asm/page.h>
 
@@ -137,7 +137,6 @@ enum zone_stat_item {
        NUMA_HIT,               /* allocated in intended node */
        NUMA_MISS,              /* allocated in non intended node */
        NUMA_FOREIGN,           /* was intended here, hit elsewhere */
-       NUMA_INTERLEAVE_HIT,    /* interleaver preferred this zone */
        NUMA_LOCAL,             /* allocation from local node */
        NUMA_OTHER,             /* allocation from other node */
 #endif
@@ -318,16 +317,6 @@ enum zone_type {
  * match the requested limits. See gfp_zone() in include/linux/gfp.h
  */
 
-#if MAX_NR_ZONES < 2
-#define ZONES_SHIFT 0
-#elif MAX_NR_ZONES <= 2
-#define ZONES_SHIFT 1
-#elif MAX_NR_ZONES <= 4
-#define ZONES_SHIFT 2
-#else
-#error ZONES_SHIFT -- too many zones configured adjust calculation
-#endif
-
 struct zone {
        /* Fields commonly accessed by the page allocator */
 
@@ -1030,8 +1019,6 @@ static inline unsigned long early_pfn_to_nid(unsigned long pfn)
  * PA_SECTION_SHIFT            physical address to/from section number
  * PFN_SECTION_SHIFT           pfn to/from section number
  */
-#define SECTIONS_SHIFT         (MAX_PHYSMEM_BITS - SECTION_SIZE_BITS)
-
 #define PA_SECTION_SHIFT       (SECTION_SIZE_BITS)
 #define PFN_SECTION_SHIFT      (SECTION_SIZE_BITS - PAGE_SHIFT)
 
index b20029221fb1b6e95a1d1a689ba56850d8837f56..d6ed61ef451df403377f77e010a52711dac8e5a9 100644 (file)
@@ -155,9 +155,6 @@ struct fsmc_nand_platform_data {
        unsigned int            width;
        unsigned int            bank;
 
-       /* CLE, ALE offsets */
-       unsigned int            cle_off;
-       unsigned int            ale_off;
        enum access_mode        mode;
 
        void                    (*select_bank)(uint32_t bank, uint32_t busw);
index 81d61e70459938e6aab57239898e31fc8389e25c..f9ac2897b86b040f0143b9bbc3d10bb9699f6cd6 100644 (file)
@@ -98,7 +98,7 @@ struct mtd_oob_ops {
 };
 
 #define MTD_MAX_OOBFREE_ENTRIES_LARGE  32
-#define MTD_MAX_ECCPOS_ENTRIES_LARGE   448
+#define MTD_MAX_ECCPOS_ENTRIES_LARGE   640
 /*
  * Internal ECC layout control structure. For historical reasons, there is a
  * similar, smaller struct nand_ecclayout_user (in mtd-abi.h) that is retained
diff --git a/include/linux/page-flags-layout.h b/include/linux/page-flags-layout.h
new file mode 100644 (file)
index 0000000..586ddb6
--- /dev/null
@@ -0,0 +1,83 @@
+#ifndef _LINUX_PAGE_FLAGS_LAYOUT
+#define _LINUX_PAGE_FLAGS_LAYOUT
+
+#include <linux/numa.h>
+#include <generated/bounds.h>
+
+#if MAX_NR_ZONES < 2
+#define ZONES_SHIFT 0
+#elif MAX_NR_ZONES <= 2
+#define ZONES_SHIFT 1
+#elif MAX_NR_ZONES <= 4
+#define ZONES_SHIFT 2
+#else
+#error ZONES_SHIFT -- too many zones configured adjust calculation
+#endif
+
+#ifdef CONFIG_SPARSEMEM
+#include <asm/sparsemem.h>
+
+/* 
+ * SECTION_SHIFT               #bits space required to store a section #
+ */
+#define SECTIONS_SHIFT         (MAX_PHYSMEM_BITS - SECTION_SIZE_BITS)
+#endif
+
+/*
+ * page->flags layout:
+ *
+ * There are five possibilities for how page->flags get laid out.  The first
+ * (and second) is for the normal case, without sparsemem. The third is for
+ * sparsemem when there is plenty of space for node and section. The last is
+ * when we have run out of space and have to fall back to an alternate (slower)
+ * way of determining the node.
+ *
+ * No sparsemem or sparsemem vmemmap: |       NODE     | ZONE |            ... | FLAGS |
+ *     "      plus space for last_nid:|       NODE     | ZONE | LAST_NID | ... | FLAGS |
+ * classic sparse with space for node:| SECTION | NODE | ZONE |            ... | FLAGS |
+ *     "      plus space for last_nid:| SECTION | NODE | ZONE | LAST_NID | ... | FLAGS |
+ * classic sparse no space for node:  | SECTION |     ZONE    |            ... | FLAGS |
+ */
+#if defined(CONFIG_SPARSEMEM) && !defined(CONFIG_SPARSEMEM_VMEMMAP)
+
+#define SECTIONS_WIDTH         SECTIONS_SHIFT
+#else
+#define SECTIONS_WIDTH         0
+#endif
+
+#define ZONES_WIDTH            ZONES_SHIFT
+
+#if SECTIONS_WIDTH+ZONES_WIDTH+NODES_SHIFT <= BITS_PER_LONG - NR_PAGEFLAGS
+#define NODES_WIDTH            NODES_SHIFT
+#else
+#ifdef CONFIG_SPARSEMEM_VMEMMAP
+#error "Vmemmap: No space for nodes field in page flags"
+#endif
+#define NODES_WIDTH            0
+#endif
+
+#ifdef CONFIG_SCHED_NUMA
+#define LAST_NID_SHIFT NODES_SHIFT
+#else
+#define LAST_NID_SHIFT 0
+#endif
+
+#if SECTIONS_WIDTH+ZONES_WIDTH+NODES_SHIFT+LAST_NID_SHIFT <= BITS_PER_LONG - NR_PAGEFLAGS
+#define LAST_NID_WIDTH LAST_NID_SHIFT
+#else
+#define LAST_NID_WIDTH 0
+#endif
+
+/*
+ * We are going to use the flags for the page to node mapping if its in
+ * there.  This includes the case where there is no node, so it is implicit.
+ */
+#if !(NODES_WIDTH > 0 || NODES_SHIFT == 0)
+#define NODE_NOT_IN_PAGE_FLAGS
+#endif
+
+#if defined(CONFIG_SCHED_NUMA) && LAST_NID_WIDTH == 0
+#define LAST_NID_NOT_IN_PAGE_FLAGS
+#endif
+
+#endif /* _LINUX_PAGE_FLAGS_LAYOUT */
index 2e902359aee596f128dee568d06e0e0ab3149dfe..6bfb2faa0b1937555f5ca8fa937c7007bf5b3bc4 100644 (file)
@@ -803,12 +803,16 @@ static inline void perf_event_task_tick(void)                             { }
 do {                                                                   \
        static struct notifier_block fn##_nb __cpuinitdata =            \
                { .notifier_call = fn, .priority = CPU_PRI_PERF };      \
+       unsigned long cpu = smp_processor_id();                         \
+       unsigned long flags;                                            \
        fn(&fn##_nb, (unsigned long)CPU_UP_PREPARE,                     \
-               (void *)(unsigned long)smp_processor_id());             \
+               (void *)(unsigned long)cpu);                            \
+       local_irq_save(flags);                                          \
        fn(&fn##_nb, (unsigned long)CPU_STARTING,                       \
-               (void *)(unsigned long)smp_processor_id());             \
+               (void *)(unsigned long)cpu);                            \
+       local_irq_restore(flags);                                       \
        fn(&fn##_nb, (unsigned long)CPU_ONLINE,                         \
-               (void *)(unsigned long)smp_processor_id());             \
+               (void *)(unsigned long)cpu);                            \
        register_cpu_notifier(&fn##_nb);                                \
 } while (0)
 
index 00474b047145ed1f54f3003fe597873a4665cc48..65e3e87eacc59aab1d95a8bd1a14a2e61f29c1f3 100644 (file)
@@ -47,15 +47,9 @@ static inline struct pid_namespace *get_pid_ns(struct pid_namespace *ns)
 }
 
 extern struct pid_namespace *copy_pid_ns(unsigned long flags, struct pid_namespace *ns);
-extern void free_pid_ns(struct kref *kref);
 extern void zap_pid_ns_processes(struct pid_namespace *pid_ns);
 extern int reboot_pid_ns(struct pid_namespace *pid_ns, int cmd);
-
-static inline void put_pid_ns(struct pid_namespace *ns)
-{
-       if (ns != &init_pid_ns)
-               kref_put(&ns->kref, free_pid_ns);
-}
+extern void put_pid_ns(struct pid_namespace *ns);
 
 #else /* !CONFIG_PID_NS */
 #include <linux/err.h>
diff --git a/include/linux/platform_data/ad5449.h b/include/linux/platform_data/ad5449.h
new file mode 100644 (file)
index 0000000..bd712bd
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * AD5415, AD5426, AD5429, AD5432, AD5439, AD5443, AD5449 Digital to Analog
+ * Converter driver.
+ *
+ * Copyright 2012 Analog Devices Inc.
+ *  Author: Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#ifndef __LINUX_PLATFORM_DATA_AD5449_H__
+#define __LINUX_PLATFORM_DATA_AD5449_H__
+
+/**
+ * enum ad5449_sdo_mode - AD5449 SDO pin configuration
+ * @AD5449_SDO_DRIVE_FULL: Drive the SDO pin with full strength.
+ * @AD5449_SDO_DRIVE_WEAK: Drive the SDO pin with not full strength.
+ * @AD5449_SDO_OPEN_DRAIN: Operate the SDO pin in open-drain mode.
+ * @AD5449_SDO_DISABLED: Disable the SDO pin, in this mode it is not possible to
+ *                     read back from the device.
+ */
+enum ad5449_sdo_mode {
+       AD5449_SDO_DRIVE_FULL = 0x0,
+       AD5449_SDO_DRIVE_WEAK = 0x1,
+       AD5449_SDO_OPEN_DRAIN = 0x2,
+       AD5449_SDO_DISABLED = 0x3,
+};
+
+/**
+ * struct ad5449_platform_data - Platform data for the ad5449 DAC driver
+ * @sdo_mode: SDO pin mode
+ * @hardware_clear_to_midscale: Whether asserting the hardware CLR pin sets the
+ *                     outputs to midscale (true) or to zero scale(false).
+ */
+struct ad5449_platform_data {
+       enum ad5449_sdo_mode sdo_mode;
+       bool hardware_clear_to_midscale;
+};
+
+#endif
diff --git a/include/linux/platform_data/ads7828.h b/include/linux/platform_data/ads7828.h
new file mode 100644 (file)
index 0000000..3245f45
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * TI ADS7828 A/D Converter platform data definition
+ *
+ * Copyright (c) 2012 Savoir-faire Linux Inc.
+ *          Vivien Didelot <vivien.didelot@savoirfairelinux.com>
+ *
+ * For further information, see the Documentation/hwmon/ads7828 file.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _PDATA_ADS7828_H
+#define _PDATA_ADS7828_H
+
+/**
+ * struct ads7828_platform_data - optional ADS7828 connectivity info
+ * @diff_input:                Differential input mode.
+ * @ext_vref:          Use an external voltage reference.
+ * @vref_mv:           Voltage reference value, if external.
+ */
+struct ads7828_platform_data {
+       bool diff_input;
+       bool ext_vref;
+       unsigned int vref_mv;
+};
+
+#endif /* _PDATA_ADS7828_H */
index 63f3c28042396afd1d2333f7bf59e1a78bcf6c54..92c7fd72f63669b0354179a5f8c3370feb347e0f 100644 (file)
@@ -17,5 +17,7 @@ struct imx_ssi_platform_data {
        void (*ac97_warm_reset)(struct snd_ac97 *ac97);
 };
 
+extern int mxc_set_irq_fiq(unsigned int irq, unsigned int type);
+
 #endif /* __MACH_SSI_H */
 
index d0c5825876f8a2d1d124a3d51fac880951a63b2f..f3d6e4f20962e6761811758f6b32f6f09a441a21 100644 (file)
@@ -16,6 +16,8 @@
 #ifndef __DAVINCI_ASP_H
 #define __DAVINCI_ASP_H
 
+#include <linux/genalloc.h>
+
 struct snd_platform_data {
        u32 tx_dma_offset;
        u32 rx_dma_offset;
@@ -30,6 +32,7 @@ struct snd_platform_data {
        unsigned enable_channel_combine:1;
        unsigned sram_size_playback;
        unsigned sram_size_capture;
+       struct gen_pool *sram_pool;
 
        /*
         * If McBSP peripheral gets the clock from an external pin,
index 1b9080385b4618b2b3c76ab057a7bf271df8d73d..f6d30cc1cb77eeb4681f9bd83f7471973ec17581 100644 (file)
@@ -61,7 +61,9 @@ static inline int imx_dma_is_ipu(struct dma_chan *chan)
 static inline int imx_dma_is_general_purpose(struct dma_chan *chan)
 {
        return strstr(dev_name(chan->device->dev), "sdma") ||
-               !strcmp(dev_name(chan->device->dev), "imx-dma");
+               !strcmp(dev_name(chan->device->dev), "imx1-dma") ||
+               !strcmp(dev_name(chan->device->dev), "imx21-dma") ||
+               !strcmp(dev_name(chan->device->dev), "imx27-dma");
 }
 
 #endif
index b081c7245ec8a94cd7ed3664c1f91a0e15814897..044a124bfbbc6b313d96f187a598fcb1438b8cc6 100644 (file)
@@ -12,6 +12,7 @@ struct macb_platform_data {
        u32             phy_mask;
        int             phy_irq_pin;    /* PHY IRQ */
        u8              is_rmii;        /* using RMII interface? */
+       u8              rev_eth_addr;   /* reverse Ethernet address byte order */
 };
 
 #endif /* __MACB_PDATA_H__ */
diff --git a/include/linux/platform_data/mtd-nomadik-nand.h b/include/linux/platform_data/mtd-nomadik-nand.h
deleted file mode 100644 (file)
index c3c8254..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef __ASM_ARCH_NAND_H
-#define __ASM_ARCH_NAND_H
-
-struct nomadik_nand_platform_data {
-       struct mtd_partition *parts;
-       int nparts;
-       int options;
-       int (*init) (void);
-       int (*exit) (void);
-};
-
-#define NAND_IO_DATA   0x40000000
-#define NAND_IO_CMD    0x40800000
-#define NAND_IO_ADDR   0x41000000
-
-#endif                         /* __ASM_ARCH_NAND_H */
index 30dea251b835b3433af3fd93a840a2d70a91cc57..27a23b318cef9fcdc7f199cf320bb65f601ece9f 100644 (file)
  * struct u300_gpio_platform - U300 GPIO platform data
  * @ports: number of GPIO block ports
  * @gpio_base: first GPIO number for this block (use a free range)
- * @gpio_irq_base: first GPIO IRQ number for this block (use a free range)
  * @pinctrl_device: pin control device to spawn as child
  */
 struct u300_gpio_platform {
        u8 ports;
        int gpio_base;
-       int gpio_irq_base;
        struct platform_device *pinctrl_device;
 };
 
similarity index 66%
rename from arch/arm/plat-nomadik/include/plat/pincfg.h
rename to include/linux/platform_data/pinctrl-nomadik.h
index 3b8ec60af351500a5cbcb80c970b8026c7d8477d..f73b2f0c55b77f6fc61605f6315563494d6692fc 100644 (file)
@@ -1,16 +1,17 @@
 /*
- * Copyright (C) ST-Ericsson SA 2010
+ * Structures and registers for GPIO access in the Nomadik SoC
  *
- * License terms: GNU General Public License, version 2
- * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
+ * Copyright (C) 2008 STMicroelectronics
+ *     Author: Prafulla WADASKAR <prafulla.wadaskar@st.com>
+ * Copyright (C) 2009 Alessandro Rubini <rubini@unipv.it>
  *
- * Based on arch/arm/mach-pxa/include/mach/mfp.h:
- *   Copyright (C) 2007 Marvell International Ltd.
- *   eric miao <eric.miao@marvell.com>
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
  */
 
-#ifndef __PLAT_PINCFG_H
-#define __PLAT_PINCFG_H
+#ifndef __PLAT_NOMADIK_GPIO
+#define __PLAT_NOMADIK_GPIO
 
 /*
  * pin configurations are represented by 32-bit integers:
@@ -166,8 +167,100 @@ typedef unsigned long pin_cfg_t;
        (PIN_CFG_DEFAULT |\
         (PIN_NUM(num) | PIN_##alt | PIN_OUTPUT_##val))
 
+/*
+ * "nmk_gpio" and "NMK_GPIO" stand for "Nomadik GPIO", leaving
+ * the "gpio" namespace for generic and cross-machine functions
+ */
+
+#define GPIO_BLOCK_SHIFT 5
+#define NMK_GPIO_PER_CHIP (1 << GPIO_BLOCK_SHIFT)
+
+/* Register in the logic block */
+#define NMK_GPIO_DAT   0x00
+#define NMK_GPIO_DATS  0x04
+#define NMK_GPIO_DATC  0x08
+#define NMK_GPIO_PDIS  0x0c
+#define NMK_GPIO_DIR   0x10
+#define NMK_GPIO_DIRS  0x14
+#define NMK_GPIO_DIRC  0x18
+#define NMK_GPIO_SLPC  0x1c
+#define NMK_GPIO_AFSLA 0x20
+#define NMK_GPIO_AFSLB 0x24
+#define NMK_GPIO_LOWEMI        0x28
+
+#define NMK_GPIO_RIMSC 0x40
+#define NMK_GPIO_FIMSC 0x44
+#define NMK_GPIO_IS    0x48
+#define NMK_GPIO_IC    0x4c
+#define NMK_GPIO_RWIMSC        0x50
+#define NMK_GPIO_FWIMSC        0x54
+#define NMK_GPIO_WKS   0x58
+/* These appear in DB8540 and later ASICs */
+#define NMK_GPIO_EDGELEVEL 0x5C
+#define NMK_GPIO_LEVEL 0x60
+
+/* Alternate functions: function C is set in hw by setting both A and B */
+#define NMK_GPIO_ALT_GPIO      0
+#define NMK_GPIO_ALT_A 1
+#define NMK_GPIO_ALT_B 2
+#define NMK_GPIO_ALT_C (NMK_GPIO_ALT_A | NMK_GPIO_ALT_B)
+
+#define NMK_GPIO_ALT_CX_SHIFT 2
+#define NMK_GPIO_ALT_C1        ((1<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C)
+#define NMK_GPIO_ALT_C2        ((2<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C)
+#define NMK_GPIO_ALT_C3        ((3<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C)
+#define NMK_GPIO_ALT_C4        ((4<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C)
+
+/* Pull up/down values */
+enum nmk_gpio_pull {
+       NMK_GPIO_PULL_NONE,
+       NMK_GPIO_PULL_UP,
+       NMK_GPIO_PULL_DOWN,
+};
+
+/* Sleep mode */
+enum nmk_gpio_slpm {
+       NMK_GPIO_SLPM_INPUT,
+       NMK_GPIO_SLPM_WAKEUP_ENABLE = NMK_GPIO_SLPM_INPUT,
+       NMK_GPIO_SLPM_NOCHANGE,
+       NMK_GPIO_SLPM_WAKEUP_DISABLE = NMK_GPIO_SLPM_NOCHANGE,
+};
+
+/* Older deprecated pin config API that should go away soon */
 extern int nmk_config_pin(pin_cfg_t cfg, bool sleep);
 extern int nmk_config_pins(pin_cfg_t *cfgs, int num);
 extern int nmk_config_pins_sleep(pin_cfg_t *cfgs, int num);
-
+extern int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode);
+extern int nmk_gpio_set_pull(int gpio, enum nmk_gpio_pull pull);
+#ifdef CONFIG_PINCTRL_NOMADIK
+extern int nmk_gpio_set_mode(int gpio, int gpio_mode);
+#else
+static inline int nmk_gpio_set_mode(int gpio, int gpio_mode)
+{
+       return -ENODEV;
+}
 #endif
+extern int nmk_gpio_get_mode(int gpio);
+
+extern void nmk_gpio_wakeups_suspend(void);
+extern void nmk_gpio_wakeups_resume(void);
+
+extern void nmk_gpio_clocks_enable(void);
+extern void nmk_gpio_clocks_disable(void);
+
+extern void nmk_gpio_read_pull(int gpio_bank, u32 *pull_up);
+
+/*
+ * Platform data to register a block: only the initial gpio/irq number.
+ */
+struct nmk_gpio_platform_data {
+       char *name;
+       int first_gpio;
+       int first_irq;
+       int num_gpio;
+       u32 (*get_secondary_status)(unsigned int bank);
+       void (*set_ioforce)(bool enable);
+       bool supports_sleepmode;
+};
+
+#endif /* __PLAT_NOMADIK_GPIO */
index a357eb26bd258dfd6a969bf218da86d322f41ba1..ce70f7b5a8e1a0c77fb10b232c10fd405a5a48f1 100644 (file)
@@ -7,9 +7,13 @@
 
 #define OMAP4_MCSPI_REG_OFFSET 0x100
 
+#define MCSPI_PINDIR_D0_OUT_D1_IN      0
+#define MCSPI_PINDIR_D0_IN_D1_OUT      1
+
 struct omap2_mcspi_platform_config {
        unsigned short  num_cs;
        unsigned int regs_offset;
+       unsigned int pin_dir:1;
 };
 
 struct omap2_mcspi_dev_attr {
diff --git a/include/linux/platform_data/uio_dmem_genirq.h b/include/linux/platform_data/uio_dmem_genirq.h
new file mode 100644 (file)
index 0000000..973c1bb
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * include/linux/platform_data/uio_dmem_genirq.h
+ *
+ * Copyright (C) 2012 Damian Hobson-Garcia
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _UIO_DMEM_GENIRQ_H
+#define _UIO_DMEM_GENIRQ_H
+
+#include <linux/uio_driver.h>
+
+struct uio_dmem_genirq_pdata {
+       struct uio_info uioinfo;
+       unsigned int *dynamic_region_sizes;
+       unsigned int num_dynamic_regions;
+};
+#endif /* _UIO_DMEM_GENIRQ_H */
index 007e687c4f6915866b9d551bbc37cd14747f28ac..03d7bb145311e5aca53beb6f078dbac218c434d8 100644 (file)
@@ -546,10 +546,9 @@ struct dev_pm_info {
        unsigned long           active_jiffies;
        unsigned long           suspended_jiffies;
        unsigned long           accounting_timestamp;
-       struct dev_pm_qos_request *pq_req;
 #endif
        struct pm_subsys_data   *subsys_data;  /* Owned by the subsystem. */
-       struct pm_qos_constraints *constraints;
+       struct dev_pm_qos       *qos;
 };
 
 extern void update_pm_runtime_accounting(struct device *dev);
index 9924ea1f22e07306f39607e08df8b36244832ab9..5a95013905c8c9ab96fde04c3dc8a914b78119da 100644 (file)
@@ -20,6 +20,13 @@ enum {
        PM_QOS_NUM_CLASSES,
 };
 
+enum pm_qos_flags_status {
+       PM_QOS_FLAGS_UNDEFINED = -1,
+       PM_QOS_FLAGS_NONE,
+       PM_QOS_FLAGS_SOME,
+       PM_QOS_FLAGS_ALL,
+};
+
 #define PM_QOS_DEFAULT_VALUE -1
 
 #define PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE       (2000 * USEC_PER_SEC)
@@ -27,14 +34,31 @@ enum {
 #define PM_QOS_NETWORK_THROUGHPUT_DEFAULT_VALUE        0
 #define PM_QOS_DEV_LAT_DEFAULT_VALUE           0
 
+#define PM_QOS_FLAG_NO_POWER_OFF       (1 << 0)
+#define PM_QOS_FLAG_REMOTE_WAKEUP      (1 << 1)
+
 struct pm_qos_request {
        struct plist_node node;
        int pm_qos_class;
        struct delayed_work work; /* for pm_qos_update_request_timeout */
 };
 
+struct pm_qos_flags_request {
+       struct list_head node;
+       s32 flags;      /* Do not change to 64 bit */
+};
+
+enum dev_pm_qos_req_type {
+       DEV_PM_QOS_LATENCY = 1,
+       DEV_PM_QOS_FLAGS,
+};
+
 struct dev_pm_qos_request {
-       struct plist_node node;
+       enum dev_pm_qos_req_type type;
+       union {
+               struct plist_node pnode;
+               struct pm_qos_flags_request flr;
+       } data;
        struct device *dev;
 };
 
@@ -45,8 +69,8 @@ enum pm_qos_type {
 };
 
 /*
- * Note: The lockless read path depends on the CPU accessing
- * target_value atomically.  Atomic access is only guaranteed on all CPU
+ * Note: The lockless read path depends on the CPU accessing target_value
+ * or effective_flags atomically.  Atomic access is only guaranteed on all CPU
  * types linux supports for 32 bit quantites
  */
 struct pm_qos_constraints {
@@ -57,6 +81,18 @@ struct pm_qos_constraints {
        struct blocking_notifier_head *notifiers;
 };
 
+struct pm_qos_flags {
+       struct list_head list;
+       s32 effective_flags;    /* Do not change to 64 bit */
+};
+
+struct dev_pm_qos {
+       struct pm_qos_constraints latency;
+       struct pm_qos_flags flags;
+       struct dev_pm_qos_request *latency_req;
+       struct dev_pm_qos_request *flags_req;
+};
+
 /* Action requested to pm_qos_update_target */
 enum pm_qos_req_action {
        PM_QOS_ADD_REQ,         /* Add a new request */
@@ -71,6 +107,9 @@ static inline int dev_pm_qos_request_active(struct dev_pm_qos_request *req)
 
 int pm_qos_update_target(struct pm_qos_constraints *c, struct plist_node *node,
                         enum pm_qos_req_action action, int value);
+bool pm_qos_update_flags(struct pm_qos_flags *pqf,
+                        struct pm_qos_flags_request *req,
+                        enum pm_qos_req_action action, s32 val);
 void pm_qos_add_request(struct pm_qos_request *req, int pm_qos_class,
                        s32 value);
 void pm_qos_update_request(struct pm_qos_request *req,
@@ -86,10 +125,12 @@ int pm_qos_request_active(struct pm_qos_request *req);
 s32 pm_qos_read_value(struct pm_qos_constraints *c);
 
 #ifdef CONFIG_PM
+enum pm_qos_flags_status __dev_pm_qos_flags(struct device *dev, s32 mask);
+enum pm_qos_flags_status dev_pm_qos_flags(struct device *dev, s32 mask);
 s32 __dev_pm_qos_read_value(struct device *dev);
 s32 dev_pm_qos_read_value(struct device *dev);
 int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req,
-                          s32 value);
+                          enum dev_pm_qos_req_type type, s32 value);
 int dev_pm_qos_update_request(struct dev_pm_qos_request *req, s32 new_value);
 int dev_pm_qos_remove_request(struct dev_pm_qos_request *req);
 int dev_pm_qos_add_notifier(struct device *dev,
@@ -103,12 +144,19 @@ void dev_pm_qos_constraints_destroy(struct device *dev);
 int dev_pm_qos_add_ancestor_request(struct device *dev,
                                    struct dev_pm_qos_request *req, s32 value);
 #else
+static inline enum pm_qos_flags_status __dev_pm_qos_flags(struct device *dev,
+                                                         s32 mask)
+                       { return PM_QOS_FLAGS_UNDEFINED; }
+static inline enum pm_qos_flags_status dev_pm_qos_flags(struct device *dev,
+                                                       s32 mask)
+                       { return PM_QOS_FLAGS_UNDEFINED; }
 static inline s32 __dev_pm_qos_read_value(struct device *dev)
                        { return 0; }
 static inline s32 dev_pm_qos_read_value(struct device *dev)
                        { return 0; }
 static inline int dev_pm_qos_add_request(struct device *dev,
                                         struct dev_pm_qos_request *req,
+                                        enum dev_pm_qos_req_type type,
                                         s32 value)
                        { return 0; }
 static inline int dev_pm_qos_update_request(struct dev_pm_qos_request *req,
@@ -144,10 +192,31 @@ static inline int dev_pm_qos_add_ancestor_request(struct device *dev,
 #ifdef CONFIG_PM_RUNTIME
 int dev_pm_qos_expose_latency_limit(struct device *dev, s32 value);
 void dev_pm_qos_hide_latency_limit(struct device *dev);
+int dev_pm_qos_expose_flags(struct device *dev, s32 value);
+void dev_pm_qos_hide_flags(struct device *dev);
+int dev_pm_qos_update_flags(struct device *dev, s32 mask, bool set);
+
+static inline s32 dev_pm_qos_requested_latency(struct device *dev)
+{
+       return dev->power.qos->latency_req->data.pnode.prio;
+}
+
+static inline s32 dev_pm_qos_requested_flags(struct device *dev)
+{
+       return dev->power.qos->flags_req->data.flr.flags;
+}
 #else
 static inline int dev_pm_qos_expose_latency_limit(struct device *dev, s32 value)
                        { return 0; }
 static inline void dev_pm_qos_hide_latency_limit(struct device *dev) {}
+static inline int dev_pm_qos_expose_flags(struct device *dev, s32 value)
+                       { return 0; }
+static inline void dev_pm_qos_hide_flags(struct device *dev) {}
+static inline int dev_pm_qos_update_flags(struct device *dev, s32 m, bool set)
+                       { return 0; }
+
+static inline s32 dev_pm_qos_requested_latency(struct device *dev) { return 0; }
+static inline s32 dev_pm_qos_requested_flags(struct device *dev) { return 0; }
 #endif
 
 #endif
index 2415a64c5e51d937ba0fc7d20cf78011b1b77dd6..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1,2 +0,0 @@
-header-y += md_p.h
-header-y += md_u.h
index fb1abb3367e9520a7e68cf738709e7510abe80f0..358c04bfbe2ad31c691ac07e87b5988395f2c2f3 100644 (file)
    (for example /usr/src/linux/COPYING); if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
 */
-
 #ifndef _MD_U_H
 #define _MD_U_H
 
-/*
- * Different major versions are not compatible.
- * Different minor versions are only downward compatible.
- * Different patchlevel versions are downward and upward compatible.
- */
-#define MD_MAJOR_VERSION                0
-#define MD_MINOR_VERSION                90
-/*
- * MD_PATCHLEVEL_VERSION indicates kernel functionality.
- * >=1 means different superblock formats are selectable using SET_ARRAY_INFO
- *     and major_version/minor_version accordingly
- * >=2 means that Internal bitmaps are supported by setting MD_SB_BITMAP_PRESENT
- *     in the super status byte
- * >=3 means that bitmap superblock version 4 is supported, which uses
- *     little-ending representation rather than host-endian
- */
-#define MD_PATCHLEVEL_VERSION           3
-
-/* ioctls */
-
-/* status */
-#define RAID_VERSION           _IOR (MD_MAJOR, 0x10, mdu_version_t)
-#define GET_ARRAY_INFO         _IOR (MD_MAJOR, 0x11, mdu_array_info_t)
-#define GET_DISK_INFO          _IOR (MD_MAJOR, 0x12, mdu_disk_info_t)
-#define PRINT_RAID_DEBUG       _IO (MD_MAJOR, 0x13)
-#define RAID_AUTORUN           _IO (MD_MAJOR, 0x14)
-#define GET_BITMAP_FILE                _IOR (MD_MAJOR, 0x15, mdu_bitmap_file_t)
-
-/* configuration */
-#define CLEAR_ARRAY            _IO (MD_MAJOR, 0x20)
-#define ADD_NEW_DISK           _IOW (MD_MAJOR, 0x21, mdu_disk_info_t)
-#define HOT_REMOVE_DISK                _IO (MD_MAJOR, 0x22)
-#define SET_ARRAY_INFO         _IOW (MD_MAJOR, 0x23, mdu_array_info_t)
-#define SET_DISK_INFO          _IO (MD_MAJOR, 0x24)
-#define WRITE_RAID_INFO                _IO (MD_MAJOR, 0x25)
-#define UNPROTECT_ARRAY                _IO (MD_MAJOR, 0x26)
-#define PROTECT_ARRAY          _IO (MD_MAJOR, 0x27)
-#define HOT_ADD_DISK           _IO (MD_MAJOR, 0x28)
-#define SET_DISK_FAULTY                _IO (MD_MAJOR, 0x29)
-#define HOT_GENERATE_ERROR     _IO (MD_MAJOR, 0x2a)
-#define SET_BITMAP_FILE                _IOW (MD_MAJOR, 0x2b, int)
+#include <uapi/linux/raid/md_u.h>
 
-/* usage */
-#define RUN_ARRAY              _IOW (MD_MAJOR, 0x30, mdu_param_t)
-/*  0x31 was START_ARRAY  */
-#define STOP_ARRAY             _IO (MD_MAJOR, 0x32)
-#define STOP_ARRAY_RO          _IO (MD_MAJOR, 0x33)
-#define RESTART_ARRAY_RW       _IO (MD_MAJOR, 0x34)
-
-/* 63 partitions with the alternate major number (mdp) */
-#define MdpMinorShift 6
-#ifdef __KERNEL__
 extern int mdp_major;
-#endif
-
-typedef struct mdu_version_s {
-       int major;
-       int minor;
-       int patchlevel;
-} mdu_version_t;
-
-typedef struct mdu_array_info_s {
-       /*
-        * Generic constant information
-        */
-       int major_version;
-       int minor_version;
-       int patch_version;
-       int ctime;
-       int level;
-       int size;
-       int nr_disks;
-       int raid_disks;
-       int md_minor;
-       int not_persistent;
-
-       /*
-        * Generic state information
-        */
-       int utime;              /*  0 Superblock update time                  */
-       int state;              /*  1 State bits (clean, ...)                 */
-       int active_disks;       /*  2 Number of currently active disks        */
-       int working_disks;      /*  3 Number of working disks                 */
-       int failed_disks;       /*  4 Number of failed disks                  */
-       int spare_disks;        /*  5 Number of spare disks                   */
-
-       /*
-        * Personality information
-        */
-       int layout;             /*  0 the array's physical layout             */
-       int chunk_size; /*  1 chunk size in bytes                     */
-
-} mdu_array_info_t;
-
-/* non-obvious values for 'level' */
-#define        LEVEL_MULTIPATH         (-4)
-#define        LEVEL_LINEAR            (-1)
-#define        LEVEL_FAULTY            (-5)
-
-/* we need a value for 'no level specified' and 0
- * means 'raid0', so we need something else.  This is
- * for internal use only
- */
-#define        LEVEL_NONE              (-1000000)
-
-typedef struct mdu_disk_info_s {
-       /*
-        * configuration/status of one particular disk
-        */
-       int number;
-       int major;
-       int minor;
-       int raid_disk;
-       int state;
-
-} mdu_disk_info_t;
-
-typedef struct mdu_start_info_s {
-       /*
-        * configuration/status of one particular disk
-        */
-       int major;
-       int minor;
-       int raid_disk;
-       int state;
-
-} mdu_start_info_t;
-
-typedef struct mdu_bitmap_file_s
-{
-       char pathname[4096];
-} mdu_bitmap_file_t;
-
-typedef struct mdu_param_s
-{
-       int                     personality;    /* 1,2,3,4 */
-       int                     chunk_size;     /* in bytes */
-       int                     max_fault;      /* unused for now */
-} mdu_param_t;
-
 #endif 
-
index e11ccb4cf48dd5f6874322f375ce1537d007974c..0a260d8a18bf92dc3b8d4b582d3506e169d9dac5 100644 (file)
@@ -46,20 +46,17 @@ extern int ___ratelimit(struct ratelimit_state *rs, const char *func);
 #define WARN_ON_RATELIMIT(condition, state)                    \
                WARN_ON((condition) && __ratelimit(state))
 
-#define __WARN_RATELIMIT(condition, state, format...)          \
-({                                                             \
-       int rtn = 0;                                            \
-       if (unlikely(__ratelimit(state)))                       \
-               rtn = WARN(condition, format);                  \
-       rtn;                                                    \
-})
-
-#define WARN_RATELIMIT(condition, format...)                   \
+#define WARN_RATELIMIT(condition, format, ...)                 \
 ({                                                             \
        static DEFINE_RATELIMIT_STATE(_rs,                      \
                                      DEFAULT_RATELIMIT_INTERVAL,       \
                                      DEFAULT_RATELIMIT_BURST); \
-       __WARN_RATELIMIT(condition, &_rs, format);              \
+       int rtn = !!(condition);                                \
+                                                               \
+       if (unlikely(rtn && __ratelimit(&_rs)))                 \
+               WARN(rtn, format, ##__VA_ARGS__);               \
+                                                               \
+       rtn;                                                    \
 })
 
 #else
@@ -67,15 +64,9 @@ extern int ___ratelimit(struct ratelimit_state *rs, const char *func);
 #define WARN_ON_RATELIMIT(condition, state)                    \
        WARN_ON(condition)
 
-#define __WARN_RATELIMIT(condition, state, format...)          \
-({                                                             \
-       int rtn = WARN(condition, format);                      \
-       rtn;                                                    \
-})
-
-#define WARN_RATELIMIT(condition, format...)                   \
+#define WARN_RATELIMIT(condition, format, ...)                 \
 ({                                                             \
-       int rtn = WARN(condition, format);                      \
+       int rtn = WARN(condition, format, ##__VA_ARGS__);       \
        rtn;                                                    \
 })
 
index e0f0fab204154ffd472effa0f8702c926f6720d6..c92dd28eaa6c5014fcee89c22deabcda9f865810 100644 (file)
@@ -286,23 +286,6 @@ static inline void list_splice_init_rcu(struct list_head *list,
                &pos->member != (head); \
                pos = list_entry_rcu(pos->member.next, typeof(*pos), member))
 
-
-/**
- * list_for_each_continue_rcu
- * @pos:       the &struct list_head to use as a loop cursor.
- * @head:      the head for your list.
- *
- * Iterate over an rcu-protected list, continuing after current point.
- *
- * This list-traversal primitive may safely run concurrently with
- * the _rcu list-mutation primitives such as list_add_rcu()
- * as long as the traversal is guarded by rcu_read_lock().
- */
-#define list_for_each_continue_rcu(pos, head) \
-       for ((pos) = rcu_dereference_raw(list_next_rcu(pos)); \
-               (pos) != (head); \
-               (pos) = rcu_dereference_raw(list_next_rcu(pos)))
-
 /**
  * list_for_each_entry_continue_rcu - continue iteration over list of given type
  * @pos:       the type * to use as a loop cursor.
index 7c968e4f929ea49806c5e17e53bdfdfb997e4c79..f35e82c44eeede43a20b1bbc0b4d9e911ee0db07 100644 (file)
@@ -90,6 +90,20 @@ extern void do_trace_rcu_torture_read(char *rcutorturename,
  * that started after call_rcu() was invoked.  RCU read-side critical
  * sections are delimited by rcu_read_lock() and rcu_read_unlock(),
  * and may be nested.
+ *
+ * Note that all CPUs must agree that the grace period extended beyond
+ * all pre-existing RCU read-side critical section.  This means that
+ * on systems with more than one CPU, when "func()" is invoked, each
+ * CPU is guaranteed to have executed a full memory barrier since the
+ * end of its last RCU read-side critical section whose beginning
+ * preceded the call to call_rcu().  Note that this guarantee includes
+ * CPUs that are offline, idle, or executing in user mode, as well as
+ * CPUs that are executing in the kernel.  Furthermore, if CPU A
+ * invoked call_rcu() and CPU B invoked the resulting RCU callback
+ * function "func()", then both CPU A and CPU B are guaranteed to execute
+ * a full memory barrier during the time interval between the call to
+ * call_rcu() and the invocation of "func()" -- even if CPU A and CPU B
+ * are the same CPU (but again only if the system has more than one CPU).
  */
 extern void call_rcu(struct rcu_head *head,
                              void (*func)(struct rcu_head *head));
@@ -118,6 +132,9 @@ extern void call_rcu(struct rcu_head *head,
  *  OR
  *  - rcu_read_lock_bh() and rcu_read_unlock_bh(), if in process context.
  *  These may be nested.
+ *
+ * See the description of call_rcu() for more detailed information on
+ * memory ordering guarantees.
  */
 extern void call_rcu_bh(struct rcu_head *head,
                        void (*func)(struct rcu_head *head));
@@ -137,6 +154,9 @@ extern void call_rcu_bh(struct rcu_head *head,
  *  OR
  *  anything that disables preemption.
  *  These may be nested.
+ *
+ * See the description of call_rcu() for more detailed information on
+ * memory ordering guarantees.
  */
 extern void call_rcu_sched(struct rcu_head *head,
                           void (*func)(struct rcu_head *rcu));
@@ -204,6 +224,8 @@ static inline void rcu_user_enter(void) { }
 static inline void rcu_user_exit(void) { }
 static inline void rcu_user_enter_after_irq(void) { }
 static inline void rcu_user_exit_after_irq(void) { }
+static inline void rcu_user_hooks_switch(struct task_struct *prev,
+                                        struct task_struct *next) { }
 #endif /* CONFIG_RCU_USER_QS */
 
 extern void exit_rcu(void);
index e3bcc3f4dcb8426c4e5e487016417e0e43113666..fedf7ba74590756354627f9f37f402f89c76f137 100644 (file)
@@ -19,6 +19,7 @@
 struct module;
 struct device;
 struct i2c_client;
+struct irq_domain;
 struct spi_device;
 struct regmap;
 struct regmap_range_cfg;
@@ -53,6 +54,9 @@ enum regmap_endian {
        REGMAP_ENDIAN_NATIVE,
 };
 
+typedef void (*regmap_lock)(void *);
+typedef void (*regmap_unlock)(void *);
+
 /**
  * Configuration for the register map of a device.
  *
@@ -75,6 +79,12 @@ enum regmap_endian {
  * @precious_reg: Optional callback returning true if the rgister
  *                should not be read outside of a call from the driver
  *                (eg, a clear on read interrupt status register).
+ * @lock:         Optional lock callback (overrides regmap's default lock
+ *                function, based on spinlock or mutex).
+ * @unlock:       As above for unlocking.
+ * @lock_arg:     this field is passed as the only argument of lock/unlock
+ *                functions (ignored in case regular lock/unlock functions
+ *                are not overridden).
  *
  * @max_register: Optional, specifies the maximum valid register index.
  * @reg_defaults: Power on reset values for registers (for use with
@@ -116,6 +126,9 @@ struct regmap_config {
        bool (*readable_reg)(struct device *dev, unsigned int reg);
        bool (*volatile_reg)(struct device *dev, unsigned int reg);
        bool (*precious_reg)(struct device *dev, unsigned int reg);
+       regmap_lock lock;
+       regmap_unlock unlock;
+       void *lock_arg;
 
        unsigned int max_register;
        const struct reg_default *reg_defaults;
@@ -133,7 +146,7 @@ struct regmap_config {
        enum regmap_endian val_format_endian;
 
        const struct regmap_range_cfg *ranges;
-       unsigned int n_ranges;
+       unsigned int num_ranges;
 };
 
 /**
@@ -142,6 +155,8 @@ struct regmap_config {
  *     1. page selector register update;
  *     2. access through data window registers.
  *
+ * @name: Descriptive name for diagnostics
+ *
  * @range_min: Address of the lowest register address in virtual range.
  * @range_max: Address of the highest register in virtual range.
  *
@@ -153,6 +168,8 @@ struct regmap_config {
  * @window_len: Number of registers in data window.
  */
 struct regmap_range_cfg {
+       const char *name;
+
        /* Registers of virtual address range */
        unsigned int range_min;
        unsigned int range_max;
@@ -181,7 +198,9 @@ typedef void (*regmap_hw_free_context)(void *context);
  * Description of a hardware bus for the register map infrastructure.
  *
  * @fast_io: Register IO is fast. Use a spinlock instead of a mutex
- *           to perform locking.
+ *          to perform locking. This field is ignored if custom lock/unlock
+ *          functions are used (see fields lock/unlock of
+ *          struct regmap_config).
  * @write: Write operation.
  * @gather_write: Write operation with split register/value, return -ENOTSUPP
  *                if not implemented  on a given device.
@@ -317,6 +336,7 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
 void regmap_del_irq_chip(int irq, struct regmap_irq_chip_data *data);
 int regmap_irq_chip_get_base(struct regmap_irq_chip_data *data);
 int regmap_irq_get_virq(struct regmap_irq_chip_data *data, int irq);
+struct irq_domain *regmap_irq_get_domain(struct regmap_irq_chip_data *data);
 
 #else
 
index 7932a3bf21bdba89f84275b7b990bcaa3a5773b0..f2b72b230b9ba495965c1b5fa4ddd1d619e10608 100644 (file)
@@ -181,6 +181,8 @@ enum regulator_type {
  * @type: Indicates if the regulator is a voltage or current regulator.
  * @owner: Module providing the regulator, used for refcounting.
  *
+ * @continuous_voltage_range: Indicates if the regulator can set any
+ *                            voltage within constrains range.
  * @n_voltages: Number of selectors available for ops.list_voltage().
  *
  * @min_uV: Voltage given by the lowest selector (if linear mapping)
@@ -199,6 +201,7 @@ struct regulator_desc {
        const char *name;
        const char *supply_name;
        int id;
+       bool continuous_voltage_range;
        unsigned n_voltages;
        struct regulator_ops *ops;
        int irq;
diff --git a/include/linux/regulator/tps51632-regulator.h b/include/linux/regulator/tps51632-regulator.h
new file mode 100644 (file)
index 0000000..d00841e
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * tps51632-regulator.h -- TPS51632 regulator
+ *
+ * Interface for regulator driver for TPS51632 3-2-1 Phase D-Cap Step Down
+ * Driverless Controller with serial VID control and DVFS.
+ *
+ * Copyright (C) 2012 NVIDIA Corporation
+
+ * Author: Laxman Dewangan <ldewangan@nvidia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef __LINUX_REGULATOR_TPS51632_H
+#define __LINUX_REGULATOR_TPS51632_H
+
+/*
+ * struct tps51632_regulator_platform_data - tps51632 regulator platform data.
+ *
+ * @reg_init_data: The regulator init data.
+ * @enable_pwm_dvfs: Enable PWM DVFS or not.
+ * @dvfs_step_20mV: Step for DVFS is 20mV or 10mV.
+ * @max_voltage_uV: Maximum possible voltage in PWM-DVFS mode.
+ * @base_voltage_uV: Base voltage when PWM-DVFS enabled.
+ */
+struct tps51632_regulator_platform_data {
+       struct regulator_init_data *reg_init_data;
+       bool enable_pwm_dvfs;
+       bool dvfs_step_20mV;
+       int max_voltage_uV;
+       int base_voltage_uV;
+};
+
+#endif /* __LINUX_REGULATOR_TPS51632_H */
diff --git a/include/linux/regulator/tps65090-regulator.h b/include/linux/regulator/tps65090-regulator.h
deleted file mode 100644 (file)
index 0fa04b6..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Regulator driver interface for TI TPS65090 PMIC family
- *
- * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
-
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
-
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __REGULATOR_TPS65090_H
-#define __REGULATOR_TPS65090_H
-
-#include <linux/regulator/machine.h>
-
-#define tps65090_rails(_name) "tps65090_"#_name
-
-enum {
-       TPS65090_ID_DCDC1,
-       TPS65090_ID_DCDC2,
-       TPS65090_ID_DCDC3,
-       TPS65090_ID_FET1,
-       TPS65090_ID_FET2,
-       TPS65090_ID_FET3,
-       TPS65090_ID_FET4,
-       TPS65090_ID_FET5,
-       TPS65090_ID_FET6,
-       TPS65090_ID_FET7,
-};
-
-/*
- * struct tps65090_regulator_platform_data
- *
- * @regulator: The regulator init data.
- * @slew_rate_uV_per_us: Slew rate microvolt per microsec.
- */
-
-struct tps65090_regulator_platform_data {
-       struct regulator_init_data regulator;
-};
-
-#endif /* __REGULATOR_TPS65090_H */
index a0166481eb203e090562310fc91d6c107dd14438..fb27acd9e79797c1ee9704cf456fff01235dddcf 100644 (file)
@@ -109,6 +109,8 @@ extern void update_cpu_load_nohz(void);
 
 extern unsigned long get_parent_ip(unsigned long addr);
 
+extern void dump_cpu_task(int cpu);
+
 struct seq_file;
 struct cfs_rq;
 struct task_group;
@@ -823,6 +825,7 @@ enum cpu_idle_type {
 #define SD_ASYM_PACKING                0x0800  /* Place busy groups earlier in the domain */
 #define SD_PREFER_SIBLING      0x1000  /* Prefer to place tasks in a sibling domain */
 #define SD_OVERLAP             0x2000  /* sched_domains of this level overlap */
+#define SD_NUMA                        0x4000  /* cross-node balancing */
 
 extern int __weak arch_sd_sibiling_asym_packing(void);
 
@@ -1061,6 +1064,7 @@ struct sched_class {
 
 #ifdef CONFIG_SMP
        int  (*select_task_rq)(struct task_struct *p, int sd_flag, int flags);
+       void (*migrate_task_rq)(struct task_struct *p, int next_cpu);
 
        void (*pre_schedule) (struct rq *this_rq, struct task_struct *task);
        void (*post_schedule) (struct rq *this_rq);
@@ -1095,6 +1099,18 @@ struct load_weight {
        unsigned long weight, inv_weight;
 };
 
+struct sched_avg {
+       /*
+        * These sums represent an infinite geometric series and so are bound
+        * above by 1024/(1-y).  Thus we only need a u32 to store them for for all
+        * choices of y < 1-2^(-32)*1024.
+        */
+       u32 runnable_avg_sum, runnable_avg_period;
+       u64 last_runnable_update;
+       s64 decay_count;
+       unsigned long load_avg_contrib;
+};
+
 #ifdef CONFIG_SCHEDSTATS
 struct sched_statistics {
        u64                     wait_start;
@@ -1155,6 +1171,15 @@ struct sched_entity {
        /* rq "owned" by this entity/group: */
        struct cfs_rq           *my_q;
 #endif
+/*
+ * Load-tracking only depends on SMP, FAIR_GROUP_SCHED dependency below may be
+ * removed when useful for applications beyond shares distribution (e.g.
+ * load-balance).
+ */
+#if defined(CONFIG_SMP) && defined(CONFIG_FAIR_GROUP_SCHED)
+       /* Per-entity load-tracking */
+       struct sched_avg        avg;
+#endif
 };
 
 struct sched_rt_entity {
@@ -1479,6 +1504,17 @@ struct task_struct {
        short il_next;
        short pref_node_fork;
 #endif
+#ifdef CONFIG_SCHED_NUMA
+       int node;                       /* task home node   */
+       int numa_scan_seq;
+       int numa_migrate_seq;
+       unsigned int numa_scan_period;
+       u64 node_stamp;                 /* migration stamp  */
+       unsigned long numa_contrib;
+       unsigned long *numa_faults;
+       struct callback_head numa_work;
+#endif /* CONFIG_SCHED_NUMA */
+
        struct rcu_head rcu;
 
        /*
@@ -1553,6 +1589,24 @@ struct task_struct {
 /* Future-safe accessor for struct task_struct's cpus_allowed. */
 #define tsk_cpus_allowed(tsk) (&(tsk)->cpus_allowed)
 
+#ifdef CONFIG_SCHED_NUMA
+static inline int tsk_home_node(struct task_struct *p)
+{
+       return p->node;
+}
+
+extern void task_numa_fault(int node, int pages);
+#else
+static inline int tsk_home_node(struct task_struct *p)
+{
+       return -1;
+}
+
+static inline void task_numa_fault(int node, int pages)
+{
+}
+#endif /* CONFIG_SCHED_NUMA */
+
 /*
  * Priority of a process goes from 0..MAX_PRIO-1, valid RT
  * priority is 0..MAX_RT_PRIO-1, and SCHED_NORMAL/SCHED_BATCH
@@ -1844,14 +1898,6 @@ static inline void rcu_copy_process(struct task_struct *p)
 
 #endif
 
-static inline void rcu_switch(struct task_struct *prev,
-                             struct task_struct *next)
-{
-#ifdef CONFIG_RCU_USER_QS
-       rcu_user_hooks_switch(prev, next);
-#endif
-}
-
 static inline void tsk_restore_flags(struct task_struct *task,
                                unsigned long orig_flags, unsigned long flags)
 {
@@ -1990,6 +2036,12 @@ enum sched_tunable_scaling {
 };
 extern enum sched_tunable_scaling sysctl_sched_tunable_scaling;
 
+extern unsigned int sysctl_sched_numa_scan_delay;
+extern unsigned int sysctl_sched_numa_scan_period_min;
+extern unsigned int sysctl_sched_numa_scan_period_max;
+extern unsigned int sysctl_sched_numa_scan_size;
+extern unsigned int sysctl_sched_numa_settle_count;
+
 #ifdef CONFIG_SCHED_DEBUG
 extern unsigned int sysctl_sched_migration_cost;
 extern unsigned int sysctl_sched_nr_migrate;
@@ -2000,18 +2052,17 @@ extern unsigned int sysctl_sched_shares_window;
 int sched_proc_update_handler(struct ctl_table *table, int write,
                void __user *buffer, size_t *length,
                loff_t *ppos);
-#endif
-#ifdef CONFIG_SCHED_DEBUG
+
 static inline unsigned int get_sysctl_timer_migration(void)
 {
        return sysctl_timer_migration;
 }
-#else
+#else /* CONFIG_SCHED_DEBUG */
 static inline unsigned int get_sysctl_timer_migration(void)
 {
        return 1;
 }
-#endif
+#endif /* CONFIG_SCHED_DEBUG */
 extern unsigned int sysctl_sched_rt_period;
 extern int sysctl_sched_rt_runtime;
 
@@ -2072,6 +2123,7 @@ extern int sched_setscheduler(struct task_struct *, int,
                              const struct sched_param *);
 extern int sched_setscheduler_nocheck(struct task_struct *, int,
                                      const struct sched_param *);
+extern void sched_setnode(struct task_struct *p, int node);
 extern struct task_struct *idle_task(int cpu);
 /**
  * is_idle_task - is the specified task an idle task?
index 05e88bdcf7d95cbe493bfa8ed890010bd0094890..0f6afc657f778f2e682e7fb108e97b6788a53973 100644 (file)
@@ -694,6 +694,12 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
  *     userspace to load a kernel module with the given name.
  *     @kmod_name name of the module requested by the kernel
  *     Return 0 if successful.
+ * @kernel_module_from_file:
+ *     Load a kernel module from userspace.
+ *     @file contains the file structure pointing to the file containing
+ *     the kernel module to load. If the module is being loaded from a blob,
+ *     this argument will be NULL.
+ *     Return 0 if permission is granted.
  * @task_fix_setuid:
  *     Update the module's state after setting one or more of the user
  *     identity attributes of the current process.  The @flags parameter
@@ -1508,6 +1514,7 @@ struct security_operations {
        int (*kernel_act_as)(struct cred *new, u32 secid);
        int (*kernel_create_files_as)(struct cred *new, struct inode *inode);
        int (*kernel_module_request)(char *kmod_name);
+       int (*kernel_module_from_file)(struct file *file);
        int (*task_fix_setuid) (struct cred *new, const struct cred *old,
                                int flags);
        int (*task_setpgid) (struct task_struct *p, pid_t pgid);
@@ -1765,6 +1772,7 @@ void security_transfer_creds(struct cred *new, const struct cred *old);
 int security_kernel_act_as(struct cred *new, u32 secid);
 int security_kernel_create_files_as(struct cred *new, struct inode *inode);
 int security_kernel_module_request(char *kmod_name);
+int security_kernel_module_from_file(struct file *file);
 int security_task_fix_setuid(struct cred *new, const struct cred *old,
                             int flags);
 int security_task_setpgid(struct task_struct *p, pid_t pgid);
@@ -2278,6 +2286,11 @@ static inline int security_kernel_module_request(char *kmod_name)
        return 0;
 }
 
+static inline int security_kernel_module_from_file(struct file *file)
+{
+       return 0;
+}
+
 static inline int security_task_fix_setuid(struct cred *new,
                                           const struct cred *old,
                                           int flags)
index d9b0c84220c73897630f7cc7d35864c4eeeadb69..8f721e465e05b968ed1b5223c4b1e7eb61be78e2 100644 (file)
@@ -3,8 +3,6 @@
  *
  * Copyright (C) 2009-2010 Nokia Corporation
  *
- * Contact: Aaro Koskinen <aaro.koskinen@nokia.com>
- *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
index 55a5c52cbb25a7eee3dee42542016a65dd9db5c7..0adac7813903805f5fe37621691cb8a199fc4578 100644 (file)
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  *
  * Copyright (C) IBM Corporation, 2006
+ * Copyright (C) Fujitsu, 2012
  *
  * Author: Paul McKenney <paulmck@us.ibm.com>
+ *        Lai Jiangshan <laijs@cn.fujitsu.com>
  *
  * For detailed explanation of Read-Copy Update mechanism see -
  *             Documentation/RCU/ *.txt
@@ -40,6 +42,8 @@ struct rcu_batch {
        struct rcu_head *head, **tail;
 };
 
+#define RCU_BATCH_INIT(name) { NULL, &(name.head) }
+
 struct srcu_struct {
        unsigned completed;
        struct srcu_struct_array __percpu *per_cpu_ref;
@@ -70,12 +74,42 @@ int __init_srcu_struct(struct srcu_struct *sp, const char *name,
        __init_srcu_struct((sp), #sp, &__srcu_key); \
 })
 
+#define __SRCU_DEP_MAP_INIT(srcu_name) .dep_map = { .name = #srcu_name },
 #else /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */
 
 int init_srcu_struct(struct srcu_struct *sp);
 
+#define __SRCU_DEP_MAP_INIT(srcu_name)
 #endif /* #else #ifdef CONFIG_DEBUG_LOCK_ALLOC */
 
+void process_srcu(struct work_struct *work);
+
+#define __SRCU_STRUCT_INIT(name)                                       \
+       {                                                               \
+               .completed = -300,                                      \
+               .per_cpu_ref = &name##_srcu_array,                      \
+               .queue_lock = __SPIN_LOCK_UNLOCKED(name.queue_lock),    \
+               .running = false,                                       \
+               .batch_queue = RCU_BATCH_INIT(name.batch_queue),        \
+               .batch_check0 = RCU_BATCH_INIT(name.batch_check0),      \
+               .batch_check1 = RCU_BATCH_INIT(name.batch_check1),      \
+               .batch_done = RCU_BATCH_INIT(name.batch_done),          \
+               .work = __DELAYED_WORK_INITIALIZER(name.work, process_srcu, 0),\
+               __SRCU_DEP_MAP_INIT(name)                               \
+       }
+
+/*
+ * define and init a srcu struct at build time.
+ * dont't call init_srcu_struct() nor cleanup_srcu_struct() on it.
+ */
+#define DEFINE_SRCU(name)                                              \
+       static DEFINE_PER_CPU(struct srcu_struct_array, name##_srcu_array);\
+       struct srcu_struct name = __SRCU_STRUCT_INIT(name);
+
+#define DEFINE_STATIC_SRCU(name)                                               \
+       static DEFINE_PER_CPU(struct srcu_struct_array, name##_srcu_array);\
+       static struct srcu_struct name = __SRCU_STRUCT_INIT(name);
+
 /**
  * call_srcu() - Queue a callback for invocation after an SRCU grace period
  * @sp: srcu_struct in queue the callback
index 5f44e9740cd2a3453da6767778911fb3aa59eab1..07a9c7a2e088e5baedd31426a1679dab23def26c 100644 (file)
@@ -13,6 +13,12 @@ struct ssb_serial_port {
        unsigned int reg_shift;
 };
 
+struct ssb_pflash {
+       bool present;
+       u8 buswidth;
+       u32 window;
+       u32 window_size;
+};
 
 struct ssb_mipscore {
        struct ssb_device *dev;
@@ -20,9 +26,7 @@ struct ssb_mipscore {
        int nr_serial_ports;
        struct ssb_serial_port serial_ports[4];
 
-       u8 flash_buswidth;
-       u32 flash_window;
-       u32 flash_window_size;
+       struct ssb_pflash pflash;
 };
 
 extern void ssb_mipscore_init(struct ssb_mipscore *mcore);
index 727f0cd739213cc70054d3412b181527f504d2f2..32bc035bcd685ed74132b1ff7c111f0104bda8c0 100644 (file)
@@ -868,4 +868,5 @@ asmlinkage long sys_process_vm_writev(pid_t pid,
 
 asmlinkage long sys_kcmp(pid_t pid1, pid_t pid2, int type,
                         unsigned long idx1, unsigned long idx2);
+asmlinkage long sys_finit_module(int fd, const char __user *uargs);
 #endif
index 8a7fc4be2d75f11d0ff774e727940dd16a2c64aa..60b7aac15e0e436b9b6451321d421a286fa9a40b 100644 (file)
@@ -191,7 +191,8 @@ struct tcp_sock {
        u8      do_early_retrans:1,/* Enable RFC5827 early-retransmit  */
                early_retrans_delayed:1, /* Delayed ER timer installed */
                syn_data:1,     /* SYN includes data */
-               syn_fastopen:1; /* SYN includes Fast Open option */
+               syn_fastopen:1, /* SYN includes Fast Open option */
+               syn_data_acked:1;/* data in SYN is acked by SYN-ACK */
 
 /* RTT measurement */
        u32     srtt;           /* smoothed round trip time << 3        */
similarity index 86%
rename from arch/arm/mach-tegra/include/mach/tegra-ahb.h
rename to include/linux/tegra-ahb.h
index e0f8c84b1d8c014aaac2b53661351c283b1aca75..f1cd075ceee1f23fb5d2a70256a3dbfc41403a08 100644 (file)
@@ -11,9 +11,9 @@
  * more details.
  */
 
-#ifndef __MACH_TEGRA_AHB_H__
-#define __MACH_TEGRA_AHB_H__
+#ifndef __LINUX_AHB_H__
+#define __LINUX_AHB_H__
 
 extern int tegra_ahb_enable_smmu(struct device_node *ahb);
 
-#endif /* __MACH_TEGRA_AHB_H__ */
+#endif /* __LINUX_AHB_H__ */
index 91b34812cd8478a2aacfbdacc6818c75e4bfe587..807f2146fe35cd8e53276a2a03ee027618efb9db 100644 (file)
 #include <linux/device.h>
 #include <linux/workqueue.h>
 
+#define THERMAL_TRIPS_NONE     -1
+#define THERMAL_MAX_TRIPS      12
+#define THERMAL_NAME_LENGTH    20
+
+/* No upper/lower limit requirement */
+#define THERMAL_NO_LIMIT       -1UL
+
+/* Unit conversion macros */
+#define KELVIN_TO_CELSIUS(t)   (long)(((long)t-2732 >= 0) ?    \
+                               ((long)t-2732+5)/10 : ((long)t-2732-5)/10)
+#define CELSIUS_TO_KELVIN(t)   ((t)*10+2732)
+
+/* Adding event notification support elements */
+#define THERMAL_GENL_FAMILY_NAME                "thermal_event"
+#define THERMAL_GENL_VERSION                    0x01
+#define THERMAL_GENL_MCAST_GROUP_NAME           "thermal_mc_group"
+
+/* Default Thermal Governor: Does Linear Throttling */
+#define DEFAULT_THERMAL_GOVERNOR       "step_wise"
+
 struct thermal_zone_device;
 struct thermal_cooling_device;
 
@@ -50,6 +70,30 @@ enum thermal_trend {
        THERMAL_TREND_DROPPING, /* temperature is dropping */
 };
 
+/* Events supported by Thermal Netlink */
+enum events {
+       THERMAL_AUX0,
+       THERMAL_AUX1,
+       THERMAL_CRITICAL,
+       THERMAL_DEV_FAULT,
+};
+
+/* attributes of thermal_genl_family */
+enum {
+       THERMAL_GENL_ATTR_UNSPEC,
+       THERMAL_GENL_ATTR_EVENT,
+       __THERMAL_GENL_ATTR_MAX,
+};
+#define THERMAL_GENL_ATTR_MAX (__THERMAL_GENL_ATTR_MAX - 1)
+
+/* commands supported by the thermal_genl_family */
+enum {
+       THERMAL_GENL_CMD_UNSPEC,
+       THERMAL_GENL_CMD_EVENT,
+       __THERMAL_GENL_CMD_MAX,
+};
+#define THERMAL_GENL_CMD_MAX (__THERMAL_GENL_CMD_MAX - 1)
+
 struct thermal_zone_device_ops {
        int (*bind) (struct thermal_zone_device *,
                     struct thermal_cooling_device *);
@@ -83,11 +127,6 @@ struct thermal_cooling_device_ops {
        int (*set_cur_state) (struct thermal_cooling_device *, unsigned long);
 };
 
-#define THERMAL_NO_LIMIT -1UL /* no upper/lower limit requirement */
-
-#define THERMAL_TRIPS_NONE -1
-#define THERMAL_MAX_TRIPS 12
-#define THERMAL_NAME_LENGTH 20
 struct thermal_cooling_device {
        int id;
        char type[THERMAL_NAME_LENGTH];
@@ -100,10 +139,6 @@ struct thermal_cooling_device {
        struct list_head node;
 };
 
-#define KELVIN_TO_CELSIUS(t)   (long)(((long)t-2732 >= 0) ?    \
-                               ((long)t-2732+5)/10 : ((long)t-2732-5)/10)
-#define CELSIUS_TO_KELVIN(t)   ((t)*10+2732)
-
 struct thermal_attr {
        struct device_attribute attr;
        char name[THERMAL_NAME_LENGTH];
@@ -125,46 +160,61 @@ struct thermal_zone_device {
        int passive;
        unsigned int forced_passive;
        const struct thermal_zone_device_ops *ops;
+       const struct thermal_zone_params *tzp;
+       struct thermal_governor *governor;
        struct list_head thermal_instances;
        struct idr idr;
        struct mutex lock; /* protect thermal_instances list */
        struct list_head node;
        struct delayed_work poll_queue;
 };
-/* Adding event notification support elements */
-#define THERMAL_GENL_FAMILY_NAME                "thermal_event"
-#define THERMAL_GENL_VERSION                    0x01
-#define THERMAL_GENL_MCAST_GROUP_NAME           "thermal_mc_group"
 
-enum events {
-       THERMAL_AUX0,
-       THERMAL_AUX1,
-       THERMAL_CRITICAL,
-       THERMAL_DEV_FAULT,
+/* Structure that holds thermal governor information */
+struct thermal_governor {
+       char name[THERMAL_NAME_LENGTH];
+       int (*throttle)(struct thermal_zone_device *tz, int trip);
+       struct list_head        governor_list;
+       struct module           *owner;
 };
 
-struct thermal_genl_event {
-       u32 orig;
-       enum events event;
+/* Structure that holds binding parameters for a zone */
+struct thermal_bind_params {
+       struct thermal_cooling_device *cdev;
+
+       /*
+        * This is a measure of 'how effectively these devices can
+        * cool 'this' thermal zone. The shall be determined by platform
+        * characterization. This is on a 'percentage' scale.
+        * See Documentation/thermal/sysfs-api.txt for more information.
+        */
+       int weight;
+
+       /*
+        * This is a bit mask that gives the binding relation between this
+        * thermal zone and cdev, for a particular trip point.
+        * See Documentation/thermal/sysfs-api.txt for more information.
+        */
+       int trip_mask;
+       int (*match) (struct thermal_zone_device *tz,
+                       struct thermal_cooling_device *cdev);
 };
-/* attributes of thermal_genl_family */
-enum {
-       THERMAL_GENL_ATTR_UNSPEC,
-       THERMAL_GENL_ATTR_EVENT,
-       __THERMAL_GENL_ATTR_MAX,
+
+/* Structure to define Thermal Zone parameters */
+struct thermal_zone_params {
+       char governor_name[THERMAL_NAME_LENGTH];
+       int num_tbps;   /* Number of tbp entries */
+       struct thermal_bind_params *tbp;
 };
-#define THERMAL_GENL_ATTR_MAX (__THERMAL_GENL_ATTR_MAX - 1)
 
-/* commands supported by the thermal_genl_family */
-enum {
-       THERMAL_GENL_CMD_UNSPEC,
-       THERMAL_GENL_CMD_EVENT,
-       __THERMAL_GENL_CMD_MAX,
+struct thermal_genl_event {
+       u32 orig;
+       enum events event;
 };
-#define THERMAL_GENL_CMD_MAX (__THERMAL_GENL_CMD_MAX - 1)
 
+/* Function declarations */
 struct thermal_zone_device *thermal_zone_device_register(const char *, int, int,
-               void *, const struct thermal_zone_device_ops *, int, int);
+               void *, const struct thermal_zone_device_ops *,
+               const struct thermal_zone_params *, int, int);
 void thermal_zone_device_unregister(struct thermal_zone_device *);
 
 int thermal_zone_bind_cooling_device(struct thermal_zone_device *, int,
@@ -173,10 +223,20 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *, int,
 int thermal_zone_unbind_cooling_device(struct thermal_zone_device *, int,
                                       struct thermal_cooling_device *);
 void thermal_zone_device_update(struct thermal_zone_device *);
+
 struct thermal_cooling_device *thermal_cooling_device_register(char *, void *,
                const struct thermal_cooling_device_ops *);
 void thermal_cooling_device_unregister(struct thermal_cooling_device *);
 
+int get_tz_trend(struct thermal_zone_device *, int);
+struct thermal_instance *get_thermal_instance(struct thermal_zone_device *,
+               struct thermal_cooling_device *, int);
+void thermal_cdev_update(struct thermal_cooling_device *);
+void notify_thermal_framework(struct thermal_zone_device *, int);
+
+int thermal_register_governor(struct thermal_governor *);
+void thermal_unregister_governor(struct thermal_governor *);
+
 #ifdef CONFIG_NET
 extern int thermal_generate_netlink_event(u32 orig, enum events event);
 #else
index f37fceb69b73d294e9b045293f6bbbf71b72388d..1a6567b48492d3dd782b0646a9d87d496b8c95f1 100644 (file)
@@ -142,4 +142,10 @@ static inline u64 get_cpu_idle_time_us(int cpu, u64 *unused) { return -1; }
 static inline u64 get_cpu_iowait_time_us(int cpu, u64 *unused) { return -1; }
 # endif /* !NO_HZ */
 
+# ifdef CONFIG_CPU_IDLE_GOV_MENU
+extern void menu_hrtimer_cancel(void);
+# else
+static inline void menu_hrtimer_cancel(void) {}
+# endif /* CONFIG_CPU_IDLE_GOV_MENU */
+
 #endif
index f0b4eb47297c8b10a356c96d929e272702a7dd7b..d7ff88fb896715ba58838fe89d329ed0821439bb 100644 (file)
@@ -188,7 +188,9 @@ struct tty_port_operations {
 };
        
 struct tty_port {
+       struct tty_bufhead      buf;            /* Locked internally */
        struct tty_struct       *tty;           /* Back pointer */
+       struct tty_struct       *itty;          /* internal back ptr */
        const struct tty_port_operations *ops;  /* Port operations */
        spinlock_t              lock;           /* Lock protecting tty field */
        int                     blocked_open;   /* Waiting to open */
@@ -197,6 +199,9 @@ struct tty_port {
        wait_queue_head_t       close_wait;     /* Close waiters */
        wait_queue_head_t       delta_msr_wait; /* Modem status change */
        unsigned long           flags;          /* TTY flags ASY_*/
+       unsigned long           iflags;         /* TTYP_ internal flags */
+#define TTYP_FLUSHING                  1  /* Flushing to ldisc in progress */
+#define TTYP_FLUSHPENDING              2  /* Queued buffer flush pending */
        unsigned char           console:1;      /* port is a console */
        struct mutex            mutex;          /* Locking */
        struct mutex            buf_mutex;      /* Buffer alloc lock */
@@ -235,6 +240,7 @@ struct tty_struct {
        struct mutex ldisc_mutex;
        struct tty_ldisc *ldisc;
 
+       struct mutex atomic_write_lock;
        struct mutex legacy_mutex;
        struct mutex termios_mutex;
        spinlock_t ctrl_lock;
@@ -254,7 +260,6 @@ struct tty_struct {
 
        struct tty_struct *link;
        struct fasync_struct *fasync;
-       struct tty_bufhead buf;         /* Locked internally */
        int alt_speed;          /* For magic substitution of 38400 bps */
        wait_queue_head_t write_wait;
        wait_queue_head_t read_wait;
@@ -265,37 +270,10 @@ struct tty_struct {
 
 #define N_TTY_BUF_SIZE 4096
 
-       /*
-        * The following is data for the N_TTY line discipline.  For
-        * historical reasons, this is included in the tty structure.
-        * Mostly locked by the BKL.
-        */
-       unsigned int column;
-       unsigned char lnext:1, erasing:1, raw:1, real_raw:1, icanon:1;
        unsigned char closing:1;
-       unsigned char echo_overrun:1;
        unsigned short minimum_to_wake;
-       unsigned long overrun_time;
-       int num_overrun;
-       unsigned long process_char_map[256/(8*sizeof(unsigned long))];
-       char *read_buf;
-       int read_head;
-       int read_tail;
-       int read_cnt;
-       unsigned long read_flags[N_TTY_BUF_SIZE/(8*sizeof(unsigned long))];
-       unsigned char *echo_buf;
-       unsigned int echo_pos;
-       unsigned int echo_cnt;
-       int canon_data;
-       unsigned long canon_head;
-       unsigned int canon_column;
-       struct mutex atomic_read_lock;
-       struct mutex atomic_write_lock;
-       struct mutex output_lock;
-       struct mutex echo_lock;
        unsigned char *write_buf;
        int write_cnt;
-       spinlock_t read_lock;
        /* If the tty has a pending do_SAK, queue it here - akpm */
        struct work_struct SAK_work;
        struct tty_port *port;
@@ -335,8 +313,6 @@ struct tty_file_private {
 #define TTY_PTY_LOCK           16      /* pty private */
 #define TTY_NO_WRITE_SPLIT     17      /* Preserve write boundaries to driver */
 #define TTY_HUPPED             18      /* Post driver->hangup() */
-#define TTY_FLUSHING           19      /* Flushing to ldisc in progress */
-#define TTY_FLUSHPENDING       20      /* Queued buffer flush pending */
 #define TTY_HUPPING            21      /* ->hangup() in progress */
 
 #define TTY_WRITE_FLUSH(tty) tty_write_flush((tty))
@@ -412,9 +388,9 @@ extern void disassociate_ctty(int priv);
 extern void no_tty(void);
 extern void tty_flip_buffer_push(struct tty_struct *tty);
 extern void tty_flush_to_ldisc(struct tty_struct *tty);
-extern void tty_buffer_free_all(struct tty_struct *tty);
+extern void tty_buffer_free_all(struct tty_port *port);
 extern void tty_buffer_flush(struct tty_struct *tty);
-extern void tty_buffer_init(struct tty_struct *tty);
+extern void tty_buffer_init(struct tty_port *port);
 extern speed_t tty_get_baud_rate(struct tty_struct *tty);
 extern speed_t tty_termios_baud_rate(struct ktermios *termios);
 extern speed_t tty_termios_input_baud_rate(struct ktermios *termios);
@@ -535,7 +511,7 @@ extern void n_tty_inherit_ops(struct tty_ldisc_ops *ops);
 /* tty_audit.c */
 #ifdef CONFIG_AUDIT
 extern void tty_audit_add_data(struct tty_struct *tty, unsigned char *data,
-                              size_t size);
+                              size_t size, unsigned icanon);
 extern void tty_audit_exit(void);
 extern void tty_audit_fork(struct signal_struct *sig);
 extern void tty_audit_tiocsti(struct tty_struct *tty, char ch);
@@ -544,7 +520,7 @@ extern int tty_audit_push_task(struct task_struct *tsk,
                               kuid_t loginuid, u32 sessionid);
 #else
 static inline void tty_audit_add_data(struct tty_struct *tty,
-                                     unsigned char *data, size_t size)
+               unsigned char *data, size_t size, unsigned icanon)
 {
 }
 static inline void tty_audit_tiocsti(struct tty_struct *tty, char ch)
index 9239d033a0a3a94f503d11682bf6324a53179bd8..2002344ed36ad9de8c152b666eff10922ba930b8 100644 (file)
@@ -11,7 +11,7 @@ void tty_schedule_flip(struct tty_struct *tty);
 static inline int tty_insert_flip_char(struct tty_struct *tty,
                                        unsigned char ch, char flag)
 {
-       struct tty_buffer *tb = tty->buf.tail;
+       struct tty_buffer *tb = tty->port->buf.tail;
        if (tb && tb->used < tb->size) {
                tb->flag_buf_ptr[tb->used] = flag;
                tb->char_buf_ptr[tb->used++] = ch;
index e6f0331e3d456281c87370e8c0275961c04ca084..24594571c5a3aa8a094d9cca3795420e32cb4ce0 100644 (file)
@@ -35,16 +35,6 @@ struct inode;
 # include <asm/uprobes.h>
 #endif
 
-/* flags that denote/change uprobes behaviour */
-
-/* Have a copy of original instruction */
-#define UPROBE_COPY_INSN       0x1
-
-/* Dont run handlers when first register/ last unregister in progress*/
-#define UPROBE_RUN_HANDLER     0x2
-/* Can skip singlestep */
-#define UPROBE_SKIP_SSTEP      0x4
-
 struct uprobe_consumer {
        int (*handler)(struct uprobe_consumer *self, struct pt_regs *regs);
        /*
@@ -59,7 +49,6 @@ struct uprobe_consumer {
 #ifdef CONFIG_UPROBES
 enum uprobe_task_state {
        UTASK_RUNNING,
-       UTASK_BP_HIT,
        UTASK_SSTEP,
        UTASK_SSTEP_ACK,
        UTASK_SSTEP_TRAPPED,
index 07915a32fb9dcda932989cb495798cdc48bb1059..f51f9981de1ed9157257f63fff244e4397c71fe1 100644 (file)
@@ -482,6 +482,7 @@ struct usb3_lpm_parameters {
  * @connect_time: time device was first connected
  * @do_remote_wakeup:  remote wakeup should be enabled
  * @reset_resume: needs reset instead of resume
+ * @port_is_suspended: the upstream port is suspended (L2 or U3)
  * @wusb_dev: if this is a Wireless USB device, link to the WUSB
  *     specific data for the device.
  * @slot_id: Slot ID assigned by xHCI
@@ -560,6 +561,7 @@ struct usb_device {
 
        unsigned do_remote_wakeup:1;
        unsigned reset_resume:1;
+       unsigned port_is_suspended:1;
 #endif
        struct wusb_dev *wusb_dev;
        int slot_id;
@@ -588,8 +590,9 @@ extern struct usb_device *usb_hub_find_child(struct usb_device *hdev,
  */
 #define usb_hub_for_each_child(hdev, port1, child) \
        for (port1 = 1, child = usb_hub_find_child(hdev, port1); \
-               port1 <= hdev->maxchild; \
-               child = usb_hub_find_child(hdev, ++port1))
+                       port1 <= hdev->maxchild; \
+                       child = usb_hub_find_child(hdev, ++port1)) \
+               if (!child) continue; else
 
 /* USB device locking */
 #define usb_lock_device(udev)          device_lock(&(udev)->dev)
@@ -1129,8 +1132,8 @@ extern int usb_disabled(void);
  * Note: URB_DIR_IN/OUT is automatically set in usb_submit_urb().
  */
 #define URB_SHORT_NOT_OK       0x0001  /* report short reads as errors */
-#define URB_ISO_ASAP           0x0002  /* iso-only, urb->start_frame
-                                        * ignored */
+#define URB_ISO_ASAP           0x0002  /* iso-only; use the first unexpired
+                                        * slot in the schedule */
 #define URB_NO_TRANSFER_DMA_MAP        0x0004  /* urb->transfer_dma valid on submit */
 #define URB_NO_FSBR            0x0020  /* UHCI-specific */
 #define URB_ZERO_PACKET                0x0040  /* Finish bulk OUT with short packet */
@@ -1309,15 +1312,20 @@ typedef void (*usb_complete_t)(struct urb *);
  * the transfer interval in the endpoint descriptor is logarithmic.
  * Device drivers must convert that value to linear units themselves.)
  *
- * Isochronous URBs normally use the URB_ISO_ASAP transfer flag, telling
- * the host controller to schedule the transfer as soon as bandwidth
- * utilization allows, and then set start_frame to reflect the actual frame
- * selected during submission.  Otherwise drivers must specify the start_frame
- * and handle the case where the transfer can't begin then.  However, drivers
- * won't know how bandwidth is currently allocated, and while they can
- * find the current frame using usb_get_current_frame_number () they can't
- * know the range for that frame number.  (Ranges for frame counter values
- * are HC-specific, and can go from 256 to 65536 frames from "now".)
+ * If an isochronous endpoint queue isn't already running, the host
+ * controller will schedule a new URB to start as soon as bandwidth
+ * utilization allows.  If the queue is running then a new URB will be
+ * scheduled to start in the first transfer slot following the end of the
+ * preceding URB, if that slot has not already expired.  If the slot has
+ * expired (which can happen when IRQ delivery is delayed for a long time),
+ * the scheduling behavior depends on the URB_ISO_ASAP flag.  If the flag
+ * is clear then the URB will be scheduled to start in the expired slot,
+ * implying that some of its packets will not be transferred; if the flag
+ * is set then the URB will be scheduled in the first unexpired slot,
+ * breaking the queue's synchronization.  Upon URB completion, the
+ * start_frame field will be set to the (micro)frame number in which the
+ * transfer was scheduled.  Ranges for frame counter values are HC-specific
+ * and can go from as low as 256 to as high as 65536 frames.
  *
  * Isochronous URBs have a different data transfer model, in part because
  * the quality of service is only "best effort".  Callers provide specially
@@ -1778,17 +1786,6 @@ static inline int usb_translate_errors(int error_code)
 extern void usb_register_notify(struct notifier_block *nb);
 extern void usb_unregister_notify(struct notifier_block *nb);
 
-#ifdef DEBUG
-#define dbg(format, arg...)                                            \
-       printk(KERN_DEBUG "%s: " format "\n", __FILE__, ##arg)
-#else
-#define dbg(format, arg...)                                            \
-do {                                                                   \
-       if (0)                                                          \
-               printk(KERN_DEBUG "%s: " format "\n", __FILE__, ##arg); \
-} while (0)
-#endif
-
 /* debugfs stuff */
 extern struct dentry *usb_debug_root;
 
index b607f3532e880011453fd04462cbe90801538a6d..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1,10 +0,0 @@
-header-y += audio.h
-header-y += cdc.h
-header-y += ch9.h
-header-y += ch11.h
-header-y += functionfs.h
-header-y += gadgetfs.h
-header-y += midi.h
-header-y += g_printer.h
-header-y += tmc.h
-header-y += video.h
index a54b8255d75f099259c8e77ced1c8eef9aeb1158..3d84619110a4691f6d49900538f93077aa65251b 100644 (file)
  * Types and defines in this file are either specific to version 1.0 of
  * this standard or common for newer versions.
  */
-
 #ifndef __LINUX_USB_AUDIO_H
 #define __LINUX_USB_AUDIO_H
 
-#include <linux/types.h>
-
-/* bInterfaceProtocol values to denote the version of the standard used */
-#define UAC_VERSION_1                  0x00
-#define UAC_VERSION_2                  0x20
-
-/* A.2 Audio Interface Subclass Codes */
-#define USB_SUBCLASS_AUDIOCONTROL      0x01
-#define USB_SUBCLASS_AUDIOSTREAMING    0x02
-#define USB_SUBCLASS_MIDISTREAMING     0x03
-
-/* A.5 Audio Class-Specific AC Interface Descriptor Subtypes */
-#define UAC_HEADER                     0x01
-#define UAC_INPUT_TERMINAL             0x02
-#define UAC_OUTPUT_TERMINAL            0x03
-#define UAC_MIXER_UNIT                 0x04
-#define UAC_SELECTOR_UNIT              0x05
-#define UAC_FEATURE_UNIT               0x06
-#define UAC1_PROCESSING_UNIT           0x07
-#define UAC1_EXTENSION_UNIT            0x08
-
-/* A.6 Audio Class-Specific AS Interface Descriptor Subtypes */
-#define UAC_AS_GENERAL                 0x01
-#define UAC_FORMAT_TYPE                        0x02
-#define UAC_FORMAT_SPECIFIC            0x03
-
-/* A.7 Processing Unit Process Types */
-#define UAC_PROCESS_UNDEFINED          0x00
-#define UAC_PROCESS_UP_DOWNMIX         0x01
-#define UAC_PROCESS_DOLBY_PROLOGIC     0x02
-#define UAC_PROCESS_STEREO_EXTENDER    0x03
-#define UAC_PROCESS_REVERB             0x04
-#define UAC_PROCESS_CHORUS             0x05
-#define UAC_PROCESS_DYN_RANGE_COMP     0x06
-
-/* A.8 Audio Class-Specific Endpoint Descriptor Subtypes */
-#define UAC_EP_GENERAL                 0x01
-
-/* A.9 Audio Class-Specific Request Codes */
-#define UAC_SET_                       0x00
-#define UAC_GET_                       0x80
-
-#define UAC__CUR                       0x1
-#define UAC__MIN                       0x2
-#define UAC__MAX                       0x3
-#define UAC__RES                       0x4
-#define UAC__MEM                       0x5
-
-#define UAC_SET_CUR                    (UAC_SET_ | UAC__CUR)
-#define UAC_GET_CUR                    (UAC_GET_ | UAC__CUR)
-#define UAC_SET_MIN                    (UAC_SET_ | UAC__MIN)
-#define UAC_GET_MIN                    (UAC_GET_ | UAC__MIN)
-#define UAC_SET_MAX                    (UAC_SET_ | UAC__MAX)
-#define UAC_GET_MAX                    (UAC_GET_ | UAC__MAX)
-#define UAC_SET_RES                    (UAC_SET_ | UAC__RES)
-#define UAC_GET_RES                    (UAC_GET_ | UAC__RES)
-#define UAC_SET_MEM                    (UAC_SET_ | UAC__MEM)
-#define UAC_GET_MEM                    (UAC_GET_ | UAC__MEM)
-
-#define UAC_GET_STAT                   0xff
-
-/* A.10 Control Selector Codes */
-
-/* A.10.1 Terminal Control Selectors */
-#define UAC_TERM_COPY_PROTECT          0x01
-
-/* A.10.2 Feature Unit Control Selectors */
-#define UAC_FU_MUTE                    0x01
-#define UAC_FU_VOLUME                  0x02
-#define UAC_FU_BASS                    0x03
-#define UAC_FU_MID                     0x04
-#define UAC_FU_TREBLE                  0x05
-#define UAC_FU_GRAPHIC_EQUALIZER       0x06
-#define UAC_FU_AUTOMATIC_GAIN          0x07
-#define UAC_FU_DELAY                   0x08
-#define UAC_FU_BASS_BOOST              0x09
-#define UAC_FU_LOUDNESS                        0x0a
-
-#define UAC_CONTROL_BIT(CS)    (1 << ((CS) - 1))
-
-/* A.10.3.1 Up/Down-mix Processing Unit Controls Selectors */
-#define UAC_UD_ENABLE                  0x01
-#define UAC_UD_MODE_SELECT             0x02
-
-/* A.10.3.2 Dolby Prologic (tm) Processing Unit Controls Selectors */
-#define UAC_DP_ENABLE                  0x01
-#define UAC_DP_MODE_SELECT             0x02
-
-/* A.10.3.3 3D Stereo Extender Processing Unit Control Selectors */
-#define UAC_3D_ENABLE                  0x01
-#define UAC_3D_SPACE                   0x02
-
-/* A.10.3.4 Reverberation Processing Unit Control Selectors */
-#define UAC_REVERB_ENABLE              0x01
-#define UAC_REVERB_LEVEL               0x02
-#define UAC_REVERB_TIME                        0x03
-#define UAC_REVERB_FEEDBACK            0x04
-
-/* A.10.3.5 Chorus Processing Unit Control Selectors */
-#define UAC_CHORUS_ENABLE              0x01
-#define UAC_CHORUS_LEVEL               0x02
-#define UAC_CHORUS_RATE                        0x03
-#define UAC_CHORUS_DEPTH               0x04
-
-/* A.10.3.6 Dynamic Range Compressor Unit Control Selectors */
-#define UAC_DCR_ENABLE                 0x01
-#define UAC_DCR_RATE                   0x02
-#define UAC_DCR_MAXAMPL                        0x03
-#define UAC_DCR_THRESHOLD              0x04
-#define UAC_DCR_ATTACK_TIME            0x05
-#define UAC_DCR_RELEASE_TIME           0x06
-
-/* A.10.4 Extension Unit Control Selectors */
-#define UAC_XU_ENABLE                  0x01
-
-/* MIDI - A.1 MS Class-Specific Interface Descriptor Subtypes */
-#define UAC_MS_HEADER                  0x01
-#define UAC_MIDI_IN_JACK               0x02
-#define UAC_MIDI_OUT_JACK              0x03
-
-/* MIDI - A.1 MS Class-Specific Endpoint Descriptor Subtypes */
-#define UAC_MS_GENERAL                 0x01
-
-/* Terminals - 2.1 USB Terminal Types */
-#define UAC_TERMINAL_UNDEFINED         0x100
-#define UAC_TERMINAL_STREAMING         0x101
-#define UAC_TERMINAL_VENDOR_SPEC       0x1FF
-
-/* Terminal Control Selectors */
-/* 4.3.2  Class-Specific AC Interface Descriptor */
-struct uac1_ac_header_descriptor {
-       __u8  bLength;                  /* 8 + n */
-       __u8  bDescriptorType;          /* USB_DT_CS_INTERFACE */
-       __u8  bDescriptorSubtype;       /* UAC_MS_HEADER */
-       __le16 bcdADC;                  /* 0x0100 */
-       __le16 wTotalLength;            /* includes Unit and Terminal desc. */
-       __u8  bInCollection;            /* n */
-       __u8  baInterfaceNr[];          /* [n] */
-} __attribute__ ((packed));
-
-#define UAC_DT_AC_HEADER_SIZE(n)       (8 + (n))
-
-/* As above, but more useful for defining your own descriptors: */
-#define DECLARE_UAC_AC_HEADER_DESCRIPTOR(n)                    \
-struct uac1_ac_header_descriptor_##n {                 \
-       __u8  bLength;                                          \
-       __u8  bDescriptorType;                                  \
-       __u8  bDescriptorSubtype;                               \
-       __le16 bcdADC;                                          \
-       __le16 wTotalLength;                                    \
-       __u8  bInCollection;                                    \
-       __u8  baInterfaceNr[n];                                 \
-} __attribute__ ((packed))
-
-/* 4.3.2.1 Input Terminal Descriptor */
-struct uac_input_terminal_descriptor {
-       __u8  bLength;                  /* in bytes: 12 */
-       __u8  bDescriptorType;          /* CS_INTERFACE descriptor type */
-       __u8  bDescriptorSubtype;       /* INPUT_TERMINAL descriptor subtype */
-       __u8  bTerminalID;              /* Constant uniquely terminal ID */
-       __le16 wTerminalType;           /* USB Audio Terminal Types */
-       __u8  bAssocTerminal;           /* ID of the Output Terminal associated */
-       __u8  bNrChannels;              /* Number of logical output channels */
-       __le16 wChannelConfig;
-       __u8  iChannelNames;
-       __u8  iTerminal;
-} __attribute__ ((packed));
-
-#define UAC_DT_INPUT_TERMINAL_SIZE                     12
-
-/* Terminals - 2.2 Input Terminal Types */
-#define UAC_INPUT_TERMINAL_UNDEFINED                   0x200
-#define UAC_INPUT_TERMINAL_MICROPHONE                  0x201
-#define UAC_INPUT_TERMINAL_DESKTOP_MICROPHONE          0x202
-#define UAC_INPUT_TERMINAL_PERSONAL_MICROPHONE         0x203
-#define UAC_INPUT_TERMINAL_OMNI_DIR_MICROPHONE         0x204
-#define UAC_INPUT_TERMINAL_MICROPHONE_ARRAY            0x205
-#define UAC_INPUT_TERMINAL_PROC_MICROPHONE_ARRAY       0x206
-
-/* Terminals - control selectors */
-
-#define UAC_TERMINAL_CS_COPY_PROTECT_CONTROL           0x01
-
-/* 4.3.2.2 Output Terminal Descriptor */
-struct uac1_output_terminal_descriptor {
-       __u8  bLength;                  /* in bytes: 9 */
-       __u8  bDescriptorType;          /* CS_INTERFACE descriptor type */
-       __u8  bDescriptorSubtype;       /* OUTPUT_TERMINAL descriptor subtype */
-       __u8  bTerminalID;              /* Constant uniquely terminal ID */
-       __le16 wTerminalType;           /* USB Audio Terminal Types */
-       __u8  bAssocTerminal;           /* ID of the Input Terminal associated */
-       __u8  bSourceID;                /* ID of the connected Unit or Terminal*/
-       __u8  iTerminal;
-} __attribute__ ((packed));
-
-#define UAC_DT_OUTPUT_TERMINAL_SIZE                    9
-
-/* Terminals - 2.3 Output Terminal Types */
-#define UAC_OUTPUT_TERMINAL_UNDEFINED                  0x300
-#define UAC_OUTPUT_TERMINAL_SPEAKER                    0x301
-#define UAC_OUTPUT_TERMINAL_HEADPHONES                 0x302
-#define UAC_OUTPUT_TERMINAL_HEAD_MOUNTED_DISPLAY_AUDIO 0x303
-#define UAC_OUTPUT_TERMINAL_DESKTOP_SPEAKER            0x304
-#define UAC_OUTPUT_TERMINAL_ROOM_SPEAKER               0x305
-#define UAC_OUTPUT_TERMINAL_COMMUNICATION_SPEAKER      0x306
-#define UAC_OUTPUT_TERMINAL_LOW_FREQ_EFFECTS_SPEAKER   0x307
-
-/* Set bControlSize = 2 as default setting */
-#define UAC_DT_FEATURE_UNIT_SIZE(ch)           (7 + ((ch) + 1) * 2)
-
-/* As above, but more useful for defining your own descriptors: */
-#define DECLARE_UAC_FEATURE_UNIT_DESCRIPTOR(ch)                        \
-struct uac_feature_unit_descriptor_##ch {                      \
-       __u8  bLength;                                          \
-       __u8  bDescriptorType;                                  \
-       __u8  bDescriptorSubtype;                               \
-       __u8  bUnitID;                                          \
-       __u8  bSourceID;                                        \
-       __u8  bControlSize;                                     \
-       __le16 bmaControls[ch + 1];                             \
-       __u8  iFeature;                                         \
-} __attribute__ ((packed))
-
-/* 4.3.2.3 Mixer Unit Descriptor */
-struct uac_mixer_unit_descriptor {
-       __u8 bLength;
-       __u8 bDescriptorType;
-       __u8 bDescriptorSubtype;
-       __u8 bUnitID;
-       __u8 bNrInPins;
-       __u8 baSourceID[];
-} __attribute__ ((packed));
+#include <uapi/linux/usb/audio.h>
 
-static inline __u8 uac_mixer_unit_bNrChannels(struct uac_mixer_unit_descriptor *desc)
-{
-       return desc->baSourceID[desc->bNrInPins];
-}
-
-static inline __u32 uac_mixer_unit_wChannelConfig(struct uac_mixer_unit_descriptor *desc,
-                                                 int protocol)
-{
-       if (protocol == UAC_VERSION_1)
-               return (desc->baSourceID[desc->bNrInPins + 2] << 8) |
-                       desc->baSourceID[desc->bNrInPins + 1];
-       else
-               return  (desc->baSourceID[desc->bNrInPins + 4] << 24) |
-                       (desc->baSourceID[desc->bNrInPins + 3] << 16) |
-                       (desc->baSourceID[desc->bNrInPins + 2] << 8)  |
-                       (desc->baSourceID[desc->bNrInPins + 1]);
-}
-
-static inline __u8 uac_mixer_unit_iChannelNames(struct uac_mixer_unit_descriptor *desc,
-                                               int protocol)
-{
-       return (protocol == UAC_VERSION_1) ?
-               desc->baSourceID[desc->bNrInPins + 3] :
-               desc->baSourceID[desc->bNrInPins + 5];
-}
-
-static inline __u8 *uac_mixer_unit_bmControls(struct uac_mixer_unit_descriptor *desc,
-                                             int protocol)
-{
-       return (protocol == UAC_VERSION_1) ?
-               &desc->baSourceID[desc->bNrInPins + 4] :
-               &desc->baSourceID[desc->bNrInPins + 6];
-}
-
-static inline __u8 uac_mixer_unit_iMixer(struct uac_mixer_unit_descriptor *desc)
-{
-       __u8 *raw = (__u8 *) desc;
-       return raw[desc->bLength - 1];
-}
-
-/* 4.3.2.4 Selector Unit Descriptor */
-struct uac_selector_unit_descriptor {
-       __u8 bLength;
-       __u8 bDescriptorType;
-       __u8 bDescriptorSubtype;
-       __u8 bUintID;
-       __u8 bNrInPins;
-       __u8 baSourceID[];
-} __attribute__ ((packed));
-
-static inline __u8 uac_selector_unit_iSelector(struct uac_selector_unit_descriptor *desc)
-{
-       __u8 *raw = (__u8 *) desc;
-       return raw[desc->bLength - 1];
-}
-
-/* 4.3.2.5 Feature Unit Descriptor */
-struct uac_feature_unit_descriptor {
-       __u8 bLength;
-       __u8 bDescriptorType;
-       __u8 bDescriptorSubtype;
-       __u8 bUnitID;
-       __u8 bSourceID;
-       __u8 bControlSize;
-       __u8 bmaControls[0]; /* variable length */
-} __attribute__((packed));
-
-static inline __u8 uac_feature_unit_iFeature(struct uac_feature_unit_descriptor *desc)
-{
-       __u8 *raw = (__u8 *) desc;
-       return raw[desc->bLength - 1];
-}
-
-/* 4.3.2.6 Processing Unit Descriptors */
-struct uac_processing_unit_descriptor {
-       __u8 bLength;
-       __u8 bDescriptorType;
-       __u8 bDescriptorSubtype;
-       __u8 bUnitID;
-       __u16 wProcessType;
-       __u8 bNrInPins;
-       __u8 baSourceID[];
-} __attribute__ ((packed));
-
-static inline __u8 uac_processing_unit_bNrChannels(struct uac_processing_unit_descriptor *desc)
-{
-       return desc->baSourceID[desc->bNrInPins];
-}
-
-static inline __u32 uac_processing_unit_wChannelConfig(struct uac_processing_unit_descriptor *desc,
-                                                      int protocol)
-{
-       if (protocol == UAC_VERSION_1)
-               return (desc->baSourceID[desc->bNrInPins + 2] << 8) |
-                       desc->baSourceID[desc->bNrInPins + 1];
-       else
-               return  (desc->baSourceID[desc->bNrInPins + 4] << 24) |
-                       (desc->baSourceID[desc->bNrInPins + 3] << 16) |
-                       (desc->baSourceID[desc->bNrInPins + 2] << 8)  |
-                       (desc->baSourceID[desc->bNrInPins + 1]);
-}
-
-static inline __u8 uac_processing_unit_iChannelNames(struct uac_processing_unit_descriptor *desc,
-                                                    int protocol)
-{
-       return (protocol == UAC_VERSION_1) ?
-               desc->baSourceID[desc->bNrInPins + 3] :
-               desc->baSourceID[desc->bNrInPins + 5];
-}
-
-static inline __u8 uac_processing_unit_bControlSize(struct uac_processing_unit_descriptor *desc,
-                                                   int protocol)
-{
-       return (protocol == UAC_VERSION_1) ?
-               desc->baSourceID[desc->bNrInPins + 4] :
-               desc->baSourceID[desc->bNrInPins + 6];
-}
-
-static inline __u8 *uac_processing_unit_bmControls(struct uac_processing_unit_descriptor *desc,
-                                                  int protocol)
-{
-       return (protocol == UAC_VERSION_1) ?
-               &desc->baSourceID[desc->bNrInPins + 5] :
-               &desc->baSourceID[desc->bNrInPins + 7];
-}
-
-static inline __u8 uac_processing_unit_iProcessing(struct uac_processing_unit_descriptor *desc,
-                                                  int protocol)
-{
-       __u8 control_size = uac_processing_unit_bControlSize(desc, protocol);
-       return desc->baSourceID[desc->bNrInPins + control_size];
-}
-
-static inline __u8 *uac_processing_unit_specific(struct uac_processing_unit_descriptor *desc,
-                                                int protocol)
-{
-       __u8 control_size = uac_processing_unit_bControlSize(desc, protocol);
-       return &desc->baSourceID[desc->bNrInPins + control_size + 1];
-}
-
-/* 4.5.2 Class-Specific AS Interface Descriptor */
-struct uac1_as_header_descriptor {
-       __u8  bLength;                  /* in bytes: 7 */
-       __u8  bDescriptorType;          /* USB_DT_CS_INTERFACE */
-       __u8  bDescriptorSubtype;       /* AS_GENERAL */
-       __u8  bTerminalLink;            /* Terminal ID of connected Terminal */
-       __u8  bDelay;                   /* Delay introduced by the data path */
-       __le16 wFormatTag;              /* The Audio Data Format */
-} __attribute__ ((packed));
-
-#define UAC_DT_AS_HEADER_SIZE          7
-
-/* Formats - A.1.1 Audio Data Format Type I Codes */
-#define UAC_FORMAT_TYPE_I_UNDEFINED    0x0
-#define UAC_FORMAT_TYPE_I_PCM          0x1
-#define UAC_FORMAT_TYPE_I_PCM8         0x2
-#define UAC_FORMAT_TYPE_I_IEEE_FLOAT   0x3
-#define UAC_FORMAT_TYPE_I_ALAW         0x4
-#define UAC_FORMAT_TYPE_I_MULAW                0x5
-
-struct uac_format_type_i_continuous_descriptor {
-       __u8  bLength;                  /* in bytes: 8 + (ns * 3) */
-       __u8  bDescriptorType;          /* USB_DT_CS_INTERFACE */
-       __u8  bDescriptorSubtype;       /* FORMAT_TYPE */
-       __u8  bFormatType;              /* FORMAT_TYPE_1 */
-       __u8  bNrChannels;              /* physical channels in the stream */
-       __u8  bSubframeSize;            /* */
-       __u8  bBitResolution;
-       __u8  bSamFreqType;
-       __u8  tLowerSamFreq[3];
-       __u8  tUpperSamFreq[3];
-} __attribute__ ((packed));
-
-#define UAC_FORMAT_TYPE_I_CONTINUOUS_DESC_SIZE 14
-
-struct uac_format_type_i_discrete_descriptor {
-       __u8  bLength;                  /* in bytes: 8 + (ns * 3) */
-       __u8  bDescriptorType;          /* USB_DT_CS_INTERFACE */
-       __u8  bDescriptorSubtype;       /* FORMAT_TYPE */
-       __u8  bFormatType;              /* FORMAT_TYPE_1 */
-       __u8  bNrChannels;              /* physical channels in the stream */
-       __u8  bSubframeSize;            /* */
-       __u8  bBitResolution;
-       __u8  bSamFreqType;
-       __u8  tSamFreq[][3];
-} __attribute__ ((packed));
-
-#define DECLARE_UAC_FORMAT_TYPE_I_DISCRETE_DESC(n)             \
-struct uac_format_type_i_discrete_descriptor_##n {             \
-       __u8  bLength;                                          \
-       __u8  bDescriptorType;                                  \
-       __u8  bDescriptorSubtype;                               \
-       __u8  bFormatType;                                      \
-       __u8  bNrChannels;                                      \
-       __u8  bSubframeSize;                                    \
-       __u8  bBitResolution;                                   \
-       __u8  bSamFreqType;                                     \
-       __u8  tSamFreq[n][3];                                   \
-} __attribute__ ((packed))
-
-#define UAC_FORMAT_TYPE_I_DISCRETE_DESC_SIZE(n)        (8 + (n * 3))
-
-struct uac_format_type_i_ext_descriptor {
-       __u8 bLength;
-       __u8 bDescriptorType;
-       __u8 bDescriptorSubtype;
-       __u8 bFormatType;
-       __u8 bSubslotSize;
-       __u8 bBitResolution;
-       __u8 bHeaderLength;
-       __u8 bControlSize;
-       __u8 bSideBandProtocol;
-} __attribute__((packed));
-
-/* Formats - Audio Data Format Type I Codes */
-
-#define UAC_FORMAT_TYPE_II_MPEG        0x1001
-#define UAC_FORMAT_TYPE_II_AC3 0x1002
-
-struct uac_format_type_ii_discrete_descriptor {
-       __u8 bLength;
-       __u8 bDescriptorType;
-       __u8 bDescriptorSubtype;
-       __u8 bFormatType;
-       __le16 wMaxBitRate;
-       __le16 wSamplesPerFrame;
-       __u8 bSamFreqType;
-       __u8 tSamFreq[][3];
-} __attribute__((packed));
-
-struct uac_format_type_ii_ext_descriptor {
-       __u8 bLength;
-       __u8 bDescriptorType;
-       __u8 bDescriptorSubtype;
-       __u8 bFormatType;
-       __u16 wMaxBitRate;
-       __u16 wSamplesPerFrame;
-       __u8 bHeaderLength;
-       __u8 bSideBandProtocol;
-} __attribute__((packed));
-
-/* type III */
-#define UAC_FORMAT_TYPE_III_IEC1937_AC3        0x2001
-#define UAC_FORMAT_TYPE_III_IEC1937_MPEG1_LAYER1       0x2002
-#define UAC_FORMAT_TYPE_III_IEC1937_MPEG2_NOEXT        0x2003
-#define UAC_FORMAT_TYPE_III_IEC1937_MPEG2_EXT  0x2004
-#define UAC_FORMAT_TYPE_III_IEC1937_MPEG2_LAYER1_LS    0x2005
-#define UAC_FORMAT_TYPE_III_IEC1937_MPEG2_LAYER23_LS   0x2006
-
-/* Formats - A.2 Format Type Codes */
-#define UAC_FORMAT_TYPE_UNDEFINED      0x0
-#define UAC_FORMAT_TYPE_I              0x1
-#define UAC_FORMAT_TYPE_II             0x2
-#define UAC_FORMAT_TYPE_III            0x3
-#define UAC_EXT_FORMAT_TYPE_I          0x81
-#define UAC_EXT_FORMAT_TYPE_II         0x82
-#define UAC_EXT_FORMAT_TYPE_III                0x83
-
-struct uac_iso_endpoint_descriptor {
-       __u8  bLength;                  /* in bytes: 7 */
-       __u8  bDescriptorType;          /* USB_DT_CS_ENDPOINT */
-       __u8  bDescriptorSubtype;       /* EP_GENERAL */
-       __u8  bmAttributes;
-       __u8  bLockDelayUnits;
-       __le16 wLockDelay;
-} __attribute__((packed));
-#define UAC_ISO_ENDPOINT_DESC_SIZE     7
-
-#define UAC_EP_CS_ATTR_SAMPLE_RATE     0x01
-#define UAC_EP_CS_ATTR_PITCH_CONTROL   0x02
-#define UAC_EP_CS_ATTR_FILL_MAX                0x80
-
-/* status word format (3.7.1.1) */
-
-#define UAC1_STATUS_TYPE_ORIG_MASK             0x0f
-#define UAC1_STATUS_TYPE_ORIG_AUDIO_CONTROL_IF 0x0
-#define UAC1_STATUS_TYPE_ORIG_AUDIO_STREAM_IF  0x1
-#define UAC1_STATUS_TYPE_ORIG_AUDIO_STREAM_EP  0x2
-
-#define UAC1_STATUS_TYPE_IRQ_PENDING           (1 << 7)
-#define UAC1_STATUS_TYPE_MEM_CHANGED           (1 << 6)
-
-struct uac1_status_word {
-       __u8 bStatusType;
-       __u8 bOriginator;
-} __attribute__((packed));
-
-#ifdef __KERNEL__
 
 struct usb_audio_control {
        struct list_head list;
@@ -561,6 +41,4 @@ struct usb_audio_control_selector {
        struct usb_descriptor_header *desc;
 };
 
-#endif /* __KERNEL__ */
-
 #endif /* __LINUX_USB_AUDIO_H */
diff --git a/include/linux/usb/cdc_ncm.h b/include/linux/usb/cdc_ncm.h
new file mode 100644 (file)
index 0000000..3b8f9d4
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) ST-Ericsson 2010-2012
+ * Contact: Alexey Orishko <alexey.orishko@stericsson.com>
+ * Original author: Hans Petter Selasky <hans.petter.selasky@stericsson.com>
+ *
+ * USB Host Driver for Network Control Model (NCM)
+ * http://www.usb.org/developers/devclass_docs/NCM10.zip
+ *
+ * The NCM encoding, decoding and initialization logic
+ * derives from FreeBSD 8.x. if_cdce.c and if_cdcereg.h
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose this file to be licensed under the terms
+ * of the GNU General Public License (GPL) Version 2 or the 2-clause
+ * BSD license listed below:
+ *
+ * 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.
+ */
+
+#define CDC_NCM_COMM_ALTSETTING_NCM            0
+#define CDC_NCM_COMM_ALTSETTING_MBIM           1
+
+#define CDC_NCM_DATA_ALTSETTING_NCM            1
+#define CDC_NCM_DATA_ALTSETTING_MBIM           2
+
+/* CDC NCM subclass 3.2.1 */
+#define USB_CDC_NCM_NDP16_LENGTH_MIN           0x10
+
+/* Maximum NTB length */
+#define        CDC_NCM_NTB_MAX_SIZE_TX                 32768   /* bytes */
+#define        CDC_NCM_NTB_MAX_SIZE_RX                 32768   /* bytes */
+
+/* Minimum value for MaxDatagramSize, ch. 6.2.9 */
+#define        CDC_NCM_MIN_DATAGRAM_SIZE               1514    /* bytes */
+
+/* Minimum value for MaxDatagramSize, ch. 8.1.3 */
+#define CDC_MBIM_MIN_DATAGRAM_SIZE             2048    /* bytes */
+
+#define        CDC_NCM_MIN_TX_PKT                      512     /* bytes */
+
+/* Default value for MaxDatagramSize */
+#define        CDC_NCM_MAX_DATAGRAM_SIZE               8192    /* bytes */
+
+/*
+ * Maximum amount of datagrams in NCM Datagram Pointer Table, not counting
+ * the last NULL entry.
+ */
+#define        CDC_NCM_DPT_DATAGRAMS_MAX               40
+
+/* Restart the timer, if amount of datagrams is less than given value */
+#define        CDC_NCM_RESTART_TIMER_DATAGRAM_CNT      3
+#define        CDC_NCM_TIMER_PENDING_CNT               2
+#define CDC_NCM_TIMER_INTERVAL                 (400UL * NSEC_PER_USEC)
+
+/* The following macro defines the minimum header space */
+#define        CDC_NCM_MIN_HDR_SIZE \
+       (sizeof(struct usb_cdc_ncm_nth16) + sizeof(struct usb_cdc_ncm_ndp16) + \
+       (CDC_NCM_DPT_DATAGRAMS_MAX + 1) * sizeof(struct usb_cdc_ncm_dpe16))
+
+#define CDC_NCM_NDP_SIZE \
+       (sizeof(struct usb_cdc_ncm_ndp16) +                             \
+             (CDC_NCM_DPT_DATAGRAMS_MAX + 1) * sizeof(struct usb_cdc_ncm_dpe16))
+
+#define cdc_ncm_comm_intf_is_mbim(x)  ((x)->desc.bInterfaceSubClass == USB_CDC_SUBCLASS_MBIM && \
+                                      (x)->desc.bInterfaceProtocol == USB_CDC_PROTO_NONE)
+#define cdc_ncm_data_intf_is_mbim(x)  ((x)->desc.bInterfaceProtocol == USB_CDC_MBIM_PROTO_NTB)
+
+struct cdc_ncm_ctx {
+       struct usb_cdc_ncm_ntb_parameters ncm_parm;
+       struct hrtimer tx_timer;
+       struct tasklet_struct bh;
+
+       const struct usb_cdc_ncm_desc *func_desc;
+       const struct usb_cdc_mbim_desc   *mbim_desc;
+       const struct usb_cdc_header_desc *header_desc;
+       const struct usb_cdc_union_desc *union_desc;
+       const struct usb_cdc_ether_desc *ether_desc;
+
+       struct net_device *netdev;
+       struct usb_device *udev;
+       struct usb_host_endpoint *in_ep;
+       struct usb_host_endpoint *out_ep;
+       struct usb_host_endpoint *status_ep;
+       struct usb_interface *intf;
+       struct usb_interface *control;
+       struct usb_interface *data;
+
+       struct sk_buff *tx_curr_skb;
+       struct sk_buff *tx_rem_skb;
+       __le32 tx_rem_sign;
+
+       spinlock_t mtx;
+       atomic_t stop;
+
+       u32 tx_timer_pending;
+       u32 tx_curr_frame_num;
+       u32 rx_speed;
+       u32 tx_speed;
+       u32 rx_max;
+       u32 tx_max;
+       u32 max_datagram_size;
+       u16 tx_max_datagrams;
+       u16 tx_remainder;
+       u16 tx_modulus;
+       u16 tx_ndp_modulus;
+       u16 tx_seq;
+       u16 rx_seq;
+       u16 connected;
+};
+
+extern int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_altsetting);
+extern void cdc_ncm_unbind(struct usbnet *dev, struct usb_interface *intf);
+extern struct sk_buff *cdc_ncm_fill_tx_frame(struct cdc_ncm_ctx *ctx, struct sk_buff *skb, __le32 sign);
+extern int cdc_ncm_rx_verify_nth16(struct cdc_ncm_ctx *ctx, struct sk_buff *skb_in);
+extern int cdc_ncm_rx_verify_ndp16(struct sk_buff *skb_in, int ndpoffset);
index d1d732c2838d3a48788c16fe87bd9552a8558ab8..9c210f2283dfd0268e1e7e580b1b6b3091801429 100644 (file)
  *     someone that the two other points are non-issues for that
  *     particular descriptor type.
  */
-
 #ifndef __LINUX_USB_CH9_H
 #define __LINUX_USB_CH9_H
 
-#include <linux/types.h>       /* __u8 etc */
-#include <asm/byteorder.h>     /* le16_to_cpu */
-
-/*-------------------------------------------------------------------------*/
-
-/* CONTROL REQUEST SUPPORT */
-
-/*
- * USB directions
- *
- * This bit flag is used in endpoint descriptors' bEndpointAddress field.
- * It's also one of three fields in control requests bRequestType.
- */
-#define USB_DIR_OUT                    0               /* to device */
-#define USB_DIR_IN                     0x80            /* to host */
-
-/*
- * USB types, the second of three bRequestType fields
- */
-#define USB_TYPE_MASK                  (0x03 << 5)
-#define USB_TYPE_STANDARD              (0x00 << 5)
-#define USB_TYPE_CLASS                 (0x01 << 5)
-#define USB_TYPE_VENDOR                        (0x02 << 5)
-#define USB_TYPE_RESERVED              (0x03 << 5)
-
-/*
- * USB recipients, the third of three bRequestType fields
- */
-#define USB_RECIP_MASK                 0x1f
-#define USB_RECIP_DEVICE               0x00
-#define USB_RECIP_INTERFACE            0x01
-#define USB_RECIP_ENDPOINT             0x02
-#define USB_RECIP_OTHER                        0x03
-/* From Wireless USB 1.0 */
-#define USB_RECIP_PORT                 0x04
-#define USB_RECIP_RPIPE                0x05
-
-/*
- * Standard requests, for the bRequest field of a SETUP packet.
- *
- * These are qualified by the bRequestType field, so that for example
- * TYPE_CLASS or TYPE_VENDOR specific feature flags could be retrieved
- * by a GET_STATUS request.
- */
-#define USB_REQ_GET_STATUS             0x00
-#define USB_REQ_CLEAR_FEATURE          0x01
-#define USB_REQ_SET_FEATURE            0x03
-#define USB_REQ_SET_ADDRESS            0x05
-#define USB_REQ_GET_DESCRIPTOR         0x06
-#define USB_REQ_SET_DESCRIPTOR         0x07
-#define USB_REQ_GET_CONFIGURATION      0x08
-#define USB_REQ_SET_CONFIGURATION      0x09
-#define USB_REQ_GET_INTERFACE          0x0A
-#define USB_REQ_SET_INTERFACE          0x0B
-#define USB_REQ_SYNCH_FRAME            0x0C
-#define USB_REQ_SET_SEL                        0x30
-#define USB_REQ_SET_ISOCH_DELAY                0x31
-
-#define USB_REQ_SET_ENCRYPTION         0x0D    /* Wireless USB */
-#define USB_REQ_GET_ENCRYPTION         0x0E
-#define USB_REQ_RPIPE_ABORT            0x0E
-#define USB_REQ_SET_HANDSHAKE          0x0F
-#define USB_REQ_RPIPE_RESET            0x0F
-#define USB_REQ_GET_HANDSHAKE          0x10
-#define USB_REQ_SET_CONNECTION         0x11
-#define USB_REQ_SET_SECURITY_DATA      0x12
-#define USB_REQ_GET_SECURITY_DATA      0x13
-#define USB_REQ_SET_WUSB_DATA          0x14
-#define USB_REQ_LOOPBACK_DATA_WRITE    0x15
-#define USB_REQ_LOOPBACK_DATA_READ     0x16
-#define USB_REQ_SET_INTERFACE_DS       0x17
-
-/* The Link Power Management (LPM) ECN defines USB_REQ_TEST_AND_SET command,
- * used by hubs to put ports into a new L1 suspend state, except that it
- * forgot to define its number ...
- */
-
-/*
- * USB feature flags are written using USB_REQ_{CLEAR,SET}_FEATURE, and
- * are read as a bit array returned by USB_REQ_GET_STATUS.  (So there
- * are at most sixteen features of each type.)  Hubs may also support a
- * new USB_REQ_TEST_AND_SET_FEATURE to put ports into L1 suspend.
- */
-#define USB_DEVICE_SELF_POWERED                0       /* (read only) */
-#define USB_DEVICE_REMOTE_WAKEUP       1       /* dev may initiate wakeup */
-#define USB_DEVICE_TEST_MODE           2       /* (wired high speed only) */
-#define USB_DEVICE_BATTERY             2       /* (wireless) */
-#define USB_DEVICE_B_HNP_ENABLE                3       /* (otg) dev may initiate HNP */
-#define USB_DEVICE_WUSB_DEVICE         3       /* (wireless)*/
-#define USB_DEVICE_A_HNP_SUPPORT       4       /* (otg) RH port supports HNP */
-#define USB_DEVICE_A_ALT_HNP_SUPPORT   5       /* (otg) other RH port does */
-#define USB_DEVICE_DEBUG_MODE          6       /* (special devices only) */
-
-/*
- * Test Mode Selectors
- * See USB 2.0 spec Table 9-7
- */
-#define        TEST_J          1
-#define        TEST_K          2
-#define        TEST_SE0_NAK    3
-#define        TEST_PACKET     4
-#define        TEST_FORCE_EN   5
-
-/*
- * New Feature Selectors as added by USB 3.0
- * See USB 3.0 spec Table 9-6
- */
-#define USB_DEVICE_U1_ENABLE   48      /* dev may initiate U1 transition */
-#define USB_DEVICE_U2_ENABLE   49      /* dev may initiate U2 transition */
-#define USB_DEVICE_LTM_ENABLE  50      /* dev may send LTM */
-#define USB_INTRF_FUNC_SUSPEND 0       /* function suspend */
-
-#define USB_INTR_FUNC_SUSPEND_OPT_MASK 0xFF00
-/*
- * Suspend Options, Table 9-7 USB 3.0 spec
- */
-#define USB_INTRF_FUNC_SUSPEND_LP      (1 << (8 + 0))
-#define USB_INTRF_FUNC_SUSPEND_RW      (1 << (8 + 1))
-
-#define USB_ENDPOINT_HALT              0       /* IN/OUT will STALL */
-
-/* Bit array elements as returned by the USB_REQ_GET_STATUS request. */
-#define USB_DEV_STAT_U1_ENABLED                2       /* transition into U1 state */
-#define USB_DEV_STAT_U2_ENABLED                3       /* transition into U2 state */
-#define USB_DEV_STAT_LTM_ENABLED       4       /* Latency tolerance messages */
-
-/**
- * struct usb_ctrlrequest - SETUP data for a USB device control request
- * @bRequestType: matches the USB bmRequestType field
- * @bRequest: matches the USB bRequest field
- * @wValue: matches the USB wValue field (le16 byte order)
- * @wIndex: matches the USB wIndex field (le16 byte order)
- * @wLength: matches the USB wLength field (le16 byte order)
- *
- * This structure is used to send control requests to a USB device.  It matches
- * the different fields of the USB 2.0 Spec section 9.3, table 9-2.  See the
- * USB spec for a fuller description of the different fields, and what they are
- * used for.
- *
- * Note that the driver for any interface can issue control requests.
- * For most devices, interfaces don't coordinate with each other, so
- * such requests may be made at any time.
- */
-struct usb_ctrlrequest {
-       __u8 bRequestType;
-       __u8 bRequest;
-       __le16 wValue;
-       __le16 wIndex;
-       __le16 wLength;
-} __attribute__ ((packed));
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * STANDARD DESCRIPTORS ... as returned by GET_DESCRIPTOR, or
- * (rarely) accepted by SET_DESCRIPTOR.
- *
- * Note that all multi-byte values here are encoded in little endian
- * byte order "on the wire".  Within the kernel and when exposed
- * through the Linux-USB APIs, they are not converted to cpu byte
- * order; it is the responsibility of the client code to do this.
- * The single exception is when device and configuration descriptors (but
- * not other descriptors) are read from usbfs (i.e. /proc/bus/usb/BBB/DDD);
- * in this case the fields are converted to host endianness by the kernel.
- */
-
-/*
- * Descriptor types ... USB 2.0 spec table 9.5
- */
-#define USB_DT_DEVICE                  0x01
-#define USB_DT_CONFIG                  0x02
-#define USB_DT_STRING                  0x03
-#define USB_DT_INTERFACE               0x04
-#define USB_DT_ENDPOINT                        0x05
-#define USB_DT_DEVICE_QUALIFIER                0x06
-#define USB_DT_OTHER_SPEED_CONFIG      0x07
-#define USB_DT_INTERFACE_POWER         0x08
-/* these are from a minor usb 2.0 revision (ECN) */
-#define USB_DT_OTG                     0x09
-#define USB_DT_DEBUG                   0x0a
-#define USB_DT_INTERFACE_ASSOCIATION   0x0b
-/* these are from the Wireless USB spec */
-#define USB_DT_SECURITY                        0x0c
-#define USB_DT_KEY                     0x0d
-#define USB_DT_ENCRYPTION_TYPE         0x0e
-#define USB_DT_BOS                     0x0f
-#define USB_DT_DEVICE_CAPABILITY       0x10
-#define USB_DT_WIRELESS_ENDPOINT_COMP  0x11
-#define USB_DT_WIRE_ADAPTER            0x21
-#define USB_DT_RPIPE                   0x22
-#define USB_DT_CS_RADIO_CONTROL                0x23
-/* From the T10 UAS specification */
-#define USB_DT_PIPE_USAGE              0x24
-/* From the USB 3.0 spec */
-#define        USB_DT_SS_ENDPOINT_COMP         0x30
-
-/* Conventional codes for class-specific descriptors.  The convention is
- * defined in the USB "Common Class" Spec (3.11).  Individual class specs
- * are authoritative for their usage, not the "common class" writeup.
- */
-#define USB_DT_CS_DEVICE               (USB_TYPE_CLASS | USB_DT_DEVICE)
-#define USB_DT_CS_CONFIG               (USB_TYPE_CLASS | USB_DT_CONFIG)
-#define USB_DT_CS_STRING               (USB_TYPE_CLASS | USB_DT_STRING)
-#define USB_DT_CS_INTERFACE            (USB_TYPE_CLASS | USB_DT_INTERFACE)
-#define USB_DT_CS_ENDPOINT             (USB_TYPE_CLASS | USB_DT_ENDPOINT)
-
-/* All standard descriptors have these 2 fields at the beginning */
-struct usb_descriptor_header {
-       __u8  bLength;
-       __u8  bDescriptorType;
-} __attribute__ ((packed));
-
-
-/*-------------------------------------------------------------------------*/
-
-/* USB_DT_DEVICE: Device descriptor */
-struct usb_device_descriptor {
-       __u8  bLength;
-       __u8  bDescriptorType;
-
-       __le16 bcdUSB;
-       __u8  bDeviceClass;
-       __u8  bDeviceSubClass;
-       __u8  bDeviceProtocol;
-       __u8  bMaxPacketSize0;
-       __le16 idVendor;
-       __le16 idProduct;
-       __le16 bcdDevice;
-       __u8  iManufacturer;
-       __u8  iProduct;
-       __u8  iSerialNumber;
-       __u8  bNumConfigurations;
-} __attribute__ ((packed));
-
-#define USB_DT_DEVICE_SIZE             18
-
-
-/*
- * Device and/or Interface Class codes
- * as found in bDeviceClass or bInterfaceClass
- * and defined by www.usb.org documents
- */
-#define USB_CLASS_PER_INTERFACE                0       /* for DeviceClass */
-#define USB_CLASS_AUDIO                        1
-#define USB_CLASS_COMM                 2
-#define USB_CLASS_HID                  3
-#define USB_CLASS_PHYSICAL             5
-#define USB_CLASS_STILL_IMAGE          6
-#define USB_CLASS_PRINTER              7
-#define USB_CLASS_MASS_STORAGE         8
-#define USB_CLASS_HUB                  9
-#define USB_CLASS_CDC_DATA             0x0a
-#define USB_CLASS_CSCID                        0x0b    /* chip+ smart card */
-#define USB_CLASS_CONTENT_SEC          0x0d    /* content security */
-#define USB_CLASS_VIDEO                        0x0e
-#define USB_CLASS_WIRELESS_CONTROLLER  0xe0
-#define USB_CLASS_MISC                 0xef
-#define USB_CLASS_APP_SPEC             0xfe
-#define USB_CLASS_VENDOR_SPEC          0xff
-
-#define USB_SUBCLASS_VENDOR_SPEC       0xff
-
-/*-------------------------------------------------------------------------*/
-
-/* USB_DT_CONFIG: Configuration descriptor information.
- *
- * USB_DT_OTHER_SPEED_CONFIG is the same descriptor, except that the
- * descriptor type is different.  Highspeed-capable devices can look
- * different depending on what speed they're currently running.  Only
- * devices with a USB_DT_DEVICE_QUALIFIER have any OTHER_SPEED_CONFIG
- * descriptors.
- */
-struct usb_config_descriptor {
-       __u8  bLength;
-       __u8  bDescriptorType;
-
-       __le16 wTotalLength;
-       __u8  bNumInterfaces;
-       __u8  bConfigurationValue;
-       __u8  iConfiguration;
-       __u8  bmAttributes;
-       __u8  bMaxPower;
-} __attribute__ ((packed));
-
-#define USB_DT_CONFIG_SIZE             9
-
-/* from config descriptor bmAttributes */
-#define USB_CONFIG_ATT_ONE             (1 << 7)        /* must be set */
-#define USB_CONFIG_ATT_SELFPOWER       (1 << 6)        /* self powered */
-#define USB_CONFIG_ATT_WAKEUP          (1 << 5)        /* can wakeup */
-#define USB_CONFIG_ATT_BATTERY         (1 << 4)        /* battery powered */
-
-/*-------------------------------------------------------------------------*/
-
-/* USB_DT_STRING: String descriptor */
-struct usb_string_descriptor {
-       __u8  bLength;
-       __u8  bDescriptorType;
-
-       __le16 wData[1];                /* UTF-16LE encoded */
-} __attribute__ ((packed));
-
-/* note that "string" zero is special, it holds language codes that
- * the device supports, not Unicode characters.
- */
-
-/*-------------------------------------------------------------------------*/
-
-/* USB_DT_INTERFACE: Interface descriptor */
-struct usb_interface_descriptor {
-       __u8  bLength;
-       __u8  bDescriptorType;
-
-       __u8  bInterfaceNumber;
-       __u8  bAlternateSetting;
-       __u8  bNumEndpoints;
-       __u8  bInterfaceClass;
-       __u8  bInterfaceSubClass;
-       __u8  bInterfaceProtocol;
-       __u8  iInterface;
-} __attribute__ ((packed));
-
-#define USB_DT_INTERFACE_SIZE          9
-
-/*-------------------------------------------------------------------------*/
-
-/* USB_DT_ENDPOINT: Endpoint descriptor */
-struct usb_endpoint_descriptor {
-       __u8  bLength;
-       __u8  bDescriptorType;
-
-       __u8  bEndpointAddress;
-       __u8  bmAttributes;
-       __le16 wMaxPacketSize;
-       __u8  bInterval;
-
-       /* NOTE:  these two are _only_ in audio endpoints. */
-       /* use USB_DT_ENDPOINT*_SIZE in bLength, not sizeof. */
-       __u8  bRefresh;
-       __u8  bSynchAddress;
-} __attribute__ ((packed));
-
-#define USB_DT_ENDPOINT_SIZE           7
-#define USB_DT_ENDPOINT_AUDIO_SIZE     9       /* Audio extension */
-
-
-/*
- * Endpoints
- */
-#define USB_ENDPOINT_NUMBER_MASK       0x0f    /* in bEndpointAddress */
-#define USB_ENDPOINT_DIR_MASK          0x80
-
-#define USB_ENDPOINT_XFERTYPE_MASK     0x03    /* in bmAttributes */
-#define USB_ENDPOINT_XFER_CONTROL      0
-#define USB_ENDPOINT_XFER_ISOC         1
-#define USB_ENDPOINT_XFER_BULK         2
-#define USB_ENDPOINT_XFER_INT          3
-#define USB_ENDPOINT_MAX_ADJUSTABLE    0x80
-
-/* The USB 3.0 spec redefines bits 5:4 of bmAttributes as interrupt ep type. */
-#define USB_ENDPOINT_INTRTYPE          0x30
-#define USB_ENDPOINT_INTR_PERIODIC     (0 << 4)
-#define USB_ENDPOINT_INTR_NOTIFICATION (1 << 4)
-
-#define USB_ENDPOINT_SYNCTYPE          0x0c
-#define USB_ENDPOINT_SYNC_NONE         (0 << 2)
-#define USB_ENDPOINT_SYNC_ASYNC                (1 << 2)
-#define USB_ENDPOINT_SYNC_ADAPTIVE     (2 << 2)
-#define USB_ENDPOINT_SYNC_SYNC         (3 << 2)
-
-#define USB_ENDPOINT_USAGE_MASK                0x30
-#define USB_ENDPOINT_USAGE_DATA                0x00
-#define USB_ENDPOINT_USAGE_FEEDBACK    0x10
-#define USB_ENDPOINT_USAGE_IMPLICIT_FB 0x20    /* Implicit feedback Data endpoint */
-
-/*-------------------------------------------------------------------------*/
-
-/**
- * usb_endpoint_num - get the endpoint's number
- * @epd: endpoint to be checked
- *
- * Returns @epd's number: 0 to 15.
- */
-static inline int usb_endpoint_num(const struct usb_endpoint_descriptor *epd)
-{
-       return epd->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
-}
-
-/**
- * usb_endpoint_type - get the endpoint's transfer type
- * @epd: endpoint to be checked
- *
- * Returns one of USB_ENDPOINT_XFER_{CONTROL, ISOC, BULK, INT} according
- * to @epd's transfer type.
- */
-static inline int usb_endpoint_type(const struct usb_endpoint_descriptor *epd)
-{
-       return epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
-}
-
-/**
- * usb_endpoint_dir_in - check if the endpoint has IN direction
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint is of type IN, otherwise it returns false.
- */
-static inline int usb_endpoint_dir_in(const struct usb_endpoint_descriptor *epd)
-{
-       return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN);
-}
-
-/**
- * usb_endpoint_dir_out - check if the endpoint has OUT direction
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint is of type OUT, otherwise it returns false.
- */
-static inline int usb_endpoint_dir_out(
-                               const struct usb_endpoint_descriptor *epd)
-{
-       return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT);
-}
-
-/**
- * usb_endpoint_xfer_bulk - check if the endpoint has bulk transfer type
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint is of type bulk, otherwise it returns false.
- */
-static inline int usb_endpoint_xfer_bulk(
-                               const struct usb_endpoint_descriptor *epd)
-{
-       return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
-               USB_ENDPOINT_XFER_BULK);
-}
-
-/**
- * usb_endpoint_xfer_control - check if the endpoint has control transfer type
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint is of type control, otherwise it returns false.
- */
-static inline int usb_endpoint_xfer_control(
-                               const struct usb_endpoint_descriptor *epd)
-{
-       return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
-               USB_ENDPOINT_XFER_CONTROL);
-}
-
-/**
- * usb_endpoint_xfer_int - check if the endpoint has interrupt transfer type
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint is of type interrupt, otherwise it returns
- * false.
- */
-static inline int usb_endpoint_xfer_int(
-                               const struct usb_endpoint_descriptor *epd)
-{
-       return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
-               USB_ENDPOINT_XFER_INT);
-}
-
-/**
- * usb_endpoint_xfer_isoc - check if the endpoint has isochronous transfer type
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint is of type isochronous, otherwise it returns
- * false.
- */
-static inline int usb_endpoint_xfer_isoc(
-                               const struct usb_endpoint_descriptor *epd)
-{
-       return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
-               USB_ENDPOINT_XFER_ISOC);
-}
-
-/**
- * usb_endpoint_is_bulk_in - check if the endpoint is bulk IN
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint has bulk transfer type and IN direction,
- * otherwise it returns false.
- */
-static inline int usb_endpoint_is_bulk_in(
-                               const struct usb_endpoint_descriptor *epd)
-{
-       return usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_in(epd);
-}
-
-/**
- * usb_endpoint_is_bulk_out - check if the endpoint is bulk OUT
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint has bulk transfer type and OUT direction,
- * otherwise it returns false.
- */
-static inline int usb_endpoint_is_bulk_out(
-                               const struct usb_endpoint_descriptor *epd)
-{
-       return usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_out(epd);
-}
-
-/**
- * usb_endpoint_is_int_in - check if the endpoint is interrupt IN
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint has interrupt transfer type and IN direction,
- * otherwise it returns false.
- */
-static inline int usb_endpoint_is_int_in(
-                               const struct usb_endpoint_descriptor *epd)
-{
-       return usb_endpoint_xfer_int(epd) && usb_endpoint_dir_in(epd);
-}
-
-/**
- * usb_endpoint_is_int_out - check if the endpoint is interrupt OUT
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint has interrupt transfer type and OUT direction,
- * otherwise it returns false.
- */
-static inline int usb_endpoint_is_int_out(
-                               const struct usb_endpoint_descriptor *epd)
-{
-       return usb_endpoint_xfer_int(epd) && usb_endpoint_dir_out(epd);
-}
-
-/**
- * usb_endpoint_is_isoc_in - check if the endpoint is isochronous IN
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint has isochronous transfer type and IN direction,
- * otherwise it returns false.
- */
-static inline int usb_endpoint_is_isoc_in(
-                               const struct usb_endpoint_descriptor *epd)
-{
-       return usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_in(epd);
-}
-
-/**
- * usb_endpoint_is_isoc_out - check if the endpoint is isochronous OUT
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint has isochronous transfer type and OUT direction,
- * otherwise it returns false.
- */
-static inline int usb_endpoint_is_isoc_out(
-                               const struct usb_endpoint_descriptor *epd)
-{
-       return usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_out(epd);
-}
-
-/**
- * usb_endpoint_maxp - get endpoint's max packet size
- * @epd: endpoint to be checked
- *
- * Returns @epd's max packet
- */
-static inline int usb_endpoint_maxp(const struct usb_endpoint_descriptor *epd)
-{
-       return __le16_to_cpu(epd->wMaxPacketSize);
-}
-
-static inline int usb_endpoint_interrupt_type(
-               const struct usb_endpoint_descriptor *epd)
-{
-       return epd->bmAttributes & USB_ENDPOINT_INTRTYPE;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* USB_DT_SS_ENDPOINT_COMP: SuperSpeed Endpoint Companion descriptor */
-struct usb_ss_ep_comp_descriptor {
-       __u8  bLength;
-       __u8  bDescriptorType;
-
-       __u8  bMaxBurst;
-       __u8  bmAttributes;
-       __le16 wBytesPerInterval;
-} __attribute__ ((packed));
-
-#define USB_DT_SS_EP_COMP_SIZE         6
-
-/* Bits 4:0 of bmAttributes if this is a bulk endpoint */
-static inline int
-usb_ss_max_streams(const struct usb_ss_ep_comp_descriptor *comp)
-{
-       int             max_streams;
-
-       if (!comp)
-               return 0;
-
-       max_streams = comp->bmAttributes & 0x1f;
-
-       if (!max_streams)
-               return 0;
-
-       max_streams = 1 << max_streams;
-
-       return max_streams;
-}
-
-/* Bits 1:0 of bmAttributes if this is an isoc endpoint */
-#define USB_SS_MULT(p)                 (1 + ((p) & 0x3))
-
-/*-------------------------------------------------------------------------*/
-
-/* USB_DT_DEVICE_QUALIFIER: Device Qualifier descriptor */
-struct usb_qualifier_descriptor {
-       __u8  bLength;
-       __u8  bDescriptorType;
-
-       __le16 bcdUSB;
-       __u8  bDeviceClass;
-       __u8  bDeviceSubClass;
-       __u8  bDeviceProtocol;
-       __u8  bMaxPacketSize0;
-       __u8  bNumConfigurations;
-       __u8  bRESERVED;
-} __attribute__ ((packed));
-
-
-/*-------------------------------------------------------------------------*/
-
-/* USB_DT_OTG (from OTG 1.0a supplement) */
-struct usb_otg_descriptor {
-       __u8  bLength;
-       __u8  bDescriptorType;
-
-       __u8  bmAttributes;     /* support for HNP, SRP, etc */
-} __attribute__ ((packed));
-
-/* from usb_otg_descriptor.bmAttributes */
-#define USB_OTG_SRP            (1 << 0)
-#define USB_OTG_HNP            (1 << 1)        /* swap host/device roles */
-
-/*-------------------------------------------------------------------------*/
-
-/* USB_DT_DEBUG:  for special highspeed devices, replacing serial console */
-struct usb_debug_descriptor {
-       __u8  bLength;
-       __u8  bDescriptorType;
-
-       /* bulk endpoints with 8 byte maxpacket */
-       __u8  bDebugInEndpoint;
-       __u8  bDebugOutEndpoint;
-} __attribute__((packed));
-
-/*-------------------------------------------------------------------------*/
-
-/* USB_DT_INTERFACE_ASSOCIATION: groups interfaces */
-struct usb_interface_assoc_descriptor {
-       __u8  bLength;
-       __u8  bDescriptorType;
-
-       __u8  bFirstInterface;
-       __u8  bInterfaceCount;
-       __u8  bFunctionClass;
-       __u8  bFunctionSubClass;
-       __u8  bFunctionProtocol;
-       __u8  iFunction;
-} __attribute__ ((packed));
-
-
-/*-------------------------------------------------------------------------*/
-
-/* USB_DT_SECURITY:  group of wireless security descriptors, including
- * encryption types available for setting up a CC/association.
- */
-struct usb_security_descriptor {
-       __u8  bLength;
-       __u8  bDescriptorType;
-
-       __le16 wTotalLength;
-       __u8  bNumEncryptionTypes;
-} __attribute__((packed));
-
-/*-------------------------------------------------------------------------*/
-
-/* USB_DT_KEY:  used with {GET,SET}_SECURITY_DATA; only public keys
- * may be retrieved.
- */
-struct usb_key_descriptor {
-       __u8  bLength;
-       __u8  bDescriptorType;
-
-       __u8  tTKID[3];
-       __u8  bReserved;
-       __u8  bKeyData[0];
-} __attribute__((packed));
-
-/*-------------------------------------------------------------------------*/
-
-/* USB_DT_ENCRYPTION_TYPE:  bundled in DT_SECURITY groups */
-struct usb_encryption_descriptor {
-       __u8  bLength;
-       __u8  bDescriptorType;
-
-       __u8  bEncryptionType;
-#define        USB_ENC_TYPE_UNSECURE           0
-#define        USB_ENC_TYPE_WIRED              1       /* non-wireless mode */
-#define        USB_ENC_TYPE_CCM_1              2       /* aes128/cbc session */
-#define        USB_ENC_TYPE_RSA_1              3       /* rsa3072/sha1 auth */
-       __u8  bEncryptionValue;         /* use in SET_ENCRYPTION */
-       __u8  bAuthKeyIndex;
-} __attribute__((packed));
-
-
-/*-------------------------------------------------------------------------*/
-
-/* USB_DT_BOS:  group of device-level capabilities */
-struct usb_bos_descriptor {
-       __u8  bLength;
-       __u8  bDescriptorType;
-
-       __le16 wTotalLength;
-       __u8  bNumDeviceCaps;
-} __attribute__((packed));
-
-#define USB_DT_BOS_SIZE                5
-/*-------------------------------------------------------------------------*/
-
-/* USB_DT_DEVICE_CAPABILITY:  grouped with BOS */
-struct usb_dev_cap_header {
-       __u8  bLength;
-       __u8  bDescriptorType;
-       __u8  bDevCapabilityType;
-} __attribute__((packed));
-
-#define        USB_CAP_TYPE_WIRELESS_USB       1
-
-struct usb_wireless_cap_descriptor {   /* Ultra Wide Band */
-       __u8  bLength;
-       __u8  bDescriptorType;
-       __u8  bDevCapabilityType;
-
-       __u8  bmAttributes;
-#define        USB_WIRELESS_P2P_DRD            (1 << 1)
-#define        USB_WIRELESS_BEACON_MASK        (3 << 2)
-#define        USB_WIRELESS_BEACON_SELF        (1 << 2)
-#define        USB_WIRELESS_BEACON_DIRECTED    (2 << 2)
-#define        USB_WIRELESS_BEACON_NONE        (3 << 2)
-       __le16 wPHYRates;       /* bit rates, Mbps */
-#define        USB_WIRELESS_PHY_53             (1 << 0)        /* always set */
-#define        USB_WIRELESS_PHY_80             (1 << 1)
-#define        USB_WIRELESS_PHY_107            (1 << 2)        /* always set */
-#define        USB_WIRELESS_PHY_160            (1 << 3)
-#define        USB_WIRELESS_PHY_200            (1 << 4)        /* always set */
-#define        USB_WIRELESS_PHY_320            (1 << 5)
-#define        USB_WIRELESS_PHY_400            (1 << 6)
-#define        USB_WIRELESS_PHY_480            (1 << 7)
-       __u8  bmTFITXPowerInfo; /* TFI power levels */
-       __u8  bmFFITXPowerInfo; /* FFI power levels */
-       __le16 bmBandGroup;
-       __u8  bReserved;
-} __attribute__((packed));
-
-/* USB 2.0 Extension descriptor */
-#define        USB_CAP_TYPE_EXT                2
-
-struct usb_ext_cap_descriptor {                /* Link Power Management */
-       __u8  bLength;
-       __u8  bDescriptorType;
-       __u8  bDevCapabilityType;
-       __le32 bmAttributes;
-#define USB_LPM_SUPPORT                        (1 << 1)        /* supports LPM */
-#define USB_BESL_SUPPORT               (1 << 2)        /* supports BESL */
-#define USB_BESL_BASELINE_VALID                (1 << 3)        /* Baseline BESL valid*/
-#define USB_BESL_DEEP_VALID            (1 << 4)        /* Deep BESL valid */
-#define USB_GET_BESL_BASELINE(p)       (((p) & (0xf << 8)) >> 8)
-#define USB_GET_BESL_DEEP(p)           (((p) & (0xf << 12)) >> 12)
-} __attribute__((packed));
-
-#define USB_DT_USB_EXT_CAP_SIZE        7
-
-/*
- * SuperSpeed USB Capability descriptor: Defines the set of SuperSpeed USB
- * specific device level capabilities
- */
-#define                USB_SS_CAP_TYPE         3
-struct usb_ss_cap_descriptor {         /* Link Power Management */
-       __u8  bLength;
-       __u8  bDescriptorType;
-       __u8  bDevCapabilityType;
-       __u8  bmAttributes;
-#define USB_LTM_SUPPORT                        (1 << 1) /* supports LTM */
-       __le16 wSpeedSupported;
-#define USB_LOW_SPEED_OPERATION                (1)      /* Low speed operation */
-#define USB_FULL_SPEED_OPERATION       (1 << 1) /* Full speed operation */
-#define USB_HIGH_SPEED_OPERATION       (1 << 2) /* High speed operation */
-#define USB_5GBPS_OPERATION            (1 << 3) /* Operation at 5Gbps */
-       __u8  bFunctionalitySupport;
-       __u8  bU1devExitLat;
-       __le16 bU2DevExitLat;
-} __attribute__((packed));
-
-#define USB_DT_USB_SS_CAP_SIZE 10
-
-/*
- * Container ID Capability descriptor: Defines the instance unique ID used to
- * identify the instance across all operating modes
- */
-#define        CONTAINER_ID_TYPE       4
-struct usb_ss_container_id_descriptor {
-       __u8  bLength;
-       __u8  bDescriptorType;
-       __u8  bDevCapabilityType;
-       __u8  bReserved;
-       __u8  ContainerID[16]; /* 128-bit number */
-} __attribute__((packed));
-
-#define USB_DT_USB_SS_CONTN_ID_SIZE    20
-/*-------------------------------------------------------------------------*/
-
-/* USB_DT_WIRELESS_ENDPOINT_COMP:  companion descriptor associated with
- * each endpoint descriptor for a wireless device
- */
-struct usb_wireless_ep_comp_descriptor {
-       __u8  bLength;
-       __u8  bDescriptorType;
-
-       __u8  bMaxBurst;
-       __u8  bMaxSequence;
-       __le16 wMaxStreamDelay;
-       __le16 wOverTheAirPacketSize;
-       __u8  bOverTheAirInterval;
-       __u8  bmCompAttributes;
-#define USB_ENDPOINT_SWITCH_MASK       0x03    /* in bmCompAttributes */
-#define USB_ENDPOINT_SWITCH_NO         0
-#define USB_ENDPOINT_SWITCH_SWITCH     1
-#define USB_ENDPOINT_SWITCH_SCALE      2
-} __attribute__((packed));
-
-/*-------------------------------------------------------------------------*/
-
-/* USB_REQ_SET_HANDSHAKE is a four-way handshake used between a wireless
- * host and a device for connection set up, mutual authentication, and
- * exchanging short lived session keys.  The handshake depends on a CC.
- */
-struct usb_handshake {
-       __u8 bMessageNumber;
-       __u8 bStatus;
-       __u8 tTKID[3];
-       __u8 bReserved;
-       __u8 CDID[16];
-       __u8 nonce[16];
-       __u8 MIC[8];
-} __attribute__((packed));
-
-/*-------------------------------------------------------------------------*/
-
-/* USB_REQ_SET_CONNECTION modifies or revokes a connection context (CC).
- * A CC may also be set up using non-wireless secure channels (including
- * wired USB!), and some devices may support CCs with multiple hosts.
- */
-struct usb_connection_context {
-       __u8 CHID[16];          /* persistent host id */
-       __u8 CDID[16];          /* device id (unique w/in host context) */
-       __u8 CK[16];            /* connection key */
-} __attribute__((packed));
-
-/*-------------------------------------------------------------------------*/
+#include <uapi/linux/usb/ch9.h>
 
-/* USB 2.0 defines three speeds, here's how Linux identifies them */
-
-enum usb_device_speed {
-       USB_SPEED_UNKNOWN = 0,                  /* enumerating */
-       USB_SPEED_LOW, USB_SPEED_FULL,          /* usb 1.1 */
-       USB_SPEED_HIGH,                         /* usb 2.0 */
-       USB_SPEED_WIRELESS,                     /* wireless (usb 2.5) */
-       USB_SPEED_SUPER,                        /* usb 3.0 */
-};
-
-#ifdef __KERNEL__
 
 /**
  * usb_speed_string() - Returns human readable-name of the speed.
@@ -919,86 +43,4 @@ enum usb_device_speed {
  */
 extern const char *usb_speed_string(enum usb_device_speed speed);
 
-#endif
-
-enum usb_device_state {
-       /* NOTATTACHED isn't in the USB spec, and this state acts
-        * the same as ATTACHED ... but it's clearer this way.
-        */
-       USB_STATE_NOTATTACHED = 0,
-
-       /* chapter 9 and authentication (wireless) device states */
-       USB_STATE_ATTACHED,
-       USB_STATE_POWERED,                      /* wired */
-       USB_STATE_RECONNECTING,                 /* auth */
-       USB_STATE_UNAUTHENTICATED,              /* auth */
-       USB_STATE_DEFAULT,                      /* limited function */
-       USB_STATE_ADDRESS,
-       USB_STATE_CONFIGURED,                   /* most functions */
-
-       USB_STATE_SUSPENDED
-
-       /* NOTE:  there are actually four different SUSPENDED
-        * states, returning to POWERED, DEFAULT, ADDRESS, or
-        * CONFIGURED respectively when SOF tokens flow again.
-        * At this level there's no difference between L1 and L2
-        * suspend states.  (L2 being original USB 1.1 suspend.)
-        */
-};
-
-enum usb3_link_state {
-       USB3_LPM_U0 = 0,
-       USB3_LPM_U1,
-       USB3_LPM_U2,
-       USB3_LPM_U3
-};
-
-/*
- * A U1 timeout of 0x0 means the parent hub will reject any transitions to U1.
- * 0xff means the parent hub will accept transitions to U1, but will not
- * initiate a transition.
- *
- * A U1 timeout of 0x1 to 0x7F also causes the hub to initiate a transition to
- * U1 after that many microseconds.  Timeouts of 0x80 to 0xFE are reserved
- * values.
- *
- * A U2 timeout of 0x0 means the parent hub will reject any transitions to U2.
- * 0xff means the parent hub will accept transitions to U2, but will not
- * initiate a transition.
- *
- * A U2 timeout of 0x1 to 0xFE also causes the hub to initiate a transition to
- * U2 after N*256 microseconds.  Therefore a U2 timeout value of 0x1 means a U2
- * idle timer of 256 microseconds, 0x2 means 512 microseconds, 0xFE means
- * 65.024ms.
- */
-#define USB3_LPM_DISABLED              0x0
-#define USB3_LPM_U1_MAX_TIMEOUT                0x7F
-#define USB3_LPM_U2_MAX_TIMEOUT                0xFE
-#define USB3_LPM_DEVICE_INITIATED      0xFF
-
-struct usb_set_sel_req {
-       __u8    u1_sel;
-       __u8    u1_pel;
-       __le16  u2_sel;
-       __le16  u2_pel;
-} __attribute__ ((packed));
-
-/*
- * The Set System Exit Latency control transfer provides one byte each for
- * U1 SEL and U1 PEL, so the max exit latency is 0xFF.  U2 SEL and U2 PEL each
- * are two bytes long.
- */
-#define USB3_LPM_MAX_U1_SEL_PEL                0xFF
-#define USB3_LPM_MAX_U2_SEL_PEL                0xFFFF
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * As per USB compliance update, a device that is actively drawing
- * more than 100mA from USB must report itself as bus-powered in
- * the GetStatus(DEVICE) call.
- * http://compliance.usb.org/index.asp?UpdateFile=Electrical&Format=Standard#34
- */
-#define USB_SELF_POWER_VBUS_MAX_DRAW           100
-
 #endif /* __LINUX_USB_CH9_H */
index c9d09f8b7ff2d66579ee58700658667347ef8094..67ac74bde6d0d533bb36e12697e424ddfb69e2b6 100644 (file)
@@ -29,6 +29,8 @@
  *                     initialization.
  * @port_power_off:    set to 1 if the controller needs to be powered down
  *                     after initialization.
+ * @no_io_watchdog:    set to 1 if the controller does not need the I/O
+ *                     watchdog to run.
  *
  * These are general configuration options for the EHCI controller. All of
  * these options are activating more or less workarounds for some hardware.
@@ -41,6 +43,7 @@ struct usb_ehci_pdata {
        unsigned        big_endian_mmio:1;
        unsigned        port_power_on:1;
        unsigned        port_power_off:1;
+       unsigned        no_io_watchdog:1;
 
        /* Turn on all power and clocks */
        int (*power_on)(struct platform_device *pdev);
index fc618d8d1e92e845b00f800b86d64a9c2c040408..639ee45779fb381edb59a0ae70e1d5ffe0f90f7f 100644 (file)
@@ -1,16 +1,8 @@
 #ifndef __EZUSB_H
 #define __EZUSB_H
 
-
-extern int ezusb_writememory(struct usb_device *dev, int address,
-                            unsigned char *data, int length, __u8 bRequest);
-
 extern int ezusb_fx1_set_reset(struct usb_device *dev, unsigned char reset_bit);
-extern int ezusb_fx2_set_reset(struct usb_device *dev, unsigned char reset_bit);
-
 extern int ezusb_fx1_ihex_firmware_download(struct usb_device *dev,
                                            const char *firmware_path);
-extern int ezusb_fx2_ihex_firmware_download(struct usb_device *dev,
-                                           const char *firmware_path);
 
 #endif /* __EZUSB_H */
index a843d085136459974720cc6c9f5149406c6877c6..65d0a88dbc675c8bb7d2bfe6256183cfd8a18ec0 100644 (file)
@@ -1,171 +1,8 @@
 #ifndef __LINUX_FUNCTIONFS_H__
 #define __LINUX_FUNCTIONFS_H__ 1
 
+#include <uapi/linux/usb/functionfs.h>
 
-#include <linux/types.h>
-#include <linux/ioctl.h>
-
-#include <linux/usb/ch9.h>
-
-
-enum {
-       FUNCTIONFS_DESCRIPTORS_MAGIC = 1,
-       FUNCTIONFS_STRINGS_MAGIC     = 2
-};
-
-
-#ifndef __KERNEL__
-
-/* Descriptor of an non-audio endpoint */
-struct usb_endpoint_descriptor_no_audio {
-       __u8  bLength;
-       __u8  bDescriptorType;
-
-       __u8  bEndpointAddress;
-       __u8  bmAttributes;
-       __le16 wMaxPacketSize;
-       __u8  bInterval;
-} __attribute__((packed));
-
-
-/*
- * All numbers must be in little endian order.
- */
-
-struct usb_functionfs_descs_head {
-       __le32 magic;
-       __le32 length;
-       __le32 fs_count;
-       __le32 hs_count;
-} __attribute__((packed));
-
-/*
- * Descriptors format:
- *
- * | off | name      | type         | description                          |
- * |-----+-----------+--------------+--------------------------------------|
- * |   0 | magic     | LE32         | FUNCTIONFS_{FS,HS}_DESCRIPTORS_MAGIC |
- * |   4 | length    | LE32         | length of the whole data chunk       |
- * |   8 | fs_count  | LE32         | number of full-speed descriptors     |
- * |  12 | hs_count  | LE32         | number of high-speed descriptors     |
- * |  16 | fs_descrs | Descriptor[] | list of full-speed descriptors       |
- * |     | hs_descrs | Descriptor[] | list of high-speed descriptors       |
- *
- * descs are just valid USB descriptors and have the following format:
- *
- * | off | name            | type | description              |
- * |-----+-----------------+------+--------------------------|
- * |   0 | bLength         | U8   | length of the descriptor |
- * |   1 | bDescriptorType | U8   | descriptor type          |
- * |   2 | payload         |      | descriptor's payload     |
- */
-
-struct usb_functionfs_strings_head {
-       __le32 magic;
-       __le32 length;
-       __le32 str_count;
-       __le32 lang_count;
-} __attribute__((packed));
-
-/*
- * Strings format:
- *
- * | off | name       | type                  | description                |
- * |-----+------------+-----------------------+----------------------------|
- * |   0 | magic      | LE32                  | FUNCTIONFS_STRINGS_MAGIC   |
- * |   4 | length     | LE32                  | length of the data chunk   |
- * |   8 | str_count  | LE32                  | number of strings          |
- * |  12 | lang_count | LE32                  | number of languages        |
- * |  16 | stringtab  | StringTab[lang_count] | table of strings per lang  |
- *
- * For each language there is one stringtab entry (ie. there are lang_count
- * stringtab entires).  Each StringTab has following format:
- *
- * | off | name    | type              | description                        |
- * |-----+---------+-------------------+------------------------------------|
- * |   0 | lang    | LE16              | language code                      |
- * |   2 | strings | String[str_count] | array of strings in given language |
- *
- * For each string there is one strings entry (ie. there are str_count
- * string entries).  Each String is a NUL terminated string encoded in
- * UTF-8.
- */
-
-#endif
-
-
-/*
- * Events are delivered on the ep0 file descriptor, when the user mode driver
- * reads from this file descriptor after writing the descriptors.  Don't
- * stop polling this descriptor.
- */
-
-enum usb_functionfs_event_type {
-       FUNCTIONFS_BIND,
-       FUNCTIONFS_UNBIND,
-
-       FUNCTIONFS_ENABLE,
-       FUNCTIONFS_DISABLE,
-
-       FUNCTIONFS_SETUP,
-
-       FUNCTIONFS_SUSPEND,
-       FUNCTIONFS_RESUME
-};
-
-/* NOTE:  this structure must stay the same size and layout on
- * both 32-bit and 64-bit kernels.
- */
-struct usb_functionfs_event {
-       union {
-               /* SETUP: packet; DATA phase i/o precedes next event
-                *(setup.bmRequestType & USB_DIR_IN) flags direction */
-               struct usb_ctrlrequest  setup;
-       } __attribute__((packed)) u;
-
-       /* enum usb_functionfs_event_type */
-       __u8                            type;
-       __u8                            _pad[3];
-} __attribute__((packed));
-
-
-/* Endpoint ioctls */
-/* The same as in gadgetfs */
-
-/* IN transfers may be reported to the gadget driver as complete
- *     when the fifo is loaded, before the host reads the data;
- * OUT transfers may be reported to the host's "client" driver as
- *     complete when they're sitting in the FIFO unread.
- * THIS returns how many bytes are "unclaimed" in the endpoint fifo
- * (needed for precise fault handling, when the hardware allows it)
- */
-#define        FUNCTIONFS_FIFO_STATUS  _IO('g', 1)
-
-/* discards any unclaimed data in the fifo. */
-#define        FUNCTIONFS_FIFO_FLUSH   _IO('g', 2)
-
-/* resets endpoint halt+toggle; used to implement set_interface.
- * some hardware (like pxa2xx) can't support this.
- */
-#define        FUNCTIONFS_CLEAR_HALT   _IO('g', 3)
-
-/* Specific for functionfs */
-
-/*
- * Returns reverse mapping of an interface.  Called on EP0.  If there
- * is no such interface returns -EDOM.  If function is not active
- * returns -ENODEV.
- */
-#define        FUNCTIONFS_INTERFACE_REVMAP     _IO('g', 128)
-
-/*
- * Returns real bEndpointAddress of an endpoint.  If function is not
- * active returns -ENODEV.
- */
-#define        FUNCTIONFS_ENDPOINT_REVMAP      _IO('g', 129)
-
-
-#ifdef __KERNEL__
 
 struct ffs_data;
 struct usb_composite_dev;
@@ -197,5 +34,3 @@ static void functionfs_release_dev_callback(struct ffs_data *ffs_data)
 
 
 #endif
-
-#endif
index 74e7755168b72c3efed2c39e46a39d7eefc5f858..012f2b7eb2b6b299e21596a9e650487759815dfb 100644 (file)
@@ -25,6 +25,7 @@
  * @big_endian_desc:   BE descriptors
  * @big_endian_mmio:   BE registers
  * @no_big_frame_no:   no big endian frame_no shift
+ * @num_ports:         number of ports
  *
  * These are general configuration options for the OHCI controller. All of
  * these options are activating more or less workarounds for some hardware.
@@ -33,6 +34,7 @@ struct usb_ohci_pdata {
        unsigned        big_endian_desc:1;
        unsigned        big_endian_mmio:1;
        unsigned        no_big_frame_no:1;
+       unsigned int    num_ports;
 
        /* Turn on all power and clocks */
        int (*power_on)(struct platform_device *pdev);
index 533b1157f22e675cf858c40d6e4b4a5ed17ee5ec..25fa1a63fc2e1b4af3a41273fd4c9c7e79e8ecd2 100644 (file)
  * @name: the name of this virtqueue (mainly for debugging)
  * @vdev: the virtio device this queue was created for.
  * @priv: a pointer for the virtqueue implementation to use.
+ * @index: the zero-based ordinal number for this queue.
+ * @num_free: number of elements we expect to be able to fit.
+ *
+ * A note on @num_free: with indirect buffers, each buffer needs one
+ * element in the queue, otherwise a buffer will need one element per
+ * sg element.
  */
 struct virtqueue {
        struct list_head list;
        void (*callback)(struct virtqueue *vq);
        const char *name;
        struct virtio_device *vdev;
+       unsigned int index;
+       unsigned int num_free;
        void *priv;
 };
 
@@ -50,8 +58,6 @@ void *virtqueue_detach_unused_buf(struct virtqueue *vq);
 
 unsigned int virtqueue_get_vring_size(struct virtqueue *vq);
 
-int virtqueue_get_queue_index(struct virtqueue *vq);
-
 /**
  * virtio_device - representation of a device using virtio
  * @index: unique position on the virtio bus
index d6b4440387b70a336d9da8af35e1224a20af04ba..4195b97a3def6a84574519da4a6fe37b7e954406 100644 (file)
@@ -1,7 +1,31 @@
+/*
+ * This header is BSD licensed so anyone can use the definitions to implement
+ * compatible drivers/servers.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
 #ifndef _LINUX_VIRTIO_SCSI_H
 #define _LINUX_VIRTIO_SCSI_H
-/* This header is BSD licensed so anyone can use the definitions to implement
- * compatible drivers/servers. */
 
 #define VIRTIO_SCSI_CDB_SIZE   32
 #define VIRTIO_SCSI_SENSE_SIZE 96
index b5f8988e42837b6d703783f6f94dd6b9e4b09cba..0a996a3517edd2e652bb389ca4093d9928e7b974 100644 (file)
@@ -53,7 +53,6 @@ struct unix_sock {
        struct path             path;
        struct mutex            readlock;
        struct sock             *peer;
-       struct sock             *other;
        struct list_head        link;
        atomic_long_t           inflight;
        spinlock_t              lock;
index 6a76e0a0705eff9926c3558c3120f6cfab71eb71..42f21766c538b4bfeab6d140aaaa0fcada8e1f16 100644 (file)
 
 #define A2MP_FEAT_EXT  0x8000
 
+enum amp_mgr_state {
+       READ_LOC_AMP_INFO,
+       READ_LOC_AMP_ASSOC,
+       READ_LOC_AMP_ASSOC_FINAL,
+};
+
 struct amp_mgr {
+       struct list_head        list;
        struct l2cap_conn       *l2cap_conn;
        struct l2cap_chan       *a2mp_chan;
+       struct l2cap_chan       *bredr_chan;
        struct kref             kref;
        __u8                    ident;
        __u8                    handle;
+       enum amp_mgr_state      state;
        unsigned long           flags;
+
+       struct list_head        amp_ctrls;
+       struct mutex            amp_ctrls_lock;
 };
 
 struct a2mp_cmd {
@@ -118,9 +130,19 @@ struct a2mp_physlink_rsp {
 #define A2MP_STATUS_PHYS_LINK_EXISTS           0x05
 #define A2MP_STATUS_SECURITY_VIOLATION         0x06
 
-void amp_mgr_get(struct amp_mgr *mgr);
+extern struct list_head amp_mgr_list;
+extern struct mutex amp_mgr_list_lock;
+
+struct amp_mgr *amp_mgr_get(struct amp_mgr *mgr);
 int amp_mgr_put(struct amp_mgr *mgr);
+u8 __next_ident(struct amp_mgr *mgr);
 struct l2cap_chan *a2mp_channel_create(struct l2cap_conn *conn,
                                       struct sk_buff *skb);
+struct amp_mgr *amp_mgr_lookup_by_state(u8 state);
+void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len, void *data);
+void a2mp_discover_amp(struct l2cap_chan *chan);
+void a2mp_send_getinfo_rsp(struct hci_dev *hdev);
+void a2mp_send_getampassoc_rsp(struct hci_dev *hdev, u8 status);
+void a2mp_send_create_phy_link_req(struct hci_dev *hdev, u8 status);
 
 #endif /* __A2MP_H */
diff --git a/include/net/bluetooth/amp.h b/include/net/bluetooth/amp.h
new file mode 100644 (file)
index 0000000..2e7c79e
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+   Copyright (c) 2011,2012 Intel Corp.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License version 2 and
+   only version 2 as published by the Free Software Foundation.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+*/
+
+#ifndef __AMP_H
+#define __AMP_H
+
+struct amp_ctrl {
+       struct list_head        list;
+       struct kref             kref;
+       __u8                    id;
+       __u16                   assoc_len_so_far;
+       __u16                   assoc_rem_len;
+       __u16                   assoc_len;
+       __u8                    *assoc;
+};
+
+int amp_ctrl_put(struct amp_ctrl *ctrl);
+void amp_ctrl_get(struct amp_ctrl *ctrl);
+struct amp_ctrl *amp_ctrl_add(struct amp_mgr *mgr, u8 id);
+struct amp_ctrl *amp_ctrl_lookup(struct amp_mgr *mgr, u8 id);
+void amp_ctrl_list_flush(struct amp_mgr *mgr);
+
+struct hci_conn *phylink_add(struct hci_dev *hdev, struct amp_mgr *mgr,
+                            u8 remote_id, bool out);
+
+int phylink_gen_key(struct hci_conn *hcon, u8 *data, u8 *len, u8 *type);
+
+void amp_read_loc_info(struct hci_dev *hdev, struct amp_mgr *mgr);
+void amp_read_loc_assoc_frag(struct hci_dev *hdev, u8 phy_handle);
+void amp_read_loc_assoc(struct hci_dev *hdev, struct amp_mgr *mgr);
+void amp_read_loc_assoc_final_data(struct hci_dev *hdev,
+                                  struct hci_conn *hcon);
+void amp_create_phylink(struct hci_dev *hdev, struct amp_mgr *mgr,
+                       struct hci_conn *hcon);
+void amp_accept_phylink(struct hci_dev *hdev, struct amp_mgr *mgr,
+                       struct hci_conn *hcon);
+void amp_write_remote_assoc(struct hci_dev *hdev, u8 handle);
+void amp_write_rem_assoc_continue(struct hci_dev *hdev, u8 handle);
+
+#endif /* __AMP_H */
index ede036977ae8b6debe3ee4560f7e93905bd92f9a..2554b3f5222ae0fa32b7f6fce650fb65327a65db 100644 (file)
@@ -180,7 +180,6 @@ static inline void bacpy(bdaddr_t *dst, bdaddr_t *src)
 }
 
 void baswap(bdaddr_t *dst, bdaddr_t *src);
-char *batostr(bdaddr_t *ba);
 
 /* Common socket structures and functions */
 
index 76b2b6bdcf36a281d558925a2a7a707ca2e1dddf..6c414f4302fea70608cf8270c029c4be0f43561b 100644 (file)
@@ -33,6 +33,8 @@
 #define HCI_LINK_KEY_SIZE      16
 #define HCI_AMP_LINK_KEY_SIZE  (2 * HCI_LINK_KEY_SIZE)
 
+#define HCI_MAX_AMP_ASSOC_SIZE 672
+
 /* HCI dev events */
 #define HCI_DEV_REG                    1
 #define HCI_DEV_UNREG                  2
@@ -113,6 +115,7 @@ enum {
        HCI_SSP_ENABLED,
        HCI_HS_ENABLED,
        HCI_LE_ENABLED,
+       HCI_LE_PERIPHERAL,
        HCI_CONNECTABLE,
        HCI_DISCOVERABLE,
        HCI_LINK_SECURITY,
@@ -196,6 +199,7 @@ enum {
 #define ACL_START_NO_FLUSH     0x00
 #define ACL_CONT               0x01
 #define ACL_START              0x02
+#define ACL_COMPLETE           0x03
 #define ACL_ACTIVE_BCAST       0x04
 #define ACL_PICO_BCAST         0x08
 
@@ -205,6 +209,7 @@ enum {
 #define ESCO_LINK      0x02
 /* Low Energy links do not have defined link type. Use invented one */
 #define LE_LINK                0x80
+#define AMP_LINK       0x81
 
 /* LMP features */
 #define LMP_3SLOT      0x01
@@ -556,12 +561,46 @@ struct hci_cp_accept_phy_link {
        __u8     key[HCI_AMP_LINK_KEY_SIZE];
 } __packed;
 
-#define HCI_OP_DISCONN_PHY_LINK        0x0437
+#define HCI_OP_DISCONN_PHY_LINK                0x0437
 struct hci_cp_disconn_phy_link {
        __u8     phy_handle;
        __u8     reason;
 } __packed;
 
+struct ext_flow_spec {
+       __u8       id;
+       __u8       stype;
+       __le16     msdu;
+       __le32     sdu_itime;
+       __le32     acc_lat;
+       __le32     flush_to;
+} __packed;
+
+#define HCI_OP_CREATE_LOGICAL_LINK     0x0438
+#define HCI_OP_ACCEPT_LOGICAL_LINK     0x0439
+struct hci_cp_create_accept_logical_link {
+       __u8                  phy_handle;
+       struct ext_flow_spec  tx_flow_spec;
+       struct ext_flow_spec  rx_flow_spec;
+} __packed;
+
+#define HCI_OP_DISCONN_LOGICAL_LINK    0x043a
+struct hci_cp_disconn_logical_link {
+       __le16   log_handle;
+} __packed;
+
+#define HCI_OP_LOGICAL_LINK_CANCEL     0x043b
+struct hci_cp_logical_link_cancel {
+       __u8     phy_handle;
+       __u8     flow_spec_id;
+} __packed;
+
+struct hci_rp_logical_link_cancel {
+       __u8     status;
+       __u8     phy_handle;
+       __u8     flow_spec_id;
+} __packed;
+
 #define HCI_OP_SNIFF_MODE              0x0803
 struct hci_cp_sniff_mode {
        __le16   handle;
@@ -894,6 +933,12 @@ struct hci_rp_le_read_buffer_size {
        __u8     le_max_pkt;
 } __packed;
 
+#define HCI_OP_LE_READ_ADV_TX_POWER    0x2007
+struct hci_rp_le_read_adv_tx_power {
+       __u8    status;
+       __s8    tx_power;
+} __packed;
+
 #define HCI_OP_LE_SET_SCAN_PARAM       0x200b
 struct hci_cp_le_set_scan_param {
        __u8    type;
index e7d454609881a30d929ec8aa613390df157c8b43..6642b3c91d3386c5c3d5da26ad7d9be5b48044f1 100644 (file)
@@ -73,6 +73,7 @@ struct discovery_state {
 struct hci_conn_hash {
        struct list_head list;
        unsigned int     acl_num;
+       unsigned int     amp_num;
        unsigned int     sco_num;
        unsigned int     le_num;
 };
@@ -124,6 +125,14 @@ struct le_scan_params {
 
 #define HCI_MAX_SHORT_NAME_LENGTH      10
 
+struct amp_assoc {
+       __u16   len;
+       __u16   offset;
+       __u16   rem_len;
+       __u16   len_so_far;
+       __u8    data[HCI_MAX_AMP_ASSOC_SIZE];
+};
+
 #define NUM_REASSEMBLY 4
 struct hci_dev {
        struct list_head list;
@@ -177,6 +186,8 @@ struct hci_dev {
        __u32           amp_max_flush_to;
        __u32           amp_be_flush_to;
 
+       struct amp_assoc        loc_assoc;
+
        __u8            flow_ctl_mode;
 
        unsigned int    auto_accept_delay;
@@ -252,8 +263,6 @@ struct hci_dev {
 
        struct sk_buff_head     driver_init;
 
-       void                    *core_data;
-
        atomic_t                promisc;
 
        struct dentry           *debugfs;
@@ -269,6 +278,8 @@ struct hci_dev {
        struct work_struct      le_scan;
        struct le_scan_params   le_scan_params;
 
+       __s8                    adv_tx_power;
+
        int (*open)(struct hci_dev *hdev);
        int (*close)(struct hci_dev *hdev);
        int (*flush)(struct hci_dev *hdev);
@@ -277,6 +288,8 @@ struct hci_dev {
        int (*ioctl)(struct hci_dev *hdev, unsigned int cmd, unsigned long arg);
 };
 
+#define HCI_PHY_HANDLE(handle) (handle & 0xff)
+
 struct hci_conn {
        struct list_head list;
 
@@ -310,6 +323,7 @@ struct hci_conn {
 
        __u8            remote_cap;
        __u8            remote_auth;
+       __u8            remote_id;
        bool            flush_key;
 
        unsigned int    sent;
@@ -339,10 +353,11 @@ struct hci_conn {
 
 struct hci_chan {
        struct list_head list;
-
+       __u16 handle;
        struct hci_conn *conn;
        struct sk_buff_head data_q;
        unsigned int    sent;
+       __u8            state;
 };
 
 extern struct list_head hci_dev_list;
@@ -438,6 +453,9 @@ static inline void hci_conn_hash_add(struct hci_dev *hdev, struct hci_conn *c)
        case ACL_LINK:
                h->acl_num++;
                break;
+       case AMP_LINK:
+               h->amp_num++;
+               break;
        case LE_LINK:
                h->le_num++;
                break;
@@ -459,6 +477,9 @@ static inline void hci_conn_hash_del(struct hci_dev *hdev, struct hci_conn *c)
        case ACL_LINK:
                h->acl_num--;
                break;
+       case AMP_LINK:
+               h->amp_num--;
+               break;
        case LE_LINK:
                h->le_num--;
                break;
@@ -475,6 +496,8 @@ static inline unsigned int hci_conn_num(struct hci_dev *hdev, __u8 type)
        switch (type) {
        case ACL_LINK:
                return h->acl_num;
+       case AMP_LINK:
+               return h->amp_num;
        case LE_LINK:
                return h->le_num;
        case SCO_LINK:
@@ -556,6 +579,7 @@ void hci_conn_check_pending(struct hci_dev *hdev);
 struct hci_chan *hci_chan_create(struct hci_conn *conn);
 void hci_chan_del(struct hci_chan *chan);
 void hci_chan_list_flush(struct hci_conn *conn);
+struct hci_chan *hci_chan_lookup_handle(struct hci_dev *hdev, __u16 handle);
 
 struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst,
                             __u8 dst_type, __u8 sec_level, __u8 auth_type);
@@ -584,7 +608,10 @@ static inline void hci_conn_put(struct hci_conn *conn)
 
        if (atomic_dec_and_test(&conn->refcnt)) {
                unsigned long timeo;
-               if (conn->type == ACL_LINK || conn->type == LE_LINK) {
+
+               switch (conn->type) {
+               case ACL_LINK:
+               case LE_LINK:
                        del_timer(&conn->idle_timer);
                        if (conn->state == BT_CONNECTED) {
                                timeo = conn->disc_timeout;
@@ -593,12 +620,20 @@ static inline void hci_conn_put(struct hci_conn *conn)
                        } else {
                                timeo = msecs_to_jiffies(10);
                        }
-               } else {
+                       break;
+
+               case AMP_LINK:
+                       timeo = conn->disc_timeout;
+                       break;
+
+               default:
                        timeo = msecs_to_jiffies(10);
+                       break;
                }
+
                cancel_delayed_work(&conn->disc_work);
                queue_delayed_work(conn->hdev->workqueue,
-                                       &conn->disc_work, timeo);
+                                  &conn->disc_work, timeo);
        }
 }
 
@@ -715,18 +750,28 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
 #define SET_HCIDEV_DEV(hdev, pdev) ((hdev)->dev.parent = (pdev))
 
 /* ----- LMP capabilities ----- */
-#define lmp_rswitch_capable(dev)   ((dev)->features[0] & LMP_RSWITCH)
 #define lmp_encrypt_capable(dev)   ((dev)->features[0] & LMP_ENCRYPT)
+#define lmp_rswitch_capable(dev)   ((dev)->features[0] & LMP_RSWITCH)
+#define lmp_hold_capable(dev)      ((dev)->features[0] & LMP_HOLD)
 #define lmp_sniff_capable(dev)     ((dev)->features[0] & LMP_SNIFF)
-#define lmp_sniffsubr_capable(dev) ((dev)->features[5] & LMP_SNIFF_SUBR)
+#define lmp_park_capable(dev)      ((dev)->features[1] & LMP_PARK)
+#define lmp_inq_rssi_capable(dev)  ((dev)->features[3] & LMP_RSSI_INQ)
 #define lmp_esco_capable(dev)      ((dev)->features[3] & LMP_ESCO)
+#define lmp_bredr_capable(dev)     (!((dev)->features[4] & LMP_NO_BREDR))
+#define lmp_le_capable(dev)        ((dev)->features[4] & LMP_LE)
+#define lmp_sniffsubr_capable(dev) ((dev)->features[5] & LMP_SNIFF_SUBR)
+#define lmp_pause_enc_capable(dev) ((dev)->features[5] & LMP_PAUSE_ENC)
+#define lmp_ext_inq_capable(dev)   ((dev)->features[6] & LMP_EXT_INQ)
+#define lmp_le_br_capable(dev)     ((dev)->features[6] & LMP_SIMUL_LE_BR)
 #define lmp_ssp_capable(dev)       ((dev)->features[6] & LMP_SIMPLE_PAIR)
 #define lmp_no_flush_capable(dev)  ((dev)->features[6] & LMP_NO_FLUSH)
-#define lmp_le_capable(dev)        ((dev)->features[4] & LMP_LE)
-#define lmp_bredr_capable(dev)     (!((dev)->features[4] & LMP_NO_BREDR))
+#define lmp_lsto_capable(dev)      ((dev)->features[7] & LMP_LSTO)
+#define lmp_inq_tx_pwr_capable(dev) ((dev)->features[7] & LMP_INQ_TX_PWR)
+#define lmp_ext_feat_capable(dev)  ((dev)->features[7] & LMP_EXTFEATURES)
 
 /* ----- Extended LMP capabilities ----- */
 #define lmp_host_le_capable(dev)   ((dev)->host_features[0] & LMP_HOST_LE)
+#define lmp_host_le_br_capable(dev) ((dev)->host_features[0] & LMP_HOST_LE_BREDR)
 
 /* ----- HCI protocols ----- */
 static inline int hci_proto_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr,
@@ -789,6 +834,10 @@ static inline void hci_proto_disconn_cfm(struct hci_conn *conn, __u8 reason)
                sco_disconn_cfm(conn, reason);
                break;
 
+       /* L2CAP would be handled for BREDR chan */
+       case AMP_LINK:
+               break;
+
        default:
                BT_ERR("unknown link type %d", conn->type);
                break;
@@ -841,7 +890,7 @@ struct hci_cb {
 
 static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status)
 {
-       struct list_head *p;
+       struct hci_cb *cb;
        __u8 encrypt;
 
        hci_proto_auth_cfm(conn, status);
@@ -852,8 +901,7 @@ static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status)
        encrypt = (conn->link_mode & HCI_LM_ENCRYPT) ? 0x01 : 0x00;
 
        read_lock(&hci_cb_list_lock);
-       list_for_each(p, &hci_cb_list) {
-               struct hci_cb *cb = list_entry(p, struct hci_cb, list);
+       list_for_each_entry(cb, &hci_cb_list, list) {
                if (cb->security_cfm)
                        cb->security_cfm(conn, status, encrypt);
        }
@@ -863,7 +911,7 @@ static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status)
 static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status,
                                                                __u8 encrypt)
 {
-       struct list_head *p;
+       struct hci_cb *cb;
 
        if (conn->sec_level == BT_SECURITY_SDP)
                conn->sec_level = BT_SECURITY_LOW;
@@ -874,8 +922,7 @@ static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status,
        hci_proto_encrypt_cfm(conn, status, encrypt);
 
        read_lock(&hci_cb_list_lock);
-       list_for_each(p, &hci_cb_list) {
-               struct hci_cb *cb = list_entry(p, struct hci_cb, list);
+       list_for_each_entry(cb, &hci_cb_list, list) {
                if (cb->security_cfm)
                        cb->security_cfm(conn, status, encrypt);
        }
@@ -884,11 +931,10 @@ static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status,
 
 static inline void hci_key_change_cfm(struct hci_conn *conn, __u8 status)
 {
-       struct list_head *p;
+       struct hci_cb *cb;
 
        read_lock(&hci_cb_list_lock);
-       list_for_each(p, &hci_cb_list) {
-               struct hci_cb *cb = list_entry(p, struct hci_cb, list);
+       list_for_each_entry(cb, &hci_cb_list, list) {
                if (cb->key_change_cfm)
                        cb->key_change_cfm(conn, status);
        }
@@ -898,11 +944,10 @@ static inline void hci_key_change_cfm(struct hci_conn *conn, __u8 status)
 static inline void hci_role_switch_cfm(struct hci_conn *conn, __u8 status,
                                                                __u8 role)
 {
-       struct list_head *p;
+       struct hci_cb *cb;
 
        read_lock(&hci_cb_list_lock);
-       list_for_each(p, &hci_cb_list) {
-               struct hci_cb *cb = list_entry(p, struct hci_cb, list);
+       list_for_each_entry(cb, &hci_cb_list, list) {
                if (cb->role_switch_cfm)
                        cb->role_switch_cfm(conn, status, role);
        }
index 7ed8e356425a16dc33c5afd5e4a80eaafdd6ea64..49783e9488565a13886155c291df073cdf541ebe 100644 (file)
 /* L2CAP defaults */
 #define L2CAP_DEFAULT_MTU              672
 #define L2CAP_DEFAULT_MIN_MTU          48
-#define L2CAP_DEFAULT_FLUSH_TO         0xffff
+#define L2CAP_DEFAULT_FLUSH_TO         0xFFFF
+#define L2CAP_EFS_DEFAULT_FLUSH_TO     0xFFFFFFFF
 #define L2CAP_DEFAULT_TX_WINDOW                63
 #define L2CAP_DEFAULT_EXT_WINDOW       0x3FFF
 #define L2CAP_DEFAULT_MAX_TX           3
 #define L2CAP_DEFAULT_RETRANS_TO       2000    /* 2 seconds */
 #define L2CAP_DEFAULT_MONITOR_TO       12000   /* 12 seconds */
-#define L2CAP_DEFAULT_MAX_PDU_SIZE     1009    /* Sized for 3-DH5 packet */
+#define L2CAP_DEFAULT_MAX_PDU_SIZE     1492    /* Sized for AMP packet */
 #define L2CAP_DEFAULT_ACK_TO           200
 #define L2CAP_DEFAULT_MAX_SDU_SIZE     0xFFFF
 #define L2CAP_DEFAULT_SDU_ITIME                0xFFFFFFFF
@@ -51,6 +52,8 @@
 #define L2CAP_ENC_TIMEOUT              msecs_to_jiffies(5000)
 #define L2CAP_CONN_TIMEOUT             msecs_to_jiffies(40000)
 #define L2CAP_INFO_TIMEOUT             msecs_to_jiffies(4000)
+#define L2CAP_MOVE_TIMEOUT             msecs_to_jiffies(4000)
+#define L2CAP_MOVE_ERTX_TIMEOUT                msecs_to_jiffies(60000)
 
 #define L2CAP_A2MP_DEFAULT_MTU         670
 
@@ -433,6 +436,8 @@ struct l2cap_chan {
        struct sock *sk;
 
        struct l2cap_conn       *conn;
+       struct hci_conn         *hs_hcon;
+       struct hci_chan         *hs_hchan;
        struct kref     kref;
 
        __u8            state;
@@ -476,6 +481,11 @@ struct l2cap_chan {
        unsigned long   conn_state;
        unsigned long   flags;
 
+       __u8            local_amp_id;
+       __u8            move_id;
+       __u8            move_state;
+       __u8            move_role;
+
        __u16           next_tx_seq;
        __u16           expected_ack_seq;
        __u16           expected_tx_seq;
@@ -508,6 +518,8 @@ struct l2cap_chan {
        __u32           remote_acc_lat;
        __u32           remote_flush_to;
 
+       __u8            ctrl_id;
+
        struct delayed_work     chan_timer;
        struct delayed_work     retrans_timer;
        struct delayed_work     monitor_timer;
@@ -538,6 +550,7 @@ struct l2cap_ops {
        void                    (*state_change) (struct l2cap_chan *chan,
                                                 int state);
        void                    (*ready) (struct l2cap_chan *chan);
+       void                    (*defer) (struct l2cap_chan *chan);
        struct sk_buff          *(*alloc_skb) (struct l2cap_chan *chan,
                                               unsigned long len, int nb);
 };
@@ -640,6 +653,9 @@ enum {
 enum {
        L2CAP_RX_STATE_RECV,
        L2CAP_RX_STATE_SREJ_SENT,
+       L2CAP_RX_STATE_MOVE,
+       L2CAP_RX_STATE_WAIT_P,
+       L2CAP_RX_STATE_WAIT_F,
 };
 
 enum {
@@ -670,6 +686,25 @@ enum {
        L2CAP_EV_RECV_FRAME,
 };
 
+enum {
+       L2CAP_MOVE_ROLE_NONE,
+       L2CAP_MOVE_ROLE_INITIATOR,
+       L2CAP_MOVE_ROLE_RESPONDER,
+};
+
+enum {
+       L2CAP_MOVE_STABLE,
+       L2CAP_MOVE_WAIT_REQ,
+       L2CAP_MOVE_WAIT_RSP,
+       L2CAP_MOVE_WAIT_RSP_SUCCESS,
+       L2CAP_MOVE_WAIT_CONFIRM,
+       L2CAP_MOVE_WAIT_CONFIRM_RSP,
+       L2CAP_MOVE_WAIT_LOGICAL_COMP,
+       L2CAP_MOVE_WAIT_LOGICAL_CFM,
+       L2CAP_MOVE_WAIT_LOCAL_BUSY,
+       L2CAP_MOVE_WAIT_PREPARE,
+};
+
 void l2cap_chan_hold(struct l2cap_chan *c);
 void l2cap_chan_put(struct l2cap_chan *c);
 
@@ -745,6 +780,10 @@ static inline void l2cap_chan_no_ready(struct l2cap_chan *chan)
 {
 }
 
+static inline void l2cap_chan_no_defer(struct l2cap_chan *chan)
+{
+}
+
 extern bool disable_ertm;
 
 int l2cap_init_sockets(void);
@@ -767,6 +806,9 @@ int l2cap_chan_check_security(struct l2cap_chan *chan);
 void l2cap_chan_set_defaults(struct l2cap_chan *chan);
 int l2cap_ertm_init(struct l2cap_chan *chan);
 void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan);
+void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan);
 void l2cap_chan_del(struct l2cap_chan *chan, int err);
+void l2cap_send_conn_req(struct l2cap_chan *chan);
+void l2cap_move_start(struct l2cap_chan *chan);
 
 #endif /* __L2CAP_H */
index 1b49890822449df661d576219181b10c64d57a6c..86583ce97b1bd6c2be1a602677db0b6cf8324e9f 100644 (file)
@@ -498,6 +498,7 @@ enum station_parameters_apply_mask {
  * @plink_action: plink action to take
  * @plink_state: set the peer link state for a station
  * @ht_capa: HT capabilities of station
+ * @vht_capa: VHT capabilities of station
  * @uapsd_queues: bitmap of queues configured for uapsd. same format
  *     as the AC bitmap in the QoS info field
  * @max_sp: max Service Period. same format as the MAX_SP in the
@@ -517,6 +518,7 @@ struct station_parameters {
        u8 plink_action;
        u8 plink_state;
        struct ieee80211_ht_cap *ht_capa;
+       struct ieee80211_vht_cap *vht_capa;
        u8 uapsd_queues;
        u8 max_sp;
 };
@@ -1000,8 +1002,10 @@ struct cfg80211_ssid {
  * @n_channels: total number of channels to scan
  * @ie: optional information element(s) to add into Probe Request or %NULL
  * @ie_len: length of ie in octets
+ * @flags: bit field of flags controlling operation
  * @rates: bitmap of rates to advertise for each band
  * @wiphy: the wiphy this was for
+ * @scan_start: time (in jiffies) when the scan started
  * @wdev: the wireless device to scan for
  * @aborted: (internal) scan request was notified as aborted
  * @no_cck: used to send probe requests at non CCK rate in 2GHz band
@@ -1012,6 +1016,7 @@ struct cfg80211_scan_request {
        u32 n_channels;
        const u8 *ie;
        size_t ie_len;
+       u32 flags;
 
        u32 rates[IEEE80211_NUM_BANDS];
 
@@ -1019,6 +1024,7 @@ struct cfg80211_scan_request {
 
        /* internal */
        struct wiphy *wiphy;
+       unsigned long scan_start;
        bool aborted;
        bool no_cck;
 
@@ -1044,6 +1050,7 @@ struct cfg80211_match_set {
  * @interval: interval between each scheduled scan cycle
  * @ie: optional information element(s) to add into Probe Request or %NULL
  * @ie_len: length of ie in octets
+ * @flags: bit field of flags controlling operation
  * @match_sets: sets of parameters to be matched for a scan result
  *     entry to be considered valid and to be passed to the host
  *     (others are filtered out).
@@ -1061,6 +1068,7 @@ struct cfg80211_sched_scan_request {
        u32 interval;
        const u8 *ie;
        size_t ie_len;
+       u32 flags;
        struct cfg80211_match_set *match_sets;
        int n_match_sets;
        s32 rssi_thold;
@@ -1068,6 +1076,7 @@ struct cfg80211_sched_scan_request {
        /* internal */
        struct wiphy *wiphy;
        struct net_device *dev;
+       unsigned long scan_start;
 
        /* keep last */
        struct ieee80211_channel *channels[0];
@@ -1152,6 +1161,9 @@ const u8 *ieee80211_bss_get_ie(struct cfg80211_bss *bss, u8 ie);
  * @key_len: length of WEP key for shared key authentication
  * @key_idx: index of WEP key for shared key authentication
  * @key: WEP key for shared key authentication
+ * @sae_data: Non-IE data to use with SAE or %NULL. This starts with
+ *     Authentication transaction sequence number field.
+ * @sae_data_len: Length of sae_data buffer in octets
  */
 struct cfg80211_auth_request {
        struct cfg80211_bss *bss;
@@ -1160,6 +1172,8 @@ struct cfg80211_auth_request {
        enum nl80211_auth_type auth_type;
        const u8 *key;
        u8 key_len, key_idx;
+       const u8 *sae_data;
+       size_t sae_data_len;
 };
 
 /**
@@ -1218,6 +1232,7 @@ struct cfg80211_deauth_request {
        const u8 *ie;
        size_t ie_len;
        u16 reason_code;
+       bool local_state_change;
 };
 
 /**
index 8a2a203eb15d087c4838e80aa52e55208cbee1d5..20210d79e36aaa8dade4e1b3c706392a02e7c986 100644 (file)
@@ -47,6 +47,8 @@ struct fib6_config {
        unsigned long   fc_expires;
        struct nlattr   *fc_mx;
        int             fc_mx_len;
+       int             fc_mp_len;
+       struct nlattr   *fc_mp;
 
        struct nl_info  fc_nlinfo;
 };
@@ -99,6 +101,14 @@ struct rt6_info {
 
        struct in6_addr                 rt6i_gateway;
 
+       /* Multipath routes:
+        * siblings is a list of rt6_info that have the the same metric/weight,
+        * destination, but not the same gateway. nsiblings is just a cache
+        * to speed up lookup.
+        */
+       struct list_head                rt6i_siblings;
+       unsigned int                    rt6i_nsiblings;
+
        atomic_t                        rt6i_ref;
 
        /* These are in a separate cache line. */
index 82558c8decf86e7cf720d6b7a190455c31e60be3..71c2f9c2f5bea84bed7930668c26215f29fc96b4 100644 (file)
@@ -143,6 +143,41 @@ struct ieee80211_low_level_stats {
        unsigned int dot11RTSSuccessCount;
 };
 
+/**
+ * enum ieee80211_chanctx_change - change flag for channel context
+ * @IEEE80211_CHANCTX_CHANGE_CHANNEL_TYPE: The channel type was changed
+ * @IEEE80211_CHANCTX_CHANGE_RX_CHAINS: The number of RX chains changed
+ */
+enum ieee80211_chanctx_change {
+       IEEE80211_CHANCTX_CHANGE_CHANNEL_TYPE   = BIT(0),
+       IEEE80211_CHANCTX_CHANGE_RX_CHAINS      = BIT(1),
+};
+
+/**
+ * struct ieee80211_chanctx_conf - channel context that vifs may be tuned to
+ *
+ * This is the driver-visible part. The ieee80211_chanctx
+ * that contains it is visible in mac80211 only.
+ *
+ * @channel: the channel to tune to
+ * @channel_type: the channel (HT) type
+ * @rx_chains_static: The number of RX chains that must always be
+ *     active on the channel to receive MIMO transmissions
+ * @rx_chains_dynamic: The number of RX chains that must be enabled
+ *     after RTS/CTS handshake to receive SMPS MIMO transmissions;
+ *     this will always be >= @rx_chains_always.
+ * @drv_priv: data area for driver use, will always be aligned to
+ *     sizeof(void *), size is determined in hw information.
+ */
+struct ieee80211_chanctx_conf {
+       struct ieee80211_channel *channel;
+       enum nl80211_channel_type channel_type;
+
+       u8 rx_chains_static, rx_chains_dynamic;
+
+       u8 drv_priv[0] __attribute__((__aligned__(sizeof(void *))));
+};
+
 /**
  * enum ieee80211_bss_change - BSS change notification flags
  *
@@ -223,6 +258,7 @@ enum ieee80211_rssi_event {
  * @assoc: association status
  * @ibss_joined: indicates whether this station is part of an IBSS
  *     or not
+ * @ibss_creator: indicates if a new IBSS network is being created
  * @aid: association ID number, valid only when @assoc is true
  * @use_cts_prot: use CTS protection
  * @use_short_preamble: use 802.11b short preamble;
@@ -278,6 +314,7 @@ struct ieee80211_bss_conf {
        const u8 *bssid;
        /* association related data */
        bool assoc, ibss_joined;
+       bool ibss_creator;
        u16 aid;
        /* erp related data */
        bool use_cts_prot;
@@ -794,6 +831,8 @@ enum ieee80211_conf_flags {
  * @IEEE80211_CONF_CHANGE_RETRY_LIMITS: retry limits changed
  * @IEEE80211_CONF_CHANGE_IDLE: Idle flag changed
  * @IEEE80211_CONF_CHANGE_SMPS: Spatial multiplexing powersave mode changed
+ *     Note that this is only valid if channel contexts are not used,
+ *     otherwise each channel context has the number of chains listed.
  */
 enum ieee80211_conf_changed {
        IEEE80211_CONF_CHANGE_SMPS              = BIT(1),
@@ -859,7 +898,9 @@ enum ieee80211_smps_mode {
  *
  * @smps_mode: spatial multiplexing powersave mode; note that
  *     %IEEE80211_SMPS_STATIC is used when the device is not
- *     configured for an HT channel
+ *     configured for an HT channel.
+ *     Note that this is only valid if channel contexts are not used,
+ *     otherwise each channel context has the number of chains listed.
  */
 struct ieee80211_conf {
        u32 flags;
@@ -931,6 +972,11 @@ enum ieee80211_vif_flags {
  *     at runtime, mac80211 will never touch this field
  * @hw_queue: hardware queue for each AC
  * @cab_queue: content-after-beacon (DTIM beacon really) queue, AP mode only
+ * @chanctx_conf: The channel context this interface is assigned to, or %NULL
+ *     when it is not assigned. This pointer is RCU-protected due to the TX
+ *     path needing to access it; even though the netdev carrier will always
+ *     be off when it is %NULL there can still be races and packets could be
+ *     processed after it switches back to %NULL.
  * @drv_priv: data area for driver use, will always be aligned to
  *     sizeof(void *).
  */
@@ -943,6 +989,8 @@ struct ieee80211_vif {
        u8 cab_queue;
        u8 hw_queue[IEEE80211_NUM_ACS];
 
+       struct ieee80211_chanctx_conf __rcu *chanctx_conf;
+
        u32 driver_flags;
 
        /* must be last */
@@ -1076,6 +1124,8 @@ enum ieee80211_sta_state {
  * @aid: AID we assigned to the station if we're an AP
  * @supp_rates: Bitmap of supported rates (per band)
  * @ht_cap: HT capabilities of this STA; restricted to our own TX capabilities
+ * @vht_cap: VHT capabilities of this STA; Not restricting any capabilities
+ *     of remote STA. Taking as is.
  * @wme: indicates whether the STA supports WME. Only valid during AP-mode.
  * @drv_priv: data area for driver use, will always be aligned to
  *     sizeof(void *), size is determined in hw information.
@@ -1088,6 +1138,7 @@ struct ieee80211_sta {
        u8 addr[ETH_ALEN];
        u16 aid;
        struct ieee80211_sta_ht_cap ht_cap;
+       struct ieee80211_sta_vht_cap vht_cap;
        bool wme;
        u8 uapsd_queues;
        u8 max_sp;
@@ -1325,6 +1376,8 @@ enum ieee80211_hw_flags {
  *     within &struct ieee80211_vif.
  * @sta_data_size: size (in bytes) of the drv_priv data area
  *     within &struct ieee80211_sta.
+ * @chanctx_data_size: size (in bytes) of the drv_priv data area
+ *     within &struct ieee80211_chanctx_conf.
  *
  * @max_rates: maximum number of alternate rate retry stages the hw
  *     can handle.
@@ -1369,6 +1422,7 @@ struct ieee80211_hw {
        int channel_change_time;
        int vif_data_size;
        int sta_data_size;
+       int chanctx_data_size;
        int napi_weight;
        u16 queues;
        u16 max_listen_interval;
@@ -2317,6 +2371,16 @@ enum ieee80211_rate_control_changed {
  *     The callback will be called before each transmission and upon return
  *     mac80211 will transmit the frame right away.
  *     The callback is optional and can (should!) sleep.
+ *
+ * @add_chanctx: Notifies device driver about new channel context creation.
+ * @remove_chanctx: Notifies device driver about channel context destruction.
+ * @change_chanctx: Notifies device driver about channel context changes that
+ *     may happen when combining different virtual interfaces on the same
+ *     channel context with different settings
+ * @assign_vif_chanctx: Notifies device driver about channel context being bound
+ *     to vif. Possible use is for hw queue remapping.
+ * @unassign_vif_chanctx: Notifies device driver about channel context being
+ *     unbound from vif.
  */
 struct ieee80211_ops {
        void (*tx)(struct ieee80211_hw *hw,
@@ -2461,6 +2525,20 @@ struct ieee80211_ops {
 
        void    (*mgd_prepare_tx)(struct ieee80211_hw *hw,
                                  struct ieee80211_vif *vif);
+
+       int (*add_chanctx)(struct ieee80211_hw *hw,
+                          struct ieee80211_chanctx_conf *ctx);
+       void (*remove_chanctx)(struct ieee80211_hw *hw,
+                              struct ieee80211_chanctx_conf *ctx);
+       void (*change_chanctx)(struct ieee80211_hw *hw,
+                              struct ieee80211_chanctx_conf *ctx,
+                              u32 changed);
+       int (*assign_vif_chanctx)(struct ieee80211_hw *hw,
+                                 struct ieee80211_vif *vif,
+                                 struct ieee80211_chanctx_conf *ctx);
+       void (*unassign_vif_chanctx)(struct ieee80211_hw *hw,
+                                    struct ieee80211_vif *vif,
+                                    struct ieee80211_chanctx_conf *ctx);
 };
 
 /**
@@ -3523,6 +3601,27 @@ void ieee80211_iter_keys(struct ieee80211_hw *hw,
                                      void *data),
                         void *iter_data);
 
+/**
+ * ieee80211_iter_chan_contexts_atomic - iterate channel contexts
+ * @hw: pointre obtained from ieee80211_alloc_hw().
+ * @iter: iterator function
+ * @iter_data: data passed to iterator function
+ *
+ * Iterate all active channel contexts. This function is atomic and
+ * doesn't acquire any locks internally that might be held in other
+ * places while calling into the driver.
+ *
+ * The iterator will not find a context that's being added (during
+ * the driver callback to add it) but will find it while it's being
+ * removed.
+ */
+void ieee80211_iter_chan_contexts_atomic(
+       struct ieee80211_hw *hw,
+       void (*iter)(struct ieee80211_hw *hw,
+                    struct ieee80211_chanctx_conf *chanctx_conf,
+                    void *data),
+       void *iter_data);
+
 /**
  * ieee80211_ap_probereq_get - retrieve a Probe Request template
  * @hw: pointer obtained from ieee80211_alloc_hw().
index 6df30ed1581c5b750f13335a3fd1b1743e05159e..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1,10 +0,0 @@
-header-y += asequencer.h
-header-y += asound.h
-header-y += asound_fm.h
-header-y += emu10k1.h
-header-y += hdsp.h
-header-y += hdspm.h
-header-y += sb16_csp.h
-header-y += sfnt_info.h
-header-y += compress_params.h
-header-y += compress_offload.h
index 1505e6d5ef8241081c24c74b6218e01a37afc8d2..75935ce739c555109feeadf97347d5beb75528a0 100644 (file)
 #ifndef __SOUND_ASEQUENCER_H
 #define __SOUND_ASEQUENCER_H
 
-#ifdef __KERNEL__
 #include <linux/ioctl.h>
 #include <sound/asound.h>
-#endif
-
-/** version of the sequencer */
-#define SNDRV_SEQ_VERSION SNDRV_PROTOCOL_VERSION (1, 0, 1)
-
-/**
- * definition of sequencer event types
- */
-
-/** system messages
- * event data type = #snd_seq_result
- */
-#define SNDRV_SEQ_EVENT_SYSTEM         0
-#define SNDRV_SEQ_EVENT_RESULT         1
-
-/** note messages (channel specific)
- * event data type = #snd_seq_ev_note
- */
-#define SNDRV_SEQ_EVENT_NOTE           5
-#define SNDRV_SEQ_EVENT_NOTEON         6
-#define SNDRV_SEQ_EVENT_NOTEOFF                7
-#define SNDRV_SEQ_EVENT_KEYPRESS       8
-       
-/** control messages (channel specific)
- * event data type = #snd_seq_ev_ctrl
- */
-#define SNDRV_SEQ_EVENT_CONTROLLER     10
-#define SNDRV_SEQ_EVENT_PGMCHANGE      11
-#define SNDRV_SEQ_EVENT_CHANPRESS      12
-#define SNDRV_SEQ_EVENT_PITCHBEND      13      /**< from -8192 to 8191 */
-#define SNDRV_SEQ_EVENT_CONTROL14      14      /**< 14 bit controller value */
-#define SNDRV_SEQ_EVENT_NONREGPARAM    15      /**< 14 bit NRPN address + 14 bit unsigned value */
-#define SNDRV_SEQ_EVENT_REGPARAM       16      /**< 14 bit RPN address + 14 bit unsigned value */
-
-/** synchronisation messages
- * event data type = #snd_seq_ev_ctrl
- */
-#define SNDRV_SEQ_EVENT_SONGPOS                20      /* Song Position Pointer with LSB and MSB values */
-#define SNDRV_SEQ_EVENT_SONGSEL                21      /* Song Select with song ID number */
-#define SNDRV_SEQ_EVENT_QFRAME         22      /* midi time code quarter frame */
-#define SNDRV_SEQ_EVENT_TIMESIGN       23      /* SMF Time Signature event */
-#define SNDRV_SEQ_EVENT_KEYSIGN                24      /* SMF Key Signature event */
-               
-/** timer messages
- * event data type = snd_seq_ev_queue_control
- */
-#define SNDRV_SEQ_EVENT_START          30      /* midi Real Time Start message */
-#define SNDRV_SEQ_EVENT_CONTINUE       31      /* midi Real Time Continue message */
-#define SNDRV_SEQ_EVENT_STOP           32      /* midi Real Time Stop message */       
-#define        SNDRV_SEQ_EVENT_SETPOS_TICK     33      /* set tick queue position */
-#define SNDRV_SEQ_EVENT_SETPOS_TIME    34      /* set realtime queue position */
-#define SNDRV_SEQ_EVENT_TEMPO          35      /* (SMF) Tempo event */
-#define SNDRV_SEQ_EVENT_CLOCK          36      /* midi Real Time Clock message */
-#define SNDRV_SEQ_EVENT_TICK           37      /* midi Real Time Tick message */
-#define SNDRV_SEQ_EVENT_QUEUE_SKEW     38      /* skew queue tempo */
-
-/** others
- * event data type = none
- */
-#define SNDRV_SEQ_EVENT_TUNE_REQUEST   40      /* tune request */
-#define SNDRV_SEQ_EVENT_RESET          41      /* reset to power-on state */
-#define SNDRV_SEQ_EVENT_SENSING                42      /* "active sensing" event */
-
-/** echo back, kernel private messages
- * event data type = any type
- */
-#define SNDRV_SEQ_EVENT_ECHO           50      /* echo event */
-#define SNDRV_SEQ_EVENT_OSS            51      /* OSS raw event */
-
-/** system status messages (broadcast for subscribers)
- * event data type = snd_seq_addr
- */
-#define SNDRV_SEQ_EVENT_CLIENT_START   60      /* new client has connected */
-#define SNDRV_SEQ_EVENT_CLIENT_EXIT    61      /* client has left the system */
-#define SNDRV_SEQ_EVENT_CLIENT_CHANGE  62      /* client status/info has changed */
-#define SNDRV_SEQ_EVENT_PORT_START     63      /* new port was created */
-#define SNDRV_SEQ_EVENT_PORT_EXIT      64      /* port was deleted from system */
-#define SNDRV_SEQ_EVENT_PORT_CHANGE    65      /* port status/info has changed */
-
-/** port connection changes
- * event data type = snd_seq_connect
- */
-#define SNDRV_SEQ_EVENT_PORT_SUBSCRIBED        66      /* ports connected */
-#define SNDRV_SEQ_EVENT_PORT_UNSUBSCRIBED 67   /* ports disconnected */
-
-/* 70-89:  synthesizer events - obsoleted */
-
-/** user-defined events with fixed length
- * event data type = any
- */
-#define SNDRV_SEQ_EVENT_USR0           90
-#define SNDRV_SEQ_EVENT_USR1           91
-#define SNDRV_SEQ_EVENT_USR2           92
-#define SNDRV_SEQ_EVENT_USR3           93
-#define SNDRV_SEQ_EVENT_USR4           94
-#define SNDRV_SEQ_EVENT_USR5           95
-#define SNDRV_SEQ_EVENT_USR6           96
-#define SNDRV_SEQ_EVENT_USR7           97
-#define SNDRV_SEQ_EVENT_USR8           98
-#define SNDRV_SEQ_EVENT_USR9           99
-
-/* 100-118: instrument layer - obsoleted */
-/* 119-129: reserved */
-
-/* 130-139: variable length events
- * event data type = snd_seq_ev_ext
- * (SNDRV_SEQ_EVENT_LENGTH_VARIABLE must be set)
- */
-#define SNDRV_SEQ_EVENT_SYSEX          130     /* system exclusive data (variable length) */
-#define SNDRV_SEQ_EVENT_BOUNCE         131     /* error event */
-/* 132-134: reserved */
-#define SNDRV_SEQ_EVENT_USR_VAR0       135
-#define SNDRV_SEQ_EVENT_USR_VAR1       136
-#define SNDRV_SEQ_EVENT_USR_VAR2       137
-#define SNDRV_SEQ_EVENT_USR_VAR3       138
-#define SNDRV_SEQ_EVENT_USR_VAR4       139
-
-/* 150-151: kernel events with quote - DO NOT use in user clients */
-#define SNDRV_SEQ_EVENT_KERNEL_ERROR   150
-#define SNDRV_SEQ_EVENT_KERNEL_QUOTE   151     /* obsolete */
-
-/* 152-191: reserved */
-
-/* 192-254: hardware specific events */
-
-/* 255: special event */
-#define SNDRV_SEQ_EVENT_NONE           255
-
-
-typedef unsigned char snd_seq_event_type_t;
-
-/** event address */
-struct snd_seq_addr {
-       unsigned char client;   /**< Client number:         0..255, 255 = broadcast to all clients */
-       unsigned char port;     /**< Port within client:    0..255, 255 = broadcast to all ports */
-};
-
-/** port connection */
-struct snd_seq_connect {
-       struct snd_seq_addr sender;
-       struct snd_seq_addr dest;
-};
-
-
-#define SNDRV_SEQ_ADDRESS_UNKNOWN      253     /* unknown source */
-#define SNDRV_SEQ_ADDRESS_SUBSCRIBERS  254     /* send event to all subscribed ports */
-#define SNDRV_SEQ_ADDRESS_BROADCAST    255     /* send event to all queues/clients/ports/channels */
-#define SNDRV_SEQ_QUEUE_DIRECT         253     /* direct dispatch */
-
-       /* event mode flag - NOTE: only 8 bits available! */
-#define SNDRV_SEQ_TIME_STAMP_TICK      (0<<0) /* timestamp in clock ticks */
-#define SNDRV_SEQ_TIME_STAMP_REAL      (1<<0) /* timestamp in real time */
-#define SNDRV_SEQ_TIME_STAMP_MASK      (1<<0)
-
-#define SNDRV_SEQ_TIME_MODE_ABS                (0<<1)  /* absolute timestamp */
-#define SNDRV_SEQ_TIME_MODE_REL                (1<<1)  /* relative to current time */
-#define SNDRV_SEQ_TIME_MODE_MASK       (1<<1)
-
-#define SNDRV_SEQ_EVENT_LENGTH_FIXED   (0<<2)  /* fixed event size */
-#define SNDRV_SEQ_EVENT_LENGTH_VARIABLE        (1<<2)  /* variable event size */
-#define SNDRV_SEQ_EVENT_LENGTH_VARUSR  (2<<2)  /* variable event size - user memory space */
-#define SNDRV_SEQ_EVENT_LENGTH_MASK    (3<<2)
-
-#define SNDRV_SEQ_PRIORITY_NORMAL      (0<<4)  /* normal priority */
-#define SNDRV_SEQ_PRIORITY_HIGH                (1<<4)  /* event should be processed before others */
-#define SNDRV_SEQ_PRIORITY_MASK                (1<<4)
-
-
-       /* note event */
-struct snd_seq_ev_note {
-       unsigned char channel;
-       unsigned char note;
-       unsigned char velocity;
-       unsigned char off_velocity;     /* only for SNDRV_SEQ_EVENT_NOTE */
-       unsigned int duration;          /* only for SNDRV_SEQ_EVENT_NOTE */
-};
-
-       /* controller event */
-struct snd_seq_ev_ctrl {
-       unsigned char channel;
-       unsigned char unused1, unused2, unused3;        /* pad */
-       unsigned int param;
-       signed int value;
-};
-
-       /* generic set of bytes (12x8 bit) */
-struct snd_seq_ev_raw8 {
-       unsigned char d[12];    /* 8 bit value */
-};
-
-       /* generic set of integers (3x32 bit) */
-struct snd_seq_ev_raw32 {
-       unsigned int d[3];      /* 32 bit value */
-};
-
-       /* external stored data */
-struct snd_seq_ev_ext {
-       unsigned int len;       /* length of data */
-       void *ptr;              /* pointer to data (note: maybe 64-bit) */
-} __attribute__((packed));
-
-struct snd_seq_result {
-       int event;              /* processed event type */
-       int result;
-};
-
-
-struct snd_seq_real_time {
-       unsigned int tv_sec;    /* seconds */
-       unsigned int tv_nsec;   /* nanoseconds */
-};
-
-typedef unsigned int snd_seq_tick_time_t;      /* midi ticks */
-
-union snd_seq_timestamp {
-       snd_seq_tick_time_t tick;
-       struct snd_seq_real_time time;
-};
-
-struct snd_seq_queue_skew {
-       unsigned int value;
-       unsigned int base;
-};
-
-       /* queue timer control */
-struct snd_seq_ev_queue_control {
-       unsigned char queue;                    /* affected queue */
-       unsigned char pad[3];                   /* reserved */
-       union {
-               signed int value;               /* affected value (e.g. tempo) */
-               union snd_seq_timestamp time;   /* time */
-               unsigned int position;          /* sync position */
-               struct snd_seq_queue_skew skew;
-               unsigned int d32[2];
-               unsigned char d8[8];
-       } param;
-};
-
-       /* quoted event - inside the kernel only */
-struct snd_seq_ev_quote {
-       struct snd_seq_addr origin;             /* original sender */
-       unsigned short value;           /* optional data */
-       struct snd_seq_event *event;            /* quoted event */
-} __attribute__((packed));
-
-
-       /* sequencer event */
-struct snd_seq_event {
-       snd_seq_event_type_t type;      /* event type */
-       unsigned char flags;            /* event flags */
-       char tag;
-       
-       unsigned char queue;            /* schedule queue */
-       union snd_seq_timestamp time;   /* schedule time */
-
-
-       struct snd_seq_addr source;     /* source address */
-       struct snd_seq_addr dest;       /* destination address */
-
-       union {                         /* event data... */
-               struct snd_seq_ev_note note;
-               struct snd_seq_ev_ctrl control;
-               struct snd_seq_ev_raw8 raw8;
-               struct snd_seq_ev_raw32 raw32;
-               struct snd_seq_ev_ext ext;
-               struct snd_seq_ev_queue_control queue;
-               union snd_seq_timestamp time;
-               struct snd_seq_addr addr;
-               struct snd_seq_connect connect;
-               struct snd_seq_result result;
-               struct snd_seq_ev_quote quote;
-       } data;
-};
-
-
-/*
- * bounce event - stored as variable size data
- */
-struct snd_seq_event_bounce {
-       int err;
-       struct snd_seq_event event;
-       /* external data follows here. */
-};
-
-#ifdef __KERNEL__
+#include <uapi/sound/asequencer.h>
 
 /* helper macro */
 #define snd_seq_event_bounce_ext_data(ev) ((void*)((char *)(ev)->data.ext.ptr + sizeof(struct snd_seq_event_bounce)))
@@ -368,311 +83,4 @@ struct snd_seq_event_bounce {
 /* queue sync port */
 #define snd_seq_queue_sync_port(q)     ((q) + 16)
 
-#endif /* __KERNEL__ */
-
-       /* system information */
-struct snd_seq_system_info {
-       int queues;                     /* maximum queues count */
-       int clients;                    /* maximum clients count */
-       int ports;                      /* maximum ports per client */
-       int channels;                   /* maximum channels per port */
-       int cur_clients;                /* current clients */
-       int cur_queues;                 /* current queues */
-       char reserved[24];
-};
-
-
-       /* system running information */
-struct snd_seq_running_info {
-       unsigned char client;           /* client id */
-       unsigned char big_endian;       /* 1 = big-endian */
-       unsigned char cpu_mode;         /* 4 = 32bit, 8 = 64bit */
-       unsigned char pad;              /* reserved */
-       unsigned char reserved[12];
-};
-
-
-       /* known client numbers */
-#define SNDRV_SEQ_CLIENT_SYSTEM                0
-       /* internal client numbers */
-#define SNDRV_SEQ_CLIENT_DUMMY         14      /* midi through */
-#define SNDRV_SEQ_CLIENT_OSS           15      /* oss sequencer emulator */
-
-
-       /* client types */
-typedef int __bitwise snd_seq_client_type_t;
-#define        NO_CLIENT       ((__force snd_seq_client_type_t) 0)
-#define        USER_CLIENT     ((__force snd_seq_client_type_t) 1)
-#define        KERNEL_CLIENT   ((__force snd_seq_client_type_t) 2)
-                        
-       /* event filter flags */
-#define SNDRV_SEQ_FILTER_BROADCAST     (1<<0)  /* accept broadcast messages */
-#define SNDRV_SEQ_FILTER_MULTICAST     (1<<1)  /* accept multicast messages */
-#define SNDRV_SEQ_FILTER_BOUNCE                (1<<2)  /* accept bounce event in error */
-#define SNDRV_SEQ_FILTER_USE_EVENT     (1<<31) /* use event filter */
-
-struct snd_seq_client_info {
-       int client;                     /* client number to inquire */
-       snd_seq_client_type_t type;     /* client type */
-       char name[64];                  /* client name */
-       unsigned int filter;            /* filter flags */
-       unsigned char multicast_filter[8]; /* multicast filter bitmap */
-       unsigned char event_filter[32]; /* event filter bitmap */
-       int num_ports;                  /* RO: number of ports */
-       int event_lost;                 /* number of lost events */
-       char reserved[64];              /* for future use */
-};
-
-
-/* client pool size */
-struct snd_seq_client_pool {
-       int client;                     /* client number to inquire */
-       int output_pool;                /* outgoing (write) pool size */
-       int input_pool;                 /* incoming (read) pool size */
-       int output_room;                /* minimum free pool size for select/blocking mode */
-       int output_free;                /* unused size */
-       int input_free;                 /* unused size */
-       char reserved[64];
-};
-
-
-/* Remove events by specified criteria */
-
-#define SNDRV_SEQ_REMOVE_INPUT         (1<<0)  /* Flush input queues */
-#define SNDRV_SEQ_REMOVE_OUTPUT                (1<<1)  /* Flush output queues */
-#define SNDRV_SEQ_REMOVE_DEST          (1<<2)  /* Restrict by destination q:client:port */
-#define SNDRV_SEQ_REMOVE_DEST_CHANNEL  (1<<3)  /* Restrict by channel */
-#define SNDRV_SEQ_REMOVE_TIME_BEFORE   (1<<4)  /* Restrict to before time */
-#define SNDRV_SEQ_REMOVE_TIME_AFTER    (1<<5)  /* Restrict to time or after */
-#define SNDRV_SEQ_REMOVE_TIME_TICK     (1<<6)  /* Time is in ticks */
-#define SNDRV_SEQ_REMOVE_EVENT_TYPE    (1<<7)  /* Restrict to event type */
-#define SNDRV_SEQ_REMOVE_IGNORE_OFF    (1<<8)  /* Do not flush off events */
-#define SNDRV_SEQ_REMOVE_TAG_MATCH     (1<<9)  /* Restrict to events with given tag */
-
-struct snd_seq_remove_events {
-       unsigned int  remove_mode;      /* Flags that determine what gets removed */
-
-       union snd_seq_timestamp time;
-
-       unsigned char queue;    /* Queue for REMOVE_DEST */
-       struct snd_seq_addr dest;       /* Address for REMOVE_DEST */
-       unsigned char channel;  /* Channel for REMOVE_DEST */
-
-       int  type;      /* For REMOVE_EVENT_TYPE */
-       char  tag;      /* Tag for REMOVE_TAG */
-
-       int  reserved[10];      /* To allow for future binary compatibility */
-
-};
-
-
-       /* known port numbers */
-#define SNDRV_SEQ_PORT_SYSTEM_TIMER    0
-#define SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE 1
-
-       /* port capabilities (32 bits) */
-#define SNDRV_SEQ_PORT_CAP_READ                (1<<0)  /* readable from this port */
-#define SNDRV_SEQ_PORT_CAP_WRITE       (1<<1)  /* writable to this port */
-
-#define SNDRV_SEQ_PORT_CAP_SYNC_READ   (1<<2)
-#define SNDRV_SEQ_PORT_CAP_SYNC_WRITE  (1<<3)
-
-#define SNDRV_SEQ_PORT_CAP_DUPLEX      (1<<4)
-
-#define SNDRV_SEQ_PORT_CAP_SUBS_READ   (1<<5)  /* allow read subscription */
-#define SNDRV_SEQ_PORT_CAP_SUBS_WRITE  (1<<6)  /* allow write subscription */
-#define SNDRV_SEQ_PORT_CAP_NO_EXPORT   (1<<7)  /* routing not allowed */
-
-       /* port type */
-#define SNDRV_SEQ_PORT_TYPE_SPECIFIC   (1<<0)  /* hardware specific */
-#define SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC (1<<1)        /* generic MIDI device */
-#define SNDRV_SEQ_PORT_TYPE_MIDI_GM    (1<<2)  /* General MIDI compatible device */
-#define SNDRV_SEQ_PORT_TYPE_MIDI_GS    (1<<3)  /* GS compatible device */
-#define SNDRV_SEQ_PORT_TYPE_MIDI_XG    (1<<4)  /* XG compatible device */
-#define SNDRV_SEQ_PORT_TYPE_MIDI_MT32  (1<<5)  /* MT-32 compatible device */
-#define SNDRV_SEQ_PORT_TYPE_MIDI_GM2   (1<<6)  /* General MIDI 2 compatible device */
-
-/* other standards...*/
-#define SNDRV_SEQ_PORT_TYPE_SYNTH      (1<<10) /* Synth device (no MIDI compatible - direct wavetable) */
-#define SNDRV_SEQ_PORT_TYPE_DIRECT_SAMPLE (1<<11)      /* Sampling device (support sample download) */
-#define SNDRV_SEQ_PORT_TYPE_SAMPLE     (1<<12) /* Sampling device (sample can be downloaded at any time) */
-/*...*/
-#define SNDRV_SEQ_PORT_TYPE_HARDWARE   (1<<16) /* driver for a hardware device */
-#define SNDRV_SEQ_PORT_TYPE_SOFTWARE   (1<<17) /* implemented in software */
-#define SNDRV_SEQ_PORT_TYPE_SYNTHESIZER        (1<<18) /* generates sound */
-#define SNDRV_SEQ_PORT_TYPE_PORT       (1<<19) /* connects to other device(s) */
-#define SNDRV_SEQ_PORT_TYPE_APPLICATION        (1<<20) /* application (sequencer/editor) */
-
-/* misc. conditioning flags */
-#define SNDRV_SEQ_PORT_FLG_GIVEN_PORT  (1<<0)
-#define SNDRV_SEQ_PORT_FLG_TIMESTAMP   (1<<1)
-#define SNDRV_SEQ_PORT_FLG_TIME_REAL   (1<<2)
-
-struct snd_seq_port_info {
-       struct snd_seq_addr addr;       /* client/port numbers */
-       char name[64];                  /* port name */
-
-       unsigned int capability;        /* port capability bits */
-       unsigned int type;              /* port type bits */
-       int midi_channels;              /* channels per MIDI port */
-       int midi_voices;                /* voices per MIDI port */
-       int synth_voices;               /* voices per SYNTH port */
-
-       int read_use;                   /* R/O: subscribers for output (from this port) */
-       int write_use;                  /* R/O: subscribers for input (to this port) */
-
-       void *kernel;                   /* reserved for kernel use (must be NULL) */
-       unsigned int flags;             /* misc. conditioning */
-       unsigned char time_queue;       /* queue # for timestamping */
-       char reserved[59];              /* for future use */
-};
-
-
-/* queue flags */
-#define SNDRV_SEQ_QUEUE_FLG_SYNC       (1<<0)  /* sync enabled */
-
-/* queue information */
-struct snd_seq_queue_info {
-       int queue;              /* queue id */
-
-       /*
-        *  security settings, only owner of this queue can start/stop timer
-        *  etc. if the queue is locked for other clients
-        */
-       int owner;              /* client id for owner of the queue */
-       unsigned locked:1;      /* timing queue locked for other queues */
-       char name[64];          /* name of this queue */
-       unsigned int flags;     /* flags */
-       char reserved[60];      /* for future use */
-
-};
-
-/* queue info/status */
-struct snd_seq_queue_status {
-       int queue;                      /* queue id */
-       int events;                     /* read-only - queue size */
-       snd_seq_tick_time_t tick;       /* current tick */
-       struct snd_seq_real_time time;  /* current time */
-       int running;                    /* running state of queue */
-       int flags;                      /* various flags */
-       char reserved[64];              /* for the future */
-};
-
-
-/* queue tempo */
-struct snd_seq_queue_tempo {
-       int queue;                      /* sequencer queue */
-       unsigned int tempo;             /* current tempo, us/tick */
-       int ppq;                        /* time resolution, ticks/quarter */
-       unsigned int skew_value;        /* queue skew */
-       unsigned int skew_base;         /* queue skew base */
-       char reserved[24];              /* for the future */
-};
-
-
-/* sequencer timer sources */
-#define SNDRV_SEQ_TIMER_ALSA           0       /* ALSA timer */
-#define SNDRV_SEQ_TIMER_MIDI_CLOCK     1       /* Midi Clock (CLOCK event) */
-#define SNDRV_SEQ_TIMER_MIDI_TICK      2       /* Midi Timer Tick (TICK event) */
-
-/* queue timer info */
-struct snd_seq_queue_timer {
-       int queue;                      /* sequencer queue */
-       int type;                       /* source timer type */
-       union {
-               struct {
-                       struct snd_timer_id id; /* ALSA's timer ID */
-                       unsigned int resolution;        /* resolution in Hz */
-               } alsa;
-       } u;
-       char reserved[64];              /* for the future use */
-};
-
-
-struct snd_seq_queue_client {
-       int queue;              /* sequencer queue */
-       int client;             /* sequencer client */
-       int used;               /* queue is used with this client
-                                  (must be set for accepting events) */
-       /* per client watermarks */
-       char reserved[64];      /* for future use */
-};
-
-
-#define SNDRV_SEQ_PORT_SUBS_EXCLUSIVE  (1<<0)  /* exclusive connection */
-#define SNDRV_SEQ_PORT_SUBS_TIMESTAMP  (1<<1)
-#define SNDRV_SEQ_PORT_SUBS_TIME_REAL  (1<<2)
-
-struct snd_seq_port_subscribe {
-       struct snd_seq_addr sender;     /* sender address */
-       struct snd_seq_addr dest;       /* destination address */
-       unsigned int voices;            /* number of voices to be allocated (0 = don't care) */
-       unsigned int flags;             /* modes */
-       unsigned char queue;            /* input time-stamp queue (optional) */
-       unsigned char pad[3];           /* reserved */
-       char reserved[64];
-};
-
-/* type of query subscription */
-#define SNDRV_SEQ_QUERY_SUBS_READ      0
-#define SNDRV_SEQ_QUERY_SUBS_WRITE     1
-
-struct snd_seq_query_subs {
-       struct snd_seq_addr root;       /* client/port id to be searched */
-       int type;               /* READ or WRITE */
-       int index;              /* 0..N-1 */
-       int num_subs;           /* R/O: number of subscriptions on this port */
-       struct snd_seq_addr addr;       /* R/O: result */
-       unsigned char queue;    /* R/O: result */
-       unsigned int flags;     /* R/O: result */
-       char reserved[64];      /* for future use */
-};
-
-
-/*
- *  IOCTL commands
- */
-
-#define SNDRV_SEQ_IOCTL_PVERSION       _IOR ('S', 0x00, int)
-#define SNDRV_SEQ_IOCTL_CLIENT_ID      _IOR ('S', 0x01, int)
-#define SNDRV_SEQ_IOCTL_SYSTEM_INFO    _IOWR('S', 0x02, struct snd_seq_system_info)
-#define SNDRV_SEQ_IOCTL_RUNNING_MODE   _IOWR('S', 0x03, struct snd_seq_running_info)
-
-#define SNDRV_SEQ_IOCTL_GET_CLIENT_INFO        _IOWR('S', 0x10, struct snd_seq_client_info)
-#define SNDRV_SEQ_IOCTL_SET_CLIENT_INFO        _IOW ('S', 0x11, struct snd_seq_client_info)
-
-#define SNDRV_SEQ_IOCTL_CREATE_PORT    _IOWR('S', 0x20, struct snd_seq_port_info)
-#define SNDRV_SEQ_IOCTL_DELETE_PORT    _IOW ('S', 0x21, struct snd_seq_port_info)
-#define SNDRV_SEQ_IOCTL_GET_PORT_INFO  _IOWR('S', 0x22, struct snd_seq_port_info)
-#define SNDRV_SEQ_IOCTL_SET_PORT_INFO  _IOW ('S', 0x23, struct snd_seq_port_info)
-
-#define SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT _IOW ('S', 0x30, struct snd_seq_port_subscribe)
-#define SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT _IOW ('S', 0x31, struct snd_seq_port_subscribe)
-
-#define SNDRV_SEQ_IOCTL_CREATE_QUEUE   _IOWR('S', 0x32, struct snd_seq_queue_info)
-#define SNDRV_SEQ_IOCTL_DELETE_QUEUE   _IOW ('S', 0x33, struct snd_seq_queue_info)
-#define SNDRV_SEQ_IOCTL_GET_QUEUE_INFO _IOWR('S', 0x34, struct snd_seq_queue_info)
-#define SNDRV_SEQ_IOCTL_SET_QUEUE_INFO _IOWR('S', 0x35, struct snd_seq_queue_info)
-#define SNDRV_SEQ_IOCTL_GET_NAMED_QUEUE        _IOWR('S', 0x36, struct snd_seq_queue_info)
-#define SNDRV_SEQ_IOCTL_GET_QUEUE_STATUS _IOWR('S', 0x40, struct snd_seq_queue_status)
-#define SNDRV_SEQ_IOCTL_GET_QUEUE_TEMPO        _IOWR('S', 0x41, struct snd_seq_queue_tempo)
-#define SNDRV_SEQ_IOCTL_SET_QUEUE_TEMPO        _IOW ('S', 0x42, struct snd_seq_queue_tempo)
-#define SNDRV_SEQ_IOCTL_GET_QUEUE_OWNER        _IOWR('S', 0x43, struct snd_seq_queue_owner)
-#define SNDRV_SEQ_IOCTL_SET_QUEUE_OWNER        _IOW ('S', 0x44, struct snd_seq_queue_owner)
-#define SNDRV_SEQ_IOCTL_GET_QUEUE_TIMER        _IOWR('S', 0x45, struct snd_seq_queue_timer)
-#define SNDRV_SEQ_IOCTL_SET_QUEUE_TIMER        _IOW ('S', 0x46, struct snd_seq_queue_timer)
-/* XXX
-#define SNDRV_SEQ_IOCTL_GET_QUEUE_SYNC _IOWR('S', 0x53, struct snd_seq_queue_sync)
-#define SNDRV_SEQ_IOCTL_SET_QUEUE_SYNC _IOW ('S', 0x54, struct snd_seq_queue_sync)
-*/
-#define SNDRV_SEQ_IOCTL_GET_QUEUE_CLIENT       _IOWR('S', 0x49, struct snd_seq_queue_client)
-#define SNDRV_SEQ_IOCTL_SET_QUEUE_CLIENT       _IOW ('S', 0x4a, struct snd_seq_queue_client)
-#define SNDRV_SEQ_IOCTL_GET_CLIENT_POOL        _IOWR('S', 0x4b, struct snd_seq_client_pool)
-#define SNDRV_SEQ_IOCTL_SET_CLIENT_POOL        _IOW ('S', 0x4c, struct snd_seq_client_pool)
-#define SNDRV_SEQ_IOCTL_REMOVE_EVENTS  _IOW ('S', 0x4e, struct snd_seq_remove_events)
-#define SNDRV_SEQ_IOCTL_QUERY_SUBS     _IOWR('S', 0x4f, struct snd_seq_query_subs)
-#define SNDRV_SEQ_IOCTL_GET_SUBSCRIPTION       _IOWR('S', 0x50, struct snd_seq_port_subscribe)
-#define SNDRV_SEQ_IOCTL_QUERY_NEXT_CLIENT      _IOWR('S', 0x51, struct snd_seq_client_info)
-#define SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT        _IOWR('S', 0x52, struct snd_seq_port_info)
-
 #endif /* __SOUND_ASEQUENCER_H */
index dfe7d441748c208501d0cc3c3806ba293da9b862..c2dff5369d339d07f181ab5fd75887e976cfffb0 100644 (file)
  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  *
  */
-
 #ifndef __SOUND_ASOUND_H
 #define __SOUND_ASOUND_H
 
-#include <linux/types.h>
-
-#ifdef __KERNEL__
 #include <linux/ioctl.h>
 #include <linux/time.h>
 #include <asm/byteorder.h>
 #endif
 #endif
 
-#endif /* __KERNEL__ **/
-
-/*
- *  protocol version
- */
-
-#define SNDRV_PROTOCOL_VERSION(major, minor, subminor) (((major)<<16)|((minor)<<8)|(subminor))
-#define SNDRV_PROTOCOL_MAJOR(version) (((version)>>16)&0xffff)
-#define SNDRV_PROTOCOL_MINOR(version) (((version)>>8)&0xff)
-#define SNDRV_PROTOCOL_MICRO(version) ((version)&0xff)
-#define SNDRV_PROTOCOL_INCOMPATIBLE(kversion, uversion) \
-       (SNDRV_PROTOCOL_MAJOR(kversion) != SNDRV_PROTOCOL_MAJOR(uversion) || \
-        (SNDRV_PROTOCOL_MAJOR(kversion) == SNDRV_PROTOCOL_MAJOR(uversion) && \
-          SNDRV_PROTOCOL_MINOR(kversion) != SNDRV_PROTOCOL_MINOR(uversion)))
-
-/****************************************************************************
- *                                                                          *
- *        Digital audio interface                                          *
- *                                                                          *
- ****************************************************************************/
-
-struct snd_aes_iec958 {
-       unsigned char status[24];       /* AES/IEC958 channel status bits */
-       unsigned char subcode[147];     /* AES/IEC958 subcode bits */
-       unsigned char pad;              /* nothing */
-       unsigned char dig_subframe[4];  /* AES/IEC958 subframe bits */
-};
-
-/****************************************************************************
- *                                                                          *
- *        CEA-861 Audio InfoFrame. Used in HDMI and DisplayPort                    *
- *                                                                          *
- ****************************************************************************/
-
-struct snd_cea_861_aud_if {
-       unsigned char db1_ct_cc; /* coding type and channel count */
-       unsigned char db2_sf_ss; /* sample frequency and size */
-       unsigned char db3; /* not used, all zeros */
-       unsigned char db4_ca; /* channel allocation code */
-       unsigned char db5_dminh_lsv; /* downmix inhibit & level-shit values */
-};
-
-/****************************************************************************
- *                                                                          *
- *      Section for driver hardware dependent interface - /dev/snd/hw?      *
- *                                                                          *
- ****************************************************************************/
-
-#define SNDRV_HWDEP_VERSION            SNDRV_PROTOCOL_VERSION(1, 0, 1)
-
-enum {
-       SNDRV_HWDEP_IFACE_OPL2 = 0,
-       SNDRV_HWDEP_IFACE_OPL3,
-       SNDRV_HWDEP_IFACE_OPL4,
-       SNDRV_HWDEP_IFACE_SB16CSP,      /* Creative Signal Processor */
-       SNDRV_HWDEP_IFACE_EMU10K1,      /* FX8010 processor in EMU10K1 chip */
-       SNDRV_HWDEP_IFACE_YSS225,       /* Yamaha FX processor */
-       SNDRV_HWDEP_IFACE_ICS2115,      /* Wavetable synth */
-       SNDRV_HWDEP_IFACE_SSCAPE,       /* Ensoniq SoundScape ISA card (MC68EC000) */
-       SNDRV_HWDEP_IFACE_VX,           /* Digigram VX cards */
-       SNDRV_HWDEP_IFACE_MIXART,       /* Digigram miXart cards */
-       SNDRV_HWDEP_IFACE_USX2Y,        /* Tascam US122, US224 & US428 usb */
-       SNDRV_HWDEP_IFACE_EMUX_WAVETABLE, /* EmuX wavetable */  
-       SNDRV_HWDEP_IFACE_BLUETOOTH,    /* Bluetooth audio */
-       SNDRV_HWDEP_IFACE_USX2Y_PCM,    /* Tascam US122, US224 & US428 rawusb pcm */
-       SNDRV_HWDEP_IFACE_PCXHR,        /* Digigram PCXHR */
-       SNDRV_HWDEP_IFACE_SB_RC,        /* SB Extigy/Audigy2NX remote control */
-       SNDRV_HWDEP_IFACE_HDA,          /* HD-audio */
-       SNDRV_HWDEP_IFACE_USB_STREAM,   /* direct access to usb stream */
-
-       /* Don't forget to change the following: */
-       SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_USB_STREAM
-};
-
-struct snd_hwdep_info {
-       unsigned int device;            /* WR: device number */
-       int card;                       /* R: card number */
-       unsigned char id[64];           /* ID (user selectable) */
-       unsigned char name[80];         /* hwdep name */
-       int iface;                      /* hwdep interface */
-       unsigned char reserved[64];     /* reserved for future */
-};
-
-/* generic DSP loader */
-struct snd_hwdep_dsp_status {
-       unsigned int version;           /* R: driver-specific version */
-       unsigned char id[32];           /* R: driver-specific ID string */
-       unsigned int num_dsps;          /* R: number of DSP images to transfer */
-       unsigned int dsp_loaded;        /* R: bit flags indicating the loaded DSPs */
-       unsigned int chip_ready;        /* R: 1 = initialization finished */
-       unsigned char reserved[16];     /* reserved for future use */
-};
-
-struct snd_hwdep_dsp_image {
-       unsigned int index;             /* W: DSP index */
-       unsigned char name[64];         /* W: ID (e.g. file name) */
-       unsigned char __user *image;    /* W: binary image */
-       size_t length;                  /* W: size of image in bytes */
-       unsigned long driver_data;      /* W: driver-specific data */
-};
-
-#define SNDRV_HWDEP_IOCTL_PVERSION     _IOR ('H', 0x00, int)
-#define SNDRV_HWDEP_IOCTL_INFO         _IOR ('H', 0x01, struct snd_hwdep_info)
-#define SNDRV_HWDEP_IOCTL_DSP_STATUS   _IOR('H', 0x02, struct snd_hwdep_dsp_status)
-#define SNDRV_HWDEP_IOCTL_DSP_LOAD     _IOW('H', 0x03, struct snd_hwdep_dsp_image)
-
-/*****************************************************************************
- *                                                                           *
- *             Digital Audio (PCM) interface - /dev/snd/pcm??                *
- *                                                                           *
- *****************************************************************************/
-
-#define SNDRV_PCM_VERSION              SNDRV_PROTOCOL_VERSION(2, 0, 10)
-
-typedef unsigned long snd_pcm_uframes_t;
-typedef signed long snd_pcm_sframes_t;
-
-enum {
-       SNDRV_PCM_CLASS_GENERIC = 0,    /* standard mono or stereo device */
-       SNDRV_PCM_CLASS_MULTI,          /* multichannel device */
-       SNDRV_PCM_CLASS_MODEM,          /* software modem class */
-       SNDRV_PCM_CLASS_DIGITIZER,      /* digitizer class */
-       /* Don't forget to change the following: */
-       SNDRV_PCM_CLASS_LAST = SNDRV_PCM_CLASS_DIGITIZER,
-};
-
-enum {
-       SNDRV_PCM_SUBCLASS_GENERIC_MIX = 0, /* mono or stereo subdevices are mixed together */
-       SNDRV_PCM_SUBCLASS_MULTI_MIX,   /* multichannel subdevices are mixed together */
-       /* Don't forget to change the following: */
-       SNDRV_PCM_SUBCLASS_LAST = SNDRV_PCM_SUBCLASS_MULTI_MIX,
-};
-
-enum {
-       SNDRV_PCM_STREAM_PLAYBACK = 0,
-       SNDRV_PCM_STREAM_CAPTURE,
-       SNDRV_PCM_STREAM_LAST = SNDRV_PCM_STREAM_CAPTURE,
-};
-
-typedef int __bitwise snd_pcm_access_t;
-#define        SNDRV_PCM_ACCESS_MMAP_INTERLEAVED       ((__force snd_pcm_access_t) 0) /* interleaved mmap */
-#define        SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED    ((__force snd_pcm_access_t) 1) /* noninterleaved mmap */
-#define        SNDRV_PCM_ACCESS_MMAP_COMPLEX           ((__force snd_pcm_access_t) 2) /* complex mmap */
-#define        SNDRV_PCM_ACCESS_RW_INTERLEAVED         ((__force snd_pcm_access_t) 3) /* readi/writei */
-#define        SNDRV_PCM_ACCESS_RW_NONINTERLEAVED      ((__force snd_pcm_access_t) 4) /* readn/writen */
-#define        SNDRV_PCM_ACCESS_LAST           SNDRV_PCM_ACCESS_RW_NONINTERLEAVED
-
-typedef int __bitwise snd_pcm_format_t;
-#define        SNDRV_PCM_FORMAT_S8     ((__force snd_pcm_format_t) 0)
-#define        SNDRV_PCM_FORMAT_U8     ((__force snd_pcm_format_t) 1)
-#define        SNDRV_PCM_FORMAT_S16_LE ((__force snd_pcm_format_t) 2)
-#define        SNDRV_PCM_FORMAT_S16_BE ((__force snd_pcm_format_t) 3)
-#define        SNDRV_PCM_FORMAT_U16_LE ((__force snd_pcm_format_t) 4)
-#define        SNDRV_PCM_FORMAT_U16_BE ((__force snd_pcm_format_t) 5)
-#define        SNDRV_PCM_FORMAT_S24_LE ((__force snd_pcm_format_t) 6) /* low three bytes */
-#define        SNDRV_PCM_FORMAT_S24_BE ((__force snd_pcm_format_t) 7) /* low three bytes */
-#define        SNDRV_PCM_FORMAT_U24_LE ((__force snd_pcm_format_t) 8) /* low three bytes */
-#define        SNDRV_PCM_FORMAT_U24_BE ((__force snd_pcm_format_t) 9) /* low three bytes */
-#define        SNDRV_PCM_FORMAT_S32_LE ((__force snd_pcm_format_t) 10)
-#define        SNDRV_PCM_FORMAT_S32_BE ((__force snd_pcm_format_t) 11)
-#define        SNDRV_PCM_FORMAT_U32_LE ((__force snd_pcm_format_t) 12)
-#define        SNDRV_PCM_FORMAT_U32_BE ((__force snd_pcm_format_t) 13)
-#define        SNDRV_PCM_FORMAT_FLOAT_LE       ((__force snd_pcm_format_t) 14) /* 4-byte float, IEEE-754 32-bit, range -1.0 to 1.0 */
-#define        SNDRV_PCM_FORMAT_FLOAT_BE       ((__force snd_pcm_format_t) 15) /* 4-byte float, IEEE-754 32-bit, range -1.0 to 1.0 */
-#define        SNDRV_PCM_FORMAT_FLOAT64_LE     ((__force snd_pcm_format_t) 16) /* 8-byte float, IEEE-754 64-bit, range -1.0 to 1.0 */
-#define        SNDRV_PCM_FORMAT_FLOAT64_BE     ((__force snd_pcm_format_t) 17) /* 8-byte float, IEEE-754 64-bit, range -1.0 to 1.0 */
-#define        SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE ((__force snd_pcm_format_t) 18) /* IEC-958 subframe, Little Endian */
-#define        SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE ((__force snd_pcm_format_t) 19) /* IEC-958 subframe, Big Endian */
-#define        SNDRV_PCM_FORMAT_MU_LAW         ((__force snd_pcm_format_t) 20)
-#define        SNDRV_PCM_FORMAT_A_LAW          ((__force snd_pcm_format_t) 21)
-#define        SNDRV_PCM_FORMAT_IMA_ADPCM      ((__force snd_pcm_format_t) 22)
-#define        SNDRV_PCM_FORMAT_MPEG           ((__force snd_pcm_format_t) 23)
-#define        SNDRV_PCM_FORMAT_GSM            ((__force snd_pcm_format_t) 24)
-#define        SNDRV_PCM_FORMAT_SPECIAL        ((__force snd_pcm_format_t) 31)
-#define        SNDRV_PCM_FORMAT_S24_3LE        ((__force snd_pcm_format_t) 32) /* in three bytes */
-#define        SNDRV_PCM_FORMAT_S24_3BE        ((__force snd_pcm_format_t) 33) /* in three bytes */
-#define        SNDRV_PCM_FORMAT_U24_3LE        ((__force snd_pcm_format_t) 34) /* in three bytes */
-#define        SNDRV_PCM_FORMAT_U24_3BE        ((__force snd_pcm_format_t) 35) /* in three bytes */
-#define        SNDRV_PCM_FORMAT_S20_3LE        ((__force snd_pcm_format_t) 36) /* in three bytes */
-#define        SNDRV_PCM_FORMAT_S20_3BE        ((__force snd_pcm_format_t) 37) /* in three bytes */
-#define        SNDRV_PCM_FORMAT_U20_3LE        ((__force snd_pcm_format_t) 38) /* in three bytes */
-#define        SNDRV_PCM_FORMAT_U20_3BE        ((__force snd_pcm_format_t) 39) /* in three bytes */
-#define        SNDRV_PCM_FORMAT_S18_3LE        ((__force snd_pcm_format_t) 40) /* in three bytes */
-#define        SNDRV_PCM_FORMAT_S18_3BE        ((__force snd_pcm_format_t) 41) /* in three bytes */
-#define        SNDRV_PCM_FORMAT_U18_3LE        ((__force snd_pcm_format_t) 42) /* in three bytes */
-#define        SNDRV_PCM_FORMAT_U18_3BE        ((__force snd_pcm_format_t) 43) /* in three bytes */
-#define        SNDRV_PCM_FORMAT_G723_24        ((__force snd_pcm_format_t) 44) /* 8 samples in 3 bytes */
-#define        SNDRV_PCM_FORMAT_G723_24_1B     ((__force snd_pcm_format_t) 45) /* 1 sample in 1 byte */
-#define        SNDRV_PCM_FORMAT_G723_40        ((__force snd_pcm_format_t) 46) /* 8 Samples in 5 bytes */
-#define        SNDRV_PCM_FORMAT_G723_40_1B     ((__force snd_pcm_format_t) 47) /* 1 sample in 1 byte */
-#define        SNDRV_PCM_FORMAT_LAST           SNDRV_PCM_FORMAT_G723_40_1B
-
-#ifdef SNDRV_LITTLE_ENDIAN
-#define        SNDRV_PCM_FORMAT_S16            SNDRV_PCM_FORMAT_S16_LE
-#define        SNDRV_PCM_FORMAT_U16            SNDRV_PCM_FORMAT_U16_LE
-#define        SNDRV_PCM_FORMAT_S24            SNDRV_PCM_FORMAT_S24_LE
-#define        SNDRV_PCM_FORMAT_U24            SNDRV_PCM_FORMAT_U24_LE
-#define        SNDRV_PCM_FORMAT_S32            SNDRV_PCM_FORMAT_S32_LE
-#define        SNDRV_PCM_FORMAT_U32            SNDRV_PCM_FORMAT_U32_LE
-#define        SNDRV_PCM_FORMAT_FLOAT          SNDRV_PCM_FORMAT_FLOAT_LE
-#define        SNDRV_PCM_FORMAT_FLOAT64        SNDRV_PCM_FORMAT_FLOAT64_LE
-#define        SNDRV_PCM_FORMAT_IEC958_SUBFRAME SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE
-#endif
-#ifdef SNDRV_BIG_ENDIAN
-#define        SNDRV_PCM_FORMAT_S16            SNDRV_PCM_FORMAT_S16_BE
-#define        SNDRV_PCM_FORMAT_U16            SNDRV_PCM_FORMAT_U16_BE
-#define        SNDRV_PCM_FORMAT_S24            SNDRV_PCM_FORMAT_S24_BE
-#define        SNDRV_PCM_FORMAT_U24            SNDRV_PCM_FORMAT_U24_BE
-#define        SNDRV_PCM_FORMAT_S32            SNDRV_PCM_FORMAT_S32_BE
-#define        SNDRV_PCM_FORMAT_U32            SNDRV_PCM_FORMAT_U32_BE
-#define        SNDRV_PCM_FORMAT_FLOAT          SNDRV_PCM_FORMAT_FLOAT_BE
-#define        SNDRV_PCM_FORMAT_FLOAT64        SNDRV_PCM_FORMAT_FLOAT64_BE
-#define        SNDRV_PCM_FORMAT_IEC958_SUBFRAME SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE
-#endif
-
-typedef int __bitwise snd_pcm_subformat_t;
-#define        SNDRV_PCM_SUBFORMAT_STD         ((__force snd_pcm_subformat_t) 0)
-#define        SNDRV_PCM_SUBFORMAT_LAST        SNDRV_PCM_SUBFORMAT_STD
-
-#define SNDRV_PCM_INFO_MMAP            0x00000001      /* hardware supports mmap */
-#define SNDRV_PCM_INFO_MMAP_VALID      0x00000002      /* period data are valid during transfer */
-#define SNDRV_PCM_INFO_DOUBLE          0x00000004      /* Double buffering needed for PCM start/stop */
-#define SNDRV_PCM_INFO_BATCH           0x00000010      /* double buffering */
-#define SNDRV_PCM_INFO_INTERLEAVED     0x00000100      /* channels are interleaved */
-#define SNDRV_PCM_INFO_NONINTERLEAVED  0x00000200      /* channels are not interleaved */
-#define SNDRV_PCM_INFO_COMPLEX         0x00000400      /* complex frame organization (mmap only) */
-#define SNDRV_PCM_INFO_BLOCK_TRANSFER  0x00010000      /* hardware transfer block of samples */
-#define SNDRV_PCM_INFO_OVERRANGE       0x00020000      /* hardware supports ADC (capture) overrange detection */
-#define SNDRV_PCM_INFO_RESUME          0x00040000      /* hardware supports stream resume after suspend */
-#define SNDRV_PCM_INFO_PAUSE           0x00080000      /* pause ioctl is supported */
-#define SNDRV_PCM_INFO_HALF_DUPLEX     0x00100000      /* only half duplex */
-#define SNDRV_PCM_INFO_JOINT_DUPLEX    0x00200000      /* playback and capture stream are somewhat correlated */
-#define SNDRV_PCM_INFO_SYNC_START      0x00400000      /* pcm support some kind of sync go */
-#define SNDRV_PCM_INFO_NO_PERIOD_WAKEUP        0x00800000      /* period wakeup can be disabled */
-#define SNDRV_PCM_INFO_FIFO_IN_FRAMES  0x80000000      /* internal kernel flag - FIFO size is in frames */
-
-typedef int __bitwise snd_pcm_state_t;
-#define        SNDRV_PCM_STATE_OPEN            ((__force snd_pcm_state_t) 0) /* stream is open */
-#define        SNDRV_PCM_STATE_SETUP           ((__force snd_pcm_state_t) 1) /* stream has a setup */
-#define        SNDRV_PCM_STATE_PREPARED        ((__force snd_pcm_state_t) 2) /* stream is ready to start */
-#define        SNDRV_PCM_STATE_RUNNING         ((__force snd_pcm_state_t) 3) /* stream is running */
-#define        SNDRV_PCM_STATE_XRUN            ((__force snd_pcm_state_t) 4) /* stream reached an xrun */
-#define        SNDRV_PCM_STATE_DRAINING        ((__force snd_pcm_state_t) 5) /* stream is draining */
-#define        SNDRV_PCM_STATE_PAUSED          ((__force snd_pcm_state_t) 6) /* stream is paused */
-#define        SNDRV_PCM_STATE_SUSPENDED       ((__force snd_pcm_state_t) 7) /* hardware is suspended */
-#define        SNDRV_PCM_STATE_DISCONNECTED    ((__force snd_pcm_state_t) 8) /* hardware is disconnected */
-#define        SNDRV_PCM_STATE_LAST            SNDRV_PCM_STATE_DISCONNECTED
-
-enum {
-       SNDRV_PCM_MMAP_OFFSET_DATA = 0x00000000,
-       SNDRV_PCM_MMAP_OFFSET_STATUS = 0x80000000,
-       SNDRV_PCM_MMAP_OFFSET_CONTROL = 0x81000000,
-};
-
-union snd_pcm_sync_id {
-       unsigned char id[16];
-       unsigned short id16[8];
-       unsigned int id32[4];
-};
-
-struct snd_pcm_info {
-       unsigned int device;            /* RO/WR (control): device number */
-       unsigned int subdevice;         /* RO/WR (control): subdevice number */
-       int stream;                     /* RO/WR (control): stream direction */
-       int card;                       /* R: card number */
-       unsigned char id[64];           /* ID (user selectable) */
-       unsigned char name[80];         /* name of this device */
-       unsigned char subname[32];      /* subdevice name */
-       int dev_class;                  /* SNDRV_PCM_CLASS_* */
-       int dev_subclass;               /* SNDRV_PCM_SUBCLASS_* */
-       unsigned int subdevices_count;
-       unsigned int subdevices_avail;
-       union snd_pcm_sync_id sync;     /* hardware synchronization ID */
-       unsigned char reserved[64];     /* reserved for future... */
-};
-
-typedef int snd_pcm_hw_param_t;
-#define        SNDRV_PCM_HW_PARAM_ACCESS       0       /* Access type */
-#define        SNDRV_PCM_HW_PARAM_FORMAT       1       /* Format */
-#define        SNDRV_PCM_HW_PARAM_SUBFORMAT    2       /* Subformat */
-#define        SNDRV_PCM_HW_PARAM_FIRST_MASK   SNDRV_PCM_HW_PARAM_ACCESS
-#define        SNDRV_PCM_HW_PARAM_LAST_MASK    SNDRV_PCM_HW_PARAM_SUBFORMAT
-
-#define        SNDRV_PCM_HW_PARAM_SAMPLE_BITS  8       /* Bits per sample */
-#define        SNDRV_PCM_HW_PARAM_FRAME_BITS   9       /* Bits per frame */
-#define        SNDRV_PCM_HW_PARAM_CHANNELS     10      /* Channels */
-#define        SNDRV_PCM_HW_PARAM_RATE         11      /* Approx rate */
-#define        SNDRV_PCM_HW_PARAM_PERIOD_TIME  12      /* Approx distance between
-                                                * interrupts in us
-                                                */
-#define        SNDRV_PCM_HW_PARAM_PERIOD_SIZE  13      /* Approx frames between
-                                                * interrupts
-                                                */
-#define        SNDRV_PCM_HW_PARAM_PERIOD_BYTES 14      /* Approx bytes between
-                                                * interrupts
-                                                */
-#define        SNDRV_PCM_HW_PARAM_PERIODS      15      /* Approx interrupts per
-                                                * buffer
-                                                */
-#define        SNDRV_PCM_HW_PARAM_BUFFER_TIME  16      /* Approx duration of buffer
-                                                * in us
-                                                */
-#define        SNDRV_PCM_HW_PARAM_BUFFER_SIZE  17      /* Size of buffer in frames */
-#define        SNDRV_PCM_HW_PARAM_BUFFER_BYTES 18      /* Size of buffer in bytes */
-#define        SNDRV_PCM_HW_PARAM_TICK_TIME    19      /* Approx tick duration in us */
-#define        SNDRV_PCM_HW_PARAM_FIRST_INTERVAL       SNDRV_PCM_HW_PARAM_SAMPLE_BITS
-#define        SNDRV_PCM_HW_PARAM_LAST_INTERVAL        SNDRV_PCM_HW_PARAM_TICK_TIME
-
-#define SNDRV_PCM_HW_PARAMS_NORESAMPLE (1<<0)  /* avoid rate resampling */
-#define SNDRV_PCM_HW_PARAMS_EXPORT_BUFFER      (1<<1)  /* export buffer */
-#define SNDRV_PCM_HW_PARAMS_NO_PERIOD_WAKEUP   (1<<2)  /* disable period wakeups */
-
-struct snd_interval {
-       unsigned int min, max;
-       unsigned int openmin:1,
-                    openmax:1,
-                    integer:1,
-                    empty:1;
-};
-
-#define SNDRV_MASK_MAX 256
-
-struct snd_mask {
-       __u32 bits[(SNDRV_MASK_MAX+31)/32];
-};
-
-struct snd_pcm_hw_params {
-       unsigned int flags;
-       struct snd_mask masks[SNDRV_PCM_HW_PARAM_LAST_MASK - 
-                              SNDRV_PCM_HW_PARAM_FIRST_MASK + 1];
-       struct snd_mask mres[5];        /* reserved masks */
-       struct snd_interval intervals[SNDRV_PCM_HW_PARAM_LAST_INTERVAL -
-                                       SNDRV_PCM_HW_PARAM_FIRST_INTERVAL + 1];
-       struct snd_interval ires[9];    /* reserved intervals */
-       unsigned int rmask;             /* W: requested masks */
-       unsigned int cmask;             /* R: changed masks */
-       unsigned int info;              /* R: Info flags for returned setup */
-       unsigned int msbits;            /* R: used most significant bits */
-       unsigned int rate_num;          /* R: rate numerator */
-       unsigned int rate_den;          /* R: rate denominator */
-       snd_pcm_uframes_t fifo_size;    /* R: chip FIFO size in frames */
-       unsigned char reserved[64];     /* reserved for future */
-};
-
-enum {
-       SNDRV_PCM_TSTAMP_NONE = 0,
-       SNDRV_PCM_TSTAMP_ENABLE,
-       SNDRV_PCM_TSTAMP_LAST = SNDRV_PCM_TSTAMP_ENABLE,
-};
-
-struct snd_pcm_sw_params {
-       int tstamp_mode;                        /* timestamp mode */
-       unsigned int period_step;
-       unsigned int sleep_min;                 /* min ticks to sleep */
-       snd_pcm_uframes_t avail_min;            /* min avail frames for wakeup */
-       snd_pcm_uframes_t xfer_align;           /* obsolete: xfer size need to be a multiple */
-       snd_pcm_uframes_t start_threshold;      /* min hw_avail frames for automatic start */
-       snd_pcm_uframes_t stop_threshold;       /* min avail frames for automatic stop */
-       snd_pcm_uframes_t silence_threshold;    /* min distance from noise for silence filling */
-       snd_pcm_uframes_t silence_size;         /* silence block size */
-       snd_pcm_uframes_t boundary;             /* pointers wrap point */
-       unsigned char reserved[64];             /* reserved for future */
-};
-
-struct snd_pcm_channel_info {
-       unsigned int channel;
-       __kernel_off_t offset;          /* mmap offset */
-       unsigned int first;             /* offset to first sample in bits */
-       unsigned int step;              /* samples distance in bits */
-};
-
-struct snd_pcm_status {
-       snd_pcm_state_t state;          /* stream state */
-       struct timespec trigger_tstamp; /* time when stream was started/stopped/paused */
-       struct timespec tstamp;         /* reference timestamp */
-       snd_pcm_uframes_t appl_ptr;     /* appl ptr */
-       snd_pcm_uframes_t hw_ptr;       /* hw ptr */
-       snd_pcm_sframes_t delay;        /* current delay in frames */
-       snd_pcm_uframes_t avail;        /* number of frames available */
-       snd_pcm_uframes_t avail_max;    /* max frames available on hw since last status */
-       snd_pcm_uframes_t overrange;    /* count of ADC (capture) overrange detections from last status */
-       snd_pcm_state_t suspended_state; /* suspended stream state */
-       unsigned char reserved[60];     /* must be filled with zero */
-};
-
-struct snd_pcm_mmap_status {
-       snd_pcm_state_t state;          /* RO: state - SNDRV_PCM_STATE_XXXX */
-       int pad1;                       /* Needed for 64 bit alignment */
-       snd_pcm_uframes_t hw_ptr;       /* RO: hw ptr (0...boundary-1) */
-       struct timespec tstamp;         /* Timestamp */
-       snd_pcm_state_t suspended_state; /* RO: suspended stream state */
-};
-
-struct snd_pcm_mmap_control {
-       snd_pcm_uframes_t appl_ptr;     /* RW: appl ptr (0...boundary-1) */
-       snd_pcm_uframes_t avail_min;    /* RW: min available frames for wakeup */
-};
-
-#define SNDRV_PCM_SYNC_PTR_HWSYNC      (1<<0)  /* execute hwsync */
-#define SNDRV_PCM_SYNC_PTR_APPL                (1<<1)  /* get appl_ptr from driver (r/w op) */
-#define SNDRV_PCM_SYNC_PTR_AVAIL_MIN   (1<<2)  /* get avail_min from driver */
-
-struct snd_pcm_sync_ptr {
-       unsigned int flags;
-       union {
-               struct snd_pcm_mmap_status status;
-               unsigned char reserved[64];
-       } s;
-       union {
-               struct snd_pcm_mmap_control control;
-               unsigned char reserved[64];
-       } c;
-};
-
-struct snd_xferi {
-       snd_pcm_sframes_t result;
-       void __user *buf;
-       snd_pcm_uframes_t frames;
-};
-
-struct snd_xfern {
-       snd_pcm_sframes_t result;
-       void __user * __user *bufs;
-       snd_pcm_uframes_t frames;
-};
-
-enum {
-       SNDRV_PCM_TSTAMP_TYPE_GETTIMEOFDAY = 0, /* gettimeofday equivalent */
-       SNDRV_PCM_TSTAMP_TYPE_MONOTONIC,        /* posix_clock_monotonic equivalent */
-       SNDRV_PCM_TSTAMP_TYPE_LAST = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC,
-};
-
-/* channel positions */
-enum {
-       SNDRV_CHMAP_UNKNOWN = 0,
-       SNDRV_CHMAP_NA,         /* N/A, silent */
-       SNDRV_CHMAP_MONO,       /* mono stream */
-       /* this follows the alsa-lib mixer channel value + 3 */
-       SNDRV_CHMAP_FL,         /* front left */
-       SNDRV_CHMAP_FR,         /* front right */
-       SNDRV_CHMAP_RL,         /* rear left */
-       SNDRV_CHMAP_RR,         /* rear right */
-       SNDRV_CHMAP_FC,         /* front center */
-       SNDRV_CHMAP_LFE,        /* LFE */
-       SNDRV_CHMAP_SL,         /* side left */
-       SNDRV_CHMAP_SR,         /* side right */
-       SNDRV_CHMAP_RC,         /* rear center */
-       /* new definitions */
-       SNDRV_CHMAP_FLC,        /* front left center */
-       SNDRV_CHMAP_FRC,        /* front right center */
-       SNDRV_CHMAP_RLC,        /* rear left center */
-       SNDRV_CHMAP_RRC,        /* rear right center */
-       SNDRV_CHMAP_FLW,        /* front left wide */
-       SNDRV_CHMAP_FRW,        /* front right wide */
-       SNDRV_CHMAP_FLH,        /* front left high */
-       SNDRV_CHMAP_FCH,        /* front center high */
-       SNDRV_CHMAP_FRH,        /* front right high */
-       SNDRV_CHMAP_TC,         /* top center */
-       SNDRV_CHMAP_TFL,        /* top front left */
-       SNDRV_CHMAP_TFR,        /* top front right */
-       SNDRV_CHMAP_TFC,        /* top front center */
-       SNDRV_CHMAP_TRL,        /* top rear left */
-       SNDRV_CHMAP_TRR,        /* top rear right */
-       SNDRV_CHMAP_TRC,        /* top rear center */
-       SNDRV_CHMAP_LAST = SNDRV_CHMAP_TRC,
-};
-
-#define SNDRV_CHMAP_POSITION_MASK      0xffff
-#define SNDRV_CHMAP_PHASE_INVERSE      (0x01 << 16)
-#define SNDRV_CHMAP_DRIVER_SPEC                (0x02 << 16)
-
-#define SNDRV_PCM_IOCTL_PVERSION       _IOR('A', 0x00, int)
-#define SNDRV_PCM_IOCTL_INFO           _IOR('A', 0x01, struct snd_pcm_info)
-#define SNDRV_PCM_IOCTL_TSTAMP         _IOW('A', 0x02, int)
-#define SNDRV_PCM_IOCTL_TTSTAMP                _IOW('A', 0x03, int)
-#define SNDRV_PCM_IOCTL_HW_REFINE      _IOWR('A', 0x10, struct snd_pcm_hw_params)
-#define SNDRV_PCM_IOCTL_HW_PARAMS      _IOWR('A', 0x11, struct snd_pcm_hw_params)
-#define SNDRV_PCM_IOCTL_HW_FREE                _IO('A', 0x12)
-#define SNDRV_PCM_IOCTL_SW_PARAMS      _IOWR('A', 0x13, struct snd_pcm_sw_params)
-#define SNDRV_PCM_IOCTL_STATUS         _IOR('A', 0x20, struct snd_pcm_status)
-#define SNDRV_PCM_IOCTL_DELAY          _IOR('A', 0x21, snd_pcm_sframes_t)
-#define SNDRV_PCM_IOCTL_HWSYNC         _IO('A', 0x22)
-#define SNDRV_PCM_IOCTL_SYNC_PTR       _IOWR('A', 0x23, struct snd_pcm_sync_ptr)
-#define SNDRV_PCM_IOCTL_CHANNEL_INFO   _IOR('A', 0x32, struct snd_pcm_channel_info)
-#define SNDRV_PCM_IOCTL_PREPARE                _IO('A', 0x40)
-#define SNDRV_PCM_IOCTL_RESET          _IO('A', 0x41)
-#define SNDRV_PCM_IOCTL_START          _IO('A', 0x42)
-#define SNDRV_PCM_IOCTL_DROP           _IO('A', 0x43)
-#define SNDRV_PCM_IOCTL_DRAIN          _IO('A', 0x44)
-#define SNDRV_PCM_IOCTL_PAUSE          _IOW('A', 0x45, int)
-#define SNDRV_PCM_IOCTL_REWIND         _IOW('A', 0x46, snd_pcm_uframes_t)
-#define SNDRV_PCM_IOCTL_RESUME         _IO('A', 0x47)
-#define SNDRV_PCM_IOCTL_XRUN           _IO('A', 0x48)
-#define SNDRV_PCM_IOCTL_FORWARD                _IOW('A', 0x49, snd_pcm_uframes_t)
-#define SNDRV_PCM_IOCTL_WRITEI_FRAMES  _IOW('A', 0x50, struct snd_xferi)
-#define SNDRV_PCM_IOCTL_READI_FRAMES   _IOR('A', 0x51, struct snd_xferi)
-#define SNDRV_PCM_IOCTL_WRITEN_FRAMES  _IOW('A', 0x52, struct snd_xfern)
-#define SNDRV_PCM_IOCTL_READN_FRAMES   _IOR('A', 0x53, struct snd_xfern)
-#define SNDRV_PCM_IOCTL_LINK           _IOW('A', 0x60, int)
-#define SNDRV_PCM_IOCTL_UNLINK         _IO('A', 0x61)
-
-/*****************************************************************************
- *                                                                           *
- *                            MIDI v1.0 interface                            *
- *                                                                           *
- *****************************************************************************/
-
-/*
- *  Raw MIDI section - /dev/snd/midi??
- */
-
-#define SNDRV_RAWMIDI_VERSION          SNDRV_PROTOCOL_VERSION(2, 0, 0)
-
-enum {
-       SNDRV_RAWMIDI_STREAM_OUTPUT = 0,
-       SNDRV_RAWMIDI_STREAM_INPUT,
-       SNDRV_RAWMIDI_STREAM_LAST = SNDRV_RAWMIDI_STREAM_INPUT,
-};
-
-#define SNDRV_RAWMIDI_INFO_OUTPUT              0x00000001
-#define SNDRV_RAWMIDI_INFO_INPUT               0x00000002
-#define SNDRV_RAWMIDI_INFO_DUPLEX              0x00000004
-
-struct snd_rawmidi_info {
-       unsigned int device;            /* RO/WR (control): device number */
-       unsigned int subdevice;         /* RO/WR (control): subdevice number */
-       int stream;                     /* WR: stream */
-       int card;                       /* R: card number */
-       unsigned int flags;             /* SNDRV_RAWMIDI_INFO_XXXX */
-       unsigned char id[64];           /* ID (user selectable) */
-       unsigned char name[80];         /* name of device */
-       unsigned char subname[32];      /* name of active or selected subdevice */
-       unsigned int subdevices_count;
-       unsigned int subdevices_avail;
-       unsigned char reserved[64];     /* reserved for future use */
-};
-
-struct snd_rawmidi_params {
-       int stream;
-       size_t buffer_size;             /* queue size in bytes */
-       size_t avail_min;               /* minimum avail bytes for wakeup */
-       unsigned int no_active_sensing: 1; /* do not send active sensing byte in close() */
-       unsigned char reserved[16];     /* reserved for future use */
-};
-
-struct snd_rawmidi_status {
-       int stream;
-       struct timespec tstamp;         /* Timestamp */
-       size_t avail;                   /* available bytes */
-       size_t xruns;                   /* count of overruns since last status (in bytes) */
-       unsigned char reserved[16];     /* reserved for future use */
-};
-
-#define SNDRV_RAWMIDI_IOCTL_PVERSION   _IOR('W', 0x00, int)
-#define SNDRV_RAWMIDI_IOCTL_INFO       _IOR('W', 0x01, struct snd_rawmidi_info)
-#define SNDRV_RAWMIDI_IOCTL_PARAMS     _IOWR('W', 0x10, struct snd_rawmidi_params)
-#define SNDRV_RAWMIDI_IOCTL_STATUS     _IOWR('W', 0x20, struct snd_rawmidi_status)
-#define SNDRV_RAWMIDI_IOCTL_DROP       _IOW('W', 0x30, int)
-#define SNDRV_RAWMIDI_IOCTL_DRAIN      _IOW('W', 0x31, int)
-
-/*
- *  Timer section - /dev/snd/timer
- */
-
-#define SNDRV_TIMER_VERSION            SNDRV_PROTOCOL_VERSION(2, 0, 6)
-
-enum {
-       SNDRV_TIMER_CLASS_NONE = -1,
-       SNDRV_TIMER_CLASS_SLAVE = 0,
-       SNDRV_TIMER_CLASS_GLOBAL,
-       SNDRV_TIMER_CLASS_CARD,
-       SNDRV_TIMER_CLASS_PCM,
-       SNDRV_TIMER_CLASS_LAST = SNDRV_TIMER_CLASS_PCM,
-};
-
-/* slave timer classes */
-enum {
-       SNDRV_TIMER_SCLASS_NONE = 0,
-       SNDRV_TIMER_SCLASS_APPLICATION,
-       SNDRV_TIMER_SCLASS_SEQUENCER,           /* alias */
-       SNDRV_TIMER_SCLASS_OSS_SEQUENCER,       /* alias */
-       SNDRV_TIMER_SCLASS_LAST = SNDRV_TIMER_SCLASS_OSS_SEQUENCER,
-};
-
-/* global timers (device member) */
-#define SNDRV_TIMER_GLOBAL_SYSTEM      0
-#define SNDRV_TIMER_GLOBAL_RTC         1
-#define SNDRV_TIMER_GLOBAL_HPET                2
-#define SNDRV_TIMER_GLOBAL_HRTIMER     3
-
-/* info flags */
-#define SNDRV_TIMER_FLG_SLAVE          (1<<0)  /* cannot be controlled */
-
-struct snd_timer_id {
-       int dev_class;
-       int dev_sclass;
-       int card;
-       int device;
-       int subdevice;
-};
-
-struct snd_timer_ginfo {
-       struct snd_timer_id tid;        /* requested timer ID */
-       unsigned int flags;             /* timer flags - SNDRV_TIMER_FLG_* */
-       int card;                       /* card number */
-       unsigned char id[64];           /* timer identification */
-       unsigned char name[80];         /* timer name */
-       unsigned long reserved0;        /* reserved for future use */
-       unsigned long resolution;       /* average period resolution in ns */
-       unsigned long resolution_min;   /* minimal period resolution in ns */
-       unsigned long resolution_max;   /* maximal period resolution in ns */
-       unsigned int clients;           /* active timer clients */
-       unsigned char reserved[32];
-};
-
-struct snd_timer_gparams {
-       struct snd_timer_id tid;        /* requested timer ID */
-       unsigned long period_num;       /* requested precise period duration (in seconds) - numerator */
-       unsigned long period_den;       /* requested precise period duration (in seconds) - denominator */
-       unsigned char reserved[32];
-};
-
-struct snd_timer_gstatus {
-       struct snd_timer_id tid;        /* requested timer ID */
-       unsigned long resolution;       /* current period resolution in ns */
-       unsigned long resolution_num;   /* precise current period resolution (in seconds) - numerator */
-       unsigned long resolution_den;   /* precise current period resolution (in seconds) - denominator */
-       unsigned char reserved[32];
-};
-
-struct snd_timer_select {
-       struct snd_timer_id id; /* bind to timer ID */
-       unsigned char reserved[32];     /* reserved */
-};
-
-struct snd_timer_info {
-       unsigned int flags;             /* timer flags - SNDRV_TIMER_FLG_* */
-       int card;                       /* card number */
-       unsigned char id[64];           /* timer identificator */
-       unsigned char name[80];         /* timer name */
-       unsigned long reserved0;        /* reserved for future use */
-       unsigned long resolution;       /* average period resolution in ns */
-       unsigned char reserved[64];     /* reserved */
-};
-
-#define SNDRV_TIMER_PSFLG_AUTO         (1<<0)  /* auto start, otherwise one-shot */
-#define SNDRV_TIMER_PSFLG_EXCLUSIVE    (1<<1)  /* exclusive use, precise start/stop/pause/continue */
-#define SNDRV_TIMER_PSFLG_EARLY_EVENT  (1<<2)  /* write early event to the poll queue */
-
-struct snd_timer_params {
-       unsigned int flags;             /* flags - SNDRV_MIXER_PSFLG_* */
-       unsigned int ticks;             /* requested resolution in ticks */
-       unsigned int queue_size;        /* total size of queue (32-1024) */
-       unsigned int reserved0;         /* reserved, was: failure locations */
-       unsigned int filter;            /* event filter (bitmask of SNDRV_TIMER_EVENT_*) */
-       unsigned char reserved[60];     /* reserved */
-};
-
-struct snd_timer_status {
-       struct timespec tstamp;         /* Timestamp - last update */
-       unsigned int resolution;        /* current period resolution in ns */
-       unsigned int lost;              /* counter of master tick lost */
-       unsigned int overrun;           /* count of read queue overruns */
-       unsigned int queue;             /* used queue size */
-       unsigned char reserved[64];     /* reserved */
-};
-
-#define SNDRV_TIMER_IOCTL_PVERSION     _IOR('T', 0x00, int)
-#define SNDRV_TIMER_IOCTL_NEXT_DEVICE  _IOWR('T', 0x01, struct snd_timer_id)
-#define SNDRV_TIMER_IOCTL_TREAD                _IOW('T', 0x02, int)
-#define SNDRV_TIMER_IOCTL_GINFO                _IOWR('T', 0x03, struct snd_timer_ginfo)
-#define SNDRV_TIMER_IOCTL_GPARAMS      _IOW('T', 0x04, struct snd_timer_gparams)
-#define SNDRV_TIMER_IOCTL_GSTATUS      _IOWR('T', 0x05, struct snd_timer_gstatus)
-#define SNDRV_TIMER_IOCTL_SELECT       _IOW('T', 0x10, struct snd_timer_select)
-#define SNDRV_TIMER_IOCTL_INFO         _IOR('T', 0x11, struct snd_timer_info)
-#define SNDRV_TIMER_IOCTL_PARAMS       _IOW('T', 0x12, struct snd_timer_params)
-#define SNDRV_TIMER_IOCTL_STATUS       _IOR('T', 0x14, struct snd_timer_status)
-/* The following four ioctls are changed since 1.0.9 due to confliction */
-#define SNDRV_TIMER_IOCTL_START                _IO('T', 0xa0)
-#define SNDRV_TIMER_IOCTL_STOP         _IO('T', 0xa1)
-#define SNDRV_TIMER_IOCTL_CONTINUE     _IO('T', 0xa2)
-#define SNDRV_TIMER_IOCTL_PAUSE                _IO('T', 0xa3)
-
-struct snd_timer_read {
-       unsigned int resolution;
-       unsigned int ticks;
-};
-
-enum {
-       SNDRV_TIMER_EVENT_RESOLUTION = 0,       /* val = resolution in ns */
-       SNDRV_TIMER_EVENT_TICK,                 /* val = ticks */
-       SNDRV_TIMER_EVENT_START,                /* val = resolution in ns */
-       SNDRV_TIMER_EVENT_STOP,                 /* val = 0 */
-       SNDRV_TIMER_EVENT_CONTINUE,             /* val = resolution in ns */
-       SNDRV_TIMER_EVENT_PAUSE,                /* val = 0 */
-       SNDRV_TIMER_EVENT_EARLY,                /* val = 0, early event */
-       SNDRV_TIMER_EVENT_SUSPEND,              /* val = 0 */
-       SNDRV_TIMER_EVENT_RESUME,               /* val = resolution in ns */
-       /* master timer events for slave timer instances */
-       SNDRV_TIMER_EVENT_MSTART = SNDRV_TIMER_EVENT_START + 10,
-       SNDRV_TIMER_EVENT_MSTOP = SNDRV_TIMER_EVENT_STOP + 10,
-       SNDRV_TIMER_EVENT_MCONTINUE = SNDRV_TIMER_EVENT_CONTINUE + 10,
-       SNDRV_TIMER_EVENT_MPAUSE = SNDRV_TIMER_EVENT_PAUSE + 10,
-       SNDRV_TIMER_EVENT_MSUSPEND = SNDRV_TIMER_EVENT_SUSPEND + 10,
-       SNDRV_TIMER_EVENT_MRESUME = SNDRV_TIMER_EVENT_RESUME + 10,
-};
-
-struct snd_timer_tread {
-       int event;
-       struct timespec tstamp;
-       unsigned int val;
-};
-
-/****************************************************************************
- *                                                                          *
- *        Section for driver control interface - /dev/snd/control?          *
- *                                                                          *
- ****************************************************************************/
-
-#define SNDRV_CTL_VERSION              SNDRV_PROTOCOL_VERSION(2, 0, 7)
-
-struct snd_ctl_card_info {
-       int card;                       /* card number */
-       int pad;                        /* reserved for future (was type) */
-       unsigned char id[16];           /* ID of card (user selectable) */
-       unsigned char driver[16];       /* Driver name */
-       unsigned char name[32];         /* Short name of soundcard */
-       unsigned char longname[80];     /* name + info text about soundcard */
-       unsigned char reserved_[16];    /* reserved for future (was ID of mixer) */
-       unsigned char mixername[80];    /* visual mixer identification */
-       unsigned char components[128];  /* card components / fine identification, delimited with one space (AC97 etc..) */
-};
-
-typedef int __bitwise snd_ctl_elem_type_t;
-#define        SNDRV_CTL_ELEM_TYPE_NONE        ((__force snd_ctl_elem_type_t) 0) /* invalid */
-#define        SNDRV_CTL_ELEM_TYPE_BOOLEAN     ((__force snd_ctl_elem_type_t) 1) /* boolean type */
-#define        SNDRV_CTL_ELEM_TYPE_INTEGER     ((__force snd_ctl_elem_type_t) 2) /* integer type */
-#define        SNDRV_CTL_ELEM_TYPE_ENUMERATED  ((__force snd_ctl_elem_type_t) 3) /* enumerated type */
-#define        SNDRV_CTL_ELEM_TYPE_BYTES       ((__force snd_ctl_elem_type_t) 4) /* byte array */
-#define        SNDRV_CTL_ELEM_TYPE_IEC958      ((__force snd_ctl_elem_type_t) 5) /* IEC958 (S/PDIF) setup */
-#define        SNDRV_CTL_ELEM_TYPE_INTEGER64   ((__force snd_ctl_elem_type_t) 6) /* 64-bit integer type */
-#define        SNDRV_CTL_ELEM_TYPE_LAST        SNDRV_CTL_ELEM_TYPE_INTEGER64
-
-typedef int __bitwise snd_ctl_elem_iface_t;
-#define        SNDRV_CTL_ELEM_IFACE_CARD       ((__force snd_ctl_elem_iface_t) 0) /* global control */
-#define        SNDRV_CTL_ELEM_IFACE_HWDEP      ((__force snd_ctl_elem_iface_t) 1) /* hardware dependent device */
-#define        SNDRV_CTL_ELEM_IFACE_MIXER      ((__force snd_ctl_elem_iface_t) 2) /* virtual mixer device */
-#define        SNDRV_CTL_ELEM_IFACE_PCM        ((__force snd_ctl_elem_iface_t) 3) /* PCM device */
-#define        SNDRV_CTL_ELEM_IFACE_RAWMIDI    ((__force snd_ctl_elem_iface_t) 4) /* RawMidi device */
-#define        SNDRV_CTL_ELEM_IFACE_TIMER      ((__force snd_ctl_elem_iface_t) 5) /* timer device */
-#define        SNDRV_CTL_ELEM_IFACE_SEQUENCER  ((__force snd_ctl_elem_iface_t) 6) /* sequencer client */
-#define        SNDRV_CTL_ELEM_IFACE_LAST       SNDRV_CTL_ELEM_IFACE_SEQUENCER
-
-#define SNDRV_CTL_ELEM_ACCESS_READ             (1<<0)
-#define SNDRV_CTL_ELEM_ACCESS_WRITE            (1<<1)
-#define SNDRV_CTL_ELEM_ACCESS_READWRITE                (SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE)
-#define SNDRV_CTL_ELEM_ACCESS_VOLATILE         (1<<2)  /* control value may be changed without a notification */
-#define SNDRV_CTL_ELEM_ACCESS_TIMESTAMP                (1<<3)  /* when was control changed */
-#define SNDRV_CTL_ELEM_ACCESS_TLV_READ         (1<<4)  /* TLV read is possible */
-#define SNDRV_CTL_ELEM_ACCESS_TLV_WRITE                (1<<5)  /* TLV write is possible */
-#define SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE    (SNDRV_CTL_ELEM_ACCESS_TLV_READ|SNDRV_CTL_ELEM_ACCESS_TLV_WRITE)
-#define SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND      (1<<6)  /* TLV command is possible */
-#define SNDRV_CTL_ELEM_ACCESS_INACTIVE         (1<<8)  /* control does actually nothing, but may be updated */
-#define SNDRV_CTL_ELEM_ACCESS_LOCK             (1<<9)  /* write lock */
-#define SNDRV_CTL_ELEM_ACCESS_OWNER            (1<<10) /* write lock owner */
-#define SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK     (1<<28) /* kernel use a TLV callback */ 
-#define SNDRV_CTL_ELEM_ACCESS_USER             (1<<29) /* user space element */
-/* bits 30 and 31 are obsoleted (for indirect access) */
-
-/* for further details see the ACPI and PCI power management specification */
-#define SNDRV_CTL_POWER_D0             0x0000  /* full On */
-#define SNDRV_CTL_POWER_D1             0x0100  /* partial On */
-#define SNDRV_CTL_POWER_D2             0x0200  /* partial On */
-#define SNDRV_CTL_POWER_D3             0x0300  /* Off */
-#define SNDRV_CTL_POWER_D3hot          (SNDRV_CTL_POWER_D3|0x0000)     /* Off, with power */
-#define SNDRV_CTL_POWER_D3cold         (SNDRV_CTL_POWER_D3|0x0001)     /* Off, without power */
-
-struct snd_ctl_elem_id {
-       unsigned int numid;             /* numeric identifier, zero = invalid */
-       snd_ctl_elem_iface_t iface;     /* interface identifier */
-       unsigned int device;            /* device/client number */
-       unsigned int subdevice;         /* subdevice (substream) number */
-       unsigned char name[44];         /* ASCII name of item */
-       unsigned int index;             /* index of item */
-};
-
-struct snd_ctl_elem_list {
-       unsigned int offset;            /* W: first element ID to get */
-       unsigned int space;             /* W: count of element IDs to get */
-       unsigned int used;              /* R: count of element IDs set */
-       unsigned int count;             /* R: count of all elements */
-       struct snd_ctl_elem_id __user *pids; /* R: IDs */
-       unsigned char reserved[50];
-};
-
-struct snd_ctl_elem_info {
-       struct snd_ctl_elem_id id;      /* W: element ID */
-       snd_ctl_elem_type_t type;       /* R: value type - SNDRV_CTL_ELEM_TYPE_* */
-       unsigned int access;            /* R: value access (bitmask) - SNDRV_CTL_ELEM_ACCESS_* */
-       unsigned int count;             /* count of values */
-       __kernel_pid_t owner;           /* owner's PID of this control */
-       union {
-               struct {
-                       long min;               /* R: minimum value */
-                       long max;               /* R: maximum value */
-                       long step;              /* R: step (0 variable) */
-               } integer;
-               struct {
-                       long long min;          /* R: minimum value */
-                       long long max;          /* R: maximum value */
-                       long long step;         /* R: step (0 variable) */
-               } integer64;
-               struct {
-                       unsigned int items;     /* R: number of items */
-                       unsigned int item;      /* W: item number */
-                       char name[64];          /* R: value name */
-                       __u64 names_ptr;        /* W: names list (ELEM_ADD only) */
-                       unsigned int names_length;
-               } enumerated;
-               unsigned char reserved[128];
-       } value;
-       union {
-               unsigned short d[4];            /* dimensions */
-               unsigned short *d_ptr;          /* indirect - obsoleted */
-       } dimen;
-       unsigned char reserved[64-4*sizeof(unsigned short)];
-};
-
-struct snd_ctl_elem_value {
-       struct snd_ctl_elem_id id;      /* W: element ID */
-       unsigned int indirect: 1;       /* W: indirect access - obsoleted */
-       union {
-               union {
-                       long value[128];
-                       long *value_ptr;        /* obsoleted */
-               } integer;
-               union {
-                       long long value[64];
-                       long long *value_ptr;   /* obsoleted */
-               } integer64;
-               union {
-                       unsigned int item[128];
-                       unsigned int *item_ptr; /* obsoleted */
-               } enumerated;
-               union {
-                       unsigned char data[512];
-                       unsigned char *data_ptr;        /* obsoleted */
-               } bytes;
-               struct snd_aes_iec958 iec958;
-       } value;                /* RO */
-       struct timespec tstamp;
-       unsigned char reserved[128-sizeof(struct timespec)];
-};
-
-struct snd_ctl_tlv {
-       unsigned int numid;     /* control element numeric identification */
-       unsigned int length;    /* in bytes aligned to 4 */
-       unsigned int tlv[0];    /* first TLV */
-};
-
-#define SNDRV_CTL_IOCTL_PVERSION       _IOR('U', 0x00, int)
-#define SNDRV_CTL_IOCTL_CARD_INFO      _IOR('U', 0x01, struct snd_ctl_card_info)
-#define SNDRV_CTL_IOCTL_ELEM_LIST      _IOWR('U', 0x10, struct snd_ctl_elem_list)
-#define SNDRV_CTL_IOCTL_ELEM_INFO      _IOWR('U', 0x11, struct snd_ctl_elem_info)
-#define SNDRV_CTL_IOCTL_ELEM_READ      _IOWR('U', 0x12, struct snd_ctl_elem_value)
-#define SNDRV_CTL_IOCTL_ELEM_WRITE     _IOWR('U', 0x13, struct snd_ctl_elem_value)
-#define SNDRV_CTL_IOCTL_ELEM_LOCK      _IOW('U', 0x14, struct snd_ctl_elem_id)
-#define SNDRV_CTL_IOCTL_ELEM_UNLOCK    _IOW('U', 0x15, struct snd_ctl_elem_id)
-#define SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS _IOWR('U', 0x16, int)
-#define SNDRV_CTL_IOCTL_ELEM_ADD       _IOWR('U', 0x17, struct snd_ctl_elem_info)
-#define SNDRV_CTL_IOCTL_ELEM_REPLACE   _IOWR('U', 0x18, struct snd_ctl_elem_info)
-#define SNDRV_CTL_IOCTL_ELEM_REMOVE    _IOWR('U', 0x19, struct snd_ctl_elem_id)
-#define SNDRV_CTL_IOCTL_TLV_READ       _IOWR('U', 0x1a, struct snd_ctl_tlv)
-#define SNDRV_CTL_IOCTL_TLV_WRITE      _IOWR('U', 0x1b, struct snd_ctl_tlv)
-#define SNDRV_CTL_IOCTL_TLV_COMMAND    _IOWR('U', 0x1c, struct snd_ctl_tlv)
-#define SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE _IOWR('U', 0x20, int)
-#define SNDRV_CTL_IOCTL_HWDEP_INFO     _IOR('U', 0x21, struct snd_hwdep_info)
-#define SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE        _IOR('U', 0x30, int)
-#define SNDRV_CTL_IOCTL_PCM_INFO       _IOWR('U', 0x31, struct snd_pcm_info)
-#define SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE _IOW('U', 0x32, int)
-#define SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE _IOWR('U', 0x40, int)
-#define SNDRV_CTL_IOCTL_RAWMIDI_INFO   _IOWR('U', 0x41, struct snd_rawmidi_info)
-#define SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE _IOW('U', 0x42, int)
-#define SNDRV_CTL_IOCTL_POWER          _IOWR('U', 0xd0, int)
-#define SNDRV_CTL_IOCTL_POWER_STATE    _IOR('U', 0xd1, int)
-
-/*
- *  Read interface.
- */
-
-enum sndrv_ctl_event_type {
-       SNDRV_CTL_EVENT_ELEM = 0,
-       SNDRV_CTL_EVENT_LAST = SNDRV_CTL_EVENT_ELEM,
-};
-
-#define SNDRV_CTL_EVENT_MASK_VALUE     (1<<0)  /* element value was changed */
-#define SNDRV_CTL_EVENT_MASK_INFO      (1<<1)  /* element info was changed */
-#define SNDRV_CTL_EVENT_MASK_ADD       (1<<2)  /* element was added */
-#define SNDRV_CTL_EVENT_MASK_TLV       (1<<3)  /* element TLV tree was changed */
-#define SNDRV_CTL_EVENT_MASK_REMOVE    (~0U)   /* element was removed */
-
-struct snd_ctl_event {
-       int type;       /* event type - SNDRV_CTL_EVENT_* */
-       union {
-               struct {
-                       unsigned int mask;
-                       struct snd_ctl_elem_id id;
-               } elem;
-               unsigned char data8[60];
-       } data;
-};
-
-/*
- *  Control names
- */
-
-#define SNDRV_CTL_NAME_NONE                            ""
-#define SNDRV_CTL_NAME_PLAYBACK                                "Playback "
-#define SNDRV_CTL_NAME_CAPTURE                         "Capture "
-
-#define SNDRV_CTL_NAME_IEC958_NONE                     ""
-#define SNDRV_CTL_NAME_IEC958_SWITCH                   "Switch"
-#define SNDRV_CTL_NAME_IEC958_VOLUME                   "Volume"
-#define SNDRV_CTL_NAME_IEC958_DEFAULT                  "Default"
-#define SNDRV_CTL_NAME_IEC958_MASK                     "Mask"
-#define SNDRV_CTL_NAME_IEC958_CON_MASK                 "Con Mask"
-#define SNDRV_CTL_NAME_IEC958_PRO_MASK                 "Pro Mask"
-#define SNDRV_CTL_NAME_IEC958_PCM_STREAM               "PCM Stream"
-#define SNDRV_CTL_NAME_IEC958(expl,direction,what)     "IEC958 " expl SNDRV_CTL_NAME_##direction SNDRV_CTL_NAME_IEC958_##what
-
+#include <uapi/sound/asound.h>
 #endif /* __SOUND_ASOUND_H */
index 50a059e7d11616d4eb836cf7f0cc738cc0eaed3f..6d9e15ed1dcf0cb2875a10ca6795b14f3d4e0c51 100644 (file)
@@ -19,6 +19,7 @@
 
 struct cs4271_platform_data {
        int gpio_nreset;        /* GPIO driving Reset pin, if any */
+       int amutec_eq_bmutec:1; /* flag to enable AMUTEC=BMUTEC */
 };
 
 #endif /* __CS4271_H */
index 1a33f48ebe7875f6ae6b6769583646a2e501dae9..3707288ae9bf7da01d13910829da635589e0ffc2 100644 (file)
@@ -1,8 +1,3 @@
-#ifndef __SOUND_EMU10K1_H
-#define __SOUND_EMU10K1_H
-
-#include <linux/types.h>
-
 /*
  *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>,
  *                  Creative Labs, Inc.
@@ -24,8 +19,9 @@
  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  *
  */
+#ifndef __SOUND_EMU10K1_H
+#define __SOUND_EMU10K1_H
 
-#ifdef __KERNEL__
 
 #include <sound/pcm.h>
 #include <sound/rawmidi.h>
@@ -38,6 +34,7 @@
 #include <linux/mutex.h>
 
 #include <asm/io.h>
+#include <uapi/sound/emu10k1.h>
 
 /* ------------------- DEFINES -------------------- */
 
@@ -1899,350 +1896,4 @@ int snd_emu10k1_fx8010_register_irq_handler(struct snd_emu10k1 *emu,
 int snd_emu10k1_fx8010_unregister_irq_handler(struct snd_emu10k1 *emu,
                                              struct snd_emu10k1_fx8010_irq *irq);
 
-#endif /* __KERNEL__ */
-
-/*
- * ---- FX8010 ----
- */
-
-#define EMU10K1_CARD_CREATIVE                  0x00000000
-#define EMU10K1_CARD_EMUAPS                    0x00000001
-
-#define EMU10K1_FX8010_PCM_COUNT               8
-
-/* instruction set */
-#define iMAC0   0x00   /* R = A + (X * Y >> 31)   ; saturation */
-#define iMAC1   0x01   /* R = A + (-X * Y >> 31)  ; saturation */
-#define iMAC2   0x02   /* R = A + (X * Y >> 31)   ; wraparound */
-#define iMAC3   0x03   /* R = A + (-X * Y >> 31)  ; wraparound */
-#define iMACINT0 0x04  /* R = A + X * Y           ; saturation */
-#define iMACINT1 0x05  /* R = A + X * Y           ; wraparound (31-bit) */
-#define iACC3   0x06   /* R = A + X + Y           ; saturation */
-#define iMACMV   0x07  /* R = A, acc += X * Y >> 31 */
-#define iANDXOR  0x08  /* R = (A & X) ^ Y */
-#define iTSTNEG  0x09  /* R = (A >= Y) ? X : ~X */
-#define iLIMITGE 0x0a  /* R = (A >= Y) ? X : Y */
-#define iLIMITLT 0x0b  /* R = (A < Y) ? X : Y */
-#define iLOG    0x0c   /* R = linear_data, A (log_data), X (max_exp), Y (format_word) */
-#define iEXP    0x0d   /* R = log_data, A (linear_data), X (max_exp), Y (format_word) */
-#define iINTERP  0x0e  /* R = A + (X * (Y - A) >> 31)  ; saturation */
-#define iSKIP    0x0f  /* R = A (cc_reg), X (count), Y (cc_test) */
-
-/* GPRs */
-#define FXBUS(x)       (0x00 + (x))    /* x = 0x00 - 0x0f */
-#define EXTIN(x)       (0x10 + (x))    /* x = 0x00 - 0x0f */
-#define EXTOUT(x)      (0x20 + (x))    /* x = 0x00 - 0x0f physical outs -> FXWC low 16 bits */
-#define FXBUS2(x)      (0x30 + (x))    /* x = 0x00 - 0x0f copies of fx buses for capture -> FXWC high 16 bits */
-                                       /* NB: 0x31 and 0x32 are shared with Center/LFE on SB live 5.1 */
-
-#define C_00000000     0x40
-#define C_00000001     0x41
-#define C_00000002     0x42
-#define C_00000003     0x43
-#define C_00000004     0x44
-#define C_00000008     0x45
-#define C_00000010     0x46
-#define C_00000020     0x47
-#define C_00000100     0x48
-#define C_00010000     0x49
-#define C_00080000     0x4a
-#define C_10000000     0x4b
-#define C_20000000     0x4c
-#define C_40000000     0x4d
-#define C_80000000     0x4e
-#define C_7fffffff     0x4f
-#define C_ffffffff     0x50
-#define C_fffffffe     0x51
-#define C_c0000000     0x52
-#define C_4f1bbcdc     0x53
-#define C_5a7ef9db     0x54
-#define C_00100000     0x55            /* ?? */
-#define GPR_ACCU       0x56            /* ACCUM, accumulator */
-#define GPR_COND       0x57            /* CCR, condition register */
-#define GPR_NOISE0     0x58            /* noise source */
-#define GPR_NOISE1     0x59            /* noise source */
-#define GPR_IRQ                0x5a            /* IRQ register */
-#define GPR_DBAC       0x5b            /* TRAM Delay Base Address Counter */
-#define GPR(x)         (FXGPREGBASE + (x)) /* free GPRs: x = 0x00 - 0xff */
-#define ITRAM_DATA(x)  (TANKMEMDATAREGBASE + 0x00 + (x)) /* x = 0x00 - 0x7f */
-#define ETRAM_DATA(x)  (TANKMEMDATAREGBASE + 0x80 + (x)) /* x = 0x00 - 0x1f */
-#define ITRAM_ADDR(x)  (TANKMEMADDRREGBASE + 0x00 + (x)) /* x = 0x00 - 0x7f */
-#define ETRAM_ADDR(x)  (TANKMEMADDRREGBASE + 0x80 + (x)) /* x = 0x00 - 0x1f */
-
-#define A_ITRAM_DATA(x)        (TANKMEMDATAREGBASE + 0x00 + (x)) /* x = 0x00 - 0xbf */
-#define A_ETRAM_DATA(x)        (TANKMEMDATAREGBASE + 0xc0 + (x)) /* x = 0x00 - 0x3f */
-#define A_ITRAM_ADDR(x)        (TANKMEMADDRREGBASE + 0x00 + (x)) /* x = 0x00 - 0xbf */
-#define A_ETRAM_ADDR(x)        (TANKMEMADDRREGBASE + 0xc0 + (x)) /* x = 0x00 - 0x3f */
-#define A_ITRAM_CTL(x) (A_TANKMEMCTLREGBASE + 0x00 + (x)) /* x = 0x00 - 0xbf */
-#define A_ETRAM_CTL(x) (A_TANKMEMCTLREGBASE + 0xc0 + (x)) /* x = 0x00 - 0x3f */
-
-#define A_FXBUS(x)     (0x00 + (x))    /* x = 0x00 - 0x3f FX buses */
-#define A_EXTIN(x)     (0x40 + (x))    /* x = 0x00 - 0x0f physical ins */
-#define A_P16VIN(x)    (0x50 + (x))    /* x = 0x00 - 0x0f p16v ins (A2 only) "EMU32 inputs" */
-#define A_EXTOUT(x)    (0x60 + (x))    /* x = 0x00 - 0x1f physical outs -> A_FXWC1 0x79-7f unknown   */
-#define A_FXBUS2(x)    (0x80 + (x))    /* x = 0x00 - 0x1f extra outs used for EFX capture -> A_FXWC2 */
-#define A_EMU32OUTH(x) (0xa0 + (x))    /* x = 0x00 - 0x0f "EMU32_OUT_10 - _1F" - ??? */
-#define A_EMU32OUTL(x) (0xb0 + (x))    /* x = 0x00 - 0x0f "EMU32_OUT_1 - _F" - ??? */
-#define A3_EMU32IN(x)  (0x160 + (x))   /* x = 0x00 - 0x3f "EMU32_IN_00 - _3F" - Only when .device = 0x0008 */
-#define A3_EMU32OUT(x) (0x1E0 + (x))   /* x = 0x00 - 0x0f "EMU32_OUT_00 - _3F" - Only when .device = 0x0008 */
-#define A_GPR(x)       (A_FXGPREGBASE + (x))
-
-/* cc_reg constants */
-#define CC_REG_NORMALIZED C_00000001
-#define CC_REG_BORROW  C_00000002
-#define CC_REG_MINUS   C_00000004
-#define CC_REG_ZERO    C_00000008
-#define CC_REG_SATURATE        C_00000010
-#define CC_REG_NONZERO C_00000100
-
-/* FX buses */
-#define FXBUS_PCM_LEFT         0x00
-#define FXBUS_PCM_RIGHT                0x01
-#define FXBUS_PCM_LEFT_REAR    0x02
-#define FXBUS_PCM_RIGHT_REAR   0x03
-#define FXBUS_MIDI_LEFT                0x04
-#define FXBUS_MIDI_RIGHT       0x05
-#define FXBUS_PCM_CENTER       0x06
-#define FXBUS_PCM_LFE          0x07
-#define FXBUS_PCM_LEFT_FRONT   0x08
-#define FXBUS_PCM_RIGHT_FRONT  0x09
-#define FXBUS_MIDI_REVERB      0x0c
-#define FXBUS_MIDI_CHORUS      0x0d
-#define FXBUS_PCM_LEFT_SIDE    0x0e
-#define FXBUS_PCM_RIGHT_SIDE   0x0f
-#define FXBUS_PT_LEFT          0x14
-#define FXBUS_PT_RIGHT         0x15
-
-/* Inputs */
-#define EXTIN_AC97_L      0x00 /* AC'97 capture channel - left */
-#define EXTIN_AC97_R      0x01 /* AC'97 capture channel - right */
-#define EXTIN_SPDIF_CD_L   0x02        /* internal S/PDIF CD - onboard - left */
-#define EXTIN_SPDIF_CD_R   0x03        /* internal S/PDIF CD - onboard - right */
-#define EXTIN_ZOOM_L      0x04 /* Zoom Video I2S - left */
-#define EXTIN_ZOOM_R      0x05 /* Zoom Video I2S - right */
-#define EXTIN_TOSLINK_L           0x06 /* LiveDrive - TOSLink Optical - left */
-#define EXTIN_TOSLINK_R    0x07        /* LiveDrive - TOSLink Optical - right */
-#define EXTIN_LINE1_L     0x08 /* LiveDrive - Line/Mic 1 - left */
-#define EXTIN_LINE1_R     0x09 /* LiveDrive - Line/Mic 1 - right */
-#define EXTIN_COAX_SPDIF_L 0x0a        /* LiveDrive - Coaxial S/PDIF - left */
-#define EXTIN_COAX_SPDIF_R 0x0b /* LiveDrive - Coaxial S/PDIF - right */
-#define EXTIN_LINE2_L     0x0c /* LiveDrive - Line/Mic 2 - left */
-#define EXTIN_LINE2_R     0x0d /* LiveDrive - Line/Mic 2 - right */
-
-/* Outputs */
-#define EXTOUT_AC97_L     0x00 /* AC'97 playback channel - left */
-#define EXTOUT_AC97_R     0x01 /* AC'97 playback channel - right */
-#define EXTOUT_TOSLINK_L   0x02        /* LiveDrive - TOSLink Optical - left */
-#define EXTOUT_TOSLINK_R   0x03        /* LiveDrive - TOSLink Optical - right */
-#define EXTOUT_AC97_CENTER 0x04        /* SB Live 5.1 - center */
-#define EXTOUT_AC97_LFE           0x05 /* SB Live 5.1 - LFE */
-#define EXTOUT_HEADPHONE_L 0x06        /* LiveDrive - Headphone - left */
-#define EXTOUT_HEADPHONE_R 0x07        /* LiveDrive - Headphone - right */
-#define EXTOUT_REAR_L     0x08 /* Rear channel - left */
-#define EXTOUT_REAR_R     0x09 /* Rear channel - right */
-#define EXTOUT_ADC_CAP_L   0x0a        /* ADC Capture buffer - left */
-#define EXTOUT_ADC_CAP_R   0x0b        /* ADC Capture buffer - right */
-#define EXTOUT_MIC_CAP    0x0c /* MIC Capture buffer */
-#define EXTOUT_AC97_REAR_L 0x0d        /* SB Live 5.1 (c) 2003 - Rear Left */
-#define EXTOUT_AC97_REAR_R 0x0e        /* SB Live 5.1 (c) 2003 - Rear Right */
-#define EXTOUT_ACENTER    0x11 /* Analog Center */
-#define EXTOUT_ALFE       0x12 /* Analog LFE */
-
-/* Audigy Inputs */
-#define A_EXTIN_AC97_L         0x00    /* AC'97 capture channel - left */
-#define A_EXTIN_AC97_R         0x01    /* AC'97 capture channel - right */
-#define A_EXTIN_SPDIF_CD_L     0x02    /* digital CD left */
-#define A_EXTIN_SPDIF_CD_R     0x03    /* digital CD left */
-#define A_EXTIN_OPT_SPDIF_L     0x04    /* audigy drive Optical SPDIF - left */
-#define A_EXTIN_OPT_SPDIF_R     0x05    /*                              right */ 
-#define A_EXTIN_LINE2_L                0x08    /* audigy drive line2/mic2 - left */
-#define A_EXTIN_LINE2_R                0x09    /*                           right */
-#define A_EXTIN_ADC_L          0x0a    /* Philips ADC - left */
-#define A_EXTIN_ADC_R          0x0b    /*               right */
-#define A_EXTIN_AUX2_L         0x0c    /* audigy drive aux2 - left */
-#define A_EXTIN_AUX2_R         0x0d    /*                   - right */
-
-/* Audigiy Outputs */
-#define A_EXTOUT_FRONT_L       0x00    /* digital front left */
-#define A_EXTOUT_FRONT_R       0x01    /*               right */
-#define A_EXTOUT_CENTER                0x02    /* digital front center */
-#define A_EXTOUT_LFE           0x03    /* digital front lfe */
-#define A_EXTOUT_HEADPHONE_L   0x04    /* headphone audigy drive left */
-#define A_EXTOUT_HEADPHONE_R   0x05    /*                        right */
-#define A_EXTOUT_REAR_L                0x06    /* digital rear left */
-#define A_EXTOUT_REAR_R                0x07    /*              right */
-#define A_EXTOUT_AFRONT_L      0x08    /* analog front left */
-#define A_EXTOUT_AFRONT_R      0x09    /*              right */
-#define A_EXTOUT_ACENTER       0x0a    /* analog center */
-#define A_EXTOUT_ALFE          0x0b    /* analog LFE */
-#define A_EXTOUT_ASIDE_L       0x0c    /* analog side left  - Audigy 2 ZS */
-#define A_EXTOUT_ASIDE_R       0x0d    /*             right - Audigy 2 ZS */
-#define A_EXTOUT_AREAR_L       0x0e    /* analog rear left */
-#define A_EXTOUT_AREAR_R       0x0f    /*             right */
-#define A_EXTOUT_AC97_L                0x10    /* AC97 left (front) */
-#define A_EXTOUT_AC97_R                0x11    /*      right */
-#define A_EXTOUT_ADC_CAP_L     0x16    /* ADC capture buffer left */
-#define A_EXTOUT_ADC_CAP_R     0x17    /*                    right */
-#define A_EXTOUT_MIC_CAP       0x18    /* Mic capture buffer */
-
-/* Audigy constants */
-#define A_C_00000000   0xc0
-#define A_C_00000001   0xc1
-#define A_C_00000002   0xc2
-#define A_C_00000003   0xc3
-#define A_C_00000004   0xc4
-#define A_C_00000008   0xc5
-#define A_C_00000010   0xc6
-#define A_C_00000020   0xc7
-#define A_C_00000100   0xc8
-#define A_C_00010000   0xc9
-#define A_C_00000800   0xca
-#define A_C_10000000   0xcb
-#define A_C_20000000   0xcc
-#define A_C_40000000   0xcd
-#define A_C_80000000   0xce
-#define A_C_7fffffff   0xcf
-#define A_C_ffffffff   0xd0
-#define A_C_fffffffe   0xd1
-#define A_C_c0000000   0xd2
-#define A_C_4f1bbcdc   0xd3
-#define A_C_5a7ef9db   0xd4
-#define A_C_00100000   0xd5
-#define A_GPR_ACCU     0xd6            /* ACCUM, accumulator */
-#define A_GPR_COND     0xd7            /* CCR, condition register */
-#define A_GPR_NOISE0   0xd8            /* noise source */
-#define A_GPR_NOISE1   0xd9            /* noise source */
-#define A_GPR_IRQ      0xda            /* IRQ register */
-#define A_GPR_DBAC     0xdb            /* TRAM Delay Base Address Counter - internal */
-#define A_GPR_DBACE    0xde            /* TRAM Delay Base Address Counter - external */
-
-/* definitions for debug register */
-#define EMU10K1_DBG_ZC                 0x80000000      /* zero tram counter */
-#define EMU10K1_DBG_SATURATION_OCCURED 0x02000000      /* saturation control */
-#define EMU10K1_DBG_SATURATION_ADDR    0x01ff0000      /* saturation address */
-#define EMU10K1_DBG_SINGLE_STEP                0x00008000      /* single step mode */
-#define EMU10K1_DBG_STEP               0x00004000      /* start single step */
-#define EMU10K1_DBG_CONDITION_CODE     0x00003e00      /* condition code */
-#define EMU10K1_DBG_SINGLE_STEP_ADDR   0x000001ff      /* single step address */
-
-/* tank memory address line */
-#ifndef __KERNEL__
-#define TANKMEMADDRREG_ADDR_MASK 0x000fffff    /* 20 bit tank address field                    */
-#define TANKMEMADDRREG_CLEAR    0x00800000     /* Clear tank memory                            */
-#define TANKMEMADDRREG_ALIGN    0x00400000     /* Align read or write relative to tank access  */
-#define TANKMEMADDRREG_WRITE    0x00200000     /* Write to tank memory                         */
-#define TANKMEMADDRREG_READ     0x00100000     /* Read from tank memory                        */
-#endif
-
-struct snd_emu10k1_fx8010_info {
-       unsigned int internal_tram_size;        /* in samples */
-       unsigned int external_tram_size;        /* in samples */
-       char fxbus_names[16][32];               /* names of FXBUSes */
-       char extin_names[16][32];               /* names of external inputs */
-       char extout_names[32][32];              /* names of external outputs */
-       unsigned int gpr_controls;              /* count of GPR controls */
-};
-
-#define EMU10K1_GPR_TRANSLATION_NONE           0
-#define EMU10K1_GPR_TRANSLATION_TABLE100       1
-#define EMU10K1_GPR_TRANSLATION_BASS           2
-#define EMU10K1_GPR_TRANSLATION_TREBLE         3
-#define EMU10K1_GPR_TRANSLATION_ONOFF          4
-
-struct snd_emu10k1_fx8010_control_gpr {
-       struct snd_ctl_elem_id id;              /* full control ID definition */
-       unsigned int vcount;            /* visible count */
-       unsigned int count;             /* count of GPR (1..16) */
-       unsigned short gpr[32];         /* GPR number(s) */
-       unsigned int value[32];         /* initial values */
-       unsigned int min;               /* minimum range */
-       unsigned int max;               /* maximum range */
-       unsigned int translation;       /* translation type (EMU10K1_GPR_TRANSLATION*) */
-       const unsigned int *tlv;
-};
-
-/* old ABI without TLV support */
-struct snd_emu10k1_fx8010_control_old_gpr {
-       struct snd_ctl_elem_id id;
-       unsigned int vcount;
-       unsigned int count;
-       unsigned short gpr[32];
-       unsigned int value[32];
-       unsigned int min;
-       unsigned int max;
-       unsigned int translation;
-};
-
-struct snd_emu10k1_fx8010_code {
-       char name[128];
-
-       DECLARE_BITMAP(gpr_valid, 0x200); /* bitmask of valid initializers */
-       __u32 __user *gpr_map;          /* initializers */
-
-       unsigned int gpr_add_control_count; /* count of GPR controls to add/replace */
-       struct snd_emu10k1_fx8010_control_gpr __user *gpr_add_controls; /* GPR controls to add/replace */
-
-       unsigned int gpr_del_control_count; /* count of GPR controls to remove */
-       struct snd_ctl_elem_id __user *gpr_del_controls; /* IDs of GPR controls to remove */
-
-       unsigned int gpr_list_control_count; /* count of GPR controls to list */
-       unsigned int gpr_list_control_total; /* total count of GPR controls */
-       struct snd_emu10k1_fx8010_control_gpr __user *gpr_list_controls; /* listed GPR controls */
-
-       DECLARE_BITMAP(tram_valid, 0x100); /* bitmask of valid initializers */
-       __u32 __user *tram_data_map;      /* data initializers */
-       __u32 __user *tram_addr_map;      /* map initializers */
-
-       DECLARE_BITMAP(code_valid, 1024); /* bitmask of valid instructions */
-       __u32 __user *code;               /* one instruction - 64 bits */
-};
-
-struct snd_emu10k1_fx8010_tram {
-       unsigned int address;           /* 31.bit == 1 -> external TRAM */
-       unsigned int size;              /* size in samples (4 bytes) */
-       unsigned int *samples;          /* pointer to samples (20-bit) */
-                                       /* NULL->clear memory */
-};
-
-struct snd_emu10k1_fx8010_pcm_rec {
-       unsigned int substream;         /* substream number */
-       unsigned int res1;              /* reserved */
-       unsigned int channels;          /* 16-bit channels count, zero = remove this substream */
-       unsigned int tram_start;        /* ring buffer position in TRAM (in samples) */
-       unsigned int buffer_size;       /* count of buffered samples */
-       unsigned short gpr_size;                /* GPR containing size of ringbuffer in samples (host) */
-       unsigned short gpr_ptr;         /* GPR containing current pointer in the ring buffer (host = reset, FX8010) */
-       unsigned short gpr_count;       /* GPR containing count of samples between two interrupts (host) */
-       unsigned short gpr_tmpcount;    /* GPR containing current count of samples to interrupt (host = set, FX8010) */
-       unsigned short gpr_trigger;     /* GPR containing trigger (activate) information (host) */
-       unsigned short gpr_running;     /* GPR containing info if PCM is running (FX8010) */
-       unsigned char pad;              /* reserved */
-       unsigned char etram[32];        /* external TRAM address & data (one per channel) */
-       unsigned int res2;              /* reserved */
-};
-
-#define SNDRV_EMU10K1_VERSION          SNDRV_PROTOCOL_VERSION(1, 0, 1)
-
-#define SNDRV_EMU10K1_IOCTL_INFO       _IOR ('H', 0x10, struct snd_emu10k1_fx8010_info)
-#define SNDRV_EMU10K1_IOCTL_CODE_POKE  _IOW ('H', 0x11, struct snd_emu10k1_fx8010_code)
-#define SNDRV_EMU10K1_IOCTL_CODE_PEEK  _IOWR('H', 0x12, struct snd_emu10k1_fx8010_code)
-#define SNDRV_EMU10K1_IOCTL_TRAM_SETUP _IOW ('H', 0x20, int)
-#define SNDRV_EMU10K1_IOCTL_TRAM_POKE  _IOW ('H', 0x21, struct snd_emu10k1_fx8010_tram)
-#define SNDRV_EMU10K1_IOCTL_TRAM_PEEK  _IOWR('H', 0x22, struct snd_emu10k1_fx8010_tram)
-#define SNDRV_EMU10K1_IOCTL_PCM_POKE   _IOW ('H', 0x30, struct snd_emu10k1_fx8010_pcm_rec)
-#define SNDRV_EMU10K1_IOCTL_PCM_PEEK   _IOWR('H', 0x31, struct snd_emu10k1_fx8010_pcm_rec)
-#define SNDRV_EMU10K1_IOCTL_PVERSION   _IOR ('H', 0x40, int)
-#define SNDRV_EMU10K1_IOCTL_STOP       _IO  ('H', 0x80)
-#define SNDRV_EMU10K1_IOCTL_CONTINUE   _IO  ('H', 0x81)
-#define SNDRV_EMU10K1_IOCTL_ZERO_TRAM_COUNTER _IO ('H', 0x82)
-#define SNDRV_EMU10K1_IOCTL_SINGLE_STEP        _IOW ('H', 0x83, int)
-#define SNDRV_EMU10K1_IOCTL_DBG_READ   _IOR ('H', 0x84, int)
-
-/* typedefs for compatibility to user-space */
-typedef struct snd_emu10k1_fx8010_info emu10k1_fx8010_info_t;
-typedef struct snd_emu10k1_fx8010_control_gpr emu10k1_fx8010_control_gpr_t;
-typedef struct snd_emu10k1_fx8010_code emu10k1_fx8010_code_t;
-typedef struct snd_emu10k1_fx8010_tram emu10k1_fx8010_tram_t;
-typedef struct snd_emu10k1_fx8010_pcm_rec emu10k1_fx8010_pcm_t;
-
 #endif /* __SOUND_EMU10K1_H */
index 6268a4192d5c4a3300a5792ceb08610386b9256d..45c1981c9ca2b67fa7fb5ce76f609a87bc5a08a4 100644 (file)
@@ -71,6 +71,8 @@ struct snd_pcm_ops {
        int (*prepare)(struct snd_pcm_substream *substream);
        int (*trigger)(struct snd_pcm_substream *substream, int cmd);
        snd_pcm_uframes_t (*pointer)(struct snd_pcm_substream *substream);
+       int (*wall_clock)(struct snd_pcm_substream *substream,
+                         struct timespec *audio_ts);
        int (*copy)(struct snd_pcm_substream *substream, int channel,
                    snd_pcm_uframes_t pos,
                    void __user *buf, snd_pcm_uframes_t count);
@@ -281,6 +283,7 @@ struct snd_pcm_runtime {
        unsigned long hw_ptr_jiffies;   /* Time when hw_ptr is updated */
        unsigned long hw_ptr_buffer_jiffies; /* buffer time in jiffies */
        snd_pcm_sframes_t delay;        /* extra delay; typically FIFO size */
+       u64 hw_ptr_wrap;                /* offset for hw_ptr due to boundary wrap-around */
 
        /* -- HW params -- */
        snd_pcm_access_t access;        /* access mode */
index 7e950560e5912dc8e1b20dc58b31c795fb94d6e5..c7c7788005e460bd8c41615ae5f86f4854839349 100644 (file)
@@ -1,6 +1,3 @@
-#ifndef __SOUND_SB16_CSP_H
-#define __SOUND_SB16_CSP_H
-
 /*
  *  Copyright (c) 1999 by Uros Bizjak <uros@kss-loka.si>
  *                        Takashi Iwai <tiwai@suse.de>
  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  *
  */
+#ifndef __SOUND_SB16_CSP_H
+#define __SOUND_SB16_CSP_H
 
-/* CSP modes */
-#define SNDRV_SB_CSP_MODE_NONE         0x00
-#define SNDRV_SB_CSP_MODE_DSP_READ     0x01    /* Record from DSP */
-#define SNDRV_SB_CSP_MODE_DSP_WRITE    0x02    /* Play to DSP */
-#define SNDRV_SB_CSP_MODE_QSOUND               0x04    /* QSound */
-
-/* CSP load flags */
-#define SNDRV_SB_CSP_LOAD_FROMUSER     0x01
-#define SNDRV_SB_CSP_LOAD_INITBLOCK    0x02
-
-/* CSP sample width */
-#define SNDRV_SB_CSP_SAMPLE_8BIT               0x01
-#define SNDRV_SB_CSP_SAMPLE_16BIT              0x02
-
-/* CSP channels */
-#define SNDRV_SB_CSP_MONO                      0x01
-#define SNDRV_SB_CSP_STEREO            0x02
-
-/* CSP rates */
-#define SNDRV_SB_CSP_RATE_8000         0x01
-#define SNDRV_SB_CSP_RATE_11025                0x02
-#define SNDRV_SB_CSP_RATE_22050                0x04
-#define SNDRV_SB_CSP_RATE_44100                0x08
-#define SNDRV_SB_CSP_RATE_ALL          0x0f
-
-/* CSP running state */
-#define SNDRV_SB_CSP_ST_IDLE           0x00
-#define SNDRV_SB_CSP_ST_LOADED         0x01
-#define SNDRV_SB_CSP_ST_RUNNING                0x02
-#define SNDRV_SB_CSP_ST_PAUSED         0x04
-#define SNDRV_SB_CSP_ST_AUTO           0x08
-#define SNDRV_SB_CSP_ST_QSOUND         0x10
-
-/* maximum QSound value (180 degrees right) */
-#define SNDRV_SB_CSP_QSOUND_MAX_RIGHT  0x20
-
-/* maximum microcode RIFF file size */
-#define SNDRV_SB_CSP_MAX_MICROCODE_FILE_SIZE   0x3000
-
-/* microcode header */
-struct snd_sb_csp_mc_header {
-       char codec_name[16];            /* id name of codec */
-       unsigned short func_req;        /* requested function */
-};
-
-/* microcode to be loaded */
-struct snd_sb_csp_microcode {
-       struct snd_sb_csp_mc_header info;
-       unsigned char data[SNDRV_SB_CSP_MAX_MICROCODE_FILE_SIZE];
-};
-
-/* start CSP with sample_width in mono/stereo */
-struct snd_sb_csp_start {
-       int sample_width;       /* sample width, look above */
-       int channels;           /* channels, look above */
-};
-
-/* CSP information */
-struct snd_sb_csp_info {
-       char codec_name[16];            /* id name of codec */
-       unsigned short func_nr;         /* function number */
-       unsigned int acc_format;        /* accepted PCM formats */
-       unsigned short acc_channels;    /* accepted channels */
-       unsigned short acc_width;       /* accepted sample width */
-       unsigned short acc_rates;       /* accepted sample rates */
-       unsigned short csp_mode;        /* CSP mode, see above */
-       unsigned short run_channels;    /* current channels  */
-       unsigned short run_width;       /* current sample width */
-       unsigned short version;         /* version id: 0x10 - 0x1f */
-       unsigned short state;           /* state bits */
-};
-
-/* HWDEP controls */
-/* get CSP information */
-#define SNDRV_SB_CSP_IOCTL_INFO                _IOR('H', 0x10, struct snd_sb_csp_info)
-/* load microcode to CSP */
-/* NOTE: struct snd_sb_csp_microcode overflows the max size (13 bits)
- * defined for some architectures like MIPS, and it leads to build errors.
- * (x86 and co have 14-bit size, thus it's valid, though.)
- * As a workaround for skipping the size-limit check, here we don't use the
- * normal _IOW() macro but _IOC() with the manual argument.
- */
-#define SNDRV_SB_CSP_IOCTL_LOAD_CODE   \
-       _IOC(_IOC_WRITE, 'H', 0x11, sizeof(struct snd_sb_csp_microcode))
-/* unload microcode from CSP */
-#define SNDRV_SB_CSP_IOCTL_UNLOAD_CODE _IO('H', 0x12)
-/* start CSP */
-#define SNDRV_SB_CSP_IOCTL_START               _IOW('H', 0x13, struct snd_sb_csp_start)
-/* stop CSP */
-#define SNDRV_SB_CSP_IOCTL_STOP                _IO('H', 0x14)
-/* pause CSP and DMA transfer */
-#define SNDRV_SB_CSP_IOCTL_PAUSE               _IO('H', 0x15)
-/* restart CSP and DMA transfer */
-#define SNDRV_SB_CSP_IOCTL_RESTART     _IO('H', 0x16)
-
-#ifdef __KERNEL__
 #include <sound/sb.h>
 #include <sound/hwdep.h>
 #include <linux/firmware.h>
+#include <uapi/sound/sb16_csp.h>
 
 struct snd_sb_csp;
 
@@ -183,6 +87,4 @@ struct snd_sb_csp {
 };
 
 int snd_sb_csp_new(struct snd_sb *chip, int device, struct snd_hwdep ** rhwdep);
-#endif
-
 #endif /* __SOUND_SB16_CSP */
index 6e595ba545f4f6eaa0125bb585db6cad90914f78..2c531f478410b056f2d07ee7ac5b12f6c7c943d7 100644 (file)
@@ -690,9 +690,11 @@ __SC_COMP(__NR_process_vm_writev, sys_process_vm_writev, \
           compat_sys_process_vm_writev)
 #define __NR_kcmp 272
 __SYSCALL(__NR_kcmp, sys_kcmp)
+#define __NR_finit_module 273
+__SYSCALL(__NR_finit_module, sys_finit_module)
 
 #undef __NR_syscalls
-#define __NR_syscalls 273
+#define __NR_syscalls 274
 
 /*
  * All syscalls below here should go away really,
index d8c713e148e3a5c15fc166e507fe811210872027..5dc1fea49ecdc5216747a87b0fd994f73ac5cef1 100644 (file)
@@ -193,6 +193,7 @@ struct fuse_file_lock {
 #define FUSE_FLOCK_LOCKS       (1 << 10)
 #define FUSE_HAS_IOCTL_DIR     (1 << 11)
 #define FUSE_AUTO_INVAL_DATA   (1 << 12)
+#define FUSE_DO_READDIRPLUS    (1 << 13)
 
 /**
  * CUSE INIT request/reply flags
@@ -299,6 +300,7 @@ enum fuse_opcode {
        FUSE_NOTIFY_REPLY  = 41,
        FUSE_BATCH_FORGET  = 42,
        FUSE_FALLOCATE     = 43,
+       FUSE_READDIRPLUS   = 44,
 
        /* CUSE specific operations */
        CUSE_INIT          = 4096,
@@ -630,6 +632,16 @@ struct fuse_dirent {
 #define FUSE_DIRENT_SIZE(d) \
        FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET + (d)->namelen)
 
+struct fuse_direntplus {
+       struct fuse_entry_out entry_out;
+       struct fuse_dirent dirent;
+};
+
+#define FUSE_NAME_OFFSET_DIRENTPLUS \
+       offsetof(struct fuse_direntplus, dirent.name)
+#define FUSE_DIRENTPLUS_SIZE(d) \
+       FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET_DIRENTPLUS + (d)->dirent.namelen)
+
 struct fuse_notify_inval_inode_out {
        __u64   ino;
        __s64   off;
index aafaa5aa54d46bb9a93a8137a22344408298223f..30ab3cd3b8a55b7f347eda392cae4578645af9e0 100644 (file)
@@ -1 +1,2 @@
 # UAPI Header export list
+header-y += hsi_char.h
index 8c469af939aab33a2117d7361e247371c6303750..bbde90fa58380bb6d6940d9ec7454af7a4d55608 100644 (file)
@@ -109,9 +109,10 @@ enum {
        INET_DIAG_TOS,
        INET_DIAG_TCLASS,
        INET_DIAG_SKMEMINFO,
+       INET_DIAG_SHUTDOWN,
 };
 
-#define INET_DIAG_MAX INET_DIAG_SKMEMINFO
+#define INET_DIAG_MAX INET_DIAG_SHUTDOWN
 
 
 /* INET_DIAG_MEM */
index 0a6d6ba44c858959cd2ed6b912751c5f36810989..65ad5c624c70d3867426229fa67584bd9bb0592d 100644 (file)
@@ -167,6 +167,7 @@ struct kvm_pit_config {
 #define KVM_EXIT_OSI              18
 #define KVM_EXIT_PAPR_HCALL      19
 #define KVM_EXIT_S390_UCONTROL   20
+#define KVM_EXIT_WATCHDOG         21
 
 /* For KVM_EXIT_INTERNAL_ERROR */
 #define KVM_INTERNAL_ERROR_EMULATION 1
@@ -477,6 +478,8 @@ struct kvm_ppc_smmu_info {
        struct kvm_ppc_one_seg_page_size sps[KVM_PPC_PAGE_SIZES_MAX_SZ];
 };
 
+#define KVM_PPC_PVINFO_FLAGS_EV_IDLE   (1<<0)
+
 #define KVMIO 0xAE
 
 /* machine type bits, to be used as argument to KVM_CREATE_VM */
@@ -626,6 +629,7 @@ struct kvm_ppc_smmu_info {
 #define KVM_CAP_READONLY_MEM 81
 #endif
 #define KVM_CAP_IRQFD_RESAMPLE 82
+#define KVM_CAP_PPC_BOOKE_WATCHDOG 83
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
@@ -848,6 +852,9 @@ struct kvm_s390_ucas_mapping {
 #define KVM_PPC_GET_SMMU_INFO    _IOR(KVMIO,  0xa6, struct kvm_ppc_smmu_info)
 /* Available with KVM_CAP_PPC_ALLOC_HTAB */
 #define KVM_PPC_ALLOCATE_HTAB    _IOWR(KVMIO, 0xa7, __u32)
+#define KVM_CREATE_SPAPR_TCE     _IOW(KVMIO,  0xa8, struct kvm_create_spapr_tce)
+/* Available with KVM_CAP_RMA */
+#define KVM_ALLOCATE_RMA         _IOR(KVMIO,  0xa9, struct kvm_allocate_rma)
 
 /*
  * ioctls for vcpu fds
@@ -911,9 +918,6 @@ struct kvm_s390_ucas_mapping {
 /* Available with KVM_CAP_XCRS */
 #define KVM_GET_XCRS             _IOR(KVMIO,  0xa6, struct kvm_xcrs)
 #define KVM_SET_XCRS             _IOW(KVMIO,  0xa7, struct kvm_xcrs)
-#define KVM_CREATE_SPAPR_TCE     _IOW(KVMIO,  0xa8, struct kvm_create_spapr_tce)
-/* Available with KVM_CAP_RMA */
-#define KVM_ALLOCATE_RMA         _IOR(KVMIO,  0xa9, struct kvm_allocate_rma)
 /* Available with KVM_CAP_SW_TLB */
 #define KVM_DIRTY_TLB            _IOW(KVMIO,  0xaa, struct kvm_dirty_tlb)
 /* Available with KVM_CAP_ONE_REG */
index 23e62e0537e2d1080f0c78ce2ffb946a23264676..a2bcd04a48ff0a213b8cb1cc64f0db55ec18cd13 100644 (file)
@@ -20,6 +20,8 @@ enum {
        MPOL_PREFERRED,
        MPOL_BIND,
        MPOL_INTERLEAVE,
+       MPOL_LOCAL,
+       MPOL_NOOP,              /* retain existing policy for range */
        MPOL_MAX,       /* always last member of enum */
 };
 
@@ -47,9 +49,16 @@ enum mpol_rebind_step {
 
 /* Flags for mbind */
 #define MPOL_MF_STRICT (1<<0)  /* Verify existing pages in the mapping */
-#define MPOL_MF_MOVE   (1<<1)  /* Move pages owned by this process to conform to mapping */
-#define MPOL_MF_MOVE_ALL (1<<2)        /* Move every page to conform to mapping */
-#define MPOL_MF_INTERNAL (1<<3)        /* Internal flags start here */
+#define MPOL_MF_MOVE    (1<<1) /* Move pages owned by this process to conform
+                                  to policy */
+#define MPOL_MF_MOVE_ALL (1<<2)        /* Move every page to conform to policy */
+#define MPOL_MF_LAZY    (1<<3) /* Modifies '_MOVE:  lazy migrate on fault */
+#define MPOL_MF_INTERNAL (1<<4)        /* Internal flags start here */
+
+#define MPOL_MF_VALID  (MPOL_MF_STRICT   |     \
+                        MPOL_MF_MOVE     |     \
+                        MPOL_MF_MOVE_ALL |     \
+                        MPOL_MF_LAZY)
 
 /*
  * Internal flags that share the struct mempolicy flags word with
@@ -59,6 +68,8 @@ enum mpol_rebind_step {
 #define MPOL_F_SHARED  (1 << 0)        /* identify shared policies */
 #define MPOL_F_LOCAL   (1 << 1)        /* preferred local allocation */
 #define MPOL_F_REBINDING (1 << 2)      /* identify policies in rebinding */
+#define MPOL_F_MOF     (1 << 3) /* this policy wants migrate on fault */
+#define MPOL_F_HOME    (1 << 4) /* this is the home-node policy */
 
 
 #endif /* _UAPI_LINUX_MEMPOLICY_H */
index 7df9b500c80493e944591a2192b07253f1b42669..617d0fbfc96f43ae51f372f6eec2b968e507e163 100644 (file)
@@ -1273,6 +1273,14 @@ enum nl80211_commands {
  *     the connection request from a station. nl80211_connect_failed_reason
  *     enum has different reasons of connection failure.
  *
+ * @NL80211_ATTR_SAE_DATA: SAE elements in Authentication frames. This starts
+ *     with the Authentication transaction sequence number field.
+ *
+ * @NL80211_ATTR_VHT_CAPABILITY: VHT Capability information element (from
+ *     association request when used with NL80211_CMD_NEW_STATION)
+ *
+ * @NL80211_ATTR_SCAN_FLAGS: scan request control flags (u32)
+ *
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
  */
@@ -1530,6 +1538,12 @@ enum nl80211_attrs {
 
        NL80211_ATTR_CONN_FAILED_REASON,
 
+       NL80211_ATTR_SAE_DATA,
+
+       NL80211_ATTR_VHT_CAPABILITY,
+
+       NL80211_ATTR_SCAN_FLAGS,
+
        /* add attributes here, update the policy in nl80211.c */
 
        __NL80211_ATTR_AFTER_LAST,
@@ -1573,6 +1587,7 @@ enum nl80211_attrs {
 #define NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY    16
 #define NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY    24
 #define NL80211_HT_CAPABILITY_LEN              26
+#define NL80211_VHT_CAPABILITY_LEN             12
 
 #define NL80211_MAX_NR_CIPHER_SUITES           5
 #define NL80211_MAX_NR_AKM_SUITES              2
@@ -2489,6 +2504,7 @@ enum nl80211_bss_status {
  * @NL80211_AUTHTYPE_SHARED_KEY: Shared Key authentication (WEP only)
  * @NL80211_AUTHTYPE_FT: Fast BSS Transition (IEEE 802.11r)
  * @NL80211_AUTHTYPE_NETWORK_EAP: Network EAP (some Cisco APs and mainly LEAP)
+ * @NL80211_AUTHTYPE_SAE: Simultaneous authentication of equals
  * @__NL80211_AUTHTYPE_NUM: internal
  * @NL80211_AUTHTYPE_MAX: maximum valid auth algorithm
  * @NL80211_AUTHTYPE_AUTOMATIC: determine automatically (if necessary by
@@ -2500,6 +2516,7 @@ enum nl80211_auth_type {
        NL80211_AUTHTYPE_SHARED_KEY,
        NL80211_AUTHTYPE_FT,
        NL80211_AUTHTYPE_NETWORK_EAP,
+       NL80211_AUTHTYPE_SAE,
 
        /* keep last */
        __NL80211_AUTHTYPE_NUM,
@@ -3028,6 +3045,12 @@ enum nl80211_ap_sme_features {
  *     in the interface combinations, even when it's only used for scan
  *     and remain-on-channel. This could be due to, for example, the
  *     remain-on-channel implementation requiring a channel context.
+ * @NL80211_FEATURE_SAE: This driver supports simultaneous authentication of
+ *     equals (SAE) with user space SME (NL80211_CMD_AUTHENTICATE) in station
+ *     mode
+ * @NL80211_FEATURE_LOW_PRIORITY_SCAN: This driver supports low priority scan
+ * @NL80211_FEATURE_SCAN_FLUSH: Scan flush is supported
+ * @NL80211_FEATURE_AP_SCAN: Support scanning using an AP vif
  */
 enum nl80211_feature_flags {
        NL80211_FEATURE_SK_TX_STATUS                    = 1 << 0,
@@ -3035,6 +3058,10 @@ enum nl80211_feature_flags {
        NL80211_FEATURE_INACTIVITY_TIMER                = 1 << 2,
        NL80211_FEATURE_CELL_BASE_REG_HINTS             = 1 << 3,
        NL80211_FEATURE_P2P_DEVICE_NEEDS_CHANNEL        = 1 << 4,
+       NL80211_FEATURE_SAE                             = 1 << 5,
+       NL80211_FEATURE_LOW_PRIORITY_SCAN               = 1 << 6,
+       NL80211_FEATURE_SCAN_FLUSH                      = 1 << 7,
+       NL80211_FEATURE_AP_SCAN                         = 1 << 8,
 };
 
 /**
@@ -3069,4 +3096,25 @@ enum nl80211_connect_failed_reason {
        NL80211_CONN_FAIL_BLOCKED_CLIENT,
 };
 
+/**
+ * enum nl80211_scan_flags -  scan request control flags
+ *
+ * Scan request control flags are used to control the handling
+ * of NL80211_CMD_TRIGGER_SCAN and NL80211_CMD_START_SCHED_SCAN
+ * requests.
+ *
+ * @NL80211_SCAN_FLAG_LOW_PRIORITY: scan request has low priority
+ * @NL80211_SCAN_FLAG_FLUSH: flush cache before scanning
+ * @NL80211_SCAN_FLAG_AP: force a scan even if the interface is configured
+ *     as AP and the beaconing has already been configured. This attribute is
+ *     dangerous because will destroy stations performance as a lot of frames
+ *     will be lost while scanning off-channel, therefore it must be used only
+ *     when really needed
+ */
+enum nl80211_scan_flags {
+       NL80211_SCAN_FLAG_LOW_PRIORITY                  = 1<<0,
+       NL80211_SCAN_FLAG_FLUSH                         = 1<<1,
+       NL80211_SCAN_FLAG_AP                            = 1<<2,
+};
+
 #endif /* __LINUX_NL80211_H */
index aafaa5aa54d46bb9a93a8137a22344408298223f..e2c3d25405d7e20de2dc708088b0399350bd861f 100644 (file)
@@ -1 +1,3 @@
 # UAPI Header export list
+header-y += md_p.h
+header-y += md_u.h
diff --git a/include/uapi/linux/raid/md_u.h b/include/uapi/linux/raid/md_u.h
new file mode 100644 (file)
index 0000000..4133e74
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+   md_u.h : user <=> kernel API between Linux raidtools and RAID drivers
+          Copyright (C) 1998 Ingo Molnar
+         
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+   
+   You should have received a copy of the GNU General Public License
+   (for example /usr/src/linux/COPYING); if not, write to the Free
+   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
+*/
+
+#ifndef _UAPI_MD_U_H
+#define _UAPI_MD_U_H
+
+/*
+ * Different major versions are not compatible.
+ * Different minor versions are only downward compatible.
+ * Different patchlevel versions are downward and upward compatible.
+ */
+#define MD_MAJOR_VERSION                0
+#define MD_MINOR_VERSION                90
+/*
+ * MD_PATCHLEVEL_VERSION indicates kernel functionality.
+ * >=1 means different superblock formats are selectable using SET_ARRAY_INFO
+ *     and major_version/minor_version accordingly
+ * >=2 means that Internal bitmaps are supported by setting MD_SB_BITMAP_PRESENT
+ *     in the super status byte
+ * >=3 means that bitmap superblock version 4 is supported, which uses
+ *     little-ending representation rather than host-endian
+ */
+#define MD_PATCHLEVEL_VERSION           3
+
+/* ioctls */
+
+/* status */
+#define RAID_VERSION           _IOR (MD_MAJOR, 0x10, mdu_version_t)
+#define GET_ARRAY_INFO         _IOR (MD_MAJOR, 0x11, mdu_array_info_t)
+#define GET_DISK_INFO          _IOR (MD_MAJOR, 0x12, mdu_disk_info_t)
+#define PRINT_RAID_DEBUG       _IO (MD_MAJOR, 0x13)
+#define RAID_AUTORUN           _IO (MD_MAJOR, 0x14)
+#define GET_BITMAP_FILE                _IOR (MD_MAJOR, 0x15, mdu_bitmap_file_t)
+
+/* configuration */
+#define CLEAR_ARRAY            _IO (MD_MAJOR, 0x20)
+#define ADD_NEW_DISK           _IOW (MD_MAJOR, 0x21, mdu_disk_info_t)
+#define HOT_REMOVE_DISK                _IO (MD_MAJOR, 0x22)
+#define SET_ARRAY_INFO         _IOW (MD_MAJOR, 0x23, mdu_array_info_t)
+#define SET_DISK_INFO          _IO (MD_MAJOR, 0x24)
+#define WRITE_RAID_INFO                _IO (MD_MAJOR, 0x25)
+#define UNPROTECT_ARRAY                _IO (MD_MAJOR, 0x26)
+#define PROTECT_ARRAY          _IO (MD_MAJOR, 0x27)
+#define HOT_ADD_DISK           _IO (MD_MAJOR, 0x28)
+#define SET_DISK_FAULTY                _IO (MD_MAJOR, 0x29)
+#define HOT_GENERATE_ERROR     _IO (MD_MAJOR, 0x2a)
+#define SET_BITMAP_FILE                _IOW (MD_MAJOR, 0x2b, int)
+
+/* usage */
+#define RUN_ARRAY              _IOW (MD_MAJOR, 0x30, mdu_param_t)
+/*  0x31 was START_ARRAY  */
+#define STOP_ARRAY             _IO (MD_MAJOR, 0x32)
+#define STOP_ARRAY_RO          _IO (MD_MAJOR, 0x33)
+#define RESTART_ARRAY_RW       _IO (MD_MAJOR, 0x34)
+
+/* 63 partitions with the alternate major number (mdp) */
+#define MdpMinorShift 6
+
+typedef struct mdu_version_s {
+       int major;
+       int minor;
+       int patchlevel;
+} mdu_version_t;
+
+typedef struct mdu_array_info_s {
+       /*
+        * Generic constant information
+        */
+       int major_version;
+       int minor_version;
+       int patch_version;
+       int ctime;
+       int level;
+       int size;
+       int nr_disks;
+       int raid_disks;
+       int md_minor;
+       int not_persistent;
+
+       /*
+        * Generic state information
+        */
+       int utime;              /*  0 Superblock update time                  */
+       int state;              /*  1 State bits (clean, ...)                 */
+       int active_disks;       /*  2 Number of currently active disks        */
+       int working_disks;      /*  3 Number of working disks                 */
+       int failed_disks;       /*  4 Number of failed disks                  */
+       int spare_disks;        /*  5 Number of spare disks                   */
+
+       /*
+        * Personality information
+        */
+       int layout;             /*  0 the array's physical layout             */
+       int chunk_size; /*  1 chunk size in bytes                     */
+
+} mdu_array_info_t;
+
+/* non-obvious values for 'level' */
+#define        LEVEL_MULTIPATH         (-4)
+#define        LEVEL_LINEAR            (-1)
+#define        LEVEL_FAULTY            (-5)
+
+/* we need a value for 'no level specified' and 0
+ * means 'raid0', so we need something else.  This is
+ * for internal use only
+ */
+#define        LEVEL_NONE              (-1000000)
+
+typedef struct mdu_disk_info_s {
+       /*
+        * configuration/status of one particular disk
+        */
+       int number;
+       int major;
+       int minor;
+       int raid_disk;
+       int state;
+
+} mdu_disk_info_t;
+
+typedef struct mdu_start_info_s {
+       /*
+        * configuration/status of one particular disk
+        */
+       int major;
+       int minor;
+       int raid_disk;
+       int state;
+
+} mdu_start_info_t;
+
+typedef struct mdu_bitmap_file_s
+{
+       char pathname[4096];
+} mdu_bitmap_file_t;
+
+typedef struct mdu_param_s
+{
+       int                     personality;    /* 1,2,3,4 */
+       int                     chunk_size;     /* in bytes */
+       int                     max_fault;      /* unused for now */
+} mdu_param_t;
+
+#endif /* _UAPI_MD_U_H */
index c4b89a5cb7df4ffa3f93a0206e1f03bf19829d31..e962faa5ab0dcf9d58909b0256a78f51029e290b 100644 (file)
@@ -130,6 +130,7 @@ enum {
 #define TCPI_OPT_WSCALE                4
 #define TCPI_OPT_ECN           8 /* ECN was negociated at TCP session init */
 #define TCPI_OPT_ECN_SEEN      16 /* we received at least one packet with ECT */
+#define TCPI_OPT_SYN_DATA      32 /* SYN-ACK acked data in SYN sent or rcvd */
 
 enum tcp_ca_state {
        TCP_CA_Open = 0,
index b1d2bf16b33c92fe4f5e27aafe5d34fe87d5fede..b8a24941db21e82b11d80d0912c057a54bcf7742 100644 (file)
@@ -37,6 +37,7 @@ enum {
        UNIX_DIAG_ICONS,
        UNIX_DIAG_RQLEN,
        UNIX_DIAG_MEMINFO,
+       UNIX_DIAG_SHUTDOWN,
 
        UNIX_DIAG_MAX,
 };
index aafaa5aa54d46bb9a93a8137a22344408298223f..6cb4ea8268349b44864c93d94960a6670059f4ed 100644 (file)
@@ -1 +1,11 @@
 # UAPI Header export list
+header-y += audio.h
+header-y += cdc.h
+header-y += ch11.h
+header-y += ch9.h
+header-y += functionfs.h
+header-y += g_printer.h
+header-y += gadgetfs.h
+header-y += midi.h
+header-y += tmc.h
+header-y += video.h
diff --git a/include/uapi/linux/usb/audio.h b/include/uapi/linux/usb/audio.h
new file mode 100644 (file)
index 0000000..ac90037
--- /dev/null
@@ -0,0 +1,545 @@
+/*
+ * <linux/usb/audio.h> -- USB Audio definitions.
+ *
+ * Copyright (C) 2006 Thumtronics Pty Ltd.
+ * Developed for Thumtronics by Grey Innovation
+ * Ben Williamson <ben.williamson@greyinnovation.com>
+ *
+ * This software is distributed under the terms of the GNU General Public
+ * License ("GPL") version 2, as published by the Free Software Foundation.
+ *
+ * This file holds USB constants and structures defined
+ * by the USB Device Class Definition for Audio Devices.
+ * Comments below reference relevant sections of that document:
+ *
+ * http://www.usb.org/developers/devclass_docs/audio10.pdf
+ *
+ * Types and defines in this file are either specific to version 1.0 of
+ * this standard or common for newer versions.
+ */
+
+#ifndef _UAPI__LINUX_USB_AUDIO_H
+#define _UAPI__LINUX_USB_AUDIO_H
+
+#include <linux/types.h>
+
+/* bInterfaceProtocol values to denote the version of the standard used */
+#define UAC_VERSION_1                  0x00
+#define UAC_VERSION_2                  0x20
+
+/* A.2 Audio Interface Subclass Codes */
+#define USB_SUBCLASS_AUDIOCONTROL      0x01
+#define USB_SUBCLASS_AUDIOSTREAMING    0x02
+#define USB_SUBCLASS_MIDISTREAMING     0x03
+
+/* A.5 Audio Class-Specific AC Interface Descriptor Subtypes */
+#define UAC_HEADER                     0x01
+#define UAC_INPUT_TERMINAL             0x02
+#define UAC_OUTPUT_TERMINAL            0x03
+#define UAC_MIXER_UNIT                 0x04
+#define UAC_SELECTOR_UNIT              0x05
+#define UAC_FEATURE_UNIT               0x06
+#define UAC1_PROCESSING_UNIT           0x07
+#define UAC1_EXTENSION_UNIT            0x08
+
+/* A.6 Audio Class-Specific AS Interface Descriptor Subtypes */
+#define UAC_AS_GENERAL                 0x01
+#define UAC_FORMAT_TYPE                        0x02
+#define UAC_FORMAT_SPECIFIC            0x03
+
+/* A.7 Processing Unit Process Types */
+#define UAC_PROCESS_UNDEFINED          0x00
+#define UAC_PROCESS_UP_DOWNMIX         0x01
+#define UAC_PROCESS_DOLBY_PROLOGIC     0x02
+#define UAC_PROCESS_STEREO_EXTENDER    0x03
+#define UAC_PROCESS_REVERB             0x04
+#define UAC_PROCESS_CHORUS             0x05
+#define UAC_PROCESS_DYN_RANGE_COMP     0x06
+
+/* A.8 Audio Class-Specific Endpoint Descriptor Subtypes */
+#define UAC_EP_GENERAL                 0x01
+
+/* A.9 Audio Class-Specific Request Codes */
+#define UAC_SET_                       0x00
+#define UAC_GET_                       0x80
+
+#define UAC__CUR                       0x1
+#define UAC__MIN                       0x2
+#define UAC__MAX                       0x3
+#define UAC__RES                       0x4
+#define UAC__MEM                       0x5
+
+#define UAC_SET_CUR                    (UAC_SET_ | UAC__CUR)
+#define UAC_GET_CUR                    (UAC_GET_ | UAC__CUR)
+#define UAC_SET_MIN                    (UAC_SET_ | UAC__MIN)
+#define UAC_GET_MIN                    (UAC_GET_ | UAC__MIN)
+#define UAC_SET_MAX                    (UAC_SET_ | UAC__MAX)
+#define UAC_GET_MAX                    (UAC_GET_ | UAC__MAX)
+#define UAC_SET_RES                    (UAC_SET_ | UAC__RES)
+#define UAC_GET_RES                    (UAC_GET_ | UAC__RES)
+#define UAC_SET_MEM                    (UAC_SET_ | UAC__MEM)
+#define UAC_GET_MEM                    (UAC_GET_ | UAC__MEM)
+
+#define UAC_GET_STAT                   0xff
+
+/* A.10 Control Selector Codes */
+
+/* A.10.1 Terminal Control Selectors */
+#define UAC_TERM_COPY_PROTECT          0x01
+
+/* A.10.2 Feature Unit Control Selectors */
+#define UAC_FU_MUTE                    0x01
+#define UAC_FU_VOLUME                  0x02
+#define UAC_FU_BASS                    0x03
+#define UAC_FU_MID                     0x04
+#define UAC_FU_TREBLE                  0x05
+#define UAC_FU_GRAPHIC_EQUALIZER       0x06
+#define UAC_FU_AUTOMATIC_GAIN          0x07
+#define UAC_FU_DELAY                   0x08
+#define UAC_FU_BASS_BOOST              0x09
+#define UAC_FU_LOUDNESS                        0x0a
+
+#define UAC_CONTROL_BIT(CS)    (1 << ((CS) - 1))
+
+/* A.10.3.1 Up/Down-mix Processing Unit Controls Selectors */
+#define UAC_UD_ENABLE                  0x01
+#define UAC_UD_MODE_SELECT             0x02
+
+/* A.10.3.2 Dolby Prologic (tm) Processing Unit Controls Selectors */
+#define UAC_DP_ENABLE                  0x01
+#define UAC_DP_MODE_SELECT             0x02
+
+/* A.10.3.3 3D Stereo Extender Processing Unit Control Selectors */
+#define UAC_3D_ENABLE                  0x01
+#define UAC_3D_SPACE                   0x02
+
+/* A.10.3.4 Reverberation Processing Unit Control Selectors */
+#define UAC_REVERB_ENABLE              0x01
+#define UAC_REVERB_LEVEL               0x02
+#define UAC_REVERB_TIME                        0x03
+#define UAC_REVERB_FEEDBACK            0x04
+
+/* A.10.3.5 Chorus Processing Unit Control Selectors */
+#define UAC_CHORUS_ENABLE              0x01
+#define UAC_CHORUS_LEVEL               0x02
+#define UAC_CHORUS_RATE                        0x03
+#define UAC_CHORUS_DEPTH               0x04
+
+/* A.10.3.6 Dynamic Range Compressor Unit Control Selectors */
+#define UAC_DCR_ENABLE                 0x01
+#define UAC_DCR_RATE                   0x02
+#define UAC_DCR_MAXAMPL                        0x03
+#define UAC_DCR_THRESHOLD              0x04
+#define UAC_DCR_ATTACK_TIME            0x05
+#define UAC_DCR_RELEASE_TIME           0x06
+
+/* A.10.4 Extension Unit Control Selectors */
+#define UAC_XU_ENABLE                  0x01
+
+/* MIDI - A.1 MS Class-Specific Interface Descriptor Subtypes */
+#define UAC_MS_HEADER                  0x01
+#define UAC_MIDI_IN_JACK               0x02
+#define UAC_MIDI_OUT_JACK              0x03
+
+/* MIDI - A.1 MS Class-Specific Endpoint Descriptor Subtypes */
+#define UAC_MS_GENERAL                 0x01
+
+/* Terminals - 2.1 USB Terminal Types */
+#define UAC_TERMINAL_UNDEFINED         0x100
+#define UAC_TERMINAL_STREAMING         0x101
+#define UAC_TERMINAL_VENDOR_SPEC       0x1FF
+
+/* Terminal Control Selectors */
+/* 4.3.2  Class-Specific AC Interface Descriptor */
+struct uac1_ac_header_descriptor {
+       __u8  bLength;                  /* 8 + n */
+       __u8  bDescriptorType;          /* USB_DT_CS_INTERFACE */
+       __u8  bDescriptorSubtype;       /* UAC_MS_HEADER */
+       __le16 bcdADC;                  /* 0x0100 */
+       __le16 wTotalLength;            /* includes Unit and Terminal desc. */
+       __u8  bInCollection;            /* n */
+       __u8  baInterfaceNr[];          /* [n] */
+} __attribute__ ((packed));
+
+#define UAC_DT_AC_HEADER_SIZE(n)       (8 + (n))
+
+/* As above, but more useful for defining your own descriptors: */
+#define DECLARE_UAC_AC_HEADER_DESCRIPTOR(n)                    \
+struct uac1_ac_header_descriptor_##n {                 \
+       __u8  bLength;                                          \
+       __u8  bDescriptorType;                                  \
+       __u8  bDescriptorSubtype;                               \
+       __le16 bcdADC;                                          \
+       __le16 wTotalLength;                                    \
+       __u8  bInCollection;                                    \
+       __u8  baInterfaceNr[n];                                 \
+} __attribute__ ((packed))
+
+/* 4.3.2.1 Input Terminal Descriptor */
+struct uac_input_terminal_descriptor {
+       __u8  bLength;                  /* in bytes: 12 */
+       __u8  bDescriptorType;          /* CS_INTERFACE descriptor type */
+       __u8  bDescriptorSubtype;       /* INPUT_TERMINAL descriptor subtype */
+       __u8  bTerminalID;              /* Constant uniquely terminal ID */
+       __le16 wTerminalType;           /* USB Audio Terminal Types */
+       __u8  bAssocTerminal;           /* ID of the Output Terminal associated */
+       __u8  bNrChannels;              /* Number of logical output channels */
+       __le16 wChannelConfig;
+       __u8  iChannelNames;
+       __u8  iTerminal;
+} __attribute__ ((packed));
+
+#define UAC_DT_INPUT_TERMINAL_SIZE                     12
+
+/* Terminals - 2.2 Input Terminal Types */
+#define UAC_INPUT_TERMINAL_UNDEFINED                   0x200
+#define UAC_INPUT_TERMINAL_MICROPHONE                  0x201
+#define UAC_INPUT_TERMINAL_DESKTOP_MICROPHONE          0x202
+#define UAC_INPUT_TERMINAL_PERSONAL_MICROPHONE         0x203
+#define UAC_INPUT_TERMINAL_OMNI_DIR_MICROPHONE         0x204
+#define UAC_INPUT_TERMINAL_MICROPHONE_ARRAY            0x205
+#define UAC_INPUT_TERMINAL_PROC_MICROPHONE_ARRAY       0x206
+
+/* Terminals - control selectors */
+
+#define UAC_TERMINAL_CS_COPY_PROTECT_CONTROL           0x01
+
+/* 4.3.2.2 Output Terminal Descriptor */
+struct uac1_output_terminal_descriptor {
+       __u8  bLength;                  /* in bytes: 9 */
+       __u8  bDescriptorType;          /* CS_INTERFACE descriptor type */
+       __u8  bDescriptorSubtype;       /* OUTPUT_TERMINAL descriptor subtype */
+       __u8  bTerminalID;              /* Constant uniquely terminal ID */
+       __le16 wTerminalType;           /* USB Audio Terminal Types */
+       __u8  bAssocTerminal;           /* ID of the Input Terminal associated */
+       __u8  bSourceID;                /* ID of the connected Unit or Terminal*/
+       __u8  iTerminal;
+} __attribute__ ((packed));
+
+#define UAC_DT_OUTPUT_TERMINAL_SIZE                    9
+
+/* Terminals - 2.3 Output Terminal Types */
+#define UAC_OUTPUT_TERMINAL_UNDEFINED                  0x300
+#define UAC_OUTPUT_TERMINAL_SPEAKER                    0x301
+#define UAC_OUTPUT_TERMINAL_HEADPHONES                 0x302
+#define UAC_OUTPUT_TERMINAL_HEAD_MOUNTED_DISPLAY_AUDIO 0x303
+#define UAC_OUTPUT_TERMINAL_DESKTOP_SPEAKER            0x304
+#define UAC_OUTPUT_TERMINAL_ROOM_SPEAKER               0x305
+#define UAC_OUTPUT_TERMINAL_COMMUNICATION_SPEAKER      0x306
+#define UAC_OUTPUT_TERMINAL_LOW_FREQ_EFFECTS_SPEAKER   0x307
+
+/* Set bControlSize = 2 as default setting */
+#define UAC_DT_FEATURE_UNIT_SIZE(ch)           (7 + ((ch) + 1) * 2)
+
+/* As above, but more useful for defining your own descriptors: */
+#define DECLARE_UAC_FEATURE_UNIT_DESCRIPTOR(ch)                        \
+struct uac_feature_unit_descriptor_##ch {                      \
+       __u8  bLength;                                          \
+       __u8  bDescriptorType;                                  \
+       __u8  bDescriptorSubtype;                               \
+       __u8  bUnitID;                                          \
+       __u8  bSourceID;                                        \
+       __u8  bControlSize;                                     \
+       __le16 bmaControls[ch + 1];                             \
+       __u8  iFeature;                                         \
+} __attribute__ ((packed))
+
+/* 4.3.2.3 Mixer Unit Descriptor */
+struct uac_mixer_unit_descriptor {
+       __u8 bLength;
+       __u8 bDescriptorType;
+       __u8 bDescriptorSubtype;
+       __u8 bUnitID;
+       __u8 bNrInPins;
+       __u8 baSourceID[];
+} __attribute__ ((packed));
+
+static inline __u8 uac_mixer_unit_bNrChannels(struct uac_mixer_unit_descriptor *desc)
+{
+       return desc->baSourceID[desc->bNrInPins];
+}
+
+static inline __u32 uac_mixer_unit_wChannelConfig(struct uac_mixer_unit_descriptor *desc,
+                                                 int protocol)
+{
+       if (protocol == UAC_VERSION_1)
+               return (desc->baSourceID[desc->bNrInPins + 2] << 8) |
+                       desc->baSourceID[desc->bNrInPins + 1];
+       else
+               return  (desc->baSourceID[desc->bNrInPins + 4] << 24) |
+                       (desc->baSourceID[desc->bNrInPins + 3] << 16) |
+                       (desc->baSourceID[desc->bNrInPins + 2] << 8)  |
+                       (desc->baSourceID[desc->bNrInPins + 1]);
+}
+
+static inline __u8 uac_mixer_unit_iChannelNames(struct uac_mixer_unit_descriptor *desc,
+                                               int protocol)
+{
+       return (protocol == UAC_VERSION_1) ?
+               desc->baSourceID[desc->bNrInPins + 3] :
+               desc->baSourceID[desc->bNrInPins + 5];
+}
+
+static inline __u8 *uac_mixer_unit_bmControls(struct uac_mixer_unit_descriptor *desc,
+                                             int protocol)
+{
+       return (protocol == UAC_VERSION_1) ?
+               &desc->baSourceID[desc->bNrInPins + 4] :
+               &desc->baSourceID[desc->bNrInPins + 6];
+}
+
+static inline __u8 uac_mixer_unit_iMixer(struct uac_mixer_unit_descriptor *desc)
+{
+       __u8 *raw = (__u8 *) desc;
+       return raw[desc->bLength - 1];
+}
+
+/* 4.3.2.4 Selector Unit Descriptor */
+struct uac_selector_unit_descriptor {
+       __u8 bLength;
+       __u8 bDescriptorType;
+       __u8 bDescriptorSubtype;
+       __u8 bUintID;
+       __u8 bNrInPins;
+       __u8 baSourceID[];
+} __attribute__ ((packed));
+
+static inline __u8 uac_selector_unit_iSelector(struct uac_selector_unit_descriptor *desc)
+{
+       __u8 *raw = (__u8 *) desc;
+       return raw[desc->bLength - 1];
+}
+
+/* 4.3.2.5 Feature Unit Descriptor */
+struct uac_feature_unit_descriptor {
+       __u8 bLength;
+       __u8 bDescriptorType;
+       __u8 bDescriptorSubtype;
+       __u8 bUnitID;
+       __u8 bSourceID;
+       __u8 bControlSize;
+       __u8 bmaControls[0]; /* variable length */
+} __attribute__((packed));
+
+static inline __u8 uac_feature_unit_iFeature(struct uac_feature_unit_descriptor *desc)
+{
+       __u8 *raw = (__u8 *) desc;
+       return raw[desc->bLength - 1];
+}
+
+/* 4.3.2.6 Processing Unit Descriptors */
+struct uac_processing_unit_descriptor {
+       __u8 bLength;
+       __u8 bDescriptorType;
+       __u8 bDescriptorSubtype;
+       __u8 bUnitID;
+       __u16 wProcessType;
+       __u8 bNrInPins;
+       __u8 baSourceID[];
+} __attribute__ ((packed));
+
+static inline __u8 uac_processing_unit_bNrChannels(struct uac_processing_unit_descriptor *desc)
+{
+       return desc->baSourceID[desc->bNrInPins];
+}
+
+static inline __u32 uac_processing_unit_wChannelConfig(struct uac_processing_unit_descriptor *desc,
+                                                      int protocol)
+{
+       if (protocol == UAC_VERSION_1)
+               return (desc->baSourceID[desc->bNrInPins + 2] << 8) |
+                       desc->baSourceID[desc->bNrInPins + 1];
+       else
+               return  (desc->baSourceID[desc->bNrInPins + 4] << 24) |
+                       (desc->baSourceID[desc->bNrInPins + 3] << 16) |
+                       (desc->baSourceID[desc->bNrInPins + 2] << 8)  |
+                       (desc->baSourceID[desc->bNrInPins + 1]);
+}
+
+static inline __u8 uac_processing_unit_iChannelNames(struct uac_processing_unit_descriptor *desc,
+                                                    int protocol)
+{
+       return (protocol == UAC_VERSION_1) ?
+               desc->baSourceID[desc->bNrInPins + 3] :
+               desc->baSourceID[desc->bNrInPins + 5];
+}
+
+static inline __u8 uac_processing_unit_bControlSize(struct uac_processing_unit_descriptor *desc,
+                                                   int protocol)
+{
+       return (protocol == UAC_VERSION_1) ?
+               desc->baSourceID[desc->bNrInPins + 4] :
+               desc->baSourceID[desc->bNrInPins + 6];
+}
+
+static inline __u8 *uac_processing_unit_bmControls(struct uac_processing_unit_descriptor *desc,
+                                                  int protocol)
+{
+       return (protocol == UAC_VERSION_1) ?
+               &desc->baSourceID[desc->bNrInPins + 5] :
+               &desc->baSourceID[desc->bNrInPins + 7];
+}
+
+static inline __u8 uac_processing_unit_iProcessing(struct uac_processing_unit_descriptor *desc,
+                                                  int protocol)
+{
+       __u8 control_size = uac_processing_unit_bControlSize(desc, protocol);
+       return desc->baSourceID[desc->bNrInPins + control_size];
+}
+
+static inline __u8 *uac_processing_unit_specific(struct uac_processing_unit_descriptor *desc,
+                                                int protocol)
+{
+       __u8 control_size = uac_processing_unit_bControlSize(desc, protocol);
+       return &desc->baSourceID[desc->bNrInPins + control_size + 1];
+}
+
+/* 4.5.2 Class-Specific AS Interface Descriptor */
+struct uac1_as_header_descriptor {
+       __u8  bLength;                  /* in bytes: 7 */
+       __u8  bDescriptorType;          /* USB_DT_CS_INTERFACE */
+       __u8  bDescriptorSubtype;       /* AS_GENERAL */
+       __u8  bTerminalLink;            /* Terminal ID of connected Terminal */
+       __u8  bDelay;                   /* Delay introduced by the data path */
+       __le16 wFormatTag;              /* The Audio Data Format */
+} __attribute__ ((packed));
+
+#define UAC_DT_AS_HEADER_SIZE          7
+
+/* Formats - A.1.1 Audio Data Format Type I Codes */
+#define UAC_FORMAT_TYPE_I_UNDEFINED    0x0
+#define UAC_FORMAT_TYPE_I_PCM          0x1
+#define UAC_FORMAT_TYPE_I_PCM8         0x2
+#define UAC_FORMAT_TYPE_I_IEEE_FLOAT   0x3
+#define UAC_FORMAT_TYPE_I_ALAW         0x4
+#define UAC_FORMAT_TYPE_I_MULAW                0x5
+
+struct uac_format_type_i_continuous_descriptor {
+       __u8  bLength;                  /* in bytes: 8 + (ns * 3) */
+       __u8  bDescriptorType;          /* USB_DT_CS_INTERFACE */
+       __u8  bDescriptorSubtype;       /* FORMAT_TYPE */
+       __u8  bFormatType;              /* FORMAT_TYPE_1 */
+       __u8  bNrChannels;              /* physical channels in the stream */
+       __u8  bSubframeSize;            /* */
+       __u8  bBitResolution;
+       __u8  bSamFreqType;
+       __u8  tLowerSamFreq[3];
+       __u8  tUpperSamFreq[3];
+} __attribute__ ((packed));
+
+#define UAC_FORMAT_TYPE_I_CONTINUOUS_DESC_SIZE 14
+
+struct uac_format_type_i_discrete_descriptor {
+       __u8  bLength;                  /* in bytes: 8 + (ns * 3) */
+       __u8  bDescriptorType;          /* USB_DT_CS_INTERFACE */
+       __u8  bDescriptorSubtype;       /* FORMAT_TYPE */
+       __u8  bFormatType;              /* FORMAT_TYPE_1 */
+       __u8  bNrChannels;              /* physical channels in the stream */
+       __u8  bSubframeSize;            /* */
+       __u8  bBitResolution;
+       __u8  bSamFreqType;
+       __u8  tSamFreq[][3];
+} __attribute__ ((packed));
+
+#define DECLARE_UAC_FORMAT_TYPE_I_DISCRETE_DESC(n)             \
+struct uac_format_type_i_discrete_descriptor_##n {             \
+       __u8  bLength;                                          \
+       __u8  bDescriptorType;                                  \
+       __u8  bDescriptorSubtype;                               \
+       __u8  bFormatType;                                      \
+       __u8  bNrChannels;                                      \
+       __u8  bSubframeSize;                                    \
+       __u8  bBitResolution;                                   \
+       __u8  bSamFreqType;                                     \
+       __u8  tSamFreq[n][3];                                   \
+} __attribute__ ((packed))
+
+#define UAC_FORMAT_TYPE_I_DISCRETE_DESC_SIZE(n)        (8 + (n * 3))
+
+struct uac_format_type_i_ext_descriptor {
+       __u8 bLength;
+       __u8 bDescriptorType;
+       __u8 bDescriptorSubtype;
+       __u8 bFormatType;
+       __u8 bSubslotSize;
+       __u8 bBitResolution;
+       __u8 bHeaderLength;
+       __u8 bControlSize;
+       __u8 bSideBandProtocol;
+} __attribute__((packed));
+
+/* Formats - Audio Data Format Type I Codes */
+
+#define UAC_FORMAT_TYPE_II_MPEG        0x1001
+#define UAC_FORMAT_TYPE_II_AC3 0x1002
+
+struct uac_format_type_ii_discrete_descriptor {
+       __u8 bLength;
+       __u8 bDescriptorType;
+       __u8 bDescriptorSubtype;
+       __u8 bFormatType;
+       __le16 wMaxBitRate;
+       __le16 wSamplesPerFrame;
+       __u8 bSamFreqType;
+       __u8 tSamFreq[][3];
+} __attribute__((packed));
+
+struct uac_format_type_ii_ext_descriptor {
+       __u8 bLength;
+       __u8 bDescriptorType;
+       __u8 bDescriptorSubtype;
+       __u8 bFormatType;
+       __u16 wMaxBitRate;
+       __u16 wSamplesPerFrame;
+       __u8 bHeaderLength;
+       __u8 bSideBandProtocol;
+} __attribute__((packed));
+
+/* type III */
+#define UAC_FORMAT_TYPE_III_IEC1937_AC3        0x2001
+#define UAC_FORMAT_TYPE_III_IEC1937_MPEG1_LAYER1       0x2002
+#define UAC_FORMAT_TYPE_III_IEC1937_MPEG2_NOEXT        0x2003
+#define UAC_FORMAT_TYPE_III_IEC1937_MPEG2_EXT  0x2004
+#define UAC_FORMAT_TYPE_III_IEC1937_MPEG2_LAYER1_LS    0x2005
+#define UAC_FORMAT_TYPE_III_IEC1937_MPEG2_LAYER23_LS   0x2006
+
+/* Formats - A.2 Format Type Codes */
+#define UAC_FORMAT_TYPE_UNDEFINED      0x0
+#define UAC_FORMAT_TYPE_I              0x1
+#define UAC_FORMAT_TYPE_II             0x2
+#define UAC_FORMAT_TYPE_III            0x3
+#define UAC_EXT_FORMAT_TYPE_I          0x81
+#define UAC_EXT_FORMAT_TYPE_II         0x82
+#define UAC_EXT_FORMAT_TYPE_III                0x83
+
+struct uac_iso_endpoint_descriptor {
+       __u8  bLength;                  /* in bytes: 7 */
+       __u8  bDescriptorType;          /* USB_DT_CS_ENDPOINT */
+       __u8  bDescriptorSubtype;       /* EP_GENERAL */
+       __u8  bmAttributes;
+       __u8  bLockDelayUnits;
+       __le16 wLockDelay;
+} __attribute__((packed));
+#define UAC_ISO_ENDPOINT_DESC_SIZE     7
+
+#define UAC_EP_CS_ATTR_SAMPLE_RATE     0x01
+#define UAC_EP_CS_ATTR_PITCH_CONTROL   0x02
+#define UAC_EP_CS_ATTR_FILL_MAX                0x80
+
+/* status word format (3.7.1.1) */
+
+#define UAC1_STATUS_TYPE_ORIG_MASK             0x0f
+#define UAC1_STATUS_TYPE_ORIG_AUDIO_CONTROL_IF 0x0
+#define UAC1_STATUS_TYPE_ORIG_AUDIO_STREAM_IF  0x1
+#define UAC1_STATUS_TYPE_ORIG_AUDIO_STREAM_EP  0x2
+
+#define UAC1_STATUS_TYPE_IRQ_PENDING           (1 << 7)
+#define UAC1_STATUS_TYPE_MEM_CHANGED           (1 << 6)
+
+struct uac1_status_word {
+       __u8 bStatusType;
+       __u8 bOriginator;
+} __attribute__((packed));
+
+
+#endif /* _UAPI__LINUX_USB_AUDIO_H */
similarity index 93%
rename from include/linux/usb/cdc.h
rename to include/uapi/linux/usb/cdc.h
index 81a927930bfd35a68f57bff638d662da9d6f6cf8..f35aa0a338c7610d89aa7f9e92e47d7e3a0de0a2 100644 (file)
@@ -19,6 +19,7 @@
 #define USB_CDC_SUBCLASS_OBEX                  0x0b
 #define USB_CDC_SUBCLASS_EEM                   0x0c
 #define USB_CDC_SUBCLASS_NCM                   0x0d
+#define USB_CDC_SUBCLASS_MBIM                  0x0e
 
 #define USB_CDC_PROTO_NONE                     0
 
@@ -33,6 +34,7 @@
 #define USB_CDC_PROTO_EEM                      7
 
 #define USB_CDC_NCM_PROTO_NTB                  1
+#define USB_CDC_MBIM_PROTO_NTB                 2
 
 /*-------------------------------------------------------------------------*/
 
@@ -53,6 +55,7 @@
 #define USB_CDC_DMM_TYPE               0x14
 #define USB_CDC_OBEX_TYPE              0x15
 #define USB_CDC_NCM_TYPE               0x1a
+#define USB_CDC_MBIM_TYPE              0x1b
 
 /* "Header Functional Descriptor" from CDC spec  5.2.3.1 */
 struct usb_cdc_header_desc {
@@ -187,6 +190,21 @@ struct usb_cdc_ncm_desc {
        __le16  bcdNcmVersion;
        __u8    bmNetworkCapabilities;
 } __attribute__ ((packed));
+
+/* "MBIM Control Model Functional Descriptor" */
+struct usb_cdc_mbim_desc {
+       __u8    bLength;
+       __u8    bDescriptorType;
+       __u8    bDescriptorSubType;
+
+       __le16  bcdMBIMVersion;
+       __le16  wMaxControlMessage;
+       __u8    bNumberFilters;
+       __u8    bMaxFilterSize;
+       __le16  wMaxSegmentSize;
+       __u8    bmNetworkCapabilities;
+} __attribute__ ((packed));
+
 /*-------------------------------------------------------------------------*/
 
 /*
@@ -332,6 +350,11 @@ struct usb_cdc_ncm_nth32 {
 #define USB_CDC_NCM_NDP32_CRC_SIGN     0x316D636E /* ncm1 */
 #define USB_CDC_NCM_NDP32_NOCRC_SIGN   0x306D636E /* ncm0 */
 
+#define USB_CDC_MBIM_NDP16_IPS_SIGN     0x00535049 /* IPS<sessionID> : IPS0 for now */
+#define USB_CDC_MBIM_NDP32_IPS_SIGN     0x00737069 /* ips<sessionID> : ips0 for now */
+#define USB_CDC_MBIM_NDP16_DSS_SIGN     0x00535344 /* DSS<sessionID> */
+#define USB_CDC_MBIM_NDP32_DSS_SIGN     0x00737364 /* dss<sessionID> */
+
 /* 16-bit NCM Datagram Pointer Entry */
 struct usb_cdc_ncm_dpe16 {
        __le16  wDatagramIndex;
diff --git a/include/uapi/linux/usb/ch9.h b/include/uapi/linux/usb/ch9.h
new file mode 100644 (file)
index 0000000..5059847
--- /dev/null
@@ -0,0 +1,993 @@
+/*
+ * This file holds USB constants and structures that are needed for
+ * USB device APIs.  These are used by the USB device model, which is
+ * defined in chapter 9 of the USB 2.0 specification and in the
+ * Wireless USB 1.0 (spread around).  Linux has several APIs in C that
+ * need these:
+ *
+ * - the master/host side Linux-USB kernel driver API;
+ * - the "usbfs" user space API; and
+ * - the Linux "gadget" slave/device/peripheral side driver API.
+ *
+ * USB 2.0 adds an additional "On The Go" (OTG) mode, which lets systems
+ * act either as a USB master/host or as a USB slave/device.  That means
+ * the master and slave side APIs benefit from working well together.
+ *
+ * There's also "Wireless USB", using low power short range radios for
+ * peripheral interconnection but otherwise building on the USB framework.
+ *
+ * Note all descriptors are declared '__attribute__((packed))' so that:
+ *
+ * [a] they never get padded, either internally (USB spec writers
+ *     probably handled that) or externally;
+ *
+ * [b] so that accessing bigger-than-a-bytes fields will never
+ *     generate bus errors on any platform, even when the location of
+ *     its descriptor inside a bundle isn't "naturally aligned", and
+ *
+ * [c] for consistency, removing all doubt even when it appears to
+ *     someone that the two other points are non-issues for that
+ *     particular descriptor type.
+ */
+
+#ifndef _UAPI__LINUX_USB_CH9_H
+#define _UAPI__LINUX_USB_CH9_H
+
+#include <linux/types.h>       /* __u8 etc */
+#include <asm/byteorder.h>     /* le16_to_cpu */
+
+/*-------------------------------------------------------------------------*/
+
+/* CONTROL REQUEST SUPPORT */
+
+/*
+ * USB directions
+ *
+ * This bit flag is used in endpoint descriptors' bEndpointAddress field.
+ * It's also one of three fields in control requests bRequestType.
+ */
+#define USB_DIR_OUT                    0               /* to device */
+#define USB_DIR_IN                     0x80            /* to host */
+
+/*
+ * USB types, the second of three bRequestType fields
+ */
+#define USB_TYPE_MASK                  (0x03 << 5)
+#define USB_TYPE_STANDARD              (0x00 << 5)
+#define USB_TYPE_CLASS                 (0x01 << 5)
+#define USB_TYPE_VENDOR                        (0x02 << 5)
+#define USB_TYPE_RESERVED              (0x03 << 5)
+
+/*
+ * USB recipients, the third of three bRequestType fields
+ */
+#define USB_RECIP_MASK                 0x1f
+#define USB_RECIP_DEVICE               0x00
+#define USB_RECIP_INTERFACE            0x01
+#define USB_RECIP_ENDPOINT             0x02
+#define USB_RECIP_OTHER                        0x03
+/* From Wireless USB 1.0 */
+#define USB_RECIP_PORT                 0x04
+#define USB_RECIP_RPIPE                0x05
+
+/*
+ * Standard requests, for the bRequest field of a SETUP packet.
+ *
+ * These are qualified by the bRequestType field, so that for example
+ * TYPE_CLASS or TYPE_VENDOR specific feature flags could be retrieved
+ * by a GET_STATUS request.
+ */
+#define USB_REQ_GET_STATUS             0x00
+#define USB_REQ_CLEAR_FEATURE          0x01
+#define USB_REQ_SET_FEATURE            0x03
+#define USB_REQ_SET_ADDRESS            0x05
+#define USB_REQ_GET_DESCRIPTOR         0x06
+#define USB_REQ_SET_DESCRIPTOR         0x07
+#define USB_REQ_GET_CONFIGURATION      0x08
+#define USB_REQ_SET_CONFIGURATION      0x09
+#define USB_REQ_GET_INTERFACE          0x0A
+#define USB_REQ_SET_INTERFACE          0x0B
+#define USB_REQ_SYNCH_FRAME            0x0C
+#define USB_REQ_SET_SEL                        0x30
+#define USB_REQ_SET_ISOCH_DELAY                0x31
+
+#define USB_REQ_SET_ENCRYPTION         0x0D    /* Wireless USB */
+#define USB_REQ_GET_ENCRYPTION         0x0E
+#define USB_REQ_RPIPE_ABORT            0x0E
+#define USB_REQ_SET_HANDSHAKE          0x0F
+#define USB_REQ_RPIPE_RESET            0x0F
+#define USB_REQ_GET_HANDSHAKE          0x10
+#define USB_REQ_SET_CONNECTION         0x11
+#define USB_REQ_SET_SECURITY_DATA      0x12
+#define USB_REQ_GET_SECURITY_DATA      0x13
+#define USB_REQ_SET_WUSB_DATA          0x14
+#define USB_REQ_LOOPBACK_DATA_WRITE    0x15
+#define USB_REQ_LOOPBACK_DATA_READ     0x16
+#define USB_REQ_SET_INTERFACE_DS       0x17
+
+/* The Link Power Management (LPM) ECN defines USB_REQ_TEST_AND_SET command,
+ * used by hubs to put ports into a new L1 suspend state, except that it
+ * forgot to define its number ...
+ */
+
+/*
+ * USB feature flags are written using USB_REQ_{CLEAR,SET}_FEATURE, and
+ * are read as a bit array returned by USB_REQ_GET_STATUS.  (So there
+ * are at most sixteen features of each type.)  Hubs may also support a
+ * new USB_REQ_TEST_AND_SET_FEATURE to put ports into L1 suspend.
+ */
+#define USB_DEVICE_SELF_POWERED                0       /* (read only) */
+#define USB_DEVICE_REMOTE_WAKEUP       1       /* dev may initiate wakeup */
+#define USB_DEVICE_TEST_MODE           2       /* (wired high speed only) */
+#define USB_DEVICE_BATTERY             2       /* (wireless) */
+#define USB_DEVICE_B_HNP_ENABLE                3       /* (otg) dev may initiate HNP */
+#define USB_DEVICE_WUSB_DEVICE         3       /* (wireless)*/
+#define USB_DEVICE_A_HNP_SUPPORT       4       /* (otg) RH port supports HNP */
+#define USB_DEVICE_A_ALT_HNP_SUPPORT   5       /* (otg) other RH port does */
+#define USB_DEVICE_DEBUG_MODE          6       /* (special devices only) */
+
+/*
+ * Test Mode Selectors
+ * See USB 2.0 spec Table 9-7
+ */
+#define        TEST_J          1
+#define        TEST_K          2
+#define        TEST_SE0_NAK    3
+#define        TEST_PACKET     4
+#define        TEST_FORCE_EN   5
+
+/*
+ * New Feature Selectors as added by USB 3.0
+ * See USB 3.0 spec Table 9-6
+ */
+#define USB_DEVICE_U1_ENABLE   48      /* dev may initiate U1 transition */
+#define USB_DEVICE_U2_ENABLE   49      /* dev may initiate U2 transition */
+#define USB_DEVICE_LTM_ENABLE  50      /* dev may send LTM */
+#define USB_INTRF_FUNC_SUSPEND 0       /* function suspend */
+
+#define USB_INTR_FUNC_SUSPEND_OPT_MASK 0xFF00
+/*
+ * Suspend Options, Table 9-7 USB 3.0 spec
+ */
+#define USB_INTRF_FUNC_SUSPEND_LP      (1 << (8 + 0))
+#define USB_INTRF_FUNC_SUSPEND_RW      (1 << (8 + 1))
+
+#define USB_ENDPOINT_HALT              0       /* IN/OUT will STALL */
+
+/* Bit array elements as returned by the USB_REQ_GET_STATUS request. */
+#define USB_DEV_STAT_U1_ENABLED                2       /* transition into U1 state */
+#define USB_DEV_STAT_U2_ENABLED                3       /* transition into U2 state */
+#define USB_DEV_STAT_LTM_ENABLED       4       /* Latency tolerance messages */
+
+/**
+ * struct usb_ctrlrequest - SETUP data for a USB device control request
+ * @bRequestType: matches the USB bmRequestType field
+ * @bRequest: matches the USB bRequest field
+ * @wValue: matches the USB wValue field (le16 byte order)
+ * @wIndex: matches the USB wIndex field (le16 byte order)
+ * @wLength: matches the USB wLength field (le16 byte order)
+ *
+ * This structure is used to send control requests to a USB device.  It matches
+ * the different fields of the USB 2.0 Spec section 9.3, table 9-2.  See the
+ * USB spec for a fuller description of the different fields, and what they are
+ * used for.
+ *
+ * Note that the driver for any interface can issue control requests.
+ * For most devices, interfaces don't coordinate with each other, so
+ * such requests may be made at any time.
+ */
+struct usb_ctrlrequest {
+       __u8 bRequestType;
+       __u8 bRequest;
+       __le16 wValue;
+       __le16 wIndex;
+       __le16 wLength;
+} __attribute__ ((packed));
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * STANDARD DESCRIPTORS ... as returned by GET_DESCRIPTOR, or
+ * (rarely) accepted by SET_DESCRIPTOR.
+ *
+ * Note that all multi-byte values here are encoded in little endian
+ * byte order "on the wire".  Within the kernel and when exposed
+ * through the Linux-USB APIs, they are not converted to cpu byte
+ * order; it is the responsibility of the client code to do this.
+ * The single exception is when device and configuration descriptors (but
+ * not other descriptors) are read from usbfs (i.e. /proc/bus/usb/BBB/DDD);
+ * in this case the fields are converted to host endianness by the kernel.
+ */
+
+/*
+ * Descriptor types ... USB 2.0 spec table 9.5
+ */
+#define USB_DT_DEVICE                  0x01
+#define USB_DT_CONFIG                  0x02
+#define USB_DT_STRING                  0x03
+#define USB_DT_INTERFACE               0x04
+#define USB_DT_ENDPOINT                        0x05
+#define USB_DT_DEVICE_QUALIFIER                0x06
+#define USB_DT_OTHER_SPEED_CONFIG      0x07
+#define USB_DT_INTERFACE_POWER         0x08
+/* these are from a minor usb 2.0 revision (ECN) */
+#define USB_DT_OTG                     0x09
+#define USB_DT_DEBUG                   0x0a
+#define USB_DT_INTERFACE_ASSOCIATION   0x0b
+/* these are from the Wireless USB spec */
+#define USB_DT_SECURITY                        0x0c
+#define USB_DT_KEY                     0x0d
+#define USB_DT_ENCRYPTION_TYPE         0x0e
+#define USB_DT_BOS                     0x0f
+#define USB_DT_DEVICE_CAPABILITY       0x10
+#define USB_DT_WIRELESS_ENDPOINT_COMP  0x11
+#define USB_DT_WIRE_ADAPTER            0x21
+#define USB_DT_RPIPE                   0x22
+#define USB_DT_CS_RADIO_CONTROL                0x23
+/* From the T10 UAS specification */
+#define USB_DT_PIPE_USAGE              0x24
+/* From the USB 3.0 spec */
+#define        USB_DT_SS_ENDPOINT_COMP         0x30
+
+/* Conventional codes for class-specific descriptors.  The convention is
+ * defined in the USB "Common Class" Spec (3.11).  Individual class specs
+ * are authoritative for their usage, not the "common class" writeup.
+ */
+#define USB_DT_CS_DEVICE               (USB_TYPE_CLASS | USB_DT_DEVICE)
+#define USB_DT_CS_CONFIG               (USB_TYPE_CLASS | USB_DT_CONFIG)
+#define USB_DT_CS_STRING               (USB_TYPE_CLASS | USB_DT_STRING)
+#define USB_DT_CS_INTERFACE            (USB_TYPE_CLASS | USB_DT_INTERFACE)
+#define USB_DT_CS_ENDPOINT             (USB_TYPE_CLASS | USB_DT_ENDPOINT)
+
+/* All standard descriptors have these 2 fields at the beginning */
+struct usb_descriptor_header {
+       __u8  bLength;
+       __u8  bDescriptorType;
+} __attribute__ ((packed));
+
+
+/*-------------------------------------------------------------------------*/
+
+/* USB_DT_DEVICE: Device descriptor */
+struct usb_device_descriptor {
+       __u8  bLength;
+       __u8  bDescriptorType;
+
+       __le16 bcdUSB;
+       __u8  bDeviceClass;
+       __u8  bDeviceSubClass;
+       __u8  bDeviceProtocol;
+       __u8  bMaxPacketSize0;
+       __le16 idVendor;
+       __le16 idProduct;
+       __le16 bcdDevice;
+       __u8  iManufacturer;
+       __u8  iProduct;
+       __u8  iSerialNumber;
+       __u8  bNumConfigurations;
+} __attribute__ ((packed));
+
+#define USB_DT_DEVICE_SIZE             18
+
+
+/*
+ * Device and/or Interface Class codes
+ * as found in bDeviceClass or bInterfaceClass
+ * and defined by www.usb.org documents
+ */
+#define USB_CLASS_PER_INTERFACE                0       /* for DeviceClass */
+#define USB_CLASS_AUDIO                        1
+#define USB_CLASS_COMM                 2
+#define USB_CLASS_HID                  3
+#define USB_CLASS_PHYSICAL             5
+#define USB_CLASS_STILL_IMAGE          6
+#define USB_CLASS_PRINTER              7
+#define USB_CLASS_MASS_STORAGE         8
+#define USB_CLASS_HUB                  9
+#define USB_CLASS_CDC_DATA             0x0a
+#define USB_CLASS_CSCID                        0x0b    /* chip+ smart card */
+#define USB_CLASS_CONTENT_SEC          0x0d    /* content security */
+#define USB_CLASS_VIDEO                        0x0e
+#define USB_CLASS_WIRELESS_CONTROLLER  0xe0
+#define USB_CLASS_MISC                 0xef
+#define USB_CLASS_APP_SPEC             0xfe
+#define USB_CLASS_VENDOR_SPEC          0xff
+
+#define USB_SUBCLASS_VENDOR_SPEC       0xff
+
+/*-------------------------------------------------------------------------*/
+
+/* USB_DT_CONFIG: Configuration descriptor information.
+ *
+ * USB_DT_OTHER_SPEED_CONFIG is the same descriptor, except that the
+ * descriptor type is different.  Highspeed-capable devices can look
+ * different depending on what speed they're currently running.  Only
+ * devices with a USB_DT_DEVICE_QUALIFIER have any OTHER_SPEED_CONFIG
+ * descriptors.
+ */
+struct usb_config_descriptor {
+       __u8  bLength;
+       __u8  bDescriptorType;
+
+       __le16 wTotalLength;
+       __u8  bNumInterfaces;
+       __u8  bConfigurationValue;
+       __u8  iConfiguration;
+       __u8  bmAttributes;
+       __u8  bMaxPower;
+} __attribute__ ((packed));
+
+#define USB_DT_CONFIG_SIZE             9
+
+/* from config descriptor bmAttributes */
+#define USB_CONFIG_ATT_ONE             (1 << 7)        /* must be set */
+#define USB_CONFIG_ATT_SELFPOWER       (1 << 6)        /* self powered */
+#define USB_CONFIG_ATT_WAKEUP          (1 << 5)        /* can wakeup */
+#define USB_CONFIG_ATT_BATTERY         (1 << 4)        /* battery powered */
+
+/*-------------------------------------------------------------------------*/
+
+/* USB_DT_STRING: String descriptor */
+struct usb_string_descriptor {
+       __u8  bLength;
+       __u8  bDescriptorType;
+
+       __le16 wData[1];                /* UTF-16LE encoded */
+} __attribute__ ((packed));
+
+/* note that "string" zero is special, it holds language codes that
+ * the device supports, not Unicode characters.
+ */
+
+/*-------------------------------------------------------------------------*/
+
+/* USB_DT_INTERFACE: Interface descriptor */
+struct usb_interface_descriptor {
+       __u8  bLength;
+       __u8  bDescriptorType;
+
+       __u8  bInterfaceNumber;
+       __u8  bAlternateSetting;
+       __u8  bNumEndpoints;
+       __u8  bInterfaceClass;
+       __u8  bInterfaceSubClass;
+       __u8  bInterfaceProtocol;
+       __u8  iInterface;
+} __attribute__ ((packed));
+
+#define USB_DT_INTERFACE_SIZE          9
+
+/*-------------------------------------------------------------------------*/
+
+/* USB_DT_ENDPOINT: Endpoint descriptor */
+struct usb_endpoint_descriptor {
+       __u8  bLength;
+       __u8  bDescriptorType;
+
+       __u8  bEndpointAddress;
+       __u8  bmAttributes;
+       __le16 wMaxPacketSize;
+       __u8  bInterval;
+
+       /* NOTE:  these two are _only_ in audio endpoints. */
+       /* use USB_DT_ENDPOINT*_SIZE in bLength, not sizeof. */
+       __u8  bRefresh;
+       __u8  bSynchAddress;
+} __attribute__ ((packed));
+
+#define USB_DT_ENDPOINT_SIZE           7
+#define USB_DT_ENDPOINT_AUDIO_SIZE     9       /* Audio extension */
+
+
+/*
+ * Endpoints
+ */
+#define USB_ENDPOINT_NUMBER_MASK       0x0f    /* in bEndpointAddress */
+#define USB_ENDPOINT_DIR_MASK          0x80
+
+#define USB_ENDPOINT_XFERTYPE_MASK     0x03    /* in bmAttributes */
+#define USB_ENDPOINT_XFER_CONTROL      0
+#define USB_ENDPOINT_XFER_ISOC         1
+#define USB_ENDPOINT_XFER_BULK         2
+#define USB_ENDPOINT_XFER_INT          3
+#define USB_ENDPOINT_MAX_ADJUSTABLE    0x80
+
+/* The USB 3.0 spec redefines bits 5:4 of bmAttributes as interrupt ep type. */
+#define USB_ENDPOINT_INTRTYPE          0x30
+#define USB_ENDPOINT_INTR_PERIODIC     (0 << 4)
+#define USB_ENDPOINT_INTR_NOTIFICATION (1 << 4)
+
+#define USB_ENDPOINT_SYNCTYPE          0x0c
+#define USB_ENDPOINT_SYNC_NONE         (0 << 2)
+#define USB_ENDPOINT_SYNC_ASYNC                (1 << 2)
+#define USB_ENDPOINT_SYNC_ADAPTIVE     (2 << 2)
+#define USB_ENDPOINT_SYNC_SYNC         (3 << 2)
+
+#define USB_ENDPOINT_USAGE_MASK                0x30
+#define USB_ENDPOINT_USAGE_DATA                0x00
+#define USB_ENDPOINT_USAGE_FEEDBACK    0x10
+#define USB_ENDPOINT_USAGE_IMPLICIT_FB 0x20    /* Implicit feedback Data endpoint */
+
+/*-------------------------------------------------------------------------*/
+
+/**
+ * usb_endpoint_num - get the endpoint's number
+ * @epd: endpoint to be checked
+ *
+ * Returns @epd's number: 0 to 15.
+ */
+static inline int usb_endpoint_num(const struct usb_endpoint_descriptor *epd)
+{
+       return epd->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+}
+
+/**
+ * usb_endpoint_type - get the endpoint's transfer type
+ * @epd: endpoint to be checked
+ *
+ * Returns one of USB_ENDPOINT_XFER_{CONTROL, ISOC, BULK, INT} according
+ * to @epd's transfer type.
+ */
+static inline int usb_endpoint_type(const struct usb_endpoint_descriptor *epd)
+{
+       return epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
+}
+
+/**
+ * usb_endpoint_dir_in - check if the endpoint has IN direction
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint is of type IN, otherwise it returns false.
+ */
+static inline int usb_endpoint_dir_in(const struct usb_endpoint_descriptor *epd)
+{
+       return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN);
+}
+
+/**
+ * usb_endpoint_dir_out - check if the endpoint has OUT direction
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint is of type OUT, otherwise it returns false.
+ */
+static inline int usb_endpoint_dir_out(
+                               const struct usb_endpoint_descriptor *epd)
+{
+       return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT);
+}
+
+/**
+ * usb_endpoint_xfer_bulk - check if the endpoint has bulk transfer type
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint is of type bulk, otherwise it returns false.
+ */
+static inline int usb_endpoint_xfer_bulk(
+                               const struct usb_endpoint_descriptor *epd)
+{
+       return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+               USB_ENDPOINT_XFER_BULK);
+}
+
+/**
+ * usb_endpoint_xfer_control - check if the endpoint has control transfer type
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint is of type control, otherwise it returns false.
+ */
+static inline int usb_endpoint_xfer_control(
+                               const struct usb_endpoint_descriptor *epd)
+{
+       return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+               USB_ENDPOINT_XFER_CONTROL);
+}
+
+/**
+ * usb_endpoint_xfer_int - check if the endpoint has interrupt transfer type
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint is of type interrupt, otherwise it returns
+ * false.
+ */
+static inline int usb_endpoint_xfer_int(
+                               const struct usb_endpoint_descriptor *epd)
+{
+       return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+               USB_ENDPOINT_XFER_INT);
+}
+
+/**
+ * usb_endpoint_xfer_isoc - check if the endpoint has isochronous transfer type
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint is of type isochronous, otherwise it returns
+ * false.
+ */
+static inline int usb_endpoint_xfer_isoc(
+                               const struct usb_endpoint_descriptor *epd)
+{
+       return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+               USB_ENDPOINT_XFER_ISOC);
+}
+
+/**
+ * usb_endpoint_is_bulk_in - check if the endpoint is bulk IN
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint has bulk transfer type and IN direction,
+ * otherwise it returns false.
+ */
+static inline int usb_endpoint_is_bulk_in(
+                               const struct usb_endpoint_descriptor *epd)
+{
+       return usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_in(epd);
+}
+
+/**
+ * usb_endpoint_is_bulk_out - check if the endpoint is bulk OUT
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint has bulk transfer type and OUT direction,
+ * otherwise it returns false.
+ */
+static inline int usb_endpoint_is_bulk_out(
+                               const struct usb_endpoint_descriptor *epd)
+{
+       return usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_out(epd);
+}
+
+/**
+ * usb_endpoint_is_int_in - check if the endpoint is interrupt IN
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint has interrupt transfer type and IN direction,
+ * otherwise it returns false.
+ */
+static inline int usb_endpoint_is_int_in(
+                               const struct usb_endpoint_descriptor *epd)
+{
+       return usb_endpoint_xfer_int(epd) && usb_endpoint_dir_in(epd);
+}
+
+/**
+ * usb_endpoint_is_int_out - check if the endpoint is interrupt OUT
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint has interrupt transfer type and OUT direction,
+ * otherwise it returns false.
+ */
+static inline int usb_endpoint_is_int_out(
+                               const struct usb_endpoint_descriptor *epd)
+{
+       return usb_endpoint_xfer_int(epd) && usb_endpoint_dir_out(epd);
+}
+
+/**
+ * usb_endpoint_is_isoc_in - check if the endpoint is isochronous IN
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint has isochronous transfer type and IN direction,
+ * otherwise it returns false.
+ */
+static inline int usb_endpoint_is_isoc_in(
+                               const struct usb_endpoint_descriptor *epd)
+{
+       return usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_in(epd);
+}
+
+/**
+ * usb_endpoint_is_isoc_out - check if the endpoint is isochronous OUT
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint has isochronous transfer type and OUT direction,
+ * otherwise it returns false.
+ */
+static inline int usb_endpoint_is_isoc_out(
+                               const struct usb_endpoint_descriptor *epd)
+{
+       return usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_out(epd);
+}
+
+/**
+ * usb_endpoint_maxp - get endpoint's max packet size
+ * @epd: endpoint to be checked
+ *
+ * Returns @epd's max packet
+ */
+static inline int usb_endpoint_maxp(const struct usb_endpoint_descriptor *epd)
+{
+       return __le16_to_cpu(epd->wMaxPacketSize);
+}
+
+static inline int usb_endpoint_interrupt_type(
+               const struct usb_endpoint_descriptor *epd)
+{
+       return epd->bmAttributes & USB_ENDPOINT_INTRTYPE;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* USB_DT_SS_ENDPOINT_COMP: SuperSpeed Endpoint Companion descriptor */
+struct usb_ss_ep_comp_descriptor {
+       __u8  bLength;
+       __u8  bDescriptorType;
+
+       __u8  bMaxBurst;
+       __u8  bmAttributes;
+       __le16 wBytesPerInterval;
+} __attribute__ ((packed));
+
+#define USB_DT_SS_EP_COMP_SIZE         6
+
+/* Bits 4:0 of bmAttributes if this is a bulk endpoint */
+static inline int
+usb_ss_max_streams(const struct usb_ss_ep_comp_descriptor *comp)
+{
+       int             max_streams;
+
+       if (!comp)
+               return 0;
+
+       max_streams = comp->bmAttributes & 0x1f;
+
+       if (!max_streams)
+               return 0;
+
+       max_streams = 1 << max_streams;
+
+       return max_streams;
+}
+
+/* Bits 1:0 of bmAttributes if this is an isoc endpoint */
+#define USB_SS_MULT(p)                 (1 + ((p) & 0x3))
+
+/*-------------------------------------------------------------------------*/
+
+/* USB_DT_DEVICE_QUALIFIER: Device Qualifier descriptor */
+struct usb_qualifier_descriptor {
+       __u8  bLength;
+       __u8  bDescriptorType;
+
+       __le16 bcdUSB;
+       __u8  bDeviceClass;
+       __u8  bDeviceSubClass;
+       __u8  bDeviceProtocol;
+       __u8  bMaxPacketSize0;
+       __u8  bNumConfigurations;
+       __u8  bRESERVED;
+} __attribute__ ((packed));
+
+
+/*-------------------------------------------------------------------------*/
+
+/* USB_DT_OTG (from OTG 1.0a supplement) */
+struct usb_otg_descriptor {
+       __u8  bLength;
+       __u8  bDescriptorType;
+
+       __u8  bmAttributes;     /* support for HNP, SRP, etc */
+} __attribute__ ((packed));
+
+/* from usb_otg_descriptor.bmAttributes */
+#define USB_OTG_SRP            (1 << 0)
+#define USB_OTG_HNP            (1 << 1)        /* swap host/device roles */
+
+/*-------------------------------------------------------------------------*/
+
+/* USB_DT_DEBUG:  for special highspeed devices, replacing serial console */
+struct usb_debug_descriptor {
+       __u8  bLength;
+       __u8  bDescriptorType;
+
+       /* bulk endpoints with 8 byte maxpacket */
+       __u8  bDebugInEndpoint;
+       __u8  bDebugOutEndpoint;
+} __attribute__((packed));
+
+/*-------------------------------------------------------------------------*/
+
+/* USB_DT_INTERFACE_ASSOCIATION: groups interfaces */
+struct usb_interface_assoc_descriptor {
+       __u8  bLength;
+       __u8  bDescriptorType;
+
+       __u8  bFirstInterface;
+       __u8  bInterfaceCount;
+       __u8  bFunctionClass;
+       __u8  bFunctionSubClass;
+       __u8  bFunctionProtocol;
+       __u8  iFunction;
+} __attribute__ ((packed));
+
+
+/*-------------------------------------------------------------------------*/
+
+/* USB_DT_SECURITY:  group of wireless security descriptors, including
+ * encryption types available for setting up a CC/association.
+ */
+struct usb_security_descriptor {
+       __u8  bLength;
+       __u8  bDescriptorType;
+
+       __le16 wTotalLength;
+       __u8  bNumEncryptionTypes;
+} __attribute__((packed));
+
+/*-------------------------------------------------------------------------*/
+
+/* USB_DT_KEY:  used with {GET,SET}_SECURITY_DATA; only public keys
+ * may be retrieved.
+ */
+struct usb_key_descriptor {
+       __u8  bLength;
+       __u8  bDescriptorType;
+
+       __u8  tTKID[3];
+       __u8  bReserved;
+       __u8  bKeyData[0];
+} __attribute__((packed));
+
+/*-------------------------------------------------------------------------*/
+
+/* USB_DT_ENCRYPTION_TYPE:  bundled in DT_SECURITY groups */
+struct usb_encryption_descriptor {
+       __u8  bLength;
+       __u8  bDescriptorType;
+
+       __u8  bEncryptionType;
+#define        USB_ENC_TYPE_UNSECURE           0
+#define        USB_ENC_TYPE_WIRED              1       /* non-wireless mode */
+#define        USB_ENC_TYPE_CCM_1              2       /* aes128/cbc session */
+#define        USB_ENC_TYPE_RSA_1              3       /* rsa3072/sha1 auth */
+       __u8  bEncryptionValue;         /* use in SET_ENCRYPTION */
+       __u8  bAuthKeyIndex;
+} __attribute__((packed));
+
+
+/*-------------------------------------------------------------------------*/
+
+/* USB_DT_BOS:  group of device-level capabilities */
+struct usb_bos_descriptor {
+       __u8  bLength;
+       __u8  bDescriptorType;
+
+       __le16 wTotalLength;
+       __u8  bNumDeviceCaps;
+} __attribute__((packed));
+
+#define USB_DT_BOS_SIZE                5
+/*-------------------------------------------------------------------------*/
+
+/* USB_DT_DEVICE_CAPABILITY:  grouped with BOS */
+struct usb_dev_cap_header {
+       __u8  bLength;
+       __u8  bDescriptorType;
+       __u8  bDevCapabilityType;
+} __attribute__((packed));
+
+#define        USB_CAP_TYPE_WIRELESS_USB       1
+
+struct usb_wireless_cap_descriptor {   /* Ultra Wide Band */
+       __u8  bLength;
+       __u8  bDescriptorType;
+       __u8  bDevCapabilityType;
+
+       __u8  bmAttributes;
+#define        USB_WIRELESS_P2P_DRD            (1 << 1)
+#define        USB_WIRELESS_BEACON_MASK        (3 << 2)
+#define        USB_WIRELESS_BEACON_SELF        (1 << 2)
+#define        USB_WIRELESS_BEACON_DIRECTED    (2 << 2)
+#define        USB_WIRELESS_BEACON_NONE        (3 << 2)
+       __le16 wPHYRates;       /* bit rates, Mbps */
+#define        USB_WIRELESS_PHY_53             (1 << 0)        /* always set */
+#define        USB_WIRELESS_PHY_80             (1 << 1)
+#define        USB_WIRELESS_PHY_107            (1 << 2)        /* always set */
+#define        USB_WIRELESS_PHY_160            (1 << 3)
+#define        USB_WIRELESS_PHY_200            (1 << 4)        /* always set */
+#define        USB_WIRELESS_PHY_320            (1 << 5)
+#define        USB_WIRELESS_PHY_400            (1 << 6)
+#define        USB_WIRELESS_PHY_480            (1 << 7)
+       __u8  bmTFITXPowerInfo; /* TFI power levels */
+       __u8  bmFFITXPowerInfo; /* FFI power levels */
+       __le16 bmBandGroup;
+       __u8  bReserved;
+} __attribute__((packed));
+
+/* USB 2.0 Extension descriptor */
+#define        USB_CAP_TYPE_EXT                2
+
+struct usb_ext_cap_descriptor {                /* Link Power Management */
+       __u8  bLength;
+       __u8  bDescriptorType;
+       __u8  bDevCapabilityType;
+       __le32 bmAttributes;
+#define USB_LPM_SUPPORT                        (1 << 1)        /* supports LPM */
+#define USB_BESL_SUPPORT               (1 << 2)        /* supports BESL */
+#define USB_BESL_BASELINE_VALID                (1 << 3)        /* Baseline BESL valid*/
+#define USB_BESL_DEEP_VALID            (1 << 4)        /* Deep BESL valid */
+#define USB_GET_BESL_BASELINE(p)       (((p) & (0xf << 8)) >> 8)
+#define USB_GET_BESL_DEEP(p)           (((p) & (0xf << 12)) >> 12)
+} __attribute__((packed));
+
+#define USB_DT_USB_EXT_CAP_SIZE        7
+
+/*
+ * SuperSpeed USB Capability descriptor: Defines the set of SuperSpeed USB
+ * specific device level capabilities
+ */
+#define                USB_SS_CAP_TYPE         3
+struct usb_ss_cap_descriptor {         /* Link Power Management */
+       __u8  bLength;
+       __u8  bDescriptorType;
+       __u8  bDevCapabilityType;
+       __u8  bmAttributes;
+#define USB_LTM_SUPPORT                        (1 << 1) /* supports LTM */
+       __le16 wSpeedSupported;
+#define USB_LOW_SPEED_OPERATION                (1)      /* Low speed operation */
+#define USB_FULL_SPEED_OPERATION       (1 << 1) /* Full speed operation */
+#define USB_HIGH_SPEED_OPERATION       (1 << 2) /* High speed operation */
+#define USB_5GBPS_OPERATION            (1 << 3) /* Operation at 5Gbps */
+       __u8  bFunctionalitySupport;
+       __u8  bU1devExitLat;
+       __le16 bU2DevExitLat;
+} __attribute__((packed));
+
+#define USB_DT_USB_SS_CAP_SIZE 10
+
+/*
+ * Container ID Capability descriptor: Defines the instance unique ID used to
+ * identify the instance across all operating modes
+ */
+#define        CONTAINER_ID_TYPE       4
+struct usb_ss_container_id_descriptor {
+       __u8  bLength;
+       __u8  bDescriptorType;
+       __u8  bDevCapabilityType;
+       __u8  bReserved;
+       __u8  ContainerID[16]; /* 128-bit number */
+} __attribute__((packed));
+
+#define USB_DT_USB_SS_CONTN_ID_SIZE    20
+/*-------------------------------------------------------------------------*/
+
+/* USB_DT_WIRELESS_ENDPOINT_COMP:  companion descriptor associated with
+ * each endpoint descriptor for a wireless device
+ */
+struct usb_wireless_ep_comp_descriptor {
+       __u8  bLength;
+       __u8  bDescriptorType;
+
+       __u8  bMaxBurst;
+       __u8  bMaxSequence;
+       __le16 wMaxStreamDelay;
+       __le16 wOverTheAirPacketSize;
+       __u8  bOverTheAirInterval;
+       __u8  bmCompAttributes;
+#define USB_ENDPOINT_SWITCH_MASK       0x03    /* in bmCompAttributes */
+#define USB_ENDPOINT_SWITCH_NO         0
+#define USB_ENDPOINT_SWITCH_SWITCH     1
+#define USB_ENDPOINT_SWITCH_SCALE      2
+} __attribute__((packed));
+
+/*-------------------------------------------------------------------------*/
+
+/* USB_REQ_SET_HANDSHAKE is a four-way handshake used between a wireless
+ * host and a device for connection set up, mutual authentication, and
+ * exchanging short lived session keys.  The handshake depends on a CC.
+ */
+struct usb_handshake {
+       __u8 bMessageNumber;
+       __u8 bStatus;
+       __u8 tTKID[3];
+       __u8 bReserved;
+       __u8 CDID[16];
+       __u8 nonce[16];
+       __u8 MIC[8];
+} __attribute__((packed));
+
+/*-------------------------------------------------------------------------*/
+
+/* USB_REQ_SET_CONNECTION modifies or revokes a connection context (CC).
+ * A CC may also be set up using non-wireless secure channels (including
+ * wired USB!), and some devices may support CCs with multiple hosts.
+ */
+struct usb_connection_context {
+       __u8 CHID[16];          /* persistent host id */
+       __u8 CDID[16];          /* device id (unique w/in host context) */
+       __u8 CK[16];            /* connection key */
+} __attribute__((packed));
+
+/*-------------------------------------------------------------------------*/
+
+/* USB 2.0 defines three speeds, here's how Linux identifies them */
+
+enum usb_device_speed {
+       USB_SPEED_UNKNOWN = 0,                  /* enumerating */
+       USB_SPEED_LOW, USB_SPEED_FULL,          /* usb 1.1 */
+       USB_SPEED_HIGH,                         /* usb 2.0 */
+       USB_SPEED_WIRELESS,                     /* wireless (usb 2.5) */
+       USB_SPEED_SUPER,                        /* usb 3.0 */
+};
+
+
+enum usb_device_state {
+       /* NOTATTACHED isn't in the USB spec, and this state acts
+        * the same as ATTACHED ... but it's clearer this way.
+        */
+       USB_STATE_NOTATTACHED = 0,
+
+       /* chapter 9 and authentication (wireless) device states */
+       USB_STATE_ATTACHED,
+       USB_STATE_POWERED,                      /* wired */
+       USB_STATE_RECONNECTING,                 /* auth */
+       USB_STATE_UNAUTHENTICATED,              /* auth */
+       USB_STATE_DEFAULT,                      /* limited function */
+       USB_STATE_ADDRESS,
+       USB_STATE_CONFIGURED,                   /* most functions */
+
+       USB_STATE_SUSPENDED
+
+       /* NOTE:  there are actually four different SUSPENDED
+        * states, returning to POWERED, DEFAULT, ADDRESS, or
+        * CONFIGURED respectively when SOF tokens flow again.
+        * At this level there's no difference between L1 and L2
+        * suspend states.  (L2 being original USB 1.1 suspend.)
+        */
+};
+
+enum usb3_link_state {
+       USB3_LPM_U0 = 0,
+       USB3_LPM_U1,
+       USB3_LPM_U2,
+       USB3_LPM_U3
+};
+
+/*
+ * A U1 timeout of 0x0 means the parent hub will reject any transitions to U1.
+ * 0xff means the parent hub will accept transitions to U1, but will not
+ * initiate a transition.
+ *
+ * A U1 timeout of 0x1 to 0x7F also causes the hub to initiate a transition to
+ * U1 after that many microseconds.  Timeouts of 0x80 to 0xFE are reserved
+ * values.
+ *
+ * A U2 timeout of 0x0 means the parent hub will reject any transitions to U2.
+ * 0xff means the parent hub will accept transitions to U2, but will not
+ * initiate a transition.
+ *
+ * A U2 timeout of 0x1 to 0xFE also causes the hub to initiate a transition to
+ * U2 after N*256 microseconds.  Therefore a U2 timeout value of 0x1 means a U2
+ * idle timer of 256 microseconds, 0x2 means 512 microseconds, 0xFE means
+ * 65.024ms.
+ */
+#define USB3_LPM_DISABLED              0x0
+#define USB3_LPM_U1_MAX_TIMEOUT                0x7F
+#define USB3_LPM_U2_MAX_TIMEOUT                0xFE
+#define USB3_LPM_DEVICE_INITIATED      0xFF
+
+struct usb_set_sel_req {
+       __u8    u1_sel;
+       __u8    u1_pel;
+       __le16  u2_sel;
+       __le16  u2_pel;
+} __attribute__ ((packed));
+
+/*
+ * The Set System Exit Latency control transfer provides one byte each for
+ * U1 SEL and U1 PEL, so the max exit latency is 0xFF.  U2 SEL and U2 PEL each
+ * are two bytes long.
+ */
+#define USB3_LPM_MAX_U1_SEL_PEL                0xFF
+#define USB3_LPM_MAX_U2_SEL_PEL                0xFFFF
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * As per USB compliance update, a device that is actively drawing
+ * more than 100mA from USB must report itself as bus-powered in
+ * the GetStatus(DEVICE) call.
+ * http://compliance.usb.org/index.asp?UpdateFile=Electrical&Format=Standard#34
+ */
+#define USB_SELF_POWER_VBUS_MAX_DRAW           100
+
+#endif /* _UAPI__LINUX_USB_CH9_H */
diff --git a/include/uapi/linux/usb/functionfs.h b/include/uapi/linux/usb/functionfs.h
new file mode 100644 (file)
index 0000000..d6b0128
--- /dev/null
@@ -0,0 +1,169 @@
+#ifndef _UAPI__LINUX_FUNCTIONFS_H__
+#define _UAPI__LINUX_FUNCTIONFS_H__
+
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+
+#include <linux/usb/ch9.h>
+
+
+enum {
+       FUNCTIONFS_DESCRIPTORS_MAGIC = 1,
+       FUNCTIONFS_STRINGS_MAGIC     = 2
+};
+
+
+#ifndef __KERNEL__
+
+/* Descriptor of an non-audio endpoint */
+struct usb_endpoint_descriptor_no_audio {
+       __u8  bLength;
+       __u8  bDescriptorType;
+
+       __u8  bEndpointAddress;
+       __u8  bmAttributes;
+       __le16 wMaxPacketSize;
+       __u8  bInterval;
+} __attribute__((packed));
+
+
+/*
+ * All numbers must be in little endian order.
+ */
+
+struct usb_functionfs_descs_head {
+       __le32 magic;
+       __le32 length;
+       __le32 fs_count;
+       __le32 hs_count;
+} __attribute__((packed));
+
+/*
+ * Descriptors format:
+ *
+ * | off | name      | type         | description                          |
+ * |-----+-----------+--------------+--------------------------------------|
+ * |   0 | magic     | LE32         | FUNCTIONFS_{FS,HS}_DESCRIPTORS_MAGIC |
+ * |   4 | length    | LE32         | length of the whole data chunk       |
+ * |   8 | fs_count  | LE32         | number of full-speed descriptors     |
+ * |  12 | hs_count  | LE32         | number of high-speed descriptors     |
+ * |  16 | fs_descrs | Descriptor[] | list of full-speed descriptors       |
+ * |     | hs_descrs | Descriptor[] | list of high-speed descriptors       |
+ *
+ * descs are just valid USB descriptors and have the following format:
+ *
+ * | off | name            | type | description              |
+ * |-----+-----------------+------+--------------------------|
+ * |   0 | bLength         | U8   | length of the descriptor |
+ * |   1 | bDescriptorType | U8   | descriptor type          |
+ * |   2 | payload         |      | descriptor's payload     |
+ */
+
+struct usb_functionfs_strings_head {
+       __le32 magic;
+       __le32 length;
+       __le32 str_count;
+       __le32 lang_count;
+} __attribute__((packed));
+
+/*
+ * Strings format:
+ *
+ * | off | name       | type                  | description                |
+ * |-----+------------+-----------------------+----------------------------|
+ * |   0 | magic      | LE32                  | FUNCTIONFS_STRINGS_MAGIC   |
+ * |   4 | length     | LE32                  | length of the data chunk   |
+ * |   8 | str_count  | LE32                  | number of strings          |
+ * |  12 | lang_count | LE32                  | number of languages        |
+ * |  16 | stringtab  | StringTab[lang_count] | table of strings per lang  |
+ *
+ * For each language there is one stringtab entry (ie. there are lang_count
+ * stringtab entires).  Each StringTab has following format:
+ *
+ * | off | name    | type              | description                        |
+ * |-----+---------+-------------------+------------------------------------|
+ * |   0 | lang    | LE16              | language code                      |
+ * |   2 | strings | String[str_count] | array of strings in given language |
+ *
+ * For each string there is one strings entry (ie. there are str_count
+ * string entries).  Each String is a NUL terminated string encoded in
+ * UTF-8.
+ */
+
+#endif
+
+
+/*
+ * Events are delivered on the ep0 file descriptor, when the user mode driver
+ * reads from this file descriptor after writing the descriptors.  Don't
+ * stop polling this descriptor.
+ */
+
+enum usb_functionfs_event_type {
+       FUNCTIONFS_BIND,
+       FUNCTIONFS_UNBIND,
+
+       FUNCTIONFS_ENABLE,
+       FUNCTIONFS_DISABLE,
+
+       FUNCTIONFS_SETUP,
+
+       FUNCTIONFS_SUSPEND,
+       FUNCTIONFS_RESUME
+};
+
+/* NOTE:  this structure must stay the same size and layout on
+ * both 32-bit and 64-bit kernels.
+ */
+struct usb_functionfs_event {
+       union {
+               /* SETUP: packet; DATA phase i/o precedes next event
+                *(setup.bmRequestType & USB_DIR_IN) flags direction */
+               struct usb_ctrlrequest  setup;
+       } __attribute__((packed)) u;
+
+       /* enum usb_functionfs_event_type */
+       __u8                            type;
+       __u8                            _pad[3];
+} __attribute__((packed));
+
+
+/* Endpoint ioctls */
+/* The same as in gadgetfs */
+
+/* IN transfers may be reported to the gadget driver as complete
+ *     when the fifo is loaded, before the host reads the data;
+ * OUT transfers may be reported to the host's "client" driver as
+ *     complete when they're sitting in the FIFO unread.
+ * THIS returns how many bytes are "unclaimed" in the endpoint fifo
+ * (needed for precise fault handling, when the hardware allows it)
+ */
+#define        FUNCTIONFS_FIFO_STATUS  _IO('g', 1)
+
+/* discards any unclaimed data in the fifo. */
+#define        FUNCTIONFS_FIFO_FLUSH   _IO('g', 2)
+
+/* resets endpoint halt+toggle; used to implement set_interface.
+ * some hardware (like pxa2xx) can't support this.
+ */
+#define        FUNCTIONFS_CLEAR_HALT   _IO('g', 3)
+
+/* Specific for functionfs */
+
+/*
+ * Returns reverse mapping of an interface.  Called on EP0.  If there
+ * is no such interface returns -EDOM.  If function is not active
+ * returns -ENODEV.
+ */
+#define        FUNCTIONFS_INTERFACE_REVMAP     _IO('g', 128)
+
+/*
+ * Returns real bEndpointAddress of an endpoint.  If function is not
+ * active returns -ENODEV.
+ */
+#define        FUNCTIONFS_ENDPOINT_REVMAP      _IO('g', 129)
+
+
+
+#endif /* _UAPI__LINUX_FUNCTIONFS_H__ */
index aafaa5aa54d46bb9a93a8137a22344408298223f..0f7d279ebde35fd1be21cc922def324eaacb240f 100644 (file)
@@ -1 +1,11 @@
 # UAPI Header export list
+header-y += asequencer.h
+header-y += asound.h
+header-y += asound_fm.h
+header-y += compress_offload.h
+header-y += compress_params.h
+header-y += emu10k1.h
+header-y += hdsp.h
+header-y += hdspm.h
+header-y += sb16_csp.h
+header-y += sfnt_info.h
diff --git a/include/uapi/sound/asequencer.h b/include/uapi/sound/asequencer.h
new file mode 100644 (file)
index 0000000..09c8a00
--- /dev/null
@@ -0,0 +1,614 @@
+/*
+ *  Main header file for the ALSA sequencer
+ *  Copyright (c) 1998-1999 by Frank van de Pol <fvdpol@coil.demon.nl>
+ *            (c) 1998-1999 by Jaroslav Kysela <perex@perex.cz>
+ *
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+#ifndef _UAPI__SOUND_ASEQUENCER_H
+#define _UAPI__SOUND_ASEQUENCER_H
+
+
+/** version of the sequencer */
+#define SNDRV_SEQ_VERSION SNDRV_PROTOCOL_VERSION (1, 0, 1)
+
+/**
+ * definition of sequencer event types
+ */
+
+/** system messages
+ * event data type = #snd_seq_result
+ */
+#define SNDRV_SEQ_EVENT_SYSTEM         0
+#define SNDRV_SEQ_EVENT_RESULT         1
+
+/** note messages (channel specific)
+ * event data type = #snd_seq_ev_note
+ */
+#define SNDRV_SEQ_EVENT_NOTE           5
+#define SNDRV_SEQ_EVENT_NOTEON         6
+#define SNDRV_SEQ_EVENT_NOTEOFF                7
+#define SNDRV_SEQ_EVENT_KEYPRESS       8
+       
+/** control messages (channel specific)
+ * event data type = #snd_seq_ev_ctrl
+ */
+#define SNDRV_SEQ_EVENT_CONTROLLER     10
+#define SNDRV_SEQ_EVENT_PGMCHANGE      11
+#define SNDRV_SEQ_EVENT_CHANPRESS      12
+#define SNDRV_SEQ_EVENT_PITCHBEND      13      /**< from -8192 to 8191 */
+#define SNDRV_SEQ_EVENT_CONTROL14      14      /**< 14 bit controller value */
+#define SNDRV_SEQ_EVENT_NONREGPARAM    15      /**< 14 bit NRPN address + 14 bit unsigned value */
+#define SNDRV_SEQ_EVENT_REGPARAM       16      /**< 14 bit RPN address + 14 bit unsigned value */
+
+/** synchronisation messages
+ * event data type = #snd_seq_ev_ctrl
+ */
+#define SNDRV_SEQ_EVENT_SONGPOS                20      /* Song Position Pointer with LSB and MSB values */
+#define SNDRV_SEQ_EVENT_SONGSEL                21      /* Song Select with song ID number */
+#define SNDRV_SEQ_EVENT_QFRAME         22      /* midi time code quarter frame */
+#define SNDRV_SEQ_EVENT_TIMESIGN       23      /* SMF Time Signature event */
+#define SNDRV_SEQ_EVENT_KEYSIGN                24      /* SMF Key Signature event */
+               
+/** timer messages
+ * event data type = snd_seq_ev_queue_control
+ */
+#define SNDRV_SEQ_EVENT_START          30      /* midi Real Time Start message */
+#define SNDRV_SEQ_EVENT_CONTINUE       31      /* midi Real Time Continue message */
+#define SNDRV_SEQ_EVENT_STOP           32      /* midi Real Time Stop message */       
+#define        SNDRV_SEQ_EVENT_SETPOS_TICK     33      /* set tick queue position */
+#define SNDRV_SEQ_EVENT_SETPOS_TIME    34      /* set realtime queue position */
+#define SNDRV_SEQ_EVENT_TEMPO          35      /* (SMF) Tempo event */
+#define SNDRV_SEQ_EVENT_CLOCK          36      /* midi Real Time Clock message */
+#define SNDRV_SEQ_EVENT_TICK           37      /* midi Real Time Tick message */
+#define SNDRV_SEQ_EVENT_QUEUE_SKEW     38      /* skew queue tempo */
+
+/** others
+ * event data type = none
+ */
+#define SNDRV_SEQ_EVENT_TUNE_REQUEST   40      /* tune request */
+#define SNDRV_SEQ_EVENT_RESET          41      /* reset to power-on state */
+#define SNDRV_SEQ_EVENT_SENSING                42      /* "active sensing" event */
+
+/** echo back, kernel private messages
+ * event data type = any type
+ */
+#define SNDRV_SEQ_EVENT_ECHO           50      /* echo event */
+#define SNDRV_SEQ_EVENT_OSS            51      /* OSS raw event */
+
+/** system status messages (broadcast for subscribers)
+ * event data type = snd_seq_addr
+ */
+#define SNDRV_SEQ_EVENT_CLIENT_START   60      /* new client has connected */
+#define SNDRV_SEQ_EVENT_CLIENT_EXIT    61      /* client has left the system */
+#define SNDRV_SEQ_EVENT_CLIENT_CHANGE  62      /* client status/info has changed */
+#define SNDRV_SEQ_EVENT_PORT_START     63      /* new port was created */
+#define SNDRV_SEQ_EVENT_PORT_EXIT      64      /* port was deleted from system */
+#define SNDRV_SEQ_EVENT_PORT_CHANGE    65      /* port status/info has changed */
+
+/** port connection changes
+ * event data type = snd_seq_connect
+ */
+#define SNDRV_SEQ_EVENT_PORT_SUBSCRIBED        66      /* ports connected */
+#define SNDRV_SEQ_EVENT_PORT_UNSUBSCRIBED 67   /* ports disconnected */
+
+/* 70-89:  synthesizer events - obsoleted */
+
+/** user-defined events with fixed length
+ * event data type = any
+ */
+#define SNDRV_SEQ_EVENT_USR0           90
+#define SNDRV_SEQ_EVENT_USR1           91
+#define SNDRV_SEQ_EVENT_USR2           92
+#define SNDRV_SEQ_EVENT_USR3           93
+#define SNDRV_SEQ_EVENT_USR4           94
+#define SNDRV_SEQ_EVENT_USR5           95
+#define SNDRV_SEQ_EVENT_USR6           96
+#define SNDRV_SEQ_EVENT_USR7           97
+#define SNDRV_SEQ_EVENT_USR8           98
+#define SNDRV_SEQ_EVENT_USR9           99
+
+/* 100-118: instrument layer - obsoleted */
+/* 119-129: reserved */
+
+/* 130-139: variable length events
+ * event data type = snd_seq_ev_ext
+ * (SNDRV_SEQ_EVENT_LENGTH_VARIABLE must be set)
+ */
+#define SNDRV_SEQ_EVENT_SYSEX          130     /* system exclusive data (variable length) */
+#define SNDRV_SEQ_EVENT_BOUNCE         131     /* error event */
+/* 132-134: reserved */
+#define SNDRV_SEQ_EVENT_USR_VAR0       135
+#define SNDRV_SEQ_EVENT_USR_VAR1       136
+#define SNDRV_SEQ_EVENT_USR_VAR2       137
+#define SNDRV_SEQ_EVENT_USR_VAR3       138
+#define SNDRV_SEQ_EVENT_USR_VAR4       139
+
+/* 150-151: kernel events with quote - DO NOT use in user clients */
+#define SNDRV_SEQ_EVENT_KERNEL_ERROR   150
+#define SNDRV_SEQ_EVENT_KERNEL_QUOTE   151     /* obsolete */
+
+/* 152-191: reserved */
+
+/* 192-254: hardware specific events */
+
+/* 255: special event */
+#define SNDRV_SEQ_EVENT_NONE           255
+
+
+typedef unsigned char snd_seq_event_type_t;
+
+/** event address */
+struct snd_seq_addr {
+       unsigned char client;   /**< Client number:         0..255, 255 = broadcast to all clients */
+       unsigned char port;     /**< Port within client:    0..255, 255 = broadcast to all ports */
+};
+
+/** port connection */
+struct snd_seq_connect {
+       struct snd_seq_addr sender;
+       struct snd_seq_addr dest;
+};
+
+
+#define SNDRV_SEQ_ADDRESS_UNKNOWN      253     /* unknown source */
+#define SNDRV_SEQ_ADDRESS_SUBSCRIBERS  254     /* send event to all subscribed ports */
+#define SNDRV_SEQ_ADDRESS_BROADCAST    255     /* send event to all queues/clients/ports/channels */
+#define SNDRV_SEQ_QUEUE_DIRECT         253     /* direct dispatch */
+
+       /* event mode flag - NOTE: only 8 bits available! */
+#define SNDRV_SEQ_TIME_STAMP_TICK      (0<<0) /* timestamp in clock ticks */
+#define SNDRV_SEQ_TIME_STAMP_REAL      (1<<0) /* timestamp in real time */
+#define SNDRV_SEQ_TIME_STAMP_MASK      (1<<0)
+
+#define SNDRV_SEQ_TIME_MODE_ABS                (0<<1)  /* absolute timestamp */
+#define SNDRV_SEQ_TIME_MODE_REL                (1<<1)  /* relative to current time */
+#define SNDRV_SEQ_TIME_MODE_MASK       (1<<1)
+
+#define SNDRV_SEQ_EVENT_LENGTH_FIXED   (0<<2)  /* fixed event size */
+#define SNDRV_SEQ_EVENT_LENGTH_VARIABLE        (1<<2)  /* variable event size */
+#define SNDRV_SEQ_EVENT_LENGTH_VARUSR  (2<<2)  /* variable event size - user memory space */
+#define SNDRV_SEQ_EVENT_LENGTH_MASK    (3<<2)
+
+#define SNDRV_SEQ_PRIORITY_NORMAL      (0<<4)  /* normal priority */
+#define SNDRV_SEQ_PRIORITY_HIGH                (1<<4)  /* event should be processed before others */
+#define SNDRV_SEQ_PRIORITY_MASK                (1<<4)
+
+
+       /* note event */
+struct snd_seq_ev_note {
+       unsigned char channel;
+       unsigned char note;
+       unsigned char velocity;
+       unsigned char off_velocity;     /* only for SNDRV_SEQ_EVENT_NOTE */
+       unsigned int duration;          /* only for SNDRV_SEQ_EVENT_NOTE */
+};
+
+       /* controller event */
+struct snd_seq_ev_ctrl {
+       unsigned char channel;
+       unsigned char unused1, unused2, unused3;        /* pad */
+       unsigned int param;
+       signed int value;
+};
+
+       /* generic set of bytes (12x8 bit) */
+struct snd_seq_ev_raw8 {
+       unsigned char d[12];    /* 8 bit value */
+};
+
+       /* generic set of integers (3x32 bit) */
+struct snd_seq_ev_raw32 {
+       unsigned int d[3];      /* 32 bit value */
+};
+
+       /* external stored data */
+struct snd_seq_ev_ext {
+       unsigned int len;       /* length of data */
+       void *ptr;              /* pointer to data (note: maybe 64-bit) */
+} __attribute__((packed));
+
+struct snd_seq_result {
+       int event;              /* processed event type */
+       int result;
+};
+
+
+struct snd_seq_real_time {
+       unsigned int tv_sec;    /* seconds */
+       unsigned int tv_nsec;   /* nanoseconds */
+};
+
+typedef unsigned int snd_seq_tick_time_t;      /* midi ticks */
+
+union snd_seq_timestamp {
+       snd_seq_tick_time_t tick;
+       struct snd_seq_real_time time;
+};
+
+struct snd_seq_queue_skew {
+       unsigned int value;
+       unsigned int base;
+};
+
+       /* queue timer control */
+struct snd_seq_ev_queue_control {
+       unsigned char queue;                    /* affected queue */
+       unsigned char pad[3];                   /* reserved */
+       union {
+               signed int value;               /* affected value (e.g. tempo) */
+               union snd_seq_timestamp time;   /* time */
+               unsigned int position;          /* sync position */
+               struct snd_seq_queue_skew skew;
+               unsigned int d32[2];
+               unsigned char d8[8];
+       } param;
+};
+
+       /* quoted event - inside the kernel only */
+struct snd_seq_ev_quote {
+       struct snd_seq_addr origin;             /* original sender */
+       unsigned short value;           /* optional data */
+       struct snd_seq_event *event;            /* quoted event */
+} __attribute__((packed));
+
+
+       /* sequencer event */
+struct snd_seq_event {
+       snd_seq_event_type_t type;      /* event type */
+       unsigned char flags;            /* event flags */
+       char tag;
+       
+       unsigned char queue;            /* schedule queue */
+       union snd_seq_timestamp time;   /* schedule time */
+
+
+       struct snd_seq_addr source;     /* source address */
+       struct snd_seq_addr dest;       /* destination address */
+
+       union {                         /* event data... */
+               struct snd_seq_ev_note note;
+               struct snd_seq_ev_ctrl control;
+               struct snd_seq_ev_raw8 raw8;
+               struct snd_seq_ev_raw32 raw32;
+               struct snd_seq_ev_ext ext;
+               struct snd_seq_ev_queue_control queue;
+               union snd_seq_timestamp time;
+               struct snd_seq_addr addr;
+               struct snd_seq_connect connect;
+               struct snd_seq_result result;
+               struct snd_seq_ev_quote quote;
+       } data;
+};
+
+
+/*
+ * bounce event - stored as variable size data
+ */
+struct snd_seq_event_bounce {
+       int err;
+       struct snd_seq_event event;
+       /* external data follows here. */
+};
+
+
+       /* system information */
+struct snd_seq_system_info {
+       int queues;                     /* maximum queues count */
+       int clients;                    /* maximum clients count */
+       int ports;                      /* maximum ports per client */
+       int channels;                   /* maximum channels per port */
+       int cur_clients;                /* current clients */
+       int cur_queues;                 /* current queues */
+       char reserved[24];
+};
+
+
+       /* system running information */
+struct snd_seq_running_info {
+       unsigned char client;           /* client id */
+       unsigned char big_endian;       /* 1 = big-endian */
+       unsigned char cpu_mode;         /* 4 = 32bit, 8 = 64bit */
+       unsigned char pad;              /* reserved */
+       unsigned char reserved[12];
+};
+
+
+       /* known client numbers */
+#define SNDRV_SEQ_CLIENT_SYSTEM                0
+       /* internal client numbers */
+#define SNDRV_SEQ_CLIENT_DUMMY         14      /* midi through */
+#define SNDRV_SEQ_CLIENT_OSS           15      /* oss sequencer emulator */
+
+
+       /* client types */
+typedef int __bitwise snd_seq_client_type_t;
+#define        NO_CLIENT       ((__force snd_seq_client_type_t) 0)
+#define        USER_CLIENT     ((__force snd_seq_client_type_t) 1)
+#define        KERNEL_CLIENT   ((__force snd_seq_client_type_t) 2)
+                        
+       /* event filter flags */
+#define SNDRV_SEQ_FILTER_BROADCAST     (1<<0)  /* accept broadcast messages */
+#define SNDRV_SEQ_FILTER_MULTICAST     (1<<1)  /* accept multicast messages */
+#define SNDRV_SEQ_FILTER_BOUNCE                (1<<2)  /* accept bounce event in error */
+#define SNDRV_SEQ_FILTER_USE_EVENT     (1<<31) /* use event filter */
+
+struct snd_seq_client_info {
+       int client;                     /* client number to inquire */
+       snd_seq_client_type_t type;     /* client type */
+       char name[64];                  /* client name */
+       unsigned int filter;            /* filter flags */
+       unsigned char multicast_filter[8]; /* multicast filter bitmap */
+       unsigned char event_filter[32]; /* event filter bitmap */
+       int num_ports;                  /* RO: number of ports */
+       int event_lost;                 /* number of lost events */
+       char reserved[64];              /* for future use */
+};
+
+
+/* client pool size */
+struct snd_seq_client_pool {
+       int client;                     /* client number to inquire */
+       int output_pool;                /* outgoing (write) pool size */
+       int input_pool;                 /* incoming (read) pool size */
+       int output_room;                /* minimum free pool size for select/blocking mode */
+       int output_free;                /* unused size */
+       int input_free;                 /* unused size */
+       char reserved[64];
+};
+
+
+/* Remove events by specified criteria */
+
+#define SNDRV_SEQ_REMOVE_INPUT         (1<<0)  /* Flush input queues */
+#define SNDRV_SEQ_REMOVE_OUTPUT                (1<<1)  /* Flush output queues */
+#define SNDRV_SEQ_REMOVE_DEST          (1<<2)  /* Restrict by destination q:client:port */
+#define SNDRV_SEQ_REMOVE_DEST_CHANNEL  (1<<3)  /* Restrict by channel */
+#define SNDRV_SEQ_REMOVE_TIME_BEFORE   (1<<4)  /* Restrict to before time */
+#define SNDRV_SEQ_REMOVE_TIME_AFTER    (1<<5)  /* Restrict to time or after */
+#define SNDRV_SEQ_REMOVE_TIME_TICK     (1<<6)  /* Time is in ticks */
+#define SNDRV_SEQ_REMOVE_EVENT_TYPE    (1<<7)  /* Restrict to event type */
+#define SNDRV_SEQ_REMOVE_IGNORE_OFF    (1<<8)  /* Do not flush off events */
+#define SNDRV_SEQ_REMOVE_TAG_MATCH     (1<<9)  /* Restrict to events with given tag */
+
+struct snd_seq_remove_events {
+       unsigned int  remove_mode;      /* Flags that determine what gets removed */
+
+       union snd_seq_timestamp time;
+
+       unsigned char queue;    /* Queue for REMOVE_DEST */
+       struct snd_seq_addr dest;       /* Address for REMOVE_DEST */
+       unsigned char channel;  /* Channel for REMOVE_DEST */
+
+       int  type;      /* For REMOVE_EVENT_TYPE */
+       char  tag;      /* Tag for REMOVE_TAG */
+
+       int  reserved[10];      /* To allow for future binary compatibility */
+
+};
+
+
+       /* known port numbers */
+#define SNDRV_SEQ_PORT_SYSTEM_TIMER    0
+#define SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE 1
+
+       /* port capabilities (32 bits) */
+#define SNDRV_SEQ_PORT_CAP_READ                (1<<0)  /* readable from this port */
+#define SNDRV_SEQ_PORT_CAP_WRITE       (1<<1)  /* writable to this port */
+
+#define SNDRV_SEQ_PORT_CAP_SYNC_READ   (1<<2)
+#define SNDRV_SEQ_PORT_CAP_SYNC_WRITE  (1<<3)
+
+#define SNDRV_SEQ_PORT_CAP_DUPLEX      (1<<4)
+
+#define SNDRV_SEQ_PORT_CAP_SUBS_READ   (1<<5)  /* allow read subscription */
+#define SNDRV_SEQ_PORT_CAP_SUBS_WRITE  (1<<6)  /* allow write subscription */
+#define SNDRV_SEQ_PORT_CAP_NO_EXPORT   (1<<7)  /* routing not allowed */
+
+       /* port type */
+#define SNDRV_SEQ_PORT_TYPE_SPECIFIC   (1<<0)  /* hardware specific */
+#define SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC (1<<1)        /* generic MIDI device */
+#define SNDRV_SEQ_PORT_TYPE_MIDI_GM    (1<<2)  /* General MIDI compatible device */
+#define SNDRV_SEQ_PORT_TYPE_MIDI_GS    (1<<3)  /* GS compatible device */
+#define SNDRV_SEQ_PORT_TYPE_MIDI_XG    (1<<4)  /* XG compatible device */
+#define SNDRV_SEQ_PORT_TYPE_MIDI_MT32  (1<<5)  /* MT-32 compatible device */
+#define SNDRV_SEQ_PORT_TYPE_MIDI_GM2   (1<<6)  /* General MIDI 2 compatible device */
+
+/* other standards...*/
+#define SNDRV_SEQ_PORT_TYPE_SYNTH      (1<<10) /* Synth device (no MIDI compatible - direct wavetable) */
+#define SNDRV_SEQ_PORT_TYPE_DIRECT_SAMPLE (1<<11)      /* Sampling device (support sample download) */
+#define SNDRV_SEQ_PORT_TYPE_SAMPLE     (1<<12) /* Sampling device (sample can be downloaded at any time) */
+/*...*/
+#define SNDRV_SEQ_PORT_TYPE_HARDWARE   (1<<16) /* driver for a hardware device */
+#define SNDRV_SEQ_PORT_TYPE_SOFTWARE   (1<<17) /* implemented in software */
+#define SNDRV_SEQ_PORT_TYPE_SYNTHESIZER        (1<<18) /* generates sound */
+#define SNDRV_SEQ_PORT_TYPE_PORT       (1<<19) /* connects to other device(s) */
+#define SNDRV_SEQ_PORT_TYPE_APPLICATION        (1<<20) /* application (sequencer/editor) */
+
+/* misc. conditioning flags */
+#define SNDRV_SEQ_PORT_FLG_GIVEN_PORT  (1<<0)
+#define SNDRV_SEQ_PORT_FLG_TIMESTAMP   (1<<1)
+#define SNDRV_SEQ_PORT_FLG_TIME_REAL   (1<<2)
+
+struct snd_seq_port_info {
+       struct snd_seq_addr addr;       /* client/port numbers */
+       char name[64];                  /* port name */
+
+       unsigned int capability;        /* port capability bits */
+       unsigned int type;              /* port type bits */
+       int midi_channels;              /* channels per MIDI port */
+       int midi_voices;                /* voices per MIDI port */
+       int synth_voices;               /* voices per SYNTH port */
+
+       int read_use;                   /* R/O: subscribers for output (from this port) */
+       int write_use;                  /* R/O: subscribers for input (to this port) */
+
+       void *kernel;                   /* reserved for kernel use (must be NULL) */
+       unsigned int flags;             /* misc. conditioning */
+       unsigned char time_queue;       /* queue # for timestamping */
+       char reserved[59];              /* for future use */
+};
+
+
+/* queue flags */
+#define SNDRV_SEQ_QUEUE_FLG_SYNC       (1<<0)  /* sync enabled */
+
+/* queue information */
+struct snd_seq_queue_info {
+       int queue;              /* queue id */
+
+       /*
+        *  security settings, only owner of this queue can start/stop timer
+        *  etc. if the queue is locked for other clients
+        */
+       int owner;              /* client id for owner of the queue */
+       unsigned locked:1;      /* timing queue locked for other queues */
+       char name[64];          /* name of this queue */
+       unsigned int flags;     /* flags */
+       char reserved[60];      /* for future use */
+
+};
+
+/* queue info/status */
+struct snd_seq_queue_status {
+       int queue;                      /* queue id */
+       int events;                     /* read-only - queue size */
+       snd_seq_tick_time_t tick;       /* current tick */
+       struct snd_seq_real_time time;  /* current time */
+       int running;                    /* running state of queue */
+       int flags;                      /* various flags */
+       char reserved[64];              /* for the future */
+};
+
+
+/* queue tempo */
+struct snd_seq_queue_tempo {
+       int queue;                      /* sequencer queue */
+       unsigned int tempo;             /* current tempo, us/tick */
+       int ppq;                        /* time resolution, ticks/quarter */
+       unsigned int skew_value;        /* queue skew */
+       unsigned int skew_base;         /* queue skew base */
+       char reserved[24];              /* for the future */
+};
+
+
+/* sequencer timer sources */
+#define SNDRV_SEQ_TIMER_ALSA           0       /* ALSA timer */
+#define SNDRV_SEQ_TIMER_MIDI_CLOCK     1       /* Midi Clock (CLOCK event) */
+#define SNDRV_SEQ_TIMER_MIDI_TICK      2       /* Midi Timer Tick (TICK event) */
+
+/* queue timer info */
+struct snd_seq_queue_timer {
+       int queue;                      /* sequencer queue */
+       int type;                       /* source timer type */
+       union {
+               struct {
+                       struct snd_timer_id id; /* ALSA's timer ID */
+                       unsigned int resolution;        /* resolution in Hz */
+               } alsa;
+       } u;
+       char reserved[64];              /* for the future use */
+};
+
+
+struct snd_seq_queue_client {
+       int queue;              /* sequencer queue */
+       int client;             /* sequencer client */
+       int used;               /* queue is used with this client
+                                  (must be set for accepting events) */
+       /* per client watermarks */
+       char reserved[64];      /* for future use */
+};
+
+
+#define SNDRV_SEQ_PORT_SUBS_EXCLUSIVE  (1<<0)  /* exclusive connection */
+#define SNDRV_SEQ_PORT_SUBS_TIMESTAMP  (1<<1)
+#define SNDRV_SEQ_PORT_SUBS_TIME_REAL  (1<<2)
+
+struct snd_seq_port_subscribe {
+       struct snd_seq_addr sender;     /* sender address */
+       struct snd_seq_addr dest;       /* destination address */
+       unsigned int voices;            /* number of voices to be allocated (0 = don't care) */
+       unsigned int flags;             /* modes */
+       unsigned char queue;            /* input time-stamp queue (optional) */
+       unsigned char pad[3];           /* reserved */
+       char reserved[64];
+};
+
+/* type of query subscription */
+#define SNDRV_SEQ_QUERY_SUBS_READ      0
+#define SNDRV_SEQ_QUERY_SUBS_WRITE     1
+
+struct snd_seq_query_subs {
+       struct snd_seq_addr root;       /* client/port id to be searched */
+       int type;               /* READ or WRITE */
+       int index;              /* 0..N-1 */
+       int num_subs;           /* R/O: number of subscriptions on this port */
+       struct snd_seq_addr addr;       /* R/O: result */
+       unsigned char queue;    /* R/O: result */
+       unsigned int flags;     /* R/O: result */
+       char reserved[64];      /* for future use */
+};
+
+
+/*
+ *  IOCTL commands
+ */
+
+#define SNDRV_SEQ_IOCTL_PVERSION       _IOR ('S', 0x00, int)
+#define SNDRV_SEQ_IOCTL_CLIENT_ID      _IOR ('S', 0x01, int)
+#define SNDRV_SEQ_IOCTL_SYSTEM_INFO    _IOWR('S', 0x02, struct snd_seq_system_info)
+#define SNDRV_SEQ_IOCTL_RUNNING_MODE   _IOWR('S', 0x03, struct snd_seq_running_info)
+
+#define SNDRV_SEQ_IOCTL_GET_CLIENT_INFO        _IOWR('S', 0x10, struct snd_seq_client_info)
+#define SNDRV_SEQ_IOCTL_SET_CLIENT_INFO        _IOW ('S', 0x11, struct snd_seq_client_info)
+
+#define SNDRV_SEQ_IOCTL_CREATE_PORT    _IOWR('S', 0x20, struct snd_seq_port_info)
+#define SNDRV_SEQ_IOCTL_DELETE_PORT    _IOW ('S', 0x21, struct snd_seq_port_info)
+#define SNDRV_SEQ_IOCTL_GET_PORT_INFO  _IOWR('S', 0x22, struct snd_seq_port_info)
+#define SNDRV_SEQ_IOCTL_SET_PORT_INFO  _IOW ('S', 0x23, struct snd_seq_port_info)
+
+#define SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT _IOW ('S', 0x30, struct snd_seq_port_subscribe)
+#define SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT _IOW ('S', 0x31, struct snd_seq_port_subscribe)
+
+#define SNDRV_SEQ_IOCTL_CREATE_QUEUE   _IOWR('S', 0x32, struct snd_seq_queue_info)
+#define SNDRV_SEQ_IOCTL_DELETE_QUEUE   _IOW ('S', 0x33, struct snd_seq_queue_info)
+#define SNDRV_SEQ_IOCTL_GET_QUEUE_INFO _IOWR('S', 0x34, struct snd_seq_queue_info)
+#define SNDRV_SEQ_IOCTL_SET_QUEUE_INFO _IOWR('S', 0x35, struct snd_seq_queue_info)
+#define SNDRV_SEQ_IOCTL_GET_NAMED_QUEUE        _IOWR('S', 0x36, struct snd_seq_queue_info)
+#define SNDRV_SEQ_IOCTL_GET_QUEUE_STATUS _IOWR('S', 0x40, struct snd_seq_queue_status)
+#define SNDRV_SEQ_IOCTL_GET_QUEUE_TEMPO        _IOWR('S', 0x41, struct snd_seq_queue_tempo)
+#define SNDRV_SEQ_IOCTL_SET_QUEUE_TEMPO        _IOW ('S', 0x42, struct snd_seq_queue_tempo)
+#define SNDRV_SEQ_IOCTL_GET_QUEUE_OWNER        _IOWR('S', 0x43, struct snd_seq_queue_owner)
+#define SNDRV_SEQ_IOCTL_SET_QUEUE_OWNER        _IOW ('S', 0x44, struct snd_seq_queue_owner)
+#define SNDRV_SEQ_IOCTL_GET_QUEUE_TIMER        _IOWR('S', 0x45, struct snd_seq_queue_timer)
+#define SNDRV_SEQ_IOCTL_SET_QUEUE_TIMER        _IOW ('S', 0x46, struct snd_seq_queue_timer)
+/* XXX
+#define SNDRV_SEQ_IOCTL_GET_QUEUE_SYNC _IOWR('S', 0x53, struct snd_seq_queue_sync)
+#define SNDRV_SEQ_IOCTL_SET_QUEUE_SYNC _IOW ('S', 0x54, struct snd_seq_queue_sync)
+*/
+#define SNDRV_SEQ_IOCTL_GET_QUEUE_CLIENT       _IOWR('S', 0x49, struct snd_seq_queue_client)
+#define SNDRV_SEQ_IOCTL_SET_QUEUE_CLIENT       _IOW ('S', 0x4a, struct snd_seq_queue_client)
+#define SNDRV_SEQ_IOCTL_GET_CLIENT_POOL        _IOWR('S', 0x4b, struct snd_seq_client_pool)
+#define SNDRV_SEQ_IOCTL_SET_CLIENT_POOL        _IOW ('S', 0x4c, struct snd_seq_client_pool)
+#define SNDRV_SEQ_IOCTL_REMOVE_EVENTS  _IOW ('S', 0x4e, struct snd_seq_remove_events)
+#define SNDRV_SEQ_IOCTL_QUERY_SUBS     _IOWR('S', 0x4f, struct snd_seq_query_subs)
+#define SNDRV_SEQ_IOCTL_GET_SUBSCRIPTION       _IOWR('S', 0x50, struct snd_seq_port_subscribe)
+#define SNDRV_SEQ_IOCTL_QUERY_NEXT_CLIENT      _IOWR('S', 0x51, struct snd_seq_client_info)
+#define SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT        _IOWR('S', 0x52, struct snd_seq_port_info)
+
+#endif /* _UAPI__SOUND_ASEQUENCER_H */
diff --git a/include/uapi/sound/asound.h b/include/uapi/sound/asound.h
new file mode 100644 (file)
index 0000000..85b2e4d
--- /dev/null
@@ -0,0 +1,960 @@
+/*
+ *  Advanced Linux Sound Architecture - ALSA - Driver
+ *  Copyright (c) 1994-2003 by Jaroslav Kysela <perex@perex.cz>,
+ *                             Abramo Bagnara <abramo@alsa-project.org>
+ *
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef _UAPI__SOUND_ASOUND_H
+#define _UAPI__SOUND_ASOUND_H
+
+#include <linux/types.h>
+
+
+/*
+ *  protocol version
+ */
+
+#define SNDRV_PROTOCOL_VERSION(major, minor, subminor) (((major)<<16)|((minor)<<8)|(subminor))
+#define SNDRV_PROTOCOL_MAJOR(version) (((version)>>16)&0xffff)
+#define SNDRV_PROTOCOL_MINOR(version) (((version)>>8)&0xff)
+#define SNDRV_PROTOCOL_MICRO(version) ((version)&0xff)
+#define SNDRV_PROTOCOL_INCOMPATIBLE(kversion, uversion) \
+       (SNDRV_PROTOCOL_MAJOR(kversion) != SNDRV_PROTOCOL_MAJOR(uversion) || \
+        (SNDRV_PROTOCOL_MAJOR(kversion) == SNDRV_PROTOCOL_MAJOR(uversion) && \
+          SNDRV_PROTOCOL_MINOR(kversion) != SNDRV_PROTOCOL_MINOR(uversion)))
+
+/****************************************************************************
+ *                                                                          *
+ *        Digital audio interface                                          *
+ *                                                                          *
+ ****************************************************************************/
+
+struct snd_aes_iec958 {
+       unsigned char status[24];       /* AES/IEC958 channel status bits */
+       unsigned char subcode[147];     /* AES/IEC958 subcode bits */
+       unsigned char pad;              /* nothing */
+       unsigned char dig_subframe[4];  /* AES/IEC958 subframe bits */
+};
+
+/****************************************************************************
+ *                                                                          *
+ *        CEA-861 Audio InfoFrame. Used in HDMI and DisplayPort                    *
+ *                                                                          *
+ ****************************************************************************/
+
+struct snd_cea_861_aud_if {
+       unsigned char db1_ct_cc; /* coding type and channel count */
+       unsigned char db2_sf_ss; /* sample frequency and size */
+       unsigned char db3; /* not used, all zeros */
+       unsigned char db4_ca; /* channel allocation code */
+       unsigned char db5_dminh_lsv; /* downmix inhibit & level-shit values */
+};
+
+/****************************************************************************
+ *                                                                          *
+ *      Section for driver hardware dependent interface - /dev/snd/hw?      *
+ *                                                                          *
+ ****************************************************************************/
+
+#define SNDRV_HWDEP_VERSION            SNDRV_PROTOCOL_VERSION(1, 0, 1)
+
+enum {
+       SNDRV_HWDEP_IFACE_OPL2 = 0,
+       SNDRV_HWDEP_IFACE_OPL3,
+       SNDRV_HWDEP_IFACE_OPL4,
+       SNDRV_HWDEP_IFACE_SB16CSP,      /* Creative Signal Processor */
+       SNDRV_HWDEP_IFACE_EMU10K1,      /* FX8010 processor in EMU10K1 chip */
+       SNDRV_HWDEP_IFACE_YSS225,       /* Yamaha FX processor */
+       SNDRV_HWDEP_IFACE_ICS2115,      /* Wavetable synth */
+       SNDRV_HWDEP_IFACE_SSCAPE,       /* Ensoniq SoundScape ISA card (MC68EC000) */
+       SNDRV_HWDEP_IFACE_VX,           /* Digigram VX cards */
+       SNDRV_HWDEP_IFACE_MIXART,       /* Digigram miXart cards */
+       SNDRV_HWDEP_IFACE_USX2Y,        /* Tascam US122, US224 & US428 usb */
+       SNDRV_HWDEP_IFACE_EMUX_WAVETABLE, /* EmuX wavetable */  
+       SNDRV_HWDEP_IFACE_BLUETOOTH,    /* Bluetooth audio */
+       SNDRV_HWDEP_IFACE_USX2Y_PCM,    /* Tascam US122, US224 & US428 rawusb pcm */
+       SNDRV_HWDEP_IFACE_PCXHR,        /* Digigram PCXHR */
+       SNDRV_HWDEP_IFACE_SB_RC,        /* SB Extigy/Audigy2NX remote control */
+       SNDRV_HWDEP_IFACE_HDA,          /* HD-audio */
+       SNDRV_HWDEP_IFACE_USB_STREAM,   /* direct access to usb stream */
+
+       /* Don't forget to change the following: */
+       SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_USB_STREAM
+};
+
+struct snd_hwdep_info {
+       unsigned int device;            /* WR: device number */
+       int card;                       /* R: card number */
+       unsigned char id[64];           /* ID (user selectable) */
+       unsigned char name[80];         /* hwdep name */
+       int iface;                      /* hwdep interface */
+       unsigned char reserved[64];     /* reserved for future */
+};
+
+/* generic DSP loader */
+struct snd_hwdep_dsp_status {
+       unsigned int version;           /* R: driver-specific version */
+       unsigned char id[32];           /* R: driver-specific ID string */
+       unsigned int num_dsps;          /* R: number of DSP images to transfer */
+       unsigned int dsp_loaded;        /* R: bit flags indicating the loaded DSPs */
+       unsigned int chip_ready;        /* R: 1 = initialization finished */
+       unsigned char reserved[16];     /* reserved for future use */
+};
+
+struct snd_hwdep_dsp_image {
+       unsigned int index;             /* W: DSP index */
+       unsigned char name[64];         /* W: ID (e.g. file name) */
+       unsigned char __user *image;    /* W: binary image */
+       size_t length;                  /* W: size of image in bytes */
+       unsigned long driver_data;      /* W: driver-specific data */
+};
+
+#define SNDRV_HWDEP_IOCTL_PVERSION     _IOR ('H', 0x00, int)
+#define SNDRV_HWDEP_IOCTL_INFO         _IOR ('H', 0x01, struct snd_hwdep_info)
+#define SNDRV_HWDEP_IOCTL_DSP_STATUS   _IOR('H', 0x02, struct snd_hwdep_dsp_status)
+#define SNDRV_HWDEP_IOCTL_DSP_LOAD     _IOW('H', 0x03, struct snd_hwdep_dsp_image)
+
+/*****************************************************************************
+ *                                                                           *
+ *             Digital Audio (PCM) interface - /dev/snd/pcm??                *
+ *                                                                           *
+ *****************************************************************************/
+
+#define SNDRV_PCM_VERSION              SNDRV_PROTOCOL_VERSION(2, 0, 11)
+
+typedef unsigned long snd_pcm_uframes_t;
+typedef signed long snd_pcm_sframes_t;
+
+enum {
+       SNDRV_PCM_CLASS_GENERIC = 0,    /* standard mono or stereo device */
+       SNDRV_PCM_CLASS_MULTI,          /* multichannel device */
+       SNDRV_PCM_CLASS_MODEM,          /* software modem class */
+       SNDRV_PCM_CLASS_DIGITIZER,      /* digitizer class */
+       /* Don't forget to change the following: */
+       SNDRV_PCM_CLASS_LAST = SNDRV_PCM_CLASS_DIGITIZER,
+};
+
+enum {
+       SNDRV_PCM_SUBCLASS_GENERIC_MIX = 0, /* mono or stereo subdevices are mixed together */
+       SNDRV_PCM_SUBCLASS_MULTI_MIX,   /* multichannel subdevices are mixed together */
+       /* Don't forget to change the following: */
+       SNDRV_PCM_SUBCLASS_LAST = SNDRV_PCM_SUBCLASS_MULTI_MIX,
+};
+
+enum {
+       SNDRV_PCM_STREAM_PLAYBACK = 0,
+       SNDRV_PCM_STREAM_CAPTURE,
+       SNDRV_PCM_STREAM_LAST = SNDRV_PCM_STREAM_CAPTURE,
+};
+
+typedef int __bitwise snd_pcm_access_t;
+#define        SNDRV_PCM_ACCESS_MMAP_INTERLEAVED       ((__force snd_pcm_access_t) 0) /* interleaved mmap */
+#define        SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED    ((__force snd_pcm_access_t) 1) /* noninterleaved mmap */
+#define        SNDRV_PCM_ACCESS_MMAP_COMPLEX           ((__force snd_pcm_access_t) 2) /* complex mmap */
+#define        SNDRV_PCM_ACCESS_RW_INTERLEAVED         ((__force snd_pcm_access_t) 3) /* readi/writei */
+#define        SNDRV_PCM_ACCESS_RW_NONINTERLEAVED      ((__force snd_pcm_access_t) 4) /* readn/writen */
+#define        SNDRV_PCM_ACCESS_LAST           SNDRV_PCM_ACCESS_RW_NONINTERLEAVED
+
+typedef int __bitwise snd_pcm_format_t;
+#define        SNDRV_PCM_FORMAT_S8     ((__force snd_pcm_format_t) 0)
+#define        SNDRV_PCM_FORMAT_U8     ((__force snd_pcm_format_t) 1)
+#define        SNDRV_PCM_FORMAT_S16_LE ((__force snd_pcm_format_t) 2)
+#define        SNDRV_PCM_FORMAT_S16_BE ((__force snd_pcm_format_t) 3)
+#define        SNDRV_PCM_FORMAT_U16_LE ((__force snd_pcm_format_t) 4)
+#define        SNDRV_PCM_FORMAT_U16_BE ((__force snd_pcm_format_t) 5)
+#define        SNDRV_PCM_FORMAT_S24_LE ((__force snd_pcm_format_t) 6) /* low three bytes */
+#define        SNDRV_PCM_FORMAT_S24_BE ((__force snd_pcm_format_t) 7) /* low three bytes */
+#define        SNDRV_PCM_FORMAT_U24_LE ((__force snd_pcm_format_t) 8) /* low three bytes */
+#define        SNDRV_PCM_FORMAT_U24_BE ((__force snd_pcm_format_t) 9) /* low three bytes */
+#define        SNDRV_PCM_FORMAT_S32_LE ((__force snd_pcm_format_t) 10)
+#define        SNDRV_PCM_FORMAT_S32_BE ((__force snd_pcm_format_t) 11)
+#define        SNDRV_PCM_FORMAT_U32_LE ((__force snd_pcm_format_t) 12)
+#define        SNDRV_PCM_FORMAT_U32_BE ((__force snd_pcm_format_t) 13)
+#define        SNDRV_PCM_FORMAT_FLOAT_LE       ((__force snd_pcm_format_t) 14) /* 4-byte float, IEEE-754 32-bit, range -1.0 to 1.0 */
+#define        SNDRV_PCM_FORMAT_FLOAT_BE       ((__force snd_pcm_format_t) 15) /* 4-byte float, IEEE-754 32-bit, range -1.0 to 1.0 */
+#define        SNDRV_PCM_FORMAT_FLOAT64_LE     ((__force snd_pcm_format_t) 16) /* 8-byte float, IEEE-754 64-bit, range -1.0 to 1.0 */
+#define        SNDRV_PCM_FORMAT_FLOAT64_BE     ((__force snd_pcm_format_t) 17) /* 8-byte float, IEEE-754 64-bit, range -1.0 to 1.0 */
+#define        SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE ((__force snd_pcm_format_t) 18) /* IEC-958 subframe, Little Endian */
+#define        SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE ((__force snd_pcm_format_t) 19) /* IEC-958 subframe, Big Endian */
+#define        SNDRV_PCM_FORMAT_MU_LAW         ((__force snd_pcm_format_t) 20)
+#define        SNDRV_PCM_FORMAT_A_LAW          ((__force snd_pcm_format_t) 21)
+#define        SNDRV_PCM_FORMAT_IMA_ADPCM      ((__force snd_pcm_format_t) 22)
+#define        SNDRV_PCM_FORMAT_MPEG           ((__force snd_pcm_format_t) 23)
+#define        SNDRV_PCM_FORMAT_GSM            ((__force snd_pcm_format_t) 24)
+#define        SNDRV_PCM_FORMAT_SPECIAL        ((__force snd_pcm_format_t) 31)
+#define        SNDRV_PCM_FORMAT_S24_3LE        ((__force snd_pcm_format_t) 32) /* in three bytes */
+#define        SNDRV_PCM_FORMAT_S24_3BE        ((__force snd_pcm_format_t) 33) /* in three bytes */
+#define        SNDRV_PCM_FORMAT_U24_3LE        ((__force snd_pcm_format_t) 34) /* in three bytes */
+#define        SNDRV_PCM_FORMAT_U24_3BE        ((__force snd_pcm_format_t) 35) /* in three bytes */
+#define        SNDRV_PCM_FORMAT_S20_3LE        ((__force snd_pcm_format_t) 36) /* in three bytes */
+#define        SNDRV_PCM_FORMAT_S20_3BE        ((__force snd_pcm_format_t) 37) /* in three bytes */
+#define        SNDRV_PCM_FORMAT_U20_3LE        ((__force snd_pcm_format_t) 38) /* in three bytes */
+#define        SNDRV_PCM_FORMAT_U20_3BE        ((__force snd_pcm_format_t) 39) /* in three bytes */
+#define        SNDRV_PCM_FORMAT_S18_3LE        ((__force snd_pcm_format_t) 40) /* in three bytes */
+#define        SNDRV_PCM_FORMAT_S18_3BE        ((__force snd_pcm_format_t) 41) /* in three bytes */
+#define        SNDRV_PCM_FORMAT_U18_3LE        ((__force snd_pcm_format_t) 42) /* in three bytes */
+#define        SNDRV_PCM_FORMAT_U18_3BE        ((__force snd_pcm_format_t) 43) /* in three bytes */
+#define        SNDRV_PCM_FORMAT_G723_24        ((__force snd_pcm_format_t) 44) /* 8 samples in 3 bytes */
+#define        SNDRV_PCM_FORMAT_G723_24_1B     ((__force snd_pcm_format_t) 45) /* 1 sample in 1 byte */
+#define        SNDRV_PCM_FORMAT_G723_40        ((__force snd_pcm_format_t) 46) /* 8 Samples in 5 bytes */
+#define        SNDRV_PCM_FORMAT_G723_40_1B     ((__force snd_pcm_format_t) 47) /* 1 sample in 1 byte */
+#define        SNDRV_PCM_FORMAT_LAST           SNDRV_PCM_FORMAT_G723_40_1B
+
+#ifdef SNDRV_LITTLE_ENDIAN
+#define        SNDRV_PCM_FORMAT_S16            SNDRV_PCM_FORMAT_S16_LE
+#define        SNDRV_PCM_FORMAT_U16            SNDRV_PCM_FORMAT_U16_LE
+#define        SNDRV_PCM_FORMAT_S24            SNDRV_PCM_FORMAT_S24_LE
+#define        SNDRV_PCM_FORMAT_U24            SNDRV_PCM_FORMAT_U24_LE
+#define        SNDRV_PCM_FORMAT_S32            SNDRV_PCM_FORMAT_S32_LE
+#define        SNDRV_PCM_FORMAT_U32            SNDRV_PCM_FORMAT_U32_LE
+#define        SNDRV_PCM_FORMAT_FLOAT          SNDRV_PCM_FORMAT_FLOAT_LE
+#define        SNDRV_PCM_FORMAT_FLOAT64        SNDRV_PCM_FORMAT_FLOAT64_LE
+#define        SNDRV_PCM_FORMAT_IEC958_SUBFRAME SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE
+#endif
+#ifdef SNDRV_BIG_ENDIAN
+#define        SNDRV_PCM_FORMAT_S16            SNDRV_PCM_FORMAT_S16_BE
+#define        SNDRV_PCM_FORMAT_U16            SNDRV_PCM_FORMAT_U16_BE
+#define        SNDRV_PCM_FORMAT_S24            SNDRV_PCM_FORMAT_S24_BE
+#define        SNDRV_PCM_FORMAT_U24            SNDRV_PCM_FORMAT_U24_BE
+#define        SNDRV_PCM_FORMAT_S32            SNDRV_PCM_FORMAT_S32_BE
+#define        SNDRV_PCM_FORMAT_U32            SNDRV_PCM_FORMAT_U32_BE
+#define        SNDRV_PCM_FORMAT_FLOAT          SNDRV_PCM_FORMAT_FLOAT_BE
+#define        SNDRV_PCM_FORMAT_FLOAT64        SNDRV_PCM_FORMAT_FLOAT64_BE
+#define        SNDRV_PCM_FORMAT_IEC958_SUBFRAME SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE
+#endif
+
+typedef int __bitwise snd_pcm_subformat_t;
+#define        SNDRV_PCM_SUBFORMAT_STD         ((__force snd_pcm_subformat_t) 0)
+#define        SNDRV_PCM_SUBFORMAT_LAST        SNDRV_PCM_SUBFORMAT_STD
+
+#define SNDRV_PCM_INFO_MMAP            0x00000001      /* hardware supports mmap */
+#define SNDRV_PCM_INFO_MMAP_VALID      0x00000002      /* period data are valid during transfer */
+#define SNDRV_PCM_INFO_DOUBLE          0x00000004      /* Double buffering needed for PCM start/stop */
+#define SNDRV_PCM_INFO_BATCH           0x00000010      /* double buffering */
+#define SNDRV_PCM_INFO_INTERLEAVED     0x00000100      /* channels are interleaved */
+#define SNDRV_PCM_INFO_NONINTERLEAVED  0x00000200      /* channels are not interleaved */
+#define SNDRV_PCM_INFO_COMPLEX         0x00000400      /* complex frame organization (mmap only) */
+#define SNDRV_PCM_INFO_BLOCK_TRANSFER  0x00010000      /* hardware transfer block of samples */
+#define SNDRV_PCM_INFO_OVERRANGE       0x00020000      /* hardware supports ADC (capture) overrange detection */
+#define SNDRV_PCM_INFO_RESUME          0x00040000      /* hardware supports stream resume after suspend */
+#define SNDRV_PCM_INFO_PAUSE           0x00080000      /* pause ioctl is supported */
+#define SNDRV_PCM_INFO_HALF_DUPLEX     0x00100000      /* only half duplex */
+#define SNDRV_PCM_INFO_JOINT_DUPLEX    0x00200000      /* playback and capture stream are somewhat correlated */
+#define SNDRV_PCM_INFO_SYNC_START      0x00400000      /* pcm support some kind of sync go */
+#define SNDRV_PCM_INFO_NO_PERIOD_WAKEUP        0x00800000      /* period wakeup can be disabled */
+#define SNDRV_PCM_INFO_HAS_WALL_CLOCK   0x01000000      /* has audio wall clock for audio/system time sync */
+#define SNDRV_PCM_INFO_FIFO_IN_FRAMES  0x80000000      /* internal kernel flag - FIFO size is in frames */
+
+typedef int __bitwise snd_pcm_state_t;
+#define        SNDRV_PCM_STATE_OPEN            ((__force snd_pcm_state_t) 0) /* stream is open */
+#define        SNDRV_PCM_STATE_SETUP           ((__force snd_pcm_state_t) 1) /* stream has a setup */
+#define        SNDRV_PCM_STATE_PREPARED        ((__force snd_pcm_state_t) 2) /* stream is ready to start */
+#define        SNDRV_PCM_STATE_RUNNING         ((__force snd_pcm_state_t) 3) /* stream is running */
+#define        SNDRV_PCM_STATE_XRUN            ((__force snd_pcm_state_t) 4) /* stream reached an xrun */
+#define        SNDRV_PCM_STATE_DRAINING        ((__force snd_pcm_state_t) 5) /* stream is draining */
+#define        SNDRV_PCM_STATE_PAUSED          ((__force snd_pcm_state_t) 6) /* stream is paused */
+#define        SNDRV_PCM_STATE_SUSPENDED       ((__force snd_pcm_state_t) 7) /* hardware is suspended */
+#define        SNDRV_PCM_STATE_DISCONNECTED    ((__force snd_pcm_state_t) 8) /* hardware is disconnected */
+#define        SNDRV_PCM_STATE_LAST            SNDRV_PCM_STATE_DISCONNECTED
+
+enum {
+       SNDRV_PCM_MMAP_OFFSET_DATA = 0x00000000,
+       SNDRV_PCM_MMAP_OFFSET_STATUS = 0x80000000,
+       SNDRV_PCM_MMAP_OFFSET_CONTROL = 0x81000000,
+};
+
+union snd_pcm_sync_id {
+       unsigned char id[16];
+       unsigned short id16[8];
+       unsigned int id32[4];
+};
+
+struct snd_pcm_info {
+       unsigned int device;            /* RO/WR (control): device number */
+       unsigned int subdevice;         /* RO/WR (control): subdevice number */
+       int stream;                     /* RO/WR (control): stream direction */
+       int card;                       /* R: card number */
+       unsigned char id[64];           /* ID (user selectable) */
+       unsigned char name[80];         /* name of this device */
+       unsigned char subname[32];      /* subdevice name */
+       int dev_class;                  /* SNDRV_PCM_CLASS_* */
+       int dev_subclass;               /* SNDRV_PCM_SUBCLASS_* */
+       unsigned int subdevices_count;
+       unsigned int subdevices_avail;
+       union snd_pcm_sync_id sync;     /* hardware synchronization ID */
+       unsigned char reserved[64];     /* reserved for future... */
+};
+
+typedef int snd_pcm_hw_param_t;
+#define        SNDRV_PCM_HW_PARAM_ACCESS       0       /* Access type */
+#define        SNDRV_PCM_HW_PARAM_FORMAT       1       /* Format */
+#define        SNDRV_PCM_HW_PARAM_SUBFORMAT    2       /* Subformat */
+#define        SNDRV_PCM_HW_PARAM_FIRST_MASK   SNDRV_PCM_HW_PARAM_ACCESS
+#define        SNDRV_PCM_HW_PARAM_LAST_MASK    SNDRV_PCM_HW_PARAM_SUBFORMAT
+
+#define        SNDRV_PCM_HW_PARAM_SAMPLE_BITS  8       /* Bits per sample */
+#define        SNDRV_PCM_HW_PARAM_FRAME_BITS   9       /* Bits per frame */
+#define        SNDRV_PCM_HW_PARAM_CHANNELS     10      /* Channels */
+#define        SNDRV_PCM_HW_PARAM_RATE         11      /* Approx rate */
+#define        SNDRV_PCM_HW_PARAM_PERIOD_TIME  12      /* Approx distance between
+                                                * interrupts in us
+                                                */
+#define        SNDRV_PCM_HW_PARAM_PERIOD_SIZE  13      /* Approx frames between
+                                                * interrupts
+                                                */
+#define        SNDRV_PCM_HW_PARAM_PERIOD_BYTES 14      /* Approx bytes between
+                                                * interrupts
+                                                */
+#define        SNDRV_PCM_HW_PARAM_PERIODS      15      /* Approx interrupts per
+                                                * buffer
+                                                */
+#define        SNDRV_PCM_HW_PARAM_BUFFER_TIME  16      /* Approx duration of buffer
+                                                * in us
+                                                */
+#define        SNDRV_PCM_HW_PARAM_BUFFER_SIZE  17      /* Size of buffer in frames */
+#define        SNDRV_PCM_HW_PARAM_BUFFER_BYTES 18      /* Size of buffer in bytes */
+#define        SNDRV_PCM_HW_PARAM_TICK_TIME    19      /* Approx tick duration in us */
+#define        SNDRV_PCM_HW_PARAM_FIRST_INTERVAL       SNDRV_PCM_HW_PARAM_SAMPLE_BITS
+#define        SNDRV_PCM_HW_PARAM_LAST_INTERVAL        SNDRV_PCM_HW_PARAM_TICK_TIME
+
+#define SNDRV_PCM_HW_PARAMS_NORESAMPLE (1<<0)  /* avoid rate resampling */
+#define SNDRV_PCM_HW_PARAMS_EXPORT_BUFFER      (1<<1)  /* export buffer */
+#define SNDRV_PCM_HW_PARAMS_NO_PERIOD_WAKEUP   (1<<2)  /* disable period wakeups */
+
+struct snd_interval {
+       unsigned int min, max;
+       unsigned int openmin:1,
+                    openmax:1,
+                    integer:1,
+                    empty:1;
+};
+
+#define SNDRV_MASK_MAX 256
+
+struct snd_mask {
+       __u32 bits[(SNDRV_MASK_MAX+31)/32];
+};
+
+struct snd_pcm_hw_params {
+       unsigned int flags;
+       struct snd_mask masks[SNDRV_PCM_HW_PARAM_LAST_MASK - 
+                              SNDRV_PCM_HW_PARAM_FIRST_MASK + 1];
+       struct snd_mask mres[5];        /* reserved masks */
+       struct snd_interval intervals[SNDRV_PCM_HW_PARAM_LAST_INTERVAL -
+                                       SNDRV_PCM_HW_PARAM_FIRST_INTERVAL + 1];
+       struct snd_interval ires[9];    /* reserved intervals */
+       unsigned int rmask;             /* W: requested masks */
+       unsigned int cmask;             /* R: changed masks */
+       unsigned int info;              /* R: Info flags for returned setup */
+       unsigned int msbits;            /* R: used most significant bits */
+       unsigned int rate_num;          /* R: rate numerator */
+       unsigned int rate_den;          /* R: rate denominator */
+       snd_pcm_uframes_t fifo_size;    /* R: chip FIFO size in frames */
+       unsigned char reserved[64];     /* reserved for future */
+};
+
+enum {
+       SNDRV_PCM_TSTAMP_NONE = 0,
+       SNDRV_PCM_TSTAMP_ENABLE,
+       SNDRV_PCM_TSTAMP_LAST = SNDRV_PCM_TSTAMP_ENABLE,
+};
+
+struct snd_pcm_sw_params {
+       int tstamp_mode;                        /* timestamp mode */
+       unsigned int period_step;
+       unsigned int sleep_min;                 /* min ticks to sleep */
+       snd_pcm_uframes_t avail_min;            /* min avail frames for wakeup */
+       snd_pcm_uframes_t xfer_align;           /* obsolete: xfer size need to be a multiple */
+       snd_pcm_uframes_t start_threshold;      /* min hw_avail frames for automatic start */
+       snd_pcm_uframes_t stop_threshold;       /* min avail frames for automatic stop */
+       snd_pcm_uframes_t silence_threshold;    /* min distance from noise for silence filling */
+       snd_pcm_uframes_t silence_size;         /* silence block size */
+       snd_pcm_uframes_t boundary;             /* pointers wrap point */
+       unsigned char reserved[64];             /* reserved for future */
+};
+
+struct snd_pcm_channel_info {
+       unsigned int channel;
+       __kernel_off_t offset;          /* mmap offset */
+       unsigned int first;             /* offset to first sample in bits */
+       unsigned int step;              /* samples distance in bits */
+};
+
+struct snd_pcm_status {
+       snd_pcm_state_t state;          /* stream state */
+       struct timespec trigger_tstamp; /* time when stream was started/stopped/paused */
+       struct timespec tstamp;         /* reference timestamp */
+       snd_pcm_uframes_t appl_ptr;     /* appl ptr */
+       snd_pcm_uframes_t hw_ptr;       /* hw ptr */
+       snd_pcm_sframes_t delay;        /* current delay in frames */
+       snd_pcm_uframes_t avail;        /* number of frames available */
+       snd_pcm_uframes_t avail_max;    /* max frames available on hw since last status */
+       snd_pcm_uframes_t overrange;    /* count of ADC (capture) overrange detections from last status */
+       snd_pcm_state_t suspended_state; /* suspended stream state */
+       struct timespec audio_tstamp;   /* from sample counter or wall clock */
+       unsigned char reserved[60-sizeof(struct timespec)]; /* must be filled with zero */
+};
+
+struct snd_pcm_mmap_status {
+       snd_pcm_state_t state;          /* RO: state - SNDRV_PCM_STATE_XXXX */
+       int pad1;                       /* Needed for 64 bit alignment */
+       snd_pcm_uframes_t hw_ptr;       /* RO: hw ptr (0...boundary-1) */
+       struct timespec tstamp;         /* Timestamp */
+       snd_pcm_state_t suspended_state; /* RO: suspended stream state */
+       struct timespec audio_tstamp;   /* from sample counter or wall clock */
+};
+
+struct snd_pcm_mmap_control {
+       snd_pcm_uframes_t appl_ptr;     /* RW: appl ptr (0...boundary-1) */
+       snd_pcm_uframes_t avail_min;    /* RW: min available frames for wakeup */
+};
+
+#define SNDRV_PCM_SYNC_PTR_HWSYNC      (1<<0)  /* execute hwsync */
+#define SNDRV_PCM_SYNC_PTR_APPL                (1<<1)  /* get appl_ptr from driver (r/w op) */
+#define SNDRV_PCM_SYNC_PTR_AVAIL_MIN   (1<<2)  /* get avail_min from driver */
+
+struct snd_pcm_sync_ptr {
+       unsigned int flags;
+       union {
+               struct snd_pcm_mmap_status status;
+               unsigned char reserved[64];
+       } s;
+       union {
+               struct snd_pcm_mmap_control control;
+               unsigned char reserved[64];
+       } c;
+};
+
+struct snd_xferi {
+       snd_pcm_sframes_t result;
+       void __user *buf;
+       snd_pcm_uframes_t frames;
+};
+
+struct snd_xfern {
+       snd_pcm_sframes_t result;
+       void __user * __user *bufs;
+       snd_pcm_uframes_t frames;
+};
+
+enum {
+       SNDRV_PCM_TSTAMP_TYPE_GETTIMEOFDAY = 0, /* gettimeofday equivalent */
+       SNDRV_PCM_TSTAMP_TYPE_MONOTONIC,        /* posix_clock_monotonic equivalent */
+       SNDRV_PCM_TSTAMP_TYPE_LAST = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC,
+};
+
+/* channel positions */
+enum {
+       SNDRV_CHMAP_UNKNOWN = 0,
+       SNDRV_CHMAP_NA,         /* N/A, silent */
+       SNDRV_CHMAP_MONO,       /* mono stream */
+       /* this follows the alsa-lib mixer channel value + 3 */
+       SNDRV_CHMAP_FL,         /* front left */
+       SNDRV_CHMAP_FR,         /* front right */
+       SNDRV_CHMAP_RL,         /* rear left */
+       SNDRV_CHMAP_RR,         /* rear right */
+       SNDRV_CHMAP_FC,         /* front center */
+       SNDRV_CHMAP_LFE,        /* LFE */
+       SNDRV_CHMAP_SL,         /* side left */
+       SNDRV_CHMAP_SR,         /* side right */
+       SNDRV_CHMAP_RC,         /* rear center */
+       /* new definitions */
+       SNDRV_CHMAP_FLC,        /* front left center */
+       SNDRV_CHMAP_FRC,        /* front right center */
+       SNDRV_CHMAP_RLC,        /* rear left center */
+       SNDRV_CHMAP_RRC,        /* rear right center */
+       SNDRV_CHMAP_FLW,        /* front left wide */
+       SNDRV_CHMAP_FRW,        /* front right wide */
+       SNDRV_CHMAP_FLH,        /* front left high */
+       SNDRV_CHMAP_FCH,        /* front center high */
+       SNDRV_CHMAP_FRH,        /* front right high */
+       SNDRV_CHMAP_TC,         /* top center */
+       SNDRV_CHMAP_TFL,        /* top front left */
+       SNDRV_CHMAP_TFR,        /* top front right */
+       SNDRV_CHMAP_TFC,        /* top front center */
+       SNDRV_CHMAP_TRL,        /* top rear left */
+       SNDRV_CHMAP_TRR,        /* top rear right */
+       SNDRV_CHMAP_TRC,        /* top rear center */
+       SNDRV_CHMAP_LAST = SNDRV_CHMAP_TRC,
+};
+
+#define SNDRV_CHMAP_POSITION_MASK      0xffff
+#define SNDRV_CHMAP_PHASE_INVERSE      (0x01 << 16)
+#define SNDRV_CHMAP_DRIVER_SPEC                (0x02 << 16)
+
+#define SNDRV_PCM_IOCTL_PVERSION       _IOR('A', 0x00, int)
+#define SNDRV_PCM_IOCTL_INFO           _IOR('A', 0x01, struct snd_pcm_info)
+#define SNDRV_PCM_IOCTL_TSTAMP         _IOW('A', 0x02, int)
+#define SNDRV_PCM_IOCTL_TTSTAMP                _IOW('A', 0x03, int)
+#define SNDRV_PCM_IOCTL_HW_REFINE      _IOWR('A', 0x10, struct snd_pcm_hw_params)
+#define SNDRV_PCM_IOCTL_HW_PARAMS      _IOWR('A', 0x11, struct snd_pcm_hw_params)
+#define SNDRV_PCM_IOCTL_HW_FREE                _IO('A', 0x12)
+#define SNDRV_PCM_IOCTL_SW_PARAMS      _IOWR('A', 0x13, struct snd_pcm_sw_params)
+#define SNDRV_PCM_IOCTL_STATUS         _IOR('A', 0x20, struct snd_pcm_status)
+#define SNDRV_PCM_IOCTL_DELAY          _IOR('A', 0x21, snd_pcm_sframes_t)
+#define SNDRV_PCM_IOCTL_HWSYNC         _IO('A', 0x22)
+#define SNDRV_PCM_IOCTL_SYNC_PTR       _IOWR('A', 0x23, struct snd_pcm_sync_ptr)
+#define SNDRV_PCM_IOCTL_CHANNEL_INFO   _IOR('A', 0x32, struct snd_pcm_channel_info)
+#define SNDRV_PCM_IOCTL_PREPARE                _IO('A', 0x40)
+#define SNDRV_PCM_IOCTL_RESET          _IO('A', 0x41)
+#define SNDRV_PCM_IOCTL_START          _IO('A', 0x42)
+#define SNDRV_PCM_IOCTL_DROP           _IO('A', 0x43)
+#define SNDRV_PCM_IOCTL_DRAIN          _IO('A', 0x44)
+#define SNDRV_PCM_IOCTL_PAUSE          _IOW('A', 0x45, int)
+#define SNDRV_PCM_IOCTL_REWIND         _IOW('A', 0x46, snd_pcm_uframes_t)
+#define SNDRV_PCM_IOCTL_RESUME         _IO('A', 0x47)
+#define SNDRV_PCM_IOCTL_XRUN           _IO('A', 0x48)
+#define SNDRV_PCM_IOCTL_FORWARD                _IOW('A', 0x49, snd_pcm_uframes_t)
+#define SNDRV_PCM_IOCTL_WRITEI_FRAMES  _IOW('A', 0x50, struct snd_xferi)
+#define SNDRV_PCM_IOCTL_READI_FRAMES   _IOR('A', 0x51, struct snd_xferi)
+#define SNDRV_PCM_IOCTL_WRITEN_FRAMES  _IOW('A', 0x52, struct snd_xfern)
+#define SNDRV_PCM_IOCTL_READN_FRAMES   _IOR('A', 0x53, struct snd_xfern)
+#define SNDRV_PCM_IOCTL_LINK           _IOW('A', 0x60, int)
+#define SNDRV_PCM_IOCTL_UNLINK         _IO('A', 0x61)
+
+/*****************************************************************************
+ *                                                                           *
+ *                            MIDI v1.0 interface                            *
+ *                                                                           *
+ *****************************************************************************/
+
+/*
+ *  Raw MIDI section - /dev/snd/midi??
+ */
+
+#define SNDRV_RAWMIDI_VERSION          SNDRV_PROTOCOL_VERSION(2, 0, 0)
+
+enum {
+       SNDRV_RAWMIDI_STREAM_OUTPUT = 0,
+       SNDRV_RAWMIDI_STREAM_INPUT,
+       SNDRV_RAWMIDI_STREAM_LAST = SNDRV_RAWMIDI_STREAM_INPUT,
+};
+
+#define SNDRV_RAWMIDI_INFO_OUTPUT              0x00000001
+#define SNDRV_RAWMIDI_INFO_INPUT               0x00000002
+#define SNDRV_RAWMIDI_INFO_DUPLEX              0x00000004
+
+struct snd_rawmidi_info {
+       unsigned int device;            /* RO/WR (control): device number */
+       unsigned int subdevice;         /* RO/WR (control): subdevice number */
+       int stream;                     /* WR: stream */
+       int card;                       /* R: card number */
+       unsigned int flags;             /* SNDRV_RAWMIDI_INFO_XXXX */
+       unsigned char id[64];           /* ID (user selectable) */
+       unsigned char name[80];         /* name of device */
+       unsigned char subname[32];      /* name of active or selected subdevice */
+       unsigned int subdevices_count;
+       unsigned int subdevices_avail;
+       unsigned char reserved[64];     /* reserved for future use */
+};
+
+struct snd_rawmidi_params {
+       int stream;
+       size_t buffer_size;             /* queue size in bytes */
+       size_t avail_min;               /* minimum avail bytes for wakeup */
+       unsigned int no_active_sensing: 1; /* do not send active sensing byte in close() */
+       unsigned char reserved[16];     /* reserved for future use */
+};
+
+struct snd_rawmidi_status {
+       int stream;
+       struct timespec tstamp;         /* Timestamp */
+       size_t avail;                   /* available bytes */
+       size_t xruns;                   /* count of overruns since last status (in bytes) */
+       unsigned char reserved[16];     /* reserved for future use */
+};
+
+#define SNDRV_RAWMIDI_IOCTL_PVERSION   _IOR('W', 0x00, int)
+#define SNDRV_RAWMIDI_IOCTL_INFO       _IOR('W', 0x01, struct snd_rawmidi_info)
+#define SNDRV_RAWMIDI_IOCTL_PARAMS     _IOWR('W', 0x10, struct snd_rawmidi_params)
+#define SNDRV_RAWMIDI_IOCTL_STATUS     _IOWR('W', 0x20, struct snd_rawmidi_status)
+#define SNDRV_RAWMIDI_IOCTL_DROP       _IOW('W', 0x30, int)
+#define SNDRV_RAWMIDI_IOCTL_DRAIN      _IOW('W', 0x31, int)
+
+/*
+ *  Timer section - /dev/snd/timer
+ */
+
+#define SNDRV_TIMER_VERSION            SNDRV_PROTOCOL_VERSION(2, 0, 6)
+
+enum {
+       SNDRV_TIMER_CLASS_NONE = -1,
+       SNDRV_TIMER_CLASS_SLAVE = 0,
+       SNDRV_TIMER_CLASS_GLOBAL,
+       SNDRV_TIMER_CLASS_CARD,
+       SNDRV_TIMER_CLASS_PCM,
+       SNDRV_TIMER_CLASS_LAST = SNDRV_TIMER_CLASS_PCM,
+};
+
+/* slave timer classes */
+enum {
+       SNDRV_TIMER_SCLASS_NONE = 0,
+       SNDRV_TIMER_SCLASS_APPLICATION,
+       SNDRV_TIMER_SCLASS_SEQUENCER,           /* alias */
+       SNDRV_TIMER_SCLASS_OSS_SEQUENCER,       /* alias */
+       SNDRV_TIMER_SCLASS_LAST = SNDRV_TIMER_SCLASS_OSS_SEQUENCER,
+};
+
+/* global timers (device member) */
+#define SNDRV_TIMER_GLOBAL_SYSTEM      0
+#define SNDRV_TIMER_GLOBAL_RTC         1
+#define SNDRV_TIMER_GLOBAL_HPET                2
+#define SNDRV_TIMER_GLOBAL_HRTIMER     3
+
+/* info flags */
+#define SNDRV_TIMER_FLG_SLAVE          (1<<0)  /* cannot be controlled */
+
+struct snd_timer_id {
+       int dev_class;
+       int dev_sclass;
+       int card;
+       int device;
+       int subdevice;
+};
+
+struct snd_timer_ginfo {
+       struct snd_timer_id tid;        /* requested timer ID */
+       unsigned int flags;             /* timer flags - SNDRV_TIMER_FLG_* */
+       int card;                       /* card number */
+       unsigned char id[64];           /* timer identification */
+       unsigned char name[80];         /* timer name */
+       unsigned long reserved0;        /* reserved for future use */
+       unsigned long resolution;       /* average period resolution in ns */
+       unsigned long resolution_min;   /* minimal period resolution in ns */
+       unsigned long resolution_max;   /* maximal period resolution in ns */
+       unsigned int clients;           /* active timer clients */
+       unsigned char reserved[32];
+};
+
+struct snd_timer_gparams {
+       struct snd_timer_id tid;        /* requested timer ID */
+       unsigned long period_num;       /* requested precise period duration (in seconds) - numerator */
+       unsigned long period_den;       /* requested precise period duration (in seconds) - denominator */
+       unsigned char reserved[32];
+};
+
+struct snd_timer_gstatus {
+       struct snd_timer_id tid;        /* requested timer ID */
+       unsigned long resolution;       /* current period resolution in ns */
+       unsigned long resolution_num;   /* precise current period resolution (in seconds) - numerator */
+       unsigned long resolution_den;   /* precise current period resolution (in seconds) - denominator */
+       unsigned char reserved[32];
+};
+
+struct snd_timer_select {
+       struct snd_timer_id id; /* bind to timer ID */
+       unsigned char reserved[32];     /* reserved */
+};
+
+struct snd_timer_info {
+       unsigned int flags;             /* timer flags - SNDRV_TIMER_FLG_* */
+       int card;                       /* card number */
+       unsigned char id[64];           /* timer identificator */
+       unsigned char name[80];         /* timer name */
+       unsigned long reserved0;        /* reserved for future use */
+       unsigned long resolution;       /* average period resolution in ns */
+       unsigned char reserved[64];     /* reserved */
+};
+
+#define SNDRV_TIMER_PSFLG_AUTO         (1<<0)  /* auto start, otherwise one-shot */
+#define SNDRV_TIMER_PSFLG_EXCLUSIVE    (1<<1)  /* exclusive use, precise start/stop/pause/continue */
+#define SNDRV_TIMER_PSFLG_EARLY_EVENT  (1<<2)  /* write early event to the poll queue */
+
+struct snd_timer_params {
+       unsigned int flags;             /* flags - SNDRV_MIXER_PSFLG_* */
+       unsigned int ticks;             /* requested resolution in ticks */
+       unsigned int queue_size;        /* total size of queue (32-1024) */
+       unsigned int reserved0;         /* reserved, was: failure locations */
+       unsigned int filter;            /* event filter (bitmask of SNDRV_TIMER_EVENT_*) */
+       unsigned char reserved[60];     /* reserved */
+};
+
+struct snd_timer_status {
+       struct timespec tstamp;         /* Timestamp - last update */
+       unsigned int resolution;        /* current period resolution in ns */
+       unsigned int lost;              /* counter of master tick lost */
+       unsigned int overrun;           /* count of read queue overruns */
+       unsigned int queue;             /* used queue size */
+       unsigned char reserved[64];     /* reserved */
+};
+
+#define SNDRV_TIMER_IOCTL_PVERSION     _IOR('T', 0x00, int)
+#define SNDRV_TIMER_IOCTL_NEXT_DEVICE  _IOWR('T', 0x01, struct snd_timer_id)
+#define SNDRV_TIMER_IOCTL_TREAD                _IOW('T', 0x02, int)
+#define SNDRV_TIMER_IOCTL_GINFO                _IOWR('T', 0x03, struct snd_timer_ginfo)
+#define SNDRV_TIMER_IOCTL_GPARAMS      _IOW('T', 0x04, struct snd_timer_gparams)
+#define SNDRV_TIMER_IOCTL_GSTATUS      _IOWR('T', 0x05, struct snd_timer_gstatus)
+#define SNDRV_TIMER_IOCTL_SELECT       _IOW('T', 0x10, struct snd_timer_select)
+#define SNDRV_TIMER_IOCTL_INFO         _IOR('T', 0x11, struct snd_timer_info)
+#define SNDRV_TIMER_IOCTL_PARAMS       _IOW('T', 0x12, struct snd_timer_params)
+#define SNDRV_TIMER_IOCTL_STATUS       _IOR('T', 0x14, struct snd_timer_status)
+/* The following four ioctls are changed since 1.0.9 due to confliction */
+#define SNDRV_TIMER_IOCTL_START                _IO('T', 0xa0)
+#define SNDRV_TIMER_IOCTL_STOP         _IO('T', 0xa1)
+#define SNDRV_TIMER_IOCTL_CONTINUE     _IO('T', 0xa2)
+#define SNDRV_TIMER_IOCTL_PAUSE                _IO('T', 0xa3)
+
+struct snd_timer_read {
+       unsigned int resolution;
+       unsigned int ticks;
+};
+
+enum {
+       SNDRV_TIMER_EVENT_RESOLUTION = 0,       /* val = resolution in ns */
+       SNDRV_TIMER_EVENT_TICK,                 /* val = ticks */
+       SNDRV_TIMER_EVENT_START,                /* val = resolution in ns */
+       SNDRV_TIMER_EVENT_STOP,                 /* val = 0 */
+       SNDRV_TIMER_EVENT_CONTINUE,             /* val = resolution in ns */
+       SNDRV_TIMER_EVENT_PAUSE,                /* val = 0 */
+       SNDRV_TIMER_EVENT_EARLY,                /* val = 0, early event */
+       SNDRV_TIMER_EVENT_SUSPEND,              /* val = 0 */
+       SNDRV_TIMER_EVENT_RESUME,               /* val = resolution in ns */
+       /* master timer events for slave timer instances */
+       SNDRV_TIMER_EVENT_MSTART = SNDRV_TIMER_EVENT_START + 10,
+       SNDRV_TIMER_EVENT_MSTOP = SNDRV_TIMER_EVENT_STOP + 10,
+       SNDRV_TIMER_EVENT_MCONTINUE = SNDRV_TIMER_EVENT_CONTINUE + 10,
+       SNDRV_TIMER_EVENT_MPAUSE = SNDRV_TIMER_EVENT_PAUSE + 10,
+       SNDRV_TIMER_EVENT_MSUSPEND = SNDRV_TIMER_EVENT_SUSPEND + 10,
+       SNDRV_TIMER_EVENT_MRESUME = SNDRV_TIMER_EVENT_RESUME + 10,
+};
+
+struct snd_timer_tread {
+       int event;
+       struct timespec tstamp;
+       unsigned int val;
+};
+
+/****************************************************************************
+ *                                                                          *
+ *        Section for driver control interface - /dev/snd/control?          *
+ *                                                                          *
+ ****************************************************************************/
+
+#define SNDRV_CTL_VERSION              SNDRV_PROTOCOL_VERSION(2, 0, 7)
+
+struct snd_ctl_card_info {
+       int card;                       /* card number */
+       int pad;                        /* reserved for future (was type) */
+       unsigned char id[16];           /* ID of card (user selectable) */
+       unsigned char driver[16];       /* Driver name */
+       unsigned char name[32];         /* Short name of soundcard */
+       unsigned char longname[80];     /* name + info text about soundcard */
+       unsigned char reserved_[16];    /* reserved for future (was ID of mixer) */
+       unsigned char mixername[80];    /* visual mixer identification */
+       unsigned char components[128];  /* card components / fine identification, delimited with one space (AC97 etc..) */
+};
+
+typedef int __bitwise snd_ctl_elem_type_t;
+#define        SNDRV_CTL_ELEM_TYPE_NONE        ((__force snd_ctl_elem_type_t) 0) /* invalid */
+#define        SNDRV_CTL_ELEM_TYPE_BOOLEAN     ((__force snd_ctl_elem_type_t) 1) /* boolean type */
+#define        SNDRV_CTL_ELEM_TYPE_INTEGER     ((__force snd_ctl_elem_type_t) 2) /* integer type */
+#define        SNDRV_CTL_ELEM_TYPE_ENUMERATED  ((__force snd_ctl_elem_type_t) 3) /* enumerated type */
+#define        SNDRV_CTL_ELEM_TYPE_BYTES       ((__force snd_ctl_elem_type_t) 4) /* byte array */
+#define        SNDRV_CTL_ELEM_TYPE_IEC958      ((__force snd_ctl_elem_type_t) 5) /* IEC958 (S/PDIF) setup */
+#define        SNDRV_CTL_ELEM_TYPE_INTEGER64   ((__force snd_ctl_elem_type_t) 6) /* 64-bit integer type */
+#define        SNDRV_CTL_ELEM_TYPE_LAST        SNDRV_CTL_ELEM_TYPE_INTEGER64
+
+typedef int __bitwise snd_ctl_elem_iface_t;
+#define        SNDRV_CTL_ELEM_IFACE_CARD       ((__force snd_ctl_elem_iface_t) 0) /* global control */
+#define        SNDRV_CTL_ELEM_IFACE_HWDEP      ((__force snd_ctl_elem_iface_t) 1) /* hardware dependent device */
+#define        SNDRV_CTL_ELEM_IFACE_MIXER      ((__force snd_ctl_elem_iface_t) 2) /* virtual mixer device */
+#define        SNDRV_CTL_ELEM_IFACE_PCM        ((__force snd_ctl_elem_iface_t) 3) /* PCM device */
+#define        SNDRV_CTL_ELEM_IFACE_RAWMIDI    ((__force snd_ctl_elem_iface_t) 4) /* RawMidi device */
+#define        SNDRV_CTL_ELEM_IFACE_TIMER      ((__force snd_ctl_elem_iface_t) 5) /* timer device */
+#define        SNDRV_CTL_ELEM_IFACE_SEQUENCER  ((__force snd_ctl_elem_iface_t) 6) /* sequencer client */
+#define        SNDRV_CTL_ELEM_IFACE_LAST       SNDRV_CTL_ELEM_IFACE_SEQUENCER
+
+#define SNDRV_CTL_ELEM_ACCESS_READ             (1<<0)
+#define SNDRV_CTL_ELEM_ACCESS_WRITE            (1<<1)
+#define SNDRV_CTL_ELEM_ACCESS_READWRITE                (SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE)
+#define SNDRV_CTL_ELEM_ACCESS_VOLATILE         (1<<2)  /* control value may be changed without a notification */
+#define SNDRV_CTL_ELEM_ACCESS_TIMESTAMP                (1<<3)  /* when was control changed */
+#define SNDRV_CTL_ELEM_ACCESS_TLV_READ         (1<<4)  /* TLV read is possible */
+#define SNDRV_CTL_ELEM_ACCESS_TLV_WRITE                (1<<5)  /* TLV write is possible */
+#define SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE    (SNDRV_CTL_ELEM_ACCESS_TLV_READ|SNDRV_CTL_ELEM_ACCESS_TLV_WRITE)
+#define SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND      (1<<6)  /* TLV command is possible */
+#define SNDRV_CTL_ELEM_ACCESS_INACTIVE         (1<<8)  /* control does actually nothing, but may be updated */
+#define SNDRV_CTL_ELEM_ACCESS_LOCK             (1<<9)  /* write lock */
+#define SNDRV_CTL_ELEM_ACCESS_OWNER            (1<<10) /* write lock owner */
+#define SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK     (1<<28) /* kernel use a TLV callback */ 
+#define SNDRV_CTL_ELEM_ACCESS_USER             (1<<29) /* user space element */
+/* bits 30 and 31 are obsoleted (for indirect access) */
+
+/* for further details see the ACPI and PCI power management specification */
+#define SNDRV_CTL_POWER_D0             0x0000  /* full On */
+#define SNDRV_CTL_POWER_D1             0x0100  /* partial On */
+#define SNDRV_CTL_POWER_D2             0x0200  /* partial On */
+#define SNDRV_CTL_POWER_D3             0x0300  /* Off */
+#define SNDRV_CTL_POWER_D3hot          (SNDRV_CTL_POWER_D3|0x0000)     /* Off, with power */
+#define SNDRV_CTL_POWER_D3cold         (SNDRV_CTL_POWER_D3|0x0001)     /* Off, without power */
+
+struct snd_ctl_elem_id {
+       unsigned int numid;             /* numeric identifier, zero = invalid */
+       snd_ctl_elem_iface_t iface;     /* interface identifier */
+       unsigned int device;            /* device/client number */
+       unsigned int subdevice;         /* subdevice (substream) number */
+       unsigned char name[44];         /* ASCII name of item */
+       unsigned int index;             /* index of item */
+};
+
+struct snd_ctl_elem_list {
+       unsigned int offset;            /* W: first element ID to get */
+       unsigned int space;             /* W: count of element IDs to get */
+       unsigned int used;              /* R: count of element IDs set */
+       unsigned int count;             /* R: count of all elements */
+       struct snd_ctl_elem_id __user *pids; /* R: IDs */
+       unsigned char reserved[50];
+};
+
+struct snd_ctl_elem_info {
+       struct snd_ctl_elem_id id;      /* W: element ID */
+       snd_ctl_elem_type_t type;       /* R: value type - SNDRV_CTL_ELEM_TYPE_* */
+       unsigned int access;            /* R: value access (bitmask) - SNDRV_CTL_ELEM_ACCESS_* */
+       unsigned int count;             /* count of values */
+       __kernel_pid_t owner;           /* owner's PID of this control */
+       union {
+               struct {
+                       long min;               /* R: minimum value */
+                       long max;               /* R: maximum value */
+                       long step;              /* R: step (0 variable) */
+               } integer;
+               struct {
+                       long long min;          /* R: minimum value */
+                       long long max;          /* R: maximum value */
+                       long long step;         /* R: step (0 variable) */
+               } integer64;
+               struct {
+                       unsigned int items;     /* R: number of items */
+                       unsigned int item;      /* W: item number */
+                       char name[64];          /* R: value name */
+                       __u64 names_ptr;        /* W: names list (ELEM_ADD only) */
+                       unsigned int names_length;
+               } enumerated;
+               unsigned char reserved[128];
+       } value;
+       union {
+               unsigned short d[4];            /* dimensions */
+               unsigned short *d_ptr;          /* indirect - obsoleted */
+       } dimen;
+       unsigned char reserved[64-4*sizeof(unsigned short)];
+};
+
+struct snd_ctl_elem_value {
+       struct snd_ctl_elem_id id;      /* W: element ID */
+       unsigned int indirect: 1;       /* W: indirect access - obsoleted */
+       union {
+               union {
+                       long value[128];
+                       long *value_ptr;        /* obsoleted */
+               } integer;
+               union {
+                       long long value[64];
+                       long long *value_ptr;   /* obsoleted */
+               } integer64;
+               union {
+                       unsigned int item[128];
+                       unsigned int *item_ptr; /* obsoleted */
+               } enumerated;
+               union {
+                       unsigned char data[512];
+                       unsigned char *data_ptr;        /* obsoleted */
+               } bytes;
+               struct snd_aes_iec958 iec958;
+       } value;                /* RO */
+       struct timespec tstamp;
+       unsigned char reserved[128-sizeof(struct timespec)];
+};
+
+struct snd_ctl_tlv {
+       unsigned int numid;     /* control element numeric identification */
+       unsigned int length;    /* in bytes aligned to 4 */
+       unsigned int tlv[0];    /* first TLV */
+};
+
+#define SNDRV_CTL_IOCTL_PVERSION       _IOR('U', 0x00, int)
+#define SNDRV_CTL_IOCTL_CARD_INFO      _IOR('U', 0x01, struct snd_ctl_card_info)
+#define SNDRV_CTL_IOCTL_ELEM_LIST      _IOWR('U', 0x10, struct snd_ctl_elem_list)
+#define SNDRV_CTL_IOCTL_ELEM_INFO      _IOWR('U', 0x11, struct snd_ctl_elem_info)
+#define SNDRV_CTL_IOCTL_ELEM_READ      _IOWR('U', 0x12, struct snd_ctl_elem_value)
+#define SNDRV_CTL_IOCTL_ELEM_WRITE     _IOWR('U', 0x13, struct snd_ctl_elem_value)
+#define SNDRV_CTL_IOCTL_ELEM_LOCK      _IOW('U', 0x14, struct snd_ctl_elem_id)
+#define SNDRV_CTL_IOCTL_ELEM_UNLOCK    _IOW('U', 0x15, struct snd_ctl_elem_id)
+#define SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS _IOWR('U', 0x16, int)
+#define SNDRV_CTL_IOCTL_ELEM_ADD       _IOWR('U', 0x17, struct snd_ctl_elem_info)
+#define SNDRV_CTL_IOCTL_ELEM_REPLACE   _IOWR('U', 0x18, struct snd_ctl_elem_info)
+#define SNDRV_CTL_IOCTL_ELEM_REMOVE    _IOWR('U', 0x19, struct snd_ctl_elem_id)
+#define SNDRV_CTL_IOCTL_TLV_READ       _IOWR('U', 0x1a, struct snd_ctl_tlv)
+#define SNDRV_CTL_IOCTL_TLV_WRITE      _IOWR('U', 0x1b, struct snd_ctl_tlv)
+#define SNDRV_CTL_IOCTL_TLV_COMMAND    _IOWR('U', 0x1c, struct snd_ctl_tlv)
+#define SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE _IOWR('U', 0x20, int)
+#define SNDRV_CTL_IOCTL_HWDEP_INFO     _IOR('U', 0x21, struct snd_hwdep_info)
+#define SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE        _IOR('U', 0x30, int)
+#define SNDRV_CTL_IOCTL_PCM_INFO       _IOWR('U', 0x31, struct snd_pcm_info)
+#define SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE _IOW('U', 0x32, int)
+#define SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE _IOWR('U', 0x40, int)
+#define SNDRV_CTL_IOCTL_RAWMIDI_INFO   _IOWR('U', 0x41, struct snd_rawmidi_info)
+#define SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE _IOW('U', 0x42, int)
+#define SNDRV_CTL_IOCTL_POWER          _IOWR('U', 0xd0, int)
+#define SNDRV_CTL_IOCTL_POWER_STATE    _IOR('U', 0xd1, int)
+
+/*
+ *  Read interface.
+ */
+
+enum sndrv_ctl_event_type {
+       SNDRV_CTL_EVENT_ELEM = 0,
+       SNDRV_CTL_EVENT_LAST = SNDRV_CTL_EVENT_ELEM,
+};
+
+#define SNDRV_CTL_EVENT_MASK_VALUE     (1<<0)  /* element value was changed */
+#define SNDRV_CTL_EVENT_MASK_INFO      (1<<1)  /* element info was changed */
+#define SNDRV_CTL_EVENT_MASK_ADD       (1<<2)  /* element was added */
+#define SNDRV_CTL_EVENT_MASK_TLV       (1<<3)  /* element TLV tree was changed */
+#define SNDRV_CTL_EVENT_MASK_REMOVE    (~0U)   /* element was removed */
+
+struct snd_ctl_event {
+       int type;       /* event type - SNDRV_CTL_EVENT_* */
+       union {
+               struct {
+                       unsigned int mask;
+                       struct snd_ctl_elem_id id;
+               } elem;
+               unsigned char data8[60];
+       } data;
+};
+
+/*
+ *  Control names
+ */
+
+#define SNDRV_CTL_NAME_NONE                            ""
+#define SNDRV_CTL_NAME_PLAYBACK                                "Playback "
+#define SNDRV_CTL_NAME_CAPTURE                         "Capture "
+
+#define SNDRV_CTL_NAME_IEC958_NONE                     ""
+#define SNDRV_CTL_NAME_IEC958_SWITCH                   "Switch"
+#define SNDRV_CTL_NAME_IEC958_VOLUME                   "Volume"
+#define SNDRV_CTL_NAME_IEC958_DEFAULT                  "Default"
+#define SNDRV_CTL_NAME_IEC958_MASK                     "Mask"
+#define SNDRV_CTL_NAME_IEC958_CON_MASK                 "Con Mask"
+#define SNDRV_CTL_NAME_IEC958_PRO_MASK                 "Pro Mask"
+#define SNDRV_CTL_NAME_IEC958_PCM_STREAM               "PCM Stream"
+#define SNDRV_CTL_NAME_IEC958(expl,direction,what)     "IEC958 " expl SNDRV_CTL_NAME_##direction SNDRV_CTL_NAME_IEC958_##what
+
+#endif /* _UAPI__SOUND_ASOUND_H */
diff --git a/include/uapi/sound/emu10k1.h b/include/uapi/sound/emu10k1.h
new file mode 100644 (file)
index 0000000..d1bbaf7
--- /dev/null
@@ -0,0 +1,373 @@
+/*
+ *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>,
+ *                  Creative Labs, Inc.
+ *  Definitions for EMU10K1 (SB Live!) chips
+ *
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+#ifndef _UAPI__SOUND_EMU10K1_H
+#define _UAPI__SOUND_EMU10K1_H
+
+#include <linux/types.h>
+
+
+
+/*
+ * ---- FX8010 ----
+ */
+
+#define EMU10K1_CARD_CREATIVE                  0x00000000
+#define EMU10K1_CARD_EMUAPS                    0x00000001
+
+#define EMU10K1_FX8010_PCM_COUNT               8
+
+/* instruction set */
+#define iMAC0   0x00   /* R = A + (X * Y >> 31)   ; saturation */
+#define iMAC1   0x01   /* R = A + (-X * Y >> 31)  ; saturation */
+#define iMAC2   0x02   /* R = A + (X * Y >> 31)   ; wraparound */
+#define iMAC3   0x03   /* R = A + (-X * Y >> 31)  ; wraparound */
+#define iMACINT0 0x04  /* R = A + X * Y           ; saturation */
+#define iMACINT1 0x05  /* R = A + X * Y           ; wraparound (31-bit) */
+#define iACC3   0x06   /* R = A + X + Y           ; saturation */
+#define iMACMV   0x07  /* R = A, acc += X * Y >> 31 */
+#define iANDXOR  0x08  /* R = (A & X) ^ Y */
+#define iTSTNEG  0x09  /* R = (A >= Y) ? X : ~X */
+#define iLIMITGE 0x0a  /* R = (A >= Y) ? X : Y */
+#define iLIMITLT 0x0b  /* R = (A < Y) ? X : Y */
+#define iLOG    0x0c   /* R = linear_data, A (log_data), X (max_exp), Y (format_word) */
+#define iEXP    0x0d   /* R = log_data, A (linear_data), X (max_exp), Y (format_word) */
+#define iINTERP  0x0e  /* R = A + (X * (Y - A) >> 31)  ; saturation */
+#define iSKIP    0x0f  /* R = A (cc_reg), X (count), Y (cc_test) */
+
+/* GPRs */
+#define FXBUS(x)       (0x00 + (x))    /* x = 0x00 - 0x0f */
+#define EXTIN(x)       (0x10 + (x))    /* x = 0x00 - 0x0f */
+#define EXTOUT(x)      (0x20 + (x))    /* x = 0x00 - 0x0f physical outs -> FXWC low 16 bits */
+#define FXBUS2(x)      (0x30 + (x))    /* x = 0x00 - 0x0f copies of fx buses for capture -> FXWC high 16 bits */
+                                       /* NB: 0x31 and 0x32 are shared with Center/LFE on SB live 5.1 */
+
+#define C_00000000     0x40
+#define C_00000001     0x41
+#define C_00000002     0x42
+#define C_00000003     0x43
+#define C_00000004     0x44
+#define C_00000008     0x45
+#define C_00000010     0x46
+#define C_00000020     0x47
+#define C_00000100     0x48
+#define C_00010000     0x49
+#define C_00080000     0x4a
+#define C_10000000     0x4b
+#define C_20000000     0x4c
+#define C_40000000     0x4d
+#define C_80000000     0x4e
+#define C_7fffffff     0x4f
+#define C_ffffffff     0x50
+#define C_fffffffe     0x51
+#define C_c0000000     0x52
+#define C_4f1bbcdc     0x53
+#define C_5a7ef9db     0x54
+#define C_00100000     0x55            /* ?? */
+#define GPR_ACCU       0x56            /* ACCUM, accumulator */
+#define GPR_COND       0x57            /* CCR, condition register */
+#define GPR_NOISE0     0x58            /* noise source */
+#define GPR_NOISE1     0x59            /* noise source */
+#define GPR_IRQ                0x5a            /* IRQ register */
+#define GPR_DBAC       0x5b            /* TRAM Delay Base Address Counter */
+#define GPR(x)         (FXGPREGBASE + (x)) /* free GPRs: x = 0x00 - 0xff */
+#define ITRAM_DATA(x)  (TANKMEMDATAREGBASE + 0x00 + (x)) /* x = 0x00 - 0x7f */
+#define ETRAM_DATA(x)  (TANKMEMDATAREGBASE + 0x80 + (x)) /* x = 0x00 - 0x1f */
+#define ITRAM_ADDR(x)  (TANKMEMADDRREGBASE + 0x00 + (x)) /* x = 0x00 - 0x7f */
+#define ETRAM_ADDR(x)  (TANKMEMADDRREGBASE + 0x80 + (x)) /* x = 0x00 - 0x1f */
+
+#define A_ITRAM_DATA(x)        (TANKMEMDATAREGBASE + 0x00 + (x)) /* x = 0x00 - 0xbf */
+#define A_ETRAM_DATA(x)        (TANKMEMDATAREGBASE + 0xc0 + (x)) /* x = 0x00 - 0x3f */
+#define A_ITRAM_ADDR(x)        (TANKMEMADDRREGBASE + 0x00 + (x)) /* x = 0x00 - 0xbf */
+#define A_ETRAM_ADDR(x)        (TANKMEMADDRREGBASE + 0xc0 + (x)) /* x = 0x00 - 0x3f */
+#define A_ITRAM_CTL(x) (A_TANKMEMCTLREGBASE + 0x00 + (x)) /* x = 0x00 - 0xbf */
+#define A_ETRAM_CTL(x) (A_TANKMEMCTLREGBASE + 0xc0 + (x)) /* x = 0x00 - 0x3f */
+
+#define A_FXBUS(x)     (0x00 + (x))    /* x = 0x00 - 0x3f FX buses */
+#define A_EXTIN(x)     (0x40 + (x))    /* x = 0x00 - 0x0f physical ins */
+#define A_P16VIN(x)    (0x50 + (x))    /* x = 0x00 - 0x0f p16v ins (A2 only) "EMU32 inputs" */
+#define A_EXTOUT(x)    (0x60 + (x))    /* x = 0x00 - 0x1f physical outs -> A_FXWC1 0x79-7f unknown   */
+#define A_FXBUS2(x)    (0x80 + (x))    /* x = 0x00 - 0x1f extra outs used for EFX capture -> A_FXWC2 */
+#define A_EMU32OUTH(x) (0xa0 + (x))    /* x = 0x00 - 0x0f "EMU32_OUT_10 - _1F" - ??? */
+#define A_EMU32OUTL(x) (0xb0 + (x))    /* x = 0x00 - 0x0f "EMU32_OUT_1 - _F" - ??? */
+#define A3_EMU32IN(x)  (0x160 + (x))   /* x = 0x00 - 0x3f "EMU32_IN_00 - _3F" - Only when .device = 0x0008 */
+#define A3_EMU32OUT(x) (0x1E0 + (x))   /* x = 0x00 - 0x0f "EMU32_OUT_00 - _3F" - Only when .device = 0x0008 */
+#define A_GPR(x)       (A_FXGPREGBASE + (x))
+
+/* cc_reg constants */
+#define CC_REG_NORMALIZED C_00000001
+#define CC_REG_BORROW  C_00000002
+#define CC_REG_MINUS   C_00000004
+#define CC_REG_ZERO    C_00000008
+#define CC_REG_SATURATE        C_00000010
+#define CC_REG_NONZERO C_00000100
+
+/* FX buses */
+#define FXBUS_PCM_LEFT         0x00
+#define FXBUS_PCM_RIGHT                0x01
+#define FXBUS_PCM_LEFT_REAR    0x02
+#define FXBUS_PCM_RIGHT_REAR   0x03
+#define FXBUS_MIDI_LEFT                0x04
+#define FXBUS_MIDI_RIGHT       0x05
+#define FXBUS_PCM_CENTER       0x06
+#define FXBUS_PCM_LFE          0x07
+#define FXBUS_PCM_LEFT_FRONT   0x08
+#define FXBUS_PCM_RIGHT_FRONT  0x09
+#define FXBUS_MIDI_REVERB      0x0c
+#define FXBUS_MIDI_CHORUS      0x0d
+#define FXBUS_PCM_LEFT_SIDE    0x0e
+#define FXBUS_PCM_RIGHT_SIDE   0x0f
+#define FXBUS_PT_LEFT          0x14
+#define FXBUS_PT_RIGHT         0x15
+
+/* Inputs */
+#define EXTIN_AC97_L      0x00 /* AC'97 capture channel - left */
+#define EXTIN_AC97_R      0x01 /* AC'97 capture channel - right */
+#define EXTIN_SPDIF_CD_L   0x02        /* internal S/PDIF CD - onboard - left */
+#define EXTIN_SPDIF_CD_R   0x03        /* internal S/PDIF CD - onboard - right */
+#define EXTIN_ZOOM_L      0x04 /* Zoom Video I2S - left */
+#define EXTIN_ZOOM_R      0x05 /* Zoom Video I2S - right */
+#define EXTIN_TOSLINK_L           0x06 /* LiveDrive - TOSLink Optical - left */
+#define EXTIN_TOSLINK_R    0x07        /* LiveDrive - TOSLink Optical - right */
+#define EXTIN_LINE1_L     0x08 /* LiveDrive - Line/Mic 1 - left */
+#define EXTIN_LINE1_R     0x09 /* LiveDrive - Line/Mic 1 - right */
+#define EXTIN_COAX_SPDIF_L 0x0a        /* LiveDrive - Coaxial S/PDIF - left */
+#define EXTIN_COAX_SPDIF_R 0x0b /* LiveDrive - Coaxial S/PDIF - right */
+#define EXTIN_LINE2_L     0x0c /* LiveDrive - Line/Mic 2 - left */
+#define EXTIN_LINE2_R     0x0d /* LiveDrive - Line/Mic 2 - right */
+
+/* Outputs */
+#define EXTOUT_AC97_L     0x00 /* AC'97 playback channel - left */
+#define EXTOUT_AC97_R     0x01 /* AC'97 playback channel - right */
+#define EXTOUT_TOSLINK_L   0x02        /* LiveDrive - TOSLink Optical - left */
+#define EXTOUT_TOSLINK_R   0x03        /* LiveDrive - TOSLink Optical - right */
+#define EXTOUT_AC97_CENTER 0x04        /* SB Live 5.1 - center */
+#define EXTOUT_AC97_LFE           0x05 /* SB Live 5.1 - LFE */
+#define EXTOUT_HEADPHONE_L 0x06        /* LiveDrive - Headphone - left */
+#define EXTOUT_HEADPHONE_R 0x07        /* LiveDrive - Headphone - right */
+#define EXTOUT_REAR_L     0x08 /* Rear channel - left */
+#define EXTOUT_REAR_R     0x09 /* Rear channel - right */
+#define EXTOUT_ADC_CAP_L   0x0a        /* ADC Capture buffer - left */
+#define EXTOUT_ADC_CAP_R   0x0b        /* ADC Capture buffer - right */
+#define EXTOUT_MIC_CAP    0x0c /* MIC Capture buffer */
+#define EXTOUT_AC97_REAR_L 0x0d        /* SB Live 5.1 (c) 2003 - Rear Left */
+#define EXTOUT_AC97_REAR_R 0x0e        /* SB Live 5.1 (c) 2003 - Rear Right */
+#define EXTOUT_ACENTER    0x11 /* Analog Center */
+#define EXTOUT_ALFE       0x12 /* Analog LFE */
+
+/* Audigy Inputs */
+#define A_EXTIN_AC97_L         0x00    /* AC'97 capture channel - left */
+#define A_EXTIN_AC97_R         0x01    /* AC'97 capture channel - right */
+#define A_EXTIN_SPDIF_CD_L     0x02    /* digital CD left */
+#define A_EXTIN_SPDIF_CD_R     0x03    /* digital CD left */
+#define A_EXTIN_OPT_SPDIF_L     0x04    /* audigy drive Optical SPDIF - left */
+#define A_EXTIN_OPT_SPDIF_R     0x05    /*                              right */ 
+#define A_EXTIN_LINE2_L                0x08    /* audigy drive line2/mic2 - left */
+#define A_EXTIN_LINE2_R                0x09    /*                           right */
+#define A_EXTIN_ADC_L          0x0a    /* Philips ADC - left */
+#define A_EXTIN_ADC_R          0x0b    /*               right */
+#define A_EXTIN_AUX2_L         0x0c    /* audigy drive aux2 - left */
+#define A_EXTIN_AUX2_R         0x0d    /*                   - right */
+
+/* Audigiy Outputs */
+#define A_EXTOUT_FRONT_L       0x00    /* digital front left */
+#define A_EXTOUT_FRONT_R       0x01    /*               right */
+#define A_EXTOUT_CENTER                0x02    /* digital front center */
+#define A_EXTOUT_LFE           0x03    /* digital front lfe */
+#define A_EXTOUT_HEADPHONE_L   0x04    /* headphone audigy drive left */
+#define A_EXTOUT_HEADPHONE_R   0x05    /*                        right */
+#define A_EXTOUT_REAR_L                0x06    /* digital rear left */
+#define A_EXTOUT_REAR_R                0x07    /*              right */
+#define A_EXTOUT_AFRONT_L      0x08    /* analog front left */
+#define A_EXTOUT_AFRONT_R      0x09    /*              right */
+#define A_EXTOUT_ACENTER       0x0a    /* analog center */
+#define A_EXTOUT_ALFE          0x0b    /* analog LFE */
+#define A_EXTOUT_ASIDE_L       0x0c    /* analog side left  - Audigy 2 ZS */
+#define A_EXTOUT_ASIDE_R       0x0d    /*             right - Audigy 2 ZS */
+#define A_EXTOUT_AREAR_L       0x0e    /* analog rear left */
+#define A_EXTOUT_AREAR_R       0x0f    /*             right */
+#define A_EXTOUT_AC97_L                0x10    /* AC97 left (front) */
+#define A_EXTOUT_AC97_R                0x11    /*      right */
+#define A_EXTOUT_ADC_CAP_L     0x16    /* ADC capture buffer left */
+#define A_EXTOUT_ADC_CAP_R     0x17    /*                    right */
+#define A_EXTOUT_MIC_CAP       0x18    /* Mic capture buffer */
+
+/* Audigy constants */
+#define A_C_00000000   0xc0
+#define A_C_00000001   0xc1
+#define A_C_00000002   0xc2
+#define A_C_00000003   0xc3
+#define A_C_00000004   0xc4
+#define A_C_00000008   0xc5
+#define A_C_00000010   0xc6
+#define A_C_00000020   0xc7
+#define A_C_00000100   0xc8
+#define A_C_00010000   0xc9
+#define A_C_00000800   0xca
+#define A_C_10000000   0xcb
+#define A_C_20000000   0xcc
+#define A_C_40000000   0xcd
+#define A_C_80000000   0xce
+#define A_C_7fffffff   0xcf
+#define A_C_ffffffff   0xd0
+#define A_C_fffffffe   0xd1
+#define A_C_c0000000   0xd2
+#define A_C_4f1bbcdc   0xd3
+#define A_C_5a7ef9db   0xd4
+#define A_C_00100000   0xd5
+#define A_GPR_ACCU     0xd6            /* ACCUM, accumulator */
+#define A_GPR_COND     0xd7            /* CCR, condition register */
+#define A_GPR_NOISE0   0xd8            /* noise source */
+#define A_GPR_NOISE1   0xd9            /* noise source */
+#define A_GPR_IRQ      0xda            /* IRQ register */
+#define A_GPR_DBAC     0xdb            /* TRAM Delay Base Address Counter - internal */
+#define A_GPR_DBACE    0xde            /* TRAM Delay Base Address Counter - external */
+
+/* definitions for debug register */
+#define EMU10K1_DBG_ZC                 0x80000000      /* zero tram counter */
+#define EMU10K1_DBG_SATURATION_OCCURED 0x02000000      /* saturation control */
+#define EMU10K1_DBG_SATURATION_ADDR    0x01ff0000      /* saturation address */
+#define EMU10K1_DBG_SINGLE_STEP                0x00008000      /* single step mode */
+#define EMU10K1_DBG_STEP               0x00004000      /* start single step */
+#define EMU10K1_DBG_CONDITION_CODE     0x00003e00      /* condition code */
+#define EMU10K1_DBG_SINGLE_STEP_ADDR   0x000001ff      /* single step address */
+
+/* tank memory address line */
+#ifndef __KERNEL__
+#define TANKMEMADDRREG_ADDR_MASK 0x000fffff    /* 20 bit tank address field                    */
+#define TANKMEMADDRREG_CLEAR    0x00800000     /* Clear tank memory                            */
+#define TANKMEMADDRREG_ALIGN    0x00400000     /* Align read or write relative to tank access  */
+#define TANKMEMADDRREG_WRITE    0x00200000     /* Write to tank memory                         */
+#define TANKMEMADDRREG_READ     0x00100000     /* Read from tank memory                        */
+#endif
+
+struct snd_emu10k1_fx8010_info {
+       unsigned int internal_tram_size;        /* in samples */
+       unsigned int external_tram_size;        /* in samples */
+       char fxbus_names[16][32];               /* names of FXBUSes */
+       char extin_names[16][32];               /* names of external inputs */
+       char extout_names[32][32];              /* names of external outputs */
+       unsigned int gpr_controls;              /* count of GPR controls */
+};
+
+#define EMU10K1_GPR_TRANSLATION_NONE           0
+#define EMU10K1_GPR_TRANSLATION_TABLE100       1
+#define EMU10K1_GPR_TRANSLATION_BASS           2
+#define EMU10K1_GPR_TRANSLATION_TREBLE         3
+#define EMU10K1_GPR_TRANSLATION_ONOFF          4
+
+struct snd_emu10k1_fx8010_control_gpr {
+       struct snd_ctl_elem_id id;              /* full control ID definition */
+       unsigned int vcount;            /* visible count */
+       unsigned int count;             /* count of GPR (1..16) */
+       unsigned short gpr[32];         /* GPR number(s) */
+       unsigned int value[32];         /* initial values */
+       unsigned int min;               /* minimum range */
+       unsigned int max;               /* maximum range */
+       unsigned int translation;       /* translation type (EMU10K1_GPR_TRANSLATION*) */
+       const unsigned int *tlv;
+};
+
+/* old ABI without TLV support */
+struct snd_emu10k1_fx8010_control_old_gpr {
+       struct snd_ctl_elem_id id;
+       unsigned int vcount;
+       unsigned int count;
+       unsigned short gpr[32];
+       unsigned int value[32];
+       unsigned int min;
+       unsigned int max;
+       unsigned int translation;
+};
+
+struct snd_emu10k1_fx8010_code {
+       char name[128];
+
+       DECLARE_BITMAP(gpr_valid, 0x200); /* bitmask of valid initializers */
+       __u32 __user *gpr_map;          /* initializers */
+
+       unsigned int gpr_add_control_count; /* count of GPR controls to add/replace */
+       struct snd_emu10k1_fx8010_control_gpr __user *gpr_add_controls; /* GPR controls to add/replace */
+
+       unsigned int gpr_del_control_count; /* count of GPR controls to remove */
+       struct snd_ctl_elem_id __user *gpr_del_controls; /* IDs of GPR controls to remove */
+
+       unsigned int gpr_list_control_count; /* count of GPR controls to list */
+       unsigned int gpr_list_control_total; /* total count of GPR controls */
+       struct snd_emu10k1_fx8010_control_gpr __user *gpr_list_controls; /* listed GPR controls */
+
+       DECLARE_BITMAP(tram_valid, 0x100); /* bitmask of valid initializers */
+       __u32 __user *tram_data_map;      /* data initializers */
+       __u32 __user *tram_addr_map;      /* map initializers */
+
+       DECLARE_BITMAP(code_valid, 1024); /* bitmask of valid instructions */
+       __u32 __user *code;               /* one instruction - 64 bits */
+};
+
+struct snd_emu10k1_fx8010_tram {
+       unsigned int address;           /* 31.bit == 1 -> external TRAM */
+       unsigned int size;              /* size in samples (4 bytes) */
+       unsigned int *samples;          /* pointer to samples (20-bit) */
+                                       /* NULL->clear memory */
+};
+
+struct snd_emu10k1_fx8010_pcm_rec {
+       unsigned int substream;         /* substream number */
+       unsigned int res1;              /* reserved */
+       unsigned int channels;          /* 16-bit channels count, zero = remove this substream */
+       unsigned int tram_start;        /* ring buffer position in TRAM (in samples) */
+       unsigned int buffer_size;       /* count of buffered samples */
+       unsigned short gpr_size;                /* GPR containing size of ringbuffer in samples (host) */
+       unsigned short gpr_ptr;         /* GPR containing current pointer in the ring buffer (host = reset, FX8010) */
+       unsigned short gpr_count;       /* GPR containing count of samples between two interrupts (host) */
+       unsigned short gpr_tmpcount;    /* GPR containing current count of samples to interrupt (host = set, FX8010) */
+       unsigned short gpr_trigger;     /* GPR containing trigger (activate) information (host) */
+       unsigned short gpr_running;     /* GPR containing info if PCM is running (FX8010) */
+       unsigned char pad;              /* reserved */
+       unsigned char etram[32];        /* external TRAM address & data (one per channel) */
+       unsigned int res2;              /* reserved */
+};
+
+#define SNDRV_EMU10K1_VERSION          SNDRV_PROTOCOL_VERSION(1, 0, 1)
+
+#define SNDRV_EMU10K1_IOCTL_INFO       _IOR ('H', 0x10, struct snd_emu10k1_fx8010_info)
+#define SNDRV_EMU10K1_IOCTL_CODE_POKE  _IOW ('H', 0x11, struct snd_emu10k1_fx8010_code)
+#define SNDRV_EMU10K1_IOCTL_CODE_PEEK  _IOWR('H', 0x12, struct snd_emu10k1_fx8010_code)
+#define SNDRV_EMU10K1_IOCTL_TRAM_SETUP _IOW ('H', 0x20, int)
+#define SNDRV_EMU10K1_IOCTL_TRAM_POKE  _IOW ('H', 0x21, struct snd_emu10k1_fx8010_tram)
+#define SNDRV_EMU10K1_IOCTL_TRAM_PEEK  _IOWR('H', 0x22, struct snd_emu10k1_fx8010_tram)
+#define SNDRV_EMU10K1_IOCTL_PCM_POKE   _IOW ('H', 0x30, struct snd_emu10k1_fx8010_pcm_rec)
+#define SNDRV_EMU10K1_IOCTL_PCM_PEEK   _IOWR('H', 0x31, struct snd_emu10k1_fx8010_pcm_rec)
+#define SNDRV_EMU10K1_IOCTL_PVERSION   _IOR ('H', 0x40, int)
+#define SNDRV_EMU10K1_IOCTL_STOP       _IO  ('H', 0x80)
+#define SNDRV_EMU10K1_IOCTL_CONTINUE   _IO  ('H', 0x81)
+#define SNDRV_EMU10K1_IOCTL_ZERO_TRAM_COUNTER _IO ('H', 0x82)
+#define SNDRV_EMU10K1_IOCTL_SINGLE_STEP        _IOW ('H', 0x83, int)
+#define SNDRV_EMU10K1_IOCTL_DBG_READ   _IOR ('H', 0x84, int)
+
+/* typedefs for compatibility to user-space */
+typedef struct snd_emu10k1_fx8010_info emu10k1_fx8010_info_t;
+typedef struct snd_emu10k1_fx8010_control_gpr emu10k1_fx8010_control_gpr_t;
+typedef struct snd_emu10k1_fx8010_code emu10k1_fx8010_code_t;
+typedef struct snd_emu10k1_fx8010_tram emu10k1_fx8010_tram_t;
+typedef struct snd_emu10k1_fx8010_pcm_rec emu10k1_fx8010_pcm_t;
+
+#endif /* _UAPI__SOUND_EMU10K1_H */
diff --git a/include/uapi/sound/sb16_csp.h b/include/uapi/sound/sb16_csp.h
new file mode 100644 (file)
index 0000000..3b96907
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ *  Copyright (c) 1999 by Uros Bizjak <uros@kss-loka.si>
+ *                        Takashi Iwai <tiwai@suse.de>
+ *
+ *  SB16ASP/AWE32 CSP control
+ *
+ *   This program is free software; you can redistribute it and/or modify 
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+#ifndef _UAPI__SOUND_SB16_CSP_H
+#define _UAPI__SOUND_SB16_CSP_H
+
+
+/* CSP modes */
+#define SNDRV_SB_CSP_MODE_NONE         0x00
+#define SNDRV_SB_CSP_MODE_DSP_READ     0x01    /* Record from DSP */
+#define SNDRV_SB_CSP_MODE_DSP_WRITE    0x02    /* Play to DSP */
+#define SNDRV_SB_CSP_MODE_QSOUND               0x04    /* QSound */
+
+/* CSP load flags */
+#define SNDRV_SB_CSP_LOAD_FROMUSER     0x01
+#define SNDRV_SB_CSP_LOAD_INITBLOCK    0x02
+
+/* CSP sample width */
+#define SNDRV_SB_CSP_SAMPLE_8BIT               0x01
+#define SNDRV_SB_CSP_SAMPLE_16BIT              0x02
+
+/* CSP channels */
+#define SNDRV_SB_CSP_MONO                      0x01
+#define SNDRV_SB_CSP_STEREO            0x02
+
+/* CSP rates */
+#define SNDRV_SB_CSP_RATE_8000         0x01
+#define SNDRV_SB_CSP_RATE_11025                0x02
+#define SNDRV_SB_CSP_RATE_22050                0x04
+#define SNDRV_SB_CSP_RATE_44100                0x08
+#define SNDRV_SB_CSP_RATE_ALL          0x0f
+
+/* CSP running state */
+#define SNDRV_SB_CSP_ST_IDLE           0x00
+#define SNDRV_SB_CSP_ST_LOADED         0x01
+#define SNDRV_SB_CSP_ST_RUNNING                0x02
+#define SNDRV_SB_CSP_ST_PAUSED         0x04
+#define SNDRV_SB_CSP_ST_AUTO           0x08
+#define SNDRV_SB_CSP_ST_QSOUND         0x10
+
+/* maximum QSound value (180 degrees right) */
+#define SNDRV_SB_CSP_QSOUND_MAX_RIGHT  0x20
+
+/* maximum microcode RIFF file size */
+#define SNDRV_SB_CSP_MAX_MICROCODE_FILE_SIZE   0x3000
+
+/* microcode header */
+struct snd_sb_csp_mc_header {
+       char codec_name[16];            /* id name of codec */
+       unsigned short func_req;        /* requested function */
+};
+
+/* microcode to be loaded */
+struct snd_sb_csp_microcode {
+       struct snd_sb_csp_mc_header info;
+       unsigned char data[SNDRV_SB_CSP_MAX_MICROCODE_FILE_SIZE];
+};
+
+/* start CSP with sample_width in mono/stereo */
+struct snd_sb_csp_start {
+       int sample_width;       /* sample width, look above */
+       int channels;           /* channels, look above */
+};
+
+/* CSP information */
+struct snd_sb_csp_info {
+       char codec_name[16];            /* id name of codec */
+       unsigned short func_nr;         /* function number */
+       unsigned int acc_format;        /* accepted PCM formats */
+       unsigned short acc_channels;    /* accepted channels */
+       unsigned short acc_width;       /* accepted sample width */
+       unsigned short acc_rates;       /* accepted sample rates */
+       unsigned short csp_mode;        /* CSP mode, see above */
+       unsigned short run_channels;    /* current channels  */
+       unsigned short run_width;       /* current sample width */
+       unsigned short version;         /* version id: 0x10 - 0x1f */
+       unsigned short state;           /* state bits */
+};
+
+/* HWDEP controls */
+/* get CSP information */
+#define SNDRV_SB_CSP_IOCTL_INFO                _IOR('H', 0x10, struct snd_sb_csp_info)
+/* load microcode to CSP */
+/* NOTE: struct snd_sb_csp_microcode overflows the max size (13 bits)
+ * defined for some architectures like MIPS, and it leads to build errors.
+ * (x86 and co have 14-bit size, thus it's valid, though.)
+ * As a workaround for skipping the size-limit check, here we don't use the
+ * normal _IOW() macro but _IOC() with the manual argument.
+ */
+#define SNDRV_SB_CSP_IOCTL_LOAD_CODE   \
+       _IOC(_IOC_WRITE, 'H', 0x11, sizeof(struct snd_sb_csp_microcode))
+/* unload microcode from CSP */
+#define SNDRV_SB_CSP_IOCTL_UNLOAD_CODE _IO('H', 0x12)
+/* start CSP */
+#define SNDRV_SB_CSP_IOCTL_START               _IOW('H', 0x13, struct snd_sb_csp_start)
+/* stop CSP */
+#define SNDRV_SB_CSP_IOCTL_STOP                _IO('H', 0x14)
+/* pause CSP and DMA transfer */
+#define SNDRV_SB_CSP_IOCTL_PAUSE               _IO('H', 0x15)
+/* restart CSP and DMA transfer */
+#define SNDRV_SB_CSP_IOCTL_RESTART     _IO('H', 0x16)
+
+
+#endif /* _UAPI__SOUND_SB16_CSP_H */
index aecee9d112cbe6aea2532652c8c3f768bb829cce..8e39879fd6fd06a908d9bd4d7c98112adabb9b9c 100644 (file)
@@ -170,7 +170,7 @@ gnttab_set_unmap_op(struct gnttab_unmap_grant_ref *unmap, phys_addr_t addr,
        unmap->dev_bus_addr = 0;
 }
 
-int arch_gnttab_map_shared(unsigned long *frames, unsigned long nr_gframes,
+int arch_gnttab_map_shared(xen_pfn_t *frames, unsigned long nr_gframes,
                           unsigned long max_nr_gframes,
                           void **__shared);
 int arch_gnttab_map_status(uint64_t *frames, unsigned long nr_gframes,
@@ -190,16 +190,4 @@ int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops,
                      struct gnttab_map_grant_ref *kunmap_ops,
                      struct page **pages, unsigned int count);
 
-/* Perform a batch of grant map/copy operations. Retry every batch slot
- * for which the hypervisor returns GNTST_eagain. This is typically due
- * to paged out target frames.
- *
- * Will retry for 1, 2, ... 255 ms, i.e. 256 times during 32 seconds.
- *
- * Return value in each iand every status field of the batch guaranteed
- * to not be GNTST_eagain.
- */
-void gnttab_batch_map(struct gnttab_map_grant_ref *batch, unsigned count);
-void gnttab_batch_copy(struct gnttab_copy *batch, unsigned count);
-
 #endif /* __ASM_GNTTAB_H__ */
index f9f8b975ae7448bfdae47100ad7da63a34fbe39b..e40fae9bf11acd67b64ece81bae1d04efefc44fd 100644 (file)
@@ -310,7 +310,7 @@ struct gnttab_setup_table {
     uint32_t nr_frames;
     /* OUT parameters. */
     int16_t  status;              /* GNTST_* */
-    GUEST_HANDLE(ulong) frame_list;
+    GUEST_HANDLE(xen_pfn_t) frame_list;
 };
 DEFINE_GUEST_HANDLE_STRUCT(gnttab_setup_table);
 
index b66d04ce6957549a1097c532bc483e5ee6ab38d8..90712e2072d57ba6c6154549352266d253ab3615 100644 (file)
@@ -179,28 +179,8 @@ struct xen_add_to_physmap {
 };
 DEFINE_GUEST_HANDLE_STRUCT(xen_add_to_physmap);
 
-/*
- * Translates a list of domain-specific GPFNs into MFNs. Returns a -ve error
- * code on failure. This call only works for auto-translated guests.
- */
-#define XENMEM_translate_gpfn_list  8
-struct xen_translate_gpfn_list {
-    /* Which domain to translate for? */
-    domid_t domid;
-
-    /* Length of list. */
-    xen_ulong_t nr_gpfns;
-
-    /* List of GPFNs to translate. */
-    GUEST_HANDLE(ulong) gpfn_list;
-
-    /*
-     * Output list to contain MFN translations. May be the same as the input
-     * list (in which case each input GPFN is overwritten with the output MFN).
-     */
-    GUEST_HANDLE(ulong) mfn_list;
-};
-DEFINE_GUEST_HANDLE_STRUCT(xen_translate_gpfn_list);
+/*** REMOVED ***/
+/*#define XENMEM_translate_gpfn_list  8*/
 
 /*
  * Returns the pseudo-physical memory map as it was when the domain
index 886a5d80a18fdcbaa572c8350a400d59ab4455ba..b67589447682b6a5f8c268cc57d271237f0823d9 100644 (file)
@@ -493,6 +493,7 @@ struct dom0_vga_console_info {
 /* These flags are passed in the 'flags' field of start_info_t. */
 #define SIF_PRIVILEGED    (1<<0)  /* Is the domain privileged? */
 #define SIF_INITDOMAIN    (1<<1)  /* Is this the initial control domain? */
+#define SIF_IS_PVINHVM    (1<<4)  /* Is it a PV running in HVM container? */
 #define SIF_PM_MASK       (0xFF<<8) /* reserve 1 byte for xen-pm options */
 
 typedef uint64_t cpumap_t;
index a74d4362c4f84aca7a7218162a6cdba7df385fff..e7101bb954fbaf9183251489a34239ef47040030 100644 (file)
@@ -18,6 +18,10 @@ extern enum xen_domain_type xen_domain_type;
                                 xen_domain_type == XEN_PV_DOMAIN)
 #define xen_hvm_domain()       (xen_domain() &&                        \
                                 xen_domain_type == XEN_HVM_DOMAIN)
+/* xen_pv_domain check is necessary as start_info ptr is null in HVM. Also,
+ * note, xen PVH domain shares lot of HVM code */
+#define xen_pvh_domain()       (xen_pv_domain() &&                     \
+                               (xen_start_info->flags & SIF_IS_PVINHVM))
 
 #ifdef CONFIG_XEN_DOM0
 #include <xen/interface/xen.h>
index 6fdd6e339326a079a2b6b5a3a1d2940b2bd81bd8..aafcea56ae02c3de2441242dadcecac3503fbafc 100644 (file)
@@ -582,14 +582,13 @@ config RCU_FAST_NO_HZ
        depends on NO_HZ && SMP
        default n
        help
-         This option causes RCU to attempt to accelerate grace periods
-         in order to allow CPUs to enter dynticks-idle state more
-         quickly.  On the other hand, this option increases the overhead
-         of the dynticks-idle checking, particularly on systems with
-         large numbers of CPUs.
+         This option causes RCU to attempt to accelerate grace periods in
+         order to allow CPUs to enter dynticks-idle state more quickly.
+         On the other hand, this option increases the overhead of the
+         dynticks-idle checking, thus degrading scheduling latency.
 
-         Say Y if energy efficiency is critically important, particularly
-               if you have relatively few CPUs.
+         Say Y if energy efficiency is critically important, and you don't
+               care about real-time response.
 
          Say N if you are unsure.
 
@@ -696,6 +695,20 @@ config LOG_BUF_SHIFT
 config HAVE_UNSTABLE_SCHED_CLOCK
        bool
 
+#
+# For architectures that (ab)use NUMA to represent different memory regions
+# all cpu-local but of different latencies, such as SuperH.
+#
+config EMBEDDED_NUMA
+       bool
+
+config SCHED_NUMA
+       bool "Memory placement aware NUMA scheduler"
+       default n
+       depends on SMP && NUMA && MIGRATION && !EMBEDDED_NUMA
+       help
+         This option adds support for automatic NUMA aware memory/task placement.
+
 menuconfig CGROUPS
        boolean "Control Group support"
        depends on EVENTFD
index ed206fd88cca76e75a0d8866ab703a7f6fdf38d6..e81175ef25f82d129dbe4c3b5df70f718d59d782 100644 (file)
@@ -249,7 +249,7 @@ static void untag_chunk(struct node *p)
                list_del_rcu(&chunk->hash);
                spin_unlock(&hash_lock);
                spin_unlock(&entry->lock);
-               fsnotify_destroy_mark(entry);
+               fsnotify_destroy_mark(entry, audit_tree_group);
                goto out;
        }
 
@@ -291,7 +291,7 @@ static void untag_chunk(struct node *p)
                owner->root = new;
        spin_unlock(&hash_lock);
        spin_unlock(&entry->lock);
-       fsnotify_destroy_mark(entry);
+       fsnotify_destroy_mark(entry, audit_tree_group);
        fsnotify_put_mark(&new->mark);  /* drop initial reference */
        goto out;
 
@@ -331,7 +331,7 @@ static int create_chunk(struct inode *inode, struct audit_tree *tree)
                spin_unlock(&hash_lock);
                chunk->dead = 1;
                spin_unlock(&entry->lock);
-               fsnotify_destroy_mark(entry);
+               fsnotify_destroy_mark(entry, audit_tree_group);
                fsnotify_put_mark(entry);
                return 0;
        }
@@ -412,7 +412,7 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree)
                spin_unlock(&chunk_entry->lock);
                spin_unlock(&old_entry->lock);
 
-               fsnotify_destroy_mark(chunk_entry);
+               fsnotify_destroy_mark(chunk_entry, audit_tree_group);
 
                fsnotify_put_mark(chunk_entry);
                fsnotify_put_mark(old_entry);
@@ -443,7 +443,7 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree)
        spin_unlock(&hash_lock);
        spin_unlock(&chunk_entry->lock);
        spin_unlock(&old_entry->lock);
-       fsnotify_destroy_mark(old_entry);
+       fsnotify_destroy_mark(old_entry, audit_tree_group);
        fsnotify_put_mark(chunk_entry); /* drop initial reference */
        fsnotify_put_mark(old_entry); /* pair to fsnotify_find mark_entry */
        return 0;
index 9a9ae6e3d290025179a964c577de517f24fbe75c..4a599f699adcfeca242e34f1a9691385a500450e 100644 (file)
@@ -350,7 +350,7 @@ static void audit_remove_parent_watches(struct audit_parent *parent)
        }
        mutex_unlock(&audit_filter_mutex);
 
-       fsnotify_destroy_mark(&parent->mark);
+       fsnotify_destroy_mark(&parent->mark, audit_watch_group);
 }
 
 /* Get path information necessary for adding watches. */
@@ -457,7 +457,7 @@ void audit_remove_watch_rule(struct audit_krule *krule)
 
                if (list_empty(&parent->watches)) {
                        audit_get_parent(parent);
-                       fsnotify_destroy_mark(&parent->mark);
+                       fsnotify_destroy_mark(&parent->mark, audit_watch_group);
                        audit_put_parent(parent);
                }
        }
index 2f186ed80c40589ef9662fb400c82c1a95854f6a..fc7376bf86ea8133e44677e6ede62fc9581dc6e6 100644 (file)
@@ -1159,7 +1159,7 @@ void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk)
        cred = current_cred();
 
        spin_lock_irq(&tsk->sighand->siglock);
-       if (tsk->signal && tsk->signal->tty && tsk->signal->tty->name)
+       if (tsk->signal && tsk->signal->tty)
                tty = tsk->signal->tty->name;
        else
                tty = "(none)";
index 13774b3b39aac9b73e25ba34a366d5402b70df00..8e2c5df4be9d3dcb08d1ff56d5f53cc9c64d9ccd 100644 (file)
@@ -1962,9 +1962,8 @@ static void cgroup_task_migrate(struct cgroup *cgrp, struct cgroup *oldcgrp,
         * trading it for newcg is protected by cgroup_mutex, we're safe to drop
         * it here; it will be freed under RCU.
         */
-       put_css_set(oldcg);
-
        set_bit(CGRP_RELEASABLE, &oldcgrp->flags);
+       put_css_set(oldcg);
 }
 
 /**
@@ -4815,73 +4814,37 @@ static const struct file_operations proc_cgroupstats_operations = {
  *
  * A pointer to the shared css_set was automatically copied in
  * fork.c by dup_task_struct().  However, we ignore that copy, since
- * it was not made under the protection of RCU, cgroup_mutex or
- * threadgroup_change_begin(), so it might no longer be a valid
- * cgroup pointer.  cgroup_attach_task() might have already changed
- * current->cgroups, allowing the previously referenced cgroup
- * group to be removed and freed.
- *
- * Outside the pointer validity we also need to process the css_set
- * inheritance between threadgoup_change_begin() and
- * threadgoup_change_end(), this way there is no leak in any process
- * wide migration performed by cgroup_attach_proc() that could otherwise
- * miss a thread because it is too early or too late in the fork stage.
+ * it was not made under the protection of RCU or cgroup_mutex, so
+ * might no longer be a valid cgroup pointer.  cgroup_attach_task() might
+ * have already changed current->cgroups, allowing the previously
+ * referenced cgroup group to be removed and freed.
  *
  * At the point that cgroup_fork() is called, 'current' is the parent
  * task, and the passed argument 'child' points to the child task.
  */
 void cgroup_fork(struct task_struct *child)
 {
-       /*
-        * We don't need to task_lock() current because current->cgroups
-        * can't be changed concurrently here. The parent obviously hasn't
-        * exited and called cgroup_exit(), and we are synchronized against
-        * cgroup migration through threadgroup_change_begin().
-        */
+       task_lock(current);
        child->cgroups = current->cgroups;
        get_css_set(child->cgroups);
+       task_unlock(current);
        INIT_LIST_HEAD(&child->cg_list);
 }
 
-/**
- * cgroup_fork_callbacks - run fork callbacks
- * @child: the new task
- *
- * Called on a new task very soon before adding it to the
- * tasklist. No need to take any locks since no-one can
- * be operating on this task.
- */
-void cgroup_fork_callbacks(struct task_struct *child)
-{
-       if (need_forkexit_callback) {
-               int i;
-               for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
-                       struct cgroup_subsys *ss = subsys[i];
-
-                       /*
-                        * forkexit callbacks are only supported for
-                        * builtin subsystems.
-                        */
-                       if (!ss || ss->module)
-                               continue;
-
-                       if (ss->fork)
-                               ss->fork(child);
-               }
-       }
-}
-
 /**
  * cgroup_post_fork - called on a new task after adding it to the task list
  * @child: the task in question
  *
- * Adds the task to the list running through its css_set if necessary.
- * Has to be after the task is visible on the task list in case we race
- * with the first call to cgroup_iter_start() - to guarantee that the
- * new task ends up on its list.
+ * Adds the task to the list running through its css_set if necessary and
+ * call the subsystem fork() callbacks.  Has to be after the task is
+ * visible on the task list in case we race with the first call to
+ * cgroup_iter_start() - to guarantee that the new task ends up on its
+ * list.
  */
 void cgroup_post_fork(struct task_struct *child)
 {
+       int i;
+
        /*
         * use_task_css_set_links is set to 1 before we walk the tasklist
         * under the tasklist_lock and we read it here after we added the child
@@ -4895,22 +4858,36 @@ void cgroup_post_fork(struct task_struct *child)
         */
        if (use_task_css_set_links) {
                write_lock(&css_set_lock);
-               if (list_empty(&child->cg_list)) {
+               task_lock(child);
+               if (list_empty(&child->cg_list))
+                       list_add(&child->cg_list, &child->cgroups->tasks);
+               task_unlock(child);
+               write_unlock(&css_set_lock);
+       }
+
+       /*
+        * Call ss->fork().  This must happen after @child is linked on
+        * css_set; otherwise, @child might change state between ->fork()
+        * and addition to css_set.
+        */
+       if (need_forkexit_callback) {
+               for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
+                       struct cgroup_subsys *ss = subsys[i];
+
                        /*
-                        * It's safe to use child->cgroups without task_lock()
-                        * here because we are protected through
-                        * threadgroup_change_begin() against concurrent
-                        * css_set change in cgroup_task_migrate(). Also
-                        * the task can't exit at that point until
-                        * wake_up_new_task() is called, so we are protected
-                        * against cgroup_exit() setting child->cgroup to
-                        * init_css_set.
+                        * fork/exit callbacks are supported only for
+                        * builtin subsystems and we don't need further
+                        * synchronization as they never go away.
                         */
-                       list_add(&child->cg_list, &child->cgroups->tasks);
+                       if (!ss || ss->module)
+                               continue;
+
+                       if (ss->fork)
+                               ss->fork(child);
                }
-               write_unlock(&css_set_lock);
        }
 }
+
 /**
  * cgroup_exit - detach cgroup from exiting task
  * @tsk: pointer to task_struct of exiting process
index b1724ce98981d25e76980193b7e3984c9f7717cd..8a92b0e52099185136ace406dcefa7129b1ba5e1 100644 (file)
@@ -84,50 +84,6 @@ static const char *freezer_state_strs[] = {
 
 struct cgroup_subsys freezer_subsys;
 
-/* Locks taken and their ordering
- * ------------------------------
- * cgroup_mutex (AKA cgroup_lock)
- * freezer->lock
- * css_set_lock
- * task->alloc_lock (AKA task_lock)
- * task->sighand->siglock
- *
- * cgroup code forces css_set_lock to be taken before task->alloc_lock
- *
- * freezer_create(), freezer_destroy():
- * cgroup_mutex [ by cgroup core ]
- *
- * freezer_can_attach():
- * cgroup_mutex (held by caller of can_attach)
- *
- * freezer_fork() (preserving fork() performance means can't take cgroup_mutex):
- * freezer->lock
- *  sighand->siglock (if the cgroup is freezing)
- *
- * freezer_read():
- * cgroup_mutex
- *  freezer->lock
- *   write_lock css_set_lock (cgroup iterator start)
- *    task->alloc_lock
- *   read_lock css_set_lock (cgroup iterator start)
- *
- * freezer_write() (freeze):
- * cgroup_mutex
- *  freezer->lock
- *   write_lock css_set_lock (cgroup iterator start)
- *    task->alloc_lock
- *   read_lock css_set_lock (cgroup iterator start)
- *    sighand->siglock (fake signal delivery inside freeze_task())
- *
- * freezer_write() (unfreeze):
- * cgroup_mutex
- *  freezer->lock
- *   write_lock css_set_lock (cgroup iterator start)
- *    task->alloc_lock
- *   read_lock css_set_lock (cgroup iterator start)
- *    task->alloc_lock (inside __thaw_task(), prevents race with refrigerator())
- *     sighand->siglock
- */
 static struct cgroup_subsys_state *freezer_create(struct cgroup *cgroup)
 {
        struct freezer *freezer;
@@ -150,96 +106,106 @@ static void freezer_destroy(struct cgroup *cgroup)
        kfree(freezer);
 }
 
-/* task is frozen or will freeze immediately when next it gets woken */
-static bool is_task_frozen_enough(struct task_struct *task)
-{
-       return frozen(task) ||
-               (task_is_stopped_or_traced(task) && freezing(task));
-}
-
 /*
- * The call to cgroup_lock() in the freezer.state write method prevents
- * a write to that file racing against an attach, and hence the
- * can_attach() result will remain valid until the attach completes.
+ * Tasks can be migrated into a different freezer anytime regardless of its
+ * current state.  freezer_attach() is responsible for making new tasks
+ * conform to the current state.
+ *
+ * Freezer state changes and task migration are synchronized via
+ * @freezer->lock.  freezer_attach() makes the new tasks conform to the
+ * current state and all following state changes can see the new tasks.
  */
-static int freezer_can_attach(struct cgroup *new_cgroup,
-                             struct cgroup_taskset *tset)
+static void freezer_attach(struct cgroup *new_cgrp, struct cgroup_taskset *tset)
 {
-       struct freezer *freezer;
+       struct freezer *freezer = cgroup_freezer(new_cgrp);
        struct task_struct *task;
 
+       spin_lock_irq(&freezer->lock);
+
        /*
-        * Anything frozen can't move or be moved to/from.
+        * Make the new tasks conform to the current state of @new_cgrp.
+        * For simplicity, when migrating any task to a FROZEN cgroup, we
+        * revert it to FREEZING and let update_if_frozen() determine the
+        * correct state later.
+        *
+        * Tasks in @tset are on @new_cgrp but may not conform to its
+        * current state before executing the following - !frozen tasks may
+        * be visible in a FROZEN cgroup and frozen tasks in a THAWED one.
+        * This means that, to determine whether to freeze, one should test
+        * whether the state equals THAWED.
         */
-       cgroup_taskset_for_each(task, new_cgroup, tset)
-               if (cgroup_freezing(task))
-                       return -EBUSY;
-
-       freezer = cgroup_freezer(new_cgroup);
-       if (freezer->state != CGROUP_THAWED)
-               return -EBUSY;
+       cgroup_taskset_for_each(task, new_cgrp, tset) {
+               if (freezer->state == CGROUP_THAWED) {
+                       __thaw_task(task);
+               } else {
+                       freeze_task(task);
+                       freezer->state = CGROUP_FREEZING;
+               }
+       }
 
-       return 0;
+       spin_unlock_irq(&freezer->lock);
 }
 
 static void freezer_fork(struct task_struct *task)
 {
        struct freezer *freezer;
 
-       /*
-        * No lock is needed, since the task isn't on tasklist yet,
-        * so it can't be moved to another cgroup, which means the
-        * freezer won't be removed and will be valid during this
-        * function call.  Nevertheless, apply RCU read-side critical
-        * section to suppress RCU lockdep false positives.
-        */
        rcu_read_lock();
        freezer = task_freezer(task);
-       rcu_read_unlock();
 
        /*
         * The root cgroup is non-freezable, so we can skip the
         * following check.
         */
        if (!freezer->css.cgroup->parent)
-               return;
+               goto out;
 
        spin_lock_irq(&freezer->lock);
-       BUG_ON(freezer->state == CGROUP_FROZEN);
-
-       /* Locking avoids race with FREEZING -> THAWED transitions. */
-       if (freezer->state == CGROUP_FREEZING)
+       /*
+        * @task might have been just migrated into a FROZEN cgroup.  Test
+        * equality with THAWED.  Read the comment in freezer_attach().
+        */
+       if (freezer->state != CGROUP_THAWED)
                freeze_task(task);
        spin_unlock_irq(&freezer->lock);
+out:
+       rcu_read_unlock();
 }
 
 /*
- * caller must hold freezer->lock
+ * We change from FREEZING to FROZEN lazily if the cgroup was only
+ * partially frozen when we exitted write.  Caller must hold freezer->lock.
+ *
+ * Task states and freezer state might disagree while tasks are being
+ * migrated into or out of @cgroup, so we can't verify task states against
+ * @freezer state here.  See freezer_attach() for details.
  */
-static void update_if_frozen(struct cgroup *cgroup,
-                                struct freezer *freezer)
+static void update_if_frozen(struct cgroup *cgroup, struct freezer *freezer)
 {
        struct cgroup_iter it;
        struct task_struct *task;
-       unsigned int nfrozen = 0, ntotal = 0;
-       enum freezer_state old_state = freezer->state;
+
+       if (freezer->state != CGROUP_FREEZING)
+               return;
 
        cgroup_iter_start(cgroup, &it);
-       while ((task = cgroup_iter_next(cgroup, &it))) {
-               ntotal++;
-               if (freezing(task) && is_task_frozen_enough(task))
-                       nfrozen++;
-       }
 
-       if (old_state == CGROUP_THAWED) {
-               BUG_ON(nfrozen > 0);
-       } else if (old_state == CGROUP_FREEZING) {
-               if (nfrozen == ntotal)
-                       freezer->state = CGROUP_FROZEN;
-       } else { /* old_state == CGROUP_FROZEN */
-               BUG_ON(nfrozen != ntotal);
+       while ((task = cgroup_iter_next(cgroup, &it))) {
+               if (freezing(task)) {
+                       /*
+                        * freezer_should_skip() indicates that the task
+                        * should be skipped when determining freezing
+                        * completion.  Consider it frozen in addition to
+                        * the usual frozen condition.
+                        */
+                       if (!frozen(task) && !task_is_stopped_or_traced(task) &&
+                           !freezer_should_skip(task))
+                               goto notyet;
+               }
        }
 
+       freezer->state = CGROUP_FROZEN;
+notyet:
        cgroup_iter_end(cgroup, &it);
 }
 
@@ -249,44 +215,26 @@ static int freezer_read(struct cgroup *cgroup, struct cftype *cft,
        struct freezer *freezer;
        enum freezer_state state;
 
-       if (!cgroup_lock_live_group(cgroup))
-               return -ENODEV;
-
        freezer = cgroup_freezer(cgroup);
        spin_lock_irq(&freezer->lock);
+       update_if_frozen(cgroup, freezer);
        state = freezer->state;
-       if (state == CGROUP_FREEZING) {
-               /* We change from FREEZING to FROZEN lazily if the cgroup was
-                * only partially frozen when we exitted write. */
-               update_if_frozen(cgroup, freezer);
-               state = freezer->state;
-       }
        spin_unlock_irq(&freezer->lock);
-       cgroup_unlock();
 
        seq_puts(m, freezer_state_strs[state]);
        seq_putc(m, '\n');
        return 0;
 }
 
-static int try_to_freeze_cgroup(struct cgroup *cgroup, struct freezer *freezer)
+static void freeze_cgroup(struct cgroup *cgroup, struct freezer *freezer)
 {
        struct cgroup_iter it;
        struct task_struct *task;
-       unsigned int num_cant_freeze_now = 0;
 
        cgroup_iter_start(cgroup, &it);
-       while ((task = cgroup_iter_next(cgroup, &it))) {
-               if (!freeze_task(task))
-                       continue;
-               if (is_task_frozen_enough(task))
-                       continue;
-               if (!freezing(task) && !freezer_should_skip(task))
-                       num_cant_freeze_now++;
-       }
+       while ((task = cgroup_iter_next(cgroup, &it)))
+               freeze_task(task);
        cgroup_iter_end(cgroup, &it);
-
-       return num_cant_freeze_now ? -EBUSY : 0;
 }
 
 static void unfreeze_cgroup(struct cgroup *cgroup, struct freezer *freezer)
@@ -300,18 +248,14 @@ static void unfreeze_cgroup(struct cgroup *cgroup, struct freezer *freezer)
        cgroup_iter_end(cgroup, &it);
 }
 
-static int freezer_change_state(struct cgroup *cgroup,
-                               enum freezer_state goal_state)
+static void freezer_change_state(struct cgroup *cgroup,
+                                enum freezer_state goal_state)
 {
-       struct freezer *freezer;
-       int retval = 0;
-
-       freezer = cgroup_freezer(cgroup);
+       struct freezer *freezer = cgroup_freezer(cgroup);
 
+       /* also synchronizes against task migration, see freezer_attach() */
        spin_lock_irq(&freezer->lock);
 
-       update_if_frozen(cgroup, freezer);
-
        switch (goal_state) {
        case CGROUP_THAWED:
                if (freezer->state != CGROUP_THAWED)
@@ -323,22 +267,19 @@ static int freezer_change_state(struct cgroup *cgroup,
                if (freezer->state == CGROUP_THAWED)
                        atomic_inc(&system_freezing_cnt);
                freezer->state = CGROUP_FREEZING;
-               retval = try_to_freeze_cgroup(cgroup, freezer);
+               freeze_cgroup(cgroup, freezer);
                break;
        default:
                BUG();
        }
 
        spin_unlock_irq(&freezer->lock);
-
-       return retval;
 }
 
 static int freezer_write(struct cgroup *cgroup,
                         struct cftype *cft,
                         const char *buffer)
 {
-       int retval;
        enum freezer_state goal_state;
 
        if (strcmp(buffer, freezer_state_strs[CGROUP_THAWED]) == 0)
@@ -348,11 +289,8 @@ static int freezer_write(struct cgroup *cgroup,
        else
                return -EINVAL;
 
-       if (!cgroup_lock_live_group(cgroup))
-               return -ENODEV;
-       retval = freezer_change_state(cgroup, goal_state);
-       cgroup_unlock();
-       return retval;
+       freezer_change_state(cgroup, goal_state);
+       return 0;
 }
 
 static struct cftype files[] = {
@@ -370,7 +308,7 @@ struct cgroup_subsys freezer_subsys = {
        .create         = freezer_create,
        .destroy        = freezer_destroy,
        .subsys_id      = freezer_subsys_id,
-       .can_attach     = freezer_can_attach,
+       .attach         = freezer_attach,
        .fork           = freezer_fork,
        .base_cftypes   = files,
 
index 42bd331ee0abff1d542583e14beb20d91f6fae62..86bd65e394774699af8ae447dc3d4f79a2ebdcfe 100644 (file)
@@ -247,13 +247,18 @@ static int __ref take_cpu_down(void *_param)
 {
        struct take_cpu_down_param *param = _param;
        int err;
+       unsigned long flags;
 
        /* Ensure this CPU doesn't handle any more interrupts. */
+       local_irq_save(flags);
        err = __cpu_disable();
-       if (err < 0)
+       if (err < 0) {
+               local_irq_restore(flags);
                return err;
+       }
 
        cpu_notify(CPU_DYING | param->mod, param->hcpu);
+       local_irq_restore(flags);
        return 0;
 }
 
@@ -286,7 +291,7 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen)
        }
        smpboot_park_threads(cpu);
 
-       err = __stop_machine(take_cpu_down, &tcd_param, cpumask_of(cpu));
+       err = stop_cpus(cpumask_of(cpu), take_cpu_down, &tcd_param);
        if (err) {
                /* CPU didn't die: tell everyone.  Can't complain. */
                smpboot_unpark_threads(cpu);
@@ -348,11 +353,13 @@ static int __cpuinit _cpu_up(unsigned int cpu, int tasks_frozen)
        unsigned long mod = tasks_frozen ? CPU_TASKS_FROZEN : 0;
        struct task_struct *idle;
 
-       if (cpu_online(cpu) || !cpu_present(cpu))
-               return -EINVAL;
-
        cpu_hotplug_begin();
 
+       if (cpu_online(cpu) || !cpu_present(cpu)) {
+               ret = -EINVAL;
+               goto out;
+       }
+
        idle = idle_thread_get(cpu);
        if (IS_ERR(idle)) {
                ret = PTR_ERR(idle);
index 48cea3da6d052c77bdfe3b5b8e766f0a3033c28c..8888afb846e95f36f5fa4ab27b82685785083bd8 100644 (file)
 
 static struct kmem_cache *cred_jar;
 
-/*
- * The common credentials for the initial task's thread group
- */
-#ifdef CONFIG_KEYS
-static struct thread_group_cred init_tgcred = {
-       .usage  = ATOMIC_INIT(2),
-       .tgid   = 0,
-       .lock   = __SPIN_LOCK_UNLOCKED(init_cred.tgcred.lock),
-};
-#endif
-
 /*
  * The initial credentials for the initial task
  */
@@ -65,9 +54,6 @@ struct cred init_cred = {
        .user                   = INIT_USER,
        .user_ns                = &init_user_ns,
        .group_info             = &init_groups,
-#ifdef CONFIG_KEYS
-       .tgcred                 = &init_tgcred,
-#endif
 };
 
 static inline void set_cred_subscribers(struct cred *cred, int n)
@@ -95,36 +81,6 @@ static inline void alter_cred_subscribers(const struct cred *_cred, int n)
 #endif
 }
 
-/*
- * Dispose of the shared task group credentials
- */
-#ifdef CONFIG_KEYS
-static void release_tgcred_rcu(struct rcu_head *rcu)
-{
-       struct thread_group_cred *tgcred =
-               container_of(rcu, struct thread_group_cred, rcu);
-
-       BUG_ON(atomic_read(&tgcred->usage) != 0);
-
-       key_put(tgcred->session_keyring);
-       key_put(tgcred->process_keyring);
-       kfree(tgcred);
-}
-#endif
-
-/*
- * Release a set of thread group credentials.
- */
-static void release_tgcred(struct cred *cred)
-{
-#ifdef CONFIG_KEYS
-       struct thread_group_cred *tgcred = cred->tgcred;
-
-       if (atomic_dec_and_test(&tgcred->usage))
-               call_rcu(&tgcred->rcu, release_tgcred_rcu);
-#endif
-}
-
 /*
  * The RCU callback to actually dispose of a set of credentials
  */
@@ -150,9 +106,10 @@ static void put_cred_rcu(struct rcu_head *rcu)
 #endif
 
        security_cred_free(cred);
+       key_put(cred->session_keyring);
+       key_put(cred->process_keyring);
        key_put(cred->thread_keyring);
        key_put(cred->request_key_auth);
-       release_tgcred(cred);
        if (cred->group_info)
                put_group_info(cred->group_info);
        free_uid(cred->user);
@@ -246,15 +203,6 @@ struct cred *cred_alloc_blank(void)
        if (!new)
                return NULL;
 
-#ifdef CONFIG_KEYS
-       new->tgcred = kzalloc(sizeof(*new->tgcred), GFP_KERNEL);
-       if (!new->tgcred) {
-               kmem_cache_free(cred_jar, new);
-               return NULL;
-       }
-       atomic_set(&new->tgcred->usage, 1);
-#endif
-
        atomic_set(&new->usage, 1);
 #ifdef CONFIG_DEBUG_CREDENTIALS
        new->magic = CRED_MAGIC;
@@ -308,9 +256,10 @@ struct cred *prepare_creds(void)
        get_user_ns(new->user_ns);
 
 #ifdef CONFIG_KEYS
+       key_get(new->session_keyring);
+       key_get(new->process_keyring);
        key_get(new->thread_keyring);
        key_get(new->request_key_auth);
-       atomic_inc(&new->tgcred->usage);
 #endif
 
 #ifdef CONFIG_SECURITY
@@ -334,39 +283,20 @@ EXPORT_SYMBOL(prepare_creds);
  */
 struct cred *prepare_exec_creds(void)
 {
-       struct thread_group_cred *tgcred = NULL;
        struct cred *new;
 
-#ifdef CONFIG_KEYS
-       tgcred = kmalloc(sizeof(*tgcred), GFP_KERNEL);
-       if (!tgcred)
-               return NULL;
-#endif
-
        new = prepare_creds();
-       if (!new) {
-               kfree(tgcred);
+       if (!new)
                return new;
-       }
 
 #ifdef CONFIG_KEYS
        /* newly exec'd tasks don't get a thread keyring */
        key_put(new->thread_keyring);
        new->thread_keyring = NULL;
 
-       /* create a new per-thread-group creds for all this set of threads to
-        * share */
-       memcpy(tgcred, new->tgcred, sizeof(struct thread_group_cred));
-
-       atomic_set(&tgcred->usage, 1);
-       spin_lock_init(&tgcred->lock);
-
        /* inherit the session keyring; new process keyring */
-       key_get(tgcred->session_keyring);
-       tgcred->process_keyring = NULL;
-
-       release_tgcred(new);
-       new->tgcred = tgcred;
+       key_put(new->process_keyring);
+       new->process_keyring = NULL;
 #endif
 
        return new;
@@ -383,9 +313,6 @@ struct cred *prepare_exec_creds(void)
  */
 int copy_creds(struct task_struct *p, unsigned long clone_flags)
 {
-#ifdef CONFIG_KEYS
-       struct thread_group_cred *tgcred;
-#endif
        struct cred *new;
        int ret;
 
@@ -425,22 +352,12 @@ int copy_creds(struct task_struct *p, unsigned long clone_flags)
                        install_thread_keyring_to_cred(new);
        }
 
-       /* we share the process and session keyrings between all the threads in
-        * a process - this is slightly icky as we violate COW credentials a
-        * bit */
+       /* The process keyring is only shared between the threads in a process;
+        * anything outside of those threads doesn't inherit.
+        */
        if (!(clone_flags & CLONE_THREAD)) {
-               tgcred = kmalloc(sizeof(*tgcred), GFP_KERNEL);
-               if (!tgcred) {
-                       ret = -ENOMEM;
-                       goto error_put;
-               }
-               atomic_set(&tgcred->usage, 1);
-               spin_lock_init(&tgcred->lock);
-               tgcred->process_keyring = NULL;
-               tgcred->session_keyring = key_get(new->tgcred->session_keyring);
-
-               release_tgcred(new);
-               new->tgcred = tgcred;
+               key_put(new->process_keyring);
+               new->process_keyring = NULL;
        }
 #endif
 
@@ -643,9 +560,6 @@ void __init cred_init(void)
  */
 struct cred *prepare_kernel_cred(struct task_struct *daemon)
 {
-#ifdef CONFIG_KEYS
-       struct thread_group_cred *tgcred;
-#endif
        const struct cred *old;
        struct cred *new;
 
@@ -653,14 +567,6 @@ struct cred *prepare_kernel_cred(struct task_struct *daemon)
        if (!new)
                return NULL;
 
-#ifdef CONFIG_KEYS
-       tgcred = kmalloc(sizeof(*tgcred), GFP_KERNEL);
-       if (!tgcred) {
-               kmem_cache_free(cred_jar, new);
-               return NULL;
-       }
-#endif
-
        kdebug("prepare_kernel_cred() alloc %p", new);
 
        if (daemon)
@@ -678,13 +584,10 @@ struct cred *prepare_kernel_cred(struct task_struct *daemon)
        get_group_info(new->group_info);
 
 #ifdef CONFIG_KEYS
-       atomic_set(&tgcred->usage, 1);
-       spin_lock_init(&tgcred->lock);
-       tgcred->process_keyring = NULL;
-       tgcred->session_keyring = NULL;
-       new->tgcred = tgcred;
-       new->request_key_auth = NULL;
+       new->session_keyring = NULL;
+       new->process_keyring = NULL;
        new->thread_keyring = NULL;
+       new->request_key_auth = NULL;
        new->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING;
 #endif
 
index 98256bc71ee136915b126b81dd1e61b8990a8ce3..5cc4e7e42e689a7076ece7eb252f5a1f3a1eb5b6 100644 (file)
@@ -78,15 +78,23 @@ static struct mutex uprobes_mmap_mutex[UPROBES_HASH_SZ];
  */
 static atomic_t uprobe_events = ATOMIC_INIT(0);
 
+/* Have a copy of original instruction */
+#define UPROBE_COPY_INSN       0
+/* Dont run handlers when first register/ last unregister in progress*/
+#define UPROBE_RUN_HANDLER     1
+/* Can skip singlestep */
+#define UPROBE_SKIP_SSTEP      2
+
 struct uprobe {
        struct rb_node          rb_node;        /* node in the rb tree */
        atomic_t                ref;
        struct rw_semaphore     consumer_rwsem;
+       struct mutex            copy_mutex;     /* TODO: kill me and UPROBE_COPY_INSN */
        struct list_head        pending_list;
        struct uprobe_consumer  *consumers;
        struct inode            *inode;         /* Also hold a ref to inode */
        loff_t                  offset;
-       int                     flags;
+       unsigned long           flags;
        struct arch_uprobe      arch;
 };
 
@@ -100,17 +108,12 @@ struct uprobe {
  */
 static bool valid_vma(struct vm_area_struct *vma, bool is_register)
 {
-       if (!vma->vm_file)
-               return false;
-
-       if (!is_register)
-               return true;
+       vm_flags_t flags = VM_HUGETLB | VM_MAYEXEC | VM_SHARED;
 
-       if ((vma->vm_flags & (VM_HUGETLB|VM_READ|VM_WRITE|VM_EXEC|VM_SHARED))
-                               == (VM_READ|VM_EXEC))
-               return true;
+       if (is_register)
+               flags |= VM_WRITE;
 
-       return false;
+       return vma->vm_file && (vma->vm_flags & flags) == VM_MAYEXEC;
 }
 
 static unsigned long offset_to_vaddr(struct vm_area_struct *vma, loff_t offset)
@@ -193,19 +196,44 @@ bool __weak is_swbp_insn(uprobe_opcode_t *insn)
        return *insn == UPROBE_SWBP_INSN;
 }
 
+static void copy_opcode(struct page *page, unsigned long vaddr, uprobe_opcode_t *opcode)
+{
+       void *kaddr = kmap_atomic(page);
+       memcpy(opcode, kaddr + (vaddr & ~PAGE_MASK), UPROBE_SWBP_INSN_SIZE);
+       kunmap_atomic(kaddr);
+}
+
+static int verify_opcode(struct page *page, unsigned long vaddr, uprobe_opcode_t *new_opcode)
+{
+       uprobe_opcode_t old_opcode;
+       bool is_swbp;
+
+       copy_opcode(page, vaddr, &old_opcode);
+       is_swbp = is_swbp_insn(&old_opcode);
+
+       if (is_swbp_insn(new_opcode)) {
+               if (is_swbp)            /* register: already installed? */
+                       return 0;
+       } else {
+               if (!is_swbp)           /* unregister: was it changed by us? */
+                       return 0;
+       }
+
+       return 1;
+}
+
 /*
  * NOTE:
  * Expect the breakpoint instruction to be the smallest size instruction for
  * the architecture. If an arch has variable length instruction and the
  * breakpoint instruction is not of the smallest length instruction
- * supported by that architecture then we need to modify read_opcode /
+ * supported by that architecture then we need to modify is_swbp_at_addr and
  * write_opcode accordingly. This would never be a problem for archs that
  * have fixed length instructions.
  */
 
 /*
  * write_opcode - write the opcode at a given virtual address.
- * @auprobe: arch breakpointing information.
  * @mm: the probed process address space.
  * @vaddr: the virtual address to store the opcode.
  * @opcode: opcode to be written at @vaddr.
@@ -216,8 +244,8 @@ bool __weak is_swbp_insn(uprobe_opcode_t *insn)
  * For mm @mm, write the opcode at @vaddr.
  * Return 0 (success) or a negative errno.
  */
-static int write_opcode(struct arch_uprobe *auprobe, struct mm_struct *mm,
-                       unsigned long vaddr, uprobe_opcode_t opcode)
+static int write_opcode(struct mm_struct *mm, unsigned long vaddr,
+                       uprobe_opcode_t opcode)
 {
        struct page *old_page, *new_page;
        void *vaddr_old, *vaddr_new;
@@ -226,10 +254,14 @@ static int write_opcode(struct arch_uprobe *auprobe, struct mm_struct *mm,
 
 retry:
        /* Read the page with vaddr into memory */
-       ret = get_user_pages(NULL, mm, vaddr, 1, 0, 0, &old_page, &vma);
+       ret = get_user_pages(NULL, mm, vaddr, 1, 0, 1, &old_page, &vma);
        if (ret <= 0)
                return ret;
 
+       ret = verify_opcode(old_page, vaddr, &opcode);
+       if (ret <= 0)
+               goto put_old;
+
        ret = -ENOMEM;
        new_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, vaddr);
        if (!new_page)
@@ -263,63 +295,6 @@ put_old:
        return ret;
 }
 
-/**
- * read_opcode - read the opcode at a given virtual address.
- * @mm: the probed process address space.
- * @vaddr: the virtual address to read the opcode.
- * @opcode: location to store the read opcode.
- *
- * Called with mm->mmap_sem held (for read and with a reference to
- * mm.
- *
- * For mm @mm, read the opcode at @vaddr and store it in @opcode.
- * Return 0 (success) or a negative errno.
- */
-static int read_opcode(struct mm_struct *mm, unsigned long vaddr, uprobe_opcode_t *opcode)
-{
-       struct page *page;
-       void *vaddr_new;
-       int ret;
-
-       ret = get_user_pages(NULL, mm, vaddr, 1, 0, 1, &page, NULL);
-       if (ret <= 0)
-               return ret;
-
-       vaddr_new = kmap_atomic(page);
-       vaddr &= ~PAGE_MASK;
-       memcpy(opcode, vaddr_new + vaddr, UPROBE_SWBP_INSN_SIZE);
-       kunmap_atomic(vaddr_new);
-
-       put_page(page);
-
-       return 0;
-}
-
-static int is_swbp_at_addr(struct mm_struct *mm, unsigned long vaddr)
-{
-       uprobe_opcode_t opcode;
-       int result;
-
-       if (current->mm == mm) {
-               pagefault_disable();
-               result = __copy_from_user_inatomic(&opcode, (void __user*)vaddr,
-                                                               sizeof(opcode));
-               pagefault_enable();
-
-               if (likely(result == 0))
-                       goto out;
-       }
-
-       result = read_opcode(mm, vaddr, &opcode);
-       if (result)
-               return result;
-out:
-       if (is_swbp_insn(&opcode))
-               return 1;
-
-       return 0;
-}
-
 /**
  * set_swbp - store breakpoint at a given address.
  * @auprobe: arch specific probepoint information.
@@ -331,18 +306,7 @@ out:
  */
 int __weak set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr)
 {
-       int result;
-       /*
-        * See the comment near uprobes_hash().
-        */
-       result = is_swbp_at_addr(mm, vaddr);
-       if (result == 1)
-               return 0;
-
-       if (result)
-               return result;
-
-       return write_opcode(auprobe, mm, vaddr, UPROBE_SWBP_INSN);
+       return write_opcode(mm, vaddr, UPROBE_SWBP_INSN);
 }
 
 /**
@@ -357,16 +321,7 @@ int __weak set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned
 int __weak
 set_orig_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr)
 {
-       int result;
-
-       result = is_swbp_at_addr(mm, vaddr);
-       if (!result)
-               return -EINVAL;
-
-       if (result != 1)
-               return result;
-
-       return write_opcode(auprobe, mm, vaddr, *(uprobe_opcode_t *)auprobe->insn);
+       return write_opcode(mm, vaddr, *(uprobe_opcode_t *)auprobe->insn);
 }
 
 static int match_uprobe(struct uprobe *l, struct uprobe *r)
@@ -473,7 +428,7 @@ static struct uprobe *insert_uprobe(struct uprobe *uprobe)
        spin_unlock(&uprobes_treelock);
 
        /* For now assume that the instruction need not be single-stepped */
-       uprobe->flags |= UPROBE_SKIP_SSTEP;
+       __set_bit(UPROBE_SKIP_SSTEP, &uprobe->flags);
 
        return u;
 }
@@ -495,6 +450,7 @@ static struct uprobe *alloc_uprobe(struct inode *inode, loff_t offset)
        uprobe->inode = igrab(inode);
        uprobe->offset = offset;
        init_rwsem(&uprobe->consumer_rwsem);
+       mutex_init(&uprobe->copy_mutex);
 
        /* add to uprobes_tree, sorted on inode:offset */
        cur_uprobe = insert_uprobe(uprobe);
@@ -515,7 +471,7 @@ static void handler_chain(struct uprobe *uprobe, struct pt_regs *regs)
 {
        struct uprobe_consumer *uc;
 
-       if (!(uprobe->flags & UPROBE_RUN_HANDLER))
+       if (!test_bit(UPROBE_RUN_HANDLER, &uprobe->flags))
                return;
 
        down_read(&uprobe->consumer_rwsem);
@@ -621,29 +577,43 @@ static int copy_insn(struct uprobe *uprobe, struct file *filp)
        return __copy_insn(mapping, filp, uprobe->arch.insn, bytes, uprobe->offset);
 }
 
-/*
- * How mm->uprobes_state.count gets updated
- * uprobe_mmap() increments the count if
- *     - it successfully adds a breakpoint.
- *     - it cannot add a breakpoint, but sees that there is a underlying
- *       breakpoint (via a is_swbp_at_addr()).
- *
- * uprobe_munmap() decrements the count if
- *     - it sees a underlying breakpoint, (via is_swbp_at_addr)
- *       (Subsequent uprobe_unregister wouldnt find the breakpoint
- *       unless a uprobe_mmap kicks in, since the old vma would be
- *       dropped just after uprobe_munmap.)
- *
- * uprobe_register increments the count if:
- *     - it successfully adds a breakpoint.
- *
- * uprobe_unregister decrements the count if:
- *     - it sees a underlying breakpoint and removes successfully.
- *       (via is_swbp_at_addr)
- *       (Subsequent uprobe_munmap wouldnt find the breakpoint
- *       since there is no underlying breakpoint after the
- *       breakpoint removal.)
- */
+static int prepare_uprobe(struct uprobe *uprobe, struct file *file,
+                               struct mm_struct *mm, unsigned long vaddr)
+{
+       int ret = 0;
+
+       if (test_bit(UPROBE_COPY_INSN, &uprobe->flags))
+               return ret;
+
+       mutex_lock(&uprobe->copy_mutex);
+       if (test_bit(UPROBE_COPY_INSN, &uprobe->flags))
+               goto out;
+
+       ret = copy_insn(uprobe, file);
+       if (ret)
+               goto out;
+
+       ret = -ENOTSUPP;
+       if (is_swbp_insn((uprobe_opcode_t *)uprobe->arch.insn))
+               goto out;
+
+       ret = arch_uprobe_analyze_insn(&uprobe->arch, mm, vaddr);
+       if (ret)
+               goto out;
+
+       /* write_opcode() assumes we don't cross page boundary */
+       BUG_ON((uprobe->offset & ~PAGE_MASK) +
+                       UPROBE_SWBP_INSN_SIZE > PAGE_SIZE);
+
+       smp_wmb(); /* pairs with rmb() in find_active_uprobe() */
+       set_bit(UPROBE_COPY_INSN, &uprobe->flags);
+
+ out:
+       mutex_unlock(&uprobe->copy_mutex);
+
+       return ret;
+}
+
 static int
 install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm,
                        struct vm_area_struct *vma, unsigned long vaddr)
@@ -661,24 +631,9 @@ install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm,
        if (!uprobe->consumers)
                return 0;
 
-       if (!(uprobe->flags & UPROBE_COPY_INSN)) {
-               ret = copy_insn(uprobe, vma->vm_file);
-               if (ret)
-                       return ret;
-
-               if (is_swbp_insn((uprobe_opcode_t *)uprobe->arch.insn))
-                       return -ENOTSUPP;
-
-               ret = arch_uprobe_analyze_insn(&uprobe->arch, mm, vaddr);
-               if (ret)
-                       return ret;
-
-               /* write_opcode() assumes we don't cross page boundary */
-               BUG_ON((uprobe->offset & ~PAGE_MASK) +
-                               UPROBE_SWBP_INSN_SIZE > PAGE_SIZE);
-
-               uprobe->flags |= UPROBE_COPY_INSN;
-       }
+       ret = prepare_uprobe(uprobe, vma->vm_file, mm, vaddr);
+       if (ret)
+               return ret;
 
        /*
         * set MMF_HAS_UPROBES in advance for uprobe_pre_sstep_notifier(),
@@ -697,15 +652,15 @@ install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm,
        return ret;
 }
 
-static void
+static int
 remove_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, unsigned long vaddr)
 {
        /* can happen if uprobe_register() fails */
        if (!test_bit(MMF_HAS_UPROBES, &mm->flags))
-               return;
+               return 0;
 
        set_bit(MMF_RECALC_UPROBES, &mm->flags);
-       set_orig_insn(&uprobe->arch, mm, vaddr);
+       return set_orig_insn(&uprobe->arch, mm, vaddr);
 }
 
 /*
@@ -820,7 +775,7 @@ static int register_for_each_vma(struct uprobe *uprobe, bool is_register)
                struct mm_struct *mm = info->mm;
                struct vm_area_struct *vma;
 
-               if (err)
+               if (err && is_register)
                        goto free;
 
                down_write(&mm->mmap_sem);
@@ -836,7 +791,7 @@ static int register_for_each_vma(struct uprobe *uprobe, bool is_register)
                if (is_register)
                        err = install_breakpoint(uprobe, mm, vma, info->vaddr);
                else
-                       remove_breakpoint(uprobe, mm, info->vaddr);
+                       err |= remove_breakpoint(uprobe, mm, info->vaddr);
 
  unlock:
                up_write(&mm->mmap_sem);
@@ -893,13 +848,15 @@ int uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer *
        mutex_lock(uprobes_hash(inode));
        uprobe = alloc_uprobe(inode, offset);
 
-       if (uprobe && !consumer_add(uprobe, uc)) {
+       if (!uprobe) {
+               ret = -ENOMEM;
+       } else if (!consumer_add(uprobe, uc)) {
                ret = __uprobe_register(uprobe);
                if (ret) {
                        uprobe->consumers = NULL;
                        __uprobe_unregister(uprobe);
                } else {
-                       uprobe->flags |= UPROBE_RUN_HANDLER;
+                       set_bit(UPROBE_RUN_HANDLER, &uprobe->flags);
                }
        }
 
@@ -932,7 +889,7 @@ void uprobe_unregister(struct inode *inode, loff_t offset, struct uprobe_consume
        if (consumer_del(uprobe, uc)) {
                if (!uprobe->consumers) {
                        __uprobe_unregister(uprobe);
-                       uprobe->flags &= ~UPROBE_RUN_HANDLER;
+                       clear_bit(UPROBE_RUN_HANDLER, &uprobe->flags);
                }
        }
 
@@ -1393,10 +1350,11 @@ bool uprobe_deny_signal(void)
  */
 static bool can_skip_sstep(struct uprobe *uprobe, struct pt_regs *regs)
 {
-       if (arch_uprobe_skip_sstep(&uprobe->arch, regs))
-               return true;
-
-       uprobe->flags &= ~UPROBE_SKIP_SSTEP;
+       if (test_bit(UPROBE_SKIP_SSTEP, &uprobe->flags)) {
+               if (arch_uprobe_skip_sstep(&uprobe->arch, regs))
+                       return true;
+               clear_bit(UPROBE_SKIP_SSTEP, &uprobe->flags);
+       }
        return false;
 }
 
@@ -1419,6 +1377,30 @@ static void mmf_recalc_uprobes(struct mm_struct *mm)
        clear_bit(MMF_HAS_UPROBES, &mm->flags);
 }
 
+static int is_swbp_at_addr(struct mm_struct *mm, unsigned long vaddr)
+{
+       struct page *page;
+       uprobe_opcode_t opcode;
+       int result;
+
+       pagefault_disable();
+       result = __copy_from_user_inatomic(&opcode, (void __user*)vaddr,
+                                                       sizeof(opcode));
+       pagefault_enable();
+
+       if (likely(result == 0))
+               goto out;
+
+       result = get_user_pages(NULL, mm, vaddr, 1, 0, 1, &page, NULL);
+       if (result < 0)
+               return result;
+
+       copy_opcode(page, vaddr, &opcode);
+       put_page(page);
+ out:
+       return is_swbp_insn(&opcode);
+}
+
 static struct uprobe *find_active_uprobe(unsigned long bp_vaddr, int *is_swbp)
 {
        struct mm_struct *mm = current->mm;
@@ -1489,38 +1471,41 @@ static void handle_swbp(struct pt_regs *regs)
                }
                return;
        }
+       /*
+        * TODO: move copy_insn/etc into _register and remove this hack.
+        * After we hit the bp, _unregister + _register can install the
+        * new and not-yet-analyzed uprobe at the same address, restart.
+        */
+       smp_rmb(); /* pairs with wmb() in install_breakpoint() */
+       if (unlikely(!test_bit(UPROBE_COPY_INSN, &uprobe->flags)))
+               goto restart;
 
        utask = current->utask;
        if (!utask) {
                utask = add_utask();
                /* Cannot allocate; re-execute the instruction. */
                if (!utask)
-                       goto cleanup_ret;
+                       goto restart;
        }
-       utask->active_uprobe = uprobe;
+
        handler_chain(uprobe, regs);
-       if (uprobe->flags & UPROBE_SKIP_SSTEP && can_skip_sstep(uprobe, regs))
-               goto cleanup_ret;
+       if (can_skip_sstep(uprobe, regs))
+               goto out;
 
-       utask->state = UTASK_SSTEP;
        if (!pre_ssout(uprobe, regs, bp_vaddr)) {
                arch_uprobe_enable_step(&uprobe->arch);
+               utask->active_uprobe = uprobe;
+               utask->state = UTASK_SSTEP;
                return;
        }
 
-cleanup_ret:
-       if (utask) {
-               utask->active_uprobe = NULL;
-               utask->state = UTASK_RUNNING;
-       }
-       if (!(uprobe->flags & UPROBE_SKIP_SSTEP))
-
-               /*
-                * cannot singlestep; cannot skip instruction;
-                * re-execute the instruction.
-                */
-               instruction_pointer_set(regs, bp_vaddr);
-
+restart:
+       /*
+        * cannot singlestep; cannot skip instruction;
+        * re-execute the instruction.
+        */
+       instruction_pointer_set(regs, bp_vaddr);
+out:
        put_uprobe(uprobe);
 }
 
@@ -1552,13 +1537,12 @@ static void handle_singlestep(struct uprobe_task *utask, struct pt_regs *regs)
 }
 
 /*
- * On breakpoint hit, breakpoint notifier sets the TIF_UPROBE flag.  (and on
- * subsequent probe hits on the thread sets the state to UTASK_BP_HIT) and
- * allows the thread to return from interrupt.
+ * On breakpoint hit, breakpoint notifier sets the TIF_UPROBE flag and
+ * allows the thread to return from interrupt. After that handle_swbp()
+ * sets utask->active_uprobe.
  *
- * On singlestep exception, singlestep notifier sets the TIF_UPROBE flag and
- * also sets the state to UTASK_SSTEP_ACK and allows the thread to return from
- * interrupt.
+ * On singlestep exception, singlestep notifier sets the TIF_UPROBE flag
+ * and allows the thread to return from interrupt.
  *
  * While returning to userspace, thread notices the TIF_UPROBE flag and calls
  * uprobe_notify_resume().
@@ -1567,11 +1551,13 @@ void uprobe_notify_resume(struct pt_regs *regs)
 {
        struct uprobe_task *utask;
 
+       clear_thread_flag(TIF_UPROBE);
+
        utask = current->utask;
-       if (!utask || utask->state == UTASK_BP_HIT)
-               handle_swbp(regs);
-       else
+       if (utask && utask->active_uprobe)
                handle_singlestep(utask, regs);
+       else
+               handle_swbp(regs);
 }
 
 /*
@@ -1580,17 +1566,10 @@ void uprobe_notify_resume(struct pt_regs *regs)
  */
 int uprobe_pre_sstep_notifier(struct pt_regs *regs)
 {
-       struct uprobe_task *utask;
-
        if (!current->mm || !test_bit(MMF_HAS_UPROBES, &current->mm->flags))
                return 0;
 
-       utask = current->utask;
-       if (utask)
-               utask->state = UTASK_BP_HIT;
-
        set_thread_flag(TIF_UPROBE);
-
        return 1;
 }
 
index 8b20ab7d3aa2951eff91a4e09e0af23a90992747..acc4cb62f32fd70318b61a38cc34ac00da6911b0 100644 (file)
@@ -1135,7 +1135,6 @@ static struct task_struct *copy_process(unsigned long clone_flags,
 {
        int retval;
        struct task_struct *p;
-       int cgroup_callbacks_done = 0;
 
        if ((clone_flags & (CLONE_NEWNS|CLONE_FS)) == (CLONE_NEWNS|CLONE_FS))
                return ERR_PTR(-EINVAL);
@@ -1393,12 +1392,6 @@ static struct task_struct *copy_process(unsigned long clone_flags,
        INIT_LIST_HEAD(&p->thread_group);
        p->task_works = NULL;
 
-       /* Now that the task is set up, run cgroup callbacks if
-        * necessary. We need to run them before the task is visible
-        * on the tasklist. */
-       cgroup_fork_callbacks(p);
-       cgroup_callbacks_done = 1;
-
        /* Need tasklist lock for parent etc handling! */
        write_lock_irq(&tasklist_lock);
 
@@ -1503,7 +1496,7 @@ bad_fork_cleanup_cgroup:
 #endif
        if (clone_flags & CLONE_THREAD)
                threadgroup_change_end(current);
-       cgroup_exit(p, cgroup_callbacks_done);
+       cgroup_exit(p, 0);
        delayacct_tsk_free(p);
        module_put(task_thread_info(p)->exec_domain->module);
 bad_fork_cleanup_count:
index 4e316e1acf584dda201b2b7ee9369a05590229a3..8715a798aa7ce1bb038e0cb2274238fd73356995 100644 (file)
@@ -141,6 +141,23 @@ static ssize_t fscaps_show(struct kobject *kobj,
 }
 KERNEL_ATTR_RO(fscaps);
 
+int rcu_expedited;
+static ssize_t rcu_expedited_show(struct kobject *kobj,
+                                 struct kobj_attribute *attr, char *buf)
+{
+       return sprintf(buf, "%d\n", rcu_expedited);
+}
+static ssize_t rcu_expedited_store(struct kobject *kobj,
+                                  struct kobj_attribute *attr,
+                                  const char *buf, size_t count)
+{
+       if (kstrtoint(buf, 0, &rcu_expedited))
+               return -EINVAL;
+
+       return count;
+}
+KERNEL_ATTR_RW(rcu_expedited);
+
 /*
  * Make /sys/kernel/notes give the raw contents of our kernel .notes section.
  */
@@ -182,6 +199,7 @@ static struct attribute * kernel_attrs[] = {
        &kexec_crash_size_attr.attr,
        &vmcoreinfo_attr.attr,
 #endif
+       &rcu_expedited_attr.attr,
        NULL
 };
 
index 91c32a0b612cd75038d96dc802c07528f1e80ade..b2c71c5873e441ae1d9a89d8caa7517eb5bcf976 100644 (file)
@@ -39,7 +39,7 @@ static void l_stop(struct seq_file *m, void *v)
 
 static void print_name(struct seq_file *m, struct lock_class *class)
 {
-       char str[128];
+       char str[KSYM_NAME_LEN];
        const char *name = class->name;
 
        if (!name) {
index 6114a13419bdc3e7424e82db981131c580f6349c..24f9247b7d0214d4b3755bb4396f14d9ef712753 100644 (file)
@@ -11,5 +11,4 @@
 
 extern struct key *modsign_keyring;
 
-extern int mod_verify_sig(const void *mod, unsigned long modlen,
-                         const void *sig, unsigned long siglen);
+extern int mod_verify_sig(const void *mod, unsigned long *_modlen);
index 0e2da8695f8ed2d80b4b498eed883e49936fc59f..bd600ebb41611ec4800862abe728891869023629 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/ftrace_event.h>
 #include <linux/init.h>
 #include <linux/kallsyms.h>
+#include <linux/file.h>
 #include <linux/fs.h>
 #include <linux/sysfs.h>
 #include <linux/kernel.h>
@@ -28,6 +29,7 @@
 #include <linux/vmalloc.h>
 #include <linux/elf.h>
 #include <linux/proc_fs.h>
+#include <linux/security.h>
 #include <linux/seq_file.h>
 #include <linux/syscalls.h>
 #include <linux/fcntl.h>
@@ -2420,26 +2422,18 @@ static inline void kmemleak_load_module(const struct module *mod,
 #endif
 
 #ifdef CONFIG_MODULE_SIG
-static int module_sig_check(struct load_info *info,
-                           const void *mod, unsigned long *len)
+static int module_sig_check(struct load_info *info)
 {
        int err = -ENOKEY;
-       const unsigned long markerlen = sizeof(MODULE_SIG_STRING) - 1;
-       const void *p = mod, *end = mod + *len;
+       unsigned long markerlen = sizeof(MODULE_SIG_STRING) - 1;
+       const void *mod = info->hdr;
 
-       /* Poor man's memmem. */
-       while ((p = memchr(p, MODULE_SIG_STRING[0], end - p))) {
-               if (p + markerlen > end)
-                       break;
-
-               if (memcmp(p, MODULE_SIG_STRING, markerlen) == 0) {
-                       const void *sig = p + markerlen;
-                       /* Truncate module up to signature. */
-                       *len = p - mod;
-                       err = mod_verify_sig(mod, *len, sig, end - sig);
-                       break;
-               }
-               p++;
+       if (info->len > markerlen &&
+           memcmp(mod + info->len - markerlen, MODULE_SIG_STRING,
+                  markerlen) == 0) {
+               /* We truncate the module to discard the signature */
+               info->len -= markerlen;
+               err = mod_verify_sig(mod, &info->len);
        }
 
        if (!err) {
@@ -2457,59 +2451,107 @@ static int module_sig_check(struct load_info *info,
        return err;
 }
 #else /* !CONFIG_MODULE_SIG */
-static int module_sig_check(struct load_info *info,
-                           void *mod, unsigned long *len)
+static int module_sig_check(struct load_info *info)
 {
        return 0;
 }
 #endif /* !CONFIG_MODULE_SIG */
 
-/* Sets info->hdr, info->len and info->sig_ok. */
-static int copy_and_check(struct load_info *info,
-                         const void __user *umod, unsigned long len,
-                         const char __user *uargs)
+/* Sanity checks against invalid binaries, wrong arch, weird elf version. */
+static int elf_header_check(struct load_info *info)
+{
+       if (info->len < sizeof(*(info->hdr)))
+               return -ENOEXEC;
+
+       if (memcmp(info->hdr->e_ident, ELFMAG, SELFMAG) != 0
+           || info->hdr->e_type != ET_REL
+           || !elf_check_arch(info->hdr)
+           || info->hdr->e_shentsize != sizeof(Elf_Shdr))
+               return -ENOEXEC;
+
+       if (info->hdr->e_shoff >= info->len
+           || (info->hdr->e_shnum * sizeof(Elf_Shdr) >
+               info->len - info->hdr->e_shoff))
+               return -ENOEXEC;
+
+       return 0;
+}
+
+/* Sets info->hdr and info->len. */
+static int copy_module_from_user(const void __user *umod, unsigned long len,
+                                 struct load_info *info)
 {
        int err;
-       Elf_Ehdr *hdr;
 
-       if (len < sizeof(*hdr))
+       info->len = len;
+       if (info->len < sizeof(*(info->hdr)))
                return -ENOEXEC;
 
+       err = security_kernel_module_from_file(NULL);
+       if (err)
+               return err;
+
        /* Suck in entire file: we'll want most of it. */
-       if ((hdr = vmalloc(len)) == NULL)
+       info->hdr = vmalloc(info->len);
+       if (!info->hdr)
                return -ENOMEM;
 
-       if (copy_from_user(hdr, umod, len) != 0) {
-               err = -EFAULT;
-               goto free_hdr;
+       if (copy_from_user(info->hdr, umod, info->len) != 0) {
+               vfree(info->hdr);
+               return -EFAULT;
        }
 
-       err = module_sig_check(info, hdr, &len);
+       return 0;
+}
+
+/* Sets info->hdr and info->len. */
+static int copy_module_from_fd(int fd, struct load_info *info)
+{
+       struct file *file;
+       int err;
+       struct kstat stat;
+       loff_t pos;
+       ssize_t bytes = 0;
+
+       file = fget(fd);
+       if (!file)
+               return -ENOEXEC;
+
+       err = security_kernel_module_from_file(file);
        if (err)
-               goto free_hdr;
+               goto out;
 
-       /* Sanity checks against insmoding binaries or wrong arch,
-          weird elf version */
-       if (memcmp(hdr->e_ident, ELFMAG, SELFMAG) != 0
-           || hdr->e_type != ET_REL
-           || !elf_check_arch(hdr)
-           || hdr->e_shentsize != sizeof(Elf_Shdr)) {
-               err = -ENOEXEC;
-               goto free_hdr;
-       }
+       err = vfs_getattr(file->f_vfsmnt, file->f_dentry, &stat);
+       if (err)
+               goto out;
 
-       if (hdr->e_shoff >= len ||
-           hdr->e_shnum * sizeof(Elf_Shdr) > len - hdr->e_shoff) {
-               err = -ENOEXEC;
-               goto free_hdr;
+       if (stat.size > INT_MAX) {
+               err = -EFBIG;
+               goto out;
+       }
+       info->hdr = vmalloc(stat.size);
+       if (!info->hdr) {
+               err = -ENOMEM;
+               goto out;
        }
 
-       info->hdr = hdr;
-       info->len = len;
-       return 0;
+       pos = 0;
+       while (pos < stat.size) {
+               bytes = kernel_read(file, pos, (char *)(info->hdr) + pos,
+                                   stat.size - pos);
+               if (bytes < 0) {
+                       vfree(info->hdr);
+                       err = bytes;
+                       goto out;
+               }
+               if (bytes == 0)
+                       break;
+               pos += bytes;
+       }
+       info->len = pos;
 
-free_hdr:
-       vfree(hdr);
+out:
+       fput(file);
        return err;
 }
 
@@ -2948,33 +2990,123 @@ static bool finished_loading(const char *name)
        return ret;
 }
 
+/* Call module constructors. */
+static void do_mod_ctors(struct module *mod)
+{
+#ifdef CONFIG_CONSTRUCTORS
+       unsigned long i;
+
+       for (i = 0; i < mod->num_ctors; i++)
+               mod->ctors[i]();
+#endif
+}
+
+/* This is where the real work happens */
+static int do_init_module(struct module *mod)
+{
+       int ret = 0;
+
+       blocking_notifier_call_chain(&module_notify_list,
+                       MODULE_STATE_COMING, mod);
+
+       /* Set RO and NX regions for core */
+       set_section_ro_nx(mod->module_core,
+                               mod->core_text_size,
+                               mod->core_ro_size,
+                               mod->core_size);
+
+       /* Set RO and NX regions for init */
+       set_section_ro_nx(mod->module_init,
+                               mod->init_text_size,
+                               mod->init_ro_size,
+                               mod->init_size);
+
+       do_mod_ctors(mod);
+       /* Start the module */
+       if (mod->init != NULL)
+               ret = do_one_initcall(mod->init);
+       if (ret < 0) {
+               /* Init routine failed: abort.  Try to protect us from
+                   buggy refcounters. */
+               mod->state = MODULE_STATE_GOING;
+               synchronize_sched();
+               module_put(mod);
+               blocking_notifier_call_chain(&module_notify_list,
+                                            MODULE_STATE_GOING, mod);
+               free_module(mod);
+               wake_up_all(&module_wq);
+               return ret;
+       }
+       if (ret > 0) {
+               printk(KERN_WARNING
+"%s: '%s'->init suspiciously returned %d, it should follow 0/-E convention\n"
+"%s: loading module anyway...\n",
+                      __func__, mod->name, ret,
+                      __func__);
+               dump_stack();
+       }
+
+       /* Now it's a first class citizen! */
+       mod->state = MODULE_STATE_LIVE;
+       blocking_notifier_call_chain(&module_notify_list,
+                                    MODULE_STATE_LIVE, mod);
+
+       /* We need to finish all async code before the module init sequence is done */
+       async_synchronize_full();
+
+       mutex_lock(&module_mutex);
+       /* Drop initial reference. */
+       module_put(mod);
+       trim_init_extable(mod);
+#ifdef CONFIG_KALLSYMS
+       mod->num_symtab = mod->core_num_syms;
+       mod->symtab = mod->core_symtab;
+       mod->strtab = mod->core_strtab;
+#endif
+       unset_module_init_ro_nx(mod);
+       module_free(mod, mod->module_init);
+       mod->module_init = NULL;
+       mod->init_size = 0;
+       mod->init_ro_size = 0;
+       mod->init_text_size = 0;
+       mutex_unlock(&module_mutex);
+       wake_up_all(&module_wq);
+
+       return 0;
+}
+
+static int may_init_module(void)
+{
+       if (!capable(CAP_SYS_MODULE) || modules_disabled)
+               return -EPERM;
+
+       return 0;
+}
+
 /* Allocate and load the module: note that size of section 0 is always
    zero, and we rely on this for optional sections. */
-static struct module *load_module(void __user *umod,
-                                 unsigned long len,
-                                 const char __user *uargs)
+static int load_module(struct load_info *info, const char __user *uargs)
 {
-       struct load_info info = { NULL, };
        struct module *mod, *old;
        long err;
 
-       pr_debug("load_module: umod=%p, len=%lu, uargs=%p\n",
-              umod, len, uargs);
+       err = module_sig_check(info);
+       if (err)
+               goto free_copy;
 
-       /* Copy in the blobs from userspace, check they are vaguely sane. */
-       err = copy_and_check(&info, umod, len, uargs);
+       err = elf_header_check(info);
        if (err)
-               return ERR_PTR(err);
+               goto free_copy;
 
        /* Figure out module layout, and allocate all the memory. */
-       mod = layout_and_allocate(&info);
+       mod = layout_and_allocate(info);
        if (IS_ERR(mod)) {
                err = PTR_ERR(mod);
                goto free_copy;
        }
 
 #ifdef CONFIG_MODULE_SIG
-       mod->sig_ok = info.sig_ok;
+       mod->sig_ok = info->sig_ok;
        if (!mod->sig_ok)
                add_taint_module(mod, TAINT_FORCED_MODULE);
 #endif
@@ -2986,25 +3118,25 @@ static struct module *load_module(void __user *umod,
 
        /* Now we've got everything in the final locations, we can
         * find optional sections. */
-       find_module_sections(mod, &info);
+       find_module_sections(mod, info);
 
        err = check_module_license_and_versions(mod);
        if (err)
                goto free_unload;
 
        /* Set up MODINFO_ATTR fields */
-       setup_modinfo(mod, &info);
+       setup_modinfo(mod, info);
 
        /* Fix up syms, so that st_value is a pointer to location. */
-       err = simplify_symbols(mod, &info);
+       err = simplify_symbols(mod, info);
        if (err < 0)
                goto free_modinfo;
 
-       err = apply_relocations(mod, &info);
+       err = apply_relocations(mod, info);
        if (err < 0)
                goto free_modinfo;
 
-       err = post_relocation(mod, &info);
+       err = post_relocation(mod, info);
        if (err < 0)
                goto free_modinfo;
 
@@ -3044,14 +3176,14 @@ again:
        }
 
        /* This has to be done once we're sure module name is unique. */
-       dynamic_debug_setup(info.debug, info.num_debug);
+       dynamic_debug_setup(info->debug, info->num_debug);
 
        /* Find duplicate symbols */
        err = verify_export_symbols(mod);
        if (err < 0)
                goto ddebug;
 
-       module_bug_finalize(info.hdr, info.sechdrs, mod);
+       module_bug_finalize(info->hdr, info->sechdrs, mod);
        list_add_rcu(&mod->list, &modules);
        mutex_unlock(&module_mutex);
 
@@ -3062,16 +3194,17 @@ again:
                goto unlink;
 
        /* Link in to syfs. */
-       err = mod_sysfs_setup(mod, &info, mod->kp, mod->num_kp);
+       err = mod_sysfs_setup(mod, info, mod->kp, mod->num_kp);
        if (err < 0)
                goto unlink;
 
        /* Get rid of temporary copy. */
-       free_copy(&info);
+       free_copy(info);
 
        /* Done! */
        trace_module_load(mod);
-       return mod;
+
+       return do_init_module(mod);
 
  unlink:
        mutex_lock(&module_mutex);
@@ -3080,7 +3213,7 @@ again:
        module_bug_cleanup(mod);
        wake_up_all(&module_wq);
  ddebug:
-       dynamic_debug_remove(info.debug);
+       dynamic_debug_remove(info->debug);
  unlock:
        mutex_unlock(&module_mutex);
        synchronize_sched();
@@ -3092,106 +3225,48 @@ again:
  free_unload:
        module_unload_free(mod);
  free_module:
-       module_deallocate(mod, &info);
+       module_deallocate(mod, info);
  free_copy:
-       free_copy(&info);
-       return ERR_PTR(err);
-}
-
-/* Call module constructors. */
-static void do_mod_ctors(struct module *mod)
-{
-#ifdef CONFIG_CONSTRUCTORS
-       unsigned long i;
-
-       for (i = 0; i < mod->num_ctors; i++)
-               mod->ctors[i]();
-#endif
+       free_copy(info);
+       return err;
 }
 
-/* This is where the real work happens */
 SYSCALL_DEFINE3(init_module, void __user *, umod,
                unsigned long, len, const char __user *, uargs)
 {
-       struct module *mod;
-       int ret = 0;
-
-       /* Must have permission */
-       if (!capable(CAP_SYS_MODULE) || modules_disabled)
-               return -EPERM;
+       int err;
+       struct load_info info = { };
 
-       /* Do all the hard work */
-       mod = load_module(umod, len, uargs);
-       if (IS_ERR(mod))
-               return PTR_ERR(mod);
+       err = may_init_module();
+       if (err)
+               return err;
 
-       blocking_notifier_call_chain(&module_notify_list,
-                       MODULE_STATE_COMING, mod);
+       pr_debug("init_module: umod=%p, len=%lu, uargs=%p\n",
+              umod, len, uargs);
 
-       /* Set RO and NX regions for core */
-       set_section_ro_nx(mod->module_core,
-                               mod->core_text_size,
-                               mod->core_ro_size,
-                               mod->core_size);
+       err = copy_module_from_user(umod, len, &info);
+       if (err)
+               return err;
 
-       /* Set RO and NX regions for init */
-       set_section_ro_nx(mod->module_init,
-                               mod->init_text_size,
-                               mod->init_ro_size,
-                               mod->init_size);
+       return load_module(&info, uargs);
+}
 
-       do_mod_ctors(mod);
-       /* Start the module */
-       if (mod->init != NULL)
-               ret = do_one_initcall(mod->init);
-       if (ret < 0) {
-               /* Init routine failed: abort.  Try to protect us from
-                   buggy refcounters. */
-               mod->state = MODULE_STATE_GOING;
-               synchronize_sched();
-               module_put(mod);
-               blocking_notifier_call_chain(&module_notify_list,
-                                            MODULE_STATE_GOING, mod);
-               free_module(mod);
-               wake_up_all(&module_wq);
-               return ret;
-       }
-       if (ret > 0) {
-               printk(KERN_WARNING
-"%s: '%s'->init suspiciously returned %d, it should follow 0/-E convention\n"
-"%s: loading module anyway...\n",
-                      __func__, mod->name, ret,
-                      __func__);
-               dump_stack();
-       }
+SYSCALL_DEFINE2(finit_module, int, fd, const char __user *, uargs)
+{
+       int err;
+       struct load_info info = { };
 
-       /* Now it's a first class citizen! */
-       mod->state = MODULE_STATE_LIVE;
-       blocking_notifier_call_chain(&module_notify_list,
-                                    MODULE_STATE_LIVE, mod);
+       err = may_init_module();
+       if (err)
+               return err;
 
-       /* We need to finish all async code before the module init sequence is done */
-       async_synchronize_full();
+       pr_debug("finit_module: fd=%d, uargs=%p\n", fd, uargs);
 
-       mutex_lock(&module_mutex);
-       /* Drop initial reference. */
-       module_put(mod);
-       trim_init_extable(mod);
-#ifdef CONFIG_KALLSYMS
-       mod->num_symtab = mod->core_num_syms;
-       mod->symtab = mod->core_symtab;
-       mod->strtab = mod->core_strtab;
-#endif
-       unset_module_init_ro_nx(mod);
-       module_free(mod, mod->module_init);
-       mod->module_init = NULL;
-       mod->init_size = 0;
-       mod->init_ro_size = 0;
-       mod->init_text_size = 0;
-       mutex_unlock(&module_mutex);
-       wake_up_all(&module_wq);
+       err = copy_module_from_fd(fd, &info);
+       if (err)
+               return err;
 
-       return 0;
+       return load_module(&info, uargs);
 }
 
 static inline int within(unsigned long addr, void *start, unsigned long size)
index 6b09f6983ac0d75ef35828ebacccb74db57a1817..f2970bddc5ea6224b8c0357970a543c90ac11da0 100644 (file)
  *     - Information block
  */
 struct module_signature {
-       enum pkey_algo          algo : 8;       /* Public-key crypto algorithm */
-       enum pkey_hash_algo     hash : 8;       /* Digest algorithm */
-       enum pkey_id_type       id_type : 8;    /* Key identifier type */
-       u8                      signer_len;     /* Length of signer's name */
-       u8                      key_id_len;     /* Length of key identifier */
-       u8                      __pad[3];
-       __be32                  sig_len;        /* Length of signature data */
+       u8      algo;           /* Public-key crypto algorithm [enum pkey_algo] */
+       u8      hash;           /* Digest algorithm [enum pkey_hash_algo] */
+       u8      id_type;        /* Key identifier type [enum pkey_id_type] */
+       u8      signer_len;     /* Length of signer's name */
+       u8      key_id_len;     /* Length of key identifier */
+       u8      __pad[3];
+       __be32  sig_len;        /* Length of signature data */
 };
 
 /*
@@ -183,27 +183,33 @@ static struct key *request_asymmetric_key(const char *signer, size_t signer_len,
 /*
  * Verify the signature on a module.
  */
-int mod_verify_sig(const void *mod, unsigned long modlen,
-                  const void *sig, unsigned long siglen)
+int mod_verify_sig(const void *mod, unsigned long *_modlen)
 {
        struct public_key_signature *pks;
        struct module_signature ms;
        struct key *key;
-       size_t sig_len;
+       const void *sig;
+       size_t modlen = *_modlen, sig_len;
        int ret;
 
-       pr_devel("==>%s(,%lu,,%lu,)\n", __func__, modlen, siglen);
+       pr_devel("==>%s(,%zu)\n", __func__, modlen);
 
-       if (siglen <= sizeof(ms))
+       if (modlen <= sizeof(ms))
                return -EBADMSG;
 
-       memcpy(&ms, sig + (siglen - sizeof(ms)), sizeof(ms));
-       siglen -= sizeof(ms);
+       memcpy(&ms, mod + (modlen - sizeof(ms)), sizeof(ms));
+       modlen -= sizeof(ms);
 
        sig_len = be32_to_cpu(ms.sig_len);
-       if (sig_len >= siglen ||
-           siglen - sig_len != (size_t)ms.signer_len + ms.key_id_len)
+       if (sig_len >= modlen)
                return -EBADMSG;
+       modlen -= sig_len;
+       if ((size_t)ms.signer_len + ms.key_id_len >= modlen)
+               return -EBADMSG;
+       modlen -= (size_t)ms.signer_len + ms.key_id_len;
+
+       *_modlen = modlen;
+       sig = mod + modlen;
 
        /* For the moment, only support RSA and X.509 identifiers */
        if (ms.algo != PKEY_ALGO_RSA ||
index 478bad2745e3a8357fcc2f9a56059d167bf67e49..eb00be205811959c708fe2bf5e3aee0547dcfa36 100644 (file)
@@ -133,19 +133,26 @@ struct pid_namespace *copy_pid_ns(unsigned long flags, struct pid_namespace *old
        return create_pid_namespace(old_ns);
 }
 
-void free_pid_ns(struct kref *kref)
+static void free_pid_ns(struct kref *kref)
 {
-       struct pid_namespace *ns, *parent;
+       struct pid_namespace *ns;
 
        ns = container_of(kref, struct pid_namespace, kref);
-
-       parent = ns->parent;
        destroy_pid_namespace(ns);
+}
 
-       if (parent != NULL)
-               put_pid_ns(parent);
+void put_pid_ns(struct pid_namespace *ns)
+{
+       struct pid_namespace *parent;
+
+       while (ns != &init_pid_ns) {
+               parent = ns->parent;
+               if (!kref_put(&ns->kref, free_pid_ns))
+                       break;
+               ns = parent;
+       }
 }
-EXPORT_SYMBOL_GPL(free_pid_ns);
+EXPORT_SYMBOL_GPL(put_pid_ns);
 
 void zap_pid_ns_processes(struct pid_namespace *pid_ns)
 {
index f458238109ccd32d195c39b02f1d0cc6efdc09c0..1c16f9167de15c4151be06ad54be69a7ed8faeb6 100644 (file)
@@ -59,7 +59,7 @@ static ssize_t pm_async_store(struct kobject *kobj, struct kobj_attribute *attr,
 {
        unsigned long val;
 
-       if (strict_strtoul(buf, 10, &val))
+       if (kstrtoul(buf, 10, &val))
                return -EINVAL;
 
        if (val > 1)
index 846bd42c7ed179673846817da8bb2e69078ce673..9322ff7eaad68d41512763d3b337d123601f32b7 100644 (file)
@@ -212,6 +212,69 @@ int pm_qos_update_target(struct pm_qos_constraints *c, struct plist_node *node,
        }
 }
 
+/**
+ * pm_qos_flags_remove_req - Remove device PM QoS flags request.
+ * @pqf: Device PM QoS flags set to remove the request from.
+ * @req: Request to remove from the set.
+ */
+static void pm_qos_flags_remove_req(struct pm_qos_flags *pqf,
+                                   struct pm_qos_flags_request *req)
+{
+       s32 val = 0;
+
+       list_del(&req->node);
+       list_for_each_entry(req, &pqf->list, node)
+               val |= req->flags;
+
+       pqf->effective_flags = val;
+}
+
+/**
+ * pm_qos_update_flags - Update a set of PM QoS flags.
+ * @pqf: Set of flags to update.
+ * @req: Request to add to the set, to modify, or to remove from the set.
+ * @action: Action to take on the set.
+ * @val: Value of the request to add or modify.
+ *
+ * Update the given set of PM QoS flags and call notifiers if the aggregate
+ * value has changed.  Returns 1 if the aggregate constraint value has changed,
+ * 0 otherwise.
+ */
+bool pm_qos_update_flags(struct pm_qos_flags *pqf,
+                        struct pm_qos_flags_request *req,
+                        enum pm_qos_req_action action, s32 val)
+{
+       unsigned long irqflags;
+       s32 prev_value, curr_value;
+
+       spin_lock_irqsave(&pm_qos_lock, irqflags);
+
+       prev_value = list_empty(&pqf->list) ? 0 : pqf->effective_flags;
+
+       switch (action) {
+       case PM_QOS_REMOVE_REQ:
+               pm_qos_flags_remove_req(pqf, req);
+               break;
+       case PM_QOS_UPDATE_REQ:
+               pm_qos_flags_remove_req(pqf, req);
+       case PM_QOS_ADD_REQ:
+               req->flags = val;
+               INIT_LIST_HEAD(&req->node);
+               list_add_tail(&req->node, &pqf->list);
+               pqf->effective_flags |= val;
+               break;
+       default:
+               /* no action */
+               ;
+       }
+
+       curr_value = list_empty(&pqf->list) ? 0 : pqf->effective_flags;
+
+       spin_unlock_irqrestore(&pm_qos_lock, irqflags);
+
+       return prev_value != curr_value;
+}
+
 /**
  * pm_qos_request - returns current system wide qos expectation
  * @pm_qos_class: identification of which qos value is requested
@@ -500,7 +563,7 @@ static ssize_t pm_qos_power_write(struct file *filp, const char __user *buf,
                } else {
                        ascii_value[count] = '\0';
                }
-               ret = strict_strtoul(ascii_value, 16, &ulval);
+               ret = kstrtoul(ascii_value, 16, &ulval);
                if (ret) {
                        pr_debug("%s, 0x%lx, 0x%x\n", ascii_value, ulval, ret);
                        return -EINVAL;
index 3c9d764eb0d8af7e2db7ec99888061a5a573b7ed..7c33ed200410843a97dc39f59da4080f270832e2 100644 (file)
@@ -126,7 +126,7 @@ static int swsusp_extents_insert(unsigned long swap_offset)
 
        /* Figure out where to put the new node */
        while (*new) {
-               ext = container_of(*new, struct swsusp_extent, node);
+               ext = rb_entry(*new, struct swsusp_extent, node);
                parent = *new;
                if (swap_offset < ext->start) {
                        /* Try to merge */
index 2d607f4d1797cb02e0e4fb60453312a8d3491975..22e070f3470a66569f12d917bcf9b655f4817d4d 100644 (file)
@@ -87,6 +87,12 @@ static DEFINE_SEMAPHORE(console_sem);
 struct console *console_drivers;
 EXPORT_SYMBOL_GPL(console_drivers);
 
+#ifdef CONFIG_LOCKDEP
+static struct lockdep_map console_lock_dep_map = {
+       .name = "console_lock"
+};
+#endif
+
 /*
  * This is used for debugging the mess that is the VT code by
  * keeping track if we have the console semaphore held. It's
@@ -1908,12 +1914,14 @@ static int __cpuinit console_cpu_notify(struct notifier_block *self,
  */
 void console_lock(void)
 {
-       BUG_ON(in_interrupt());
+       might_sleep();
+
        down(&console_sem);
        if (console_suspended)
                return;
        console_locked = 1;
        console_may_schedule = 1;
+       mutex_acquire(&console_lock_dep_map, 0, 0, _RET_IP_);
 }
 EXPORT_SYMBOL(console_lock);
 
@@ -1935,6 +1943,7 @@ int console_trylock(void)
        }
        console_locked = 1;
        console_may_schedule = 0;
+       mutex_acquire(&console_lock_dep_map, 0, 1, _RET_IP_);
        return 1;
 }
 EXPORT_SYMBOL(console_trylock);
@@ -2095,6 +2104,7 @@ skip:
                local_irq_restore(flags);
        }
        console_locked = 0;
+       mutex_release(&console_lock_dep_map, 1, _RET_IP_);
 
        /* Release the exclusive_console once it is used */
        if (unlikely(exclusive_console))
index 8ba99cdc651556305b5faf82d783e6475d14ec67..7ff057d7063d559274c415464f713f0abb33bfae 100644 (file)
@@ -109,4 +109,13 @@ static inline bool __rcu_reclaim(char *rn, struct rcu_head *head)
        }
 }
 
+extern int rcu_expedited;
+
+#if defined(CONFIG_SMP) || defined(CONFIG_RCU_TRACE)
+
+extern int rcu_cpu_stall_suppress;
+int rcu_jiffies_till_stall_check(void);
+
+#endif /* defined(CONFIG_SMP) || defined(CONFIG_RCU_TRACE) */
+
 #endif /* __LINUX_RCU_H */
index 29ca1c6da59496133947e5a1c3d1a860ef261e3e..06cec61be6f909fefe66c11cac925103b175785f 100644 (file)
 #include <linux/export.h>
 #include <linux/hardirq.h>
 #include <linux/delay.h>
+#include <linux/module.h>
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/rcu.h>
 
 #include "rcu.h"
 
+module_param(rcu_expedited, int, 0);
+
 #ifdef CONFIG_PREEMPT_RCU
 
 /*
@@ -409,3 +412,54 @@ EXPORT_SYMBOL_GPL(do_trace_rcu_torture_read);
 #else
 #define do_trace_rcu_torture_read(rcutorturename, rhp) do { } while (0)
 #endif
+
+#if defined(CONFIG_SMP) || defined(CONFIG_RCU_TRACE)
+
+#ifdef CONFIG_PROVE_RCU
+#define RCU_STALL_DELAY_DELTA         (5 * HZ)
+#else
+#define RCU_STALL_DELAY_DELTA         0
+#endif
+
+int rcu_cpu_stall_suppress __read_mostly; /* 1 = suppress stall warnings. */
+int rcu_cpu_stall_timeout __read_mostly = CONFIG_RCU_CPU_STALL_TIMEOUT;
+
+module_param(rcu_cpu_stall_suppress, int, 0644);
+module_param(rcu_cpu_stall_timeout, int, 0644);
+
+int rcu_jiffies_till_stall_check(void)
+{
+       int till_stall_check = ACCESS_ONCE(rcu_cpu_stall_timeout);
+
+       /*
+        * Limit check must be consistent with the Kconfig limits
+        * for CONFIG_RCU_CPU_STALL_TIMEOUT.
+        */
+       if (till_stall_check < 3) {
+               ACCESS_ONCE(rcu_cpu_stall_timeout) = 3;
+               till_stall_check = 3;
+       } else if (till_stall_check > 300) {
+               ACCESS_ONCE(rcu_cpu_stall_timeout) = 300;
+               till_stall_check = 300;
+       }
+       return till_stall_check * HZ + RCU_STALL_DELAY_DELTA;
+}
+
+static int rcu_panic(struct notifier_block *this, unsigned long ev, void *ptr)
+{
+       rcu_cpu_stall_suppress = 1;
+       return NOTIFY_DONE;
+}
+
+static struct notifier_block rcu_panic_block = {
+       .notifier_call = rcu_panic,
+};
+
+static int __init check_cpu_stall_init(void)
+{
+       atomic_notifier_chain_register(&panic_notifier_list, &rcu_panic_block);
+       return 0;
+}
+early_initcall(check_cpu_stall_init);
+
+#endif /* defined(CONFIG_SMP) || defined(CONFIG_RCU_TRACE) */
index e4c6a598d6f749c9b5e322c372b953aea29c7b84..386e776e2a2506823dec01aa969a40a55ea5ec0d 100644 (file)
@@ -51,10 +51,10 @@ static void __call_rcu(struct rcu_head *head,
                       void (*func)(struct rcu_head *rcu),
                       struct rcu_ctrlblk *rcp);
 
-#include "rcutiny_plugin.h"
-
 static long long rcu_dynticks_nesting = DYNTICK_TASK_EXIT_IDLE;
 
+#include "rcutiny_plugin.h"
+
 /* Common code for rcu_idle_enter() and rcu_irq_exit(), see kernel/rcutree.c. */
 static void rcu_idle_enter_common(long long newval)
 {
@@ -205,6 +205,7 @@ int rcu_is_cpu_rrupt_from_idle(void)
  */
 static int rcu_qsctr_help(struct rcu_ctrlblk *rcp)
 {
+       reset_cpu_stall_ticks(rcp);
        if (rcp->rcucblist != NULL &&
            rcp->donetail != rcp->curtail) {
                rcp->donetail = rcp->curtail;
@@ -251,6 +252,7 @@ void rcu_bh_qs(int cpu)
  */
 void rcu_check_callbacks(int cpu, int user)
 {
+       check_cpu_stalls();
        if (user || rcu_is_cpu_rrupt_from_idle())
                rcu_sched_qs(cpu);
        else if (!in_softirq())
index 3d0190282204308005f1867abe6d53125787e1b0..7b0ab308a2d98b98b72d87570925d8fce99c8b6b 100644 (file)
@@ -33,6 +33,9 @@ struct rcu_ctrlblk {
        struct rcu_head **donetail;     /* ->next pointer of last "done" CB. */
        struct rcu_head **curtail;      /* ->next pointer of last CB. */
        RCU_TRACE(long qlen);           /* Number of pending CBs. */
+       RCU_TRACE(unsigned long gp_start); /* Start time for stalls. */
+       RCU_TRACE(unsigned long ticks_this_gp); /* Statistic for stalls. */
+       RCU_TRACE(unsigned long jiffies_stall); /* Jiffies at next stall. */
        RCU_TRACE(char *name);          /* Name of RCU type. */
 };
 
@@ -54,6 +57,51 @@ int rcu_scheduler_active __read_mostly;
 EXPORT_SYMBOL_GPL(rcu_scheduler_active);
 #endif /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */
 
+#ifdef CONFIG_RCU_TRACE
+
+static void check_cpu_stall(struct rcu_ctrlblk *rcp)
+{
+       unsigned long j;
+       unsigned long js;
+
+       if (rcu_cpu_stall_suppress)
+               return;
+       rcp->ticks_this_gp++;
+       j = jiffies;
+       js = rcp->jiffies_stall;
+       if (*rcp->curtail && ULONG_CMP_GE(j, js)) {
+               printk(KERN_ERR "INFO: %s stall on CPU (%lu ticks this GP) idle=%llx (t=%lu jiffies q=%ld)\n",
+                      rcp->name, rcp->ticks_this_gp, rcu_dynticks_nesting,
+                      jiffies - rcp->gp_start, rcp->qlen);
+               dump_stack();
+       }
+       if (*rcp->curtail && ULONG_CMP_GE(j, js))
+               rcp->jiffies_stall = jiffies +
+                       3 * rcu_jiffies_till_stall_check() + 3;
+       else if (ULONG_CMP_GE(j, js))
+               rcp->jiffies_stall = jiffies + rcu_jiffies_till_stall_check();
+}
+
+static void check_cpu_stall_preempt(void);
+
+#endif /* #ifdef CONFIG_RCU_TRACE */
+
+static void reset_cpu_stall_ticks(struct rcu_ctrlblk *rcp)
+{
+#ifdef CONFIG_RCU_TRACE
+       rcp->ticks_this_gp = 0;
+       rcp->gp_start = jiffies;
+       rcp->jiffies_stall = jiffies + rcu_jiffies_till_stall_check();
+#endif /* #ifdef CONFIG_RCU_TRACE */
+}
+
+static void check_cpu_stalls(void)
+{
+       RCU_TRACE(check_cpu_stall(&rcu_bh_ctrlblk));
+       RCU_TRACE(check_cpu_stall(&rcu_sched_ctrlblk));
+       RCU_TRACE(check_cpu_stall_preempt());
+}
+
 #ifdef CONFIG_TINY_PREEMPT_RCU
 
 #include <linux/delay.h>
@@ -448,6 +496,7 @@ static void rcu_preempt_start_gp(void)
                /* Official start of GP. */
                rcu_preempt_ctrlblk.gpnum++;
                RCU_TRACE(rcu_preempt_ctrlblk.n_grace_periods++);
+               reset_cpu_stall_ticks(&rcu_preempt_ctrlblk.rcb);
 
                /* Any blocked RCU readers block new GP. */
                if (rcu_preempt_blocked_readers_any())
@@ -706,7 +755,10 @@ void synchronize_rcu(void)
                return;
 
        /* Once we get past the fastpath checks, same code as rcu_barrier(). */
-       rcu_barrier();
+       if (rcu_expedited)
+               synchronize_rcu_expedited();
+       else
+               rcu_barrier();
 }
 EXPORT_SYMBOL_GPL(synchronize_rcu);
 
@@ -1051,4 +1103,11 @@ MODULE_AUTHOR("Paul E. McKenney");
 MODULE_DESCRIPTION("Read-Copy Update tracing for tiny implementation");
 MODULE_LICENSE("GPL");
 
+static void check_cpu_stall_preempt(void)
+{
+#ifdef CONFIG_TINY_PREEMPT_RCU
+       check_cpu_stall(&rcu_preempt_ctrlblk.rcb);
+#endif /* #ifdef CONFIG_TINY_PREEMPT_RCU */
+}
+
 #endif /* #ifdef CONFIG_RCU_TRACE */
index aaa7b9f3532a86c87580fa6202a20df8c9dcd249..31dea01c85fd50fb3297627dc81556a146f249c5 100644 (file)
@@ -339,7 +339,6 @@ rcu_stutter_wait(char *title)
 
 struct rcu_torture_ops {
        void (*init)(void);
-       void (*cleanup)(void);
        int (*readlock)(void);
        void (*read_delay)(struct rcu_random_state *rrsp);
        void (*readunlock)(int idx);
@@ -431,7 +430,6 @@ static void rcu_torture_deferred_free(struct rcu_torture *p)
 
 static struct rcu_torture_ops rcu_ops = {
        .init           = NULL,
-       .cleanup        = NULL,
        .readlock       = rcu_torture_read_lock,
        .read_delay     = rcu_read_delay,
        .readunlock     = rcu_torture_read_unlock,
@@ -475,7 +473,6 @@ static void rcu_sync_torture_init(void)
 
 static struct rcu_torture_ops rcu_sync_ops = {
        .init           = rcu_sync_torture_init,
-       .cleanup        = NULL,
        .readlock       = rcu_torture_read_lock,
        .read_delay     = rcu_read_delay,
        .readunlock     = rcu_torture_read_unlock,
@@ -493,7 +490,6 @@ static struct rcu_torture_ops rcu_sync_ops = {
 
 static struct rcu_torture_ops rcu_expedited_ops = {
        .init           = rcu_sync_torture_init,
-       .cleanup        = NULL,
        .readlock       = rcu_torture_read_lock,
        .read_delay     = rcu_read_delay,  /* just reuse rcu's version. */
        .readunlock     = rcu_torture_read_unlock,
@@ -536,7 +532,6 @@ static void rcu_bh_torture_deferred_free(struct rcu_torture *p)
 
 static struct rcu_torture_ops rcu_bh_ops = {
        .init           = NULL,
-       .cleanup        = NULL,
        .readlock       = rcu_bh_torture_read_lock,
        .read_delay     = rcu_read_delay,  /* just reuse rcu's version. */
        .readunlock     = rcu_bh_torture_read_unlock,
@@ -553,7 +548,6 @@ static struct rcu_torture_ops rcu_bh_ops = {
 
 static struct rcu_torture_ops rcu_bh_sync_ops = {
        .init           = rcu_sync_torture_init,
-       .cleanup        = NULL,
        .readlock       = rcu_bh_torture_read_lock,
        .read_delay     = rcu_read_delay,  /* just reuse rcu's version. */
        .readunlock     = rcu_bh_torture_read_unlock,
@@ -570,7 +564,6 @@ static struct rcu_torture_ops rcu_bh_sync_ops = {
 
 static struct rcu_torture_ops rcu_bh_expedited_ops = {
        .init           = rcu_sync_torture_init,
-       .cleanup        = NULL,
        .readlock       = rcu_bh_torture_read_lock,
        .read_delay     = rcu_read_delay,  /* just reuse rcu's version. */
        .readunlock     = rcu_bh_torture_read_unlock,
@@ -589,19 +582,7 @@ static struct rcu_torture_ops rcu_bh_expedited_ops = {
  * Definitions for srcu torture testing.
  */
 
-static struct srcu_struct srcu_ctl;
-
-static void srcu_torture_init(void)
-{
-       init_srcu_struct(&srcu_ctl);
-       rcu_sync_torture_init();
-}
-
-static void srcu_torture_cleanup(void)
-{
-       synchronize_srcu(&srcu_ctl);
-       cleanup_srcu_struct(&srcu_ctl);
-}
+DEFINE_STATIC_SRCU(srcu_ctl);
 
 static int srcu_torture_read_lock(void) __acquires(&srcu_ctl)
 {
@@ -672,8 +653,7 @@ static int srcu_torture_stats(char *page)
 }
 
 static struct rcu_torture_ops srcu_ops = {
-       .init           = srcu_torture_init,
-       .cleanup        = srcu_torture_cleanup,
+       .init           = rcu_sync_torture_init,
        .readlock       = srcu_torture_read_lock,
        .read_delay     = srcu_read_delay,
        .readunlock     = srcu_torture_read_unlock,
@@ -687,8 +667,7 @@ static struct rcu_torture_ops srcu_ops = {
 };
 
 static struct rcu_torture_ops srcu_sync_ops = {
-       .init           = srcu_torture_init,
-       .cleanup        = srcu_torture_cleanup,
+       .init           = rcu_sync_torture_init,
        .readlock       = srcu_torture_read_lock,
        .read_delay     = srcu_read_delay,
        .readunlock     = srcu_torture_read_unlock,
@@ -712,8 +691,7 @@ static void srcu_torture_read_unlock_raw(int idx) __releases(&srcu_ctl)
 }
 
 static struct rcu_torture_ops srcu_raw_ops = {
-       .init           = srcu_torture_init,
-       .cleanup        = srcu_torture_cleanup,
+       .init           = rcu_sync_torture_init,
        .readlock       = srcu_torture_read_lock_raw,
        .read_delay     = srcu_read_delay,
        .readunlock     = srcu_torture_read_unlock_raw,
@@ -727,8 +705,7 @@ static struct rcu_torture_ops srcu_raw_ops = {
 };
 
 static struct rcu_torture_ops srcu_raw_sync_ops = {
-       .init           = srcu_torture_init,
-       .cleanup        = srcu_torture_cleanup,
+       .init           = rcu_sync_torture_init,
        .readlock       = srcu_torture_read_lock_raw,
        .read_delay     = srcu_read_delay,
        .readunlock     = srcu_torture_read_unlock_raw,
@@ -747,8 +724,7 @@ static void srcu_torture_synchronize_expedited(void)
 }
 
 static struct rcu_torture_ops srcu_expedited_ops = {
-       .init           = srcu_torture_init,
-       .cleanup        = srcu_torture_cleanup,
+       .init           = rcu_sync_torture_init,
        .readlock       = srcu_torture_read_lock,
        .read_delay     = srcu_read_delay,
        .readunlock     = srcu_torture_read_unlock,
@@ -783,7 +759,6 @@ static void rcu_sched_torture_deferred_free(struct rcu_torture *p)
 
 static struct rcu_torture_ops sched_ops = {
        .init           = rcu_sync_torture_init,
-       .cleanup        = NULL,
        .readlock       = sched_torture_read_lock,
        .read_delay     = rcu_read_delay,  /* just reuse rcu's version. */
        .readunlock     = sched_torture_read_unlock,
@@ -799,7 +774,6 @@ static struct rcu_torture_ops sched_ops = {
 
 static struct rcu_torture_ops sched_sync_ops = {
        .init           = rcu_sync_torture_init,
-       .cleanup        = NULL,
        .readlock       = sched_torture_read_lock,
        .read_delay     = rcu_read_delay,  /* just reuse rcu's version. */
        .readunlock     = sched_torture_read_unlock,
@@ -814,7 +788,6 @@ static struct rcu_torture_ops sched_sync_ops = {
 
 static struct rcu_torture_ops sched_expedited_ops = {
        .init           = rcu_sync_torture_init,
-       .cleanup        = NULL,
        .readlock       = sched_torture_read_lock,
        .read_delay     = rcu_read_delay,  /* just reuse rcu's version. */
        .readunlock     = sched_torture_read_unlock,
@@ -1396,12 +1369,16 @@ rcu_torture_print_module_parms(struct rcu_torture_ops *cur_ops, char *tag)
                 "fqs_duration=%d fqs_holdoff=%d fqs_stutter=%d "
                 "test_boost=%d/%d test_boost_interval=%d "
                 "test_boost_duration=%d shutdown_secs=%d "
+                "stall_cpu=%d stall_cpu_holdoff=%d "
+                "n_barrier_cbs=%d "
                 "onoff_interval=%d onoff_holdoff=%d\n",
                 torture_type, tag, nrealreaders, nfakewriters,
                 stat_interval, verbose, test_no_idle_hz, shuffle_interval,
                 stutter, irqreader, fqs_duration, fqs_holdoff, fqs_stutter,
                 test_boost, cur_ops->can_boost,
                 test_boost_interval, test_boost_duration, shutdown_secs,
+                stall_cpu, stall_cpu_holdoff,
+                n_barrier_cbs,
                 onoff_interval, onoff_holdoff);
 }
 
@@ -1502,6 +1479,7 @@ rcu_torture_onoff(void *arg)
        unsigned long delta;
        int maxcpu = -1;
        DEFINE_RCU_RANDOM(rand);
+       int ret;
        unsigned long starttime;
 
        VERBOSE_PRINTK_STRING("rcu_torture_onoff task started");
@@ -1522,7 +1500,13 @@ rcu_torture_onoff(void *arg)
                                         torture_type, cpu);
                        starttime = jiffies;
                        n_offline_attempts++;
-                       if (cpu_down(cpu) == 0) {
+                       ret = cpu_down(cpu);
+                       if (ret) {
+                               if (verbose)
+                                       pr_alert("%s" TORTURE_FLAG
+                                                "rcu_torture_onoff task: offline %d failed: errno %d\n",
+                                                torture_type, cpu, ret);
+                       } else {
                                if (verbose)
                                        pr_alert("%s" TORTURE_FLAG
                                                 "rcu_torture_onoff task: offlined %d\n",
@@ -1936,8 +1920,6 @@ rcu_torture_cleanup(void)
 
        rcu_torture_stats_print();  /* -After- the stats thread is stopped! */
 
-       if (cur_ops->cleanup)
-               cur_ops->cleanup();
        if (atomic_read(&n_rcu_torture_error) || n_rcu_torture_barrier_error)
                rcu_torture_print_module_parms(cur_ops, "End of test: FAILURE");
        else if (n_online_successes != n_online_attempts ||
index 74df86bd9204aef5ec9d14ca8b4b0094777bef87..45093733d776211b67d9a4dabaddbd548cc56081 100644 (file)
@@ -68,9 +68,9 @@ static struct lock_class_key rcu_fqs_class[RCU_NUM_LVLS];
        .level = { &sname##_state.node[0] }, \
        .call = cr, \
        .fqs_state = RCU_GP_IDLE, \
-       .gpnum = -300, \
-       .completed = -300, \
-       .onofflock = __RAW_SPIN_LOCK_UNLOCKED(&sname##_state.onofflock), \
+       .gpnum = 0UL - 300UL, \
+       .completed = 0UL - 300UL, \
+       .orphan_lock = __RAW_SPIN_LOCK_UNLOCKED(&sname##_state.orphan_lock), \
        .orphan_nxttail = &sname##_state.orphan_nxtlist, \
        .orphan_donetail = &sname##_state.orphan_donelist, \
        .barrier_mutex = __MUTEX_INITIALIZER(sname##_state.barrier_mutex), \
@@ -212,19 +212,13 @@ DEFINE_PER_CPU(struct rcu_dynticks, rcu_dynticks) = {
 #endif
 };
 
-static int blimit = 10;                /* Maximum callbacks per rcu_do_batch. */
-static int qhimark = 10000;    /* If this many pending, ignore blimit. */
-static int qlowmark = 100;     /* Once only this many pending, use blimit. */
+static long blimit = 10;       /* Maximum callbacks per rcu_do_batch. */
+static long qhimark = 10000;   /* If this many pending, ignore blimit. */
+static long qlowmark = 100;    /* Once only this many pending, use blimit. */
 
-module_param(blimit, int, 0444);
-module_param(qhimark, int, 0444);
-module_param(qlowmark, int, 0444);
-
-int rcu_cpu_stall_suppress __read_mostly; /* 1 = suppress stall warnings. */
-int rcu_cpu_stall_timeout __read_mostly = CONFIG_RCU_CPU_STALL_TIMEOUT;
-
-module_param(rcu_cpu_stall_suppress, int, 0644);
-module_param(rcu_cpu_stall_timeout, int, 0644);
+module_param(blimit, long, 0444);
+module_param(qhimark, long, 0444);
+module_param(qlowmark, long, 0444);
 
 static ulong jiffies_till_first_fqs = RCU_JIFFIES_TILL_FORCE_QS;
 static ulong jiffies_till_next_fqs = RCU_JIFFIES_TILL_FORCE_QS;
@@ -313,7 +307,7 @@ static int
 cpu_needs_another_gp(struct rcu_state *rsp, struct rcu_data *rdp)
 {
        return *rdp->nxttail[RCU_DONE_TAIL +
-                            ACCESS_ONCE(rsp->completed) != rdp->completed] &&
+                            (ACCESS_ONCE(rsp->completed) != rdp->completed)] &&
               !rcu_gp_in_progress(rsp);
 }
 
@@ -849,28 +843,33 @@ static int rcu_implicit_dynticks_qs(struct rcu_data *rdp)
        return 0;
 }
 
-static int jiffies_till_stall_check(void)
+static void record_gp_stall_check_time(struct rcu_state *rsp)
 {
-       int till_stall_check = ACCESS_ONCE(rcu_cpu_stall_timeout);
-
-       /*
-        * Limit check must be consistent with the Kconfig limits
-        * for CONFIG_RCU_CPU_STALL_TIMEOUT.
-        */
-       if (till_stall_check < 3) {
-               ACCESS_ONCE(rcu_cpu_stall_timeout) = 3;
-               till_stall_check = 3;
-       } else if (till_stall_check > 300) {
-               ACCESS_ONCE(rcu_cpu_stall_timeout) = 300;
-               till_stall_check = 300;
-       }
-       return till_stall_check * HZ + RCU_STALL_DELAY_DELTA;
+       rsp->gp_start = jiffies;
+       rsp->jiffies_stall = jiffies + rcu_jiffies_till_stall_check();
 }
 
-static void record_gp_stall_check_time(struct rcu_state *rsp)
+/*
+ * Dump stacks of all tasks running on stalled CPUs.  This is a fallback
+ * for architectures that do not implement trigger_all_cpu_backtrace().
+ * The NMI-triggered stack traces are more accurate because they are
+ * printed by the target CPU.
+ */
+static void rcu_dump_cpu_stacks(struct rcu_state *rsp)
 {
-       rsp->gp_start = jiffies;
-       rsp->jiffies_stall = jiffies + jiffies_till_stall_check();
+       int cpu;
+       unsigned long flags;
+       struct rcu_node *rnp;
+
+       rcu_for_each_leaf_node(rsp, rnp) {
+               raw_spin_lock_irqsave(&rnp->lock, flags);
+               if (rnp->qsmask != 0) {
+                       for (cpu = 0; cpu <= rnp->grphi - rnp->grplo; cpu++)
+                               if (rnp->qsmask & (1UL << cpu))
+                                       dump_cpu_task(rnp->grplo + cpu);
+               }
+               raw_spin_unlock_irqrestore(&rnp->lock, flags);
+       }
 }
 
 static void print_other_cpu_stall(struct rcu_state *rsp)
@@ -880,6 +879,7 @@ static void print_other_cpu_stall(struct rcu_state *rsp)
        unsigned long flags;
        int ndetected = 0;
        struct rcu_node *rnp = rcu_get_root(rsp);
+       long totqlen = 0;
 
        /* Only let one CPU complain about others per time interval. */
 
@@ -889,7 +889,7 @@ static void print_other_cpu_stall(struct rcu_state *rsp)
                raw_spin_unlock_irqrestore(&rnp->lock, flags);
                return;
        }
-       rsp->jiffies_stall = jiffies + 3 * jiffies_till_stall_check() + 3;
+       rsp->jiffies_stall = jiffies + 3 * rcu_jiffies_till_stall_check() + 3;
        raw_spin_unlock_irqrestore(&rnp->lock, flags);
 
        /*
@@ -924,12 +924,15 @@ static void print_other_cpu_stall(struct rcu_state *rsp)
        raw_spin_unlock_irqrestore(&rnp->lock, flags);
 
        print_cpu_stall_info_end();
-       printk(KERN_CONT "(detected by %d, t=%ld jiffies)\n",
-              smp_processor_id(), (long)(jiffies - rsp->gp_start));
+       for_each_possible_cpu(cpu)
+               totqlen += per_cpu_ptr(rsp->rda, cpu)->qlen;
+       pr_cont("(detected by %d, t=%ld jiffies, g=%lu, c=%lu, q=%lu)\n",
+              smp_processor_id(), (long)(jiffies - rsp->gp_start),
+              rsp->gpnum, rsp->completed, totqlen);
        if (ndetected == 0)
                printk(KERN_ERR "INFO: Stall ended before state dump start\n");
        else if (!trigger_all_cpu_backtrace())
-               dump_stack();
+               rcu_dump_cpu_stacks(rsp);
 
        /* Complain about tasks blocking the grace period. */
 
@@ -940,8 +943,10 @@ static void print_other_cpu_stall(struct rcu_state *rsp)
 
 static void print_cpu_stall(struct rcu_state *rsp)
 {
+       int cpu;
        unsigned long flags;
        struct rcu_node *rnp = rcu_get_root(rsp);
+       long totqlen = 0;
 
        /*
         * OK, time to rat on ourselves...
@@ -952,14 +957,17 @@ static void print_cpu_stall(struct rcu_state *rsp)
        print_cpu_stall_info_begin();
        print_cpu_stall_info(rsp, smp_processor_id());
        print_cpu_stall_info_end();
-       printk(KERN_CONT " (t=%lu jiffies)\n", jiffies - rsp->gp_start);
+       for_each_possible_cpu(cpu)
+               totqlen += per_cpu_ptr(rsp->rda, cpu)->qlen;
+       pr_cont(" (t=%lu jiffies g=%lu c=%lu q=%lu)\n",
+               jiffies - rsp->gp_start, rsp->gpnum, rsp->completed, totqlen);
        if (!trigger_all_cpu_backtrace())
                dump_stack();
 
        raw_spin_lock_irqsave(&rnp->lock, flags);
        if (ULONG_CMP_GE(jiffies, rsp->jiffies_stall))
                rsp->jiffies_stall = jiffies +
-                                    3 * jiffies_till_stall_check() + 3;
+                                    3 * rcu_jiffies_till_stall_check() + 3;
        raw_spin_unlock_irqrestore(&rnp->lock, flags);
 
        set_need_resched();  /* kick ourselves to get things going. */
@@ -990,12 +998,6 @@ static void check_cpu_stall(struct rcu_state *rsp, struct rcu_data *rdp)
        }
 }
 
-static int rcu_panic(struct notifier_block *this, unsigned long ev, void *ptr)
-{
-       rcu_cpu_stall_suppress = 1;
-       return NOTIFY_DONE;
-}
-
 /**
  * rcu_cpu_stall_reset - prevent further stall warnings in current grace period
  *
@@ -1013,15 +1015,6 @@ void rcu_cpu_stall_reset(void)
                rsp->jiffies_stall = jiffies + ULONG_MAX / 2;
 }
 
-static struct notifier_block rcu_panic_block = {
-       .notifier_call = rcu_panic,
-};
-
-static void __init check_cpu_stall_init(void)
-{
-       atomic_notifier_chain_register(&panic_notifier_list, &rcu_panic_block);
-}
-
 /*
  * Update CPU-local rcu_data state to record the newly noticed grace period.
  * This is used both when we started the grace period and when we notice
@@ -1404,15 +1397,37 @@ rcu_start_gp(struct rcu_state *rsp, unsigned long flags)
            !cpu_needs_another_gp(rsp, rdp)) {
                /*
                 * Either we have not yet spawned the grace-period
-                * task or this CPU does not need another grace period.
+                * task, this CPU does not need another grace period,
+                * or a grace period is already in progress.
                 * Either way, don't start a new grace period.
                 */
                raw_spin_unlock_irqrestore(&rnp->lock, flags);
                return;
        }
 
+       /*
+        * Because there is no grace period in progress right now,
+        * any callbacks we have up to this point will be satisfied
+        * by the next grace period.  So promote all callbacks to be
+        * handled after the end of the next grace period.  If the
+        * CPU is not yet aware of the end of the previous grace period,
+        * we need to allow for the callback advancement that will
+        * occur when it does become aware.  Deadlock prevents us from
+        * making it aware at this point: We cannot acquire a leaf
+        * rcu_node ->lock while holding the root rcu_node ->lock.
+        */
+       rdp->nxttail[RCU_NEXT_READY_TAIL] = rdp->nxttail[RCU_NEXT_TAIL];
+       if (rdp->completed == rsp->completed)
+               rdp->nxttail[RCU_WAIT_TAIL] = rdp->nxttail[RCU_NEXT_TAIL];
+
        rsp->gp_flags = RCU_GP_FLAG_INIT;
-       raw_spin_unlock_irqrestore(&rnp->lock, flags);
+       raw_spin_unlock(&rnp->lock); /* Interrupts remain disabled. */
+
+       /* Ensure that CPU is aware of completion of last grace period. */
+       rcu_process_gp_end(rsp, rdp);
+       local_irq_restore(flags);
+
+       /* Wake up rcu_gp_kthread() to start the grace period. */
        wake_up(&rsp->gp_wq);
 }
 
@@ -1573,7 +1588,7 @@ rcu_check_quiescent_state(struct rcu_state *rsp, struct rcu_data *rdp)
 /*
  * Send the specified CPU's RCU callbacks to the orphanage.  The
  * specified CPU must be offline, and the caller must hold the
- * ->onofflock.
+ * ->orphan_lock.
  */
 static void
 rcu_send_cbs_to_orphanage(int cpu, struct rcu_state *rsp,
@@ -1581,8 +1596,8 @@ rcu_send_cbs_to_orphanage(int cpu, struct rcu_state *rsp,
 {
        /*
         * Orphan the callbacks.  First adjust the counts.  This is safe
-        * because ->onofflock excludes _rcu_barrier()'s adoption of
-        * the callbacks, thus no memory barrier is required.
+        * because _rcu_barrier() excludes CPU-hotplug operations, so it
+        * cannot be running now.  Thus no memory barrier is required.
         */
        if (rdp->nxtlist != NULL) {
                rsp->qlen_lazy += rdp->qlen_lazy;
@@ -1623,7 +1638,7 @@ rcu_send_cbs_to_orphanage(int cpu, struct rcu_state *rsp,
 
 /*
  * Adopt the RCU callbacks from the specified rcu_state structure's
- * orphanage.  The caller must hold the ->onofflock.
+ * orphanage.  The caller must hold the ->orphan_lock.
  */
 static void rcu_adopt_orphan_cbs(struct rcu_state *rsp)
 {
@@ -1702,7 +1717,7 @@ static void rcu_cleanup_dead_cpu(int cpu, struct rcu_state *rsp)
 
        /* Exclude any attempts to start a new grace period. */
        mutex_lock(&rsp->onoff_mutex);
-       raw_spin_lock_irqsave(&rsp->onofflock, flags);
+       raw_spin_lock_irqsave(&rsp->orphan_lock, flags);
 
        /* Orphan the dead CPU's callbacks, and adopt them if appropriate. */
        rcu_send_cbs_to_orphanage(cpu, rsp, rnp, rdp);
@@ -1729,10 +1744,10 @@ static void rcu_cleanup_dead_cpu(int cpu, struct rcu_state *rsp)
        /*
         * We still hold the leaf rcu_node structure lock here, and
         * irqs are still disabled.  The reason for this subterfuge is
-        * because invoking rcu_report_unblock_qs_rnp() with ->onofflock
+        * because invoking rcu_report_unblock_qs_rnp() with ->orphan_lock
         * held leads to deadlock.
         */
-       raw_spin_unlock(&rsp->onofflock); /* irqs remain disabled. */
+       raw_spin_unlock(&rsp->orphan_lock); /* irqs remain disabled. */
        rnp = rdp->mynode;
        if (need_report & RCU_OFL_TASKS_NORM_GP)
                rcu_report_unblock_qs_rnp(rnp, flags);
@@ -1769,7 +1784,8 @@ static void rcu_do_batch(struct rcu_state *rsp, struct rcu_data *rdp)
 {
        unsigned long flags;
        struct rcu_head *next, *list, **tail;
-       int bl, count, count_lazy, i;
+       long bl, count, count_lazy;
+       int i;
 
        /* If no callbacks are ready, just return.*/
        if (!cpu_has_callbacks_ready_to_invoke(rdp)) {
@@ -2210,6 +2226,19 @@ static inline int rcu_blocking_is_gp(void)
  * softirq handlers will have completed, since in some kernels, these
  * handlers can run in process context, and can block.
  *
+ * Note that this guarantee implies a further memory-ordering guarantee.
+ * On systems with more than one CPU, when synchronize_sched() returns,
+ * each CPU is guaranteed to have executed a full memory barrier since
+ * the end of its last RCU-sched read-side critical section whose beginning
+ * preceded the call to synchronize_sched().  Note that this guarantee
+ * includes CPUs that are offline, idle, or executing in user mode, as
+ * well as CPUs that are executing in the kernel.  Furthermore, if CPU A
+ * invoked synchronize_sched(), which returned to its caller on CPU B,
+ * then both CPU A and CPU B are guaranteed to have executed a full memory
+ * barrier during the execution of synchronize_sched() -- even if CPU A
+ * and CPU B are the same CPU (but again only if the system has more than
+ * one CPU).
+ *
  * This primitive provides the guarantees made by the (now removed)
  * synchronize_kernel() API.  In contrast, synchronize_rcu() only
  * guarantees that rcu_read_lock() sections will have completed.
@@ -2224,7 +2253,10 @@ void synchronize_sched(void)
                           "Illegal synchronize_sched() in RCU-sched read-side critical section");
        if (rcu_blocking_is_gp())
                return;
-       wait_rcu_gp(call_rcu_sched);
+       if (rcu_expedited)
+               synchronize_sched_expedited();
+       else
+               wait_rcu_gp(call_rcu_sched);
 }
 EXPORT_SYMBOL_GPL(synchronize_sched);
 
@@ -2236,6 +2268,9 @@ EXPORT_SYMBOL_GPL(synchronize_sched);
  * read-side critical sections have completed.  RCU read-side critical
  * sections are delimited by rcu_read_lock_bh() and rcu_read_unlock_bh(),
  * and may be nested.
+ *
+ * See the description of synchronize_sched() for more detailed information
+ * on memory ordering guarantees.
  */
 void synchronize_rcu_bh(void)
 {
@@ -2245,13 +2280,13 @@ void synchronize_rcu_bh(void)
                           "Illegal synchronize_rcu_bh() in RCU-bh read-side critical section");
        if (rcu_blocking_is_gp())
                return;
-       wait_rcu_gp(call_rcu_bh);
+       if (rcu_expedited)
+               synchronize_rcu_bh_expedited();
+       else
+               wait_rcu_gp(call_rcu_bh);
 }
 EXPORT_SYMBOL_GPL(synchronize_rcu_bh);
 
-static atomic_t sync_sched_expedited_started = ATOMIC_INIT(0);
-static atomic_t sync_sched_expedited_done = ATOMIC_INIT(0);
-
 static int synchronize_sched_expedited_cpu_stop(void *data)
 {
        /*
@@ -2308,10 +2343,32 @@ static int synchronize_sched_expedited_cpu_stop(void *data)
  */
 void synchronize_sched_expedited(void)
 {
-       int firstsnap, s, snap, trycount = 0;
+       long firstsnap, s, snap;
+       int trycount = 0;
+       struct rcu_state *rsp = &rcu_sched_state;
+
+       /*
+        * If we are in danger of counter wrap, just do synchronize_sched().
+        * By allowing sync_sched_expedited_started to advance no more than
+        * ULONG_MAX/8 ahead of sync_sched_expedited_done, we are ensuring
+        * that more than 3.5 billion CPUs would be required to force a
+        * counter wrap on a 32-bit system.  Quite a few more CPUs would of
+        * course be required on a 64-bit system.
+        */
+       if (ULONG_CMP_GE((ulong)atomic_long_read(&rsp->expedited_start),
+                        (ulong)atomic_long_read(&rsp->expedited_done) +
+                        ULONG_MAX / 8)) {
+               synchronize_sched();
+               atomic_long_inc(&rsp->expedited_wrap);
+               return;
+       }
 
-       /* Note that atomic_inc_return() implies full memory barrier. */
-       firstsnap = snap = atomic_inc_return(&sync_sched_expedited_started);
+       /*
+        * Take a ticket.  Note that atomic_inc_return() implies a
+        * full memory barrier.
+        */
+       snap = atomic_long_inc_return(&rsp->expedited_start);
+       firstsnap = snap;
        get_online_cpus();
        WARN_ON_ONCE(cpu_is_offline(raw_smp_processor_id()));
 
@@ -2323,48 +2380,65 @@ void synchronize_sched_expedited(void)
                             synchronize_sched_expedited_cpu_stop,
                             NULL) == -EAGAIN) {
                put_online_cpus();
+               atomic_long_inc(&rsp->expedited_tryfail);
+
+               /* Check to see if someone else did our work for us. */
+               s = atomic_long_read(&rsp->expedited_done);
+               if (ULONG_CMP_GE((ulong)s, (ulong)firstsnap)) {
+                       /* ensure test happens before caller kfree */
+                       smp_mb__before_atomic_inc(); /* ^^^ */
+                       atomic_long_inc(&rsp->expedited_workdone1);
+                       return;
+               }
 
                /* No joy, try again later.  Or just synchronize_sched(). */
                if (trycount++ < 10) {
                        udelay(trycount * num_online_cpus());
                } else {
-                       synchronize_sched();
+                       wait_rcu_gp(call_rcu_sched);
+                       atomic_long_inc(&rsp->expedited_normal);
                        return;
                }
 
-               /* Check to see if someone else did our work for us. */
-               s = atomic_read(&sync_sched_expedited_done);
-               if (UINT_CMP_GE((unsigned)s, (unsigned)firstsnap)) {
-                       smp_mb(); /* ensure test happens before caller kfree */
+               /* Recheck to see if someone else did our work for us. */
+               s = atomic_long_read(&rsp->expedited_done);
+               if (ULONG_CMP_GE((ulong)s, (ulong)firstsnap)) {
+                       /* ensure test happens before caller kfree */
+                       smp_mb__before_atomic_inc(); /* ^^^ */
+                       atomic_long_inc(&rsp->expedited_workdone2);
                        return;
                }
 
                /*
                 * Refetching sync_sched_expedited_started allows later
-                * callers to piggyback on our grace period.  We subtract
-                * 1 to get the same token that the last incrementer got.
-                * We retry after they started, so our grace period works
-                * for them, and they started after our first try, so their
-                * grace period works for us.
+                * callers to piggyback on our grace period.  We retry
+                * after they started, so our grace period works for them,
+                * and they started after our first try, so their grace
+                * period works for us.
                 */
                get_online_cpus();
-               snap = atomic_read(&sync_sched_expedited_started);
+               snap = atomic_long_read(&rsp->expedited_start);
                smp_mb(); /* ensure read is before try_stop_cpus(). */
        }
+       atomic_long_inc(&rsp->expedited_stoppedcpus);
 
        /*
         * Everyone up to our most recent fetch is covered by our grace
         * period.  Update the counter, but only if our work is still
         * relevant -- which it won't be if someone who started later
-        * than we did beat us to the punch.
+        * than we did already did their update.
         */
        do {
-               s = atomic_read(&sync_sched_expedited_done);
-               if (UINT_CMP_GE((unsigned)s, (unsigned)snap)) {
-                       smp_mb(); /* ensure test happens before caller kfree */
+               atomic_long_inc(&rsp->expedited_done_tries);
+               s = atomic_long_read(&rsp->expedited_done);
+               if (ULONG_CMP_GE((ulong)s, (ulong)snap)) {
+                       /* ensure test happens before caller kfree */
+                       smp_mb__before_atomic_inc(); /* ^^^ */
+                       atomic_long_inc(&rsp->expedited_done_lost);
                        break;
                }
-       } while (atomic_cmpxchg(&sync_sched_expedited_done, s, snap) != s);
+       } while (atomic_long_cmpxchg(&rsp->expedited_done, s, snap) != s);
+       atomic_long_inc(&rsp->expedited_done_exit);
 
        put_online_cpus();
 }
@@ -2977,7 +3051,6 @@ void __init rcu_init(void)
        cpu_notifier(rcu_cpu_notify, 0);
        for_each_online_cpu(cpu)
                rcu_cpu_notify(NULL, CPU_UP_PREPARE, (void *)(long)cpu);
-       check_cpu_stall_init();
 }
 
 #include "rcutree_plugin.h"
index a240f032848eec8d00e156da54fce3cd24a4b525..ce938b31d878f92f6a3d15e5ed3edfd17dc5bd6e 100644 (file)
@@ -330,11 +330,6 @@ struct rcu_data {
 
 #define RCU_JIFFIES_TILL_FORCE_QS       3      /* for rsp->jiffies_force_qs */
 
-#ifdef CONFIG_PROVE_RCU
-#define RCU_STALL_DELAY_DELTA         (5 * HZ)
-#else
-#define RCU_STALL_DELAY_DELTA         0
-#endif
 #define RCU_STALL_RAT_DELAY            2       /* Allow other CPUs time */
                                                /*  to take at least one */
                                                /*  scheduling clock irq */
@@ -383,9 +378,8 @@ struct rcu_state {
 
        /* End of fields guarded by root rcu_node's lock. */
 
-       raw_spinlock_t onofflock ____cacheline_internodealigned_in_smp;
-                                               /* exclude on/offline and */
-                                               /*  starting new GP. */
+       raw_spinlock_t orphan_lock ____cacheline_internodealigned_in_smp;
+                                               /* Protect following fields. */
        struct rcu_head *orphan_nxtlist;        /* Orphaned callbacks that */
                                                /*  need a grace period. */
        struct rcu_head **orphan_nxttail;       /* Tail of above. */
@@ -394,7 +388,7 @@ struct rcu_state {
        struct rcu_head **orphan_donetail;      /* Tail of above. */
        long qlen_lazy;                         /* Number of lazy callbacks. */
        long qlen;                              /* Total number of callbacks. */
-       /* End of fields guarded by onofflock. */
+       /* End of fields guarded by orphan_lock. */
 
        struct mutex onoff_mutex;               /* Coordinate hotplug & GPs. */
 
@@ -405,6 +399,18 @@ struct rcu_state {
                                                /*  _rcu_barrier(). */
        /* End of fields guarded by barrier_mutex. */
 
+       atomic_long_t expedited_start;          /* Starting ticket. */
+       atomic_long_t expedited_done;           /* Done ticket. */
+       atomic_long_t expedited_wrap;           /* # near-wrap incidents. */
+       atomic_long_t expedited_tryfail;        /* # acquisition failures. */
+       atomic_long_t expedited_workdone1;      /* # done by others #1. */
+       atomic_long_t expedited_workdone2;      /* # done by others #2. */
+       atomic_long_t expedited_normal;         /* # fallbacks to normal. */
+       atomic_long_t expedited_stoppedcpus;    /* # successful stop_cpus. */
+       atomic_long_t expedited_done_tries;     /* # tries to update _done. */
+       atomic_long_t expedited_done_lost;      /* # times beaten to _done. */
+       atomic_long_t expedited_done_exit;      /* # times exited _done loop. */
+
        unsigned long jiffies_force_qs;         /* Time at which to invoke */
                                                /*  force_quiescent_state(). */
        unsigned long n_force_qs;               /* Number of calls to */
index f921154881870b0d4d489b84fdb1f40ccde7495b..986f41db09f277dc51d8a0a22fc5d0b4bef754b3 100644 (file)
@@ -670,6 +670,9 @@ EXPORT_SYMBOL_GPL(kfree_call_rcu);
  * concurrently with new RCU read-side critical sections that began while
  * synchronize_rcu() was waiting.  RCU read-side critical sections are
  * delimited by rcu_read_lock() and rcu_read_unlock(), and may be nested.
+ *
+ * See the description of synchronize_sched() for more detailed information
+ * on memory ordering guarantees.
  */
 void synchronize_rcu(void)
 {
@@ -679,7 +682,10 @@ void synchronize_rcu(void)
                           "Illegal synchronize_rcu() in RCU read-side critical section");
        if (!rcu_scheduler_active)
                return;
-       wait_rcu_gp(call_rcu);
+       if (rcu_expedited)
+               synchronize_rcu_expedited();
+       else
+               wait_rcu_gp(call_rcu);
 }
 EXPORT_SYMBOL_GPL(synchronize_rcu);
 
@@ -757,7 +763,8 @@ static void rcu_report_exp_rnp(struct rcu_state *rsp, struct rcu_node *rnp,
  * grace period for the specified rcu_node structure.  If there are no such
  * tasks, report it up the rcu_node hierarchy.
  *
- * Caller must hold sync_rcu_preempt_exp_mutex and rsp->onofflock.
+ * Caller must hold sync_rcu_preempt_exp_mutex and must exclude
+ * CPU hotplug operations.
  */
 static void
 sync_rcu_preempt_exp_init(struct rcu_state *rsp, struct rcu_node *rnp)
@@ -831,7 +838,7 @@ void synchronize_rcu_expedited(void)
                        udelay(trycount * num_online_cpus());
                } else {
                        put_online_cpus();
-                       synchronize_rcu();
+                       wait_rcu_gp(call_rcu);
                        return;
                }
        }
@@ -875,6 +882,11 @@ EXPORT_SYMBOL_GPL(synchronize_rcu_expedited);
 
 /**
  * rcu_barrier - Wait until all in-flight call_rcu() callbacks complete.
+ *
+ * Note that this primitive will not always wait for an RCU grace period
+ * to complete.  For example, if there are no RCU callbacks queued anywhere
+ * in the system, then rcu_barrier() is within its rights to return
+ * immediately, without waiting for anything, much less an RCU grace period.
  */
 void rcu_barrier(void)
 {
index 693513bc50e6d00921bff73ed4eb03f852ceec43..73abfb00a3ab7a44c2c39bfbc006df304bacb76c 100644 (file)
 #define RCU_TREE_NONCORE
 #include "rcutree.h"
 
-static int show_rcubarrier(struct seq_file *m, void *unused)
+static int r_open(struct inode *inode, struct file *file,
+                                       const struct seq_operations *op)
 {
-       struct rcu_state *rsp;
+       int ret = seq_open(file, op);
+       if (!ret) {
+               struct seq_file *m = (struct seq_file *)file->private_data;
+               m->private = inode->i_private;
+       }
+       return ret;
+}
+
+static void *r_start(struct seq_file *m, loff_t *pos)
+{
+       struct rcu_state *rsp = (struct rcu_state *)m->private;
+       *pos = cpumask_next(*pos - 1, cpu_possible_mask);
+       if ((*pos) < nr_cpu_ids)
+               return per_cpu_ptr(rsp->rda, *pos);
+       return NULL;
+}
+
+static void *r_next(struct seq_file *m, void *v, loff_t *pos)
+{
+       (*pos)++;
+       return r_start(m, pos);
+}
 
-       for_each_rcu_flavor(rsp)
-               seq_printf(m, "%s: bcc: %d nbd: %lu\n",
-                          rsp->name,
-                          atomic_read(&rsp->barrier_cpu_count),
-                          rsp->n_barrier_done);
+static void r_stop(struct seq_file *m, void *v)
+{
+}
+
+static int show_rcubarrier(struct seq_file *m, void *v)
+{
+       struct rcu_state *rsp = (struct rcu_state *)m->private;
+       seq_printf(m, "bcc: %d nbd: %lu\n",
+                  atomic_read(&rsp->barrier_cpu_count),
+                  rsp->n_barrier_done);
        return 0;
 }
 
 static int rcubarrier_open(struct inode *inode, struct file *file)
 {
-       return single_open(file, show_rcubarrier, NULL);
+       return single_open(file, show_rcubarrier, inode->i_private);
 }
 
 static const struct file_operations rcubarrier_fops = {
        .owner = THIS_MODULE,
        .open = rcubarrier_open,
        .read = seq_read,
-       .llseek = seq_lseek,
-       .release = single_release,
+       .llseek = no_llseek,
+       .release = seq_release,
 };
 
 #ifdef CONFIG_RCU_BOOST
@@ -118,97 +145,69 @@ static void print_one_rcu_data(struct seq_file *m, struct rcu_data *rdp)
                   rdp->n_cbs_invoked, rdp->n_cbs_orphaned, rdp->n_cbs_adopted);
 }
 
-static int show_rcudata(struct seq_file *m, void *unused)
+static int show_rcudata(struct seq_file *m, void *v)
 {
-       int cpu;
-       struct rcu_state *rsp;
-
-       for_each_rcu_flavor(rsp) {
-               seq_printf(m, "%s:\n", rsp->name);
-               for_each_possible_cpu(cpu)
-                       print_one_rcu_data(m, per_cpu_ptr(rsp->rda, cpu));
-       }
+       print_one_rcu_data(m, (struct rcu_data *)v);
        return 0;
 }
 
+static const struct seq_operations rcudate_op = {
+       .start = r_start,
+       .next  = r_next,
+       .stop  = r_stop,
+       .show  = show_rcudata,
+};
+
 static int rcudata_open(struct inode *inode, struct file *file)
 {
-       return single_open(file, show_rcudata, NULL);
+       return r_open(inode, file, &rcudate_op);
 }
 
 static const struct file_operations rcudata_fops = {
        .owner = THIS_MODULE,
        .open = rcudata_open,
        .read = seq_read,
-       .llseek = seq_lseek,
-       .release = single_release,
+       .llseek = no_llseek,
+       .release = seq_release,
 };
 
-static void print_one_rcu_data_csv(struct seq_file *m, struct rcu_data *rdp)
+static int show_rcuexp(struct seq_file *m, void *v)
 {
-       if (!rdp->beenonline)
-               return;
-       seq_printf(m, "%d,%s,%lu,%lu,%d,%d",
-                  rdp->cpu,
-                  cpu_is_offline(rdp->cpu) ? "\"N\"" : "\"Y\"",
-                  rdp->completed, rdp->gpnum,
-                  rdp->passed_quiesce, rdp->qs_pending);
-       seq_printf(m, ",%d,%llx,%d,%lu",
-                  atomic_read(&rdp->dynticks->dynticks),
-                  rdp->dynticks->dynticks_nesting,
-                  rdp->dynticks->dynticks_nmi_nesting,
-                  rdp->dynticks_fqs);
-       seq_printf(m, ",%lu", rdp->offline_fqs);
-       seq_printf(m, ",%ld,%ld,\"%c%c%c%c\"", rdp->qlen_lazy, rdp->qlen,
-                  ".N"[rdp->nxttail[RCU_NEXT_READY_TAIL] !=
-                       rdp->nxttail[RCU_NEXT_TAIL]],
-                  ".R"[rdp->nxttail[RCU_WAIT_TAIL] !=
-                       rdp->nxttail[RCU_NEXT_READY_TAIL]],
-                  ".W"[rdp->nxttail[RCU_DONE_TAIL] !=
-                       rdp->nxttail[RCU_WAIT_TAIL]],
-                  ".D"[&rdp->nxtlist != rdp->nxttail[RCU_DONE_TAIL]]);
-#ifdef CONFIG_RCU_BOOST
-       seq_printf(m, ",%d,\"%c\"",
-                  per_cpu(rcu_cpu_has_work, rdp->cpu),
-                  convert_kthread_status(per_cpu(rcu_cpu_kthread_status,
-                                         rdp->cpu)));
-#endif /* #ifdef CONFIG_RCU_BOOST */
-       seq_printf(m, ",%ld", rdp->blimit);
-       seq_printf(m, ",%lu,%lu,%lu\n",
-                  rdp->n_cbs_invoked, rdp->n_cbs_orphaned, rdp->n_cbs_adopted);
-}
-
-static int show_rcudata_csv(struct seq_file *m, void *unused)
-{
-       int cpu;
-       struct rcu_state *rsp;
-
-       seq_puts(m, "\"CPU\",\"Online?\",\"c\",\"g\",\"pq\",\"pq\",");
-       seq_puts(m, "\"dt\",\"dt nesting\",\"dt NMI nesting\",\"df\",");
-       seq_puts(m, "\"of\",\"qll\",\"ql\",\"qs\"");
-#ifdef CONFIG_RCU_BOOST
-       seq_puts(m, "\"kt\",\"ktl\"");
-#endif /* #ifdef CONFIG_RCU_BOOST */
-       seq_puts(m, ",\"b\",\"ci\",\"co\",\"ca\"\n");
-       for_each_rcu_flavor(rsp) {
-               seq_printf(m, "\"%s:\"\n", rsp->name);
-               for_each_possible_cpu(cpu)
-                       print_one_rcu_data_csv(m, per_cpu_ptr(rsp->rda, cpu));
-       }
+       struct rcu_state *rsp = (struct rcu_state *)v;
+
+       seq_printf(m, "s=%lu d=%lu w=%lu tf=%lu wd1=%lu wd2=%lu n=%lu sc=%lu dt=%lu dl=%lu dx=%lu",
+                  atomic_long_read(&rsp->expedited_start),
+                  atomic_long_read(&rsp->expedited_done),
+                  atomic_long_read(&rsp->expedited_wrap),
+                  atomic_long_read(&rsp->expedited_tryfail),
+                  atomic_long_read(&rsp->expedited_workdone1),
+                  atomic_long_read(&rsp->expedited_workdone2),
+                  atomic_long_read(&rsp->expedited_normal),
+                  atomic_long_read(&rsp->expedited_stoppedcpus),
+                  atomic_long_read(&rsp->expedited_done_tries),
+                  atomic_long_read(&rsp->expedited_done_lost),
+                  atomic_long_read(&rsp->expedited_done_exit));
        return 0;
 }
 
-static int rcudata_csv_open(struct inode *inode, struct file *file)
+static const struct seq_operations rcuexp_op = {
+       .start = r_start,
+       .next  = r_next,
+       .stop  = r_stop,
+       .show  = show_rcuexp,
+};
+
+static int rcuexp_open(struct inode *inode, struct file *file)
 {
-       return single_open(file, show_rcudata_csv, NULL);
+       return r_open(inode, file, &rcuexp_op);
 }
 
-static const struct file_operations rcudata_csv_fops = {
+static const struct file_operations rcuexp_fops = {
        .owner = THIS_MODULE,
-       .open = rcudata_csv_open,
+       .open = rcuexp_open,
        .read = seq_read,
-       .llseek = seq_lseek,
-       .release = single_release,
+       .llseek = no_llseek,
+       .release = seq_release,
 };
 
 #ifdef CONFIG_RCU_BOOST
@@ -254,27 +253,11 @@ static const struct file_operations rcu_node_boost_fops = {
        .owner = THIS_MODULE,
        .open = rcu_node_boost_open,
        .read = seq_read,
-       .llseek = seq_lseek,
+       .llseek = no_llseek,
        .release = single_release,
 };
 
-/*
- * Create the rcuboost debugfs entry.  Standard error return.
- */
-static int rcu_boost_trace_create_file(struct dentry *rcudir)
-{
-       return !debugfs_create_file("rcuboost", 0444, rcudir, NULL,
-                                   &rcu_node_boost_fops);
-}
-
-#else /* #ifdef CONFIG_RCU_BOOST */
-
-static int rcu_boost_trace_create_file(struct dentry *rcudir)
-{
-       return 0;  /* There cannot be an error if we didn't create it! */
-}
-
-#endif /* #else #ifdef CONFIG_RCU_BOOST */
+#endif /* #ifdef CONFIG_RCU_BOOST */
 
 static void print_one_rcu_state(struct seq_file *m, struct rcu_state *rsp)
 {
@@ -283,8 +266,8 @@ static void print_one_rcu_state(struct seq_file *m, struct rcu_state *rsp)
        struct rcu_node *rnp;
 
        gpnum = rsp->gpnum;
-       seq_printf(m, "%s: c=%lu g=%lu s=%d jfq=%ld j=%x ",
-                  rsp->name, rsp->completed, gpnum, rsp->fqs_state,
+       seq_printf(m, "c=%lu g=%lu s=%d jfq=%ld j=%x ",
+                  rsp->completed, gpnum, rsp->fqs_state,
                   (long)(rsp->jiffies_force_qs - jiffies),
                   (int)(jiffies & 0xffff));
        seq_printf(m, "nfqs=%lu/nfqsng=%lu(%lu) fqlh=%lu oqlen=%ld/%ld\n",
@@ -306,26 +289,24 @@ static void print_one_rcu_state(struct seq_file *m, struct rcu_state *rsp)
        seq_puts(m, "\n");
 }
 
-static int show_rcuhier(struct seq_file *m, void *unused)
+static int show_rcuhier(struct seq_file *m, void *v)
 {
-       struct rcu_state *rsp;
-
-       for_each_rcu_flavor(rsp)
-               print_one_rcu_state(m, rsp);
+       struct rcu_state *rsp = (struct rcu_state *)m->private;
+       print_one_rcu_state(m, rsp);
        return 0;
 }
 
 static int rcuhier_open(struct inode *inode, struct file *file)
 {
-       return single_open(file, show_rcuhier, NULL);
+       return single_open(file, show_rcuhier, inode->i_private);
 }
 
 static const struct file_operations rcuhier_fops = {
        .owner = THIS_MODULE,
        .open = rcuhier_open,
        .read = seq_read,
-       .llseek = seq_lseek,
-       .release = single_release,
+       .llseek = no_llseek,
+       .release = seq_release,
 };
 
 static void show_one_rcugp(struct seq_file *m, struct rcu_state *rsp)
@@ -338,42 +319,42 @@ static void show_one_rcugp(struct seq_file *m, struct rcu_state *rsp)
        struct rcu_node *rnp = &rsp->node[0];
 
        raw_spin_lock_irqsave(&rnp->lock, flags);
-       completed = rsp->completed;
-       gpnum = rsp->gpnum;
-       if (rsp->completed == rsp->gpnum)
+       completed = ACCESS_ONCE(rsp->completed);
+       gpnum = ACCESS_ONCE(rsp->gpnum);
+       if (completed == gpnum)
                gpage = 0;
        else
                gpage = jiffies - rsp->gp_start;
        gpmax = rsp->gp_max;
        raw_spin_unlock_irqrestore(&rnp->lock, flags);
-       seq_printf(m, "%s: completed=%ld  gpnum=%lu  age=%ld  max=%ld\n",
-                  rsp->name, completed, gpnum, gpage, gpmax);
+       seq_printf(m, "completed=%lu  gpnum=%lu  age=%ld  max=%ld\n",
+                  completed, gpnum, gpage, gpmax);
 }
 
-static int show_rcugp(struct seq_file *m, void *unused)
+static int show_rcugp(struct seq_file *m, void *v)
 {
-       struct rcu_state *rsp;
-
-       for_each_rcu_flavor(rsp)
-               show_one_rcugp(m, rsp);
+       struct rcu_state *rsp = (struct rcu_state *)m->private;
+       show_one_rcugp(m, rsp);
        return 0;
 }
 
 static int rcugp_open(struct inode *inode, struct file *file)
 {
-       return single_open(file, show_rcugp, NULL);
+       return single_open(file, show_rcugp, inode->i_private);
 }
 
 static const struct file_operations rcugp_fops = {
        .owner = THIS_MODULE,
        .open = rcugp_open,
        .read = seq_read,
-       .llseek = seq_lseek,
-       .release = single_release,
+       .llseek = no_llseek,
+       .release = seq_release,
 };
 
 static void print_one_rcu_pending(struct seq_file *m, struct rcu_data *rdp)
 {
+       if (!rdp->beenonline)
+               return;
        seq_printf(m, "%3d%cnp=%ld ",
                   rdp->cpu,
                   cpu_is_offline(rdp->cpu) ? '!' : ' ',
@@ -389,34 +370,30 @@ static void print_one_rcu_pending(struct seq_file *m, struct rcu_data *rdp)
                   rdp->n_rp_need_nothing);
 }
 
-static int show_rcu_pending(struct seq_file *m, void *unused)
+static int show_rcu_pending(struct seq_file *m, void *v)
 {
-       int cpu;
-       struct rcu_data *rdp;
-       struct rcu_state *rsp;
-
-       for_each_rcu_flavor(rsp) {
-               seq_printf(m, "%s:\n", rsp->name);
-               for_each_possible_cpu(cpu) {
-                       rdp = per_cpu_ptr(rsp->rda, cpu);
-                       if (rdp->beenonline)
-                               print_one_rcu_pending(m, rdp);
-               }
-       }
+       print_one_rcu_pending(m, (struct rcu_data *)v);
        return 0;
 }
 
+static const struct seq_operations rcu_pending_op = {
+       .start = r_start,
+       .next  = r_next,
+       .stop  = r_stop,
+       .show  = show_rcu_pending,
+};
+
 static int rcu_pending_open(struct inode *inode, struct file *file)
 {
-       return single_open(file, show_rcu_pending, NULL);
+       return r_open(inode, file, &rcu_pending_op);
 }
 
 static const struct file_operations rcu_pending_fops = {
        .owner = THIS_MODULE,
        .open = rcu_pending_open,
        .read = seq_read,
-       .llseek = seq_lseek,
-       .release = single_release,
+       .llseek = no_llseek,
+       .release = seq_release,
 };
 
 static int show_rcutorture(struct seq_file *m, void *unused)
@@ -446,43 +423,58 @@ static struct dentry *rcudir;
 
 static int __init rcutree_trace_init(void)
 {
+       struct rcu_state *rsp;
        struct dentry *retval;
+       struct dentry *rspdir;
 
        rcudir = debugfs_create_dir("rcu", NULL);
        if (!rcudir)
                goto free_out;
 
-       retval = debugfs_create_file("rcubarrier", 0444, rcudir,
-                                               NULL, &rcubarrier_fops);
-       if (!retval)
-               goto free_out;
-
-       retval = debugfs_create_file("rcudata", 0444, rcudir,
-                                               NULL, &rcudata_fops);
-       if (!retval)
-               goto free_out;
-
-       retval = debugfs_create_file("rcudata.csv", 0444, rcudir,
-                                               NULL, &rcudata_csv_fops);
-       if (!retval)
-               goto free_out;
-
-       if (rcu_boost_trace_create_file(rcudir))
-               goto free_out;
-
-       retval = debugfs_create_file("rcugp", 0444, rcudir, NULL, &rcugp_fops);
-       if (!retval)
-               goto free_out;
-
-       retval = debugfs_create_file("rcuhier", 0444, rcudir,
-                                               NULL, &rcuhier_fops);
-       if (!retval)
-               goto free_out;
+       for_each_rcu_flavor(rsp) {
+               rspdir = debugfs_create_dir(rsp->name, rcudir);
+               if (!rspdir)
+                       goto free_out;
+
+                       retval = debugfs_create_file("rcudata", 0444,
+                                       rspdir, rsp, &rcudata_fops);
+                       if (!retval)
+                               goto free_out;
+
+                       retval = debugfs_create_file("rcuexp", 0444,
+                                       rspdir, rsp, &rcuexp_fops);
+                       if (!retval)
+                               goto free_out;
+
+                       retval = debugfs_create_file("rcu_pending", 0444,
+                                       rspdir, rsp, &rcu_pending_fops);
+                       if (!retval)
+                               goto free_out;
+
+                       retval = debugfs_create_file("rcubarrier", 0444,
+                                       rspdir, rsp, &rcubarrier_fops);
+                       if (!retval)
+                               goto free_out;
 
-       retval = debugfs_create_file("rcu_pending", 0444, rcudir,
-                                               NULL, &rcu_pending_fops);
-       if (!retval)
-               goto free_out;
+#ifdef CONFIG_RCU_BOOST
+                       if (rsp == &rcu_preempt_state) {
+                               retval = debugfs_create_file("rcuboost", 0444,
+                                       rspdir, NULL, &rcu_node_boost_fops);
+                               if (!retval)
+                                       goto free_out;
+                       }
+#endif
+
+                       retval = debugfs_create_file("rcugp", 0444,
+                                       rspdir, rsp, &rcugp_fops);
+                       if (!retval)
+                               goto free_out;
+
+                       retval = debugfs_create_file("rcuhier", 0444,
+                                       rspdir, rsp, &rcuhier_fops);
+                       if (!retval)
+                               goto free_out;
+       }
 
        retval = debugfs_create_file("rcutorture", 0444, rcudir,
                                                NULL, &rcutorture_fops);
index 2d8927fda712f5ee1e19f1fe364fbad557d8a736..bf41f826465574b6203b98569a44c9dc8b563bb4 100644 (file)
@@ -952,6 +952,8 @@ void set_task_cpu(struct task_struct *p, unsigned int new_cpu)
        trace_sched_migrate_task(p, new_cpu);
 
        if (task_cpu(p) != new_cpu) {
+               if (p->sched_class->migrate_task_rq)
+                       p->sched_class->migrate_task_rq(p, new_cpu);
                p->se.nr_migrations++;
                perf_sw_event(PERF_COUNT_SW_CPU_MIGRATIONS, 1, NULL, 0);
        }
@@ -1524,6 +1526,15 @@ static void __sched_fork(struct task_struct *p)
        p->se.vruntime                  = 0;
        INIT_LIST_HEAD(&p->se.group_node);
 
+/*
+ * Load-tracking only depends on SMP, FAIR_GROUP_SCHED dependency below may be
+ * removed when useful for applications beyond shares distribution (e.g.
+ * load-balance).
+ */
+#if defined(CONFIG_SMP) && defined(CONFIG_FAIR_GROUP_SCHED)
+       p->se.avg.runnable_avg_period = 0;
+       p->se.avg.runnable_avg_sum = 0;
+#endif
 #ifdef CONFIG_SCHEDSTATS
        memset(&p->se.statistics, 0, sizeof(p->se.statistics));
 #endif
@@ -1533,6 +1544,21 @@ static void __sched_fork(struct task_struct *p)
 #ifdef CONFIG_PREEMPT_NOTIFIERS
        INIT_HLIST_HEAD(&p->preempt_notifiers);
 #endif
+
+#ifdef CONFIG_SCHED_NUMA
+       if (p->mm && atomic_read(&p->mm->mm_users) == 1) {
+               p->mm->numa_next_scan = jiffies;
+               p->mm->numa_scan_seq = 0;
+       }
+
+       p->node = -1;
+       p->node_stamp = 0ULL;
+       p->numa_scan_seq = p->mm ? p->mm->numa_scan_seq : 0;
+       p->numa_migrate_seq = p->mm ? p->mm->numa_scan_seq - 1 : 0;
+       p->numa_faults = NULL;
+       p->numa_scan_period = sysctl_sched_numa_scan_delay;
+       p->numa_work.next = &p->numa_work;
+#endif /* CONFIG_SCHED_NUMA */
 }
 
 /*
@@ -1774,6 +1800,7 @@ static void finish_task_switch(struct rq *rq, struct task_struct *prev)
        if (mm)
                mmdrop(mm);
        if (unlikely(prev_state == TASK_DEAD)) {
+               task_numa_free(prev);
                /*
                 * Remove function-return probe instances associated with this
                 * task and put them back on the free list.
@@ -1887,7 +1914,7 @@ context_switch(struct rq *rq, struct task_struct *prev,
 #endif
 
        /* Here we just switch the register state and the stack. */
-       rcu_switch(prev, next);
+       rcu_user_hooks_switch(prev, next);
        switch_to(prev, next, prev);
 
        barrier();
@@ -5484,7 +5511,9 @@ static void destroy_sched_domains(struct sched_domain *sd, int cpu)
 DEFINE_PER_CPU(struct sched_domain *, sd_llc);
 DEFINE_PER_CPU(int, sd_llc_id);
 
-static void update_top_cache_domain(int cpu)
+DEFINE_PER_CPU(struct sched_domain *, sd_node);
+
+static void update_domain_cache(int cpu)
 {
        struct sched_domain *sd;
        int id = cpu;
@@ -5495,6 +5524,15 @@ static void update_top_cache_domain(int cpu)
 
        rcu_assign_pointer(per_cpu(sd_llc, cpu), sd);
        per_cpu(sd_llc_id, cpu) = id;
+
+       for_each_domain(cpu, sd) {
+               if (cpumask_equal(sched_domain_span(sd),
+                                 cpumask_of_node(cpu_to_node(cpu))))
+                       goto got_node;
+       }
+       sd = NULL;
+got_node:
+       rcu_assign_pointer(per_cpu(sd_node, cpu), sd);
 }
 
 /*
@@ -5537,7 +5575,7 @@ cpu_attach_domain(struct sched_domain *sd, struct root_domain *rd, int cpu)
        rcu_assign_pointer(rq->sd, sd);
        destroy_sched_domains(tmp, cpu);
 
-       update_top_cache_domain(cpu);
+       update_domain_cache(cpu);
 }
 
 /* cpus with isolated domains */
@@ -5959,6 +5997,45 @@ static struct sched_domain_topology_level default_topology[] = {
 
 static struct sched_domain_topology_level *sched_domain_topology = default_topology;
 
+#ifdef CONFIG_SCHED_NUMA
+
+/*
+ * Requeues a task ensuring its on the right load-balance list so
+ * that it might get migrated to its new home.
+ *
+ * Since home-node is pure preference there's no hard migrate to force
+ * us anywhere, this also allows us to call this from atomic context if
+ * required.
+ */
+void sched_setnode(struct task_struct *p, int node)
+{
+       unsigned long flags;
+       int on_rq, running;
+       struct rq *rq;
+
+       if (!sched_feat(NUMA_MIGRATION))
+               return;
+
+       rq = task_rq_lock(p, &flags);
+       on_rq = p->on_rq;
+       running = task_current(rq, p);
+
+       if (on_rq)
+               dequeue_task(rq, p, 0);
+       if (running)
+               p->sched_class->put_prev_task(rq, p);
+
+       p->node = node;
+
+       if (running)
+               p->sched_class->set_curr_task(rq);
+       if (on_rq)
+               enqueue_task(rq, p, 0);
+       task_rq_unlock(rq, p, &flags);
+}
+
+#endif /* CONFIG_SCHED_NUMA */
+
 #ifdef CONFIG_NUMA
 
 static int sched_domains_numa_levels;
@@ -6004,6 +6081,7 @@ sd_numa_init(struct sched_domain_topology_level *tl, int cpu)
                                        | 0*SD_SHARE_PKG_RESOURCES
                                        | 1*SD_SERIALIZE
                                        | 0*SD_PREFER_SIBLING
+                                       | 1*SD_NUMA
                                        | sd_local_flags(level)
                                        ,
                .last_balance           = jiffies,
@@ -6865,6 +6943,12 @@ void __init sched_init(void)
                rq->avg_idle = 2*sysctl_sched_migration_cost;
 
                INIT_LIST_HEAD(&rq->cfs_tasks);
+#ifdef CONFIG_SCHED_NUMA
+               INIT_LIST_HEAD(&rq->offnode_tasks);
+               rq->onnode_running = 0;
+               rq->offnode_running = 0;
+               rq->offnode_weight = 0;
+#endif
 
                rq_attach_root(rq, &def_root_domain);
 #ifdef CONFIG_NO_HZ
@@ -8076,3 +8160,9 @@ struct cgroup_subsys cpuacct_subsys = {
        .base_cftypes = files,
 };
 #endif /* CONFIG_CGROUP_CPUACCT */
+
+void dump_cpu_task(int cpu)
+{
+       pr_info("Task dump for CPU %d:\n", cpu);
+       sched_show_task(cpu_curr(cpu));
+}
index 6f79596e0ea91acc791ca3512a351f07605e3fbf..82cf7332ab6dda88c8e1f75b0c47f1ad0a2fbe56 100644 (file)
@@ -61,14 +61,20 @@ static unsigned long nsec_low(unsigned long long nsec)
 static void print_cfs_group_stats(struct seq_file *m, int cpu, struct task_group *tg)
 {
        struct sched_entity *se = tg->se[cpu];
-       if (!se)
-               return;
 
 #define P(F) \
        SEQ_printf(m, "  .%-30s: %lld\n", #F, (long long)F)
 #define PN(F) \
        SEQ_printf(m, "  .%-30s: %lld.%06ld\n", #F, SPLIT_NS((long long)F))
 
+       if (!se) {
+               struct sched_avg *avg = &cpu_rq(cpu)->avg;
+               P(avg->runnable_avg_sum);
+               P(avg->runnable_avg_period);
+               return;
+       }
+
+
        PN(se->exec_start);
        PN(se->vruntime);
        PN(se->sum_exec_runtime);
@@ -85,6 +91,12 @@ static void print_cfs_group_stats(struct seq_file *m, int cpu, struct task_group
        P(se->statistics.wait_count);
 #endif
        P(se->load.weight);
+#ifdef CONFIG_SMP
+       P(se->avg.runnable_avg_sum);
+       P(se->avg.runnable_avg_period);
+       P(se->avg.load_avg_contrib);
+       P(se->avg.decay_count);
+#endif
 #undef PN
 #undef P
 }
@@ -132,6 +144,9 @@ print_task(struct seq_file *m, struct rq *rq, struct task_struct *p)
        SEQ_printf(m, "%15Ld %15Ld %15Ld.%06ld %15Ld.%06ld %15Ld.%06ld",
                0LL, 0LL, 0LL, 0L, 0LL, 0L, 0LL, 0L);
 #endif
+#ifdef CONFIG_SCHED_NUMA
+       SEQ_printf(m, " %d/%d", p->node, cpu_to_node(task_cpu(p)));
+#endif
 #ifdef CONFIG_CGROUP_SCHED
        SEQ_printf(m, " %s", task_group_path(task_group(p)));
 #endif
@@ -206,14 +221,18 @@ void print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq)
        SEQ_printf(m, "  .%-30s: %ld\n", "load", cfs_rq->load.weight);
 #ifdef CONFIG_FAIR_GROUP_SCHED
 #ifdef CONFIG_SMP
-       SEQ_printf(m, "  .%-30s: %Ld.%06ld\n", "load_avg",
-                       SPLIT_NS(cfs_rq->load_avg));
-       SEQ_printf(m, "  .%-30s: %Ld.%06ld\n", "load_period",
-                       SPLIT_NS(cfs_rq->load_period));
-       SEQ_printf(m, "  .%-30s: %ld\n", "load_contrib",
-                       cfs_rq->load_contribution);
-       SEQ_printf(m, "  .%-30s: %d\n", "load_tg",
-                       atomic_read(&cfs_rq->tg->load_weight));
+       SEQ_printf(m, "  .%-30s: %lld\n", "runnable_load_avg",
+                       cfs_rq->runnable_load_avg);
+       SEQ_printf(m, "  .%-30s: %lld\n", "blocked_load_avg",
+                       cfs_rq->blocked_load_avg);
+       SEQ_printf(m, "  .%-30s: %ld\n", "tg_load_avg",
+                       atomic64_read(&cfs_rq->tg->load_avg));
+       SEQ_printf(m, "  .%-30s: %lld\n", "tg_load_contrib",
+                       cfs_rq->tg_load_contrib);
+       SEQ_printf(m, "  .%-30s: %d\n", "tg_runnable_contrib",
+                       cfs_rq->tg_runnable_contrib);
+       SEQ_printf(m, "  .%-30s: %d\n", "tg->runnable_avg",
+                       atomic_read(&cfs_rq->tg->runnable_avg));
 #endif
 
        print_cfs_group_stats(m, cpu, cfs_rq->tg);
index 6b800a14b9903c81d7bc9b2176b03e750c951108..50e5793367f8bd0e076f2239dc71fd1b19d04530 100644 (file)
@@ -18,6 +18,9 @@
  *
  *  Adaptive scheduling granularity, math enhancements by Peter Zijlstra
  *  Copyright (C) 2007 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
+ *
+ *  NUMA placement, statistics and algorithm by Andrea Arcangeli,
+ *  CFS balancing changes by Peter Zijlstra. Copyright (C) 2012 Red Hat, Inc.
  */
 
 #include <linux/latencytop.h>
@@ -26,6 +29,9 @@
 #include <linux/slab.h>
 #include <linux/profile.h>
 #include <linux/interrupt.h>
+#include <linux/random.h>
+#include <linux/mempolicy.h>
+#include <linux/task_work.h>
 
 #include <trace/events/sched.h>
 
@@ -259,6 +265,9 @@ static inline struct cfs_rq *group_cfs_rq(struct sched_entity *grp)
        return grp->my_q;
 }
 
+static void update_cfs_rq_blocked_load(struct cfs_rq *cfs_rq,
+                                      int force_update);
+
 static inline void list_add_leaf_cfs_rq(struct cfs_rq *cfs_rq)
 {
        if (!cfs_rq->on_list) {
@@ -278,6 +287,8 @@ static inline void list_add_leaf_cfs_rq(struct cfs_rq *cfs_rq)
                }
 
                cfs_rq->on_list = 1;
+               /* We should have no load, but we need to update last_decay. */
+               update_cfs_rq_blocked_load(cfs_rq, 0);
        }
 }
 
@@ -653,9 +664,6 @@ static u64 sched_vslice(struct cfs_rq *cfs_rq, struct sched_entity *se)
        return calc_delta_fair(sched_slice(cfs_rq, se), se);
 }
 
-static void update_cfs_load(struct cfs_rq *cfs_rq, int global_update);
-static void update_cfs_shares(struct cfs_rq *cfs_rq);
-
 /*
  * Update the current task's runtime statistics. Skip current tasks that
  * are not in our scheduling class.
@@ -675,10 +683,6 @@ __update_curr(struct cfs_rq *cfs_rq, struct sched_entity *curr,
 
        curr->vruntime += delta_exec_weighted;
        update_min_vruntime(cfs_rq);
-
-#if defined CONFIG_SMP && defined CONFIG_FAIR_GROUP_SCHED
-       cfs_rq->load_unacc_exec_time += delta_exec;
-#endif
 }
 
 static void update_curr(struct cfs_rq *cfs_rq)
@@ -773,100 +777,284 @@ update_stats_curr_start(struct cfs_rq *cfs_rq, struct sched_entity *se)
 }
 
 /**************************************************
- * Scheduling class queueing methods:
+ * Scheduling class numa methods.
+ *
+ * The purpose of the NUMA bits are to maintain compute (task) and data
+ * (memory) locality. We try and achieve this by making tasks stick to
+ * a particular node (their home node) but if fairness mandates they run
+ * elsewhere for long enough, we let the memory follow them.
+ *
+ * Tasks start out with their home-node unset (-1) this effectively means
+ * they act !NUMA until we've established the task is busy enough to bother
+ * with placement.
+ *
+ * We keep a home-node per task and use periodic fault scans to try and
+ * estalish a task<->page relation. This assumes the task<->page relation is a
+ * compute<->data relation, this is false for things like virt. and n:m
+ * threading solutions but its the best we can do given the information we
+ * have.
  */
 
-static void
-account_entity_enqueue(struct cfs_rq *cfs_rq, struct sched_entity *se)
-{
-       update_load_add(&cfs_rq->load, se->load.weight);
-       if (!parent_entity(se))
-               update_load_add(&rq_of(cfs_rq)->load, se->load.weight);
 #ifdef CONFIG_SMP
-       if (entity_is_task(se))
-               list_add(&se->group_node, &rq_of(cfs_rq)->cfs_tasks);
+static unsigned long task_h_load(struct task_struct *p);
 #endif
-       cfs_rq->nr_running++;
+
+#ifdef CONFIG_SCHED_NUMA
+static struct list_head *account_numa_enqueue(struct rq *rq, struct task_struct *p)
+{
+       struct list_head *tasks = &rq->cfs_tasks;
+
+       if (tsk_home_node(p) != cpu_to_node(task_cpu(p))) {
+               p->numa_contrib = task_h_load(p);
+               rq->offnode_weight += p->numa_contrib;
+               rq->offnode_running++;
+               tasks = &rq->offnode_tasks;
+       } else
+               rq->onnode_running++;
+
+       return tasks;
 }
 
-static void
-account_entity_dequeue(struct cfs_rq *cfs_rq, struct sched_entity *se)
+static void account_numa_dequeue(struct rq *rq, struct task_struct *p)
 {
-       update_load_sub(&cfs_rq->load, se->load.weight);
-       if (!parent_entity(se))
-               update_load_sub(&rq_of(cfs_rq)->load, se->load.weight);
-       if (entity_is_task(se))
-               list_del_init(&se->group_node);
-       cfs_rq->nr_running--;
+       if (tsk_home_node(p) != cpu_to_node(task_cpu(p))) {
+               rq->offnode_weight -= p->numa_contrib;
+               rq->offnode_running--;
+       } else
+               rq->onnode_running--;
 }
 
-#ifdef CONFIG_FAIR_GROUP_SCHED
-/* we need this in update_cfs_load and load-balance functions below */
-static inline int throttled_hierarchy(struct cfs_rq *cfs_rq);
-# ifdef CONFIG_SMP
-static void update_cfs_rq_load_contribution(struct cfs_rq *cfs_rq,
-                                           int global_update)
+/*
+ * Scan @scan_size MB every @scan_period after an initial @scan_delay.
+ */
+unsigned int sysctl_sched_numa_scan_delay = 1000;      /* ms */
+unsigned int sysctl_sched_numa_scan_period_min = 100;  /* ms */
+unsigned int sysctl_sched_numa_scan_period_max = 100*16;/* ms */
+unsigned int sysctl_sched_numa_scan_size = 256;                /* MB */
+
+/*
+ * Wait for the 2-sample stuff to settle before migrating again
+ */
+unsigned int sysctl_sched_numa_settle_count = 2;
+
+static void task_numa_placement(struct task_struct *p)
 {
-       struct task_group *tg = cfs_rq->tg;
-       long load_avg;
+       unsigned long faults, max_faults = 0;
+       int node, max_node = -1;
+       int seq = ACCESS_ONCE(p->mm->numa_scan_seq);
 
-       load_avg = div64_u64(cfs_rq->load_avg, cfs_rq->load_period+1);
-       load_avg -= cfs_rq->load_contribution;
+       if (p->numa_scan_seq == seq)
+               return;
+
+       p->numa_scan_seq = seq;
+
+       for (node = 0; node < nr_node_ids; node++) {
+               faults = p->numa_faults[node];
 
-       if (global_update || abs(load_avg) > cfs_rq->load_contribution / 8) {
-               atomic_add(load_avg, &tg->load_weight);
-               cfs_rq->load_contribution += load_avg;
+               if (faults > max_faults) {
+                       max_faults = faults;
+                       max_node = node;
+               }
+
+               p->numa_faults[node] /= 2;
+       }
+
+       if (max_node == -1)
+               return;
+
+       if (p->node != max_node) {
+               p->numa_scan_period = sysctl_sched_numa_scan_period_min;
+               if (sched_feat(NUMA_SETTLE) &&
+                   (seq - p->numa_migrate_seq) <= (int)sysctl_sched_numa_settle_count)
+                       return;
+               p->numa_migrate_seq = seq;
+               sched_setnode(p, max_node);
+       } else {
+               p->numa_scan_period = min(sysctl_sched_numa_scan_period_max,
+                               p->numa_scan_period * 2);
        }
 }
 
-static void update_cfs_load(struct cfs_rq *cfs_rq, int global_update)
+/*
+ * Got a PROT_NONE fault for a page on @node.
+ */
+void task_numa_fault(int node, int pages)
+{
+       struct task_struct *p = current;
+
+       if (unlikely(!p->numa_faults)) {
+               int size = sizeof(unsigned long) * nr_node_ids;
+
+               p->numa_faults = kzalloc(size, GFP_KERNEL);
+               if (!p->numa_faults)
+                       return;
+       }
+
+       task_numa_placement(p);
+
+       p->numa_faults[node] += pages;
+}
+
+/*
+ * The expensive part of numa migration is done from task_work context.
+ * Triggered from task_tick_numa().
+ */
+void task_numa_work(struct callback_head *work)
 {
-       u64 period = sysctl_sched_shares_window;
-       u64 now, delta;
-       unsigned long load = cfs_rq->load.weight;
+       unsigned long migrate, next_scan, now = jiffies;
+       struct task_struct *p = current;
+       struct mm_struct *mm = p->mm;
+       struct vm_area_struct *vma;
+       unsigned long offset, end;
+       long length;
 
-       if (cfs_rq->tg == &root_task_group || throttled_hierarchy(cfs_rq))
+       WARN_ON_ONCE(p != container_of(work, struct task_struct, numa_work));
+
+       work->next = work; /* protect against double add */
+       /*
+        * Who cares about NUMA placement when they're dying.
+        *
+        * NOTE: make sure not to dereference p->mm before this check,
+        * exit_task_work() happens _after_ exit_mm() so we could be called
+        * without p->mm even though we still had it when we enqueued this
+        * work.
+        */
+       if (p->flags & PF_EXITING)
                return;
 
-       now = rq_of(cfs_rq)->clock_task;
-       delta = now - cfs_rq->load_stamp;
+       /*
+        * Enforce maximal scan/migration frequency..
+        */
+       migrate = mm->numa_next_scan;
+       if (time_before(now, migrate))
+               return;
 
-       /* truncate load history at 4 idle periods */
-       if (cfs_rq->load_stamp > cfs_rq->load_last &&
-           now - cfs_rq->load_last > 4 * period) {
-               cfs_rq->load_period = 0;
-               cfs_rq->load_avg = 0;
-               delta = period - 1;
+       next_scan = now + 2*msecs_to_jiffies(sysctl_sched_numa_scan_period_min);
+       if (cmpxchg(&mm->numa_next_scan, migrate, next_scan) != migrate)
+               return;
+
+       offset = mm->numa_scan_offset;
+       length = sysctl_sched_numa_scan_size;
+       length <<= 20;
+
+       down_write(&mm->mmap_sem);
+       vma = find_vma(mm, offset);
+       if (!vma) {
+               ACCESS_ONCE(mm->numa_scan_seq)++;
+               offset = 0;
+               vma = mm->mmap;
        }
+       for (; vma && length > 0; vma = vma->vm_next) {
+               if (!vma_migratable(vma))
+                       continue;
+
+               offset = max(offset, vma->vm_start);
+               end = min(ALIGN(offset + length, HPAGE_SIZE), vma->vm_end);
+               length -= end - offset;
+
+               change_prot_none(vma, offset, end);
 
-       cfs_rq->load_stamp = now;
-       cfs_rq->load_unacc_exec_time = 0;
-       cfs_rq->load_period += delta;
-       if (load) {
-               cfs_rq->load_last = now;
-               cfs_rq->load_avg += delta * load;
+               offset = end;
        }
+       mm->numa_scan_offset = offset;
+       up_write(&mm->mmap_sem);
+}
 
-       /* consider updating load contribution on each fold or truncate */
-       if (global_update || cfs_rq->load_period > period
-           || !cfs_rq->load_period)
-               update_cfs_rq_load_contribution(cfs_rq, global_update);
+/*
+ * Drive the periodic memory faults..
+ */
+void task_tick_numa(struct rq *rq, struct task_struct *curr)
+{
+       struct callback_head *work = &curr->numa_work;
+       u64 period, now;
 
-       while (cfs_rq->load_period > period) {
-               /*
-                * Inline assembly required to prevent the compiler
-                * optimising this loop into a divmod call.
-                * See __iter_div_u64_rem() for another example of this.
-                */
-               asm("" : "+rm" (cfs_rq->load_period));
-               cfs_rq->load_period /= 2;
-               cfs_rq->load_avg /= 2;
+       /*
+        * We don't care about NUMA placement if we don't have memory.
+        */
+       if (!curr->mm || (curr->flags & PF_EXITING) || work->next != work)
+               return;
+
+       /*
+        * Using runtime rather than walltime has the dual advantage that
+        * we (mostly) drive the selection from busy threads and that the
+        * task needs to have done some actual work before we bother with
+        * NUMA placement.
+        */
+       now = curr->se.sum_exec_runtime;
+       period = (u64)curr->numa_scan_period * NSEC_PER_MSEC;
+
+       if (now - curr->node_stamp > period) {
+               if (!curr->node_stamp)
+                       curr->numa_scan_period = sysctl_sched_numa_scan_period_min;
+               curr->node_stamp = now;
+
+               if (!time_before(jiffies, curr->mm->numa_next_scan)) {
+                       init_task_work(work, task_numa_work); /* TODO: move this into sched_fork() */
+                       task_work_add(curr, work, true);
+               }
+       }
+}
+#else
+#ifdef CONFIG_SMP
+static struct list_head *account_numa_enqueue(struct rq *rq, struct task_struct *p)
+{
+       return NULL;
+}
+#endif
+
+static void account_numa_dequeue(struct rq *rq, struct task_struct *p)
+{
+}
+
+static void task_tick_numa(struct rq *rq, struct task_struct *curr)
+{
+}
+#endif /* CONFIG_SCHED_NUMA */
+
+/**************************************************
+ * Scheduling class queueing methods:
+ */
+
+static void
+account_entity_enqueue(struct cfs_rq *cfs_rq, struct sched_entity *se)
+{
+       update_load_add(&cfs_rq->load, se->load.weight);
+       if (!parent_entity(se))
+               update_load_add(&rq_of(cfs_rq)->load, se->load.weight);
+#ifdef CONFIG_SMP
+       if (entity_is_task(se)) {
+               struct rq *rq = rq_of(cfs_rq);
+               struct task_struct *p = task_of(se);
+               struct list_head *tasks = &rq->cfs_tasks;
+
+               if (tsk_home_node(p) != -1)
+                       tasks = account_numa_enqueue(rq, p);
+
+               list_add(&se->group_node, tasks);
        }
+#endif /* CONFIG_SMP */
+       cfs_rq->nr_running++;
+}
+
+static void
+account_entity_dequeue(struct cfs_rq *cfs_rq, struct sched_entity *se)
+{
+       update_load_sub(&cfs_rq->load, se->load.weight);
+       if (!parent_entity(se))
+               update_load_sub(&rq_of(cfs_rq)->load, se->load.weight);
+       if (entity_is_task(se)) {
+               struct task_struct *p = task_of(se);
+
+               list_del_init(&se->group_node);
 
-       if (!cfs_rq->curr && !cfs_rq->nr_running && !cfs_rq->load_avg)
-               list_del_leaf_cfs_rq(cfs_rq);
+               if (tsk_home_node(p) != -1)
+                       account_numa_dequeue(rq_of(cfs_rq), p);
+       }
+       cfs_rq->nr_running--;
 }
 
+#ifdef CONFIG_FAIR_GROUP_SCHED
+# ifdef CONFIG_SMP
 static inline long calc_tg_weight(struct task_group *tg, struct cfs_rq *cfs_rq)
 {
        long tg_weight;
@@ -876,8 +1064,8 @@ static inline long calc_tg_weight(struct task_group *tg, struct cfs_rq *cfs_rq)
         * to gain a more accurate current total weight. See
         * update_cfs_rq_load_contribution().
         */
-       tg_weight = atomic_read(&tg->load_weight);
-       tg_weight -= cfs_rq->load_contribution;
+       tg_weight = atomic64_read(&tg->load_avg);
+       tg_weight -= cfs_rq->tg_load_contrib;
        tg_weight += cfs_rq->load.weight;
 
        return tg_weight;
@@ -901,27 +1089,11 @@ static long calc_cfs_shares(struct cfs_rq *cfs_rq, struct task_group *tg)
 
        return shares;
 }
-
-static void update_entity_shares_tick(struct cfs_rq *cfs_rq)
-{
-       if (cfs_rq->load_unacc_exec_time > sysctl_sched_shares_window) {
-               update_cfs_load(cfs_rq, 0);
-               update_cfs_shares(cfs_rq);
-       }
-}
 # else /* CONFIG_SMP */
-static void update_cfs_load(struct cfs_rq *cfs_rq, int global_update)
-{
-}
-
 static inline long calc_cfs_shares(struct cfs_rq *cfs_rq, struct task_group *tg)
 {
        return tg->shares;
 }
-
-static inline void update_entity_shares_tick(struct cfs_rq *cfs_rq)
-{
-}
 # endif /* CONFIG_SMP */
 static void reweight_entity(struct cfs_rq *cfs_rq, struct sched_entity *se,
                            unsigned long weight)
@@ -939,6 +1111,8 @@ static void reweight_entity(struct cfs_rq *cfs_rq, struct sched_entity *se,
                account_entity_enqueue(cfs_rq, se);
 }
 
+static inline int throttled_hierarchy(struct cfs_rq *cfs_rq);
+
 static void update_cfs_shares(struct cfs_rq *cfs_rq)
 {
        struct task_group *tg;
@@ -958,18 +1132,478 @@ static void update_cfs_shares(struct cfs_rq *cfs_rq)
        reweight_entity(cfs_rq_of(se), se, shares);
 }
 #else /* CONFIG_FAIR_GROUP_SCHED */
-static void update_cfs_load(struct cfs_rq *cfs_rq, int global_update)
+static inline void update_cfs_shares(struct cfs_rq *cfs_rq)
 {
 }
+#endif /* CONFIG_FAIR_GROUP_SCHED */
 
-static inline void update_cfs_shares(struct cfs_rq *cfs_rq)
+/* Only depends on SMP, FAIR_GROUP_SCHED may be removed when useful in lb */
+#if defined(CONFIG_SMP) && defined(CONFIG_FAIR_GROUP_SCHED)
+/*
+ * We choose a half-life close to 1 scheduling period.
+ * Note: The tables below are dependent on this value.
+ */
+#define LOAD_AVG_PERIOD 32
+#define LOAD_AVG_MAX 47742 /* maximum possible load avg */
+#define LOAD_AVG_MAX_N 345 /* number of full periods to produce LOAD_MAX_AVG */
+
+/* Precomputed fixed inverse multiplies for multiplication by y^n */
+static const u32 runnable_avg_yN_inv[] = {
+       0xffffffff, 0xfa83b2da, 0xf5257d14, 0xefe4b99a, 0xeac0c6e6, 0xe5b906e6,
+       0xe0ccdeeb, 0xdbfbb796, 0xd744fcc9, 0xd2a81d91, 0xce248c14, 0xc9b9bd85,
+       0xc5672a10, 0xc12c4cc9, 0xbd08a39e, 0xb8fbaf46, 0xb504f333, 0xb123f581,
+       0xad583ee9, 0xa9a15ab4, 0xa5fed6a9, 0xa2704302, 0x9ef5325f, 0x9b8d39b9,
+       0x9837f050, 0x94f4efa8, 0x91c3d373, 0x8ea4398a, 0x8b95c1e3, 0x88980e80,
+       0x85aac367, 0x82cd8698,
+};
+
+/*
+ * Precomputed \Sum y^k { 1<=k<=n }.  These are floor(true_value) to prevent
+ * over-estimates when re-combining.
+ */
+static const u32 runnable_avg_yN_sum[] = {
+           0, 1002, 1982, 2941, 3880, 4798, 5697, 6576, 7437, 8279, 9103,
+        9909,10698,11470,12226,12966,13690,14398,15091,15769,16433,17082,
+       17718,18340,18949,19545,20128,20698,21256,21802,22336,22859,23371,
+};
+
+/*
+ * Approximate:
+ *   val * y^n,    where y^32 ~= 0.5 (~1 scheduling period)
+ */
+static __always_inline u64 decay_load(u64 val, u64 n)
 {
+       unsigned int local_n;
+
+       if (!n)
+               return val;
+       else if (unlikely(n > LOAD_AVG_PERIOD * 63))
+               return 0;
+
+       /* after bounds checking we can collapse to 32-bit */
+       local_n = n;
+
+       /*
+        * As y^PERIOD = 1/2, we can combine
+        *    y^n = 1/2^(n/PERIOD) * k^(n%PERIOD)
+        * With a look-up table which covers k^n (n<PERIOD)
+        *
+        * To achieve constant time decay_load.
+        */
+       if (unlikely(local_n >= LOAD_AVG_PERIOD)) {
+               val >>= local_n / LOAD_AVG_PERIOD;
+               local_n %= LOAD_AVG_PERIOD;
+       }
+
+       val *= runnable_avg_yN_inv[local_n];
+       /* We don't use SRR here since we always want to round down. */
+       return val >> 32;
 }
 
-static inline void update_entity_shares_tick(struct cfs_rq *cfs_rq)
+/*
+ * For updates fully spanning n periods, the contribution to runnable
+ * average will be: \Sum 1024*y^n
+ *
+ * We can compute this reasonably efficiently by combining:
+ *   y^PERIOD = 1/2 with precomputed \Sum 1024*y^n {for  n <PERIOD}
+ */
+static u32 __compute_runnable_contrib(u64 n)
 {
+       u32 contrib = 0;
+
+       if (likely(n <= LOAD_AVG_PERIOD))
+               return runnable_avg_yN_sum[n];
+       else if (unlikely(n >= LOAD_AVG_MAX_N))
+               return LOAD_AVG_MAX;
+
+       /* Compute \Sum k^n combining precomputed values for k^i, \Sum k^j */
+       do {
+               contrib /= 2; /* y^LOAD_AVG_PERIOD = 1/2 */
+               contrib += runnable_avg_yN_sum[LOAD_AVG_PERIOD];
+
+               n -= LOAD_AVG_PERIOD;
+       } while (n > LOAD_AVG_PERIOD);
+
+       contrib = decay_load(contrib, n);
+       return contrib + runnable_avg_yN_sum[n];
 }
-#endif /* CONFIG_FAIR_GROUP_SCHED */
+
+/*
+ * We can represent the historical contribution to runnable average as the
+ * coefficients of a geometric series.  To do this we sub-divide our runnable
+ * history into segments of approximately 1ms (1024us); label the segment that
+ * occurred N-ms ago p_N, with p_0 corresponding to the current period, e.g.
+ *
+ * [<- 1024us ->|<- 1024us ->|<- 1024us ->| ...
+ *      p0            p1           p2
+ *     (now)       (~1ms ago)  (~2ms ago)
+ *
+ * Let u_i denote the fraction of p_i that the entity was runnable.
+ *
+ * We then designate the fractions u_i as our co-efficients, yielding the
+ * following representation of historical load:
+ *   u_0 + u_1*y + u_2*y^2 + u_3*y^3 + ...
+ *
+ * We choose y based on the with of a reasonably scheduling period, fixing:
+ *   y^32 = 0.5
+ *
+ * This means that the contribution to load ~32ms ago (u_32) will be weighted
+ * approximately half as much as the contribution to load within the last ms
+ * (u_0).
+ *
+ * When a period "rolls over" and we have new u_0`, multiplying the previous
+ * sum again by y is sufficient to update:
+ *   load_avg = u_0` + y*(u_0 + u_1*y + u_2*y^2 + ... )
+ *            = u_0 + u_1*y + u_2*y^2 + ... [re-labeling u_i --> u_{i+1}]
+ */
+static __always_inline int __update_entity_runnable_avg(u64 now,
+                                                       struct sched_avg *sa,
+                                                       int runnable)
+{
+       u64 delta, periods;
+       u32 runnable_contrib;
+       int delta_w, decayed = 0;
+
+       delta = now - sa->last_runnable_update;
+       /*
+        * This should only happen when time goes backwards, which it
+        * unfortunately does during sched clock init when we swap over to TSC.
+        */
+       if ((s64)delta < 0) {
+               sa->last_runnable_update = now;
+               return 0;
+       }
+
+       /*
+        * Use 1024ns as the unit of measurement since it's a reasonable
+        * approximation of 1us and fast to compute.
+        */
+       delta >>= 10;
+       if (!delta)
+               return 0;
+       sa->last_runnable_update = now;
+
+       /* delta_w is the amount already accumulated against our next period */
+       delta_w = sa->runnable_avg_period % 1024;
+       if (delta + delta_w >= 1024) {
+               /* period roll-over */
+               decayed = 1;
+
+               /*
+                * Now that we know we're crossing a period boundary, figure
+                * out how much from delta we need to complete the current
+                * period and accrue it.
+                */
+               delta_w = 1024 - delta_w;
+               if (runnable)
+                       sa->runnable_avg_sum += delta_w;
+               sa->runnable_avg_period += delta_w;
+
+               delta -= delta_w;
+
+               /* Figure out how many additional periods this update spans */
+               periods = delta / 1024;
+               delta %= 1024;
+
+               sa->runnable_avg_sum = decay_load(sa->runnable_avg_sum,
+                                                 periods + 1);
+               sa->runnable_avg_period = decay_load(sa->runnable_avg_period,
+                                                    periods + 1);
+
+               /* Efficiently calculate \sum (1..n_period) 1024*y^i */
+               runnable_contrib = __compute_runnable_contrib(periods);
+               if (runnable)
+                       sa->runnable_avg_sum += runnable_contrib;
+               sa->runnable_avg_period += runnable_contrib;
+       }
+
+       /* Remainder of delta accrued against u_0` */
+       if (runnable)
+               sa->runnable_avg_sum += delta;
+       sa->runnable_avg_period += delta;
+
+       return decayed;
+}
+
+/* Synchronize an entity's decay with its parenting cfs_rq.*/
+static inline u64 __synchronize_entity_decay(struct sched_entity *se)
+{
+       struct cfs_rq *cfs_rq = cfs_rq_of(se);
+       u64 decays = atomic64_read(&cfs_rq->decay_counter);
+
+       decays -= se->avg.decay_count;
+       if (!decays)
+               return 0;
+
+       se->avg.load_avg_contrib = decay_load(se->avg.load_avg_contrib, decays);
+       se->avg.decay_count = 0;
+
+       return decays;
+}
+
+#ifdef CONFIG_FAIR_GROUP_SCHED
+static inline void __update_cfs_rq_tg_load_contrib(struct cfs_rq *cfs_rq,
+                                                int force_update)
+{
+       struct task_group *tg = cfs_rq->tg;
+       s64 tg_contrib;
+
+       tg_contrib = cfs_rq->runnable_load_avg + cfs_rq->blocked_load_avg;
+       tg_contrib -= cfs_rq->tg_load_contrib;
+
+       if (force_update || abs64(tg_contrib) > cfs_rq->tg_load_contrib / 8) {
+               atomic64_add(tg_contrib, &tg->load_avg);
+               cfs_rq->tg_load_contrib += tg_contrib;
+       }
+}
+
+/*
+ * Aggregate cfs_rq runnable averages into an equivalent task_group
+ * representation for computing load contributions.
+ */
+static inline void __update_tg_runnable_avg(struct sched_avg *sa,
+                                                 struct cfs_rq *cfs_rq)
+{
+       struct task_group *tg = cfs_rq->tg;
+       long contrib;
+
+       /* The fraction of a cpu used by this cfs_rq */
+       contrib = div_u64(sa->runnable_avg_sum << NICE_0_SHIFT,
+                         sa->runnable_avg_period + 1);
+       contrib -= cfs_rq->tg_runnable_contrib;
+
+       if (abs(contrib) > cfs_rq->tg_runnable_contrib / 64) {
+               atomic_add(contrib, &tg->runnable_avg);
+               cfs_rq->tg_runnable_contrib += contrib;
+       }
+}
+
+static inline void __update_group_entity_contrib(struct sched_entity *se)
+{
+       struct cfs_rq *cfs_rq = group_cfs_rq(se);
+       struct task_group *tg = cfs_rq->tg;
+       int runnable_avg;
+
+       u64 contrib;
+
+       contrib = cfs_rq->tg_load_contrib * tg->shares;
+       se->avg.load_avg_contrib = div64_u64(contrib,
+                                            atomic64_read(&tg->load_avg) + 1);
+
+       /*
+        * For group entities we need to compute a correction term in the case
+        * that they are consuming <1 cpu so that we would contribute the same
+        * load as a task of equal weight.
+        *
+        * Explicitly co-ordinating this measurement would be expensive, but
+        * fortunately the sum of each cpus contribution forms a usable
+        * lower-bound on the true value.
+        *
+        * Consider the aggregate of 2 contributions.  Either they are disjoint
+        * (and the sum represents true value) or they are disjoint and we are
+        * understating by the aggregate of their overlap.
+        *
+        * Extending this to N cpus, for a given overlap, the maximum amount we
+        * understand is then n_i(n_i+1)/2 * w_i where n_i is the number of
+        * cpus that overlap for this interval and w_i is the interval width.
+        *
+        * On a small machine; the first term is well-bounded which bounds the
+        * total error since w_i is a subset of the period.  Whereas on a
+        * larger machine, while this first term can be larger, if w_i is the
+        * of consequential size guaranteed to see n_i*w_i quickly converge to
+        * our upper bound of 1-cpu.
+        */
+       runnable_avg = atomic_read(&tg->runnable_avg);
+       if (runnable_avg < NICE_0_LOAD) {
+               se->avg.load_avg_contrib *= runnable_avg;
+               se->avg.load_avg_contrib >>= NICE_0_SHIFT;
+       }
+}
+#else
+static inline void __update_cfs_rq_tg_load_contrib(struct cfs_rq *cfs_rq,
+                                                int force_update) {}
+static inline void __update_tg_runnable_avg(struct sched_avg *sa,
+                                                 struct cfs_rq *cfs_rq) {}
+static inline void __update_group_entity_contrib(struct sched_entity *se) {}
+#endif
+
+static inline void __update_task_entity_contrib(struct sched_entity *se)
+{
+       u32 contrib;
+
+       /* avoid overflowing a 32-bit type w/ SCHED_LOAD_SCALE */
+       contrib = se->avg.runnable_avg_sum * scale_load_down(se->load.weight);
+       contrib /= (se->avg.runnable_avg_period + 1);
+       se->avg.load_avg_contrib = scale_load(contrib);
+}
+
+/* Compute the current contribution to load_avg by se, return any delta */
+static long __update_entity_load_avg_contrib(struct sched_entity *se)
+{
+       long old_contrib = se->avg.load_avg_contrib;
+
+       if (entity_is_task(se)) {
+               __update_task_entity_contrib(se);
+       } else {
+               __update_tg_runnable_avg(&se->avg, group_cfs_rq(se));
+               __update_group_entity_contrib(se);
+       }
+
+       return se->avg.load_avg_contrib - old_contrib;
+}
+
+static inline void subtract_blocked_load_contrib(struct cfs_rq *cfs_rq,
+                                                long load_contrib)
+{
+       if (likely(load_contrib < cfs_rq->blocked_load_avg))
+               cfs_rq->blocked_load_avg -= load_contrib;
+       else
+               cfs_rq->blocked_load_avg = 0;
+}
+
+static inline u64 cfs_rq_clock_task(struct cfs_rq *cfs_rq);
+
+/* Update a sched_entity's runnable average */
+static inline void update_entity_load_avg(struct sched_entity *se,
+                                         int update_cfs_rq)
+{
+       struct cfs_rq *cfs_rq = cfs_rq_of(se);
+       long contrib_delta;
+       u64 now;
+
+       /*
+        * For a group entity we need to use their owned cfs_rq_clock_task() in
+        * case they are the parent of a throttled hierarchy.
+        */
+       if (entity_is_task(se))
+               now = cfs_rq_clock_task(cfs_rq);
+       else
+               now = cfs_rq_clock_task(group_cfs_rq(se));
+
+       if (!__update_entity_runnable_avg(now, &se->avg, se->on_rq))
+               return;
+
+       contrib_delta = __update_entity_load_avg_contrib(se);
+
+       if (!update_cfs_rq)
+               return;
+
+       if (se->on_rq)
+               cfs_rq->runnable_load_avg += contrib_delta;
+       else
+               subtract_blocked_load_contrib(cfs_rq, -contrib_delta);
+}
+
+/*
+ * Decay the load contributed by all blocked children and account this so that
+ * their contribution may appropriately discounted when they wake up.
+ */
+static void update_cfs_rq_blocked_load(struct cfs_rq *cfs_rq, int force_update)
+{
+       u64 now = cfs_rq_clock_task(cfs_rq) >> 20;
+       u64 decays;
+
+       decays = now - cfs_rq->last_decay;
+       if (!decays && !force_update)
+               return;
+
+       if (atomic64_read(&cfs_rq->removed_load)) {
+               u64 removed_load = atomic64_xchg(&cfs_rq->removed_load, 0);
+               subtract_blocked_load_contrib(cfs_rq, removed_load);
+       }
+
+       if (decays) {
+               cfs_rq->blocked_load_avg = decay_load(cfs_rq->blocked_load_avg,
+                                                     decays);
+               atomic64_add(decays, &cfs_rq->decay_counter);
+               cfs_rq->last_decay = now;
+       }
+
+       __update_cfs_rq_tg_load_contrib(cfs_rq, force_update);
+       update_cfs_shares(cfs_rq);
+}
+
+static inline void update_rq_runnable_avg(struct rq *rq, int runnable)
+{
+       __update_entity_runnable_avg(rq->clock_task, &rq->avg, runnable);
+       __update_tg_runnable_avg(&rq->avg, &rq->cfs);
+}
+
+/* Add the load generated by se into cfs_rq's child load-average */
+static inline void enqueue_entity_load_avg(struct cfs_rq *cfs_rq,
+                                                 struct sched_entity *se,
+                                                 int wakeup)
+{
+       /*
+        * We track migrations using entity decay_count <= 0, on a wake-up
+        * migration we use a negative decay count to track the remote decays
+        * accumulated while sleeping.
+        */
+       if (unlikely(se->avg.decay_count <= 0)) {
+               se->avg.last_runnable_update = rq_of(cfs_rq)->clock_task;
+               if (se->avg.decay_count) {
+                       /*
+                        * In a wake-up migration we have to approximate the
+                        * time sleeping.  This is because we can't synchronize
+                        * clock_task between the two cpus, and it is not
+                        * guaranteed to be read-safe.  Instead, we can
+                        * approximate this using our carried decays, which are
+                        * explicitly atomically readable.
+                        */
+                       se->avg.last_runnable_update -= (-se->avg.decay_count)
+                                                       << 20;
+                       update_entity_load_avg(se, 0);
+                       /* Indicate that we're now synchronized and on-rq */
+                       se->avg.decay_count = 0;
+               }
+               wakeup = 0;
+       } else {
+               __synchronize_entity_decay(se);
+       }
+
+       /* migrated tasks did not contribute to our blocked load */
+       if (wakeup) {
+               subtract_blocked_load_contrib(cfs_rq, se->avg.load_avg_contrib);
+               update_entity_load_avg(se, 0);
+       }
+
+       cfs_rq->runnable_load_avg += se->avg.load_avg_contrib;
+       /* we force update consideration on load-balancer moves */
+       update_cfs_rq_blocked_load(cfs_rq, !wakeup);
+}
+
+/*
+ * Remove se's load from this cfs_rq child load-average, if the entity is
+ * transitioning to a blocked state we track its projected decay using
+ * blocked_load_avg.
+ */
+static inline void dequeue_entity_load_avg(struct cfs_rq *cfs_rq,
+                                                 struct sched_entity *se,
+                                                 int sleep)
+{
+       update_entity_load_avg(se, 1);
+       /* we force update consideration on load-balancer moves */
+       update_cfs_rq_blocked_load(cfs_rq, !sleep);
+
+       cfs_rq->runnable_load_avg -= se->avg.load_avg_contrib;
+       if (sleep) {
+               cfs_rq->blocked_load_avg += se->avg.load_avg_contrib;
+               se->avg.decay_count = atomic64_read(&cfs_rq->decay_counter);
+       } /* migrations, e.g. sleep=0 leave decay_count == 0 */
+}
+#else
+static inline void update_entity_load_avg(struct sched_entity *se,
+                                         int update_cfs_rq) {}
+static inline void update_rq_runnable_avg(struct rq *rq, int runnable) {}
+static inline void enqueue_entity_load_avg(struct cfs_rq *cfs_rq,
+                                          struct sched_entity *se,
+                                          int wakeup) {}
+static inline void dequeue_entity_load_avg(struct cfs_rq *cfs_rq,
+                                          struct sched_entity *se,
+                                          int sleep) {}
+static inline void update_cfs_rq_blocked_load(struct cfs_rq *cfs_rq,
+                                             int force_update) {}
+#endif
 
 static void enqueue_sleeper(struct cfs_rq *cfs_rq, struct sched_entity *se)
 {
@@ -1096,9 +1730,8 @@ enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int flags)
         * Update run-time statistics of the 'current'.
         */
        update_curr(cfs_rq);
-       update_cfs_load(cfs_rq, 0);
        account_entity_enqueue(cfs_rq, se);
-       update_cfs_shares(cfs_rq);
+       enqueue_entity_load_avg(cfs_rq, se, flags & ENQUEUE_WAKEUP);
 
        if (flags & ENQUEUE_WAKEUP) {
                place_entity(cfs_rq, se, 0);
@@ -1190,9 +1823,8 @@ dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int flags)
 
        if (se != cfs_rq->curr)
                __dequeue_entity(cfs_rq, se);
-       se->on_rq = 0;
-       update_cfs_load(cfs_rq, 0);
        account_entity_dequeue(cfs_rq, se);
+       dequeue_entity_load_avg(cfs_rq, se, flags & DEQUEUE_SLEEP);
 
        /*
         * Normalize the entity after updating the min_vruntime because the
@@ -1206,7 +1838,7 @@ dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int flags)
        return_cfs_rq_runtime(cfs_rq);
 
        update_min_vruntime(cfs_rq);
-       update_cfs_shares(cfs_rq);
+       se->on_rq = 0;
 }
 
 /*
@@ -1340,6 +1972,8 @@ static void put_prev_entity(struct cfs_rq *cfs_rq, struct sched_entity *prev)
                update_stats_wait_start(cfs_rq, prev);
                /* Put 'current' back into the tree. */
                __enqueue_entity(cfs_rq, prev);
+               /* in !on_rq case, update occurred at dequeue */
+               update_entity_load_avg(prev, 1);
        }
        cfs_rq->curr = NULL;
 }
@@ -1353,9 +1987,10 @@ entity_tick(struct cfs_rq *cfs_rq, struct sched_entity *curr, int queued)
        update_curr(cfs_rq);
 
        /*
-        * Update share accounting for long-running entities.
+        * Ensure that runnable average is periodically updated.
         */
-       update_entity_shares_tick(cfs_rq);
+       update_entity_load_avg(curr, 1);
+       update_cfs_rq_blocked_load(cfs_rq, 1);
 
 #ifdef CONFIG_SCHED_HRTICK
        /*
@@ -1448,6 +2083,15 @@ static inline struct cfs_bandwidth *tg_cfs_bandwidth(struct task_group *tg)
        return &tg->cfs_bandwidth;
 }
 
+/* rq->task_clock normalized against any time this cfs_rq has spent throttled */
+static inline u64 cfs_rq_clock_task(struct cfs_rq *cfs_rq)
+{
+       if (unlikely(cfs_rq->throttle_count))
+               return cfs_rq->throttled_clock_task;
+
+       return rq_of(cfs_rq)->clock_task - cfs_rq->throttled_clock_task_time;
+}
+
 /* returns 0 on failure to allocate runtime */
 static int assign_cfs_rq_runtime(struct cfs_rq *cfs_rq)
 {
@@ -1591,15 +2235,10 @@ static int tg_unthrottle_up(struct task_group *tg, void *data)
 
        cfs_rq->throttle_count--;
 #ifdef CONFIG_SMP
-       if (!cfs_rq->throttle_count) {
-               u64 delta = rq->clock_task - cfs_rq->load_stamp;
-
-               /* leaving throttled state, advance shares averaging windows */
-               cfs_rq->load_stamp += delta;
-               cfs_rq->load_last += delta;
-
-               /* update entity weight now that we are on_rq again */
-               update_cfs_shares(cfs_rq);
+       if (!cfs_rq->throttle_count) {
+               /* adjust cfs_rq_clock_task() */
+               cfs_rq->throttled_clock_task_time += rq->clock_task -
+                                            cfs_rq->throttled_clock_task;
        }
 #endif
 
@@ -1611,9 +2250,9 @@ static int tg_throttle_down(struct task_group *tg, void *data)
        struct rq *rq = data;
        struct cfs_rq *cfs_rq = tg->cfs_rq[cpu_of(rq)];
 
-       /* group is entering throttled state, record last load */
+       /* group is entering throttled state, stop time */
        if (!cfs_rq->throttle_count)
-               update_cfs_load(cfs_rq, 0);
+               cfs_rq->throttled_clock_task = rq->clock_task;
        cfs_rq->throttle_count++;
 
        return 0;
@@ -1628,7 +2267,7 @@ static void throttle_cfs_rq(struct cfs_rq *cfs_rq)
 
        se = cfs_rq->tg->se[cpu_of(rq_of(cfs_rq))];
 
-       /* account load preceding throttle */
+       /* freeze hierarchy runnable averages while throttled */
        rcu_read_lock();
        walk_tg_tree_from(cfs_rq->tg, tg_throttle_down, tg_nop, (void *)rq);
        rcu_read_unlock();
@@ -1652,7 +2291,7 @@ static void throttle_cfs_rq(struct cfs_rq *cfs_rq)
                rq->nr_running -= task_delta;
 
        cfs_rq->throttled = 1;
-       cfs_rq->throttled_timestamp = rq->clock;
+       cfs_rq->throttled_clock = rq->clock;
        raw_spin_lock(&cfs_b->lock);
        list_add_tail_rcu(&cfs_rq->throttled_list, &cfs_b->throttled_cfs_rq);
        raw_spin_unlock(&cfs_b->lock);
@@ -1670,10 +2309,9 @@ void unthrottle_cfs_rq(struct cfs_rq *cfs_rq)
 
        cfs_rq->throttled = 0;
        raw_spin_lock(&cfs_b->lock);
-       cfs_b->throttled_time += rq->clock - cfs_rq->throttled_timestamp;
+       cfs_b->throttled_time += rq->clock - cfs_rq->throttled_clock;
        list_del_rcu(&cfs_rq->throttled_list);
        raw_spin_unlock(&cfs_b->lock);
-       cfs_rq->throttled_timestamp = 0;
 
        update_rq_clock(rq);
        /* update hierarchical throttle state */
@@ -2073,8 +2711,13 @@ static void unthrottle_offline_cfs_rqs(struct rq *rq)
 }
 
 #else /* CONFIG_CFS_BANDWIDTH */
-static __always_inline
-void account_cfs_rq_runtime(struct cfs_rq *cfs_rq, unsigned long delta_exec) {}
+static inline u64 cfs_rq_clock_task(struct cfs_rq *cfs_rq)
+{
+       return rq_of(cfs_rq)->clock_task;
+}
+
+static void account_cfs_rq_runtime(struct cfs_rq *cfs_rq,
+                                    unsigned long delta_exec) {}
 static void check_cfs_rq_runtime(struct cfs_rq *cfs_rq) {}
 static void check_enqueue_throttle(struct cfs_rq *cfs_rq) {}
 static __always_inline void return_cfs_rq_runtime(struct cfs_rq *cfs_rq) {}
@@ -2207,12 +2850,14 @@ enqueue_task_fair(struct rq *rq, struct task_struct *p, int flags)
                if (cfs_rq_throttled(cfs_rq))
                        break;
 
-               update_cfs_load(cfs_rq, 0);
-               update_cfs_shares(cfs_rq);
+               update_entity_load_avg(se, 1);
+               update_cfs_rq_blocked_load(cfs_rq, 0);
        }
 
-       if (!se)
+       if (!se) {
+               update_rq_runnable_avg(rq, rq->nr_running);
                inc_nr_running(rq);
+       }
        hrtick_update(rq);
 }
 
@@ -2266,12 +2911,14 @@ static void dequeue_task_fair(struct rq *rq, struct task_struct *p, int flags)
                if (cfs_rq_throttled(cfs_rq))
                        break;
 
-               update_cfs_load(cfs_rq, 0);
-               update_cfs_shares(cfs_rq);
+               update_entity_load_avg(se, 1);
+               update_cfs_rq_blocked_load(cfs_rq, 0);
        }
 
-       if (!se)
+       if (!se) {
                dec_nr_running(rq);
+               update_rq_runnable_avg(rq, 1);
+       }
        hrtick_update(rq);
 }
 
@@ -2681,6 +3328,35 @@ done:
        return target;
 }
 
+#ifdef CONFIG_SCHED_NUMA
+static inline bool pick_numa_rand(int n)
+{
+       return !(get_random_int() % n);
+}
+
+/*
+ * Pick a random elegible CPU in the target node, hopefully faster
+ * than doing a least-loaded scan.
+ */
+static int numa_select_node_cpu(struct task_struct *p, int node)
+{
+       int weight = cpumask_weight(cpumask_of_node(node));
+       int i, cpu = -1;
+
+       for_each_cpu_and(i, cpumask_of_node(node), tsk_cpus_allowed(p)) {
+               if (cpu < 0 || pick_numa_rand(weight))
+                       cpu = i;
+       }
+
+       return cpu;
+}
+#else
+static int numa_select_node_cpu(struct task_struct *p, int node)
+{
+       return -1;
+}
+#endif /* CONFIG_SCHED_NUMA */
+
 /*
  * sched_balance_self: balance the current task (running on cpu) in domains
  * that have the 'flag' flag set. In practice, this is SD_BALANCE_FORK and
@@ -2701,6 +3377,7 @@ select_task_rq_fair(struct task_struct *p, int sd_flag, int wake_flags)
        int new_cpu = cpu;
        int want_affine = 0;
        int sync = wake_flags & WF_SYNC;
+       int node = tsk_home_node(p);
 
        if (p->nr_cpus_allowed == 1)
                return prev_cpu;
@@ -2712,6 +3389,36 @@ select_task_rq_fair(struct task_struct *p, int sd_flag, int wake_flags)
        }
 
        rcu_read_lock();
+       if (sched_feat_numa(NUMA_TTWU_BIAS) && node != -1) {
+               /*
+                * For fork,exec find the idlest cpu in the home-node.
+                */
+               if (sd_flag & (SD_BALANCE_FORK|SD_BALANCE_EXEC)) {
+                       int node_cpu = numa_select_node_cpu(p, node);
+                       if (node_cpu < 0)
+                               goto find_sd;
+
+                       new_cpu = cpu = node_cpu;
+                       sd = per_cpu(sd_node, cpu);
+                       goto pick_idlest;
+               }
+
+               /*
+                * For wake, pretend we were running in the home-node.
+                */
+               if (cpu_to_node(prev_cpu) != node) {
+                       int node_cpu = numa_select_node_cpu(p, node);
+                       if (node_cpu < 0)
+                               goto find_sd;
+
+                       if (sched_feat_numa(NUMA_TTWU_TO))
+                               cpu = node_cpu;
+                       else
+                               prev_cpu = node_cpu;
+               }
+       }
+
+find_sd:
        for_each_domain(cpu, tmp) {
                if (!(tmp->flags & SD_LOAD_BALANCE))
                        continue;
@@ -2738,6 +3445,7 @@ select_task_rq_fair(struct task_struct *p, int sd_flag, int wake_flags)
                goto unlock;
        }
 
+pick_idlest:
        while (sd) {
                int load_idx = sd->forkexec_idx;
                struct sched_group *group;
@@ -2781,6 +3489,37 @@ unlock:
 
        return new_cpu;
 }
+
+/*
+ * Load-tracking only depends on SMP, FAIR_GROUP_SCHED dependency below may be
+ * removed when useful for applications beyond shares distribution (e.g.
+ * load-balance).
+ */
+#ifdef CONFIG_FAIR_GROUP_SCHED
+/*
+ * Called immediately before a task is migrated to a new cpu; task_cpu(p) and
+ * cfs_rq_of(p) references at time of call are still valid and identify the
+ * previous cpu.  However, the caller only guarantees p->pi_lock is held; no
+ * other assumptions, including the state of rq->lock, should be made.
+ */
+static void
+migrate_task_rq_fair(struct task_struct *p, int next_cpu)
+{
+       struct sched_entity *se = &p->se;
+       struct cfs_rq *cfs_rq = cfs_rq_of(se);
+
+       /*
+        * Load tracking: accumulate removed load so that it can be processed
+        * when we next update owning cfs_rq under rq->lock.  Tasks contribute
+        * to blocked load iff they have a positive decay-count.  It can never
+        * be negative here since on-rq tasks have decay-count == 0.
+        */
+       if (se->avg.decay_count) {
+               se->avg.decay_count = -__synchronize_entity_decay(se);
+               atomic64_add(se->avg.load_avg_contrib, &cfs_rq->removed_load);
+       }
+}
+#endif
 #endif /* CONFIG_SMP */
 
 static unsigned long
@@ -2907,7 +3646,7 @@ static void check_preempt_wakeup(struct rq *rq, struct task_struct *p, int wake_
         * Batch and idle tasks do not preempt non-idle tasks (their preemption
         * is driven by the tick):
         */
-       if (unlikely(p->policy != SCHED_NORMAL))
+       if (unlikely(p->policy != SCHED_NORMAL) || !sched_feat(WAKEUP_PREEMPTION))
                return;
 
        find_matching_se(&se, &pse);
@@ -3033,8 +3772,122 @@ static bool yield_to_task_fair(struct rq *rq, struct task_struct *p, bool preemp
 
 #ifdef CONFIG_SMP
 /**************************************************
- * Fair scheduling class load-balancing methods:
- */
+ * Fair scheduling class load-balancing methods.
+ *
+ * BASICS
+ *
+ * The purpose of load-balancing is to achieve the same basic fairness the
+ * per-cpu scheduler provides, namely provide a proportional amount of compute
+ * time to each task. This is expressed in the following equation:
+ *
+ *   W_i,n/P_i == W_j,n/P_j for all i,j                               (1)
+ *
+ * Where W_i,n is the n-th weight average for cpu i. The instantaneous weight
+ * W_i,0 is defined as:
+ *
+ *   W_i,0 = \Sum_j w_i,j                                             (2)
+ *
+ * Where w_i,j is the weight of the j-th runnable task on cpu i. This weight
+ * is derived from the nice value as per prio_to_weight[].
+ *
+ * The weight average is an exponential decay average of the instantaneous
+ * weight:
+ *
+ *   W'_i,n = (2^n - 1) / 2^n * W_i,n + 1 / 2^n * W_i,0               (3)
+ *
+ * P_i is the cpu power (or compute capacity) of cpu i, typically it is the
+ * fraction of 'recent' time available for SCHED_OTHER task execution. But it
+ * can also include other factors [XXX].
+ *
+ * To achieve this balance we define a measure of imbalance which follows
+ * directly from (1):
+ *
+ *   imb_i,j = max{ avg(W/P), W_i/P_i } - min{ avg(W/P), W_j/P_j }    (4)
+ *
+ * We them move tasks around to minimize the imbalance. In the continuous
+ * function space it is obvious this converges, in the discrete case we get
+ * a few fun cases generally called infeasible weight scenarios.
+ *
+ * [XXX expand on:
+ *     - infeasible weights;
+ *     - local vs global optima in the discrete case. ]
+ *
+ *
+ * SCHED DOMAINS
+ *
+ * In order to solve the imbalance equation (4), and avoid the obvious O(n^2)
+ * for all i,j solution, we create a tree of cpus that follows the hardware
+ * topology where each level pairs two lower groups (or better). This results
+ * in O(log n) layers. Furthermore we reduce the number of cpus going up the
+ * tree to only the first of the previous level and we decrease the frequency
+ * of load-balance at each level inv. proportional to the number of cpus in
+ * the groups.
+ *
+ * This yields:
+ *
+ *     log_2 n     1     n
+ *   \Sum       { --- * --- * 2^i } = O(n)                            (5)
+ *     i = 0      2^i   2^i
+ *                               `- size of each group
+ *         |         |     `- number of cpus doing load-balance
+ *         |         `- freq
+ *         `- sum over all levels
+ *
+ * Coupled with a limit on how many tasks we can migrate every balance pass,
+ * this makes (5) the runtime complexity of the balancer.
+ *
+ * An important property here is that each CPU is still (indirectly) connected
+ * to every other cpu in at most O(log n) steps:
+ *
+ * The adjacency matrix of the resulting graph is given by:
+ *
+ *             log_2 n     
+ *   A_i,j = \Union     (i % 2^k == 0) && i / 2^(k+1) == j / 2^(k+1)  (6)
+ *             k = 0
+ *
+ * And you'll find that:
+ *
+ *   A^(log_2 n)_i,j != 0  for all i,j                                (7)
+ *
+ * Showing there's indeed a path between every cpu in at most O(log n) steps.
+ * The task movement gives a factor of O(m), giving a convergence complexity
+ * of:
+ *
+ *   O(nm log n),  n := nr_cpus, m := nr_tasks                        (8)
+ *
+ *
+ * WORK CONSERVING
+ *
+ * In order to avoid CPUs going idle while there's still work to do, new idle
+ * balancing is more aggressive and has the newly idle cpu iterate up the domain
+ * tree itself instead of relying on other CPUs to bring it work.
+ *
+ * This adds some complexity to both (5) and (8) but it reduces the total idle
+ * time.
+ *
+ * [XXX more?]
+ *
+ *
+ * CGROUPS
+ *
+ * Cgroups make a horror show out of (2), instead of a simple sum we get:
+ *
+ *                                s_k,i
+ *   W_i,0 = \Sum_j \Prod_k w_k * -----                               (9)
+ *                                 S_k
+ *
+ * Where
+ *
+ *   s_k,i = \Sum_j w_i,j,k  and  S_k = \Sum_i s_k,i                 (10)
+ *
+ * w_i,j,k is the weight of the j-th runnable task in the k-th cgroup on cpu i.
+ *
+ * The big problem is S_k, its a global sum needed to compute a local (W_i)
+ * property.
+ *
+ * [XXX write more on how we solve this.. _after_ merging pjt's patches that
+ *      rewrite all of this once again.]
+ */ 
 
 static unsigned long __read_mostly max_load_balance_interval = HZ/10;
 
@@ -3060,9 +3913,14 @@ struct lb_env {
 
        unsigned int            flags;
 
+       struct list_head        *tasks;
+
        unsigned int            loop;
        unsigned int            loop_break;
        unsigned int            loop_max;
+
+       struct rq *             (*find_busiest_queue)(struct lb_env *,
+                                                     struct sched_group *);
 };
 
 /*
@@ -3077,11 +3935,28 @@ static void move_task(struct task_struct *p, struct lb_env *env)
        check_preempt_curr(env->dst_rq, p, 0);
 }
 
+static int task_numa_hot(struct task_struct *p, struct lb_env *env)
+{
+       int from_dist, to_dist;
+       int node = tsk_home_node(p);
+
+       if (!sched_feat_numa(NUMA_HOT) || node == -1)
+               return 0; /* no node preference */
+
+       from_dist = node_distance(cpu_to_node(env->src_cpu), node);
+       to_dist = node_distance(cpu_to_node(env->dst_cpu), node);
+
+       if (to_dist < from_dist)
+               return 0; /* getting closer is ok */
+
+       return 1; /* stick to where we are */
+}
+
 /*
  * Is this task likely cache-hot:
  */
 static int
-task_hot(struct task_struct *p, u64 now, struct sched_domain *sd)
+task_hot(struct task_struct *p, struct lb_env *env)
 {
        s64 delta;
 
@@ -3104,7 +3979,7 @@ task_hot(struct task_struct *p, u64 now, struct sched_domain *sd)
        if (sysctl_sched_migration_cost == 0)
                return 0;
 
-       delta = now - p->se.exec_start;
+       delta = env->src_rq->clock_task - p->se.exec_start;
 
        return delta < (s64)sysctl_sched_migration_cost;
 }
@@ -3161,7 +4036,9 @@ int can_migrate_task(struct task_struct *p, struct lb_env *env)
         * 2) too many balance attempts have failed.
         */
 
-       tsk_cache_hot = task_hot(p, env->src_rq->clock_task, env->sd);
+       tsk_cache_hot = task_hot(p, env);
+       if (env->idle == CPU_NOT_IDLE)
+               tsk_cache_hot |= task_numa_hot(p, env);
        if (!tsk_cache_hot ||
                env->sd->nr_balance_failed > env->sd->cache_nice_tries) {
 #ifdef CONFIG_SCHEDSTATS
@@ -3187,11 +4064,11 @@ int can_migrate_task(struct task_struct *p, struct lb_env *env)
  *
  * Called with both runqueues locked.
  */
-static int move_one_task(struct lb_env *env)
+static int __move_one_task(struct lb_env *env)
 {
        struct task_struct *p, *n;
 
-       list_for_each_entry_safe(p, n, &env->src_rq->cfs_tasks, se.group_node) {
+       list_for_each_entry_safe(p, n, env->tasks, se.group_node) {
                if (throttled_lb_pair(task_group(p), env->src_rq->cpu, env->dst_cpu))
                        continue;
 
@@ -3210,7 +4087,20 @@ static int move_one_task(struct lb_env *env)
        return 0;
 }
 
-static unsigned long task_h_load(struct task_struct *p);
+static int move_one_task(struct lb_env *env)
+{
+       if (sched_feat_numa(NUMA_PULL)) {
+               env->tasks = offnode_tasks(env->src_rq);
+               if (__move_one_task(env))
+                       return 1;
+       }
+
+       env->tasks = &env->src_rq->cfs_tasks;
+       if (__move_one_task(env))
+               return 1;
+
+       return 0;
+}
 
 static const unsigned int sched_nr_migrate_break = 32;
 
@@ -3223,7 +4113,6 @@ static const unsigned int sched_nr_migrate_break = 32;
  */
 static int move_tasks(struct lb_env *env)
 {
-       struct list_head *tasks = &env->src_rq->cfs_tasks;
        struct task_struct *p;
        unsigned long load;
        int pulled = 0;
@@ -3231,8 +4120,9 @@ static int move_tasks(struct lb_env *env)
        if (env->imbalance <= 0)
                return 0;
 
-       while (!list_empty(tasks)) {
-               p = list_first_entry(tasks, struct task_struct, se.group_node);
+again:
+       while (!list_empty(env->tasks)) {
+               p = list_first_entry(env->tasks, struct task_struct, se.group_node);
 
                env->loop++;
                /* We've more or less seen every task there is, call it quits */
@@ -3243,7 +4133,7 @@ static int move_tasks(struct lb_env *env)
                if (env->loop > env->loop_break) {
                        env->loop_break += sched_nr_migrate_break;
                        env->flags |= LBF_NEED_BREAK;
-                       break;
+                       goto out;
                }
 
                if (throttled_lb_pair(task_group(p), env->src_cpu, env->dst_cpu))
@@ -3271,7 +4161,7 @@ static int move_tasks(struct lb_env *env)
                 * the critical section.
                 */
                if (env->idle == CPU_NEWLY_IDLE)
-                       break;
+                       goto out;
 #endif
 
                /*
@@ -3279,13 +4169,20 @@ static int move_tasks(struct lb_env *env)
                 * weighted load.
                 */
                if (env->imbalance <= 0)
-                       break;
+                       goto out;
 
                continue;
 next:
-               list_move_tail(&p->se.group_node, tasks);
+               list_move_tail(&p->se.group_node, env->tasks);
+       }
+
+       if (env->tasks == offnode_tasks(env->src_rq)) {
+               env->tasks = &env->src_rq->cfs_tasks;
+               env->loop = 0;
+               goto again;
        }
 
+out:
        /*
         * Right now, this is one of only two places move_task() is called,
         * so we can safely collect move_task() stats here rather than
@@ -3300,52 +4197,58 @@ next:
 /*
  * update tg->load_weight by folding this cpu's load_avg
  */
-static int update_shares_cpu(struct task_group *tg, int cpu)
+static void __update_blocked_averages_cpu(struct task_group *tg, int cpu)
 {
-       struct cfs_rq *cfs_rq;
-       unsigned long flags;
-       struct rq *rq;
-
-       if (!tg->se[cpu])
-               return 0;
-
-       rq = cpu_rq(cpu);
-       cfs_rq = tg->cfs_rq[cpu];
-
-       raw_spin_lock_irqsave(&rq->lock, flags);
-
-       update_rq_clock(rq);
-       update_cfs_load(cfs_rq, 1);
+       struct sched_entity *se = tg->se[cpu];
+       struct cfs_rq *cfs_rq = tg->cfs_rq[cpu];
 
-       /*
-        * We need to update shares after updating tg->load_weight in
-        * order to adjust the weight of groups with long running tasks.
-        */
-       update_cfs_shares(cfs_rq);
+       /* throttled entities do not contribute to load */
+       if (throttled_hierarchy(cfs_rq))
+               return;
 
-       raw_spin_unlock_irqrestore(&rq->lock, flags);
+       update_cfs_rq_blocked_load(cfs_rq, 1);
 
-       return 0;
+       if (se) {
+               update_entity_load_avg(se, 1);
+               /*
+                * We pivot on our runnable average having decayed to zero for
+                * list removal.  This generally implies that all our children
+                * have also been removed (modulo rounding error or bandwidth
+                * control); however, such cases are rare and we can fix these
+                * at enqueue.
+                *
+                * TODO: fix up out-of-order children on enqueue.
+                */
+               if (!se->avg.runnable_avg_sum && !cfs_rq->nr_running)
+                       list_del_leaf_cfs_rq(cfs_rq);
+       } else {
+               struct rq *rq = rq_of(cfs_rq);
+               update_rq_runnable_avg(rq, rq->nr_running);
+       }
 }
 
-static void update_shares(int cpu)
+static void update_blocked_averages(int cpu)
 {
-       struct cfs_rq *cfs_rq;
        struct rq *rq = cpu_rq(cpu);
+       struct cfs_rq *cfs_rq;
+       unsigned long flags;
 
-       rcu_read_lock();
+       raw_spin_lock_irqsave(&rq->lock, flags);
+       update_rq_clock(rq);
        /*
         * Iterates the task_group tree in a bottom up fashion, see
         * list_add_leaf_cfs_rq() for details.
         */
        for_each_leaf_cfs_rq(rq, cfs_rq) {
-               /* throttled entities do not contribute to load */
-               if (throttled_hierarchy(cfs_rq))
-                       continue;
-
-               update_shares_cpu(cfs_rq->tg, cpu);
+               /*
+                * Note: We may want to consider periodically releasing
+                * rq->lock about these updates so that creating many task
+                * groups does not result in continually extending hold time.
+                */
+               __update_blocked_averages_cpu(cfs_rq->tg, rq->cpu);
        }
-       rcu_read_unlock();
+
+       raw_spin_unlock_irqrestore(&rq->lock, flags);
 }
 
 /*
@@ -3397,19 +4300,20 @@ static unsigned long task_h_load(struct task_struct *p)
        return load;
 }
 #else
-static inline void update_shares(int cpu)
+static inline void update_blocked_averages(int cpu)
 {
 }
 
 static inline void update_h_load(long cpu)
 {
 }
-
+#ifdef CONFIG_SMP
 static unsigned long task_h_load(struct task_struct *p)
 {
        return p->se.load.weight;
 }
 #endif
+#endif
 
 /********** Helpers for find_busiest_group ************************/
 /*
@@ -3440,6 +4344,14 @@ struct sd_lb_stats {
        unsigned int  busiest_group_weight;
 
        int group_imb; /* Is there imbalance in this sd */
+#ifdef CONFIG_SCHED_NUMA
+       struct sched_group *numa_group; /* group which has offnode_tasks */
+       unsigned long numa_group_weight;
+       unsigned long numa_group_running;
+
+       unsigned long this_offnode_running;
+       unsigned long this_onnode_running;
+#endif
 };
 
 /*
@@ -3455,6 +4367,11 @@ struct sg_lb_stats {
        unsigned long group_weight;
        int group_imb; /* Is there an imbalance in the group ? */
        int group_has_capacity; /* Is there extra capacity in the group? */
+#ifdef CONFIG_SCHED_NUMA
+       unsigned long numa_offnode_weight;
+       unsigned long numa_offnode_running;
+       unsigned long numa_onnode_running;
+#endif
 };
 
 /**
@@ -3483,6 +4400,121 @@ static inline int get_sd_load_idx(struct sched_domain *sd,
        return load_idx;
 }
 
+#ifdef CONFIG_SCHED_NUMA
+static inline void update_sg_numa_stats(struct sg_lb_stats *sgs, struct rq *rq)
+{
+       sgs->numa_offnode_weight += rq->offnode_weight;
+       sgs->numa_offnode_running += rq->offnode_running;
+       sgs->numa_onnode_running += rq->onnode_running;
+}
+
+/*
+ * Since the offnode lists are indiscriminate (they contain tasks for all other
+ * nodes) it is impossible to say if there's any task on there that wants to
+ * move towards the pulling cpu. Therefore select a random offnode list to pull
+ * from such that eventually we'll try them all.
+ *
+ * Select a random group that has offnode tasks as sds->numa_group
+ */
+static inline void update_sd_numa_stats(struct sched_domain *sd,
+               struct sched_group *group, struct sd_lb_stats *sds,
+               int local_group, struct sg_lb_stats *sgs)
+{
+       if (!(sd->flags & SD_NUMA))
+               return;
+
+       if (local_group) {
+               sds->this_offnode_running = sgs->numa_offnode_running;
+               sds->this_onnode_running  = sgs->numa_onnode_running;
+               return;
+       }
+
+       if (!sgs->numa_offnode_running)
+               return;
+
+       if (!sds->numa_group || pick_numa_rand(sd->span_weight / group->group_weight)) {
+               sds->numa_group = group;
+               sds->numa_group_weight = sgs->numa_offnode_weight;
+               sds->numa_group_running = sgs->numa_offnode_running;
+       }
+}
+
+/*
+ * Pick a random queue from the group that has offnode tasks.
+ */
+static struct rq *find_busiest_numa_queue(struct lb_env *env,
+                                         struct sched_group *group)
+{
+       struct rq *busiest = NULL, *rq;
+       int cpu;
+
+       for_each_cpu_and(cpu, sched_group_cpus(group), env->cpus) {
+               rq = cpu_rq(cpu);
+               if (!rq->offnode_running)
+                       continue;
+               if (!busiest || pick_numa_rand(group->group_weight))
+                       busiest = rq;
+       }
+
+       return busiest;
+}
+
+/*
+ * Called in case of no other imbalance, if there is a queue running offnode
+ * tasksk we'll say we're imbalanced anyway to nudge these tasks towards their
+ * proper node.
+ */
+static inline int check_numa_busiest_group(struct lb_env *env, struct sd_lb_stats *sds)
+{
+       if (!sched_feat(NUMA_PULL_BIAS))
+               return 0;
+
+       if (!sds->numa_group)
+               return 0;
+
+       /*
+        * Only pull an offnode task home if we've got offnode or !numa tasks to trade for it.
+        */
+       if (!sds->this_offnode_running &&
+           !(sds->this_nr_running - sds->this_onnode_running - sds->this_offnode_running))
+               return 0;
+
+       env->imbalance = sds->numa_group_weight / sds->numa_group_running;
+       sds->busiest = sds->numa_group;
+       env->find_busiest_queue = find_busiest_numa_queue;
+       return 1;
+}
+
+static inline bool need_active_numa_balance(struct lb_env *env)
+{
+       return env->find_busiest_queue == find_busiest_numa_queue &&
+                       env->src_rq->offnode_running == 1 &&
+                       env->src_rq->nr_running == 1;
+}
+
+#else /* CONFIG_SCHED_NUMA */
+
+static inline void update_sg_numa_stats(struct sg_lb_stats *sgs, struct rq *rq)
+{
+}
+
+static inline void update_sd_numa_stats(struct sched_domain *sd,
+               struct sched_group *group, struct sd_lb_stats *sds,
+               int local_group, struct sg_lb_stats *sgs)
+{
+}
+
+static inline int check_numa_busiest_group(struct lb_env *env, struct sd_lb_stats *sds)
+{
+       return 0;
+}
+
+static inline bool need_active_numa_balance(struct lb_env *env)
+{
+       return false;
+}
+#endif /* CONFIG_SCHED_NUMA */
+
 unsigned long default_scale_freq_power(struct sched_domain *sd, int cpu)
 {
        return SCHED_POWER_SCALE;
@@ -3698,6 +4730,8 @@ static inline void update_sg_lb_stats(struct lb_env *env,
                sgs->sum_weighted_load += weighted_cpuload(i);
                if (idle_cpu(i))
                        sgs->idle_cpus++;
+
+               update_sg_numa_stats(sgs, rq);
        }
 
        /*
@@ -3851,6 +4885,8 @@ static inline void update_sd_lb_stats(struct lb_env *env,
                        sds->group_imb = sgs.group_imb;
                }
 
+               update_sd_numa_stats(env->sd, sg, sds, local_group, &sgs);
+
                sg = sg->next;
        } while (sg != env->sd->groups);
 }
@@ -4081,7 +5117,7 @@ find_busiest_group(struct lb_env *env, int *balance)
 
        /* There is no busy sibling group to pull tasks from */
        if (!sds.busiest || sds.busiest_nr_running == 0)
-               goto out_balanced;
+               goto ret;
 
        sds.avg_load = (SCHED_POWER_SCALE * sds.total_load) / sds.total_pwr;
 
@@ -4103,14 +5139,14 @@ find_busiest_group(struct lb_env *env, int *balance)
         * don't try and pull any tasks.
         */
        if (sds.this_load >= sds.max_load)
-               goto out_balanced;
+               goto ret;
 
        /*
         * Don't pull any tasks if this group is already above the domain
         * average load.
         */
        if (sds.this_load >= sds.avg_load)
-               goto out_balanced;
+               goto ret;
 
        if (env->idle == CPU_IDLE) {
                /*
@@ -4137,6 +5173,9 @@ force_balance:
        return sds.busiest;
 
 out_balanced:
+       if (check_numa_busiest_group(env, &sds))
+               return sds.busiest;
+
 ret:
        env->imbalance = 0;
        return NULL;
@@ -4215,6 +5254,9 @@ static int need_active_balance(struct lb_env *env)
                        return 1;
        }
 
+       if (need_active_numa_balance(env))
+               return 1;
+
        return unlikely(sd->nr_balance_failed > sd->cache_nice_tries+2);
 }
 
@@ -4236,13 +5278,14 @@ static int load_balance(int this_cpu, struct rq *this_rq,
        struct cpumask *cpus = __get_cpu_var(load_balance_tmpmask);
 
        struct lb_env env = {
-               .sd             = sd,
-               .dst_cpu        = this_cpu,
-               .dst_rq         = this_rq,
-               .dst_grpmask    = sched_group_cpus(sd->groups),
-               .idle           = idle,
-               .loop_break     = sched_nr_migrate_break,
-               .cpus           = cpus,
+               .sd                 = sd,
+               .dst_cpu            = this_cpu,
+               .dst_rq             = this_rq,
+               .dst_grpmask        = sched_group_cpus(sd->groups),
+               .idle               = idle,
+               .loop_break         = sched_nr_migrate_break,
+               .cpus               = cpus,
+               .find_busiest_queue = find_busiest_queue,
        };
 
        cpumask_copy(cpus, cpu_active_mask);
@@ -4261,11 +5304,13 @@ redo:
                goto out_balanced;
        }
 
-       busiest = find_busiest_queue(&env, group);
+       busiest = env.find_busiest_queue(&env, group);
        if (!busiest) {
                schedstat_inc(sd, lb_nobusyq[idle]);
                goto out_balanced;
        }
+       env.src_rq  = busiest;
+       env.src_cpu = busiest->cpu;
 
        BUG_ON(busiest == env.dst_rq);
 
@@ -4284,6 +5329,10 @@ redo:
                env.src_cpu   = busiest->cpu;
                env.src_rq    = busiest;
                env.loop_max  = min(sysctl_sched_nr_migrate, busiest->nr_running);
+               if (sched_feat_numa(NUMA_PULL))
+                       env.tasks = offnode_tasks(busiest);
+               else
+                       env.tasks = &busiest->cfs_tasks;
 
                update_h_load(env.src_cpu);
 more_balance:
@@ -4457,12 +5506,14 @@ void idle_balance(int this_cpu, struct rq *this_rq)
        if (this_rq->avg_idle < sysctl_sched_migration_cost)
                return;
 
+       update_rq_runnable_avg(this_rq, 1);
+
        /*
         * Drop the rq->lock, but keep IRQ/preempt disabled.
         */
        raw_spin_unlock(&this_rq->lock);
 
-       update_shares(this_cpu);
+       update_blocked_averages(this_cpu);
        rcu_read_lock();
        for_each_domain(this_cpu, sd) {
                unsigned long interval;
@@ -4717,7 +5768,7 @@ static void rebalance_domains(int cpu, enum cpu_idle_type idle)
        int update_next_balance = 0;
        int need_serialize;
 
-       update_shares(cpu);
+       update_blocked_averages(cpu);
 
        rcu_read_lock();
        for_each_domain(cpu, sd) {
@@ -4954,6 +6005,11 @@ static void task_tick_fair(struct rq *rq, struct task_struct *curr, int queued)
                cfs_rq = cfs_rq_of(se);
                entity_tick(cfs_rq, se, queued);
        }
+
+       update_rq_runnable_avg(rq, 1);
+
+       if (sched_feat_numa(NUMA))
+               task_tick_numa(rq, curr);
 }
 
 /*
@@ -5046,6 +6102,20 @@ static void switched_from_fair(struct rq *rq, struct task_struct *p)
                place_entity(cfs_rq, se, 0);
                se->vruntime -= cfs_rq->min_vruntime;
        }
+
+#if defined(CONFIG_FAIR_GROUP_SCHED) && defined(CONFIG_SMP)
+       /*
+       * Remove our load from contribution when we leave sched_fair
+       * and ensure we don't carry in an old decay_count if we
+       * switch back.
+       */
+       if (p->se.avg.decay_count) {
+               struct cfs_rq *cfs_rq = cfs_rq_of(&p->se);
+               __synchronize_entity_decay(&p->se);
+               subtract_blocked_load_contrib(cfs_rq,
+                               p->se.avg.load_avg_contrib);
+       }
+#endif
 }
 
 /*
@@ -5092,11 +6162,16 @@ void init_cfs_rq(struct cfs_rq *cfs_rq)
 #ifndef CONFIG_64BIT
        cfs_rq->min_vruntime_copy = cfs_rq->min_vruntime;
 #endif
+#if defined(CONFIG_FAIR_GROUP_SCHED) && defined(CONFIG_SMP)
+       atomic64_set(&cfs_rq->decay_counter, 1);
+       atomic64_set(&cfs_rq->removed_load, 0);
+#endif
 }
 
 #ifdef CONFIG_FAIR_GROUP_SCHED
 static void task_move_group_fair(struct task_struct *p, int on_rq)
 {
+       struct cfs_rq *cfs_rq;
        /*
         * If the task was not on the rq at the time of this cgroup movement
         * it must have been asleep, sleeping tasks keep their ->vruntime
@@ -5128,8 +6203,19 @@ static void task_move_group_fair(struct task_struct *p, int on_rq)
        if (!on_rq)
                p->se.vruntime -= cfs_rq_of(&p->se)->min_vruntime;
        set_task_rq(p, task_cpu(p));
-       if (!on_rq)
-               p->se.vruntime += cfs_rq_of(&p->se)->min_vruntime;
+       if (!on_rq) {
+               cfs_rq = cfs_rq_of(&p->se);
+               p->se.vruntime += cfs_rq->min_vruntime;
+#ifdef CONFIG_SMP
+               /*
+                * migrate_task_rq_fair() will have removed our previous
+                * contribution, but we must synchronize for ongoing future
+                * decay.
+                */
+               p->se.avg.decay_count = atomic64_read(&cfs_rq->decay_counter);
+               cfs_rq->blocked_load_avg += p->se.avg.load_avg_contrib;
+#endif
+       }
 }
 
 void free_fair_sched_group(struct task_group *tg)
@@ -5214,10 +6300,6 @@ void init_tg_cfs_entry(struct task_group *tg, struct cfs_rq *cfs_rq,
 
        cfs_rq->tg = tg;
        cfs_rq->rq = rq;
-#ifdef CONFIG_SMP
-       /* allow initial update_cfs_load() to truncate */
-       cfs_rq->load_stamp = 1;
-#endif
        init_cfs_rq_runtime(cfs_rq);
 
        tg->cfs_rq[cpu] = cfs_rq;
@@ -5264,8 +6346,11 @@ int sched_group_set_shares(struct task_group *tg, unsigned long shares)
                se = tg->se[i];
                /* Propagate contribution to hierarchy */
                raw_spin_lock_irqsave(&rq->lock, flags);
-               for_each_sched_entity(se)
+               for_each_sched_entity(se) {
                        update_cfs_shares(group_cfs_rq(se));
+                       /* update contribution to parent */
+                       update_entity_load_avg(se, 1);
+               }
                raw_spin_unlock_irqrestore(&rq->lock, flags);
        }
 
@@ -5319,7 +6404,9 @@ const struct sched_class fair_sched_class = {
 
 #ifdef CONFIG_SMP
        .select_task_rq         = select_task_rq_fair,
-
+#ifdef CONFIG_FAIR_GROUP_SCHED
+       .migrate_task_rq        = migrate_task_rq_fair,
+#endif
        .rq_online              = rq_online_fair,
        .rq_offline             = rq_offline_fair,
 
index eebefcad7027a0587977fb1cecaeb0d13cac79a0..1eff2cd79cf8960faf22a1c8035a5d68fc89b7ea 100644 (file)
@@ -31,6 +31,11 @@ SCHED_FEAT(LAST_BUDDY, true)
  */
 SCHED_FEAT(CACHE_HOT_BUDDY, true)
 
+/*
+ * Allow wakeup-time preemption of the current task:
+ */
+SCHED_FEAT(WAKEUP_PREEMPTION, true)
+
 /*
  * Use arch dependent cpu power functions
  */
@@ -61,3 +66,17 @@ SCHED_FEAT(TTWU_QUEUE, true)
 SCHED_FEAT(FORCE_SD_OVERLAP, false)
 SCHED_FEAT(RT_RUNTIME_SHARE, true)
 SCHED_FEAT(LB_MIN, false)
+
+#ifdef CONFIG_SCHED_NUMA
+/* Do the working set probing faults: */
+SCHED_FEAT(NUMA,           true)
+/* Do actual migration/placement based on the working set information: */
+SCHED_FEAT(NUMA_MIGRATION, true)
+SCHED_FEAT(NUMA_HOT,       true)
+SCHED_FEAT(NUMA_TTWU_BIAS, false)
+SCHED_FEAT(NUMA_TTWU_TO,   false)
+SCHED_FEAT(NUMA_PULL,      true)
+SCHED_FEAT(NUMA_PULL_BIAS, true)
+SCHED_FEAT(NUMA_SETTLE,    true)
+#endif
+
index 7a7db09cfabc18af1b35dd2bee57bf60d4103cf4..508e77e6e1371f32ad0ef7c82f896e2a3a5650fc 100644 (file)
@@ -3,6 +3,7 @@
 #include <linux/mutex.h>
 #include <linux/spinlock.h>
 #include <linux/stop_machine.h>
+#include <linux/slab.h>
 
 #include "cpupri.h"
 
@@ -112,6 +113,8 @@ struct task_group {
        unsigned long shares;
 
        atomic_t load_weight;
+       atomic64_t load_avg;
+       atomic_t runnable_avg;
 #endif
 
 #ifdef CONFIG_RT_GROUP_SCHED
@@ -222,22 +225,29 @@ struct cfs_rq {
        unsigned int nr_spread_over;
 #endif
 
+#ifdef CONFIG_SMP
+/*
+ * Load-tracking only depends on SMP, FAIR_GROUP_SCHED dependency below may be
+ * removed when useful for applications beyond shares distribution (e.g.
+ * load-balance).
+ */
 #ifdef CONFIG_FAIR_GROUP_SCHED
-       struct rq *rq;  /* cpu runqueue to which this cfs_rq is attached */
-
        /*
-        * leaf cfs_rqs are those that hold tasks (lowest schedulable entity in
-        * a hierarchy). Non-leaf lrqs hold other higher schedulable entities
-        * (like users, containers etc.)
-        *
-        * leaf_cfs_rq_list ties together list of leaf cfs_rq's in a cpu. This
-        * list is used during load balance.
+        * CFS Load tracking
+        * Under CFS, load is tracked on a per-entity basis and aggregated up.
+        * This allows for the description of both thread and group usage (in
+        * the FAIR_GROUP_SCHED case).
         */
-       int on_list;
-       struct list_head leaf_cfs_rq_list;
-       struct task_group *tg;  /* group that "owns" this runqueue */
+       u64 runnable_load_avg, blocked_load_avg;
+       atomic64_t decay_counter, removed_load;
+       u64 last_decay;
+#endif /* CONFIG_FAIR_GROUP_SCHED */
+/* These always depend on CONFIG_FAIR_GROUP_SCHED */
+#ifdef CONFIG_FAIR_GROUP_SCHED
+       u32 tg_runnable_contrib;
+       u64 tg_load_contrib;
+#endif /* CONFIG_FAIR_GROUP_SCHED */
 
-#ifdef CONFIG_SMP
        /*
         *   h_load = weight * f(tg)
         *
@@ -245,26 +255,30 @@ struct cfs_rq {
         * this group.
         */
        unsigned long h_load;
+#endif /* CONFIG_SMP */
+
+#ifdef CONFIG_FAIR_GROUP_SCHED
+       struct rq *rq;  /* cpu runqueue to which this cfs_rq is attached */
 
        /*
-        * Maintaining per-cpu shares distribution for group scheduling
+        * leaf cfs_rqs are those that hold tasks (lowest schedulable entity in
+        * a hierarchy). Non-leaf lrqs hold other higher schedulable entities
+        * (like users, containers etc.)
         *
-        * load_stamp is the last time we updated the load average
-        * load_last is the last time we updated the load average and saw load
-        * load_unacc_exec_time is currently unaccounted execution time
+        * leaf_cfs_rq_list ties together list of leaf cfs_rq's in a cpu. This
+        * list is used during load balance.
         */
-       u64 load_avg;
-       u64 load_period;
-       u64 load_stamp, load_last, load_unacc_exec_time;
+       int on_list;
+       struct list_head leaf_cfs_rq_list;
+       struct task_group *tg;  /* group that "owns" this runqueue */
 
-       unsigned long load_contribution;
-#endif /* CONFIG_SMP */
 #ifdef CONFIG_CFS_BANDWIDTH
        int runtime_enabled;
        u64 runtime_expires;
        s64 runtime_remaining;
 
-       u64 throttled_timestamp;
+       u64 throttled_clock, throttled_clock_task;
+       u64 throttled_clock_task_time;
        int throttled, throttle_count;
        struct list_head throttled_list;
 #endif /* CONFIG_CFS_BANDWIDTH */
@@ -418,6 +432,13 @@ struct rq {
 
        struct list_head cfs_tasks;
 
+#ifdef CONFIG_SCHED_NUMA
+       unsigned long    onnode_running;
+       unsigned long    offnode_running;
+       unsigned long    offnode_weight;
+       struct list_head offnode_tasks;
+#endif
+
        u64 rt_avg;
        u64 age_stamp;
        u64 idle_stamp;
@@ -467,6 +488,8 @@ struct rq {
 #ifdef CONFIG_SMP
        struct llist_head wake_list;
 #endif
+
+       struct sched_avg avg;
 };
 
 static inline int cpu_of(struct rq *rq)
@@ -486,6 +509,27 @@ DECLARE_PER_CPU(struct rq, runqueues);
 #define cpu_curr(cpu)          (cpu_rq(cpu)->curr)
 #define raw_rq()               (&__raw_get_cpu_var(runqueues))
 
+#ifdef CONFIG_SCHED_NUMA
+static inline struct list_head *offnode_tasks(struct rq *rq)
+{
+       return &rq->offnode_tasks;
+}
+
+static inline void task_numa_free(struct task_struct *p)
+{
+       kfree(p->numa_faults);
+}
+#else /* CONFIG_SCHED_NUMA */
+static inline struct list_head *offnode_tasks(struct rq *rq)
+{
+       return NULL;
+}
+
+static inline void task_numa_free(struct task_struct *p)
+{
+}
+#endif /* CONFIG_SCHED_NUMA */
+
 #ifdef CONFIG_SMP
 
 #define rcu_dereference_check_sched_domain(p) \
@@ -529,6 +573,7 @@ static inline struct sched_domain *highest_flag_domain(int cpu, int flag)
 
 DECLARE_PER_CPU(struct sched_domain *, sd_llc);
 DECLARE_PER_CPU(int, sd_llc_id);
+DECLARE_PER_CPU(struct sched_domain *, sd_node);
 
 extern int group_balance_cpu(struct sched_group *sg);
 
@@ -648,6 +693,12 @@ extern struct static_key sched_feat_keys[__SCHED_FEAT_NR];
 #define sched_feat(x) (sysctl_sched_features & (1UL << __SCHED_FEAT_##x))
 #endif /* SCHED_DEBUG && HAVE_JUMP_LABEL */
 
+#ifdef CONFIG_SCHED_NUMA
+#define sched_feat_numa(x) sched_feat(x)
+#else
+#define sched_feat_numa(x) (0)
+#endif
+
 static inline u64 global_rt_period(void)
 {
        return (u64)sysctl_sched_rt_period * NSEC_PER_USEC;
@@ -1212,4 +1263,3 @@ static inline u64 irq_time_read(int cpu)
 }
 #endif /* CONFIG_64BIT */
 #endif /* CONFIG_IRQ_TIME_ACCOUNTING */
-
index ee376beedaf96ca31cc3066d06cedf59a552290f..5af44b59377013cfa84298cc5a164dec4701a4b1 100644 (file)
@@ -396,25 +396,29 @@ int __secure_computing(int this_syscall)
 #ifdef CONFIG_SECCOMP_FILTER
        case SECCOMP_MODE_FILTER: {
                int data;
+               struct pt_regs *regs = task_pt_regs(current);
                ret = seccomp_run_filters(this_syscall);
                data = ret & SECCOMP_RET_DATA;
                ret &= SECCOMP_RET_ACTION;
                switch (ret) {
                case SECCOMP_RET_ERRNO:
                        /* Set the low-order 16-bits as a errno. */
-                       syscall_set_return_value(current, task_pt_regs(current),
+                       syscall_set_return_value(current, regs,
                                                 -data, 0);
                        goto skip;
                case SECCOMP_RET_TRAP:
                        /* Show the handler the original registers. */
-                       syscall_rollback(current, task_pt_regs(current));
+                       syscall_rollback(current, regs);
                        /* Let the filter pass back 16 bits of data. */
                        seccomp_send_sigsys(this_syscall, data);
                        goto skip;
                case SECCOMP_RET_TRACE:
                        /* Skip these calls if there is no tracer. */
-                       if (!ptrace_event_enabled(current, PTRACE_EVENT_SECCOMP))
+                       if (!ptrace_event_enabled(current, PTRACE_EVENT_SECCOMP)) {
+                               syscall_set_return_value(current, regs,
+                                                        -ENOSYS, 0);
                                goto skip;
+                       }
                        /* Allow the BPF to provide the event message */
                        ptrace_event(PTRACE_EVENT_SECCOMP, data);
                        /*
@@ -425,6 +429,9 @@ int __secure_computing(int this_syscall)
                         */
                        if (fatal_signal_pending(current))
                                break;
+                       if (syscall_get_nr(current, regs) < 0)
+                               goto skip;  /* Explicit request to skip. */
+
                        return 0;
                case SECCOMP_RET_ALLOW:
                        return 0;
index 97c465ebd8444cebc0f3a6e44ae0fdb04b552a2e..2b859828cdc327d811627fbf877318de8dbc5595 100644 (file)
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  *
  * Copyright (C) IBM Corporation, 2006
+ * Copyright (C) Fujitsu, 2012
  *
  * Author: Paul McKenney <paulmck@us.ibm.com>
+ *        Lai Jiangshan <laijs@cn.fujitsu.com>
  *
  * For detailed explanation of Read-Copy Update mechanism see -
  *             Documentation/RCU/ *.txt
 #include <linux/delay.h>
 #include <linux/srcu.h>
 
+#include <trace/events/rcu.h>
+
+#include "rcu.h"
+
 /*
  * Initialize an rcu_batch structure to empty.
  */
@@ -92,9 +98,6 @@ static inline void rcu_batch_move(struct rcu_batch *to, struct rcu_batch *from)
        }
 }
 
-/* single-thread state-machine */
-static void process_srcu(struct work_struct *work);
-
 static int init_srcu_struct_fields(struct srcu_struct *sp)
 {
        sp->completed = 0;
@@ -464,7 +467,9 @@ static void __synchronize_srcu(struct srcu_struct *sp, int trycount)
  */
 void synchronize_srcu(struct srcu_struct *sp)
 {
-       __synchronize_srcu(sp, SYNCHRONIZE_SRCU_TRYCOUNT);
+       __synchronize_srcu(sp, rcu_expedited
+                          ? SYNCHRONIZE_SRCU_EXP_TRYCOUNT
+                          : SYNCHRONIZE_SRCU_TRYCOUNT);
 }
 EXPORT_SYMBOL_GPL(synchronize_srcu);
 
@@ -637,7 +642,7 @@ static void srcu_reschedule(struct srcu_struct *sp)
 /*
  * This is the work-queue function that handles SRCU grace periods.
  */
-static void process_srcu(struct work_struct *work)
+void process_srcu(struct work_struct *work)
 {
        struct srcu_struct *sp;
 
@@ -648,3 +653,4 @@ static void process_srcu(struct work_struct *work)
        srcu_invoke_callbacks(sp);
        srcu_reschedule(sp);
 }
+EXPORT_SYMBOL_GPL(process_srcu);
index c5cb5b99cb8152808f569f6b993010a33e646bce..e6e0ece5f6a04401506d62fb602d7034d4273fe1 100644 (file)
@@ -1265,15 +1265,16 @@ DECLARE_RWSEM(uts_sem);
  * Work around broken programs that cannot handle "Linux 3.0".
  * Instead we map 3.x to 2.6.40+x, so e.g. 3.0 would be 2.6.40
  */
-static int override_release(char __user *release, int len)
+static int override_release(char __user *release, size_t len)
 {
        int ret = 0;
-       char buf[65];
 
        if (current->personality & UNAME26) {
-               char *rest = UTS_RELEASE;
+               const char *rest = UTS_RELEASE;
+               char buf[65] = { 0 };
                int ndots = 0;
                unsigned v;
+               size_t copy;
 
                while (*rest) {
                        if (*rest == '.' && ++ndots >= 3)
@@ -1283,8 +1284,9 @@ static int override_release(char __user *release, int len)
                        rest++;
                }
                v = ((LINUX_VERSION_CODE >> 8) & 0xff) + 40;
-               snprintf(buf, len, "2.6.%u%s", v, rest);
-               ret = copy_to_user(release, buf, len);
+               copy = clamp_t(size_t, len, 1, sizeof(buf));
+               copy = scnprintf(buf, copy, "2.6.%u%s", v, rest);
+               ret = copy_to_user(release, buf, copy + 1);
        }
        return ret;
 }
index dbff751e408647badd0d7e92b935962bfc3ef8e2..395084d4ce16002d3b513d948a641f2c674cd43d 100644 (file)
@@ -25,6 +25,7 @@ cond_syscall(sys_swapoff);
 cond_syscall(sys_kexec_load);
 cond_syscall(compat_sys_kexec_load);
 cond_syscall(sys_init_module);
+cond_syscall(sys_finit_module);
 cond_syscall(sys_delete_module);
 cond_syscall(sys_socketpair);
 cond_syscall(sys_bind);
index 26f65eaa01f9c94366aa5156f9c304bbc589808f..b769d25e20e7bfd18eeedd03b886715965d5dbbb 100644 (file)
@@ -256,9 +256,11 @@ static int min_sched_granularity_ns = 100000;              /* 100 usecs */
 static int max_sched_granularity_ns = NSEC_PER_SEC;    /* 1 second */
 static int min_wakeup_granularity_ns;                  /* 0 usecs */
 static int max_wakeup_granularity_ns = NSEC_PER_SEC;   /* 1 second */
+#ifdef CONFIG_SMP
 static int min_sched_tunable_scaling = SCHED_TUNABLESCALING_NONE;
 static int max_sched_tunable_scaling = SCHED_TUNABLESCALING_END-1;
-#endif
+#endif /* CONFIG_SMP */
+#endif /* CONFIG_SCHED_DEBUG */
 
 #ifdef CONFIG_COMPACTION
 static int min_extfrag_threshold;
@@ -301,6 +303,7 @@ static struct ctl_table kern_table[] = {
                .extra1         = &min_wakeup_granularity_ns,
                .extra2         = &max_wakeup_granularity_ns,
        },
+#ifdef CONFIG_SMP
        {
                .procname       = "sched_tunable_scaling",
                .data           = &sysctl_sched_tunable_scaling,
@@ -347,7 +350,45 @@ static struct ctl_table kern_table[] = {
                .extra1         = &zero,
                .extra2         = &one,
        },
-#endif
+#endif /* CONFIG_SMP */
+#ifdef CONFIG_SCHED_NUMA
+       {
+               .procname       = "sched_numa_scan_delay_ms",
+               .data           = &sysctl_sched_numa_scan_delay,
+               .maxlen         = sizeof(unsigned int),
+               .mode           = 0644,
+               .proc_handler   = proc_dointvec,
+       },
+       {
+               .procname       = "sched_numa_scan_period_min_ms",
+               .data           = &sysctl_sched_numa_scan_period_min,
+               .maxlen         = sizeof(unsigned int),
+               .mode           = 0644,
+               .proc_handler   = proc_dointvec,
+       },
+       {
+               .procname       = "sched_numa_scan_period_max_ms",
+               .data           = &sysctl_sched_numa_scan_period_max,
+               .maxlen         = sizeof(unsigned int),
+               .mode           = 0644,
+               .proc_handler   = proc_dointvec,
+       },
+       {
+               .procname       = "sched_numa_scan_size_mb",
+               .data           = &sysctl_sched_numa_scan_size,
+               .maxlen         = sizeof(unsigned int),
+               .mode           = 0644,
+               .proc_handler   = proc_dointvec,
+       },
+       {
+               .procname       = "sched_numa_settle_count",
+               .data           = &sysctl_sched_numa_settle_count,
+               .maxlen         = sizeof(unsigned int),
+               .mode           = 0644,
+               .proc_handler   = proc_dointvec,
+       },
+#endif /* CONFIG_SCHED_NUMA */
+#endif /* CONFIG_SCHED_DEBUG */
        {
                .procname       = "sched_rt_period_us",
                .data           = &sysctl_sched_rt_period,
index a40260885265707603d72dee9df79f030e973221..7587672d0d2155c8384249f3525fedc6edfa1a02 100644 (file)
@@ -98,6 +98,49 @@ static ktime_t tick_init_jiffy_update(void)
        return period;
 }
 
+
+static void tick_sched_do_timer(ktime_t now)
+{
+       int cpu = smp_processor_id();
+
+#ifdef CONFIG_NO_HZ
+       /*
+        * Check if the do_timer duty was dropped. We don't care about
+        * concurrency: This happens only when the cpu in charge went
+        * into a long sleep. If two cpus happen to assign themself to
+        * this duty, then the jiffies update is still serialized by
+        * xtime_lock.
+        */
+       if (unlikely(tick_do_timer_cpu == TICK_DO_TIMER_NONE))
+               tick_do_timer_cpu = cpu;
+#endif
+
+       /* Check, if the jiffies need an update */
+       if (tick_do_timer_cpu == cpu)
+               tick_do_update_jiffies64(now);
+}
+
+static void tick_sched_handle(struct tick_sched *ts, struct pt_regs *regs)
+{
+#ifdef CONFIG_NO_HZ
+       /*
+        * When we are idle and the tick is stopped, we have to touch
+        * the watchdog as we might not schedule for a really long
+        * time. This happens on complete idle SMP systems while
+        * waiting on the login prompt. We also increment the "start of
+        * idle" jiffy stamp so the idle accounting adjustment we do
+        * when we go busy again does not account too much ticks.
+        */
+       if (ts->tick_stopped) {
+               touch_softlockup_watchdog();
+               if (is_idle_task(current))
+                       ts->idle_jiffies++;
+       }
+#endif
+       update_process_times(user_mode(regs));
+       profile_tick(CPU_PROFILING);
+}
+
 /*
  * NOHZ - aka dynamic tick functionality
  */
@@ -526,6 +569,8 @@ void tick_nohz_irq_exit(void)
        if (!ts->inidle)
                return;
 
+       /* Cancel the timer because CPU already waken up from the C-states*/
+       menu_hrtimer_cancel();
        __tick_nohz_idle_enter(ts);
 }
 
@@ -621,6 +666,8 @@ void tick_nohz_idle_exit(void)
 
        ts->inidle = 0;
 
+       /* Cancel the timer because CPU already waken up from the C-states*/
+       menu_hrtimer_cancel();
        if (ts->idle_active || ts->tick_stopped)
                now = ktime_get();
 
@@ -648,40 +695,12 @@ static void tick_nohz_handler(struct clock_event_device *dev)
 {
        struct tick_sched *ts = &__get_cpu_var(tick_cpu_sched);
        struct pt_regs *regs = get_irq_regs();
-       int cpu = smp_processor_id();
        ktime_t now = ktime_get();
 
        dev->next_event.tv64 = KTIME_MAX;
 
-       /*
-        * Check if the do_timer duty was dropped. We don't care about
-        * concurrency: This happens only when the cpu in charge went
-        * into a long sleep. If two cpus happen to assign themself to
-        * this duty, then the jiffies update is still serialized by
-        * xtime_lock.
-        */
-       if (unlikely(tick_do_timer_cpu == TICK_DO_TIMER_NONE))
-               tick_do_timer_cpu = cpu;
-
-       /* Check, if the jiffies need an update */
-       if (tick_do_timer_cpu == cpu)
-               tick_do_update_jiffies64(now);
-
-       /*
-        * When we are idle and the tick is stopped, we have to touch
-        * the watchdog as we might not schedule for a really long
-        * time. This happens on complete idle SMP systems while
-        * waiting on the login prompt. We also increment the "start
-        * of idle" jiffy stamp so the idle accounting adjustment we
-        * do when we go busy again does not account too much ticks.
-        */
-       if (ts->tick_stopped) {
-               touch_softlockup_watchdog();
-               ts->idle_jiffies++;
-       }
-
-       update_process_times(user_mode(regs));
-       profile_tick(CPU_PROFILING);
+       tick_sched_do_timer(now);
+       tick_sched_handle(ts, regs);
 
        while (tick_nohz_reprogram(ts, now)) {
                now = ktime_get();
@@ -794,7 +813,7 @@ void tick_check_idle(int cpu)
 #ifdef CONFIG_HIGH_RES_TIMERS
 /*
  * We rearm the timer until we get disabled by the idle code.
- * Called with interrupts disabled and timer->base->cpu_base->lock held.
+ * Called with interrupts disabled.
  */
 static enum hrtimer_restart tick_sched_timer(struct hrtimer *timer)
 {
@@ -802,45 +821,15 @@ static enum hrtimer_restart tick_sched_timer(struct hrtimer *timer)
                container_of(timer, struct tick_sched, sched_timer);
        struct pt_regs *regs = get_irq_regs();
        ktime_t now = ktime_get();
-       int cpu = smp_processor_id();
-
-#ifdef CONFIG_NO_HZ
-       /*
-        * Check if the do_timer duty was dropped. We don't care about
-        * concurrency: This happens only when the cpu in charge went
-        * into a long sleep. If two cpus happen to assign themself to
-        * this duty, then the jiffies update is still serialized by
-        * xtime_lock.
-        */
-       if (unlikely(tick_do_timer_cpu == TICK_DO_TIMER_NONE))
-               tick_do_timer_cpu = cpu;
-#endif
 
-       /* Check, if the jiffies need an update */
-       if (tick_do_timer_cpu == cpu)
-               tick_do_update_jiffies64(now);
+       tick_sched_do_timer(now);
 
        /*
         * Do not call, when we are not in irq context and have
         * no valid regs pointer
         */
-       if (regs) {
-               /*
-                * When we are idle and the tick is stopped, we have to touch
-                * the watchdog as we might not schedule for a really long
-                * time. This happens on complete idle SMP systems while
-                * waiting on the login prompt. We also increment the "start of
-                * idle" jiffy stamp so the idle accounting adjustment we do
-                * when we go busy again does not account too much ticks.
-                */
-               if (ts->tick_stopped) {
-                       touch_softlockup_watchdog();
-                       if (is_idle_task(current))
-                               ts->idle_jiffies++;
-               }
-               update_process_times(user_mode(regs));
-               profile_tick(CPU_PROFILING);
-       }
+       if (regs)
+               tick_sched_handle(ts, regs);
 
        hrtimer_forward(timer, now, tick_period);
 
index b32ed0e385a59b40b971bd04e0e374d333992749..b979426d16c6efc48e743b6a9df48a78bcaa9f4b 100644 (file)
@@ -1567,6 +1567,10 @@ int ring_buffer_resize(struct ring_buffer *buffer, unsigned long size,
 
                put_online_cpus();
        } else {
+               /* Make sure this CPU has been intitialized */
+               if (!cpumask_test_cpu(cpu_id, buffer->cpumask))
+                       goto out;
+
                cpu_buffer = buffer->buffers[cpu_id];
 
                if (nr_pages == cpu_buffer->nr_pages)
index d951daa0ca9a81b21f6b1387b140f537b53c27c1..a1135c652a7c49b587e1acc71fb4c4b61a8b715d 100644 (file)
@@ -1477,7 +1477,11 @@ bool mod_delayed_work_on(int cpu, struct workqueue_struct *wq,
        } while (unlikely(ret == -EAGAIN));
 
        if (likely(ret >= 0)) {
-               __queue_delayed_work(cpu, wq, dwork, delay);
+               if (!delay)
+                       __queue_work(cpu, wq, &dwork->work);
+               else
+                       __queue_delayed_work(cpu, wq, dwork, delay);
+
                local_irq_restore(flags);
        }
 
@@ -2982,7 +2986,7 @@ bool cancel_delayed_work(struct delayed_work *dwork)
 
        set_work_cpu_and_clear_pending(&dwork->work, work_cpu(&dwork->work));
        local_irq_restore(flags);
-       return true;
+       return ret;
 }
 EXPORT_SYMBOL(cancel_delayed_work);
 
@@ -3475,7 +3479,7 @@ unsigned int work_busy(struct work_struct *work)
        unsigned int ret = 0;
 
        if (!gcwq)
-               return false;
+               return 0;
 
        spin_lock_irqsave(&gcwq->lock, flags);
 
index 28e9d6c98941290108acdf8e73953022975e8bc2..6a4b500e93d12bdff6bb4086127033c59e604970 100644 (file)
@@ -970,7 +970,7 @@ config RCU_TORTURE_TEST_RUNNABLE
 
 config RCU_CPU_STALL_TIMEOUT
        int "RCU CPU stall timeout in seconds"
-       depends on TREE_RCU || TREE_PREEMPT_RCU
+       depends on TREE_RCU || TREE_PREEMPT_RCU || RCU_TRACE
        range 3 300
        default 60
        help
index 821a16229111eba69f189ae9be683f02eeb70862..e91b9dffc853e95009c44e647e0cb9e6a8de374d 100644 (file)
@@ -12,7 +12,7 @@ lib-y := ctype.o string.o vsprintf.o cmdline.o \
         idr.o int_sqrt.o extable.o \
         sha1.o md5.o irq_regs.o reciprocal_div.o argv_split.o \
         proportions.o flex_proportions.o prio_heap.o ratelimit.o show_mem.o \
-        is_single_threaded.o plist.o decompress.o
+        is_single_threaded.o plist.o decompress.o earlycpio.o
 
 lib-$(CONFIG_MMU) += ioremap.o
 lib-$(CONFIG_SMP) += cpumask.o
index de2c8b5a715bd9c1f75129bc40293ac68f1f92e9..11b9b01fda6b67303db4a7df22c19e2c35c4c095 100644 (file)
@@ -81,7 +81,7 @@ next_tag:
                goto next_tag;
        }
 
-       if (unlikely((tag & 0x1f) == 0x1f)) {
+       if (unlikely((tag & 0x1f) == ASN1_LONG_TAG)) {
                do {
                        if (unlikely(datalen - dp < 2))
                                goto data_overrun_error;
@@ -91,12 +91,12 @@ next_tag:
 
        /* Extract the length */
        len = data[dp++];
-       if (len < 0x7f) {
+       if (len <= 0x7f) {
                dp += len;
                goto next_tag;
        }
 
-       if (unlikely(len == 0x80)) {
+       if (unlikely(len == ASN1_INDEFINITE_LENGTH)) {
                /* Indefinite length */
                if (unlikely((tag & ASN1_CONS_BIT) == ASN1_PRIM << 5))
                        goto indefinite_len_primitive;
@@ -222,7 +222,7 @@ next_op:
                if (unlikely(dp >= datalen - 1))
                        goto data_overrun_error;
                tag = data[dp++];
-               if (unlikely((tag & 0x1f) == 0x1f))
+               if (unlikely((tag & 0x1f) == ASN1_LONG_TAG))
                        goto long_tag_not_supported;
 
                if (op & ASN1_OP_MATCH__ANY) {
@@ -254,7 +254,7 @@ next_op:
 
                len = data[dp++];
                if (len > 0x7f) {
-                       if (unlikely(len == 0x80)) {
+                       if (unlikely(len == ASN1_INDEFINITE_LENGTH)) {
                                /* Indefinite length */
                                if (unlikely(!(tag & ASN1_CONS_BIT)))
                                        goto indefinite_len_primitive;
index b9087bff008be9ef4b4eb2ebb7acea898b69be8d..59f4a1a8187d5201113684d671b785a3133ea62a 100644 (file)
@@ -45,6 +45,12 @@ enum {
        dma_debug_coherent,
 };
 
+enum map_err_types {
+       MAP_ERR_CHECK_NOT_APPLICABLE,
+       MAP_ERR_NOT_CHECKED,
+       MAP_ERR_CHECKED,
+};
+
 #define DMA_DEBUG_STACKTRACE_ENTRIES 5
 
 struct dma_debug_entry {
@@ -57,6 +63,7 @@ struct dma_debug_entry {
        int              direction;
        int              sg_call_ents;
        int              sg_mapped_ents;
+       enum map_err_types  map_err_type;
 #ifdef CONFIG_STACKTRACE
        struct           stack_trace stacktrace;
        unsigned long    st_entries[DMA_DEBUG_STACKTRACE_ENTRIES];
@@ -114,6 +121,12 @@ static struct device_driver *current_driver                    __read_mostly;
 
 static DEFINE_RWLOCK(driver_name_lock);
 
+static const char *const maperr2str[] = {
+       [MAP_ERR_CHECK_NOT_APPLICABLE] = "dma map error check not applicable",
+       [MAP_ERR_NOT_CHECKED] = "dma map error not checked",
+       [MAP_ERR_CHECKED] = "dma map error checked",
+};
+
 static const char *type2name[4] = { "single", "page",
                                    "scather-gather", "coherent" };
 
@@ -264,7 +277,7 @@ static struct dma_debug_entry *__hash_bucket_find(struct hash_bucket *bucket,
                                                  match_fn match)
 {
        struct dma_debug_entry *entry, *ret = NULL;
-       int matches = 0, match_lvl, last_lvl = 0;
+       int matches = 0, match_lvl, last_lvl = -1;
 
        list_for_each_entry(entry, &bucket->list, list) {
                if (!match(ref, entry))
@@ -293,7 +306,7 @@ static struct dma_debug_entry *__hash_bucket_find(struct hash_bucket *bucket,
                } else if (match_lvl > last_lvl) {
                        /*
                         * We found an entry that fits better then the
-                        * previous one
+                        * previous one or it is the 1st match.
                         */
                        last_lvl = match_lvl;
                        ret      = entry;
@@ -376,11 +389,12 @@ void debug_dma_dump_mappings(struct device *dev)
                list_for_each_entry(entry, &bucket->list, list) {
                        if (!dev || dev == entry->dev) {
                                dev_info(entry->dev,
-                                        "%s idx %d P=%Lx D=%Lx L=%Lx %s\n",
+                                        "%s idx %d P=%Lx D=%Lx L=%Lx %s %s\n",
                                         type2name[entry->type], idx,
                                         (unsigned long long)entry->paddr,
                                         entry->dev_addr, entry->size,
-                                        dir2name[entry->direction]);
+                                        dir2name[entry->direction],
+                                        maperr2str[entry->map_err_type]);
                        }
                }
 
@@ -838,13 +852,28 @@ static __init int dma_debug_entries_cmdline(char *str)
 __setup("dma_debug=", dma_debug_cmdline);
 __setup("dma_debug_entries=", dma_debug_entries_cmdline);
 
+/* Calling dma_mapping_error() from dma-debug api will result in calling
+   debug_dma_mapping_error() - need internal mapping error routine to
+   avoid debug checks */
+#ifndef DMA_ERROR_CODE
+#define DMA_ERROR_CODE 0
+#endif
+static inline int has_mapping_error(struct device *dev, dma_addr_t dma_addr)
+{
+       const struct dma_map_ops *ops = get_dma_ops(dev);
+       if (ops->mapping_error)
+               return ops->mapping_error(dev, dma_addr);
+
+       return (dma_addr == DMA_ERROR_CODE);
+}
+
 static void check_unmap(struct dma_debug_entry *ref)
 {
        struct dma_debug_entry *entry;
        struct hash_bucket *bucket;
        unsigned long flags;
 
-       if (dma_mapping_error(ref->dev, ref->dev_addr)) {
+       if (unlikely(has_mapping_error(ref->dev, ref->dev_addr))) {
                err_printk(ref->dev, NULL, "DMA-API: device driver tries "
                           "to free an invalid DMA memory address\n");
                return;
@@ -910,6 +939,15 @@ static void check_unmap(struct dma_debug_entry *ref)
                           dir2name[ref->direction]);
        }
 
+       if (entry->map_err_type == MAP_ERR_NOT_CHECKED) {
+               err_printk(ref->dev, entry,
+                          "DMA-API: device driver failed to check map error"
+                          "[device address=0x%016llx] [size=%llu bytes] "
+                          "[mapped as %s]",
+                          ref->dev_addr, ref->size,
+                          type2name[entry->type]);
+       }
+
        hash_bucket_del(entry);
        dma_entry_free(entry);
 
@@ -1017,7 +1055,7 @@ void debug_dma_map_page(struct device *dev, struct page *page, size_t offset,
        if (unlikely(global_disable))
                return;
 
-       if (unlikely(dma_mapping_error(dev, dma_addr)))
+       if (unlikely(has_mapping_error(dev, dma_addr)))
                return;
 
        entry = dma_entry_alloc();
@@ -1030,6 +1068,7 @@ void debug_dma_map_page(struct device *dev, struct page *page, size_t offset,
        entry->dev_addr  = dma_addr;
        entry->size      = size;
        entry->direction = direction;
+       entry->map_err_type = MAP_ERR_NOT_CHECKED;
 
        if (map_single)
                entry->type = dma_debug_single;
@@ -1045,6 +1084,30 @@ void debug_dma_map_page(struct device *dev, struct page *page, size_t offset,
 }
 EXPORT_SYMBOL(debug_dma_map_page);
 
+void debug_dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
+{
+       struct dma_debug_entry ref;
+       struct dma_debug_entry *entry;
+       struct hash_bucket *bucket;
+       unsigned long flags;
+
+       if (unlikely(global_disable))
+               return;
+
+       ref.dev = dev;
+       ref.dev_addr = dma_addr;
+       bucket = get_hash_bucket(&ref, &flags);
+       entry = bucket_find_exact(bucket, &ref);
+
+       if (!entry)
+               goto out;
+
+       entry->map_err_type = MAP_ERR_CHECKED;
+out:
+       put_hash_bucket(bucket, &flags);
+}
+EXPORT_SYMBOL(debug_dma_mapping_error);
+
 void debug_dma_unmap_page(struct device *dev, dma_addr_t addr,
                          size_t size, int direction, bool map_single)
 {
diff --git a/lib/earlycpio.c b/lib/earlycpio.c
new file mode 100644 (file)
index 0000000..8078ef4
--- /dev/null
@@ -0,0 +1,145 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2012 Intel Corporation; author H. Peter Anvin
+ *
+ *   This file is part of the Linux kernel, and is made available
+ *   under the terms of the GNU General Public License version 2, as
+ *   published by the Free Software Foundation.
+ *
+ *   This program is distributed in the hope it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *   General Public License for more details.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * earlycpio.c
+ *
+ * Find a specific cpio member; must precede any compressed content.
+ * This is used to locate data items in the initramfs used by the
+ * kernel itself during early boot (before the main initramfs is
+ * decompressed.)  It is the responsibility of the initramfs creator
+ * to ensure that these items are uncompressed at the head of the
+ * blob.  Depending on the boot loader or package tool that may be a
+ * separate file or part of the same file.
+ */
+
+#include <linux/earlycpio.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+
+enum cpio_fields {
+       C_MAGIC,
+       C_INO,
+       C_MODE,
+       C_UID,
+       C_GID,
+       C_NLINK,
+       C_MTIME,
+       C_FILESIZE,
+       C_MAJ,
+       C_MIN,
+       C_RMAJ,
+       C_RMIN,
+       C_NAMESIZE,
+       C_CHKSUM,
+       C_NFIELDS
+};
+
+/**
+ * cpio_data find_cpio_data - Search for files in an uncompressed cpio
+ * @path:   The directory to search for, including a slash at the end
+ * @data:   Pointer to the the cpio archive or a header inside
+ * @len:    Remaining length of the cpio based on data pointer
+ * @offset: When a matching file is found, this is the offset to the
+ *          beginning of the cpio. It can be used to iterate through
+ *          the cpio to find all files inside of a directory path
+ *
+ * @return: struct cpio_data containing the address, length and
+ *          filename (with the directory path cut off) of the found file.
+ *          If you search for a filename and not for files in a directory,
+ *          pass the absolute path of the filename in the cpio and make sure
+ *          the match returned an empty filename string.
+ */
+
+struct cpio_data __cpuinit find_cpio_data(const char *path, void *data,
+                                         size_t len,  long *offset)
+{
+       const size_t cpio_header_len = 8*C_NFIELDS - 2;
+       struct cpio_data cd = { NULL, 0, "" };
+       const char *p, *dptr, *nptr;
+       unsigned int ch[C_NFIELDS], *chp, v;
+       unsigned char c, x;
+       size_t mypathsize = strlen(path);
+       int i, j;
+
+       p = data;
+
+       while (len > cpio_header_len) {
+               if (!*p) {
+                       /* All cpio headers need to be 4-byte aligned */
+                       p += 4;
+                       len -= 4;
+                       continue;
+               }
+
+               j = 6;          /* The magic field is only 6 characters */
+               chp = ch;
+               for (i = C_NFIELDS; i; i--) {
+                       v = 0;
+                       while (j--) {
+                               v <<= 4;
+                               c = *p++;
+
+                               x = c - '0';
+                               if (x < 10) {
+                                       v += x;
+                                       continue;
+                               }
+
+                               x = (c | 0x20) - 'a';
+                               if (x < 6) {
+                                       v += x + 10;
+                                       continue;
+                               }
+
+                               goto quit; /* Invalid hexadecimal */
+                       }
+                       *chp++ = v;
+                       j = 8;  /* All other fields are 8 characters */
+               }
+
+               if ((ch[C_MAGIC] - 0x070701) > 1)
+                       goto quit; /* Invalid magic */
+
+               len -= cpio_header_len;
+
+               dptr = PTR_ALIGN(p + ch[C_NAMESIZE], 4);
+               nptr = PTR_ALIGN(dptr + ch[C_FILESIZE], 4);
+
+               if (nptr > p + len || dptr < p || nptr < dptr)
+                       goto quit; /* Buffer overrun */
+
+               if ((ch[C_MODE] & 0170000) == 0100000 &&
+                   ch[C_NAMESIZE] >= mypathsize &&
+                   !memcmp(p, path, mypathsize)) {
+                       *offset = (long)nptr - (long)data;
+                       if (ch[C_NAMESIZE] - mypathsize >= MAX_CPIO_FILE_NAME) {
+                               pr_warn(
+                               "File %s exceeding MAX_CPIO_FILE_NAME [%d]\n",
+                               p, MAX_CPIO_FILE_NAME);
+                       }
+                       strlcpy(cd.name, p + mypathsize, MAX_CPIO_FILE_NAME);
+
+                       cd.data = (void *)dptr;
+                       cd.size = ch[C_FILESIZE];
+                       return cd; /* Found it! */
+               }
+               len -= (nptr - p);
+               p = nptr;
+       }
+
+quit:
+       return cd;
+}
index 2c4ce17651d825c97c7d89ecea52bf53f17ce0aa..9eef55838fca5ff99580982e85ea0c0fa6dea839 100644 (file)
@@ -346,7 +346,7 @@ static unsigned long isolate_freepages_block(struct compact_control *cc,
         * pages requested were isolated. If there were any failures, 0 is
         * returned and CMA will fail.
         */
-       if (strict && nr_strict_required != total_isolated)
+       if (strict && nr_strict_required > total_isolated)
                total_isolated = 0;
 
        if (locked)
index 3899a86851ceb6bf021e51c014fef16e0893a7f0..a0aaf0e56800394be8b9ae0d0da47712b6e0bb53 100644 (file)
@@ -169,7 +169,7 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size,
        if (vma->vm_private_data && !(vma->vm_flags & VM_NONLINEAR))
                goto out;
 
-       if (!vma->vm_ops->remap_pages)
+       if (!vma->vm_ops || !vma->vm_ops->remap_pages)
                goto out;
 
        if (start < vma->vm_start || start + size > vma->vm_end)
index d517cd16a6eb91e8df18f3cbd79cd67621b27d3f..2a07f97dabf11bceb05e69be4143d6cc06a7bd12 100644 (file)
@@ -105,6 +105,7 @@ struct page *kmap_to_page(void *vaddr)
 
        return virt_to_page(addr);
 }
+EXPORT_SYMBOL(kmap_to_page);
 
 static void flush_all_zero_pkmaps(void)
 {
index 40f17c34b4153fab93b4f1a2685dee0b8cac4da8..5aa935a0cc0f537261b80df86fe1438503439ad1 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/freezer.h>
 #include <linux/mman.h>
 #include <linux/pagemap.h>
+#include <linux/migrate.h>
 #include <asm/tlb.h>
 #include <asm/pgalloc.h>
 #include "internal.h"
@@ -710,7 +711,8 @@ out:
         * run pte_offset_map on the pmd, if an huge pmd could
         * materialize from under us from a different thread.
         */
-       if (unlikely(__pte_alloc(mm, vma, pmd, address)))
+       if (unlikely(pmd_none(*pmd)) &&
+           unlikely(__pte_alloc(mm, vma, pmd, address)))
                return VM_FAULT_OOM;
        /* if an huge pmd materialized from under us just retry later */
        if (unlikely(pmd_trans_huge(*pmd)))
@@ -725,6 +727,152 @@ out:
        return handle_pte_fault(mm, vma, address, pte, pmd, flags);
 }
 
+bool pmd_numa(struct vm_area_struct *vma, pmd_t pmd)
+{
+       /*
+        * See pte_prot_none().
+        */
+       if (pmd_same(pmd, pmd_modify(pmd, vma->vm_page_prot)))
+               return false;
+
+       return pmd_same(pmd, pmd_modify(pmd, vma_prot_none(vma)));
+}
+
+void do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma,
+                          unsigned long address, pmd_t *pmd,
+                          unsigned int flags, pmd_t entry)
+{
+       unsigned long haddr = address & HPAGE_PMD_MASK;
+       struct page *new_page = NULL;
+       struct page *page = NULL;
+       int node, lru;
+
+       spin_lock(&mm->page_table_lock);
+       if (unlikely(!pmd_same(*pmd, entry)))
+               goto unlock;
+
+       if (unlikely(pmd_trans_splitting(entry))) {
+               spin_unlock(&mm->page_table_lock);
+               wait_split_huge_page(vma->anon_vma, pmd);
+               return;
+       }
+
+       page = pmd_page(entry);
+       if (page) {
+               VM_BUG_ON(!PageCompound(page) || !PageHead(page));
+
+               get_page(page);
+               node = mpol_misplaced(page, vma, haddr);
+               if (node != -1)
+                       goto migrate;
+       }
+
+fixup:
+       /* change back to regular protection */
+       entry = pmd_modify(entry, vma->vm_page_prot);
+       set_pmd_at(mm, haddr, pmd, entry);
+       update_mmu_cache_pmd(vma, address, entry);
+
+unlock:
+       spin_unlock(&mm->page_table_lock);
+       if (page) {
+               task_numa_fault(page_to_nid(page), HPAGE_PMD_NR);
+               put_page(page);
+       }
+       return;
+
+migrate:
+       spin_unlock(&mm->page_table_lock);
+
+       lock_page(page);
+       spin_lock(&mm->page_table_lock);
+       if (unlikely(!pmd_same(*pmd, entry))) {
+               spin_unlock(&mm->page_table_lock);
+               unlock_page(page);
+               put_page(page);
+               return;
+       }
+       spin_unlock(&mm->page_table_lock);
+
+       new_page = alloc_pages_node(node,
+           (GFP_TRANSHUGE | GFP_THISNODE) & ~__GFP_WAIT,
+           HPAGE_PMD_ORDER);
+
+       if (!new_page)
+               goto alloc_fail;
+
+       lru = PageLRU(page);
+
+       if (lru && isolate_lru_page(page)) /* does an implicit get_page() */
+               goto alloc_fail;
+
+       if (!trylock_page(new_page))
+               BUG();
+
+       /* anon mapping, we can simply copy page->mapping to the new page: */
+       new_page->mapping = page->mapping;
+       new_page->index = page->index;
+
+       migrate_page_copy(new_page, page);
+
+       WARN_ON(PageLRU(new_page));
+
+       spin_lock(&mm->page_table_lock);
+       if (unlikely(!pmd_same(*pmd, entry))) {
+               spin_unlock(&mm->page_table_lock);
+               if (lru)
+                       putback_lru_page(page);
+
+               unlock_page(new_page);
+               ClearPageActive(new_page);      /* Set by migrate_page_copy() */
+               new_page->mapping = NULL;
+               put_page(new_page);             /* Free it */
+
+               unlock_page(page);
+               put_page(page);                 /* Drop the local reference */
+
+               return;
+       }
+
+       entry = mk_pmd(new_page, vma->vm_page_prot);
+       entry = maybe_pmd_mkwrite(pmd_mkdirty(entry), vma);
+       entry = pmd_mkhuge(entry);
+
+       page_add_new_anon_rmap(new_page, vma, haddr);
+
+       set_pmd_at(mm, haddr, pmd, entry);
+       update_mmu_cache_pmd(vma, address, entry);
+       page_remove_rmap(page);
+       spin_unlock(&mm->page_table_lock);
+
+       put_page(page);                 /* Drop the rmap reference */
+
+       task_numa_fault(node, HPAGE_PMD_NR);
+
+       if (lru)
+               put_page(page);         /* drop the LRU isolation reference */
+
+       unlock_page(new_page);
+       unlock_page(page);
+       put_page(page);                 /* Drop the local reference */
+
+       return;
+
+alloc_fail:
+       if (new_page)
+               put_page(new_page);
+
+       unlock_page(page);
+
+       spin_lock(&mm->page_table_lock);
+       if (unlikely(!pmd_same(*pmd, entry))) {
+               put_page(page);
+               page = NULL;
+               goto unlock;
+       }
+       goto fixup;
+}
+
 int copy_huge_pmd(struct mm_struct *dst_mm, struct mm_struct *src_mm,
                  pmd_t *dst_pmd, pmd_t *src_pmd, unsigned long addr,
                  struct vm_area_struct *vma)
@@ -1296,6 +1444,7 @@ static void __split_huge_page_refcount(struct page *page)
                page_tail->mapping = page->mapping;
 
                page_tail->index = page->index + i;
+               page_xchg_last_nid(page, page_last_nid(page_tail));
 
                BUG_ON(!PageAnon(page_tail));
                BUG_ON(!PageUptodate(page_tail));
@@ -1343,63 +1492,60 @@ static int __split_huge_page_map(struct page *page,
        int ret = 0, i;
        pgtable_t pgtable;
        unsigned long haddr;
+       pgprot_t prot;
 
        spin_lock(&mm->page_table_lock);
        pmd = page_check_address_pmd(page, mm, address,
                                     PAGE_CHECK_ADDRESS_PMD_SPLITTING_FLAG);
-       if (pmd) {
-               pgtable = pgtable_trans_huge_withdraw(mm);
-               pmd_populate(mm, &_pmd, pgtable);
-
-               haddr = address;
-               for (i = 0; i < HPAGE_PMD_NR; i++, haddr += PAGE_SIZE) {
-                       pte_t *pte, entry;
-                       BUG_ON(PageCompound(page+i));
-                       entry = mk_pte(page + i, vma->vm_page_prot);
-                       entry = maybe_mkwrite(pte_mkdirty(entry), vma);
-                       if (!pmd_write(*pmd))
-                               entry = pte_wrprotect(entry);
-                       else
-                               BUG_ON(page_mapcount(page) != 1);
-                       if (!pmd_young(*pmd))
-                               entry = pte_mkold(entry);
-                       pte = pte_offset_map(&_pmd, haddr);
-                       BUG_ON(!pte_none(*pte));
-                       set_pte_at(mm, haddr, pte, entry);
-                       pte_unmap(pte);
-               }
+       if (!pmd)
+               goto unlock;
 
-               smp_wmb(); /* make pte visible before pmd */
-               /*
-                * Up to this point the pmd is present and huge and
-                * userland has the whole access to the hugepage
-                * during the split (which happens in place). If we
-                * overwrite the pmd with the not-huge version
-                * pointing to the pte here (which of course we could
-                * if all CPUs were bug free), userland could trigger
-                * a small page size TLB miss on the small sized TLB
-                * while the hugepage TLB entry is still established
-                * in the huge TLB. Some CPU doesn't like that. See
-                * http://support.amd.com/us/Processor_TechDocs/41322.pdf,
-                * Erratum 383 on page 93. Intel should be safe but is
-                * also warns that it's only safe if the permission
-                * and cache attributes of the two entries loaded in
-                * the two TLB is identical (which should be the case
-                * here). But it is generally safer to never allow
-                * small and huge TLB entries for the same virtual
-                * address to be loaded simultaneously. So instead of
-                * doing "pmd_populate(); flush_tlb_range();" we first
-                * mark the current pmd notpresent (atomically because
-                * here the pmd_trans_huge and pmd_trans_splitting
-                * must remain set at all times on the pmd until the
-                * split is complete for this pmd), then we flush the
-                * SMP TLB and finally we write the non-huge version
-                * of the pmd entry with pmd_populate.
-                */
-               pmdp_invalidate(vma, address, pmd);
-               pmd_populate(mm, pmd, pgtable);
-               ret = 1;
+       prot = pmd_pgprot(*pmd);
+       pgtable = pgtable_trans_huge_withdraw(mm);
+       pmd_populate(mm, &_pmd, pgtable);
+
+       for (i = 0, haddr = address; i < HPAGE_PMD_NR; i++, haddr += PAGE_SIZE) {
+               pte_t *pte, entry;
+
+               BUG_ON(PageCompound(page+i));
+               entry = mk_pte(page + i, prot);
+               entry = pte_mkdirty(entry);
+               if (!pmd_young(*pmd))
+                       entry = pte_mkold(entry);
+               pte = pte_offset_map(&_pmd, haddr);
+               BUG_ON(!pte_none(*pte));
+               set_pte_at(mm, haddr, pte, entry);
+               pte_unmap(pte);
        }
+
+       smp_wmb(); /* make ptes visible before pmd, see __pte_alloc */
+       /*
+        * Up to this point the pmd is present and huge.
+        *
+        * If we overwrite the pmd with the not-huge version, we could trigger
+        * a small page size TLB miss on the small sized TLB while the hugepage
+        * TLB entry is still established in the huge TLB.
+        *
+        * Some CPUs don't like that. See
+        * http://support.amd.com/us/Processor_TechDocs/41322.pdf, Erratum 383
+        * on page 93.
+        *
+        * Thus it is generally safer to never allow small and huge TLB entries
+        * for overlapping virtual addresses to be loaded. So we first mark the
+        * current pmd not present, then we flush the TLB and finally we write
+        * the non-huge version of the pmd entry with pmd_populate.
+        *
+        * The above needs to be done under the ptl because pmd_trans_huge and
+        * pmd_trans_splitting must remain set on the pmd until the split is
+        * complete. The ptl also protects against concurrent faults due to
+        * making the pmd not-present.
+        */
+       set_pmd_at(mm, address, pmd, pmd_mknotpresent(*pmd));
+       flush_tlb_range(vma, address, address + HPAGE_PMD_SIZE);
+       pmd_populate(mm, pmd, pgtable);
+       ret = 1;
+
+unlock:
        spin_unlock(&mm->page_table_lock);
 
        return ret;
@@ -2287,10 +2433,8 @@ static void khugepaged_do_scan(void)
 {
        struct page *hpage = NULL;
        unsigned int progress = 0, pass_through_head = 0;
-       unsigned int pages = khugepaged_pages_to_scan;
        bool wait = true;
-
-       barrier(); /* write khugepaged_pages_to_scan to local stack */
+       unsigned int pages = ACCESS_ONCE(khugepaged_pages_to_scan);
 
        while (progress < pages) {
                if (!khugepaged_prealloc_page(&hpage, &wait))
index fb135ba4aba90349e58c79d49838860cb7db8105..b197b19d540073017d0cb68614066789ac81b1fe 100644 (file)
@@ -36,6 +36,8 @@
  *             (Gerhard.Wichert@pdb.siemens.de)
  *
  * Aug/Sep 2004 Changed to four level page tables (Andi Kleen)
+ *
+ * 2012 - NUMA placement page faults (Andrea Arcangeli, Peter Zijlstra)
  */
 
 #include <linux/kernel_stat.h>
@@ -57,6 +59,7 @@
 #include <linux/swapops.h>
 #include <linux/elf.h>
 #include <linux/gfp.h>
+#include <linux/migrate.h>
 
 #include <asm/io.h>
 #include <asm/pgalloc.h>
 
 #include "internal.h"
 
+#ifdef LAST_NID_NOT_IN_PAGE_FLAGS
+#warning Unfortunate NUMA config, growing page-frame for last_nid.
+#endif
+
 #ifndef CONFIG_NEED_MULTIPLE_NODES
 /* use the per-pgdat data instead for discontigmem - mbligh */
 unsigned long max_mapnr;
@@ -1464,6 +1471,27 @@ int zap_vma_ptes(struct vm_area_struct *vma, unsigned long address,
 }
 EXPORT_SYMBOL_GPL(zap_vma_ptes);
 
+static bool pte_numa(struct vm_area_struct *vma, pte_t pte)
+{
+       /*
+        * For NUMA page faults, we use PROT_NONE ptes in VMAs with
+        * "normal" vma->vm_page_prot protections.  Genuine PROT_NONE
+        * VMAs should never get here, because the fault handling code
+        * will notice that the VMA has no read or write permissions.
+        *
+        * This means we cannot get 'special' PROT_NONE faults from genuine
+        * PROT_NONE maps, nor from PROT_WRITE file maps that do dirty
+        * tracking.
+        *
+        * Neither case is really interesting for our current use though so we
+        * don't care.
+        */
+       if (pte_same(pte, pte_modify(pte, vma->vm_page_prot)))
+               return false;
+
+       return pte_same(pte, pte_modify(pte, vma_prot_none(vma)));
+}
+
 /**
  * follow_page - look up a page descriptor from a user-virtual address
  * @vma: vm_area_struct mapping @address
@@ -1517,6 +1545,8 @@ struct page *follow_page(struct vm_area_struct *vma, unsigned long address,
                page = follow_huge_pmd(mm, address, pmd, flags & FOLL_WRITE);
                goto out;
        }
+       if ((flags & FOLL_NUMA) && pmd_numa(vma, *pmd))
+               goto no_page_table;
        if (pmd_trans_huge(*pmd)) {
                if (flags & FOLL_SPLIT) {
                        split_huge_page_pmd(mm, pmd);
@@ -1546,6 +1576,8 @@ split_fallthrough:
        pte = *ptep;
        if (!pte_present(pte))
                goto no_page;
+       if ((flags & FOLL_NUMA) && pte_numa(vma, pte))
+               goto no_page;
        if ((flags & FOLL_WRITE) && !pte_write(pte))
                goto unlock;
 
@@ -1697,6 +1729,19 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
                        (VM_WRITE | VM_MAYWRITE) : (VM_READ | VM_MAYREAD);
        vm_flags &= (gup_flags & FOLL_FORCE) ?
                        (VM_MAYREAD | VM_MAYWRITE) : (VM_READ | VM_WRITE);
+
+       /*
+        * If FOLL_FORCE and FOLL_NUMA are both set, handle_mm_fault
+        * would be called on PROT_NONE ranges. We must never invoke
+        * handle_mm_fault on PROT_NONE ranges or the NUMA hinting
+        * page faults would unprotect the PROT_NONE ranges if
+        * _PAGE_NUMA and _PAGE_PROTNONE are sharing the same pte/pmd
+        * bitflag. So to avoid that, don't set FOLL_NUMA if
+        * FOLL_FORCE is set.
+        */
+       if (!(gup_flags & FOLL_FORCE))
+               gup_flags |= FOLL_NUMA;
+
        i = 0;
 
        do {
@@ -3433,6 +3478,67 @@ static int do_nonlinear_fault(struct mm_struct *mm, struct vm_area_struct *vma,
        return __do_fault(mm, vma, address, pmd, pgoff, flags, orig_pte);
 }
 
+static int do_numa_page(struct mm_struct *mm, struct vm_area_struct *vma,
+                       unsigned long address, pte_t *ptep, pmd_t *pmd,
+                       unsigned int flags, pte_t entry)
+{
+       struct page *page = NULL;
+       int node, page_nid = -1;
+       spinlock_t *ptl;
+
+       ptl = pte_lockptr(mm, pmd);
+       spin_lock(ptl);
+       if (unlikely(!pte_same(*ptep, entry)))
+               goto out_unlock;
+
+       page = vm_normal_page(vma, address, entry);
+       if (page) {
+               get_page(page);
+               page_nid = page_to_nid(page);
+               node = mpol_misplaced(page, vma, address);
+               if (node != -1)
+                       goto migrate;
+       }
+
+out_pte_upgrade_unlock:
+       flush_cache_page(vma, address, pte_pfn(entry));
+
+       ptep_modify_prot_start(mm, address, ptep);
+       entry = pte_modify(entry, vma->vm_page_prot);
+       ptep_modify_prot_commit(mm, address, ptep, entry);
+
+       /* No TLB flush needed because we upgraded the PTE */
+
+       update_mmu_cache(vma, address, ptep);
+
+out_unlock:
+       pte_unmap_unlock(ptep, ptl);
+out:
+       if (page) {
+               task_numa_fault(page_nid, 1);
+               put_page(page);
+       }
+
+       return 0;
+
+migrate:
+       pte_unmap_unlock(ptep, ptl);
+
+       if (!migrate_misplaced_page(page, node)) {
+               page_nid = node;
+               goto out;
+       }
+
+       ptep = pte_offset_map_lock(mm, pmd, address, &ptl);
+       if (!pte_same(*ptep, entry)) {
+               put_page(page);
+               page = NULL;
+               goto out_unlock;
+       }
+
+       goto out_pte_upgrade_unlock;
+}
+
 /*
  * These routines also need to handle stuff like marking pages dirty
  * and/or accessed for architectures that don't do it in hardware (most
@@ -3453,7 +3559,7 @@ int handle_pte_fault(struct mm_struct *mm,
        pte_t entry;
        spinlock_t *ptl;
 
-       entry = *pte;
+       entry = ACCESS_ONCE(*pte);
        if (!pte_present(entry)) {
                if (pte_none(entry)) {
                        if (vma->vm_ops) {
@@ -3471,6 +3577,9 @@ int handle_pte_fault(struct mm_struct *mm,
                                        pte, pmd, flags, entry);
        }
 
+       if (pte_numa(vma, entry))
+               return do_numa_page(mm, vma, address, pte, pmd, flags, entry);
+
        ptl = pte_lockptr(mm, pmd);
        spin_lock(ptl);
        if (unlikely(!pte_same(*pte, entry)))
@@ -3535,13 +3644,16 @@ retry:
                                                          pmd, flags);
        } else {
                pmd_t orig_pmd = *pmd;
-               int ret;
+               int ret = 0;
 
                barrier();
-               if (pmd_trans_huge(orig_pmd)) {
-                       if (flags & FAULT_FLAG_WRITE &&
-                           !pmd_write(orig_pmd) &&
-                           !pmd_trans_splitting(orig_pmd)) {
+               if (pmd_trans_huge(orig_pmd) && !pmd_trans_splitting(orig_pmd)) {
+                       if (pmd_numa(vma, orig_pmd)) {
+                               do_huge_pmd_numa_page(mm, vma, address, pmd,
+                                                     flags, orig_pmd);
+                       }
+
+                       if ((flags & FAULT_FLAG_WRITE) && !pmd_write(orig_pmd)) {
                                ret = do_huge_pmd_wp_page(mm, vma, address, pmd,
                                                          orig_pmd);
                                /*
@@ -3551,18 +3663,20 @@ retry:
                                 */
                                if (unlikely(ret & VM_FAULT_OOM))
                                        goto retry;
-                               return ret;
                        }
-                       return 0;
+
+                       return ret;
                }
        }
 
+
        /*
         * Use __pte_alloc instead of pte_alloc_map, because we can't
         * run pte_offset_map on the pmd, if an huge pmd could
         * materialize from under us from a different thread.
         */
-       if (unlikely(pmd_none(*pmd)) && __pte_alloc(mm, vma, pmd, address))
+       if (unlikely(pmd_none(*pmd)) &&
+           unlikely(__pte_alloc(mm, vma, pmd, address)))
                return VM_FAULT_OOM;
        /* if an huge pmd materialized from under us just retry later */
        if (unlikely(pmd_trans_huge(*pmd)))
index d04a8a54c294f852f55e624e3c41d1b03b7a56e9..d998810c7ec095da1f6506c2335f0751e7cd38c1 100644 (file)
@@ -117,6 +117,22 @@ static struct mempolicy default_policy = {
        .flags = MPOL_F_LOCAL,
 };
 
+static struct mempolicy preferred_node_policy[MAX_NUMNODES];
+
+static struct mempolicy *get_task_policy(struct task_struct *p)
+{
+       struct mempolicy *pol = p->mempolicy;
+       int node;
+
+       if (!pol) {
+               node = tsk_home_node(p);
+               if (node != -1)
+                       pol = &preferred_node_policy[node];
+       }
+
+       return pol;
+}
+
 static const struct mempolicy_operations {
        int (*create)(struct mempolicy *pol, const nodemask_t *nodes);
        /*
@@ -251,10 +267,10 @@ static struct mempolicy *mpol_new(unsigned short mode, unsigned short flags,
        pr_debug("setting mode %d flags %d nodes[0] %lx\n",
                 mode, flags, nodes ? nodes_addr(*nodes)[0] : -1);
 
-       if (mode == MPOL_DEFAULT) {
+       if (mode == MPOL_DEFAULT || mode == MPOL_NOOP) {
                if (nodes && !nodes_empty(*nodes))
                        return ERR_PTR(-EINVAL);
-               return NULL;    /* simply delete any existing policy */
+               return NULL;
        }
        VM_BUG_ON(!nodes);
 
@@ -269,6 +285,10 @@ static struct mempolicy *mpol_new(unsigned short mode, unsigned short flags,
                             (flags & MPOL_F_RELATIVE_NODES)))
                                return ERR_PTR(-EINVAL);
                }
+       } else if (mode == MPOL_LOCAL) {
+               if (!nodes_empty(*nodes))
+                       return ERR_PTR(-EINVAL);
+               mode = MPOL_PREFERRED;
        } else if (nodes_empty(*nodes))
                return ERR_PTR(-EINVAL);
        policy = kmem_cache_alloc(policy_cache, GFP_KERNEL);
@@ -579,22 +599,32 @@ check_range(struct mm_struct *mm, unsigned long start, unsigned long end,
                return ERR_PTR(-EFAULT);
        prev = NULL;
        for (vma = first; vma && vma->vm_start < end; vma = vma->vm_next) {
+               unsigned long endvma = vma->vm_end;
+
+               if (endvma > end)
+                       endvma = end;
+               if (vma->vm_start > start)
+                       start = vma->vm_start;
+
                if (!(flags & MPOL_MF_DISCONTIG_OK)) {
                        if (!vma->vm_next && vma->vm_end < end)
                                return ERR_PTR(-EFAULT);
                        if (prev && prev->vm_end < vma->vm_start)
                                return ERR_PTR(-EFAULT);
                }
-               if (!is_vm_hugetlb_page(vma) &&
-                   ((flags & MPOL_MF_STRICT) ||
+
+               if (is_vm_hugetlb_page(vma))
+                       goto next;
+
+               if (flags & MPOL_MF_LAZY) {
+                       change_prot_none(vma, start, endvma);
+                       goto next;
+               }
+
+               if ((flags & MPOL_MF_STRICT) ||
                     ((flags & (MPOL_MF_MOVE | MPOL_MF_MOVE_ALL)) &&
-                               vma_migratable(vma)))) {
-                       unsigned long endvma = vma->vm_end;
+                     vma_migratable(vma))) {
 
-                       if (endvma > end)
-                               endvma = end;
-                       if (vma->vm_start > start)
-                               start = vma->vm_start;
                        err = check_pgd_range(vma, start, endvma, nodes,
                                                flags, private);
                        if (err) {
@@ -602,6 +632,7 @@ check_range(struct mm_struct *mm, unsigned long start, unsigned long end,
                                break;
                        }
                }
+next:
                prev = vma;
        }
        return first;
@@ -1133,8 +1164,7 @@ static long do_mbind(unsigned long start, unsigned long len,
        int err;
        LIST_HEAD(pagelist);
 
-       if (flags & ~(unsigned long)(MPOL_MF_STRICT |
-                                    MPOL_MF_MOVE | MPOL_MF_MOVE_ALL))
+       if (flags & ~(unsigned long)MPOL_MF_VALID)
                return -EINVAL;
        if ((flags & MPOL_MF_MOVE_ALL) && !capable(CAP_SYS_NICE))
                return -EPERM;
@@ -1142,7 +1172,7 @@ static long do_mbind(unsigned long start, unsigned long len,
        if (start & ~PAGE_MASK)
                return -EINVAL;
 
-       if (mode == MPOL_DEFAULT)
+       if (mode == MPOL_DEFAULT || mode == MPOL_NOOP)
                flags &= ~MPOL_MF_STRICT;
 
        len = (len + PAGE_SIZE - 1) & PAGE_MASK;
@@ -1157,6 +1187,9 @@ static long do_mbind(unsigned long start, unsigned long len,
        if (IS_ERR(new))
                return PTR_ERR(new);
 
+       if (flags & MPOL_MF_LAZY)
+               new->flags |= MPOL_F_MOF;
+
        /*
         * If we are using the default policy then operation
         * on discontinuous address spaces is okay after all
@@ -1193,21 +1226,23 @@ static long do_mbind(unsigned long start, unsigned long len,
        vma = check_range(mm, start, end, nmask,
                          flags | MPOL_MF_INVERT, &pagelist);
 
-       err = PTR_ERR(vma);
-       if (!IS_ERR(vma)) {
-               int nr_failed = 0;
-
+       err = PTR_ERR(vma);     /* maybe ... */
+       if (!IS_ERR(vma) && mode != MPOL_NOOP)
                err = mbind_range(mm, start, end, new);
 
+       if (!err) {
+               int nr_failed = 0;
+
                if (!list_empty(&pagelist)) {
+                       WARN_ON_ONCE(flags & MPOL_MF_LAZY);
                        nr_failed = migrate_pages(&pagelist, new_vma_page,
-                                               (unsigned long)vma,
-                                               false, MIGRATE_SYNC);
+                                                 (unsigned long)vma,
+                                                 false, MIGRATE_SYNC);
                        if (nr_failed)
                                putback_lru_pages(&pagelist);
                }
 
-               if (!err && nr_failed && (flags & MPOL_MF_STRICT))
+               if (nr_failed && (flags & MPOL_MF_STRICT))
                        err = -EIO;
        } else
                putback_lru_pages(&pagelist);
@@ -1546,7 +1581,7 @@ asmlinkage long compat_sys_mbind(compat_ulong_t start, compat_ulong_t len,
 struct mempolicy *get_vma_policy(struct task_struct *task,
                struct vm_area_struct *vma, unsigned long addr)
 {
-       struct mempolicy *pol = task->mempolicy;
+       struct mempolicy *pol = get_task_policy(task);
 
        if (vma) {
                if (vma->vm_ops && vma->vm_ops->get_policy) {
@@ -1587,11 +1622,29 @@ static nodemask_t *policy_nodemask(gfp_t gfp, struct mempolicy *policy)
        return NULL;
 }
 
+/* Do dynamic interleaving for a process */
+static unsigned interleave_nodes(struct mempolicy *policy)
+{
+       unsigned nid, next;
+       struct task_struct *me = current;
+
+       nid = me->il_next;
+       next = next_node(nid, policy->v.nodes);
+       if (next >= MAX_NUMNODES)
+               next = first_node(policy->v.nodes);
+       if (next < MAX_NUMNODES)
+               me->il_next = next;
+       return nid;
+}
+
 /* Return a zonelist indicated by gfp for node representing a mempolicy */
 static struct zonelist *policy_zonelist(gfp_t gfp, struct mempolicy *policy,
        int nd)
 {
        switch (policy->mode) {
+       case MPOL_INTERLEAVE:
+               nd = interleave_nodes(policy);
+               break;
        case MPOL_PREFERRED:
                if (!(policy->flags & MPOL_F_LOCAL))
                        nd = policy->v.preferred_node;
@@ -1613,21 +1666,6 @@ static struct zonelist *policy_zonelist(gfp_t gfp, struct mempolicy *policy,
        return node_zonelist(nd, gfp);
 }
 
-/* Do dynamic interleaving for a process */
-static unsigned interleave_nodes(struct mempolicy *policy)
-{
-       unsigned nid, next;
-       struct task_struct *me = current;
-
-       nid = me->il_next;
-       next = next_node(nid, policy->v.nodes);
-       if (next >= MAX_NUMNODES)
-               next = first_node(policy->v.nodes);
-       if (next < MAX_NUMNODES)
-               me->il_next = next;
-       return nid;
-}
-
 /*
  * Depending on the memory policy provide a node from which to allocate the
  * next slab entry.
@@ -1864,21 +1902,6 @@ out:
        return ret;
 }
 
-/* Allocate a page in interleaved policy.
-   Own path because it needs to do special accounting. */
-static struct page *alloc_page_interleave(gfp_t gfp, unsigned order,
-                                       unsigned nid)
-{
-       struct zonelist *zl;
-       struct page *page;
-
-       zl = node_zonelist(nid, gfp);
-       page = __alloc_pages(gfp, order, zl);
-       if (page && page_zone(page) == zonelist_zone(&zl->_zonerefs[0]))
-               inc_zone_page_state(page, NUMA_INTERLEAVE_HIT);
-       return page;
-}
-
 /**
  *     alloc_pages_vma - Allocate a page for a VMA.
  *
@@ -1915,17 +1938,6 @@ retry_cpuset:
        pol = get_vma_policy(current, vma, addr);
        cpuset_mems_cookie = get_mems_allowed();
 
-       if (unlikely(pol->mode == MPOL_INTERLEAVE)) {
-               unsigned nid;
-
-               nid = interleave_nid(pol, vma, addr, PAGE_SHIFT + order);
-               mpol_cond_put(pol);
-               page = alloc_page_interleave(gfp, order, nid);
-               if (unlikely(!put_mems_allowed(cpuset_mems_cookie) && !page))
-                       goto retry_cpuset;
-
-               return page;
-       }
        zl = policy_zonelist(gfp, pol, node);
        if (unlikely(mpol_needs_cond_ref(pol))) {
                /*
@@ -1969,7 +1981,7 @@ retry_cpuset:
  */
 struct page *alloc_pages_current(gfp_t gfp, unsigned order)
 {
-       struct mempolicy *pol = current->mempolicy;
+       struct mempolicy *pol = get_task_policy(current);
        struct page *page;
        unsigned int cpuset_mems_cookie;
 
@@ -1983,12 +1995,9 @@ retry_cpuset:
         * No reference counting needed for current->mempolicy
         * nor system default_policy
         */
-       if (pol->mode == MPOL_INTERLEAVE)
-               page = alloc_page_interleave(gfp, order, interleave_nodes(pol));
-       else
-               page = __alloc_pages_nodemask(gfp, order,
-                               policy_zonelist(gfp, pol, numa_node_id()),
-                               policy_nodemask(gfp, pol));
+       page = __alloc_pages_nodemask(gfp, order,
+                       policy_zonelist(gfp, pol, numa_node_id()),
+                       policy_nodemask(gfp, pol));
 
        if (unlikely(!put_mems_allowed(cpuset_mems_cookie) && !page))
                goto retry_cpuset;
@@ -2175,6 +2184,115 @@ static void sp_free(struct sp_node *n)
        kmem_cache_free(sn_cache, n);
 }
 
+/**
+ * mpol_misplaced - check whether current page node is valid in policy
+ *
+ * @page   - page to be checked
+ * @vma    - vm area where page mapped
+ * @addr   - virtual address where page mapped
+ * @multi  - use multi-stage node binding
+ *
+ * Lookup current policy node id for vma,addr and "compare to" page's
+ * node id.
+ *
+ * Returns:
+ *     -1      - not misplaced, page is in the right node
+ *     node    - node id where the page should be
+ *
+ * Policy determination "mimics" alloc_page_vma().
+ * Called from fault path where we know the vma and faulting address.
+ */
+int mpol_misplaced(struct page *page, struct vm_area_struct *vma,
+                  unsigned long addr)
+{
+       struct mempolicy *pol;
+       struct zone *zone;
+       int curnid = page_to_nid(page);
+       unsigned long pgoff;
+       int polnid = -1;
+       int ret = -1;
+
+       BUG_ON(!vma);
+
+       pol = get_vma_policy(current, vma, addr);
+       if (!(pol->flags & MPOL_F_MOF))
+               goto out;
+
+       switch (pol->mode) {
+       case MPOL_INTERLEAVE:
+               BUG_ON(addr >= vma->vm_end);
+               BUG_ON(addr < vma->vm_start);
+
+               pgoff = vma->vm_pgoff;
+               pgoff += (addr - vma->vm_start) >> PAGE_SHIFT;
+               polnid = offset_il_node(pol, vma, pgoff);
+               break;
+
+       case MPOL_PREFERRED:
+               if (pol->flags & MPOL_F_LOCAL)
+                       polnid = numa_node_id();
+               else
+                       polnid = pol->v.preferred_node;
+               break;
+
+       case MPOL_BIND:
+               /*
+                * allows binding to multiple nodes.
+                * use current page if in policy nodemask,
+                * else select nearest allowed node, if any.
+                * If no allowed nodes, use current [!misplaced].
+                */
+               if (node_isset(curnid, pol->v.nodes))
+                       goto out;
+               (void)first_zones_zonelist(
+                               node_zonelist(numa_node_id(), GFP_HIGHUSER),
+                               gfp_zone(GFP_HIGHUSER),
+                               &pol->v.nodes, &zone);
+               polnid = zone->node;
+               break;
+
+       default:
+               BUG();
+       }
+
+       /*
+        * Multi-stage node selection is used in conjunction with a periodic
+        * migration fault to build a temporal task<->page relation. By
+        * using a two-stage filter we remove short/unlikely relations.
+        *
+        * Using P(p) ~ n_p / n_t as per frequentist probability, we can
+        * equate a task's usage of a particular page (n_p) per total usage
+        * of this page (n_t) (in a given time-span) to a probability.
+        *
+        * Our periodic faults will then sample this probability and getting
+        * the same result twice in a row, given these samples are fully
+        * independent, is then given by P(n)^2, provided our sample period
+        * is sufficiently short compared to the usage pattern.
+        *
+        * This quadric squishes small probabilities, making it less likely
+        * we act on an unlikely task<->page relation.
+        */
+       if (pol->flags & MPOL_F_HOME) {
+               int last_nid;
+
+               /*
+                * Migrate towards the current node, depends on
+                * task_numa_placement() details.
+                */
+               polnid = numa_node_id();
+               last_nid = page_xchg_last_nid(page, polnid);
+               if (last_nid != polnid)
+                       goto out;
+       }
+
+       if (curnid != polnid)
+               ret = polnid;
+out:
+       mpol_cond_put(pol);
+
+       return ret;
+}
+
 static void sp_delete(struct shared_policy *sp, struct sp_node *n)
 {
        pr_debug("deleting %lx-l%lx\n", n->start, n->end);
@@ -2355,6 +2473,15 @@ void __init numa_policy_init(void)
                                     sizeof(struct sp_node),
                                     0, SLAB_PANIC, NULL);
 
+       for_each_node(nid) {
+               preferred_node_policy[nid] = (struct mempolicy) {
+                       .refcnt = ATOMIC_INIT(1),
+                       .mode = MPOL_PREFERRED,
+                       .flags = MPOL_F_MOF | MPOL_F_HOME,
+                       .v = { .preferred_node = nid, },
+               };
+       }
+
        /*
         * Set interleaving policy for system init. Interleaving is only
         * enabled across suitably sized nodes (default is >= 16MB), or
@@ -2397,14 +2524,14 @@ void numa_default_policy(void)
  * "local" is pseudo-policy:  MPOL_PREFERRED with MPOL_F_LOCAL flag
  * Used only for mpol_parse_str() and mpol_to_str()
  */
-#define MPOL_LOCAL MPOL_MAX
 static const char * const policy_modes[] =
 {
        [MPOL_DEFAULT]    = "default",
        [MPOL_PREFERRED]  = "prefer",
        [MPOL_BIND]       = "bind",
        [MPOL_INTERLEAVE] = "interleave",
-       [MPOL_LOCAL]      = "local"
+       [MPOL_LOCAL]      = "local",
+       [MPOL_NOOP]       = "noop",     /* should not actually be used */
 };
 
 
@@ -2450,12 +2577,12 @@ int mpol_parse_str(char *str, struct mempolicy **mpol, int no_context)
        if (flags)
                *flags++ = '\0';        /* terminate mode string */
 
-       for (mode = 0; mode <= MPOL_LOCAL; mode++) {
+       for (mode = 0; mode < MPOL_MAX; mode++) {
                if (!strcmp(str, policy_modes[mode])) {
                        break;
                }
        }
-       if (mode > MPOL_LOCAL)
+       if (mode >= MPOL_MAX || mode == MPOL_NOOP)
                goto out;
 
        switch (mode) {
index 77ed2d7737056eea742eb29601373e7996b14432..72d10560caf6d61746bf5c1747a2d63e6fab1fc2 100644 (file)
@@ -225,7 +225,7 @@ static bool buffer_migrate_lock_buffers(struct buffer_head *head,
        struct buffer_head *bh = head;
 
        /* Simple case, sync compaction */
-       if (mode != MIGRATE_ASYNC) {
+       if (mode != MIGRATE_ASYNC && mode != MIGRATE_FAULT) {
                do {
                        get_bh(bh);
                        lock_buffer(bh);
@@ -279,12 +279,22 @@ static int migrate_page_move_mapping(struct address_space *mapping,
                struct page *newpage, struct page *page,
                struct buffer_head *head, enum migrate_mode mode)
 {
-       int expected_count;
+       int expected_count = 0;
        void **pslot;
 
+       if (mode == MIGRATE_FAULT) {
+               /*
+                * MIGRATE_FAULT has an extra reference on the page and
+                * otherwise acts like ASYNC, no point in delaying the
+                * fault, we'll try again next time.
+                */
+               expected_count++;
+       }
+
        if (!mapping) {
                /* Anonymous page without mapping */
-               if (page_count(page) != 1)
+               expected_count += 1;
+               if (page_count(page) != expected_count)
                        return -EAGAIN;
                return 0;
        }
@@ -294,7 +304,7 @@ static int migrate_page_move_mapping(struct address_space *mapping,
        pslot = radix_tree_lookup_slot(&mapping->page_tree,
                                        page_index(page));
 
-       expected_count = 2 + page_has_private(page);
+       expected_count += 2 + page_has_private(page);
        if (page_count(page) != expected_count ||
                radix_tree_deref_slot_protected(pslot, &mapping->tree_lock) != page) {
                spin_unlock_irq(&mapping->tree_lock);
@@ -313,7 +323,7 @@ static int migrate_page_move_mapping(struct address_space *mapping,
         * the mapping back due to an elevated page count, we would have to
         * block waiting on other references to be dropped.
         */
-       if (mode == MIGRATE_ASYNC && head &&
+       if ((mode == MIGRATE_ASYNC || mode == MIGRATE_FAULT) && head &&
                        !buffer_migrate_lock_buffers(head, mode)) {
                page_unfreeze_refs(page, expected_count);
                spin_unlock_irq(&mapping->tree_lock);
@@ -407,7 +417,7 @@ int migrate_huge_page_move_mapping(struct address_space *mapping,
  */
 void migrate_page_copy(struct page *newpage, struct page *page)
 {
-       if (PageHuge(page))
+       if (PageHuge(page) || PageTransHuge(page))
                copy_huge_page(newpage, page);
        else
                copy_highpage(newpage, page);
@@ -521,7 +531,7 @@ int buffer_migrate_page(struct address_space *mapping,
         * with an IRQ-safe spinlock held. In the sync case, the buffers
         * need to be locked now
         */
-       if (mode != MIGRATE_ASYNC)
+       if (mode != MIGRATE_ASYNC && mode != MIGRATE_FAULT)
                BUG_ON(!buffer_migrate_lock_buffers(head, mode));
 
        ClearPagePrivate(page);
@@ -687,7 +697,7 @@ static int __unmap_and_move(struct page *page, struct page *newpage,
        struct anon_vma *anon_vma = NULL;
 
        if (!trylock_page(page)) {
-               if (!force || mode == MIGRATE_ASYNC)
+               if (!force || mode == MIGRATE_ASYNC || mode == MIGRATE_FAULT)
                        goto out;
 
                /*
@@ -1403,4 +1413,63 @@ int migrate_vmas(struct mm_struct *mm, const nodemask_t *to,
        }
        return err;
 }
-#endif
+
+/*
+ * Attempt to migrate a misplaced page to the specified destination
+ * node.
+ */
+int migrate_misplaced_page(struct page *page, int node)
+{
+       struct address_space *mapping = page_mapping(page);
+       int page_lru = page_is_file_cache(page);
+       struct page *newpage;
+       int ret = -EAGAIN;
+       gfp_t gfp = GFP_HIGHUSER_MOVABLE;
+
+       /*
+        * Don't migrate pages that are mapped in multiple processes.
+        */
+       if (page_mapcount(page) != 1)
+               goto out;
+
+       /*
+        * Never wait for allocations just to migrate on fault, but don't dip
+        * into reserves. And, only accept pages from the specified node. No
+        * sense migrating to a different "misplaced" page!
+        */
+       if (mapping)
+               gfp = mapping_gfp_mask(mapping);
+       gfp &= ~__GFP_WAIT;
+       gfp |= __GFP_NOMEMALLOC | GFP_THISNODE;
+
+       newpage = alloc_pages_node(node, gfp, 0);
+       if (!newpage) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       if (isolate_lru_page(page)) {
+               ret = -EBUSY;
+               goto put_new;
+       }
+
+       inc_zone_page_state(page, NR_ISOLATED_ANON + page_lru);
+       ret = __unmap_and_move(page, newpage, 0, 0, MIGRATE_FAULT);
+       /*
+        * A page that has been migrated has all references removed and will be
+        * freed. A page that has not been migrated will have kepts its
+        * references and be restored.
+        */
+       dec_zone_page_state(page, NR_ISOLATED_ANON + page_lru);
+       putback_lru_page(page);
+put_new:
+       /*
+        * Move the new page to the LRU. If migration was not successful
+        * then this will free the page.
+        */
+       putback_lru_page(newpage);
+out:
+       return ret;
+}
+
+#endif /* CONFIG_NUMA */
index a40992610ab6f6c0cbe96f9a9bd43a3fa973fd96..392b124b4bee8b5735841704371e9aa06dd4497f 100644 (file)
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
 
-#ifndef pgprot_modify
-static inline pgprot_t pgprot_modify(pgprot_t oldprot, pgprot_t newprot)
-{
-       return newprot;
-}
-#endif
-
 static void change_pte_range(struct mm_struct *mm, pmd_t *pmd,
                unsigned long addr, unsigned long end, pgprot_t newprot,
                int dirty_accountable)
@@ -119,7 +112,7 @@ static inline void change_pud_range(struct vm_area_struct *vma, pgd_t *pgd,
        } while (pud++, addr = next, addr != end);
 }
 
-static void change_protection(struct vm_area_struct *vma,
+static void change_protection_range(struct vm_area_struct *vma,
                unsigned long addr, unsigned long end, pgprot_t newprot,
                int dirty_accountable)
 {
@@ -141,6 +134,20 @@ static void change_protection(struct vm_area_struct *vma,
        flush_tlb_range(vma, start, end);
 }
 
+void change_protection(struct vm_area_struct *vma, unsigned long start,
+                      unsigned long end, pgprot_t newprot,
+                      int dirty_accountable)
+{
+       struct mm_struct *mm = vma->vm_mm;
+
+       mmu_notifier_invalidate_range_start(mm, start, end);
+       if (is_vm_hugetlb_page(vma))
+               hugetlb_change_protection(vma, start, end, newprot);
+       else
+               change_protection_range(vma, start, end, newprot, dirty_accountable);
+       mmu_notifier_invalidate_range_end(mm, start, end);
+}
+
 int
 mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev,
        unsigned long start, unsigned long end, unsigned long newflags)
@@ -213,12 +220,8 @@ success:
                dirty_accountable = 1;
        }
 
-       mmu_notifier_invalidate_range_start(mm, start, end);
-       if (is_vm_hugetlb_page(vma))
-               hugetlb_change_protection(vma, start, end, vma->vm_page_prot);
-       else
-               change_protection(vma, start, end, vma->vm_page_prot, dirty_accountable);
-       mmu_notifier_invalidate_range_end(mm, start, end);
+       change_protection(vma, start, end, vma->vm_page_prot, dirty_accountable);
+
        vm_stat_account(mm, oldflags, vma->vm_file, -nrpages);
        vm_stat_account(mm, newflags, vma->vm_file, nrpages);
        perf_event_mmap(vma);
index bb90971182bd8c833e40f508e3c8b8677d6913c8..b0012ab372a45cac2067d75d3b91d34f2d4ad74b 100644 (file)
@@ -5825,7 +5825,7 @@ int alloc_contig_range(unsigned long start, unsigned long end,
        ret = start_isolate_page_range(pfn_max_align_down(start),
                                       pfn_max_align_up(end), migratetype);
        if (ret)
-               goto done;
+               return ret;
 
        ret = __alloc_contig_migrate_range(&cc, start, end);
        if (ret)
index e642627da6b75d7c6cf5258a59cfde49dca7c89e..c1283dd13c7ac03fb1f25cb5527faaa4d7fe078f 100644 (file)
@@ -88,7 +88,8 @@ pte_t ptep_clear_flush(struct vm_area_struct *vma, unsigned long address,
 {
        pte_t pte;
        pte = ptep_get_and_clear((vma)->vm_mm, address, ptep);
-       flush_tlb_page(vma, address);
+       if (pte_accessible(pte))
+               flush_tlb_page(vma, address);
        return pte;
 }
 #endif
index 33d3363658df78bc95b928202856a01ed7c54d77..6d5c83c6ddd5d416ce8ca5716bf38740bbb70540 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -4276,54 +4276,8 @@ out:
 }
 
 #ifdef CONFIG_SLABINFO
-
-static void print_slabinfo_header(struct seq_file *m)
+void get_slabinfo(struct kmem_cache *cachep, struct slabinfo *sinfo)
 {
-       /*
-        * Output format version, so at least we can change it
-        * without _too_ many complaints.
-        */
-#if STATS
-       seq_puts(m, "slabinfo - version: 2.1 (statistics)\n");
-#else
-       seq_puts(m, "slabinfo - version: 2.1\n");
-#endif
-       seq_puts(m, "# name            <active_objs> <num_objs> <objsize> "
-                "<objperslab> <pagesperslab>");
-       seq_puts(m, " : tunables <limit> <batchcount> <sharedfactor>");
-       seq_puts(m, " : slabdata <active_slabs> <num_slabs> <sharedavail>");
-#if STATS
-       seq_puts(m, " : globalstat <listallocs> <maxobjs> <grown> <reaped> "
-                "<error> <maxfreeable> <nodeallocs> <remotefrees> <alienoverflow>");
-       seq_puts(m, " : cpustat <allochit> <allocmiss> <freehit> <freemiss>");
-#endif
-       seq_putc(m, '\n');
-}
-
-static void *s_start(struct seq_file *m, loff_t *pos)
-{
-       loff_t n = *pos;
-
-       mutex_lock(&slab_mutex);
-       if (!n)
-               print_slabinfo_header(m);
-
-       return seq_list_start(&slab_caches, *pos);
-}
-
-static void *s_next(struct seq_file *m, void *p, loff_t *pos)
-{
-       return seq_list_next(p, &slab_caches, pos);
-}
-
-static void s_stop(struct seq_file *m, void *p)
-{
-       mutex_unlock(&slab_mutex);
-}
-
-static int s_show(struct seq_file *m, void *p)
-{
-       struct kmem_cache *cachep = list_entry(p, struct kmem_cache, list);
        struct slab *slabp;
        unsigned long active_objs;
        unsigned long num_objs;
@@ -4378,13 +4332,20 @@ static int s_show(struct seq_file *m, void *p)
        if (error)
                printk(KERN_ERR "slab: cache %s error: %s\n", name, error);
 
-       seq_printf(m, "%-17s %6lu %6lu %6u %4u %4d",
-                  name, active_objs, num_objs, cachep->size,
-                  cachep->num, (1 << cachep->gfporder));
-       seq_printf(m, " : tunables %4u %4u %4u",
-                  cachep->limit, cachep->batchcount, cachep->shared);
-       seq_printf(m, " : slabdata %6lu %6lu %6lu",
-                  active_slabs, num_slabs, shared_avail);
+       sinfo->active_objs = active_objs;
+       sinfo->num_objs = num_objs;
+       sinfo->active_slabs = active_slabs;
+       sinfo->num_slabs = num_slabs;
+       sinfo->shared_avail = shared_avail;
+       sinfo->limit = cachep->limit;
+       sinfo->batchcount = cachep->batchcount;
+       sinfo->shared = cachep->shared;
+       sinfo->objects_per_slab = cachep->num;
+       sinfo->cache_order = cachep->gfporder;
+}
+
+void slabinfo_show_stats(struct seq_file *m, struct kmem_cache *cachep)
+{
 #if STATS
        {                       /* list3 stats */
                unsigned long high = cachep->high_mark;
@@ -4414,31 +4375,8 @@ static int s_show(struct seq_file *m, void *p)
                           allochit, allocmiss, freehit, freemiss);
        }
 #endif
-       seq_putc(m, '\n');
-       return 0;
 }
 
-/*
- * slabinfo_op - iterator that generates /proc/slabinfo
- *
- * Output layout:
- * cache-name
- * num-active-objs
- * total-objs
- * object size
- * num-active-slabs
- * total-slabs
- * num-pages-per-slab
- * + further values on SMP and with statistics enabled
- */
-
-static const struct seq_operations slabinfo_op = {
-       .start = s_start,
-       .next = s_next,
-       .stop = s_stop,
-       .show = s_show,
-};
-
 #define MAX_SLABINFO_WRITE 128
 /**
  * slabinfo_write - Tuning for the slab allocator
@@ -4447,7 +4385,7 @@ static const struct seq_operations slabinfo_op = {
  * @count: data length
  * @ppos: unused
  */
-static ssize_t slabinfo_write(struct file *file, const char __user *buffer,
+ssize_t slabinfo_write(struct file *file, const char __user *buffer,
                       size_t count, loff_t *ppos)
 {
        char kbuf[MAX_SLABINFO_WRITE + 1], *tmp;
@@ -4490,19 +4428,6 @@ static ssize_t slabinfo_write(struct file *file, const char __user *buffer,
        return res;
 }
 
-static int slabinfo_open(struct inode *inode, struct file *file)
-{
-       return seq_open(file, &slabinfo_op);
-}
-
-static const struct file_operations proc_slabinfo_operations = {
-       .open           = slabinfo_open,
-       .read           = seq_read,
-       .write          = slabinfo_write,
-       .llseek         = seq_lseek,
-       .release        = seq_release,
-};
-
 #ifdef CONFIG_DEBUG_SLAB_LEAK
 
 static void *leaks_start(struct seq_file *m, loff_t *pos)
@@ -4631,6 +4556,16 @@ static int leaks_show(struct seq_file *m, void *p)
        return 0;
 }
 
+static void *s_next(struct seq_file *m, void *p, loff_t *pos)
+{
+       return seq_list_next(p, &slab_caches, pos);
+}
+
+static void s_stop(struct seq_file *m, void *p)
+{
+       mutex_unlock(&slab_mutex);
+}
+
 static const struct seq_operations slabstats_op = {
        .start = leaks_start,
        .next = s_next,
@@ -4665,7 +4600,6 @@ static const struct file_operations proc_slabstats_operations = {
 
 static int __init slab_proc_init(void)
 {
-       proc_create("slabinfo",S_IWUSR|S_IRUSR,NULL,&proc_slabinfo_operations);
 #ifdef CONFIG_DEBUG_SLAB_LEAK
        proc_create("slab_allocators", 0, NULL, &proc_slabstats_operations);
 #endif
index 7deeb449a3013ea279fde16bf6935b9d23ba752a..5a43c2f136212292f85e991a95a6d8f56a95f389 100644 (file)
--- a/mm/slab.h
+++ b/mm/slab.h
@@ -47,4 +47,24 @@ static inline struct kmem_cache *__kmem_cache_alias(const char *name, size_t siz
 
 int __kmem_cache_shutdown(struct kmem_cache *);
 
+struct seq_file;
+struct file;
+
+struct slabinfo {
+       unsigned long active_objs;
+       unsigned long num_objs;
+       unsigned long active_slabs;
+       unsigned long num_slabs;
+       unsigned long shared_avail;
+       unsigned int limit;
+       unsigned int batchcount;
+       unsigned int shared;
+       unsigned int objects_per_slab;
+       unsigned int cache_order;
+};
+
+void get_slabinfo(struct kmem_cache *s, struct slabinfo *sinfo);
+void slabinfo_show_stats(struct seq_file *m, struct kmem_cache *s);
+ssize_t slabinfo_write(struct file *file, const char __user *buffer,
+                      size_t count, loff_t *ppos);
 #endif
index 069a24e64403f19bd6f51c9d9a9ef4b56deef48d..5fb753da6cf003aac7caf992f6bacc25101c02bc 100644 (file)
@@ -13,6 +13,8 @@
 #include <linux/module.h>
 #include <linux/cpu.h>
 #include <linux/uaccess.h>
+#include <linux/seq_file.h>
+#include <linux/proc_fs.h>
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
 #include <asm/page.h>
@@ -192,3 +194,110 @@ int slab_is_available(void)
 {
        return slab_state >= UP;
 }
+
+#ifdef CONFIG_SLABINFO
+static void print_slabinfo_header(struct seq_file *m)
+{
+       /*
+        * Output format version, so at least we can change it
+        * without _too_ many complaints.
+        */
+#ifdef CONFIG_DEBUG_SLAB
+       seq_puts(m, "slabinfo - version: 2.1 (statistics)\n");
+#else
+       seq_puts(m, "slabinfo - version: 2.1\n");
+#endif
+       seq_puts(m, "# name            <active_objs> <num_objs> <objsize> "
+                "<objperslab> <pagesperslab>");
+       seq_puts(m, " : tunables <limit> <batchcount> <sharedfactor>");
+       seq_puts(m, " : slabdata <active_slabs> <num_slabs> <sharedavail>");
+#ifdef CONFIG_DEBUG_SLAB
+       seq_puts(m, " : globalstat <listallocs> <maxobjs> <grown> <reaped> "
+                "<error> <maxfreeable> <nodeallocs> <remotefrees> <alienoverflow>");
+       seq_puts(m, " : cpustat <allochit> <allocmiss> <freehit> <freemiss>");
+#endif
+       seq_putc(m, '\n');
+}
+
+static void *s_start(struct seq_file *m, loff_t *pos)
+{
+       loff_t n = *pos;
+
+       mutex_lock(&slab_mutex);
+       if (!n)
+               print_slabinfo_header(m);
+
+       return seq_list_start(&slab_caches, *pos);
+}
+
+static void *s_next(struct seq_file *m, void *p, loff_t *pos)
+{
+       return seq_list_next(p, &slab_caches, pos);
+}
+
+static void s_stop(struct seq_file *m, void *p)
+{
+       mutex_unlock(&slab_mutex);
+}
+
+static int s_show(struct seq_file *m, void *p)
+{
+       struct kmem_cache *s = list_entry(p, struct kmem_cache, list);
+       struct slabinfo sinfo;
+
+       memset(&sinfo, 0, sizeof(sinfo));
+       get_slabinfo(s, &sinfo);
+
+       seq_printf(m, "%-17s %6lu %6lu %6u %4u %4d",
+                  s->name, sinfo.active_objs, sinfo.num_objs, s->size,
+                  sinfo.objects_per_slab, (1 << sinfo.cache_order));
+
+       seq_printf(m, " : tunables %4u %4u %4u",
+                  sinfo.limit, sinfo.batchcount, sinfo.shared);
+       seq_printf(m, " : slabdata %6lu %6lu %6lu",
+                  sinfo.active_slabs, sinfo.num_slabs, sinfo.shared_avail);
+       slabinfo_show_stats(m, s);
+       seq_putc(m, '\n');
+       return 0;
+}
+
+/*
+ * slabinfo_op - iterator that generates /proc/slabinfo
+ *
+ * Output layout:
+ * cache-name
+ * num-active-objs
+ * total-objs
+ * object size
+ * num-active-slabs
+ * total-slabs
+ * num-pages-per-slab
+ * + further values on SMP and with statistics enabled
+ */
+static const struct seq_operations slabinfo_op = {
+       .start = s_start,
+       .next = s_next,
+       .stop = s_stop,
+       .show = s_show,
+};
+
+static int slabinfo_open(struct inode *inode, struct file *file)
+{
+       return seq_open(file, &slabinfo_op);
+}
+
+static const struct file_operations proc_slabinfo_operations = {
+       .open           = slabinfo_open,
+       .read           = seq_read,
+       .write          = slabinfo_write,
+       .llseek         = seq_lseek,
+       .release        = seq_release,
+};
+
+static int __init slab_proc_init(void)
+{
+       proc_create("slabinfo", S_IRUSR, NULL, &proc_slabinfo_operations);
+       return 0;
+}
+module_init(slab_proc_init);
+#endif /* CONFIG_SLABINFO */
index a08e4681fd0d630ff212e299f5b657f71e48c4b0..1e921c5e9576b6db64cc07fb4f4c90a8f4e2729e 100644 (file)
--- a/mm/slob.c
+++ b/mm/slob.c
@@ -429,7 +429,7 @@ static __always_inline void *
 __do_kmalloc_node(size_t size, gfp_t gfp, int node, unsigned long caller)
 {
        unsigned int *m;
-       int align = max(ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN);
+       int align = max_t(size_t, ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN);
        void *ret;
 
        gfp &= gfp_allowed_mask;
@@ -502,7 +502,7 @@ void kfree(const void *block)
 
        sp = virt_to_page(block);
        if (PageSlab(sp)) {
-               int align = max(ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN);
+               int align = max_t(size_t, ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN);
                unsigned int *m = (unsigned int *)(block - align);
                slob_free(m, *m + align);
        } else
@@ -521,7 +521,7 @@ size_t ksize(const void *block)
 
        sp = virt_to_page(block);
        if (PageSlab(sp)) {
-               int align = max(ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN);
+               int align = max_t(size_t, ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN);
                unsigned int *m = (unsigned int *)(block - align);
                return SLOB_UNITS(*m) * SLOB_UNIT;
        } else
index a0d698467f706bd617b960240cbb775cdc9cd034..35483e0ab6bc37046c911ac512a7073b9ab2bb9c 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -1092,11 +1092,11 @@ static noinline struct kmem_cache_node *free_debug_processing(
        if (!check_object(s, page, object, SLUB_RED_ACTIVE))
                goto out;
 
-       if (unlikely(s != page->slab)) {
+       if (unlikely(s != page->slab_cache)) {
                if (!PageSlab(page)) {
                        slab_err(s, page, "Attempt to free object(0x%p) "
                                "outside of slab", object);
-               } else if (!page->slab) {
+               } else if (!page->slab_cache) {
                        printk(KERN_ERR
                                "SLUB <none>: no slab for object 0x%p.\n",
                                                object);
@@ -1357,7 +1357,7 @@ static struct page *new_slab(struct kmem_cache *s, gfp_t flags, int node)
                goto out;
 
        inc_slabs_node(s, page_to_nid(page), page->objects);
-       page->slab = s;
+       page->slab_cache = s;
        __SetPageSlab(page);
        if (page->pfmemalloc)
                SetPageSlabPfmemalloc(page);
@@ -1424,7 +1424,7 @@ static void rcu_free_slab(struct rcu_head *h)
        else
                page = container_of((struct list_head *)h, struct page, lru);
 
-       __free_slab(page->slab, page);
+       __free_slab(page->slab_cache, page);
 }
 
 static void free_slab(struct kmem_cache *s, struct page *page)
@@ -2459,7 +2459,6 @@ static void __slab_free(struct kmem_cache *s, struct page *page,
        void *prior;
        void **object = (void *)x;
        int was_frozen;
-       int inuse;
        struct page new;
        unsigned long counters;
        struct kmem_cache_node *n = NULL;
@@ -2472,13 +2471,17 @@ static void __slab_free(struct kmem_cache *s, struct page *page,
                return;
 
        do {
+               if (unlikely(n)) {
+                       spin_unlock_irqrestore(&n->list_lock, flags);
+                       n = NULL;
+               }
                prior = page->freelist;
                counters = page->counters;
                set_freepointer(s, object, prior);
                new.counters = counters;
                was_frozen = new.frozen;
                new.inuse--;
-               if ((!new.inuse || !prior) && !was_frozen && !n) {
+               if ((!new.inuse || !prior) && !was_frozen) {
 
                        if (!kmem_cache_debug(s) && !prior)
 
@@ -2503,7 +2506,6 @@ static void __slab_free(struct kmem_cache *s, struct page *page,
 
                        }
                }
-               inuse = new.inuse;
 
        } while (!cmpxchg_double_slab(s, page,
                prior, counters,
@@ -2529,25 +2531,17 @@ static void __slab_free(struct kmem_cache *s, struct page *page,
                 return;
         }
 
+       if (unlikely(!new.inuse && n->nr_partial > s->min_partial))
+               goto slab_empty;
+
        /*
-        * was_frozen may have been set after we acquired the list_lock in
-        * an earlier loop. So we need to check it here again.
+        * Objects left in the slab. If it was not on the partial list before
+        * then add it.
         */
-       if (was_frozen)
-               stat(s, FREE_FROZEN);
-       else {
-               if (unlikely(!inuse && n->nr_partial > s->min_partial))
-                        goto slab_empty;
-
-               /*
-                * Objects left in the slab. If it was not on the partial list before
-                * then add it.
-                */
-               if (unlikely(!prior)) {
-                       remove_full(s, page);
-                       add_partial(n, page, DEACTIVATE_TO_TAIL);
-                       stat(s, FREE_ADD_PARTIAL);
-               }
+       if (kmem_cache_debug(s) && unlikely(!prior)) {
+               remove_full(s, page);
+               add_partial(n, page, DEACTIVATE_TO_TAIL);
+               stat(s, FREE_ADD_PARTIAL);
        }
        spin_unlock_irqrestore(&n->list_lock, flags);
        return;
@@ -2623,9 +2617,9 @@ void kmem_cache_free(struct kmem_cache *s, void *x)
 
        page = virt_to_head_page(x);
 
-       if (kmem_cache_debug(s) && page->slab != s) {
+       if (kmem_cache_debug(s) && page->slab_cache != s) {
                pr_err("kmem_cache_free: Wrong slab cache. %s but object"
-                       " is from  %s\n", page->slab->name, s->name);
+                       " is from  %s\n", page->slab_cache->name, s->name);
                WARN_ON_ONCE(1);
                return;
        }
@@ -3424,7 +3418,7 @@ size_t ksize(const void *object)
                return PAGE_SIZE << compound_order(page);
        }
 
-       return slab_ksize(page->slab);
+       return slab_ksize(page->slab_cache);
 }
 EXPORT_SYMBOL(ksize);
 
@@ -3449,8 +3443,8 @@ bool verify_mem_not_deleted(const void *x)
        }
 
        slab_lock(page);
-       if (on_freelist(page->slab, page, object)) {
-               object_err(page->slab, page, object, "Object is on free-list");
+       if (on_freelist(page->slab_cache, page, object)) {
+               object_err(page->slab_cache, page, object, "Object is on free-list");
                rv = false;
        } else {
                rv = true;
@@ -3481,7 +3475,7 @@ void kfree(const void *x)
                __free_pages(page, compound_order(page));
                return;
        }
-       slab_free(page->slab, page, object, _RET_IP_);
+       slab_free(page->slab_cache, page, object, _RET_IP_);
 }
 EXPORT_SYMBOL(kfree);
 
@@ -3692,11 +3686,11 @@ static void __init kmem_cache_bootstrap_fixup(struct kmem_cache *s)
 
                if (n) {
                        list_for_each_entry(p, &n->partial, lru)
-                               p->slab = s;
+                               p->slab_cache = s;
 
 #ifdef CONFIG_SLUB_DEBUG
                        list_for_each_entry(p, &n->full, lru)
-                               p->slab = s;
+                               p->slab_cache = s;
 #endif
                }
        }
@@ -5405,49 +5399,14 @@ __initcall(slab_sysfs_init);
  * The /proc/slabinfo ABI
  */
 #ifdef CONFIG_SLABINFO
-static void print_slabinfo_header(struct seq_file *m)
-{
-       seq_puts(m, "slabinfo - version: 2.1\n");
-       seq_puts(m, "# name            <active_objs> <num_objs> <object_size> "
-                "<objperslab> <pagesperslab>");
-       seq_puts(m, " : tunables <limit> <batchcount> <sharedfactor>");
-       seq_puts(m, " : slabdata <active_slabs> <num_slabs> <sharedavail>");
-       seq_putc(m, '\n');
-}
-
-static void *s_start(struct seq_file *m, loff_t *pos)
-{
-       loff_t n = *pos;
-
-       mutex_lock(&slab_mutex);
-       if (!n)
-               print_slabinfo_header(m);
-
-       return seq_list_start(&slab_caches, *pos);
-}
-
-static void *s_next(struct seq_file *m, void *p, loff_t *pos)
-{
-       return seq_list_next(p, &slab_caches, pos);
-}
-
-static void s_stop(struct seq_file *m, void *p)
-{
-       mutex_unlock(&slab_mutex);
-}
-
-static int s_show(struct seq_file *m, void *p)
+void get_slabinfo(struct kmem_cache *s, struct slabinfo *sinfo)
 {
        unsigned long nr_partials = 0;
        unsigned long nr_slabs = 0;
-       unsigned long nr_inuse = 0;
        unsigned long nr_objs = 0;
        unsigned long nr_free = 0;
-       struct kmem_cache *s;
        int node;
 
-       s = list_entry(p, struct kmem_cache, list);
-
        for_each_online_node(node) {
                struct kmem_cache_node *n = get_node(s, node);
 
@@ -5460,41 +5419,21 @@ static int s_show(struct seq_file *m, void *p)
                nr_free += count_partial(n, count_free);
        }
 
-       nr_inuse = nr_objs - nr_free;
-
-       seq_printf(m, "%-17s %6lu %6lu %6u %4u %4d", s->name, nr_inuse,
-                  nr_objs, s->size, oo_objects(s->oo),
-                  (1 << oo_order(s->oo)));
-       seq_printf(m, " : tunables %4u %4u %4u", 0, 0, 0);
-       seq_printf(m, " : slabdata %6lu %6lu %6lu", nr_slabs, nr_slabs,
-                  0UL);
-       seq_putc(m, '\n');
-       return 0;
+       sinfo->active_objs = nr_objs - nr_free;
+       sinfo->num_objs = nr_objs;
+       sinfo->active_slabs = nr_slabs;
+       sinfo->num_slabs = nr_slabs;
+       sinfo->objects_per_slab = oo_objects(s->oo);
+       sinfo->cache_order = oo_order(s->oo);
 }
 
-static const struct seq_operations slabinfo_op = {
-       .start = s_start,
-       .next = s_next,
-       .stop = s_stop,
-       .show = s_show,
-};
-
-static int slabinfo_open(struct inode *inode, struct file *file)
+void slabinfo_show_stats(struct seq_file *m, struct kmem_cache *s)
 {
-       return seq_open(file, &slabinfo_op);
 }
 
-static const struct file_operations proc_slabinfo_operations = {
-       .open           = slabinfo_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = seq_release,
-};
-
-static int __init slab_proc_init(void)
+ssize_t slabinfo_write(struct file *file, const char __user *buffer,
+                      size_t count, loff_t *ppos)
 {
-       proc_create("slabinfo", S_IRUSR, NULL, &proc_slabinfo_operations);
-       return 0;
+       return -EIO;
 }
-module_init(slab_proc_init);
 #endif /* CONFIG_SLABINFO */
index dc3036cdcc6a60ac4e8bea6521279b2cff687bcb..c55e26b17d93de77dc069d7f30019f7391e0d93f 100644 (file)
--- a/mm/util.c
+++ b/mm/util.c
@@ -152,7 +152,7 @@ EXPORT_SYMBOL(__krealloc);
  *
  * The contents of the object pointed to are preserved up to the
  * lesser of the new and old sizes.  If @p is %NULL, krealloc()
- * behaves exactly like kmalloc().  If @size is 0 and @p is not a
+ * behaves exactly like kmalloc().  If @new_size is 0 and @p is not a
  * %NULL pointer, the object pointed to is freed.
  */
 void *krealloc(const void *p, size_t new_size, gfp_t flags)
index c7370579111b872943c56bd694dc0bd02121092d..8fafa32e00cb6820912c96d3b5c66bcd01b415ca 100644 (file)
@@ -729,7 +729,6 @@ const char * const vmstat_text[] = {
        "numa_hit",
        "numa_miss",
        "numa_foreign",
-       "numa_interleave",
        "numa_local",
        "numa_other",
 #endif
index 9096bcb081326c92bb64b6dedb11033073998ca5..ee070722a3a36f1916b385e8872ea505105d06bb 100644 (file)
@@ -463,7 +463,9 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
 
        case NETDEV_PRE_TYPE_CHANGE:
                /* Forbid underlaying device to change its type. */
-               return NOTIFY_BAD;
+               if (vlan_uses_dev(dev))
+                       return NOTIFY_BAD;
+               break;
 
        case NETDEV_NOTIFY_PEERS:
        case NETDEV_BONDING_FAILOVER:
index 35b8911b1c8e5de48c5e6bab97e411ca55302ece..fd05c81cb348fe04a0701aad70d672a7f17f238e 100644 (file)
@@ -39,6 +39,7 @@
 #include <linux/inet.h>
 #include <linux/idr.h>
 #include <linux/file.h>
+#include <linux/highmem.h>
 #include <linux/slab.h>
 #include <net/9p/9p.h>
 #include <linux/parser.h>
@@ -325,7 +326,7 @@ static int p9_get_mapped_pages(struct virtio_chan *chan,
                int count = nr_pages;
                while (nr_pages) {
                        s = rest_of_page(data);
-                       pages[index++] = virt_to_page(data);
+                       pages[index++] = kmap_to_page(data);
                        data += s;
                        nr_pages--;
                }
index 0a9084ad19a60f71a2f9f70a8879e7ada24ccf6c..fd8d5afec0ddb372d514367df3a6a81996eeac49 100644 (file)
@@ -1167,6 +1167,8 @@ int batadv_bla_init(struct batadv_priv *bat_priv)
        uint16_t crc;
        unsigned long entrytime;
 
+       spin_lock_init(&bat_priv->bla.bcast_duplist_lock);
+
        batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla hash registering\n");
 
        /* setting claim destination address */
@@ -1210,8 +1212,8 @@ int batadv_bla_init(struct batadv_priv *bat_priv)
 /**
  * batadv_bla_check_bcast_duplist
  * @bat_priv: the bat priv with all the soft interface information
- * @bcast_packet: originator mac address
- * @hdr_size: maximum length of the frame
+ * @bcast_packet: encapsulated broadcast frame plus batman header
+ * @bcast_packet_len: length of encapsulated broadcast frame plus batman header
  *
  * check if it is on our broadcast list. Another gateway might
  * have sent the same packet because it is connected to the same backbone,
@@ -1224,20 +1226,22 @@ int batadv_bla_init(struct batadv_priv *bat_priv)
  */
 int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
                                   struct batadv_bcast_packet *bcast_packet,
-                                  int hdr_size)
+                                  int bcast_packet_len)
 {
-       int i, length, curr;
+       int i, length, curr, ret = 0;
        uint8_t *content;
        uint16_t crc;
        struct batadv_bcast_duplist_entry *entry;
 
-       length = hdr_size - sizeof(*bcast_packet);
+       length = bcast_packet_len - sizeof(*bcast_packet);
        content = (uint8_t *)bcast_packet;
        content += sizeof(*bcast_packet);
 
        /* calculate the crc ... */
        crc = crc16(0, content, length);
 
+       spin_lock_bh(&bat_priv->bla.bcast_duplist_lock);
+
        for (i = 0; i < BATADV_DUPLIST_SIZE; i++) {
                curr = (bat_priv->bla.bcast_duplist_curr + i);
                curr %= BATADV_DUPLIST_SIZE;
@@ -1259,9 +1263,12 @@ int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
                /* this entry seems to match: same crc, not too old,
                 * and from another gw. therefore return 1 to forbid it.
                 */
-               return 1;
+               ret = 1;
+               goto out;
        }
-       /* not found, add a new entry (overwrite the oldest entry) */
+       /* not found, add a new entry (overwrite the oldest entry)
+        * and allow it, its the first occurence.
+        */
        curr = (bat_priv->bla.bcast_duplist_curr + BATADV_DUPLIST_SIZE - 1);
        curr %= BATADV_DUPLIST_SIZE;
        entry = &bat_priv->bla.bcast_duplist[curr];
@@ -1270,8 +1277,10 @@ int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
        memcpy(entry->orig, bcast_packet->orig, ETH_ALEN);
        bat_priv->bla.bcast_duplist_curr = curr;
 
-       /* allow it, its the first occurence. */
-       return 0;
+out:
+       spin_unlock_bh(&bat_priv->bla.bcast_duplist_lock);
+
+       return ret;
 }
 
 
index 939fc01371dff0c209665b297b69ec6502887b1a..376b4cc6ca821ffb4279e2b4df81e61899be038f 100644 (file)
@@ -1124,8 +1124,14 @@ int batadv_recv_bcast_packet(struct sk_buff *skb,
 
        spin_unlock_bh(&orig_node->bcast_seqno_lock);
 
+       /* keep skb linear for crc calculation */
+       if (skb_linearize(skb) < 0)
+               goto out;
+
+       bcast_packet = (struct batadv_bcast_packet *)skb->data;
+
        /* check whether this has been sent by another originator before */
-       if (batadv_bla_check_bcast_duplist(bat_priv, bcast_packet, hdr_size))
+       if (batadv_bla_check_bcast_duplist(bat_priv, bcast_packet, skb->len))
                goto out;
 
        /* rebroadcast packet */
index 2ed82caacdca4bfa0cf429d74a7311523874b4c2..ac1e07a8045475ed9ce367d39440940f29ab0852 100644 (file)
@@ -205,6 +205,8 @@ struct batadv_priv_bla {
        struct batadv_hashtable *backbone_hash;
        struct batadv_bcast_duplist_entry bcast_duplist[BATADV_DUPLIST_SIZE];
        int bcast_duplist_curr;
+       /* protects bcast_duplist and bcast_duplist_curr */
+       spinlock_t bcast_duplist_lock;
        struct batadv_bla_claim_dst claim_dest;
        struct delayed_work work;
 };
index 3537d385035e61fc090e9094b83850243268f992..d3f3f7b1d32cd06b082142bcbce02c630cd4eb20 100644 (file)
@@ -11,6 +11,7 @@ menuconfig BT
        select CRYPTO_BLKCIPHER
        select CRYPTO_AES
        select CRYPTO_ECB
+       select CRYPTO_SHA256
        help
          Bluetooth is low-cost, low-power, short-range wireless technology.
          It was designed as a replacement for cables and other short-range
@@ -47,4 +48,3 @@ source "net/bluetooth/cmtp/Kconfig"
 source "net/bluetooth/hidp/Kconfig"
 
 source "drivers/bluetooth/Kconfig"
-
index fa6d94a4602a8352a6f2aa9ed13ed18ff7e6c08a..dea6a287daca88b666eaee999043a3abf6dd853a 100644 (file)
@@ -10,4 +10,4 @@ obj-$(CONFIG_BT_HIDP) += hidp/
 
 bluetooth-y := af_bluetooth.o hci_core.o hci_conn.o hci_event.o mgmt.o \
        hci_sock.o hci_sysfs.o l2cap_core.o l2cap_sock.o smp.o sco.o lib.o \
-       a2mp.o
+       a2mp.o amp.o
index 0760d1fed6f08bb13404a11622b83cf3dcf02484..d5136cfb57e2e33276b93947d7b64aa3b4d98fa8 100644 (file)
 #include <net/bluetooth/hci_core.h>
 #include <net/bluetooth/l2cap.h>
 #include <net/bluetooth/a2mp.h>
+#include <net/bluetooth/amp.h>
+
+/* Global AMP Manager list */
+LIST_HEAD(amp_mgr_list);
+DEFINE_MUTEX(amp_mgr_list_lock);
 
 /* A2MP build & send command helper functions */
 static struct a2mp_cmd *__a2mp_build(u8 code, u8 ident, u16 len, void *data)
@@ -37,8 +42,7 @@ static struct a2mp_cmd *__a2mp_build(u8 code, u8 ident, u16 len, void *data)
        return cmd;
 }
 
-static void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len,
-                     void *data)
+void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len, void *data)
 {
        struct l2cap_chan *chan = mgr->a2mp_chan;
        struct a2mp_cmd *cmd;
@@ -63,6 +67,14 @@ static void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len,
        kfree(cmd);
 }
 
+u8 __next_ident(struct amp_mgr *mgr)
+{
+       if (++mgr->ident == 0)
+               mgr->ident = 1;
+
+       return mgr->ident;
+}
+
 static inline void __a2mp_cl_bredr(struct a2mp_cl *cl)
 {
        cl->id = 0;
@@ -161,6 +173,83 @@ static int a2mp_discover_req(struct amp_mgr *mgr, struct sk_buff *skb,
        return 0;
 }
 
+static int a2mp_discover_rsp(struct amp_mgr *mgr, struct sk_buff *skb,
+                            struct a2mp_cmd *hdr)
+{
+       struct a2mp_discov_rsp *rsp = (void *) skb->data;
+       u16 len = le16_to_cpu(hdr->len);
+       struct a2mp_cl *cl;
+       u16 ext_feat;
+       bool found = false;
+
+       if (len < sizeof(*rsp))
+               return -EINVAL;
+
+       len -= sizeof(*rsp);
+       skb_pull(skb, sizeof(*rsp));
+
+       ext_feat = le16_to_cpu(rsp->ext_feat);
+
+       BT_DBG("mtu %d efm 0x%4.4x", le16_to_cpu(rsp->mtu), ext_feat);
+
+       /* check that packet is not broken for now */
+       while (ext_feat & A2MP_FEAT_EXT) {
+               if (len < sizeof(ext_feat))
+                       return -EINVAL;
+
+               ext_feat = get_unaligned_le16(skb->data);
+               BT_DBG("efm 0x%4.4x", ext_feat);
+               len -= sizeof(ext_feat);
+               skb_pull(skb, sizeof(ext_feat));
+       }
+
+       cl = (void *) skb->data;
+       while (len >= sizeof(*cl)) {
+               BT_DBG("Remote AMP id %d type %d status %d", cl->id, cl->type,
+                      cl->status);
+
+               if (cl->id != HCI_BREDR_ID && cl->type == HCI_AMP) {
+                       struct a2mp_info_req req;
+
+                       found = true;
+                       req.id = cl->id;
+                       a2mp_send(mgr, A2MP_GETINFO_REQ, __next_ident(mgr),
+                                 sizeof(req), &req);
+               }
+
+               len -= sizeof(*cl);
+               cl = (void *) skb_pull(skb, sizeof(*cl));
+       }
+
+       /* Fall back to L2CAP init sequence */
+       if (!found) {
+               struct l2cap_conn *conn = mgr->l2cap_conn;
+               struct l2cap_chan *chan;
+
+               mutex_lock(&conn->chan_lock);
+
+               list_for_each_entry(chan, &conn->chan_l, list) {
+
+                       BT_DBG("chan %p state %s", chan,
+                              state_to_string(chan->state));
+
+                       if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP)
+                               continue;
+
+                       l2cap_chan_lock(chan);
+
+                       if (chan->state == BT_CONNECT)
+                               l2cap_send_conn_req(chan);
+
+                       l2cap_chan_unlock(chan);
+               }
+
+               mutex_unlock(&conn->chan_lock);
+       }
+
+       return 0;
+}
+
 static int a2mp_change_notify(struct amp_mgr *mgr, struct sk_buff *skb,
                              struct a2mp_cmd *hdr)
 {
@@ -181,7 +270,6 @@ static int a2mp_getinfo_req(struct amp_mgr *mgr, struct sk_buff *skb,
                            struct a2mp_cmd *hdr)
 {
        struct a2mp_info_req *req  = (void *) skb->data;
-       struct a2mp_info_rsp rsp;
        struct hci_dev *hdev;
 
        if (le16_to_cpu(hdr->len) < sizeof(*req))
@@ -189,53 +277,93 @@ static int a2mp_getinfo_req(struct amp_mgr *mgr, struct sk_buff *skb,
 
        BT_DBG("id %d", req->id);
 
-       rsp.id = req->id;
-       rsp.status = A2MP_STATUS_INVALID_CTRL_ID;
-
        hdev = hci_dev_get(req->id);
-       if (hdev && hdev->amp_type != HCI_BREDR) {
-               rsp.status = 0;
-               rsp.total_bw = cpu_to_le32(hdev->amp_total_bw);
-               rsp.max_bw = cpu_to_le32(hdev->amp_max_bw);
-               rsp.min_latency = cpu_to_le32(hdev->amp_min_latency);
-               rsp.pal_cap = cpu_to_le16(hdev->amp_pal_cap);
-               rsp.assoc_size = cpu_to_le16(hdev->amp_assoc_size);
+       if (!hdev || hdev->dev_type != HCI_AMP) {
+               struct a2mp_info_rsp rsp;
+
+               rsp.id = req->id;
+               rsp.status = A2MP_STATUS_INVALID_CTRL_ID;
+
+               a2mp_send(mgr, A2MP_GETINFO_RSP, hdr->ident, sizeof(rsp),
+                         &rsp);
+
+               goto done;
        }
 
+       mgr->state = READ_LOC_AMP_INFO;
+       hci_send_cmd(hdev, HCI_OP_READ_LOCAL_AMP_INFO, 0, NULL);
+
+done:
        if (hdev)
                hci_dev_put(hdev);
 
-       a2mp_send(mgr, A2MP_GETINFO_RSP, hdr->ident, sizeof(rsp), &rsp);
-
        skb_pull(skb, sizeof(*req));
        return 0;
 }
 
+static int a2mp_getinfo_rsp(struct amp_mgr *mgr, struct sk_buff *skb,
+                           struct a2mp_cmd *hdr)
+{
+       struct a2mp_info_rsp *rsp = (struct a2mp_info_rsp *) skb->data;
+       struct a2mp_amp_assoc_req req;
+       struct amp_ctrl *ctrl;
+
+       if (le16_to_cpu(hdr->len) < sizeof(*rsp))
+               return -EINVAL;
+
+       BT_DBG("id %d status 0x%2.2x", rsp->id, rsp->status);
+
+       if (rsp->status)
+               return -EINVAL;
+
+       ctrl = amp_ctrl_add(mgr, rsp->id);
+       if (!ctrl)
+               return -ENOMEM;
+
+       req.id = rsp->id;
+       a2mp_send(mgr, A2MP_GETAMPASSOC_REQ, __next_ident(mgr), sizeof(req),
+                 &req);
+
+       skb_pull(skb, sizeof(*rsp));
+       return 0;
+}
+
 static int a2mp_getampassoc_req(struct amp_mgr *mgr, struct sk_buff *skb,
                                struct a2mp_cmd *hdr)
 {
        struct a2mp_amp_assoc_req *req = (void *) skb->data;
        struct hci_dev *hdev;
+       struct amp_mgr *tmp;
 
        if (le16_to_cpu(hdr->len) < sizeof(*req))
                return -EINVAL;
 
        BT_DBG("id %d", req->id);
 
+       /* Make sure that other request is not processed */
+       tmp = amp_mgr_lookup_by_state(READ_LOC_AMP_ASSOC);
+
        hdev = hci_dev_get(req->id);
-       if (!hdev || hdev->amp_type == HCI_BREDR) {
+       if (!hdev || hdev->amp_type == HCI_BREDR || tmp) {
                struct a2mp_amp_assoc_rsp rsp;
                rsp.id = req->id;
-               rsp.status = A2MP_STATUS_INVALID_CTRL_ID;
+
+               if (tmp) {
+                       rsp.status = A2MP_STATUS_COLLISION_OCCURED;
+                       amp_mgr_put(tmp);
+               } else {
+                       rsp.status = A2MP_STATUS_INVALID_CTRL_ID;
+               }
 
                a2mp_send(mgr, A2MP_GETAMPASSOC_RSP, hdr->ident, sizeof(rsp),
                          &rsp);
-               goto clean;
+
+               goto done;
        }
 
-       /* Placeholder for HCI Read AMP Assoc */
+       amp_read_loc_assoc(hdev, mgr);
 
-clean:
+done:
        if (hdev)
                hci_dev_put(hdev);
 
@@ -243,6 +371,68 @@ clean:
        return 0;
 }
 
+static int a2mp_getampassoc_rsp(struct amp_mgr *mgr, struct sk_buff *skb,
+                               struct a2mp_cmd *hdr)
+{
+       struct a2mp_amp_assoc_rsp *rsp = (void *) skb->data;
+       u16 len = le16_to_cpu(hdr->len);
+       struct hci_dev *hdev;
+       struct amp_ctrl *ctrl;
+       struct hci_conn *hcon;
+       size_t assoc_len;
+
+       if (len < sizeof(*rsp))
+               return -EINVAL;
+
+       assoc_len = len - sizeof(*rsp);
+
+       BT_DBG("id %d status 0x%2.2x assoc len %zu", rsp->id, rsp->status,
+              assoc_len);
+
+       if (rsp->status)
+               return -EINVAL;
+
+       /* Save remote ASSOC data */
+       ctrl = amp_ctrl_lookup(mgr, rsp->id);
+       if (ctrl) {
+               u8 *assoc;
+
+               assoc = kzalloc(assoc_len, GFP_KERNEL);
+               if (!assoc) {
+                       amp_ctrl_put(ctrl);
+                       return -ENOMEM;
+               }
+
+               memcpy(assoc, rsp->amp_assoc, assoc_len);
+               ctrl->assoc = assoc;
+               ctrl->assoc_len = assoc_len;
+               ctrl->assoc_rem_len = assoc_len;
+               ctrl->assoc_len_so_far = 0;
+
+               amp_ctrl_put(ctrl);
+       }
+
+       /* Create Phys Link */
+       hdev = hci_dev_get(rsp->id);
+       if (!hdev)
+               return -EINVAL;
+
+       hcon = phylink_add(hdev, mgr, rsp->id, true);
+       if (!hcon)
+               goto done;
+
+       BT_DBG("Created hcon %p: loc:%d -> rem:%d", hcon, hdev->id, rsp->id);
+
+       mgr->bredr_chan->ctrl_id = rsp->id;
+
+       amp_create_phylink(hdev, mgr, hcon);
+
+done:
+       hci_dev_put(hdev);
+       skb_pull(skb, len);
+       return 0;
+}
+
 static int a2mp_createphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb,
                                   struct a2mp_cmd *hdr)
 {
@@ -250,6 +440,8 @@ static int a2mp_createphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb,
 
        struct a2mp_physlink_rsp rsp;
        struct hci_dev *hdev;
+       struct hci_conn *hcon;
+       struct amp_ctrl *ctrl;
 
        if (le16_to_cpu(hdr->len) < sizeof(*req))
                return -EINVAL;
@@ -265,9 +457,43 @@ static int a2mp_createphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb,
                goto send_rsp;
        }
 
-       /* TODO process physlink create */
+       ctrl = amp_ctrl_lookup(mgr, rsp.remote_id);
+       if (!ctrl) {
+               ctrl = amp_ctrl_add(mgr, rsp.remote_id);
+               if (ctrl) {
+                       amp_ctrl_get(ctrl);
+               } else {
+                       rsp.status = A2MP_STATUS_UNABLE_START_LINK_CREATION;
+                       goto send_rsp;
+               }
+       }
 
-       rsp.status = A2MP_STATUS_SUCCESS;
+       if (ctrl) {
+               size_t assoc_len = le16_to_cpu(hdr->len) - sizeof(*req);
+               u8 *assoc;
+
+               assoc = kzalloc(assoc_len, GFP_KERNEL);
+               if (!assoc) {
+                       amp_ctrl_put(ctrl);
+                       return -ENOMEM;
+               }
+
+               memcpy(assoc, req->amp_assoc, assoc_len);
+               ctrl->assoc = assoc;
+               ctrl->assoc_len = assoc_len;
+               ctrl->assoc_rem_len = assoc_len;
+               ctrl->assoc_len_so_far = 0;
+
+               amp_ctrl_put(ctrl);
+       }
+
+       hcon = phylink_add(hdev, mgr, req->local_id, false);
+       if (hcon) {
+               amp_accept_phylink(hdev, mgr, hcon);
+               rsp.status = A2MP_STATUS_SUCCESS;
+       } else {
+               rsp.status = A2MP_STATUS_UNABLE_START_LINK_CREATION;
+       }
 
 send_rsp:
        if (hdev)
@@ -286,6 +512,7 @@ static int a2mp_discphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb,
        struct a2mp_physlink_req *req = (void *) skb->data;
        struct a2mp_physlink_rsp rsp;
        struct hci_dev *hdev;
+       struct hci_conn *hcon;
 
        if (le16_to_cpu(hdr->len) < sizeof(*req))
                return -EINVAL;
@@ -296,14 +523,22 @@ static int a2mp_discphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb,
        rsp.remote_id = req->local_id;
        rsp.status = A2MP_STATUS_SUCCESS;
 
-       hdev = hci_dev_get(req->local_id);
+       hdev = hci_dev_get(req->remote_id);
        if (!hdev) {
                rsp.status = A2MP_STATUS_INVALID_CTRL_ID;
                goto send_rsp;
        }
 
+       hcon = hci_conn_hash_lookup_ba(hdev, AMP_LINK, mgr->l2cap_conn->dst);
+       if (!hcon) {
+               BT_ERR("No phys link exist");
+               rsp.status = A2MP_STATUS_NO_PHYSICAL_LINK_EXISTS;
+               goto clean;
+       }
+
        /* TODO Disconnect Phys Link here */
 
+clean:
        hci_dev_put(hdev);
 
 send_rsp:
@@ -377,10 +612,19 @@ static int a2mp_chan_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb)
                        err = a2mp_discphyslink_req(mgr, skb, hdr);
                        break;
 
-               case A2MP_CHANGE_RSP:
                case A2MP_DISCOVER_RSP:
+                       err = a2mp_discover_rsp(mgr, skb, hdr);
+                       break;
+
                case A2MP_GETINFO_RSP:
+                       err = a2mp_getinfo_rsp(mgr, skb, hdr);
+                       break;
+
                case A2MP_GETAMPASSOC_RSP:
+                       err = a2mp_getampassoc_rsp(mgr, skb, hdr);
+                       break;
+
+               case A2MP_CHANGE_RSP:
                case A2MP_CREATEPHYSLINK_RSP:
                case A2MP_DISCONNPHYSLINK_RSP:
                        err = a2mp_cmd_rsp(mgr, skb, hdr);
@@ -455,9 +699,10 @@ static struct l2cap_ops a2mp_chan_ops = {
        .new_connection = l2cap_chan_no_new_connection,
        .teardown = l2cap_chan_no_teardown,
        .ready = l2cap_chan_no_ready,
+       .defer = l2cap_chan_no_defer,
 };
 
-static struct l2cap_chan *a2mp_chan_open(struct l2cap_conn *conn)
+static struct l2cap_chan *a2mp_chan_open(struct l2cap_conn *conn, bool locked)
 {
        struct l2cap_chan *chan;
        int err;
@@ -492,7 +737,10 @@ static struct l2cap_chan *a2mp_chan_open(struct l2cap_conn *conn)
 
        chan->conf_state = 0;
 
-       l2cap_chan_add(conn, chan);
+       if (locked)
+               __l2cap_chan_add(conn, chan);
+       else
+               l2cap_chan_add(conn, chan);
 
        chan->remote_mps = chan->omtu;
        chan->mps = chan->omtu;
@@ -503,11 +751,13 @@ static struct l2cap_chan *a2mp_chan_open(struct l2cap_conn *conn)
 }
 
 /* AMP Manager functions */
-void amp_mgr_get(struct amp_mgr *mgr)
+struct amp_mgr *amp_mgr_get(struct amp_mgr *mgr)
 {
        BT_DBG("mgr %p orig refcnt %d", mgr, atomic_read(&mgr->kref.refcount));
 
        kref_get(&mgr->kref);
+
+       return mgr;
 }
 
 static void amp_mgr_destroy(struct kref *kref)
@@ -516,6 +766,11 @@ static void amp_mgr_destroy(struct kref *kref)
 
        BT_DBG("mgr %p", mgr);
 
+       mutex_lock(&amp_mgr_list_lock);
+       list_del(&mgr->list);
+       mutex_unlock(&amp_mgr_list_lock);
+
+       amp_ctrl_list_flush(mgr);
        kfree(mgr);
 }
 
@@ -526,7 +781,7 @@ int amp_mgr_put(struct amp_mgr *mgr)
        return kref_put(&mgr->kref, &amp_mgr_destroy);
 }
 
-static struct amp_mgr *amp_mgr_create(struct l2cap_conn *conn)
+static struct amp_mgr *amp_mgr_create(struct l2cap_conn *conn, bool locked)
 {
        struct amp_mgr *mgr;
        struct l2cap_chan *chan;
@@ -539,7 +794,7 @@ static struct amp_mgr *amp_mgr_create(struct l2cap_conn *conn)
 
        mgr->l2cap_conn = conn;
 
-       chan = a2mp_chan_open(conn);
+       chan = a2mp_chan_open(conn, locked);
        if (!chan) {
                kfree(mgr);
                return NULL;
@@ -552,6 +807,14 @@ static struct amp_mgr *amp_mgr_create(struct l2cap_conn *conn)
 
        kref_init(&mgr->kref);
 
+       /* Remote AMP ctrl list initialization */
+       INIT_LIST_HEAD(&mgr->amp_ctrls);
+       mutex_init(&mgr->amp_ctrls_lock);
+
+       mutex_lock(&amp_mgr_list_lock);
+       list_add(&mgr->list, &amp_mgr_list);
+       mutex_unlock(&amp_mgr_list_lock);
+
        return mgr;
 }
 
@@ -560,7 +823,7 @@ struct l2cap_chan *a2mp_channel_create(struct l2cap_conn *conn,
 {
        struct amp_mgr *mgr;
 
-       mgr = amp_mgr_create(conn);
+       mgr = amp_mgr_create(conn, false);
        if (!mgr) {
                BT_ERR("Could not create AMP manager");
                return NULL;
@@ -570,3 +833,139 @@ struct l2cap_chan *a2mp_channel_create(struct l2cap_conn *conn,
 
        return mgr->a2mp_chan;
 }
+
+struct amp_mgr *amp_mgr_lookup_by_state(u8 state)
+{
+       struct amp_mgr *mgr;
+
+       mutex_lock(&amp_mgr_list_lock);
+       list_for_each_entry(mgr, &amp_mgr_list, list) {
+               if (mgr->state == state) {
+                       amp_mgr_get(mgr);
+                       mutex_unlock(&amp_mgr_list_lock);
+                       return mgr;
+               }
+       }
+       mutex_unlock(&amp_mgr_list_lock);
+
+       return NULL;
+}
+
+void a2mp_send_getinfo_rsp(struct hci_dev *hdev)
+{
+       struct amp_mgr *mgr;
+       struct a2mp_info_rsp rsp;
+
+       mgr = amp_mgr_lookup_by_state(READ_LOC_AMP_INFO);
+       if (!mgr)
+               return;
+
+       BT_DBG("%s mgr %p", hdev->name, mgr);
+
+       rsp.id = hdev->id;
+       rsp.status = A2MP_STATUS_INVALID_CTRL_ID;
+
+       if (hdev->amp_type != HCI_BREDR) {
+               rsp.status = 0;
+               rsp.total_bw = cpu_to_le32(hdev->amp_total_bw);
+               rsp.max_bw = cpu_to_le32(hdev->amp_max_bw);
+               rsp.min_latency = cpu_to_le32(hdev->amp_min_latency);
+               rsp.pal_cap = cpu_to_le16(hdev->amp_pal_cap);
+               rsp.assoc_size = cpu_to_le16(hdev->amp_assoc_size);
+       }
+
+       a2mp_send(mgr, A2MP_GETINFO_RSP, mgr->ident, sizeof(rsp), &rsp);
+       amp_mgr_put(mgr);
+}
+
+void a2mp_send_getampassoc_rsp(struct hci_dev *hdev, u8 status)
+{
+       struct amp_mgr *mgr;
+       struct amp_assoc *loc_assoc = &hdev->loc_assoc;
+       struct a2mp_amp_assoc_rsp *rsp;
+       size_t len;
+
+       mgr = amp_mgr_lookup_by_state(READ_LOC_AMP_ASSOC);
+       if (!mgr)
+               return;
+
+       BT_DBG("%s mgr %p", hdev->name, mgr);
+
+       len = sizeof(struct a2mp_amp_assoc_rsp) + loc_assoc->len;
+       rsp = kzalloc(len, GFP_KERNEL);
+       if (!rsp) {
+               amp_mgr_put(mgr);
+               return;
+       }
+
+       rsp->id = hdev->id;
+
+       if (status) {
+               rsp->status = A2MP_STATUS_INVALID_CTRL_ID;
+       } else {
+               rsp->status = A2MP_STATUS_SUCCESS;
+               memcpy(rsp->amp_assoc, loc_assoc->data, loc_assoc->len);
+       }
+
+       a2mp_send(mgr, A2MP_GETAMPASSOC_RSP, mgr->ident, len, rsp);
+       amp_mgr_put(mgr);
+       kfree(rsp);
+}
+
+void a2mp_send_create_phy_link_req(struct hci_dev *hdev, u8 status)
+{
+       struct amp_mgr *mgr;
+       struct amp_assoc *loc_assoc = &hdev->loc_assoc;
+       struct a2mp_physlink_req *req;
+       struct l2cap_chan *bredr_chan;
+       size_t len;
+
+       mgr = amp_mgr_lookup_by_state(READ_LOC_AMP_ASSOC_FINAL);
+       if (!mgr)
+               return;
+
+       len = sizeof(*req) + loc_assoc->len;
+
+       BT_DBG("%s mgr %p assoc_len %zu", hdev->name, mgr, len);
+
+       req = kzalloc(len, GFP_KERNEL);
+       if (!req) {
+               amp_mgr_put(mgr);
+               return;
+       }
+
+       bredr_chan = mgr->bredr_chan;
+       if (!bredr_chan)
+               goto clean;
+
+       req->local_id = hdev->id;
+       req->remote_id = bredr_chan->ctrl_id;
+       memcpy(req->amp_assoc, loc_assoc->data, loc_assoc->len);
+
+       a2mp_send(mgr, A2MP_CREATEPHYSLINK_REQ, __next_ident(mgr), len, req);
+
+clean:
+       amp_mgr_put(mgr);
+       kfree(req);
+}
+
+void a2mp_discover_amp(struct l2cap_chan *chan)
+{
+       struct l2cap_conn *conn = chan->conn;
+       struct amp_mgr *mgr = conn->hcon->amp_mgr;
+       struct a2mp_discov_req req;
+
+       BT_DBG("chan %p conn %p mgr %p", chan, conn, mgr);
+
+       if (!mgr) {
+               mgr = amp_mgr_create(conn, true);
+               if (!mgr)
+                       return;
+       }
+
+       mgr->bredr_chan = chan;
+
+       req.mtu = cpu_to_le16(L2CAP_A2MP_DEFAULT_MTU);
+       req.ext_feat = 0;
+       a2mp_send(mgr, A2MP_DISCOVER_REQ, 1, sizeof(req), &req);
+}
index ba033f09196ee45d7d6fbd170386a0d62af1d4ac..5355df63d39b673d246d131564a1e17dc116c27d 100644 (file)
@@ -569,7 +569,6 @@ static int bt_seq_show(struct seq_file *seq, void *v)
 {
        struct bt_seq_state *s = seq->private;
        struct bt_sock_list *l = s->l;
-       bdaddr_t src_baswapped, dst_baswapped;
 
        if (v == SEQ_START_TOKEN) {
                seq_puts(seq ,"sk               RefCnt Rmem   Wmem   User   Inode  Src Dst Parent");
@@ -583,18 +582,17 @@ static int bt_seq_show(struct seq_file *seq, void *v)
        } else {
                struct sock *sk = sk_entry(v);
                struct bt_sock *bt = bt_sk(sk);
-               baswap(&src_baswapped, &bt->src);
-               baswap(&dst_baswapped, &bt->dst);
 
-               seq_printf(seq, "%pK %-6d %-6u %-6u %-6u %-6lu %pM %pM %-6lu",
+               seq_printf(seq,
+                          "%pK %-6d %-6u %-6u %-6u %-6lu %pMR %pMR %-6lu",
                           sk,
                           atomic_read(&sk->sk_refcnt),
                           sk_rmem_alloc_get(sk),
                           sk_wmem_alloc_get(sk),
                           from_kuid(seq_user_ns(seq), sock_i_uid(sk)),
                           sock_i_ino(sk),
-                          &src_baswapped,
-                          &dst_baswapped,
+                          &bt->src,
+                          &bt->dst,
                           bt->parent? sock_i_ino(bt->parent): 0LU);
 
                if (l->custom_seq_show) {
diff --git a/net/bluetooth/amp.c b/net/bluetooth/amp.c
new file mode 100644 (file)
index 0000000..231d7ef
--- /dev/null
@@ -0,0 +1,374 @@
+/*
+   Copyright (c) 2011,2012 Intel Corp.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License version 2 and
+   only version 2 as published by the Free Software Foundation.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+*/
+
+#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci.h>
+#include <net/bluetooth/hci_core.h>
+#include <net/bluetooth/a2mp.h>
+#include <net/bluetooth/amp.h>
+#include <crypto/hash.h>
+
+/* Remote AMP Controllers interface */
+void amp_ctrl_get(struct amp_ctrl *ctrl)
+{
+       BT_DBG("ctrl %p orig refcnt %d", ctrl,
+              atomic_read(&ctrl->kref.refcount));
+
+       kref_get(&ctrl->kref);
+}
+
+static void amp_ctrl_destroy(struct kref *kref)
+{
+       struct amp_ctrl *ctrl = container_of(kref, struct amp_ctrl, kref);
+
+       BT_DBG("ctrl %p", ctrl);
+
+       kfree(ctrl->assoc);
+       kfree(ctrl);
+}
+
+int amp_ctrl_put(struct amp_ctrl *ctrl)
+{
+       BT_DBG("ctrl %p orig refcnt %d", ctrl,
+              atomic_read(&ctrl->kref.refcount));
+
+       return kref_put(&ctrl->kref, &amp_ctrl_destroy);
+}
+
+struct amp_ctrl *amp_ctrl_add(struct amp_mgr *mgr, u8 id)
+{
+       struct amp_ctrl *ctrl;
+
+       ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
+       if (!ctrl)
+               return NULL;
+
+       kref_init(&ctrl->kref);
+       ctrl->id = id;
+
+       mutex_lock(&mgr->amp_ctrls_lock);
+       list_add(&ctrl->list, &mgr->amp_ctrls);
+       mutex_unlock(&mgr->amp_ctrls_lock);
+
+       BT_DBG("mgr %p ctrl %p", mgr, ctrl);
+
+       return ctrl;
+}
+
+void amp_ctrl_list_flush(struct amp_mgr *mgr)
+{
+       struct amp_ctrl *ctrl, *n;
+
+       BT_DBG("mgr %p", mgr);
+
+       mutex_lock(&mgr->amp_ctrls_lock);
+       list_for_each_entry_safe(ctrl, n, &mgr->amp_ctrls, list) {
+               list_del(&ctrl->list);
+               amp_ctrl_put(ctrl);
+       }
+       mutex_unlock(&mgr->amp_ctrls_lock);
+}
+
+struct amp_ctrl *amp_ctrl_lookup(struct amp_mgr *mgr, u8 id)
+{
+       struct amp_ctrl *ctrl;
+
+       BT_DBG("mgr %p id %d", mgr, id);
+
+       mutex_lock(&mgr->amp_ctrls_lock);
+       list_for_each_entry(ctrl, &mgr->amp_ctrls, list) {
+               if (ctrl->id == id) {
+                       amp_ctrl_get(ctrl);
+                       mutex_unlock(&mgr->amp_ctrls_lock);
+                       return ctrl;
+               }
+       }
+       mutex_unlock(&mgr->amp_ctrls_lock);
+
+       return NULL;
+}
+
+/* Physical Link interface */
+static u8 __next_handle(struct amp_mgr *mgr)
+{
+       if (++mgr->handle == 0)
+               mgr->handle = 1;
+
+       return mgr->handle;
+}
+
+struct hci_conn *phylink_add(struct hci_dev *hdev, struct amp_mgr *mgr,
+                            u8 remote_id, bool out)
+{
+       bdaddr_t *dst = mgr->l2cap_conn->dst;
+       struct hci_conn *hcon;
+
+       hcon = hci_conn_add(hdev, AMP_LINK, dst);
+       if (!hcon)
+               return NULL;
+
+       BT_DBG("hcon %p dst %pMR", hcon, dst);
+
+       hcon->state = BT_CONNECT;
+       hcon->attempt++;
+       hcon->handle = __next_handle(mgr);
+       hcon->remote_id = remote_id;
+       hcon->amp_mgr = amp_mgr_get(mgr);
+       hcon->out = out;
+
+       return hcon;
+}
+
+/* AMP crypto key generation interface */
+static int hmac_sha256(u8 *key, u8 ksize, char *plaintext, u8 psize, u8 *output)
+{
+       int ret = 0;
+       struct crypto_shash *tfm;
+
+       if (!ksize)
+               return -EINVAL;
+
+       tfm = crypto_alloc_shash("hmac(sha256)", 0, 0);
+       if (IS_ERR(tfm)) {
+               BT_DBG("crypto_alloc_ahash failed: err %ld", PTR_ERR(tfm));
+               return PTR_ERR(tfm);
+       }
+
+       ret = crypto_shash_setkey(tfm, key, ksize);
+       if (ret) {
+               BT_DBG("crypto_ahash_setkey failed: err %d", ret);
+       } else {
+               struct {
+                       struct shash_desc shash;
+                       char ctx[crypto_shash_descsize(tfm)];
+               } desc;
+
+               desc.shash.tfm = tfm;
+               desc.shash.flags = CRYPTO_TFM_REQ_MAY_SLEEP;
+
+               ret = crypto_shash_digest(&desc.shash, plaintext, psize,
+                                         output);
+       }
+
+       crypto_free_shash(tfm);
+       return ret;
+}
+
+int phylink_gen_key(struct hci_conn *conn, u8 *data, u8 *len, u8 *type)
+{
+       struct hci_dev *hdev = conn->hdev;
+       struct link_key *key;
+       u8 keybuf[HCI_AMP_LINK_KEY_SIZE];
+       u8 gamp_key[HCI_AMP_LINK_KEY_SIZE];
+       int err;
+
+       if (!hci_conn_check_link_mode(conn))
+               return -EACCES;
+
+       BT_DBG("conn %p key_type %d", conn, conn->key_type);
+
+       /* Legacy key */
+       if (conn->key_type < 3) {
+               BT_ERR("Legacy key type %d", conn->key_type);
+               return -EACCES;
+       }
+
+       *type = conn->key_type;
+       *len = HCI_AMP_LINK_KEY_SIZE;
+
+       key = hci_find_link_key(hdev, &conn->dst);
+       if (!key) {
+               BT_DBG("No Link key for conn %p dst %pMR", conn, &conn->dst);
+               return -EACCES;
+       }
+
+       /* BR/EDR Link Key concatenated together with itself */
+       memcpy(&keybuf[0], key->val, HCI_LINK_KEY_SIZE);
+       memcpy(&keybuf[HCI_LINK_KEY_SIZE], key->val, HCI_LINK_KEY_SIZE);
+
+       /* Derive Generic AMP Link Key (gamp) */
+       err = hmac_sha256(keybuf, HCI_AMP_LINK_KEY_SIZE, "gamp", 4, gamp_key);
+       if (err) {
+               BT_ERR("Could not derive Generic AMP Key: err %d", err);
+               return err;
+       }
+
+       if (conn->key_type == HCI_LK_DEBUG_COMBINATION) {
+               BT_DBG("Use Generic AMP Key (gamp)");
+               memcpy(data, gamp_key, HCI_AMP_LINK_KEY_SIZE);
+               return err;
+       }
+
+       /* Derive Dedicated AMP Link Key: "802b" is 802.11 PAL keyID */
+       return hmac_sha256(gamp_key, HCI_AMP_LINK_KEY_SIZE, "802b", 4, data);
+}
+
+void amp_read_loc_assoc_frag(struct hci_dev *hdev, u8 phy_handle)
+{
+       struct hci_cp_read_local_amp_assoc cp;
+       struct amp_assoc *loc_assoc = &hdev->loc_assoc;
+
+       BT_DBG("%s handle %d", hdev->name, phy_handle);
+
+       cp.phy_handle = phy_handle;
+       cp.max_len = cpu_to_le16(hdev->amp_assoc_size);
+       cp.len_so_far = cpu_to_le16(loc_assoc->offset);
+
+       hci_send_cmd(hdev, HCI_OP_READ_LOCAL_AMP_ASSOC, sizeof(cp), &cp);
+}
+
+void amp_read_loc_assoc(struct hci_dev *hdev, struct amp_mgr *mgr)
+{
+       struct hci_cp_read_local_amp_assoc cp;
+
+       memset(&hdev->loc_assoc, 0, sizeof(struct amp_assoc));
+       memset(&cp, 0, sizeof(cp));
+
+       cp.max_len = cpu_to_le16(hdev->amp_assoc_size);
+
+       mgr->state = READ_LOC_AMP_ASSOC;
+       hci_send_cmd(hdev, HCI_OP_READ_LOCAL_AMP_ASSOC, sizeof(cp), &cp);
+}
+
+void amp_read_loc_assoc_final_data(struct hci_dev *hdev,
+                                  struct hci_conn *hcon)
+{
+       struct hci_cp_read_local_amp_assoc cp;
+       struct amp_mgr *mgr = hcon->amp_mgr;
+
+       cp.phy_handle = hcon->handle;
+       cp.len_so_far = cpu_to_le16(0);
+       cp.max_len = cpu_to_le16(hdev->amp_assoc_size);
+
+       mgr->state = READ_LOC_AMP_ASSOC_FINAL;
+
+       /* Read Local AMP Assoc final link information data */
+       hci_send_cmd(hdev, HCI_OP_READ_LOCAL_AMP_ASSOC, sizeof(cp), &cp);
+}
+
+/* Write AMP Assoc data fragments, returns true with last fragment written*/
+static bool amp_write_rem_assoc_frag(struct hci_dev *hdev,
+                                    struct hci_conn *hcon)
+{
+       struct hci_cp_write_remote_amp_assoc *cp;
+       struct amp_mgr *mgr = hcon->amp_mgr;
+       struct amp_ctrl *ctrl;
+       u16 frag_len, len;
+
+       ctrl = amp_ctrl_lookup(mgr, hcon->remote_id);
+       if (!ctrl)
+               return false;
+
+       if (!ctrl->assoc_rem_len) {
+               BT_DBG("all fragments are written");
+               ctrl->assoc_rem_len = ctrl->assoc_len;
+               ctrl->assoc_len_so_far = 0;
+
+               amp_ctrl_put(ctrl);
+               return true;
+       }
+
+       frag_len = min_t(u16, 248, ctrl->assoc_rem_len);
+       len = frag_len + sizeof(*cp);
+
+       cp = kzalloc(len, GFP_KERNEL);
+       if (!cp) {
+               amp_ctrl_put(ctrl);
+               return false;
+       }
+
+       BT_DBG("hcon %p ctrl %p frag_len %u assoc_len %u rem_len %u",
+              hcon, ctrl, frag_len, ctrl->assoc_len, ctrl->assoc_rem_len);
+
+       cp->phy_handle = hcon->handle;
+       cp->len_so_far = cpu_to_le16(ctrl->assoc_len_so_far);
+       cp->rem_len = cpu_to_le16(ctrl->assoc_rem_len);
+       memcpy(cp->frag, ctrl->assoc, frag_len);
+
+       ctrl->assoc_len_so_far += frag_len;
+       ctrl->assoc_rem_len -= frag_len;
+
+       amp_ctrl_put(ctrl);
+
+       hci_send_cmd(hdev, HCI_OP_WRITE_REMOTE_AMP_ASSOC, len, cp);
+
+       kfree(cp);
+
+       return false;
+}
+
+void amp_write_rem_assoc_continue(struct hci_dev *hdev, u8 handle)
+{
+       struct hci_conn *hcon;
+
+       BT_DBG("%s phy handle 0x%2.2x", hdev->name, handle);
+
+       hcon = hci_conn_hash_lookup_handle(hdev, handle);
+       if (!hcon)
+               return;
+
+       amp_write_rem_assoc_frag(hdev, hcon);
+}
+
+void amp_write_remote_assoc(struct hci_dev *hdev, u8 handle)
+{
+       struct hci_conn *hcon;
+
+       BT_DBG("%s phy handle 0x%2.2x", hdev->name, handle);
+
+       hcon = hci_conn_hash_lookup_handle(hdev, handle);
+       if (!hcon)
+               return;
+
+       BT_DBG("%s phy handle 0x%2.2x hcon %p", hdev->name, handle, hcon);
+
+       amp_write_rem_assoc_frag(hdev, hcon);
+}
+
+void amp_create_phylink(struct hci_dev *hdev, struct amp_mgr *mgr,
+                       struct hci_conn *hcon)
+{
+       struct hci_cp_create_phy_link cp;
+
+       cp.phy_handle = hcon->handle;
+
+       BT_DBG("%s hcon %p phy handle 0x%2.2x", hdev->name, hcon,
+              hcon->handle);
+
+       if (phylink_gen_key(mgr->l2cap_conn->hcon, cp.key, &cp.key_len,
+                           &cp.key_type)) {
+               BT_DBG("Cannot create link key");
+               return;
+       }
+
+       hci_send_cmd(hdev, HCI_OP_CREATE_PHY_LINK, sizeof(cp), &cp);
+}
+
+void amp_accept_phylink(struct hci_dev *hdev, struct amp_mgr *mgr,
+                       struct hci_conn *hcon)
+{
+       struct hci_cp_accept_phy_link cp;
+
+       cp.phy_handle = hcon->handle;
+
+       BT_DBG("%s hcon %p phy handle 0x%2.2x", hdev->name, hcon,
+              hcon->handle);
+
+       if (phylink_gen_key(mgr->l2cap_conn->hcon, cp.key, &cp.key_len,
+                           &cp.key_type)) {
+               BT_DBG("Cannot create link key");
+               return;
+       }
+
+       hci_send_cmd(hdev, HCI_OP_ACCEPT_PHY_LINK, sizeof(cp), &cp);
+}
index 4a6620bc1570901c34a1c406ffb83909c27d3348..a5b639702637404d5c1955b36163a3c459fe174c 100644 (file)
@@ -182,8 +182,7 @@ static int bnep_ctrl_set_mcfilter(struct bnep_session *s, u8 *data, int len)
                        a2 = data;
                        data += ETH_ALEN;
 
-                       BT_DBG("mc filter %s -> %s",
-                               batostr((void *) a1), batostr((void *) a2));
+                       BT_DBG("mc filter %pMR -> %pMR", a1, a2);
 
                        /* Iterate from a1 to a2 */
                        set_bit(bnep_mc_hash(a1), (ulong *) &s->mc_filter);
index 50f0d135eb8f201daf8156c433f08a973bfa338f..a4a9d4b6816c43b3216eee038f961301978b5713 100644 (file)
@@ -20,7 +20,7 @@
    SOFTWARE IS DISCLAIMED.
 */
 
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <linux/types.h>
index 6c9c1fd601cac41e879c3e041f103ee645ebd458..e0a6ebf2baa6fecd58a0cc13ea6f2906c6614a46 100644 (file)
@@ -353,7 +353,7 @@ int cmtp_add_connection(struct cmtp_connadd_req *req, struct socket *sock)
 
        BT_DBG("mtu %d", session->mtu);
 
-       sprintf(session->name, "%s", batostr(&bt_sk(sock->sk)->dst));
+       sprintf(session->name, "%pMR", &bt_sk(sock->sk)->dst);
 
        session->sock  = sock;
        session->state = BT_CONFIG;
index aacb802d1ee45d419aac1555442bb08edf227dc9..1c57482112b6e5c1eebfa30ce1ac84375db737dd 100644 (file)
@@ -20,7 +20,7 @@
    SOFTWARE IS DISCLAIMED.
 */
 
-#include <linux/module.h>
+#include <linux/export.h>
 
 #include <linux/types.h>
 #include <linux/capability.h>
index b9196a44f7598bf33b0c2bff6d0764eeeba8fc11..dc331ceca471351145b2c44ef3a1af05f53c3d5d 100644 (file)
@@ -130,6 +130,20 @@ void hci_acl_disconn(struct hci_conn *conn, __u8 reason)
        hci_send_cmd(conn->hdev, HCI_OP_DISCONNECT, sizeof(cp), &cp);
 }
 
+static void hci_amp_disconn(struct hci_conn *conn, __u8 reason)
+{
+       struct hci_cp_disconn_phy_link cp;
+
+       BT_DBG("hcon %p", conn);
+
+       conn->state = BT_DISCONN;
+
+       cp.phy_handle = HCI_PHY_HANDLE(conn->handle);
+       cp.reason = reason;
+       hci_send_cmd(conn->hdev, HCI_OP_DISCONN_PHY_LINK,
+                    sizeof(cp), &cp);
+}
+
 static void hci_add_sco(struct hci_conn *conn, __u16 handle)
 {
        struct hci_dev *hdev = conn->hdev;
@@ -230,11 +244,24 @@ void hci_sco_setup(struct hci_conn *conn, __u8 status)
        }
 }
 
+static void hci_conn_disconnect(struct hci_conn *conn)
+{
+       __u8 reason = hci_proto_disconn_ind(conn);
+
+       switch (conn->type) {
+       case ACL_LINK:
+               hci_acl_disconn(conn, reason);
+               break;
+       case AMP_LINK:
+               hci_amp_disconn(conn, reason);
+               break;
+       }
+}
+
 static void hci_conn_timeout(struct work_struct *work)
 {
        struct hci_conn *conn = container_of(work, struct hci_conn,
                                             disc_work.work);
-       __u8 reason;
 
        BT_DBG("hcon %p state %s", conn, state_to_string(conn->state));
 
@@ -253,8 +280,7 @@ static void hci_conn_timeout(struct work_struct *work)
                break;
        case BT_CONFIG:
        case BT_CONNECTED:
-               reason = hci_proto_disconn_ind(conn);
-               hci_acl_disconn(conn, reason);
+               hci_conn_disconnect(conn);
                break;
        default:
                conn->state = BT_CLOSED;
@@ -320,7 +346,7 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
 {
        struct hci_conn *conn;
 
-       BT_DBG("%s dst %s", hdev->name, batostr(dst));
+       BT_DBG("%s dst %pMR", hdev->name, dst);
 
        conn = kzalloc(sizeof(struct hci_conn), GFP_KERNEL);
        if (!conn)
@@ -437,7 +463,7 @@ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src)
        int use_src = bacmp(src, BDADDR_ANY);
        struct hci_dev *hdev = NULL, *d;
 
-       BT_DBG("%s -> %s", batostr(src), batostr(dst));
+       BT_DBG("%pMR -> %pMR", src, dst);
 
        read_lock(&hci_dev_list_lock);
 
@@ -476,6 +502,9 @@ static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
 {
        struct hci_conn *le;
 
+       if (test_bit(HCI_LE_PERIPHERAL, &hdev->flags))
+               return ERR_PTR(-ENOTSUPP);
+
        le = hci_conn_hash_lookup_ba(hdev, LE_LINK, dst);
        if (!le) {
                le = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
@@ -567,7 +596,7 @@ static struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type,
 struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst,
                             __u8 dst_type, __u8 sec_level, __u8 auth_type)
 {
-       BT_DBG("%s dst %s type 0x%x", hdev->name, batostr(dst), type);
+       BT_DBG("%s dst %pMR type 0x%x", hdev->name, dst, type);
 
        switch (type) {
        case LE_LINK:
@@ -933,6 +962,7 @@ struct hci_chan *hci_chan_create(struct hci_conn *conn)
 
        chan->conn = conn;
        skb_queue_head_init(&chan->data_q);
+       chan->state = BT_CONNECTED;
 
        list_add_rcu(&chan->list, &conn->chan_list);
 
@@ -963,3 +993,35 @@ void hci_chan_list_flush(struct hci_conn *conn)
        list_for_each_entry_safe(chan, n, &conn->chan_list, list)
                hci_chan_del(chan);
 }
+
+static struct hci_chan *__hci_chan_lookup_handle(struct hci_conn *hcon,
+                                                __u16 handle)
+{
+       struct hci_chan *hchan;
+
+       list_for_each_entry(hchan, &hcon->chan_list, list) {
+               if (hchan->handle == handle)
+                       return hchan;
+       }
+
+       return NULL;
+}
+
+struct hci_chan *hci_chan_lookup_handle(struct hci_dev *hdev, __u16 handle)
+{
+       struct hci_conn_hash *h = &hdev->conn_hash;
+       struct hci_conn *hcon;
+       struct hci_chan *hchan = NULL;
+
+       rcu_read_lock();
+
+       list_for_each_entry_rcu(hcon, &h->list, list) {
+               hchan = __hci_chan_lookup_handle(hcon, handle);
+               if (hchan)
+                       break;
+       }
+
+       rcu_read_unlock();
+
+       return hchan;
+}
index 8a0ce706aebd624ae7fd1c50b9670780dc4f6761..515d0c394f35e29820801444e3a9d4510e549f2d 100644 (file)
@@ -178,48 +178,13 @@ static void hci_reset_req(struct hci_dev *hdev, unsigned long opt)
 
 static void bredr_init(struct hci_dev *hdev)
 {
-       struct hci_cp_delete_stored_link_key cp;
-       __le16 param;
-       __u8 flt_type;
-
        hdev->flow_ctl_mode = HCI_FLOW_CTL_MODE_PACKET_BASED;
 
-       /* Mandatory initialization */
-
        /* Read Local Supported Features */
        hci_send_cmd(hdev, HCI_OP_READ_LOCAL_FEATURES, 0, NULL);
 
        /* Read Local Version */
        hci_send_cmd(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL);
-
-       /* Read Buffer Size (ACL mtu, max pkt, etc.) */
-       hci_send_cmd(hdev, HCI_OP_READ_BUFFER_SIZE, 0, NULL);
-
-       /* Read BD Address */
-       hci_send_cmd(hdev, HCI_OP_READ_BD_ADDR, 0, NULL);
-
-       /* Read Class of Device */
-       hci_send_cmd(hdev, HCI_OP_READ_CLASS_OF_DEV, 0, NULL);
-
-       /* Read Local Name */
-       hci_send_cmd(hdev, HCI_OP_READ_LOCAL_NAME, 0, NULL);
-
-       /* Read Voice Setting */
-       hci_send_cmd(hdev, HCI_OP_READ_VOICE_SETTING, 0, NULL);
-
-       /* Optional initialization */
-
-       /* Clear Event Filters */
-       flt_type = HCI_FLT_CLEAR_ALL;
-       hci_send_cmd(hdev, HCI_OP_SET_EVENT_FLT, 1, &flt_type);
-
-       /* Connection accept timeout ~20 secs */
-       param = __constant_cpu_to_le16(0x7d00);
-       hci_send_cmd(hdev, HCI_OP_WRITE_CA_TIMEOUT, 2, &param);
-
-       bacpy(&cp.bdaddr, BDADDR_ANY);
-       cp.delete_all = 1;
-       hci_send_cmd(hdev, HCI_OP_DELETE_STORED_LINK_KEY, sizeof(cp), &cp);
 }
 
 static void amp_init(struct hci_dev *hdev)
@@ -273,14 +238,6 @@ static void hci_init_req(struct hci_dev *hdev, unsigned long opt)
        }
 }
 
-static void hci_le_init_req(struct hci_dev *hdev, unsigned long opt)
-{
-       BT_DBG("%s", hdev->name);
-
-       /* Read LE buffer size */
-       hci_send_cmd(hdev, HCI_OP_LE_READ_BUFFER_SIZE, 0, NULL);
-}
-
 static void hci_scan_req(struct hci_dev *hdev, unsigned long opt)
 {
        __u8 scan = opt;
@@ -405,7 +362,7 @@ struct inquiry_entry *hci_inquiry_cache_lookup(struct hci_dev *hdev,
        struct discovery_state *cache = &hdev->discovery;
        struct inquiry_entry *e;
 
-       BT_DBG("cache %p, %s", cache, batostr(bdaddr));
+       BT_DBG("cache %p, %pMR", cache, bdaddr);
 
        list_for_each_entry(e, &cache->all, all) {
                if (!bacmp(&e->data.bdaddr, bdaddr))
@@ -421,7 +378,7 @@ struct inquiry_entry *hci_inquiry_cache_lookup_unknown(struct hci_dev *hdev,
        struct discovery_state *cache = &hdev->discovery;
        struct inquiry_entry *e;
 
-       BT_DBG("cache %p, %s", cache, batostr(bdaddr));
+       BT_DBG("cache %p, %pMR", cache, bdaddr);
 
        list_for_each_entry(e, &cache->unknown, list) {
                if (!bacmp(&e->data.bdaddr, bdaddr))
@@ -438,7 +395,7 @@ struct inquiry_entry *hci_inquiry_cache_lookup_resolve(struct hci_dev *hdev,
        struct discovery_state *cache = &hdev->discovery;
        struct inquiry_entry *e;
 
-       BT_DBG("cache %p bdaddr %s state %d", cache, batostr(bdaddr), state);
+       BT_DBG("cache %p bdaddr %pMR state %d", cache, bdaddr, state);
 
        list_for_each_entry(e, &cache->resolve, list) {
                if (!bacmp(bdaddr, BDADDR_ANY) && e->name_state == state)
@@ -475,7 +432,7 @@ bool hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data,
        struct discovery_state *cache = &hdev->discovery;
        struct inquiry_entry *ie;
 
-       BT_DBG("cache %p, %s", cache, batostr(&data->bdaddr));
+       BT_DBG("cache %p, %pMR", cache, &data->bdaddr);
 
        if (ssp)
                *ssp = data->ssp_mode;
@@ -687,10 +644,6 @@ int hci_dev_open(__u16 dev)
 
                ret = __hci_request(hdev, hci_init_req, 0, HCI_INIT_TIMEOUT);
 
-               if (lmp_host_le_capable(hdev))
-                       ret = __hci_request(hdev, hci_le_init_req, 0,
-                                           HCI_INIT_TIMEOUT);
-
                clear_bit(HCI_INIT, &hdev->flags);
        }
 
@@ -1039,10 +992,17 @@ int hci_get_dev_info(void __user *arg)
        di.type     = (hdev->bus & 0x0f) | (hdev->dev_type << 4);
        di.flags    = hdev->flags;
        di.pkt_type = hdev->pkt_type;
-       di.acl_mtu  = hdev->acl_mtu;
-       di.acl_pkts = hdev->acl_pkts;
-       di.sco_mtu  = hdev->sco_mtu;
-       di.sco_pkts = hdev->sco_pkts;
+       if (lmp_bredr_capable(hdev)) {
+               di.acl_mtu  = hdev->acl_mtu;
+               di.acl_pkts = hdev->acl_pkts;
+               di.sco_mtu  = hdev->sco_mtu;
+               di.sco_pkts = hdev->sco_pkts;
+       } else {
+               di.acl_mtu  = hdev->le_mtu;
+               di.acl_pkts = hdev->le_pkts;
+               di.sco_mtu  = 0;
+               di.sco_pkts = 0;
+       }
        di.link_policy = hdev->link_policy;
        di.link_mode   = hdev->link_mode;
 
@@ -1259,7 +1219,7 @@ int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key,
                list_add(&key->list, &hdev->link_keys);
        }
 
-       BT_DBG("%s key for %s type %u", hdev->name, batostr(bdaddr), type);
+       BT_DBG("%s key for %pMR type %u", hdev->name, bdaddr, type);
 
        /* Some buggy controller combinations generate a changed
         * combination key for legacy pairing even when there's no
@@ -1338,7 +1298,7 @@ int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr)
        if (!key)
                return -ENOENT;
 
-       BT_DBG("%s removing %s", hdev->name, batostr(bdaddr));
+       BT_DBG("%s removing %pMR", hdev->name, bdaddr);
 
        list_del(&key->list);
        kfree(key);
@@ -1354,7 +1314,7 @@ int hci_remove_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr)
                if (bacmp(bdaddr, &k->bdaddr))
                        continue;
 
-               BT_DBG("%s removing %s", hdev->name, batostr(bdaddr));
+               BT_DBG("%s removing %pMR", hdev->name, bdaddr);
 
                list_del(&k->list);
                kfree(k);
@@ -1401,7 +1361,7 @@ int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr)
        if (!data)
                return -ENOENT;
 
-       BT_DBG("%s removing %s", hdev->name, batostr(bdaddr));
+       BT_DBG("%s removing %pMR", hdev->name, bdaddr);
 
        list_del(&data->list);
        kfree(data);
@@ -1440,7 +1400,7 @@ int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash,
        memcpy(data->hash, hash, sizeof(data->hash));
        memcpy(data->randomizer, randomizer, sizeof(data->randomizer));
 
-       BT_DBG("%s for %s", hdev->name, batostr(bdaddr));
+       BT_DBG("%s for %pMR", hdev->name, bdaddr);
 
        return 0;
 }
@@ -1617,6 +1577,9 @@ int hci_le_scan(struct hci_dev *hdev, u8 type, u16 interval, u16 window,
 
        BT_DBG("%s", hdev->name);
 
+       if (test_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags))
+               return -ENOTSUPP;
+
        if (work_busy(&hdev->le_scan))
                return -EINPROGRESS;
 
@@ -2153,9 +2116,10 @@ static void hci_add_acl_hdr(struct sk_buff *skb, __u16 handle, __u16 flags)
        hdr->dlen   = cpu_to_le16(len);
 }
 
-static void hci_queue_acl(struct hci_conn *conn, struct sk_buff_head *queue,
+static void hci_queue_acl(struct hci_chan *chan, struct sk_buff_head *queue,
                          struct sk_buff *skb, __u16 flags)
 {
+       struct hci_conn *conn = chan->conn;
        struct hci_dev *hdev = conn->hdev;
        struct sk_buff *list;
 
@@ -2163,7 +2127,18 @@ static void hci_queue_acl(struct hci_conn *conn, struct sk_buff_head *queue,
        skb->data_len = 0;
 
        bt_cb(skb)->pkt_type = HCI_ACLDATA_PKT;
-       hci_add_acl_hdr(skb, conn->handle, flags);
+
+       switch (hdev->dev_type) {
+       case HCI_BREDR:
+               hci_add_acl_hdr(skb, conn->handle, flags);
+               break;
+       case HCI_AMP:
+               hci_add_acl_hdr(skb, chan->handle, flags);
+               break;
+       default:
+               BT_ERR("%s unknown dev_type %d", hdev->name, hdev->dev_type);
+               return;
+       }
 
        list = skb_shinfo(skb)->frag_list;
        if (!list) {
@@ -2202,14 +2177,13 @@ static void hci_queue_acl(struct hci_conn *conn, struct sk_buff_head *queue,
 
 void hci_send_acl(struct hci_chan *chan, struct sk_buff *skb, __u16 flags)
 {
-       struct hci_conn *conn = chan->conn;
-       struct hci_dev *hdev = conn->hdev;
+       struct hci_dev *hdev = chan->conn->hdev;
 
        BT_DBG("%s chan %p flags 0x%4.4x", hdev->name, chan, flags);
 
        skb->dev = (void *) hdev;
 
-       hci_queue_acl(conn, &chan->data_q, skb, flags);
+       hci_queue_acl(chan, &chan->data_q, skb, flags);
 
        queue_work(hdev->workqueue, &hdev->tx_work);
 }
@@ -2311,8 +2285,8 @@ static void hci_link_tx_to(struct hci_dev *hdev, __u8 type)
        /* Kill stalled connections */
        list_for_each_entry_rcu(c, &h->list, list) {
                if (c->type == type && c->sent) {
-                       BT_ERR("%s killing stalled connection %s",
-                              hdev->name, batostr(&c->dst));
+                       BT_ERR("%s killing stalled connection %pMR",
+                              hdev->name, &c->dst);
                        hci_acl_disconn(c, HCI_ERROR_REMOTE_USER_TERM);
                }
        }
@@ -2381,6 +2355,9 @@ static struct hci_chan *hci_chan_sent(struct hci_dev *hdev, __u8 type,
        case ACL_LINK:
                cnt = hdev->acl_cnt;
                break;
+       case AMP_LINK:
+               cnt = hdev->block_cnt;
+               break;
        case SCO_LINK:
        case ESCO_LINK:
                cnt = hdev->sco_cnt;
@@ -2510,11 +2487,19 @@ static void hci_sched_acl_blk(struct hci_dev *hdev)
        struct hci_chan *chan;
        struct sk_buff *skb;
        int quote;
+       u8 type;
 
        __check_timeout(hdev, cnt);
 
+       BT_DBG("%s", hdev->name);
+
+       if (hdev->dev_type == HCI_AMP)
+               type = AMP_LINK;
+       else
+               type = ACL_LINK;
+
        while (hdev->block_cnt > 0 &&
-              (chan = hci_chan_sent(hdev, ACL_LINK, &quote))) {
+              (chan = hci_chan_sent(hdev, type, &quote))) {
                u32 priority = (skb_peek(&chan->data_q))->priority;
                while (quote > 0 && (skb = skb_peek(&chan->data_q))) {
                        int blocks;
@@ -2547,14 +2532,19 @@ static void hci_sched_acl_blk(struct hci_dev *hdev)
        }
 
        if (cnt != hdev->block_cnt)
-               hci_prio_recalculate(hdev, ACL_LINK);
+               hci_prio_recalculate(hdev, type);
 }
 
 static void hci_sched_acl(struct hci_dev *hdev)
 {
        BT_DBG("%s", hdev->name);
 
-       if (!hci_conn_num(hdev, ACL_LINK))
+       /* No ACL link over BR/EDR controller */
+       if (!hci_conn_num(hdev, ACL_LINK) && hdev->dev_type == HCI_BREDR)
+               return;
+
+       /* No AMP link over AMP controller */
+       if (!hci_conn_num(hdev, AMP_LINK) && hdev->dev_type == HCI_AMP)
                return;
 
        switch (hdev->flow_ctl_mode) {
index 2022b43c7353ee98d7546d6c9e0ef67c43811d3f..aae80531f8cefabcd1388a3457ef0a42b1ee5328 100644 (file)
@@ -30,6 +30,8 @@
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
 #include <net/bluetooth/mgmt.h>
+#include <net/bluetooth/a2mp.h>
+#include <net/bluetooth/amp.h>
 
 /* Handle HCI Event packets */
 
@@ -458,10 +460,10 @@ static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
 
 static u8 hci_get_inquiry_mode(struct hci_dev *hdev)
 {
-       if (hdev->features[6] & LMP_EXT_INQ)
+       if (lmp_ext_inq_capable(hdev))
                return 2;
 
-       if (hdev->features[3] & LMP_RSSI_INQ)
+       if (lmp_inq_rssi_capable(hdev))
                return 1;
 
        if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 &&
@@ -505,28 +507,30 @@ static void hci_setup_event_mask(struct hci_dev *hdev)
        if (hdev->hci_ver < BLUETOOTH_VER_1_2)
                return;
 
-       events[4] |= 0x01; /* Flow Specification Complete */
-       events[4] |= 0x02; /* Inquiry Result with RSSI */
-       events[4] |= 0x04; /* Read Remote Extended Features Complete */
-       events[5] |= 0x08; /* Synchronous Connection Complete */
-       events[5] |= 0x10; /* Synchronous Connection Changed */
+       if (lmp_bredr_capable(hdev)) {
+               events[4] |= 0x01; /* Flow Specification Complete */
+               events[4] |= 0x02; /* Inquiry Result with RSSI */
+               events[4] |= 0x04; /* Read Remote Extended Features Complete */
+               events[5] |= 0x08; /* Synchronous Connection Complete */
+               events[5] |= 0x10; /* Synchronous Connection Changed */
+       }
 
-       if (hdev->features[3] & LMP_RSSI_INQ)
+       if (lmp_inq_rssi_capable(hdev))
                events[4] |= 0x02; /* Inquiry Result with RSSI */
 
        if (lmp_sniffsubr_capable(hdev))
                events[5] |= 0x20; /* Sniff Subrating */
 
-       if (hdev->features[5] & LMP_PAUSE_ENC)
+       if (lmp_pause_enc_capable(hdev))
                events[5] |= 0x80; /* Encryption Key Refresh Complete */
 
-       if (hdev->features[6] & LMP_EXT_INQ)
+       if (lmp_ext_inq_capable(hdev))
                events[5] |= 0x40; /* Extended Inquiry Result */
 
        if (lmp_no_flush_capable(hdev))
                events[7] |= 0x01; /* Enhanced Flush Complete */
 
-       if (hdev->features[7] & LMP_LSTO)
+       if (lmp_lsto_capable(hdev))
                events[6] |= 0x80; /* Link Supervision Timeout Changed */
 
        if (lmp_ssp_capable(hdev)) {
@@ -546,6 +550,53 @@ static void hci_setup_event_mask(struct hci_dev *hdev)
                events[7] |= 0x20;      /* LE Meta-Event */
 
        hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
+
+       if (lmp_le_capable(hdev)) {
+               memset(events, 0, sizeof(events));
+               events[0] = 0x1f;
+               hci_send_cmd(hdev, HCI_OP_LE_SET_EVENT_MASK,
+                            sizeof(events), events);
+       }
+}
+
+static void bredr_setup(struct hci_dev *hdev)
+{
+       struct hci_cp_delete_stored_link_key cp;
+       __le16 param;
+       __u8 flt_type;
+
+       /* Read Buffer Size (ACL mtu, max pkt, etc.) */
+       hci_send_cmd(hdev, HCI_OP_READ_BUFFER_SIZE, 0, NULL);
+
+       /* Read Class of Device */
+       hci_send_cmd(hdev, HCI_OP_READ_CLASS_OF_DEV, 0, NULL);
+
+       /* Read Local Name */
+       hci_send_cmd(hdev, HCI_OP_READ_LOCAL_NAME, 0, NULL);
+
+       /* Read Voice Setting */
+       hci_send_cmd(hdev, HCI_OP_READ_VOICE_SETTING, 0, NULL);
+
+       /* Clear Event Filters */
+       flt_type = HCI_FLT_CLEAR_ALL;
+       hci_send_cmd(hdev, HCI_OP_SET_EVENT_FLT, 1, &flt_type);
+
+       /* Connection accept timeout ~20 secs */
+       param = __constant_cpu_to_le16(0x7d00);
+       hci_send_cmd(hdev, HCI_OP_WRITE_CA_TIMEOUT, 2, &param);
+
+       bacpy(&cp.bdaddr, BDADDR_ANY);
+       cp.delete_all = 1;
+       hci_send_cmd(hdev, HCI_OP_DELETE_STORED_LINK_KEY, sizeof(cp), &cp);
+}
+
+static void le_setup(struct hci_dev *hdev)
+{
+       /* Read LE Buffer Size */
+       hci_send_cmd(hdev, HCI_OP_LE_READ_BUFFER_SIZE, 0, NULL);
+
+       /* Read LE Advertising Channel TX Power */
+       hci_send_cmd(hdev, HCI_OP_LE_READ_ADV_TX_POWER, 0, NULL);
 }
 
 static void hci_setup(struct hci_dev *hdev)
@@ -553,6 +604,15 @@ static void hci_setup(struct hci_dev *hdev)
        if (hdev->dev_type != HCI_BREDR)
                return;
 
+       /* Read BD Address */
+       hci_send_cmd(hdev, HCI_OP_READ_BD_ADDR, 0, NULL);
+
+       if (lmp_bredr_capable(hdev))
+               bredr_setup(hdev);
+
+       if (lmp_le_capable(hdev))
+               le_setup(hdev);
+
        hci_setup_event_mask(hdev);
 
        if (hdev->hci_ver > BLUETOOTH_VER_1_1)
@@ -573,13 +633,13 @@ static void hci_setup(struct hci_dev *hdev)
                }
        }
 
-       if (hdev->features[3] & LMP_RSSI_INQ)
+       if (lmp_inq_rssi_capable(hdev))
                hci_setup_inquiry_mode(hdev);
 
-       if (hdev->features[7] & LMP_INQ_TX_PWR)
+       if (lmp_inq_tx_pwr_capable(hdev))
                hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL);
 
-       if (hdev->features[7] & LMP_EXTFEATURES) {
+       if (lmp_ext_feat_capable(hdev)) {
                struct hci_cp_read_local_ext_features cp;
 
                cp.page = 0x01;
@@ -626,11 +686,11 @@ static void hci_setup_link_policy(struct hci_dev *hdev)
 
        if (lmp_rswitch_capable(hdev))
                link_policy |= HCI_LP_RSWITCH;
-       if (hdev->features[0] & LMP_HOLD)
+       if (lmp_hold_capable(hdev))
                link_policy |= HCI_LP_HOLD;
        if (lmp_sniff_capable(hdev))
                link_policy |= HCI_LP_SNIFF;
-       if (hdev->features[1] & LMP_PARK)
+       if (lmp_park_capable(hdev))
                link_policy |= HCI_LP_PARK;
 
        cp.policy = cpu_to_le16(link_policy);
@@ -720,10 +780,10 @@ static void hci_set_le_support(struct hci_dev *hdev)
 
        if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
                cp.le = 1;
-               cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR);
+               cp.simul = !!lmp_le_br_capable(hdev);
        }
 
-       if (cp.le != !!(hdev->host_features[0] & LMP_HOST_LE))
+       if (cp.le != !!lmp_host_le_capable(hdev))
                hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp),
                             &cp);
 }
@@ -846,7 +906,7 @@ static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
        BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
 
        if (rp->status)
-               return;
+               goto a2mp_rsp;
 
        hdev->amp_status = rp->amp_status;
        hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
@@ -860,6 +920,46 @@ static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
        hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
 
        hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status);
+
+a2mp_rsp:
+       a2mp_send_getinfo_rsp(hdev);
+}
+
+static void hci_cc_read_local_amp_assoc(struct hci_dev *hdev,
+                                       struct sk_buff *skb)
+{
+       struct hci_rp_read_local_amp_assoc *rp = (void *) skb->data;
+       struct amp_assoc *assoc = &hdev->loc_assoc;
+       size_t rem_len, frag_len;
+
+       BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
+
+       if (rp->status)
+               goto a2mp_rsp;
+
+       frag_len = skb->len - sizeof(*rp);
+       rem_len = __le16_to_cpu(rp->rem_len);
+
+       if (rem_len > frag_len) {
+               BT_DBG("frag_len %zu rem_len %zu", frag_len, rem_len);
+
+               memcpy(assoc->data + assoc->offset, rp->frag, frag_len);
+               assoc->offset += frag_len;
+
+               /* Read other fragments */
+               amp_read_loc_assoc_frag(hdev, rp->phy_handle);
+
+               return;
+       }
+
+       memcpy(assoc->data + assoc->offset, rp->frag, rem_len);
+       assoc->len = assoc->offset + rem_len;
+       assoc->offset = 0;
+
+a2mp_rsp:
+       /* Send A2MP Rsp when all fragments are received */
+       a2mp_send_getampassoc_rsp(hdev, rp->status);
+       a2mp_send_create_phy_link_req(hdev, rp->status);
 }
 
 static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
@@ -976,6 +1076,28 @@ static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
        hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status);
 }
 
+static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev,
+                                       struct sk_buff *skb)
+{
+       struct hci_rp_le_read_adv_tx_power *rp = (void *) skb->data;
+
+       BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
+
+       if (!rp->status)
+               hdev->adv_tx_power = rp->tx_power;
+
+       hci_req_complete(hdev, HCI_OP_LE_READ_ADV_TX_POWER, rp->status);
+}
+
+static void hci_cc_le_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
+{
+       __u8 status = *((__u8 *) skb->data);
+
+       BT_DBG("%s status 0x%2.2x", hdev->name, status);
+
+       hci_req_complete(hdev, HCI_OP_LE_SET_EVENT_MASK, status);
+}
+
 static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
 {
        struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
@@ -1165,6 +1287,11 @@ static void hci_cc_write_le_host_supported(struct hci_dev *hdev,
                        hdev->host_features[0] |= LMP_HOST_LE;
                else
                        hdev->host_features[0] &= ~LMP_HOST_LE;
+
+               if (sent->simul)
+                       hdev->host_features[0] |= LMP_HOST_LE_BREDR;
+               else
+                       hdev->host_features[0] &= ~LMP_HOST_LE_BREDR;
        }
 
        if (test_bit(HCI_MGMT, &hdev->dev_flags) &&
@@ -1174,6 +1301,20 @@ static void hci_cc_write_le_host_supported(struct hci_dev *hdev,
        hci_req_complete(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, status);
 }
 
+static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev,
+                                         struct sk_buff *skb)
+{
+       struct hci_rp_write_remote_amp_assoc *rp = (void *) skb->data;
+
+       BT_DBG("%s status 0x%2.2x phy_handle 0x%2.2x",
+              hdev->name, rp->status, rp->phy_handle);
+
+       if (rp->status)
+               return;
+
+       amp_write_rem_assoc_continue(hdev, rp->phy_handle);
+}
+
 static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
 {
        BT_DBG("%s status 0x%2.2x", hdev->name, status);
@@ -1210,7 +1351,7 @@ static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
 
        conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
 
-       BT_DBG("%s bdaddr %s hcon %p", hdev->name, batostr(&cp->bdaddr), conn);
+       BT_DBG("%s bdaddr %pMR hcon %p", hdev->name, &cp->bdaddr, conn);
 
        if (status) {
                if (conn && conn->state == BT_CONNECT) {
@@ -1639,8 +1780,7 @@ static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
                        return;
                }
 
-               BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&conn->dst),
-                      conn);
+               BT_DBG("%s bdaddr %pMR conn %p", hdev->name, &conn->dst, conn);
 
                conn->state = BT_CLOSED;
                mgmt_connect_failed(hdev, &conn->dst, conn->type,
@@ -1657,6 +1797,38 @@ static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
        BT_DBG("%s status 0x%2.2x", hdev->name, status);
 }
 
+static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status)
+{
+       struct hci_cp_create_phy_link *cp;
+
+       BT_DBG("%s status 0x%2.2x", hdev->name, status);
+
+       if (status)
+               return;
+
+       cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_PHY_LINK);
+       if (!cp)
+               return;
+
+       amp_write_remote_assoc(hdev, cp->phy_handle);
+}
+
+static void hci_cs_accept_phylink(struct hci_dev *hdev, u8 status)
+{
+       struct hci_cp_accept_phy_link *cp;
+
+       BT_DBG("%s status 0x%2.2x", hdev->name, status);
+
+       if (status)
+               return;
+
+       cp = hci_sent_cmd_data(hdev, HCI_OP_ACCEPT_PHY_LINK);
+       if (!cp)
+               return;
+
+       amp_write_remote_assoc(hdev, cp->phy_handle);
+}
+
 static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
        __u8 status = *((__u8 *) skb->data);
@@ -1822,7 +1994,7 @@ static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
        struct hci_ev_conn_request *ev = (void *) skb->data;
        int mask = hdev->link_mode;
 
-       BT_DBG("%s bdaddr %s type 0x%x", hdev->name, batostr(&ev->bdaddr),
+       BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr,
               ev->link_type);
 
        mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
@@ -2314,6 +2486,10 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
                hci_cc_read_local_amp_info(hdev, skb);
                break;
 
+       case HCI_OP_READ_LOCAL_AMP_ASSOC:
+               hci_cc_read_local_amp_assoc(hdev, skb);
+               break;
+
        case HCI_OP_DELETE_STORED_LINK_KEY:
                hci_cc_delete_stored_link_key(hdev, skb);
                break;
@@ -2350,6 +2526,14 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
                hci_cc_le_read_buffer_size(hdev, skb);
                break;
 
+       case HCI_OP_LE_READ_ADV_TX_POWER:
+               hci_cc_le_read_adv_tx_power(hdev, skb);
+               break;
+
+       case HCI_OP_LE_SET_EVENT_MASK:
+               hci_cc_le_set_event_mask(hdev, skb);
+               break;
+
        case HCI_OP_USER_CONFIRM_REPLY:
                hci_cc_user_confirm_reply(hdev, skb);
                break;
@@ -2386,6 +2570,10 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
                hci_cc_write_le_host_supported(hdev, skb);
                break;
 
+       case HCI_OP_WRITE_REMOTE_AMP_ASSOC:
+               hci_cc_write_remote_amp_assoc(hdev, skb);
+               break;
+
        default:
                BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
                break;
@@ -2467,6 +2655,14 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
                hci_cs_le_start_enc(hdev, ev->status);
                break;
 
+       case HCI_OP_CREATE_PHY_LINK:
+               hci_cs_create_phylink(hdev, ev->status);
+               break;
+
+       case HCI_OP_ACCEPT_PHY_LINK:
+               hci_cs_accept_phylink(hdev, ev->status);
+               break;
+
        default:
                BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
                break;
@@ -2574,6 +2770,27 @@ static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
        queue_work(hdev->workqueue, &hdev->tx_work);
 }
 
+static struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev,
+                                                __u16 handle)
+{
+       struct hci_chan *chan;
+
+       switch (hdev->dev_type) {
+       case HCI_BREDR:
+               return hci_conn_hash_lookup_handle(hdev, handle);
+       case HCI_AMP:
+               chan = hci_chan_lookup_handle(hdev, handle);
+               if (chan)
+                       return chan->conn;
+               break;
+       default:
+               BT_ERR("%s unknown dev_type %d", hdev->name, hdev->dev_type);
+               break;
+       }
+
+       return NULL;
+}
+
 static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
        struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
@@ -2595,13 +2812,13 @@ static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb)
 
        for (i = 0; i < ev->num_hndl; i++) {
                struct hci_comp_blocks_info *info = &ev->handles[i];
-               struct hci_conn *conn;
+               struct hci_conn *conn = NULL;
                __u16  handle, block_count;
 
                handle = __le16_to_cpu(info->handle);
                block_count = __le16_to_cpu(info->blocks);
 
-               conn = hci_conn_hash_lookup_handle(hdev, handle);
+               conn = __hci_conn_lookup_handle(hdev, handle);
                if (!conn)
                        continue;
 
@@ -2609,6 +2826,7 @@ static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb)
 
                switch (conn->type) {
                case ACL_LINK:
+               case AMP_LINK:
                        hdev->block_cnt += block_count;
                        if (hdev->block_cnt > hdev->num_blocks)
                                hdev->block_cnt = hdev->num_blocks;
@@ -2705,13 +2923,13 @@ static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
 
        key = hci_find_link_key(hdev, &ev->bdaddr);
        if (!key) {
-               BT_DBG("%s link key not found for %s", hdev->name,
-                      batostr(&ev->bdaddr));
+               BT_DBG("%s link key not found for %pMR", hdev->name,
+                      &ev->bdaddr);
                goto not_found;
        }
 
-       BT_DBG("%s found key type %u for %s", hdev->name, key->type,
-              batostr(&ev->bdaddr));
+       BT_DBG("%s found key type %u for %pMR", hdev->name, key->type,
+              &ev->bdaddr);
 
        if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) &&
            key->type == HCI_LK_DEBUG_COMBINATION) {
@@ -3558,6 +3776,22 @@ static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
        }
 }
 
+static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb)
+{
+       struct hci_ev_channel_selected *ev = (void *) skb->data;
+       struct hci_conn *hcon;
+
+       BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle);
+
+       skb_pull(skb, sizeof(*ev));
+
+       hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
+       if (!hcon)
+               return;
+
+       amp_read_loc_assoc_final_data(hdev, hcon);
+}
+
 void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
 {
        struct hci_event_hdr *hdr = (void *) skb->data;
@@ -3722,6 +3956,10 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
                hci_le_meta_evt(hdev, skb);
                break;
 
+       case HCI_EV_CHANNEL_SELECTED:
+               hci_chan_selected_evt(hdev, skb);
+               break;
+
        case HCI_EV_REMOTE_OOB_DATA_REQUEST:
                hci_remote_oob_data_request_evt(hdev, skb);
                break;
index a20e61c3653dbf84f3c567977757f61239fd2a82..55cceee02a840598d8b8f49d9f6b0ad989719ba8 100644 (file)
@@ -38,7 +38,7 @@ static ssize_t show_link_address(struct device *dev,
                                 struct device_attribute *attr, char *buf)
 {
        struct hci_conn *conn = to_hci_conn(dev);
-       return sprintf(buf, "%s\n", batostr(&conn->dst));
+       return sprintf(buf, "%pMR\n", &conn->dst);
 }
 
 static ssize_t show_link_features(struct device *dev,
@@ -224,7 +224,7 @@ static ssize_t show_address(struct device *dev,
                            struct device_attribute *attr, char *buf)
 {
        struct hci_dev *hdev = to_hci_dev(dev);
-       return sprintf(buf, "%s\n", batostr(&hdev->bdaddr));
+       return sprintf(buf, "%pMR\n", &hdev->bdaddr);
 }
 
 static ssize_t show_features(struct device *dev,
@@ -406,8 +406,8 @@ static int inquiry_cache_show(struct seq_file *f, void *p)
 
        list_for_each_entry(e, &cache->all, all) {
                struct inquiry_data *data = &e->data;
-               seq_printf(f, "%s %d %d %d 0x%.2x%.2x%.2x 0x%.4x %d %d %u\n",
-                          batostr(&data->bdaddr),
+               seq_printf(f, "%pMR %d %d %d 0x%.2x%.2x%.2x 0x%.4x %d %d %u\n",
+                          &data->bdaddr,
                           data->pscan_rep_mode, data->pscan_period_mode,
                           data->pscan_mode, data->dev_class[2],
                           data->dev_class[1], data->dev_class[0],
@@ -440,7 +440,7 @@ static int blacklist_show(struct seq_file *f, void *p)
        hci_dev_lock(hdev);
 
        list_for_each_entry(b, &hdev->blacklist, list)
-               seq_printf(f, "%s\n", batostr(&b->bdaddr));
+               seq_printf(f, "%pMR\n", &b->bdaddr);
 
        hci_dev_unlock(hdev);
 
index ccd985da65180656d7df83a986655c4b82258220..0c0028463fa3479f5448053772b14fe11360fa49 100644 (file)
@@ -932,8 +932,12 @@ static int hidp_setup_hid(struct hidp_session *session,
        hid->country = req->country;
 
        strncpy(hid->name, req->name, 128);
-       strncpy(hid->phys, batostr(&bt_sk(session->ctrl_sock->sk)->src), 64);
-       strncpy(hid->uniq, batostr(&bt_sk(session->ctrl_sock->sk)->dst), 64);
+
+       snprintf(hid->phys, sizeof(hid->phys), "%pMR",
+                &bt_sk(session->ctrl_sock->sk)->src);
+
+       snprintf(hid->uniq, sizeof(hid->uniq), "%pMR",
+                &bt_sk(session->ctrl_sock->sk)->dst);
 
        hid->dev.parent = &session->conn->dev;
        hid->ll_driver = &hidp_hid_driver;
index a91239dcda417f5a862346c981bb941aba44d086..fae0c70e8e106471094984e3781101634521f39e 100644 (file)
@@ -48,19 +48,20 @@ static LIST_HEAD(chan_list);
 static DEFINE_RWLOCK(chan_list_lock);
 
 static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
-                               u8 code, u8 ident, u16 dlen, void *data);
+                                      u8 code, u8 ident, u16 dlen, void *data);
 static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
-                                                               void *data);
+                          void *data);
 static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data);
 static void l2cap_send_disconn_req(struct l2cap_conn *conn,
                                   struct l2cap_chan *chan, int err);
 
 static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
-                   struct sk_buff_head *skbs, u8 event);
+                    struct sk_buff_head *skbs, u8 event);
 
 /* ---- L2CAP channels ---- */
 
-static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid)
+static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn,
+                                                  u16 cid)
 {
        struct l2cap_chan *c;
 
@@ -71,7 +72,8 @@ static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16
        return NULL;
 }
 
-static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
+static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn,
+                                                  u16 cid)
 {
        struct l2cap_chan *c;
 
@@ -84,7 +86,8 @@ static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16
 
 /* Find channel with given SCID.
  * Returns locked channel. */
-static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
+static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn,
+                                                u16 cid)
 {
        struct l2cap_chan *c;
 
@@ -97,7 +100,25 @@ static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 ci
        return c;
 }
 
-static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
+/* Find channel with given DCID.
+ * Returns locked channel.
+ */
+static struct l2cap_chan *l2cap_get_chan_by_dcid(struct l2cap_conn *conn,
+                                                u16 cid)
+{
+       struct l2cap_chan *c;
+
+       mutex_lock(&conn->chan_lock);
+       c = __l2cap_get_chan_by_dcid(conn, cid);
+       if (c)
+               l2cap_chan_lock(c);
+       mutex_unlock(&conn->chan_lock);
+
+       return c;
+}
+
+static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn,
+                                                   u8 ident)
 {
        struct l2cap_chan *c;
 
@@ -108,6 +129,20 @@ static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8
        return NULL;
 }
 
+static struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn,
+                                                 u8 ident)
+{
+       struct l2cap_chan *c;
+
+       mutex_lock(&conn->chan_lock);
+       c = __l2cap_get_chan_by_ident(conn, ident);
+       if (c)
+               l2cap_chan_lock(c);
+       mutex_unlock(&conn->chan_lock);
+
+       return c;
+}
+
 static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src)
 {
        struct l2cap_chan *c;
@@ -178,7 +213,7 @@ static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
 static void __l2cap_state_change(struct l2cap_chan *chan, int state)
 {
        BT_DBG("chan %p %s -> %s", chan, state_to_string(chan->state),
-                                               state_to_string(state));
+              state_to_string(state));
 
        chan->state = state;
        chan->ops->state_change(chan, state);
@@ -361,7 +396,7 @@ static void l2cap_seq_list_append(struct l2cap_seq_list *seq_list, u16 seq)
 static void l2cap_chan_timeout(struct work_struct *work)
 {
        struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
-                                                       chan_timer.work);
+                                              chan_timer.work);
        struct l2cap_conn *conn = chan->conn;
        int reason;
 
@@ -373,7 +408,7 @@ static void l2cap_chan_timeout(struct work_struct *work)
        if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG)
                reason = ECONNREFUSED;
        else if (chan->state == BT_CONNECT &&
-                                       chan->sec_level != BT_SECURITY_SDP)
+                chan->sec_level != BT_SECURITY_SDP)
                reason = ECONNREFUSED;
        else
                reason = ETIMEDOUT;
@@ -455,7 +490,7 @@ void l2cap_chan_set_defaults(struct l2cap_chan *chan)
        set_bit(FLAG_FORCE_ACTIVE, &chan->flags);
 }
 
-static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
+void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
 {
        BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
               __le16_to_cpu(chan->psm), chan->dcid);
@@ -504,7 +539,7 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
        chan->local_msdu        = L2CAP_DEFAULT_MAX_SDU_SIZE;
        chan->local_sdu_itime   = L2CAP_DEFAULT_SDU_ITIME;
        chan->local_acc_lat     = L2CAP_DEFAULT_ACC_LAT;
-       chan->local_flush_to    = L2CAP_DEFAULT_FLUSH_TO;
+       chan->local_flush_to    = L2CAP_EFS_DEFAULT_FLUSH_TO;
 
        l2cap_chan_hold(chan);
 
@@ -527,6 +562,7 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err)
        BT_DBG("chan %p, conn %p, err %d", chan, conn, err);
 
        if (conn) {
+               struct amp_mgr *mgr = conn->hcon->amp_mgr;
                /* Delete from channel list */
                list_del(&chan->list);
 
@@ -536,10 +572,12 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err)
 
                if (chan->chan_type != L2CAP_CHAN_CONN_FIX_A2MP)
                        hci_conn_put(conn->hcon);
+
+               if (mgr && mgr->bredr_chan == chan)
+                       mgr->bredr_chan = NULL;
        }
 
-       if (chan->ops->teardown)
-               chan->ops->teardown(chan, err);
+       chan->ops->teardown(chan, err);
 
        if (test_bit(CONF_NOT_COMPLETE, &chan->conf_state))
                return;
@@ -573,19 +611,18 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason)
        struct l2cap_conn *conn = chan->conn;
        struct sock *sk = chan->sk;
 
-       BT_DBG("chan %p state %s sk %p", chan,
-                                       state_to_string(chan->state), sk);
+       BT_DBG("chan %p state %s sk %p", chan, state_to_string(chan->state),
+              sk);
 
        switch (chan->state) {
        case BT_LISTEN:
-               if (chan->ops->teardown)
-                       chan->ops->teardown(chan, 0);
+               chan->ops->teardown(chan, 0);
                break;
 
        case BT_CONNECTED:
        case BT_CONFIG:
                if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
-                                       conn->hcon->type == ACL_LINK) {
+                   conn->hcon->type == ACL_LINK) {
                        __set_chan_timer(chan, sk->sk_sndtimeo);
                        l2cap_send_disconn_req(conn, chan, reason);
                } else
@@ -594,7 +631,7 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason)
 
        case BT_CONNECT2:
                if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
-                                       conn->hcon->type == ACL_LINK) {
+                   conn->hcon->type == ACL_LINK) {
                        struct l2cap_conn_rsp rsp;
                        __u16 result;
 
@@ -609,7 +646,7 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason)
                        rsp.result = cpu_to_le16(result);
                        rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
                        l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
-                                                       sizeof(rsp), &rsp);
+                                      sizeof(rsp), &rsp);
                }
 
                l2cap_chan_del(chan, reason);
@@ -621,8 +658,7 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason)
                break;
 
        default:
-               if (chan->ops->teardown)
-                       chan->ops->teardown(chan, 0);
+               chan->ops->teardown(chan, 0);
                break;
        }
 }
@@ -691,7 +727,8 @@ static u8 l2cap_get_ident(struct l2cap_conn *conn)
        return id;
 }
 
-static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
+static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
+                          void *data)
 {
        struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
        u8 flags;
@@ -712,16 +749,31 @@ static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
        hci_send_acl(conn->hchan, skb, flags);
 }
 
+static bool __chan_is_moving(struct l2cap_chan *chan)
+{
+       return chan->move_state != L2CAP_MOVE_STABLE &&
+              chan->move_state != L2CAP_MOVE_WAIT_PREPARE;
+}
+
 static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
 {
        struct hci_conn *hcon = chan->conn->hcon;
        u16 flags;
 
        BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len,
-                                                       skb->priority);
+              skb->priority);
+
+       if (chan->hs_hcon && !__chan_is_moving(chan)) {
+               if (chan->hs_hchan)
+                       hci_send_acl(chan->hs_hchan, skb, ACL_COMPLETE);
+               else
+                       kfree_skb(skb);
+
+               return;
+       }
 
        if (!test_bit(FLAG_FLUSHABLE, &chan->flags) &&
-                                       lmp_no_flush_capable(hcon->hdev))
+           lmp_no_flush_capable(hcon->hdev))
                flags = ACL_START_NO_FLUSH;
        else
                flags = ACL_START;
@@ -895,6 +947,9 @@ static void l2cap_send_sframe(struct l2cap_chan *chan,
        if (!control->sframe)
                return;
 
+       if (__chan_is_moving(chan))
+               return;
+
        if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state) &&
            !control->poll)
                control->final = 1;
@@ -946,7 +1001,19 @@ static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
        return !test_bit(CONF_CONNECT_PEND, &chan->conf_state);
 }
 
-static void l2cap_send_conn_req(struct l2cap_chan *chan)
+static bool __amp_capable(struct l2cap_chan *chan)
+{
+       struct l2cap_conn *conn = chan->conn;
+
+       if (enable_hs &&
+           chan->chan_policy == BT_CHANNEL_POLICY_AMP_PREFERRED &&
+           conn->fixed_chan_mask & L2CAP_FC_A2MP)
+               return true;
+       else
+               return false;
+}
+
+void l2cap_send_conn_req(struct l2cap_chan *chan)
 {
        struct l2cap_conn *conn = chan->conn;
        struct l2cap_conn_req req;
@@ -961,6 +1028,76 @@ static void l2cap_send_conn_req(struct l2cap_chan *chan)
        l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, sizeof(req), &req);
 }
 
+static void l2cap_send_create_chan_req(struct l2cap_chan *chan, u8 amp_id)
+{
+       struct l2cap_create_chan_req req;
+       req.scid = cpu_to_le16(chan->scid);
+       req.psm  = chan->psm;
+       req.amp_id = amp_id;
+
+       chan->ident = l2cap_get_ident(chan->conn);
+
+       l2cap_send_cmd(chan->conn, chan->ident, L2CAP_CREATE_CHAN_REQ,
+                      sizeof(req), &req);
+}
+
+static void l2cap_move_setup(struct l2cap_chan *chan)
+{
+       struct sk_buff *skb;
+
+       BT_DBG("chan %p", chan);
+
+       if (chan->mode != L2CAP_MODE_ERTM)
+               return;
+
+       __clear_retrans_timer(chan);
+       __clear_monitor_timer(chan);
+       __clear_ack_timer(chan);
+
+       chan->retry_count = 0;
+       skb_queue_walk(&chan->tx_q, skb) {
+               if (bt_cb(skb)->control.retries)
+                       bt_cb(skb)->control.retries = 1;
+               else
+                       break;
+       }
+
+       chan->expected_tx_seq = chan->buffer_seq;
+
+       clear_bit(CONN_REJ_ACT, &chan->conn_state);
+       clear_bit(CONN_SREJ_ACT, &chan->conn_state);
+       l2cap_seq_list_clear(&chan->retrans_list);
+       l2cap_seq_list_clear(&chan->srej_list);
+       skb_queue_purge(&chan->srej_q);
+
+       chan->tx_state = L2CAP_TX_STATE_XMIT;
+       chan->rx_state = L2CAP_RX_STATE_MOVE;
+
+       set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
+}
+
+static void l2cap_move_done(struct l2cap_chan *chan)
+{
+       u8 move_role = chan->move_role;
+       BT_DBG("chan %p", chan);
+
+       chan->move_state = L2CAP_MOVE_STABLE;
+       chan->move_role = L2CAP_MOVE_ROLE_NONE;
+
+       if (chan->mode != L2CAP_MODE_ERTM)
+               return;
+
+       switch (move_role) {
+       case L2CAP_MOVE_ROLE_INITIATOR:
+               l2cap_tx(chan, NULL, NULL, L2CAP_EV_EXPLICIT_POLL);
+               chan->rx_state = L2CAP_RX_STATE_WAIT_F;
+               break;
+       case L2CAP_MOVE_ROLE_RESPONDER:
+               chan->rx_state = L2CAP_RX_STATE_WAIT_P;
+               break;
+       }
+}
+
 static void l2cap_chan_ready(struct l2cap_chan *chan)
 {
        /* This clears all conf flags, including CONF_NOT_COMPLETE */
@@ -972,6 +1109,16 @@ static void l2cap_chan_ready(struct l2cap_chan *chan)
        chan->ops->ready(chan);
 }
 
+static void l2cap_start_connection(struct l2cap_chan *chan)
+{
+       if (__amp_capable(chan)) {
+               BT_DBG("chan %p AMP capable: discover AMPs", chan);
+               a2mp_discover_amp(chan);
+       } else {
+               l2cap_send_conn_req(chan);
+       }
+}
+
 static void l2cap_do_start(struct l2cap_chan *chan)
 {
        struct l2cap_conn *conn = chan->conn;
@@ -986,8 +1133,9 @@ static void l2cap_do_start(struct l2cap_chan *chan)
                        return;
 
                if (l2cap_chan_check_security(chan) &&
-                               __l2cap_no_conn_pending(chan))
-                       l2cap_send_conn_req(chan);
+                   __l2cap_no_conn_pending(chan)) {
+                       l2cap_start_connection(chan);
+               }
        } else {
                struct l2cap_info_req req;
                req.type = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK);
@@ -997,8 +1145,8 @@ static void l2cap_do_start(struct l2cap_chan *chan)
 
                schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT);
 
-               l2cap_send_cmd(conn, conn->info_ident,
-                                       L2CAP_INFO_REQ, sizeof(req), &req);
+               l2cap_send_cmd(conn, conn->info_ident, L2CAP_INFO_REQ,
+                              sizeof(req), &req);
        }
 }
 
@@ -1018,7 +1166,8 @@ static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
        }
 }
 
-static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
+static void l2cap_send_disconn_req(struct l2cap_conn *conn,
+                                  struct l2cap_chan *chan, int err)
 {
        struct sock *sk = chan->sk;
        struct l2cap_disconn_req req;
@@ -1033,14 +1182,14 @@ static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *c
        }
 
        if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) {
-               __l2cap_state_change(chan, BT_DISCONN);
+               l2cap_state_change(chan, BT_DISCONN);
                return;
        }
 
        req.dcid = cpu_to_le16(chan->dcid);
        req.scid = cpu_to_le16(chan->scid);
-       l2cap_send_cmd(conn, l2cap_get_ident(conn),
-                       L2CAP_DISCONN_REQ, sizeof(req), &req);
+       l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_DISCONN_REQ,
+                      sizeof(req), &req);
 
        lock_sock(sk);
        __l2cap_state_change(chan, BT_DISCONN);
@@ -1069,20 +1218,20 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
 
                if (chan->state == BT_CONNECT) {
                        if (!l2cap_chan_check_security(chan) ||
-                                       !__l2cap_no_conn_pending(chan)) {
+                           !__l2cap_no_conn_pending(chan)) {
                                l2cap_chan_unlock(chan);
                                continue;
                        }
 
                        if (!l2cap_mode_supported(chan->mode, conn->feat_mask)
-                                       && test_bit(CONF_STATE2_DEVICE,
+                           && test_bit(CONF_STATE2_DEVICE,
                                        &chan->conf_state)) {
                                l2cap_chan_close(chan, ECONNRESET);
                                l2cap_chan_unlock(chan);
                                continue;
                        }
 
-                       l2cap_send_conn_req(chan);
+                       l2cap_start_connection(chan);
 
                } else if (chan->state == BT_CONNECT2) {
                        struct l2cap_conn_rsp rsp;
@@ -1094,11 +1243,9 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
                                lock_sock(sk);
                                if (test_bit(BT_SK_DEFER_SETUP,
                                             &bt_sk(sk)->flags)) {
-                                       struct sock *parent = bt_sk(sk)->parent;
                                        rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND);
                                        rsp.status = __constant_cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
-                                       if (parent)
-                                               parent->sk_data_ready(parent, 0);
+                                       chan->ops->defer(chan);
 
                                } else {
                                        __l2cap_state_change(chan, BT_CONFIG);
@@ -1112,17 +1259,17 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
                        }
 
                        l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
-                                                       sizeof(rsp), &rsp);
+                                      sizeof(rsp), &rsp);
 
                        if (test_bit(CONF_REQ_SENT, &chan->conf_state) ||
-                                       rsp.result != L2CAP_CR_SUCCESS) {
+                           rsp.result != L2CAP_CR_SUCCESS) {
                                l2cap_chan_unlock(chan);
                                continue;
                        }
 
                        set_bit(CONF_REQ_SENT, &chan->conf_state);
                        l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
-                                               l2cap_build_conf_req(chan, buf), buf);
+                                      l2cap_build_conf_req(chan, buf), buf);
                        chan->num_conf_req++;
                }
 
@@ -1204,8 +1351,6 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn)
        bacpy(&bt_sk(sk)->src, conn->src);
        bacpy(&bt_sk(sk)->dst, conn->dst);
 
-       bt_accept_enqueue(parent, sk);
-
        l2cap_chan_add(conn, chan);
 
        l2cap_chan_ready(chan);
@@ -1270,7 +1415,7 @@ static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
 
        list_for_each_entry(chan, &conn->chan_l, list) {
                if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags))
-                       __l2cap_chan_set_err(chan, err);
+                       l2cap_chan_set_err(chan, err);
        }
 
        mutex_unlock(&conn->chan_lock);
@@ -1279,7 +1424,7 @@ static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
 static void l2cap_info_timeout(struct work_struct *work)
 {
        struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
-                                                       info_timer.work);
+                                              info_timer.work);
 
        conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
        conn->info_ident = 0;
@@ -1333,7 +1478,7 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err)
 static void security_timeout(struct work_struct *work)
 {
        struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
-                                               security_timer.work);
+                                              security_timer.work);
 
        BT_DBG("conn %p", conn);
 
@@ -1355,7 +1500,7 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
        if (!hchan)
                return NULL;
 
-       conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
+       conn = kzalloc(sizeof(struct l2cap_conn), GFP_KERNEL);
        if (!conn) {
                hci_chan_del(hchan);
                return NULL;
@@ -1367,10 +1512,22 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
 
        BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan);
 
-       if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
-               conn->mtu = hcon->hdev->le_mtu;
-       else
+       switch (hcon->type) {
+       case AMP_LINK:
+               conn->mtu = hcon->hdev->block_mtu;
+               break;
+
+       case LE_LINK:
+               if (hcon->hdev->le_mtu) {
+                       conn->mtu = hcon->hdev->le_mtu;
+                       break;
+               }
+               /* fall through */
+
+       default:
                conn->mtu = hcon->hdev->acl_mtu;
+               break;
+       }
 
        conn->src = &hcon->hdev->bdaddr;
        conn->dst = &hcon->dst;
@@ -1448,7 +1605,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
        __u8 auth_type;
        int err;
 
-       BT_DBG("%s -> %s (type %u) psm 0x%2.2x", batostr(src), batostr(dst),
+       BT_DBG("%pMR -> %pMR (type %u) psm 0x%2.2x", src, dst,
               dst_type, __le16_to_cpu(psm));
 
        hdev = hci_get_route(dst, src);
@@ -1461,7 +1618,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
 
        /* PSM must be odd and lsb of upper byte must be 0 */
        if ((__le16_to_cpu(psm) & 0x0101) != 0x0001 && !cid &&
-                                       chan->chan_type != L2CAP_CHAN_RAW) {
+           chan->chan_type != L2CAP_CHAN_RAW) {
                err = -EINVAL;
                goto done;
        }
@@ -1657,6 +1814,9 @@ static void l2cap_streaming_send(struct l2cap_chan *chan,
 
        BT_DBG("chan %p, skbs %p", chan, skbs);
 
+       if (__chan_is_moving(chan))
+               return;
+
        skb_queue_splice_tail_init(skbs, &chan->tx_q);
 
        while (!skb_queue_empty(&chan->tx_q)) {
@@ -1699,6 +1859,9 @@ static int l2cap_ertm_send(struct l2cap_chan *chan)
        if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
                return 0;
 
+       if (__chan_is_moving(chan))
+               return 0;
+
        while (chan->tx_send_head &&
               chan->unacked_frames < chan->remote_tx_win &&
               chan->tx_state == L2CAP_TX_STATE_XMIT) {
@@ -1764,13 +1927,16 @@ static void l2cap_ertm_resend(struct l2cap_chan *chan)
        if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
                return;
 
+       if (__chan_is_moving(chan))
+               return;
+
        while (chan->retrans_list.head != L2CAP_SEQ_LIST_CLEAR) {
                seq = l2cap_seq_list_pop(&chan->retrans_list);
 
                skb = l2cap_ertm_seq_in_queue(&chan->tx_q, seq);
                if (!skb) {
                        BT_DBG("Error: Can't retransmit seq %d, frame missing",
-                               seq);
+                              seq);
                        continue;
                }
 
@@ -1795,9 +1961,9 @@ static void l2cap_ertm_resend(struct l2cap_chan *chan)
                        /* Cloned sk_buffs are read-only, so we need a
                         * writeable copy
                         */
-                       tx_skb = skb_copy(skb, GFP_ATOMIC);
+                       tx_skb = skb_copy(skb, GFP_KERNEL);
                } else {
-                       tx_skb = skb_clone(skb, GFP_ATOMIC);
+                       tx_skb = skb_clone(skb, GFP_KERNEL);
                }
 
                if (!tx_skb) {
@@ -1855,7 +2021,7 @@ static void l2cap_retransmit_all(struct l2cap_chan *chan,
        if (chan->unacked_frames) {
                skb_queue_walk(&chan->tx_q, skb) {
                        if (bt_cb(skb)->control.txseq == control->reqseq ||
-                               skb == chan->tx_send_head)
+                           skb == chan->tx_send_head)
                                break;
                }
 
@@ -2106,7 +2272,9 @@ static int l2cap_segment_sdu(struct l2cap_chan *chan,
        /* PDU size is derived from the HCI MTU */
        pdu_len = chan->conn->mtu;
 
-       pdu_len = min_t(size_t, pdu_len, L2CAP_BREDR_MAX_PAYLOAD);
+       /* Constrain PDU size for BR/EDR connections */
+       if (!chan->hs_hcon)
+               pdu_len = min_t(size_t, pdu_len, L2CAP_BREDR_MAX_PAYLOAD);
 
        /* Adjust for largest possible L2CAP overhead. */
        if (chan->fcs)
@@ -2156,7 +2324,7 @@ static int l2cap_segment_sdu(struct l2cap_chan *chan,
 }
 
 int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,
-                                                               u32 priority)
+                   u32 priority)
 {
        struct sk_buff *skb;
        int err;
@@ -2543,7 +2711,7 @@ static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
                /* Don't send frame to the socket it came from */
                if (skb->sk == sk)
                        continue;
-               nskb = skb_clone(skb, GFP_ATOMIC);
+               nskb = skb_clone(skb, GFP_KERNEL);
                if (!nskb)
                        continue;
 
@@ -2569,7 +2737,7 @@ static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, u8 code,
        len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
        count = min_t(unsigned int, conn->mtu, len);
 
-       skb = bt_skb_alloc(count, GFP_ATOMIC);
+       skb = bt_skb_alloc(count, GFP_KERNEL);
        if (!skb)
                return NULL;
 
@@ -2599,7 +2767,7 @@ static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, u8 code,
        while (len) {
                count = min_t(unsigned int, conn->mtu, len);
 
-               *frag = bt_skb_alloc(count, GFP_ATOMIC);
+               *frag = bt_skb_alloc(count, GFP_KERNEL);
                if (!*frag)
                        goto fail;
 
@@ -2618,7 +2786,8 @@ fail:
        return NULL;
 }
 
-static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
+static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen,
+                                    unsigned long *val)
 {
        struct l2cap_conf_opt *opt = *ptr;
        int len;
@@ -2692,7 +2861,7 @@ static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan)
                efs.msdu        = cpu_to_le16(chan->local_msdu);
                efs.sdu_itime   = cpu_to_le32(chan->local_sdu_itime);
                efs.acc_lat     = __constant_cpu_to_le32(L2CAP_DEFAULT_ACC_LAT);
-               efs.flush_to    = __constant_cpu_to_le32(L2CAP_DEFAULT_FLUSH_TO);
+               efs.flush_to    = __constant_cpu_to_le32(L2CAP_EFS_DEFAULT_FLUSH_TO);
                break;
 
        case L2CAP_MODE_STREAMING:
@@ -2709,7 +2878,7 @@ static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan)
        }
 
        l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs),
-                                                       (unsigned long) &efs);
+                          (unsigned long) &efs);
 }
 
 static void l2cap_ack_timeout(struct work_struct *work)
@@ -2749,6 +2918,11 @@ int l2cap_ertm_init(struct l2cap_chan *chan)
 
        skb_queue_head_init(&chan->tx_q);
 
+       chan->local_amp_id = 0;
+       chan->move_id = 0;
+       chan->move_state = L2CAP_MOVE_STABLE;
+       chan->move_role = L2CAP_MOVE_ROLE_NONE;
+
        if (chan->mode != L2CAP_MODE_ERTM)
                return 0;
 
@@ -2795,16 +2969,54 @@ static inline bool __l2cap_efs_supported(struct l2cap_chan *chan)
        return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_FLOW;
 }
 
+static void __l2cap_set_ertm_timeouts(struct l2cap_chan *chan,
+                                     struct l2cap_conf_rfc *rfc)
+{
+       if (chan->local_amp_id && chan->hs_hcon) {
+               u64 ertm_to = chan->hs_hcon->hdev->amp_be_flush_to;
+
+               /* Class 1 devices have must have ERTM timeouts
+                * exceeding the Link Supervision Timeout.  The
+                * default Link Supervision Timeout for AMP
+                * controllers is 10 seconds.
+                *
+                * Class 1 devices use 0xffffffff for their
+                * best-effort flush timeout, so the clamping logic
+                * will result in a timeout that meets the above
+                * requirement.  ERTM timeouts are 16-bit values, so
+                * the maximum timeout is 65.535 seconds.
+                */
+
+               /* Convert timeout to milliseconds and round */
+               ertm_to = DIV_ROUND_UP_ULL(ertm_to, 1000);
+
+               /* This is the recommended formula for class 2 devices
+                * that start ERTM timers when packets are sent to the
+                * controller.
+                */
+               ertm_to = 3 * ertm_to + 500;
+
+               if (ertm_to > 0xffff)
+                       ertm_to = 0xffff;
+
+               rfc->retrans_timeout = cpu_to_le16((u16) ertm_to);
+               rfc->monitor_timeout = rfc->retrans_timeout;
+       } else {
+               rfc->retrans_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
+               rfc->monitor_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
+       }
+}
+
 static inline void l2cap_txwin_setup(struct l2cap_chan *chan)
 {
        if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW &&
-                                               __l2cap_ews_supported(chan)) {
+           __l2cap_ews_supported(chan)) {
                /* use extended control field */
                set_bit(FLAG_EXT_CTRL, &chan->flags);
                chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
        } else {
                chan->tx_win = min_t(u16, chan->tx_win,
-                                               L2CAP_DEFAULT_TX_WINDOW);
+                                    L2CAP_DEFAULT_TX_WINDOW);
                chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
        }
        chan->ack_win = chan->tx_win;
@@ -2844,7 +3056,7 @@ done:
        switch (chan->mode) {
        case L2CAP_MODE_BASIC:
                if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
-                               !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
+                   !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
                        break;
 
                rfc.mode            = L2CAP_MODE_BASIC;
@@ -2855,28 +3067,27 @@ done:
                rfc.max_pdu_size    = 0;
 
                l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
-                                                       (unsigned long) &rfc);
+                                  (unsigned long) &rfc);
                break;
 
        case L2CAP_MODE_ERTM:
                rfc.mode            = L2CAP_MODE_ERTM;
                rfc.max_transmit    = chan->max_tx;
-               rfc.retrans_timeout = 0;
-               rfc.monitor_timeout = 0;
+
+               __l2cap_set_ertm_timeouts(chan, &rfc);
 
                size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
-                                               L2CAP_EXT_HDR_SIZE -
-                                               L2CAP_SDULEN_SIZE -
-                                               L2CAP_FCS_SIZE);
+                            L2CAP_EXT_HDR_SIZE - L2CAP_SDULEN_SIZE -
+                            L2CAP_FCS_SIZE);
                rfc.max_pdu_size = cpu_to_le16(size);
 
                l2cap_txwin_setup(chan);
 
                rfc.txwin_size = min_t(u16, chan->tx_win,
-                                               L2CAP_DEFAULT_TX_WINDOW);
+                                      L2CAP_DEFAULT_TX_WINDOW);
 
                l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
-                                                       (unsigned long) &rfc);
+                                  (unsigned long) &rfc);
 
                if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
                        l2cap_add_opt_efs(&ptr, chan);
@@ -2885,14 +3096,14 @@ done:
                        break;
 
                if (chan->fcs == L2CAP_FCS_NONE ||
-                               test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
+                   test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
                        chan->fcs = L2CAP_FCS_NONE;
                        l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
                }
 
                if (test_bit(FLAG_EXT_CTRL, &chan->flags))
                        l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
-                                                               chan->tx_win);
+                                          chan->tx_win);
                break;
 
        case L2CAP_MODE_STREAMING:
@@ -2904,13 +3115,12 @@ done:
                rfc.monitor_timeout = 0;
 
                size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
-                                               L2CAP_EXT_HDR_SIZE -
-                                               L2CAP_SDULEN_SIZE -
-                                               L2CAP_FCS_SIZE);
+                            L2CAP_EXT_HDR_SIZE - L2CAP_SDULEN_SIZE -
+                            L2CAP_FCS_SIZE);
                rfc.max_pdu_size = cpu_to_le16(size);
 
                l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
-                                                       (unsigned long) &rfc);
+                                  (unsigned long) &rfc);
 
                if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
                        l2cap_add_opt_efs(&ptr, chan);
@@ -2919,7 +3129,7 @@ done:
                        break;
 
                if (chan->fcs == L2CAP_FCS_NONE ||
-                               test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
+                   test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
                        chan->fcs = L2CAP_FCS_NONE;
                        l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
                }
@@ -3011,7 +3221,7 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
        case L2CAP_MODE_ERTM:
                if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) {
                        chan->mode = l2cap_select_mode(rfc.mode,
-                                       chan->conn->feat_mask);
+                                                      chan->conn->feat_mask);
                        break;
                }
 
@@ -3036,8 +3246,8 @@ done:
                if (chan->num_conf_rsp == 1)
                        return -ECONNREFUSED;
 
-               l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
-                                       sizeof(rfc), (unsigned long) &rfc);
+               l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
+                                  (unsigned long) &rfc);
        }
 
        if (result == L2CAP_CONF_SUCCESS) {
@@ -3054,8 +3264,8 @@ done:
 
                if (remote_efs) {
                        if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
-                                       efs.stype != L2CAP_SERV_NOTRAFIC &&
-                                       efs.stype != chan->local_stype) {
+                           efs.stype != L2CAP_SERV_NOTRAFIC &&
+                           efs.stype != chan->local_stype) {
 
                                result = L2CAP_CONF_UNACCEPT;
 
@@ -3063,8 +3273,8 @@ done:
                                        return -ECONNREFUSED;
 
                                l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
-                                                       sizeof(efs),
-                                                       (unsigned long) &efs);
+                                                  sizeof(efs),
+                                                  (unsigned long) &efs);
                        } else {
                                /* Send PENDING Conf Rsp */
                                result = L2CAP_CONF_PENDING;
@@ -3087,51 +3297,45 @@ done:
                        chan->remote_max_tx = rfc.max_transmit;
 
                        size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
-                                               chan->conn->mtu -
-                                               L2CAP_EXT_HDR_SIZE -
-                                               L2CAP_SDULEN_SIZE -
-                                               L2CAP_FCS_SIZE);
+                                    chan->conn->mtu - L2CAP_EXT_HDR_SIZE -
+                                    L2CAP_SDULEN_SIZE - L2CAP_FCS_SIZE);
                        rfc.max_pdu_size = cpu_to_le16(size);
                        chan->remote_mps = size;
 
-                       rfc.retrans_timeout =
-                               __constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
-                       rfc.monitor_timeout =
-                               __constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
+                       __l2cap_set_ertm_timeouts(chan, &rfc);
 
                        set_bit(CONF_MODE_DONE, &chan->conf_state);
 
                        l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
-                                       sizeof(rfc), (unsigned long) &rfc);
+                                          sizeof(rfc), (unsigned long) &rfc);
 
                        if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
                                chan->remote_id = efs.id;
                                chan->remote_stype = efs.stype;
                                chan->remote_msdu = le16_to_cpu(efs.msdu);
                                chan->remote_flush_to =
-                                               le32_to_cpu(efs.flush_to);
+                                       le32_to_cpu(efs.flush_to);
                                chan->remote_acc_lat =
-                                               le32_to_cpu(efs.acc_lat);
+                                       le32_to_cpu(efs.acc_lat);
                                chan->remote_sdu_itime =
                                        le32_to_cpu(efs.sdu_itime);
                                l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
-                                       sizeof(efs), (unsigned long) &efs);
+                                                  sizeof(efs),
+                                                  (unsigned long) &efs);
                        }
                        break;
 
                case L2CAP_MODE_STREAMING:
                        size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
-                                               chan->conn->mtu -
-                                               L2CAP_EXT_HDR_SIZE -
-                                               L2CAP_SDULEN_SIZE -
-                                               L2CAP_FCS_SIZE);
+                                    chan->conn->mtu - L2CAP_EXT_HDR_SIZE -
+                                    L2CAP_SDULEN_SIZE - L2CAP_FCS_SIZE);
                        rfc.max_pdu_size = cpu_to_le16(size);
                        chan->remote_mps = size;
 
                        set_bit(CONF_MODE_DONE, &chan->conf_state);
 
-                       l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
-                                       sizeof(rfc), (unsigned long) &rfc);
+                       l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
+                                          (unsigned long) &rfc);
 
                        break;
 
@@ -3152,7 +3356,8 @@ done:
        return ptr - data;
 }
 
-static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, void *data, u16 *result)
+static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len,
+                               void *data, u16 *result)
 {
        struct l2cap_conf_req *req = data;
        void *ptr = req->data;
@@ -3179,7 +3384,7 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, voi
                case L2CAP_CONF_FLUSH_TO:
                        chan->flush_to = val;
                        l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
-                                                       2, chan->flush_to);
+                                          2, chan->flush_to);
                        break;
 
                case L2CAP_CONF_RFC:
@@ -3187,13 +3392,13 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, voi
                                memcpy(&rfc, (void *)val, olen);
 
                        if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
-                                                       rfc.mode != chan->mode)
+                           rfc.mode != chan->mode)
                                return -ECONNREFUSED;
 
                        chan->fcs = 0;
 
                        l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
-                                       sizeof(rfc), (unsigned long) &rfc);
+                                          sizeof(rfc), (unsigned long) &rfc);
                        break;
 
                case L2CAP_CONF_EWS:
@@ -3207,12 +3412,12 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, voi
                                memcpy(&efs, (void *)val, olen);
 
                        if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
-                                       efs.stype != L2CAP_SERV_NOTRAFIC &&
-                                       efs.stype != chan->local_stype)
+                           efs.stype != L2CAP_SERV_NOTRAFIC &&
+                           efs.stype != chan->local_stype)
                                return -ECONNREFUSED;
 
-                       l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
-                                       sizeof(efs), (unsigned long) &efs);
+                       l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, sizeof(efs),
+                                          (unsigned long) &efs);
                        break;
                }
        }
@@ -3235,10 +3440,10 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, voi
                        if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
                                chan->local_msdu = le16_to_cpu(efs.msdu);
                                chan->local_sdu_itime =
-                                               le32_to_cpu(efs.sdu_itime);
+                                       le32_to_cpu(efs.sdu_itime);
                                chan->local_acc_lat = le32_to_cpu(efs.acc_lat);
                                chan->local_flush_to =
-                                               le32_to_cpu(efs.flush_to);
+                                       le32_to_cpu(efs.flush_to);
                        }
                        break;
 
@@ -3253,7 +3458,8 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, voi
        return ptr - data;
 }
 
-static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags)
+static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data,
+                               u16 result, u16 flags)
 {
        struct l2cap_conf_rsp *rsp = data;
        void *ptr = rsp->data;
@@ -3277,14 +3483,13 @@ void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
        rsp.dcid   = cpu_to_le16(chan->scid);
        rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS);
        rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
-       l2cap_send_cmd(conn, chan->ident,
-                               L2CAP_CONN_RSP, sizeof(rsp), &rsp);
+       l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
 
        if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
                return;
 
        l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
-                       l2cap_build_conf_req(chan, buf), buf);
+                      l2cap_build_conf_req(chan, buf), buf);
        chan->num_conf_req++;
 }
 
@@ -3339,7 +3544,8 @@ static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
        }
 }
 
-static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
+static inline int l2cap_command_rej(struct l2cap_conn *conn,
+                                   struct l2cap_cmd_hdr *cmd, u8 *data)
 {
        struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
 
@@ -3347,7 +3553,7 @@ static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hd
                return 0;
 
        if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
-                                       cmd->ident == conn->info_ident) {
+           cmd->ident == conn->info_ident) {
                cancel_delayed_work(&conn->info_timer);
 
                conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
@@ -3359,7 +3565,9 @@ static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hd
        return 0;
 }
 
-static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
+static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn,
+                                       struct l2cap_cmd_hdr *cmd,
+                                       u8 *data, u8 rsp_code, u8 amp_id)
 {
        struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
        struct l2cap_conn_rsp rsp;
@@ -3386,7 +3594,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
 
        /* Check if the ACL is secure enough (if not SDP) */
        if (psm != __constant_cpu_to_le16(L2CAP_PSM_SDP) &&
-                               !hci_conn_check_link_mode(conn->hcon)) {
+           !hci_conn_check_link_mode(conn->hcon)) {
                conn->disc_reason = HCI_ERROR_AUTH_FAILURE;
                result = L2CAP_CR_SEC_BLOCK;
                goto response;
@@ -3410,8 +3618,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
        bacpy(&bt_sk(sk)->dst, conn->dst);
        chan->psm  = psm;
        chan->dcid = scid;
-
-       bt_accept_enqueue(parent, sk);
+       chan->local_amp_id = amp_id;
 
        __l2cap_chan_add(conn, chan);
 
@@ -3427,10 +3634,19 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
                                __l2cap_state_change(chan, BT_CONNECT2);
                                result = L2CAP_CR_PEND;
                                status = L2CAP_CS_AUTHOR_PEND;
-                               parent->sk_data_ready(parent, 0);
+                               chan->ops->defer(chan);
                        } else {
-                               __l2cap_state_change(chan, BT_CONFIG);
-                               result = L2CAP_CR_SUCCESS;
+                               /* Force pending result for AMP controllers.
+                                * The connection will succeed after the
+                                * physical link is up.
+                                */
+                               if (amp_id) {
+                                       __l2cap_state_change(chan, BT_CONNECT2);
+                                       result = L2CAP_CR_PEND;
+                               } else {
+                                       __l2cap_state_change(chan, BT_CONFIG);
+                                       result = L2CAP_CR_SUCCESS;
+                               }
                                status = L2CAP_CS_NO_INFO;
                        }
                } else {
@@ -3453,7 +3669,7 @@ sendresp:
        rsp.dcid   = cpu_to_le16(dcid);
        rsp.result = cpu_to_le16(result);
        rsp.status = cpu_to_le16(status);
-       l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
+       l2cap_send_cmd(conn, cmd->ident, rsp_code, sizeof(rsp), &rsp);
 
        if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
                struct l2cap_info_req info;
@@ -3464,23 +3680,31 @@ sendresp:
 
                schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT);
 
-               l2cap_send_cmd(conn, conn->info_ident,
-                                       L2CAP_INFO_REQ, sizeof(info), &info);
+               l2cap_send_cmd(conn, conn->info_ident, L2CAP_INFO_REQ,
+                              sizeof(info), &info);
        }
 
        if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
-                               result == L2CAP_CR_SUCCESS) {
+           result == L2CAP_CR_SUCCESS) {
                u8 buf[128];
                set_bit(CONF_REQ_SENT, &chan->conf_state);
                l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
-                                       l2cap_build_conf_req(chan, buf), buf);
+                              l2cap_build_conf_req(chan, buf), buf);
                chan->num_conf_req++;
        }
 
+       return chan;
+}
+
+static int l2cap_connect_req(struct l2cap_conn *conn,
+                            struct l2cap_cmd_hdr *cmd, u8 *data)
+{
+       l2cap_connect(conn, cmd, data, L2CAP_CONN_RSP, 0);
        return 0;
 }
 
-static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
+static int l2cap_connect_create_rsp(struct l2cap_conn *conn,
+                                   struct l2cap_cmd_hdr *cmd, u8 *data)
 {
        struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
        u16 scid, dcid, result, status;
@@ -3494,7 +3718,7 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd
        status = __le16_to_cpu(rsp->status);
 
        BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x",
-                                               dcid, scid, result, status);
+              dcid, scid, result, status);
 
        mutex_lock(&conn->chan_lock);
 
@@ -3527,7 +3751,7 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd
                        break;
 
                l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
-                                       l2cap_build_conf_req(chan, req), req);
+                              l2cap_build_conf_req(chan, req), req);
                chan->num_conf_req++;
                break;
 
@@ -3559,7 +3783,25 @@ static inline void set_default_fcs(struct l2cap_chan *chan)
                chan->fcs = L2CAP_FCS_CRC16;
 }
 
-static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
+static void l2cap_send_efs_conf_rsp(struct l2cap_chan *chan, void *data,
+                                   u8 ident, u16 flags)
+{
+       struct l2cap_conn *conn = chan->conn;
+
+       BT_DBG("conn %p chan %p ident %d flags 0x%4.4x", conn, chan, ident,
+              flags);
+
+       clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
+       set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
+
+       l2cap_send_cmd(conn, ident, L2CAP_CONF_RSP,
+                      l2cap_build_conf_rsp(chan, data,
+                                           L2CAP_CONF_SUCCESS, flags), data);
+}
+
+static inline int l2cap_config_req(struct l2cap_conn *conn,
+                                  struct l2cap_cmd_hdr *cmd, u16 cmd_len,
+                                  u8 *data)
 {
        struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
        u16 dcid, flags;
@@ -3584,7 +3826,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
                rej.dcid = cpu_to_le16(chan->dcid);
 
                l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
-                               sizeof(rej), &rej);
+                              sizeof(rej), &rej);
                goto unlock;
        }
 
@@ -3592,8 +3834,8 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
        len = cmd_len - sizeof(*req);
        if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) {
                l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
-                               l2cap_build_conf_rsp(chan, rsp,
-                                       L2CAP_CONF_REJECT, flags), rsp);
+                              l2cap_build_conf_rsp(chan, rsp,
+                              L2CAP_CONF_REJECT, flags), rsp);
                goto unlock;
        }
 
@@ -3604,8 +3846,8 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
        if (flags & L2CAP_CONF_FLAG_CONTINUATION) {
                /* Incomplete config. Send empty response. */
                l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
-                               l2cap_build_conf_rsp(chan, rsp,
-                                       L2CAP_CONF_SUCCESS, flags), rsp);
+                              l2cap_build_conf_rsp(chan, rsp,
+                              L2CAP_CONF_SUCCESS, flags), rsp);
                goto unlock;
        }
 
@@ -3616,6 +3858,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
                goto unlock;
        }
 
+       chan->ident = cmd->ident;
        l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
        chan->num_conf_rsp++;
 
@@ -3643,23 +3886,22 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
        if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
                u8 buf[64];
                l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
-                                       l2cap_build_conf_req(chan, buf), buf);
+                              l2cap_build_conf_req(chan, buf), buf);
                chan->num_conf_req++;
        }
 
        /* Got Conf Rsp PENDING from remote side and asume we sent
           Conf Rsp PENDING in the code above */
        if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) &&
-                       test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
+           test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
 
                /* check compatibility */
 
-               clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
-               set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
-
-               l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
-                                       l2cap_build_conf_rsp(chan, rsp,
-                                       L2CAP_CONF_SUCCESS, flags), rsp);
+               /* Send rsp for BR/EDR channel */
+               if (!chan->ctrl_id)
+                       l2cap_send_efs_conf_rsp(chan, rsp, cmd->ident, flags);
+               else
+                       chan->ident = cmd->ident;
        }
 
 unlock:
@@ -3667,7 +3909,8 @@ unlock:
        return err;
 }
 
-static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
+static inline int l2cap_config_rsp(struct l2cap_conn *conn,
+                                  struct l2cap_cmd_hdr *cmd, u8 *data)
 {
        struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
        u16 scid, flags, result;
@@ -3699,7 +3942,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
                        char buf[64];
 
                        len = l2cap_parse_conf_rsp(chan, rsp->data, len,
-                                                               buf, &result);
+                                                  buf, &result);
                        if (len < 0) {
                                l2cap_send_disconn_req(conn, chan, ECONNRESET);
                                goto done;
@@ -3707,12 +3950,11 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
 
                        /* check compatibility */
 
-                       clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
-                       set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
-
-                       l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
-                                               l2cap_build_conf_rsp(chan, buf,
-                                               L2CAP_CONF_SUCCESS, 0x0000), buf);
+                       if (!chan->ctrl_id)
+                               l2cap_send_efs_conf_rsp(chan, buf, cmd->ident,
+                                                       0);
+                       else
+                               chan->ident = cmd->ident;
                }
                goto done;
 
@@ -3728,14 +3970,14 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
                        /* throw out any old stored conf requests */
                        result = L2CAP_CONF_SUCCESS;
                        len = l2cap_parse_conf_rsp(chan, rsp->data, len,
-                                                               req, &result);
+                                                  req, &result);
                        if (len < 0) {
                                l2cap_send_disconn_req(conn, chan, ECONNRESET);
                                goto done;
                        }
 
                        l2cap_send_cmd(conn, l2cap_get_ident(conn),
-                                               L2CAP_CONF_REQ, len, req);
+                                      L2CAP_CONF_REQ, len, req);
                        chan->num_conf_req++;
                        if (result != L2CAP_CONF_SUCCESS)
                                goto done;
@@ -3773,7 +4015,8 @@ done:
        return err;
 }
 
-static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
+static inline int l2cap_disconnect_req(struct l2cap_conn *conn,
+                                      struct l2cap_cmd_hdr *cmd, u8 *data)
 {
        struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
        struct l2cap_disconn_rsp rsp;
@@ -3819,7 +4062,8 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd
        return 0;
 }
 
-static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
+static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn,
+                                      struct l2cap_cmd_hdr *cmd, u8 *data)
 {
        struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
        u16 dcid, scid;
@@ -3853,7 +4097,8 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd
        return 0;
 }
 
-static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
+static inline int l2cap_information_req(struct l2cap_conn *conn,
+                                       struct l2cap_cmd_hdr *cmd, u8 *data)
 {
        struct l2cap_info_req *req = (struct l2cap_info_req *) data;
        u16 type;
@@ -3870,14 +4115,14 @@ static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cm
                rsp->result = __constant_cpu_to_le16(L2CAP_IR_SUCCESS);
                if (!disable_ertm)
                        feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
-                                                        | L2CAP_FEAT_FCS;
+                               | L2CAP_FEAT_FCS;
                if (enable_hs)
                        feat_mask |= L2CAP_FEAT_EXT_FLOW
-                                               | L2CAP_FEAT_EXT_WINDOW;
+                               | L2CAP_FEAT_EXT_WINDOW;
 
                put_unaligned_le32(feat_mask, rsp->data);
-               l2cap_send_cmd(conn, cmd->ident,
-                                       L2CAP_INFO_RSP, sizeof(buf), buf);
+               l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf),
+                              buf);
        } else if (type == L2CAP_IT_FIXED_CHAN) {
                u8 buf[12];
                struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
@@ -3890,20 +4135,21 @@ static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cm
                rsp->type   = __constant_cpu_to_le16(L2CAP_IT_FIXED_CHAN);
                rsp->result = __constant_cpu_to_le16(L2CAP_IR_SUCCESS);
                memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan));
-               l2cap_send_cmd(conn, cmd->ident,
-                                       L2CAP_INFO_RSP, sizeof(buf), buf);
+               l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf),
+                              buf);
        } else {
                struct l2cap_info_rsp rsp;
                rsp.type   = cpu_to_le16(type);
                rsp.result = __constant_cpu_to_le16(L2CAP_IR_NOTSUPP);
-               l2cap_send_cmd(conn, cmd->ident,
-                                       L2CAP_INFO_RSP, sizeof(rsp), &rsp);
+               l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(rsp),
+                              &rsp);
        }
 
        return 0;
 }
 
-static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
+static inline int l2cap_information_rsp(struct l2cap_conn *conn,
+                                       struct l2cap_cmd_hdr *cmd, u8 *data)
 {
        struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
        u16 type, result;
@@ -3915,7 +4161,7 @@ static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cm
 
        /* L2CAP Info req/rsp are unbound to channels, add extra checks */
        if (cmd->ident != conn->info_ident ||
-                       conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
+           conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
                return 0;
 
        cancel_delayed_work(&conn->info_timer);
@@ -3940,7 +4186,7 @@ static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cm
                        conn->info_ident = l2cap_get_ident(conn);
 
                        l2cap_send_cmd(conn, conn->info_ident,
-                                       L2CAP_INFO_REQ, sizeof(req), &req);
+                                      L2CAP_INFO_REQ, sizeof(req), &req);
                } else {
                        conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
                        conn->info_ident = 0;
@@ -3961,12 +4207,12 @@ static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cm
        return 0;
 }
 
-static inline int l2cap_create_channel_req(struct l2cap_conn *conn,
-                                       struct l2cap_cmd_hdr *cmd, u16 cmd_len,
-                                       void *data)
+static int l2cap_create_channel_req(struct l2cap_conn *conn,
+                                   struct l2cap_cmd_hdr *cmd,
+                                   u16 cmd_len, void *data)
 {
        struct l2cap_create_chan_req *req = data;
-       struct l2cap_create_chan_rsp rsp;
+       struct l2cap_chan *chan;
        u16 psm, scid;
 
        if (cmd_len != sizeof(*req))
@@ -3980,56 +4226,98 @@ static inline int l2cap_create_channel_req(struct l2cap_conn *conn,
 
        BT_DBG("psm 0x%2.2x, scid 0x%4.4x, amp_id %d", psm, scid, req->amp_id);
 
-       /* Placeholder: Always reject */
-       rsp.dcid = 0;
-       rsp.scid = cpu_to_le16(scid);
-       rsp.result = __constant_cpu_to_le16(L2CAP_CR_NO_MEM);
-       rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
+       if (req->amp_id) {
+               struct hci_dev *hdev;
 
-       l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP,
-                      sizeof(rsp), &rsp);
+               /* Validate AMP controller id */
+               hdev = hci_dev_get(req->amp_id);
+               if (!hdev || hdev->dev_type != HCI_AMP ||
+                   !test_bit(HCI_UP, &hdev->flags)) {
+                       struct l2cap_create_chan_rsp rsp;
+
+                       rsp.dcid = 0;
+                       rsp.scid = cpu_to_le16(scid);
+                       rsp.result = __constant_cpu_to_le16(L2CAP_CR_BAD_AMP);
+                       rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
+
+                       l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP,
+                                      sizeof(rsp), &rsp);
+
+                       if (hdev)
+                               hci_dev_put(hdev);
+
+                       return 0;
+               }
+
+               hci_dev_put(hdev);
+       }
+
+       chan = l2cap_connect(conn, cmd, data, L2CAP_CREATE_CHAN_RSP,
+                            req->amp_id);
 
        return 0;
 }
 
-static inline int l2cap_create_channel_rsp(struct l2cap_conn *conn,
-                                       struct l2cap_cmd_hdr *cmd, void *data)
+static void l2cap_send_move_chan_req(struct l2cap_chan *chan, u8 dest_amp_id)
 {
-       BT_DBG("conn %p", conn);
+       struct l2cap_move_chan_req req;
+       u8 ident;
 
-       return l2cap_connect_rsp(conn, cmd, data);
+       BT_DBG("chan %p, dest_amp_id %d", chan, dest_amp_id);
+
+       ident = l2cap_get_ident(chan->conn);
+       chan->ident = ident;
+
+       req.icid = cpu_to_le16(chan->scid);
+       req.dest_amp_id = dest_amp_id;
+
+       l2cap_send_cmd(chan->conn, ident, L2CAP_MOVE_CHAN_REQ, sizeof(req),
+                      &req);
+
+       __set_chan_timer(chan, L2CAP_MOVE_TIMEOUT);
 }
 
-static void l2cap_send_move_chan_rsp(struct l2cap_conn *conn, u8 ident,
-                                    u16 icid, u16 result)
+static void l2cap_send_move_chan_rsp(struct l2cap_chan *chan, u16 result)
 {
        struct l2cap_move_chan_rsp rsp;
 
-       BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result);
+       BT_DBG("chan %p, result 0x%4.4x", chan, result);
 
-       rsp.icid = cpu_to_le16(icid);
+       rsp.icid = cpu_to_le16(chan->dcid);
        rsp.result = cpu_to_le16(result);
 
-       l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_RSP, sizeof(rsp), &rsp);
+       l2cap_send_cmd(chan->conn, chan->ident, L2CAP_MOVE_CHAN_RSP,
+                      sizeof(rsp), &rsp);
 }
 
-static void l2cap_send_move_chan_cfm(struct l2cap_conn *conn,
-                                    struct l2cap_chan *chan,
-                                    u16 icid, u16 result)
+static void l2cap_send_move_chan_cfm(struct l2cap_chan *chan, u16 result)
 {
        struct l2cap_move_chan_cfm cfm;
-       u8 ident;
 
-       BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result);
+       BT_DBG("chan %p, result 0x%4.4x", chan, result);
 
-       ident = l2cap_get_ident(conn);
-       if (chan)
-               chan->ident = ident;
+       chan->ident = l2cap_get_ident(chan->conn);
 
-       cfm.icid = cpu_to_le16(icid);
+       cfm.icid = cpu_to_le16(chan->scid);
        cfm.result = cpu_to_le16(result);
 
-       l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM, sizeof(cfm), &cfm);
+       l2cap_send_cmd(chan->conn, chan->ident, L2CAP_MOVE_CHAN_CFM,
+                      sizeof(cfm), &cfm);
+
+       __set_chan_timer(chan, L2CAP_MOVE_TIMEOUT);
+}
+
+static void l2cap_send_move_chan_cfm_icid(struct l2cap_conn *conn, u16 icid)
+{
+       struct l2cap_move_chan_cfm cfm;
+
+       BT_DBG("conn %p, icid 0x%4.4x", conn, icid);
+
+       cfm.icid = cpu_to_le16(icid);
+       cfm.result = __constant_cpu_to_le16(L2CAP_MC_UNCONFIRMED);
+
+       l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_MOVE_CHAN_CFM,
+                      sizeof(cfm), &cfm);
 }
 
 static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident,
@@ -4043,11 +4331,286 @@ static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident,
        l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp);
 }
 
+static void __release_logical_link(struct l2cap_chan *chan)
+{
+       chan->hs_hchan = NULL;
+       chan->hs_hcon = NULL;
+
+       /* Placeholder - release the logical link */
+}
+
+static void l2cap_logical_fail(struct l2cap_chan *chan)
+{
+       /* Logical link setup failed */
+       if (chan->state != BT_CONNECTED) {
+               /* Create channel failure, disconnect */
+               l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
+               return;
+       }
+
+       switch (chan->move_role) {
+       case L2CAP_MOVE_ROLE_RESPONDER:
+               l2cap_move_done(chan);
+               l2cap_send_move_chan_rsp(chan, L2CAP_MR_NOT_SUPP);
+               break;
+       case L2CAP_MOVE_ROLE_INITIATOR:
+               if (chan->move_state == L2CAP_MOVE_WAIT_LOGICAL_COMP ||
+                   chan->move_state == L2CAP_MOVE_WAIT_LOGICAL_CFM) {
+                       /* Remote has only sent pending or
+                        * success responses, clean up
+                        */
+                       l2cap_move_done(chan);
+               }
+
+               /* Other amp move states imply that the move
+                * has already aborted
+                */
+               l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED);
+               break;
+       }
+}
+
+static void l2cap_logical_finish_create(struct l2cap_chan *chan,
+                                       struct hci_chan *hchan)
+{
+       struct l2cap_conf_rsp rsp;
+       u8 code;
+
+       chan->hs_hcon = hchan->conn;
+       chan->hs_hcon->l2cap_data = chan->conn;
+
+       code = l2cap_build_conf_rsp(chan, &rsp,
+                                   L2CAP_CONF_SUCCESS, 0);
+       l2cap_send_cmd(chan->conn, chan->ident, L2CAP_CONF_RSP, code,
+                      &rsp);
+       set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
+
+       if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
+               int err = 0;
+
+               set_default_fcs(chan);
+
+               err = l2cap_ertm_init(chan);
+               if (err < 0)
+                       l2cap_send_disconn_req(chan->conn, chan, -err);
+               else
+                       l2cap_chan_ready(chan);
+       }
+}
+
+static void l2cap_logical_finish_move(struct l2cap_chan *chan,
+                                     struct hci_chan *hchan)
+{
+       chan->hs_hcon = hchan->conn;
+       chan->hs_hcon->l2cap_data = chan->conn;
+
+       BT_DBG("move_state %d", chan->move_state);
+
+       switch (chan->move_state) {
+       case L2CAP_MOVE_WAIT_LOGICAL_COMP:
+               /* Move confirm will be sent after a success
+                * response is received
+                */
+               chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS;
+               break;
+       case L2CAP_MOVE_WAIT_LOGICAL_CFM:
+               if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
+                       chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY;
+               } else if (chan->move_role == L2CAP_MOVE_ROLE_INITIATOR) {
+                       chan->move_state = L2CAP_MOVE_WAIT_CONFIRM_RSP;
+                       l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED);
+               } else if (chan->move_role == L2CAP_MOVE_ROLE_RESPONDER) {
+                       chan->move_state = L2CAP_MOVE_WAIT_CONFIRM;
+                       l2cap_send_move_chan_rsp(chan, L2CAP_MR_SUCCESS);
+               }
+               break;
+       default:
+               /* Move was not in expected state, free the channel */
+               __release_logical_link(chan);
+
+               chan->move_state = L2CAP_MOVE_STABLE;
+       }
+}
+
+/* Call with chan locked */
+static void l2cap_logical_cfm(struct l2cap_chan *chan, struct hci_chan *hchan,
+                             u8 status)
+{
+       BT_DBG("chan %p, hchan %p, status %d", chan, hchan, status);
+
+       if (status) {
+               l2cap_logical_fail(chan);
+               __release_logical_link(chan);
+               return;
+       }
+
+       if (chan->state != BT_CONNECTED) {
+               /* Ignore logical link if channel is on BR/EDR */
+               if (chan->local_amp_id)
+                       l2cap_logical_finish_create(chan, hchan);
+       } else {
+               l2cap_logical_finish_move(chan, hchan);
+       }
+}
+
+void l2cap_move_start(struct l2cap_chan *chan)
+{
+       BT_DBG("chan %p", chan);
+
+       if (chan->local_amp_id == HCI_BREDR_ID) {
+               if (chan->chan_policy != BT_CHANNEL_POLICY_AMP_PREFERRED)
+                       return;
+               chan->move_role = L2CAP_MOVE_ROLE_INITIATOR;
+               chan->move_state = L2CAP_MOVE_WAIT_PREPARE;
+               /* Placeholder - start physical link setup */
+       } else {
+               chan->move_role = L2CAP_MOVE_ROLE_INITIATOR;
+               chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS;
+               chan->move_id = 0;
+               l2cap_move_setup(chan);
+               l2cap_send_move_chan_req(chan, 0);
+       }
+}
+
+static void l2cap_do_create(struct l2cap_chan *chan, int result,
+                           u8 local_amp_id, u8 remote_amp_id)
+{
+       if (!test_bit(CONF_CONNECT_PEND, &chan->conf_state)) {
+               struct l2cap_conn_rsp rsp;
+               char buf[128];
+               rsp.scid = cpu_to_le16(chan->dcid);
+               rsp.dcid = cpu_to_le16(chan->scid);
+
+               /* Incoming channel on AMP */
+               if (result == L2CAP_CR_SUCCESS) {
+                       /* Send successful response */
+                       rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
+                       rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
+               } else {
+                       /* Send negative response */
+                       rsp.result = cpu_to_le16(L2CAP_CR_NO_MEM);
+                       rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
+               }
+
+               l2cap_send_cmd(chan->conn, chan->ident, L2CAP_CREATE_CHAN_RSP,
+                              sizeof(rsp), &rsp);
+
+               if (result == L2CAP_CR_SUCCESS) {
+                       __l2cap_state_change(chan, BT_CONFIG);
+                       set_bit(CONF_REQ_SENT, &chan->conf_state);
+                       l2cap_send_cmd(chan->conn, l2cap_get_ident(chan->conn),
+                                      L2CAP_CONF_REQ,
+                                      l2cap_build_conf_req(chan, buf), buf);
+                       chan->num_conf_req++;
+               }
+       } else {
+               /* Outgoing channel on AMP */
+               if (result == L2CAP_CR_SUCCESS) {
+                       chan->local_amp_id = local_amp_id;
+                       l2cap_send_create_chan_req(chan, remote_amp_id);
+               } else {
+                       /* Revert to BR/EDR connect */
+                       l2cap_send_conn_req(chan);
+               }
+       }
+}
+
+static void l2cap_do_move_initiate(struct l2cap_chan *chan, u8 local_amp_id,
+                                  u8 remote_amp_id)
+{
+       l2cap_move_setup(chan);
+       chan->move_id = local_amp_id;
+       chan->move_state = L2CAP_MOVE_WAIT_RSP;
+
+       l2cap_send_move_chan_req(chan, remote_amp_id);
+}
+
+static void l2cap_do_move_respond(struct l2cap_chan *chan, int result)
+{
+       struct hci_chan *hchan = NULL;
+
+       /* Placeholder - get hci_chan for logical link */
+
+       if (hchan) {
+               if (hchan->state == BT_CONNECTED) {
+                       /* Logical link is ready to go */
+                       chan->hs_hcon = hchan->conn;
+                       chan->hs_hcon->l2cap_data = chan->conn;
+                       chan->move_state = L2CAP_MOVE_WAIT_CONFIRM;
+                       l2cap_send_move_chan_rsp(chan, L2CAP_MR_SUCCESS);
+
+                       l2cap_logical_cfm(chan, hchan, L2CAP_MR_SUCCESS);
+               } else {
+                       /* Wait for logical link to be ready */
+                       chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM;
+               }
+       } else {
+               /* Logical link not available */
+               l2cap_send_move_chan_rsp(chan, L2CAP_MR_NOT_ALLOWED);
+       }
+}
+
+static void l2cap_do_move_cancel(struct l2cap_chan *chan, int result)
+{
+       if (chan->move_role == L2CAP_MOVE_ROLE_RESPONDER) {
+               u8 rsp_result;
+               if (result == -EINVAL)
+                       rsp_result = L2CAP_MR_BAD_ID;
+               else
+                       rsp_result = L2CAP_MR_NOT_ALLOWED;
+
+               l2cap_send_move_chan_rsp(chan, rsp_result);
+       }
+
+       chan->move_role = L2CAP_MOVE_ROLE_NONE;
+       chan->move_state = L2CAP_MOVE_STABLE;
+
+       /* Restart data transmission */
+       l2cap_ertm_send(chan);
+}
+
+void l2cap_physical_cfm(struct l2cap_chan *chan, int result, u8 local_amp_id,
+                       u8 remote_amp_id)
+{
+       BT_DBG("chan %p, result %d, local_amp_id %d, remote_amp_id %d",
+              chan, result, local_amp_id, remote_amp_id);
+
+       l2cap_chan_lock(chan);
+
+       if (chan->state == BT_DISCONN || chan->state == BT_CLOSED) {
+               l2cap_chan_unlock(chan);
+               return;
+       }
+
+       if (chan->state != BT_CONNECTED) {
+               l2cap_do_create(chan, result, local_amp_id, remote_amp_id);
+       } else if (result != L2CAP_MR_SUCCESS) {
+               l2cap_do_move_cancel(chan, result);
+       } else {
+               switch (chan->move_role) {
+               case L2CAP_MOVE_ROLE_INITIATOR:
+                       l2cap_do_move_initiate(chan, local_amp_id,
+                                              remote_amp_id);
+                       break;
+               case L2CAP_MOVE_ROLE_RESPONDER:
+                       l2cap_do_move_respond(chan, result);
+                       break;
+               default:
+                       l2cap_do_move_cancel(chan, result);
+                       break;
+               }
+       }
+
+       l2cap_chan_unlock(chan);
+}
+
 static inline int l2cap_move_channel_req(struct l2cap_conn *conn,
                                         struct l2cap_cmd_hdr *cmd,
                                         u16 cmd_len, void *data)
 {
        struct l2cap_move_chan_req *req = data;
+       struct l2cap_move_chan_rsp rsp;
+       struct l2cap_chan *chan;
        u16 icid = 0;
        u16 result = L2CAP_MR_NOT_ALLOWED;
 
@@ -4061,15 +4624,206 @@ static inline int l2cap_move_channel_req(struct l2cap_conn *conn,
        if (!enable_hs)
                return -EINVAL;
 
-       /* Placeholder: Always refuse */
-       l2cap_send_move_chan_rsp(conn, cmd->ident, icid, result);
+       chan = l2cap_get_chan_by_dcid(conn, icid);
+       if (!chan) {
+               rsp.icid = cpu_to_le16(icid);
+               rsp.result = __constant_cpu_to_le16(L2CAP_MR_NOT_ALLOWED);
+               l2cap_send_cmd(conn, cmd->ident, L2CAP_MOVE_CHAN_RSP,
+                              sizeof(rsp), &rsp);
+               return 0;
+       }
+
+       chan->ident = cmd->ident;
+
+       if (chan->scid < L2CAP_CID_DYN_START ||
+           chan->chan_policy == BT_CHANNEL_POLICY_BREDR_ONLY ||
+           (chan->mode != L2CAP_MODE_ERTM &&
+            chan->mode != L2CAP_MODE_STREAMING)) {
+               result = L2CAP_MR_NOT_ALLOWED;
+               goto send_move_response;
+       }
+
+       if (chan->local_amp_id == req->dest_amp_id) {
+               result = L2CAP_MR_SAME_ID;
+               goto send_move_response;
+       }
+
+       if (req->dest_amp_id) {
+               struct hci_dev *hdev;
+               hdev = hci_dev_get(req->dest_amp_id);
+               if (!hdev || hdev->dev_type != HCI_AMP ||
+                   !test_bit(HCI_UP, &hdev->flags)) {
+                       if (hdev)
+                               hci_dev_put(hdev);
+
+                       result = L2CAP_MR_BAD_ID;
+                       goto send_move_response;
+               }
+               hci_dev_put(hdev);
+       }
+
+       /* Detect a move collision.  Only send a collision response
+        * if this side has "lost", otherwise proceed with the move.
+        * The winner has the larger bd_addr.
+        */
+       if ((__chan_is_moving(chan) ||
+            chan->move_role != L2CAP_MOVE_ROLE_NONE) &&
+           bacmp(conn->src, conn->dst) > 0) {
+               result = L2CAP_MR_COLLISION;
+               goto send_move_response;
+       }
+
+       chan->move_role = L2CAP_MOVE_ROLE_RESPONDER;
+       l2cap_move_setup(chan);
+       chan->move_id = req->dest_amp_id;
+       icid = chan->dcid;
+
+       if (!req->dest_amp_id) {
+               /* Moving to BR/EDR */
+               if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
+                       chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY;
+                       result = L2CAP_MR_PEND;
+               } else {
+                       chan->move_state = L2CAP_MOVE_WAIT_CONFIRM;
+                       result = L2CAP_MR_SUCCESS;
+               }
+       } else {
+               chan->move_state = L2CAP_MOVE_WAIT_PREPARE;
+               /* Placeholder - uncomment when amp functions are available */
+               /*amp_accept_physical(chan, req->dest_amp_id);*/
+               result = L2CAP_MR_PEND;
+       }
+
+send_move_response:
+       l2cap_send_move_chan_rsp(chan, result);
+
+       l2cap_chan_unlock(chan);
 
        return 0;
 }
 
-static inline int l2cap_move_channel_rsp(struct l2cap_conn *conn,
-                                        struct l2cap_cmd_hdr *cmd,
-                                        u16 cmd_len, void *data)
+static void l2cap_move_continue(struct l2cap_conn *conn, u16 icid, u16 result)
+{
+       struct l2cap_chan *chan;
+       struct hci_chan *hchan = NULL;
+
+       chan = l2cap_get_chan_by_scid(conn, icid);
+       if (!chan) {
+               l2cap_send_move_chan_cfm_icid(conn, icid);
+               return;
+       }
+
+       __clear_chan_timer(chan);
+       if (result == L2CAP_MR_PEND)
+               __set_chan_timer(chan, L2CAP_MOVE_ERTX_TIMEOUT);
+
+       switch (chan->move_state) {
+       case L2CAP_MOVE_WAIT_LOGICAL_COMP:
+               /* Move confirm will be sent when logical link
+                * is complete.
+                */
+               chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM;
+               break;
+       case L2CAP_MOVE_WAIT_RSP_SUCCESS:
+               if (result == L2CAP_MR_PEND) {
+                       break;
+               } else if (test_bit(CONN_LOCAL_BUSY,
+                                   &chan->conn_state)) {
+                       chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY;
+               } else {
+                       /* Logical link is up or moving to BR/EDR,
+                        * proceed with move
+                        */
+                       chan->move_state = L2CAP_MOVE_WAIT_CONFIRM_RSP;
+                       l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED);
+               }
+               break;
+       case L2CAP_MOVE_WAIT_RSP:
+               /* Moving to AMP */
+               if (result == L2CAP_MR_SUCCESS) {
+                       /* Remote is ready, send confirm immediately
+                        * after logical link is ready
+                        */
+                       chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM;
+               } else {
+                       /* Both logical link and move success
+                        * are required to confirm
+                        */
+                       chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_COMP;
+               }
+
+               /* Placeholder - get hci_chan for logical link */
+               if (!hchan) {
+                       /* Logical link not available */
+                       l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED);
+                       break;
+               }
+
+               /* If the logical link is not yet connected, do not
+                * send confirmation.
+                */
+               if (hchan->state != BT_CONNECTED)
+                       break;
+
+               /* Logical link is already ready to go */
+
+               chan->hs_hcon = hchan->conn;
+               chan->hs_hcon->l2cap_data = chan->conn;
+
+               if (result == L2CAP_MR_SUCCESS) {
+                       /* Can confirm now */
+                       l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED);
+               } else {
+                       /* Now only need move success
+                        * to confirm
+                        */
+                       chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS;
+               }
+
+               l2cap_logical_cfm(chan, hchan, L2CAP_MR_SUCCESS);
+               break;
+       default:
+               /* Any other amp move state means the move failed. */
+               chan->move_id = chan->local_amp_id;
+               l2cap_move_done(chan);
+               l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED);
+       }
+
+       l2cap_chan_unlock(chan);
+}
+
+static void l2cap_move_fail(struct l2cap_conn *conn, u8 ident, u16 icid,
+                           u16 result)
+{
+       struct l2cap_chan *chan;
+
+       chan = l2cap_get_chan_by_ident(conn, ident);
+       if (!chan) {
+               /* Could not locate channel, icid is best guess */
+               l2cap_send_move_chan_cfm_icid(conn, icid);
+               return;
+       }
+
+       __clear_chan_timer(chan);
+
+       if (chan->move_role == L2CAP_MOVE_ROLE_INITIATOR) {
+               if (result == L2CAP_MR_COLLISION) {
+                       chan->move_role = L2CAP_MOVE_ROLE_RESPONDER;
+               } else {
+                       /* Cleanup - cancel move */
+                       chan->move_id = chan->local_amp_id;
+                       l2cap_move_done(chan);
+               }
+       }
+
+       l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED);
+
+       l2cap_chan_unlock(chan);
+}
+
+static int l2cap_move_channel_rsp(struct l2cap_conn *conn,
+                                 struct l2cap_cmd_hdr *cmd,
+                                 u16 cmd_len, void *data)
 {
        struct l2cap_move_chan_rsp *rsp = data;
        u16 icid, result;
@@ -4082,17 +4836,20 @@ static inline int l2cap_move_channel_rsp(struct l2cap_conn *conn,
 
        BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result);
 
-       /* Placeholder: Always unconfirmed */
-       l2cap_send_move_chan_cfm(conn, NULL, icid, L2CAP_MC_UNCONFIRMED);
+       if (result == L2CAP_MR_SUCCESS || result == L2CAP_MR_PEND)
+               l2cap_move_continue(conn, icid, result);
+       else
+               l2cap_move_fail(conn, cmd->ident, icid, result);
 
        return 0;
 }
 
-static inline int l2cap_move_channel_confirm(struct l2cap_conn *conn,
-                                            struct l2cap_cmd_hdr *cmd,
-                                            u16 cmd_len, void *data)
+static int l2cap_move_channel_confirm(struct l2cap_conn *conn,
+                                     struct l2cap_cmd_hdr *cmd,
+                                     u16 cmd_len, void *data)
 {
        struct l2cap_move_chan_cfm *cfm = data;
+       struct l2cap_chan *chan;
        u16 icid, result;
 
        if (cmd_len != sizeof(*cfm))
@@ -4103,8 +4860,29 @@ static inline int l2cap_move_channel_confirm(struct l2cap_conn *conn,
 
        BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result);
 
+       chan = l2cap_get_chan_by_dcid(conn, icid);
+       if (!chan) {
+               /* Spec requires a response even if the icid was not found */
+               l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid);
+               return 0;
+       }
+
+       if (chan->move_state == L2CAP_MOVE_WAIT_CONFIRM) {
+               if (result == L2CAP_MC_CONFIRMED) {
+                       chan->local_amp_id = chan->move_id;
+                       if (!chan->local_amp_id)
+                               __release_logical_link(chan);
+               } else {
+                       chan->move_id = chan->local_amp_id;
+               }
+
+               l2cap_move_done(chan);
+       }
+
        l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid);
 
+       l2cap_chan_unlock(chan);
+
        return 0;
 }
 
@@ -4113,6 +4891,7 @@ static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn,
                                                 u16 cmd_len, void *data)
 {
        struct l2cap_move_chan_cfm_rsp *rsp = data;
+       struct l2cap_chan *chan;
        u16 icid;
 
        if (cmd_len != sizeof(*rsp))
@@ -4122,11 +4901,28 @@ static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn,
 
        BT_DBG("icid 0x%4.4x", icid);
 
+       chan = l2cap_get_chan_by_scid(conn, icid);
+       if (!chan)
+               return 0;
+
+       __clear_chan_timer(chan);
+
+       if (chan->move_state == L2CAP_MOVE_WAIT_CONFIRM_RSP) {
+               chan->local_amp_id = chan->move_id;
+
+               if (!chan->local_amp_id && chan->hs_hchan)
+                       __release_logical_link(chan);
+
+               l2cap_move_done(chan);
+       }
+
+       l2cap_chan_unlock(chan);
+
        return 0;
 }
 
 static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
-                                                       u16 to_multiplier)
+                                        u16 to_multiplier)
 {
        u16 max_latency;
 
@@ -4147,7 +4943,8 @@ static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
 }
 
 static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
-                                       struct l2cap_cmd_hdr *cmd, u8 *data)
+                                             struct l2cap_cmd_hdr *cmd,
+                                             u8 *data)
 {
        struct hci_conn *hcon = conn->hcon;
        struct l2cap_conn_param_update_req *req;
@@ -4169,7 +4966,7 @@ static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
        to_multiplier   = __le16_to_cpu(req->to_multiplier);
 
        BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
-                                               min, max, latency, to_multiplier);
+              min, max, latency, to_multiplier);
 
        memset(&rsp, 0, sizeof(rsp));
 
@@ -4180,7 +4977,7 @@ static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
                rsp.result = __constant_cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
 
        l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
-                                                       sizeof(rsp), &rsp);
+                      sizeof(rsp), &rsp);
 
        if (!err)
                hci_le_conn_update(hcon, min, max, latency, to_multiplier);
@@ -4189,7 +4986,8 @@ static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
 }
 
 static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
-                       struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
+                                     struct l2cap_cmd_hdr *cmd, u16 cmd_len,
+                                     u8 *data)
 {
        int err = 0;
 
@@ -4203,7 +5001,8 @@ static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
                break;
 
        case L2CAP_CONN_RSP:
-               err = l2cap_connect_rsp(conn, cmd, data);
+       case L2CAP_CREATE_CHAN_RSP:
+               err = l2cap_connect_create_rsp(conn, cmd, data);
                break;
 
        case L2CAP_CONF_REQ:
@@ -4241,10 +5040,6 @@ static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
                err = l2cap_create_channel_req(conn, cmd, cmd_len, data);
                break;
 
-       case L2CAP_CREATE_CHAN_RSP:
-               err = l2cap_create_channel_rsp(conn, cmd, data);
-               break;
-
        case L2CAP_MOVE_CHAN_REQ:
                err = l2cap_move_channel_req(conn, cmd, cmd_len, data);
                break;
@@ -4271,7 +5066,7 @@ static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
 }
 
 static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
-                                       struct l2cap_cmd_hdr *cmd, u8 *data)
+                                  struct l2cap_cmd_hdr *cmd, u8 *data)
 {
        switch (cmd->code) {
        case L2CAP_COMMAND_REJ:
@@ -4290,7 +5085,7 @@ static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
 }
 
 static inline void l2cap_sig_channel(struct l2cap_conn *conn,
-                                                       struct sk_buff *skb)
+                                    struct sk_buff *skb)
 {
        u8 *data = skb->data;
        int len = skb->len;
@@ -4307,7 +5102,8 @@ static inline void l2cap_sig_channel(struct l2cap_conn *conn,
 
                cmd_len = le16_to_cpu(cmd.len);
 
-               BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd.code, cmd_len, cmd.ident);
+               BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd.code, cmd_len,
+                      cmd.ident);
 
                if (cmd_len > len || !cmd.ident) {
                        BT_DBG("corrupted command");
@@ -4326,7 +5122,8 @@ static inline void l2cap_sig_channel(struct l2cap_conn *conn,
 
                        /* FIXME: Map err to a valid reason */
                        rej.reason = __constant_cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
-                       l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
+                       l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ,
+                                      sizeof(rej), &rej);
                }
 
                data += cmd_len;
@@ -4391,8 +5188,8 @@ static void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
        }
 }
 
-static void append_skb_frag(struct sk_buff *skb,
-                       struct sk_buff *new_frag, struct sk_buff **last_frag)
+static void append_skb_frag(struct sk_buff *skb, struct sk_buff *new_frag,
+                           struct sk_buff **last_frag)
 {
        /* skb->len reflects data in skb as well as all fragments
         * skb->data_len reflects only data in fragments
@@ -4492,6 +5289,12 @@ static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb,
        return err;
 }
 
+static int l2cap_resegment(struct l2cap_chan *chan)
+{
+       /* Placeholder */
+       return 0;
+}
+
 void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
 {
        u8 event;
@@ -4641,7 +5444,7 @@ static u8 l2cap_classify_txseq(struct l2cap_chan *chan, u16 txseq)
 
        if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) {
                if (__seq_offset(chan, txseq, chan->last_acked_seq) >=
-                                                               chan->tx_win) {
+                   chan->tx_win) {
                        /* See notes below regarding "double poll" and
                         * invalid packets.
                         */
@@ -4682,8 +5485,7 @@ static u8 l2cap_classify_txseq(struct l2cap_chan *chan, u16 txseq)
        }
 
        if (__seq_offset(chan, txseq, chan->last_acked_seq) <
-               __seq_offset(chan, chan->expected_tx_seq,
-                            chan->last_acked_seq)){
+           __seq_offset(chan, chan->expected_tx_seq, chan->last_acked_seq)) {
                BT_DBG("Duplicate - expected_tx_seq later than txseq");
                return L2CAP_TXSEQ_DUPLICATE;
        }
@@ -4808,8 +5610,8 @@ static int l2cap_rx_state_recv(struct l2cap_chan *chan,
                if (control->final) {
                        clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
 
-                       if (!test_and_clear_bit(CONN_REJ_ACT,
-                                               &chan->conn_state)) {
+                       if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state) &&
+                           !__chan_is_moving(chan)) {
                                control->final = 0;
                                l2cap_retransmit_all(chan, control);
                        }
@@ -4998,6 +5800,96 @@ static int l2cap_rx_state_srej_sent(struct l2cap_chan *chan,
        return err;
 }
 
+static int l2cap_finish_move(struct l2cap_chan *chan)
+{
+       BT_DBG("chan %p", chan);
+
+       chan->rx_state = L2CAP_RX_STATE_RECV;
+
+       if (chan->hs_hcon)
+               chan->conn->mtu = chan->hs_hcon->hdev->block_mtu;
+       else
+               chan->conn->mtu = chan->conn->hcon->hdev->acl_mtu;
+
+       return l2cap_resegment(chan);
+}
+
+static int l2cap_rx_state_wait_p(struct l2cap_chan *chan,
+                                struct l2cap_ctrl *control,
+                                struct sk_buff *skb, u8 event)
+{
+       int err;
+
+       BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb,
+              event);
+
+       if (!control->poll)
+               return -EPROTO;
+
+       l2cap_process_reqseq(chan, control->reqseq);
+
+       if (!skb_queue_empty(&chan->tx_q))
+               chan->tx_send_head = skb_peek(&chan->tx_q);
+       else
+               chan->tx_send_head = NULL;
+
+       /* Rewind next_tx_seq to the point expected
+        * by the receiver.
+        */
+       chan->next_tx_seq = control->reqseq;
+       chan->unacked_frames = 0;
+
+       err = l2cap_finish_move(chan);
+       if (err)
+               return err;
+
+       set_bit(CONN_SEND_FBIT, &chan->conn_state);
+       l2cap_send_i_or_rr_or_rnr(chan);
+
+       if (event == L2CAP_EV_RECV_IFRAME)
+               return -EPROTO;
+
+       return l2cap_rx_state_recv(chan, control, NULL, event);
+}
+
+static int l2cap_rx_state_wait_f(struct l2cap_chan *chan,
+                                struct l2cap_ctrl *control,
+                                struct sk_buff *skb, u8 event)
+{
+       int err;
+
+       if (!control->final)
+               return -EPROTO;
+
+       clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
+
+       chan->rx_state = L2CAP_RX_STATE_RECV;
+       l2cap_process_reqseq(chan, control->reqseq);
+
+       if (!skb_queue_empty(&chan->tx_q))
+               chan->tx_send_head = skb_peek(&chan->tx_q);
+       else
+               chan->tx_send_head = NULL;
+
+       /* Rewind next_tx_seq to the point expected
+        * by the receiver.
+        */
+       chan->next_tx_seq = control->reqseq;
+       chan->unacked_frames = 0;
+
+       if (chan->hs_hcon)
+               chan->conn->mtu = chan->hs_hcon->hdev->block_mtu;
+       else
+               chan->conn->mtu = chan->conn->hcon->hdev->acl_mtu;
+
+       err = l2cap_resegment(chan);
+
+       if (!err)
+               err = l2cap_rx_state_recv(chan, control, skb, event);
+
+       return err;
+}
+
 static bool __valid_reqseq(struct l2cap_chan *chan, u16 reqseq)
 {
        /* Make sure reqseq is for a packet that has been sent but not acked */
@@ -5024,6 +5916,12 @@ static int l2cap_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
                        err = l2cap_rx_state_srej_sent(chan, control, skb,
                                                       event);
                        break;
+               case L2CAP_RX_STATE_WAIT_P:
+                       err = l2cap_rx_state_wait_p(chan, control, skb, event);
+                       break;
+               case L2CAP_RX_STATE_WAIT_F:
+                       err = l2cap_rx_state_wait_f(chan, control, skb, event);
+                       break;
                default:
                        /* shut it down */
                        break;
@@ -5323,7 +6221,7 @@ int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
        int exact = 0, lm1 = 0, lm2 = 0;
        struct l2cap_chan *c;
 
-       BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
+       BT_DBG("hdev %s, bdaddr %pMR", hdev->name, bdaddr);
 
        /* Find listening sockets and check their link_mode */
        read_lock(&chan_list_lock);
@@ -5353,7 +6251,7 @@ void l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
 {
        struct l2cap_conn *conn;
 
-       BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
+       BT_DBG("hcon %p bdaddr %pMR status %d", hcon, &hcon->dst, status);
 
        if (!status) {
                conn = l2cap_conn_add(hcon, status);
@@ -5443,7 +6341,7 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
                }
 
                if (!status && (chan->state == BT_CONNECTED ||
-                                               chan->state == BT_CONFIG)) {
+                               chan->state == BT_CONFIG)) {
                        struct sock *sk = chan->sk;
 
                        clear_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags);
@@ -5456,7 +6354,7 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
 
                if (chan->state == BT_CONNECT) {
                        if (!status) {
-                               l2cap_send_conn_req(chan);
+                               l2cap_start_connection(chan);
                        } else {
                                __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
                        }
@@ -5470,11 +6368,9 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
                        if (!status) {
                                if (test_bit(BT_SK_DEFER_SETUP,
                                             &bt_sk(sk)->flags)) {
-                                       struct sock *parent = bt_sk(sk)->parent;
                                        res = L2CAP_CR_PEND;
                                        stat = L2CAP_CS_AUTHOR_PEND;
-                                       if (parent)
-                                               parent->sk_data_ready(parent, 0);
+                                       chan->ops->defer(chan);
                                } else {
                                        __l2cap_state_change(chan, BT_CONFIG);
                                        res = L2CAP_CR_SUCCESS;
@@ -5494,7 +6390,7 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
                        rsp.result = cpu_to_le16(res);
                        rsp.status = cpu_to_le16(stat);
                        l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
-                                                       sizeof(rsp), &rsp);
+                                      sizeof(rsp), &rsp);
 
                        if (!test_bit(CONF_REQ_SENT, &chan->conf_state) &&
                            res == L2CAP_CR_SUCCESS) {
@@ -5519,6 +6415,12 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
 int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
 {
        struct l2cap_conn *conn = hcon->l2cap_data;
+       struct l2cap_hdr *hdr;
+       int len;
+
+       /* For AMP controller do not create l2cap conn */
+       if (!conn && hcon->hdev->dev_type != HCI_BREDR)
+               goto drop;
 
        if (!conn)
                conn = l2cap_conn_add(hcon, 0);
@@ -5528,10 +6430,10 @@ int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
 
        BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
 
-       if (!(flags & ACL_CONT)) {
-               struct l2cap_hdr *hdr;
-               int len;
-
+       switch (flags) {
+       case ACL_START:
+       case ACL_START_NO_FLUSH:
+       case ACL_COMPLETE:
                if (conn->rx_len) {
                        BT_ERR("Unexpected start frame (len %d)", skb->len);
                        kfree_skb(conn->rx_skb);
@@ -5560,20 +6462,22 @@ int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
 
                if (skb->len > len) {
                        BT_ERR("Frame is too long (len %d, expected len %d)",
-                               skb->len, len);
+                              skb->len, len);
                        l2cap_conn_unreliable(conn, ECOMM);
                        goto drop;
                }
 
                /* Allocate skb for the complete frame (with header) */
-               conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
+               conn->rx_skb = bt_skb_alloc(len, GFP_KERNEL);
                if (!conn->rx_skb)
                        goto drop;
 
                skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
-                                                               skb->len);
+                                         skb->len);
                conn->rx_len = len - skb->len;
-       } else {
+               break;
+
+       case ACL_CONT:
                BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
 
                if (!conn->rx_len) {
@@ -5584,7 +6488,7 @@ int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
 
                if (skb->len > conn->rx_len) {
                        BT_ERR("Fragment is too long (len %d, expected %d)",
-                                       skb->len, conn->rx_len);
+                              skb->len, conn->rx_len);
                        kfree_skb(conn->rx_skb);
                        conn->rx_skb = NULL;
                        conn->rx_len = 0;
@@ -5593,7 +6497,7 @@ int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
                }
 
                skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
-                                                               skb->len);
+                                         skb->len);
                conn->rx_len -= skb->len;
 
                if (!conn->rx_len) {
@@ -5601,6 +6505,7 @@ int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
                        l2cap_recv_frame(conn, conn->rx_skb);
                        conn->rx_skb = NULL;
                }
+               break;
        }
 
 drop:
@@ -5617,12 +6522,11 @@ static int l2cap_debugfs_show(struct seq_file *f, void *p)
        list_for_each_entry(c, &chan_list, global_l) {
                struct sock *sk = c->sk;
 
-               seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n",
-                                       batostr(&bt_sk(sk)->src),
-                                       batostr(&bt_sk(sk)->dst),
-                                       c->state, __le16_to_cpu(c->psm),
-                                       c->scid, c->dcid, c->imtu, c->omtu,
-                                       c->sec_level, c->mode);
+               seq_printf(f, "%pMR %pMR %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n",
+                          &bt_sk(sk)->src, &bt_sk(sk)->dst,
+                          c->state, __le16_to_cpu(c->psm),
+                          c->scid, c->dcid, c->imtu, c->omtu,
+                          c->sec_level, c->mode);
        }
 
        read_unlock(&chan_list_lock);
@@ -5653,8 +6557,8 @@ int __init l2cap_init(void)
                return err;
 
        if (bt_debugfs) {
-               l2cap_debugfs = debugfs_create_file("l2cap", 0444,
-                                       bt_debugfs, NULL, &l2cap_debugfs_fops);
+               l2cap_debugfs = debugfs_create_file("l2cap", 0444, bt_debugfs,
+                                                   NULL, &l2cap_debugfs_fops);
                if (!l2cap_debugfs)
                        BT_ERR("Failed to create L2CAP debug file");
        }
index 083f2bf065d4d788e59702d29b71b39aaa7bd688..1bcfb8422fdcf55096e9b4131e07eab63d5c365c 100644 (file)
@@ -40,7 +40,8 @@ static struct bt_sock_list l2cap_sk_list = {
 
 static const struct proto_ops l2cap_sock_ops;
 static void l2cap_sock_init(struct sock *sk, struct sock *parent);
-static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio);
+static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock,
+                                    int proto, gfp_t prio);
 
 static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
 {
@@ -106,7 +107,8 @@ done:
        return err;
 }
 
-static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int alen, int flags)
+static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr,
+                             int alen, int flags)
 {
        struct sock *sk = sock->sk;
        struct l2cap_chan *chan = l2cap_pi(sk)->chan;
@@ -134,7 +136,7 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al
        lock_sock(sk);
 
        err = bt_sock_wait_state(sk, BT_CONNECTED,
-                       sock_sndtimeo(sk, flags & O_NONBLOCK));
+                                sock_sndtimeo(sk, flags & O_NONBLOCK));
 
        release_sock(sk);
 
@@ -185,7 +187,8 @@ done:
        return err;
 }
 
-static int l2cap_sock_accept(struct socket *sock, struct socket *newsock, int flags)
+static int l2cap_sock_accept(struct socket *sock, struct socket *newsock,
+                            int flags)
 {
        DECLARE_WAITQUEUE(wait, current);
        struct sock *sk = sock->sk, *nsk;
@@ -241,7 +244,8 @@ done:
        return err;
 }
 
-static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *len, int peer)
+static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr,
+                             int *len, int peer)
 {
        struct sockaddr_l2 *la = (struct sockaddr_l2 *) addr;
        struct sock *sk = sock->sk;
@@ -266,7 +270,8 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *l
        return 0;
 }
 
-static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __user *optval, int __user *optlen)
+static int l2cap_sock_getsockopt_old(struct socket *sock, int optname,
+                                    char __user *optval, int __user *optlen)
 {
        struct sock *sk = sock->sk;
        struct l2cap_chan *chan = l2cap_pi(sk)->chan;
@@ -309,7 +314,7 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __us
                        break;
                case BT_SECURITY_HIGH:
                        opt = L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT |
-                                                       L2CAP_LM_SECURE;
+                             L2CAP_LM_SECURE;
                        break;
                default:
                        opt = 0;
@@ -353,7 +358,8 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __us
        return err;
 }
 
-static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen)
+static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname,
+                                char __user *optval, int __user *optlen)
 {
        struct sock *sk = sock->sk;
        struct l2cap_chan *chan = l2cap_pi(sk)->chan;
@@ -377,19 +383,20 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch
        switch (optname) {
        case BT_SECURITY:
                if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED &&
-                                       chan->chan_type != L2CAP_CHAN_RAW) {
+                   chan->chan_type != L2CAP_CHAN_RAW) {
                        err = -EINVAL;
                        break;
                }
 
                memset(&sec, 0, sizeof(sec));
-               if (chan->conn)
+               if (chan->conn) {
                        sec.level = chan->conn->hcon->sec_level;
-               else
-                       sec.level = chan->sec_level;
 
-               if (sk->sk_state == BT_CONNECTED)
-                       sec.key_size = chan->conn->hcon->enc_key_size;
+                       if (sk->sk_state == BT_CONNECTED)
+                               sec.key_size = chan->conn->hcon->enc_key_size;
+               } else {
+                       sec.level = chan->sec_level;
+               }
 
                len = min_t(unsigned int, len, sizeof(sec));
                if (copy_to_user(optval, (char *) &sec, len))
@@ -411,14 +418,14 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch
 
        case BT_FLUSHABLE:
                if (put_user(test_bit(FLAG_FLUSHABLE, &chan->flags),
-                                               (u32 __user *) optval))
+                            (u32 __user *) optval))
                        err = -EFAULT;
 
                break;
 
        case BT_POWER:
                if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM
-                               && sk->sk_type != SOCK_RAW) {
+                   && sk->sk_type != SOCK_RAW) {
                        err = -EINVAL;
                        break;
                }
@@ -466,7 +473,8 @@ static bool l2cap_valid_mtu(struct l2cap_chan *chan, u16 mtu)
        return true;
 }
 
-static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __user *optval, unsigned int optlen)
+static int l2cap_sock_setsockopt_old(struct socket *sock, int optname,
+                                    char __user *optval, unsigned int optlen)
 {
        struct sock *sk = sock->sk;
        struct l2cap_chan *chan = l2cap_pi(sk)->chan;
@@ -529,6 +537,7 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us
                chan->fcs  = opts.fcs;
                chan->max_tx = opts.max_tx;
                chan->tx_win = opts.txwin_size;
+               chan->flush_to = opts.flush_to;
                break;
 
        case L2CAP_LM:
@@ -564,7 +573,8 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us
        return err;
 }
 
-static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen)
+static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
+                                char __user *optval, unsigned int optlen)
 {
        struct sock *sk = sock->sk;
        struct l2cap_chan *chan = l2cap_pi(sk)->chan;
@@ -587,7 +597,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
        switch (optname) {
        case BT_SECURITY:
                if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED &&
-                                       chan->chan_type != L2CAP_CHAN_RAW) {
+                   chan->chan_type != L2CAP_CHAN_RAW) {
                        err = -EINVAL;
                        break;
                }
@@ -601,7 +611,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
                }
 
                if (sec.level < BT_SECURITY_LOW ||
-                                       sec.level > BT_SECURITY_HIGH) {
+                   sec.level > BT_SECURITY_HIGH) {
                        err = -EINVAL;
                        break;
                }
@@ -627,7 +637,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
 
                /* or for ACL link */
                } else if ((sk->sk_state == BT_CONNECT2 &&
-                          test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) ||
+                           test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) ||
                           sk->sk_state == BT_CONNECTED) {
                        if (!l2cap_chan_check_security(chan))
                                set_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags);
@@ -684,7 +694,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
 
        case BT_POWER:
                if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED &&
-                                       chan->chan_type != L2CAP_CHAN_RAW) {
+                   chan->chan_type != L2CAP_CHAN_RAW) {
                        err = -EINVAL;
                        break;
                }
@@ -720,12 +730,17 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
                }
 
                if (chan->mode != L2CAP_MODE_ERTM &&
-                               chan->mode != L2CAP_MODE_STREAMING) {
+                   chan->mode != L2CAP_MODE_STREAMING) {
                        err = -EOPNOTSUPP;
                        break;
                }
 
                chan->chan_policy = (u8) opt;
+
+               if (sk->sk_state == BT_CONNECTED &&
+                   chan->move_role == L2CAP_MOVE_ROLE_NONE)
+                       l2cap_move_start(chan);
+
                break;
 
        default:
@@ -737,7 +752,8 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
        return err;
 }
 
-static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len)
+static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
+                             struct msghdr *msg, size_t len)
 {
        struct sock *sk = sock->sk;
        struct l2cap_chan *chan = l2cap_pi(sk)->chan;
@@ -762,7 +778,8 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms
        return err;
 }
 
-static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len, int flags)
+static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
+                             struct msghdr *msg, size_t len, int flags)
 {
        struct sock *sk = sock->sk;
        struct l2cap_pinfo *pi = l2cap_pi(sk);
@@ -866,7 +883,7 @@ static int l2cap_sock_shutdown(struct socket *sock, int how)
 
                if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime)
                        err = bt_sock_wait_state(sk, BT_CLOSED,
-                                                       sk->sk_lingertime);
+                                                sk->sk_lingertime);
        }
 
        if (!err && sk->sk_err)
@@ -930,7 +947,7 @@ static struct l2cap_chan *l2cap_sock_new_connection_cb(struct l2cap_chan *chan)
        }
 
        sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP,
-                                                               GFP_ATOMIC);
+                             GFP_ATOMIC);
        if (!sk)
                return NULL;
 
@@ -938,6 +955,8 @@ static struct l2cap_chan *l2cap_sock_new_connection_cb(struct l2cap_chan *chan)
 
        l2cap_sock_init(sk, parent);
 
+       bt_accept_enqueue(parent, sk);
+
        return l2cap_pi(sk)->chan;
 }
 
@@ -1068,6 +1087,15 @@ static void l2cap_sock_ready_cb(struct l2cap_chan *chan)
        release_sock(sk);
 }
 
+static void l2cap_sock_defer_cb(struct l2cap_chan *chan)
+{
+       struct sock *sk = chan->data;
+       struct sock *parent = bt_sk(sk)->parent;
+
+       if (parent)
+               parent->sk_data_ready(parent, 0);
+}
+
 static struct l2cap_ops l2cap_chan_ops = {
        .name           = "L2CAP Socket Interface",
        .new_connection = l2cap_sock_new_connection_cb,
@@ -1076,6 +1104,7 @@ static struct l2cap_ops l2cap_chan_ops = {
        .teardown       = l2cap_sock_teardown_cb,
        .state_change   = l2cap_sock_state_change_cb,
        .ready          = l2cap_sock_ready_cb,
+       .defer          = l2cap_sock_defer_cb,
        .alloc_skb      = l2cap_sock_alloc_skb_cb,
 };
 
@@ -1083,7 +1112,8 @@ static void l2cap_sock_destruct(struct sock *sk)
 {
        BT_DBG("sk %p", sk);
 
-       l2cap_chan_put(l2cap_pi(sk)->chan);
+       if (l2cap_pi(sk)->chan)
+               l2cap_chan_put(l2cap_pi(sk)->chan);
        if (l2cap_pi(sk)->rx_busy_skb) {
                kfree_skb(l2cap_pi(sk)->rx_busy_skb);
                l2cap_pi(sk)->rx_busy_skb = NULL;
@@ -1159,7 +1189,8 @@ static struct proto l2cap_proto = {
        .obj_size       = sizeof(struct l2cap_pinfo)
 };
 
-static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio)
+static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock,
+                                    int proto, gfp_t prio)
 {
        struct sock *sk;
        struct l2cap_chan *chan;
@@ -1204,7 +1235,7 @@ static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol,
        sock->state = SS_UNCONNECTED;
 
        if (sock->type != SOCK_SEQPACKET && sock->type != SOCK_STREAM &&
-                       sock->type != SOCK_DGRAM && sock->type != SOCK_RAW)
+           sock->type != SOCK_DGRAM && sock->type != SOCK_RAW)
                return -ESOCKTNOSUPPORT;
 
        if (sock->type == SOCK_RAW && !kern && !capable(CAP_NET_RAW))
@@ -1261,7 +1292,8 @@ int __init l2cap_init_sockets(void)
                goto error;
        }
 
-       err = bt_procfs_init(THIS_MODULE, &init_net, "l2cap", &l2cap_sk_list, NULL);
+       err = bt_procfs_init(THIS_MODULE, &init_net, "l2cap", &l2cap_sk_list,
+                            NULL);
        if (err < 0) {
                BT_ERR("Failed to create L2CAP proc file");
                bt_sock_unregister(BTPROTO_L2CAP);
index e1c97527e16ca352d4e55016b3a1f70b3e40d5b6..b3fbc73516c415ee1654eb6f2aa38d5e390fb00b 100644 (file)
@@ -41,20 +41,6 @@ void baswap(bdaddr_t *dst, bdaddr_t *src)
 }
 EXPORT_SYMBOL(baswap);
 
-char *batostr(bdaddr_t *ba)
-{
-       static char str[2][18];
-       static int i = 1;
-
-       i ^= 1;
-       sprintf(str[i], "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
-               ba->b[5], ba->b[4], ba->b[3],
-               ba->b[2], ba->b[1], ba->b[0]);
-
-       return str[i];
-}
-EXPORT_SYMBOL(batostr);
-
 /* Bluetooth error codes to Unix errno mapping */
 int bt_to_errno(__u16 code)
 {
index aa2ea0a8142cc0d6c7378ced06be1257b2f846d7..585654bd250f52264f6706a612a4ae3a41142e26 100644 (file)
@@ -376,15 +376,15 @@ static u32 get_supported_settings(struct hci_dev *hdev)
        u32 settings = 0;
 
        settings |= MGMT_SETTING_POWERED;
-       settings |= MGMT_SETTING_CONNECTABLE;
-       settings |= MGMT_SETTING_FAST_CONNECTABLE;
-       settings |= MGMT_SETTING_DISCOVERABLE;
        settings |= MGMT_SETTING_PAIRABLE;
 
        if (lmp_ssp_capable(hdev))
                settings |= MGMT_SETTING_SSP;
 
        if (lmp_bredr_capable(hdev)) {
+               settings |= MGMT_SETTING_CONNECTABLE;
+               settings |= MGMT_SETTING_FAST_CONNECTABLE;
+               settings |= MGMT_SETTING_DISCOVERABLE;
                settings |= MGMT_SETTING_BREDR;
                settings |= MGMT_SETTING_LINK_SECURITY;
        }
@@ -565,7 +565,7 @@ static int update_eir(struct hci_dev *hdev)
        if (!hdev_is_powered(hdev))
                return 0;
 
-       if (!(hdev->features[6] & LMP_EXT_INQ))
+       if (!lmp_ext_inq_capable(hdev))
                return 0;
 
        if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
@@ -867,6 +867,10 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
 
        BT_DBG("request for %s", hdev->name);
 
+       if (!lmp_bredr_capable(hdev))
+               return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
+                                MGMT_STATUS_NOT_SUPPORTED);
+
        timeout = __le16_to_cpu(cp->timeout);
        if (!cp->val && timeout > 0)
                return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
@@ -962,6 +966,10 @@ static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
 
        BT_DBG("request for %s", hdev->name);
 
+       if (!lmp_bredr_capable(hdev))
+               return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
+                                 MGMT_STATUS_NOT_SUPPORTED);
+
        hci_dev_lock(hdev);
 
        if (!hdev_is_powered(hdev)) {
@@ -1060,6 +1068,10 @@ static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
 
        BT_DBG("request for %s", hdev->name);
 
+       if (!lmp_bredr_capable(hdev))
+               return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
+                                 MGMT_STATUS_NOT_SUPPORTED);
+
        hci_dev_lock(hdev);
 
        if (!hdev_is_powered(hdev)) {
@@ -1213,7 +1225,7 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
        }
 
        val = !!cp->val;
-       enabled = !!(hdev->host_features[0] & LMP_HOST_LE);
+       enabled = !!lmp_host_le_capable(hdev);
 
        if (!hdev_is_powered(hdev) || val == enabled) {
                bool changed = false;
@@ -1249,7 +1261,7 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
 
        if (val) {
                hci_cp.le = val;
-               hci_cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR);
+               hci_cp.simul = !!lmp_le_br_capable(hdev);
        }
 
        err = hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
@@ -2594,6 +2606,10 @@ static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
 
        BT_DBG("%s", hdev->name);
 
+       if (!lmp_bredr_capable(hdev))
+               return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
+                                 MGMT_STATUS_NOT_SUPPORTED);
+
        if (!hdev_is_powered(hdev))
                return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
                                  MGMT_STATUS_NOT_POWERED);
@@ -2871,6 +2887,21 @@ static void settings_rsp(struct pending_cmd *cmd, void *data)
        mgmt_pending_free(cmd);
 }
 
+static int set_bredr_scan(struct hci_dev *hdev)
+{
+       u8 scan = 0;
+
+       if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
+               scan |= SCAN_PAGE;
+       if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
+               scan |= SCAN_INQUIRY;
+
+       if (!scan)
+               return 0;
+
+       return hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
+}
+
 int mgmt_powered(struct hci_dev *hdev, u8 powered)
 {
        struct cmd_lookup match = { NULL, hdev };
@@ -2882,16 +2913,6 @@ int mgmt_powered(struct hci_dev *hdev, u8 powered)
        mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
 
        if (powered) {
-               u8 scan = 0;
-
-               if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
-                       scan |= SCAN_PAGE;
-               if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
-                       scan |= SCAN_INQUIRY;
-
-               if (scan)
-                       hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
-
                if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
                        u8 ssp = 1;
 
@@ -2902,15 +2923,18 @@ int mgmt_powered(struct hci_dev *hdev, u8 powered)
                        struct hci_cp_write_le_host_supported cp;
 
                        cp.le = 1;
-                       cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR);
+                       cp.simul = !!lmp_le_br_capable(hdev);
 
                        hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED,
                                     sizeof(cp), &cp);
                }
 
-               update_class(hdev);
-               update_name(hdev, hdev->dev_name);
-               update_eir(hdev);
+               if (lmp_bredr_capable(hdev)) {
+                       set_bredr_scan(hdev);
+                       update_class(hdev);
+                       update_name(hdev, hdev->dev_name);
+                       update_eir(hdev);
+               }
        } else {
                u8 status = MGMT_STATUS_NOT_POWERED;
                mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status);
@@ -3125,6 +3149,9 @@ int mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
        struct pending_cmd *cmd;
        int err;
 
+       mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
+                            hdev);
+
        cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
        if (!cmd)
                return -ENOENT;
@@ -3137,8 +3164,6 @@ int mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
 
        mgmt_pending_remove(cmd);
 
-       mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
-                            hdev);
        return err;
 }
 
@@ -3358,7 +3383,7 @@ static int clear_eir(struct hci_dev *hdev)
 {
        struct hci_cp_write_eir cp;
 
-       if (!(hdev->features[6] & LMP_EXT_INQ))
+       if (!lmp_ext_inq_capable(hdev))
                return 0;
 
        memset(hdev->eir, 0, sizeof(hdev->eir));
index c75107ef89204877315ea8d61248c2fa4e2bddd2..201fdf73720933f9fbbbb3bea3bedd1db6d5bbcf 100644 (file)
@@ -377,8 +377,8 @@ static int __rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst,
        int err = 0;
        u8 dlci;
 
-       BT_DBG("dlc %p state %ld %s %s channel %d",
-                       d, d->state, batostr(src), batostr(dst), channel);
+       BT_DBG("dlc %p state %ld %pMR -> %pMR channel %d",
+              d, d->state, src, dst, channel);
 
        if (channel < 1 || channel > 30)
                return -EINVAL;
@@ -676,7 +676,7 @@ static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src,
        struct socket *sock;
        struct sock *sk;
 
-       BT_DBG("%s %s", batostr(src), batostr(dst));
+       BT_DBG("%pMR -> %pMR", src, dst);
 
        *err = rfcomm_l2sock_create(&sock);
        if (*err < 0)
@@ -709,7 +709,7 @@ static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src,
 
        bacpy(&addr.l2_bdaddr, dst);
        addr.l2_family = AF_BLUETOOTH;
-       addr.l2_psm    = cpu_to_le16(RFCOMM_PSM);
+       addr.l2_psm    = __constant_cpu_to_le16(RFCOMM_PSM);
        addr.l2_cid    = 0;
        *err = kernel_connect(sock, (struct sockaddr *) &addr, sizeof(addr), O_NONBLOCK);
        if (*err == 0 || *err == -EINPROGRESS)
@@ -1987,7 +1987,7 @@ static int rfcomm_add_listener(bdaddr_t *ba)
        /* Bind socket */
        bacpy(&addr.l2_bdaddr, ba);
        addr.l2_family = AF_BLUETOOTH;
-       addr.l2_psm    = cpu_to_le16(RFCOMM_PSM);
+       addr.l2_psm    = __constant_cpu_to_le16(RFCOMM_PSM);
        addr.l2_cid    = 0;
        err = kernel_bind(sock, (struct sockaddr *) &addr, sizeof(addr));
        if (err < 0) {
@@ -2125,11 +2125,10 @@ static int rfcomm_dlc_debugfs_show(struct seq_file *f, void *x)
                list_for_each_entry(d, &s->dlcs, list) {
                        struct sock *sk = s->sock->sk;
 
-                       seq_printf(f, "%s %s %ld %d %d %d %d\n",
-                                               batostr(&bt_sk(sk)->src),
-                                               batostr(&bt_sk(sk)->dst),
-                                               d->state, d->dlci, d->mtu,
-                                               d->rx_credits, d->tx_credits);
+                       seq_printf(f, "%pMR %pMR %ld %d %d %d %d\n",
+                                  &bt_sk(sk)->src, &bt_sk(sk)->dst,
+                                  d->state, d->dlci, d->mtu,
+                                  d->rx_credits, d->tx_credits);
                }
        }
 
index b3226f3658cfda1142c7484b110324115dccc85b..4ddef57d03a7f4ee31c80035270d0cfb93a8a71e 100644 (file)
@@ -334,7 +334,7 @@ static int rfcomm_sock_bind(struct socket *sock, struct sockaddr *addr, int addr
        struct sock *sk = sock->sk;
        int err = 0;
 
-       BT_DBG("sk %p %s", sk, batostr(&sa->rc_bdaddr));
+       BT_DBG("sk %p %pMR", sk, &sa->rc_bdaddr);
 
        if (!addr || addr->sa_family != AF_BLUETOOTH)
                return -EINVAL;
@@ -975,10 +975,9 @@ static int rfcomm_sock_debugfs_show(struct seq_file *f, void *p)
        read_lock(&rfcomm_sk_list.lock);
 
        sk_for_each(sk, node, &rfcomm_sk_list.head) {
-               seq_printf(f, "%s %s %d %d\n",
-                               batostr(&bt_sk(sk)->src),
-                               batostr(&bt_sk(sk)->dst),
-                               sk->sk_state, rfcomm_pi(sk)->channel);
+               seq_printf(f, "%pMR %pMR %d %d\n",
+                          &bt_sk(sk)->src, &bt_sk(sk)->dst,
+                          sk->sk_state, rfcomm_pi(sk)->channel);
        }
 
        read_unlock(&rfcomm_sk_list.lock);
index ccc248791d50239c24fce5c0635245f33f654fa3..bd6fd0f43d2b36f3652127d51f5bdf7e797add58 100644 (file)
@@ -166,7 +166,7 @@ static struct device *rfcomm_get_device(struct rfcomm_dev *dev)
 static ssize_t show_address(struct device *tty_dev, struct device_attribute *attr, char *buf)
 {
        struct rfcomm_dev *dev = dev_get_drvdata(tty_dev);
-       return sprintf(buf, "%s\n", batostr(&dev->dst));
+       return sprintf(buf, "%pMR\n", &dev->dst);
 }
 
 static ssize_t show_channel(struct device *tty_dev, struct device_attribute *attr, char *buf)
@@ -663,8 +663,8 @@ static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp)
        if (!dev)
                return -ENODEV;
 
-       BT_DBG("dev %p dst %s channel %d opened %d", dev, batostr(&dev->dst),
-                               dev->channel, dev->port.count);
+       BT_DBG("dev %p dst %pMR channel %d opened %d", dev, &dev->dst,
+              dev->channel, dev->port.count);
 
        spin_lock_irqsave(&dev->port.lock, flags);
        if (++dev->port.count > 1) {
index dc42b917aaafad3f050177694c438648af2b22bb..450cdcd88e5c9a624372927639433f67fc2fde1d 100644 (file)
@@ -172,7 +172,7 @@ static int sco_connect(struct sock *sk)
        struct hci_dev  *hdev;
        int err, type;
 
-       BT_DBG("%s -> %s", batostr(src), batostr(dst));
+       BT_DBG("%pMR -> %pMR", src, dst);
 
        hdev = hci_get_route(dst, src);
        if (!hdev)
@@ -460,7 +460,7 @@ static int sco_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_le
        struct sock *sk = sock->sk;
        int err = 0;
 
-       BT_DBG("sk %p %s", sk, batostr(&sa->sco_bdaddr));
+       BT_DBG("sk %p %pMR", sk, &sa->sco_bdaddr);
 
        if (!addr || addr->sa_family != AF_BLUETOOTH)
                return -EINVAL;
@@ -893,7 +893,7 @@ int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
        struct hlist_node *node;
        int lm = 0;
 
-       BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
+       BT_DBG("hdev %s, bdaddr %pMR", hdev->name, bdaddr);
 
        /* Find listening sockets */
        read_lock(&sco_sk_list.lock);
@@ -914,7 +914,7 @@ int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
 
 void sco_connect_cfm(struct hci_conn *hcon, __u8 status)
 {
-       BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
+       BT_DBG("hcon %p bdaddr %pMR status %d", hcon, &hcon->dst, status);
        if (!status) {
                struct sco_conn *conn;
 
@@ -959,8 +959,8 @@ static int sco_debugfs_show(struct seq_file *f, void *p)
        read_lock(&sco_sk_list.lock);
 
        sk_for_each(sk, node, &sco_sk_list.head) {
-               seq_printf(f, "%s %s %d\n", batostr(&bt_sk(sk)->src),
-                          batostr(&bt_sk(sk)->dst), sk->sk_state);
+               seq_printf(f, "%pMR %pMR %d\n", &bt_sk(sk)->src,
+                          &bt_sk(sk)->dst, sk->sk_state);
        }
 
        read_unlock(&sco_sk_list.lock);
index 8c225ef349cd733614dfeaca0f2f1bceccdae064..9176bc17595c80c6738b1a3fc64466c82c39fcb9 100644 (file)
@@ -32,6 +32,8 @@
 
 #define SMP_TIMEOUT    msecs_to_jiffies(30000)
 
+#define AUTH_REQ_MASK   0x07
+
 static inline void swap128(u8 src[16], u8 dst[16])
 {
        int i;
@@ -165,7 +167,7 @@ static struct sk_buff *smp_build_cmd(struct l2cap_conn *conn, u8 code,
 
        lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
        lh->len = cpu_to_le16(sizeof(code) + dlen);
-       lh->cid = cpu_to_le16(L2CAP_CID_SMP);
+       lh->cid = __constant_cpu_to_le16(L2CAP_CID_SMP);
 
        memcpy(skb_put(skb, sizeof(code)), &code, sizeof(code));
 
@@ -230,7 +232,7 @@ static void build_pairing_cmd(struct l2cap_conn *conn,
                req->max_key_size = SMP_MAX_ENC_KEY_SIZE;
                req->init_key_dist = 0;
                req->resp_key_dist = dist_keys;
-               req->auth_req = authreq;
+               req->auth_req = (authreq & AUTH_REQ_MASK);
                return;
        }
 
@@ -239,7 +241,7 @@ static void build_pairing_cmd(struct l2cap_conn *conn,
        rsp->max_key_size = SMP_MAX_ENC_KEY_SIZE;
        rsp->init_key_dist = 0;
        rsp->resp_key_dist = req->resp_key_dist & dist_keys;
-       rsp->auth_req = authreq;
+       rsp->auth_req = (authreq & AUTH_REQ_MASK);
 }
 
 static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size)
index 159aa8bef9e7fe2f89f9b508c39a209aa92d3c0d..66f6f56bcb2325bef8c12dfd77a13dd56032e408 100644 (file)
@@ -2244,22 +2244,33 @@ bad_tag:
 
 
 /*
- * Atomically queue work on a connection.  Bump @con reference to
- * avoid races with connection teardown.
+ * Atomically queue work on a connection after the specified delay.
+ * Bump @con reference to avoid races with connection teardown.
+ * Returns 0 if work was queued, or an error code otherwise.
  */
-static void queue_con(struct ceph_connection *con)
+static int queue_con_delay(struct ceph_connection *con, unsigned long delay)
 {
        if (!con->ops->get(con)) {
-               dout("queue_con %p ref count 0\n", con);
-               return;
+               dout("%s %p ref count 0\n", __func__, con);
+
+               return -ENOENT;
        }
 
-       if (!queue_delayed_work(ceph_msgr_wq, &con->work, 0)) {
-               dout("queue_con %p - already queued\n", con);
+       if (!queue_delayed_work(ceph_msgr_wq, &con->work, delay)) {
+               dout("%s %p - already queued\n", __func__, con);
                con->ops->put(con);
-       } else {
-               dout("queue_con %p\n", con);
+
+               return -EBUSY;
        }
+
+       dout("%s %p %lu\n", __func__, con, delay);
+
+       return 0;
+}
+
+static void queue_con(struct ceph_connection *con)
+{
+       (void) queue_con_delay(con, 0);
 }
 
 /*
@@ -2294,16 +2305,14 @@ restart:
 
        if (test_and_clear_bit(CON_FLAG_BACKOFF, &con->flags)) {
                dout("con_work %p backing off\n", con);
-               if (queue_delayed_work(ceph_msgr_wq, &con->work,
-                                      round_jiffies_relative(con->delay))) {
-                       dout("con_work %p backoff %lu\n", con, con->delay);
-                       mutex_unlock(&con->mutex);
-                       return;
-               } else {
-                       con->ops->put(con);
+               ret = queue_con_delay(con, round_jiffies_relative(con->delay));
+               if (ret) {
                        dout("con_work %p FAILED to back off %lu\n", con,
                             con->delay);
+                       BUG_ON(ret == -ENOENT);
+                       set_bit(CON_FLAG_BACKOFF, &con->flags);
                }
+               goto done;
        }
 
        if (con->state == CON_STATE_STANDBY) {
@@ -2397,24 +2406,8 @@ static void ceph_fault(struct ceph_connection *con)
                        con->delay = BASE_DELAY_INTERVAL;
                else if (con->delay < MAX_DELAY_INTERVAL)
                        con->delay *= 2;
-               con->ops->get(con);
-               if (queue_delayed_work(ceph_msgr_wq, &con->work,
-                                      round_jiffies_relative(con->delay))) {
-                       dout("fault queued %p delay %lu\n", con, con->delay);
-               } else {
-                       con->ops->put(con);
-                       dout("fault failed to queue %p delay %lu, backoff\n",
-                            con, con->delay);
-                       /*
-                        * In many cases we see a socket state change
-                        * while con_work is running and end up
-                        * queuing (non-delayed) work, such that we
-                        * can't backoff with a delay.  Set a flag so
-                        * that when con_work restarts we schedule the
-                        * delay then.
-                        */
-                       set_bit(CON_FLAG_BACKOFF, &con->flags);
-               }
+               set_bit(CON_FLAG_BACKOFF, &con->flags);
+               queue_con(con);
        }
 
 out_unlock:
index 09cb3f6dc40c4a573a9597ca851b9a91a09a1c3d..b4978e2d6ddfdeb064655c68037049963798e22c 100644 (file)
@@ -6264,7 +6264,6 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char
                goto out;
 
        /* Ensure the device has been registrered */
-       err = -EINVAL;
        if (dev->reg_state != NETREG_REGISTERED)
                goto out;
 
index d1dc14c2aac4ee00fa6dab706131bbe41d3790f7..1d1c216ffd9aae3a06261ab3dea7d31deb9a8e29 100644 (file)
@@ -2427,11 +2427,7 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev)
                }
        } else {                /* IPV6 * */
 
-               if (pkt_dev->min_in6_daddr.s6_addr32[0] == 0 &&
-                   pkt_dev->min_in6_daddr.s6_addr32[1] == 0 &&
-                   pkt_dev->min_in6_daddr.s6_addr32[2] == 0 &&
-                   pkt_dev->min_in6_daddr.s6_addr32[3] == 0) ;
-               else {
+               if (!ipv6_addr_any(&pkt_dev->min_in6_daddr)) {
                        int i;
 
                        /* Only random destinations yet */
index 76d4c2c3c89b9d170e89c39fbf0ed5729621a0bc..64fe3cca2a4ed949865be0a4574a739e3ac588ef 100644 (file)
@@ -128,7 +128,7 @@ static rtnl_doit_func rtnl_get_doit(int protocol, int msgindex)
        if (tab == NULL || tab[msgindex].doit == NULL)
                tab = rtnl_msg_handlers[PF_UNSPEC];
 
-       return tab ? tab[msgindex].doit : NULL;
+       return tab[msgindex].doit;
 }
 
 static rtnl_dumpit_func rtnl_get_dumpit(int protocol, int msgindex)
@@ -143,7 +143,7 @@ static rtnl_dumpit_func rtnl_get_dumpit(int protocol, int msgindex)
        if (tab == NULL || tab[msgindex].dumpit == NULL)
                tab = rtnl_msg_handlers[PF_UNSPEC];
 
-       return tab ? tab[msgindex].dumpit : NULL;
+       return tab[msgindex].dumpit;
 }
 
 static rtnl_calcit_func rtnl_get_calcit(int protocol, int msgindex)
@@ -158,7 +158,7 @@ static rtnl_calcit_func rtnl_get_calcit(int protocol, int msgindex)
        if (tab == NULL || tab[msgindex].calcit == NULL)
                tab = rtnl_msg_handlers[PF_UNSPEC];
 
-       return tab ? tab[msgindex].calcit : NULL;
+       return tab[msgindex].calcit;
 }
 
 /**
index 6e04b1fa11f2d4c6d0e0aacb27441688c5fe1438..4007c1437fdaf615bbf197ad52e545529e7bce59 100644 (file)
@@ -3379,10 +3379,12 @@ EXPORT_SYMBOL(__skb_warn_lro_forwarding);
 
 void kfree_skb_partial(struct sk_buff *skb, bool head_stolen)
 {
-       if (head_stolen)
+       if (head_stolen) {
+               skb_release_head_state(skb);
                kmem_cache_free(skbuff_head_cache, skb);
-       else
+       } else {
                __kfree_skb(skb);
+       }
 }
 EXPORT_SYMBOL(kfree_skb_partial);
 
index 8a146cfcc366fbead42d31d882893a74ec8dcf4e..c49412cdd12c867ffda0afefe1d2146d25e002bc 100644 (file)
@@ -1074,6 +1074,9 @@ int sock_getsockopt(struct socket *sock, int level, int optname,
        case SO_NOFCS:
                v.val = sock_flag(sk, SOCK_NOFCS);
                break;
+       case SO_BINDTODEVICE:
+               v.val = sk->sk_bound_dev_if;
+               break;
        default:
                return -ENOPROTOOPT;
        }
index 8aa4b1115384e3018b461ca153bd932a511c3fef..0a0c71fccd0dabba0cc26c6be44d905ffc94d262 100644 (file)
@@ -259,20 +259,16 @@ static int __init init_dns_resolver(void)
        if (!cred)
                return -ENOMEM;
 
-       keyring = key_alloc(&key_type_keyring, ".dns_resolver",
+       keyring = keyring_alloc(".dns_resolver",
                            GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred,
                            (KEY_POS_ALL & ~KEY_POS_SETATTR) |
                            KEY_USR_VIEW | KEY_USR_READ,
-                           KEY_ALLOC_NOT_IN_QUOTA);
+                           KEY_ALLOC_NOT_IN_QUOTA, NULL);
        if (IS_ERR(keyring)) {
                ret = PTR_ERR(keyring);
                goto failed_put_cred;
        }
 
-       ret = key_instantiate_and_link(keyring, NULL, 0, NULL, NULL);
-       if (ret < 0)
-               goto failed_put_key;
-
        ret = register_key_type(&key_type_dns_resolver);
        if (ret < 0)
                goto failed_put_key;
@@ -304,3 +300,4 @@ static void __exit exit_dns_resolver(void)
 module_init(init_dns_resolver)
 module_exit(exit_dns_resolver)
 MODULE_LICENSE("GPL");
+
index 71b125cd5db18a3af37d124d4eb3495f3e03fdea..4797a800faf809dd7fae7c958de67181d67e58d2 100644 (file)
@@ -803,7 +803,7 @@ struct fib_info *fib_create_info(struct fib_config *cfg)
                unsigned int bytes;
 
                if (!new_size)
-                       new_size = 1;
+                       new_size = 16;
                bytes = new_size * sizeof(struct hlist_head *);
                new_info_hash = fib_info_hash_alloc(bytes);
                new_laddrhash = fib_info_hash_alloc(bytes);
index 535584c00f9118fe33a17e79b858e66935f424f9..e5bad82d35842036b2a71bfb5c017c16b055d36b 100644 (file)
@@ -105,6 +105,9 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
        r->id.idiag_src[0] = inet->inet_rcv_saddr;
        r->id.idiag_dst[0] = inet->inet_daddr;
 
+       if (nla_put_u8(skb, INET_DIAG_SHUTDOWN, sk->sk_shutdown))
+               goto errout;
+
        /* IPv6 dual-stack sockets use inet->tos for IPv4 connections,
         * hence this needs to be included regardless of socket family.
         */
index 432f4bb77238fcc5c80d5ab7c6ad35bb55609c53..a8c651216fa62a44d9226eed3294e3e5f3484a3d 100644 (file)
@@ -1163,8 +1163,12 @@ static bool rt_bind_exception(struct rtable *rt, struct fib_nh_exception *fnhe,
        spin_lock_bh(&fnhe_lock);
 
        if (daddr == fnhe->fnhe_daddr) {
-               struct rtable *orig;
-
+               struct rtable *orig = rcu_dereference(fnhe->fnhe_rth);
+               if (orig && rt_is_expired(orig)) {
+                       fnhe->fnhe_gw = 0;
+                       fnhe->fnhe_pmtu = 0;
+                       fnhe->fnhe_expires = 0;
+               }
                if (fnhe->fnhe_pmtu) {
                        unsigned long expires = fnhe->fnhe_expires;
                        unsigned long diff = expires - jiffies;
@@ -1181,7 +1185,6 @@ static bool rt_bind_exception(struct rtable *rt, struct fib_nh_exception *fnhe,
                } else if (!rt->rt_gateway)
                        rt->rt_gateway = daddr;
 
-               orig = rcu_dereference(fnhe->fnhe_rth);
                rcu_assign_pointer(fnhe->fnhe_rth, rt);
                if (orig)
                        rt_free(orig);
index f32c02e2a54346cf4e120d39e17d4d1b5e966189..733f48593ec3995ab7eb5f7d9a92de7383cc7132 100644 (file)
@@ -536,30 +536,29 @@ int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg)
 {
        struct tcp_sock *tp = tcp_sk(sk);
        int answ;
+       bool slow;
 
        switch (cmd) {
        case SIOCINQ:
                if (sk->sk_state == TCP_LISTEN)
                        return -EINVAL;
 
-               lock_sock(sk);
+               slow = lock_sock_fast(sk);
                if ((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV))
                        answ = 0;
                else if (sock_flag(sk, SOCK_URGINLINE) ||
                         !tp->urg_data ||
                         before(tp->urg_seq, tp->copied_seq) ||
                         !before(tp->urg_seq, tp->rcv_nxt)) {
-                       struct sk_buff *skb;
 
                        answ = tp->rcv_nxt - tp->copied_seq;
 
-                       /* Subtract 1, if FIN is in queue. */
-                       skb = skb_peek_tail(&sk->sk_receive_queue);
-                       if (answ && skb)
-                               answ -= tcp_hdr(skb)->fin;
+                       /* Subtract 1, if FIN was received */
+                       if (answ && sock_flag(sk, SOCK_DONE))
+                               answ--;
                } else
                        answ = tp->urg_seq - tp->copied_seq;
-               release_sock(sk);
+               unlock_sock_fast(sk, slow);
                break;
        case SIOCATMARK:
                answ = tp->urg_data && tp->urg_seq == tp->copied_seq;
@@ -2766,6 +2765,8 @@ void tcp_get_info(const struct sock *sk, struct tcp_info *info)
                info->tcpi_options |= TCPI_OPT_ECN;
        if (tp->ecn_flags & TCP_ECN_SEEN)
                info->tcpi_options |= TCPI_OPT_ECN_SEEN;
+       if (tp->syn_data_acked)
+               info->tcpi_options |= TCPI_OPT_SYN_DATA;
 
        info->tcpi_rto = jiffies_to_usecs(icsk->icsk_rto);
        info->tcpi_ato = jiffies_to_usecs(icsk->icsk_ack.ato);
index 432c36649db3dd8d579ddb05ae886dd3251dcb66..4ca5110d6ba964006e3f74935e43453c69d403a3 100644 (file)
@@ -3552,6 +3552,24 @@ static bool tcp_process_frto(struct sock *sk, int flag)
        return false;
 }
 
+/* RFC 5961 7 [ACK Throttling] */
+static void tcp_send_challenge_ack(struct sock *sk)
+{
+       /* unprotected vars, we dont care of overwrites */
+       static u32 challenge_timestamp;
+       static unsigned int challenge_count;
+       u32 now = jiffies / HZ;
+
+       if (now != challenge_timestamp) {
+               challenge_timestamp = now;
+               challenge_count = 0;
+       }
+       if (++challenge_count <= sysctl_tcp_challenge_ack_limit) {
+               NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPCHALLENGEACK);
+               tcp_send_ack(sk);
+       }
+}
+
 /* This routine deals with incoming acks, but not outgoing ones. */
 static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
 {
@@ -3571,8 +3589,14 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
        /* If the ack is older than previous acks
         * then we can probably ignore it.
         */
-       if (before(ack, prior_snd_una))
+       if (before(ack, prior_snd_una)) {
+               /* RFC 5961 5.2 [Blind Data Injection Attack].[Mitigation] */
+               if (before(ack, prior_snd_una - tp->max_window)) {
+                       tcp_send_challenge_ack(sk);
+                       return -1;
+               }
                goto old_ack;
+       }
 
        /* If the ack includes data we haven't sent yet, discard
         * this segment (RFC793 Section 3.9).
@@ -5241,23 +5265,6 @@ out:
 }
 #endif /* CONFIG_NET_DMA */
 
-static void tcp_send_challenge_ack(struct sock *sk)
-{
-       /* unprotected vars, we dont care of overwrites */
-       static u32 challenge_timestamp;
-       static unsigned int challenge_count;
-       u32 now = jiffies / HZ;
-
-       if (now != challenge_timestamp) {
-               challenge_timestamp = now;
-               challenge_count = 0;
-       }
-       if (++challenge_count <= sysctl_tcp_challenge_ack_limit) {
-               NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPCHALLENGEACK);
-               tcp_send_ack(sk);
-       }
-}
-
 /* Does PAWS and seqno based validation of an incoming segment, flags will
  * play significant role here.
  */
@@ -5646,6 +5653,7 @@ static bool tcp_rcv_fastopen_synack(struct sock *sk, struct sk_buff *synack,
                tcp_rearm_rto(sk);
                return true;
        }
+       tp->syn_data_acked = tp->syn_data;
        return false;
 }
 
@@ -5963,7 +5971,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
 
        req = tp->fastopen_rsk;
        if (req != NULL) {
-               BUG_ON(sk->sk_state != TCP_SYN_RECV &&
+               WARN_ON_ONCE(sk->sk_state != TCP_SYN_RECV &&
                    sk->sk_state != TCP_FIN_WAIT1);
 
                if (tcp_check_req(sk, skb, req, NULL, true) == NULL)
@@ -6052,7 +6060,15 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
                         * ACK we have received, this would have acknowledged
                         * our SYNACK so stop the SYNACK timer.
                         */
-                       if (acceptable && req != NULL) {
+                       if (req != NULL) {
+                               /* Return RST if ack_seq is invalid.
+                                * Note that RFC793 only says to generate a
+                                * DUPACK for it but for TCP Fast Open it seems
+                                * better to treat this case like TCP_SYN_RECV
+                                * above.
+                                */
+                               if (!acceptable)
+                                       return 1;
                                /* We no longer need the request sock. */
                                reqsk_fastopen_remove(sk, req, false);
                                tcp_rearm_rto(sk);
index ef998b008a570ba0976b911d85d0b98bb6d834fb..d9285f943c7e44ff9487fde541400935813836e6 100644 (file)
@@ -1461,6 +1461,7 @@ static int tcp_v4_conn_req_fastopen(struct sock *sk,
                skb_set_owner_r(skb, child);
                __skb_queue_tail(&child->sk_receive_queue, skb);
                tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq;
+               tp->syn_data_acked = 1;
        }
        sk->sk_data_ready(sk, 0);
        bh_unlock_sock(child);
@@ -1918,7 +1919,6 @@ EXPORT_SYMBOL(tcp_v4_do_rcv);
 
 void tcp_v4_early_demux(struct sk_buff *skb)
 {
-       struct net *net = dev_net(skb->dev);
        const struct iphdr *iph;
        const struct tcphdr *th;
        struct sock *sk;
@@ -1926,16 +1926,16 @@ void tcp_v4_early_demux(struct sk_buff *skb)
        if (skb->pkt_type != PACKET_HOST)
                return;
 
-       if (!pskb_may_pull(skb, ip_hdrlen(skb) + sizeof(struct tcphdr)))
+       if (!pskb_may_pull(skb, skb_transport_offset(skb) + sizeof(struct tcphdr)))
                return;
 
        iph = ip_hdr(skb);
-       th = (struct tcphdr *) ((char *)iph + ip_hdrlen(skb));
+       th = tcp_hdr(skb);
 
        if (th->doff < sizeof(struct tcphdr) / 4)
                return;
 
-       sk = __inet_lookup_established(net, &tcp_hashinfo,
+       sk = __inet_lookup_established(dev_net(skb->dev), &tcp_hashinfo,
                                       iph->saddr, th->source,
                                       iph->daddr, ntohs(th->dest),
                                       skb->skb_iif);
index 27536ba16c9da7b89d5385073c7ae4d4f9e27f3c..a7302d974f32ca563e4aeb589a193e7617c396a5 100644 (file)
@@ -510,6 +510,7 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req,
                newtp->rx_opt.mss_clamp = req->mss;
                TCP_ECN_openreq_child(newtp, req);
                newtp->fastopen_rsk = NULL;
+               newtp->syn_data_acked = 0;
 
                TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_PASSIVEOPENS);
        }
index fc04711e80c89dd0dc92ff1027efaa7324b218c3..d47c1b4421a339a3378ef23646c8f99b41d7490b 100644 (file)
@@ -347,8 +347,8 @@ void tcp_retransmit_timer(struct sock *sk)
                return;
        }
        if (tp->fastopen_rsk) {
-               BUG_ON(sk->sk_state != TCP_SYN_RECV &&
-                   sk->sk_state != TCP_FIN_WAIT1);
+               WARN_ON_ONCE(sk->sk_state != TCP_SYN_RECV &&
+                            sk->sk_state != TCP_FIN_WAIT1);
                tcp_fastopen_synack_timer(sk);
                /* Before we receive ACK to our SYN-ACK don't retransmit
                 * anything else (e.g., data or FIN segments).
index 24995a93ef8c94b22224dd344a9d474a72d28cc1..710cafd2e1a9f7a7308ffc4fa82a02abec431523 100644 (file)
@@ -672,6 +672,8 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
                            iter->rt6i_idev == rt->rt6i_idev &&
                            ipv6_addr_equal(&iter->rt6i_gateway,
                                            &rt->rt6i_gateway)) {
+                               if (rt->rt6i_nsiblings)
+                                       rt->rt6i_nsiblings = 0;
                                if (!(iter->rt6i_flags & RTF_EXPIRES))
                                        return -EEXIST;
                                if (!(rt->rt6i_flags & RTF_EXPIRES))
@@ -680,6 +682,21 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
                                        rt6_set_expires(iter, rt->dst.expires);
                                return -EEXIST;
                        }
+                       /* If we have the same destination and the same metric,
+                        * but not the same gateway, then the route we try to
+                        * add is sibling to this route, increment our counter
+                        * of siblings, and later we will add our route to the
+                        * list.
+                        * Only static routes (which don't have flag
+                        * RTF_EXPIRES) are used for ECMPv6.
+                        *
+                        * To avoid long list, we only had siblings if the
+                        * route have a gateway.
+                        */
+                       if (rt->rt6i_flags & RTF_GATEWAY &&
+                           !(rt->rt6i_flags & RTF_EXPIRES) &&
+                           !(iter->rt6i_flags & RTF_EXPIRES))
+                               rt->rt6i_nsiblings++;
                }
 
                if (iter->rt6i_metric > rt->rt6i_metric)
@@ -692,6 +709,35 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
        if (ins == &fn->leaf)
                fn->rr_ptr = NULL;
 
+       /* Link this route to others same route. */
+       if (rt->rt6i_nsiblings) {
+               unsigned int rt6i_nsiblings;
+               struct rt6_info *sibling, *temp_sibling;
+
+               /* Find the first route that have the same metric */
+               sibling = fn->leaf;
+               while (sibling) {
+                       if (sibling->rt6i_metric == rt->rt6i_metric) {
+                               list_add_tail(&rt->rt6i_siblings,
+                                             &sibling->rt6i_siblings);
+                               break;
+                       }
+                       sibling = sibling->dst.rt6_next;
+               }
+               /* For each sibling in the list, increment the counter of
+                * siblings. BUG() if counters does not match, list of siblings
+                * is broken!
+                */
+               rt6i_nsiblings = 0;
+               list_for_each_entry_safe(sibling, temp_sibling,
+                                        &rt->rt6i_siblings, rt6i_siblings) {
+                       sibling->rt6i_nsiblings++;
+                       BUG_ON(sibling->rt6i_nsiblings != rt->rt6i_nsiblings);
+                       rt6i_nsiblings++;
+               }
+               BUG_ON(rt6i_nsiblings != rt->rt6i_nsiblings);
+       }
+
        /*
         *      insert node
         */
@@ -1193,6 +1239,17 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp,
        if (fn->rr_ptr == rt)
                fn->rr_ptr = NULL;
 
+       /* Remove this entry from other siblings */
+       if (rt->rt6i_nsiblings) {
+               struct rt6_info *sibling, *next_sibling;
+
+               list_for_each_entry_safe(sibling, next_sibling,
+                                        &rt->rt6i_siblings, rt6i_siblings)
+                       sibling->rt6i_nsiblings--;
+               rt->rt6i_nsiblings = 0;
+               list_del_init(&rt->rt6i_siblings);
+       }
+
        /* Adjust walkers */
        read_lock(&fib6_walker_lock);
        FOR_WALKERS(w) {
index 7c7e963260e1792be01a329d4298dc1123c8f738..c42650cf8d4d71a24f46314aee1b56bc89ecf0b0 100644 (file)
@@ -57,6 +57,7 @@
 #include <net/xfrm.h>
 #include <net/netevent.h>
 #include <net/netlink.h>
+#include <net/nexthop.h>
 
 #include <asm/uaccess.h>
 
@@ -289,6 +290,8 @@ static inline struct rt6_info *ip6_dst_alloc(struct net *net,
                memset(dst + 1, 0, sizeof(*rt) - sizeof(*dst));
                rt6_init_peer(rt, table ? &table->tb6_peers : net->ipv6.peers);
                rt->rt6i_genid = rt_genid(net);
+               INIT_LIST_HEAD(&rt->rt6i_siblings);
+               rt->rt6i_nsiblings = 0;
        }
        return rt;
 }
@@ -385,6 +388,69 @@ static bool rt6_need_strict(const struct in6_addr *daddr)
                (IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL | IPV6_ADDR_LOOPBACK);
 }
 
+/* Multipath route selection:
+ *   Hash based function using packet header and flowlabel.
+ * Adapted from fib_info_hashfn()
+ */
+static int rt6_info_hash_nhsfn(unsigned int candidate_count,
+                              const struct flowi6 *fl6)
+{
+       unsigned int val = fl6->flowi6_proto;
+
+       val ^= (__force u32)fl6->daddr.s6_addr32[0];
+       val ^= (__force u32)fl6->daddr.s6_addr32[1];
+       val ^= (__force u32)fl6->daddr.s6_addr32[2];
+       val ^= (__force u32)fl6->daddr.s6_addr32[3];
+
+       val ^= (__force u32)fl6->saddr.s6_addr32[0];
+       val ^= (__force u32)fl6->saddr.s6_addr32[1];
+       val ^= (__force u32)fl6->saddr.s6_addr32[2];
+       val ^= (__force u32)fl6->saddr.s6_addr32[3];
+
+       /* Work only if this not encapsulated */
+       switch (fl6->flowi6_proto) {
+       case IPPROTO_UDP:
+       case IPPROTO_TCP:
+       case IPPROTO_SCTP:
+               val ^= (__force u16)fl6->fl6_sport;
+               val ^= (__force u16)fl6->fl6_dport;
+               break;
+
+       case IPPROTO_ICMPV6:
+               val ^= (__force u16)fl6->fl6_icmp_type;
+               val ^= (__force u16)fl6->fl6_icmp_code;
+               break;
+       }
+       /* RFC6438 recommands to use flowlabel */
+       val ^= (__force u32)fl6->flowlabel;
+
+       /* Perhaps, we need to tune, this function? */
+       val = val ^ (val >> 7) ^ (val >> 12);
+       return val % candidate_count;
+}
+
+static struct rt6_info *rt6_multipath_select(struct rt6_info *match,
+                                            struct flowi6 *fl6)
+{
+       struct rt6_info *sibling, *next_sibling;
+       int route_choosen;
+
+       route_choosen = rt6_info_hash_nhsfn(match->rt6i_nsiblings + 1, fl6);
+       /* Don't change the route, if route_choosen == 0
+        * (siblings does not include ourself)
+        */
+       if (route_choosen)
+               list_for_each_entry_safe(sibling, next_sibling,
+                               &match->rt6i_siblings, rt6i_siblings) {
+                       route_choosen--;
+                       if (route_choosen == 0) {
+                               match = sibling;
+                               break;
+                       }
+               }
+       return match;
+}
+
 /*
  *     Route lookup. Any table->tb6_lock is implied.
  */
@@ -702,6 +768,8 @@ static struct rt6_info *ip6_pol_route_lookup(struct net *net,
 restart:
        rt = fn->leaf;
        rt = rt6_device_match(net, rt, &fl6->saddr, fl6->flowi6_oif, flags);
+       if (rt->rt6i_nsiblings && fl6->flowi6_oif == 0)
+               rt = rt6_multipath_select(rt, fl6);
        BACKTRACK(net, &fl6->saddr);
 out:
        dst_use(&rt->dst, jiffies);
@@ -863,7 +931,8 @@ restart_2:
 
 restart:
        rt = rt6_select(fn, oif, strict | reachable);
-
+       if (rt->rt6i_nsiblings && oif == 0)
+               rt = rt6_multipath_select(rt, fl6);
        BACKTRACK(net, &fl6->saddr);
        if (rt == net->ipv6.ip6_null_entry ||
            rt->rt6i_flags & RTF_CACHE)
@@ -2249,6 +2318,7 @@ static const struct nla_policy rtm_ipv6_policy[RTA_MAX+1] = {
        [RTA_IIF]               = { .type = NLA_U32 },
        [RTA_PRIORITY]          = { .type = NLA_U32 },
        [RTA_METRICS]           = { .type = NLA_NESTED },
+       [RTA_MULTIPATH]         = { .len = sizeof(struct rtnexthop) },
 };
 
 static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh,
@@ -2326,11 +2396,65 @@ static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh,
        if (tb[RTA_TABLE])
                cfg->fc_table = nla_get_u32(tb[RTA_TABLE]);
 
+       if (tb[RTA_MULTIPATH]) {
+               cfg->fc_mp = nla_data(tb[RTA_MULTIPATH]);
+               cfg->fc_mp_len = nla_len(tb[RTA_MULTIPATH]);
+       }
+
        err = 0;
 errout:
        return err;
 }
 
+static int ip6_route_multipath(struct fib6_config *cfg, int add)
+{
+       struct fib6_config r_cfg;
+       struct rtnexthop *rtnh;
+       int remaining;
+       int attrlen;
+       int err = 0, last_err = 0;
+
+beginning:
+       rtnh = (struct rtnexthop *)cfg->fc_mp;
+       remaining = cfg->fc_mp_len;
+
+       /* Parse a Multipath Entry */
+       while (rtnh_ok(rtnh, remaining)) {
+               memcpy(&r_cfg, cfg, sizeof(*cfg));
+               if (rtnh->rtnh_ifindex)
+                       r_cfg.fc_ifindex = rtnh->rtnh_ifindex;
+
+               attrlen = rtnh_attrlen(rtnh);
+               if (attrlen > 0) {
+                       struct nlattr *nla, *attrs = rtnh_attrs(rtnh);
+
+                       nla = nla_find(attrs, attrlen, RTA_GATEWAY);
+                       if (nla) {
+                               nla_memcpy(&r_cfg.fc_gateway, nla, 16);
+                               r_cfg.fc_flags |= RTF_GATEWAY;
+                       }
+               }
+               err = add ? ip6_route_add(&r_cfg) : ip6_route_del(&r_cfg);
+               if (err) {
+                       last_err = err;
+                       /* If we are trying to remove a route, do not stop the
+                        * loop when ip6_route_del() fails (because next hop is
+                        * already gone), we should try to remove all next hops.
+                        */
+                       if (add) {
+                               /* If add fails, we should try to delete all
+                                * next hops that have been already added.
+                                */
+                               add = 0;
+                               goto beginning;
+                       }
+               }
+               rtnh = rtnh_next(rtnh, &remaining);
+       }
+
+       return last_err;
+}
+
 static int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
 {
        struct fib6_config cfg;
@@ -2340,7 +2464,10 @@ static int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *a
        if (err < 0)
                return err;
 
-       return ip6_route_del(&cfg);
+       if (cfg.fc_mp)
+               return ip6_route_multipath(&cfg, 0);
+       else
+               return ip6_route_del(&cfg);
 }
 
 static int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
@@ -2352,7 +2479,10 @@ static int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *a
        if (err < 0)
                return err;
 
-       return ip6_route_add(&cfg);
+       if (cfg.fc_mp)
+               return ip6_route_multipath(&cfg, 1);
+       else
+               return ip6_route_add(&cfg);
 }
 
 static inline size_t rt6_nlmsg_size(void)
index 26175bffbaa060ad8da6357330ff596a5391cef6..bb6782e849960e9aa2ea5063fdaea3b2484d1a3f 100644 (file)
@@ -1741,11 +1741,11 @@ static void tcp_v6_early_demux(struct sk_buff *skb)
                skb->destructor = sock_edemux;
                if (sk->sk_state != TCP_TIME_WAIT) {
                        struct dst_entry *dst = sk->sk_rx_dst;
-                       struct inet_sock *icsk = inet_sk(sk);
+
                        if (dst)
                                dst = dst_check(dst, inet6_sk(sk)->rx_dst_cookie);
                        if (dst &&
-                           icsk->rx_dst_ifindex == skb->skb_iif)
+                           inet_sk(sk)->rx_dst_ifindex == skb->skb_iif)
                                skb_dst_set_noref(skb, dst);
                }
        }
index 95a3a7a336ba86a0b8b3790a7ce8e722f17db1a2..496ce2cebcd7316f7a1eab1051758e2f90b22263 100644 (file)
@@ -421,6 +421,8 @@ static int ircomm_tty_install(struct tty_driver *driver, struct tty_struct *tty)
                hashbin_insert(ircomm_tty, (irda_queue_t *) self, line, NULL);
        }
 
+       tty->driver_data = self;
+
        return tty_port_install(&self->port, driver, tty);
 }
 
index 63af25458fdad7afd6ec253ac365a35d26772dbd..b4ecf267a34b384deb9491b51e3b4e81d545dd70 100644 (file)
@@ -248,7 +248,7 @@ config MAC80211_MHWMP_DEBUG
          Do not select this option.
 
 config MAC80211_MESH_SYNC_DEBUG
-       bool "Verbose mesh mesh synchronization debugging"
+       bool "Verbose mesh synchronization debugging"
        depends on MAC80211_DEBUG_MENU
        depends on MAC80211_MESH
        ---help---
index a7dd110faafaf80509d75849ce982744af41d2b2..4911202334d94d0be28c4c2b1541820f65d2dfb7 100644 (file)
@@ -8,6 +8,7 @@ mac80211-y := \
        wpa.o \
        scan.o offchannel.o \
        ht.o agg-tx.o agg-rx.o \
+       vht.o \
        ibss.o \
        iface.o \
        rate.o \
index 05f3a313db8852b36c677cad188fd7154d6564ef..5eab1325a0f6fc3ff2e53df503fc26e366dec14f 100644 (file)
@@ -372,10 +372,11 @@ static int ieee80211_config_default_mgmt_key(struct wiphy *wiphy,
 
 static void rate_idx_to_bitrate(struct rate_info *rate, struct sta_info *sta, int idx)
 {
+       enum ieee80211_band band = ieee80211_get_sdata_band(sta->sdata);
+
        if (!(rate->flags & RATE_INFO_FLAGS_MCS)) {
                struct ieee80211_supported_band *sband;
-               sband = sta->local->hw.wiphy->bands[
-                               sta->local->oper_channel->band];
+               sband = sta->local->hw.wiphy->bands[band];
                rate->legacy = sband->bitrates[idx].bitrate;
        } else
                rate->mcs = idx;
@@ -532,6 +533,8 @@ static void ieee80211_get_et_stats(struct wiphy *wiphy,
                                   u64 *data)
 {
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       struct ieee80211_chanctx_conf *chanctx_conf;
+       struct ieee80211_channel *channel;
        struct sta_info *sta;
        struct ieee80211_local *local = sdata->local;
        struct station_info sinfo;
@@ -607,19 +610,26 @@ static void ieee80211_get_et_stats(struct wiphy *wiphy,
 do_survey:
        i = STA_STATS_LEN - STA_STATS_SURVEY_LEN;
        /* Get survey stats for current channel */
-       q = 0;
-       while (true) {
-               survey.filled = 0;
-               if (drv_get_survey(local, q, &survey) != 0) {
-                       survey.filled = 0;
-                       break;
-               }
+       survey.filled = 0;
 
-               if (survey.channel &&
-                   (local->oper_channel->center_freq ==
-                    survey.channel->center_freq))
-                       break;
-               q++;
+       rcu_read_lock();
+       chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
+       if (chanctx_conf)
+               channel = chanctx_conf->channel;
+       else
+               channel = NULL;
+       rcu_read_unlock();
+
+       if (channel) {
+               q = 0;
+               do {
+                       survey.filled = 0;
+                       if (drv_get_survey(local, q, &survey) != 0) {
+                               survey.filled = 0;
+                               break;
+                       }
+                       q++;
+               } while (channel != survey.channel);
        }
 
        if (survey.filled)
@@ -724,47 +734,42 @@ static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev,
        return ret;
 }
 
-static int ieee80211_set_channel(struct wiphy *wiphy,
-                                struct net_device *netdev,
-                                struct ieee80211_channel *chan,
-                                enum nl80211_channel_type channel_type)
+static int ieee80211_set_monitor_channel(struct wiphy *wiphy,
+                                        struct ieee80211_channel *chan,
+                                        enum nl80211_channel_type channel_type)
 {
        struct ieee80211_local *local = wiphy_priv(wiphy);
-       struct ieee80211_sub_if_data *sdata = NULL;
-
-       if (netdev)
-               sdata = IEEE80211_DEV_TO_SUB_IF(netdev);
-
-       switch (ieee80211_get_channel_mode(local, NULL)) {
-       case CHAN_MODE_HOPPING:
-               return -EBUSY;
-       case CHAN_MODE_FIXED:
-               if (local->oper_channel != chan ||
-                   (!sdata && local->_oper_channel_type != channel_type))
-                       return -EBUSY;
-               if (!sdata && local->_oper_channel_type == channel_type)
-                       return 0;
-               break;
-       case CHAN_MODE_UNDEFINED:
-               break;
-       }
-
-       if (!ieee80211_set_channel_type(local, sdata, channel_type))
-               return -EBUSY;
+       struct ieee80211_sub_if_data *sdata;
+       int ret = 0;
 
-       local->oper_channel = chan;
+       if (local->monitor_channel == chan &&
+           local->monitor_channel_type == channel_type)
+               return 0;
 
-       /* auto-detects changes */
-       ieee80211_hw_config(local, 0);
+       mutex_lock(&local->iflist_mtx);
+       if (local->use_chanctx) {
+               sdata = rcu_dereference_protected(
+                               local->monitor_sdata,
+                               lockdep_is_held(&local->iflist_mtx));
+               if (sdata) {
+                       ieee80211_vif_release_channel(sdata);
+                       ret = ieee80211_vif_use_channel(
+                                       sdata, chan, channel_type,
+                                       IEEE80211_CHANCTX_EXCLUSIVE);
+               }
+       } else if (local->open_count == local->monitors) {
+               local->_oper_channel = chan;
+               local->_oper_channel_type = channel_type;
+               ieee80211_hw_config(local, 0);
+       }
 
-       return 0;
-}
+       if (ret == 0) {
+               local->monitor_channel = chan;
+               local->monitor_channel_type = channel_type;
+       }
+       mutex_unlock(&local->iflist_mtx);
 
-static int ieee80211_set_monitor_channel(struct wiphy *wiphy,
-                                        struct ieee80211_channel *chan,
-                                        enum nl80211_channel_type channel_type)
-{
-       return ieee80211_set_channel(wiphy, NULL, chan, channel_type);
+       return ret;
 }
 
 static int ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata,
@@ -879,8 +884,13 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
        if (old)
                return -EALREADY;
 
-       err = ieee80211_set_channel(wiphy, dev, params->channel,
-                                   params->channel_type);
+       /* TODO: make hostapd tell us what it wants */
+       sdata->smps_mode = IEEE80211_SMPS_OFF;
+       sdata->needed_rx_chains = sdata->local->rx_chains;
+
+       err = ieee80211_vif_use_channel(sdata, params->channel,
+                                       params->channel_type,
+                                       IEEE80211_CHANCTX_SHARED);
        if (err)
                return err;
 
@@ -963,6 +973,8 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
        sta_info_flush(sdata->local, sdata);
        ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED);
 
+       ieee80211_vif_release_channel(sdata);
+
        return 0;
 }
 
@@ -1019,9 +1031,10 @@ static int sta_apply_parameters(struct ieee80211_local *local,
        int i, j;
        struct ieee80211_supported_band *sband;
        struct ieee80211_sub_if_data *sdata = sta->sdata;
+       enum ieee80211_band band = ieee80211_get_sdata_band(sdata);
        u32 mask, set;
 
-       sband = local->hw.wiphy->bands[local->oper_channel->band];
+       sband = local->hw.wiphy->bands[band];
 
        mask = params->sta_flags_mask;
        set = params->sta_flags_set;
@@ -1136,7 +1149,7 @@ static int sta_apply_parameters(struct ieee80211_local *local,
                                        rates |= BIT(j);
                        }
                }
-               sta->sta.supp_rates[local->oper_channel->band] = rates;
+               sta->sta.supp_rates[band] = rates;
        }
 
        if (params->ht_capa)
@@ -1144,6 +1157,11 @@ static int sta_apply_parameters(struct ieee80211_local *local,
                                                  params->ht_capa,
                                                  &sta->sta.ht_cap);
 
+       if (params->vht_capa)
+               ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband,
+                                                   params->vht_capa,
+                                                   &sta->sta.vht_cap);
+
        if (ieee80211_vif_is_mesh(&sdata->vif)) {
 #ifdef CONFIG_MAC80211_MESH
                if (sdata->u.mesh.security & IEEE80211_MESH_SEC_SECURED)
@@ -1664,8 +1682,13 @@ static int ieee80211_join_mesh(struct wiphy *wiphy, struct net_device *dev,
        if (err)
                return err;
 
-       err = ieee80211_set_channel(wiphy, dev, setup->channel,
-                                   setup->channel_type);
+       /* can mesh use other SMPS modes? */
+       sdata->smps_mode = IEEE80211_SMPS_OFF;
+       sdata->needed_rx_chains = sdata->local->rx_chains;
+
+       err = ieee80211_vif_use_channel(sdata, setup->channel,
+                                       setup->channel_type,
+                                       IEEE80211_CHANCTX_SHARED);
        if (err)
                return err;
 
@@ -1679,6 +1702,7 @@ static int ieee80211_leave_mesh(struct wiphy *wiphy, struct net_device *dev)
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
        ieee80211_stop_mesh(sdata);
+       ieee80211_vif_release_channel(sdata);
 
        return 0;
 }
@@ -1688,10 +1712,14 @@ static int ieee80211_change_bss(struct wiphy *wiphy,
                                struct net_device *dev,
                                struct bss_parameters *params)
 {
-       struct ieee80211_sub_if_data *sdata;
+       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       enum ieee80211_band band;
        u32 changed = 0;
 
-       sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       if (!rtnl_dereference(sdata->u.ap.beacon))
+               return -ENOENT;
+
+       band = ieee80211_get_sdata_band(sdata);
 
        if (params->use_cts_prot >= 0) {
                sdata->vif.bss_conf.use_cts_prot = params->use_cts_prot;
@@ -1704,7 +1732,7 @@ static int ieee80211_change_bss(struct wiphy *wiphy,
        }
 
        if (!sdata->vif.bss_conf.use_short_slot &&
-           sdata->local->oper_channel->band == IEEE80211_BAND_5GHZ) {
+           band == IEEE80211_BAND_5GHZ) {
                sdata->vif.bss_conf.use_short_slot = true;
                changed |= BSS_CHANGED_ERP_SLOT;
        }
@@ -1718,9 +1746,7 @@ static int ieee80211_change_bss(struct wiphy *wiphy,
        if (params->basic_rates) {
                int i, j;
                u32 rates = 0;
-               struct ieee80211_local *local = wiphy_priv(wiphy);
-               struct ieee80211_supported_band *sband =
-                       wiphy->bands[local->oper_channel->band];
+               struct ieee80211_supported_band *sband = wiphy->bands[band];
 
                for (i = 0; i < params->basic_rates_len; i++) {
                        int rate = (params->basic_rates[i] & 0x7f) * 5;
@@ -1829,7 +1855,16 @@ static int ieee80211_scan(struct wiphy *wiphy,
                 * beaconing hasn't been configured yet
                 */
        case NL80211_IFTYPE_AP:
-               if (sdata->u.ap.beacon)
+               /*
+                * If the scan has been forced (and the driver supports
+                * forcing), don't care about being beaconing already.
+                * This will create problems to the attached stations (e.g. all
+                * the  frames sent while scanning on other channel will be
+                * lost)
+                */
+               if (sdata->u.ap.beacon &&
+                   (!(wiphy->features & NL80211_FEATURE_AP_SCAN) ||
+                    !(req->flags & NL80211_SCAN_FLAG_AP)))
                        return -EOPNOTSUPP;
                break;
        default:
@@ -1872,20 +1907,6 @@ static int ieee80211_auth(struct wiphy *wiphy, struct net_device *dev,
 static int ieee80211_assoc(struct wiphy *wiphy, struct net_device *dev,
                           struct cfg80211_assoc_request *req)
 {
-       struct ieee80211_local *local = wiphy_priv(wiphy);
-       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-
-       switch (ieee80211_get_channel_mode(local, sdata)) {
-       case CHAN_MODE_HOPPING:
-               return -EBUSY;
-       case CHAN_MODE_FIXED:
-               if (local->oper_channel == req->bss->channel)
-                       break;
-               return -EBUSY;
-       case CHAN_MODE_UNDEFINED:
-               break;
-       }
-
        return ieee80211_mgd_assoc(IEEE80211_DEV_TO_SUB_IF(dev), req);
 }
 
@@ -1904,30 +1925,12 @@ static int ieee80211_disassoc(struct wiphy *wiphy, struct net_device *dev,
 static int ieee80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
                               struct cfg80211_ibss_params *params)
 {
-       struct ieee80211_local *local = wiphy_priv(wiphy);
-       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-
-       switch (ieee80211_get_channel_mode(local, sdata)) {
-       case CHAN_MODE_HOPPING:
-               return -EBUSY;
-       case CHAN_MODE_FIXED:
-               if (!params->channel_fixed)
-                       return -EBUSY;
-               if (local->oper_channel == params->channel)
-                       break;
-               return -EBUSY;
-       case CHAN_MODE_UNDEFINED:
-               break;
-       }
-
-       return ieee80211_ibss_join(sdata, params);
+       return ieee80211_ibss_join(IEEE80211_DEV_TO_SUB_IF(dev), params);
 }
 
 static int ieee80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
 {
-       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-
-       return ieee80211_ibss_leave(sdata);
+       return ieee80211_ibss_leave(IEEE80211_DEV_TO_SUB_IF(dev));
 }
 
 static int ieee80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
@@ -1971,9 +1974,13 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy,
                                  enum nl80211_tx_power_setting type, int mbm)
 {
        struct ieee80211_local *local = wiphy_priv(wiphy);
-       struct ieee80211_channel *chan = local->oper_channel;
+       struct ieee80211_channel *chan = local->_oper_channel;
        u32 changes = 0;
 
+       /* FIXME */
+       if (local->use_chanctx)
+               return -EOPNOTSUPP;
+
        switch (type) {
        case NL80211_TX_POWER_AUTOMATIC:
                local->user_power_level = -1;
@@ -2067,13 +2074,12 @@ int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata,
 
        /*
         * If not associated, or current association is not an HT
-        * association, there's no need to send an action frame.
+        * association, there's no need to do anything, just store
+        * the new value until we associate.
         */
        if (!sdata->u.mgd.associated ||
-           sdata->vif.bss_conf.channel_type == NL80211_CHAN_NO_HT) {
-               ieee80211_recalc_smps(sdata->local);
+           sdata->vif.bss_conf.channel_type == NL80211_CHAN_NO_HT)
                return 0;
-       }
 
        ap = sdata->u.mgd.associated->bssid;
 
@@ -2189,6 +2195,9 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local,
 
        lockdep_assert_held(&local->mtx);
 
+       if (local->use_chanctx && !local->ops->remain_on_channel)
+               return -EOPNOTSUPP;
+
        roc = kzalloc(sizeof(*roc), GFP_KERNEL);
        if (!roc)
                return -ENOMEM;
@@ -2515,10 +2524,20 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
 
        /* Check if the operating channel is the requested channel */
        if (!need_offchan) {
-               need_offchan = chan != local->oper_channel;
-               if (channel_type_valid &&
-                   channel_type != local->_oper_channel_type)
+               struct ieee80211_chanctx_conf *chanctx_conf;
+
+               rcu_read_lock();
+               chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
+
+               if (chanctx_conf) {
+                       need_offchan = chan != chanctx_conf->channel;
+                       if (channel_type_valid &&
+                           channel_type != chanctx_conf->channel_type)
+                               need_offchan = true;
+               } else {
                        need_offchan = true;
+               }
+               rcu_read_unlock();
        }
 
        if (need_offchan && !offchan) {
@@ -2667,7 +2686,7 @@ static u16 ieee80211_get_tdls_sta_capab(struct ieee80211_sub_if_data *sdata)
        u16 capab;
 
        capab = 0;
-       if (local->oper_channel->band != IEEE80211_BAND_2GHZ)
+       if (ieee80211_get_sdata_band(sdata) != IEEE80211_BAND_2GHZ)
                return capab;
 
        if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE))
@@ -2699,7 +2718,7 @@ ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev,
                               u16 status_code, struct sk_buff *skb)
 {
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-       struct ieee80211_local *local = sdata->local;
+       enum ieee80211_band band = ieee80211_get_sdata_band(sdata);
        struct ieee80211_tdls_data *tf;
 
        tf = (void *)skb_put(skb, offsetof(struct ieee80211_tdls_data, u));
@@ -2719,10 +2738,8 @@ ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev,
                tf->u.setup_req.capability =
                        cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata));
 
-               ieee80211_add_srates_ie(sdata, skb, false,
-                                       local->oper_channel->band);
-               ieee80211_add_ext_srates_ie(sdata, skb, false,
-                                           local->oper_channel->band);
+               ieee80211_add_srates_ie(sdata, skb, false, band);
+               ieee80211_add_ext_srates_ie(sdata, skb, false, band);
                ieee80211_tdls_add_ext_capab(skb);
                break;
        case WLAN_TDLS_SETUP_RESPONSE:
@@ -2735,10 +2752,8 @@ ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev,
                tf->u.setup_resp.capability =
                        cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata));
 
-               ieee80211_add_srates_ie(sdata, skb, false,
-                                       local->oper_channel->band);
-               ieee80211_add_ext_srates_ie(sdata, skb, false,
-                                           local->oper_channel->band);
+               ieee80211_add_srates_ie(sdata, skb, false, band);
+               ieee80211_add_ext_srates_ie(sdata, skb, false, band);
                ieee80211_tdls_add_ext_capab(skb);
                break;
        case WLAN_TDLS_SETUP_CONFIRM:
@@ -2776,7 +2791,7 @@ ieee80211_prep_tdls_direct(struct wiphy *wiphy, struct net_device *dev,
                           u16 status_code, struct sk_buff *skb)
 {
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-       struct ieee80211_local *local = sdata->local;
+       enum ieee80211_band band = ieee80211_get_sdata_band(sdata);
        struct ieee80211_mgmt *mgmt;
 
        mgmt = (void *)skb_put(skb, 24);
@@ -2799,10 +2814,8 @@ ieee80211_prep_tdls_direct(struct wiphy *wiphy, struct net_device *dev,
                mgmt->u.action.u.tdls_discover_resp.capability =
                        cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata));
 
-               ieee80211_add_srates_ie(sdata, skb, false,
-                                       local->oper_channel->band);
-               ieee80211_add_ext_srates_ie(sdata, skb, false,
-                                           local->oper_channel->band);
+               ieee80211_add_srates_ie(sdata, skb, false, band);
+               ieee80211_add_ext_srates_ie(sdata, skb, false, band);
                ieee80211_tdls_add_ext_capab(skb);
                break;
        default:
@@ -2819,7 +2832,6 @@ static int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
 {
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
        struct ieee80211_local *local = sdata->local;
-       struct ieee80211_tx_info *info;
        struct sk_buff *skb = NULL;
        bool send_direct;
        int ret;
@@ -2845,7 +2857,6 @@ static int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
        if (!skb)
                return -ENOMEM;
 
-       info = IEEE80211_SKB_CB(skb);
        skb_reserve(skb, local->hw.extra_tx_headroom);
 
        switch (action_code) {
@@ -2982,12 +2993,19 @@ static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev,
        bool qos;
        struct ieee80211_tx_info *info;
        struct sta_info *sta;
+       struct ieee80211_chanctx_conf *chanctx_conf;
+       enum ieee80211_band band;
 
        rcu_read_lock();
+       chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
+       if (WARN_ON(!chanctx_conf)) {
+               rcu_read_unlock();
+               return -EINVAL;
+       }
+       band = chanctx_conf->channel->band;
        sta = sta_info_get(sdata, peer);
        if (sta) {
                qos = test_sta_flag(sta, WLAN_STA_WME);
-               rcu_read_unlock();
        } else {
                rcu_read_unlock();
                return -ENOLINK;
@@ -3005,8 +3023,10 @@ static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev,
        }
 
        skb = dev_alloc_skb(local->hw.extra_tx_headroom + size);
-       if (!skb)
+       if (!skb) {
+               rcu_read_unlock();
                return -ENOMEM;
+       }
 
        skb->dev = dev;
 
@@ -3031,8 +3051,9 @@ static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev,
                nullfunc->qos_ctrl = cpu_to_le16(7);
 
        local_bh_disable();
-       ieee80211_xmit(sdata, skb);
+       ieee80211_xmit(sdata, skb, band);
        local_bh_enable();
+       rcu_read_unlock();
 
        *cookie = (unsigned long) skb;
        return 0;
@@ -3042,10 +3063,19 @@ static struct ieee80211_channel *
 ieee80211_cfg_get_channel(struct wiphy *wiphy, struct wireless_dev *wdev,
                          enum nl80211_channel_type *type)
 {
-       struct ieee80211_local *local = wiphy_priv(wiphy);
+       struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
+       struct ieee80211_chanctx_conf *chanctx_conf;
+       struct ieee80211_channel *chan = NULL;
+
+       rcu_read_lock();
+       chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
+       if (chanctx_conf) {
+               *type = chanctx_conf->channel_type;
+               chan = chanctx_conf->channel;
+       }
+       rcu_read_unlock();
 
-       *type = local->_oper_channel_type;
-       return local->oper_channel;
+       return chan;
 }
 
 #ifdef CONFIG_PM
index 0bfc914ddd1504d16a2ebf8ad74655d6deb60e53..f84b86028a9cd50bc95c10ec3410c4250c190eb1 100644 (file)
  */
 
 #include <linux/nl80211.h>
+#include <linux/export.h>
 #include <net/cfg80211.h>
 #include "ieee80211_i.h"
-
-static enum ieee80211_chan_mode
-__ieee80211_get_channel_mode(struct ieee80211_local *local,
-                            struct ieee80211_sub_if_data *ignore)
-{
-       struct ieee80211_sub_if_data *sdata;
-
-       lockdep_assert_held(&local->iflist_mtx);
-
-       list_for_each_entry(sdata, &local->interfaces, list) {
-               if (sdata == ignore)
-                       continue;
-
-               if (!ieee80211_sdata_running(sdata))
-                       continue;
-
-               switch (sdata->vif.type) {
-               case NL80211_IFTYPE_MONITOR:
-                       continue;
-               case NL80211_IFTYPE_STATION:
-                       if (!sdata->u.mgd.associated)
-                               continue;
-                       break;
-               case NL80211_IFTYPE_ADHOC:
-                       if (!sdata->u.ibss.ssid_len)
-                               continue;
-                       if (!sdata->u.ibss.fixed_channel)
-                               return CHAN_MODE_HOPPING;
-                       break;
-               case NL80211_IFTYPE_AP_VLAN:
-                       /* will also have _AP interface */
-                       continue;
-               case NL80211_IFTYPE_AP:
-                       if (!sdata->u.ap.beacon)
-                               continue;
-                       break;
-               case NL80211_IFTYPE_MESH_POINT:
-                       if (!sdata->wdev.mesh_id_len)
-                               continue;
-                       break;
-               default:
-                       break;
-               }
-
-               return CHAN_MODE_FIXED;
-       }
-
-       return CHAN_MODE_UNDEFINED;
-}
-
-enum ieee80211_chan_mode
-ieee80211_get_channel_mode(struct ieee80211_local *local,
-                          struct ieee80211_sub_if_data *ignore)
-{
-       enum ieee80211_chan_mode mode;
-
-       mutex_lock(&local->iflist_mtx);
-       mode = __ieee80211_get_channel_mode(local, ignore);
-       mutex_unlock(&local->iflist_mtx);
-
-       return mode;
-}
-
-static enum nl80211_channel_type
-ieee80211_get_superchan(struct ieee80211_local *local,
-                       struct ieee80211_sub_if_data *sdata)
-{
-       enum nl80211_channel_type superchan = NL80211_CHAN_NO_HT;
-       struct ieee80211_sub_if_data *tmp;
-
-       mutex_lock(&local->iflist_mtx);
-       list_for_each_entry(tmp, &local->interfaces, list) {
-               if (tmp == sdata)
-                       continue;
-
-               if (!ieee80211_sdata_running(tmp))
-                       continue;
-
-               switch (tmp->vif.bss_conf.channel_type) {
-               case NL80211_CHAN_NO_HT:
-               case NL80211_CHAN_HT20:
-                       if (superchan > tmp->vif.bss_conf.channel_type)
-                               break;
-
-                       superchan = tmp->vif.bss_conf.channel_type;
-                       break;
-               case NL80211_CHAN_HT40PLUS:
-                       WARN_ON(superchan == NL80211_CHAN_HT40MINUS);
-                       superchan = NL80211_CHAN_HT40PLUS;
-                       break;
-               case NL80211_CHAN_HT40MINUS:
-                       WARN_ON(superchan == NL80211_CHAN_HT40PLUS);
-                       superchan = NL80211_CHAN_HT40MINUS;
-                       break;
-               }
-       }
-       mutex_unlock(&local->iflist_mtx);
-
-       return superchan;
-}
+#include "driver-ops.h"
 
 static bool
 ieee80211_channel_types_are_compatible(enum nl80211_channel_type chantype1,
@@ -148,23 +50,350 @@ ieee80211_channel_types_are_compatible(enum nl80211_channel_type chantype1,
        return true;
 }
 
-bool ieee80211_set_channel_type(struct ieee80211_local *local,
-                               struct ieee80211_sub_if_data *sdata,
-                               enum nl80211_channel_type chantype)
+static void ieee80211_change_chantype(struct ieee80211_local *local,
+                                     struct ieee80211_chanctx *ctx,
+                                     enum nl80211_channel_type chantype)
 {
-       enum nl80211_channel_type superchan;
-       enum nl80211_channel_type compatchan;
+       if (chantype == ctx->conf.channel_type)
+               return;
 
-       superchan = ieee80211_get_superchan(local, sdata);
-       if (!ieee80211_channel_types_are_compatible(superchan, chantype,
-                                                   &compatchan))
-               return false;
+       ctx->conf.channel_type = chantype;
+       drv_change_chanctx(local, ctx, IEEE80211_CHANCTX_CHANGE_CHANNEL_TYPE);
 
-       local->_oper_channel_type = compatchan;
+       if (!local->use_chanctx) {
+               local->_oper_channel_type = chantype;
+               ieee80211_hw_config(local, 0);
+       }
+}
 
-       if (sdata)
-               sdata->vif.bss_conf.channel_type = chantype;
+static struct ieee80211_chanctx *
+ieee80211_find_chanctx(struct ieee80211_local *local,
+                      struct ieee80211_channel *channel,
+                      enum nl80211_channel_type channel_type,
+                      enum ieee80211_chanctx_mode mode)
+{
+       struct ieee80211_chanctx *ctx;
+       enum nl80211_channel_type compat_type;
 
-       return true;
+       lockdep_assert_held(&local->chanctx_mtx);
+
+       if (mode == IEEE80211_CHANCTX_EXCLUSIVE)
+               return NULL;
+       if (WARN_ON(!channel))
+               return NULL;
+
+       list_for_each_entry(ctx, &local->chanctx_list, list) {
+               compat_type = ctx->conf.channel_type;
+
+               if (ctx->mode == IEEE80211_CHANCTX_EXCLUSIVE)
+                       continue;
+               if (ctx->conf.channel != channel)
+                       continue;
+               if (!ieee80211_channel_types_are_compatible(ctx->conf.channel_type,
+                                                           channel_type,
+                                                           &compat_type))
+                       continue;
+
+               ieee80211_change_chantype(local, ctx, compat_type);
+
+               return ctx;
+       }
+
+       return NULL;
+}
+
+static struct ieee80211_chanctx *
+ieee80211_new_chanctx(struct ieee80211_local *local,
+                     struct ieee80211_channel *channel,
+                     enum nl80211_channel_type channel_type,
+                     enum ieee80211_chanctx_mode mode)
+{
+       struct ieee80211_chanctx *ctx;
+       int err;
+
+       lockdep_assert_held(&local->chanctx_mtx);
+
+       ctx = kzalloc(sizeof(*ctx) + local->hw.chanctx_data_size, GFP_KERNEL);
+       if (!ctx)
+               return ERR_PTR(-ENOMEM);
+
+       ctx->conf.channel = channel;
+       ctx->conf.channel_type = channel_type;
+       ctx->conf.rx_chains_static = 1;
+       ctx->conf.rx_chains_dynamic = 1;
+       ctx->mode = mode;
+
+       if (!local->use_chanctx) {
+               local->_oper_channel_type = channel_type;
+               local->_oper_channel = channel;
+               ieee80211_hw_config(local, 0);
+       } else {
+               err = drv_add_chanctx(local, ctx);
+               if (err) {
+                       kfree(ctx);
+                       return ERR_PTR(err);
+               }
+       }
+
+       list_add_rcu(&ctx->list, &local->chanctx_list);
+
+       return ctx;
+}
+
+static void ieee80211_free_chanctx(struct ieee80211_local *local,
+                                  struct ieee80211_chanctx *ctx)
+{
+       lockdep_assert_held(&local->chanctx_mtx);
+
+       WARN_ON_ONCE(ctx->refcount != 0);
+
+       if (!local->use_chanctx) {
+               local->_oper_channel_type = NL80211_CHAN_NO_HT;
+               ieee80211_hw_config(local, 0);
+       } else {
+               drv_remove_chanctx(local, ctx);
+       }
+
+       list_del_rcu(&ctx->list);
+       kfree_rcu(ctx, rcu_head);
+}
+
+static int ieee80211_assign_vif_chanctx(struct ieee80211_sub_if_data *sdata,
+                                       struct ieee80211_chanctx *ctx)
+{
+       struct ieee80211_local *local = sdata->local;
+       int ret;
+
+       lockdep_assert_held(&local->chanctx_mtx);
+
+       ret = drv_assign_vif_chanctx(local, sdata, ctx);
+       if (ret)
+               return ret;
+
+       rcu_assign_pointer(sdata->vif.chanctx_conf, &ctx->conf);
+       ctx->refcount++;
+
+       return 0;
+}
+
+static enum nl80211_channel_type
+ieee80211_calc_chantype(struct ieee80211_local *local,
+                       struct ieee80211_chanctx *ctx)
+{
+       struct ieee80211_chanctx_conf *conf = &ctx->conf;
+       struct ieee80211_sub_if_data *sdata;
+       enum nl80211_channel_type result = NL80211_CHAN_NO_HT;
+
+       lockdep_assert_held(&local->chanctx_mtx);
+
+       rcu_read_lock();
+       list_for_each_entry_rcu(sdata, &local->interfaces, list) {
+               if (!ieee80211_sdata_running(sdata))
+                       continue;
+               if (rcu_access_pointer(sdata->vif.chanctx_conf) != conf)
+                       continue;
+
+               WARN_ON_ONCE(!ieee80211_channel_types_are_compatible(
+                                       sdata->vif.bss_conf.channel_type,
+                                       result, &result));
+       }
+       rcu_read_unlock();
+
+       return result;
+}
+
+static void ieee80211_recalc_chanctx_chantype(struct ieee80211_local *local,
+                                             struct ieee80211_chanctx *ctx)
+{
+       enum nl80211_channel_type chantype;
+
+       lockdep_assert_held(&local->chanctx_mtx);
+
+       chantype = ieee80211_calc_chantype(local, ctx);
+       ieee80211_change_chantype(local, ctx, chantype);
+}
+
+static void ieee80211_unassign_vif_chanctx(struct ieee80211_sub_if_data *sdata,
+                                          struct ieee80211_chanctx *ctx)
+{
+       struct ieee80211_local *local = sdata->local;
+
+       lockdep_assert_held(&local->chanctx_mtx);
+
+       ctx->refcount--;
+       rcu_assign_pointer(sdata->vif.chanctx_conf, NULL);
+
+       drv_unassign_vif_chanctx(local, sdata, ctx);
+
+       if (ctx->refcount > 0) {
+               ieee80211_recalc_chanctx_chantype(sdata->local, ctx);
+               ieee80211_recalc_smps_chanctx(local, ctx);
+       }
+}
+
+static void __ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata)
+{
+       struct ieee80211_local *local = sdata->local;
+       struct ieee80211_chanctx_conf *conf;
+       struct ieee80211_chanctx *ctx;
+
+       lockdep_assert_held(&local->chanctx_mtx);
+
+       conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
+                                        lockdep_is_held(&local->chanctx_mtx));
+       if (!conf)
+               return;
+
+       ctx = container_of(conf, struct ieee80211_chanctx, conf);
+
+       ieee80211_unassign_vif_chanctx(sdata, ctx);
+       if (ctx->refcount == 0)
+               ieee80211_free_chanctx(local, ctx);
+}
+
+void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local,
+                                  struct ieee80211_chanctx *chanctx)
+{
+       struct ieee80211_sub_if_data *sdata;
+       u8 rx_chains_static, rx_chains_dynamic;
+
+       lockdep_assert_held(&local->chanctx_mtx);
+
+       rx_chains_static = 1;
+       rx_chains_dynamic = 1;
+
+       rcu_read_lock();
+       list_for_each_entry_rcu(sdata, &local->interfaces, list) {
+               u8 needed_static, needed_dynamic;
+
+               if (!ieee80211_sdata_running(sdata))
+                       continue;
+
+               if (rcu_access_pointer(sdata->vif.chanctx_conf) !=
+                                               &chanctx->conf)
+                       continue;
+
+               switch (sdata->vif.type) {
+               case NL80211_IFTYPE_P2P_DEVICE:
+                       continue;
+               case NL80211_IFTYPE_STATION:
+                       if (!sdata->u.mgd.associated)
+                               continue;
+                       break;
+               case NL80211_IFTYPE_AP_VLAN:
+                       continue;
+               case NL80211_IFTYPE_AP:
+               case NL80211_IFTYPE_ADHOC:
+               case NL80211_IFTYPE_WDS:
+               case NL80211_IFTYPE_MESH_POINT:
+                       break;
+               default:
+                       WARN_ON_ONCE(1);
+               }
+
+               switch (sdata->smps_mode) {
+               default:
+                       WARN_ONCE(1, "Invalid SMPS mode %d\n",
+                                 sdata->smps_mode);
+                       /* fall through */
+               case IEEE80211_SMPS_OFF:
+                       needed_static = sdata->needed_rx_chains;
+                       needed_dynamic = sdata->needed_rx_chains;
+                       break;
+               case IEEE80211_SMPS_DYNAMIC:
+                       needed_static = 1;
+                       needed_dynamic = sdata->needed_rx_chains;
+                       break;
+               case IEEE80211_SMPS_STATIC:
+                       needed_static = 1;
+                       needed_dynamic = 1;
+                       break;
+               }
+
+               rx_chains_static = max(rx_chains_static, needed_static);
+               rx_chains_dynamic = max(rx_chains_dynamic, needed_dynamic);
+       }
+       rcu_read_unlock();
+
+       if (!local->use_chanctx) {
+               if (rx_chains_static > 1)
+                       local->smps_mode = IEEE80211_SMPS_OFF;
+               else if (rx_chains_dynamic > 1)
+                       local->smps_mode = IEEE80211_SMPS_DYNAMIC;
+               else
+                       local->smps_mode = IEEE80211_SMPS_STATIC;
+               ieee80211_hw_config(local, 0);
+       }
+
+       if (rx_chains_static == chanctx->conf.rx_chains_static &&
+           rx_chains_dynamic == chanctx->conf.rx_chains_dynamic)
+               return;
+
+       chanctx->conf.rx_chains_static = rx_chains_static;
+       chanctx->conf.rx_chains_dynamic = rx_chains_dynamic;
+       drv_change_chanctx(local, chanctx, IEEE80211_CHANCTX_CHANGE_RX_CHAINS);
+}
+
+int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata,
+                             struct ieee80211_channel *channel,
+                             enum nl80211_channel_type channel_type,
+                             enum ieee80211_chanctx_mode mode)
+{
+       struct ieee80211_local *local = sdata->local;
+       struct ieee80211_chanctx *ctx;
+       int ret;
+
+       WARN_ON(sdata->dev && netif_carrier_ok(sdata->dev));
+
+       mutex_lock(&local->chanctx_mtx);
+       __ieee80211_vif_release_channel(sdata);
+
+       ctx = ieee80211_find_chanctx(local, channel, channel_type, mode);
+       if (!ctx)
+               ctx = ieee80211_new_chanctx(local, channel, channel_type, mode);
+       if (IS_ERR(ctx)) {
+               ret = PTR_ERR(ctx);
+               goto out;
+       }
+
+       sdata->vif.bss_conf.channel_type = channel_type;
+
+       ret = ieee80211_assign_vif_chanctx(sdata, ctx);
+       if (ret) {
+               /* if assign fails refcount stays the same */
+               if (ctx->refcount == 0)
+                       ieee80211_free_chanctx(local, ctx);
+               goto out;
+       }
+
+       ieee80211_recalc_smps_chanctx(local, ctx);
+ out:
+       mutex_unlock(&local->chanctx_mtx);
+       return ret;
+}
+
+void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata)
+{
+       WARN_ON(sdata->dev && netif_carrier_ok(sdata->dev));
+
+       mutex_lock(&sdata->local->chanctx_mtx);
+       __ieee80211_vif_release_channel(sdata);
+       mutex_unlock(&sdata->local->chanctx_mtx);
+}
+
+void ieee80211_iter_chan_contexts_atomic(
+       struct ieee80211_hw *hw,
+       void (*iter)(struct ieee80211_hw *hw,
+                    struct ieee80211_chanctx_conf *chanctx_conf,
+                    void *data),
+       void *iter_data)
+{
+       struct ieee80211_local *local = hw_to_local(hw);
+       struct ieee80211_chanctx *ctx;
 
+       rcu_read_lock();
+       list_for_each_entry_rcu(ctx, &local->chanctx_list, list)
+               iter(hw, &ctx->conf, iter_data);
+       rcu_read_unlock();
 }
+EXPORT_SYMBOL_GPL(ieee80211_iter_chan_contexts_atomic);
index 9be4e6d71d00d736db7eeee2f24a645b1c41b2bb..214ed4ecd739f10ae201e6dfa9112c0dd943f5b8 100644 (file)
@@ -2,9 +2,9 @@
 #define __MAC80211_DEBUGFS_H
 
 #ifdef CONFIG_MAC80211_DEBUGFS
-extern void debugfs_hw_add(struct ieee80211_local *local);
-extern int mac80211_format_buffer(char __user *userbuf, size_t count,
-                                 loff_t *ppos, char *fmt, ...);
+void debugfs_hw_add(struct ieee80211_local *local);
+int __printf(4, 5) mac80211_format_buffer(char __user *userbuf, size_t count,
+                                         loff_t *ppos, char *fmt, ...);
 #else
 static inline void debugfs_hw_add(struct ieee80211_local *local)
 {
index 6d5aec9418ee203b43708499878864548822a2f2..3393ad5b8ab1875c5252bfe921b6e3c28680a524 100644 (file)
@@ -217,7 +217,7 @@ static ssize_t ieee80211_if_fmt_smps(const struct ieee80211_sub_if_data *sdata,
 
        return snprintf(buf, buflen, "request: %s\nused: %s\n",
                        smps_modes[sdata->u.mgd.req_smps],
-                       smps_modes[sdata->u.mgd.ap_smps]);
+                       smps_modes[sdata->smps_mode]);
 }
 
 static ssize_t ieee80211_if_parse_smps(struct ieee80211_sub_if_data *sdata,
@@ -395,14 +395,14 @@ __IEEE80211_IF_FILE_W(uapsd_max_sp_len);
 
 /* AP attributes */
 IEEE80211_IF_FILE(num_mcast_sta, u.ap.num_mcast_sta, ATOMIC);
-IEEE80211_IF_FILE(num_sta_ps, u.ap.num_sta_ps, ATOMIC);
-IEEE80211_IF_FILE(dtim_count, u.ap.dtim_count, DEC);
+IEEE80211_IF_FILE(num_sta_ps, u.ap.ps.num_sta_ps, ATOMIC);
+IEEE80211_IF_FILE(dtim_count, u.ap.ps.dtim_count, DEC);
 
 static ssize_t ieee80211_if_fmt_num_buffered_multicast(
        const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
 {
        return scnprintf(buf, buflen, "%u\n",
-                        skb_queue_len(&sdata->u.ap.ps_bc_buf));
+                        skb_queue_len(&sdata->u.ap.ps.bc_buf));
 }
 __IEEE80211_IF_FILE(num_buffered_multicast, NULL);
 
@@ -471,7 +471,7 @@ IEEE80211_IF_FILE(dropped_frames_congestion,
                  u.mesh.mshstats.dropped_frames_congestion, DEC);
 IEEE80211_IF_FILE(dropped_frames_no_route,
                  u.mesh.mshstats.dropped_frames_no_route, DEC);
-IEEE80211_IF_FILE(estab_plinks, u.mesh.mshstats.estab_plinks, ATOMIC);
+IEEE80211_IF_FILE(estab_plinks, u.mesh.estab_plinks, ATOMIC);
 
 /* Mesh parameters */
 IEEE80211_IF_FILE(dot11MeshMaxRetries,
index da9003b20004227b76f5ad89f04ad4445bf7d0ec..77407b31e1ffb7120927f872f24ce5276904c5fe 100644 (file)
@@ -871,4 +871,69 @@ static inline void drv_mgd_prepare_tx(struct ieee80211_local *local,
                local->ops->mgd_prepare_tx(&local->hw, &sdata->vif);
        trace_drv_return_void(local);
 }
+
+static inline int drv_add_chanctx(struct ieee80211_local *local,
+                                 struct ieee80211_chanctx *ctx)
+{
+       int ret = -EOPNOTSUPP;
+
+       trace_drv_add_chanctx(local, ctx);
+       if (local->ops->add_chanctx)
+               ret = local->ops->add_chanctx(&local->hw, &ctx->conf);
+       trace_drv_return_int(local, ret);
+
+       return ret;
+}
+
+static inline void drv_remove_chanctx(struct ieee80211_local *local,
+                                     struct ieee80211_chanctx *ctx)
+{
+       trace_drv_remove_chanctx(local, ctx);
+       if (local->ops->remove_chanctx)
+               local->ops->remove_chanctx(&local->hw, &ctx->conf);
+       trace_drv_return_void(local);
+}
+
+static inline void drv_change_chanctx(struct ieee80211_local *local,
+                                     struct ieee80211_chanctx *ctx,
+                                     u32 changed)
+{
+       trace_drv_change_chanctx(local, ctx, changed);
+       if (local->ops->change_chanctx)
+               local->ops->change_chanctx(&local->hw, &ctx->conf, changed);
+       trace_drv_return_void(local);
+}
+
+static inline int drv_assign_vif_chanctx(struct ieee80211_local *local,
+                                        struct ieee80211_sub_if_data *sdata,
+                                        struct ieee80211_chanctx *ctx)
+{
+       int ret = 0;
+
+       check_sdata_in_driver(sdata);
+
+       trace_drv_assign_vif_chanctx(local, sdata, ctx);
+       if (local->ops->assign_vif_chanctx)
+               ret = local->ops->assign_vif_chanctx(&local->hw,
+                                                    &sdata->vif,
+                                                    &ctx->conf);
+       trace_drv_return_int(local, ret);
+
+       return ret;
+}
+
+static inline void drv_unassign_vif_chanctx(struct ieee80211_local *local,
+                                           struct ieee80211_sub_if_data *sdata,
+                                           struct ieee80211_chanctx *ctx)
+{
+       check_sdata_in_driver(sdata);
+
+       trace_drv_unassign_vif_chanctx(local, sdata, ctx);
+       if (local->ops->unassign_vif_chanctx)
+               local->ops->unassign_vif_chanctx(&local->hw,
+                                                &sdata->vif,
+                                                &ctx->conf);
+       trace_drv_return_void(local);
+}
+
 #endif /* __MAC80211_DRIVER_OPS */
index 5f3620f0bc0a651257aa53e28b91c4b2114be637..3d5332e367f8c4193e8af11b98250f66e7193548 100644 (file)
@@ -26,7 +26,6 @@
 #include "rate.h"
 
 #define IEEE80211_SCAN_INTERVAL (2 * HZ)
-#define IEEE80211_SCAN_INTERVAL_SLOW (15 * HZ)
 #define IEEE80211_IBSS_JOIN_TIMEOUT (7 * HZ)
 
 #define IEEE80211_IBSS_MERGE_INTERVAL (30 * HZ)
@@ -39,7 +38,8 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
                                      const u8 *bssid, const int beacon_int,
                                      struct ieee80211_channel *chan,
                                      const u32 basic_rates,
-                                     const u16 capability, u64 tsf)
+                                     const u16 capability, u64 tsf,
+                                     bool creator)
 {
        struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
        struct ieee80211_local *local = sdata->local;
@@ -72,25 +72,27 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
        /* if merging, indicate to driver that we leave the old IBSS */
        if (sdata->vif.bss_conf.ibss_joined) {
                sdata->vif.bss_conf.ibss_joined = false;
+               sdata->vif.bss_conf.ibss_creator = false;
                netif_carrier_off(sdata->dev);
                ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IBSS);
        }
 
-       memcpy(ifibss->bssid, bssid, ETH_ALEN);
-
        sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0;
 
-       local->oper_channel = chan;
        channel_type = ifibss->channel_type;
        if (!cfg80211_can_beacon_sec_chan(local->hw.wiphy, chan, channel_type))
                channel_type = NL80211_CHAN_HT20;
-       if (!ieee80211_set_channel_type(local, sdata, channel_type)) {
-               /* can only fail due to HT40+/- mismatch */
-               channel_type = NL80211_CHAN_HT20;
-               WARN_ON(!ieee80211_set_channel_type(local, sdata,
-                                                   NL80211_CHAN_HT20));
+
+       ieee80211_vif_release_channel(sdata);
+       if (ieee80211_vif_use_channel(sdata, chan, channel_type,
+                                     ifibss->fixed_channel ?
+                                       IEEE80211_CHANCTX_SHARED :
+                                       IEEE80211_CHANCTX_EXCLUSIVE)) {
+               sdata_info(sdata, "Failed to join IBSS, no channel context\n");
+               return;
        }
-       ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
+
+       memcpy(ifibss->bssid, bssid, ETH_ALEN);
 
        sband = local->hw.wiphy->bands[chan->band];
 
@@ -197,6 +199,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
        bss_change |= BSS_CHANGED_HT;
        bss_change |= BSS_CHANGED_IBSS;
        sdata->vif.bss_conf.ibss_joined = true;
+       sdata->vif.bss_conf.ibss_creator = creator;
        ieee80211_bss_info_change_notify(sdata, bss_change);
 
        ieee80211_sta_def_wmm_params(sdata, sband->n_bitrates, supp_rates);
@@ -249,7 +252,8 @@ static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
                                  cbss->channel,
                                  basic_rates,
                                  cbss->capability,
-                                 cbss->tsf);
+                                 cbss->tsf,
+                                 false);
 }
 
 static struct sta_info *ieee80211_ibss_finish_sta(struct sta_info *sta,
@@ -279,7 +283,7 @@ static struct sta_info *ieee80211_ibss_finish_sta(struct sta_info *sta,
                ibss_dbg(sdata,
                         "TX Auth SA=%pM DA=%pM BSSID=%pM (auth_transaction=1)\n",
                         sdata->vif.addr, addr, sdata->u.ibss.bssid);
-               ieee80211_send_auth(sdata, 1, WLAN_AUTH_OPEN, NULL, 0,
+               ieee80211_send_auth(sdata, 1, WLAN_AUTH_OPEN, 0, NULL, 0,
                                    addr, sdata->u.ibss.bssid, NULL, 0, 0);
        }
        return sta;
@@ -294,7 +298,8 @@ ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
        struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
        struct ieee80211_local *local = sdata->local;
        struct sta_info *sta;
-       int band = local->oper_channel->band;
+       struct ieee80211_chanctx_conf *chanctx_conf;
+       int band;
 
        /*
         * XXX: Consider removing the least recently used entry and
@@ -317,6 +322,13 @@ ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
                return NULL;
        }
 
+       rcu_read_lock();
+       chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
+       if (WARN_ON_ONCE(!chanctx_conf))
+               return NULL;
+       band = chanctx_conf->channel->band;
+       rcu_read_unlock();
+
        sta = sta_info_alloc(sdata, addr, GFP_KERNEL);
        if (!sta) {
                rcu_read_lock();
@@ -389,7 +401,7 @@ static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata,
         * However, try to reply to authentication attempts if someone
         * has actually implemented this.
         */
-       ieee80211_send_auth(sdata, 2, WLAN_AUTH_OPEN, NULL, 0,
+       ieee80211_send_auth(sdata, 2, WLAN_AUTH_OPEN, 0, NULL, 0,
                            mgmt->sa, sdata->u.ibss.bssid, NULL, 0, 0);
 }
 
@@ -517,7 +529,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
                goto put_bss;
 
        /* different channel */
-       if (cbss->channel != local->oper_channel)
+       if (sdata->u.ibss.fixed_channel &&
+           sdata->u.ibss.channel != cbss->channel)
                goto put_bss;
 
        /* different SSID */
@@ -592,7 +605,8 @@ void ieee80211_ibss_rx_no_sta(struct ieee80211_sub_if_data *sdata,
        struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
        struct ieee80211_local *local = sdata->local;
        struct sta_info *sta;
-       int band = local->oper_channel->band;
+       struct ieee80211_chanctx_conf *chanctx_conf;
+       int band;
 
        /*
         * XXX: Consider removing the least recently used entry and
@@ -610,6 +624,15 @@ void ieee80211_ibss_rx_no_sta(struct ieee80211_sub_if_data *sdata,
        if (!ether_addr_equal(bssid, sdata->u.ibss.bssid))
                return;
 
+       rcu_read_lock();
+       chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
+       if (WARN_ON_ONCE(!chanctx_conf)) {
+               rcu_read_unlock();
+               return;
+       }
+       band = chanctx_conf->channel->band;
+       rcu_read_unlock();
+
        sta = sta_info_alloc(sdata, addr, GFP_ATOMIC);
        if (!sta)
                return;
@@ -715,7 +738,7 @@ static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata)
 
        __ieee80211_sta_join_ibss(sdata, bssid, sdata->vif.bss_conf.beacon_int,
                                  ifibss->channel, ifibss->basic_rates,
-                                 capability, 0);
+                                 capability, 0, true);
 }
 
 /*
@@ -784,18 +807,8 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
                int interval = IEEE80211_SCAN_INTERVAL;
 
                if (time_after(jiffies, ifibss->ibss_join_req +
-                              IEEE80211_IBSS_JOIN_TIMEOUT)) {
-                       if (!(local->oper_channel->flags & IEEE80211_CHAN_NO_IBSS)) {
-                               ieee80211_sta_create_ibss(sdata);
-                               return;
-                       }
-                       sdata_info(sdata, "IBSS not allowed on %d MHz\n",
-                                  local->oper_channel->center_freq);
-
-                       /* No IBSS found - decrease scan interval and continue
-                        * scanning. */
-                       interval = IEEE80211_SCAN_INTERVAL_SLOW;
-               }
+                              IEEE80211_IBSS_JOIN_TIMEOUT))
+                       ieee80211_sta_create_ibss(sdata);
 
                mod_timer(&ifibss->timer,
                          round_jiffies(jiffies + interval));
@@ -1086,17 +1099,6 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
        sdata->u.ibss.channel_type = params->channel_type;
        sdata->u.ibss.fixed_channel = params->channel_fixed;
 
-       /* fix ourselves to that channel now already */
-       if (params->channel_fixed) {
-               sdata->local->oper_channel = params->channel;
-               if (!ieee80211_set_channel_type(sdata->local, sdata,
-                                              params->channel_type)) {
-                       mutex_unlock(&sdata->u.ibss.mtx);
-                       kfree_skb(skb);
-                       return -EINVAL;
-               }
-       }
-
        if (params->ie) {
                sdata->u.ibss.ie = kmemdup(params->ie, params->ie_len,
                                           GFP_KERNEL);
@@ -1134,6 +1136,9 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
        changed |= BSS_CHANGED_HT;
        ieee80211_bss_info_change_notify(sdata, changed);
 
+       sdata->smps_mode = IEEE80211_SMPS_OFF;
+       sdata->needed_rx_chains = sdata->local->rx_chains;
+
        ieee80211_queue_work(&sdata->local->hw, &sdata->work);
 
        return 0;
@@ -1197,6 +1202,7 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
                                        lockdep_is_held(&sdata->u.ibss.mtx));
        RCU_INIT_POINTER(sdata->u.ibss.presp, NULL);
        sdata->vif.bss_conf.ibss_joined = false;
+       sdata->vif.bss_conf.ibss_creator = false;
        ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED |
                                                BSS_CHANGED_IBSS);
        synchronize_rcu();
index 8c804550465b37857d6dc50b082881ec5bd4ac35..3026519b236afb0f7cd9c32907e790d18d93e018 100644 (file)
@@ -280,23 +280,27 @@ struct probe_resp {
        u8 data[0];
 };
 
-struct ieee80211_if_ap {
-       struct beacon_data __rcu *beacon;
-       struct probe_resp __rcu *probe_resp;
-
-       struct list_head vlans;
-
+struct ps_data {
        /* yes, this looks ugly, but guarantees that we can later use
         * bitmap_empty :)
         * NB: don't touch this bitmap, use sta_info_{set,clear}_tim_bit */
        u8 tim[sizeof(unsigned long) * BITS_TO_LONGS(IEEE80211_MAX_AID + 1)];
-       struct sk_buff_head ps_bc_buf;
+       struct sk_buff_head bc_buf;
        atomic_t num_sta_ps; /* number of stations in PS mode */
-       atomic_t num_mcast_sta; /* number of stations receiving multicast */
        int dtim_count;
        bool dtim_bc_mc;
 };
 
+struct ieee80211_if_ap {
+       struct beacon_data __rcu *beacon;
+       struct probe_resp __rcu *probe_resp;
+
+       struct list_head vlans;
+
+       struct ps_data ps;
+       atomic_t num_mcast_sta; /* number of stations receiving multicast */
+};
+
 struct ieee80211_if_wds {
        struct sta_info *sta;
        u8 remote_addr[ETH_ALEN];
@@ -316,7 +320,6 @@ struct mesh_stats {
        __u32 dropped_frames_ttl;       /* Not transmitted since mesh_ttl == 0*/
        __u32 dropped_frames_no_route;  /* Not transmitted, no route found */
        __u32 dropped_frames_congestion;/* Not forwarded due to congestion */
-       atomic_t estab_plinks;
 };
 
 #define PREQ_Q_F_START         0x1
@@ -378,8 +381,9 @@ struct ieee80211_mgd_auth_data {
        u8 key_len, key_idx;
        bool done;
 
-       size_t ie_len;
-       u8 ie[];
+       u16 sae_trans, sae_status;
+       size_t data_len;
+       u8 data[];
 };
 
 struct ieee80211_mgd_assoc_data {
@@ -433,7 +437,6 @@ struct ieee80211_if_managed {
        bool powersave; /* powersave requested for this iface */
        bool broken_ap; /* AP is broken -- turn off powersave */
        enum ieee80211_smps_mode req_smps, /* requested smps mode */
-                                ap_smps, /* smps mode AP thinks we're in */
                                 driver_smps_mode; /* smps mode request */
 
        struct work_struct request_smps_work;
@@ -599,6 +602,7 @@ struct ieee80211_if_mesh {
        int preq_queue_len;
        struct mesh_stats mshstats;
        struct mesh_config mshcfg;
+       atomic_t estab_plinks;
        u32 mesh_seqnum;
        bool accepting_plinks;
        int num_gates;
@@ -610,7 +614,7 @@ struct ieee80211_if_mesh {
                IEEE80211_MESH_SEC_SECURED = 0x2,
        } security;
        /* Extensible Synchronization Framework */
-       struct ieee80211_mesh_sync_ops *sync_ops;
+       const struct ieee80211_mesh_sync_ops *sync_ops;
        s64 sync_offset_clockdrift_max;
        spinlock_t sync_offset_lock;
        bool adjusting_tbtt;
@@ -658,6 +662,30 @@ enum ieee80211_sdata_state_bits {
        SDATA_STATE_OFFCHANNEL,
 };
 
+/**
+ * enum ieee80211_chanctx_mode - channel context configuration mode
+ *
+ * @IEEE80211_CHANCTX_SHARED: channel context may be used by
+ *     multiple interfaces
+ * @IEEE80211_CHANCTX_EXCLUSIVE: channel context can be used
+ *     only by a single interface. This can be used for example for
+ *     non-fixed channel IBSS.
+ */
+enum ieee80211_chanctx_mode {
+       IEEE80211_CHANCTX_SHARED,
+       IEEE80211_CHANCTX_EXCLUSIVE
+};
+
+struct ieee80211_chanctx {
+       struct list_head list;
+       struct rcu_head rcu_head;
+
+       enum ieee80211_chanctx_mode mode;
+       int refcount;
+
+       struct ieee80211_chanctx_conf conf;
+};
+
 struct ieee80211_sub_if_data {
        struct list_head list;
 
@@ -704,11 +732,17 @@ struct ieee80211_sub_if_data {
 
        struct ieee80211_tx_queue_params tx_conf[IEEE80211_NUM_ACS];
 
+       /* used to reconfigure hardware SM PS */
+       struct work_struct recalc_smps;
+
        struct work_struct work;
        struct sk_buff_head skb_queue;
 
        bool arp_filter_state;
 
+       u8 needed_rx_chains;
+       enum ieee80211_smps_mode smps_mode;
+
        /*
         * AP this belongs to: self in AP mode and
         * corresponding AP in VLAN mode, NULL for
@@ -749,6 +783,21 @@ struct ieee80211_sub_if_data *vif_to_sdata(struct ieee80211_vif *p)
        return container_of(p, struct ieee80211_sub_if_data, vif);
 }
 
+static inline enum ieee80211_band
+ieee80211_get_sdata_band(struct ieee80211_sub_if_data *sdata)
+{
+       enum ieee80211_band band = IEEE80211_BAND_2GHZ;
+       struct ieee80211_chanctx_conf *chanctx_conf;
+
+       rcu_read_lock();
+       chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
+       if (!WARN_ON(!chanctx_conf))
+               band = chanctx_conf->channel->band;
+       rcu_read_unlock();
+
+       return band;
+}
+
 enum sdata_queue_type {
        IEEE80211_SDATA_QUEUE_TYPE_FRAME        = 0,
        IEEE80211_SDATA_QUEUE_AGG_START         = 1,
@@ -821,6 +870,7 @@ enum {
  * @SCAN_SUSPEND: Suspend the scan and go back to operating channel to
  *     send out data
  * @SCAN_RESUME: Resume the scan and scan the next channel
+ * @SCAN_ABORT: Abort the scan and go back to operating channel
  */
 enum mac80211_scan_state {
        SCAN_DECISION,
@@ -828,6 +878,7 @@ enum mac80211_scan_state {
        SCAN_SEND_PROBE,
        SCAN_SUSPEND,
        SCAN_RESUME,
+       SCAN_ABORT,
 };
 
 struct ieee80211_local {
@@ -858,15 +909,14 @@ struct ieee80211_local {
 
        bool wiphy_ciphers_allocated;
 
+       bool use_chanctx;
+
        /* protects the aggregated multicast list and filter calls */
        spinlock_t filter_lock;
 
        /* used for uploading changed mc list */
        struct work_struct reconfig_filter;
 
-       /* used to reconfigure hardware SM PS */
-       struct work_struct recalc_smps;
-
        /* aggregated multicast list */
        struct netdev_hw_addr_list mc_list;
 
@@ -903,6 +953,9 @@ struct ieee80211_local {
        /* wowlan is enabled -- don't reconfig on resume */
        bool wowlan;
 
+       /* number of RX chains the hardware has */
+       u8 rx_chains;
+
        int tx_headroom; /* required headroom for hardware/radiotap */
 
        /* Tasklet and skb queue to process calls from IRQ mode. All frames
@@ -980,13 +1033,19 @@ struct ieee80211_local {
        enum mac80211_scan_state next_scan_state;
        struct delayed_work scan_work;
        struct ieee80211_sub_if_data __rcu *scan_sdata;
+       struct ieee80211_channel *csa_channel;
+       /* For backward compatibility only -- do not use */
+       struct ieee80211_channel *_oper_channel;
        enum nl80211_channel_type _oper_channel_type;
-       struct ieee80211_channel *oper_channel, *csa_channel;
 
        /* Temporary remain-on-channel for off-channel operations */
        struct ieee80211_channel *tmp_channel;
        enum nl80211_channel_type tmp_channel_type;
 
+       /* channel contexts */
+       struct list_head chanctx_list;
+       struct mutex chanctx_mtx;
+
        /* SNMP counters */
        /* dot11CountersTable */
        u32 dot11TransmittedFragmentCount;
@@ -1091,6 +1150,8 @@ struct ieee80211_local {
 
        /* virtual monitor interface */
        struct ieee80211_sub_if_data __rcu *monitor_sdata;
+       struct ieee80211_channel *monitor_channel;
+       enum nl80211_channel_type monitor_channel_type;
 };
 
 static inline struct ieee80211_sub_if_data *
@@ -1133,6 +1194,8 @@ struct ieee802_11_elems {
        u8 *wmm_param;
        struct ieee80211_ht_cap *ht_cap_elem;
        struct ieee80211_ht_operation *ht_operation;
+       struct ieee80211_vht_cap *vht_cap_elem;
+       struct ieee80211_vht_operation *vht_operation;
        struct ieee80211_meshconf_ie *mesh_config;
        u8 *mesh_id;
        u8 *peering;
@@ -1359,6 +1422,13 @@ void ieee80211_ba_session_work(struct work_struct *work);
 void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid);
 void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid);
 
+u8 ieee80211_mcs_to_chains(const struct ieee80211_mcs_info *mcs);
+
+/* VHT */
+void ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
+                                        struct ieee80211_supported_band *sband,
+                                        struct ieee80211_vht_cap *vht_cap_ie,
+                                        struct ieee80211_sta_vht_cap *vht_cap);
 /* Spectrum management */
 void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata,
                                       struct ieee80211_mgmt *mgmt,
@@ -1393,11 +1463,42 @@ void mac80211_ev_michael_mic_failure(struct ieee80211_sub_if_data *sdata, int ke
                                     gfp_t gfp);
 void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata,
                               bool bss_notify);
-void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb);
+void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb,
+                   enum ieee80211_band band);
+
+void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata,
+                                struct sk_buff *skb, int tid,
+                                enum ieee80211_band band);
 
-void ieee80211_tx_skb_tid(struct ieee80211_sub_if_data *sdata,
-                         struct sk_buff *skb, int tid);
-static void inline ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata,
+static inline void
+ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata,
+                         struct sk_buff *skb, int tid,
+                         enum ieee80211_band band)
+{
+       rcu_read_lock();
+       __ieee80211_tx_skb_tid_band(sdata, skb, tid, band);
+       rcu_read_unlock();
+}
+
+static inline void ieee80211_tx_skb_tid(struct ieee80211_sub_if_data *sdata,
+                                       struct sk_buff *skb, int tid)
+{
+       struct ieee80211_chanctx_conf *chanctx_conf;
+
+       rcu_read_lock();
+       chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
+       if (WARN_ON(!chanctx_conf)) {
+               rcu_read_unlock();
+               kfree_skb(skb);
+               return;
+       }
+
+       __ieee80211_tx_skb_tid_band(sdata, skb, tid,
+                                   chanctx_conf->channel->band);
+       rcu_read_unlock();
+}
+
+static inline void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata,
                                    struct sk_buff *skb)
 {
        /* Send all internal mgmt frames on VO. Accordingly set TID to 7. */
@@ -1444,7 +1545,7 @@ static inline void ieee80211_add_pending_skbs(struct ieee80211_local *local,
 }
 
 void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
-                        u16 transaction, u16 auth_alg,
+                        u16 transaction, u16 auth_alg, u16 status,
                         u8 *extra, size_t extra_len, const u8 *bssid,
                         const u8 *da, const u8 *key, u8 key_len, u8 key_idx);
 void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata,
@@ -1464,7 +1565,7 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
                              const u8 *ssid, size_t ssid_len,
                              const u8 *ie, size_t ie_len,
                              u32 ratemask, bool directed, bool no_cck,
-                             struct ieee80211_channel *channel);
+                             struct ieee80211_channel *channel, bool scan);
 
 void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata,
                                  const size_t supp_rates_len,
@@ -1474,7 +1575,7 @@ u32 ieee80211_sta_get_rates(struct ieee80211_local *local,
                            enum ieee80211_band band, u32 *basic_rates);
 int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata,
                             enum ieee80211_smps_mode smps_mode);
-void ieee80211_recalc_smps(struct ieee80211_local *local);
+void ieee80211_recalc_smps(struct ieee80211_sub_if_data *sdata);
 
 size_t ieee80211_ie_split(const u8 *ies, size_t ielen,
                          const u8 *ids, int n_ids, size_t offset);
@@ -1495,21 +1596,19 @@ int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata,
                                enum ieee80211_band band);
 
 /* channel management */
-enum ieee80211_chan_mode {
-       CHAN_MODE_UNDEFINED,
-       CHAN_MODE_HOPPING,
-       CHAN_MODE_FIXED,
-};
-
-enum ieee80211_chan_mode
-ieee80211_get_channel_mode(struct ieee80211_local *local,
-                          struct ieee80211_sub_if_data *ignore);
-bool ieee80211_set_channel_type(struct ieee80211_local *local,
-                               struct ieee80211_sub_if_data *sdata,
-                               enum nl80211_channel_type chantype);
 enum nl80211_channel_type
 ieee80211_ht_oper_to_channel_type(struct ieee80211_ht_operation *ht_oper);
 
+int __must_check
+ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata,
+                         struct ieee80211_channel *channel,
+                         enum nl80211_channel_type channel_type,
+                         enum ieee80211_chanctx_mode mode);
+void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata);
+
+void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local,
+                                  struct ieee80211_chanctx *chanctx);
+
 #ifdef CONFIG_MAC80211_NOINLINE
 #define debug_noinline noinline
 #else
index 6f8a73c64fb31bde831609fa88a9b4e0425f02b9..bc3e3e1db093aac04a87eafcec51b824dc81c8f2 100644 (file)
@@ -380,6 +380,15 @@ static int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
                goto out_unlock;
        }
 
+       ret = ieee80211_vif_use_channel(sdata, local->monitor_channel,
+                                       local->monitor_channel_type,
+                                       IEEE80211_CHANCTX_EXCLUSIVE);
+       if (ret) {
+               drv_remove_interface(local, sdata);
+               kfree(sdata);
+               goto out_unlock;
+       }
+
        rcu_assign_pointer(local->monitor_sdata, sdata);
  out_unlock:
        mutex_unlock(&local->iflist_mtx);
@@ -403,6 +412,8 @@ static void ieee80211_del_virtual_monitor(struct ieee80211_local *local)
        rcu_assign_pointer(local->monitor_sdata, NULL);
        synchronize_net();
 
+       ieee80211_vif_release_channel(sdata);
+
        drv_remove_interface(local, sdata);
 
        kfree(sdata);
@@ -665,7 +676,6 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
        struct sk_buff *skb, *tmp;
        u32 hw_reconf_flags = 0;
        int i;
-       enum nl80211_channel_type orig_ct;
 
        clear_bit(SDATA_STATE_RUNNING, &sdata->state);
 
@@ -729,6 +739,8 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
        del_timer_sync(&local->dynamic_ps_timer);
        cancel_work_sync(&local->dynamic_ps_enable_work);
 
+       cancel_work_sync(&sdata->recalc_smps);
+
        /* APs need special treatment */
        if (sdata->vif.type == NL80211_IFTYPE_AP) {
                struct ieee80211_sub_if_data *vlan, *tmpsdata;
@@ -755,8 +767,8 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
                WARN_ON(!list_empty(&sdata->u.ap.vlans));
 
                /* free all potentially still buffered bcast frames */
-               local->total_ps_buffered -= skb_queue_len(&sdata->u.ap.ps_bc_buf);
-               skb_queue_purge(&sdata->u.ap.ps_bc_buf);
+               local->total_ps_buffered -= skb_queue_len(&sdata->u.ap.ps.bc_buf);
+               skb_queue_purge(&sdata->u.ap.ps.bc_buf);
        } else if (sdata->vif.type == NL80211_IFTYPE_STATION) {
                ieee80211_mgd_stop(sdata);
        }
@@ -837,14 +849,8 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
                hw_reconf_flags = 0;
        }
 
-       /* Re-calculate channel-type, in case there are multiple vifs
-        * on different channel types.
-        */
-       orig_ct = local->_oper_channel_type;
-       ieee80211_set_channel_type(local, NULL, NL80211_CHAN_NO_HT);
-
        /* do after stop to avoid reconfiguring when we stop anyway */
-       if (hw_reconf_flags || (orig_ct != local->_oper_channel_type))
+       if (hw_reconf_flags)
                ieee80211_hw_config(local, hw_reconf_flags);
 
        spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
@@ -853,7 +859,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
                        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
                        if (info->control.vif == &sdata->vif) {
                                __skb_unlink(skb, &local->pending[i]);
-                               dev_kfree_skb_irq(skb);
+                               ieee80211_free_txskb(&local->hw, skb);
                        }
                }
        }
@@ -1121,6 +1127,13 @@ static void ieee80211_iface_work(struct work_struct *work)
        }
 }
 
+static void ieee80211_recalc_smps_work(struct work_struct *work)
+{
+       struct ieee80211_sub_if_data *sdata =
+               container_of(work, struct ieee80211_sub_if_data, recalc_smps);
+
+       ieee80211_recalc_smps(sdata);
+}
 
 /*
  * Helper function to initialise an interface to a specific type.
@@ -1149,6 +1162,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
 
        skb_queue_head_init(&sdata->skb_queue);
        INIT_WORK(&sdata->work, ieee80211_iface_work);
+       INIT_WORK(&sdata->recalc_smps, ieee80211_recalc_smps_work);
 
        switch (type) {
        case NL80211_IFTYPE_P2P_GO:
@@ -1157,7 +1171,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
                sdata->vif.p2p = true;
                /* fall through */
        case NL80211_IFTYPE_AP:
-               skb_queue_head_init(&sdata->u.ap.ps_bc_buf);
+               skb_queue_head_init(&sdata->u.ap.ps.bc_buf);
                INIT_LIST_HEAD(&sdata->u.ap.vlans);
                break;
        case NL80211_IFTYPE_P2P_CLIENT:
@@ -1282,11 +1296,6 @@ int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata,
        if (type == ieee80211_vif_type_p2p(&sdata->vif))
                return 0;
 
-       /* Setting ad-hoc mode on non-IBSS channel is not supported. */
-       if (sdata->local->oper_channel->flags & IEEE80211_CHAN_NO_IBSS &&
-           type == NL80211_IFTYPE_ADHOC)
-               return -EOPNOTSUPP;
-
        if (ieee80211_sdata_running(sdata)) {
                ret = ieee80211_runtime_change_iftype(sdata, type);
                if (ret)
@@ -1298,9 +1307,6 @@ int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata,
        }
 
        /* reset some values that shouldn't be kept across type changes */
-       sdata->vif.bss_conf.basic_rates =
-               ieee80211_mandatory_rates(sdata->local,
-                       sdata->local->oper_channel->band);
        sdata->drop_unencrypted = 0;
        if (type == NL80211_IFTYPE_STATION)
                sdata->u.mgd.use_4addr = false;
index c80c4490351ce54fb75c41cdb9be1a313b0ffef5..c42094be2f0bccfca4411519673bc0f531a58164 100644 (file)
@@ -93,23 +93,21 @@ static void ieee80211_reconfig_filter(struct work_struct *work)
        ieee80211_configure_filter(local);
 }
 
-int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
+static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local)
 {
        struct ieee80211_channel *chan;
-       int ret = 0;
+       u32 changed = 0;
        int power;
        enum nl80211_channel_type channel_type;
        u32 offchannel_flag;
 
-       might_sleep();
-
        offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL;
        if (local->scan_channel) {
                chan = local->scan_channel;
                /* If scanning on oper channel, use whatever channel-type
                 * is currently in use.
                 */
-               if (chan == local->oper_channel)
+               if (chan == local->_oper_channel)
                        channel_type = local->_oper_channel_type;
                else
                        channel_type = NL80211_CHAN_NO_HT;
@@ -117,11 +115,11 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
                chan = local->tmp_channel;
                channel_type = local->tmp_channel_type;
        } else {
-               chan = local->oper_channel;
+               chan = local->_oper_channel;
                channel_type = local->_oper_channel_type;
        }
 
-       if (chan != local->oper_channel ||
+       if (chan != local->_oper_channel ||
            channel_type != local->_oper_channel_type)
                local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL;
        else
@@ -164,6 +162,21 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
                local->hw.conf.power_level = power;
        }
 
+       return changed;
+}
+
+int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
+{
+       int ret = 0;
+
+       might_sleep();
+
+       if (!local->use_chanctx)
+               changed |= ieee80211_hw_conf_chan(local);
+       else
+               changed &= ~(IEEE80211_CONF_CHANGE_CHANNEL |
+                            IEEE80211_CONF_CHANGE_POWER);
+
        if (changed && local->open_count) {
                ret = drv_config(local, changed);
                /*
@@ -359,14 +372,6 @@ void ieee80211_restart_hw(struct ieee80211_hw *hw)
 }
 EXPORT_SYMBOL(ieee80211_restart_hw);
 
-static void ieee80211_recalc_smps_work(struct work_struct *work)
-{
-       struct ieee80211_local *local =
-               container_of(work, struct ieee80211_local, recalc_smps);
-
-       ieee80211_recalc_smps(local);
-}
-
 #ifdef CONFIG_INET
 static int ieee80211_ifa_changed(struct notifier_block *nb,
                                 unsigned long data, void *arg)
@@ -540,6 +545,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
        struct ieee80211_local *local;
        int priv_size, i;
        struct wiphy *wiphy;
+       bool use_chanctx;
 
        if (WARN_ON(!ops->tx || !ops->start || !ops->stop || !ops->config ||
                    !ops->add_interface || !ops->remove_interface ||
@@ -549,6 +555,14 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
        if (WARN_ON(ops->sta_state && (ops->sta_add || ops->sta_remove)))
                return NULL;
 
+       /* check all or no channel context operations exist */
+       i = !!ops->add_chanctx + !!ops->remove_chanctx +
+           !!ops->change_chanctx + !!ops->assign_vif_chanctx +
+           !!ops->unassign_vif_chanctx;
+       if (WARN_ON(i != 0 && i != 5))
+               return NULL;
+       use_chanctx = i == 5;
+
        /* Ensure 32-byte alignment of our private data and hw private data.
         * We use the wiphy priv data for both our ieee80211_local and for
         * the driver's private data
@@ -584,8 +598,14 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
        if (ops->remain_on_channel)
                wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
 
-       wiphy->features = NL80211_FEATURE_SK_TX_STATUS |
-                         NL80211_FEATURE_HT_IBSS;
+       wiphy->features |= NL80211_FEATURE_SK_TX_STATUS |
+                          NL80211_FEATURE_SAE |
+                          NL80211_FEATURE_HT_IBSS;
+
+       if (!ops->hw_scan)
+               wiphy->features |= NL80211_FEATURE_LOW_PRIORITY_SCAN |
+                                  NL80211_FEATURE_AP_SCAN;
+
 
        if (!ops->set_key)
                wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
@@ -599,6 +619,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
        local->hw.priv = (char *)local + ALIGN(sizeof(*local), NETDEV_ALIGN);
 
        local->ops = ops;
+       local->use_chanctx = use_chanctx;
 
        /* set up some defaults */
        local->hw.queues = 1;
@@ -626,6 +647,9 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
        spin_lock_init(&local->filter_lock);
        spin_lock_init(&local->queue_stop_reason_lock);
 
+       INIT_LIST_HEAD(&local->chanctx_list);
+       mutex_init(&local->chanctx_mtx);
+
        /*
         * The rx_skb_queue is only accessed from tasklets,
         * but other SKB queues are used from within IRQ
@@ -641,7 +665,6 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
        INIT_WORK(&local->restart_work, ieee80211_restart_work);
 
        INIT_WORK(&local->reconfig_filter, ieee80211_reconfig_filter);
-       INIT_WORK(&local->recalc_smps, ieee80211_recalc_smps_work);
        local->smps_mode = IEEE80211_SMPS_OFF;
 
        INIT_WORK(&local->dynamic_ps_enable_work,
@@ -719,6 +742,25 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
        if ((hw->flags & IEEE80211_HW_SCAN_WHILE_IDLE) && !local->ops->hw_scan)
                return -EINVAL;
 
+       if (!local->use_chanctx) {
+               for (i = 0; i < local->hw.wiphy->n_iface_combinations; i++) {
+                       const struct ieee80211_iface_combination *comb;
+
+                       comb = &local->hw.wiphy->iface_combinations[i];
+
+                       if (comb->num_different_channels > 1)
+                               return -EINVAL;
+               }
+
+               /*
+                * WDS is currently prohibited when channel contexts are used
+                * because there's no clear definition of which channel WDS
+                * type interfaces use
+                */
+               if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_WDS))
+                       return -EINVAL;
+       }
+
        /* Only HW csum features are currently compatible with mac80211 */
        feature_whitelist = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
                            NETIF_F_HW_CSUM;
@@ -728,6 +770,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
        if (hw->max_report_rates == 0)
                hw->max_report_rates = hw->max_rates;
 
+       local->rx_chains = 1;
+
        /*
         * generic code guarantees at least one band,
         * set this very early because much code assumes
@@ -743,18 +787,29 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
                sband = local->hw.wiphy->bands[band];
                if (!sband)
                        continue;
-               if (!local->oper_channel) {
+               if (!local->use_chanctx && !local->_oper_channel) {
                        /* init channel we're on */
                        local->hw.conf.channel =
-                       local->oper_channel = &sband->channels[0];
+                       local->_oper_channel = &sband->channels[0];
                        local->hw.conf.channel_type = NL80211_CHAN_NO_HT;
                }
+               if (!local->monitor_channel) {
+                       local->monitor_channel = &sband->channels[0];
+                       local->monitor_channel_type = NL80211_CHAN_NO_HT;
+               }
                channels += sband->n_channels;
 
                if (max_bitrates < sband->n_bitrates)
                        max_bitrates = sband->n_bitrates;
                supp_ht = supp_ht || sband->ht_cap.ht_supported;
                supp_vht = supp_vht || sband->vht_cap.vht_supported;
+
+               if (sband->ht_cap.ht_supported)
+                       local->rx_chains =
+                               max(ieee80211_mcs_to_chains(&sband->ht_cap.mcs),
+                                   local->rx_chains);
+
+               /* TODO: consider VHT for RX chains, hopefully it's the same */
        }
 
        local->int_scan_req = kzalloc(sizeof(*local->int_scan_req) +
@@ -778,19 +833,13 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
        hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR);
        hw->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_MONITOR);
 
-       /*
-        * mac80211 doesn't support more than 1 channel, and also not more
-        * than one IBSS interface
-        */
+       /* mac80211 doesn't support more than one IBSS interface right now */
        for (i = 0; i < hw->wiphy->n_iface_combinations; i++) {
                const struct ieee80211_iface_combination *c;
                int j;
 
                c = &hw->wiphy->iface_combinations[i];
 
-               if (c->num_different_channels > 1)
-                       return -EINVAL;
-
                for (j = 0; j < c->n_limits; j++)
                        if ((c->limits[j].types & BIT(NL80211_IFTYPE_ADHOC)) &&
                            c->limits[j].max > 1)
@@ -832,7 +881,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
 
        if (supp_vht)
                local->scan_ies_len +=
-                       2 + sizeof(struct ieee80211_vht_capabilities);
+                       2 + sizeof(struct ieee80211_vht_cap);
 
        if (!local->ops->hw_scan) {
                /* For hw_scan, driver needs to set these up. */
index ff0296c7bab8b131f07a9846b608e7b91944a93e..5bed4fd5ee19e792c186bfa2dc6917ce7a12325a 100644 (file)
@@ -97,7 +97,7 @@ bool mesh_matches_local(struct ieee80211_sub_if_data *sdata,
             (ifmsh->mesh_auth_id == ie->mesh_config->meshconf_auth)))
                goto mismatch;
 
-       ieee80211_sta_get_rates(local, ie, local->oper_channel->band,
+       ieee80211_sta_get_rates(local, ie, ieee80211_get_sdata_band(sdata),
                                &basic_rates);
 
        if (sdata->vif.bss_conf.basic_rates != basic_rates)
@@ -264,7 +264,7 @@ mesh_add_meshconf_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata)
        /* Authentication Protocol identifier */
        *pos++ = ifmsh->mesh_auth_id;
        /* Mesh Formation Info - number of neighbors */
-       neighbors = atomic_read(&ifmsh->mshstats.estab_plinks);
+       neighbors = atomic_read(&ifmsh->estab_plinks);
        /* Number of neighbor mesh STAs or 15 whichever is smaller */
        neighbors = (neighbors > 15) ? 15 : neighbors;
        *pos++ = neighbors << 1;
@@ -355,12 +355,22 @@ int mesh_add_ds_params_ie(struct sk_buff *skb,
 {
        struct ieee80211_local *local = sdata->local;
        struct ieee80211_supported_band *sband;
-       struct ieee80211_channel *chan = local->oper_channel;
+       struct ieee80211_chanctx_conf *chanctx_conf;
+       struct ieee80211_channel *chan;
        u8 *pos;
 
        if (skb_tailroom(skb) < 3)
                return -ENOMEM;
 
+       rcu_read_lock();
+       chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
+       if (WARN_ON(!chanctx_conf)) {
+               rcu_read_unlock();
+               return -EINVAL;
+       }
+       chan = chanctx_conf->channel;
+       rcu_read_unlock();
+
        sband = local->hw.wiphy->bands[chan->band];
        if (sband->band == IEEE80211_BAND_2GHZ) {
                pos = skb_put(skb, 2 + 1);
@@ -376,10 +386,11 @@ int mesh_add_ht_cap_ie(struct sk_buff *skb,
                       struct ieee80211_sub_if_data *sdata)
 {
        struct ieee80211_local *local = sdata->local;
+       enum ieee80211_band band = ieee80211_get_sdata_band(sdata);
        struct ieee80211_supported_band *sband;
        u8 *pos;
 
-       sband = local->hw.wiphy->bands[local->oper_channel->band];
+       sband = local->hw.wiphy->bands[band];
        if (!sband->ht_cap.ht_supported ||
            sdata->vif.bss_conf.channel_type == NL80211_CHAN_NO_HT)
                return 0;
@@ -397,14 +408,26 @@ int mesh_add_ht_oper_ie(struct sk_buff *skb,
                        struct ieee80211_sub_if_data *sdata)
 {
        struct ieee80211_local *local = sdata->local;
-       struct ieee80211_channel *channel = local->oper_channel;
+       struct ieee80211_chanctx_conf *chanctx_conf;
+       struct ieee80211_channel *channel;
        enum nl80211_channel_type channel_type =
-                               sdata->vif.bss_conf.channel_type;
-       struct ieee80211_supported_band *sband =
-                               local->hw.wiphy->bands[channel->band];
-       struct ieee80211_sta_ht_cap *ht_cap = &sband->ht_cap;
+               sdata->vif.bss_conf.channel_type;
+       struct ieee80211_supported_band *sband;
+       struct ieee80211_sta_ht_cap *ht_cap;
        u8 *pos;
 
+       rcu_read_lock();
+       chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
+       if (WARN_ON(!chanctx_conf)) {
+               rcu_read_unlock();
+               return -EINVAL;
+       }
+       channel = chanctx_conf->channel;
+       rcu_read_unlock();
+
+       sband = local->hw.wiphy->bands[channel->band];
+       ht_cap = &sband->ht_cap;
+
        if (!ht_cap->ht_supported || channel_type == NL80211_CHAN_NO_HT)
                return 0;
 
@@ -610,7 +633,7 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata)
        sdata->vif.bss_conf.beacon_int = MESH_DEFAULT_BEACON_INTERVAL;
        sdata->vif.bss_conf.basic_rates =
                ieee80211_mandatory_rates(sdata->local,
-                                         sdata->local->oper_channel->band);
+                                         ieee80211_get_sdata_band(sdata));
        ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON |
                                                BSS_CHANGED_BEACON_ENABLED |
                                                BSS_CHANGED_HT |
index 25d0f17dec71e74c8c9e514f17155628ce6dfff6..9285f3f67e6634901ee494a1dd66c15c4cfa4dba 100644 (file)
@@ -256,7 +256,7 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata);
 void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata);
 void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata);
 void ieee80211_mesh_root_setup(struct ieee80211_if_mesh *ifmsh);
-struct ieee80211_mesh_sync_ops *ieee80211_mesh_sync_ops_get(u8 method);
+const struct ieee80211_mesh_sync_ops *ieee80211_mesh_sync_ops_get(u8 method);
 
 /* Mesh paths */
 int mesh_nexthop_lookup(struct sk_buff *skb,
@@ -324,7 +324,7 @@ extern int mesh_allocated;
 static inline int mesh_plink_free_count(struct ieee80211_sub_if_data *sdata)
 {
        return sdata->u.mesh.mshcfg.dot11MeshMaxPeerLinks -
-              atomic_read(&sdata->u.mesh.mshstats.estab_plinks);
+              atomic_read(&sdata->u.mesh.estab_plinks);
 }
 
 static inline bool mesh_plink_availables(struct ieee80211_sub_if_data *sdata)
index 3ab34d81689753e0beaf7af4a9c7c806f9da6915..234fe755968bfae25bfd307637f1afe710bf2ae7 100644 (file)
@@ -50,14 +50,14 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
 static inline
 u32 mesh_plink_inc_estab_count(struct ieee80211_sub_if_data *sdata)
 {
-       atomic_inc(&sdata->u.mesh.mshstats.estab_plinks);
+       atomic_inc(&sdata->u.mesh.estab_plinks);
        return mesh_accept_plinks_update(sdata);
 }
 
 static inline
 u32 mesh_plink_dec_estab_count(struct ieee80211_sub_if_data *sdata)
 {
-       atomic_dec(&sdata->u.mesh.mshstats.estab_plinks);
+       atomic_dec(&sdata->u.mesh.estab_plinks);
        return mesh_accept_plinks_update(sdata);
 }
 
@@ -252,6 +252,8 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
        mgmt->u.action.u.self_prot.action_code = action;
 
        if (action != WLAN_SP_MESH_PEERING_CLOSE) {
+               enum ieee80211_band band = ieee80211_get_sdata_band(sdata);
+
                /* capability info */
                pos = skb_put(skb, 2);
                memset(pos, 0, 2);
@@ -260,10 +262,8 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
                        pos = skb_put(skb, 2);
                        memcpy(pos + 2, &plid, 2);
                }
-               if (ieee80211_add_srates_ie(sdata, skb, true,
-                                           local->oper_channel->band) ||
-                   ieee80211_add_ext_srates_ie(sdata, skb, true,
-                                               local->oper_channel->band) ||
+               if (ieee80211_add_srates_ie(sdata, skb, true, band) ||
+                   ieee80211_add_ext_srates_ie(sdata, skb, true, band) ||
                    mesh_add_rsn_ie(skb, sdata) ||
                    mesh_add_meshid_ie(skb, sdata) ||
                    mesh_add_meshconf_ie(skb, sdata))
@@ -343,7 +343,7 @@ static struct sta_info *mesh_peer_init(struct ieee80211_sub_if_data *sdata,
                                       struct ieee802_11_elems *elems)
 {
        struct ieee80211_local *local = sdata->local;
-       enum ieee80211_band band = local->oper_channel->band;
+       enum ieee80211_band band = ieee80211_get_sdata_band(sdata);
        struct ieee80211_supported_band *sband;
        u32 rates, basic_rates = 0;
        struct sta_info *sta;
index a16b7b4b1e026a9af85b47f0c596e472b2b71ded..407c8705e10d30fed4cf50f322178a1c2d4dc308 100644 (file)
@@ -234,49 +234,7 @@ static void mesh_sync_offset_adjust_tbtt(struct ieee80211_sub_if_data *sdata)
        spin_unlock_bh(&ifmsh->sync_offset_lock);
 }
 
-static const u8 *mesh_get_vendor_oui(struct ieee80211_sub_if_data *sdata)
-{
-       struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
-       u8 offset;
-
-       if (!ifmsh->ie || !ifmsh->ie_len)
-               return NULL;
-
-       offset = ieee80211_ie_split_vendor(ifmsh->ie,
-                                       ifmsh->ie_len, 0);
-
-       if (!offset)
-               return NULL;
-
-       return ifmsh->ie + offset + 2;
-}
-
-static void mesh_sync_vendor_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
-                                  u16 stype,
-                                  struct ieee80211_mgmt *mgmt,
-                                  struct ieee802_11_elems *elems,
-                                  struct ieee80211_rx_status *rx_status)
-{
-       const u8 *oui;
-
-       WARN_ON(sdata->u.mesh.mesh_sp_id != IEEE80211_SYNC_METHOD_VENDOR);
-       msync_dbg(sdata, "called mesh_sync_vendor_rx_bcn_presp\n");
-       oui = mesh_get_vendor_oui(sdata);
-       /*  here you would implement the vendor offset tracking for this oui */
-}
-
-static void mesh_sync_vendor_adjust_tbtt(struct ieee80211_sub_if_data *sdata)
-{
-       const u8 *oui;
-
-       WARN_ON(sdata->u.mesh.mesh_sp_id != IEEE80211_SYNC_METHOD_VENDOR);
-       msync_dbg(sdata, "called mesh_sync_vendor_adjust_tbtt\n");
-       oui = mesh_get_vendor_oui(sdata);
-       /*  here you would implement the vendor tsf adjustment for this oui */
-}
-
-/* global variable */
-static struct sync_method sync_methods[] = {
+static const struct sync_method sync_methods[] = {
        {
                .method = IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET,
                .ops = {
@@ -284,18 +242,11 @@ static struct sync_method sync_methods[] = {
                        .adjust_tbtt = &mesh_sync_offset_adjust_tbtt,
                }
        },
-       {
-               .method = IEEE80211_SYNC_METHOD_VENDOR,
-               .ops = {
-                       .rx_bcn_presp = &mesh_sync_vendor_rx_bcn_presp,
-                       .adjust_tbtt = &mesh_sync_vendor_adjust_tbtt,
-               }
-       },
 };
 
-struct ieee80211_mesh_sync_ops *ieee80211_mesh_sync_ops_get(u8 method)
+const struct ieee80211_mesh_sync_ops *ieee80211_mesh_sync_ops_get(u8 method)
 {
-       struct ieee80211_mesh_sync_ops *ops = NULL;
+       const struct ieee80211_mesh_sync_ops *ops = NULL;
        u8 i;
 
        for (i = 0 ; i < ARRAY_SIZE(sync_methods); ++i) {
index e714ed8bb198727c6738c1e3ae7650243dd2a07e..861e1c40b1b90bbcfc2283ef2885b28b1ba303bf 100644 (file)
@@ -178,20 +178,30 @@ static u32 ieee80211_config_ht_tx(struct ieee80211_sub_if_data *sdata,
 {
        struct ieee80211_local *local = sdata->local;
        struct ieee80211_supported_band *sband;
+       struct ieee80211_chanctx_conf *chanctx_conf;
+       struct ieee80211_channel *chan;
        struct sta_info *sta;
        u32 changed = 0;
        u16 ht_opmode;
        bool disable_40 = false;
 
-       sband = local->hw.wiphy->bands[local->oper_channel->band];
+       rcu_read_lock();
+       chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
+       if (WARN_ON(!chanctx_conf)) {
+               rcu_read_unlock();
+               return 0;
+       }
+       chan = chanctx_conf->channel;
+       rcu_read_unlock();
+       sband = local->hw.wiphy->bands[chan->band];
 
        switch (sdata->vif.bss_conf.channel_type) {
        case NL80211_CHAN_HT40PLUS:
-               if (local->oper_channel->flags & IEEE80211_CHAN_NO_HT40PLUS)
+               if (chan->flags & IEEE80211_CHAN_NO_HT40PLUS)
                        disable_40 = true;
                break;
        case NL80211_CHAN_HT40MINUS:
-               if (local->oper_channel->flags & IEEE80211_CHAN_NO_HT40MINUS)
+               if (chan->flags & IEEE80211_CHAN_NO_HT40MINUS)
                        disable_40 = true;
                break;
        default:
@@ -343,7 +353,7 @@ static void ieee80211_add_vht_ie(struct ieee80211_sub_if_data *sdata,
        cap = vht_cap.cap;
 
        /* reserve and fill IE */
-       pos = skb_put(skb, sizeof(struct ieee80211_vht_capabilities) + 2);
+       pos = skb_put(skb, sizeof(struct ieee80211_vht_cap) + 2);
        ieee80211_ie_build_vht_cap(pos, &vht_cap, cap);
 }
 
@@ -359,11 +369,21 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
        int i, count, rates_len, supp_rates_len;
        u16 capab;
        struct ieee80211_supported_band *sband;
+       struct ieee80211_chanctx_conf *chanctx_conf;
+       struct ieee80211_channel *chan;
        u32 rates = 0;
 
        lockdep_assert_held(&ifmgd->mtx);
 
-       sband = local->hw.wiphy->bands[local->oper_channel->band];
+       rcu_read_lock();
+       chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
+       if (WARN_ON(!chanctx_conf)) {
+               rcu_read_unlock();
+               return;
+       }
+       chan = chanctx_conf->channel;
+       rcu_read_unlock();
+       sband = local->hw.wiphy->bands[chan->band];
 
        if (assoc_data->supp_rates_len) {
                /*
@@ -392,7 +412,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
                        4 + /* power capability */
                        2 + 2 * sband->n_channels + /* supported channels */
                        2 + sizeof(struct ieee80211_ht_cap) + /* HT */
-                       2 + sizeof(struct ieee80211_vht_capabilities) + /* VHT */
+                       2 + sizeof(struct ieee80211_vht_cap) + /* VHT */
                        assoc_data->ie_len + /* extra IEs */
                        9, /* WMM */
                        GFP_KERNEL);
@@ -485,7 +505,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
                *pos++ = WLAN_EID_PWR_CAPABILITY;
                *pos++ = 2;
                *pos++ = 0; /* min tx power */
-               *pos++ = local->oper_channel->max_power; /* max tx power */
+               *pos++ = chan->max_power; /* max tx power */
 
                /* 2. supported channels */
                /* TODO: get this in reg domain format */
@@ -523,7 +543,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
 
        if (!(ifmgd->flags & IEEE80211_STA_DISABLE_11N))
                ieee80211_add_ht_ie(sdata, skb, assoc_data->ap_ht_param,
-                                   sband, local->oper_channel, ifmgd->ap_smps);
+                                   sband, chan, sdata->smps_mode);
 
        if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT))
                ieee80211_add_vht_ie(sdata, skb, sband);
@@ -657,18 +677,18 @@ static void ieee80211_chswitch_work(struct work_struct *work)
        if (!ifmgd->associated)
                goto out;
 
-       sdata->local->oper_channel = sdata->local->csa_channel;
+       sdata->local->_oper_channel = sdata->local->csa_channel;
        if (!sdata->local->ops->channel_switch) {
                /* call "hw_config" only if doing sw channel switch */
                ieee80211_hw_config(sdata->local,
                        IEEE80211_CONF_CHANGE_CHANNEL);
        } else {
                /* update the device channel directly */
-               sdata->local->hw.conf.channel = sdata->local->oper_channel;
+               sdata->local->hw.conf.channel = sdata->local->_oper_channel;
        }
 
        /* XXX: shouldn't really modify cfg80211-owned data! */
-       ifmgd->associated->channel = sdata->local->oper_channel;
+       ifmgd->associated->channel = sdata->local->_oper_channel;
 
        /* XXX: wait for a beacon first? */
        ieee80211_wake_queues_by_reason(&sdata->local->hw,
@@ -680,11 +700,8 @@ static void ieee80211_chswitch_work(struct work_struct *work)
 
 void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool success)
 {
-       struct ieee80211_sub_if_data *sdata;
-       struct ieee80211_if_managed *ifmgd;
-
-       sdata = vif_to_sdata(vif);
-       ifmgd = &sdata->u.mgd;
+       struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+       struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
 
        trace_api_chswitch_done(sdata, success);
        if (!success) {
@@ -723,6 +740,7 @@ void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
        int new_freq = ieee80211_channel_to_frequency(sw_elem->new_ch_num,
                                                      cbss->channel->band);
+       struct ieee80211_chanctx *chanctx;
 
        ASSERT_MGD_MTX(ifmgd);
 
@@ -748,10 +766,34 @@ void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
                return;
        }
 
-       sdata->local->csa_channel = new_ch;
-
        ifmgd->flags |= IEEE80211_STA_CSA_RECEIVED;
 
+       if (sdata->local->use_chanctx) {
+               sdata_info(sdata,
+                          "not handling channel switch with channel contexts\n");
+               ieee80211_queue_work(&sdata->local->hw,
+                                    &ifmgd->csa_connection_drop_work);
+       }
+
+       mutex_lock(&sdata->local->chanctx_mtx);
+       if (WARN_ON(!rcu_access_pointer(sdata->vif.chanctx_conf))) {
+               mutex_unlock(&sdata->local->chanctx_mtx);
+               return;
+       }
+       chanctx = container_of(rcu_access_pointer(sdata->vif.chanctx_conf),
+                              struct ieee80211_chanctx, conf);
+       if (chanctx->refcount > 1) {
+               sdata_info(sdata,
+                          "channel switch with multiple interfaces on the same channel, disconnecting\n");
+               ieee80211_queue_work(&sdata->local->hw,
+                                    &ifmgd->csa_connection_drop_work);
+               mutex_unlock(&sdata->local->chanctx_mtx);
+               return;
+       }
+       mutex_unlock(&sdata->local->chanctx_mtx);
+
+       sdata->local->csa_channel = new_ch;
+
        if (sw_elem->mode)
                ieee80211_stop_queues_by_reason(&sdata->local->hw,
                                IEEE80211_QUEUE_STOP_REASON_CSA);
@@ -1280,7 +1322,7 @@ static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata,
        }
 
        use_short_slot = !!(capab & WLAN_CAPABILITY_SHORT_SLOT_TIME);
-       if (sdata->local->oper_channel->band == IEEE80211_BAND_5GHZ)
+       if (ieee80211_get_sdata_band(sdata) == IEEE80211_BAND_5GHZ)
                use_short_slot = true;
 
        if (use_protection != bss_conf->use_cts_prot) {
@@ -1350,7 +1392,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
        ieee80211_recalc_ps(local, -1);
        mutex_unlock(&local->iflist_mtx);
 
-       ieee80211_recalc_smps(local);
+       ieee80211_recalc_smps(sdata);
        ieee80211_recalc_ps_vif(sdata);
 
        netif_tx_start_all_queues(sdata->dev);
@@ -1465,9 +1507,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
        changed |= BSS_CHANGED_BSSID | BSS_CHANGED_HT;
        ieee80211_bss_info_change_notify(sdata, changed);
 
-       /* channel(_type) changes are handled by ieee80211_hw_config */
-       WARN_ON(!ieee80211_set_channel_type(local, sdata, NL80211_CHAN_NO_HT));
-       ieee80211_hw_config(local, 0);
+       ieee80211_vif_release_channel(sdata);
 
        /* disassociated - set to defaults now */
        ieee80211_set_wmm_default(sdata, false);
@@ -1589,7 +1629,7 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata)
 
                ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid_len, NULL,
                                         0, (u32) -1, true, false,
-                                        ifmgd->associated->channel);
+                                        ifmgd->associated->channel, false);
        }
 
        ifmgd->probe_timeout = jiffies + msecs_to_jiffies(probe_wait_ms);
@@ -1692,8 +1732,7 @@ struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw,
                ssid_len = ssid[1];
 
        skb = ieee80211_build_probe_req(sdata, cbss->bssid,
-                                       (u32) -1,
-                                       sdata->local->oper_channel,
+                                       (u32) -1, cbss->channel,
                                        ssid + 2, ssid_len,
                                        NULL, 0, true);
 
@@ -1804,6 +1843,7 @@ static void ieee80211_destroy_auth_data(struct ieee80211_sub_if_data *sdata,
 
                memset(sdata->u.mgd.bssid, 0, ETH_ALEN);
                ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID);
+               ieee80211_vif_release_channel(sdata);
        }
 
        cfg80211_put_bss(auth_data->bss);
@@ -1824,7 +1864,7 @@ static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata,
                return;
        auth_data->expected_transaction = 4;
        drv_mgd_prepare_tx(sdata->local, sdata);
-       ieee80211_send_auth(sdata, 3, auth_data->algorithm,
+       ieee80211_send_auth(sdata, 3, auth_data->algorithm, 0,
                            elems.challenge - 2, elems.challenge_len + 2,
                            auth_data->bss->bssid, auth_data->bss->bssid,
                            auth_data->key, auth_data->key_len,
@@ -1858,8 +1898,13 @@ ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
        status_code = le16_to_cpu(mgmt->u.auth.status_code);
 
        if (auth_alg != ifmgd->auth_data->algorithm ||
-           auth_transaction != ifmgd->auth_data->expected_transaction)
+           auth_transaction != ifmgd->auth_data->expected_transaction) {
+               sdata_info(sdata, "%pM unexpected authentication state: alg %d (expected %d) transact %d (expected %d)\n",
+                          mgmt->sa, auth_alg, ifmgd->auth_data->algorithm,
+                          auth_transaction,
+                          ifmgd->auth_data->expected_transaction);
                return RX_MGMT_NONE;
+       }
 
        if (status_code != WLAN_STATUS_SUCCESS) {
                sdata_info(sdata, "%pM denied authentication (status %d)\n",
@@ -1872,6 +1917,7 @@ ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
        case WLAN_AUTH_OPEN:
        case WLAN_AUTH_LEAP:
        case WLAN_AUTH_FT:
+       case WLAN_AUTH_SAE:
                break;
        case WLAN_AUTH_SHARED_KEY:
                if (ifmgd->auth_data->expected_transaction != 4) {
@@ -1891,6 +1937,15 @@ ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
        ifmgd->auth_data->timeout = jiffies + IEEE80211_AUTH_WAIT_ASSOC;
        run_again(ifmgd, ifmgd->auth_data->timeout);
 
+       if (ifmgd->auth_data->algorithm == WLAN_AUTH_SAE &&
+           ifmgd->auth_data->expected_transaction != 2) {
+               /*
+                * Report auth frame to user space for processing since another
+                * round of Authentication frames is still needed.
+                */
+               return RX_MGMT_CFG80211_RX_AUTH;
+       }
+
        /* move station state to auth */
        mutex_lock(&sdata->local->sta_mtx);
        sta = sta_info_get(sdata, bssid);
@@ -2030,6 +2085,7 @@ static void ieee80211_destroy_assoc_data(struct ieee80211_sub_if_data *sdata,
 
                memset(sdata->u.mgd.bssid, 0, ETH_ALEN);
                ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID);
+               ieee80211_vif_release_channel(sdata);
        }
 
        kfree(assoc_data);
@@ -2091,7 +2147,7 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
                return false;
        }
 
-       sband = local->hw.wiphy->bands[local->oper_channel->band];
+       sband = local->hw.wiphy->bands[ieee80211_get_sdata_band(sdata)];
 
        if (elems.ht_cap_elem && !(ifmgd->flags & IEEE80211_STA_DISABLE_11N))
                ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
@@ -2100,6 +2156,11 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
        sta->supports_40mhz =
                sta->sta.ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40;
 
+       if (elems.vht_cap_elem && !(ifmgd->flags & IEEE80211_STA_DISABLE_VHT))
+               ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband,
+                                                   elems.vht_cap_elem,
+                                                   &sta->sta.vht_cap);
+
        rate_control_rate_init(sta);
 
        if (ifmgd->flags & IEEE80211_STA_MFP_ENABLED)
@@ -2369,6 +2430,8 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
        size_t baselen;
        struct ieee802_11_elems elems;
        struct ieee80211_local *local = sdata->local;
+       struct ieee80211_chanctx_conf *chanctx_conf;
+       struct ieee80211_channel *chan;
        u32 changed = 0;
        bool erp_valid, directed_tim = false;
        u8 erp_value = 0;
@@ -2382,8 +2445,19 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
        if (baselen > len)
                return;
 
-       if (rx_status->freq != local->oper_channel->center_freq)
+       rcu_read_lock();
+       chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
+       if (!chanctx_conf) {
+               rcu_read_unlock();
+               return;
+       }
+
+       if (rx_status->freq != chanctx_conf->channel->center_freq) {
+               rcu_read_unlock();
                return;
+       }
+       chan = chanctx_conf->channel;
+       rcu_read_unlock();
 
        if (ifmgd->assoc_data && !ifmgd->assoc_data->have_beacon &&
            ether_addr_equal(mgmt->bssid, ifmgd->assoc_data->bss->bssid)) {
@@ -2543,19 +2617,14 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
 
 
        if (elems.ht_cap_elem && elems.ht_operation && elems.wmm_param &&
-           !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) {
-               struct ieee80211_supported_band *sband;
-
-               sband = local->hw.wiphy->bands[local->oper_channel->band];
-
+           !(ifmgd->flags & IEEE80211_STA_DISABLE_11N))
                changed |= ieee80211_config_ht_tx(sdata, elems.ht_operation,
                                                  bssid, true);
-       }
 
        if (elems.country_elem && elems.pwr_constr_elem &&
            mgmt->u.probe_resp.capab_info &
                                cpu_to_le16(WLAN_CAPABILITY_SPECTRUM_MGMT))
-               ieee80211_handle_pwr_constr(sdata, local->oper_channel,
+               ieee80211_handle_pwr_constr(sdata, chan,
                                            elems.country_elem,
                                            elems.country_elem_len,
                                            elems.pwr_constr_elem);
@@ -2703,13 +2772,23 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata)
        drv_mgd_prepare_tx(local, sdata);
 
        if (auth_data->bss->proberesp_ies) {
+               u16 trans = 1;
+               u16 status = 0;
+
                sdata_info(sdata, "send auth to %pM (try %d/%d)\n",
                           auth_data->bss->bssid, auth_data->tries,
                           IEEE80211_AUTH_MAX_TRIES);
 
                auth_data->expected_transaction = 2;
-               ieee80211_send_auth(sdata, 1, auth_data->algorithm,
-                                   auth_data->ie, auth_data->ie_len,
+
+               if (auth_data->algorithm == WLAN_AUTH_SAE) {
+                       trans = auth_data->sae_trans;
+                       status = auth_data->sae_status;
+                       auth_data->expected_transaction = trans;
+               }
+
+               ieee80211_send_auth(sdata, trans, auth_data->algorithm, status,
+                                   auth_data->data, auth_data->data_len,
                                    auth_data->bss->bssid,
                                    auth_data->bss->bssid, NULL, 0, 0);
        } else {
@@ -2728,7 +2807,7 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata)
                 */
                ieee80211_send_probe_req(sdata, NULL, ssidie + 2, ssidie[1],
                                         NULL, 0, (u32) -1, true, false,
-                                        auth_data->bss->channel);
+                                        auth_data->bss->channel, false);
        }
 
        auth_data->timeout = jiffies + IEEE80211_AUTH_TIMEOUT;
@@ -3099,39 +3178,57 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
                                   ht_cfreq, ht_oper->primary_chan,
                                   cbss->channel->band);
                        ht_oper = NULL;
+               } else {
+                       channel_type = NL80211_CHAN_HT20;
                }
        }
 
-       if (ht_oper) {
+       if (ht_oper && sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) {
+               /*
+                * cfg80211 already verified that the channel itself can
+                * be used, but it didn't check that we can do the right
+                * HT type, so do that here as well. If HT40 isn't allowed
+                * on this channel, disable 40 MHz operation.
+                */
+               const u8 *ht_cap_ie;
+               const struct ieee80211_ht_cap *ht_cap;
+               u8 chains = 1;
+
                channel_type = NL80211_CHAN_HT20;
 
-               if (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) {
-                       switch (ht_oper->ht_param &
-                                       IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
-                       case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
+               switch (ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
+               case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
+                       if (cbss->channel->flags & IEEE80211_CHAN_NO_HT40PLUS)
+                               ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ;
+                       else
                                channel_type = NL80211_CHAN_HT40PLUS;
-                               break;
-                       case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
+                       break;
+               case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
+                       if (cbss->channel->flags & IEEE80211_CHAN_NO_HT40MINUS)
+                               ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ;
+                       else
                                channel_type = NL80211_CHAN_HT40MINUS;
-                               break;
-                       }
+                       break;
                }
-       }
 
-       if (!ieee80211_set_channel_type(local, sdata, channel_type)) {
-               /* can only fail due to HT40+/- mismatch */
-               channel_type = NL80211_CHAN_HT20;
-               sdata_info(sdata,
-                          "disabling 40 MHz due to multi-vif mismatch\n");
-               ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ;
-               WARN_ON(!ieee80211_set_channel_type(local, sdata,
-                                                   channel_type));
+               ht_cap_ie = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY,
+                                            cbss->information_elements,
+                                            cbss->len_information_elements);
+               if (ht_cap_ie && ht_cap_ie[1] >= sizeof(*ht_cap)) {
+                       ht_cap = (void *)(ht_cap_ie + 2);
+                       chains = ieee80211_mcs_to_chains(&ht_cap->mcs);
+               }
+               sdata->needed_rx_chains = min(chains, local->rx_chains);
+       } else {
+               sdata->needed_rx_chains = 1;
        }
 
-       local->oper_channel = cbss->channel;
-       ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
+       /* will change later if needed */
+       sdata->smps_mode = IEEE80211_SMPS_OFF;
 
-       return 0;
+       ieee80211_vif_release_channel(sdata);
+       return ieee80211_vif_use_channel(sdata, cbss->channel, channel_type,
+                                        IEEE80211_CHANCTX_SHARED);
 }
 
 static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
@@ -3201,7 +3298,7 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
                sdata->vif.bss_conf.basic_rates = basic_rates;
 
                /* cf. IEEE 802.11 9.2.12 */
-               if (local->oper_channel->band == IEEE80211_BAND_2GHZ &&
+               if (cbss->channel->band == IEEE80211_BAND_2GHZ &&
                    have_higher_than_11mbit)
                        sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE;
                else
@@ -3263,19 +3360,33 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
        case NL80211_AUTHTYPE_NETWORK_EAP:
                auth_alg = WLAN_AUTH_LEAP;
                break;
+       case NL80211_AUTHTYPE_SAE:
+               auth_alg = WLAN_AUTH_SAE;
+               break;
        default:
                return -EOPNOTSUPP;
        }
 
-       auth_data = kzalloc(sizeof(*auth_data) + req->ie_len, GFP_KERNEL);
+       auth_data = kzalloc(sizeof(*auth_data) + req->sae_data_len +
+                           req->ie_len, GFP_KERNEL);
        if (!auth_data)
                return -ENOMEM;
 
        auth_data->bss = req->bss;
 
+       if (req->sae_data_len >= 4) {
+               __le16 *pos = (__le16 *) req->sae_data;
+               auth_data->sae_trans = le16_to_cpu(pos[0]);
+               auth_data->sae_status = le16_to_cpu(pos[1]);
+               memcpy(auth_data->data, req->sae_data + 4,
+                      req->sae_data_len - 4);
+               auth_data->data_len += req->sae_data_len - 4;
+       }
+
        if (req->ie && req->ie_len) {
-               memcpy(auth_data->ie, req->ie, req->ie_len);
-               auth_data->ie_len = req->ie_len;
+               memcpy(&auth_data->data[auth_data->data_len],
+                      req->ie, req->ie_len);
+               auth_data->data_len += req->ie_len;
        }
 
        if (req->key && req->key_len) {
@@ -3442,11 +3553,11 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
 
        if (ifmgd->req_smps == IEEE80211_SMPS_AUTOMATIC) {
                if (ifmgd->powersave)
-                       ifmgd->ap_smps = IEEE80211_SMPS_DYNAMIC;
+                       sdata->smps_mode = IEEE80211_SMPS_DYNAMIC;
                else
-                       ifmgd->ap_smps = IEEE80211_SMPS_OFF;
+                       sdata->smps_mode = IEEE80211_SMPS_OFF;
        } else
-               ifmgd->ap_smps = ifmgd->req_smps;
+               sdata->smps_mode = ifmgd->req_smps;
 
        assoc_data->capability = req->bss->capability;
        assoc_data->wmm = bss->wmm_used &&
@@ -3549,6 +3660,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
 {
        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
        u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
+       bool tx = !req->local_state_change;
 
        mutex_lock(&ifmgd->mtx);
 
@@ -3565,12 +3677,12 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
        if (ifmgd->associated &&
            ether_addr_equal(ifmgd->associated->bssid, req->bssid)) {
                ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
-                                      req->reason_code, true, frame_buf);
+                                      req->reason_code, tx, frame_buf);
        } else {
                drv_mgd_prepare_tx(sdata->local, sdata);
                ieee80211_send_deauth_disassoc(sdata, req->bssid,
                                               IEEE80211_STYPE_DEAUTH,
-                                              req->reason_code, true,
+                                              req->reason_code, tx,
                                               frame_buf);
        }
 
index 83608ac167801f1c06fc55dd3ab53370d947cbc7..c349f3aaf59ed0d62c497634dfae5885aa5cc856 100644 (file)
@@ -107,6 +107,9 @@ void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local,
 {
        struct ieee80211_sub_if_data *sdata;
 
+       if (WARN_ON(local->use_chanctx))
+               return;
+
        /*
         * notify the AP about us leaving the channel and stop all
         * STA interfaces.
@@ -145,6 +148,9 @@ void ieee80211_offchannel_return(struct ieee80211_local *local,
 {
        struct ieee80211_sub_if_data *sdata;
 
+       if (WARN_ON(local->use_chanctx))
+               return;
+
        mutex_lock(&local->iflist_mtx);
        list_for_each_entry(sdata, &local->interfaces, list) {
                if (sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE)
@@ -193,7 +199,8 @@ void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc)
 
        if (roc->mgmt_tx_cookie) {
                if (!WARN_ON(!roc->frame)) {
-                       ieee80211_tx_skb(roc->sdata, roc->frame);
+                       ieee80211_tx_skb_tid_band(roc->sdata, roc->frame, 7,
+                                                 roc->chan->band);
                        roc->frame = NULL;
                }
        } else {
index 5c572e7a1a71dc76949b993f9f57e79223533f49..9f404ac901ab60cb3d9ee69e0eb9d7516e8484f5 100644 (file)
@@ -135,6 +135,8 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
                ieee80211_bss_info_change_notify(sdata,
                        BSS_CHANGED_BEACON_ENABLED);
 
+               /* the interface is leaving the channel and is removed */
+               ieee80211_vif_release_channel(sdata);
                drv_remove_interface(local, sdata);
        }
 
index 10de668eb9f64b8e6f3f9509f7db9ad666f36af1..ec198ef6aa8af2a05ba84e3871a6ebf06c411089 100644 (file)
@@ -52,11 +52,21 @@ static inline void rate_control_rate_init(struct sta_info *sta)
        struct ieee80211_sta *ista = &sta->sta;
        void *priv_sta = sta->rate_ctrl_priv;
        struct ieee80211_supported_band *sband;
+       struct ieee80211_chanctx_conf *chanctx_conf;
 
        if (!ref)
                return;
 
-       sband = local->hw.wiphy->bands[local->oper_channel->band];
+       rcu_read_lock();
+
+       chanctx_conf = rcu_dereference(sta->sdata->vif.chanctx_conf);
+       if (WARN_ON(!chanctx_conf)) {
+               rcu_read_unlock();
+               return;
+       }
+
+       sband = local->hw.wiphy->bands[chanctx_conf->channel->band];
+       rcu_read_unlock();
 
        ref->ops->rate_init(ref->priv, sband, ista, priv_sta);
        set_sta_flag(sta, WLAN_STA_RATE_CONTROL);
index 61c621e9273fe70c26978d42433d58fca60a80b8..d07216ab5f720df9c13647c9a9b57008e4614dfc 100644 (file)
@@ -1141,12 +1141,19 @@ ieee80211_rx_h_check_more_data(struct ieee80211_rx_data *rx)
        return RX_CONTINUE;
 }
 
-static void ap_sta_ps_start(struct sta_info *sta)
+static void sta_ps_start(struct sta_info *sta)
 {
        struct ieee80211_sub_if_data *sdata = sta->sdata;
        struct ieee80211_local *local = sdata->local;
+       struct ps_data *ps;
 
-       atomic_inc(&sdata->bss->num_sta_ps);
+       if (sta->sdata->vif.type == NL80211_IFTYPE_AP ||
+           sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+               ps = &sdata->bss->ps;
+       else
+               return;
+
+       atomic_inc(&ps->num_sta_ps);
        set_sta_flag(sta, WLAN_STA_PS_STA);
        if (!(local->hw.flags & IEEE80211_HW_AP_LINK_PS))
                drv_sta_notify(local, sdata, STA_NOTIFY_SLEEP, &sta->sta);
@@ -1154,7 +1161,7 @@ static void ap_sta_ps_start(struct sta_info *sta)
               sta->sta.addr, sta->sta.aid);
 }
 
-static void ap_sta_ps_end(struct sta_info *sta)
+static void sta_ps_end(struct sta_info *sta)
 {
        ps_dbg(sta->sdata, "STA %pM aid %d exits power save mode\n",
               sta->sta.addr, sta->sta.aid);
@@ -1181,9 +1188,9 @@ int ieee80211_sta_ps_transition(struct ieee80211_sta *sta, bool start)
                return -EINVAL;
 
        if (start)
-               ap_sta_ps_start(sta_inf);
+               sta_ps_start(sta_inf);
        else
-               ap_sta_ps_end(sta_inf);
+               sta_ps_end(sta_inf);
 
        return 0;
 }
@@ -1335,10 +1342,10 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
                         */
                        if (ieee80211_is_data(hdr->frame_control) &&
                            !ieee80211_has_pm(hdr->frame_control))
-                               ap_sta_ps_end(sta);
+                               sta_ps_end(sta);
                } else {
                        if (ieee80211_has_pm(hdr->frame_control))
-                               ap_sta_ps_start(sta);
+                               sta_ps_start(sta);
                }
        }
 
@@ -1384,9 +1391,7 @@ ieee80211_reassemble_add(struct ieee80211_sub_if_data *sdata,
                         struct sk_buff **skb)
 {
        struct ieee80211_fragment_entry *entry;
-       int idx;
 
-       idx = sdata->fragment_next;
        entry = &sdata->fragments[sdata->fragment_next++];
        if (sdata->fragment_next >= IEEE80211_FRAGMENT_MAX)
                sdata->fragment_next = 0;
@@ -3010,8 +3015,7 @@ void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb)
 
        WARN_ON_ONCE(softirq_count() == 0);
 
-       if (WARN_ON(status->band < 0 ||
-                   status->band >= IEEE80211_NUM_BANDS))
+       if (WARN_ON(status->band >= IEEE80211_NUM_BANDS))
                goto drop;
 
        sband = local->hw.wiphy->bands[status->band];
@@ -3056,8 +3060,7 @@ void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb)
                         * hardware error. The driver should catch hardware
                         * errors.
                         */
-                       if (WARN((status->rate_idx < 0 ||
-                                status->rate_idx > 76),
+                       if (WARN(status->rate_idx > 76,
                                 "Rate marked as an HT rate but passed "
                                 "status->rate_idx is not "
                                 "an MCS index [0-76]: %d (0x%02x)\n",
@@ -3065,8 +3068,7 @@ void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb)
                                 status->rate_idx))
                                goto drop;
                } else {
-                       if (WARN_ON(status->rate_idx < 0 ||
-                                   status->rate_idx >= sband->n_bitrates))
+                       if (WARN_ON(status->rate_idx >= sband->n_bitrates))
                                goto drop;
                        rate = &sband->bitrates[status->rate_idx];
                }
index c4cdbde24fd3a70db1141c9460f617710daf98e2..13d23299e69605013d7dce3897816bea23a4d731 100644 (file)
@@ -336,6 +336,10 @@ EXPORT_SYMBOL(ieee80211_scan_completed);
 
 static int ieee80211_start_sw_scan(struct ieee80211_local *local)
 {
+       /* Software scan is not supported in multi-channel cases */
+       if (local->use_chanctx)
+               return -EOPNOTSUPP;
+
        /*
         * Hardware/driver doesn't support hw_scan, so use software
         * scanning instead. First send a nullfunc frame with power save
@@ -417,7 +421,7 @@ static void ieee80211_scan_state_send_probe(struct ieee80211_local *local,
                        local->scan_req->ie, local->scan_req->ie_len,
                        local->scan_req->rates[band], false,
                        local->scan_req->no_cck,
-                       local->hw.conf.channel);
+                       local->hw.conf.channel, true);
 
        /*
         * After sending probe requests, wait for probe responses
@@ -462,6 +466,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
                        sizeof(*local->hw_scan_req) +
                        req->n_channels * sizeof(req->channels[0]);
                local->hw_scan_req->ie = ies;
+               local->hw_scan_req->flags = req->flags;
 
                local->hw_scan_band = 0;
 
@@ -480,7 +485,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
        if (local->ops->hw_scan) {
                __set_bit(SCAN_HW_SCANNING, &local->scanning);
        } else if ((req->n_channels == 1) &&
-                  (req->channels[0] == local->oper_channel)) {
+                  (req->channels[0] == local->_oper_channel)) {
                /*
                 * If we are scanning only on the operating channel
                 * then we do not need to stop normal activities
@@ -562,6 +567,7 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local,
        unsigned long min_beacon_int = 0;
        struct ieee80211_sub_if_data *sdata;
        struct ieee80211_channel *next_chan;
+       enum mac80211_scan_state next_scan_state;
 
        /*
         * check if at least one STA interface is associated,
@@ -620,10 +626,18 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local,
                        usecs_to_jiffies(min_beacon_int * 1024) *
                        local->hw.conf.listen_interval);
 
-       if (associated && (!tx_empty || bad_latency || listen_int_exceeded))
-               local->next_scan_state = SCAN_SUSPEND;
-       else
-               local->next_scan_state = SCAN_SET_CHANNEL;
+       if (associated && !tx_empty) {
+               if (local->scan_req->flags & NL80211_SCAN_FLAG_LOW_PRIORITY)
+                       next_scan_state = SCAN_ABORT;
+               else
+                       next_scan_state = SCAN_SUSPEND;
+       } else if (associated && (bad_latency || listen_int_exceeded)) {
+               next_scan_state = SCAN_SUSPEND;
+       } else {
+               next_scan_state = SCAN_SET_CHANNEL;
+       }
+
+       local->next_scan_state = next_scan_state;
 
        *next_delay = 0;
 }
@@ -794,6 +808,9 @@ void ieee80211_scan_work(struct work_struct *work)
                case SCAN_RESUME:
                        ieee80211_scan_state_resume(local, &next_delay);
                        break;
+               case SCAN_ABORT:
+                       aborted = true;
+                       goto out_complete;
                }
        } while (next_delay == 0);
 
index 797dd36a220d92ac549067a9cd4d59a7ebfc09a3..f7bb54f9ab72178c4b0ac57c432fe99c17f59b34 100644 (file)
@@ -98,6 +98,7 @@ static void free_sta_work(struct work_struct *wk)
        struct tid_ampdu_tx *tid_tx;
        struct ieee80211_sub_if_data *sdata = sta->sdata;
        struct ieee80211_local *local = sdata->local;
+       struct ps_data *ps;
 
        /*
         * At this point, when being called as call_rcu callback,
@@ -107,11 +108,15 @@ static void free_sta_work(struct work_struct *wk)
         */
 
        if (test_sta_flag(sta, WLAN_STA_PS_STA)) {
-               BUG_ON(!sdata->bss);
+               if (sta->sdata->vif.type == NL80211_IFTYPE_AP ||
+                   sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+                       ps = &sdata->bss->ps;
+               else
+                       return;
 
                clear_sta_flag(sta, WLAN_STA_PS_STA);
 
-               atomic_dec(&sdata->bss->num_sta_ps);
+               atomic_dec(&ps->num_sta_ps);
                sta_info_recalc_tim(sta);
        }
 
@@ -502,22 +507,22 @@ int sta_info_insert(struct sta_info *sta)
        return err;
 }
 
-static inline void __bss_tim_set(struct ieee80211_if_ap *bss, u16 aid)
+static inline void __bss_tim_set(u8 *tim, u16 id)
 {
        /*
         * This format has been mandated by the IEEE specifications,
         * so this line may not be changed to use the __set_bit() format.
         */
-       bss->tim[aid / 8] |= (1 << (aid % 8));
+       tim[id / 8] |= (1 << (id % 8));
 }
 
-static inline void __bss_tim_clear(struct ieee80211_if_ap *bss, u16 aid)
+static inline void __bss_tim_clear(u8 *tim, u16 id)
 {
        /*
         * This format has been mandated by the IEEE specifications,
         * so this line may not be changed to use the __clear_bit() format.
         */
-       bss->tim[aid / 8] &= ~(1 << (aid % 8));
+       tim[id / 8] &= ~(1 << (id % 8));
 }
 
 static unsigned long ieee80211_tids_for_ac(int ac)
@@ -541,14 +546,23 @@ static unsigned long ieee80211_tids_for_ac(int ac)
 void sta_info_recalc_tim(struct sta_info *sta)
 {
        struct ieee80211_local *local = sta->local;
-       struct ieee80211_if_ap *bss = sta->sdata->bss;
+       struct ps_data *ps;
        unsigned long flags;
        bool indicate_tim = false;
        u8 ignore_for_tim = sta->sta.uapsd_queues;
        int ac;
+       u16 id;
+
+       if (sta->sdata->vif.type == NL80211_IFTYPE_AP ||
+           sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) {
+               if (WARN_ON_ONCE(!sta->sdata->bss))
+                       return;
 
-       if (WARN_ON_ONCE(!sta->sdata->bss))
+               ps = &sta->sdata->bss->ps;
+               id = sta->sta.aid;
+       } else {
                return;
+       }
 
        /* No need to do anything if the driver does all */
        if (local->hw.flags & IEEE80211_HW_AP_LINK_PS)
@@ -587,9 +601,9 @@ void sta_info_recalc_tim(struct sta_info *sta)
        spin_lock_irqsave(&local->tim_lock, flags);
 
        if (indicate_tim)
-               __bss_tim_set(bss, sta->sta.aid);
+               __bss_tim_set(ps->tim, id);
        else
-               __bss_tim_clear(bss, sta->sta.aid);
+               __bss_tim_clear(ps->tim, id);
 
        if (local->ops->set_tim) {
                local->tim_in_locked_section = true;
@@ -650,7 +664,7 @@ static bool sta_info_cleanup_expire_buffered_ac(struct ieee80211_local *local,
                 */
                if (!skb)
                        break;
-               dev_kfree_skb(skb);
+               ieee80211_free_txskb(&local->hw, skb);
        }
 
        /*
@@ -679,7 +693,7 @@ static bool sta_info_cleanup_expire_buffered_ac(struct ieee80211_local *local,
                local->total_ps_buffered--;
                ps_dbg(sta->sdata, "Buffered frame expired (STA %pM)\n",
                       sta->sta.addr);
-               dev_kfree_skb(skb);
+               ieee80211_free_txskb(&local->hw, skb);
        }
 
        /*
@@ -893,8 +907,8 @@ void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata,
                        continue;
 
                if (time_after(jiffies, sta->last_rx + exp_time)) {
-                       ibss_dbg(sdata, "expiring inactive STA %pM\n",
-                                sta->sta.addr);
+                       sta_dbg(sta->sdata, "expiring inactive STA %pM\n",
+                               sta->sta.addr);
                        WARN_ON(__sta_info_destroy(sta));
                }
        }
@@ -948,10 +962,17 @@ static void clear_sta_ps_flags(void *_sta)
 {
        struct sta_info *sta = _sta;
        struct ieee80211_sub_if_data *sdata = sta->sdata;
+       struct ps_data *ps;
+
+       if (sdata->vif.type == NL80211_IFTYPE_AP ||
+           sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+               ps = &sdata->bss->ps;
+       else
+               return;
 
        clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
        if (test_and_clear_sta_flag(sta, WLAN_STA_PS_STA))
-               atomic_dec(&sdata->bss->num_sta_ps);
+               atomic_dec(&ps->num_sta_ps);
 }
 
 /* powersave support code */
@@ -1008,6 +1029,7 @@ static void ieee80211_send_null_response(struct ieee80211_sub_if_data *sdata,
        __le16 fc;
        bool qos = test_sta_flag(sta, WLAN_STA_WME);
        struct ieee80211_tx_info *info;
+       struct ieee80211_chanctx_conf *chanctx_conf;
 
        if (qos) {
                fc = cpu_to_le16(IEEE80211_FTYPE_DATA |
@@ -1057,7 +1079,16 @@ static void ieee80211_send_null_response(struct ieee80211_sub_if_data *sdata,
 
        drv_allow_buffered_frames(local, sta, BIT(tid), 1, reason, false);
 
-       ieee80211_xmit(sdata, skb);
+       rcu_read_lock();
+       chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
+       if (WARN_ON(!chanctx_conf)) {
+               rcu_read_unlock();
+               kfree_skb(skb);
+               return;
+       }
+
+       ieee80211_xmit(sdata, skb, chanctx_conf->channel->band);
+       rcu_read_unlock();
 }
 
 static void
index 3af0cc4130f1986e1cf672a9246830d478e222e9..21fa5c72ea143b35617a281a9f2ee5ca0393f12d 100644 (file)
@@ -189,30 +189,31 @@ static void ieee80211_frame_acked(struct sta_info *sta, struct sk_buff *skb)
        }
 
        if (ieee80211_is_action(mgmt->frame_control) &&
-           sdata->vif.type == NL80211_IFTYPE_STATION &&
            mgmt->u.action.category == WLAN_CATEGORY_HT &&
-           mgmt->u.action.u.ht_smps.action == WLAN_HT_ACTION_SMPS) {
+           mgmt->u.action.u.ht_smps.action == WLAN_HT_ACTION_SMPS &&
+           sdata->vif.type == NL80211_IFTYPE_STATION &&
+           ieee80211_sdata_running(sdata)) {
                /*
                 * This update looks racy, but isn't -- if we come
                 * here we've definitely got a station that we're
                 * talking to, and on a managed interface that can
                 * only be the AP. And the only other place updating
-                * this variable is before we're associated.
+                * this variable in managed mode is before association.
                 */
                switch (mgmt->u.action.u.ht_smps.smps_control) {
                case WLAN_HT_SMPS_CONTROL_DYNAMIC:
-                       sta->sdata->u.mgd.ap_smps = IEEE80211_SMPS_DYNAMIC;
+                       sdata->smps_mode = IEEE80211_SMPS_DYNAMIC;
                        break;
                case WLAN_HT_SMPS_CONTROL_STATIC:
-                       sta->sdata->u.mgd.ap_smps = IEEE80211_SMPS_STATIC;
+                       sdata->smps_mode = IEEE80211_SMPS_STATIC;
                        break;
                case WLAN_HT_SMPS_CONTROL_DISABLED:
                default: /* shouldn't happen since we don't send that */
-                       sta->sdata->u.mgd.ap_smps = IEEE80211_SMPS_OFF;
+                       sdata->smps_mode = IEEE80211_SMPS_OFF;
                        break;
                }
 
-               ieee80211_queue_work(&local->hw, &local->recalc_smps);
+               ieee80211_queue_work(&local->hw, &sdata->recalc_smps);
        }
 }
 
index 18d9c8a52e9e72d98686778bb7bcab974119e638..629364705f7b193f210980217d18223a3683e474 100644 (file)
 #define VIF_PR_FMT     " vif:%s(%d%s)"
 #define VIF_PR_ARG     __get_str(vif_name), __entry->vif_type, __entry->p2p ? "/p2p" : ""
 
+#define CHANCTX_ENTRY  __field(int, freq)                                      \
+                       __field(int, chantype)                                  \
+                       __field(u8, rx_chains_static)                           \
+                       __field(u8, rx_chains_dynamic)
+#define CHANCTX_ASSIGN __entry->freq = ctx->conf.channel->center_freq;         \
+                       __entry->chantype = ctx->conf.channel_type;             \
+                       __entry->rx_chains_static = ctx->conf.rx_chains_static; \
+                       __entry->rx_chains_dynamic = ctx->conf.rx_chains_dynamic
+#define CHANCTX_PR_FMT " freq:%d MHz chantype:%d chains:%d/%d"
+#define CHANCTX_PR_ARG __entry->freq, __entry->chantype,                       \
+                       __entry->rx_chains_static, __entry->rx_chains_dynamic
+
+
+
 /*
  * Tracing for driver callbacks.
  */
@@ -1256,6 +1270,104 @@ DEFINE_EVENT(local_sdata_evt, drv_mgd_prepare_tx,
        TP_ARGS(local, sdata)
 );
 
+DECLARE_EVENT_CLASS(local_chanctx,
+       TP_PROTO(struct ieee80211_local *local,
+                struct ieee80211_chanctx *ctx),
+
+       TP_ARGS(local, ctx),
+
+       TP_STRUCT__entry(
+               LOCAL_ENTRY
+               CHANCTX_ENTRY
+       ),
+
+       TP_fast_assign(
+               LOCAL_ASSIGN;
+               CHANCTX_ASSIGN;
+       ),
+
+       TP_printk(
+               LOCAL_PR_FMT CHANCTX_PR_FMT,
+               LOCAL_PR_ARG, CHANCTX_PR_ARG
+       )
+);
+
+DEFINE_EVENT(local_chanctx, drv_add_chanctx,
+       TP_PROTO(struct ieee80211_local *local,
+                struct ieee80211_chanctx *ctx),
+       TP_ARGS(local, ctx)
+);
+
+DEFINE_EVENT(local_chanctx, drv_remove_chanctx,
+       TP_PROTO(struct ieee80211_local *local,
+                struct ieee80211_chanctx *ctx),
+       TP_ARGS(local, ctx)
+);
+
+TRACE_EVENT(drv_change_chanctx,
+       TP_PROTO(struct ieee80211_local *local,
+                struct ieee80211_chanctx *ctx,
+                u32 changed),
+
+       TP_ARGS(local, ctx, changed),
+
+       TP_STRUCT__entry(
+               LOCAL_ENTRY
+               CHANCTX_ENTRY
+               __field(u32, changed)
+       ),
+
+       TP_fast_assign(
+               LOCAL_ASSIGN;
+               CHANCTX_ASSIGN;
+               __entry->changed = changed;
+       ),
+
+       TP_printk(
+               LOCAL_PR_FMT CHANCTX_PR_FMT " changed:%#x",
+               LOCAL_PR_ARG, CHANCTX_PR_ARG, __entry->changed
+       )
+);
+
+DECLARE_EVENT_CLASS(local_sdata_chanctx,
+       TP_PROTO(struct ieee80211_local *local,
+                struct ieee80211_sub_if_data *sdata,
+                struct ieee80211_chanctx *ctx),
+
+       TP_ARGS(local, sdata, ctx),
+
+       TP_STRUCT__entry(
+               LOCAL_ENTRY
+               VIF_ENTRY
+               CHANCTX_ENTRY
+       ),
+
+       TP_fast_assign(
+               LOCAL_ASSIGN;
+               VIF_ASSIGN;
+               CHANCTX_ASSIGN;
+       ),
+
+       TP_printk(
+               LOCAL_PR_FMT VIF_PR_FMT CHANCTX_PR_FMT,
+               LOCAL_PR_ARG, VIF_PR_ARG, CHANCTX_PR_ARG
+       )
+);
+
+DEFINE_EVENT(local_sdata_chanctx, drv_assign_vif_chanctx,
+       TP_PROTO(struct ieee80211_local *local,
+                struct ieee80211_sub_if_data *sdata,
+                struct ieee80211_chanctx *ctx),
+       TP_ARGS(local, sdata, ctx)
+);
+
+DEFINE_EVENT(local_sdata_chanctx, drv_unassign_vif_chanctx,
+       TP_PROTO(struct ieee80211_local *local,
+                struct ieee80211_sub_if_data *sdata,
+                struct ieee80211_chanctx *ctx),
+       TP_ARGS(local, sdata, ctx)
+);
+
 /*
  * Tracing for API calls that drivers call.
  */
index c9bf83f36657c3ca9929e64d2fd27c47a6486e3a..065f81cb5618389801abb9c4fb5fa9b4bb01250d 100644 (file)
@@ -324,22 +324,20 @@ static void purge_old_ps_buffers(struct ieee80211_local *local)
        struct ieee80211_sub_if_data *sdata;
        struct sta_info *sta;
 
-       /*
-        * virtual interfaces are protected by RCU
-        */
-       rcu_read_lock();
-
        list_for_each_entry_rcu(sdata, &local->interfaces, list) {
-               struct ieee80211_if_ap *ap;
-               if (sdata->vif.type != NL80211_IFTYPE_AP)
+               struct ps_data *ps;
+
+               if (sdata->vif.type == NL80211_IFTYPE_AP)
+                       ps = &sdata->u.ap.ps;
+               else
                        continue;
-               ap = &sdata->u.ap;
-               skb = skb_dequeue(&ap->ps_bc_buf);
+
+               skb = skb_dequeue(&ps->bc_buf);
                if (skb) {
                        purged++;
                        dev_kfree_skb(skb);
                }
-               total += skb_queue_len(&ap->ps_bc_buf);
+               total += skb_queue_len(&ps->bc_buf);
        }
 
        /*
@@ -360,8 +358,6 @@ static void purge_old_ps_buffers(struct ieee80211_local *local)
                }
        }
 
-       rcu_read_unlock();
-
        local->total_ps_buffered = total;
        ps_dbg_hw(&local->hw, "PS buffers full - purged %d frames\n", purged);
 }
@@ -371,6 +367,7 @@ ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx)
 {
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
+       struct ps_data *ps;
 
        /*
         * broadcast/multicast frame
@@ -380,16 +377,24 @@ ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx)
         * This is done either by the hardware or us.
         */
 
-       /* powersaving STAs only in AP/VLAN mode */
-       if (!tx->sdata->bss)
+       /* powersaving STAs currently only in AP/VLAN mode */
+       if (tx->sdata->vif.type == NL80211_IFTYPE_AP ||
+           tx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) {
+               if (!tx->sdata->bss)
+                       return TX_CONTINUE;
+
+               ps = &tx->sdata->bss->ps;
+       } else {
                return TX_CONTINUE;
+       }
+
 
        /* no buffering for ordered frames */
        if (ieee80211_has_order(hdr->frame_control))
                return TX_CONTINUE;
 
        /* no stations in PS mode */
-       if (!atomic_read(&tx->sdata->bss->num_sta_ps))
+       if (!atomic_read(&ps->num_sta_ps))
                return TX_CONTINUE;
 
        info->flags |= IEEE80211_TX_CTL_SEND_AFTER_DTIM;
@@ -404,14 +409,14 @@ ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx)
        if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER)
                purge_old_ps_buffers(tx->local);
 
-       if (skb_queue_len(&tx->sdata->bss->ps_bc_buf) >= AP_MAX_BC_BUFFER) {
+       if (skb_queue_len(&ps->bc_buf) >= AP_MAX_BC_BUFFER) {
                ps_dbg(tx->sdata,
                       "BC TX buffer full - dropping the oldest frame\n");
-               dev_kfree_skb(skb_dequeue(&tx->sdata->bss->ps_bc_buf));
+               dev_kfree_skb(skb_dequeue(&ps->bc_buf));
        } else
                tx->local->total_ps_buffered++;
 
-       skb_queue_tail(&tx->sdata->bss->ps_bc_buf, tx->skb);
+       skb_queue_tail(&ps->bc_buf, tx->skb);
 
        return TX_QUEUED;
 }
@@ -951,7 +956,6 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx)
        fragnum = 0;
 
        skb_queue_walk(&tx->skbs, skb) {
-               int next_len;
                const __le16 morefrags = cpu_to_le16(IEEE80211_FCTL_MOREFRAGS);
 
                hdr = (void *)skb->data;
@@ -970,7 +974,6 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx)
                        info->flags &= ~IEEE80211_TX_CTL_RATE_CTRL_PROBE;
                } else {
                        hdr->frame_control &= ~morefrags;
-                       next_len = 0;
                }
                hdr->seq_ctrl |= cpu_to_le16(fragnum & IEEE80211_SCTL_FRAG);
                fragnum++;
@@ -1372,7 +1375,8 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
  * Returns false if the frame couldn't be transmitted but was queued instead.
  */
 static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata,
-                        struct sk_buff *skb, bool txpending)
+                        struct sk_buff *skb, bool txpending,
+                        enum ieee80211_band band)
 {
        struct ieee80211_local *local = sdata->local;
        struct ieee80211_tx_data tx;
@@ -1386,20 +1390,18 @@ static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata,
                return true;
        }
 
-       rcu_read_lock();
-
        /* initialises tx */
        led_len = skb->len;
        res_prepare = ieee80211_tx_prepare(sdata, &tx, skb);
 
        if (unlikely(res_prepare == TX_DROP)) {
                ieee80211_free_txskb(&local->hw, skb);
-               goto out;
+               return true;
        } else if (unlikely(res_prepare == TX_QUEUED)) {
-               goto out;
+               return true;
        }
 
-       info->band = local->hw.conf.channel->band;
+       info->band = band;
 
        /* set up hw_queue value early */
        if (!(info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) ||
@@ -1410,8 +1412,7 @@ static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata,
        if (!invoke_tx_handlers(&tx))
                result = __ieee80211_tx(local, &tx.skbs, led_len,
                                        tx.sta, txpending);
- out:
-       rcu_read_unlock();
+
        return result;
 }
 
@@ -1446,7 +1447,8 @@ static int ieee80211_skb_resize(struct ieee80211_sub_if_data *sdata,
        return 0;
 }
 
-void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
+void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb,
+                   enum ieee80211_band band)
 {
        struct ieee80211_local *local = sdata->local;
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
@@ -1454,8 +1456,6 @@ void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
        int headroom;
        bool may_encrypt;
 
-       rcu_read_lock();
-
        may_encrypt = !(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT);
 
        headroom = local->tx_headroom;
@@ -1466,7 +1466,6 @@ void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
 
        if (ieee80211_skb_resize(sdata, skb, headroom, may_encrypt)) {
                ieee80211_free_txskb(&local->hw, skb);
-               rcu_read_unlock();
                return;
        }
 
@@ -1478,13 +1477,11 @@ void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
            !is_multicast_ether_addr(hdr->addr1) &&
            mesh_nexthop_resolve(skb, sdata)) {
                /* skb queued: don't free */
-               rcu_read_unlock();
                return;
        }
 
        ieee80211_set_qos_hdr(sdata, skb);
-       ieee80211_tx(sdata, skb, false);
-       rcu_read_unlock();
+       ieee80211_tx(sdata, skb, false, band);
 }
 
 static bool ieee80211_parse_tx_radiotap(struct sk_buff *skb)
@@ -1574,7 +1571,8 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb,
                                         struct net_device *dev)
 {
        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-       struct ieee80211_channel *chan = local->hw.conf.channel;
+       struct ieee80211_chanctx_conf *chanctx_conf;
+       struct ieee80211_channel *chan;
        struct ieee80211_radiotap_header *prthdr =
                (struct ieee80211_radiotap_header *)skb->data;
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
@@ -1583,26 +1581,6 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb,
        u16 len_rthdr;
        int hdrlen;
 
-       /*
-        * Frame injection is not allowed if beaconing is not allowed
-        * or if we need radar detection. Beaconing is usually not allowed when
-        * the mode or operation (Adhoc, AP, Mesh) does not support DFS.
-        * Passive scan is also used in world regulatory domains where
-        * your country is not known and as such it should be treated as
-        * NO TX unless the channel is explicitly allowed in which case
-        * your current regulatory domain would not have the passive scan
-        * flag.
-        *
-        * Since AP mode uses monitor interfaces to inject/TX management
-        * frames we can make AP mode the exception to this rule once it
-        * supports radar detection as its implementation can deal with
-        * radar detection by itself. We can do that later by adding a
-        * monitor flag interfaces used for AP support.
-        */
-       if ((chan->flags & (IEEE80211_CHAN_NO_IBSS | IEEE80211_CHAN_RADAR |
-            IEEE80211_CHAN_PASSIVE_SCAN)))
-               goto fail;
-
        /* check for not even having the fixed radiotap header part */
        if (unlikely(skb->len < sizeof(struct ieee80211_radiotap_header)))
                goto fail; /* too short to be possibly valid */
@@ -1688,11 +1666,45 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb,
                }
        }
 
-       ieee80211_xmit(sdata, skb);
+       chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
+       if (!chanctx_conf) {
+               tmp_sdata = rcu_dereference(local->monitor_sdata);
+               if (tmp_sdata)
+                       chanctx_conf =
+                               rcu_dereference(tmp_sdata->vif.chanctx_conf);
+       }
+       if (!chanctx_conf)
+               goto fail_rcu;
+
+       chan = chanctx_conf->channel;
+
+       /*
+        * Frame injection is not allowed if beaconing is not allowed
+        * or if we need radar detection. Beaconing is usually not allowed when
+        * the mode or operation (Adhoc, AP, Mesh) does not support DFS.
+        * Passive scan is also used in world regulatory domains where
+        * your country is not known and as such it should be treated as
+        * NO TX unless the channel is explicitly allowed in which case
+        * your current regulatory domain would not have the passive scan
+        * flag.
+        *
+        * Since AP mode uses monitor interfaces to inject/TX management
+        * frames we can make AP mode the exception to this rule once it
+        * supports radar detection as its implementation can deal with
+        * radar detection by itself. We can do that later by adding a
+        * monitor flag interfaces used for AP support.
+        */
+       if ((chan->flags & (IEEE80211_CHAN_NO_IBSS | IEEE80211_CHAN_RADAR |
+                           IEEE80211_CHAN_PASSIVE_SCAN)))
+               goto fail_rcu;
+
+       ieee80211_xmit(sdata, skb, chan->band);
        rcu_read_unlock();
 
        return NETDEV_TX_OK;
 
+fail_rcu:
+       rcu_read_unlock();
 fail:
        dev_kfree_skb(skb);
        return NETDEV_TX_OK; /* meaning, we dealt with the skb */
@@ -1734,6 +1746,9 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
        bool multicast;
        u32 info_flags = 0;
        u16 info_id = 0;
+       struct ieee80211_chanctx_conf *chanctx_conf;
+       struct ieee80211_sub_if_data *ap_sdata;
+       enum ieee80211_band band;
 
        if (unlikely(skb->len < ETH_HLEN))
                goto fail;
@@ -1743,9 +1758,10 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
        ethertype = (skb->data[12] << 8) | skb->data[13];
        fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA);
 
+       rcu_read_lock();
+
        switch (sdata->vif.type) {
        case NL80211_IFTYPE_AP_VLAN:
-               rcu_read_lock();
                sta = rcu_dereference(sdata->u.vlan.sta);
                if (sta) {
                        fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS);
@@ -1758,7 +1774,12 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
                        authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED);
                        wme_sta = test_sta_flag(sta, WLAN_STA_WME);
                }
-               rcu_read_unlock();
+               ap_sdata = container_of(sdata->bss, struct ieee80211_sub_if_data,
+                                       u.ap);
+               chanctx_conf = rcu_dereference(ap_sdata->vif.chanctx_conf);
+               if (!chanctx_conf)
+                       goto fail_rcu;
+               band = chanctx_conf->channel->band;
                if (sta)
                        break;
                /* fall through */
@@ -1769,6 +1790,11 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
                memcpy(hdr.addr2, sdata->vif.addr, ETH_ALEN);
                memcpy(hdr.addr3, skb->data + ETH_ALEN, ETH_ALEN);
                hdrlen = 24;
+               if (sdata->vif.type == NL80211_IFTYPE_AP)
+                       chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
+               if (!chanctx_conf)
+                       goto fail_rcu;
+               band = chanctx_conf->channel->band;
                break;
        case NL80211_IFTYPE_WDS:
                fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS);
@@ -1778,15 +1804,20 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
                memcpy(hdr.addr3, skb->data, ETH_ALEN);
                memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN);
                hdrlen = 30;
+               /*
+                * This is the exception! WDS style interfaces are prohibited
+                * when channel contexts are in used so this must be valid
+                */
+               band = local->hw.conf.channel->band;
                break;
 #ifdef CONFIG_MAC80211_MESH
        case NL80211_IFTYPE_MESH_POINT:
                if (!sdata->u.mesh.mshcfg.dot11MeshTTL) {
                        /* Do not send frames with mesh_ttl == 0 */
                        sdata->u.mesh.mshstats.dropped_frames_ttl++;
-                       goto fail;
+                       goto fail_rcu;
                }
-               rcu_read_lock();
+
                if (!is_multicast_ether_addr(skb->data)) {
                        mpath = mesh_path_lookup(skb->data, sdata);
                        if (!mpath)
@@ -1803,7 +1834,6 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
                    !(mppath && !ether_addr_equal(mppath->mpp, skb->data))) {
                        hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc,
                                        skb->data, skb->data + ETH_ALEN);
-                       rcu_read_unlock();
                        meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr,
                                        sdata, NULL, NULL);
                } else {
@@ -1819,7 +1849,6 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
                                mesh_da = mppath->mpp;
                        else if (mpath)
                                mesh_da = mpath->dst;
-                       rcu_read_unlock();
 
                        hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc,
                                        mesh_da, sdata->vif.addr);
@@ -1839,13 +1868,16 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
                                                        skb->data + ETH_ALEN);
 
                }
+               chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
+               if (!chanctx_conf)
+                       goto fail_rcu;
+               band = chanctx_conf->channel->band;
                break;
 #endif
        case NL80211_IFTYPE_STATION:
                if (sdata->wdev.wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS) {
                        bool tdls_peer = false;
 
-                       rcu_read_lock();
                        sta = sta_info_get(sdata, skb->data);
                        if (sta) {
                                authorized = test_sta_flag(sta,
@@ -1856,7 +1888,6 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
                                tdls_auth = test_sta_flag(sta,
                                                WLAN_STA_TDLS_PEER_AUTH);
                        }
-                       rcu_read_unlock();
 
                        /*
                         * If the TDLS link is enabled, send everything
@@ -1871,7 +1902,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
                if (tdls_direct) {
                        /* link during setup - throw out frames to peer */
                        if (!tdls_auth)
-                               goto fail;
+                               goto fail_rcu;
 
                        /* DA SA BSSID */
                        memcpy(hdr.addr1, skb->data, ETH_ALEN);
@@ -1896,6 +1927,10 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
                        memcpy(hdr.addr3, skb->data, ETH_ALEN);
                        hdrlen = 24;
                }
+               chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
+               if (!chanctx_conf)
+                       goto fail_rcu;
+               band = chanctx_conf->channel->band;
                break;
        case NL80211_IFTYPE_ADHOC:
                /* DA SA BSSID */
@@ -1903,9 +1938,13 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
                memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN);
                memcpy(hdr.addr3, sdata->u.ibss.bssid, ETH_ALEN);
                hdrlen = 24;
+               chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
+               if (!chanctx_conf)
+                       goto fail_rcu;
+               band = chanctx_conf->channel->band;
                break;
        default:
-               goto fail;
+               goto fail_rcu;
        }
 
        /*
@@ -1915,13 +1954,11 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
         */
        multicast = is_multicast_ether_addr(hdr.addr1);
        if (!multicast) {
-               rcu_read_lock();
                sta = sta_info_get(sdata, hdr.addr1);
                if (sta) {
                        authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED);
                        wme_sta = test_sta_flag(sta, WLAN_STA_WME);
                }
-               rcu_read_unlock();
        }
 
        /* For mesh, the use of the QoS header is mandatory */
@@ -1949,7 +1986,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
 
                I802_DEBUG_INC(local->tx_handlers_drop_unauth_port);
 
-               goto fail;
+               goto fail_rcu;
        }
 
        if (unlikely(!multicast && skb->sk &&
@@ -2004,7 +2041,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
                kfree_skb(tmp_skb);
 
                if (!skb)
-                       goto fail;
+                       goto fail_rcu;
        }
 
        hdr.frame_control = fc;
@@ -2052,7 +2089,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
                head_need = max_t(int, 0, head_need);
                if (ieee80211_skb_resize(sdata, skb, head_need, true)) {
                        ieee80211_free_txskb(&local->hw, skb);
-                       return NETDEV_TX_OK;
+                       goto fail_rcu;
                }
        }
 
@@ -2104,10 +2141,13 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
        info->flags = info_flags;
        info->ack_frame_id = info_id;
 
-       ieee80211_xmit(sdata, skb);
+       ieee80211_xmit(sdata, skb, band);
+       rcu_read_unlock();
 
        return NETDEV_TX_OK;
 
+ fail_rcu:
+       rcu_read_unlock();
  fail:
        dev_kfree_skb(skb);
        return NETDEV_TX_OK;
@@ -2139,11 +2179,18 @@ static bool ieee80211_tx_pending_skb(struct ieee80211_local *local,
        struct sta_info *sta;
        struct ieee80211_hdr *hdr;
        bool result;
+       struct ieee80211_chanctx_conf *chanctx_conf;
 
        sdata = vif_to_sdata(info->control.vif);
 
        if (info->flags & IEEE80211_TX_INTFL_NEED_TXPROCESSING) {
-               result = ieee80211_tx(sdata, skb, true);
+               chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
+               if (unlikely(!chanctx_conf)) {
+                       dev_kfree_skb(skb);
+                       return true;
+               }
+               result = ieee80211_tx(sdata, skb, true,
+                                     chanctx_conf->channel->band);
        } else {
                struct sk_buff_head skbs;
 
@@ -2211,9 +2258,8 @@ void ieee80211_tx_pending(unsigned long data)
 /* functions for drivers to get certain frames */
 
 static void ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata,
-                                    struct ieee80211_if_ap *bss,
-                                    struct sk_buff *skb,
-                                    struct beacon_data *beacon)
+                                    struct ps_data *ps,
+                                    struct sk_buff *skb)
 {
        u8 *pos, *tim;
        int aid0 = 0;
@@ -2221,27 +2267,27 @@ static void ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata,
 
        /* Generate bitmap for TIM only if there are any STAs in power save
         * mode. */
-       if (atomic_read(&bss->num_sta_ps) > 0)
+       if (atomic_read(&ps->num_sta_ps) > 0)
                /* in the hope that this is faster than
                 * checking byte-for-byte */
-               have_bits = !bitmap_empty((unsigned long*)bss->tim,
+               have_bits = !bitmap_empty((unsigned long*)ps->tim,
                                          IEEE80211_MAX_AID+1);
 
-       if (bss->dtim_count == 0)
-               bss->dtim_count = sdata->vif.bss_conf.dtim_period - 1;
+       if (ps->dtim_count == 0)
+               ps->dtim_count = sdata->vif.bss_conf.dtim_period - 1;
        else
-               bss->dtim_count--;
+               ps->dtim_count--;
 
        tim = pos = (u8 *) skb_put(skb, 6);
        *pos++ = WLAN_EID_TIM;
        *pos++ = 4;
-       *pos++ = bss->dtim_count;
+       *pos++ = ps->dtim_count;
        *pos++ = sdata->vif.bss_conf.dtim_period;
 
-       if (bss->dtim_count == 0 && !skb_queue_empty(&bss->ps_bc_buf))
+       if (ps->dtim_count == 0 && !skb_queue_empty(&ps->bc_buf))
                aid0 = 1;
 
-       bss->dtim_bc_mc = aid0 == 1;
+       ps->dtim_bc_mc = aid0 == 1;
 
        if (have_bits) {
                /* Find largest even number N1 so that bits numbered 1 through
@@ -2249,14 +2295,14 @@ static void ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata,
                 * (N2 + 1) x 8 through 2007 are 0. */
                n1 = 0;
                for (i = 0; i < IEEE80211_MAX_TIM_LEN; i++) {
-                       if (bss->tim[i]) {
+                       if (ps->tim[i]) {
                                n1 = i & 0xfe;
                                break;
                        }
                }
                n2 = n1;
                for (i = IEEE80211_MAX_TIM_LEN - 1; i >= n1; i--) {
-                       if (bss->tim[i]) {
+                       if (ps->tim[i]) {
                                n2 = i;
                                break;
                        }
@@ -2266,7 +2312,7 @@ static void ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata,
                *pos++ = n1 | aid0;
                /* Part Virt Bitmap */
                skb_put(skb, n2 - n1);
-               memcpy(pos, bss->tim + n1, n2 - n1 + 1);
+               memcpy(pos, ps->tim + n1, n2 - n1 + 1);
 
                tim[1] = n2 - n1 + 4;
        } else {
@@ -2283,16 +2329,16 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
        struct sk_buff *skb = NULL;
        struct ieee80211_tx_info *info;
        struct ieee80211_sub_if_data *sdata = NULL;
-       struct ieee80211_if_ap *ap = NULL;
-       struct beacon_data *beacon;
-       enum ieee80211_band band = local->oper_channel->band;
+       enum ieee80211_band band;
        struct ieee80211_tx_rate_control txrc;
+       struct ieee80211_chanctx_conf *chanctx_conf;
 
        rcu_read_lock();
 
        sdata = vif_to_sdata(vif);
+       chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
 
-       if (!ieee80211_sdata_running(sdata))
+       if (!ieee80211_sdata_running(sdata) || !chanctx_conf)
                goto out;
 
        if (tim_offset)
@@ -2301,8 +2347,9 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
                *tim_length = 0;
 
        if (sdata->vif.type == NL80211_IFTYPE_AP) {
-               ap = &sdata->u.ap;
-               beacon = rcu_dereference(ap->beacon);
+               struct ieee80211_if_ap *ap = &sdata->u.ap;
+               struct beacon_data *beacon = rcu_dereference(ap->beacon);
+
                if (beacon) {
                        /*
                         * headroom, head length,
@@ -2326,14 +2373,12 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
                         * of the tim bitmap in mac80211 and the driver.
                         */
                        if (local->tim_in_locked_section) {
-                               ieee80211_beacon_add_tim(sdata, ap, skb,
-                                                        beacon);
+                               ieee80211_beacon_add_tim(sdata, &ap->ps, skb);
                        } else {
                                unsigned long flags;
 
                                spin_lock_irqsave(&local->tim_lock, flags);
-                               ieee80211_beacon_add_tim(sdata, ap, skb,
-                                                        beacon);
+                               ieee80211_beacon_add_tim(sdata, &ap->ps, skb);
                                spin_unlock_irqrestore(&local->tim_lock, flags);
                        }
 
@@ -2409,6 +2454,8 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
                *pos++ = WLAN_EID_SSID;
                *pos++ = 0x0;
 
+               band = chanctx_conf->channel->band;
+
                if (ieee80211_add_srates_ie(sdata, skb, true, band) ||
                    mesh_add_ds_params_ie(skb, sdata) ||
                    ieee80211_add_ext_srates_ie(sdata, skb, true, band) ||
@@ -2426,6 +2473,8 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
                goto out;
        }
 
+       band = chanctx_conf->channel->band;
+
        info = IEEE80211_SKB_CB(skb);
 
        info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
@@ -2653,29 +2702,40 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw,
        struct sk_buff *skb = NULL;
        struct ieee80211_tx_data tx;
        struct ieee80211_sub_if_data *sdata;
-       struct ieee80211_if_ap *bss = NULL;
-       struct beacon_data *beacon;
+       struct ps_data *ps;
        struct ieee80211_tx_info *info;
+       struct ieee80211_chanctx_conf *chanctx_conf;
 
        sdata = vif_to_sdata(vif);
-       bss = &sdata->u.ap;
 
        rcu_read_lock();
-       beacon = rcu_dereference(bss->beacon);
+       chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
 
-       if (sdata->vif.type != NL80211_IFTYPE_AP || !beacon || !beacon->head)
+       if (!chanctx_conf)
                goto out;
 
-       if (bss->dtim_count != 0 || !bss->dtim_bc_mc)
+       if (sdata->vif.type == NL80211_IFTYPE_AP) {
+               struct beacon_data *beacon =
+                               rcu_dereference(sdata->u.ap.beacon);
+
+               if (!beacon || !beacon->head)
+                       goto out;
+
+               ps = &sdata->u.ap.ps;
+       } else {
+               goto out;
+       }
+
+       if (ps->dtim_count != 0 || !ps->dtim_bc_mc)
                goto out; /* send buffered bc/mc only after DTIM beacon */
 
        while (1) {
-               skb = skb_dequeue(&bss->ps_bc_buf);
+               skb = skb_dequeue(&ps->bc_buf);
                if (!skb)
                        goto out;
                local->total_ps_buffered--;
 
-               if (!skb_queue_empty(&bss->ps_bc_buf) && skb->len >= 2) {
+               if (!skb_queue_empty(&ps->bc_buf) && skb->len >= 2) {
                        struct ieee80211_hdr *hdr =
                                (struct ieee80211_hdr *) skb->data;
                        /* more buffered multicast/broadcast frames ==> set
@@ -2693,7 +2753,7 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw,
        info = IEEE80211_SKB_CB(skb);
 
        tx.flags |= IEEE80211_TX_PS_BUFFERED;
-       info->band = local->oper_channel->band;
+       info->band = chanctx_conf->channel->band;
 
        if (invoke_tx_handlers(&tx))
                skb = NULL;
@@ -2704,8 +2764,9 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw,
 }
 EXPORT_SYMBOL(ieee80211_get_buffered_bc);
 
-void ieee80211_tx_skb_tid(struct ieee80211_sub_if_data *sdata,
-                         struct sk_buff *skb, int tid)
+void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata,
+                                struct sk_buff *skb, int tid,
+                                enum ieee80211_band band)
 {
        int ac = ieee802_1d_to_ac[tid & 7];
 
@@ -2722,6 +2783,6 @@ void ieee80211_tx_skb_tid(struct ieee80211_sub_if_data *sdata,
         * requirements are that we do not come into tx with bhs on.
         */
        local_bh_disable();
-       ieee80211_xmit(sdata, skb);
+       ieee80211_xmit(sdata, skb, band);
        local_bh_enable();
 }
index 22ca35054dd065753b9e7d6c4f3e5ab990903e83..60c8ad10deb1033fefb53381d7c610c2d5b390e8 100644 (file)
@@ -406,7 +406,7 @@ void ieee80211_add_pending_skb(struct ieee80211_local *local,
        int queue = info->hw_queue;
 
        if (WARN_ON(!info->control.vif)) {
-               kfree_skb(skb);
+               ieee80211_free_txskb(&local->hw, skb);
                return;
        }
 
@@ -431,7 +431,7 @@ void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local,
                struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 
                if (WARN_ON(!info->control.vif)) {
-                       kfree_skb(skb);
+                       ieee80211_free_txskb(&local->hw, skb);
                        continue;
                }
 
@@ -741,6 +741,18 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
                        else
                                elem_parse_failed = true;
                        break;
+               case WLAN_EID_VHT_CAPABILITY:
+                       if (elen >= sizeof(struct ieee80211_vht_cap))
+                               elems->vht_cap_elem = (void *)pos;
+                       else
+                               elem_parse_failed = true;
+                       break;
+               case WLAN_EID_VHT_OPERATION:
+                       if (elen >= sizeof(struct ieee80211_vht_operation))
+                               elems->vht_operation = (void *)pos;
+                       else
+                               elem_parse_failed = true;
+                       break;
                case WLAN_EID_MESH_ID:
                        elems->mesh_id = pos;
                        elems->mesh_id_len = elen;
@@ -832,6 +844,7 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata,
 {
        struct ieee80211_local *local = sdata->local;
        struct ieee80211_tx_queue_params qparam;
+       struct ieee80211_chanctx_conf *chanctx_conf;
        int ac;
        bool use_11b, enable_qos;
        int aCWmin, aCWmax;
@@ -844,8 +857,12 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata,
 
        memset(&qparam, 0, sizeof(qparam));
 
-       use_11b = (local->oper_channel->band == IEEE80211_BAND_2GHZ) &&
+       rcu_read_lock();
+       chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
+       use_11b = (chanctx_conf &&
+                  chanctx_conf->channel->band == IEEE80211_BAND_2GHZ) &&
                 !(sdata->flags & IEEE80211_SDATA_OPERATING_GMODE);
+       rcu_read_unlock();
 
        /*
         * By default disable QoS in STA mode for old access points, which do
@@ -924,7 +941,7 @@ void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata,
                                  const size_t supp_rates_len,
                                  const u8 *supp_rates)
 {
-       struct ieee80211_local *local = sdata->local;
+       struct ieee80211_chanctx_conf *chanctx_conf;
        int i, have_higher_than_11mbit = 0;
 
        /* cf. IEEE 802.11 9.2.12 */
@@ -932,11 +949,16 @@ void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata,
                if ((supp_rates[i] & 0x7f) * 5 > 110)
                        have_higher_than_11mbit = 1;
 
-       if (local->oper_channel->band == IEEE80211_BAND_2GHZ &&
+       rcu_read_lock();
+       chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
+
+       if (chanctx_conf &&
+           chanctx_conf->channel->band == IEEE80211_BAND_2GHZ &&
            have_higher_than_11mbit)
                sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE;
        else
                sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE;
+       rcu_read_unlock();
 
        ieee80211_set_wmm_default(sdata, true);
 }
@@ -968,7 +990,7 @@ u32 ieee80211_mandatory_rates(struct ieee80211_local *local,
 }
 
 void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
-                        u16 transaction, u16 auth_alg,
+                        u16 transaction, u16 auth_alg, u16 status,
                         u8 *extra, size_t extra_len, const u8 *da,
                         const u8 *bssid, const u8 *key, u8 key_len, u8 key_idx)
 {
@@ -993,7 +1015,7 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
        memcpy(mgmt->bssid, bssid, ETH_ALEN);
        mgmt->u.auth.auth_alg = cpu_to_le16(auth_alg);
        mgmt->u.auth.auth_transaction = cpu_to_le16(transaction);
-       mgmt->u.auth.status_code = cpu_to_le16(0);
+       mgmt->u.auth.status_code = cpu_to_le16(status);
        if (extra)
                memcpy(skb_put(skb, extra_len), extra, extra_len);
 
@@ -1206,7 +1228,7 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
                              const u8 *ssid, size_t ssid_len,
                              const u8 *ie, size_t ie_len,
                              u32 ratemask, bool directed, bool no_cck,
-                             struct ieee80211_channel *channel)
+                             struct ieee80211_channel *channel, bool scan)
 {
        struct sk_buff *skb;
 
@@ -1217,7 +1239,10 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
                if (no_cck)
                        IEEE80211_SKB_CB(skb)->flags |=
                                IEEE80211_TX_CTL_NO_CCK_RATE;
-               ieee80211_tx_skb(sdata, skb);
+               if (scan)
+                       ieee80211_tx_skb_tid_band(sdata, skb, 7, channel->band);
+               else
+                       ieee80211_tx_skb(sdata, skb);
        }
 }
 
@@ -1280,6 +1305,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
 {
        struct ieee80211_hw *hw = &local->hw;
        struct ieee80211_sub_if_data *sdata;
+       struct ieee80211_chanctx *ctx;
        struct sta_info *sta;
        int res, i;
 
@@ -1352,6 +1378,12 @@ int ieee80211_reconfig(struct ieee80211_local *local)
                        res = drv_add_interface(local, sdata);
        }
 
+       /* add channel contexts */
+       mutex_lock(&local->chanctx_mtx);
+       list_for_each_entry(ctx, &local->chanctx_list, list)
+               WARN_ON(drv_add_chanctx(local, ctx));
+       mutex_unlock(&local->chanctx_mtx);
+
        /* add STAs back */
        mutex_lock(&local->sta_mtx);
        list_for_each_entry(sta, &local->sta_list, list) {
@@ -1392,11 +1424,22 @@ int ieee80211_reconfig(struct ieee80211_local *local)
 
        /* Finally also reconfigure all the BSS information */
        list_for_each_entry(sdata, &local->interfaces, list) {
+               struct ieee80211_chanctx_conf *ctx_conf;
                u32 changed;
 
                if (!ieee80211_sdata_running(sdata))
                        continue;
 
+               mutex_lock(&local->chanctx_mtx);
+               ctx_conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
+                               lockdep_is_held(&local->chanctx_mtx));
+               if (ctx_conf) {
+                       ctx = container_of(ctx_conf, struct ieee80211_chanctx,
+                                          conf);
+                       drv_assign_vif_chanctx(local, sdata, ctx);
+               }
+               mutex_unlock(&local->chanctx_mtx);
+
                /* common change flags for all interface types */
                changed = BSS_CHANGED_ERP_CTS_PROT |
                          BSS_CHANGED_ERP_PREAMBLE |
@@ -1587,68 +1630,24 @@ void ieee80211_resume_disconnect(struct ieee80211_vif *vif)
 }
 EXPORT_SYMBOL_GPL(ieee80211_resume_disconnect);
 
-static int check_mgd_smps(struct ieee80211_if_managed *ifmgd,
-                         enum ieee80211_smps_mode *smps_mode)
-{
-       if (ifmgd->associated) {
-               *smps_mode = ifmgd->ap_smps;
-
-               if (*smps_mode == IEEE80211_SMPS_AUTOMATIC) {
-                       if (ifmgd->powersave)
-                               *smps_mode = IEEE80211_SMPS_DYNAMIC;
-                       else
-                               *smps_mode = IEEE80211_SMPS_OFF;
-               }
-
-               return 1;
-       }
-
-       return 0;
-}
-
-void ieee80211_recalc_smps(struct ieee80211_local *local)
+void ieee80211_recalc_smps(struct ieee80211_sub_if_data *sdata)
 {
-       struct ieee80211_sub_if_data *sdata;
-       enum ieee80211_smps_mode smps_mode = IEEE80211_SMPS_OFF;
-       int count = 0;
-
-       mutex_lock(&local->iflist_mtx);
-
-       /*
-        * This function could be improved to handle multiple
-        * interfaces better, but right now it makes any
-        * non-station interfaces force SM PS to be turned
-        * off. If there are multiple station interfaces it
-        * could also use the best possible mode, e.g. if
-        * one is in static and the other in dynamic then
-        * dynamic is ok.
-        */
-
-       list_for_each_entry(sdata, &local->interfaces, list) {
-               if (!ieee80211_sdata_running(sdata))
-                       continue;
-               if (sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE)
-                       continue;
-               if (sdata->vif.type != NL80211_IFTYPE_STATION)
-                       goto set;
+       struct ieee80211_local *local = sdata->local;
+       struct ieee80211_chanctx_conf *chanctx_conf;
+       struct ieee80211_chanctx *chanctx;
 
-               count += check_mgd_smps(&sdata->u.mgd, &smps_mode);
+       mutex_lock(&local->chanctx_mtx);
 
-               if (count > 1) {
-                       smps_mode = IEEE80211_SMPS_OFF;
-                       break;
-               }
-       }
+       chanctx_conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
+                                       lockdep_is_held(&local->chanctx_mtx));
 
-       if (smps_mode == local->smps_mode)
+       if (WARN_ON_ONCE(!chanctx_conf))
                goto unlock;
 
- set:
-       local->smps_mode = smps_mode;
-       /* changed flag is auto-detected for this */
-       ieee80211_hw_config(local, 0);
+       chanctx = container_of(chanctx_conf, struct ieee80211_chanctx, conf);
+       ieee80211_recalc_smps_chanctx(local, chanctx);
  unlock:
-       mutex_unlock(&local->iflist_mtx);
+       mutex_unlock(&local->chanctx_mtx);
 }
 
 static bool ieee80211_id_in_list(const u8 *ids, int n_ids, u8 id)
@@ -1788,8 +1787,8 @@ u8 *ieee80211_ie_build_vht_cap(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap,
        __le32 tmp;
 
        *pos++ = WLAN_EID_VHT_CAPABILITY;
-       *pos++ = sizeof(struct ieee80211_vht_capabilities);
-       memset(pos, 0, sizeof(struct ieee80211_vht_capabilities));
+       *pos++ = sizeof(struct ieee80211_vht_cap);
+       memset(pos, 0, sizeof(struct ieee80211_vht_cap));
 
        /* capability flags */
        tmp = cpu_to_le32(cap);
@@ -1947,3 +1946,19 @@ int ieee80211_ave_rssi(struct ieee80211_vif *vif)
        return ifmgd->ave_beacon_signal;
 }
 EXPORT_SYMBOL_GPL(ieee80211_ave_rssi);
+
+u8 ieee80211_mcs_to_chains(const struct ieee80211_mcs_info *mcs)
+{
+       if (!mcs)
+               return 1;
+
+       /* TODO: consider rx_highest */
+
+       if (mcs->rx_mask[3])
+               return 4;
+       if (mcs->rx_mask[2])
+               return 3;
+       if (mcs->rx_mask[1])
+               return 2;
+       return 1;
+}
diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c
new file mode 100644 (file)
index 0000000..f311388
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * VHT handling
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/ieee80211.h>
+#include <linux/export.h>
+#include <net/mac80211.h>
+#include "ieee80211_i.h"
+
+
+void ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
+                                        struct ieee80211_supported_band *sband,
+                                        struct ieee80211_vht_cap *vht_cap_ie,
+                                        struct ieee80211_sta_vht_cap *vht_cap)
+{
+       if (WARN_ON_ONCE(!vht_cap))
+               return;
+
+       memset(vht_cap, 0, sizeof(*vht_cap));
+
+       if (!vht_cap_ie || !sband->vht_cap.vht_supported)
+               return;
+
+       vht_cap->vht_supported = true;
+
+       vht_cap->cap = le32_to_cpu(vht_cap_ie->vht_cap_info);
+
+       /* Copy peer MCS info, the driver might need them. */
+       memcpy(&vht_cap->vht_mcs, &vht_cap_ie->supp_mcs,
+              sizeof(struct ieee80211_vht_mcs_info));
+}
index bdb53aba888e147cfd3bae984cd69811f520261a..8bd2f5c6a56edfa26193de6da2560c88d5ac75ce 100644 (file)
@@ -106,7 +106,8 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx)
                if (status->flag & RX_FLAG_MMIC_ERROR)
                        goto mic_fail;
 
-               if (!(status->flag & RX_FLAG_IV_STRIPPED) && rx->key)
+               if (!(status->flag & RX_FLAG_IV_STRIPPED) && rx->key &&
+                   rx->key->conf.cipher == WLAN_CIPHER_SUITE_TKIP)
                        goto update_iv;
 
                return RX_CONTINUE;
@@ -545,14 +546,19 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx)
 
 static void bip_aad(struct sk_buff *skb, u8 *aad)
 {
+       __le16 mask_fc;
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+
        /* BIP AAD: FC(masked) || A1 || A2 || A3 */
 
        /* FC type/subtype */
-       aad[0] = skb->data[0];
        /* Mask FC Retry, PwrMgt, MoreData flags to zero */
-       aad[1] = skb->data[1] & ~(BIT(4) | BIT(5) | BIT(6));
+       mask_fc = hdr->frame_control;
+       mask_fc &= ~cpu_to_le16(IEEE80211_FCTL_RETRY | IEEE80211_FCTL_PM |
+                               IEEE80211_FCTL_MOREDATA);
+       put_unaligned(mask_fc, (__le16 *) &aad[0]);
        /* A1 || A2 || A3 */
-       memcpy(aad + 2, skb->data + 4, 3 * ETH_ALEN);
+       memcpy(aad + 2, &hdr->addr1, 3 * ETH_ALEN);
 }
 
 
index 7e7198b51c068a7ea10446af4d390a9e6e2044f4..c4ee43710aab63ce34657a06ba9d26d3862a6a61 100644 (file)
@@ -2589,6 +2589,8 @@ __ip_vs_get_timeouts(struct net *net, struct ip_vs_timeout_user *u)
        struct ip_vs_proto_data *pd;
 #endif
 
+       memset(u, 0, sizeof (*u));
+
 #ifdef CONFIG_IP_VS_PROTO_TCP
        pd = ip_vs_proto_data_get(net, IPPROTO_TCP);
        u->tcp_timeout = pd->timeout_table[IP_VS_TCP_S_ESTABLISHED] / HZ;
@@ -2766,7 +2768,6 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
        {
                struct ip_vs_timeout_user t;
 
-               memset(&t, 0, sizeof(t));
                __ip_vs_get_timeouts(net, &t);
                if (copy_to_user(user, &t, sizeof(t)) != 0)
                        ret = -EFAULT;
index 16c712563860bad8b8ba03041b06cf2c386d43ab..ae7f5daeee4362bff5aee9a30a85347de70a2ccc 100644 (file)
@@ -180,9 +180,9 @@ xt_ct_set_timeout(struct nf_conn *ct, const struct xt_tgchk_param *par,
        typeof(nf_ct_timeout_find_get_hook) timeout_find_get;
        struct ctnl_timeout *timeout;
        struct nf_conn_timeout *timeout_ext;
-       const struct ipt_entry *e = par->entryinfo;
        struct nf_conntrack_l4proto *l4proto;
        int ret = 0;
+       u8 proto;
 
        rcu_read_lock();
        timeout_find_get = rcu_dereference(nf_ct_timeout_find_get_hook);
@@ -192,9 +192,11 @@ xt_ct_set_timeout(struct nf_conn *ct, const struct xt_tgchk_param *par,
                goto out;
        }
 
-       if (e->ip.invflags & IPT_INV_PROTO) {
+       proto = xt_ct_find_proto(par);
+       if (!proto) {
                ret = -EINVAL;
-               pr_info("You cannot use inversion on L4 protocol\n");
+               pr_info("You must specify a L4 protocol, and not use "
+                       "inversions on it.\n");
                goto out;
        }
 
@@ -214,7 +216,7 @@ xt_ct_set_timeout(struct nf_conn *ct, const struct xt_tgchk_param *par,
        /* Make sure the timeout policy matches any existing protocol tracker,
         * otherwise default to generic.
         */
-       l4proto = __nf_ct_l4proto_find(par->family, e->ip.proto);
+       l4proto = __nf_ct_l4proto_find(par->family, proto);
        if (timeout->l4proto->l4proto != l4proto->l4proto) {
                ret = -EINVAL;
                pr_info("Timeout policy `%s' can only be used by L4 protocol "
index ee2e5bc5a8c7b506842b6d143fba3f7aa04f3a8d..bd93e51d30acc4eded7e5e4da0898e0838dd7c43 100644 (file)
@@ -70,6 +70,7 @@ tee_tg_route4(struct sk_buff *skb, const struct xt_tee_tginfo *info)
        fl4.daddr = info->gw.ip;
        fl4.flowi4_tos = RT_TOS(iph->tos);
        fl4.flowi4_scope = RT_SCOPE_UNIVERSE;
+       fl4.flowi4_flags = FLOWI_FLAG_KNOWN_NH;
        rt = ip_route_output_key(net, &fl4);
        if (IS_ERR(rt))
                return false;
index 81aafa8e4fef894e9f24d7c460b627108884bba6..bea7464cc43fd9ced593ece7d073b66ea85d18de 100644 (file)
@@ -111,7 +111,7 @@ static struct xt_target xt_nat_target_reg[] __read_mostly = {
                .family         = NFPROTO_IPV4,
                .table          = "nat",
                .hooks          = (1 << NF_INET_POST_ROUTING) |
-                                 (1 << NF_INET_LOCAL_OUT),
+                                 (1 << NF_INET_LOCAL_IN),
                .me             = THIS_MODULE,
        },
        {
@@ -123,7 +123,7 @@ static struct xt_target xt_nat_target_reg[] __read_mostly = {
                .family         = NFPROTO_IPV4,
                .table          = "nat",
                .hooks          = (1 << NF_INET_PRE_ROUTING) |
-                                 (1 << NF_INET_LOCAL_IN),
+                                 (1 << NF_INET_LOCAL_OUT),
                .me             = THIS_MODULE,
        },
        {
@@ -133,7 +133,7 @@ static struct xt_target xt_nat_target_reg[] __read_mostly = {
                .targetsize     = sizeof(struct nf_nat_range),
                .table          = "nat",
                .hooks          = (1 << NF_INET_POST_ROUTING) |
-                                 (1 << NF_INET_LOCAL_OUT),
+                                 (1 << NF_INET_LOCAL_IN),
                .me             = THIS_MODULE,
        },
        {
@@ -143,7 +143,7 @@ static struct xt_target xt_nat_target_reg[] __read_mostly = {
                .targetsize     = sizeof(struct nf_nat_range),
                .table          = "nat",
                .hooks          = (1 << NF_INET_PRE_ROUTING) |
-                                 (1 << NF_INET_LOCAL_IN),
+                                 (1 << NF_INET_LOCAL_OUT),
                .me             = THIS_MODULE,
        },
 };
index 01e944a017a4db6be96c3d4a8e7adc8d7890b34e..4da797fa5ec57641a0fa70b5dd1e6e517884fad4 100644 (file)
@@ -138,6 +138,8 @@ static int netlink_dump(struct sock *sk);
 static DEFINE_RWLOCK(nl_table_lock);
 static atomic_t nl_table_users = ATOMIC_INIT(0);
 
+#define nl_deref_protected(X) rcu_dereference_protected(X, lockdep_is_held(&nl_table_lock));
+
 static ATOMIC_NOTIFIER_HEAD(netlink_chain);
 
 static inline u32 netlink_group_mask(u32 group)
@@ -345,6 +347,11 @@ netlink_update_listeners(struct sock *sk)
        struct hlist_node *node;
        unsigned long mask;
        unsigned int i;
+       struct listeners *listeners;
+
+       listeners = nl_deref_protected(tbl->listeners);
+       if (!listeners)
+               return;
 
        for (i = 0; i < NLGRPLONGS(tbl->groups); i++) {
                mask = 0;
@@ -352,7 +359,7 @@ netlink_update_listeners(struct sock *sk)
                        if (i < NLGRPLONGS(nlk_sk(sk)->ngroups))
                                mask |= nlk_sk(sk)->groups[i];
                }
-               tbl->listeners->masks[i] = mask;
+               listeners->masks[i] = mask;
        }
        /* this function is only called with the netlink table "grabbed", which
         * makes sure updates are visible before bind or setsockopt return. */
@@ -536,7 +543,11 @@ static int netlink_release(struct socket *sock)
        if (netlink_is_kernel(sk)) {
                BUG_ON(nl_table[sk->sk_protocol].registered == 0);
                if (--nl_table[sk->sk_protocol].registered == 0) {
-                       kfree(nl_table[sk->sk_protocol].listeners);
+                       struct listeners *old;
+
+                       old = nl_deref_protected(nl_table[sk->sk_protocol].listeners);
+                       RCU_INIT_POINTER(nl_table[sk->sk_protocol].listeners, NULL);
+                       kfree_rcu(old, rcu);
                        nl_table[sk->sk_protocol].module = NULL;
                        nl_table[sk->sk_protocol].bind = NULL;
                        nl_table[sk->sk_protocol].flags = 0;
@@ -982,7 +993,7 @@ int netlink_has_listeners(struct sock *sk, unsigned int group)
        rcu_read_lock();
        listeners = rcu_dereference(nl_table[sk->sk_protocol].listeners);
 
-       if (group - 1 < nl_table[sk->sk_protocol].groups)
+       if (listeners && group - 1 < nl_table[sk->sk_protocol].groups)
                res = test_bit(group - 1, listeners->masks);
 
        rcu_read_unlock();
@@ -1625,7 +1636,7 @@ int __netlink_change_ngroups(struct sock *sk, unsigned int groups)
                new = kzalloc(sizeof(*new) + NLGRPSZ(groups), GFP_ATOMIC);
                if (!new)
                        return -ENOMEM;
-               old = rcu_dereference_protected(tbl->listeners, 1);
+               old = nl_deref_protected(tbl->listeners);
                memcpy(new->masks, old->masks, NLGRPSZ(tbl->groups));
                rcu_assign_pointer(tbl->listeners, new);
 
index a18d975db59cea34eb0558490deb800f24c10d22..13cc744a24981ea4ce8d9ebe2c7d321ed3e2ebfa 100644 (file)
@@ -495,16 +495,15 @@ EXPORT_SYMBOL(qdisc_watchdog_init);
 
 void qdisc_watchdog_schedule(struct qdisc_watchdog *wd, psched_time_t expires)
 {
-       ktime_t time;
-
        if (test_bit(__QDISC_STATE_DEACTIVATED,
                     &qdisc_root_sleeping(wd->qdisc)->state))
                return;
 
        qdisc_throttled(wd->qdisc);
-       time = ktime_set(0, 0);
-       time = ktime_add_ns(time, PSCHED_TICKS2NS(expires));
-       hrtimer_start(&wd->timer, time, HRTIMER_MODE_ABS);
+
+       hrtimer_start(&wd->timer,
+                     ns_to_ktime(PSCHED_TICKS2NS(expires)),
+                     HRTIMER_MODE_ABS);
 }
 EXPORT_SYMBOL(qdisc_watchdog_schedule);
 
index 564b9fc8efd3c8778ef8ba155cf17f79d92a9a80..0e19948470b88ce8dff6c3e1cded52a6121fe7ea 100644 (file)
@@ -509,8 +509,7 @@ static void cbq_ovl_delay(struct cbq_class *cl)
                        cl->cpriority = TC_CBQ_MAXPRIO;
                        q->pmask |= (1<<TC_CBQ_MAXPRIO);
 
-                       expires = ktime_set(0, 0);
-                       expires = ktime_add_ns(expires, PSCHED_TICKS2NS(sched));
+                       expires = ns_to_ktime(PSCHED_TICKS2NS(sched));
                        if (hrtimer_try_to_cancel(&q->delay_timer) &&
                            ktime_to_ns(ktime_sub(
                                        hrtimer_get_expires(&q->delay_timer),
index 2a68bb3db772a4d6001716e28af4385bb9c066bb..fc2f7aa4dca7aa04b3e7bc45cd39d47b744a1da4 100644 (file)
@@ -1409,11 +1409,11 @@ static ssize_t read_flush(struct file *file, char __user *buf,
                          size_t count, loff_t *ppos,
                          struct cache_detail *cd)
 {
-       char tbuf[20];
+       char tbuf[22];
        unsigned long p = *ppos;
        size_t len;
 
-       sprintf(tbuf, "%lu\n", convert_to_wallclock(cd->flush_time));
+       snprintf(tbuf, sizeof(tbuf), "%lu\n", convert_to_wallclock(cd->flush_time));
        len = strlen(tbuf);
        if (p >= len)
                return 0;
index aaaadfbe36e9525a42a86e1f649bf66e59eb7274..75853cabf4c97b153873eda4ce67cd228581fd15 100644 (file)
@@ -254,7 +254,6 @@ struct sock_xprt {
        void                    (*old_data_ready)(struct sock *, int);
        void                    (*old_state_change)(struct sock *);
        void                    (*old_write_space)(struct sock *);
-       void                    (*old_error_report)(struct sock *);
 };
 
 /*
@@ -737,10 +736,10 @@ static int xs_tcp_send_request(struct rpc_task *task)
                dprintk("RPC:       sendmsg returned unrecognized error %d\n",
                        -status);
        case -ECONNRESET:
-       case -EPIPE:
                xs_tcp_shutdown(xprt);
        case -ECONNREFUSED:
        case -ENOTCONN:
+       case -EPIPE:
                clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags);
        }
 
@@ -781,7 +780,6 @@ static void xs_save_old_callbacks(struct sock_xprt *transport, struct sock *sk)
        transport->old_data_ready = sk->sk_data_ready;
        transport->old_state_change = sk->sk_state_change;
        transport->old_write_space = sk->sk_write_space;
-       transport->old_error_report = sk->sk_error_report;
 }
 
 static void xs_restore_old_callbacks(struct sock_xprt *transport, struct sock *sk)
@@ -789,7 +787,6 @@ static void xs_restore_old_callbacks(struct sock_xprt *transport, struct sock *s
        sk->sk_data_ready = transport->old_data_ready;
        sk->sk_state_change = transport->old_state_change;
        sk->sk_write_space = transport->old_write_space;
-       sk->sk_error_report = transport->old_error_report;
 }
 
 static void xs_reset_transport(struct sock_xprt *transport)
@@ -1453,7 +1450,7 @@ static void xs_tcp_cancel_linger_timeout(struct rpc_xprt *xprt)
        xprt_clear_connecting(xprt);
 }
 
-static void xs_sock_mark_closed(struct rpc_xprt *xprt)
+static void xs_sock_reset_connection_flags(struct rpc_xprt *xprt)
 {
        smp_mb__before_clear_bit();
        clear_bit(XPRT_CONNECTION_ABORT, &xprt->state);
@@ -1461,6 +1458,11 @@ static void xs_sock_mark_closed(struct rpc_xprt *xprt)
        clear_bit(XPRT_CLOSE_WAIT, &xprt->state);
        clear_bit(XPRT_CLOSING, &xprt->state);
        smp_mb__after_clear_bit();
+}
+
+static void xs_sock_mark_closed(struct rpc_xprt *xprt)
+{
+       xs_sock_reset_connection_flags(xprt);
        /* Mark transport as closed and wake up all pending tasks */
        xprt_disconnect_done(xprt);
 }
@@ -1516,6 +1518,7 @@ static void xs_tcp_state_change(struct sock *sk)
        case TCP_CLOSE_WAIT:
                /* The server initiated a shutdown of the socket */
                xprt->connect_cookie++;
+               clear_bit(XPRT_CONNECTED, &xprt->state);
                xs_tcp_force_close(xprt);
        case TCP_CLOSING:
                /*
@@ -1540,25 +1543,6 @@ static void xs_tcp_state_change(struct sock *sk)
        read_unlock_bh(&sk->sk_callback_lock);
 }
 
-/**
- * xs_error_report - callback mainly for catching socket errors
- * @sk: socket
- */
-static void xs_error_report(struct sock *sk)
-{
-       struct rpc_xprt *xprt;
-
-       read_lock_bh(&sk->sk_callback_lock);
-       if (!(xprt = xprt_from_sock(sk)))
-               goto out;
-       dprintk("RPC:       %s client %p...\n"
-                       "RPC:       error %d\n",
-                       __func__, xprt, sk->sk_err);
-       xprt_wake_pending_tasks(xprt, -EAGAIN);
-out:
-       read_unlock_bh(&sk->sk_callback_lock);
-}
-
 static void xs_write_space(struct sock *sk)
 {
        struct socket *sock;
@@ -1858,7 +1842,6 @@ static int xs_local_finish_connecting(struct rpc_xprt *xprt,
                sk->sk_user_data = xprt;
                sk->sk_data_ready = xs_local_data_ready;
                sk->sk_write_space = xs_udp_write_space;
-               sk->sk_error_report = xs_error_report;
                sk->sk_allocation = GFP_ATOMIC;
 
                xprt_clear_connected(xprt);
@@ -1983,7 +1966,6 @@ static void xs_udp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)
                sk->sk_user_data = xprt;
                sk->sk_data_ready = xs_udp_data_ready;
                sk->sk_write_space = xs_udp_write_space;
-               sk->sk_error_report = xs_error_report;
                sk->sk_no_check = UDP_CSUM_NORCV;
                sk->sk_allocation = GFP_ATOMIC;
 
@@ -2050,10 +2032,8 @@ static void xs_abort_connection(struct sock_xprt *transport)
        any.sa_family = AF_UNSPEC;
        result = kernel_connect(transport->sock, &any, sizeof(any), 0);
        if (!result)
-               xs_sock_mark_closed(&transport->xprt);
-       else
-               dprintk("RPC:       AF_UNSPEC connect return code %d\n",
-                               result);
+               xs_sock_reset_connection_flags(&transport->xprt);
+       dprintk("RPC:       AF_UNSPEC connect return code %d\n", result);
 }
 
 static void xs_tcp_reuse_connection(struct sock_xprt *transport)
@@ -2098,7 +2078,6 @@ static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)
                sk->sk_data_ready = xs_tcp_data_ready;
                sk->sk_state_change = xs_tcp_state_change;
                sk->sk_write_space = xs_tcp_write_space;
-               sk->sk_error_report = xs_error_report;
                sk->sk_allocation = GFP_ATOMIC;
 
                /* socket options */
index 06748f108a5732e9f847cdffd0dafe0cb996c191..5ac19dc1d5e4ffe31394f7f8721efb7a0c2073bb 100644 (file)
@@ -151,6 +151,9 @@ static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, struct unix_diag_r
            sock_diag_put_meminfo(sk, skb, UNIX_DIAG_MEMINFO))
                goto out_nlmsg_trim;
 
+       if (nla_put_u8(skb, UNIX_DIAG_SHUTDOWN, sk->sk_shutdown))
+               goto out_nlmsg_trim;
+
        return nlmsg_end(skb, nlh);
 
 out_nlmsg_trim:
index 0f7e0d621ab0e78f7f15b08a2b218fd61bd773a9..a761670af31dd7076b32e7f61f26bb4b94b22728 100644 (file)
@@ -10,11 +10,13 @@ obj-$(CONFIG_WEXT_SPY) += wext-spy.o
 obj-$(CONFIG_WEXT_PRIV) += wext-priv.o
 
 cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o scan.o nl80211.o
-cfg80211-y += mlme.o ibss.o sme.o chan.o ethtool.o mesh.o ap.o
+cfg80211-y += mlme.o ibss.o sme.o chan.o ethtool.o mesh.o ap.o trace.o
 cfg80211-$(CONFIG_CFG80211_DEBUGFS) += debugfs.o
 cfg80211-$(CONFIG_CFG80211_WEXT) += wext-compat.o wext-sme.o
 cfg80211-$(CONFIG_CFG80211_INTERNAL_REGDB) += regdb.o
 
+CFLAGS_trace.o := -I$(src)
+
 ccflags-y += -D__CHECK_ENDIAN__
 
 $(obj)/regdb.c: $(src)/db.txt $(src)/genregdb.awk
index fcc60d8dbefa2bd9a4ae96b42aa4c8b67271cda2..e143505f05bc1e856720458e71c3ed41de907902 100644 (file)
@@ -3,6 +3,7 @@
 #include <net/cfg80211.h>
 #include "nl80211.h"
 #include "core.h"
+#include "rdev-ops.h"
 
 
 static int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
@@ -23,7 +24,7 @@ static int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
        if (!wdev->beacon_interval)
                return -ENOENT;
 
-       err = rdev->ops->stop_ap(&rdev->wiphy, dev);
+       err = rdev_stop_ap(rdev, dev);
        if (!err) {
                wdev->beacon_interval = 0;
                wdev->channel = NULL;
index 2f876b9ee3443b05efc54445b747e7ee7101e50d..48febd2160ba488a7b8fccea612de1ae76b2c3fa 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/export.h>
 #include <net/cfg80211.h>
 #include "core.h"
+#include "rdev-ops.h"
 
 struct ieee80211_channel *
 rdev_freq_to_chan(struct cfg80211_registered_device *rdev,
@@ -52,6 +53,8 @@ bool cfg80211_can_beacon_sec_chan(struct wiphy *wiphy,
        struct ieee80211_channel *sec_chan;
        int diff;
 
+       trace_cfg80211_can_beacon_sec_chan(wiphy, chan, channel_type);
+
        switch (channel_type) {
        case NL80211_CHAN_HT40PLUS:
                diff = 20;
@@ -60,20 +63,25 @@ bool cfg80211_can_beacon_sec_chan(struct wiphy *wiphy,
                diff = -20;
                break;
        default:
+               trace_cfg80211_return_bool(true);
                return true;
        }
 
        sec_chan = ieee80211_get_channel(wiphy, chan->center_freq + diff);
-       if (!sec_chan)
+       if (!sec_chan) {
+               trace_cfg80211_return_bool(false);
                return false;
+       }
 
        /* we'll need a DFS capability later */
        if (sec_chan->flags & (IEEE80211_CHAN_DISABLED |
                               IEEE80211_CHAN_PASSIVE_SCAN |
                               IEEE80211_CHAN_NO_IBSS |
-                              IEEE80211_CHAN_RADAR))
+                              IEEE80211_CHAN_RADAR)) {
+               trace_cfg80211_return_bool(false);
                return false;
-
+       }
+       trace_cfg80211_return_bool(true);
        return true;
 }
 EXPORT_SYMBOL(cfg80211_can_beacon_sec_chan);
@@ -92,7 +100,7 @@ int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev,
        if (!chan)
                return -EINVAL;
 
-       return rdev->ops->set_monitor_channel(&rdev->wiphy, chan, chantype);
+       return rdev_set_monitor_channel(rdev, chan, chantype);
 }
 
 void
index 443d4d7deea299c7e997045d22d8b2b146d2c877..f280f48fbd4313fe8e47a1e87e9a83c229569e49 100644 (file)
@@ -26,6 +26,7 @@
 #include "debugfs.h"
 #include "wext-compat.h"
 #include "ethtool.h"
+#include "rdev-ops.h"
 
 /* name for sysfs, %d is appended */
 #define PHY_NAME "phy"
@@ -216,7 +217,7 @@ static void cfg80211_rfkill_poll(struct rfkill *rfkill, void *data)
 {
        struct cfg80211_registered_device *rdev = data;
 
-       rdev->ops->rfkill_poll(&rdev->wiphy);
+       rdev_rfkill_poll(rdev);
 }
 
 static int cfg80211_rfkill_set_block(void *data, bool blocked)
@@ -370,6 +371,8 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
        rdev->wiphy.rts_threshold = (u32) -1;
        rdev->wiphy.coverage_class = 0;
 
+       rdev->wiphy.features = NL80211_FEATURE_SCAN_FLUSH;
+
        return &rdev->wiphy;
 }
 EXPORT_SYMBOL(wiphy_new);
@@ -688,7 +691,7 @@ void wiphy_unregister(struct wiphy *wiphy)
        flush_work(&rdev->event_work);
 
        if (rdev->wowlan && rdev->ops->set_wakeup)
-               rdev->ops->set_wakeup(&rdev->wiphy, false);
+               rdev_set_wakeup(rdev, false);
        cfg80211_rdev_free_wowlan(rdev);
 }
 EXPORT_SYMBOL(wiphy_unregister);
@@ -962,9 +965,8 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
                if ((wdev->iftype == NL80211_IFTYPE_STATION ||
                     wdev->iftype == NL80211_IFTYPE_P2P_CLIENT) &&
                    rdev->ops->set_power_mgmt)
-                       if (rdev->ops->set_power_mgmt(wdev->wiphy, dev,
-                                                     wdev->ps,
-                                                     wdev->ps_timeout)) {
+                       if (rdev_set_power_mgmt(rdev, dev, wdev->ps,
+                                               wdev->ps_timeout)) {
                                /* assume this means it's off */
                                wdev->ps = false;
                        }
index a343be4a52bd0e16b0fdb41e565f39f3d705c823..b8eb743fe7daf737baf3a0bd79884f0551da17f1 100644 (file)
@@ -320,13 +320,15 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
                         const u8 *bssid,
                         const u8 *ssid, int ssid_len,
                         const u8 *ie, int ie_len,
-                        const u8 *key, int key_len, int key_idx);
+                        const u8 *key, int key_len, int key_idx,
+                        const u8 *sae_data, int sae_data_len);
 int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
                       struct net_device *dev, struct ieee80211_channel *chan,
                       enum nl80211_auth_type auth_type, const u8 *bssid,
                       const u8 *ssid, int ssid_len,
                       const u8 *ie, int ie_len,
-                      const u8 *key, int key_len, int key_idx);
+                      const u8 *key, int key_len, int key_idx,
+                      const u8 *sae_data, int sae_data_len);
 int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
                          struct net_device *dev,
                          struct ieee80211_channel *chan,
index 7eecdf40cf80b3420b745ff044896948c7492201..48c48ffafa1db51d9b96ea2d5a418e592dbcf436 100644 (file)
@@ -2,6 +2,7 @@
 #include <net/cfg80211.h>
 #include "core.h"
 #include "ethtool.h"
+#include "rdev-ops.h"
 
 static void cfg80211_get_drvinfo(struct net_device *dev,
                                        struct ethtool_drvinfo *info)
@@ -47,9 +48,8 @@ static void cfg80211_get_ringparam(struct net_device *dev,
        memset(rp, 0, sizeof(*rp));
 
        if (rdev->ops->get_ringparam)
-               rdev->ops->get_ringparam(wdev->wiphy,
-                                        &rp->tx_pending, &rp->tx_max_pending,
-                                        &rp->rx_pending, &rp->rx_max_pending);
+               rdev_get_ringparam(rdev, &rp->tx_pending, &rp->tx_max_pending,
+                                  &rp->rx_pending, &rp->rx_max_pending);
 }
 
 static int cfg80211_set_ringparam(struct net_device *dev,
@@ -62,8 +62,7 @@ static int cfg80211_set_ringparam(struct net_device *dev,
                return -EINVAL;
 
        if (rdev->ops->set_ringparam)
-               return rdev->ops->set_ringparam(wdev->wiphy,
-                                               rp->tx_pending, rp->rx_pending);
+               return rdev_set_ringparam(rdev, rp->tx_pending, rp->rx_pending);
 
        return -ENOTSUPP;
 }
@@ -73,7 +72,7 @@ static int cfg80211_get_sset_count(struct net_device *dev, int sset)
        struct wireless_dev *wdev = dev->ieee80211_ptr;
        struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
        if (rdev->ops->get_et_sset_count)
-               return rdev->ops->get_et_sset_count(wdev->wiphy, dev, sset);
+               return rdev_get_et_sset_count(rdev, dev, sset);
        return -EOPNOTSUPP;
 }
 
@@ -83,7 +82,7 @@ static void cfg80211_get_stats(struct net_device *dev,
        struct wireless_dev *wdev = dev->ieee80211_ptr;
        struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
        if (rdev->ops->get_et_stats)
-               rdev->ops->get_et_stats(wdev->wiphy, dev, stats, data);
+               rdev_get_et_stats(rdev, dev, stats, data);
 }
 
 static void cfg80211_get_strings(struct net_device *dev, u32 sset, u8 *data)
@@ -91,7 +90,7 @@ static void cfg80211_get_strings(struct net_device *dev, u32 sset, u8 *data)
        struct wireless_dev *wdev = dev->ieee80211_ptr;
        struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
        if (rdev->ops->get_et_strings)
-               rdev->ops->get_et_strings(wdev->wiphy, dev, sset, data);
+               rdev_get_et_strings(rdev, dev, sset, data);
 }
 
 const struct ethtool_ops cfg80211_ethtool_ops = {
index ca5672f6ee2f79925906e78dcb188ebbd32e17a6..27941d5db72bd609531d4017604ece5fdea119fd 100644 (file)
@@ -11,6 +11,7 @@
 #include <net/cfg80211.h>
 #include "wext-compat.h"
 #include "nl80211.h"
+#include "rdev-ops.h"
 
 
 void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid)
@@ -61,6 +62,8 @@ void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp)
        struct cfg80211_event *ev;
        unsigned long flags;
 
+       trace_cfg80211_ibss_joined(dev, bssid);
+
        CFG80211_DEV_WARN_ON(wdev->sme_state != CFG80211_SME_CONNECTING);
 
        ev = kzalloc(sizeof(*ev), gfp);
@@ -128,7 +131,7 @@ int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
                return err;
        }
 
-       err = rdev->ops->join_ibss(&rdev->wiphy, dev, params);
+       err = rdev_join_ibss(rdev, dev, params);
        if (err) {
                wdev->connect_keys = NULL;
                wdev->sme_state = CFG80211_SME_IDLE;
@@ -175,7 +178,7 @@ static void __cfg80211_clear_ibss(struct net_device *dev, bool nowext)
         */
        if (rdev->ops->del_key)
                for (i = 0; i < 6; i++)
-                       rdev->ops->del_key(wdev->wiphy, dev, i, false, NULL);
+                       rdev_del_key(rdev, dev, i, false, NULL);
 
        if (wdev->current_bss) {
                cfg80211_unhold_bss(wdev->current_bss);
@@ -211,7 +214,7 @@ int __cfg80211_leave_ibss(struct cfg80211_registered_device *rdev,
        if (!wdev->ssid_len)
                return -ENOLINK;
 
-       err = rdev->ops->leave_ibss(&rdev->wiphy, dev);
+       err = rdev_leave_ibss(rdev, dev);
 
        if (err)
                return err;
index c384e77ff77a4e8c2f62398c7559361c5033ad03..966cfc4cd79dc0e7dd47a819022470c7eb158996 100644 (file)
@@ -3,6 +3,7 @@
 #include <net/cfg80211.h>
 #include "nl80211.h"
 #include "core.h"
+#include "rdev-ops.h"
 
 /* Default values, timeouts in ms */
 #define MESH_TTL               31
@@ -160,7 +161,7 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
        if (err)
                return err;
 
-       err = rdev->ops->join_mesh(&rdev->wiphy, dev, conf, setup);
+       err = rdev_join_mesh(rdev, dev, conf, setup);
        if (!err) {
                memcpy(wdev->ssid, setup->mesh_id, setup->mesh_id_len);
                wdev->mesh_id_len = setup->mesh_id_len;
@@ -220,9 +221,8 @@ int cfg80211_set_mesh_freq(struct cfg80211_registered_device *rdev,
                if (err)
                        return err;
 
-               err = rdev->ops->libertas_set_mesh_channel(&rdev->wiphy,
-                                                          wdev->netdev,
-                                                          channel);
+               err = rdev_libertas_set_mesh_channel(rdev, wdev->netdev,
+                                                    channel);
                if (!err)
                        wdev->channel = channel;
 
@@ -242,6 +242,7 @@ void cfg80211_notify_new_peer_candidate(struct net_device *dev,
 {
        struct wireless_dev *wdev = dev->ieee80211_ptr;
 
+       trace_cfg80211_notify_new_peer_candidate(dev, macaddr);
        if (WARN_ON(wdev->iftype != NL80211_IFTYPE_MESH_POINT))
                return;
 
@@ -267,7 +268,7 @@ static int __cfg80211_leave_mesh(struct cfg80211_registered_device *rdev,
        if (!wdev->mesh_id_len)
                return -ENOTCONN;
 
-       err = rdev->ops->leave_mesh(&rdev->wiphy, dev);
+       err = rdev_leave_mesh(rdev, dev);
        if (!err) {
                wdev->mesh_id_len = 0;
                wdev->channel = NULL;
index 8016fee0752b0325a20409b7b1b93b5433c73872..4bfd14f7c5920c239f1802d6ddb131cd53f173db 100644 (file)
@@ -15,6 +15,8 @@
 #include <net/iw_handler.h>
 #include "core.h"
 #include "nl80211.h"
+#include "rdev-ops.h"
+
 
 void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len)
 {
@@ -22,6 +24,7 @@ void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len)
        struct wiphy *wiphy = wdev->wiphy;
        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 
+       trace_cfg80211_send_rx_auth(dev);
        wdev_lock(wdev);
 
        nl80211_send_rx_auth(rdev, dev, buf, len, GFP_KERNEL);
@@ -42,6 +45,7 @@ void cfg80211_send_rx_assoc(struct net_device *dev, struct cfg80211_bss *bss,
        u8 *ie = mgmt->u.assoc_resp.variable;
        int ieoffs = offsetof(struct ieee80211_mgmt, u.assoc_resp.variable);
 
+       trace_cfg80211_send_rx_assoc(dev, bss);
        wdev_lock(wdev);
 
        status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code);
@@ -98,6 +102,7 @@ void __cfg80211_send_deauth(struct net_device *dev,
        const u8 *bssid = mgmt->bssid;
        bool was_current = false;
 
+       trace___cfg80211_send_deauth(dev);
        ASSERT_WDEV_LOCK(wdev);
 
        if (wdev->current_bss &&
@@ -147,6 +152,7 @@ void __cfg80211_send_disassoc(struct net_device *dev,
        u16 reason_code;
        bool from_ap;
 
+       trace___cfg80211_send_disassoc(dev);
        ASSERT_WDEV_LOCK(wdev);
 
        nl80211_send_disassoc(rdev, dev, buf, len, GFP_KERNEL);
@@ -188,6 +194,7 @@ void cfg80211_send_unprot_deauth(struct net_device *dev, const u8 *buf,
        struct wiphy *wiphy = wdev->wiphy;
        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 
+       trace_cfg80211_send_unprot_deauth(dev);
        nl80211_send_unprot_deauth(rdev, dev, buf, len, GFP_ATOMIC);
 }
 EXPORT_SYMBOL(cfg80211_send_unprot_deauth);
@@ -199,6 +206,7 @@ void cfg80211_send_unprot_disassoc(struct net_device *dev, const u8 *buf,
        struct wiphy *wiphy = wdev->wiphy;
        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 
+       trace_cfg80211_send_unprot_disassoc(dev);
        nl80211_send_unprot_disassoc(rdev, dev, buf, len, GFP_ATOMIC);
 }
 EXPORT_SYMBOL(cfg80211_send_unprot_disassoc);
@@ -209,6 +217,7 @@ void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr)
        struct wiphy *wiphy = wdev->wiphy;
        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 
+       trace_cfg80211_send_auth_timeout(dev, addr);
        wdev_lock(wdev);
 
        nl80211_send_auth_timeout(rdev, dev, addr, GFP_KERNEL);
@@ -227,6 +236,7 @@ void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr)
        struct wiphy *wiphy = wdev->wiphy;
        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 
+       trace_cfg80211_send_assoc_timeout(dev, addr);
        wdev_lock(wdev);
 
        nl80211_send_assoc_timeout(rdev, dev, addr, GFP_KERNEL);
@@ -261,6 +271,7 @@ void cfg80211_michael_mic_failure(struct net_device *dev, const u8 *addr,
        }
 #endif
 
+       trace_cfg80211_michael_mic_failure(dev, addr, key_type, key_id, tsc);
        nl80211_michael_mic_failure(rdev, dev, addr, key_type, key_id, tsc, gfp);
 }
 EXPORT_SYMBOL(cfg80211_michael_mic_failure);
@@ -273,7 +284,8 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
                         const u8 *bssid,
                         const u8 *ssid, int ssid_len,
                         const u8 *ie, int ie_len,
-                        const u8 *key, int key_len, int key_idx)
+                        const u8 *key, int key_len, int key_idx,
+                        const u8 *sae_data, int sae_data_len)
 {
        struct wireless_dev *wdev = dev->ieee80211_ptr;
        struct cfg80211_auth_request req;
@@ -293,6 +305,8 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
 
        req.ie = ie;
        req.ie_len = ie_len;
+       req.sae_data = sae_data;
+       req.sae_data_len = sae_data_len;
        req.auth_type = auth_type;
        req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len,
                                   WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
@@ -307,7 +321,7 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
        if (err)
                goto out;
 
-       err = rdev->ops->auth(&rdev->wiphy, dev, &req);
+       err = rdev_auth(rdev, dev, &req);
 
 out:
        cfg80211_put_bss(req.bss);
@@ -319,7 +333,8 @@ int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
                       enum nl80211_auth_type auth_type, const u8 *bssid,
                       const u8 *ssid, int ssid_len,
                       const u8 *ie, int ie_len,
-                      const u8 *key, int key_len, int key_idx)
+                      const u8 *key, int key_len, int key_idx,
+                      const u8 *sae_data, int sae_data_len)
 {
        int err;
 
@@ -327,7 +342,8 @@ int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
        wdev_lock(dev->ieee80211_ptr);
        err = __cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid,
                                   ssid, ssid_len, ie, ie_len,
-                                  key, key_len, key_idx);
+                                  key, key_len, key_idx,
+                                  sae_data, sae_data_len);
        wdev_unlock(dev->ieee80211_ptr);
        mutex_unlock(&rdev->devlist_mtx);
 
@@ -410,7 +426,7 @@ int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
        if (err)
                goto out;
 
-       err = rdev->ops->assoc(&rdev->wiphy, dev, &req);
+       err = rdev_assoc(rdev, dev, &req);
 
 out:
        if (err) {
@@ -457,22 +473,16 @@ int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
                .reason_code = reason,
                .ie = ie,
                .ie_len = ie_len,
+               .local_state_change = local_state_change,
        };
 
        ASSERT_WDEV_LOCK(wdev);
 
-       if (local_state_change) {
-               if (wdev->current_bss &&
-                   ether_addr_equal(wdev->current_bss->pub.bssid, bssid)) {
-                       cfg80211_unhold_bss(wdev->current_bss);
-                       cfg80211_put_bss(&wdev->current_bss->pub);
-                       wdev->current_bss = NULL;
-               }
-
+       if (local_state_change && (!wdev->current_bss ||
+           !ether_addr_equal(wdev->current_bss->pub.bssid, bssid)))
                return 0;
-       }
 
-       return rdev->ops->deauth(&rdev->wiphy, dev, &req);
+       return rdev_deauth(rdev, dev, &req);
 }
 
 int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
@@ -517,7 +527,7 @@ static int __cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev,
        else
                return -ENOTCONN;
 
-       return rdev->ops->disassoc(&rdev->wiphy, dev, &req);
+       return rdev_disassoc(rdev, dev, &req);
 }
 
 int cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev,
@@ -558,7 +568,7 @@ void cfg80211_mlme_down(struct cfg80211_registered_device *rdev,
 
        memcpy(bssid, wdev->current_bss->pub.bssid, ETH_ALEN);
        req.bssid = bssid;
-       rdev->ops->deauth(&rdev->wiphy, dev, &req);
+       rdev_deauth(rdev, dev, &req);
 
        if (wdev->current_bss) {
                cfg80211_unhold_bss(wdev->current_bss);
@@ -575,6 +585,8 @@ void cfg80211_ready_on_channel(struct wireless_dev *wdev, u64 cookie,
        struct wiphy *wiphy = wdev->wiphy;
        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 
+       trace_cfg80211_ready_on_channel(wdev, cookie, chan, channel_type,
+                                       duration);
        nl80211_send_remain_on_channel(rdev, wdev, cookie, chan, channel_type,
                                       duration, gfp);
 }
@@ -588,6 +600,8 @@ void cfg80211_remain_on_channel_expired(struct wireless_dev *wdev, u64 cookie,
        struct wiphy *wiphy = wdev->wiphy;
        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 
+       trace_cfg80211_ready_on_channel_expired(wdev, cookie, chan,
+                                               channel_type);
        nl80211_send_remain_on_channel_cancel(rdev, wdev, cookie, chan,
                                              channel_type, gfp);
 }
@@ -599,6 +613,7 @@ void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr,
        struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 
+       trace_cfg80211_new_sta(dev, mac_addr, sinfo);
        nl80211_send_sta_event(rdev, dev, mac_addr, sinfo, gfp);
 }
 EXPORT_SYMBOL(cfg80211_new_sta);
@@ -608,6 +623,7 @@ void cfg80211_del_sta(struct net_device *dev, const u8 *mac_addr, gfp_t gfp)
        struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 
+       trace_cfg80211_del_sta(dev, mac_addr);
        nl80211_send_sta_del_event(rdev, dev, mac_addr, gfp);
 }
 EXPORT_SYMBOL(cfg80211_del_sta);
@@ -688,7 +704,7 @@ int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_portid,
        list_add(&nreg->list, &wdev->mgmt_registrations);
 
        if (rdev->ops->mgmt_frame_register)
-               rdev->ops->mgmt_frame_register(wiphy, wdev, frame_type, true);
+               rdev_mgmt_frame_register(rdev, wdev, frame_type, true);
 
  out:
        spin_unlock_bh(&wdev->mgmt_registrations_lock);
@@ -711,8 +727,8 @@ void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlportid)
                if (rdev->ops->mgmt_frame_register) {
                        u16 frame_type = le16_to_cpu(reg->frame_type);
 
-                       rdev->ops->mgmt_frame_register(wiphy, wdev,
-                                                      frame_type, false);
+                       rdev_mgmt_frame_register(rdev, wdev,
+                                                frame_type, false);
                }
 
                list_del(&reg->list);
@@ -838,10 +854,10 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
                return -EINVAL;
 
        /* Transmit the Action frame as requested by user space */
-       return rdev->ops->mgmt_tx(&rdev->wiphy, wdev, chan, offchan,
-                                 channel_type, channel_type_valid,
-                                 wait, buf, len, no_cck, dont_wait_for_ack,
-                                 cookie);
+       return rdev_mgmt_tx(rdev, wdev, chan, offchan,
+                           channel_type, channel_type_valid,
+                           wait, buf, len, no_cck, dont_wait_for_ack,
+                           cookie);
 }
 
 bool cfg80211_rx_mgmt(struct wireless_dev *wdev, int freq, int sig_mbm,
@@ -860,10 +876,13 @@ bool cfg80211_rx_mgmt(struct wireless_dev *wdev, int freq, int sig_mbm,
                cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE);
        u16 stype;
 
+       trace_cfg80211_rx_mgmt(wdev, freq, sig_mbm);
        stype = (le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE) >> 4;
 
-       if (!(stypes->rx & BIT(stype)))
+       if (!(stypes->rx & BIT(stype))) {
+               trace_cfg80211_return_bool(false);
                return false;
+       }
 
        data = buf + ieee80211_hdrlen(mgmt->frame_control);
        data_len = len - ieee80211_hdrlen(mgmt->frame_control);
@@ -894,6 +913,7 @@ bool cfg80211_rx_mgmt(struct wireless_dev *wdev, int freq, int sig_mbm,
 
        spin_unlock_bh(&wdev->mgmt_registrations_lock);
 
+       trace_cfg80211_return_bool(result);
        return result;
 }
 EXPORT_SYMBOL(cfg80211_rx_mgmt);
@@ -904,6 +924,8 @@ void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie,
        struct wiphy *wiphy = wdev->wiphy;
        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 
+       trace_cfg80211_mgmt_tx_status(wdev, cookie, ack);
+
        /* Indicate TX status of the Action frame to user space */
        nl80211_send_mgmt_tx_status(rdev, wdev, cookie, buf, len, ack, gfp);
 }
@@ -917,6 +939,8 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev,
        struct wiphy *wiphy = wdev->wiphy;
        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 
+       trace_cfg80211_cqm_rssi_notify(dev, rssi_event);
+
        /* Indicate roaming trigger event to user space */
        nl80211_send_cqm_rssi_notify(rdev, dev, rssi_event, gfp);
 }
@@ -929,6 +953,8 @@ void cfg80211_cqm_pktloss_notify(struct net_device *dev,
        struct wiphy *wiphy = wdev->wiphy;
        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 
+       trace_cfg80211_cqm_pktloss_notify(dev, peer, num_packets);
+
        /* Indicate roaming trigger event to user space */
        nl80211_send_cqm_pktloss_notify(rdev, dev, peer, num_packets, gfp);
 }
@@ -954,6 +980,7 @@ void cfg80211_gtk_rekey_notify(struct net_device *dev, const u8 *bssid,
        struct wiphy *wiphy = wdev->wiphy;
        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 
+       trace_cfg80211_gtk_rekey_notify(dev, bssid);
        nl80211_gtk_rekey_notify(rdev, dev, bssid, replay_ctr, gfp);
 }
 EXPORT_SYMBOL(cfg80211_gtk_rekey_notify);
@@ -965,6 +992,7 @@ void cfg80211_pmksa_candidate_notify(struct net_device *dev, int index,
        struct wiphy *wiphy = wdev->wiphy;
        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 
+       trace_cfg80211_pmksa_candidate_notify(dev, index, bssid, preauth);
        nl80211_pmksa_candidate_notify(rdev, dev, index, bssid, preauth, gfp);
 }
 EXPORT_SYMBOL(cfg80211_pmksa_candidate_notify);
@@ -977,6 +1005,8 @@ void cfg80211_ch_switch_notify(struct net_device *dev, int freq,
        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
        struct ieee80211_channel *chan;
 
+       trace_cfg80211_ch_switch_notify(dev, freq, type);
+
        wdev_lock(wdev);
 
        if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
@@ -999,12 +1029,18 @@ bool cfg80211_rx_spurious_frame(struct net_device *dev,
                                const u8 *addr, gfp_t gfp)
 {
        struct wireless_dev *wdev = dev->ieee80211_ptr;
+       bool ret;
+
+       trace_cfg80211_rx_spurious_frame(dev, addr);
 
        if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
-                   wdev->iftype != NL80211_IFTYPE_P2P_GO))
+                   wdev->iftype != NL80211_IFTYPE_P2P_GO)) {
+               trace_cfg80211_return_bool(false);
                return false;
-
-       return nl80211_unexpected_frame(dev, addr, gfp);
+       }
+       ret = nl80211_unexpected_frame(dev, addr, gfp);
+       trace_cfg80211_return_bool(ret);
+       return ret;
 }
 EXPORT_SYMBOL(cfg80211_rx_spurious_frame);
 
@@ -1012,12 +1048,18 @@ bool cfg80211_rx_unexpected_4addr_frame(struct net_device *dev,
                                        const u8 *addr, gfp_t gfp)
 {
        struct wireless_dev *wdev = dev->ieee80211_ptr;
+       bool ret;
+
+       trace_cfg80211_rx_unexpected_4addr_frame(dev, addr);
 
        if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
                    wdev->iftype != NL80211_IFTYPE_P2P_GO &&
-                   wdev->iftype != NL80211_IFTYPE_AP_VLAN))
+                   wdev->iftype != NL80211_IFTYPE_AP_VLAN)) {
+               trace_cfg80211_return_bool(false);
                return false;
-
-       return nl80211_unexpected_4addr_frame(dev, addr, gfp);
+       }
+       ret = nl80211_unexpected_4addr_frame(dev, addr, gfp);
+       trace_cfg80211_return_bool(ret);
+       return ret;
 }
 EXPORT_SYMBOL(cfg80211_rx_unexpected_4addr_frame);
index 0418a6d5c1a683f95542c64628e66f487ddea196..5d3167d71b5fb2a3f44fb676959b11343b17079b 100644 (file)
@@ -22,8 +22,8 @@
 #include "core.h"
 #include "nl80211.h"
 #include "reg.h"
+#include "rdev-ops.h"
 
-static bool nl80211_valid_auth_type(enum nl80211_auth_type auth_type);
 static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev,
                                   struct genl_info *info,
                                   struct cfg80211_crypto_settings *settings,
@@ -355,6 +355,9 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
        [NL80211_ATTR_BG_SCAN_PERIOD] = { .type = NLA_U16 },
        [NL80211_ATTR_WDEV] = { .type = NLA_U64 },
        [NL80211_ATTR_USER_REG_HINT_TYPE] = { .type = NLA_U32 },
+       [NL80211_ATTR_SAE_DATA] = { .type = NLA_BINARY, },
+       [NL80211_ATTR_VHT_CAPABILITY] = { .len = NL80211_VHT_CAPABILITY_LEN },
+       [NL80211_ATTR_SCAN_FLAGS] = { .type = NLA_U32 },
 };
 
 /* policy for the key attributes */
@@ -690,7 +693,7 @@ static int nl80211_parse_key(struct genl_info *info, struct key_parse *k)
 
 static struct cfg80211_cached_keys *
 nl80211_parse_connkeys(struct cfg80211_registered_device *rdev,
-                      struct nlattr *keys)
+                      struct nlattr *keys, bool *no_ht)
 {
        struct key_parse parse;
        struct nlattr *key;
@@ -733,6 +736,12 @@ nl80211_parse_connkeys(struct cfg80211_registered_device *rdev,
                result->params[parse.idx].key_len = parse.p.key_len;
                result->params[parse.idx].key = result->data[parse.idx];
                memcpy(result->data[parse.idx], parse.p.key, parse.p.key_len);
+
+               if (parse.p.cipher == WLAN_CIPHER_SUITE_WEP40 ||
+                   parse.p.cipher == WLAN_CIPHER_SUITE_WEP104) {
+                       if (no_ht)
+                               *no_ht = true;
+               }
        }
 
        return result;
@@ -943,7 +952,7 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 portid, u32 seq, int flag
             dev->wiphy.available_antennas_rx) && dev->ops->get_antenna) {
                u32 tx_ant = 0, rx_ant = 0;
                int res;
-               res = dev->ops->get_antenna(&dev->wiphy, &tx_ant, &rx_ant);
+               res = rdev_get_antenna(dev, &tx_ant, &rx_ant);
                if (!res) {
                        if (nla_put_u32(msg, NL80211_ATTR_WIPHY_ANTENNA_TX,
                                        tx_ant) ||
@@ -1457,7 +1466,7 @@ static int nl80211_set_wds_peer(struct sk_buff *skb, struct genl_info *info)
                return -EOPNOTSUPP;
 
        bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
-       return rdev->ops->set_wds_peer(wdev->wiphy, dev, bssid);
+       return rdev_set_wds_peer(rdev, dev, bssid);
 }
 
 
@@ -1562,9 +1571,8 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
                        if (result)
                                goto bad_res;
 
-                       result = rdev->ops->set_txq_params(&rdev->wiphy,
-                                                          netdev,
-                                                          &txq_params);
+                       result = rdev_set_txq_params(rdev, netdev,
+                                                    &txq_params);
                        if (result)
                                goto bad_res;
                }
@@ -1599,7 +1607,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
                        mbm = nla_get_u32(info->attrs[idx]);
                }
 
-               result = rdev->ops->set_tx_power(&rdev->wiphy, type, mbm);
+               result = rdev_set_tx_power(rdev, type, mbm);
                if (result)
                        goto bad_res;
        }
@@ -1628,7 +1636,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
                tx_ant = tx_ant & rdev->wiphy.available_antennas_tx;
                rx_ant = rx_ant & rdev->wiphy.available_antennas_rx;
 
-               result = rdev->ops->set_antenna(&rdev->wiphy, tx_ant, rx_ant);
+               result = rdev_set_antenna(rdev, tx_ant, rx_ant);
                if (result)
                        goto bad_res;
        }
@@ -1713,7 +1721,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
                if (changed & WIPHY_PARAM_COVERAGE_CLASS)
                        rdev->wiphy.coverage_class = coverage_class;
 
-               result = rdev->ops->set_wiphy_params(&rdev->wiphy, changed);
+               result = rdev_set_wiphy_params(rdev, changed);
                if (result) {
                        rdev->wiphy.retry_short = old_retry_short;
                        rdev->wiphy.retry_long = old_retry_long;
@@ -1765,8 +1773,7 @@ static int nl80211_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flag
                struct ieee80211_channel *chan;
                enum nl80211_channel_type channel_type;
 
-               chan = rdev->ops->get_channel(&rdev->wiphy, wdev,
-                                             &channel_type);
+               chan = rdev_get_channel(rdev, wdev, &channel_type);
                if (chan &&
                    (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ,
                                 chan->center_freq) ||
@@ -2014,9 +2021,9 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
        err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ?
                                  info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL,
                                  &flags);
-       wdev = rdev->ops->add_virtual_intf(&rdev->wiphy,
-               nla_data(info->attrs[NL80211_ATTR_IFNAME]),
-               type, err ? NULL : &flags, &params);
+       wdev = rdev_add_virtual_intf(rdev,
+                               nla_data(info->attrs[NL80211_ATTR_IFNAME]),
+                               type, err ? NULL : &flags, &params);
        if (IS_ERR(wdev)) {
                nlmsg_free(msg);
                return PTR_ERR(wdev);
@@ -2083,7 +2090,7 @@ static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info)
        if (!wdev->netdev)
                info->user_ptr[1] = NULL;
 
-       return rdev->ops->del_virtual_intf(&rdev->wiphy, wdev);
+       return rdev_del_virtual_intf(rdev, wdev);
 }
 
 static int nl80211_set_noack_map(struct sk_buff *skb, struct genl_info *info)
@@ -2100,7 +2107,7 @@ static int nl80211_set_noack_map(struct sk_buff *skb, struct genl_info *info)
 
        noack_map = nla_get_u16(info->attrs[NL80211_ATTR_NOACK_MAP]);
 
-       return rdev->ops->set_noack_map(&rdev->wiphy, dev, noack_map);
+       return rdev_set_noack_map(rdev, dev, noack_map);
 }
 
 struct get_key_cookie {
@@ -2210,8 +2217,8 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
            !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN))
                return -ENOENT;
 
-       err = rdev->ops->get_key(&rdev->wiphy, dev, key_idx, pairwise,
-                                mac_addr, &cookie, get_key_callback);
+       err = rdev_get_key(rdev, dev, key_idx, pairwise, mac_addr, &cookie,
+                          get_key_callback);
 
        if (err)
                goto free_msg;
@@ -2259,7 +2266,7 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
                if (err)
                        goto out;
 
-               err = rdev->ops->set_default_key(&rdev->wiphy, dev, key.idx,
+               err = rdev_set_default_key(rdev, dev, key.idx,
                                                 key.def_uni, key.def_multi);
 
                if (err)
@@ -2283,8 +2290,7 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
                if (err)
                        goto out;
 
-               err = rdev->ops->set_default_mgmt_key(&rdev->wiphy,
-                                                     dev, key.idx);
+               err = rdev_set_default_mgmt_key(rdev, dev, key.idx);
                if (err)
                        goto out;
 
@@ -2340,9 +2346,9 @@ static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
        wdev_lock(dev->ieee80211_ptr);
        err = nl80211_key_allowed(dev->ieee80211_ptr);
        if (!err)
-               err = rdev->ops->add_key(&rdev->wiphy, dev, key.idx,
-                                        key.type == NL80211_KEYTYPE_PAIRWISE,
-                                        mac_addr, &key.p);
+               err = rdev_add_key(rdev, dev, key.idx,
+                                  key.type == NL80211_KEYTYPE_PAIRWISE,
+                                   mac_addr, &key.p);
        wdev_unlock(dev->ieee80211_ptr);
 
        return err;
@@ -2386,9 +2392,9 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info)
                err = -ENOENT;
 
        if (!err)
-               err = rdev->ops->del_key(&rdev->wiphy, dev, key.idx,
-                                        key.type == NL80211_KEYTYPE_PAIRWISE,
-                                        mac_addr);
+               err = rdev_del_key(rdev, dev, key.idx,
+                                  key.type == NL80211_KEYTYPE_PAIRWISE,
+                                  mac_addr);
 
 #ifdef CONFIG_CFG80211_WEXT
        if (!err) {
@@ -2490,6 +2496,30 @@ static bool nl80211_get_ap_channel(struct cfg80211_registered_device *rdev,
        return ret;
 }
 
+static bool nl80211_valid_auth_type(struct cfg80211_registered_device *rdev,
+                                   enum nl80211_auth_type auth_type,
+                                   enum nl80211_commands cmd)
+{
+       if (auth_type > NL80211_AUTHTYPE_MAX)
+               return false;
+
+       switch (cmd) {
+       case NL80211_CMD_AUTHENTICATE:
+               if (!(rdev->wiphy.features & NL80211_FEATURE_SAE) &&
+                   auth_type == NL80211_AUTHTYPE_SAE)
+                       return false;
+               return true;
+       case NL80211_CMD_CONNECT:
+       case NL80211_CMD_START_AP:
+               /* SAE not supported yet */
+               if (auth_type == NL80211_AUTHTYPE_SAE)
+                       return false;
+               return true;
+       default:
+               return false;
+       }
+}
+
 static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
 {
        struct cfg80211_registered_device *rdev = info->user_ptr[0];
@@ -2559,7 +2589,8 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
        if (info->attrs[NL80211_ATTR_AUTH_TYPE]) {
                params.auth_type = nla_get_u32(
                        info->attrs[NL80211_ATTR_AUTH_TYPE]);
-               if (!nl80211_valid_auth_type(params.auth_type))
+               if (!nl80211_valid_auth_type(rdev, params.auth_type,
+                                            NL80211_CMD_START_AP))
                        return -EINVAL;
        } else
                params.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
@@ -2607,7 +2638,7 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
        if (err)
                return err;
 
-       err = rdev->ops->start_ap(&rdev->wiphy, dev, &params);
+       err = rdev_start_ap(rdev, dev, &params);
        if (!err) {
                wdev->preset_chan = params.channel;
                wdev->preset_chantype = params.channel_type;
@@ -2639,7 +2670,7 @@ static int nl80211_set_beacon(struct sk_buff *skb, struct genl_info *info)
        if (err)
                return err;
 
-       return rdev->ops->change_beacon(&rdev->wiphy, dev, &params);
+       return rdev_change_beacon(rdev, dev, &params);
 }
 
 static int nl80211_stop_ap(struct sk_buff *skb, struct genl_info *info)
@@ -2923,8 +2954,8 @@ static int nl80211_dump_station(struct sk_buff *skb,
 
        while (1) {
                memset(&sinfo, 0, sizeof(sinfo));
-               err = dev->ops->dump_station(&dev->wiphy, netdev, sta_idx,
-                                            mac_addr, &sinfo);
+               err = rdev_dump_station(dev, netdev, sta_idx,
+                                       mac_addr, &sinfo);
                if (err == -ENOENT)
                        break;
                if (err)
@@ -2969,7 +3000,7 @@ static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info)
        if (!rdev->ops->get_station)
                return -EOPNOTSUPP;
 
-       err = rdev->ops->get_station(&rdev->wiphy, dev, mac_addr, &sinfo);
+       err = rdev_get_station(rdev, dev, mac_addr, &sinfo);
        if (err)
                return err;
 
@@ -3146,7 +3177,7 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
 
        /* be aware of params.vlan when changing code here */
 
-       err = rdev->ops->change_station(&rdev->wiphy, dev, mac_addr, &params);
+       err = rdev_change_station(rdev, dev, mac_addr, &params);
 
        if (params.vlan)
                dev_put(params.vlan);
@@ -3198,6 +3229,10 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
                params.ht_capa =
                        nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]);
 
+       if (info->attrs[NL80211_ATTR_VHT_CAPABILITY])
+               params.vht_capa =
+                       nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]);
+
        if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION])
                params.plink_action =
                    nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]);
@@ -3275,7 +3310,7 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
 
        /* be aware of params.vlan when changing code here */
 
-       err = rdev->ops->add_station(&rdev->wiphy, dev, mac_addr, &params);
+       err = rdev_add_station(rdev, dev, mac_addr, &params);
 
        if (params.vlan)
                dev_put(params.vlan);
@@ -3300,7 +3335,7 @@ static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info)
        if (!rdev->ops->del_station)
                return -EOPNOTSUPP;
 
-       return rdev->ops->del_station(&rdev->wiphy, dev, mac_addr);
+       return rdev_del_station(rdev, dev, mac_addr);
 }
 
 static int nl80211_send_mpath(struct sk_buff *msg, u32 portid, u32 seq,
@@ -3382,8 +3417,8 @@ static int nl80211_dump_mpath(struct sk_buff *skb,
        }
 
        while (1) {
-               err = dev->ops->dump_mpath(&dev->wiphy, netdev, path_idx,
-                                          dst, next_hop, &pinfo);
+               err = rdev_dump_mpath(dev, netdev, path_idx, dst, next_hop,
+                                     &pinfo);
                if (err == -ENOENT)
                        break;
                if (err)
@@ -3430,7 +3465,7 @@ static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info)
        if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
                return -EOPNOTSUPP;
 
-       err = rdev->ops->get_mpath(&rdev->wiphy, dev, dst, next_hop, &pinfo);
+       err = rdev_get_mpath(rdev, dev, dst, next_hop, &pinfo);
        if (err)
                return err;
 
@@ -3469,7 +3504,7 @@ static int nl80211_set_mpath(struct sk_buff *skb, struct genl_info *info)
        if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
                return -EOPNOTSUPP;
 
-       return rdev->ops->change_mpath(&rdev->wiphy, dev, dst, next_hop);
+       return rdev_change_mpath(rdev, dev, dst, next_hop);
 }
 
 static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info)
@@ -3494,7 +3529,7 @@ static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info)
        if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
                return -EOPNOTSUPP;
 
-       return rdev->ops->add_mpath(&rdev->wiphy, dev, dst, next_hop);
+       return rdev_add_mpath(rdev, dev, dst, next_hop);
 }
 
 static int nl80211_del_mpath(struct sk_buff *skb, struct genl_info *info)
@@ -3509,7 +3544,7 @@ static int nl80211_del_mpath(struct sk_buff *skb, struct genl_info *info)
        if (!rdev->ops->del_mpath)
                return -EOPNOTSUPP;
 
-       return rdev->ops->del_mpath(&rdev->wiphy, dev, dst);
+       return rdev_del_mpath(rdev, dev, dst);
 }
 
 static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info)
@@ -3554,7 +3589,7 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info)
            dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
                return -EOPNOTSUPP;
 
-       return rdev->ops->change_bss(&rdev->wiphy, dev, &params);
+       return rdev_change_bss(rdev, dev, &params);
 }
 
 static const struct nla_policy reg_rule_policy[NL80211_REG_RULE_ATTR_MAX + 1] = {
@@ -3668,8 +3703,7 @@ static int nl80211_get_mesh_config(struct sk_buff *skb,
        if (!wdev->mesh_id_len)
                memcpy(&cur_params, &default_mesh_config, sizeof(cur_params));
        else
-               err = rdev->ops->get_mesh_config(&rdev->wiphy, dev,
-                                                &cur_params);
+               err = rdev_get_mesh_config(rdev, dev, &cur_params);
        wdev_unlock(wdev);
 
        if (err)
@@ -3971,8 +4005,7 @@ static int nl80211_update_mesh_config(struct sk_buff *skb,
                err = -ENOLINK;
 
        if (!err)
-               err = rdev->ops->update_mesh_config(&rdev->wiphy, dev,
-                                                   mask, &cfg);
+               err = rdev_update_mesh_config(rdev, dev, mask, &cfg);
 
        wdev_unlock(wdev);
 
@@ -4337,14 +4370,27 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
                }
        }
 
+       if (info->attrs[NL80211_ATTR_SCAN_FLAGS]) {
+               request->flags = nla_get_u32(
+                       info->attrs[NL80211_ATTR_SCAN_FLAGS]);
+               if (((request->flags & NL80211_SCAN_FLAG_LOW_PRIORITY) &&
+                    !(wiphy->features & NL80211_FEATURE_LOW_PRIORITY_SCAN)) ||
+                   ((request->flags & NL80211_SCAN_FLAG_FLUSH) &&
+                    !(wiphy->features & NL80211_FEATURE_SCAN_FLUSH))) {
+                       err = -EOPNOTSUPP;
+                       goto out_free;
+               }
+       }
+
        request->no_cck =
                nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]);
 
        request->wdev = wdev;
        request->wiphy = &rdev->wiphy;
+       request->scan_start = jiffies;
 
        rdev->scan_req = request;
-       err = rdev->ops->scan(&rdev->wiphy, request);
+       err = rdev_scan(rdev, request);
 
        if (!err) {
                nl80211_send_scan_start(rdev, wdev);
@@ -4568,11 +4614,24 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
                       request->ie_len);
        }
 
+       if (info->attrs[NL80211_ATTR_SCAN_FLAGS]) {
+               request->flags = nla_get_u32(
+                       info->attrs[NL80211_ATTR_SCAN_FLAGS]);
+               if (((request->flags & NL80211_SCAN_FLAG_LOW_PRIORITY) &&
+                    !(wiphy->features & NL80211_FEATURE_LOW_PRIORITY_SCAN)) ||
+                   ((request->flags & NL80211_SCAN_FLAG_FLUSH) &&
+                    !(wiphy->features & NL80211_FEATURE_SCAN_FLUSH))) {
+                       err = -EOPNOTSUPP;
+                       goto out_free;
+               }
+       }
+
        request->dev = dev;
        request->wiphy = &rdev->wiphy;
        request->interval = interval;
+       request->scan_start = jiffies;
 
-       err = rdev->ops->sched_scan_start(&rdev->wiphy, dev, request);
+       err = rdev_sched_scan_start(rdev, dev, request);
        if (!err) {
                rdev->sched_scan_req = request;
                nl80211_send_sched_scan(rdev, dev,
@@ -4815,8 +4874,7 @@ static int nl80211_dump_survey(struct sk_buff *skb,
        while (1) {
                struct ieee80211_channel *chan;
 
-               res = dev->ops->dump_survey(&dev->wiphy, netdev, survey_idx,
-                                           &survey);
+               res = rdev_dump_survey(dev, netdev, survey_idx, &survey);
                if (res == -ENOENT)
                        break;
                if (res)
@@ -4852,11 +4910,6 @@ static int nl80211_dump_survey(struct sk_buff *skb,
        return res;
 }
 
-static bool nl80211_valid_auth_type(enum nl80211_auth_type auth_type)
-{
-       return auth_type <= NL80211_AUTHTYPE_MAX;
-}
-
 static bool nl80211_valid_wpa_versions(u32 wpa_versions)
 {
        return !(wpa_versions & ~(NL80211_WPA_VERSION_1 |
@@ -4868,8 +4921,8 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
        struct cfg80211_registered_device *rdev = info->user_ptr[0];
        struct net_device *dev = info->user_ptr[1];
        struct ieee80211_channel *chan;
-       const u8 *bssid, *ssid, *ie = NULL;
-       int err, ssid_len, ie_len = 0;
+       const u8 *bssid, *ssid, *ie = NULL, *sae_data = NULL;
+       int err, ssid_len, ie_len = 0, sae_data_len = 0;
        enum nl80211_auth_type auth_type;
        struct key_parse key;
        bool local_state_change;
@@ -4945,9 +4998,23 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
        }
 
        auth_type = nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]);
-       if (!nl80211_valid_auth_type(auth_type))
+       if (!nl80211_valid_auth_type(rdev, auth_type, NL80211_CMD_AUTHENTICATE))
                return -EINVAL;
 
+       if (auth_type == NL80211_AUTHTYPE_SAE &&
+           !info->attrs[NL80211_ATTR_SAE_DATA])
+               return -EINVAL;
+
+       if (info->attrs[NL80211_ATTR_SAE_DATA]) {
+               if (auth_type != NL80211_AUTHTYPE_SAE)
+                       return -EINVAL;
+               sae_data = nla_data(info->attrs[NL80211_ATTR_SAE_DATA]);
+               sae_data_len = nla_len(info->attrs[NL80211_ATTR_SAE_DATA]);
+               /* need to include at least Auth Transaction and Status Code */
+               if (sae_data_len < 4)
+                       return -EINVAL;
+       }
+
        local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE];
 
        /*
@@ -4959,7 +5026,8 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
 
        return cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid,
                                  ssid, ssid_len, ie, ie_len,
-                                 key.p.key, key.p.key_len, key.idx);
+                                 key.p.key, key.p.key_len, key.idx,
+                                 sae_data, sae_data_len);
 }
 
 static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev,
@@ -5339,10 +5407,18 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
                return -EINVAL;
 
        if (ibss.privacy && info->attrs[NL80211_ATTR_KEYS]) {
+               bool no_ht = false;
+
                connkeys = nl80211_parse_connkeys(rdev,
-                                       info->attrs[NL80211_ATTR_KEYS]);
+                                         info->attrs[NL80211_ATTR_KEYS],
+                                         &no_ht);
                if (IS_ERR(connkeys))
                        return PTR_ERR(connkeys);
+
+               if ((ibss.channel_type != NL80211_CHAN_NO_HT) && no_ht) {
+                       kfree(connkeys);
+                       return -EINVAL;
+               }
        }
 
        ibss.control_port =
@@ -5384,7 +5460,7 @@ static int nl80211_testmode_do(struct sk_buff *skb, struct genl_info *info)
        err = -EOPNOTSUPP;
        if (rdev->ops->testmode_cmd) {
                rdev->testmode_info = info;
-               err = rdev->ops->testmode_cmd(&rdev->wiphy,
+               err = rdev_testmode_cmd(rdev,
                                nla_data(info->attrs[NL80211_ATTR_TESTDATA]),
                                nla_len(info->attrs[NL80211_ATTR_TESTDATA]));
                rdev->testmode_info = NULL;
@@ -5466,8 +5542,7 @@ static int nl80211_testmode_dump(struct sk_buff *skb,
                        genlmsg_cancel(skb, hdr);
                        break;
                }
-               err = rdev->ops->testmode_dump(&rdev->wiphy, skb, cb,
-                                              data, data_len);
+               err = rdev_testmode_dump(rdev, skb, cb, data, data_len);
                nla_nest_end(skb, tmdata);
 
                if (err == -ENOBUFS || err == -ENOENT) {
@@ -5596,7 +5671,8 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
        if (info->attrs[NL80211_ATTR_AUTH_TYPE]) {
                connect.auth_type =
                        nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]);
-               if (!nl80211_valid_auth_type(connect.auth_type))
+               if (!nl80211_valid_auth_type(rdev, connect.auth_type,
+                                            NL80211_CMD_CONNECT))
                        return -EINVAL;
        } else
                connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
@@ -5642,7 +5718,7 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
 
        if (connect.privacy && info->attrs[NL80211_ATTR_KEYS]) {
                connkeys = nl80211_parse_connkeys(rdev,
-                                       info->attrs[NL80211_ATTR_KEYS]);
+                                         info->attrs[NL80211_ATTR_KEYS], NULL);
                if (IS_ERR(connkeys))
                        return PTR_ERR(connkeys);
        }
@@ -5771,7 +5847,7 @@ static int nl80211_flush_pmksa(struct sk_buff *skb, struct genl_info *info)
        if (!rdev->ops->flush_pmksa)
                return -EOPNOTSUPP;
 
-       return rdev->ops->flush_pmksa(&rdev->wiphy, dev);
+       return rdev_flush_pmksa(rdev, dev);
 }
 
 static int nl80211_tdls_mgmt(struct sk_buff *skb, struct genl_info *info)
@@ -5798,10 +5874,10 @@ static int nl80211_tdls_mgmt(struct sk_buff *skb, struct genl_info *info)
        status_code = nla_get_u16(info->attrs[NL80211_ATTR_STATUS_CODE]);
        dialog_token = nla_get_u8(info->attrs[NL80211_ATTR_TDLS_DIALOG_TOKEN]);
 
-       return rdev->ops->tdls_mgmt(&rdev->wiphy, dev, peer, action_code,
-                                   dialog_token, status_code,
-                                   nla_data(info->attrs[NL80211_ATTR_IE]),
-                                   nla_len(info->attrs[NL80211_ATTR_IE]));
+       return rdev_tdls_mgmt(rdev, dev, peer, action_code,
+                             dialog_token, status_code,
+                             nla_data(info->attrs[NL80211_ATTR_IE]),
+                             nla_len(info->attrs[NL80211_ATTR_IE]));
 }
 
 static int nl80211_tdls_oper(struct sk_buff *skb, struct genl_info *info)
@@ -5822,7 +5898,7 @@ static int nl80211_tdls_oper(struct sk_buff *skb, struct genl_info *info)
        operation = nla_get_u8(info->attrs[NL80211_ATTR_TDLS_OPERATION]);
        peer = nla_data(info->attrs[NL80211_ATTR_MAC]);
 
-       return rdev->ops->tdls_oper(&rdev->wiphy, dev, peer, operation);
+       return rdev_tdls_oper(rdev, dev, peer, operation);
 }
 
 static int nl80211_remain_on_channel(struct sk_buff *skb,
@@ -5877,8 +5953,8 @@ static int nl80211_remain_on_channel(struct sk_buff *skb,
                goto free_msg;
        }
 
-       err = rdev->ops->remain_on_channel(&rdev->wiphy, wdev, chan,
-                                          channel_type, duration, &cookie);
+       err = rdev_remain_on_channel(rdev, wdev, chan, channel_type, duration,
+                                    &cookie);
 
        if (err)
                goto free_msg;
@@ -5912,7 +5988,7 @@ static int nl80211_cancel_remain_on_channel(struct sk_buff *skb,
 
        cookie = nla_get_u64(info->attrs[NL80211_ATTR_COOKIE]);
 
-       return rdev->ops->cancel_remain_on_channel(&rdev->wiphy, wdev, cookie);
+       return rdev_cancel_remain_on_channel(rdev, wdev, cookie);
 }
 
 static u32 rateset_to_mask(struct ieee80211_supported_band *sband,
@@ -6055,7 +6131,7 @@ static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb,
                }
        }
 
-       return rdev->ops->set_bitrate_mask(&rdev->wiphy, dev, NULL, &mask);
+       return rdev_set_bitrate_mask(rdev, dev, NULL, &mask);
 }
 
 static int nl80211_register_mgmt(struct sk_buff *skb, struct genl_info *info)
@@ -6230,7 +6306,7 @@ static int nl80211_tx_mgmt_cancel_wait(struct sk_buff *skb, struct genl_info *in
 
        cookie = nla_get_u64(info->attrs[NL80211_ATTR_COOKIE]);
 
-       return rdev->ops->mgmt_tx_cancel_wait(&rdev->wiphy, wdev, cookie);
+       return rdev_mgmt_tx_cancel_wait(rdev, wdev, cookie);
 }
 
 static int nl80211_set_power_save(struct sk_buff *skb, struct genl_info *info)
@@ -6260,8 +6336,7 @@ static int nl80211_set_power_save(struct sk_buff *skb, struct genl_info *info)
        if (state == wdev->ps)
                return 0;
 
-       err = rdev->ops->set_power_mgmt(wdev->wiphy, dev, state,
-                                       wdev->ps_timeout);
+       err = rdev_set_power_mgmt(rdev, dev, state, wdev->ps_timeout);
        if (!err)
                wdev->ps = state;
        return err;
@@ -6341,8 +6416,7 @@ static int nl80211_set_cqm_txe(struct genl_info *info,
            wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
                return -EOPNOTSUPP;
 
-       return rdev->ops->set_cqm_txe_config(wdev->wiphy, dev,
-                                            rate, pkts, intvl);
+       return rdev_set_cqm_txe_config(rdev, dev, rate, pkts, intvl);
 }
 
 static int nl80211_set_cqm_rssi(struct genl_info *info,
@@ -6364,8 +6438,7 @@ static int nl80211_set_cqm_rssi(struct genl_info *info,
            wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
                return -EOPNOTSUPP;
 
-       return rdev->ops->set_cqm_rssi_config(wdev->wiphy, dev,
-                                             threshold, hysteresis);
+       return rdev_set_cqm_rssi_config(rdev, dev, threshold, hysteresis);
 }
 
 static int nl80211_set_cqm(struct sk_buff *skb, struct genl_info *info)
@@ -6690,7 +6763,7 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
 
  set_wakeup:
        if (rdev->ops->set_wakeup && prev_enabled != !!rdev->wowlan)
-               rdev->ops->set_wakeup(&rdev->wiphy, rdev->wowlan);
+               rdev_set_wakeup(rdev, rdev->wowlan);
 
        return 0;
  error:
@@ -6746,7 +6819,7 @@ static int nl80211_set_rekey_data(struct sk_buff *skb, struct genl_info *info)
                goto out;
        }
 
-       err = rdev->ops->set_rekey_data(&rdev->wiphy, dev, &rekey_data);
+       err = rdev_set_rekey_data(rdev, dev, &rekey_data);
  out:
        wdev_unlock(wdev);
        return err;
@@ -6805,7 +6878,7 @@ static int nl80211_probe_client(struct sk_buff *skb,
 
        addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
 
-       err = rdev->ops->probe_client(&rdev->wiphy, dev, addr, &cookie);
+       err = rdev_probe_client(rdev, dev, addr, &cookie);
        if (err)
                goto free_msg;
 
@@ -7622,6 +7695,9 @@ static int nl80211_add_scan_req(struct sk_buff *msg,
            nla_put(msg, NL80211_ATTR_IE, req->ie_len, req->ie))
                goto nla_put_failure;
 
+       if (req->flags)
+               nla_put_u32(msg, NL80211_ATTR_SCAN_FLAGS, req->flags);
+
        return 0;
  nla_put_failure:
        return -ENOBUFS;
@@ -8800,7 +8876,10 @@ void cfg80211_probe_status(struct net_device *dev, const u8 *addr,
        void *hdr;
        int err;
 
+       trace_cfg80211_probe_status(dev, addr, cookie, acked);
+
        msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
+
        if (!msg)
                return;
 
@@ -8842,6 +8921,8 @@ void cfg80211_report_obss_beacon(struct wiphy *wiphy,
        void *hdr;
        u32 nlportid = ACCESS_ONCE(rdev->ap_beacons_nlportid);
 
+       trace_cfg80211_report_obss_beacon(wiphy, frame, len, freq, sig_dbm);
+
        if (!nlportid)
                return;
 
diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h
new file mode 100644 (file)
index 0000000..4a88a39
--- /dev/null
@@ -0,0 +1,861 @@
+#ifndef __CFG80211_RDEV_OPS
+#define __CFG80211_RDEV_OPS
+
+#include <linux/rtnetlink.h>
+#include <net/cfg80211.h>
+#include "core.h"
+#include "trace.h"
+
+static inline int rdev_suspend(struct cfg80211_registered_device *rdev)
+{
+       int ret;
+       trace_rdev_suspend(&rdev->wiphy, rdev->wowlan);
+       ret = rdev->ops->suspend(&rdev->wiphy, rdev->wowlan);
+       trace_rdev_return_int(&rdev->wiphy, ret);
+       return ret;
+}
+
+static inline int rdev_resume(struct cfg80211_registered_device *rdev)
+{
+       int ret;
+       trace_rdev_resume(&rdev->wiphy);
+       ret = rdev->ops->resume(&rdev->wiphy);
+       trace_rdev_return_int(&rdev->wiphy, ret);
+       return ret;
+}
+
+static inline void rdev_set_wakeup(struct cfg80211_registered_device *rdev,
+                                  bool enabled)
+{
+       trace_rdev_set_wakeup(&rdev->wiphy, enabled);
+       rdev->ops->set_wakeup(&rdev->wiphy, enabled);
+       trace_rdev_return_void(&rdev->wiphy);
+}
+
+static inline struct wireless_dev
+*rdev_add_virtual_intf(struct cfg80211_registered_device *rdev, char *name,
+                      enum nl80211_iftype type, u32 *flags,
+                      struct vif_params *params)
+{
+       struct wireless_dev *ret;
+       trace_rdev_add_virtual_intf(&rdev->wiphy, name, type);
+       ret = rdev->ops->add_virtual_intf(&rdev->wiphy, name, type, flags,
+                                         params);
+       trace_rdev_return_wdev(&rdev->wiphy, ret);
+       return ret;
+}
+
+static inline int
+rdev_del_virtual_intf(struct cfg80211_registered_device *rdev,
+                     struct wireless_dev *wdev)
+{
+       int ret;
+       trace_rdev_del_virtual_intf(&rdev->wiphy, wdev);
+       ret = rdev->ops->del_virtual_intf(&rdev->wiphy, wdev);
+       trace_rdev_return_int(&rdev->wiphy, ret);
+       return ret;
+}
+
+static inline int
+rdev_change_virtual_intf(struct cfg80211_registered_device *rdev,
+                        struct net_device *dev, enum nl80211_iftype type,
+                        u32 *flags, struct vif_params *params)
+{
+       int ret;
+       trace_rdev_change_virtual_intf(&rdev->wiphy, dev, type);
+       ret = rdev->ops->change_virtual_intf(&rdev->wiphy, dev, type, flags,
+                                            params);
+       trace_rdev_return_int(&rdev->wiphy, ret);
+       return ret;
+}
+
+static inline int rdev_add_key(struct cfg80211_registered_device *rdev,
+                              struct net_device *netdev, u8 key_index,
+                              bool pairwise, const u8 *mac_addr,
+                              struct key_params *params)
+{
+       int ret;
+       trace_rdev_add_key(&rdev->wiphy, netdev, key_index, pairwise, mac_addr);
+       ret = rdev->ops->add_key(&rdev->wiphy, netdev, key_index, pairwise,
+                                 mac_addr, params);
+       trace_rdev_return_int(&rdev->wiphy, ret);
+       return ret;
+}
+
+static inline int
+rdev_get_key(struct cfg80211_registered_device *rdev, struct net_device *netdev,
+            u8 key_index, bool pairwise, const u8 *mac_addr, void *cookie,
+            void (*callback)(void *cookie, struct key_params*))
+{
+       int ret;
+       trace_rdev_get_key(&rdev->wiphy, netdev, key_index, pairwise, mac_addr);
+       ret = rdev->ops->get_key(&rdev->wiphy, netdev, key_index, pairwise,
+                                 mac_addr, cookie, callback);
+       trace_rdev_return_int(&rdev->wiphy, ret);
+       return ret;
+}
+
+static inline int rdev_del_key(struct cfg80211_registered_device *rdev,
+                              struct net_device *netdev, u8 key_index,
+                              bool pairwise, const u8 *mac_addr)
+{
+       int ret;
+       trace_rdev_del_key(&rdev->wiphy, netdev, key_index, pairwise, mac_addr);
+       ret = rdev->ops->del_key(&rdev->wiphy, netdev, key_index, pairwise,
+                                 mac_addr);
+       trace_rdev_return_int(&rdev->wiphy, ret);
+       return ret;
+}
+
+static inline int
+rdev_set_default_key(struct cfg80211_registered_device *rdev,
+                    struct net_device *netdev, u8 key_index, bool unicast,
+                    bool multicast)
+{
+       int ret;
+       trace_rdev_set_default_key(&rdev->wiphy, netdev, key_index,
+                                  unicast, multicast);
+       ret = rdev->ops->set_default_key(&rdev->wiphy, netdev, key_index,
+                                         unicast, multicast);
+       trace_rdev_return_int(&rdev->wiphy, ret);
+       return ret;
+}
+
+static inline int
+rdev_set_default_mgmt_key(struct cfg80211_registered_device *rdev,
+                         struct net_device *netdev, u8 key_index)
+{
+       int ret;
+       trace_rdev_set_default_mgmt_key(&rdev->wiphy, netdev, key_index);
+       ret = rdev->ops->set_default_mgmt_key(&rdev->wiphy, netdev,
+                                              key_index);
+       trace_rdev_return_int(&rdev->wiphy, ret);
+       return ret;
+}
+
+static inline int rdev_start_ap(struct cfg80211_registered_device *rdev,
+                               struct net_device *dev,
+                               struct cfg80211_ap_settings *settings)
+{
+       int ret;
+       trace_rdev_start_ap(&rdev->wiphy, dev, settings);
+       ret = rdev->ops->start_ap(&rdev->wiphy, dev, settings);
+       trace_rdev_return_int(&rdev->wiphy, ret);
+       return ret;
+}
+
+static inline int rdev_change_beacon(struct cfg80211_registered_device *rdev,
+                                    struct net_device *dev,
+                                    struct cfg80211_beacon_data *info)
+{
+       int ret;
+       trace_rdev_change_beacon(&rdev->wiphy, dev, info);
+       ret = rdev->ops->change_beacon(&rdev->wiphy, dev, info);
+       trace_rdev_return_int(&rdev->wiphy, ret);
+       return ret;
+}
+
+static inline int rdev_stop_ap(struct cfg80211_registered_device *rdev,
+                              struct net_device *dev)
+{
+       int ret;
+       trace_rdev_stop_ap(&rdev->wiphy, dev);
+       ret = rdev->ops->stop_ap(&rdev->wiphy, dev);
+       trace_rdev_return_int(&rdev->wiphy, ret);
+       return ret;
+}
+
+static inline int rdev_add_station(struct cfg80211_registered_device *rdev,
+                                  struct net_device *dev, u8 *mac,
+                                  struct station_parameters *params)
+{
+       int ret;
+       trace_rdev_add_station(&rdev->wiphy, dev, mac, params);
+       ret = rdev->ops->add_station(&rdev->wiphy, dev, mac, params);
+       trace_rdev_return_int(&rdev->wiphy, ret);
+       return ret;
+}
+
+static inline int rdev_del_station(struct cfg80211_registered_device *rdev,
+                                  struct net_device *dev, u8 *mac)
+{
+       int ret;
+       trace_rdev_del_station(&rdev->wiphy, dev, mac);
+       ret = rdev->ops->del_station(&rdev->wiphy, dev, mac);
+       trace_rdev_return_int(&rdev->wiphy, ret);
+       return ret;
+}
+
+static inline int rdev_change_station(struct cfg80211_registered_device *rdev,
+                                     struct net_device *dev, u8 *mac,
+                                     struct station_parameters *params)
+{
+       int ret;
+       trace_rdev_change_station(&rdev->wiphy, dev, mac, params);
+       ret = rdev->ops->change_station(&rdev->wiphy, dev, mac, params);
+       trace_rdev_return_int(&rdev->wiphy, ret);
+       return ret;
+}
+
+static inline int rdev_get_station(struct cfg80211_registered_device *rdev,
+                                  struct net_device *dev, u8 *mac,
+                                  struct station_info *sinfo)
+{
+       int ret;
+       trace_rdev_get_station(&rdev->wiphy, dev, mac);
+       ret = rdev->ops->get_station(&rdev->wiphy, dev, mac, sinfo);
+       trace_rdev_return_int_station_info(&rdev->wiphy, ret, sinfo);
+       return ret;
+}
+
+static inline int rdev_dump_station(struct cfg80211_registered_device *rdev,
+                                   struct net_device *dev, int idx, u8 *mac,
+                                   struct station_info *sinfo)
+{
+       int ret;
+       trace_rdev_dump_station(&rdev->wiphy, dev, idx, mac);
+       ret = rdev->ops->dump_station(&rdev->wiphy, dev, idx, mac, sinfo);
+       trace_rdev_return_int_station_info(&rdev->wiphy, ret, sinfo);
+       return ret;
+}
+
+static inline int rdev_add_mpath(struct cfg80211_registered_device *rdev,
+                                struct net_device *dev, u8 *dst, u8 *next_hop)
+{
+       int ret;
+       trace_rdev_add_mpath(&rdev->wiphy, dev, dst, next_hop);
+       ret = rdev->ops->add_mpath(&rdev->wiphy, dev, dst, next_hop);
+       trace_rdev_return_int(&rdev->wiphy, ret);
+       return ret;
+}
+
+static inline int rdev_del_mpath(struct cfg80211_registered_device *rdev,
+                                struct net_device *dev, u8 *dst)
+{
+       int ret;
+       trace_rdev_del_mpath(&rdev->wiphy, dev, dst);
+       ret = rdev->ops->del_mpath(&rdev->wiphy, dev, dst);
+       trace_rdev_return_int(&rdev->wiphy, ret);
+       return ret;
+}
+
+static inline int rdev_change_mpath(struct cfg80211_registered_device *rdev,
+                                   struct net_device *dev, u8 *dst,
+                                   u8 *next_hop)
+{
+       int ret;
+       trace_rdev_change_mpath(&rdev->wiphy, dev, dst, next_hop);
+       ret = rdev->ops->change_mpath(&rdev->wiphy, dev, dst, next_hop);
+       trace_rdev_return_int(&rdev->wiphy, ret);
+       return ret;
+}
+
+static inline int rdev_get_mpath(struct cfg80211_registered_device *rdev,
+                                struct net_device *dev, u8 *dst, u8 *next_hop,
+                                struct mpath_info *pinfo)
+{
+       int ret;
+       trace_rdev_get_mpath(&rdev->wiphy, dev, dst, next_hop);
+       ret = rdev->ops->get_mpath(&rdev->wiphy, dev, dst, next_hop, pinfo);
+       trace_rdev_return_int_mpath_info(&rdev->wiphy, ret, pinfo);
+       return ret;
+
+}
+
+static inline int rdev_dump_mpath(struct cfg80211_registered_device *rdev,
+                                 struct net_device *dev, int idx, u8 *dst,
+                                 u8 *next_hop, struct mpath_info *pinfo)
+
+{
+       int ret;
+       trace_rdev_dump_mpath(&rdev->wiphy, dev, idx, dst, next_hop);
+       ret = rdev->ops->dump_mpath(&rdev->wiphy, dev, idx, dst, next_hop,
+                                    pinfo);
+       trace_rdev_return_int_mpath_info(&rdev->wiphy, ret, pinfo);
+       return ret;
+}
+
+static inline int
+rdev_get_mesh_config(struct cfg80211_registered_device *rdev,
+                    struct net_device *dev, struct mesh_config *conf)
+{
+       int ret;
+       trace_rdev_get_mesh_config(&rdev->wiphy, dev);
+       ret = rdev->ops->get_mesh_config(&rdev->wiphy, dev, conf);
+       trace_rdev_return_int_mesh_config(&rdev->wiphy, ret, conf);
+       return ret;
+}
+
+static inline int
+rdev_update_mesh_config(struct cfg80211_registered_device *rdev,
+                       struct net_device *dev, u32 mask,
+                       const struct mesh_config *nconf)
+{
+       int ret;
+       trace_rdev_update_mesh_config(&rdev->wiphy, dev, mask, nconf);
+       ret = rdev->ops->update_mesh_config(&rdev->wiphy, dev, mask, nconf);
+       trace_rdev_return_int(&rdev->wiphy, ret);
+       return ret;
+}
+
+static inline int rdev_join_mesh(struct cfg80211_registered_device *rdev,
+                                struct net_device *dev,
+                                const struct mesh_config *conf,
+                                const struct mesh_setup *setup)
+{
+       int ret;
+       trace_rdev_join_mesh(&rdev->wiphy, dev, conf, setup);
+       ret = rdev->ops->join_mesh(&rdev->wiphy, dev, conf, setup);
+       trace_rdev_return_int(&rdev->wiphy, ret);
+       return ret;
+}
+
+
+static inline int rdev_leave_mesh(struct cfg80211_registered_device *rdev,
+                                 struct net_device *dev)
+{
+       int ret;
+       trace_rdev_leave_mesh(&rdev->wiphy, dev);
+       ret = rdev->ops->leave_mesh(&rdev->wiphy, dev);
+       trace_rdev_return_int(&rdev->wiphy, ret);
+       return ret;
+}
+
+static inline int rdev_change_bss(struct cfg80211_registered_device *rdev,
+                                 struct net_device *dev,
+                                 struct bss_parameters *params)
+
+{
+       int ret;
+       trace_rdev_change_bss(&rdev->wiphy, dev, params);
+       ret = rdev->ops->change_bss(&rdev->wiphy, dev, params);
+       trace_rdev_return_int(&rdev->wiphy, ret);
+       return ret;
+}
+
+static inline int rdev_set_txq_params(struct cfg80211_registered_device *rdev,
+                                     struct net_device *dev,
+                                     struct ieee80211_txq_params *params)
+
+{
+       int ret;
+       trace_rdev_set_txq_params(&rdev->wiphy, dev, params);
+       ret = rdev->ops->set_txq_params(&rdev->wiphy, dev, params);
+       trace_rdev_return_int(&rdev->wiphy, ret);
+       return ret;
+}
+
+static inline int
+rdev_libertas_set_mesh_channel(struct cfg80211_registered_device *rdev,
+                              struct net_device *dev,
+                              struct ieee80211_channel *chan)
+{
+       int ret;
+       trace_rdev_libertas_set_mesh_channel(&rdev->wiphy, dev, chan);
+       ret = rdev->ops->libertas_set_mesh_channel(&rdev->wiphy, dev, chan);
+       trace_rdev_return_int(&rdev->wiphy, ret);
+       return ret;
+}
+
+static inline int
+rdev_set_monitor_channel(struct cfg80211_registered_device *rdev,
+                        struct ieee80211_channel *chan,
+                        enum nl80211_channel_type channel_type)
+{
+       int ret;
+       trace_rdev_set_monitor_channel(&rdev->wiphy, chan, channel_type);
+       ret = rdev->ops->set_monitor_channel(&rdev->wiphy, chan, channel_type);
+       trace_rdev_return_int(&rdev->wiphy, ret);
+       return ret;
+}
+
+static inline int rdev_scan(struct cfg80211_registered_device *rdev,
+                           struct cfg80211_scan_request *request)
+{
+       int ret;
+       trace_rdev_scan(&rdev->wiphy, request);
+       ret = rdev->ops->scan(&rdev->wiphy, request);
+       trace_rdev_return_int(&rdev->wiphy, ret);
+       return ret;
+}
+
+static inline int rdev_auth(struct cfg80211_registered_device *rdev,
+                           struct net_device *dev,
+                           struct cfg80211_auth_request *req)
+{
+       int ret;
+       trace_rdev_auth(&rdev->wiphy, dev, req);
+       ret = rdev->ops->auth(&rdev->wiphy, dev, req);
+       trace_rdev_return_int(&rdev->wiphy, ret);
+       return ret;
+}
+
+static inline int rdev_assoc(struct cfg80211_registered_device *rdev,
+                            struct net_device *dev,
+                            struct cfg80211_assoc_request *req)
+{
+       int ret;
+       trace_rdev_assoc(&rdev->wiphy, dev, req);
+       ret = rdev->ops->assoc(&rdev->wiphy, dev, req);
+       trace_rdev_return_int(&rdev->wiphy, ret);
+       return ret;
+}
+
+static inline int rdev_deauth(struct cfg80211_registered_device *rdev,
+                             struct net_device *dev,
+                             struct cfg80211_deauth_request *req)
+{
+       int ret;
+       trace_rdev_deauth(&rdev->wiphy, dev, req);
+       ret = rdev->ops->deauth(&rdev->wiphy, dev, req);
+       trace_rdev_return_int(&rdev->wiphy, ret);
+       return ret;
+}
+
+static inline int rdev_disassoc(struct cfg80211_registered_device *rdev,
+                               struct net_device *dev,
+                               struct cfg80211_disassoc_request *req)
+{
+       int ret;
+       trace_rdev_disassoc(&rdev->wiphy, dev, req);
+       ret = rdev->ops->disassoc(&rdev->wiphy, dev, req);
+       trace_rdev_return_int(&rdev->wiphy, ret);
+       return ret;
+}
+
+static inline int rdev_connect(struct cfg80211_registered_device *rdev,
+                              struct net_device *dev,
+                              struct cfg80211_connect_params *sme)
+{
+       int ret;
+       trace_rdev_connect(&rdev->wiphy, dev, sme);
+       ret = rdev->ops->connect(&rdev->wiphy, dev, sme);
+       trace_rdev_return_int(&rdev->wiphy, ret);
+       return ret;
+}
+
+static inline int rdev_disconnect(struct cfg80211_registered_device *rdev,
+                                 struct net_device *dev, u16 reason_code)
+{
+       int ret;
+       trace_rdev_disconnect(&rdev->wiphy, dev, reason_code);
+       ret = rdev->ops->disconnect(&rdev->wiphy, dev, reason_code);
+       trace_rdev_return_int(&rdev->wiphy, ret);
+       return ret;
+}
+
+static inline int rdev_join_ibss(struct cfg80211_registered_device *rdev,
+                                struct net_device *dev,
+                                struct cfg80211_ibss_params *params)
+{
+       int ret;
+       trace_rdev_join_ibss(&rdev->wiphy, dev, params);
+       ret = rdev->ops->join_ibss(&rdev->wiphy, dev, params);
+       trace_rdev_return_int(&rdev->wiphy, ret);
+       return ret;
+}
+
+static inline int rdev_leave_ibss(struct cfg80211_registered_device *rdev,
+                                 struct net_device *dev)
+{
+       int ret;
+       trace_rdev_leave_ibss(&rdev->wiphy, dev);
+       ret = rdev->ops->leave_ibss(&rdev->wiphy, dev);
+       trace_rdev_return_int(&rdev->wiphy, ret);
+       return ret;
+}
+
+static inline int
+rdev_set_wiphy_params(struct cfg80211_registered_device *rdev, u32 changed)
+{
+       int ret;
+       trace_rdev_set_wiphy_params(&rdev->wiphy, changed);
+       ret = rdev->ops->set_wiphy_params(&rdev->wiphy, changed);
+       trace_rdev_return_int(&rdev->wiphy, ret);
+       return ret;
+}
+
+static inline int rdev_set_tx_power(struct cfg80211_registered_device *rdev,
+                                   enum nl80211_tx_power_setting type, int mbm)
+{
+       int ret;
+       trace_rdev_set_tx_power(&rdev->wiphy, type, mbm);
+       ret = rdev->ops->set_tx_power(&rdev->wiphy, type, mbm);
+       trace_rdev_return_int(&rdev->wiphy, ret);
+       return ret;
+}
+
+static inline int rdev_get_tx_power(struct cfg80211_registered_device *rdev,
+                                   int *dbm)
+{
+       int ret;
+       trace_rdev_get_tx_power(&rdev->wiphy);
+       ret = rdev->ops->get_tx_power(&rdev->wiphy, dbm);
+       trace_rdev_return_int_int(&rdev->wiphy, ret, *dbm);
+       return ret;
+}
+
+static inline int rdev_set_wds_peer(struct cfg80211_registered_device *rdev,
+                                   struct net_device *dev, const u8 *addr)
+{
+       int ret;
+       trace_rdev_set_wds_peer(&rdev->wiphy, dev, addr);
+       ret = rdev->ops->set_wds_peer(&rdev->wiphy, dev, addr);
+       trace_rdev_return_int(&rdev->wiphy, ret);
+       return ret;
+}
+
+static inline void rdev_rfkill_poll(struct cfg80211_registered_device *rdev)
+{
+       trace_rdev_rfkill_poll(&rdev->wiphy);
+       rdev->ops->rfkill_poll(&rdev->wiphy);
+       trace_rdev_return_void(&rdev->wiphy);
+}
+
+
+#ifdef CONFIG_NL80211_TESTMODE
+static inline int rdev_testmode_cmd(struct cfg80211_registered_device *rdev,
+                                   void *data, int len)
+{
+       int ret;
+       trace_rdev_testmode_cmd(&rdev->wiphy);
+       ret = rdev->ops->testmode_cmd(&rdev->wiphy, data, len);
+       trace_rdev_return_int(&rdev->wiphy, ret);
+       return ret;
+}
+
+static inline int rdev_testmode_dump(struct cfg80211_registered_device *rdev,
+                                    struct sk_buff *skb,
+                                    struct netlink_callback *cb, void *data,
+                                    int len)
+{
+       int ret;
+       trace_rdev_testmode_dump(&rdev->wiphy);
+       ret = rdev->ops->testmode_dump(&rdev->wiphy, skb, cb, data, len);
+       trace_rdev_return_int(&rdev->wiphy, ret);
+       return ret;
+}
+#endif
+
+static inline int
+rdev_set_bitrate_mask(struct cfg80211_registered_device *rdev,
+                     struct net_device *dev, const u8 *peer,
+                     const struct cfg80211_bitrate_mask *mask)
+{
+       int ret;
+       trace_rdev_set_bitrate_mask(&rdev->wiphy, dev, peer, mask);
+       ret = rdev->ops->set_bitrate_mask(&rdev->wiphy, dev, peer, mask);
+       trace_rdev_return_int(&rdev->wiphy, ret);
+       return ret;
+}
+
+static inline int rdev_dump_survey(struct cfg80211_registered_device *rdev,
+                                  struct net_device *netdev, int idx,
+                                  struct survey_info *info)
+{
+       int ret;
+       trace_rdev_dump_survey(&rdev->wiphy, netdev, idx);
+       ret = rdev->ops->dump_survey(&rdev->wiphy, netdev, idx, info);
+       if (ret < 0)
+               trace_rdev_return_int(&rdev->wiphy, ret);
+       else
+               trace_rdev_return_int_survey_info(&rdev->wiphy, ret, info);
+       return ret;
+}
+
+static inline int rdev_set_pmksa(struct cfg80211_registered_device *rdev,
+                                struct net_device *netdev,
+                                struct cfg80211_pmksa *pmksa)
+{
+       int ret;
+       trace_rdev_set_pmksa(&rdev->wiphy, netdev, pmksa);
+       ret = rdev->ops->set_pmksa(&rdev->wiphy, netdev, pmksa);
+       trace_rdev_return_int(&rdev->wiphy, ret);
+       return ret;
+}
+
+static inline int rdev_del_pmksa(struct cfg80211_registered_device *rdev,
+                                struct net_device *netdev,
+                                struct cfg80211_pmksa *pmksa)
+{
+       int ret;
+       trace_rdev_del_pmksa(&rdev->wiphy, netdev, pmksa);
+       ret = rdev->ops->del_pmksa(&rdev->wiphy, netdev, pmksa);
+       trace_rdev_return_int(&rdev->wiphy, ret);
+       return ret;
+}
+
+static inline int rdev_flush_pmksa(struct cfg80211_registered_device *rdev,
+                                  struct net_device *netdev)
+{
+       int ret;
+       trace_rdev_flush_pmksa(&rdev->wiphy, netdev);
+       ret = rdev->ops->flush_pmksa(&rdev->wiphy, netdev);
+       trace_rdev_return_int(&rdev->wiphy, ret);
+       return ret;
+}
+
+static inline int
+rdev_remain_on_channel(struct cfg80211_registered_device *rdev,
+                      struct wireless_dev *wdev,
+                      struct ieee80211_channel *chan,
+                      enum nl80211_channel_type channel_type,
+                      unsigned int duration, u64 *cookie)
+{
+       int ret;
+       trace_rdev_remain_on_channel(&rdev->wiphy, wdev, chan, channel_type,
+                                    duration);
+       ret = rdev->ops->remain_on_channel(&rdev->wiphy, wdev, chan,
+                                           channel_type, duration, cookie);
+       trace_rdev_return_int_cookie(&rdev->wiphy, ret, *cookie);
+       return ret;
+}
+
+static inline int
+rdev_cancel_remain_on_channel(struct cfg80211_registered_device *rdev,
+                             struct wireless_dev *wdev, u64 cookie)
+{
+       int ret;
+       trace_rdev_cancel_remain_on_channel(&rdev->wiphy, wdev, cookie);
+       ret = rdev->ops->cancel_remain_on_channel(&rdev->wiphy, wdev, cookie);
+       trace_rdev_return_int(&rdev->wiphy, ret);
+       return ret;
+}
+
+static inline int rdev_mgmt_tx(struct cfg80211_registered_device *rdev,
+                              struct wireless_dev *wdev,
+                              struct ieee80211_channel *chan, bool offchan,
+                              enum nl80211_channel_type channel_type,
+                              bool channel_type_valid, unsigned int wait,
+                              const u8 *buf, size_t len, bool no_cck,
+                              bool dont_wait_for_ack, u64 *cookie)
+{
+       int ret;
+       trace_rdev_mgmt_tx(&rdev->wiphy, wdev, chan, offchan, channel_type,
+                          channel_type_valid, wait, no_cck, dont_wait_for_ack);
+       ret = rdev->ops->mgmt_tx(&rdev->wiphy, wdev, chan, offchan,
+                                 channel_type, channel_type_valid, wait, buf,
+                                 len, no_cck, dont_wait_for_ack, cookie);
+       trace_rdev_return_int_cookie(&rdev->wiphy, ret, *cookie);
+       return ret;
+}
+
+static inline int
+rdev_mgmt_tx_cancel_wait(struct cfg80211_registered_device *rdev,
+                        struct wireless_dev *wdev, u64 cookie)
+{
+       int ret;
+       trace_rdev_mgmt_tx_cancel_wait(&rdev->wiphy, wdev, cookie);
+       ret = rdev->ops->mgmt_tx_cancel_wait(&rdev->wiphy, wdev, cookie);
+       trace_rdev_return_int(&rdev->wiphy, ret);
+       return ret;
+}
+
+static inline int rdev_set_power_mgmt(struct cfg80211_registered_device *rdev,
+                                     struct net_device *dev, bool enabled,
+                                     int timeout)
+{
+       int ret;
+       trace_rdev_set_power_mgmt(&rdev->wiphy, dev, enabled, timeout);
+       ret = rdev->ops->set_power_mgmt(&rdev->wiphy, dev, enabled, timeout);
+       trace_rdev_return_int(&rdev->wiphy, ret);
+       return ret;
+}
+
+static inline int
+rdev_set_cqm_rssi_config(struct cfg80211_registered_device *rdev,
+                        struct net_device *dev, s32 rssi_thold, u32 rssi_hyst)
+{
+       int ret;
+       trace_rdev_set_cqm_rssi_config(&rdev->wiphy, dev, rssi_thold,
+                                      rssi_hyst);
+       ret = rdev->ops->set_cqm_rssi_config(&rdev->wiphy, dev, rssi_thold,
+                                      rssi_hyst);
+       trace_rdev_return_int(&rdev->wiphy, ret);
+       return ret;
+}
+
+static inline int
+rdev_set_cqm_txe_config(struct cfg80211_registered_device *rdev,
+                       struct net_device *dev, u32 rate, u32 pkts, u32 intvl)
+{
+       int ret;
+       trace_rdev_set_cqm_txe_config(&rdev->wiphy, dev, rate, pkts, intvl);
+       ret = rdev->ops->set_cqm_txe_config(&rdev->wiphy, dev, rate, pkts,
+                                            intvl);
+       trace_rdev_return_int(&rdev->wiphy, ret);
+       return ret;
+}
+
+static inline void
+rdev_mgmt_frame_register(struct cfg80211_registered_device *rdev,
+                        struct wireless_dev *wdev, u16 frame_type, bool reg)
+{
+       trace_rdev_mgmt_frame_register(&rdev->wiphy, wdev , frame_type, reg);
+       rdev->ops->mgmt_frame_register(&rdev->wiphy, wdev , frame_type, reg);
+       trace_rdev_return_void(&rdev->wiphy);
+}
+
+static inline int rdev_set_antenna(struct cfg80211_registered_device *rdev,
+                                  u32 tx_ant, u32 rx_ant)
+{
+       int ret;
+       trace_rdev_set_antenna(&rdev->wiphy, tx_ant, rx_ant);
+       ret = rdev->ops->set_antenna(&rdev->wiphy, tx_ant, rx_ant);
+       trace_rdev_return_int(&rdev->wiphy, ret);
+       return ret;
+}
+
+static inline int rdev_get_antenna(struct cfg80211_registered_device *rdev,
+                                  u32 *tx_ant, u32 *rx_ant)
+{
+       int ret;
+       trace_rdev_get_antenna(&rdev->wiphy);
+       ret = rdev->ops->get_antenna(&rdev->wiphy, tx_ant, rx_ant);
+       if (ret)
+               trace_rdev_return_int(&rdev->wiphy, ret);
+       else
+               trace_rdev_return_int_tx_rx(&rdev->wiphy, ret, *tx_ant,
+                                           *rx_ant);
+       return ret;
+}
+
+static inline int rdev_set_ringparam(struct cfg80211_registered_device *rdev,
+                                    u32 tx, u32 rx)
+{
+       int ret;
+       trace_rdev_set_ringparam(&rdev->wiphy, tx, rx);
+       ret = rdev->ops->set_ringparam(&rdev->wiphy, tx, rx);
+       trace_rdev_return_int(&rdev->wiphy, ret);
+       return ret;
+}
+
+static inline void rdev_get_ringparam(struct cfg80211_registered_device *rdev,
+                                     u32 *tx, u32 *tx_max, u32 *rx,
+                                     u32 *rx_max)
+{
+       trace_rdev_get_ringparam(&rdev->wiphy);
+       rdev->ops->get_ringparam(&rdev->wiphy, tx, tx_max, rx, rx_max);
+       trace_rdev_return_void_tx_rx(&rdev->wiphy, *tx, *tx_max, *rx, *rx_max);
+}
+
+static inline int
+rdev_sched_scan_start(struct cfg80211_registered_device *rdev,
+                     struct net_device *dev,
+                     struct cfg80211_sched_scan_request *request)
+{
+       int ret;
+       trace_rdev_sched_scan_start(&rdev->wiphy, dev, request);
+       ret = rdev->ops->sched_scan_start(&rdev->wiphy, dev, request);
+       trace_rdev_return_int(&rdev->wiphy, ret);
+       return ret;
+}
+
+static inline int rdev_sched_scan_stop(struct cfg80211_registered_device *rdev,
+                                      struct net_device *dev)
+{
+       int ret;
+       trace_rdev_sched_scan_stop(&rdev->wiphy, dev);
+       ret = rdev->ops->sched_scan_stop(&rdev->wiphy, dev);
+       trace_rdev_return_int(&rdev->wiphy, ret);
+       return ret;
+}
+
+static inline int rdev_set_rekey_data(struct cfg80211_registered_device *rdev,
+                                     struct net_device *dev,
+                                     struct cfg80211_gtk_rekey_data *data)
+{
+       int ret;
+       trace_rdev_set_rekey_data(&rdev->wiphy, dev);
+       ret = rdev->ops->set_rekey_data(&rdev->wiphy, dev, data);
+       trace_rdev_return_int(&rdev->wiphy, ret);
+       return ret;
+}
+
+static inline int rdev_tdls_mgmt(struct cfg80211_registered_device *rdev,
+                                struct net_device *dev, u8 *peer,
+                                u8 action_code, u8 dialog_token,
+                                u16 status_code, const u8 *buf, size_t len)
+{
+       int ret;
+       trace_rdev_tdls_mgmt(&rdev->wiphy, dev, peer, action_code,
+                            dialog_token, status_code, buf, len);
+       ret = rdev->ops->tdls_mgmt(&rdev->wiphy, dev, peer, action_code,
+                                  dialog_token, status_code, buf, len);
+       trace_rdev_return_int(&rdev->wiphy, ret);
+       return ret;
+}
+
+static inline int rdev_tdls_oper(struct cfg80211_registered_device *rdev,
+                                struct net_device *dev, u8 *peer,
+                                enum nl80211_tdls_operation oper)
+{
+       int ret;
+       trace_rdev_tdls_oper(&rdev->wiphy, dev, peer, oper);
+       ret = rdev->ops->tdls_oper(&rdev->wiphy, dev, peer, oper);
+       trace_rdev_return_int(&rdev->wiphy, ret);
+       return ret;
+}
+
+static inline int rdev_probe_client(struct cfg80211_registered_device *rdev,
+                                   struct net_device *dev, const u8 *peer,
+                                   u64 *cookie)
+{
+       int ret;
+       trace_rdev_probe_client(&rdev->wiphy, dev, peer);
+       ret = rdev->ops->probe_client(&rdev->wiphy, dev, peer, cookie);
+       trace_rdev_return_int_cookie(&rdev->wiphy, ret, *cookie);
+       return ret;
+}
+
+static inline int rdev_set_noack_map(struct cfg80211_registered_device *rdev,
+                                    struct net_device *dev, u16 noack_map)
+{
+       int ret;
+       trace_rdev_set_noack_map(&rdev->wiphy, dev, noack_map);
+       ret = rdev->ops->set_noack_map(&rdev->wiphy, dev, noack_map);
+       trace_rdev_return_int(&rdev->wiphy, ret);
+       return ret;
+}
+
+static inline int
+rdev_get_et_sset_count(struct cfg80211_registered_device *rdev,
+                      struct net_device *dev, int sset)
+{
+       int ret;
+       trace_rdev_get_et_sset_count(&rdev->wiphy, dev, sset);
+       ret = rdev->ops->get_et_sset_count(&rdev->wiphy, dev, sset);
+       trace_rdev_return_int(&rdev->wiphy, ret);
+       return ret;
+}
+
+static inline void rdev_get_et_stats(struct cfg80211_registered_device *rdev,
+                                    struct net_device *dev,
+                                    struct ethtool_stats *stats, u64 *data)
+{
+       trace_rdev_get_et_stats(&rdev->wiphy, dev);
+       rdev->ops->get_et_stats(&rdev->wiphy, dev, stats, data);
+       trace_rdev_return_void(&rdev->wiphy);
+}
+
+static inline void rdev_get_et_strings(struct cfg80211_registered_device *rdev,
+                                      struct net_device *dev, u32 sset,
+                                      u8 *data)
+{
+       trace_rdev_get_et_strings(&rdev->wiphy, dev, sset);
+       rdev->ops->get_et_strings(&rdev->wiphy, dev, sset, data);
+       trace_rdev_return_void(&rdev->wiphy);
+}
+
+static inline struct ieee80211_channel
+*rdev_get_channel(struct cfg80211_registered_device *rdev,
+                 struct wireless_dev *wdev, enum nl80211_channel_type *type)
+{
+       struct ieee80211_channel *ret;
+       trace_rdev_get_channel(&rdev->wiphy, wdev);
+       ret = rdev->ops->get_channel(&rdev->wiphy, wdev, type);
+       trace_rdev_return_channel(&rdev->wiphy, ret, *type);
+       return ret;
+}
+
+#endif /* __CFG80211_RDEV_OPS */
index 9730c9862bdcfd624af15641deefe95c0b12c8de..7f97a087f452d7c8262592e8403a1b2433ee0e25 100644 (file)
 #include "core.h"
 #include "nl80211.h"
 #include "wext-compat.h"
+#include "rdev-ops.h"
 
 #define IEEE80211_SCAN_RESULT_EXPIRE   (30 * HZ)
 
+static void bss_release(struct kref *ref)
+{
+       struct cfg80211_internal_bss *bss;
+
+       bss = container_of(ref, struct cfg80211_internal_bss, ref);
+       if (bss->pub.free_priv)
+               bss->pub.free_priv(&bss->pub);
+
+       if (bss->beacon_ies_allocated)
+               kfree(bss->pub.beacon_ies);
+       if (bss->proberesp_ies_allocated)
+               kfree(bss->pub.proberesp_ies);
+
+       BUG_ON(atomic_read(&bss->hold));
+
+       kfree(bss);
+}
+
+/* must hold dev->bss_lock! */
+static void __cfg80211_unlink_bss(struct cfg80211_registered_device *dev,
+                                 struct cfg80211_internal_bss *bss)
+{
+       list_del_init(&bss->list);
+       rb_erase(&bss->rbn, &dev->bss_tree);
+       kref_put(&bss->ref, bss_release);
+}
+
+/* must hold dev->bss_lock! */
+static void __cfg80211_bss_expire(struct cfg80211_registered_device *dev,
+                                 unsigned long expire_time)
+{
+       struct cfg80211_internal_bss *bss, *tmp;
+       bool expired = false;
+
+       list_for_each_entry_safe(bss, tmp, &dev->bss_list, list) {
+               if (atomic_read(&bss->hold))
+                       continue;
+               if (!time_after(expire_time, bss->ts))
+                       continue;
+
+               __cfg80211_unlink_bss(dev, bss);
+               expired = true;
+       }
+
+       if (expired)
+               dev->bss_generation++;
+}
+
 void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak)
 {
        struct cfg80211_scan_request *request;
@@ -45,10 +94,17 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak)
        if (wdev->netdev)
                cfg80211_sme_scan_done(wdev->netdev);
 
-       if (request->aborted)
+       if (request->aborted) {
                nl80211_send_scan_aborted(rdev, wdev);
-       else
+       } else {
+               if (request->flags & NL80211_SCAN_FLAG_FLUSH) {
+                       /* flush entries from previous scans */
+                       spin_lock_bh(&rdev->bss_lock);
+                       __cfg80211_bss_expire(rdev, request->scan_start);
+                       spin_unlock_bh(&rdev->bss_lock);
+               }
                nl80211_send_scan_done(rdev, wdev);
+       }
 
 #ifdef CONFIG_CFG80211_WEXT
        if (wdev->netdev && !request->aborted) {
@@ -89,6 +145,7 @@ void __cfg80211_scan_done(struct work_struct *wk)
 
 void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted)
 {
+       trace_cfg80211_scan_done(request, aborted);
        WARN_ON(request != wiphy_to_dev(request->wiphy)->scan_req);
 
        request->aborted = aborted;
@@ -99,22 +156,34 @@ EXPORT_SYMBOL(cfg80211_scan_done);
 void __cfg80211_sched_scan_results(struct work_struct *wk)
 {
        struct cfg80211_registered_device *rdev;
+       struct cfg80211_sched_scan_request *request;
 
        rdev = container_of(wk, struct cfg80211_registered_device,
                            sched_scan_results_wk);
 
+       request = rdev->sched_scan_req;
+
        mutex_lock(&rdev->sched_scan_mtx);
 
        /* we don't have sched_scan_req anymore if the scan is stopping */
-       if (rdev->sched_scan_req)
-               nl80211_send_sched_scan_results(rdev,
-                                               rdev->sched_scan_req->dev);
+       if (request) {
+               if (request->flags & NL80211_SCAN_FLAG_FLUSH) {
+                       /* flush entries from previous scans */
+                       spin_lock_bh(&rdev->bss_lock);
+                       __cfg80211_bss_expire(rdev, request->scan_start);
+                       spin_unlock_bh(&rdev->bss_lock);
+                       request->scan_start =
+                               jiffies + msecs_to_jiffies(request->interval);
+               }
+               nl80211_send_sched_scan_results(rdev, request->dev);
+       }
 
        mutex_unlock(&rdev->sched_scan_mtx);
 }
 
 void cfg80211_sched_scan_results(struct wiphy *wiphy)
 {
+       trace_cfg80211_sched_scan_results(wiphy);
        /* ignore if we're not scanning */
        if (wiphy_to_dev(wiphy)->sched_scan_req)
                queue_work(cfg80211_wq,
@@ -126,6 +195,8 @@ void cfg80211_sched_scan_stopped(struct wiphy *wiphy)
 {
        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 
+       trace_cfg80211_sched_scan_stopped(wiphy);
+
        mutex_lock(&rdev->sched_scan_mtx);
        __cfg80211_stop_sched_scan(rdev, true);
        mutex_unlock(&rdev->sched_scan_mtx);
@@ -145,7 +216,7 @@ int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev,
        dev = rdev->sched_scan_req->dev;
 
        if (!driver_initiated) {
-               int err = rdev->ops->sched_scan_stop(&rdev->wiphy, dev);
+               int err = rdev_sched_scan_stop(rdev, dev);
                if (err)
                        return err;
        }
@@ -158,24 +229,6 @@ int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev,
        return 0;
 }
 
-static void bss_release(struct kref *ref)
-{
-       struct cfg80211_internal_bss *bss;
-
-       bss = container_of(ref, struct cfg80211_internal_bss, ref);
-       if (bss->pub.free_priv)
-               bss->pub.free_priv(&bss->pub);
-
-       if (bss->beacon_ies_allocated)
-               kfree(bss->pub.beacon_ies);
-       if (bss->proberesp_ies_allocated)
-               kfree(bss->pub.proberesp_ies);
-
-       BUG_ON(atomic_read(&bss->hold));
-
-       kfree(bss);
-}
-
 /* must hold dev->bss_lock! */
 void cfg80211_bss_age(struct cfg80211_registered_device *dev,
                       unsigned long age_secs)
@@ -188,32 +241,9 @@ void cfg80211_bss_age(struct cfg80211_registered_device *dev,
        }
 }
 
-/* must hold dev->bss_lock! */
-static void __cfg80211_unlink_bss(struct cfg80211_registered_device *dev,
-                                 struct cfg80211_internal_bss *bss)
-{
-       list_del_init(&bss->list);
-       rb_erase(&bss->rbn, &dev->bss_tree);
-       kref_put(&bss->ref, bss_release);
-}
-
-/* must hold dev->bss_lock! */
 void cfg80211_bss_expire(struct cfg80211_registered_device *dev)
 {
-       struct cfg80211_internal_bss *bss, *tmp;
-       bool expired = false;
-
-       list_for_each_entry_safe(bss, tmp, &dev->bss_list, list) {
-               if (atomic_read(&bss->hold))
-                       continue;
-               if (!time_after(jiffies, bss->ts + IEEE80211_SCAN_RESULT_EXPIRE))
-                       continue;
-               __cfg80211_unlink_bss(dev, bss);
-               expired = true;
-       }
-
-       if (expired)
-               dev->bss_generation++;
+       __cfg80211_bss_expire(dev, jiffies - IEEE80211_SCAN_RESULT_EXPIRE);
 }
 
 const u8 *cfg80211_find_ie(u8 eid, const u8 *ies, int len)
@@ -459,6 +489,9 @@ struct cfg80211_bss *cfg80211_get_bss(struct wiphy *wiphy,
        struct cfg80211_internal_bss *bss, *res = NULL;
        unsigned long now = jiffies;
 
+       trace_cfg80211_get_bss(wiphy, channel, bssid, ssid, ssid_len, capa_mask,
+                              capa_val);
+
        spin_lock_bh(&dev->bss_lock);
 
        list_for_each_entry(bss, &dev->bss_list, list) {
@@ -480,6 +513,7 @@ struct cfg80211_bss *cfg80211_get_bss(struct wiphy *wiphy,
        spin_unlock_bh(&dev->bss_lock);
        if (!res)
                return NULL;
+       trace_cfg80211_return_bss(&res->pub);
        return &res->pub;
 }
 EXPORT_SYMBOL(cfg80211_get_bss);
@@ -792,6 +826,7 @@ cfg80211_inform_bss(struct wiphy *wiphy,
        if (res->pub.capability & WLAN_CAPABILITY_ESS)
                regulatory_hint_found_beacon(wiphy, channel, gfp);
 
+       trace_cfg80211_return_bss(&res->pub);
        /* cfg80211_bss_update gives us a referenced result */
        return &res->pub;
 }
@@ -804,10 +839,13 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy,
                          s32 signal, gfp_t gfp)
 {
        struct cfg80211_internal_bss *res;
+
        size_t ielen = len - offsetof(struct ieee80211_mgmt,
                                      u.probe_resp.variable);
        size_t privsz;
 
+       trace_cfg80211_inform_bss_frame(wiphy, channel, mgmt, len, signal);
+
        if (WARN_ON(!mgmt))
                return NULL;
 
@@ -861,6 +899,7 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy,
        if (res->pub.capability & WLAN_CAPABILITY_ESS)
                regulatory_hint_found_beacon(wiphy, channel, gfp);
 
+       trace_cfg80211_return_bss(&res->pub);
        /* cfg80211_bss_update gives us a referenced result */
        return &res->pub;
 }
@@ -962,6 +1001,7 @@ int cfg80211_wext_siwscan(struct net_device *dev,
        creq->ssids = (void *)&creq->channels[n_channels];
        creq->n_channels = n_channels;
        creq->n_ssids = 1;
+       creq->scan_start = jiffies;
 
        /* translate "Scan on frequencies" request */
        i = 0;
@@ -1026,7 +1066,7 @@ int cfg80211_wext_siwscan(struct net_device *dev,
                        creq->rates[i] = (1 << wiphy->bands[i]->n_bitrates) - 1;
 
        rdev->scan_req = creq;
-       err = rdev->ops->scan(wiphy, creq);
+       err = rdev_scan(rdev, creq);
        if (err) {
                rdev->scan_req = NULL;
                /* creq will be freed below */
index 6f39cb808302380e05fa70d9a68925f7a35dcae3..c7490027237d2984e267b1bbdec6693d6cb49d8c 100644 (file)
@@ -16,6 +16,7 @@
 #include <net/rtnetlink.h>
 #include "nl80211.h"
 #include "reg.h"
+#include "rdev-ops.h"
 
 struct cfg80211_conn {
        struct cfg80211_connect_params params;
@@ -138,10 +139,11 @@ static int cfg80211_conn_scan(struct wireless_dev *wdev)
 
        request->wdev = wdev;
        request->wiphy = &rdev->wiphy;
+       request->scan_start = jiffies;
 
        rdev->scan_req = request;
 
-       err = rdev->ops->scan(wdev->wiphy, request);
+       err = rdev_scan(rdev, request);
        if (!err) {
                wdev->conn->state = CFG80211_CONN_SCANNING;
                nl80211_send_scan_start(rdev, wdev);
@@ -179,7 +181,7 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev)
                                            params->ssid, params->ssid_len,
                                            NULL, 0,
                                            params->key, params->key_len,
-                                           params->key_idx);
+                                           params->key_idx, NULL, 0);
        case CFG80211_CONN_ASSOCIATE_NEXT:
                BUG_ON(!rdev->ops->assoc);
                wdev->conn->state = CFG80211_CONN_ASSOCIATING;
@@ -716,7 +718,7 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie,
         */
        if (rdev->ops->del_key)
                for (i = 0; i < 6; i++)
-                       rdev->ops->del_key(wdev->wiphy, dev, i, false, NULL);
+                       rdev_del_key(rdev, dev, i, false, NULL);
 
 #ifdef CONFIG_CFG80211_WEXT
        memset(&wrqu, 0, sizeof(wrqu));
@@ -892,7 +894,7 @@ int __cfg80211_connect(struct cfg80211_registered_device *rdev,
        } else {
                wdev->sme_state = CFG80211_SME_CONNECTING;
                wdev->connect_keys = connkeys;
-               err = rdev->ops->connect(&rdev->wiphy, dev, connect);
+               err = rdev_connect(rdev, dev, connect);
                if (err) {
                        wdev->connect_keys = NULL;
                        wdev->sme_state = CFG80211_SME_IDLE;
@@ -964,7 +966,7 @@ int __cfg80211_disconnect(struct cfg80211_registered_device *rdev,
                if (err)
                        return err;
        } else {
-               err = rdev->ops->disconnect(&rdev->wiphy, dev, reason);
+               err = rdev_disconnect(rdev, dev, reason);
                if (err)
                        return err;
        }
index ff574597a8544030ef18b2e2186354ef46511bc3..9bf6d5e32166c47f315c0c8819a84128b857bc1c 100644 (file)
@@ -16,6 +16,7 @@
 #include <net/cfg80211.h>
 #include "sysfs.h"
 #include "core.h"
+#include "rdev-ops.h"
 
 static inline struct cfg80211_registered_device *dev_to_rdev(
        struct device *dev)
@@ -94,7 +95,7 @@ static int wiphy_suspend(struct device *dev, pm_message_t state)
        if (rdev->ops->suspend) {
                rtnl_lock();
                if (rdev->wiphy.registered)
-                       ret = rdev->ops->suspend(&rdev->wiphy, rdev->wowlan);
+                       ret = rdev_suspend(rdev);
                rtnl_unlock();
        }
 
@@ -114,7 +115,7 @@ static int wiphy_resume(struct device *dev)
        if (rdev->ops->resume) {
                rtnl_lock();
                if (rdev->wiphy.registered)
-                       ret = rdev->ops->resume(&rdev->wiphy);
+                       ret = rdev_resume(rdev);
                rtnl_unlock();
        }
 
diff --git a/net/wireless/trace.c b/net/wireless/trace.c
new file mode 100644 (file)
index 0000000..95f997f
--- /dev/null
@@ -0,0 +1,7 @@
+#include <linux/module.h>
+
+#ifndef __CHECKER__
+#define CREATE_TRACE_POINTS
+#include "trace.h"
+
+#endif
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
new file mode 100644 (file)
index 0000000..857734c
--- /dev/null
@@ -0,0 +1,2286 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM cfg80211
+
+#if !defined(__RDEV_OPS_TRACE) || defined(TRACE_HEADER_MULTI_READ)
+#define __RDEV_OPS_TRACE
+
+#include <linux/tracepoint.h>
+
+#include <linux/rtnetlink.h>
+#include <net/cfg80211.h>
+#include "core.h"
+
+#define MAC_ENTRY(entry_mac) __array(u8, entry_mac, ETH_ALEN)
+#define MAC_ASSIGN(entry_mac, given_mac) do {                       \
+       if (given_mac)                                               \
+               memcpy(__entry->entry_mac, given_mac, ETH_ALEN);     \
+       else                                                         \
+               memset(__entry->entry_mac, 0, ETH_ALEN);             \
+       } while (0)
+#define MAC_PR_FMT "%pM"
+#define MAC_PR_ARG(entry_mac) (__entry->entry_mac)
+
+#define WIPHY_ENTRY MAC_ENTRY(wiphy_mac)
+#define WIPHY_ASSIGN MAC_ASSIGN(wiphy_mac, wiphy->perm_addr)
+#define WIPHY_PR_FMT "wiphy " MAC_PR_FMT
+#define WIPHY_PR_ARG MAC_PR_ARG(wiphy_mac)
+
+#define WDEV_ENTRY __field(u32, id)
+#define WDEV_ASSIGN (__entry->id) = (wdev->identifier)
+#define WDEV_PR_FMT ", wdev id: %u"
+#define WDEV_PR_ARG (__entry->id)
+
+#define NETDEV_ENTRY __array(char, name, IFNAMSIZ) \
+                    MAC_ENTRY(netdev_addr)        \
+                    __field(int, ifindex)
+#define NETDEV_ASSIGN                                         \
+       do {                                                   \
+               memcpy(__entry->name, netdev->name, IFNAMSIZ); \
+               MAC_ASSIGN(netdev_addr, netdev->dev_addr);     \
+               (__entry->ifindex) = (netdev->ifindex);        \
+       } while (0)
+#define NETDEV_PR_FMT ", netdev - name: %s, addr: " MAC_PR_FMT \
+                     ", intf index: %d"
+#define NETDEV_PR_ARG (__entry->name), MAC_PR_ARG(netdev_addr), \
+                     (__entry->ifindex)
+
+#define MESH_CFG_ENTRY __field(u16, dot11MeshRetryTimeout)                \
+                      __field(u16, dot11MeshConfirmTimeout)               \
+                      __field(u16, dot11MeshHoldingTimeout)               \
+                      __field(u16, dot11MeshMaxPeerLinks)                 \
+                      __field(u8, dot11MeshMaxRetries)                    \
+                      __field(u8, dot11MeshTTL)                           \
+                      __field(u8, element_ttl)                            \
+                      __field(bool, auto_open_plinks)                     \
+                      __field(u32, dot11MeshNbrOffsetMaxNeighbor)         \
+                      __field(u8, dot11MeshHWMPmaxPREQretries)            \
+                      __field(u32, path_refresh_time)                     \
+                      __field(u32, dot11MeshHWMPactivePathTimeout)        \
+                      __field(u16, min_discovery_timeout)                 \
+                      __field(u16, dot11MeshHWMPpreqMinInterval)          \
+                      __field(u16, dot11MeshHWMPperrMinInterval)          \
+                      __field(u16, dot11MeshHWMPnetDiameterTraversalTime) \
+                      __field(u8, dot11MeshHWMPRootMode)                  \
+                      __field(u16, dot11MeshHWMPRannInterval)             \
+                      __field(bool, dot11MeshGateAnnouncementProtocol)    \
+                      __field(bool, dot11MeshForwarding)                  \
+                      __field(s32, rssi_threshold)                        \
+                      __field(u16, ht_opmode)                             \
+                      __field(u32, dot11MeshHWMPactivePathToRootTimeout)  \
+                      __field(u16, dot11MeshHWMProotInterval)             \
+                      __field(u16, dot11MeshHWMPconfirmationInterval)
+#define MESH_CFG_ASSIGN                                                              \
+       do {                                                                  \
+               __entry->dot11MeshRetryTimeout = conf->dot11MeshRetryTimeout; \
+               __entry->dot11MeshConfirmTimeout =                            \
+                               conf->dot11MeshConfirmTimeout;                \
+               __entry->dot11MeshHoldingTimeout =                            \
+                               conf->dot11MeshHoldingTimeout;                \
+               __entry->dot11MeshMaxPeerLinks = conf->dot11MeshMaxPeerLinks; \
+               __entry->dot11MeshMaxRetries = conf->dot11MeshMaxRetries;     \
+               __entry->dot11MeshTTL = conf->dot11MeshTTL;                   \
+               __entry->element_ttl = conf->element_ttl;                     \
+               __entry->auto_open_plinks = conf->auto_open_plinks;           \
+               __entry->dot11MeshNbrOffsetMaxNeighbor =                      \
+                               conf->dot11MeshNbrOffsetMaxNeighbor;          \
+               __entry->dot11MeshHWMPmaxPREQretries =                        \
+                               conf->dot11MeshHWMPmaxPREQretries;            \
+               __entry->path_refresh_time = conf->path_refresh_time;         \
+               __entry->dot11MeshHWMPactivePathTimeout =                     \
+                               conf->dot11MeshHWMPactivePathTimeout;         \
+               __entry->min_discovery_timeout = conf->min_discovery_timeout; \
+               __entry->dot11MeshHWMPpreqMinInterval =                       \
+                               conf->dot11MeshHWMPpreqMinInterval;           \
+               __entry->dot11MeshHWMPperrMinInterval =                       \
+                               conf->dot11MeshHWMPperrMinInterval;           \
+               __entry->dot11MeshHWMPnetDiameterTraversalTime =              \
+                               conf->dot11MeshHWMPnetDiameterTraversalTime;  \
+               __entry->dot11MeshHWMPRootMode = conf->dot11MeshHWMPRootMode; \
+               __entry->dot11MeshHWMPRannInterval =                          \
+                               conf->dot11MeshHWMPRannInterval;              \
+               __entry->dot11MeshGateAnnouncementProtocol =                  \
+                               conf->dot11MeshGateAnnouncementProtocol;      \
+               __entry->dot11MeshForwarding = conf->dot11MeshForwarding;     \
+               __entry->rssi_threshold = conf->rssi_threshold;               \
+               __entry->ht_opmode = conf->ht_opmode;                         \
+               __entry->dot11MeshHWMPactivePathToRootTimeout =               \
+                               conf->dot11MeshHWMPactivePathToRootTimeout;   \
+               __entry->dot11MeshHWMProotInterval =                          \
+                               conf->dot11MeshHWMProotInterval;              \
+               __entry->dot11MeshHWMPconfirmationInterval =                  \
+                               conf->dot11MeshHWMPconfirmationInterval;      \
+       } while (0)
+
+#define CHAN_ENTRY __field(enum ieee80211_band, band) \
+                  __field(u16, center_freq)
+#define CHAN_ASSIGN(chan)                                        \
+       do {                                                      \
+               if (chan) {                                       \
+                       __entry->band = chan->band;               \
+                       __entry->center_freq = chan->center_freq; \
+               } else {                                          \
+                       __entry->band = 0;                        \
+                       __entry->center_freq = 0;                 \
+               }                                                 \
+       } while (0)
+#define CHAN_PR_FMT ", band: %d, freq: %u"
+#define CHAN_PR_ARG __entry->band, __entry->center_freq
+
+#define SINFO_ENTRY __field(int, generation)       \
+                   __field(u32, connected_time)    \
+                   __field(u32, inactive_time)     \
+                   __field(u32, rx_bytes)          \
+                   __field(u32, tx_bytes)          \
+                   __field(u32, rx_packets)        \
+                   __field(u32, tx_packets)        \
+                   __field(u32, tx_retries)        \
+                   __field(u32, tx_failed)         \
+                   __field(u32, rx_dropped_misc)   \
+                   __field(u32, beacon_loss_count) \
+                   __field(u16, llid)              \
+                   __field(u16, plid)              \
+                   __field(u8, plink_state)
+#define SINFO_ASSIGN                                                  \
+       do {                                                           \
+               __entry->generation = sinfo->generation;               \
+               __entry->connected_time = sinfo->connected_time;       \
+               __entry->inactive_time = sinfo->inactive_time;         \
+               __entry->rx_bytes = sinfo->rx_bytes;                   \
+               __entry->tx_bytes = sinfo->tx_bytes;                   \
+               __entry->rx_packets = sinfo->rx_packets;               \
+               __entry->tx_packets = sinfo->tx_packets;               \
+               __entry->tx_retries = sinfo->tx_retries;               \
+               __entry->tx_failed = sinfo->tx_failed;                 \
+               __entry->rx_dropped_misc = sinfo->rx_dropped_misc;     \
+               __entry->beacon_loss_count = sinfo->beacon_loss_count; \
+               __entry->llid = sinfo->llid;                           \
+               __entry->plid = sinfo->plid;                           \
+               __entry->plink_state = sinfo->plink_state;             \
+       } while (0)
+
+#define BOOL_TO_STR(bo) (bo) ? "true" : "false"
+
+/*************************************************************
+ *                     rdev->ops traces                     *
+ *************************************************************/
+
+TRACE_EVENT(rdev_suspend,
+       TP_PROTO(struct wiphy *wiphy, struct cfg80211_wowlan *wow),
+       TP_ARGS(wiphy, wow),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               __field(bool, any)
+               __field(bool, disconnect)
+               __field(bool, magic_pkt)
+               __field(bool, gtk_rekey_failure)
+               __field(bool, eap_identity_req)
+               __field(bool, four_way_handshake)
+               __field(bool, rfkill_release)
+               __field(bool, valid_wow)
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               if (wow) {
+                       __entry->any = wow->any;
+                       __entry->disconnect = wow->disconnect;
+                       __entry->magic_pkt = wow->magic_pkt;
+                       __entry->gtk_rekey_failure = wow->gtk_rekey_failure;
+                       __entry->eap_identity_req = wow->eap_identity_req;
+                       __entry->four_way_handshake = wow->four_way_handshake;
+                       __entry->rfkill_release = wow->rfkill_release;
+                       __entry->valid_wow = true;
+               } else {
+                       __entry->valid_wow = false;
+               }
+       ),
+       TP_printk(WIPHY_PR_FMT ", wow%s - any: %d, disconnect: %d, "
+                 "magic pkt: %d, gtk rekey failure: %d, eap identify req: %d, "
+                 "four way handshake: %d, rfkill release: %d.",
+                 WIPHY_PR_ARG, __entry->valid_wow ? "" : "(Not configured!)",
+                 __entry->any, __entry->disconnect, __entry->magic_pkt,
+                 __entry->gtk_rekey_failure, __entry->eap_identity_req,
+                 __entry->four_way_handshake, __entry->rfkill_release)
+);
+
+TRACE_EVENT(rdev_return_int,
+       TP_PROTO(struct wiphy *wiphy, int ret),
+       TP_ARGS(wiphy, ret),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               __field(int, ret)
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               __entry->ret = ret;
+       ),
+       TP_printk(WIPHY_PR_FMT ", returned: %d", WIPHY_PR_ARG, __entry->ret)
+);
+
+TRACE_EVENT(rdev_scan,
+       TP_PROTO(struct wiphy *wiphy, struct cfg80211_scan_request *request),
+       TP_ARGS(wiphy, request),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+       ),
+       TP_printk(WIPHY_PR_FMT, WIPHY_PR_ARG)
+);
+
+DECLARE_EVENT_CLASS(wiphy_only_evt,
+       TP_PROTO(struct wiphy *wiphy),
+       TP_ARGS(wiphy),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+       ),
+       TP_printk(WIPHY_PR_FMT, WIPHY_PR_ARG)
+);
+
+DEFINE_EVENT(wiphy_only_evt, rdev_resume,
+       TP_PROTO(struct wiphy *wiphy),
+       TP_ARGS(wiphy)
+);
+
+DEFINE_EVENT(wiphy_only_evt, rdev_return_void,
+       TP_PROTO(struct wiphy *wiphy),
+       TP_ARGS(wiphy)
+);
+
+DEFINE_EVENT(wiphy_only_evt, rdev_get_ringparam,
+       TP_PROTO(struct wiphy *wiphy),
+       TP_ARGS(wiphy)
+);
+
+DEFINE_EVENT(wiphy_only_evt, rdev_get_antenna,
+       TP_PROTO(struct wiphy *wiphy),
+       TP_ARGS(wiphy)
+);
+
+DEFINE_EVENT(wiphy_only_evt, rdev_get_tx_power,
+       TP_PROTO(struct wiphy *wiphy),
+       TP_ARGS(wiphy)
+);
+
+DEFINE_EVENT(wiphy_only_evt, rdev_rfkill_poll,
+       TP_PROTO(struct wiphy *wiphy),
+       TP_ARGS(wiphy)
+);
+
+DECLARE_EVENT_CLASS(wiphy_enabled_evt,
+       TP_PROTO(struct wiphy *wiphy, bool enabled),
+       TP_ARGS(wiphy, enabled),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               __field(bool, enabled)
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               __entry->enabled = enabled;
+       ),
+       TP_printk(WIPHY_PR_FMT ", %senabled ",
+                 WIPHY_PR_ARG, __entry->enabled ? "" : "not ")
+);
+
+DEFINE_EVENT(wiphy_enabled_evt, rdev_set_wakeup,
+       TP_PROTO(struct wiphy *wiphy, bool enabled),
+       TP_ARGS(wiphy, enabled)
+);
+
+TRACE_EVENT(rdev_add_virtual_intf,
+       TP_PROTO(struct wiphy *wiphy, char *name, enum nl80211_iftype type),
+       TP_ARGS(wiphy, name, type),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               __string(vir_intf_name, name ? name : "<noname>")
+               __field(enum nl80211_iftype, type)
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               __assign_str(vir_intf_name, name ? name : "<noname>");
+               __entry->type = type;
+       ),
+       TP_printk(WIPHY_PR_FMT ", virtual intf name: %s, type: %d",
+                 WIPHY_PR_ARG, __get_str(vir_intf_name), __entry->type)
+);
+
+DECLARE_EVENT_CLASS(wiphy_wdev_evt,
+       TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev),
+       TP_ARGS(wiphy, wdev),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               WDEV_ENTRY
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               WDEV_ASSIGN;
+       ),
+       TP_printk(WIPHY_PR_FMT WDEV_PR_FMT, WIPHY_PR_ARG, WDEV_PR_ARG)
+);
+
+DEFINE_EVENT(wiphy_wdev_evt, rdev_return_wdev,
+       TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev),
+       TP_ARGS(wiphy, wdev)
+);
+
+DEFINE_EVENT(wiphy_wdev_evt, rdev_del_virtual_intf,
+       TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev),
+       TP_ARGS(wiphy, wdev)
+);
+
+TRACE_EVENT(rdev_change_virtual_intf,
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+                enum nl80211_iftype type),
+       TP_ARGS(wiphy, netdev, type),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               NETDEV_ENTRY
+               __field(enum nl80211_iftype, type)
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               NETDEV_ASSIGN;
+               __entry->type = type;
+       ),
+       TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", type: %d",
+                 WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->type)
+);
+
+DECLARE_EVENT_CLASS(key_handle,
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
+                bool pairwise, const u8 *mac_addr),
+       TP_ARGS(wiphy, netdev, key_index, pairwise, mac_addr),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               NETDEV_ENTRY
+               MAC_ENTRY(mac_addr)
+               __field(u8, key_index)
+               __field(bool, pairwise)
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               NETDEV_ASSIGN;
+               MAC_ASSIGN(mac_addr, mac_addr);
+               __entry->key_index = key_index;
+               __entry->pairwise = pairwise;
+       ),
+       TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", key_index: %u, pairwise: %s, mac addr: " MAC_PR_FMT,
+                 WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->key_index,
+                 BOOL_TO_STR(__entry->pairwise), MAC_PR_ARG(mac_addr))
+);
+
+DEFINE_EVENT(key_handle, rdev_add_key,
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
+                bool pairwise, const u8 *mac_addr),
+       TP_ARGS(wiphy, netdev, key_index, pairwise, mac_addr)
+);
+
+DEFINE_EVENT(key_handle, rdev_get_key,
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
+                bool pairwise, const u8 *mac_addr),
+       TP_ARGS(wiphy, netdev, key_index, pairwise, mac_addr)
+);
+
+DEFINE_EVENT(key_handle, rdev_del_key,
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
+                bool pairwise, const u8 *mac_addr),
+       TP_ARGS(wiphy, netdev, key_index, pairwise, mac_addr)
+);
+
+TRACE_EVENT(rdev_set_default_key,
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
+                bool unicast, bool multicast),
+       TP_ARGS(wiphy, netdev, key_index, unicast, multicast),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               NETDEV_ENTRY
+               __field(u8, key_index)
+               __field(bool, unicast)
+               __field(bool, multicast)
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               NETDEV_ASSIGN;
+               __entry->key_index = key_index;
+               __entry->unicast = unicast;
+               __entry->multicast = multicast;
+       ),
+       TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", key index: %u, unicast: %s, multicast: %s",
+                 WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->key_index,
+                 BOOL_TO_STR(__entry->unicast),
+                 BOOL_TO_STR(__entry->multicast))
+);
+
+TRACE_EVENT(rdev_set_default_mgmt_key,
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u8 key_index),
+       TP_ARGS(wiphy, netdev, key_index),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               NETDEV_ENTRY
+               __field(u8, key_index)
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               NETDEV_ASSIGN;
+               __entry->key_index = key_index;
+       ),
+       TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", key index: %u",
+                 WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->key_index)
+);
+
+TRACE_EVENT(rdev_start_ap,
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+                struct cfg80211_ap_settings *settings),
+       TP_ARGS(wiphy, netdev, settings),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               NETDEV_ENTRY
+               CHAN_ENTRY
+               __field(int, beacon_interval)
+               __field(int, dtim_period)
+               __array(char, ssid, IEEE80211_MAX_SSID_LEN + 1)
+               __field(enum nl80211_hidden_ssid, hidden_ssid)
+               __field(u32, wpa_ver)
+               __field(bool, privacy)
+               __field(enum nl80211_auth_type, auth_type)
+               __field(int, inactivity_timeout)
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               NETDEV_ASSIGN;
+               CHAN_ASSIGN(settings->channel);
+               __entry->beacon_interval = settings->beacon_interval;
+               __entry->dtim_period = settings->dtim_period;
+               __entry->hidden_ssid = settings->hidden_ssid;
+               __entry->wpa_ver = settings->crypto.wpa_versions;
+               __entry->privacy = settings->privacy;
+               __entry->auth_type = settings->auth_type;
+               __entry->inactivity_timeout = settings->inactivity_timeout;
+               memset(__entry->ssid, 0, IEEE80211_MAX_SSID_LEN + 1);
+               memcpy(__entry->ssid, settings->ssid, settings->ssid_len);
+       ),
+       TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", AP settings - ssid: %s, "
+                 CHAN_PR_FMT ", beacon interval: %d, dtim period: %d, "
+                 "hidden ssid: %d, wpa versions: %u, privacy: %s, "
+                 "auth type: %d, inactivity timeout: %d",
+                 WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->ssid, CHAN_PR_ARG,
+                 __entry->beacon_interval, __entry->dtim_period,
+                 __entry->hidden_ssid, __entry->wpa_ver,
+                 BOOL_TO_STR(__entry->privacy), __entry->auth_type,
+                 __entry->inactivity_timeout)
+);
+
+TRACE_EVENT(rdev_change_beacon,
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+                struct cfg80211_beacon_data *info),
+       TP_ARGS(wiphy, netdev, info),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               NETDEV_ENTRY
+               __dynamic_array(u8, head, info ? info->head_len : 0)
+               __dynamic_array(u8, tail, info ? info->tail_len : 0)
+               __dynamic_array(u8, beacon_ies, info ? info->beacon_ies_len : 0)
+               __dynamic_array(u8, proberesp_ies,
+                               info ? info->proberesp_ies_len : 0)
+               __dynamic_array(u8, assocresp_ies,
+                               info ? info->assocresp_ies_len : 0)
+               __dynamic_array(u8, probe_resp, info ? info->probe_resp_len : 0)
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               NETDEV_ASSIGN;
+               if (info) {
+                       if (info->head)
+                               memcpy(__get_dynamic_array(head), info->head,
+                                      info->head_len);
+                       if (info->tail)
+                               memcpy(__get_dynamic_array(tail), info->tail,
+                                      info->tail_len);
+                       if (info->beacon_ies)
+                               memcpy(__get_dynamic_array(beacon_ies),
+                                      info->beacon_ies, info->beacon_ies_len);
+                       if (info->proberesp_ies)
+                               memcpy(__get_dynamic_array(proberesp_ies),
+                                      info->proberesp_ies,
+                                      info->proberesp_ies_len);
+                       if (info->assocresp_ies)
+                               memcpy(__get_dynamic_array(assocresp_ies),
+                                      info->assocresp_ies,
+                                      info->assocresp_ies_len);
+                       if (info->probe_resp)
+                               memcpy(__get_dynamic_array(probe_resp),
+                                      info->probe_resp, info->probe_resp_len);
+               }
+       ),
+       TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT, WIPHY_PR_ARG, NETDEV_PR_ARG)
+);
+
+DECLARE_EVENT_CLASS(wiphy_netdev_evt,
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev),
+       TP_ARGS(wiphy, netdev),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               NETDEV_ENTRY
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               NETDEV_ASSIGN;
+       ),
+       TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT, WIPHY_PR_ARG, NETDEV_PR_ARG)
+);
+
+DEFINE_EVENT(wiphy_netdev_evt, rdev_stop_ap,
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev),
+       TP_ARGS(wiphy, netdev)
+);
+
+DEFINE_EVENT(wiphy_netdev_evt, rdev_get_et_stats,
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev),
+       TP_ARGS(wiphy, netdev)
+);
+
+DEFINE_EVENT(wiphy_netdev_evt, rdev_sched_scan_stop,
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev),
+       TP_ARGS(wiphy, netdev)
+);
+
+DEFINE_EVENT(wiphy_netdev_evt, rdev_set_rekey_data,
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev),
+       TP_ARGS(wiphy, netdev)
+);
+
+DEFINE_EVENT(wiphy_netdev_evt, rdev_get_mesh_config,
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev),
+       TP_ARGS(wiphy, netdev)
+);
+
+DEFINE_EVENT(wiphy_netdev_evt, rdev_leave_mesh,
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev),
+       TP_ARGS(wiphy, netdev)
+);
+
+DEFINE_EVENT(wiphy_netdev_evt, rdev_leave_ibss,
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev),
+       TP_ARGS(wiphy, netdev)
+);
+
+DEFINE_EVENT(wiphy_netdev_evt, rdev_flush_pmksa,
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev),
+       TP_ARGS(wiphy, netdev)
+);
+
+DECLARE_EVENT_CLASS(station_add_change,
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u8 *mac,
+                struct station_parameters *params),
+       TP_ARGS(wiphy, netdev, mac, params),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               NETDEV_ENTRY
+               MAC_ENTRY(sta_mac)
+               __field(u32, sta_flags_mask)
+               __field(u32, sta_flags_set)
+               __field(u32, sta_modify_mask)
+               __field(int, listen_interval)
+               __field(u16, aid)
+               __field(u8, plink_action)
+               __field(u8, plink_state)
+               __field(u8, uapsd_queues)
+               __array(u8, ht_capa, (int)sizeof(struct ieee80211_ht_cap))
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               NETDEV_ASSIGN;
+               MAC_ASSIGN(sta_mac, mac);
+               __entry->sta_flags_mask = params->sta_flags_mask;
+               __entry->sta_flags_set = params->sta_flags_set;
+               __entry->sta_modify_mask = params->sta_modify_mask;
+               __entry->listen_interval = params->listen_interval;
+               __entry->aid = params->aid;
+               __entry->plink_action = params->plink_action;
+               __entry->plink_state = params->plink_state;
+               __entry->uapsd_queues = params->uapsd_queues;
+               memset(__entry->ht_capa, 0, sizeof(struct ieee80211_ht_cap));
+               if (params->ht_capa)
+                       memcpy(__entry->ht_capa, params->ht_capa,
+                              sizeof(struct ieee80211_ht_cap));
+       ),
+       TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", station mac: " MAC_PR_FMT
+                 ", station flags mask: %u, station flags set: %u, "
+                 "station modify mask: %u, listen interval: %d, aid: %u, "
+                 "plink action: %u, plink state: %u, uapsd queues: %u",
+                 WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(sta_mac),
+                 __entry->sta_flags_mask, __entry->sta_flags_set,
+                 __entry->sta_modify_mask, __entry->listen_interval,
+                 __entry->aid, __entry->plink_action, __entry->plink_state,
+                 __entry->uapsd_queues)
+);
+
+DEFINE_EVENT(station_add_change, rdev_add_station,
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u8 *mac,
+                struct station_parameters *params),
+       TP_ARGS(wiphy, netdev, mac, params)
+);
+
+DEFINE_EVENT(station_add_change, rdev_change_station,
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u8 *mac,
+                struct station_parameters *params),
+       TP_ARGS(wiphy, netdev, mac, params)
+);
+
+DECLARE_EVENT_CLASS(wiphy_netdev_mac_evt,
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, const u8 *mac),
+       TP_ARGS(wiphy, netdev, mac),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               NETDEV_ENTRY
+               MAC_ENTRY(sta_mac)
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               NETDEV_ASSIGN;
+               MAC_ASSIGN(sta_mac, mac);
+       ),
+       TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", mac: " MAC_PR_FMT,
+                 WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(sta_mac))
+);
+
+DEFINE_EVENT(wiphy_netdev_mac_evt, rdev_del_station,
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, const u8 *mac),
+       TP_ARGS(wiphy, netdev, mac)
+);
+
+DEFINE_EVENT(wiphy_netdev_mac_evt, rdev_get_station,
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, const u8 *mac),
+       TP_ARGS(wiphy, netdev, mac)
+);
+
+DEFINE_EVENT(wiphy_netdev_mac_evt, rdev_del_mpath,
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, const u8 *mac),
+       TP_ARGS(wiphy, netdev, mac)
+);
+
+DEFINE_EVENT(wiphy_netdev_mac_evt, rdev_set_wds_peer,
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, const u8 *mac),
+       TP_ARGS(wiphy, netdev, mac)
+);
+
+TRACE_EVENT(rdev_dump_station,
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, int idx,
+                u8 *mac),
+       TP_ARGS(wiphy, netdev, idx, mac),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               NETDEV_ENTRY
+               MAC_ENTRY(sta_mac)
+               __field(int, idx)
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               NETDEV_ASSIGN;
+               MAC_ASSIGN(sta_mac, mac);
+               __entry->idx = idx;
+       ),
+       TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", station mac: " MAC_PR_FMT ", idx: %d",
+                 WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(sta_mac),
+                 __entry->idx)
+);
+
+TRACE_EVENT(rdev_return_int_station_info,
+       TP_PROTO(struct wiphy *wiphy, int ret, struct station_info *sinfo),
+       TP_ARGS(wiphy, ret, sinfo),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               __field(int, ret)
+               SINFO_ENTRY
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               __entry->ret = ret;
+               SINFO_ASSIGN;
+       ),
+       TP_printk(WIPHY_PR_FMT ", returned %d" ,
+                 WIPHY_PR_ARG, __entry->ret)
+);
+
+DECLARE_EVENT_CLASS(mpath_evt,
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u8 *dst,
+                u8 *next_hop),
+       TP_ARGS(wiphy, netdev, dst, next_hop),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               NETDEV_ENTRY
+               MAC_ENTRY(dst)
+               MAC_ENTRY(next_hop)
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               NETDEV_ASSIGN;
+               MAC_ASSIGN(dst, dst);
+               MAC_ASSIGN(next_hop, next_hop);
+       ),
+       TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", destination: " MAC_PR_FMT ", next hop: " MAC_PR_FMT,
+                 WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(dst),
+                 MAC_PR_ARG(next_hop))
+);
+
+DEFINE_EVENT(mpath_evt, rdev_add_mpath,
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u8 *dst,
+                u8 *next_hop),
+       TP_ARGS(wiphy, netdev, dst, next_hop)
+);
+
+DEFINE_EVENT(mpath_evt, rdev_change_mpath,
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u8 *dst,
+                u8 *next_hop),
+       TP_ARGS(wiphy, netdev, dst, next_hop)
+);
+
+DEFINE_EVENT(mpath_evt, rdev_get_mpath,
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u8 *dst,
+                u8 *next_hop),
+       TP_ARGS(wiphy, netdev, dst, next_hop)
+);
+
+TRACE_EVENT(rdev_dump_mpath,
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, int idx,
+                u8 *dst, u8 *next_hop),
+       TP_ARGS(wiphy, netdev, idx, dst, next_hop),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               NETDEV_ENTRY
+               MAC_ENTRY(dst)
+               MAC_ENTRY(next_hop)
+               __field(int, idx)
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               NETDEV_ASSIGN;
+               MAC_ASSIGN(dst, dst);
+               MAC_ASSIGN(next_hop, next_hop);
+               __entry->idx = idx;
+       ),
+       TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", index: %d, destination: "
+                 MAC_PR_FMT ", next hop: " MAC_PR_FMT,
+                 WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->idx, MAC_PR_ARG(dst),
+                 MAC_PR_ARG(next_hop))
+);
+
+TRACE_EVENT(rdev_return_int_mpath_info,
+       TP_PROTO(struct wiphy *wiphy, int ret, struct mpath_info *pinfo),
+       TP_ARGS(wiphy, ret, pinfo),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               __field(int, ret)
+               __field(int, generation)
+               __field(u32, filled)
+               __field(u32, frame_qlen)
+               __field(u32, sn)
+               __field(u32, metric)
+               __field(u32, exptime)
+               __field(u32, discovery_timeout)
+               __field(u8, discovery_retries)
+               __field(u8, flags)
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               __entry->ret = ret;
+               __entry->generation = pinfo->generation;
+               __entry->filled = pinfo->filled;
+               __entry->frame_qlen = pinfo->frame_qlen;
+               __entry->sn = pinfo->sn;
+               __entry->metric = pinfo->metric;
+               __entry->exptime = pinfo->exptime;
+               __entry->discovery_timeout = pinfo->discovery_timeout;
+               __entry->discovery_retries = pinfo->discovery_retries;
+               __entry->flags = pinfo->flags;
+       ),
+       TP_printk(WIPHY_PR_FMT ", returned %d. mpath info - generation: %d, "
+                 "filled: %u, frame qlen: %u, sn: %u, metric: %u, exptime: %u,"
+                 " discovery timeout: %u, discovery retries: %u, flags: %u",
+                 WIPHY_PR_ARG, __entry->ret, __entry->generation,
+                 __entry->filled, __entry->frame_qlen, __entry->sn,
+                 __entry->metric, __entry->exptime, __entry->discovery_timeout,
+                 __entry->discovery_retries, __entry->flags)
+);
+
+TRACE_EVENT(rdev_return_int_mesh_config,
+       TP_PROTO(struct wiphy *wiphy, int ret, struct mesh_config *conf),
+       TP_ARGS(wiphy, ret, conf),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               MESH_CFG_ENTRY
+               __field(int, ret)
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               MESH_CFG_ASSIGN;
+               __entry->ret = ret;
+       ),
+       TP_printk(WIPHY_PR_FMT ", returned: %d",
+                 WIPHY_PR_ARG, __entry->ret)
+);
+
+TRACE_EVENT(rdev_update_mesh_config,
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u32 mask,
+                const struct mesh_config *conf),
+       TP_ARGS(wiphy, netdev, mask, conf),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               NETDEV_ENTRY
+               MESH_CFG_ENTRY
+               __field(u32, mask)
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               NETDEV_ASSIGN;
+               MESH_CFG_ASSIGN;
+               __entry->mask = mask;
+       ),
+       TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", mask: %u",
+                 WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->mask)
+);
+
+TRACE_EVENT(rdev_join_mesh,
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+                const struct mesh_config *conf,
+                const struct mesh_setup *setup),
+       TP_ARGS(wiphy, netdev, conf, setup),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               NETDEV_ENTRY
+               MESH_CFG_ENTRY
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               NETDEV_ASSIGN;
+               MESH_CFG_ASSIGN;
+       ),
+       TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT,
+                 WIPHY_PR_ARG, NETDEV_PR_ARG)
+);
+
+TRACE_EVENT(rdev_change_bss,
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+                struct bss_parameters *params),
+       TP_ARGS(wiphy, netdev, params),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               NETDEV_ENTRY
+               __field(int, use_cts_prot)
+               __field(int, use_short_preamble)
+               __field(int, use_short_slot_time)
+               __field(int, ap_isolate)
+               __field(int, ht_opmode)
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               NETDEV_ASSIGN;
+               __entry->use_cts_prot = params->use_cts_prot;
+               __entry->use_short_preamble = params->use_short_preamble;
+               __entry->use_short_slot_time = params->use_short_slot_time;
+               __entry->ap_isolate = params->ap_isolate;
+               __entry->ht_opmode = params->ht_opmode;
+       ),
+       TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", use cts prot: %d, "
+                 "use short preamble: %d, use short slot time: %d, "
+                 "ap isolate: %d, ht opmode: %d",
+                 WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->use_cts_prot,
+                 __entry->use_short_preamble, __entry->use_short_slot_time,
+                 __entry->ap_isolate, __entry->ht_opmode)
+);
+
+TRACE_EVENT(rdev_set_txq_params,
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+                struct ieee80211_txq_params *params),
+       TP_ARGS(wiphy, netdev, params),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               NETDEV_ENTRY
+               __field(enum nl80211_ac, ac)
+               __field(u16, txop)
+               __field(u16, cwmin)
+               __field(u16, cwmax)
+               __field(u8, aifs)
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               NETDEV_ASSIGN;
+               __entry->ac = params->ac;
+               __entry->txop = params->txop;
+               __entry->cwmin = params->cwmin;
+               __entry->cwmax = params->cwmax;
+               __entry->aifs = params->aifs;
+       ),
+       TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", ac: %d, txop: %u, cwmin: %u, cwmax: %u, aifs: %u",
+                 WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->ac, __entry->txop,
+                 __entry->cwmin, __entry->cwmax, __entry->aifs)
+);
+
+TRACE_EVENT(rdev_libertas_set_mesh_channel,
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+                struct ieee80211_channel *chan),
+       TP_ARGS(wiphy, netdev, chan),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               NETDEV_ENTRY
+               CHAN_ENTRY
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               NETDEV_ASSIGN;
+               CHAN_ASSIGN(chan);
+       ),
+       TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT CHAN_PR_FMT, WIPHY_PR_ARG,
+                 NETDEV_PR_ARG, CHAN_PR_ARG)
+);
+
+TRACE_EVENT(rdev_set_monitor_channel,
+       TP_PROTO(struct wiphy *wiphy, struct ieee80211_channel *chan,
+                enum nl80211_channel_type chan_type),
+       TP_ARGS(wiphy, chan, chan_type),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               CHAN_ENTRY
+               __field(enum nl80211_channel_type, chan_type)
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               CHAN_ASSIGN(chan);
+               __entry->chan_type = chan_type;
+       ),
+       TP_printk(WIPHY_PR_FMT CHAN_PR_FMT ", channel type : %d",
+                 WIPHY_PR_ARG, CHAN_PR_ARG, __entry->chan_type)
+);
+
+TRACE_EVENT(rdev_auth,
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+                struct cfg80211_auth_request *req),
+       TP_ARGS(wiphy, netdev, req),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               NETDEV_ENTRY
+               MAC_ENTRY(bssid)
+               __field(enum nl80211_auth_type, auth_type)
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               NETDEV_ASSIGN;
+               if (req->bss)
+                       MAC_ASSIGN(bssid, req->bss->bssid);
+               else
+                       memset(__entry->bssid, 0, ETH_ALEN);
+               __entry->auth_type = req->auth_type;
+       ),
+       TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", auth type: %d, bssid: " MAC_PR_FMT,
+                 WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->auth_type,
+                 MAC_PR_ARG(bssid))
+);
+
+TRACE_EVENT(rdev_assoc,
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+                struct cfg80211_assoc_request *req),
+       TP_ARGS(wiphy, netdev, req),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               NETDEV_ENTRY
+               MAC_ENTRY(bssid)
+               MAC_ENTRY(prev_bssid)
+               __field(bool, use_mfp)
+               __field(u32, flags)
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               NETDEV_ASSIGN;
+               if (req->bss)
+                       MAC_ASSIGN(bssid, req->bss->bssid);
+               else
+                       memset(__entry->bssid, 0, ETH_ALEN);
+               MAC_ASSIGN(prev_bssid, req->prev_bssid);
+               __entry->use_mfp = req->use_mfp;
+               __entry->flags = req->flags;
+       ),
+       TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", bssid: " MAC_PR_FMT
+                 ", previous bssid: " MAC_PR_FMT ", use mfp: %s, flags: %u",
+                 WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(bssid),
+                 MAC_PR_ARG(prev_bssid), BOOL_TO_STR(__entry->use_mfp),
+                 __entry->flags)
+);
+
+TRACE_EVENT(rdev_deauth,
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+                struct cfg80211_deauth_request *req),
+       TP_ARGS(wiphy, netdev, req),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               NETDEV_ENTRY
+               MAC_ENTRY(bssid)
+               __field(u16, reason_code)
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               NETDEV_ASSIGN;
+               MAC_ASSIGN(bssid, req->bssid);
+               __entry->reason_code = req->reason_code;
+       ),
+       TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", bssid: " MAC_PR_FMT ", reason: %u",
+                 WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(bssid),
+                 __entry->reason_code)
+);
+
+TRACE_EVENT(rdev_disassoc,
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+                struct cfg80211_disassoc_request *req),
+       TP_ARGS(wiphy, netdev, req),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               NETDEV_ENTRY
+               MAC_ENTRY(bssid)
+               __field(u16, reason_code)
+               __field(bool, local_state_change)
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               NETDEV_ASSIGN;
+               if (req->bss)
+                       MAC_ASSIGN(bssid, req->bss->bssid);
+               else
+                       memset(__entry->bssid, 0, ETH_ALEN);
+               __entry->reason_code = req->reason_code;
+               __entry->local_state_change = req->local_state_change;
+       ),
+       TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", bssid: " MAC_PR_FMT
+                 ", reason: %u, local state change: %s",
+                 WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(bssid),
+                 __entry->reason_code,
+                 BOOL_TO_STR(__entry->local_state_change))
+);
+
+TRACE_EVENT(rdev_mgmt_tx_cancel_wait,
+       TP_PROTO(struct wiphy *wiphy,
+                struct wireless_dev *wdev, u64 cookie),
+       TP_ARGS(wiphy, wdev, cookie),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               WDEV_ENTRY
+               __field(u64, cookie)
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               WDEV_ASSIGN;
+               __entry->cookie = cookie;
+       ),
+       TP_printk(WIPHY_PR_FMT WDEV_PR_FMT ", cookie: %llu ",
+                 WIPHY_PR_ARG, WDEV_PR_ARG, __entry->cookie)
+);
+
+TRACE_EVENT(rdev_set_power_mgmt,
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+                bool enabled, int timeout),
+       TP_ARGS(wiphy, netdev, enabled, timeout),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               NETDEV_ENTRY
+               __field(bool, enabled)
+               __field(int, timeout)
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               NETDEV_ASSIGN;
+               __entry->enabled = enabled;
+               __entry->timeout = timeout;
+       ),
+       TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", %senabled, timeout: %d ",
+                 WIPHY_PR_ARG, NETDEV_PR_ARG,
+                 __entry->enabled ? "" : "not ", __entry->timeout)
+);
+
+TRACE_EVENT(rdev_connect,
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+                struct cfg80211_connect_params *sme),
+       TP_ARGS(wiphy, netdev, sme),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               NETDEV_ENTRY
+               MAC_ENTRY(bssid)
+               __array(char, ssid, IEEE80211_MAX_SSID_LEN + 1)
+               __field(enum nl80211_auth_type, auth_type)
+               __field(bool, privacy)
+               __field(u32, wpa_versions)
+               __field(u32, flags)
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               NETDEV_ASSIGN;
+               MAC_ASSIGN(bssid, sme->bssid);
+               memset(__entry->ssid, 0, IEEE80211_MAX_SSID_LEN + 1);
+               memcpy(__entry->ssid, sme->ssid, sme->ssid_len);
+               __entry->auth_type = sme->auth_type;
+               __entry->privacy = sme->privacy;
+               __entry->wpa_versions = sme->crypto.wpa_versions;
+               __entry->flags = sme->flags;
+       ),
+       TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", bssid: " MAC_PR_FMT
+                 ", ssid: %s, auth type: %d, privacy: %s, wpa versions: %u, "
+                 "flags: %u",
+                 WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(bssid), __entry->ssid,
+                 __entry->auth_type, BOOL_TO_STR(__entry->privacy),
+                 __entry->wpa_versions, __entry->flags)
+);
+
+TRACE_EVENT(rdev_set_cqm_rssi_config,
+       TP_PROTO(struct wiphy *wiphy,
+                struct net_device *netdev, s32 rssi_thold,
+                u32 rssi_hyst),
+       TP_ARGS(wiphy, netdev, rssi_thold, rssi_hyst),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               NETDEV_ENTRY
+               __field(s32, rssi_thold)
+               __field(u32, rssi_hyst)
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               NETDEV_ASSIGN;
+               __entry->rssi_thold = rssi_thold;
+               __entry->rssi_hyst = rssi_hyst;
+       ),
+       TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT
+                 ", rssi_thold: %d, rssi_hyst: %u ",
+                 WIPHY_PR_ARG, NETDEV_PR_ARG,
+                __entry->rssi_thold, __entry->rssi_hyst)
+);
+
+TRACE_EVENT(rdev_set_cqm_txe_config,
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u32 rate,
+                u32 pkts, u32 intvl),
+       TP_ARGS(wiphy, netdev, rate, pkts, intvl),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               NETDEV_ENTRY
+               __field(u32, rate)
+               __field(u32, pkts)
+               __field(u32, intvl)
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               NETDEV_ASSIGN;
+               __entry->rate = rate;
+               __entry->pkts = pkts;
+               __entry->intvl = intvl;
+       ),
+       TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", rate: %u, packets: %u, interval: %u",
+                 WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->rate, __entry->pkts,
+                 __entry->intvl)
+);
+
+TRACE_EVENT(rdev_disconnect,
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+                u16 reason_code),
+       TP_ARGS(wiphy, netdev, reason_code),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               NETDEV_ENTRY
+               __field(u16, reason_code)
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               NETDEV_ASSIGN;
+               __entry->reason_code = reason_code;
+       ),
+       TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", reason code: %u", WIPHY_PR_ARG,
+                 NETDEV_PR_ARG, __entry->reason_code)
+);
+
+TRACE_EVENT(rdev_join_ibss,
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+                struct cfg80211_ibss_params *params),
+       TP_ARGS(wiphy, netdev, params),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               NETDEV_ENTRY
+               MAC_ENTRY(bssid)
+               __array(char, ssid, IEEE80211_MAX_SSID_LEN + 1)
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               NETDEV_ASSIGN;
+               MAC_ASSIGN(bssid, params->bssid);
+               memset(__entry->ssid, 0, IEEE80211_MAX_SSID_LEN + 1);
+               memcpy(__entry->ssid, params->ssid, params->ssid_len);
+       ),
+       TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", bssid: " MAC_PR_FMT ", ssid: %s",
+                 WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(bssid), __entry->ssid)
+);
+
+TRACE_EVENT(rdev_set_wiphy_params,
+       TP_PROTO(struct wiphy *wiphy, u32 changed),
+       TP_ARGS(wiphy, changed),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               __field(u32, changed)
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               __entry->changed = changed;
+       ),
+       TP_printk(WIPHY_PR_FMT ", changed: %u",
+                 WIPHY_PR_ARG, __entry->changed)
+);
+
+TRACE_EVENT(rdev_set_tx_power,
+       TP_PROTO(struct wiphy *wiphy, enum nl80211_tx_power_setting type,
+                int mbm),
+       TP_ARGS(wiphy, type, mbm),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               __field(enum nl80211_tx_power_setting, type)
+               __field(int, mbm)
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               __entry->type = type;
+               __entry->mbm = mbm;
+       ),
+       TP_printk(WIPHY_PR_FMT ", type: %d, mbm: %d",
+                 WIPHY_PR_ARG, __entry->type, __entry->mbm)
+);
+
+TRACE_EVENT(rdev_return_int_int,
+       TP_PROTO(struct wiphy *wiphy, int func_ret, int func_fill),
+       TP_ARGS(wiphy, func_ret, func_fill),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               __field(int, func_ret)
+               __field(int, func_fill)
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               __entry->func_ret = func_ret;
+               __entry->func_fill = func_fill;
+       ),
+       TP_printk(WIPHY_PR_FMT ", function returns: %d, function filled: %d",
+                 WIPHY_PR_ARG, __entry->func_ret, __entry->func_fill)
+);
+
+#ifdef CONFIG_NL80211_TESTMODE
+TRACE_EVENT(rdev_testmode_cmd,
+       TP_PROTO(struct wiphy *wiphy),
+       TP_ARGS(wiphy),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+       ),
+       TP_printk(WIPHY_PR_FMT, WIPHY_PR_ARG)
+);
+
+TRACE_EVENT(rdev_testmode_dump,
+       TP_PROTO(struct wiphy *wiphy),
+       TP_ARGS(wiphy),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+       ),
+       TP_printk(WIPHY_PR_FMT, WIPHY_PR_ARG)
+);
+#endif /* CONFIG_NL80211_TESTMODE */
+
+TRACE_EVENT(rdev_set_bitrate_mask,
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+                const u8 *peer, const struct cfg80211_bitrate_mask *mask),
+       TP_ARGS(wiphy, netdev, peer, mask),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               NETDEV_ENTRY
+               MAC_ENTRY(peer)
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               NETDEV_ASSIGN;
+               MAC_ASSIGN(peer, peer);
+       ),
+       TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", peer: " MAC_PR_FMT,
+                 WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer))
+);
+
+TRACE_EVENT(rdev_mgmt_frame_register,
+       TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev,
+                u16 frame_type, bool reg),
+       TP_ARGS(wiphy, wdev, frame_type, reg),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               WDEV_ENTRY
+               __field(u16, frame_type)
+               __field(bool, reg)
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               WDEV_ASSIGN;
+               __entry->frame_type = frame_type;
+               __entry->reg = reg;
+       ),
+       TP_printk(WIPHY_PR_FMT WDEV_PR_FMT ", frame_type: %u, reg: %s ",
+                 WIPHY_PR_ARG, WDEV_PR_ARG, __entry->frame_type,
+                 __entry->reg ? "true" : "false")
+);
+
+TRACE_EVENT(rdev_return_int_tx_rx,
+       TP_PROTO(struct wiphy *wiphy, int ret, u32 tx, u32 rx),
+       TP_ARGS(wiphy, ret, tx, rx),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               __field(int, ret)
+               __field(u32, tx)
+               __field(u32, rx)
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               __entry->ret = ret;
+               __entry->tx = tx;
+               __entry->rx = rx;
+       ),
+       TP_printk(WIPHY_PR_FMT ", returned %d, tx: %u, rx: %u",
+                 WIPHY_PR_ARG, __entry->ret, __entry->tx, __entry->rx)
+);
+
+TRACE_EVENT(rdev_return_void_tx_rx,
+       TP_PROTO(struct wiphy *wiphy, u32 tx, u32 tx_max,
+                u32 rx, u32 rx_max),
+       TP_ARGS(wiphy, tx, tx_max, rx, rx_max),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               __field(u32, tx)
+               __field(u32, tx_max)
+               __field(u32, rx)
+               __field(u32, rx_max)
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               __entry->tx = tx;
+               __entry->tx_max = tx_max;
+               __entry->rx = rx;
+               __entry->rx_max = rx_max;
+       ),
+       TP_printk(WIPHY_PR_FMT ", tx: %u, tx_max: %u, rx: %u, rx_max: %u ",
+                 WIPHY_PR_ARG, __entry->tx, __entry->tx_max, __entry->rx,
+                 __entry->rx_max)
+);
+
+DECLARE_EVENT_CLASS(tx_rx_evt,
+       TP_PROTO(struct wiphy *wiphy, u32 tx, u32 rx),
+       TP_ARGS(wiphy, rx, tx),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               __field(u32, tx)
+               __field(u32, rx)
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               __entry->tx = tx;
+               __entry->rx = rx;
+       ),
+       TP_printk(WIPHY_PR_FMT ", tx: %u, rx: %u ",
+                 WIPHY_PR_ARG, __entry->tx, __entry->rx)
+);
+
+DEFINE_EVENT(tx_rx_evt, rdev_set_ringparam,
+       TP_PROTO(struct wiphy *wiphy, u32 tx, u32 rx),
+       TP_ARGS(wiphy, rx, tx)
+);
+
+DEFINE_EVENT(tx_rx_evt, rdev_set_antenna,
+       TP_PROTO(struct wiphy *wiphy, u32 tx, u32 rx),
+       TP_ARGS(wiphy, rx, tx)
+);
+
+TRACE_EVENT(rdev_sched_scan_start,
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+                struct cfg80211_sched_scan_request *request),
+       TP_ARGS(wiphy, netdev, request),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               NETDEV_ENTRY
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               NETDEV_ASSIGN;
+       ),
+       TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT,
+                 WIPHY_PR_ARG, NETDEV_PR_ARG)
+);
+
+TRACE_EVENT(rdev_tdls_mgmt,
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+                u8 *peer, u8 action_code, u8 dialog_token,
+                u16 status_code, const u8 *buf, size_t len),
+       TP_ARGS(wiphy, netdev, peer, action_code, dialog_token, status_code,
+               buf, len),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               NETDEV_ENTRY
+               MAC_ENTRY(peer)
+               __field(u8, action_code)
+               __field(u8, dialog_token)
+               __field(u16, status_code)
+               __dynamic_array(u8, buf, len)
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               NETDEV_ASSIGN;
+               MAC_ASSIGN(peer, peer);
+               __entry->action_code = action_code;
+               __entry->dialog_token = dialog_token;
+               __entry->status_code = status_code;
+               memcpy(__get_dynamic_array(buf), buf, len);
+       ),
+       TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT MAC_PR_FMT ", action_code: %u, "
+                 "dialog_token: %u, status_code: %u, buf: %#.2x ",
+                 WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer),
+                 __entry->action_code, __entry->dialog_token,
+                 __entry->status_code, ((u8 *)__get_dynamic_array(buf))[0])
+);
+
+TRACE_EVENT(rdev_dump_survey,
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, int idx),
+       TP_ARGS(wiphy, netdev, idx),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               NETDEV_ENTRY
+               __field(int, idx)
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               NETDEV_ASSIGN;
+               __entry->idx = idx;
+       ),
+       TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", index: %d",
+                 WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->idx)
+);
+
+TRACE_EVENT(rdev_return_int_survey_info,
+       TP_PROTO(struct wiphy *wiphy, int ret, struct survey_info *info),
+       TP_ARGS(wiphy, ret, info),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               CHAN_ENTRY
+               __field(int, ret)
+               __field(u64, channel_time)
+               __field(u64, channel_time_busy)
+               __field(u64, channel_time_ext_busy)
+               __field(u64, channel_time_rx)
+               __field(u64, channel_time_tx)
+               __field(u32, filled)
+               __field(s8, noise)
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               CHAN_ASSIGN(info->channel);
+               __entry->ret = ret;
+               __entry->channel_time = info->channel_time;
+               __entry->channel_time_busy = info->channel_time_busy;
+               __entry->channel_time_ext_busy = info->channel_time_ext_busy;
+               __entry->channel_time_rx = info->channel_time_rx;
+               __entry->channel_time_tx = info->channel_time_tx;
+               __entry->filled = info->filled;
+               __entry->noise = info->noise;
+       ),
+       TP_printk(WIPHY_PR_FMT ", returned: %d, " CHAN_PR_FMT
+                 ", channel time: %llu, channel time busy: %llu, "
+                 "channel time extension busy: %llu, channel time rx: %llu, "
+                 "channel time tx: %llu, filled: %u, noise: %d",
+                 WIPHY_PR_ARG, __entry->ret, CHAN_PR_ARG,
+                 __entry->channel_time, __entry->channel_time_busy,
+                 __entry->channel_time_ext_busy, __entry->channel_time_rx,
+                 __entry->channel_time_tx, __entry->filled, __entry->noise)
+);
+
+TRACE_EVENT(rdev_tdls_oper,
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+                u8 *peer, enum nl80211_tdls_operation oper),
+       TP_ARGS(wiphy, netdev, peer, oper),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               NETDEV_ENTRY
+               MAC_ENTRY(peer)
+               __field(enum nl80211_tdls_operation, oper)
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               NETDEV_ASSIGN;
+               MAC_ASSIGN(peer, peer);
+               __entry->oper = oper;
+       ),
+       TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT MAC_PR_FMT ", oper: %d",
+                 WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer), __entry->oper)
+);
+
+DECLARE_EVENT_CLASS(rdev_pmksa,
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+                struct cfg80211_pmksa *pmksa),
+       TP_ARGS(wiphy, netdev, pmksa),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               NETDEV_ENTRY
+               MAC_ENTRY(bssid)
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               NETDEV_ASSIGN;
+               MAC_ASSIGN(bssid, pmksa->bssid);
+       ),
+       TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", bssid: " MAC_PR_FMT,
+                 WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(bssid))
+);
+
+TRACE_EVENT(rdev_probe_client,
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+                const u8 *peer),
+       TP_ARGS(wiphy, netdev, peer),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               NETDEV_ENTRY
+               MAC_ENTRY(peer)
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               NETDEV_ASSIGN;
+               MAC_ASSIGN(peer, peer);
+       ),
+       TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT MAC_PR_FMT,
+                 WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer))
+);
+
+DEFINE_EVENT(rdev_pmksa, rdev_set_pmksa,
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+                struct cfg80211_pmksa *pmksa),
+       TP_ARGS(wiphy, netdev, pmksa)
+);
+
+DEFINE_EVENT(rdev_pmksa, rdev_del_pmksa,
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+                struct cfg80211_pmksa *pmksa),
+       TP_ARGS(wiphy, netdev, pmksa)
+);
+
+TRACE_EVENT(rdev_remain_on_channel,
+       TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev,
+                struct ieee80211_channel *chan,
+                enum nl80211_channel_type channel_type, unsigned int duration),
+       TP_ARGS(wiphy, wdev, chan, channel_type, duration),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               WDEV_ENTRY
+               CHAN_ENTRY
+               __field(enum nl80211_channel_type, channel_type)
+               __field(unsigned int, duration)
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               WDEV_ASSIGN;
+               CHAN_ASSIGN(chan);
+               __entry->channel_type = channel_type;
+               __entry->duration = duration;
+       ),
+       TP_printk(WIPHY_PR_FMT WDEV_PR_FMT CHAN_PR_FMT ", channel type: %d, duration: %u",
+                 WIPHY_PR_ARG, WDEV_PR_ARG, CHAN_PR_ARG, __entry->channel_type,
+                 __entry->duration)
+);
+
+TRACE_EVENT(rdev_return_int_cookie,
+       TP_PROTO(struct wiphy *wiphy, int ret, u64 cookie),
+       TP_ARGS(wiphy, ret, cookie),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               __field(int, ret)
+               __field(u64, cookie)
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               __entry->ret = ret;
+               __entry->cookie = cookie;
+       ),
+       TP_printk(WIPHY_PR_FMT ", returned %d, cookie: %llu",
+                 WIPHY_PR_ARG, __entry->ret, __entry->cookie)
+);
+
+TRACE_EVENT(rdev_cancel_remain_on_channel,
+       TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev, u64 cookie),
+       TP_ARGS(wiphy, wdev, cookie),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               WDEV_ENTRY
+               __field(u64, cookie)
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               WDEV_ASSIGN;
+               __entry->cookie = cookie;
+       ),
+       TP_printk(WIPHY_PR_FMT WDEV_PR_FMT ", cookie: %llu",
+                 WIPHY_PR_ARG, WDEV_PR_ARG, __entry->cookie)
+);
+
+TRACE_EVENT(rdev_mgmt_tx,
+       TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev,
+                struct ieee80211_channel *chan, bool offchan,
+                enum nl80211_channel_type channel_type,
+                bool channel_type_valid, unsigned int wait, bool no_cck,
+                bool dont_wait_for_ack),
+       TP_ARGS(wiphy, wdev, chan, offchan, channel_type, channel_type_valid,
+               wait, no_cck, dont_wait_for_ack),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               WDEV_ENTRY
+               CHAN_ENTRY
+               __field(bool, offchan)
+               __field(enum nl80211_channel_type, channel_type)
+               __field(bool, channel_type_valid)
+               __field(unsigned int, wait)
+               __field(bool, no_cck)
+               __field(bool, dont_wait_for_ack)
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               WDEV_ASSIGN;
+               CHAN_ASSIGN(chan);
+               __entry->offchan = offchan;
+               __entry->channel_type = channel_type;
+               __entry->channel_type_valid = channel_type_valid;
+               __entry->wait = wait;
+               __entry->no_cck = no_cck;
+               __entry->dont_wait_for_ack = dont_wait_for_ack;
+       ),
+       TP_printk(WIPHY_PR_FMT WDEV_PR_FMT CHAN_PR_FMT ", offchan: %s, "
+                 "channel type: %d, channel type valid: %s, wait: %u, "
+                 "no cck: %s, dont wait for ack: %s",
+                 WIPHY_PR_ARG, WDEV_PR_ARG, CHAN_PR_ARG,
+                 BOOL_TO_STR(__entry->offchan), __entry->channel_type,
+                 BOOL_TO_STR(__entry->channel_type_valid), __entry->wait,
+                 BOOL_TO_STR(__entry->no_cck),
+                 BOOL_TO_STR(__entry->dont_wait_for_ack))
+);
+
+TRACE_EVENT(rdev_set_noack_map,
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+                u16 noack_map),
+       TP_ARGS(wiphy, netdev, noack_map),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               NETDEV_ENTRY
+               __field(u16, noack_map)
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               NETDEV_ASSIGN;
+               __entry->noack_map = noack_map;
+       ),
+       TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", noack_map: %u",
+                 WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->noack_map)
+);
+
+TRACE_EVENT(rdev_get_et_sset_count,
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, int sset),
+       TP_ARGS(wiphy, netdev, sset),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               NETDEV_ENTRY
+               __field(int, sset)
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               NETDEV_ASSIGN;
+               __entry->sset = sset;
+       ),
+       TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", sset: %d",
+                 WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->sset)
+);
+
+TRACE_EVENT(rdev_get_et_strings,
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u32 sset),
+       TP_ARGS(wiphy, netdev, sset),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               NETDEV_ENTRY
+               __field(u32, sset)
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               NETDEV_ASSIGN;
+               __entry->sset = sset;
+       ),
+       TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", sset: %u",
+                 WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->sset)
+);
+
+DEFINE_EVENT(wiphy_wdev_evt, rdev_get_channel,
+       TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev),
+       TP_ARGS(wiphy, wdev)
+);
+
+TRACE_EVENT(rdev_return_channel,
+       TP_PROTO(struct wiphy *wiphy, struct ieee80211_channel *chan,
+                enum nl80211_channel_type type),
+       TP_ARGS(wiphy, chan, type),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               CHAN_ENTRY
+               __field(enum nl80211_channel_type, type)
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               CHAN_ASSIGN(chan);
+               __entry->type = type;
+       ),
+       TP_printk(WIPHY_PR_FMT CHAN_PR_FMT ", channel type: %d",
+                 WIPHY_PR_ARG, CHAN_PR_ARG, __entry->type)
+);
+
+/*************************************************************
+ *          cfg80211 exported functions traces              *
+ *************************************************************/
+
+TRACE_EVENT(cfg80211_return_bool,
+       TP_PROTO(bool ret),
+       TP_ARGS(ret),
+       TP_STRUCT__entry(
+               __field(bool, ret)
+       ),
+       TP_fast_assign(
+               __entry->ret = ret;
+       ),
+       TP_printk("returned %s", BOOL_TO_STR(__entry->ret))
+);
+
+DECLARE_EVENT_CLASS(cfg80211_netdev_mac_evt,
+       TP_PROTO(struct net_device *netdev, const u8 *macaddr),
+       TP_ARGS(netdev, macaddr),
+       TP_STRUCT__entry(
+               NETDEV_ENTRY
+               MAC_ENTRY(macaddr)
+       ),
+       TP_fast_assign(
+               NETDEV_ASSIGN;
+               MAC_ASSIGN(macaddr, macaddr);
+       ),
+       TP_printk(NETDEV_PR_FMT ", mac: " MAC_PR_FMT,
+                 NETDEV_PR_ARG, MAC_PR_ARG(macaddr))
+);
+
+DEFINE_EVENT(cfg80211_netdev_mac_evt, cfg80211_notify_new_peer_candidate,
+       TP_PROTO(struct net_device *netdev, const u8 *macaddr),
+       TP_ARGS(netdev, macaddr)
+);
+
+DECLARE_EVENT_CLASS(netdev_evt_only,
+       TP_PROTO(struct net_device *netdev),
+       TP_ARGS(netdev),
+       TP_STRUCT__entry(
+               NETDEV_ENTRY
+       ),
+       TP_fast_assign(
+               NETDEV_ASSIGN;
+       ),
+       TP_printk(NETDEV_PR_FMT , NETDEV_PR_ARG)
+);
+
+DEFINE_EVENT(netdev_evt_only, cfg80211_send_rx_auth,
+       TP_PROTO(struct net_device *netdev),
+       TP_ARGS(netdev)
+);
+
+TRACE_EVENT(cfg80211_send_rx_assoc,
+       TP_PROTO(struct net_device *netdev, struct cfg80211_bss *bss),
+       TP_ARGS(netdev, bss),
+       TP_STRUCT__entry(
+               NETDEV_ENTRY
+               MAC_ENTRY(bssid)
+               CHAN_ENTRY
+       ),
+       TP_fast_assign(
+               NETDEV_ASSIGN;
+               MAC_ASSIGN(bssid, bss->bssid);
+               CHAN_ASSIGN(bss->channel);
+       ),
+       TP_printk(NETDEV_PR_FMT MAC_PR_FMT CHAN_PR_FMT,
+                 NETDEV_PR_ARG, MAC_PR_ARG(bssid), CHAN_PR_ARG)
+);
+
+DEFINE_EVENT(netdev_evt_only, __cfg80211_send_deauth,
+       TP_PROTO(struct net_device *netdev),
+       TP_ARGS(netdev)
+);
+
+DEFINE_EVENT(netdev_evt_only, __cfg80211_send_disassoc,
+       TP_PROTO(struct net_device *netdev),
+       TP_ARGS(netdev)
+);
+
+DEFINE_EVENT(netdev_evt_only, cfg80211_send_unprot_deauth,
+       TP_PROTO(struct net_device *netdev),
+       TP_ARGS(netdev)
+);
+
+DEFINE_EVENT(netdev_evt_only, cfg80211_send_unprot_disassoc,
+       TP_PROTO(struct net_device *netdev),
+       TP_ARGS(netdev)
+);
+
+DECLARE_EVENT_CLASS(netdev_mac_evt,
+       TP_PROTO(struct net_device *netdev, const u8 *mac),
+       TP_ARGS(netdev, mac),
+       TP_STRUCT__entry(
+               NETDEV_ENTRY
+               MAC_ENTRY(mac)
+       ),
+       TP_fast_assign(
+               NETDEV_ASSIGN;
+               MAC_ASSIGN(mac, mac)
+       ),
+       TP_printk(NETDEV_PR_FMT ", mac: " MAC_PR_FMT,
+                 NETDEV_PR_ARG, MAC_PR_ARG(mac))
+);
+
+DEFINE_EVENT(netdev_mac_evt, cfg80211_send_auth_timeout,
+       TP_PROTO(struct net_device *netdev, const u8 *mac),
+       TP_ARGS(netdev, mac)
+);
+
+DEFINE_EVENT(netdev_mac_evt, cfg80211_send_assoc_timeout,
+       TP_PROTO(struct net_device *netdev, const u8 *mac),
+       TP_ARGS(netdev, mac)
+);
+
+TRACE_EVENT(cfg80211_michael_mic_failure,
+       TP_PROTO(struct net_device *netdev, const u8 *addr,
+                enum nl80211_key_type key_type, int key_id, const u8 *tsc),
+       TP_ARGS(netdev, addr, key_type, key_id, tsc),
+       TP_STRUCT__entry(
+               NETDEV_ENTRY
+               MAC_ENTRY(addr)
+               __field(enum nl80211_key_type, key_type)
+               __field(int, key_id)
+               __array(u8, tsc, 6)
+       ),
+       TP_fast_assign(
+               NETDEV_ASSIGN;
+               MAC_ASSIGN(addr, addr);
+               __entry->key_type = key_type;
+               __entry->key_id = key_id;
+               memcpy(__entry->tsc, tsc, 6);
+       ),
+       TP_printk(NETDEV_PR_FMT MAC_PR_FMT ", key type: %d, key id: %d, tsc: %pm",
+                 NETDEV_PR_ARG, MAC_PR_ARG(addr), __entry->key_type,
+                 __entry->key_id, __entry->tsc)
+);
+
+TRACE_EVENT(cfg80211_ready_on_channel,
+       TP_PROTO(struct wireless_dev *wdev, u64 cookie,
+                struct ieee80211_channel *chan,
+                enum nl80211_channel_type channel_type, unsigned int duration),
+       TP_ARGS(wdev, cookie, chan, channel_type, duration),
+       TP_STRUCT__entry(
+               WDEV_ENTRY
+               __field(u64, cookie)
+               CHAN_ENTRY
+               __field(enum nl80211_channel_type, channel_type)
+               __field(unsigned int, duration)
+       ),
+       TP_fast_assign(
+               WDEV_ASSIGN;
+               __entry->cookie = cookie;
+               CHAN_ASSIGN(chan);
+               __entry->channel_type = channel_type;
+               __entry->duration = duration;
+       ),
+       TP_printk(WDEV_PR_FMT ", cookie: %llu, " CHAN_PR_FMT ", channel type: %d, duration: %u",
+                 WDEV_PR_ARG, __entry->cookie, CHAN_PR_ARG,
+                 __entry->channel_type, __entry->duration)
+);
+
+TRACE_EVENT(cfg80211_ready_on_channel_expired,
+       TP_PROTO(struct wireless_dev *wdev, u64 cookie,
+                struct ieee80211_channel *chan,
+                enum nl80211_channel_type channel_type),
+       TP_ARGS(wdev, cookie, chan, channel_type),
+       TP_STRUCT__entry(
+               WDEV_ENTRY
+               __field(u64, cookie)
+               CHAN_ENTRY
+               __field(enum nl80211_channel_type, channel_type)
+       ),
+       TP_fast_assign(
+               WDEV_ASSIGN;
+               __entry->cookie = cookie;
+               CHAN_ASSIGN(chan);
+               __entry->channel_type = channel_type;
+       ),
+       TP_printk(WDEV_PR_FMT ", cookie: %llu, " CHAN_PR_FMT ", channel type: %d",
+                 WDEV_PR_ARG, __entry->cookie, CHAN_PR_ARG,
+                 __entry->channel_type)
+);
+
+TRACE_EVENT(cfg80211_new_sta,
+       TP_PROTO(struct net_device *netdev, const u8 *mac_addr,
+                struct station_info *sinfo),
+       TP_ARGS(netdev, mac_addr, sinfo),
+       TP_STRUCT__entry(
+               NETDEV_ENTRY
+               MAC_ENTRY(mac_addr)
+               SINFO_ENTRY
+       ),
+       TP_fast_assign(
+               NETDEV_ASSIGN;
+               MAC_ASSIGN(mac_addr, mac_addr);
+               SINFO_ASSIGN;
+       ),
+       TP_printk(NETDEV_PR_FMT MAC_PR_FMT,
+                 NETDEV_PR_ARG, MAC_PR_ARG(mac_addr))
+);
+
+DEFINE_EVENT(cfg80211_netdev_mac_evt, cfg80211_del_sta,
+       TP_PROTO(struct net_device *netdev, const u8 *macaddr),
+       TP_ARGS(netdev, macaddr)
+);
+
+TRACE_EVENT(cfg80211_rx_mgmt,
+       TP_PROTO(struct wireless_dev *wdev, int freq, int sig_mbm),
+       TP_ARGS(wdev, freq, sig_mbm),
+       TP_STRUCT__entry(
+               WDEV_ENTRY
+               __field(int, freq)
+               __field(int, sig_mbm)
+       ),
+       TP_fast_assign(
+               WDEV_ASSIGN;
+               __entry->freq = freq;
+               __entry->sig_mbm = sig_mbm;
+       ),
+       TP_printk(WDEV_PR_FMT ", freq: %d, sig mbm: %d",
+                 WDEV_PR_ARG, __entry->freq, __entry->sig_mbm)
+);
+
+TRACE_EVENT(cfg80211_mgmt_tx_status,
+       TP_PROTO(struct wireless_dev *wdev, u64 cookie, bool ack),
+       TP_ARGS(wdev, cookie, ack),
+       TP_STRUCT__entry(
+               WDEV_ENTRY
+               __field(u64, cookie)
+               __field(bool, ack)
+       ),
+       TP_fast_assign(
+               WDEV_ASSIGN;
+               __entry->cookie = cookie;
+               __entry->ack = ack;
+       ),
+       TP_printk(WDEV_PR_FMT", cookie: %llu, ack: %s",
+                 WDEV_PR_ARG, __entry->cookie, BOOL_TO_STR(__entry->ack))
+);
+
+TRACE_EVENT(cfg80211_cqm_rssi_notify,
+       TP_PROTO(struct net_device *netdev,
+                enum nl80211_cqm_rssi_threshold_event rssi_event),
+       TP_ARGS(netdev, rssi_event),
+       TP_STRUCT__entry(
+               NETDEV_ENTRY
+               __field(enum nl80211_cqm_rssi_threshold_event, rssi_event)
+       ),
+       TP_fast_assign(
+               NETDEV_ASSIGN;
+               __entry->rssi_event = rssi_event;
+       ),
+       TP_printk(NETDEV_PR_FMT ", rssi event: %d",
+                 NETDEV_PR_ARG, __entry->rssi_event)
+);
+
+TRACE_EVENT(cfg80211_can_beacon_sec_chan,
+       TP_PROTO(struct wiphy *wiphy, struct ieee80211_channel *channel,
+                enum nl80211_channel_type channel_type),
+       TP_ARGS(wiphy, channel, channel_type),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               CHAN_ENTRY
+               __field(enum nl80211_channel_type, channel_type)
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               CHAN_ASSIGN(channel);
+               __entry->channel_type = channel_type;
+       ),
+       TP_printk(WIPHY_PR_FMT CHAN_PR_FMT ", channel_type: %d",
+                 WIPHY_PR_ARG, CHAN_PR_ARG, __entry->channel_type)
+);
+
+TRACE_EVENT(cfg80211_ch_switch_notify,
+       TP_PROTO(struct net_device *netdev, int freq,
+                enum nl80211_channel_type type),
+       TP_ARGS(netdev, freq, type),
+       TP_STRUCT__entry(
+               NETDEV_ENTRY
+               __field(int, freq)
+               __field(enum nl80211_channel_type, type)
+       ),
+       TP_fast_assign(
+               NETDEV_ASSIGN;
+               __entry->freq = freq;
+               __entry->type = type;
+       ),
+       TP_printk(NETDEV_PR_FMT ", freq: %d, type: %d", NETDEV_PR_ARG,
+                 __entry->freq, __entry->type)
+);
+
+DECLARE_EVENT_CLASS(cfg80211_rx_evt,
+       TP_PROTO(struct net_device *netdev, const u8 *addr),
+       TP_ARGS(netdev, addr),
+       TP_STRUCT__entry(
+               NETDEV_ENTRY
+               MAC_ENTRY(addr)
+       ),
+       TP_fast_assign(
+               NETDEV_ASSIGN;
+               MAC_ASSIGN(addr, addr);
+       ),
+       TP_printk(NETDEV_PR_FMT MAC_PR_FMT, NETDEV_PR_ARG, MAC_PR_ARG(addr))
+);
+
+DEFINE_EVENT(cfg80211_rx_evt, cfg80211_ibss_joined,
+       TP_PROTO(struct net_device *netdev, const u8 *addr),
+       TP_ARGS(netdev, addr)
+);
+
+DEFINE_EVENT(cfg80211_rx_evt, cfg80211_rx_spurious_frame,
+       TP_PROTO(struct net_device *netdev, const u8 *addr),
+       TP_ARGS(netdev, addr)
+);
+
+DEFINE_EVENT(cfg80211_rx_evt, cfg80211_rx_unexpected_4addr_frame,
+       TP_PROTO(struct net_device *netdev, const u8 *addr),
+       TP_ARGS(netdev, addr)
+);
+
+TRACE_EVENT(cfg80211_probe_status,
+       TP_PROTO(struct net_device *netdev, const u8 *addr, u64 cookie,
+                bool acked),
+       TP_ARGS(netdev, addr, cookie, acked),
+       TP_STRUCT__entry(
+               NETDEV_ENTRY
+               MAC_ENTRY(addr)
+               __field(u64, cookie)
+               __field(bool, acked)
+       ),
+       TP_fast_assign(
+               NETDEV_ASSIGN;
+               MAC_ASSIGN(addr, addr);
+               __entry->cookie = cookie;
+               __entry->acked = acked;
+       ),
+       TP_printk(NETDEV_PR_FMT MAC_PR_FMT ", cookie: %llu, acked: %s",
+                 NETDEV_PR_ARG, MAC_PR_ARG(addr), __entry->cookie,
+                 BOOL_TO_STR(__entry->acked))
+);
+
+TRACE_EVENT(cfg80211_cqm_pktloss_notify,
+       TP_PROTO(struct net_device *netdev, const u8 *peer, u32 num_packets),
+       TP_ARGS(netdev, peer, num_packets),
+       TP_STRUCT__entry(
+               NETDEV_ENTRY
+               MAC_ENTRY(peer)
+               __field(u32, num_packets)
+       ),
+       TP_fast_assign(
+               NETDEV_ASSIGN;
+               MAC_ASSIGN(peer, peer);
+               __entry->num_packets = num_packets;
+       ),
+       TP_printk(NETDEV_PR_FMT ", peer: " MAC_PR_FMT ", num of lost packets: %u",
+                 NETDEV_PR_ARG, MAC_PR_ARG(peer), __entry->num_packets)
+);
+
+DEFINE_EVENT(cfg80211_netdev_mac_evt, cfg80211_gtk_rekey_notify,
+       TP_PROTO(struct net_device *netdev, const u8 *macaddr),
+       TP_ARGS(netdev, macaddr)
+);
+
+TRACE_EVENT(cfg80211_pmksa_candidate_notify,
+       TP_PROTO(struct net_device *netdev, int index, const u8 *bssid,
+                bool preauth),
+       TP_ARGS(netdev, index, bssid, preauth),
+       TP_STRUCT__entry(
+               NETDEV_ENTRY
+               __field(int, index)
+               MAC_ENTRY(bssid)
+               __field(bool, preauth)
+       ),
+       TP_fast_assign(
+               NETDEV_ASSIGN;
+               __entry->index = index;
+               MAC_ASSIGN(bssid, bssid);
+               __entry->preauth = preauth;
+       ),
+       TP_printk(NETDEV_PR_FMT ", index:%d, bssid: " MAC_PR_FMT ", pre auth: %s",
+                 NETDEV_PR_ARG, __entry->index, MAC_PR_ARG(bssid),
+                 BOOL_TO_STR(__entry->preauth))
+);
+
+TRACE_EVENT(cfg80211_report_obss_beacon,
+       TP_PROTO(struct wiphy *wiphy, const u8 *frame, size_t len,
+                int freq, int sig_dbm),
+       TP_ARGS(wiphy, frame, len, freq, sig_dbm),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               __field(int, freq)
+               __field(int, sig_dbm)
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               __entry->freq = freq;
+               __entry->sig_dbm = sig_dbm;
+       ),
+       TP_printk(WIPHY_PR_FMT ", freq: %d, sig_dbm: %d",
+                 WIPHY_PR_ARG, __entry->freq, __entry->sig_dbm)
+);
+
+TRACE_EVENT(cfg80211_scan_done,
+       TP_PROTO(struct cfg80211_scan_request *request, bool aborted),
+       TP_ARGS(request, aborted),
+       TP_STRUCT__entry(
+               __field(u32, n_channels)
+               __dynamic_array(u8, ie, request ? request->ie_len : 0)
+               __array(u32, rates, IEEE80211_NUM_BANDS)
+               __field(u32, wdev_id)
+               MAC_ENTRY(wiphy_mac)
+               __field(bool, no_cck)
+               __field(bool, aborted)
+       ),
+       TP_fast_assign(
+               if (request) {
+                       memcpy(__get_dynamic_array(ie), request->ie,
+                              request->ie_len);
+                       memcpy(__entry->rates, request->rates,
+                              IEEE80211_NUM_BANDS);
+                       __entry->wdev_id = request->wdev ?
+                                       request->wdev->identifier : 0;
+                       if (request->wiphy)
+                               MAC_ASSIGN(wiphy_mac,
+                                          request->wiphy->perm_addr);
+                       __entry->no_cck = request->no_cck;
+               }
+               __entry->aborted = aborted;
+       ),
+       TP_printk("aborted: %s", BOOL_TO_STR(__entry->aborted))
+);
+
+DEFINE_EVENT(wiphy_only_evt, cfg80211_sched_scan_results,
+       TP_PROTO(struct wiphy *wiphy),
+       TP_ARGS(wiphy)
+);
+
+DEFINE_EVENT(wiphy_only_evt, cfg80211_sched_scan_stopped,
+       TP_PROTO(struct wiphy *wiphy),
+       TP_ARGS(wiphy)
+);
+
+TRACE_EVENT(cfg80211_get_bss,
+       TP_PROTO(struct wiphy *wiphy, struct ieee80211_channel *channel,
+                const u8 *bssid, const u8 *ssid, size_t ssid_len,
+                u16 capa_mask, u16 capa_val),
+       TP_ARGS(wiphy, channel, bssid, ssid, ssid_len, capa_mask, capa_val),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               CHAN_ENTRY
+               MAC_ENTRY(bssid)
+               __dynamic_array(u8, ssid, ssid_len)
+               __field(u16, capa_mask)
+               __field(u16, capa_val)
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               CHAN_ASSIGN(channel);
+               MAC_ASSIGN(bssid, bssid);
+               memcpy(__get_dynamic_array(ssid), ssid, ssid_len);
+               __entry->capa_mask = capa_mask;
+               __entry->capa_val = capa_val;
+       ),
+       TP_printk(WIPHY_PR_FMT CHAN_PR_FMT MAC_PR_FMT ", buf: %#.2x, "
+                 "capa_mask: %d, capa_val: %u", WIPHY_PR_ARG, CHAN_PR_ARG,
+                 MAC_PR_ARG(bssid), ((u8 *)__get_dynamic_array(ssid))[0],
+                 __entry->capa_mask, __entry->capa_val)
+);
+
+TRACE_EVENT(cfg80211_inform_bss_frame,
+       TP_PROTO(struct wiphy *wiphy, struct ieee80211_channel *channel,
+                struct ieee80211_mgmt *mgmt, size_t len,
+                s32 signal),
+       TP_ARGS(wiphy, channel, mgmt, len, signal),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               CHAN_ENTRY
+               __dynamic_array(u8, mgmt, len)
+               __field(s32, signal)
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               CHAN_ASSIGN(channel);
+               if (mgmt)
+                       memcpy(__get_dynamic_array(mgmt), mgmt, len);
+               __entry->signal = signal;
+       ),
+       TP_printk(WIPHY_PR_FMT CHAN_PR_FMT "signal: %d",
+                 WIPHY_PR_ARG, CHAN_PR_ARG, __entry->signal)
+);
+
+DECLARE_EVENT_CLASS(cfg80211_bss_evt,
+       TP_PROTO(struct cfg80211_bss *pub),
+       TP_ARGS(pub),
+       TP_STRUCT__entry(
+               MAC_ENTRY(bssid)
+               CHAN_ENTRY
+       ),
+       TP_fast_assign(
+               MAC_ASSIGN(bssid, pub->bssid);
+               CHAN_ASSIGN(pub->channel);
+       ),
+       TP_printk(MAC_PR_FMT CHAN_PR_FMT, MAC_PR_ARG(bssid), CHAN_PR_ARG)
+);
+
+DEFINE_EVENT(cfg80211_bss_evt, cfg80211_return_bss,
+       TP_PROTO(struct cfg80211_bss *pub),
+       TP_ARGS(pub)
+);
+
+TRACE_EVENT(cfg80211_return_uint,
+       TP_PROTO(unsigned int ret),
+       TP_ARGS(ret),
+       TP_STRUCT__entry(
+               __field(unsigned int, ret)
+       ),
+       TP_fast_assign(
+               __entry->ret = ret;
+       ),
+       TP_printk("ret: %d", __entry->ret)
+);
+
+TRACE_EVENT(cfg80211_return_u32,
+       TP_PROTO(u32 ret),
+       TP_ARGS(ret),
+       TP_STRUCT__entry(
+               __field(u32, ret)
+       ),
+       TP_fast_assign(
+               __entry->ret = ret;
+       ),
+       TP_printk("ret: %u", __entry->ret)
+);
+
+#endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */
+
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE trace
+#include <trace/define_trace.h>
index ef35f4ef2aa623d16f3556a5e3f4709fba363db4..343f13c1d31d66f576708ccc6d0ff4d0f047102b 100644 (file)
@@ -11,6 +11,8 @@
 #include <net/ip.h>
 #include <net/dsfield.h>
 #include "core.h"
+#include "rdev-ops.h"
+
 
 struct ieee80211_rate *
 ieee80211_get_response_rate(struct ieee80211_supported_band *sband,
@@ -703,19 +705,18 @@ void cfg80211_upload_connect_keys(struct wireless_dev *wdev)
        for (i = 0; i < 6; i++) {
                if (!wdev->connect_keys->params[i].cipher)
                        continue;
-               if (rdev->ops->add_key(wdev->wiphy, dev, i, false, NULL,
-                                       &wdev->connect_keys->params[i])) {
+               if (rdev_add_key(rdev, dev, i, false, NULL,
+                                &wdev->connect_keys->params[i])) {
                        netdev_err(dev, "failed to set key %d\n", i);
                        continue;
                }
                if (wdev->connect_keys->def == i)
-                       if (rdev->ops->set_default_key(wdev->wiphy, dev,
-                                                      i, true, true)) {
+                       if (rdev_set_default_key(rdev, dev, i, true, true)) {
                                netdev_err(dev, "failed to set defkey %d\n", i);
                                continue;
                        }
                if (wdev->connect_keys->defmgmt == i)
-                       if (rdev->ops->set_default_mgmt_key(wdev->wiphy, dev, i))
+                       if (rdev_set_default_mgmt_key(rdev, dev, i))
                                netdev_err(dev, "failed to set mgtdef %d\n", i);
        }
 
@@ -848,8 +849,7 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
                cfg80211_process_rdev_events(rdev);
        }
 
-       err = rdev->ops->change_virtual_intf(&rdev->wiphy, dev,
-                                            ntype, flags, params);
+       err = rdev_change_virtual_intf(rdev, dev, ntype, flags, params);
 
        WARN_ON(!err && dev->ieee80211_ptr->iftype != ntype);
 
index 494379eb464f43c6b33ab44290075044ce06a413..6488d2dbc1d783bb34f3009fe8a8b81b05c1b5f9 100644 (file)
@@ -19,6 +19,7 @@
 #include <net/cfg80211-wext.h>
 #include "wext-compat.h"
 #include "core.h"
+#include "rdev-ops.h"
 
 int cfg80211_wext_giwname(struct net_device *dev,
                          struct iw_request_info *info,
@@ -301,8 +302,7 @@ int cfg80211_wext_siwrts(struct net_device *dev,
        else
                wdev->wiphy->rts_threshold = rts->value;
 
-       err = rdev->ops->set_wiphy_params(wdev->wiphy,
-                                         WIPHY_PARAM_RTS_THRESHOLD);
+       err = rdev_set_wiphy_params(rdev, WIPHY_PARAM_RTS_THRESHOLD);
        if (err)
                wdev->wiphy->rts_threshold = orts;
 
@@ -342,8 +342,7 @@ int cfg80211_wext_siwfrag(struct net_device *dev,
                wdev->wiphy->frag_threshold = frag->value & ~0x1;
        }
 
-       err = rdev->ops->set_wiphy_params(wdev->wiphy,
-                                         WIPHY_PARAM_FRAG_THRESHOLD);
+       err = rdev_set_wiphy_params(rdev, WIPHY_PARAM_FRAG_THRESHOLD);
        if (err)
                wdev->wiphy->frag_threshold = ofrag;
 
@@ -396,7 +395,7 @@ static int cfg80211_wext_siwretry(struct net_device *dev,
        if (!changed)
                return 0;
 
-       err = rdev->ops->set_wiphy_params(wdev->wiphy, changed);
+       err = rdev_set_wiphy_params(rdev, changed);
        if (err) {
                wdev->wiphy->retry_short = oshort;
                wdev->wiphy->retry_long = olong;
@@ -490,8 +489,8 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
                            !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN))
                                err = -ENOENT;
                        else
-                               err = rdev->ops->del_key(&rdev->wiphy, dev, idx,
-                                                        pairwise, addr);
+                               err = rdev_del_key(rdev, dev, idx, pairwise,
+                                                  addr);
                }
                wdev->wext.connect.privacy = false;
                /*
@@ -525,8 +524,7 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
 
        err = 0;
        if (wdev->current_bss)
-               err = rdev->ops->add_key(&rdev->wiphy, dev, idx,
-                                        pairwise, addr, params);
+               err = rdev_add_key(rdev, dev, idx, pairwise, addr, params);
        if (err)
                return err;
 
@@ -552,8 +550,7 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
                                __cfg80211_leave_ibss(rdev, wdev->netdev, true);
                                rejoin = true;
                        }
-                       err = rdev->ops->set_default_key(&rdev->wiphy, dev,
-                                                        idx, true, true);
+                       err = rdev_set_default_key(rdev, dev, idx, true, true);
                }
                if (!err) {
                        wdev->wext.default_key = idx;
@@ -566,8 +563,7 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
        if (params->cipher == WLAN_CIPHER_SUITE_AES_CMAC &&
            (tx_key || (!addr && wdev->wext.default_mgmt_key == -1))) {
                if (wdev->current_bss)
-                       err = rdev->ops->set_default_mgmt_key(&rdev->wiphy,
-                                                             dev, idx);
+                       err = rdev_set_default_mgmt_key(rdev, dev, idx);
                if (!err)
                        wdev->wext.default_mgmt_key = idx;
                return err;
@@ -631,8 +627,8 @@ static int cfg80211_wext_siwencode(struct net_device *dev,
                err = 0;
                wdev_lock(wdev);
                if (wdev->current_bss)
-                       err = rdev->ops->set_default_key(&rdev->wiphy, dev,
-                                                        idx, true, true);
+                       err = rdev_set_default_key(rdev, dev, idx, true,
+                                                  true);
                if (!err)
                        wdev->wext.default_key = idx;
                wdev_unlock(wdev);
@@ -839,7 +835,7 @@ static int cfg80211_wext_giwfreq(struct net_device *dev,
                if (!rdev->ops->get_channel)
                        return -EINVAL;
 
-               chan = rdev->ops->get_channel(wdev->wiphy, wdev, &channel_type);
+               chan = rdev_get_channel(rdev, wdev, &channel_type);
                if (!chan)
                        return -EINVAL;
                freq->m = chan->center_freq;
@@ -899,7 +895,7 @@ static int cfg80211_wext_siwtxpower(struct net_device *dev,
                return 0;
        }
 
-       return rdev->ops->set_tx_power(wdev->wiphy, type, DBM_TO_MBM(dbm));
+       return rdev_set_tx_power(rdev, type, DBM_TO_MBM(dbm));
 }
 
 static int cfg80211_wext_giwtxpower(struct net_device *dev,
@@ -918,7 +914,7 @@ static int cfg80211_wext_giwtxpower(struct net_device *dev,
        if (!rdev->ops->get_tx_power)
                return -EOPNOTSUPP;
 
-       err = rdev->ops->get_tx_power(wdev->wiphy, &val);
+       err = rdev_get_tx_power(rdev, &val);
        if (err)
                return err;
 
@@ -1158,7 +1154,7 @@ static int cfg80211_wext_siwpower(struct net_device *dev,
                        timeout = wrq->value / 1000;
        }
 
-       err = rdev->ops->set_power_mgmt(wdev->wiphy, dev, ps, timeout);
+       err = rdev_set_power_mgmt(rdev, dev, ps, timeout);
        if (err)
                return err;
 
@@ -1200,7 +1196,7 @@ static int cfg80211_wds_wext_siwap(struct net_device *dev,
        if (!rdev->ops->set_wds_peer)
                return -EOPNOTSUPP;
 
-       err = rdev->ops->set_wds_peer(wdev->wiphy, dev, (u8 *) &addr->sa_data);
+       err = rdev_set_wds_peer(rdev, dev, (u8 *)&addr->sa_data);
        if (err)
                return err;
 
@@ -1272,7 +1268,7 @@ static int cfg80211_wext_siwrate(struct net_device *dev,
        if (!match)
                return -EINVAL;
 
-       return rdev->ops->set_bitrate_mask(wdev->wiphy, dev, NULL, &mask);
+       return rdev_set_bitrate_mask(rdev, dev, NULL, &mask);
 }
 
 static int cfg80211_wext_giwrate(struct net_device *dev,
@@ -1302,7 +1298,7 @@ static int cfg80211_wext_giwrate(struct net_device *dev,
        if (err)
                return err;
 
-       err = rdev->ops->get_station(&rdev->wiphy, dev, addr, &sinfo);
+       err = rdev_get_station(rdev, dev, addr, &sinfo);
        if (err)
                return err;
 
@@ -1339,7 +1335,7 @@ static struct iw_statistics *cfg80211_wireless_stats(struct net_device *dev)
        memcpy(bssid, wdev->current_bss->pub.bssid, ETH_ALEN);
        wdev_unlock(wdev);
 
-       if (rdev->ops->get_station(&rdev->wiphy, dev, bssid, &sinfo))
+       if (rdev_get_station(rdev, dev, bssid, &sinfo))
                return NULL;
 
        memset(&wstats, 0, sizeof(wstats));
@@ -1474,19 +1470,19 @@ static int cfg80211_wext_siwpmksa(struct net_device *dev,
                if (!rdev->ops->set_pmksa)
                        return -EOPNOTSUPP;
 
-               return rdev->ops->set_pmksa(&rdev->wiphy, dev, &cfg_pmksa);
+               return rdev_set_pmksa(rdev, dev, &cfg_pmksa);
 
        case IW_PMKSA_REMOVE:
                if (!rdev->ops->del_pmksa)
                        return -EOPNOTSUPP;
 
-               return rdev->ops->del_pmksa(&rdev->wiphy, dev, &cfg_pmksa);
+               return rdev_del_pmksa(rdev, dev, &cfg_pmksa);
 
        case IW_PMKSA_FLUSH:
                if (!rdev->ops->flush_pmksa)
                        return -EOPNOTSUPP;
 
-               return rdev->ops->flush_pmksa(&rdev->wiphy, dev);
+               return rdev_flush_pmksa(rdev, dev);
 
        default:
                return -EOPNOTSUPP;
index 3d13d3a3edfe821c9663de081d78045c96e69809..dda4b2b619275517826af60a61de2edb731f5524 100644 (file)
@@ -17,7 +17,7 @@ __modinst: $(modules)
        @:
 
 quiet_cmd_modules_install = INSTALL $@
-      cmd_modules_install = mkdir -p $(2); cp $@ $(2) ; $(mod_strip_cmd) $(2)/$(notdir $@)
+      cmd_modules_install = mkdir -p $(2); cp $@ $(2) ; $(mod_strip_cmd) $(2)/$(notdir $@) ; $(mod_sign_cmd) $(2)/$(notdir $@)
 
 # Modules built outside the kernel source tree go into extra by default
 INSTALL_MOD_DIR ?= extra
index 002089141df448fa569688a3e5e57b130d68e88b..a1cb0222ebe642b6fd91093f2a01bd301b026e6e 100644 (file)
@@ -14,8 +14,7 @@
 # 3)  create one <module>.mod.c file pr. module
 # 4)  create one Module.symvers file with CRC for all exported symbols
 # 5) compile all <module>.mod.c files
-# 6) final link of the module to a <module.ko> (or <module.unsigned>) file
-# 7) signs the modules to a <module.ko> file
+# 6) final link of the module to a <module.ko> file
 
 # Step 3 is used to place certain information in the module's ELF
 # section, including information such as:
@@ -33,8 +32,6 @@
 # Step 4 is solely used to allow module versioning in external modules,
 # where the CRC of each module is retrieved from the Module.symvers file.
 
-# Step 7 is dependent on CONFIG_MODULE_SIG being enabled.
-
 # KBUILD_MODPOST_WARN can be set to avoid error out in case of undefined
 # symbols in the final module linking stage
 # KBUILD_MODPOST_NOFINAL can be set to skip the final link of modules.
@@ -119,7 +116,6 @@ $(modules:.ko=.mod.o): %.mod.o: %.mod.c FORCE
 targets += $(modules:.ko=.mod.o)
 
 # Step 6), final link of the modules
-ifneq ($(CONFIG_MODULE_SIG),y)
 quiet_cmd_ld_ko_o = LD [M]  $@
       cmd_ld_ko_o = $(LD) -r $(LDFLAGS)                                 \
                              $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \
@@ -129,78 +125,7 @@ $(modules): %.ko :%.o %.mod.o FORCE
        $(call if_changed,ld_ko_o)
 
 targets += $(modules)
-else
-quiet_cmd_ld_ko_unsigned_o = LD [M]  $@
-      cmd_ld_ko_unsigned_o =                                           \
-               $(LD) -r $(LDFLAGS)                                     \
-                        $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE)     \
-                        -o $@ $(filter-out FORCE,$^)                   \
-               $(if $(AFTER_LINK),; $(AFTER_LINK))
-
-$(modules:.ko=.ko.unsigned): %.ko.unsigned :%.o %.mod.o FORCE
-       $(call if_changed,ld_ko_unsigned_o)
-
-targets += $(modules:.ko=.ko.unsigned)
-
-# Step 7), sign the modules
-MODSECKEY = ./signing_key.priv
-MODPUBKEY = ./signing_key.x509
-
-ifeq ($(wildcard $(MODSECKEY))+$(wildcard $(MODPUBKEY)),$(MODSECKEY)+$(MODPUBKEY))
-ifeq ($(KBUILD_SRC),)
-       # no O= is being used
-       SCRIPTS_DIR := scripts
-else
-       SCRIPTS_DIR := $(KBUILD_SRC)/scripts
-endif
-SIGN_MODULES := 1
-else
-SIGN_MODULES := 0
-endif
-
-# only sign if it's an in-tree module
-ifneq ($(KBUILD_EXTMOD),)
-SIGN_MODULES := 0
-endif
 
-# We strip the module as best we can - note that using both strip and eu-strip
-# results in a smaller module than using either alone.
-EU_STRIP = $(shell which eu-strip || echo true)
-
-quiet_cmd_sign_ko_stripped_ko_unsigned = STRIP [M] $@
-      cmd_sign_ko_stripped_ko_unsigned = \
-               cp $< $@ && \
-               strip -x -g $@ && \
-               $(EU_STRIP) $@
-
-ifeq ($(SIGN_MODULES),1)
-
-quiet_cmd_genkeyid = GENKEYID $@
-      cmd_genkeyid = \
-               perl $(SCRIPTS_DIR)/x509keyid $< $<.signer $<.keyid
-
-%.signer %.keyid: %
-       $(call if_changed,genkeyid)
-
-KEYRING_DEP := $(MODSECKEY) $(MODPUBKEY) $(MODPUBKEY).signer $(MODPUBKEY).keyid
-quiet_cmd_sign_ko_ko_stripped = SIGN [M] $@
-      cmd_sign_ko_ko_stripped = \
-               sh $(SCRIPTS_DIR)/sign-file $(MODSECKEY) $(MODPUBKEY) $< $@
-else
-KEYRING_DEP :=
-quiet_cmd_sign_ko_ko_unsigned = NO SIGN [M] $@
-      cmd_sign_ko_ko_unsigned = \
-               cp $< $@
-endif
-
-$(modules): %.ko :%.ko.stripped $(KEYRING_DEP) FORCE
-       $(call if_changed,sign_ko_ko_stripped)
-
-$(patsubst %.ko,%.ko.stripped,$(modules)): %.ko.stripped :%.ko.unsigned FORCE
-       $(call if_changed,sign_ko_stripped_ko_unsigned)
-
-targets += $(modules)
-endif
 
 # Add FORCE to the prequisites of a target to force it to be always rebuilt.
 # ---------------------------------------------------------------------------
index 3091794e935488c797e73207e6d0b82a7dbf99b4..2db79d34bf049cc3b301ba5fcef3339beb29bbf6 100644 (file)
@@ -3,7 +3,7 @@
 # These targets are used from top-level makefile
 
 PHONY += oldconfig xconfig gconfig menuconfig config silentoldconfig update-po-config \
-       localmodconfig localyesconfig
+       localmodconfig localyesconfig kvmconfig
 
 ifdef KBUILD_KCONFIG
 Kconfig := $(KBUILD_KCONFIG)
@@ -33,6 +33,11 @@ silentoldconfig: $(obj)/conf
        $(Q)mkdir -p include/generated
        $< --$@ $(Kconfig)
 
+kvmconfig:
+       $(Q)$(CONFIG_SHELL) $(srctree)/scripts/config -e KVMTOOL_TEST_ENABLE
+       $(Q)yes "" | make oldconfig > /dev/null
+       @echo 'Kernel configuration modified to run as KVM guest.'
+
 localyesconfig localmodconfig: $(obj)/streamline_config.pl $(obj)/conf
        $(Q)mkdir -p include/generated
        $(Q)perl $< --$@ $(srctree) $(Kconfig) > .tmp.config
old mode 100644 (file)
new mode 100755 (executable)
index e58e34e..87ca59d
-#!/bin/sh
+#!/usr/bin/perl -w
 #
 # Sign a module file using the given key.
 #
-# Format: sign-file <key> <x509> <src-file> <dst-file>
-#
-
-scripts=`dirname $0`
-
-CONFIG_MODULE_SIG_SHA512=y
-if [ -r .config ]
-then
-    . ./.config
-fi
-
-key="$1"
-x509="$2"
-src="$3"
-dst="$4"
-
-if [ ! -r "$key" ]
-then
-    echo "Can't read private key" >&2
-    exit 2
-fi
-
-if [ ! -r "$x509" ]
-then
-    echo "Can't read X.509 certificate" >&2
-    exit 2
-fi
-if [ ! -r "$x509.signer" ]
-then
-    echo "Can't read Signer name" >&2
-    exit 2;
-fi
-if [ ! -r "$x509.keyid" ]
-then
-    echo "Can't read Key identifier" >&2
-    exit 2;
-fi
+# Format:
+#
+#      ./scripts/sign-file [-v] <key> <x509> <module> [<dest>]
+#
+#
+use strict;
+use FileHandle;
+use IPC::Open2;
+
+my $verbose = 0;
+if ($#ARGV >= 0 && $ARGV[0] eq "-v") {
+    $verbose = 1;
+    shift;
+}
+
+die "Format: ./scripts/sign-file [-v] <key> <x509> <module> [<dest>]\n"
+    if ($#ARGV != 2 && $#ARGV != 3);
+
+my $private_key = $ARGV[0];
+my $x509 = $ARGV[1];
+my $module = $ARGV[2];
+my $dest = ($#ARGV == 3) ? $ARGV[3] : $ARGV[2] . "~";
+
+die "Can't read private key\n" unless (-r $private_key);
+die "Can't read X.509 certificate\n" unless (-r $x509);
+die "Can't read module\n" unless (-r $module);
+
+#
+# Read the kernel configuration
+#
+my %config = (
+    CONFIG_MODULE_SIG_SHA512 => 1
+    );
+
+if (-r ".config") {
+    open(FD, "<.config") || die ".config";
+    while (<FD>) {
+       if ($_ =~ /^(CONFIG_.*)=[ym]/) {
+           $config{$1} = 1;
+       }
+    }
+    close(FD);
+}
+
+#
+# Function to read the contents of a file into a variable.
+#
+sub read_file($)
+{
+    my ($file) = @_;
+    my $contents;
+    my $len;
+
+    open(FD, "<$file") || die $file;
+    binmode FD;
+    my @st = stat(FD);
+    die $file if (!@st);
+    $len = read(FD, $contents, $st[7]) || die $file;
+    close(FD) || die $file;
+    die "$file: Wanted length ", $st[7], ", got ", $len, "\n"
+       if ($len != $st[7]);
+    return $contents;
+}
+
+###############################################################################
+#
+# First of all, we have to parse the X.509 certificate to find certain details
+# about it.
+#
+# We read the DER-encoded X509 certificate and parse it to extract the Subject
+# name and Subject Key Identifier.  Theis provides the data we need to build
+# the certificate identifier.
+#
+# The signer's name part of the identifier is fabricated from the commonName,
+# the organizationName or the emailAddress components of the X.509 subject
+# name.
+#
+# The subject key ID is used to select which of that signer's certificates
+# we're intending to use to sign the module.
+#
+###############################################################################
+my $x509_certificate = read_file($x509);
+
+my $UNIV = 0 << 6;
+my $APPL = 1 << 6;
+my $CONT = 2 << 6;
+my $PRIV = 3 << 6;
+
+my $CONS = 0x20;
+
+my $BOOLEAN    = 0x01;
+my $INTEGER    = 0x02;
+my $BIT_STRING = 0x03;
+my $OCTET_STRING = 0x04;
+my $NULL       = 0x05;
+my $OBJ_ID     = 0x06;
+my $UTF8String = 0x0c;
+my $SEQUENCE   = 0x10;
+my $SET                = 0x11;
+my $UTCTime    = 0x17;
+my $GeneralizedTime = 0x18;
+
+my %OIDs = (
+    pack("CCC", 85, 4, 3)      => "commonName",
+    pack("CCC", 85, 4, 6)      => "countryName",
+    pack("CCC", 85, 4, 10)     => "organizationName",
+    pack("CCC", 85, 4, 11)     => "organizationUnitName",
+    pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 1, 1) => "rsaEncryption",
+    pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 1, 5) => "sha1WithRSAEncryption",
+    pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 9, 1) => "emailAddress",
+    pack("CCC", 85, 29, 35)    => "authorityKeyIdentifier",
+    pack("CCC", 85, 29, 14)    => "subjectKeyIdentifier",
+    pack("CCC", 85, 29, 19)    => "basicConstraints"
+);
+
+###############################################################################
+#
+# Extract an ASN.1 element from a string and return information about it.
+#
+###############################################################################
+sub asn1_extract($$@)
+{
+    my ($cursor, $expected_tag, $optional) = @_;
+
+    return [ -1 ]
+       if ($cursor->[1] == 0 && $optional);
+
+    die $x509, ": ", $cursor->[0], ": ASN.1 data underrun (elem ", $cursor->[1], ")\n"
+       if ($cursor->[1] < 2);
+
+    my ($tag, $len) = unpack("CC", substr(${$cursor->[2]}, $cursor->[0], 2));
+
+    if ($expected_tag != -1 && $tag != $expected_tag) {
+       return [ -1 ]
+           if ($optional);
+       die $x509, ": ", $cursor->[0], ": ASN.1 unexpected tag (", $tag,
+       " not ", $expected_tag, ")\n";
+    }
+
+    $cursor->[0] += 2;
+    $cursor->[1] -= 2;
+
+    die $x509, ": ", $cursor->[0], ": ASN.1 long tag\n"
+       if (($tag & 0x1f) == 0x1f);
+    die $x509, ": ", $cursor->[0], ": ASN.1 indefinite length\n"
+       if ($len == 0x80);
+
+    if ($len > 0x80) {
+       my $l = $len - 0x80;
+       die $x509, ": ", $cursor->[0], ": ASN.1 data underrun (len len $l)\n"
+           if ($cursor->[1] < $l);
+
+       if ($l == 0x1) {
+           $len = unpack("C", substr(${$cursor->[2]}, $cursor->[0], 1));
+       } elsif ($l = 0x2) {
+           $len = unpack("n", substr(${$cursor->[2]}, $cursor->[0], 2));
+       } elsif ($l = 0x3) {
+           $len = unpack("C", substr(${$cursor->[2]}, $cursor->[0], 1)) << 16;
+           $len = unpack("n", substr(${$cursor->[2]}, $cursor->[0] + 1, 2));
+       } elsif ($l = 0x4) {
+           $len = unpack("N", substr(${$cursor->[2]}, $cursor->[0], 4));
+       } else {
+           die $x509, ": ", $cursor->[0], ": ASN.1 element too long (", $l, ")\n";
+       }
+
+       $cursor->[0] += $l;
+       $cursor->[1] -= $l;
+    }
+
+    die $x509, ": ", $cursor->[0], ": ASN.1 data underrun (", $len, ")\n"
+       if ($cursor->[1] < $len);
+
+    my $ret = [ $tag, [ $cursor->[0], $len, $cursor->[2] ] ];
+    $cursor->[0] += $len;
+    $cursor->[1] -= $len;
+
+    return $ret;
+}
+
+###############################################################################
+#
+# Retrieve the data referred to by a cursor
+#
+###############################################################################
+sub asn1_retrieve($)
+{
+    my ($cursor) = @_;
+    my ($offset, $len, $data) = @$cursor;
+    return substr($$data, $offset, $len);
+}
+
+###############################################################################
+#
+# Roughly parse the X.509 certificate
+#
+###############################################################################
+my $cursor = [ 0, length($x509_certificate), \$x509_certificate ];
+
+my $cert = asn1_extract($cursor, $UNIV | $CONS | $SEQUENCE);
+my $tbs = asn1_extract($cert->[1], $UNIV | $CONS | $SEQUENCE);
+my $version = asn1_extract($tbs->[1], $CONT | $CONS | 0, 1);
+my $serial_number = asn1_extract($tbs->[1], $UNIV | $INTEGER);
+my $sig_type = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE);
+my $issuer = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE);
+my $validity = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE);
+my $subject = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE);
+my $key = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE);
+my $issuer_uid = asn1_extract($tbs->[1], $CONT | $CONS | 1, 1);
+my $subject_uid = asn1_extract($tbs->[1], $CONT | $CONS | 2, 1);
+my $extension_list = asn1_extract($tbs->[1], $CONT | $CONS | 3, 1);
+
+my $subject_key_id = ();
+my $authority_key_id = ();
+
+#
+# Parse the extension list
+#
+if ($extension_list->[0] != -1) {
+    my $extensions = asn1_extract($extension_list->[1], $UNIV | $CONS | $SEQUENCE);
+
+    while ($extensions->[1]->[1] > 0) {
+       my $ext = asn1_extract($extensions->[1], $UNIV | $CONS | $SEQUENCE);
+       my $x_oid = asn1_extract($ext->[1], $UNIV | $OBJ_ID);
+       my $x_crit = asn1_extract($ext->[1], $UNIV | $BOOLEAN, 1);
+       my $x_val = asn1_extract($ext->[1], $UNIV | $OCTET_STRING);
+
+       my $raw_oid = asn1_retrieve($x_oid->[1]);
+       next if (!exists($OIDs{$raw_oid}));
+       my $x_type = $OIDs{$raw_oid};
+
+       my $raw_value = asn1_retrieve($x_val->[1]);
+
+       if ($x_type eq "subjectKeyIdentifier") {
+           my $vcursor = [ 0, length($raw_value), \$raw_value ];
+
+           $subject_key_id = asn1_extract($vcursor, $UNIV | $OCTET_STRING);
+       }
+    }
+}
+
+###############################################################################
+#
+# Determine what we're going to use as the signer's name.  In order of
+# preference, take one of: commonName, organizationName or emailAddress.
+#
+###############################################################################
+my $org = "";
+my $cn = "";
+my $email = "";
+
+while ($subject->[1]->[1] > 0) {
+    my $rdn = asn1_extract($subject->[1], $UNIV | $CONS | $SET);
+    my $attr = asn1_extract($rdn->[1], $UNIV | $CONS | $SEQUENCE);
+    my $n_oid = asn1_extract($attr->[1], $UNIV | $OBJ_ID);
+    my $n_val = asn1_extract($attr->[1], -1);
+
+    my $raw_oid = asn1_retrieve($n_oid->[1]);
+    next if (!exists($OIDs{$raw_oid}));
+    my $n_type = $OIDs{$raw_oid};
+
+    my $raw_value = asn1_retrieve($n_val->[1]);
+
+    if ($n_type eq "organizationName") {
+       $org = $raw_value;
+    } elsif ($n_type eq "commonName") {
+       $cn = $raw_value;
+    } elsif ($n_type eq "emailAddress") {
+       $email = $raw_value;
+    }
+}
+
+my $signers_name = $email;
+
+if ($org && $cn) {
+    # Don't use the organizationName if the commonName repeats it
+    if (length($org) <= length($cn) &&
+       substr($cn, 0, length($org)) eq $org) {
+       $signers_name = $cn;
+       goto got_id_name;
+    }
+
+    # Or a signifcant chunk of it
+    if (length($org) >= 7 &&
+       length($cn) >= 7 &&
+       substr($cn, 0, 7) eq substr($org, 0, 7)) {
+       $signers_name = $cn;
+       goto got_id_name;
+    }
+
+    $signers_name = $org . ": " . $cn;
+} elsif ($org) {
+    $signers_name = $org;
+} elsif ($cn) {
+    $signers_name = $cn;
+}
+
+got_id_name:
+
+die $x509, ": ", "X.509: Couldn't find the Subject Key Identifier extension\n"
+    if (!$subject_key_id);
+
+my $key_identifier = asn1_retrieve($subject_key_id->[1]);
+
+###############################################################################
+#
+# Create and attach the module signature
+#
+###############################################################################
 
 #
 # Signature parameters
 #
-algo=1         # Public-key crypto algorithm: RSA
-hash=          # Digest algorithm
-id_type=1      # Identifier type: X.509
+my $algo = 1;          # Public-key crypto algorithm: RSA
+my $hash = 0;          # Digest algorithm
+my $id_type = 1;       # Identifier type: X.509
 
 #
 # Digest the data
 #
-dgst=
-if [ "$CONFIG_MODULE_SIG_SHA1" = "y" ]
-then
-    prologue="0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14"
-    dgst=-sha1
-    hash=2
-elif [ "$CONFIG_MODULE_SIG_SHA224" = "y" ]
-then
-    prologue="0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1C"
-    dgst=-sha224
-    hash=7
-elif [ "$CONFIG_MODULE_SIG_SHA256" = "y" ]
-then
-    prologue="0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20"
-    dgst=-sha256
-    hash=4
-elif [ "$CONFIG_MODULE_SIG_SHA384" = "y" ]
-then
-    prologue="0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30"
-    dgst=-sha384
-    hash=5
-elif [ "$CONFIG_MODULE_SIG_SHA512" = "y" ]
-then
-    prologue="0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40"
-    dgst=-sha512
-    hash=6
-else
-    echo "$0: Can't determine hash algorithm" >&2
-    exit 2
-fi
-
-(
-perl -e "binmode STDOUT; print pack(\"C*\", $prologue)" || exit $?
-openssl dgst $dgst -binary $src || exit $?
-) >$src.dig || exit $?
+my ($dgst, $prologue) = ();
+if (exists $config{"CONFIG_MODULE_SIG_SHA1"}) {
+    $prologue = pack("C*",
+                    0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
+                    0x2B, 0x0E, 0x03, 0x02, 0x1A,
+                    0x05, 0x00, 0x04, 0x14);
+    $dgst = "-sha1";
+    $hash = 2;
+} elsif (exists $config{"CONFIG_MODULE_SIG_SHA224"}) {
+    $prologue = pack("C*",
+                    0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09,
+                    0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04,
+                    0x05, 0x00, 0x04, 0x1C);
+    $dgst = "-sha224";
+    $hash = 7;
+} elsif (exists $config{"CONFIG_MODULE_SIG_SHA256"}) {
+    $prologue = pack("C*",
+                    0x30, 0x31, 0x30, 0x0d, 0x06, 0x09,
+                    0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01,
+                    0x05, 0x00, 0x04, 0x20);
+    $dgst = "-sha256";
+    $hash = 4;
+} elsif (exists $config{"CONFIG_MODULE_SIG_SHA384"}) {
+    $prologue = pack("C*",
+                    0x30, 0x41, 0x30, 0x0d, 0x06, 0x09,
+                    0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02,
+                    0x05, 0x00, 0x04, 0x30);
+    $dgst = "-sha384";
+    $hash = 5;
+} elsif (exists $config{"CONFIG_MODULE_SIG_SHA512"}) {
+    $prologue = pack("C*",
+                    0x30, 0x51, 0x30, 0x0d, 0x06, 0x09,
+                    0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03,
+                    0x05, 0x00, 0x04, 0x40);
+    $dgst = "-sha512";
+    $hash = 6;
+} else {
+    die "Can't determine hash algorithm";
+}
+
+#
+# Generate the digest and read from openssl's stdout
+#
+my $digest;
+$digest = readpipe("openssl dgst $dgst -binary $module") || die "openssl dgst";
 
 #
 # Generate the binary signature, which will be just the integer that comprises
 # the signature with no metadata attached.
 #
-openssl rsautl -sign -inkey $key -keyform PEM -in $src.dig -out $src.sig || exit $?
-signerlen=`stat -c %s $x509.signer`
-keyidlen=`stat -c %s $x509.keyid`
-siglen=`stat -c %s $src.sig`
+my $pid;
+$pid = open2(*read_from, *write_to,
+            "openssl rsautl -sign -inkey $private_key -keyform PEM") ||
+    die "openssl rsautl";
+binmode write_to;
+print write_to $prologue . $digest || die "pipe to openssl rsautl";
+close(write_to) || die "pipe to openssl rsautl";
+
+binmode read_from;
+my $signature;
+read(read_from, $signature, 4096) || die "pipe from openssl rsautl";
+close(read_from) || die "pipe from openssl rsautl";
+$signature = pack("n", length($signature)) . $signature,
+
+waitpid($pid, 0) || die;
+die "openssl rsautl died: $?" if ($? >> 8);
 
 #
 # Build the signed binary
 #
-(
-    cat $src || exit $?
-    echo '~Module signature appended~' || exit $?
-    cat $x509.signer $x509.keyid || exit $?
+my $unsigned_module = read_file($module);
+
+my $magic_number = "~Module signature appended~\n";
+
+my $info = pack("CCCCCxxxN",
+               $algo, $hash, $id_type,
+               length($signers_name),
+               length($key_identifier),
+               length($signature));
 
-    # Preface each signature integer with a 2-byte BE length
-    perl -e "binmode STDOUT; print pack(\"n\", $siglen)" || exit $?
-    cat $src.sig || exit $?
+if ($verbose) {
+    print "Size of unsigned module: ", length($unsigned_module), "\n";
+    print "Size of signer's name  : ", length($signers_name), "\n";
+    print "Size of key identifier : ", length($key_identifier), "\n";
+    print "Size of signature      : ", length($signature), "\n";
+    print "Size of informaton     : ", length($info), "\n";
+    print "Size of magic number   : ", length($magic_number), "\n";
+    print "Signer's name          : '", $signers_name, "'\n";
+    print "Digest                 : $dgst\n";
+}
 
-    # Generate the information block
-    perl -e "binmode STDOUT; print pack(\"CCCCCxxxN\", $algo, $hash, $id_type, $signerlen, $keyidlen, $siglen + 2)" || exit $?
-) >$dst~ || exit $?
+open(FD, ">$dest") || die $dest;
+binmode FD;
+print FD
+    $unsigned_module,
+    $signers_name,
+    $key_identifier,
+    $signature,
+    $info,
+    $magic_number
+    ;
+close FD || die $dest;
 
-# Permit in-place signing
-mv $dst~ $dst || exit $?
+if ($#ARGV != 3) {
+    rename($dest, $module) || die $module;
+}
diff --git a/scripts/x509keyid b/scripts/x509keyid
deleted file mode 100755 (executable)
index c8e91a4..0000000
+++ /dev/null
@@ -1,268 +0,0 @@
-#!/usr/bin/perl -w
-#
-# Generate an identifier from an X.509 certificate that can be placed in a
-# module signature to indentify the key to use.
-#
-# Format:
-#
-#      ./scripts/x509keyid <x509-cert> <signer's-name> <key-id>
-#
-# We read the DER-encoded X509 certificate and parse it to extract the Subject
-# name and Subject Key Identifier.  The provide the data we need to build the
-# certificate identifier.
-#
-# The signer's name part of the identifier is fabricated from the commonName,
-# the organizationName or the emailAddress components of the X.509 subject
-# name and written to the second named file.
-#
-# The subject key ID to select which of that signer's certificates we're
-# intending to use to sign the module is written to the third named file.
-#
-use strict;
-
-my $raw_data;
-
-die "Need three filenames\n" if ($#ARGV != 2);
-
-my $src = $ARGV[0];
-
-open(FD, "<$src") || die $src;
-binmode FD;
-my @st = stat(FD);
-die $src if (!@st);
-read(FD, $raw_data, $st[7]) || die $src;
-close(FD);
-
-my $UNIV = 0 << 6;
-my $APPL = 1 << 6;
-my $CONT = 2 << 6;
-my $PRIV = 3 << 6;
-
-my $CONS = 0x20;
-
-my $BOOLEAN    = 0x01;
-my $INTEGER    = 0x02;
-my $BIT_STRING = 0x03;
-my $OCTET_STRING = 0x04;
-my $NULL       = 0x05;
-my $OBJ_ID     = 0x06;
-my $UTF8String = 0x0c;
-my $SEQUENCE   = 0x10;
-my $SET                = 0x11;
-my $UTCTime    = 0x17;
-my $GeneralizedTime = 0x18;
-
-my %OIDs = (
-    pack("CCC", 85, 4, 3)      => "commonName",
-    pack("CCC", 85, 4, 6)      => "countryName",
-    pack("CCC", 85, 4, 10)     => "organizationName",
-    pack("CCC", 85, 4, 11)     => "organizationUnitName",
-    pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 1, 1) => "rsaEncryption",
-    pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 1, 5) => "sha1WithRSAEncryption",
-    pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 9, 1) => "emailAddress",
-    pack("CCC", 85, 29, 35)    => "authorityKeyIdentifier",
-    pack("CCC", 85, 29, 14)    => "subjectKeyIdentifier",
-    pack("CCC", 85, 29, 19)    => "basicConstraints"
-);
-
-###############################################################################
-#
-# Extract an ASN.1 element from a string and return information about it.
-#
-###############################################################################
-sub asn1_extract($$@)
-{
-    my ($cursor, $expected_tag, $optional) = @_;
-
-    return [ -1 ]
-       if ($cursor->[1] == 0 && $optional);
-
-    die $src, ": ", $cursor->[0], ": ASN.1 data underrun (elem ", $cursor->[1], ")\n"
-       if ($cursor->[1] < 2);
-
-    my ($tag, $len) = unpack("CC", substr(${$cursor->[2]}, $cursor->[0], 2));
-
-    if ($expected_tag != -1 && $tag != $expected_tag) {
-       return [ -1 ]
-           if ($optional);
-       die $src, ": ", $cursor->[0], ": ASN.1 unexpected tag (", $tag,
-       " not ", $expected_tag, ")\n";
-    }
-
-    $cursor->[0] += 2;
-    $cursor->[1] -= 2;
-
-    die $src, ": ", $cursor->[0], ": ASN.1 long tag\n"
-       if (($tag & 0x1f) == 0x1f);
-    die $src, ": ", $cursor->[0], ": ASN.1 indefinite length\n"
-       if ($len == 0x80);
-
-    if ($len > 0x80) {
-       my $l = $len - 0x80;
-       die $src, ": ", $cursor->[0], ": ASN.1 data underrun (len len $l)\n"
-           if ($cursor->[1] < $l);
-
-       if ($l == 0x1) {
-           $len = unpack("C", substr(${$cursor->[2]}, $cursor->[0], 1));
-       } elsif ($l = 0x2) {
-           $len = unpack("n", substr(${$cursor->[2]}, $cursor->[0], 2));
-       } elsif ($l = 0x3) {
-           $len = unpack("C", substr(${$cursor->[2]}, $cursor->[0], 1)) << 16;
-           $len = unpack("n", substr(${$cursor->[2]}, $cursor->[0] + 1, 2));
-       } elsif ($l = 0x4) {
-           $len = unpack("N", substr(${$cursor->[2]}, $cursor->[0], 4));
-       } else {
-           die $src, ": ", $cursor->[0], ": ASN.1 element too long (", $l, ")\n";
-       }
-
-       $cursor->[0] += $l;
-       $cursor->[1] -= $l;
-    }
-
-    die $src, ": ", $cursor->[0], ": ASN.1 data underrun (", $len, ")\n"
-       if ($cursor->[1] < $len);
-
-    my $ret = [ $tag, [ $cursor->[0], $len, $cursor->[2] ] ];
-    $cursor->[0] += $len;
-    $cursor->[1] -= $len;
-
-    return $ret;
-}
-
-###############################################################################
-#
-# Retrieve the data referred to by a cursor
-#
-###############################################################################
-sub asn1_retrieve($)
-{
-    my ($cursor) = @_;
-    my ($offset, $len, $data) = @$cursor;
-    return substr($$data, $offset, $len);
-}
-
-###############################################################################
-#
-# Roughly parse the X.509 certificate
-#
-###############################################################################
-my $cursor = [ 0, length($raw_data), \$raw_data ];
-
-my $cert = asn1_extract($cursor, $UNIV | $CONS | $SEQUENCE);
-my $tbs = asn1_extract($cert->[1], $UNIV | $CONS | $SEQUENCE);
-my $version = asn1_extract($tbs->[1], $CONT | $CONS | 0, 1);
-my $serial_number = asn1_extract($tbs->[1], $UNIV | $INTEGER);
-my $sig_type = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE);
-my $issuer = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE);
-my $validity = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE);
-my $subject = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE);
-my $key = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE);
-my $issuer_uid = asn1_extract($tbs->[1], $CONT | $CONS | 1, 1);
-my $subject_uid = asn1_extract($tbs->[1], $CONT | $CONS | 2, 1);
-my $extension_list = asn1_extract($tbs->[1], $CONT | $CONS | 3, 1);
-
-my $subject_key_id = ();
-my $authority_key_id = ();
-
-#
-# Parse the extension list
-#
-if ($extension_list->[0] != -1) {
-    my $extensions = asn1_extract($extension_list->[1], $UNIV | $CONS | $SEQUENCE);
-
-    while ($extensions->[1]->[1] > 0) {
-       my $ext = asn1_extract($extensions->[1], $UNIV | $CONS | $SEQUENCE);
-       my $x_oid = asn1_extract($ext->[1], $UNIV | $OBJ_ID);
-       my $x_crit = asn1_extract($ext->[1], $UNIV | $BOOLEAN, 1);
-       my $x_val = asn1_extract($ext->[1], $UNIV | $OCTET_STRING);
-
-       my $raw_oid = asn1_retrieve($x_oid->[1]);
-       next if (!exists($OIDs{$raw_oid}));
-       my $x_type = $OIDs{$raw_oid};
-
-       my $raw_value = asn1_retrieve($x_val->[1]);
-
-       if ($x_type eq "subjectKeyIdentifier") {
-           my $vcursor = [ 0, length($raw_value), \$raw_value ];
-
-           $subject_key_id = asn1_extract($vcursor, $UNIV | $OCTET_STRING);
-       }
-    }
-}
-
-###############################################################################
-#
-# Determine what we're going to use as the signer's name.  In order of
-# preference, take one of: commonName, organizationName or emailAddress.
-#
-###############################################################################
-my $org = "";
-my $cn = "";
-my $email = "";
-
-while ($subject->[1]->[1] > 0) {
-    my $rdn = asn1_extract($subject->[1], $UNIV | $CONS | $SET);
-    my $attr = asn1_extract($rdn->[1], $UNIV | $CONS | $SEQUENCE);
-    my $n_oid = asn1_extract($attr->[1], $UNIV | $OBJ_ID);
-    my $n_val = asn1_extract($attr->[1], -1);
-
-    my $raw_oid = asn1_retrieve($n_oid->[1]);
-    next if (!exists($OIDs{$raw_oid}));
-    my $n_type = $OIDs{$raw_oid};
-
-    my $raw_value = asn1_retrieve($n_val->[1]);
-
-    if ($n_type eq "organizationName") {
-       $org = $raw_value;
-    } elsif ($n_type eq "commonName") {
-       $cn = $raw_value;
-    } elsif ($n_type eq "emailAddress") {
-       $email = $raw_value;
-    }
-}
-
-my $id_name = $email;
-
-if ($org && $cn) {
-    # Don't use the organizationName if the commonName repeats it
-    if (length($org) <= length($cn) &&
-       substr($cn, 0, length($org)) eq $org) {
-       $id_name = $cn;
-       goto got_id_name;
-    }
-
-    # Or a signifcant chunk of it
-    if (length($org) >= 7 &&
-       length($cn) >= 7 &&
-       substr($cn, 0, 7) eq substr($org, 0, 7)) {
-       $id_name = $cn;
-       goto got_id_name;
-    }
-
-    $id_name = $org . ": " . $cn;
-} elsif ($org) {
-    $id_name = $org;
-} elsif ($cn) {
-    $id_name = $cn;
-}
-
-got_id_name:
-
-###############################################################################
-#
-# Output the signer's name and the key identifier that we're going to include
-# in module signatures.
-#
-###############################################################################
-die $src, ": ", "X.509: Couldn't find the Subject Key Identifier extension\n"
-    if (!$subject_key_id);
-
-my $id_key_id = asn1_retrieve($subject_key_id->[1]);
-
-open(OUTFD, ">$ARGV[1]") || die $ARGV[1];
-print OUTFD $id_name;
-close OUTFD || die $ARGV[1];
-
-open(OUTFD, ">$ARGV[2]") || die $ARGV[2];
-print OUTFD $id_key_id;
-close OUTFD || die $ARGV[2];
index b14a30c234b885199fd6f8dac080a343255a7d1f..0fe5a026aef8d22ac83619dd0bbc2ba50965b63e 100644 (file)
@@ -395,6 +395,11 @@ static int cap_kernel_module_request(char *kmod_name)
        return 0;
 }
 
+static int cap_kernel_module_from_file(struct file *file)
+{
+       return 0;
+}
+
 static int cap_task_setpgid(struct task_struct *p, pid_t pgid)
 {
        return 0;
@@ -967,6 +972,7 @@ void __init security_fixup_ops(struct security_operations *ops)
        set_to_cap_if_null(ops, kernel_act_as);
        set_to_cap_if_null(ops, kernel_create_files_as);
        set_to_cap_if_null(ops, kernel_module_request);
+       set_to_cap_if_null(ops, kernel_module_from_file);
        set_to_cap_if_null(ops, task_fix_setuid);
        set_to_cap_if_null(ops, task_setpgid);
        set_to_cap_if_null(ops, task_getpgid);
index 6ee8826662ccd7d31a4669ee34eed478cbe0deff..3b2adb794f15506311a52b2ec5442297907ee8e2 100644 (file)
@@ -127,7 +127,7 @@ struct integrity_iint_cache *integrity_iint_insert(struct inode *inode);
 struct integrity_iint_cache *integrity_iint_find(struct inode *inode);
 
 /* IMA policy related functions */
-enum ima_hooks { FILE_CHECK = 1, FILE_MMAP, BPRM_CHECK, POST_SETATTR };
+enum ima_hooks { FILE_CHECK = 1, FILE_MMAP, BPRM_CHECK, MODULE_CHECK, POST_SETATTR };
 
 int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask,
                     int flags);
index b356884fb3ef9c17dbc3d71396ac01c98e20a400..0cea3db216576520373a40c4d2df6ac8b1450257 100644 (file)
@@ -100,12 +100,12 @@ err_out:
  * ima_get_action - appraise & measure decision based on policy.
  * @inode: pointer to inode to measure
  * @mask: contains the permission mask (MAY_READ, MAY_WRITE, MAY_EXECUTE)
- * @function: calling function (FILE_CHECK, BPRM_CHECK, FILE_MMAP)
+ * @function: calling function (FILE_CHECK, BPRM_CHECK, FILE_MMAP, MODULE_CHECK)
  *
  * The policy is defined in terms of keypairs:
  *             subj=, obj=, type=, func=, mask=, fsmagic=
  *     subj,obj, and type: are LSM specific.
- *     func: FILE_CHECK | BPRM_CHECK | FILE_MMAP
+ *     func: FILE_CHECK | BPRM_CHECK | FILE_MMAP | MODULE_CHECK
  *     mask: contains the permission mask
  *     fsmagic: hex value
  *
index 73c9a268253e44718c1f02395f2ffb1f905511ca..45de18e9a6f224aac3b90512fb1e4b6453b795be 100644 (file)
@@ -280,6 +280,27 @@ int ima_file_check(struct file *file, int mask)
 }
 EXPORT_SYMBOL_GPL(ima_file_check);
 
+/**
+ * ima_module_check - based on policy, collect/store/appraise measurement.
+ * @file: pointer to the file to be measured/appraised
+ *
+ * Measure/appraise kernel modules based on policy.
+ *
+ * Always return 0 and audit dentry_open failures.
+ * Return code is based upon measurement appraisal.
+ */
+int ima_module_check(struct file *file)
+{
+       int rc;
+
+       if (!file)
+               rc = INTEGRITY_UNKNOWN;
+       else
+               rc = process_measurement(file, file->f_dentry->d_name.name,
+                                        MAY_EXEC, MODULE_CHECK);
+       return (ima_appraise & IMA_APPRAISE_ENFORCE) ? rc : 0;
+}
+
 static int __init init_ima(void)
 {
        int error;
index c7dacd2eab7a8eb59de3b00d4963b59b58396b96..af7d182d5a46123ca9308cf2e231f006aa71215d 100644 (file)
@@ -80,6 +80,7 @@ static struct ima_rule_entry default_rules[] = {
         .flags = IMA_FUNC | IMA_MASK},
        {.action = MEASURE,.func = FILE_CHECK,.mask = MAY_READ,.uid = GLOBAL_ROOT_UID,
         .flags = IMA_FUNC | IMA_MASK | IMA_UID},
+       {.action = MEASURE,.func = MODULE_CHECK, .flags = IMA_FUNC},
 };
 
 static struct ima_rule_entry default_appraise_rules[] = {
@@ -401,6 +402,8 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
                        /* PATH_CHECK is for backwards compat */
                        else if (strcmp(args[0].from, "PATH_CHECK") == 0)
                                entry->func = FILE_CHECK;
+                       else if (strcmp(args[0].from, "MODULE_CHECK") == 0)
+                               entry->func = MODULE_CHECK;
                        else if (strcmp(args[0].from, "FILE_MMAP") == 0)
                                entry->func = FILE_MMAP;
                        else if (strcmp(args[0].from, "BPRM_CHECK") == 0)
index a15c9da8f971832edb41a455b72f738fac4e9cb8..8fb7c7bd465769cb5dca49e6d6f1ad011c75de63 100644 (file)
@@ -854,13 +854,13 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
        /* if the client doesn't provide, decide on the permissions we want */
        if (perm == KEY_PERM_UNDEF) {
                perm = KEY_POS_VIEW | KEY_POS_SEARCH | KEY_POS_LINK | KEY_POS_SETATTR;
-               perm |= KEY_USR_VIEW | KEY_USR_SEARCH | KEY_USR_LINK | KEY_USR_SETATTR;
+               perm |= KEY_USR_VIEW;
 
                if (ktype->read)
-                       perm |= KEY_POS_READ | KEY_USR_READ;
+                       perm |= KEY_POS_READ;
 
                if (ktype == &key_type_keyring || ktype->update)
-                       perm |= KEY_USR_WRITE;
+                       perm |= KEY_POS_WRITE;
        }
 
        /* allocate a new key */
index 5d34b4e827d6349a46f6b892573e129e500e49db..4b5c948eb41426c76ef1810239cb0a98f9c4f918 100644 (file)
@@ -1132,12 +1132,12 @@ long keyctl_instantiate_key_iov(key_serial_t id,
        ret = rw_copy_check_uvector(WRITE, _payload_iov, ioc,
                                    ARRAY_SIZE(iovstack), iovstack, &iov);
        if (ret < 0)
-               return ret;
+               goto err;
        if (ret == 0)
                goto no_payload_free;
 
        ret = keyctl_instantiate_key_common(id, iov, ioc, ret, ringid);
-
+err:
        if (iov != iovstack)
                kfree(iov);
        return ret;
@@ -1495,7 +1495,8 @@ long keyctl_session_to_parent(void)
                goto error_keyring;
        newwork = &cred->rcu;
 
-       cred->tgcred->session_keyring = key_ref_to_ptr(keyring_r);
+       cred->session_keyring = key_ref_to_ptr(keyring_r);
+       keyring_r = NULL;
        init_task_work(newwork, key_change_session_keyring);
 
        me = current;
@@ -1519,7 +1520,7 @@ long keyctl_session_to_parent(void)
        mycred = current_cred();
        pcred = __task_cred(parent);
        if (mycred == pcred ||
-           mycred->tgcred->session_keyring == pcred->tgcred->session_keyring) {
+           mycred->session_keyring == pcred->session_keyring) {
                ret = 0;
                goto unlock;
        }
@@ -1535,9 +1536,9 @@ long keyctl_session_to_parent(void)
                goto unlock;
 
        /* the keyrings must have the same UID */
-       if ((pcred->tgcred->session_keyring &&
-            !uid_eq(pcred->tgcred->session_keyring->uid, mycred->euid)) ||
-           !uid_eq(mycred->tgcred->session_keyring->uid, mycred->euid))
+       if ((pcred->session_keyring &&
+            !uid_eq(pcred->session_keyring->uid, mycred->euid)) ||
+           !uid_eq(mycred->session_keyring->uid, mycred->euid))
                goto unlock;
 
        /* cancel an already pending keyring replacement */
index 6e42df15a24c3b3509455d8afedaed3dccf66662..6ece7f2e5707f45c2736ca4a05504c2dd391ea00 100644 (file)
@@ -257,17 +257,14 @@ error:
  * Allocate a keyring and link into the destination keyring.
  */
 struct key *keyring_alloc(const char *description, kuid_t uid, kgid_t gid,
-                         const struct cred *cred, unsigned long flags,
-                         struct key *dest)
+                         const struct cred *cred, key_perm_t perm,
+                         unsigned long flags, struct key *dest)
 {
        struct key *keyring;
        int ret;
 
        keyring = key_alloc(&key_type_keyring, description,
-                           uid, gid, cred,
-                           (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL,
-                           flags);
-
+                           uid, gid, cred, perm, flags);
        if (!IS_ERR(keyring)) {
                ret = key_instantiate_and_link(keyring, NULL, 0, dest, NULL);
                if (ret < 0) {
@@ -278,6 +275,7 @@ struct key *keyring_alloc(const char *description, kuid_t uid, kgid_t gid,
 
        return keyring;
 }
+EXPORT_SYMBOL(keyring_alloc);
 
 /**
  * keyring_search_aux - Search a keyring tree for a key matching some criteria
index a58f712605d83105b6d32e1b966436a454331a90..58dfe089094793030f56fdb895f6621e403e4157 100644 (file)
@@ -45,10 +45,12 @@ int install_user_keyrings(void)
        struct user_struct *user;
        const struct cred *cred;
        struct key *uid_keyring, *session_keyring;
+       key_perm_t user_keyring_perm;
        char buf[20];
        int ret;
        uid_t uid;
 
+       user_keyring_perm = (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL;
        cred = current_cred();
        user = cred->user;
        uid = from_kuid(cred->user_ns, user->uid);
@@ -73,8 +75,8 @@ int install_user_keyrings(void)
                uid_keyring = find_keyring_by_name(buf, true);
                if (IS_ERR(uid_keyring)) {
                        uid_keyring = keyring_alloc(buf, user->uid, INVALID_GID,
-                                                   cred, KEY_ALLOC_IN_QUOTA,
-                                                   NULL);
+                                                   cred, user_keyring_perm,
+                                                   KEY_ALLOC_IN_QUOTA, NULL);
                        if (IS_ERR(uid_keyring)) {
                                ret = PTR_ERR(uid_keyring);
                                goto error;
@@ -89,7 +91,8 @@ int install_user_keyrings(void)
                if (IS_ERR(session_keyring)) {
                        session_keyring =
                                keyring_alloc(buf, user->uid, INVALID_GID,
-                                             cred, KEY_ALLOC_IN_QUOTA, NULL);
+                                             cred, user_keyring_perm,
+                                             KEY_ALLOC_IN_QUOTA, NULL);
                        if (IS_ERR(session_keyring)) {
                                ret = PTR_ERR(session_keyring);
                                goto error_release;
@@ -130,6 +133,7 @@ int install_thread_keyring_to_cred(struct cred *new)
        struct key *keyring;
 
        keyring = keyring_alloc("_tid", new->uid, new->gid, new,
+                               KEY_POS_ALL | KEY_USR_VIEW,
                                KEY_ALLOC_QUOTA_OVERRUN, NULL);
        if (IS_ERR(keyring))
                return PTR_ERR(keyring);
@@ -170,27 +174,18 @@ static int install_thread_keyring(void)
 int install_process_keyring_to_cred(struct cred *new)
 {
        struct key *keyring;
-       int ret;
 
-       if (new->tgcred->process_keyring)
+       if (new->process_keyring)
                return -EEXIST;
 
-       keyring = keyring_alloc("_pid", new->uid, new->gid,
-                               new, KEY_ALLOC_QUOTA_OVERRUN, NULL);
+       keyring = keyring_alloc("_pid", new->uid, new->gid, new,
+                               KEY_POS_ALL | KEY_USR_VIEW,
+                               KEY_ALLOC_QUOTA_OVERRUN, NULL);
        if (IS_ERR(keyring))
                return PTR_ERR(keyring);
 
-       spin_lock_irq(&new->tgcred->lock);
-       if (!new->tgcred->process_keyring) {
-               new->tgcred->process_keyring = keyring;
-               keyring = NULL;
-               ret = 0;
-       } else {
-               ret = -EEXIST;
-       }
-       spin_unlock_irq(&new->tgcred->lock);
-       key_put(keyring);
-       return ret;
+       new->process_keyring = keyring;
+       return 0;
 }
 
 /*
@@ -231,11 +226,12 @@ int install_session_keyring_to_cred(struct cred *cred, struct key *keyring)
        /* create an empty session keyring */
        if (!keyring) {
                flags = KEY_ALLOC_QUOTA_OVERRUN;
-               if (cred->tgcred->session_keyring)
+               if (cred->session_keyring)
                        flags = KEY_ALLOC_IN_QUOTA;
 
-               keyring = keyring_alloc("_ses", cred->uid, cred->gid,
-                                       cred, flags, NULL);
+               keyring = keyring_alloc("_ses", cred->uid, cred->gid, cred,
+                                       KEY_POS_ALL | KEY_USR_VIEW | KEY_USR_READ,
+                                       flags, NULL);
                if (IS_ERR(keyring))
                        return PTR_ERR(keyring);
        } else {
@@ -243,17 +239,11 @@ int install_session_keyring_to_cred(struct cred *cred, struct key *keyring)
        }
 
        /* install the keyring */
-       spin_lock_irq(&cred->tgcred->lock);
-       old = cred->tgcred->session_keyring;
-       rcu_assign_pointer(cred->tgcred->session_keyring, keyring);
-       spin_unlock_irq(&cred->tgcred->lock);
-
-       /* we're using RCU on the pointer, but there's no point synchronising
-        * on it if it didn't previously point to anything */
-       if (old) {
-               synchronize_rcu();
+       old = cred->session_keyring;
+       rcu_assign_pointer(cred->session_keyring, keyring);
+
+       if (old)
                key_put(old);
-       }
 
        return 0;
 }
@@ -358,8 +348,6 @@ key_ref_t search_my_process_keyrings(struct key_type *type,
 
                switch (PTR_ERR(key_ref)) {
                case -EAGAIN: /* no key */
-                       if (ret)
-                               break;
                case -ENOKEY: /* negative key */
                        ret = key_ref;
                        break;
@@ -370,9 +358,9 @@ key_ref_t search_my_process_keyrings(struct key_type *type,
        }
 
        /* search the process keyring second */
-       if (cred->tgcred->process_keyring) {
+       if (cred->process_keyring) {
                key_ref = keyring_search_aux(
-                       make_key_ref(cred->tgcred->process_keyring, 1),
+                       make_key_ref(cred->process_keyring, 1),
                        cred, type, description, match, no_state_check);
                if (!IS_ERR(key_ref))
                        goto found;
@@ -391,12 +379,10 @@ key_ref_t search_my_process_keyrings(struct key_type *type,
        }
 
        /* search the session keyring */
-       if (cred->tgcred->session_keyring) {
+       if (cred->session_keyring) {
                rcu_read_lock();
                key_ref = keyring_search_aux(
-                       make_key_ref(rcu_dereference(
-                                            cred->tgcred->session_keyring),
-                                    1),
+                       make_key_ref(rcu_dereference(cred->session_keyring), 1),
                        cred, type, description, match, no_state_check);
                rcu_read_unlock();
 
@@ -566,7 +552,7 @@ try_again:
                break;
 
        case KEY_SPEC_PROCESS_KEYRING:
-               if (!cred->tgcred->process_keyring) {
+               if (!cred->process_keyring) {
                        if (!(lflags & KEY_LOOKUP_CREATE))
                                goto error;
 
@@ -578,13 +564,13 @@ try_again:
                        goto reget_creds;
                }
 
-               key = cred->tgcred->process_keyring;
+               key = cred->process_keyring;
                atomic_inc(&key->usage);
                key_ref = make_key_ref(key, 1);
                break;
 
        case KEY_SPEC_SESSION_KEYRING:
-               if (!cred->tgcred->session_keyring) {
+               if (!cred->session_keyring) {
                        /* always install a session keyring upon access if one
                         * doesn't exist yet */
                        ret = install_user_keyrings();
@@ -599,7 +585,7 @@ try_again:
                        if (ret < 0)
                                goto error;
                        goto reget_creds;
-               } else if (cred->tgcred->session_keyring ==
+               } else if (cred->session_keyring ==
                           cred->user->session_keyring &&
                           lflags & KEY_LOOKUP_CREATE) {
                        ret = join_session_keyring(NULL);
@@ -609,7 +595,7 @@ try_again:
                }
 
                rcu_read_lock();
-               key = rcu_dereference(cred->tgcred->session_keyring);
+               key = rcu_dereference(cred->session_keyring);
                atomic_inc(&key->usage);
                rcu_read_unlock();
                key_ref = make_key_ref(key, 1);
@@ -769,12 +755,6 @@ long join_session_keyring(const char *name)
        struct key *keyring;
        long ret, serial;
 
-       /* only permit this if there's a single thread in the thread group -
-        * this avoids us having to adjust the creds on all threads and risking
-        * ENOMEM */
-       if (!current_is_single_threaded())
-               return -EMLINK;
-
        new = prepare_creds();
        if (!new)
                return -ENOMEM;
@@ -786,7 +766,7 @@ long join_session_keyring(const char *name)
                if (ret < 0)
                        goto error;
 
-               serial = new->tgcred->session_keyring->serial;
+               serial = new->session_keyring->serial;
                ret = commit_creds(new);
                if (ret == 0)
                        ret = serial;
@@ -800,8 +780,10 @@ long join_session_keyring(const char *name)
        keyring = find_keyring_by_name(name, false);
        if (PTR_ERR(keyring) == -ENOKEY) {
                /* not found - try and create a new one */
-               keyring = keyring_alloc(name, old->uid, old->gid, old,
-                                       KEY_ALLOC_IN_QUOTA, NULL);
+               keyring = keyring_alloc(
+                       name, old->uid, old->gid, old,
+                       KEY_POS_ALL | KEY_USR_VIEW | KEY_USR_READ | KEY_USR_LINK,
+                       KEY_ALLOC_IN_QUOTA, NULL);
                if (IS_ERR(keyring)) {
                        ret = PTR_ERR(keyring);
                        goto error2;
@@ -809,6 +791,9 @@ long join_session_keyring(const char *name)
        } else if (IS_ERR(keyring)) {
                ret = PTR_ERR(keyring);
                goto error2;
+       } else if (keyring == new->session_keyring) {
+               ret = 0;
+               goto error2;
        }
 
        /* we've got a keyring - now to install it */
@@ -865,8 +850,7 @@ void key_change_session_keyring(struct callback_head *twork)
 
        new->jit_keyring        = old->jit_keyring;
        new->thread_keyring     = key_get(old->thread_keyring);
-       new->tgcred->tgid       = old->tgcred->tgid;
-       new->tgcred->process_keyring = key_get(old->tgcred->process_keyring);
+       new->process_keyring    = key_get(old->process_keyring);
 
        security_transfer_creds(new, old);
 
index 66e21184b559e2f0097fe73c970a7da17e2b951d..4bd6bdb74193cba33b235b4b8b3934ddc576526c 100644 (file)
@@ -126,6 +126,7 @@ static int call_sbin_request_key(struct key_construction *cons,
 
        cred = get_current_cred();
        keyring = keyring_alloc(desc, cred->fsuid, cred->fsgid, cred,
+                               KEY_POS_ALL | KEY_USR_VIEW | KEY_USR_READ,
                                KEY_ALLOC_QUOTA_OVERRUN, NULL);
        put_cred(cred);
        if (IS_ERR(keyring)) {
@@ -150,12 +151,12 @@ static int call_sbin_request_key(struct key_construction *cons,
                cred->thread_keyring ? cred->thread_keyring->serial : 0);
 
        prkey = 0;
-       if (cred->tgcred->process_keyring)
-               prkey = cred->tgcred->process_keyring->serial;
+       if (cred->process_keyring)
+               prkey = cred->process_keyring->serial;
        sprintf(keyring_str[1], "%d", prkey);
 
        rcu_read_lock();
-       session = rcu_dereference(cred->tgcred->session_keyring);
+       session = rcu_dereference(cred->session_keyring);
        if (!session)
                session = cred->user->session_keyring;
        sskey = session->serial;
@@ -297,14 +298,14 @@ static void construct_get_dest_keyring(struct key **_dest_keyring)
                                break;
 
                case KEY_REQKEY_DEFL_PROCESS_KEYRING:
-                       dest_keyring = key_get(cred->tgcred->process_keyring);
+                       dest_keyring = key_get(cred->process_keyring);
                        if (dest_keyring)
                                break;
 
                case KEY_REQKEY_DEFL_SESSION_KEYRING:
                        rcu_read_lock();
                        dest_keyring = key_get(
-                               rcu_dereference(cred->tgcred->session_keyring));
+                               rcu_dereference(cred->session_keyring));
                        rcu_read_unlock();
 
                        if (dest_keyring)
@@ -347,6 +348,7 @@ static int construct_alloc_key(struct key_type *type,
        const struct cred *cred = current_cred();
        unsigned long prealloc;
        struct key *key;
+       key_perm_t perm;
        key_ref_t key_ref;
        int ret;
 
@@ -355,8 +357,15 @@ static int construct_alloc_key(struct key_type *type,
        *_key = NULL;
        mutex_lock(&user->cons_lock);
 
+       perm = KEY_POS_VIEW | KEY_POS_SEARCH | KEY_POS_LINK | KEY_POS_SETATTR;
+       perm |= KEY_USR_VIEW;
+       if (type->read)
+               perm |= KEY_POS_READ;
+       if (type == &key_type_keyring || type->update)
+               perm |= KEY_POS_WRITE;
+
        key = key_alloc(type, description, cred->fsuid, cred->fsgid, cred,
-                       KEY_POS_ALL, flags);
+                       perm, flags);
        if (IS_ERR(key))
                goto alloc_failed;
 
index 8dcd4ae10a5fba06086ed31998c78c77ec32469c..daa97f4ac9d13515909028bf1ffa6903d8aed0c7 100644 (file)
@@ -820,6 +820,16 @@ int security_kernel_module_request(char *kmod_name)
        return security_ops->kernel_module_request(kmod_name);
 }
 
+int security_kernel_module_from_file(struct file *file)
+{
+       int ret;
+
+       ret = security_ops->kernel_module_from_file(file);
+       if (ret)
+               return ret;
+       return ima_module_check(file);
+}
+
 int security_task_fix_setuid(struct cred *new, const struct cred *old,
                             int flags)
 {
index 91cdf9435feca986cf3be980412b7d21a9dddecd..af2a3fdb8828f312e8ccc84214b29675a569a00d 100644 (file)
@@ -190,7 +190,8 @@ struct snd_pcm_status32 {
        u32 avail_max;
        u32 overrange;
        s32 suspended_state;
-       unsigned char reserved[60];
+       struct compat_timespec audio_tstamp;
+       unsigned char reserved[60-sizeof(struct compat_timespec)];
 } __attribute__((packed));
 
 
@@ -205,17 +206,16 @@ static int snd_pcm_status_user_compat(struct snd_pcm_substream *substream,
                return err;
 
        if (put_user(status.state, &src->state) ||
-           put_user(status.trigger_tstamp.tv_sec, &src->trigger_tstamp.tv_sec) ||
-           put_user(status.trigger_tstamp.tv_nsec, &src->trigger_tstamp.tv_nsec) ||
-           put_user(status.tstamp.tv_sec, &src->tstamp.tv_sec) ||
-           put_user(status.tstamp.tv_nsec, &src->tstamp.tv_nsec) ||
+           compat_put_timespec(&status.trigger_tstamp, &src->trigger_tstamp) ||
+           compat_put_timespec(&status.tstamp, &src->tstamp) ||
            put_user(status.appl_ptr, &src->appl_ptr) ||
            put_user(status.hw_ptr, &src->hw_ptr) ||
            put_user(status.delay, &src->delay) ||
            put_user(status.avail, &src->avail) ||
            put_user(status.avail_max, &src->avail_max) ||
            put_user(status.overrange, &src->overrange) ||
-           put_user(status.suspended_state, &src->suspended_state))
+           put_user(status.suspended_state, &src->suspended_state) ||
+           compat_put_timespec(&status.audio_tstamp, &src->audio_tstamp))
                return -EFAULT;
 
        return err;
@@ -364,6 +364,7 @@ struct snd_pcm_mmap_status32 {
        u32 hw_ptr;
        struct compat_timespec tstamp;
        s32 suspended_state;
+       struct compat_timespec audio_tstamp;
 } __attribute__((packed));
 
 struct snd_pcm_mmap_control32 {
@@ -426,12 +427,14 @@ static int snd_pcm_ioctl_sync_ptr_compat(struct snd_pcm_substream *substream,
        sstatus.hw_ptr = status->hw_ptr % boundary;
        sstatus.tstamp = status->tstamp;
        sstatus.suspended_state = status->suspended_state;
+       sstatus.audio_tstamp = status->audio_tstamp;
        snd_pcm_stream_unlock_irq(substream);
        if (put_user(sstatus.state, &src->s.status.state) ||
            put_user(sstatus.hw_ptr, &src->s.status.hw_ptr) ||
-           put_user(sstatus.tstamp.tv_sec, &src->s.status.tstamp.tv_sec) ||
-           put_user(sstatus.tstamp.tv_nsec, &src->s.status.tstamp.tv_nsec) ||
+           compat_put_timespec(&sstatus.tstamp, &src->s.status.tstamp) ||
            put_user(sstatus.suspended_state, &src->s.status.suspended_state) ||
+           compat_put_timespec(&sstatus.audio_tstamp,
+                   &src->s.status.audio_tstamp) ||
            put_user(scontrol.appl_ptr, &src->c.control.appl_ptr) ||
            put_user(scontrol.avail_min, &src->c.control.avail_min))
                return -EFAULT;
index f42c10a43315afdbe3761e6ef86d4fe220387124..c4840ff75d00a97ebbe12e3820ab43dd743a785e 100644 (file)
@@ -316,6 +316,8 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
        unsigned long jdelta;
        unsigned long curr_jiffies;
        struct timespec curr_tstamp;
+       struct timespec audio_tstamp;
+       int crossed_boundary = 0;
 
        old_hw_ptr = runtime->status->hw_ptr;
 
@@ -327,9 +329,14 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
         */
        pos = substream->ops->pointer(substream);
        curr_jiffies = jiffies;
-       if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE)
+       if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) {
                snd_pcm_gettime(runtime, (struct timespec *)&curr_tstamp);
 
+               if ((runtime->hw.info & SNDRV_PCM_INFO_HAS_WALL_CLOCK) &&
+                       (substream->ops->wall_clock))
+                       substream->ops->wall_clock(substream, &audio_tstamp);
+       }
+
        if (pos == SNDRV_PCM_POS_XRUN) {
                xrun(substream);
                return -EPIPE;
@@ -360,8 +367,10 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
                        hdelta = curr_jiffies - runtime->hw_ptr_jiffies;
                        if (hdelta > runtime->hw_ptr_buffer_jiffies/2) {
                                hw_base += runtime->buffer_size;
-                               if (hw_base >= runtime->boundary)
+                               if (hw_base >= runtime->boundary) {
                                        hw_base = 0;
+                                       crossed_boundary++;
+                               }
                                new_hw_ptr = hw_base + pos;
                                goto __delta;
                        }
@@ -371,8 +380,10 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
        /* pointer crosses the end of the ring buffer */
        if (new_hw_ptr < old_hw_ptr) {
                hw_base += runtime->buffer_size;
-               if (hw_base >= runtime->boundary)
+               if (hw_base >= runtime->boundary) {
                        hw_base = 0;
+                       crossed_boundary++;
+               }
                new_hw_ptr = hw_base + pos;
        }
       __delta:
@@ -410,8 +421,10 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
                while (hdelta > xrun_threshold) {
                        delta += runtime->buffer_size;
                        hw_base += runtime->buffer_size;
-                       if (hw_base >= runtime->boundary)
+                       if (hw_base >= runtime->boundary) {
                                hw_base = 0;
+                               crossed_boundary++;
+                       }
                        new_hw_ptr = hw_base + pos;
                        hdelta -= runtime->hw_ptr_buffer_jiffies;
                }
@@ -456,8 +469,10 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
                /* the delta value is small or zero in most cases */
                while (delta > 0) {
                        new_hw_ptr += runtime->period_size;
-                       if (new_hw_ptr >= runtime->boundary)
+                       if (new_hw_ptr >= runtime->boundary) {
                                new_hw_ptr -= runtime->boundary;
+                               crossed_boundary--;
+                       }
                        delta--;
                }
                /* align hw_base to buffer_size */
@@ -507,9 +522,35 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
        runtime->hw_ptr_base = hw_base;
        runtime->status->hw_ptr = new_hw_ptr;
        runtime->hw_ptr_jiffies = curr_jiffies;
-       if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE)
+       if (crossed_boundary) {
+               snd_BUG_ON(crossed_boundary != 1);
+               runtime->hw_ptr_wrap += runtime->boundary;
+       }
+       if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) {
                runtime->status->tstamp = curr_tstamp;
 
+               if (!(runtime->hw.info & SNDRV_PCM_INFO_HAS_WALL_CLOCK)) {
+                       /*
+                        * no wall clock available, provide audio timestamp
+                        * derived from pointer position+delay
+                        */
+                       u64 audio_frames, audio_nsecs;
+
+                       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+                               audio_frames = runtime->hw_ptr_wrap
+                                       + runtime->status->hw_ptr
+                                       - runtime->delay;
+                       else
+                               audio_frames = runtime->hw_ptr_wrap
+                                       + runtime->status->hw_ptr
+                                       + runtime->delay;
+                       audio_nsecs = div_u64(audio_frames * 1000000000LL,
+                                       runtime->rate);
+                       audio_tstamp = ns_to_timespec(audio_nsecs);
+               }
+               runtime->status->audio_tstamp = audio_tstamp;
+       }
+
        return snd_pcm_update_state(substream, runtime);
 }
 
@@ -1661,8 +1702,10 @@ static int snd_pcm_lib_ioctl_reset(struct snd_pcm_substream *substream,
        if (snd_pcm_running(substream) &&
            snd_pcm_update_hw_ptr(substream) >= 0)
                runtime->status->hw_ptr %= runtime->buffer_size;
-       else
+       else {
                runtime->status->hw_ptr = 0;
+               runtime->hw_ptr_wrap = 0;
+       }
        snd_pcm_stream_unlock_irqrestore(substream, flags);
        return 0;
 }
index 5e12e5bacbba36cdf64c41a1d6e7e3d984902cf9..7c800012fff9771d89782e0960730f48bb65e70b 100644 (file)
@@ -594,6 +594,8 @@ int snd_pcm_status(struct snd_pcm_substream *substream,
                snd_pcm_update_hw_ptr(substream);
                if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) {
                        status->tstamp = runtime->status->tstamp;
+                       status->audio_tstamp =
+                               runtime->status->audio_tstamp;
                        goto _tstamp_end;
                }
        }
index fe5ae09ffccba585392e786f26942265e0d90650..5e4384137a76e956137cb336c9b2af181fc930b8 100644 (file)
@@ -35,7 +35,6 @@ config SND_PCSP
        tristate "PC-Speaker support (READ HELP!)"
        depends on PCSPKR_PLATFORM && X86 && HIGH_RES_TIMERS
        depends on INPUT
-       depends on EXPERIMENTAL
        select SND_PCM
        help
          If you don't have a sound card in your computer, you can include a
index 0fe6d64ff840f02cdb17df4c27721f8e9a953cb5..1904046686e2f915f939d333e56ba44e99a2eb3c 100644 (file)
@@ -120,7 +120,6 @@ struct loopback_pcm {
        unsigned int last_drift;
        unsigned long last_jiffies;
        struct timer_list timer;
-       spinlock_t timer_lock;
 };
 
 static struct platform_device *devices[SNDRV_CARDS];
@@ -166,12 +165,12 @@ static inline unsigned int get_rate_shift(struct loopback_pcm *dpcm)
        return get_setup(dpcm)->rate_shift;
 }
 
+/* call in cable->lock */
 static void loopback_timer_start(struct loopback_pcm *dpcm)
 {
        unsigned long tick;
        unsigned int rate_shift = get_rate_shift(dpcm);
 
-       spin_lock(&dpcm->timer_lock);
        if (rate_shift != dpcm->pcm_rate_shift) {
                dpcm->pcm_rate_shift = rate_shift;
                dpcm->period_size_frac = frac_pos(dpcm, dpcm->pcm_period_size);
@@ -184,15 +183,13 @@ static void loopback_timer_start(struct loopback_pcm *dpcm)
        tick = (tick + dpcm->pcm_bps - 1) / dpcm->pcm_bps;
        dpcm->timer.expires = jiffies + tick;
        add_timer(&dpcm->timer);
-       spin_unlock(&dpcm->timer_lock);
 }
 
+/* call in cable->lock */
 static inline void loopback_timer_stop(struct loopback_pcm *dpcm)
 {
-       spin_lock(&dpcm->timer_lock);
        del_timer(&dpcm->timer);
        dpcm->timer.expires = 0;
-       spin_unlock(&dpcm->timer_lock);
 }
 
 #define CABLE_VALID_PLAYBACK   (1 << SNDRV_PCM_STREAM_PLAYBACK)
@@ -274,8 +271,8 @@ static int loopback_trigger(struct snd_pcm_substream *substream, int cmd)
                spin_lock(&cable->lock);        
                cable->running |= stream;
                cable->pause &= ~stream;
-               spin_unlock(&cable->lock);
                loopback_timer_start(dpcm);
+               spin_unlock(&cable->lock);
                if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
                        loopback_active_notify(dpcm);
                break;
@@ -283,23 +280,23 @@ static int loopback_trigger(struct snd_pcm_substream *substream, int cmd)
                spin_lock(&cable->lock);        
                cable->running &= ~stream;
                cable->pause &= ~stream;
-               spin_unlock(&cable->lock);
                loopback_timer_stop(dpcm);
+               spin_unlock(&cable->lock);
                if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
                        loopback_active_notify(dpcm);
                break;
        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
                spin_lock(&cable->lock);        
                cable->pause |= stream;
-               spin_unlock(&cable->lock);
                loopback_timer_stop(dpcm);
+               spin_unlock(&cable->lock);
                break;
        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
                spin_lock(&cable->lock);
                dpcm->last_jiffies = jiffies;
                cable->pause &= ~stream;
-               spin_unlock(&cable->lock);
                loopback_timer_start(dpcm);
+               spin_unlock(&cable->lock);
                break;
        default:
                return -EINVAL;
@@ -477,6 +474,7 @@ static inline void bytepos_finish(struct loopback_pcm *dpcm,
        dpcm->buf_pos %= dpcm->pcm_buffer_size;
 }
 
+/* call in cable->lock */
 static unsigned int loopback_pos_update(struct loopback_cable *cable)
 {
        struct loopback_pcm *dpcm_play =
@@ -485,9 +483,7 @@ static unsigned int loopback_pos_update(struct loopback_cable *cable)
                        cable->streams[SNDRV_PCM_STREAM_CAPTURE];
        unsigned long delta_play = 0, delta_capt = 0;
        unsigned int running, count1, count2;
-       unsigned long flags;
 
-       spin_lock_irqsave(&cable->lock, flags);
        running = cable->running ^ cable->pause;
        if (running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) {
                delta_play = jiffies - dpcm_play->last_jiffies;
@@ -529,32 +525,39 @@ static unsigned int loopback_pos_update(struct loopback_cable *cable)
        bytepos_finish(dpcm_play, count1);
        bytepos_finish(dpcm_capt, count1);
  unlock:
-       spin_unlock_irqrestore(&cable->lock, flags);
        return running;
 }
 
 static void loopback_timer_function(unsigned long data)
 {
        struct loopback_pcm *dpcm = (struct loopback_pcm *)data;
-       unsigned int running;
+       unsigned long flags;
 
-       running = loopback_pos_update(dpcm->cable);
-       if (running & (1 << dpcm->substream->stream)) {
+       spin_lock_irqsave(&dpcm->cable->lock, flags);
+       if (loopback_pos_update(dpcm->cable) & (1 << dpcm->substream->stream)) {
                loopback_timer_start(dpcm);
                if (dpcm->period_update_pending) {
                        dpcm->period_update_pending = 0;
+                       spin_unlock_irqrestore(&dpcm->cable->lock, flags);
+                       /* need to unlock before calling below */
                        snd_pcm_period_elapsed(dpcm->substream);
+                       return;
                }
        }
+       spin_unlock_irqrestore(&dpcm->cable->lock, flags);
 }
 
 static snd_pcm_uframes_t loopback_pointer(struct snd_pcm_substream *substream)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct loopback_pcm *dpcm = runtime->private_data;
+       snd_pcm_uframes_t pos;
 
+       spin_lock(&dpcm->cable->lock);
        loopback_pos_update(dpcm->cable);
-       return bytes_to_frames(runtime, dpcm->buf_pos);
+       pos = dpcm->buf_pos;
+       spin_unlock(&dpcm->cable->lock);
+       return bytes_to_frames(runtime, pos);
 }
 
 static struct snd_pcm_hardware loopback_pcm_hardware =
@@ -672,7 +675,6 @@ static int loopback_open(struct snd_pcm_substream *substream)
        dpcm->substream = substream;
        setup_timer(&dpcm->timer, loopback_timer_function,
                    (unsigned long)dpcm);
-       spin_lock_init(&dpcm->timer_lock);
 
        cable = loopback->cables[substream->number][dev];
        if (!cable) {
index 54bb6644a598a8177e3fbec4220df2966abd6131..4f522cf4845508cbc366fe8b4b0b16d2226f6de3 100644 (file)
@@ -134,6 +134,9 @@ struct snd_dummy {
        spinlock_t mixer_lock;
        int mixer_volume[MIXER_ADDR_LAST+1][2];
        int capture_source[MIXER_ADDR_LAST+1][2];
+       int iobox;
+       struct snd_kcontrol *cd_volume_ctl;
+       struct snd_kcontrol *cd_switch_ctl;
        const struct dummy_timer_ops *timer_ops;
 };
 
@@ -817,6 +820,57 @@ static int snd_dummy_capsrc_put(struct snd_kcontrol *kcontrol, struct snd_ctl_el
        return change;
 }
 
+static int snd_dummy_iobox_info(struct snd_kcontrol *kcontrol,
+                               struct snd_ctl_elem_info *info)
+{
+       const char *const names[] = { "None", "CD Player" };
+
+       return snd_ctl_enum_info(info, 1, 2, names);
+}
+
+static int snd_dummy_iobox_get(struct snd_kcontrol *kcontrol,
+                              struct snd_ctl_elem_value *value)
+{
+       struct snd_dummy *dummy = snd_kcontrol_chip(kcontrol);
+
+       value->value.enumerated.item[0] = dummy->iobox;
+       return 0;
+}
+
+static int snd_dummy_iobox_put(struct snd_kcontrol *kcontrol,
+                              struct snd_ctl_elem_value *value)
+{
+       struct snd_dummy *dummy = snd_kcontrol_chip(kcontrol);
+       int changed;
+
+       if (value->value.enumerated.item[0] > 1)
+               return -EINVAL;
+
+       changed = value->value.enumerated.item[0] != dummy->iobox;
+       if (changed) {
+               dummy->iobox = value->value.enumerated.item[0];
+
+               if (dummy->iobox) {
+                       dummy->cd_volume_ctl->vd[0].access &=
+                               ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
+                       dummy->cd_switch_ctl->vd[0].access &=
+                               ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
+               } else {
+                       dummy->cd_volume_ctl->vd[0].access |=
+                               SNDRV_CTL_ELEM_ACCESS_INACTIVE;
+                       dummy->cd_switch_ctl->vd[0].access |=
+                               SNDRV_CTL_ELEM_ACCESS_INACTIVE;
+               }
+
+               snd_ctl_notify(dummy->card, SNDRV_CTL_EVENT_MASK_INFO,
+                              &dummy->cd_volume_ctl->id);
+               snd_ctl_notify(dummy->card, SNDRV_CTL_EVENT_MASK_INFO,
+                              &dummy->cd_switch_ctl->id);
+       }
+
+       return changed;
+}
+
 static struct snd_kcontrol_new snd_dummy_controls[] = {
 DUMMY_VOLUME("Master Volume", 0, MIXER_ADDR_MASTER),
 DUMMY_CAPSRC("Master Capture Switch", 0, MIXER_ADDR_MASTER),
@@ -827,22 +881,37 @@ DUMMY_CAPSRC("Line Capture Switch", 0, MIXER_ADDR_LINE),
 DUMMY_VOLUME("Mic Volume", 0, MIXER_ADDR_MIC),
 DUMMY_CAPSRC("Mic Capture Switch", 0, MIXER_ADDR_MIC),
 DUMMY_VOLUME("CD Volume", 0, MIXER_ADDR_CD),
-DUMMY_CAPSRC("CD Capture Switch", 0, MIXER_ADDR_CD)
+DUMMY_CAPSRC("CD Capture Switch", 0, MIXER_ADDR_CD),
+{
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+       .name  = "External I/O Box",
+       .info  = snd_dummy_iobox_info,
+       .get   = snd_dummy_iobox_get,
+       .put   = snd_dummy_iobox_put,
+},
 };
 
 static int __devinit snd_card_dummy_new_mixer(struct snd_dummy *dummy)
 {
        struct snd_card *card = dummy->card;
+       struct snd_kcontrol *kcontrol;
        unsigned int idx;
        int err;
 
        spin_lock_init(&dummy->mixer_lock);
        strcpy(card->mixername, "Dummy Mixer");
+       dummy->iobox = 1;
 
        for (idx = 0; idx < ARRAY_SIZE(snd_dummy_controls); idx++) {
-               err = snd_ctl_add(card, snd_ctl_new1(&snd_dummy_controls[idx], dummy));
+               kcontrol = snd_ctl_new1(&snd_dummy_controls[idx], dummy);
+               err = snd_ctl_add(card, kcontrol);
                if (err < 0)
                        return err;
+               if (!strcmp(kcontrol->id.name, "CD Volume"))
+                       dummy->cd_volume_ctl = kcontrol;
+               else if (!strcmp(kcontrol->id.name, "CD Capture Switch"))
+                       dummy->cd_switch_ctl = kcontrol;
+
        }
        return 0;
 }
index a38d9643e9d8319dc38c4e3379d83d13a27e250c..affa13480659e4b302606b182ae5e4dc6d72de6f 100644 (file)
@@ -425,7 +425,7 @@ config SND_WAVEFRONT
 
 config SND_MSND_PINNACLE
        tristate "Turtle Beach MultiSound Pinnacle/Fiji driver"
-       depends on X86 && EXPERIMENTAL
+       depends on X86
        select FW_LOADER
        select SND_MPU401_UART
        select SND_PCM
@@ -438,7 +438,7 @@ config SND_MSND_PINNACLE
 
 config SND_MSND_CLASSIC
        tristate "Support for Turtle Beach MultiSound Classic, Tahiti, Monterey"
-       depends on X86 && EXPERIMENTAL
+       depends on X86
        select FW_LOADER
        select SND_MPU401_UART
        select SND_PCM
index 3d1afb612b3548ade1db68d1b60af8f3e7e6ce4b..4a7ff4e8985ba2fe3b71ac7b57a191e694063ae2 100644 (file)
@@ -1286,7 +1286,6 @@ static int __devinit snd_miro_probe(struct snd_card *card)
 
        error = snd_card_miro_aci_detect(card, miro);
        if (error < 0) {
-               snd_card_free(card);
                snd_printk(KERN_ERR "unable to detect aci chip\n");
                return -ENODEV;
        }
index f99fa251228623a161c6bcaed0d2622f5bf132bf..6150eb1582ae2247c9efdcc9bec37b8a19389954 100644 (file)
@@ -630,7 +630,7 @@ config SND_ICE1724
          AudioTrak Prodigy 192, 7.1 (HIFI/LT/XT), HD2; Hercules
          Fortissimo IV; ESI Juli@; Pontis MS300; EGO-SYS WaveTerminal
          192M; Albatron K8X800 Pro II; Chaintech ZNF3-150/250, 9CJS,
-         AV-710; Shuttle SN25P.
+         AV-710; Shuttle SN25P; Philips PSC724 Ultimate Edge.
 
          To compile this driver as a module, choose M here: the module
          will be called snd-ice1724.
index 00f157a2cf6411d8b1ad1b1ffef32f566d5e02b8..5af3cb6b0c18d36345aadfefee3d509404bbba80 100644 (file)
@@ -394,6 +394,8 @@ static int snd_als300_playback_open(struct snd_pcm_substream *substream)
        struct snd_als300_substream_data *data = kzalloc(sizeof(*data),
                                                                GFP_KERNEL);
 
+       if (!data)
+               return -ENOMEM;
        snd_als300_dbgcallenter();
        chip->playback_substream = substream;
        runtime->hw = snd_als300_playback_hw;
@@ -425,6 +427,8 @@ static int snd_als300_capture_open(struct snd_pcm_substream *substream)
        struct snd_als300_substream_data *data = kzalloc(sizeof(*data),
                                                                GFP_KERNEL);
 
+       if (!data)
+               return -ENOMEM;
        snd_als300_dbgcallenter();
        chip->capture_substream = substream;
        runtime->hw = snd_als300_capture_hw;
index 7105c3de1bca98ff5a975d15d2ba35fc19876d98..6eeb8897624b3b25a3e341e765256a4c8964f973 100644 (file)
@@ -37,8 +37,8 @@ config SND_HDA_HWDEP
          with codecs for debugging purposes.
 
 config SND_HDA_RECONFIG
-       bool "Allow dynamic codec reconfiguration (EXPERIMENTAL)"
-       depends on SND_HDA_HWDEP && EXPERIMENTAL
+       bool "Allow dynamic codec reconfiguration"
+       depends on SND_HDA_HWDEP
        help
          Say Y here to enable the HD-audio codec re-configuration feature.
          This adds the sysfs interfaces to allow user to clear the whole
@@ -72,7 +72,6 @@ config SND_HDA_INPUT_JACK
 
 config SND_HDA_PATCH_LOADER
        bool "Support initialization patch loading for HD-audio"
-       depends on EXPERIMENTAL
        select FW_LOADER
        select SND_HDA_HWDEP
        select SND_HDA_RECONFIG
index 70d4848b5cd0ad25ce272877f9c759ed010dfc58..2da78751951305957bc5e3f761248ab1906abf87 100644 (file)
@@ -1135,6 +1135,19 @@ static void restore_shutup_pins(struct hda_codec *codec)
 }
 #endif
 
+static void hda_jackpoll_work(struct work_struct *work)
+{
+       struct hda_codec *codec =
+               container_of(work, struct hda_codec, jackpoll_work.work);
+       if (!codec->jackpoll_interval)
+               return;
+
+       snd_hda_jack_set_dirty_all(codec);
+       snd_hda_jack_poll_all(codec);
+       queue_delayed_work(codec->bus->workq, &codec->jackpoll_work,
+                          codec->jackpoll_interval);
+}
+
 static void init_hda_cache(struct hda_cache_rec *cache,
                           unsigned int record_size);
 static void free_hda_cache(struct hda_cache_rec *cache);
@@ -1190,6 +1203,7 @@ static void snd_hda_codec_free(struct hda_codec *codec)
 {
        if (!codec)
                return;
+       cancel_delayed_work_sync(&codec->jackpoll_work);
        snd_hda_jack_tbl_clear(codec);
        restore_init_pincfgs(codec);
 #ifdef CONFIG_PM
@@ -1273,6 +1287,7 @@ int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus,
        snd_array_init(&codec->cvt_setups, sizeof(struct hda_cvt_setup), 8);
        snd_array_init(&codec->conn_lists, sizeof(hda_nid_t), 64);
        snd_array_init(&codec->spdif_out, sizeof(struct hda_spdif_out), 16);
+       INIT_DELAYED_WORK(&codec->jackpoll_work, hda_jackpoll_work);
 
 #ifdef CONFIG_PM
        spin_lock_init(&codec->power_lock);
@@ -2151,12 +2166,12 @@ EXPORT_SYMBOL_HDA(snd_hda_set_vmaster_tlv);
 
 /* find a mixer control element with the given name */
 static struct snd_kcontrol *
-_snd_hda_find_mixer_ctl(struct hda_codec *codec,
-                       const char *name, int idx)
+find_mixer_ctl(struct hda_codec *codec, const char *name, int dev, int idx)
 {
        struct snd_ctl_elem_id id;
        memset(&id, 0, sizeof(id));
        id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+       id.device = dev;
        id.index = idx;
        if (snd_BUG_ON(strlen(name) >= sizeof(id.name)))
                return NULL;
@@ -2174,15 +2189,16 @@ _snd_hda_find_mixer_ctl(struct hda_codec *codec,
 struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
                                            const char *name)
 {
-       return _snd_hda_find_mixer_ctl(codec, name, 0);
+       return find_mixer_ctl(codec, name, 0, 0);
 }
 EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl);
 
-static int find_empty_mixer_ctl_idx(struct hda_codec *codec, const char *name)
+static int find_empty_mixer_ctl_idx(struct hda_codec *codec, const char *name,
+                                   int dev)
 {
        int idx;
        for (idx = 0; idx < 16; idx++) { /* 16 ctlrs should be large enough */
-               if (!_snd_hda_find_mixer_ctl(codec, name, idx))
+               if (!find_mixer_ctl(codec, name, dev, idx))
                        return idx;
        }
        return -EBUSY;
@@ -2349,7 +2365,7 @@ int snd_hda_codec_reset(struct hda_codec *codec)
                return -EBUSY;
 
        /* OK, let it free */
-
+       cancel_delayed_work_sync(&codec->jackpoll_work);
 #ifdef CONFIG_PM
        cancel_delayed_work_sync(&codec->power_work);
        codec->power_on = 0;
@@ -3133,26 +3149,48 @@ static struct snd_kcontrol_new dig_mixes[] = {
 };
 
 /**
- * snd_hda_create_spdif_out_ctls - create Output SPDIF-related controls
+ * snd_hda_create_dig_out_ctls - create Output SPDIF-related controls
  * @codec: the HDA codec
- * @nid: audio out widget NID
- *
- * Creates controls related with the SPDIF output.
- * Called from each patch supporting the SPDIF out.
+ * @associated_nid: NID that new ctls associated with
+ * @cvt_nid: converter NID
+ * @type: HDA_PCM_TYPE_*
+ * Creates controls related with the digital output.
+ * Called from each patch supporting the digital out.
  *
  * Returns 0 if successful, or a negative error code.
  */
-int snd_hda_create_spdif_out_ctls(struct hda_codec *codec,
-                                 hda_nid_t associated_nid,
-                                 hda_nid_t cvt_nid)
+int snd_hda_create_dig_out_ctls(struct hda_codec *codec,
+                               hda_nid_t associated_nid,
+                               hda_nid_t cvt_nid,
+                               int type)
 {
        int err;
        struct snd_kcontrol *kctl;
        struct snd_kcontrol_new *dig_mix;
-       int idx;
+       int idx, dev = 0;
+       const int spdif_pcm_dev = 1;
        struct hda_spdif_out *spdif;
 
-       idx = find_empty_mixer_ctl_idx(codec, "IEC958 Playback Switch");
+       if (codec->primary_dig_out_type == HDA_PCM_TYPE_HDMI &&
+           type == HDA_PCM_TYPE_SPDIF) {
+               dev = spdif_pcm_dev;
+       } else if (codec->primary_dig_out_type == HDA_PCM_TYPE_SPDIF &&
+                  type == HDA_PCM_TYPE_HDMI) {
+               for (idx = 0; idx < codec->spdif_out.used; idx++) {
+                       spdif = snd_array_elem(&codec->spdif_out, idx);
+                       for (dig_mix = dig_mixes; dig_mix->name; dig_mix++) {
+                               kctl = find_mixer_ctl(codec, dig_mix->name, 0, idx);
+                               if (!kctl)
+                                       break;
+                               kctl->id.device = spdif_pcm_dev;
+                       }
+               }
+               codec->primary_dig_out_type = HDA_PCM_TYPE_HDMI;
+       }
+       if (!codec->primary_dig_out_type)
+               codec->primary_dig_out_type = type;
+
+       idx = find_empty_mixer_ctl_idx(codec, "IEC958 Playback Switch", dev);
        if (idx < 0) {
                printk(KERN_ERR "hda_codec: too many IEC958 outputs\n");
                return -EBUSY;
@@ -3162,6 +3200,7 @@ int snd_hda_create_spdif_out_ctls(struct hda_codec *codec,
                kctl = snd_ctl_new1(dig_mix, codec);
                if (!kctl)
                        return -ENOMEM;
+               kctl->id.device = dev;
                kctl->id.index = idx;
                kctl->private_value = codec->spdif_out.used - 1;
                err = snd_hda_ctl_add(codec, associated_nid, kctl);
@@ -3174,7 +3213,7 @@ int snd_hda_create_spdif_out_ctls(struct hda_codec *codec,
        spdif->status = convert_to_spdif_status(spdif->ctls);
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_create_spdif_out_ctls);
+EXPORT_SYMBOL_HDA(snd_hda_create_dig_out_ctls);
 
 /* get the hda_spdif_out entry from the given NID
  * call within spdif_mutex lock
@@ -3349,7 +3388,7 @@ int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid)
        struct snd_kcontrol_new *dig_mix;
        int idx;
 
-       idx = find_empty_mixer_ctl_idx(codec, "IEC958 Capture Switch");
+       idx = find_empty_mixer_ctl_idx(codec, "IEC958 Capture Switch", 0);
        if (idx < 0) {
                printk(KERN_ERR "hda_codec: too many IEC958 inputs\n");
                return -EBUSY;
@@ -3646,7 +3685,6 @@ static void hda_call_codec_resume(struct hda_codec *codec)
        restore_pincfgs(codec); /* restore all current pin configs */
        restore_shutup_pins(codec);
        hda_exec_init_verbs(codec);
-       snd_hda_jack_set_dirty_all(codec);
        if (codec->patch_ops.resume)
                codec->patch_ops.resume(codec);
        else {
@@ -3655,7 +3693,13 @@ static void hda_call_codec_resume(struct hda_codec *codec)
                snd_hda_codec_resume_amp(codec);
                snd_hda_codec_resume_cache(codec);
        }
-       snd_hda_jack_report_sync(codec);
+
+       if (codec->jackpoll_interval)
+               hda_jackpoll_work(&codec->jackpoll_work.work);
+       else {
+               snd_hda_jack_set_dirty_all(codec);
+               snd_hda_jack_report_sync(codec);
+       }
        snd_hda_power_down(codec); /* flag down before returning */
 }
 #endif /* CONFIG_PM */
@@ -3737,7 +3781,10 @@ int snd_hda_codec_build_controls(struct hda_codec *codec)
        if (err < 0)
                return err;
 
-       snd_hda_jack_report_sync(codec); /* call at the last init point */
+       if (codec->jackpoll_interval)
+               hda_jackpoll_work(&codec->jackpoll_work.work);
+       else
+               snd_hda_jack_report_sync(codec); /* call at the last init point */
        return 0;
 }
 
@@ -4449,7 +4496,7 @@ int snd_hda_add_new_ctls(struct hda_codec *codec,
                                addr = codec->addr;
                        else if (!idx && !knew->index) {
                                idx = find_empty_mixer_ctl_idx(codec,
-                                                              knew->name);
+                                                              knew->name, 0);
                                if (idx <= 0)
                                        return err;
                        } else
@@ -5128,6 +5175,7 @@ int snd_hda_suspend(struct hda_bus *bus)
        struct hda_codec *codec;
 
        list_for_each_entry(codec, &bus->codec_list, list) {
+               cancel_delayed_work_sync(&codec->jackpoll_work);
                if (hda_codec_is_power_on(codec))
                        hda_call_codec_suspend(codec, false);
        }
index 507fe8a917b69b09993193ef460f4fbc3f3af31a..62d4229c7b95c80c3e655615fa5a8c864f60ebeb 100644 (file)
@@ -836,6 +836,7 @@ struct hda_codec {
        struct mutex hash_mutex;
        struct snd_array spdif_out;
        unsigned int spdif_in_enable;   /* SPDIF input enable? */
+       int primary_dig_out_type;       /* primary digital out PCM type */
        const hda_nid_t *slave_dig_outs; /* optional digital out slave widgets */
        struct snd_array init_pins;     /* initial (BIOS) pin configurations */
        struct snd_array driver_pins;   /* pin configs set by codec parser */
@@ -884,6 +885,8 @@ struct hda_codec {
 
        /* jack detection */
        struct snd_array jacktbl;
+       unsigned long jackpoll_interval; /* In jiffies. Zero means no poll, rely on unsol events */
+       struct delayed_work jackpoll_work;
 
 #ifdef CONFIG_SND_HDA_INPUT_JACK
        /* jack detection */
index 72b085ae7d469e14559267558e515a578e3142dd..9cdfab945500270d9647fb404915cdd5f81839c5 100644 (file)
@@ -47,6 +47,9 @@
 #include <linux/reboot.h>
 #include <linux/io.h>
 #include <linux/pm_runtime.h>
+#include <linux/clocksource.h>
+#include <linux/time.h>
+
 #ifdef CONFIG_X86
 /* for snoop control */
 #include <asm/pgtable.h>
@@ -68,6 +71,7 @@ static int position_fix[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = -1};
 static int bdl_pos_adj[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = -1};
 static int probe_mask[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = -1};
 static int probe_only[SNDRV_CARDS];
+static int jackpoll_ms[SNDRV_CARDS];
 static bool single_cmd;
 static int enable_msi = -1;
 #ifdef CONFIG_SND_HDA_PATCH_LOADER
@@ -95,6 +99,8 @@ module_param_array(probe_mask, int, NULL, 0444);
 MODULE_PARM_DESC(probe_mask, "Bitmask to probe codecs (default = -1).");
 module_param_array(probe_only, int, NULL, 0444);
 MODULE_PARM_DESC(probe_only, "Only probing and no codec initialization.");
+module_param_array(jackpoll_ms, int, NULL, 0444);
+MODULE_PARM_DESC(jackpoll_ms, "Ms between polling for jack events (default = 0, using unsol events only)");
 module_param(single_cmd, bool, 0444);
 MODULE_PARM_DESC(single_cmd, "Use single command to communicate with codecs "
                 "(for debugging only).");
@@ -416,6 +422,9 @@ struct azx_dev {
        unsigned int insufficient :1;
        unsigned int wc_marked:1;
        unsigned int no_period_wakeup:1;
+
+       struct timecounter  azx_tc;
+       struct cyclecounter azx_cc;
 };
 
 /* CORB/RIRB */
@@ -829,8 +838,9 @@ static void azx_update_rirb(struct azx *chip)
                        smp_wmb();
                        chip->rirb.cmds[addr]--;
                } else
-                       snd_printk(KERN_ERR SFX "spurious response %#x:%#x, "
+                       snd_printk(KERN_ERR SFX "%s: spurious response %#x:%#x, "
                                   "last cmd=%#08x\n",
+                                  pci_name(chip->pci),
                                   res, res_ex,
                                   chip->last_cmd[addr]);
        }
@@ -1582,6 +1592,22 @@ static void azx_bus_reset(struct hda_bus *bus)
        bus->in_reset = 0;
 }
 
+static int get_jackpoll_interval(struct azx *chip)
+{
+       int i = jackpoll_ms[chip->dev_index];
+       unsigned int j;
+       if (i == 0)
+               return 0;
+       if (i < 50 || i > 60000)
+               j = 0;
+       else
+               j = msecs_to_jiffies(i);
+       if (j == 0)
+               snd_printk(KERN_WARNING SFX
+                          "jackpoll_ms value out of range: %d\n", i);
+       return j;
+}
+
 /*
  * Codec initialization
  */
@@ -1666,6 +1692,7 @@ static int DELAYED_INIT_MARK azx_codec_create(struct azx *chip, const char *mode
                        err = snd_hda_codec_new(chip->bus, c, &codec);
                        if (err < 0)
                                continue;
+                       codec->jackpoll_interval = get_jackpoll_interval(chip);
                        codec->beep_mode = chip->beep_mode;
                        codecs++;
                }
@@ -1728,6 +1755,64 @@ static inline void azx_release_device(struct azx_dev *azx_dev)
        azx_dev->opened = 0;
 }
 
+static cycle_t azx_cc_read(const struct cyclecounter *cc)
+{
+       struct azx_dev *azx_dev = container_of(cc, struct azx_dev, azx_cc);
+       struct snd_pcm_substream *substream = azx_dev->substream;
+       struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
+       struct azx *chip = apcm->chip;
+
+       return azx_readl(chip, WALLCLK);
+}
+
+static void azx_timecounter_init(struct snd_pcm_substream *substream,
+                               bool force, cycle_t last)
+{
+       struct azx_dev *azx_dev = get_azx_dev(substream);
+       struct timecounter *tc = &azx_dev->azx_tc;
+       struct cyclecounter *cc = &azx_dev->azx_cc;
+       u64 nsec;
+
+       cc->read = azx_cc_read;
+       cc->mask = CLOCKSOURCE_MASK(32);
+
+       /*
+        * Converting from 24 MHz to ns means applying a 125/3 factor.
+        * To avoid any saturation issues in intermediate operations,
+        * the 125 factor is applied first. The division is applied
+        * last after reading the timecounter value.
+        * Applying the 1/3 factor as part of the multiplication
+        * requires at least 20 bits for a decent precision, however
+        * overflows occur after about 4 hours or less, not a option.
+        */
+
+       cc->mult = 125; /* saturation after 195 years */
+       cc->shift = 0;
+
+       nsec = 0; /* audio time is elapsed time since trigger */
+       timecounter_init(tc, cc, nsec);
+       if (force)
+               /*
+                * force timecounter to use predefined value,
+                * used for synchronized starts
+                */
+               tc->cycle_last = last;
+}
+
+static int azx_get_wallclock_tstamp(struct snd_pcm_substream *substream,
+                               struct timespec *ts)
+{
+       struct azx_dev *azx_dev = get_azx_dev(substream);
+       u64 nsec;
+
+       nsec = timecounter_read(&azx_dev->azx_tc);
+       nsec = div_u64(nsec, 3); /* can be optimized */
+
+       *ts = ns_to_timespec(nsec);
+
+       return 0;
+}
+
 static struct snd_pcm_hardware azx_pcm_hw = {
        .info =                 (SNDRV_PCM_INFO_MMAP |
                                 SNDRV_PCM_INFO_INTERLEAVED |
@@ -1737,6 +1822,7 @@ static struct snd_pcm_hardware azx_pcm_hw = {
                                 /* SNDRV_PCM_INFO_RESUME |*/
                                 SNDRV_PCM_INFO_PAUSE |
                                 SNDRV_PCM_INFO_SYNC_START |
+                                SNDRV_PCM_INFO_HAS_WALL_CLOCK |
                                 SNDRV_PCM_INFO_NO_PERIOD_WAKEUP),
        .formats =              SNDRV_PCM_FMTBIT_S16_LE,
        .rates =                SNDRV_PCM_RATE_48000,
@@ -1776,6 +1862,12 @@ static int azx_pcm_open(struct snd_pcm_substream *substream)
        runtime->hw.rates = hinfo->rates;
        snd_pcm_limit_hw_rates(runtime);
        snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
+
+       /* avoid wrap-around with wall-clock */
+       snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_TIME,
+                               20,
+                               178000000);
+
        if (chip->align_buffer_size)
                /* constrain buffer sizes to be multiple of 128
                   bytes. This is more efficient in terms of memory
@@ -1815,6 +1907,12 @@ static int azx_pcm_open(struct snd_pcm_substream *substream)
                mutex_unlock(&chip->open_mutex);
                return -EINVAL;
        }
+
+       /* disable WALLCLOCK timestamps for capture streams
+          until we figure out how to handle digital inputs */
+       if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+               runtime->hw.info &= ~SNDRV_PCM_INFO_HAS_WALL_CLOCK;
+
        spin_lock_irqsave(&chip->reg_lock, flags);
        azx_dev->substream = substream;
        azx_dev->running = 0;
@@ -2051,6 +2149,22 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
                        azx_readl(chip, OLD_SSYNC) & ~sbits);
        else
                azx_writel(chip, SSYNC, azx_readl(chip, SSYNC) & ~sbits);
+       if (start) {
+               azx_timecounter_init(substream, 0, 0);
+               if (nsync > 1) {
+                       cycle_t cycle_last;
+
+                       /* same start cycle for master and group */
+                       azx_dev = get_azx_dev(substream);
+                       cycle_last = azx_dev->azx_tc.cycle_last;
+
+                       snd_pcm_group_for_each_entry(s, substream) {
+                               if (s->pcm->card != substream->pcm->card)
+                                       continue;
+                               azx_timecounter_init(s, 1, cycle_last);
+                       }
+               }
+       }
        spin_unlock(&chip->reg_lock);
        return 0;
 }
@@ -2193,13 +2307,11 @@ static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev)
 {
        u32 wallclk;
        unsigned int pos;
-       int stream;
 
        wallclk = azx_readl(chip, WALLCLK) - azx_dev->start_wallclk;
        if (wallclk < (azx_dev->period_wallclk * 2) / 3)
                return -1;      /* bogus (too early) interrupt */
 
-       stream = azx_dev->substream->stream;
        pos = azx_get_position(chip, azx_dev, true);
 
        if (WARN_ONCE(!azx_dev->period_bytes,
@@ -2290,6 +2402,7 @@ static struct snd_pcm_ops azx_pcm_ops = {
        .prepare = azx_pcm_prepare,
        .trigger = azx_pcm_trigger,
        .pointer = azx_pcm_pointer,
+       .wall_clock =  azx_get_wallclock_tstamp,
        .mmap = azx_pcm_mmap,
        .page = snd_pcm_sgbuf_ops_page,
 };
index 5c690cb873d469af2b419476fb790e893c2433a2..5bdbadaa20fec32cd5b8e7242964f6a536c3af0e 100644 (file)
@@ -206,6 +206,8 @@ int snd_hda_jack_detect_enable_callback(struct hda_codec *codec, hda_nid_t nid,
                jack->action = action;
        if (cb)
                jack->callback = cb;
+       if (codec->jackpoll_interval > 0)
+               return 0; /* No unsol if we're polling instead */
        return snd_hda_codec_write_cache(codec, nid, 0,
                                         AC_VERB_SET_UNSOLICITED_ENABLE,
                                         AC_USRSP_EN | jack->tag);
@@ -439,3 +441,25 @@ void snd_hda_jack_unsol_event(struct hda_codec *codec, unsigned int res)
 }
 EXPORT_SYMBOL_HDA(snd_hda_jack_unsol_event);
 
+void snd_hda_jack_poll_all(struct hda_codec *codec)
+{
+       struct hda_jack_tbl *jack = codec->jacktbl.list;
+       int i, changes = 0;
+
+       for (i = 0; i < codec->jacktbl.used; i++, jack++) {
+               unsigned int old_sense;
+               if (!jack->nid || !jack->jack_dirty || jack->phantom_jack)
+                       continue;
+               old_sense = get_jack_plug_state(jack->pin_sense);
+               jack_detect_update(codec, jack);
+               if (old_sense == get_jack_plug_state(jack->pin_sense))
+                       continue;
+               changes = 1;
+               if (jack->callback)
+                       jack->callback(codec, jack);
+       }
+       if (changes)
+               snd_hda_jack_report_sync(codec);
+}
+EXPORT_SYMBOL_HDA(snd_hda_jack_poll_all);
+
index af8dd4724da544c85a2b4df431262952dbb39c4a..4487785adf345870fff8f71deb8fdb14b64fd523 100644 (file)
@@ -84,4 +84,6 @@ void snd_hda_jack_report_sync(struct hda_codec *codec);
 
 void snd_hda_jack_unsol_event(struct hda_codec *codec, unsigned int res);
 
+void snd_hda_jack_poll_all(struct hda_codec *codec);
+
 #endif /* __SOUND_HDA_JACK_H */
index 09dbdc37f781592b45c8e8c03a80b0f133195996..8c43198b7f560ccc47d33ffe3755aa77f2f8e95c 100644 (file)
@@ -240,9 +240,11 @@ int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag,
 /*
  * SPDIF I/O
  */
-int snd_hda_create_spdif_out_ctls(struct hda_codec *codec,
-                                 hda_nid_t associated_nid,
-                                 hda_nid_t cvt_nid);
+int snd_hda_create_dig_out_ctls(struct hda_codec *codec,
+                               hda_nid_t associated_nid,
+                               hda_nid_t cvt_nid, int type);
+#define snd_hda_create_spdif_out_ctls(codec, anid, cnid) \
+       snd_hda_create_dig_out_ctls(codec, anid, cnid, HDA_PCM_TYPE_SPDIF)
 int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid);
 
 /*
index 61a71131711c734556249b17fc61fc51f1218c1a..a7f8790ae885cc71a595af5042f8b2f3e047197a 100644 (file)
@@ -873,8 +873,9 @@ static int build_digital_output(struct hda_codec *codec)
        if (!spec->multiout.dig_out_nid)
                return 0;
 
-       err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid,
-                                           spec->multiout.dig_out_nid);
+       err = snd_hda_create_dig_out_ctls(codec, spec->multiout.dig_out_nid,
+                                         spec->multiout.dig_out_nid,
+                                         spec->pcm_rec[1].pcm_type);
        if (err < 0)
                return err;
        err = snd_hda_create_spdif_share_sw(codec, &spec->multiout);
index 03b1dc317ff0341122d48a0535e41963b2834157..252d4197f2216bfed7211f6556a52f201af2c7ce 100644 (file)
@@ -4405,7 +4405,10 @@ static const struct hda_codec_ops cx_auto_patch_ops = {
 enum {
        CXT_PINCFG_LENOVO_X200,
        CXT_PINCFG_LENOVO_TP410,
+       CXT_PINCFG_LEMOTE_A1004,
+       CXT_PINCFG_LEMOTE_A1205,
        CXT_FIXUP_STEREO_DMIC,
+       CXT_FIXUP_INC_MIC_BOOST,
 };
 
 static void cxt_fixup_stereo_dmic(struct hda_codec *codec,
@@ -4415,6 +4418,19 @@ static void cxt_fixup_stereo_dmic(struct hda_codec *codec,
        spec->fixup_stereo_dmic = 1;
 }
 
+static void cxt5066_increase_mic_boost(struct hda_codec *codec,
+                                  const struct hda_fixup *fix, int action)
+{
+       if (action != HDA_FIXUP_ACT_PRE_PROBE)
+               return;
+
+       snd_hda_override_amp_caps(codec, 0x17, HDA_OUTPUT,
+                                 (0x3 << AC_AMPCAP_OFFSET_SHIFT) |
+                                 (0x4 << AC_AMPCAP_NUM_STEPS_SHIFT) |
+                                 (0x27 << AC_AMPCAP_STEP_SIZE_SHIFT) |
+                                 (0 << AC_AMPCAP_MUTE_SHIFT));
+}
+
 /* ThinkPad X200 & co with cxt5051 */
 static const struct hda_pintbl cxt_pincfg_lenovo_x200[] = {
        { 0x16, 0x042140ff }, /* HP (seq# overridden) */
@@ -4432,6 +4448,18 @@ static const struct hda_pintbl cxt_pincfg_lenovo_tp410[] = {
        {}
 };
 
+/* Lemote A1004/A1205 with cxt5066 */
+static const struct hda_pintbl cxt_pincfg_lemote[] = {
+       { 0x1a, 0x90a10020 }, /* Internal mic */
+       { 0x1b, 0x03a11020 }, /* External mic */
+       { 0x1d, 0x400101f0 }, /* Not used */
+       { 0x1e, 0x40a701f0 }, /* Not used */
+       { 0x20, 0x404501f0 }, /* Not used */
+       { 0x22, 0x404401f0 }, /* Not used */
+       { 0x23, 0x40a701f0 }, /* Not used */
+       {}
+};
+
 static const struct hda_fixup cxt_fixups[] = {
        [CXT_PINCFG_LENOVO_X200] = {
                .type = HDA_FIXUP_PINS,
@@ -4441,10 +4469,24 @@ static const struct hda_fixup cxt_fixups[] = {
                .type = HDA_FIXUP_PINS,
                .v.pins = cxt_pincfg_lenovo_tp410,
        },
+       [CXT_PINCFG_LEMOTE_A1004] = {
+               .type = HDA_FIXUP_PINS,
+               .chained = true,
+               .chain_id = CXT_FIXUP_INC_MIC_BOOST,
+               .v.pins = cxt_pincfg_lemote,
+       },
+       [CXT_PINCFG_LEMOTE_A1205] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = cxt_pincfg_lemote,
+       },
        [CXT_FIXUP_STEREO_DMIC] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = cxt_fixup_stereo_dmic,
        },
+       [CXT_FIXUP_INC_MIC_BOOST] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = cxt5066_increase_mic_boost,
+       },
 };
 
 static const struct snd_pci_quirk cxt5051_fixups[] = {
@@ -4461,6 +4503,8 @@ static const struct snd_pci_quirk cxt5066_fixups[] = {
        SND_PCI_QUIRK(0x17aa, 0x3975, "Lenovo U300s", CXT_FIXUP_STEREO_DMIC),
        SND_PCI_QUIRK(0x17aa, 0x3977, "Lenovo IdeaPad U310", CXT_FIXUP_STEREO_DMIC),
        SND_PCI_QUIRK(0x17aa, 0x397b, "Lenovo S205", CXT_FIXUP_STEREO_DMIC),
+       SND_PCI_QUIRK(0x1c06, 0x2011, "Lemote A1004", CXT_PINCFG_LEMOTE_A1004),
+       SND_PCI_QUIRK(0x1c06, 0x2012, "Lemote A1205", CXT_PINCFG_LEMOTE_A1205),
        {}
 };
 
index 71555cc54db1686519b8bd20f168d4fe5babbcad..39ca1005995d71a9863348a5e29f368741dda99d 100644 (file)
@@ -1589,9 +1589,10 @@ static int generic_hdmi_build_controls(struct hda_codec *codec)
                if (err < 0)
                        return err;
 
-               err = snd_hda_create_spdif_out_ctls(codec,
-                                                   per_pin->pin_nid,
-                                                   per_pin->mux_nids[0]);
+               err = snd_hda_create_dig_out_ctls(codec,
+                                                 per_pin->pin_nid,
+                                                 per_pin->mux_nids[0],
+                                                 HDA_PCM_TYPE_HDMI);
                if (err < 0)
                        return err;
                snd_hda_spdif_ctls_unassign(codec, pin_idx);
index 48d9d609f89b06bca17210b8ca9dfaec2a600c1d..96c08792d2108483c91165bdb87a11a7c6381c82 100644 (file)
@@ -1836,9 +1836,10 @@ static int __alc_build_controls(struct hda_codec *codec)
                        return err;
        }
        if (spec->multiout.dig_out_nid) {
-               err = snd_hda_create_spdif_out_ctls(codec,
-                                                   spec->multiout.dig_out_nid,
-                                                   spec->multiout.dig_out_nid);
+               err = snd_hda_create_dig_out_ctls(codec,
+                                                 spec->multiout.dig_out_nid,
+                                                 spec->multiout.dig_out_nid,
+                                                 spec->pcm_rec[1].pcm_type);
                if (err < 0)
                        return err;
                if (!spec->no_analog) {
@@ -5677,6 +5678,7 @@ static const struct hda_verb alc268_beep_init_verbs[] = {
 
 enum {
        ALC268_FIXUP_INV_DMIC,
+       ALC268_FIXUP_HP_EAPD,
 };
 
 static const struct alc_fixup alc268_fixups[] = {
@@ -5684,10 +5686,26 @@ static const struct alc_fixup alc268_fixups[] = {
                .type = ALC_FIXUP_FUNC,
                .v.func = alc_fixup_inv_dmic_0x12,
        },
+       [ALC268_FIXUP_HP_EAPD] = {
+               .type = ALC_FIXUP_VERBS,
+               .v.verbs = (const struct hda_verb[]) {
+                       {0x15, AC_VERB_SET_EAPD_BTLENABLE, 0},
+                       {}
+               }
+       },
 };
 
 static const struct alc_model_fixup alc268_fixup_models[] = {
        {.id = ALC268_FIXUP_INV_DMIC, .name = "inv-dmic"},
+       {.id = ALC268_FIXUP_HP_EAPD, .name = "hp-eapd"},
+       {}
+};
+
+static const struct snd_pci_quirk alc268_fixup_tbl[] = {
+       /* below is codec SSID since multiple Toshiba laptops have the
+        * same PCI SSID 1179:ff00
+        */
+       SND_PCI_QUIRK(0x1179, 0xff06, "Toshiba P200", ALC268_FIXUP_HP_EAPD),
        {}
 };
 
@@ -5722,7 +5740,7 @@ static int patch_alc268(struct hda_codec *codec)
 
        spec = codec->spec;
 
-       alc_pick_fixup(codec, alc268_fixup_models, NULL, alc268_fixups);
+       alc_pick_fixup(codec, alc268_fixup_models, alc268_fixup_tbl, alc268_fixups);
        alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
 
        /* automatic parse from the BIOS config */
@@ -6188,6 +6206,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x17aa, 0x21e9, "Thinkpad Edge 15", ALC269_FIXUP_SKU_IGNORE),
        SND_PCI_QUIRK(0x17aa, 0x21f6, "Thinkpad T530", ALC269_FIXUP_LENOVO_DOCK),
        SND_PCI_QUIRK(0x17aa, 0x21fa, "Thinkpad X230", ALC269_FIXUP_LENOVO_DOCK),
+       SND_PCI_QUIRK(0x17aa, 0x21f3, "Thinkpad T430", ALC269_FIXUP_LENOVO_DOCK),
        SND_PCI_QUIRK(0x17aa, 0x21fb, "Thinkpad T430s", ALC269_FIXUP_LENOVO_DOCK),
        SND_PCI_QUIRK(0x17aa, 0x2203, "Thinkpad X230 Tablet", ALC269_FIXUP_LENOVO_DOCK),
        SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_PCM_44K),
index 770013ff556f6be0500b14039a8e60df2fa74b2a..62141650211fcdf572a476925ec942fc68d0c020 100644 (file)
@@ -1136,9 +1136,10 @@ static int stac92xx_build_controls(struct hda_codec *codec)
        }
 
        if (spec->multiout.dig_out_nid) {
-               err = snd_hda_create_spdif_out_ctls(codec,
-                                                   spec->multiout.dig_out_nid,
-                                                   spec->multiout.dig_out_nid);
+               err = snd_hda_create_dig_out_ctls(codec,
+                                                 spec->multiout.dig_out_nid,
+                                                 spec->multiout.dig_out_nid,
+                                                 spec->autocfg.dig_out_type[0]);
                if (err < 0)
                        return err;
                err = snd_hda_create_spdif_share_sw(codec,
index f7ce33f00ea5eae767e4e14732a6de8077bec841..7e50c1324556df83e7dbb2f3cd8a7a11ed5eb7f4 100644 (file)
@@ -5,7 +5,7 @@
 
 snd-ice17xx-ak4xxx-objs := ak4xxx.o
 snd-ice1712-objs := ice1712.o delta.o hoontech.o ews.o
-snd-ice1724-objs := ice1724.o amp.o revo.o aureon.o vt1720_mobo.o pontis.o prodigy192.o prodigy_hifi.o juli.o phase.o wtm.o se.o maya44.o quartet.o
+snd-ice1724-objs := ice1724.o amp.o revo.o aureon.o vt1720_mobo.o pontis.o prodigy192.o prodigy_hifi.o juli.o phase.o wtm.o se.o maya44.o quartet.o psc724.o wm8766.o wm8776.o
 
 # Toplevel Module Dependency
 obj-$(CONFIG_SND_ICE1712) += snd-ice1712.o snd-ice17xx-ak4xxx.o
index e525da2673be3c5a4b12de44eb7c81e6ccadfcdd..d9bd27b25100c71c1ebeb0576154482df758c4da 100644 (file)
@@ -21,7 +21,6 @@
  *
  */      
 
-#include <asm/io.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
index 20bcddea2eab19320d25299180368a815bc4f90f..ce9941c5e988ede4b99494453b37fd393809f1e8 100644 (file)
@@ -46,7 +46,6 @@
  *                    on mixer switch and other coll stuff.
  */
 
-#include <linux/io.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
@@ -203,7 +202,8 @@ static void aureon_pca9554_write(struct snd_ice1712 *ice, unsigned char reg,
 static int aureon_universe_inmux_info(struct snd_kcontrol *kcontrol,
                                      struct snd_ctl_elem_info *uinfo)
 {
-       char *texts[3] = {"Internal Aux", "Wavetable", "Rear Line-In"};
+       static const char * const texts[3] =
+               {"Internal Aux", "Wavetable", "Rear Line-In"};
 
        uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
        uinfo->count = 1;
index 20c6b079d0dfc33cfc4620006bbbe944e39e91b6..bbef99bf77dfcc226d5b389e9e520d1fea403b58 100644 (file)
@@ -22,7 +22,6 @@
  *
  */      
 
-#include <asm/io.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
index 6fe35b8120400ddb8c073f9166879b9821984a33..bf289f0a1ed4fd186eb4110cc2f757b246984afb 100644 (file)
@@ -22,7 +22,6 @@
  *
  */      
 
-#include <asm/io.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
@@ -576,7 +575,7 @@ static int __devinit snd_ice1712_ews_init(struct snd_ice1712 *ice)
 /* i/o sensitivity - this callback is shared among other devices, too */
 static int snd_ice1712_ewx_io_sense_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo){
 
-       static char *texts[2] = {
+       static const char * const texts[2] = {
                "+4dBu", "-10dBV",
        };
        uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
@@ -899,7 +898,7 @@ static int snd_ice1712_6fire_control_put(struct snd_kcontrol *kcontrol, struct s
 
 static int snd_ice1712_6fire_select_input_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
 {
-       static char *texts[4] = {
+       static const char * const texts[4] = {
                "Internal", "Front Input", "Rear Input", "Wave Table"
        };
        uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
index 6914189073a4d11ad81194e5cb7ad91c0a59e7da..3d84d21e484da1586b036105e964c419c48d32c0 100644 (file)
@@ -21,7 +21,6 @@
  *
  */      
 
-#include <asm/io.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
index 5be2e120a14e25a03744b873e690f765eecb9545..dd64e223f5cffa07a0c4963f8ff092fd6c816aeb 100644 (file)
@@ -47,7 +47,6 @@
  */
 
 
-#include <linux/io.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
@@ -2686,6 +2685,7 @@ static int __devinit snd_ice1712_probe(struct pci_dev *pci,
        for (tbl = card_tables; *tbl; tbl++) {
                for (c = *tbl; c->subvendor; c++) {
                        if (c->subvendor == ice->eeprom.subvendor) {
+                               ice->card_info = c;
                                strcpy(card->shortname, c->name);
                                if (c->driver) /* specific driver? */
                                        strcpy(card->driver, c->driver);
@@ -2799,7 +2799,12 @@ static int __devinit snd_ice1712_probe(struct pci_dev *pci,
 
 static void __devexit snd_ice1712_remove(struct pci_dev *pci)
 {
-       snd_card_free(pci_get_drvdata(pci));
+       struct snd_card *card = pci_get_drvdata(pci);
+       struct snd_ice1712 *ice = card->private_data;
+
+       if (ice->card_info && ice->card_info->chip_exit)
+               ice->card_info->chip_exit(ice);
+       snd_card_free(card);
        pci_set_drvdata(pci, NULL);
 }
 
index d0e7d87f09f0ed4947462630906ec02249e583c6..b209fc30b334b455c7a83701f1f5b398de4881e4 100644 (file)
@@ -22,6 +22,7 @@
  *
  */
 
+#include <linux/io.h>
 #include <sound/control.h>
 #include <sound/ac97_codec.h>
 #include <sound/rawmidi.h>
@@ -288,6 +289,7 @@ struct snd_ice1712_spdif {
        } ops;
 };
 
+struct snd_ice1712_card_info;
 
 struct snd_ice1712 {
        unsigned long conp_dma_size;
@@ -324,6 +326,7 @@ struct snd_ice1712 {
        struct snd_info_entry *proc_entry;
 
        struct snd_ice1712_eeprom eeprom;
+       struct snd_ice1712_card_info *card_info;
 
        unsigned int pro_volumes[20];
        unsigned int omni:1;            /* Delta Omni I/O */
@@ -381,7 +384,7 @@ struct snd_ice1712 {
        unsigned char (*set_mclk)(struct snd_ice1712 *ice, unsigned int rate);
        int (*set_spdif_clock)(struct snd_ice1712 *ice, int type);
        int (*get_spdif_master_type)(struct snd_ice1712 *ice);
-       char **ext_clock_names;
+       const char * const *ext_clock_names;
        int ext_clock_count;
        void (*pro_open)(struct snd_ice1712 *, struct snd_pcm_substream *);
 #ifdef CONFIG_PM_SLEEP
@@ -513,10 +516,11 @@ static inline u8 snd_ice1712_read(struct snd_ice1712 *ice, u8 addr)
 
 struct snd_ice1712_card_info {
        unsigned int subvendor;
-       char *name;
-       char *model;
-       char *driver;
+       const char *name;
+       const char *model;
+       const char *driver;
        int (*chip_init)(struct snd_ice1712 *);
+       void (*chip_exit)(struct snd_ice1712 *);
        int (*build_controls)(struct snd_ice1712 *);
        unsigned int no_mpu401:1;
        unsigned int mpu401_1_info_flags;
index 3050a52792532ad3a58303f54a800dcc7c0ab883..58b4b6f85db3d4ef7718fb51574aa9b16d5d65df 100644 (file)
@@ -22,7 +22,6 @@
  *
  */
 
-#include <linux/io.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
@@ -54,6 +53,7 @@
 #include "wtm.h"
 #include "se.h"
 #include "quartet.h"
+#include "psc724.h"
 
 MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
 MODULE_DESCRIPTION("VIA ICEnsemble ICE1724/1720 (Envy24HT/PT)");
@@ -106,7 +106,7 @@ static int PRO_RATE_LOCKED;
 static int PRO_RATE_RESET = 1;
 static unsigned int PRO_RATE_DEFAULT = 44100;
 
-static char *ext_clock_names[1] = { "IEC958 In" };
+static const char * const ext_clock_names[1] = { "IEC958 In" };
 
 /*
  *  Basic I/O
@@ -2042,7 +2042,7 @@ static struct snd_kcontrol_new snd_vt1724_pro_rate_reset __devinitdata = {
 static int snd_vt1724_pro_route_info(struct snd_kcontrol *kcontrol,
                                     struct snd_ctl_elem_info *uinfo)
 {
-       static char *texts[] = {
+       static const char * const texts[] = {
                "PCM Out", /* 0 */
                "H/W In 0", "H/W In 1", /* 1-2 */
                "IEC958 In L", "IEC958 In R", /* 3-4 */
@@ -2232,7 +2232,7 @@ static unsigned char ooaoo_sq210_eeprom[] __devinitdata = {
 };
 
 
-struct snd_ice1712_card_info snd_vt1724_ooaoo_cards[] __devinitdata = {
+static struct snd_ice1712_card_info snd_vt1724_ooaoo_cards[] __devinitdata = {
        {
                .name = "ooAoo SQ210a",
                .model = "sq210a",
@@ -2257,6 +2257,7 @@ static struct snd_ice1712_card_info *card_tables[] __devinitdata = {
        snd_vt1724_se_cards,
        snd_vt1724_qtet_cards,
        snd_vt1724_ooaoo_cards,
+       snd_vt1724_psc724_cards,
        NULL,
 };
 
@@ -2348,6 +2349,7 @@ static int __devinit snd_vt1724_read_eeprom(struct snd_ice1712 *ice,
                                ice->eeprom.subvendor = c->subvendor;
                        } else if (c->subvendor != ice->eeprom.subvendor)
                                continue;
+                       ice->card_info = c;
                        if (!c->eeprom_size || !c->eeprom_data)
                                goto found;
                        /* if the EEPROM is given by the driver, use it */
@@ -2371,7 +2373,7 @@ static int __devinit snd_vt1724_read_eeprom(struct snd_ice1712 *ice,
                return -EIO;
        }
        ice->eeprom.version = snd_vt1724_read_i2c(ice, dev, 0x05);
-       if (ice->eeprom.version != 2)
+       if (ice->eeprom.version != 1 && ice->eeprom.version != 2)
                printk(KERN_WARNING "ice1724: Invalid EEPROM version %i\n",
                       ice->eeprom.version);
        size = ice->eeprom.size - 6;
@@ -2788,7 +2790,12 @@ __found:
 
 static void __devexit snd_vt1724_remove(struct pci_dev *pci)
 {
-       snd_card_free(pci_get_drvdata(pci));
+       struct snd_card *card = pci_get_drvdata(pci);
+       struct snd_ice1712 *ice = card->private_data;
+
+       if (ice->card_info && ice->card_info->chip_exit)
+               ice->card_info->chip_exit(ice);
+       snd_card_free(card);
        pci_set_drvdata(pci, NULL);
 }
 
index 14fd536b6452d6e5dda1ec01f12929a89c4cd7c0..a6b23b4215129f9c014e1c053e9c4574040bf081 100644 (file)
@@ -23,7 +23,6 @@
  *
  */
 
-#include <asm/io.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
@@ -435,7 +434,8 @@ static struct snd_kcontrol __devinit *ctl_find(struct snd_card *card,
 }
 
 static void __devinit add_slaves(struct snd_card *card,
-                                struct snd_kcontrol *master, char **list)
+                                struct snd_kcontrol *master,
+                                char * const *list)
 {
        for (; *list; list++) {
                struct snd_kcontrol *slave = ctl_find(card, *list);
index 726fd4b92e19e8d564adef229c9c5201a0785963..d8d749e5ed4179eda0bf18d3ba9ca19e8b96a021 100644 (file)
@@ -24,7 +24,6 @@
 
 #include <linux/init.h>
 #include <linux/slab.h>
-#include <linux/io.h>
 #include <sound/core.h>
 #include <sound/control.h>
 #include <sound/pcm.h>
@@ -358,7 +357,7 @@ static void wm8776_select_input(struct snd_maya44 *chip, int idx, int line)
 static int maya_rec_src_info(struct snd_kcontrol *kcontrol,
                             struct snd_ctl_elem_info *uinfo)
 {
-       static char *texts[] = { "Line", "Mic" };
+       static const char * const texts[] = { "Line", "Mic" };
 
        uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
        uinfo->count = 1;
@@ -407,7 +406,7 @@ static int maya_rec_src_put(struct snd_kcontrol *kcontrol,
 static int maya_pb_route_info(struct snd_kcontrol *kcontrol,
                              struct snd_ctl_elem_info *uinfo)
 {
-       static char *texts[] = {
+       static const char * const texts[] = {
                "PCM Out", /* 0 */
                "Input 1", "Input 2", "Input 3", "Input 4"
        };
index de29be8c96574e8bd89eacf81b9aee5eb8a51518..c9be75a457c30285fe9af1d536b761defee1350a 100644 (file)
@@ -42,7 +42,6 @@
  *   Digital receiver: CS8414-CS (supported in this release)
  */
 
-#include <asm/io.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
@@ -722,7 +721,7 @@ static int phase28_deemp_put(struct snd_kcontrol *kcontrol,
 static int phase28_oversampling_info(struct snd_kcontrol *k,
                                        struct snd_ctl_elem_info *uinfo)
 {
-       static char *texts[2] = { "128x", "64x" };
+       static const char * const texts[2] = { "128x", "64x"    };
 
        uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
        uinfo->count = 1;
index 92c1160d7ab52c52811609008ce9cfc6fbd54c18..3ce1289263a392afc7a50a9463dba8b378134406 100644 (file)
@@ -21,7 +21,6 @@
  *
  */
 
-#include <asm/io.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
index e36ddb94c382932a4e5c9b35095678d3b9c90ea5..3fcf581e7ef8b7beb819d1fb970b4d71c0ce1dd4 100644 (file)
@@ -54,7 +54,6 @@
  *
  */      
 
-#include <asm/io.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
@@ -283,7 +282,7 @@ static int stac9460_adc_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_el
 static int stac9460_mic_sw_info(struct snd_kcontrol *kcontrol,
                                struct snd_ctl_elem_info *uinfo)
 {
-       static char *texts[2] = { "Line In", "Mic" };
+       static const char * const texts[2] = { "Line In", "Mic" };
 
        uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
        uinfo->count = 1;
@@ -562,7 +561,7 @@ static unsigned char prodigy192_ak4114_read(void *private_data,
 static int ak4114_input_sw_info(struct snd_kcontrol *kcontrol,
                                struct snd_ctl_elem_info *uinfo)
 {
-       static char *texts[2] = { "Toslink", "Coax" };
+       static const char * const texts[2] = { "Toslink", "Coax" };
 
        uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
        uinfo->count = 1;
index 7bf093c51ce5a5569f6cec1a1f9e53a88763236f..4fea87fb5799931317c9b682e568ab837c04a66b 100644 (file)
@@ -25,7 +25,6 @@
  */
 
 
-#include <asm/io.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
diff --git a/sound/pci/ice1712/psc724.c b/sound/pci/ice1712/psc724.c
new file mode 100644 (file)
index 0000000..0b6c4e6
--- /dev/null
@@ -0,0 +1,464 @@
+/*
+ *   ALSA driver for ICEnsemble VT1724 (Envy24HT)
+ *
+ *   Lowlevel functions for Philips PSC724 Ultimate Edge
+ *
+ *     Copyright (c) 2012 Ondrej Zary <linux@rainbow-software.org>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+
+#include "ice1712.h"
+#include "envy24ht.h"
+#include "psc724.h"
+#include "wm8766.h"
+#include "wm8776.h"
+
+struct psc724_spec {
+       struct snd_wm8766 wm8766;
+       struct snd_wm8776 wm8776;
+       bool mute_all, jack_detect;
+       struct snd_ice1712 *ice;
+       struct delayed_work hp_work;
+       bool hp_connected;
+};
+
+/****************************************************************************/
+/*  PHILIPS PSC724 ULTIMATE EDGE                                            */
+/****************************************************************************/
+/*
+ *  VT1722 (Envy24GT) - 6 outputs, 4 inputs (only 2 used), 24-bit/96kHz
+ *
+ *  system configuration ICE_EEP2_SYSCONF=0x42
+ *    XIN1 49.152MHz
+ *    no MPU401
+ *    one stereo ADC, no S/PDIF receiver
+ *    three stereo DACs (FRONT, REAR, CENTER+LFE)
+ *
+ *  AC-Link configuration ICE_EEP2_ACLINK=0x80
+ *    use I2S, not AC97
+ *
+ *  I2S converters feature ICE_EEP2_I2S=0x30
+ *    I2S codec has no volume/mute control feature (bug!)
+ *    I2S codec does not support 96KHz or 192KHz (bug!)
+ *    I2S codec 24bits
+ *
+ *  S/PDIF configuration ICE_EEP2_SPDIF=0xc1
+ *    Enable integrated S/PDIF transmitter
+ *    internal S/PDIF out implemented
+ *    No S/PDIF input
+ *    External S/PDIF out implemented
+ *
+ *
+ * ** connected chips **
+ *
+ *  WM8776
+ *     2-channel DAC used for main output and stereo ADC (with 10-channel MUX)
+ *     AIN1: LINE IN, AIN2: CD/VIDEO, AIN3: AUX, AIN4: Front MIC, AIN5: Rear MIC
+ *     Controlled by I2C using VT1722 I2C interface:
+ *          MODE (pin16) -- GND
+ *          CE   (pin17) -- GND  I2C mode (address=0x34)
+ *          DI   (pin18) -- SDA  (VT1722 pin70)
+ *          CL   (pin19) -- SCLK (VT1722 pin71)
+ *
+ *  WM8766
+ *      6-channel DAC used for rear & center/LFE outputs (only 4 channels used)
+ *      Controlled by SPI using VT1722 GPIO pins:
+ *          MODE   (pin 1) -- GPIO19 (VT1722 pin99)
+ *          ML/I2S (pin11) -- GPIO18 (VT1722 pin98)
+ *          MC/IWL (pin12) -- GPIO17 (VT1722 pin97)
+ *          MD/DM  (pin13) -- GPIO16 (VT1722 pin96)
+ *          MUTE   (pin14) -- GPIO20 (VT1722 pin101)
+ *
+ *  GPIO14 is used as input for headphone jack detection (1 = connected)
+ *  GPIO22 is used as MUTE ALL output, grounding all 6 channels
+ *
+ * ** output pins and device names **
+ *
+ *   5.1ch name -- output connector color -- device (-D option)
+ *
+ *      FRONT 2ch                  -- green  -- plughw:0,0
+ *      CENTER(Lch) SUBWOOFER(Rch) -- orange -- plughw:0,2,0
+ *      REAR 2ch                   -- black  -- plughw:0,2,1
+ */
+
+/* codec access low-level functions */
+
+#define GPIO_HP_JACK   (1 << 14)
+#define GPIO_MUTE_SUR  (1 << 20)
+#define GPIO_MUTE_ALL  (1 << 22)
+
+#define JACK_INTERVAL  1000
+
+#define PSC724_SPI_DELAY 1
+
+#define PSC724_SPI_DATA        (1 << 16)
+#define PSC724_SPI_CLK (1 << 17)
+#define PSC724_SPI_LOAD        (1 << 18)
+#define PSC724_SPI_MASK        (PSC724_SPI_DATA | PSC724_SPI_CLK | PSC724_SPI_LOAD)
+
+static void psc724_wm8766_write(struct snd_wm8766 *wm, u16 addr, u16 data)
+{
+       struct psc724_spec *spec = container_of(wm, struct psc724_spec, wm8766);
+       struct snd_ice1712 *ice = spec->ice;
+       u32 st, bits;
+       int i;
+
+       snd_ice1712_save_gpio_status(ice);
+
+       st = ((addr & 0x7f) << 9) | (data & 0x1ff);
+       snd_ice1712_gpio_set_dir(ice, ice->gpio.direction | PSC724_SPI_MASK);
+       snd_ice1712_gpio_set_mask(ice, ice->gpio.write_mask & ~PSC724_SPI_MASK);
+       bits = snd_ice1712_gpio_read(ice) & ~PSC724_SPI_MASK;
+       snd_ice1712_gpio_write(ice, bits);
+
+       for (i = 0; i < 16; i++) {
+               udelay(PSC724_SPI_DELAY);
+               bits &= ~PSC724_SPI_CLK;
+               /* MSB first */
+               st <<= 1;
+               if (st & 0x10000)
+                       bits |= PSC724_SPI_DATA;
+               else
+                       bits &= ~PSC724_SPI_DATA;
+               snd_ice1712_gpio_write(ice, bits);
+               /* CLOCK high */
+               udelay(PSC724_SPI_DELAY);
+               bits |= PSC724_SPI_CLK;
+               snd_ice1712_gpio_write(ice, bits);
+       }
+       /* LOAD high */
+       udelay(PSC724_SPI_DELAY);
+       bits |= PSC724_SPI_LOAD;
+       snd_ice1712_gpio_write(ice, bits);
+       /* LOAD low, DATA and CLOCK high */
+       udelay(PSC724_SPI_DELAY);
+       bits |= (PSC724_SPI_DATA | PSC724_SPI_CLK);
+       snd_ice1712_gpio_write(ice, bits);
+
+       snd_ice1712_restore_gpio_status(ice);
+}
+
+static void psc724_wm8776_write(struct snd_wm8776 *wm, u8 addr, u8 data)
+{
+       struct psc724_spec *spec = container_of(wm, struct psc724_spec, wm8776);
+
+       snd_vt1724_write_i2c(spec->ice, 0x34, addr, data);
+}
+
+/* mute all */
+
+static void psc724_set_master_switch(struct snd_ice1712 *ice, bool on)
+{
+       unsigned int bits = snd_ice1712_gpio_read(ice);
+       struct psc724_spec *spec = ice->spec;
+
+       spec->mute_all = !on;
+       if (on)
+               bits &= ~(GPIO_MUTE_ALL | GPIO_MUTE_SUR);
+       else
+               bits |= GPIO_MUTE_ALL | GPIO_MUTE_SUR;
+       snd_ice1712_gpio_write(ice, bits);
+}
+
+static bool psc724_get_master_switch(struct snd_ice1712 *ice)
+{
+       struct psc724_spec *spec = ice->spec;
+
+       return !spec->mute_all;
+}
+
+/* jack detection */
+
+static void psc724_set_jack_state(struct snd_ice1712 *ice, bool hp_connected)
+{
+       struct psc724_spec *spec = ice->spec;
+       struct snd_ctl_elem_id elem_id;
+       struct snd_kcontrol *kctl;
+       u16 power = spec->wm8776.regs[WM8776_REG_PWRDOWN] & ~WM8776_PWR_HPPD;
+
+       psc724_set_master_switch(ice, !hp_connected);
+       if (!hp_connected)
+               power |= WM8776_PWR_HPPD;
+       snd_wm8776_set_power(&spec->wm8776, power);
+       spec->hp_connected = hp_connected;
+       /* notify about master speaker mute change */
+       memset(&elem_id, 0, sizeof(elem_id));
+       elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+       strncpy(elem_id.name, "Master Speakers Playback Switch",
+                                               sizeof(elem_id.name));
+       kctl = snd_ctl_find_id(ice->card, &elem_id);
+       snd_ctl_notify(ice->card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id);
+       /* and headphone mute change */
+       strncpy(elem_id.name, spec->wm8776.ctl[WM8776_CTL_HP_SW].name,
+                                               sizeof(elem_id.name));
+       kctl = snd_ctl_find_id(ice->card, &elem_id);
+       snd_ctl_notify(ice->card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id);
+}
+
+static void psc724_update_hp_jack_state(struct work_struct *work)
+{
+       struct psc724_spec *spec = container_of(work, struct psc724_spec,
+                                               hp_work.work);
+       struct snd_ice1712 *ice = spec->ice;
+       bool hp_connected = snd_ice1712_gpio_read(ice) & GPIO_HP_JACK;
+
+       schedule_delayed_work(&spec->hp_work, msecs_to_jiffies(JACK_INTERVAL));
+       if (hp_connected == spec->hp_connected)
+               return;
+       psc724_set_jack_state(ice, hp_connected);
+}
+
+static void psc724_set_jack_detection(struct snd_ice1712 *ice, bool on)
+{
+       struct psc724_spec *spec = ice->spec;
+
+       if (spec->jack_detect == on)
+               return;
+
+       spec->jack_detect = on;
+       if (on) {
+               bool hp_connected = snd_ice1712_gpio_read(ice) & GPIO_HP_JACK;
+               psc724_set_jack_state(ice, hp_connected);
+               schedule_delayed_work(&spec->hp_work,
+                                       msecs_to_jiffies(JACK_INTERVAL));
+       } else
+               cancel_delayed_work_sync(&spec->hp_work);
+}
+
+static bool psc724_get_jack_detection(struct snd_ice1712 *ice)
+{
+       struct psc724_spec *spec = ice->spec;
+
+       return spec->jack_detect;
+}
+
+/* mixer controls */
+
+struct psc724_control {
+       const char *name;
+       void (*set)(struct snd_ice1712 *ice, bool on);
+       bool (*get)(struct snd_ice1712 *ice);
+};
+
+static const struct psc724_control psc724_cont[] = {
+       {
+               .name = "Master Speakers Playback Switch",
+               .set = psc724_set_master_switch,
+               .get = psc724_get_master_switch,
+       },
+       {
+               .name = "Headphone Jack Detection Playback Switch",
+               .set = psc724_set_jack_detection,
+               .get = psc724_get_jack_detection,
+       },
+};
+
+static int psc724_ctl_get(struct snd_kcontrol *kcontrol,
+                                 struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
+       int n = kcontrol->private_value;
+
+       ucontrol->value.integer.value[0] = psc724_cont[n].get(ice);
+
+       return 0;
+}
+
+static int psc724_ctl_put(struct snd_kcontrol *kcontrol,
+                                 struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
+       int n = kcontrol->private_value;
+
+       psc724_cont[n].set(ice, ucontrol->value.integer.value[0]);
+
+       return 0;
+}
+
+static const char *front_volume        = "Front Playback Volume";
+static const char *front_switch        = "Front Playback Switch";
+static const char *front_zc    = "Front Zero Cross Detect Playback Switch";
+static const char *front_izd   = "Front Infinite Zero Detect Playback Switch";
+static const char *front_phase = "Front Phase Invert Playback Switch";
+static const char *front_deemph        = "Front Deemphasis Playback Switch";
+static const char *ain1_switch = "Line Capture Switch";
+static const char *ain2_switch = "CD Capture Switch";
+static const char *ain3_switch = "AUX Capture Switch";
+static const char *ain4_switch = "Front Mic Capture Switch";
+static const char *ain5_switch = "Rear Mic Capture Switch";
+static const char *rear_volume = "Surround Playback Volume";
+static const char *clfe_volume = "CLFE Playback Volume";
+static const char *rear_switch = "Surround Playback Switch";
+static const char *clfe_switch = "CLFE Playback Switch";
+static const char *rear_phase  = "Surround Phase Invert Playback Switch";
+static const char *clfe_phase  = "CLFE Phase Invert Playback Switch";
+static const char *rear_deemph = "Surround Deemphasis Playback Switch";
+static const char *clfe_deemph = "CLFE Deemphasis Playback Switch";
+static const char *rear_clfe_izd = "Rear Infinite Zero Detect Playback Switch";
+static const char *rear_clfe_zc        = "Rear Zero Cross Detect Playback Switch";
+
+static int __devinit psc724_add_controls(struct snd_ice1712 *ice)
+{
+       struct snd_kcontrol_new cont;
+       struct snd_kcontrol *ctl;
+       int err, i;
+       struct psc724_spec *spec = ice->spec;
+
+       spec->wm8776.ctl[WM8776_CTL_DAC_VOL].name = front_volume;
+       spec->wm8776.ctl[WM8776_CTL_DAC_SW].name = front_switch;
+       spec->wm8776.ctl[WM8776_CTL_DAC_ZC_SW].name = front_zc;
+       spec->wm8776.ctl[WM8776_CTL_AUX_SW].name = NULL;
+       spec->wm8776.ctl[WM8776_CTL_DAC_IZD_SW].name = front_izd;
+       spec->wm8776.ctl[WM8776_CTL_PHASE_SW].name = front_phase;
+       spec->wm8776.ctl[WM8776_CTL_DEEMPH_SW].name = front_deemph;
+       spec->wm8776.ctl[WM8776_CTL_INPUT1_SW].name = ain1_switch;
+       spec->wm8776.ctl[WM8776_CTL_INPUT2_SW].name = ain2_switch;
+       spec->wm8776.ctl[WM8776_CTL_INPUT3_SW].name = ain3_switch;
+       spec->wm8776.ctl[WM8776_CTL_INPUT4_SW].name = ain4_switch;
+       spec->wm8776.ctl[WM8776_CTL_INPUT5_SW].name = ain5_switch;
+       snd_wm8776_build_controls(&spec->wm8776);
+       spec->wm8766.ctl[WM8766_CTL_CH1_VOL].name = rear_volume;
+       spec->wm8766.ctl[WM8766_CTL_CH2_VOL].name = clfe_volume;
+       spec->wm8766.ctl[WM8766_CTL_CH3_VOL].name = NULL;
+       spec->wm8766.ctl[WM8766_CTL_CH1_SW].name = rear_switch;
+       spec->wm8766.ctl[WM8766_CTL_CH2_SW].name = clfe_switch;
+       spec->wm8766.ctl[WM8766_CTL_CH3_SW].name = NULL;
+       spec->wm8766.ctl[WM8766_CTL_PHASE1_SW].name = rear_phase;
+       spec->wm8766.ctl[WM8766_CTL_PHASE2_SW].name = clfe_phase;
+       spec->wm8766.ctl[WM8766_CTL_PHASE3_SW].name = NULL;
+       spec->wm8766.ctl[WM8766_CTL_DEEMPH1_SW].name = rear_deemph;
+       spec->wm8766.ctl[WM8766_CTL_DEEMPH2_SW].name = clfe_deemph;
+       spec->wm8766.ctl[WM8766_CTL_DEEMPH3_SW].name = NULL;
+       spec->wm8766.ctl[WM8766_CTL_IZD_SW].name = rear_clfe_izd;
+       spec->wm8766.ctl[WM8766_CTL_ZC_SW].name = rear_clfe_zc;
+       snd_wm8766_build_controls(&spec->wm8766);
+
+       memset(&cont, 0, sizeof(cont));
+       cont.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+       for (i = 0; i < ARRAY_SIZE(psc724_cont); i++) {
+               cont.private_value = i;
+               cont.name = psc724_cont[i].name;
+               cont.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
+               cont.info = snd_ctl_boolean_mono_info;
+               cont.get = psc724_ctl_get;
+               cont.put = psc724_ctl_put;
+               ctl = snd_ctl_new1(&cont, ice);
+               if (!ctl)
+                       return -ENOMEM;
+               err = snd_ctl_add(ice->card, ctl);
+               if (err < 0)
+                       return err;
+       }
+
+       return 0;
+}
+
+static void psc724_set_pro_rate(struct snd_ice1712 *ice, unsigned int rate)
+{
+       struct psc724_spec *spec = ice->spec;
+       /* restore codec volume settings after rate change (PMCLK stop) */
+       snd_wm8776_volume_restore(&spec->wm8776);
+       snd_wm8766_volume_restore(&spec->wm8766);
+}
+
+/* power management */
+
+#ifdef CONFIG_PM_SLEEP
+static int psc724_resume(struct snd_ice1712 *ice)
+{
+       struct psc724_spec *spec = ice->spec;
+
+       snd_wm8776_resume(&spec->wm8776);
+       snd_wm8766_resume(&spec->wm8766);
+
+       return 0;
+}
+#endif
+
+/* init */
+
+static int __devinit psc724_init(struct snd_ice1712 *ice)
+{
+       struct psc724_spec *spec;
+
+       spec = kzalloc(sizeof(*spec), GFP_KERNEL);
+       if (!spec)
+               return -ENOMEM;
+       ice->spec = spec;
+       spec->ice = ice;
+
+       ice->num_total_dacs = 6;
+       ice->num_total_adcs = 2;
+       spec->wm8776.ops.write = psc724_wm8776_write;
+       spec->wm8776.card = ice->card;
+       snd_wm8776_init(&spec->wm8776);
+       spec->wm8766.ops.write = psc724_wm8766_write;
+       spec->wm8766.card = ice->card;
+#ifdef CONFIG_PM_SLEEP
+       ice->pm_resume = psc724_resume;
+       ice->pm_suspend_enabled = 1;
+#endif
+       snd_wm8766_init(&spec->wm8766);
+       snd_wm8766_set_if(&spec->wm8766,
+                       WM8766_IF_FMT_I2S | WM8766_IF_IWL_24BIT);
+       ice->gpio.set_pro_rate = psc724_set_pro_rate;
+       INIT_DELAYED_WORK(&spec->hp_work, psc724_update_hp_jack_state);
+       psc724_set_jack_detection(ice, true);
+       return 0;
+}
+
+static void psc724_exit(struct snd_ice1712 *ice)
+{
+       struct psc724_spec *spec = ice->spec;
+
+       cancel_delayed_work_sync(&spec->hp_work);
+}
+
+/* PSC724 has buggy EEPROM (no 96&192kHz, all FFh GPIOs), so override it here */
+static unsigned char psc724_eeprom[] __devinitdata = {
+       [ICE_EEP2_SYSCONF]      = 0x42, /* 49.152MHz, 1 ADC, 3 DACs */
+       [ICE_EEP2_ACLINK]       = 0x80, /* I2S */
+       [ICE_EEP2_I2S]          = 0xf0, /* I2S volume, 96kHz, 24bit */
+       [ICE_EEP2_SPDIF]        = 0xc1, /* spdif out-en, out-int, no input */
+       /* GPIO outputs */
+       [ICE_EEP2_GPIO_DIR2]    = 0x5f, /* MUTE_ALL,WM8766 MUTE/MODE/ML/MC/MD */
+       /* GPIO write enable */
+       [ICE_EEP2_GPIO_MASK]    = 0xff, /* read-only */
+       [ICE_EEP2_GPIO_MASK1]   = 0xff, /* read-only */
+       [ICE_EEP2_GPIO_MASK2]   = 0xa0, /* MUTE_ALL,WM8766 MUTE/MODE/ML/MC/MD */
+       /* GPIO initial state */
+       [ICE_EEP2_GPIO_STATE2]  = 0x20, /* unmuted, all WM8766 pins low */
+};
+
+struct snd_ice1712_card_info snd_vt1724_psc724_cards[] __devinitdata = {
+       {
+               .subvendor = VT1724_SUBDEVICE_PSC724,
+               .name = "Philips PSC724 Ultimate Edge",
+               .model = "psc724",
+               .chip_init = psc724_init,
+               .chip_exit = psc724_exit,
+               .build_controls = psc724_add_controls,
+               .eeprom_size = sizeof(psc724_eeprom),
+               .eeprom_data = psc724_eeprom,
+       },
+       {} /*terminator*/
+};
diff --git a/sound/pci/ice1712/psc724.h b/sound/pci/ice1712/psc724.h
new file mode 100644 (file)
index 0000000..858e5fd
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef __SOUND_PSC724_H
+#define __SOUND_PSC724_H
+
+/* ID */
+#define PSC724_DEVICE_DESC     \
+               "{Philips,PSC724 Ultimate Edge},"
+
+#define VT1724_SUBDEVICE_PSC724                0xab170619
+
+/* entry struct */
+extern struct snd_ice1712_card_info snd_vt1724_psc724_cards[];
+
+#endif /* __SOUND_PSC724_H */
index 1948632787e6be6e97e4cac092695b89d55bfa32..c85b2ff79115350734d924aac5f7bbe37669f2c4 100644 (file)
@@ -22,7 +22,6 @@
  *
  */
 
-#include <asm/io.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
@@ -47,7 +46,7 @@ struct qtet_kcontrol_private {
        unsigned int bit;
        void (*set_register)(struct snd_ice1712 *ice, unsigned int val);
        unsigned int (*get_register)(struct snd_ice1712 *ice);
-       unsigned char *texts[2];
+       unsigned char * const texts[2];
 };
 
 enum {
@@ -63,7 +62,7 @@ enum {
        OUT34_MON12,
 };
 
-static char *ext_clock_names[3] = {"IEC958 In", "Word Clock 1xFS",
+static const char * const ext_clock_names[3] = {"IEC958 In", "Word Clock 1xFS",
        "Word Clock 256xFS"};
 
 /* chip address on I2C bus */
@@ -551,7 +550,8 @@ static int qtet_mute_put(struct snd_kcontrol *kcontrol,
 static int qtet_ain12_enum_info(struct snd_kcontrol *kcontrol,
                struct snd_ctl_elem_info *uinfo)
 {
-       static char *texts[3] = {"Line In 1/2", "Mic", "Mic + Low-cut"};
+       static const char * const texts[3] =
+               {"Line In 1/2", "Mic", "Mic + Low-cut"};
        uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
        uinfo->count = 1;
        uinfo->value.enumerated.items = ARRAY_SIZE(texts);
@@ -816,7 +816,7 @@ static struct snd_kcontrol __devinit *ctl_find(struct snd_card *card,
 }
 
 static void __devinit add_slaves(struct snd_card *card,
-               struct snd_kcontrol *master, char **list)
+               struct snd_kcontrol *master, char * const *list)
 {
        for (; *list; list++) {
                struct snd_kcontrol *slave = ctl_find(card, *list);
index b508bb360b97d1499eea3902cade76ff83f4b3f1..a1b79758766bcc0191ad884510a28f48575995af 100644 (file)
@@ -21,7 +21,6 @@
  *
  */      
 
-#include <asm/io.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
index 69673b95869da9bfd855aa4aa05acdf24f4c6835..53b555f5bbea076c8cb3c5322368923bead939e2 100644 (file)
@@ -22,7 +22,6 @@
  *
  */      
 
-#include <asm/io.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
@@ -253,7 +252,7 @@ static void se200pci_WM8776_set_input_volume(struct snd_ice1712 *ice,
        se200pci_WM8776_write(ice, 0x0f, vol2 | 0x100);
 }
 
-static const char *se200pci_sel[] = {
+static const char * const se200pci_sel[] = {
        "LINE-IN", "CD-IN", "MIC-IN", "ALL-MIX", NULL
 };
 
@@ -278,7 +277,7 @@ static void se200pci_WM8776_set_afl(struct snd_ice1712 *ice, unsigned int afl)
                se200pci_WM8776_write(ice, 0x16, 0x001);
 }
 
-static const char *se200pci_agc[] = {
+static const char * const se200pci_agc[] = {
        "Off", "LimiterMode", "ALCMode", NULL
 };
 
@@ -352,7 +351,7 @@ static void se200pci_set_pro_rate(struct snd_ice1712 *ice, unsigned int rate)
 }
 
 struct se200pci_control {
-       char *name;
+       const char *name;
        enum {
                WM8766,
                WM8776in,
@@ -363,7 +362,7 @@ struct se200pci_control {
        } target;
        enum { VOLUME1, VOLUME2, BOOLEAN, ENUM } type;
        int ch;
-       const char **member;
+       const char * const *member;
        const char *comment;
 };
 
@@ -421,7 +420,7 @@ static const struct se200pci_control se200pci_cont[] = {
 
 static int se200pci_get_enum_count(int n)
 {
-       const char **member;
+       const char * const *member;
        int c;
 
        member = se200pci_cont[n].member;
index 4c551e147c089d8186db424d6bc630ddeead58b1..8a0a8393ad9e7d5ecdd54b8d1077f7e84b925d62 100644 (file)
@@ -21,7 +21,6 @@
  *
  */      
 
-#include <asm/io.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
diff --git a/sound/pci/ice1712/wm8766.c b/sound/pci/ice1712/wm8766.c
new file mode 100644 (file)
index 0000000..8072ade
--- /dev/null
@@ -0,0 +1,361 @@
+/*
+ *   ALSA driver for ICEnsemble VT17xx
+ *
+ *   Lowlevel functions for WM8766 codec
+ *
+ *     Copyright (c) 2012 Ondrej Zary <linux@rainbow-software.org>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#include <linux/delay.h>
+#include <sound/core.h>
+#include <sound/control.h>
+#include <sound/tlv.h>
+#include "wm8766.h"
+
+/* low-level access */
+
+static void snd_wm8766_write(struct snd_wm8766 *wm, u16 addr, u16 data)
+{
+       if (addr < WM8766_REG_RESET)
+               wm->regs[addr] = data;
+       wm->ops.write(wm, addr, data);
+}
+
+/* mixer controls */
+
+static const DECLARE_TLV_DB_SCALE(wm8766_tlv, -12750, 50, 1);
+
+static struct snd_wm8766_ctl snd_wm8766_default_ctl[WM8766_CTL_COUNT] = {
+       [WM8766_CTL_CH1_VOL] = {
+               .name = "Channel 1 Playback Volume",
+               .type = SNDRV_CTL_ELEM_TYPE_INTEGER,
+               .tlv = wm8766_tlv,
+               .reg1 = WM8766_REG_DACL1,
+               .reg2 = WM8766_REG_DACR1,
+               .mask1 = WM8766_VOL_MASK,
+               .mask2 = WM8766_VOL_MASK,
+               .max = 0xff,
+               .flags = WM8766_FLAG_STEREO | WM8766_FLAG_VOL_UPDATE,
+       },
+       [WM8766_CTL_CH2_VOL] = {
+               .name = "Channel 2 Playback Volume",
+               .type = SNDRV_CTL_ELEM_TYPE_INTEGER,
+               .tlv = wm8766_tlv,
+               .reg1 = WM8766_REG_DACL2,
+               .reg2 = WM8766_REG_DACR2,
+               .mask1 = WM8766_VOL_MASK,
+               .mask2 = WM8766_VOL_MASK,
+               .max = 0xff,
+               .flags = WM8766_FLAG_STEREO | WM8766_FLAG_VOL_UPDATE,
+       },
+       [WM8766_CTL_CH3_VOL] = {
+               .name = "Channel 3 Playback Volume",
+               .type = SNDRV_CTL_ELEM_TYPE_INTEGER,
+               .tlv = wm8766_tlv,
+               .reg1 = WM8766_REG_DACL3,
+               .reg2 = WM8766_REG_DACR3,
+               .mask1 = WM8766_VOL_MASK,
+               .mask2 = WM8766_VOL_MASK,
+               .max = 0xff,
+               .flags = WM8766_FLAG_STEREO | WM8766_FLAG_VOL_UPDATE,
+       },
+       [WM8766_CTL_CH1_SW] = {
+               .name = "Channel 1 Playback Switch",
+               .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+               .reg1 = WM8766_REG_DACCTRL2,
+               .mask1 = WM8766_DAC2_MUTE1,
+               .flags = WM8766_FLAG_INVERT,
+       },
+       [WM8766_CTL_CH2_SW] = {
+               .name = "Channel 2 Playback Switch",
+               .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+               .reg1 = WM8766_REG_DACCTRL2,
+               .mask1 = WM8766_DAC2_MUTE2,
+               .flags = WM8766_FLAG_INVERT,
+       },
+       [WM8766_CTL_CH3_SW] = {
+               .name = "Channel 3 Playback Switch",
+               .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+               .reg1 = WM8766_REG_DACCTRL2,
+               .mask1 = WM8766_DAC2_MUTE3,
+               .flags = WM8766_FLAG_INVERT,
+       },
+       [WM8766_CTL_PHASE1_SW] = {
+               .name = "Channel 1 Phase Invert Playback Switch",
+               .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+               .reg1 = WM8766_REG_IFCTRL,
+               .mask1 = WM8766_PHASE_INVERT1,
+       },
+       [WM8766_CTL_PHASE2_SW] = {
+               .name = "Channel 2 Phase Invert Playback Switch",
+               .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+               .reg1 = WM8766_REG_IFCTRL,
+               .mask1 = WM8766_PHASE_INVERT2,
+       },
+       [WM8766_CTL_PHASE3_SW] = {
+               .name = "Channel 3 Phase Invert Playback Switch",
+               .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+               .reg1 = WM8766_REG_IFCTRL,
+               .mask1 = WM8766_PHASE_INVERT3,
+       },
+       [WM8766_CTL_DEEMPH1_SW] = {
+               .name = "Channel 1 Deemphasis Playback Switch",
+               .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+               .reg1 = WM8766_REG_DACCTRL2,
+               .mask1 = WM8766_DAC2_DEEMP1,
+       },
+       [WM8766_CTL_DEEMPH2_SW] = {
+               .name = "Channel 2 Deemphasis Playback Switch",
+               .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+               .reg1 = WM8766_REG_DACCTRL2,
+               .mask1 = WM8766_DAC2_DEEMP2,
+       },
+       [WM8766_CTL_DEEMPH3_SW] = {
+               .name = "Channel 3 Deemphasis Playback Switch",
+               .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+               .reg1 = WM8766_REG_DACCTRL2,
+               .mask1 = WM8766_DAC2_DEEMP3,
+       },
+       [WM8766_CTL_IZD_SW] = {
+               .name = "Infinite Zero Detect Playback Switch",
+               .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+               .reg1 = WM8766_REG_DACCTRL1,
+               .mask1 = WM8766_DAC_IZD,
+       },
+       [WM8766_CTL_ZC_SW] = {
+               .name = "Zero Cross Detect Playback Switch",
+               .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+               .reg1 = WM8766_REG_DACCTRL2,
+               .mask1 = WM8766_DAC2_ZCD,
+               .flags = WM8766_FLAG_INVERT,
+       },
+};
+
+/* exported functions */
+
+void snd_wm8766_init(struct snd_wm8766 *wm)
+{
+       int i;
+       static const u16 default_values[] = {
+               0x000, 0x100,
+               0x120, 0x000,
+               0x000, 0x100, 0x000, 0x100, 0x000,
+               0x000, 0x080,
+       };
+
+       memcpy(wm->ctl, snd_wm8766_default_ctl, sizeof(wm->ctl));
+
+       snd_wm8766_write(wm, WM8766_REG_RESET, 0x00); /* reset */
+       udelay(10);
+       /* load defaults */
+       for (i = 0; i < ARRAY_SIZE(default_values); i++)
+               snd_wm8766_write(wm, i, default_values[i]);
+}
+
+void snd_wm8766_resume(struct snd_wm8766 *wm)
+{
+       int i;
+
+       for (i = 0; i < WM8766_REG_COUNT; i++)
+               snd_wm8766_write(wm, i, wm->regs[i]);
+}
+
+void snd_wm8766_set_if(struct snd_wm8766 *wm, u16 dac)
+{
+       u16 val = wm->regs[WM8766_REG_IFCTRL] & ~WM8766_IF_MASK;
+
+       dac &= WM8766_IF_MASK;
+       snd_wm8766_write(wm, WM8766_REG_IFCTRL, val | dac);
+}
+
+void snd_wm8766_set_master_mode(struct snd_wm8766 *wm, u16 mode)
+{
+       u16 val = wm->regs[WM8766_REG_DACCTRL3] & ~WM8766_DAC3_MSTR_MASK;
+
+       mode &= WM8766_DAC3_MSTR_MASK;
+       snd_wm8766_write(wm, WM8766_REG_DACCTRL3, val | mode);
+}
+
+void snd_wm8766_set_power(struct snd_wm8766 *wm, u16 power)
+{
+       u16 val = wm->regs[WM8766_REG_DACCTRL3] & ~WM8766_DAC3_POWER_MASK;
+
+       power &= WM8766_DAC3_POWER_MASK;
+       snd_wm8766_write(wm, WM8766_REG_DACCTRL3, val | power);
+}
+
+void snd_wm8766_volume_restore(struct snd_wm8766 *wm)
+{
+       u16 val = wm->regs[WM8766_REG_DACR1];
+       /* restore volume after MCLK stopped */
+       snd_wm8766_write(wm, WM8766_REG_DACR1, val | WM8766_VOL_UPDATE);
+}
+
+/* mixer callbacks */
+
+static int snd_wm8766_volume_info(struct snd_kcontrol *kcontrol,
+                                  struct snd_ctl_elem_info *uinfo)
+{
+       struct snd_wm8766 *wm = snd_kcontrol_chip(kcontrol);
+       int n = kcontrol->private_value;
+
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+       uinfo->count = (wm->ctl[n].flags & WM8766_FLAG_STEREO) ? 2 : 1;
+       uinfo->value.integer.min = wm->ctl[n].min;
+       uinfo->value.integer.max = wm->ctl[n].max;
+
+       return 0;
+}
+
+static int snd_wm8766_enum_info(struct snd_kcontrol *kcontrol,
+                                     struct snd_ctl_elem_info *uinfo)
+{
+       struct snd_wm8766 *wm = snd_kcontrol_chip(kcontrol);
+       int n = kcontrol->private_value;
+
+       return snd_ctl_enum_info(uinfo, 1, wm->ctl[n].max,
+                                               wm->ctl[n].enum_names);
+}
+
+static int snd_wm8766_ctl_get(struct snd_kcontrol *kcontrol,
+                                 struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_wm8766 *wm = snd_kcontrol_chip(kcontrol);
+       int n = kcontrol->private_value;
+       u16 val1, val2;
+
+       if (wm->ctl[n].get)
+               wm->ctl[n].get(wm, &val1, &val2);
+       else {
+               val1 = wm->regs[wm->ctl[n].reg1] & wm->ctl[n].mask1;
+               val1 >>= __ffs(wm->ctl[n].mask1);
+               if (wm->ctl[n].flags & WM8766_FLAG_STEREO) {
+                       val2 = wm->regs[wm->ctl[n].reg2] & wm->ctl[n].mask2;
+                       val2 >>= __ffs(wm->ctl[n].mask2);
+                       if (wm->ctl[n].flags & WM8766_FLAG_VOL_UPDATE)
+                               val2 &= ~WM8766_VOL_UPDATE;
+               }
+       }
+       if (wm->ctl[n].flags & WM8766_FLAG_INVERT) {
+               val1 = wm->ctl[n].max - (val1 - wm->ctl[n].min);
+               val2 = wm->ctl[n].max - (val2 - wm->ctl[n].min);
+       }
+       ucontrol->value.integer.value[0] = val1;
+       if (wm->ctl[n].flags & WM8766_FLAG_STEREO)
+               ucontrol->value.integer.value[1] = val2;
+
+       return 0;
+}
+
+static int snd_wm8766_ctl_put(struct snd_kcontrol *kcontrol,
+                                 struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_wm8766 *wm = snd_kcontrol_chip(kcontrol);
+       int n = kcontrol->private_value;
+       u16 val, regval1, regval2;
+
+       /* this also works for enum because value is an union */
+       regval1 = ucontrol->value.integer.value[0];
+       regval2 = ucontrol->value.integer.value[1];
+       if (wm->ctl[n].flags & WM8766_FLAG_INVERT) {
+               regval1 = wm->ctl[n].max - (regval1 - wm->ctl[n].min);
+               regval2 = wm->ctl[n].max - (regval2 - wm->ctl[n].min);
+       }
+       if (wm->ctl[n].set)
+               wm->ctl[n].set(wm, regval1, regval2);
+       else {
+               val = wm->regs[wm->ctl[n].reg1] & ~wm->ctl[n].mask1;
+               val |= regval1 << __ffs(wm->ctl[n].mask1);
+               /* both stereo controls in one register */
+               if (wm->ctl[n].flags & WM8766_FLAG_STEREO &&
+                               wm->ctl[n].reg1 == wm->ctl[n].reg2) {
+                       val &= ~wm->ctl[n].mask2;
+                       val |= regval2 << __ffs(wm->ctl[n].mask2);
+               }
+               snd_wm8766_write(wm, wm->ctl[n].reg1, val);
+               /* stereo controls in different registers */
+               if (wm->ctl[n].flags & WM8766_FLAG_STEREO &&
+                               wm->ctl[n].reg1 != wm->ctl[n].reg2) {
+                       val = wm->regs[wm->ctl[n].reg2] & ~wm->ctl[n].mask2;
+                       val |= regval2 << __ffs(wm->ctl[n].mask2);
+                       if (wm->ctl[n].flags & WM8766_FLAG_VOL_UPDATE)
+                               val |= WM8766_VOL_UPDATE;
+                       snd_wm8766_write(wm, wm->ctl[n].reg2, val);
+               }
+       }
+
+       return 0;
+}
+
+static int snd_wm8766_add_control(struct snd_wm8766 *wm, int num)
+{
+       struct snd_kcontrol_new cont;
+       struct snd_kcontrol *ctl;
+
+       memset(&cont, 0, sizeof(cont));
+       cont.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+       cont.private_value = num;
+       cont.name = wm->ctl[num].name;
+       cont.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
+       if (wm->ctl[num].flags & WM8766_FLAG_LIM ||
+           wm->ctl[num].flags & WM8766_FLAG_ALC)
+               cont.access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
+       cont.tlv.p = NULL;
+       cont.get = snd_wm8766_ctl_get;
+       cont.put = snd_wm8766_ctl_put;
+
+       switch (wm->ctl[num].type) {
+       case SNDRV_CTL_ELEM_TYPE_INTEGER:
+               cont.info = snd_wm8766_volume_info;
+               cont.access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
+               cont.tlv.p = wm->ctl[num].tlv;
+               break;
+       case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
+               wm->ctl[num].max = 1;
+               if (wm->ctl[num].flags & WM8766_FLAG_STEREO)
+                       cont.info = snd_ctl_boolean_stereo_info;
+               else
+                       cont.info = snd_ctl_boolean_mono_info;
+               break;
+       case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
+               cont.info = snd_wm8766_enum_info;
+               break;
+       default:
+               return -EINVAL;
+       }
+       ctl = snd_ctl_new1(&cont, wm);
+       if (!ctl)
+               return -ENOMEM;
+       wm->ctl[num].kctl = ctl;
+
+       return snd_ctl_add(wm->card, ctl);
+}
+
+int snd_wm8766_build_controls(struct snd_wm8766 *wm)
+{
+       int err, i;
+
+       for (i = 0; i < WM8766_CTL_COUNT; i++)
+               if (wm->ctl[i].name) {
+                       err = snd_wm8766_add_control(wm, i);
+                       if (err < 0)
+                               return err;
+               }
+
+       return 0;
+}
diff --git a/sound/pci/ice1712/wm8766.h b/sound/pci/ice1712/wm8766.h
new file mode 100644 (file)
index 0000000..c119f84
--- /dev/null
@@ -0,0 +1,163 @@
+#ifndef __SOUND_WM8766_H
+#define __SOUND_WM8766_H
+
+/*
+ *   ALSA driver for ICEnsemble VT17xx
+ *
+ *   Lowlevel functions for WM8766 codec
+ *
+ *     Copyright (c) 2012 Ondrej Zary <linux@rainbow-software.org>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#define WM8766_REG_DACL1       0x00
+#define WM8766_REG_DACR1       0x01
+#define WM8766_VOL_MASK                        0x1ff           /* incl. update bit */
+#define WM8766_VOL_UPDATE              (1 << 8)        /* update volume */
+#define WM8766_REG_DACCTRL1    0x02
+#define WM8766_DAC_MUTEALL             (1 << 0)
+#define WM8766_DAC_DEEMPALL            (1 << 1)
+#define WM8766_DAC_PDWN                        (1 << 2)
+#define WM8766_DAC_ATC                 (1 << 3)
+#define WM8766_DAC_IZD                 (1 << 4)
+#define WM8766_DAC_PL_MASK             0x1e0
+#define WM8766_DAC_PL_LL               (1 << 5)        /* L chan: L signal */
+#define WM8766_DAC_PL_LR               (2 << 5)        /* L chan: R signal */
+#define WM8766_DAC_PL_LB               (3 << 5)        /* L chan: both */
+#define WM8766_DAC_PL_RL               (1 << 7)        /* R chan: L signal */
+#define WM8766_DAC_PL_RR               (2 << 7)        /* R chan: R signal */
+#define WM8766_DAC_PL_RB               (3 << 7)        /* R chan: both */
+#define WM8766_REG_IFCTRL      0x03
+#define WM8766_IF_FMT_RIGHTJ           (0 << 0)
+#define WM8766_IF_FMT_LEFTJ            (1 << 0)
+#define WM8766_IF_FMT_I2S              (2 << 0)
+#define WM8766_IF_FMT_DSP              (3 << 0)
+#define WM8766_IF_DSP_LATE             (1 << 2)        /* in DSP mode */
+#define WM8766_IF_LRC_INVERTED         (1 << 2)        /* in other modes */
+#define WM8766_IF_BCLK_INVERTED                (1 << 3)
+#define WM8766_IF_IWL_16BIT            (0 << 4)
+#define WM8766_IF_IWL_20BIT            (1 << 4)
+#define WM8766_IF_IWL_24BIT            (2 << 4)
+#define WM8766_IF_IWL_32BIT            (3 << 4)
+#define WM8766_IF_MASK                 0x3f
+#define WM8766_PHASE_INVERT1           (1 << 6)
+#define WM8766_PHASE_INVERT2           (1 << 7)
+#define WM8766_PHASE_INVERT3           (1 << 8)
+#define WM8766_REG_DACL2       0x04
+#define WM8766_REG_DACR2       0x05
+#define WM8766_REG_DACL3       0x06
+#define WM8766_REG_DACR3       0x07
+#define WM8766_REG_MASTDA      0x08
+#define WM8766_REG_DACCTRL2    0x09
+#define WM8766_DAC2_ZCD                        (1 << 0)
+#define WM8766_DAC2_ZFLAG_ALL          (0 << 1)
+#define WM8766_DAC2_ZFLAG_1            (1 << 1)
+#define WM8766_DAC2_ZFLAG_2            (2 << 1)
+#define WM8766_DAC2_ZFLAG_3            (3 << 1)
+#define WM8766_DAC2_MUTE1              (1 << 3)
+#define WM8766_DAC2_MUTE2              (1 << 4)
+#define WM8766_DAC2_MUTE3              (1 << 5)
+#define WM8766_DAC2_DEEMP1             (1 << 6)
+#define WM8766_DAC2_DEEMP2             (1 << 7)
+#define WM8766_DAC2_DEEMP3             (1 << 8)
+#define WM8766_REG_DACCTRL3    0x0a
+#define WM8766_DAC3_DACPD1             (1 << 1)
+#define WM8766_DAC3_DACPD2             (1 << 2)
+#define WM8766_DAC3_DACPD3             (1 << 3)
+#define WM8766_DAC3_PWRDNALL           (1 << 4)
+#define WM8766_DAC3_POWER_MASK         0x1e
+#define WM8766_DAC3_MASTER             (1 << 5)
+#define WM8766_DAC3_DAC128FS           (0 << 6)
+#define WM8766_DAC3_DAC192FS           (1 << 6)
+#define WM8766_DAC3_DAC256FS           (2 << 6)
+#define WM8766_DAC3_DAC384FS           (3 << 6)
+#define WM8766_DAC3_DAC512FS           (4 << 6)
+#define WM8766_DAC3_DAC768FS           (5 << 6)
+#define WM8766_DAC3_MSTR_MASK          0x1e0
+#define WM8766_REG_MUTE1       0x0c
+#define WM8766_MUTE1_MPD               (1 << 6)
+#define WM8766_REG_MUTE2       0x0f
+#define WM8766_MUTE2_MPD               (1 << 5)
+#define WM8766_REG_RESET       0x1f
+
+#define WM8766_REG_COUNT       0x10    /* don't cache the RESET register */
+
+struct snd_wm8766;
+
+struct snd_wm8766_ops {
+       void (*write)(struct snd_wm8766 *wm, u16 addr, u16 data);
+};
+
+enum snd_wm8766_ctl_id {
+       WM8766_CTL_CH1_VOL,
+       WM8766_CTL_CH2_VOL,
+       WM8766_CTL_CH3_VOL,
+       WM8766_CTL_CH1_SW,
+       WM8766_CTL_CH2_SW,
+       WM8766_CTL_CH3_SW,
+       WM8766_CTL_PHASE1_SW,
+       WM8766_CTL_PHASE2_SW,
+       WM8766_CTL_PHASE3_SW,
+       WM8766_CTL_DEEMPH1_SW,
+       WM8766_CTL_DEEMPH2_SW,
+       WM8766_CTL_DEEMPH3_SW,
+       WM8766_CTL_IZD_SW,
+       WM8766_CTL_ZC_SW,
+
+       WM8766_CTL_COUNT,
+};
+
+#define WM8766_ENUM_MAX                16
+
+#define WM8766_FLAG_STEREO     (1 << 0)
+#define WM8766_FLAG_VOL_UPDATE (1 << 1)
+#define WM8766_FLAG_INVERT     (1 << 2)
+#define WM8766_FLAG_LIM                (1 << 3)
+#define WM8766_FLAG_ALC                (1 << 4)
+
+struct snd_wm8766_ctl {
+       struct snd_kcontrol *kctl;
+       const char *name;
+       snd_ctl_elem_type_t type;
+       const char *const enum_names[WM8766_ENUM_MAX];
+       const unsigned int *tlv;
+       u16 reg1, reg2, mask1, mask2, min, max, flags;
+       void (*set)(struct snd_wm8766 *wm, u16 ch1, u16 ch2);
+       void (*get)(struct snd_wm8766 *wm, u16 *ch1, u16 *ch2);
+};
+
+enum snd_wm8766_agc_mode { WM8766_AGC_OFF, WM8766_AGC_LIM, WM8766_AGC_ALC };
+
+struct snd_wm8766 {
+       struct snd_card *card;
+       struct snd_wm8766_ctl ctl[WM8766_CTL_COUNT];
+       enum snd_wm8766_agc_mode agc_mode;
+       struct snd_wm8766_ops ops;
+       u16 regs[WM8766_REG_COUNT];     /* 9-bit registers */
+};
+
+
+
+void snd_wm8766_init(struct snd_wm8766 *wm);
+void snd_wm8766_resume(struct snd_wm8766 *wm);
+void snd_wm8766_set_if(struct snd_wm8766 *wm, u16 dac);
+void snd_wm8766_set_master_mode(struct snd_wm8766 *wm, u16 mode);
+void snd_wm8766_set_power(struct snd_wm8766 *wm, u16 power);
+void snd_wm8766_volume_restore(struct snd_wm8766 *wm);
+int snd_wm8766_build_controls(struct snd_wm8766 *wm);
+
+#endif /* __SOUND_WM8766_H */
diff --git a/sound/pci/ice1712/wm8776.c b/sound/pci/ice1712/wm8776.c
new file mode 100644 (file)
index 0000000..a3c05fe
--- /dev/null
@@ -0,0 +1,633 @@
+/*
+ *   ALSA driver for ICEnsemble VT17xx
+ *
+ *   Lowlevel functions for WM8776 codec
+ *
+ *     Copyright (c) 2012 Ondrej Zary <linux@rainbow-software.org>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#include <linux/delay.h>
+#include <sound/core.h>
+#include <sound/control.h>
+#include <sound/tlv.h>
+#include "wm8776.h"
+
+/* low-level access */
+
+static void snd_wm8776_write(struct snd_wm8776 *wm, u16 addr, u16 data)
+{
+       u8 bus_addr = addr << 1 | data >> 8;    /* addr + 9th data bit */
+       u8 bus_data = data & 0xff;              /* remaining 8 data bits */
+
+       if (addr < WM8776_REG_RESET)
+               wm->regs[addr] = data;
+       wm->ops.write(wm, bus_addr, bus_data);
+}
+
+/* register-level functions */
+
+static void snd_wm8776_activate_ctl(struct snd_wm8776 *wm,
+                                   const char *ctl_name,
+                                   bool active)
+{
+       struct snd_card *card = wm->card;
+       struct snd_kcontrol *kctl;
+       struct snd_kcontrol_volatile *vd;
+       struct snd_ctl_elem_id elem_id;
+       unsigned int index_offset;
+
+       memset(&elem_id, 0, sizeof(elem_id));
+       strncpy(elem_id.name, ctl_name, sizeof(elem_id.name));
+       elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+       kctl = snd_ctl_find_id(card, &elem_id);
+       if (!kctl)
+               return;
+       index_offset = snd_ctl_get_ioff(kctl, &kctl->id);
+       vd = &kctl->vd[index_offset];
+       if (active)
+               vd->access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
+       else
+               vd->access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
+       snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_INFO, &kctl->id);
+}
+
+static void snd_wm8776_update_agc_ctl(struct snd_wm8776 *wm)
+{
+       int i, flags_on = 0, flags_off = 0;
+
+       switch (wm->agc_mode) {
+       case WM8776_AGC_OFF:
+               flags_off = WM8776_FLAG_LIM | WM8776_FLAG_ALC;
+               break;
+       case WM8776_AGC_LIM:
+               flags_off = WM8776_FLAG_ALC;
+               flags_on = WM8776_FLAG_LIM;
+               break;
+       case WM8776_AGC_ALC_R:
+       case WM8776_AGC_ALC_L:
+       case WM8776_AGC_ALC_STEREO:
+               flags_off = WM8776_FLAG_LIM;
+               flags_on = WM8776_FLAG_ALC;
+               break;
+       }
+
+       for (i = 0; i < WM8776_CTL_COUNT; i++)
+               if (wm->ctl[i].flags & flags_off)
+                       snd_wm8776_activate_ctl(wm, wm->ctl[i].name, false);
+               else if (wm->ctl[i].flags & flags_on)
+                       snd_wm8776_activate_ctl(wm, wm->ctl[i].name, true);
+}
+
+static void snd_wm8776_set_agc(struct snd_wm8776 *wm, u16 agc, u16 nothing)
+{
+       u16 alc1 = wm->regs[WM8776_REG_ALCCTRL1] & ~WM8776_ALC1_LCT_MASK;
+       u16 alc2 = wm->regs[WM8776_REG_ALCCTRL2] & ~WM8776_ALC2_LCEN;
+
+       switch (agc) {
+       case 0: /* Off */
+               wm->agc_mode = WM8776_AGC_OFF;
+               break;
+       case 1: /* Limiter */
+               alc2 |= WM8776_ALC2_LCEN;
+               wm->agc_mode = WM8776_AGC_LIM;
+               break;
+       case 2: /* ALC Right */
+               alc1 |= WM8776_ALC1_LCSEL_ALCR;
+               alc2 |= WM8776_ALC2_LCEN;
+               wm->agc_mode = WM8776_AGC_ALC_R;
+               break;
+       case 3: /* ALC Left */
+               alc1 |= WM8776_ALC1_LCSEL_ALCL;
+               alc2 |= WM8776_ALC2_LCEN;
+               wm->agc_mode = WM8776_AGC_ALC_L;
+               break;
+       case 4: /* ALC Stereo */
+               alc1 |= WM8776_ALC1_LCSEL_ALCSTEREO;
+               alc2 |= WM8776_ALC2_LCEN;
+               wm->agc_mode = WM8776_AGC_ALC_STEREO;
+               break;
+       }
+       snd_wm8776_write(wm, WM8776_REG_ALCCTRL1, alc1);
+       snd_wm8776_write(wm, WM8776_REG_ALCCTRL2, alc2);
+       snd_wm8776_update_agc_ctl(wm);
+}
+
+static void snd_wm8776_get_agc(struct snd_wm8776 *wm, u16 *mode, u16 *nothing)
+{
+       *mode = wm->agc_mode;
+}
+
+/* mixer controls */
+
+static const DECLARE_TLV_DB_SCALE(wm8776_hp_tlv, -7400, 100, 1);
+static const DECLARE_TLV_DB_SCALE(wm8776_dac_tlv, -12750, 50, 1);
+static const DECLARE_TLV_DB_SCALE(wm8776_adc_tlv, -10350, 50, 1);
+static const DECLARE_TLV_DB_SCALE(wm8776_lct_tlv, -1600, 100, 0);
+static const DECLARE_TLV_DB_SCALE(wm8776_maxgain_tlv, 0, 400, 0);
+static const DECLARE_TLV_DB_SCALE(wm8776_ngth_tlv, -7800, 600, 0);
+static const DECLARE_TLV_DB_SCALE(wm8776_maxatten_lim_tlv, -1200, 100, 0);
+static const DECLARE_TLV_DB_SCALE(wm8776_maxatten_alc_tlv, -2100, 400, 0);
+
+static struct snd_wm8776_ctl snd_wm8776_default_ctl[WM8776_CTL_COUNT] = {
+       [WM8776_CTL_DAC_VOL] = {
+               .name = "Master Playback Volume",
+               .type = SNDRV_CTL_ELEM_TYPE_INTEGER,
+               .tlv = wm8776_dac_tlv,
+               .reg1 = WM8776_REG_DACLVOL,
+               .reg2 = WM8776_REG_DACRVOL,
+               .mask1 = WM8776_DACVOL_MASK,
+               .mask2 = WM8776_DACVOL_MASK,
+               .max = 0xff,
+               .flags = WM8776_FLAG_STEREO | WM8776_FLAG_VOL_UPDATE,
+       },
+       [WM8776_CTL_DAC_SW] = {
+               .name = "Master Playback Switch",
+               .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+               .reg1 = WM8776_REG_DACCTRL1,
+               .reg2 = WM8776_REG_DACCTRL1,
+               .mask1 = WM8776_DAC_PL_LL,
+               .mask2 = WM8776_DAC_PL_RR,
+               .flags = WM8776_FLAG_STEREO,
+       },
+       [WM8776_CTL_DAC_ZC_SW] = {
+               .name = "Master Zero Cross Detect Playback Switch",
+               .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+               .reg1 = WM8776_REG_DACCTRL1,
+               .mask1 = WM8776_DAC_DZCEN,
+       },
+       [WM8776_CTL_HP_VOL] = {
+               .name = "Headphone Playback Volume",
+               .type = SNDRV_CTL_ELEM_TYPE_INTEGER,
+               .tlv = wm8776_hp_tlv,
+               .reg1 = WM8776_REG_HPLVOL,
+               .reg2 = WM8776_REG_HPRVOL,
+               .mask1 = WM8776_HPVOL_MASK,
+               .mask2 = WM8776_HPVOL_MASK,
+               .min = 0x2f,
+               .max = 0x7f,
+               .flags = WM8776_FLAG_STEREO | WM8776_FLAG_VOL_UPDATE,
+       },
+       [WM8776_CTL_HP_SW] = {
+               .name = "Headphone Playback Switch",
+               .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+               .reg1 = WM8776_REG_PWRDOWN,
+               .mask1 = WM8776_PWR_HPPD,
+               .flags = WM8776_FLAG_INVERT,
+       },
+       [WM8776_CTL_HP_ZC_SW] = {
+               .name = "Headphone Zero Cross Detect Playback Switch",
+               .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+               .reg1 = WM8776_REG_HPLVOL,
+               .reg2 = WM8776_REG_HPRVOL,
+               .mask1 = WM8776_VOL_HPZCEN,
+               .mask2 = WM8776_VOL_HPZCEN,
+               .flags = WM8776_FLAG_STEREO,
+       },
+       [WM8776_CTL_AUX_SW] = {
+               .name = "AUX Playback Switch",
+               .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+               .reg1 = WM8776_REG_OUTMUX,
+               .mask1 = WM8776_OUTMUX_AUX,
+       },
+       [WM8776_CTL_BYPASS_SW] = {
+               .name = "Bypass Playback Switch",
+               .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+               .reg1 = WM8776_REG_OUTMUX,
+               .mask1 = WM8776_OUTMUX_BYPASS,
+       },
+       [WM8776_CTL_DAC_IZD_SW] = {
+               .name = "Infinite Zero Detect Playback Switch",
+               .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+               .reg1 = WM8776_REG_DACCTRL1,
+               .mask1 = WM8776_DAC_IZD,
+       },
+       [WM8776_CTL_PHASE_SW] = {
+               .name = "Phase Invert Playback Switch",
+               .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+               .reg1 = WM8776_REG_PHASESWAP,
+               .reg2 = WM8776_REG_PHASESWAP,
+               .mask1 = WM8776_PHASE_INVERTL,
+               .mask2 = WM8776_PHASE_INVERTR,
+               .flags = WM8776_FLAG_STEREO,
+       },
+       [WM8776_CTL_DEEMPH_SW] = {
+               .name = "Deemphasis Playback Switch",
+               .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+               .reg1 = WM8776_REG_DACCTRL2,
+               .mask1 = WM8776_DAC2_DEEMPH,
+       },
+       [WM8776_CTL_ADC_VOL] = {
+               .name = "Input Capture Volume",
+               .type = SNDRV_CTL_ELEM_TYPE_INTEGER,
+               .tlv = wm8776_adc_tlv,
+               .reg1 = WM8776_REG_ADCLVOL,
+               .reg2 = WM8776_REG_ADCRVOL,
+               .mask1 = WM8776_ADC_GAIN_MASK,
+               .mask2 = WM8776_ADC_GAIN_MASK,
+               .max = 0xff,
+               .flags = WM8776_FLAG_STEREO | WM8776_FLAG_VOL_UPDATE,
+       },
+       [WM8776_CTL_ADC_SW] = {
+               .name = "Input Capture Switch",
+               .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+               .reg1 = WM8776_REG_ADCMUX,
+               .reg2 = WM8776_REG_ADCMUX,
+               .mask1 = WM8776_ADC_MUTEL,
+               .mask2 = WM8776_ADC_MUTER,
+               .flags = WM8776_FLAG_STEREO | WM8776_FLAG_INVERT,
+       },
+       [WM8776_CTL_INPUT1_SW] = {
+               .name = "AIN1 Capture Switch",
+               .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+               .reg1 = WM8776_REG_ADCMUX,
+               .mask1 = WM8776_ADC_MUX_AIN1,
+       },
+       [WM8776_CTL_INPUT2_SW] = {
+               .name = "AIN2 Capture Switch",
+               .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+               .reg1 = WM8776_REG_ADCMUX,
+               .mask1 = WM8776_ADC_MUX_AIN2,
+       },
+       [WM8776_CTL_INPUT3_SW] = {
+               .name = "AIN3 Capture Switch",
+               .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+               .reg1 = WM8776_REG_ADCMUX,
+               .mask1 = WM8776_ADC_MUX_AIN3,
+       },
+       [WM8776_CTL_INPUT4_SW] = {
+               .name = "AIN4 Capture Switch",
+               .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+               .reg1 = WM8776_REG_ADCMUX,
+               .mask1 = WM8776_ADC_MUX_AIN4,
+       },
+       [WM8776_CTL_INPUT5_SW] = {
+               .name = "AIN5 Capture Switch",
+               .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+               .reg1 = WM8776_REG_ADCMUX,
+               .mask1 = WM8776_ADC_MUX_AIN5,
+       },
+       [WM8776_CTL_AGC_SEL] = {
+               .name = "AGC Select Capture Enum",
+               .type = SNDRV_CTL_ELEM_TYPE_ENUMERATED,
+               .enum_names = { "Off", "Limiter", "ALC Right", "ALC Left",
+                               "ALC Stereo" },
+               .max = 5,       /* .enum_names item count */
+               .set = snd_wm8776_set_agc,
+               .get = snd_wm8776_get_agc,
+       },
+       [WM8776_CTL_LIM_THR] = {
+               .name = "Limiter Threshold Capture Volume",
+               .type = SNDRV_CTL_ELEM_TYPE_INTEGER,
+               .tlv = wm8776_lct_tlv,
+               .reg1 = WM8776_REG_ALCCTRL1,
+               .mask1 = WM8776_ALC1_LCT_MASK,
+               .max = 15,
+               .flags = WM8776_FLAG_LIM,
+       },
+       [WM8776_CTL_LIM_ATK] = {
+               .name = "Limiter Attack Time Capture Enum",
+               .type = SNDRV_CTL_ELEM_TYPE_ENUMERATED,
+               .enum_names = { "0.25 ms", "0.5 ms", "1 ms", "2 ms", "4 ms",
+                       "8 ms", "16 ms", "32 ms", "64 ms", "128 ms", "256 ms" },
+               .max = 11,      /* .enum_names item count */
+               .reg1 = WM8776_REG_ALCCTRL3,
+               .mask1 = WM8776_ALC3_ATK_MASK,
+               .flags = WM8776_FLAG_LIM,
+       },
+       [WM8776_CTL_LIM_DCY] = {
+               .name = "Limiter Decay Time Capture Enum",
+               .type = SNDRV_CTL_ELEM_TYPE_ENUMERATED,
+               .enum_names = { "1.2 ms", "2.4 ms", "4.8 ms", "9.6 ms",
+                       "19.2 ms", "38.4 ms", "76.8 ms", "154 ms", "307 ms",
+                       "614 ms", "1.23 s" },
+               .max = 11,      /* .enum_names item count */
+               .reg1 = WM8776_REG_ALCCTRL3,
+               .mask1 = WM8776_ALC3_DCY_MASK,
+               .flags = WM8776_FLAG_LIM,
+       },
+       [WM8776_CTL_LIM_TRANWIN] = {
+               .name = "Limiter Transient Window Capture Enum",
+               .type = SNDRV_CTL_ELEM_TYPE_ENUMERATED,
+               .enum_names = { "0 us", "62.5 us", "125 us", "250 us", "500 us",
+                       "1 ms", "2 ms", "4 ms" },
+               .max = 8,       /* .enum_names item count */
+               .reg1 = WM8776_REG_LIMITER,
+               .mask1 = WM8776_LIM_TRANWIN_MASK,
+               .flags = WM8776_FLAG_LIM,
+       },
+       [WM8776_CTL_LIM_MAXATTN] = {
+               .name = "Limiter Maximum Attenuation Capture Volume",
+               .type = SNDRV_CTL_ELEM_TYPE_INTEGER,
+               .tlv = wm8776_maxatten_lim_tlv,
+               .reg1 = WM8776_REG_LIMITER,
+               .mask1 = WM8776_LIM_MAXATTEN_MASK,
+               .min = 3,
+               .max = 12,
+               .flags = WM8776_FLAG_LIM | WM8776_FLAG_INVERT,
+       },
+       [WM8776_CTL_ALC_TGT] = {
+               .name = "ALC Target Level Capture Volume",
+               .type = SNDRV_CTL_ELEM_TYPE_INTEGER,
+               .tlv = wm8776_lct_tlv,
+               .reg1 = WM8776_REG_ALCCTRL1,
+               .mask1 = WM8776_ALC1_LCT_MASK,
+               .max = 15,
+               .flags = WM8776_FLAG_ALC,
+       },
+       [WM8776_CTL_ALC_ATK] = {
+               .name = "ALC Attack Time Capture Enum",
+               .type = SNDRV_CTL_ELEM_TYPE_ENUMERATED,
+               .enum_names = { "8.40 ms", "16.8 ms", "33.6 ms", "67.2 ms",
+                       "134 ms", "269 ms", "538 ms", "1.08 s", "2.15 s",
+                       "4.3 s", "8.6 s" },
+               .max = 11,      /* .enum_names item count */
+               .reg1 = WM8776_REG_ALCCTRL3,
+               .mask1 = WM8776_ALC3_ATK_MASK,
+               .flags = WM8776_FLAG_ALC,
+       },
+       [WM8776_CTL_ALC_DCY] = {
+               .name = "ALC Decay Time Capture Enum",
+               .type = SNDRV_CTL_ELEM_TYPE_ENUMERATED,
+               .enum_names = { "33.5 ms", "67.0 ms", "134 ms", "268 ms",
+                       "536 ms", "1.07 s", "2.14 s", "4.29 s", "8.58 s",
+                       "17.2 s", "34.3 s" },
+               .max = 11,      /* .enum_names item count */
+               .reg1 = WM8776_REG_ALCCTRL3,
+               .mask1 = WM8776_ALC3_DCY_MASK,
+               .flags = WM8776_FLAG_ALC,
+       },
+       [WM8776_CTL_ALC_MAXGAIN] = {
+               .name = "ALC Maximum Gain Capture Volume",
+               .type = SNDRV_CTL_ELEM_TYPE_INTEGER,
+               .tlv = wm8776_maxgain_tlv,
+               .reg1 = WM8776_REG_ALCCTRL1,
+               .mask1 = WM8776_ALC1_MAXGAIN_MASK,
+               .min = 1,
+               .max = 7,
+               .flags = WM8776_FLAG_ALC,
+       },
+       [WM8776_CTL_ALC_MAXATTN] = {
+               .name = "ALC Maximum Attenuation Capture Volume",
+               .type = SNDRV_CTL_ELEM_TYPE_INTEGER,
+               .tlv = wm8776_maxatten_alc_tlv,
+               .reg1 = WM8776_REG_LIMITER,
+               .mask1 = WM8776_LIM_MAXATTEN_MASK,
+               .min = 10,
+               .max = 15,
+               .flags = WM8776_FLAG_ALC | WM8776_FLAG_INVERT,
+       },
+       [WM8776_CTL_ALC_HLD] = {
+               .name = "ALC Hold Time Capture Enum",
+               .type = SNDRV_CTL_ELEM_TYPE_ENUMERATED,
+               .enum_names = { "0 ms", "2.67 ms", "5.33 ms", "10.6 ms",
+                       "21.3 ms", "42.7 ms", "85.3 ms", "171 ms", "341 ms",
+                       "683 ms", "1.37 s", "2.73 s", "5.46 s", "10.9 s",
+                       "21.8 s", "43.7 s" },
+               .max = 16,      /* .enum_names item count */
+               .reg1 = WM8776_REG_ALCCTRL2,
+               .mask1 = WM8776_ALC2_HOLD_MASK,
+               .flags = WM8776_FLAG_ALC,
+       },
+       [WM8776_CTL_NGT_SW] = {
+               .name = "Noise Gate Capture Switch",
+               .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+               .reg1 = WM8776_REG_NOISEGATE,
+               .mask1 = WM8776_NGAT_ENABLE,
+               .flags = WM8776_FLAG_ALC,
+       },
+       [WM8776_CTL_NGT_THR] = {
+               .name = "Noise Gate Threshold Capture Volume",
+               .type = SNDRV_CTL_ELEM_TYPE_INTEGER,
+               .tlv = wm8776_ngth_tlv,
+               .reg1 = WM8776_REG_NOISEGATE,
+               .mask1 = WM8776_NGAT_THR_MASK,
+               .max = 7,
+               .flags = WM8776_FLAG_ALC,
+       },
+};
+
+/* exported functions */
+
+void snd_wm8776_init(struct snd_wm8776 *wm)
+{
+       int i;
+       static const u16 default_values[] = {
+               0x000, 0x100, 0x000,
+               0x000, 0x100, 0x000,
+               0x000, 0x090, 0x000, 0x000,
+               0x022, 0x022, 0x022,
+               0x008, 0x0cf, 0x0cf, 0x07b, 0x000,
+               0x032, 0x000, 0x0a6, 0x001, 0x001
+       };
+
+       memcpy(wm->ctl, snd_wm8776_default_ctl, sizeof(wm->ctl));
+
+       snd_wm8776_write(wm, WM8776_REG_RESET, 0x00); /* reset */
+       udelay(10);
+       /* load defaults */
+       for (i = 0; i < ARRAY_SIZE(default_values); i++)
+               snd_wm8776_write(wm, i, default_values[i]);
+}
+
+void snd_wm8776_resume(struct snd_wm8776 *wm)
+{
+       int i;
+
+       for (i = 0; i < WM8776_REG_COUNT; i++)
+               snd_wm8776_write(wm, i, wm->regs[i]);
+}
+
+void snd_wm8776_set_dac_if(struct snd_wm8776 *wm, u16 dac)
+{
+       snd_wm8776_write(wm, WM8776_REG_DACIFCTRL, dac);
+}
+
+void snd_wm8776_set_adc_if(struct snd_wm8776 *wm, u16 adc)
+{
+       snd_wm8776_write(wm, WM8776_REG_ADCIFCTRL, adc);
+}
+
+void snd_wm8776_set_master_mode(struct snd_wm8776 *wm, u16 mode)
+{
+       snd_wm8776_write(wm, WM8776_REG_MSTRCTRL, mode);
+}
+
+void snd_wm8776_set_power(struct snd_wm8776 *wm, u16 power)
+{
+       snd_wm8776_write(wm, WM8776_REG_PWRDOWN, power);
+}
+
+void snd_wm8776_volume_restore(struct snd_wm8776 *wm)
+{
+       u16 val = wm->regs[WM8776_REG_DACRVOL];
+       /* restore volume after MCLK stopped */
+       snd_wm8776_write(wm, WM8776_REG_DACRVOL, val | WM8776_VOL_UPDATE);
+}
+
+/* mixer callbacks */
+
+static int snd_wm8776_volume_info(struct snd_kcontrol *kcontrol,
+                                  struct snd_ctl_elem_info *uinfo)
+{
+       struct snd_wm8776 *wm = snd_kcontrol_chip(kcontrol);
+       int n = kcontrol->private_value;
+
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+       uinfo->count = (wm->ctl[n].flags & WM8776_FLAG_STEREO) ? 2 : 1;
+       uinfo->value.integer.min = wm->ctl[n].min;
+       uinfo->value.integer.max = wm->ctl[n].max;
+
+       return 0;
+}
+
+static int snd_wm8776_enum_info(struct snd_kcontrol *kcontrol,
+                                     struct snd_ctl_elem_info *uinfo)
+{
+       struct snd_wm8776 *wm = snd_kcontrol_chip(kcontrol);
+       int n = kcontrol->private_value;
+
+       return snd_ctl_enum_info(uinfo, 1, wm->ctl[n].max,
+                                               wm->ctl[n].enum_names);
+}
+
+static int snd_wm8776_ctl_get(struct snd_kcontrol *kcontrol,
+                                 struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_wm8776 *wm = snd_kcontrol_chip(kcontrol);
+       int n = kcontrol->private_value;
+       u16 val1, val2;
+
+       if (wm->ctl[n].get)
+               wm->ctl[n].get(wm, &val1, &val2);
+       else {
+               val1 = wm->regs[wm->ctl[n].reg1] & wm->ctl[n].mask1;
+               val1 >>= __ffs(wm->ctl[n].mask1);
+               if (wm->ctl[n].flags & WM8776_FLAG_STEREO) {
+                       val2 = wm->regs[wm->ctl[n].reg2] & wm->ctl[n].mask2;
+                       val2 >>= __ffs(wm->ctl[n].mask2);
+                       if (wm->ctl[n].flags & WM8776_FLAG_VOL_UPDATE)
+                               val2 &= ~WM8776_VOL_UPDATE;
+               }
+       }
+       if (wm->ctl[n].flags & WM8776_FLAG_INVERT) {
+               val1 = wm->ctl[n].max - (val1 - wm->ctl[n].min);
+               val2 = wm->ctl[n].max - (val2 - wm->ctl[n].min);
+       }
+       ucontrol->value.integer.value[0] = val1;
+       if (wm->ctl[n].flags & WM8776_FLAG_STEREO)
+               ucontrol->value.integer.value[1] = val2;
+
+       return 0;
+}
+
+static int snd_wm8776_ctl_put(struct snd_kcontrol *kcontrol,
+                                 struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_wm8776 *wm = snd_kcontrol_chip(kcontrol);
+       int n = kcontrol->private_value;
+       u16 val, regval1, regval2;
+
+       /* this also works for enum because value is an union */
+       regval1 = ucontrol->value.integer.value[0];
+       regval2 = ucontrol->value.integer.value[1];
+       if (wm->ctl[n].flags & WM8776_FLAG_INVERT) {
+               regval1 = wm->ctl[n].max - (regval1 - wm->ctl[n].min);
+               regval2 = wm->ctl[n].max - (regval2 - wm->ctl[n].min);
+       }
+       if (wm->ctl[n].set)
+               wm->ctl[n].set(wm, regval1, regval2);
+       else {
+               val = wm->regs[wm->ctl[n].reg1] & ~wm->ctl[n].mask1;
+               val |= regval1 << __ffs(wm->ctl[n].mask1);
+               /* both stereo controls in one register */
+               if (wm->ctl[n].flags & WM8776_FLAG_STEREO &&
+                               wm->ctl[n].reg1 == wm->ctl[n].reg2) {
+                       val &= ~wm->ctl[n].mask2;
+                       val |= regval2 << __ffs(wm->ctl[n].mask2);
+               }
+               snd_wm8776_write(wm, wm->ctl[n].reg1, val);
+               /* stereo controls in different registers */
+               if (wm->ctl[n].flags & WM8776_FLAG_STEREO &&
+                               wm->ctl[n].reg1 != wm->ctl[n].reg2) {
+                       val = wm->regs[wm->ctl[n].reg2] & ~wm->ctl[n].mask2;
+                       val |= regval2 << __ffs(wm->ctl[n].mask2);
+                       if (wm->ctl[n].flags & WM8776_FLAG_VOL_UPDATE)
+                               val |= WM8776_VOL_UPDATE;
+                       snd_wm8776_write(wm, wm->ctl[n].reg2, val);
+               }
+       }
+
+       return 0;
+}
+
+static int snd_wm8776_add_control(struct snd_wm8776 *wm, int num)
+{
+       struct snd_kcontrol_new cont;
+       struct snd_kcontrol *ctl;
+
+       memset(&cont, 0, sizeof(cont));
+       cont.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+       cont.private_value = num;
+       cont.name = wm->ctl[num].name;
+       cont.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
+       if (wm->ctl[num].flags & WM8776_FLAG_LIM ||
+           wm->ctl[num].flags & WM8776_FLAG_ALC)
+               cont.access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
+       cont.tlv.p = NULL;
+       cont.get = snd_wm8776_ctl_get;
+       cont.put = snd_wm8776_ctl_put;
+
+       switch (wm->ctl[num].type) {
+       case SNDRV_CTL_ELEM_TYPE_INTEGER:
+               cont.info = snd_wm8776_volume_info;
+               cont.access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
+               cont.tlv.p = wm->ctl[num].tlv;
+               break;
+       case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
+               wm->ctl[num].max = 1;
+               if (wm->ctl[num].flags & WM8776_FLAG_STEREO)
+                       cont.info = snd_ctl_boolean_stereo_info;
+               else
+                       cont.info = snd_ctl_boolean_mono_info;
+               break;
+       case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
+               cont.info = snd_wm8776_enum_info;
+               break;
+       default:
+               return -EINVAL;
+       }
+       ctl = snd_ctl_new1(&cont, wm);
+       if (!ctl)
+               return -ENOMEM;
+
+       return snd_ctl_add(wm->card, ctl);
+}
+
+int snd_wm8776_build_controls(struct snd_wm8776 *wm)
+{
+       int err, i;
+
+       for (i = 0; i < WM8776_CTL_COUNT; i++)
+               if (wm->ctl[i].name) {
+                       err = snd_wm8776_add_control(wm, i);
+                       if (err < 0)
+                               return err;
+               }
+
+       return 0;
+}
diff --git a/sound/pci/ice1712/wm8776.h b/sound/pci/ice1712/wm8776.h
new file mode 100644 (file)
index 0000000..93a2d69
--- /dev/null
@@ -0,0 +1,226 @@
+#ifndef __SOUND_WM8776_H
+#define __SOUND_WM8776_H
+
+/*
+ *   ALSA driver for ICEnsemble VT17xx
+ *
+ *   Lowlevel functions for WM8776 codec
+ *
+ *     Copyright (c) 2012 Ondrej Zary <linux@rainbow-software.org>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#define WM8776_REG_HPLVOL      0x00
+#define WM8776_REG_HPRVOL      0x01
+#define WM8776_REG_HPMASTER    0x02
+#define WM8776_HPVOL_MASK              0x17f           /* incl. update bit */
+#define WM8776_VOL_HPZCEN              (1 << 7)        /* zero cross detect */
+#define WM8776_VOL_UPDATE              (1 << 8)        /* update volume */
+#define WM8776_REG_DACLVOL     0x03
+#define WM8776_REG_DACRVOL     0x04
+#define WM8776_REG_DACMASTER   0x05
+#define WM8776_DACVOL_MASK             0x1ff           /* incl. update bit */
+#define WM8776_REG_PHASESWAP   0x06
+#define WM8776_PHASE_INVERTL           (1 << 0)
+#define WM8776_PHASE_INVERTR           (1 << 1)
+#define WM8776_REG_DACCTRL1    0x07
+#define WM8776_DAC_DZCEN               (1 << 0)
+#define WM8776_DAC_ATC                 (1 << 1)
+#define WM8776_DAC_IZD                 (1 << 2)
+#define WM8776_DAC_TOD                 (1 << 3)
+#define WM8776_DAC_PL_MASK             0xf0
+#define WM8776_DAC_PL_LL               (1 << 4)        /* L chan: L signal */
+#define WM8776_DAC_PL_LR               (2 << 4)        /* L chan: R signal */
+#define WM8776_DAC_PL_LB               (3 << 4)        /* L chan: both */
+#define WM8776_DAC_PL_RL               (1 << 6)        /* R chan: L signal */
+#define WM8776_DAC_PL_RR               (2 << 6)        /* R chan: R signal */
+#define WM8776_DAC_PL_RB               (3 << 6)        /* R chan: both */
+#define WM8776_REG_DACMUTE     0x08
+#define WM8776_DACMUTE                 (1 << 0)
+#define WM8776_REG_DACCTRL2    0x09
+#define WM8776_DAC2_DEEMPH             (1 << 0)
+#define WM8776_DAC2_ZFLAG_DISABLE      (0 << 1)
+#define WM8776_DAC2_ZFLAG_OWN          (1 << 1)
+#define WM8776_DAC2_ZFLAG_BOTH         (2 << 1)
+#define WM8776_DAC2_ZFLAG_EITHER       (3 << 1)
+#define WM8776_REG_DACIFCTRL   0x0a
+#define WM8776_FMT_RIGHTJ              (0 << 0)
+#define WM8776_FMT_LEFTJ               (1 << 0)
+#define WM8776_FMT_I2S                 (2 << 0)
+#define WM8776_FMT_DSP                 (3 << 0)
+#define WM8776_FMT_DSP_LATE            (1 << 2)        /* in DSP mode */
+#define WM8776_FMT_LRC_INVERTED                (1 << 2)        /* in other modes */
+#define WM8776_FMT_BCLK_INVERTED       (1 << 3)
+#define WM8776_FMT_16BIT               (0 << 4)
+#define WM8776_FMT_20BIT               (1 << 4)
+#define WM8776_FMT_24BIT               (2 << 4)
+#define WM8776_FMT_32BIT               (3 << 4)
+#define WM8776_REG_ADCIFCTRL   0x0b
+#define WM8776_FMT_ADCMCLK_INVERTED    (1 << 6)
+#define WM8776_FMT_ADCHPD              (1 << 8)
+#define WM8776_REG_MSTRCTRL    0x0c
+#define WM8776_IF_ADC256FS             (2 << 0)
+#define WM8776_IF_ADC384FS             (3 << 0)
+#define WM8776_IF_ADC512FS             (4 << 0)
+#define WM8776_IF_ADC768FS             (5 << 0)
+#define WM8776_IF_OVERSAMP64           (1 << 3)
+#define WM8776_IF_DAC128FS             (0 << 4)
+#define WM8776_IF_DAC192FS             (1 << 4)
+#define WM8776_IF_DAC256FS             (2 << 4)
+#define WM8776_IF_DAC384FS             (3 << 4)
+#define WM8776_IF_DAC512FS             (4 << 4)
+#define WM8776_IF_DAC768FS             (5 << 4)
+#define WM8776_IF_DAC_MASTER           (1 << 7)
+#define WM8776_IF_ADC_MASTER           (1 << 8)
+#define WM8776_REG_PWRDOWN     0x0d
+#define WM8776_PWR_PDWN                        (1 << 0)
+#define WM8776_PWR_ADCPD               (1 << 1)
+#define WM8776_PWR_DACPD               (1 << 2)
+#define WM8776_PWR_HPPD                        (1 << 3)
+#define WM8776_PWR_AINPD               (1 << 6)
+#define WM8776_REG_ADCLVOL     0x0e
+#define WM8776_REG_ADCRVOL     0x0f
+#define WM8776_ADC_GAIN_MASK           0xff
+#define WM8776_ADC_ZCEN                        (1 << 8)
+#define WM8776_REG_ALCCTRL1    0x10
+#define WM8776_ALC1_LCT_MASK           0x0f    /* 0=-16dB, 1=-15dB..15=-1dB */
+#define WM8776_ALC1_MAXGAIN_MASK       0x70    /* 0,1=0dB, 2=+4dB...7=+24dB */
+#define WM8776_ALC1_LCSEL_MASK         0x180
+#define WM8776_ALC1_LCSEL_LIMITER      (0 << 7)
+#define WM8776_ALC1_LCSEL_ALCR         (1 << 7)
+#define WM8776_ALC1_LCSEL_ALCL         (2 << 7)
+#define WM8776_ALC1_LCSEL_ALCSTEREO    (3 << 7)
+#define WM8776_REG_ALCCTRL2    0x11
+#define WM8776_ALC2_HOLD_MASK          0x0f    /*0=0ms, 1=2.67ms, 2=5.33ms.. */
+#define WM8776_ALC2_ZCEN               (1 << 7)
+#define WM8776_ALC2_LCEN               (1 << 8)
+#define WM8776_REG_ALCCTRL3    0x12
+#define WM8776_ALC3_ATK_MASK           0x0f
+#define WM8776_ALC3_DCY_MASK           0xf0
+#define WM8776_ALC3_FDECAY             (1 << 8)
+#define WM8776_REG_NOISEGATE   0x13
+#define WM8776_NGAT_ENABLE             (1 << 0)
+#define WM8776_NGAT_THR_MASK           0x1c    /*0=-78dB, 1=-72dB...7=-36dB */
+#define WM8776_REG_LIMITER     0x14
+#define WM8776_LIM_MAXATTEN_MASK       0x0f
+#define WM8776_LIM_TRANWIN_MASK                0x70    /*0=0us, 1=62.5us, 2=125us.. */
+#define WM8776_REG_ADCMUX      0x15
+#define WM8776_ADC_MUX_AIN1            (1 << 0)
+#define WM8776_ADC_MUX_AIN2            (1 << 1)
+#define WM8776_ADC_MUX_AIN3            (1 << 2)
+#define WM8776_ADC_MUX_AIN4            (1 << 3)
+#define WM8776_ADC_MUX_AIN5            (1 << 4)
+#define WM8776_ADC_MUTER               (1 << 6)
+#define WM8776_ADC_MUTEL               (1 << 7)
+#define WM8776_ADC_LRBOTH              (1 << 8)
+#define WM8776_REG_OUTMUX      0x16
+#define WM8776_OUTMUX_DAC              (1 << 0)
+#define WM8776_OUTMUX_AUX              (1 << 1)
+#define WM8776_OUTMUX_BYPASS           (1 << 2)
+#define WM8776_REG_RESET       0x17
+
+#define WM8776_REG_COUNT       0x17    /* don't cache the RESET register */
+
+struct snd_wm8776;
+
+struct snd_wm8776_ops {
+       void (*write)(struct snd_wm8776 *wm, u8 addr, u8 data);
+};
+
+enum snd_wm8776_ctl_id {
+       WM8776_CTL_DAC_VOL,
+       WM8776_CTL_DAC_SW,
+       WM8776_CTL_DAC_ZC_SW,
+       WM8776_CTL_HP_VOL,
+       WM8776_CTL_HP_SW,
+       WM8776_CTL_HP_ZC_SW,
+       WM8776_CTL_AUX_SW,
+       WM8776_CTL_BYPASS_SW,
+       WM8776_CTL_DAC_IZD_SW,
+       WM8776_CTL_PHASE_SW,
+       WM8776_CTL_DEEMPH_SW,
+       WM8776_CTL_ADC_VOL,
+       WM8776_CTL_ADC_SW,
+       WM8776_CTL_INPUT1_SW,
+       WM8776_CTL_INPUT2_SW,
+       WM8776_CTL_INPUT3_SW,
+       WM8776_CTL_INPUT4_SW,
+       WM8776_CTL_INPUT5_SW,
+       WM8776_CTL_AGC_SEL,
+       WM8776_CTL_LIM_THR,
+       WM8776_CTL_LIM_ATK,
+       WM8776_CTL_LIM_DCY,
+       WM8776_CTL_LIM_TRANWIN,
+       WM8776_CTL_LIM_MAXATTN,
+       WM8776_CTL_ALC_TGT,
+       WM8776_CTL_ALC_ATK,
+       WM8776_CTL_ALC_DCY,
+       WM8776_CTL_ALC_MAXGAIN,
+       WM8776_CTL_ALC_MAXATTN,
+       WM8776_CTL_ALC_HLD,
+       WM8776_CTL_NGT_SW,
+       WM8776_CTL_NGT_THR,
+
+       WM8776_CTL_COUNT,
+};
+
+#define WM8776_ENUM_MAX                16
+
+#define WM8776_FLAG_STEREO     (1 << 0)
+#define WM8776_FLAG_VOL_UPDATE (1 << 1)
+#define WM8776_FLAG_INVERT     (1 << 2)
+#define WM8776_FLAG_LIM                (1 << 3)
+#define WM8776_FLAG_ALC                (1 << 4)
+
+struct snd_wm8776_ctl {
+       const char *name;
+       snd_ctl_elem_type_t type;
+       const char *const enum_names[WM8776_ENUM_MAX];
+       const unsigned int *tlv;
+       u16 reg1, reg2, mask1, mask2, min, max, flags;
+       void (*set)(struct snd_wm8776 *wm, u16 ch1, u16 ch2);
+       void (*get)(struct snd_wm8776 *wm, u16 *ch1, u16 *ch2);
+};
+
+enum snd_wm8776_agc_mode {
+       WM8776_AGC_OFF,
+       WM8776_AGC_LIM,
+       WM8776_AGC_ALC_R,
+       WM8776_AGC_ALC_L,
+       WM8776_AGC_ALC_STEREO
+};
+
+struct snd_wm8776 {
+       struct snd_card *card;
+       struct snd_wm8776_ctl ctl[WM8776_CTL_COUNT];
+       enum snd_wm8776_agc_mode agc_mode;
+       struct snd_wm8776_ops ops;
+       u16 regs[WM8776_REG_COUNT];     /* 9-bit registers */
+};
+
+
+
+void snd_wm8776_init(struct snd_wm8776 *wm);
+void snd_wm8776_resume(struct snd_wm8776 *wm);
+void snd_wm8776_set_dac_if(struct snd_wm8776 *wm, u16 dac);
+void snd_wm8776_set_adc_if(struct snd_wm8776 *wm, u16 adc);
+void snd_wm8776_set_master_mode(struct snd_wm8776 *wm, u16 mode);
+void snd_wm8776_set_power(struct snd_wm8776 *wm, u16 power);
+void snd_wm8776_volume_restore(struct snd_wm8776 *wm);
+int snd_wm8776_build_controls(struct snd_wm8776 *wm);
+
+#endif /* __SOUND_WM8776_H */
index e618f789026ea7dc4ff2ddddf4fc46a3e1328a39..184163bbd73251f4dad875e34fb37f0a190e5a39 100644 (file)
@@ -25,7 +25,6 @@
 
 
 
-#include <linux/io.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
index b12308b5ba2a01170b56b5cd7b69a9d1d93aa6e3..f1cd1e387801bee9d73692f02ec7a2bca546ca28 100644 (file)
@@ -971,6 +971,7 @@ static inline void snd_hdspm_initialize_midi_flush(struct hdspm *hdspm);
 static int hdspm_update_simple_mixer_controls(struct hdspm *hdspm);
 static int hdspm_autosync_ref(struct hdspm *hdspm);
 static int snd_hdspm_set_defaults(struct hdspm *hdspm);
+static int hdspm_system_clock_mode(struct hdspm *hdspm);
 static void hdspm_set_sgbuf(struct hdspm *hdspm,
                            struct snd_pcm_substream *substream,
                             unsigned int reg, int channels);
@@ -1989,10 +1990,14 @@ static int hdspm_get_system_sample_rate(struct hdspm *hdspm)
        rate = hdspm_calc_dds_value(hdspm, period);
 
        if (rate > 207000) {
-               /* Unreasonable high sample rate as seen on PCI MADI cards.
-                * Use the cached value instead.
-                */
-               rate = hdspm->system_sample_rate;
+               /* Unreasonable high sample rate as seen on PCI MADI cards. */
+               if (0 == hdspm_system_clock_mode(hdspm)) {
+                       /* master mode, return internal sample rate */
+                       rate = hdspm->system_sample_rate;
+               } else {
+                       /* slave mode, return external sample rate */
+                       rate = hdspm_external_sample_rate(hdspm);
+               }
        }
 
        return rate;
@@ -2000,12 +2005,14 @@ static int hdspm_get_system_sample_rate(struct hdspm *hdspm)
 
 
 #define HDSPM_SYSTEM_SAMPLE_RATE(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-  .name = xname, \
-  .index = xindex, \
-  .access = SNDRV_CTL_ELEM_ACCESS_READ, \
-  .info = snd_hdspm_info_system_sample_rate, \
-  .get = snd_hdspm_get_system_sample_rate \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+       .name = xname, \
+       .index = xindex, \
+       .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
+               SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
+       .info = snd_hdspm_info_system_sample_rate, \
+       .put = snd_hdspm_put_system_sample_rate, \
+       .get = snd_hdspm_get_system_sample_rate \
 }
 
 static int snd_hdspm_info_system_sample_rate(struct snd_kcontrol *kcontrol,
@@ -2030,6 +2037,16 @@ static int snd_hdspm_get_system_sample_rate(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
+static int snd_hdspm_put_system_sample_rate(struct snd_kcontrol *kcontrol,
+                                           struct snd_ctl_elem_value *
+                                           ucontrol)
+{
+       struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
+
+       hdspm_set_dds_value(hdspm, ucontrol->value.enumerated.item[0]);
+       return 0;
+}
+
 
 /**
  * Returns the WordClock sample rate class for the given card.
@@ -2163,6 +2180,7 @@ static int snd_hdspm_get_autosync_sample_rate(struct snd_kcontrol *kcontrol,
                                hdspm_get_s1_sample_rate(hdspm,
                                                kcontrol->private_value-1);
                }
+               break;
 
        case AIO:
                switch (kcontrol->private_value) {
@@ -2183,6 +2201,7 @@ static int snd_hdspm_get_autosync_sample_rate(struct snd_kcontrol *kcontrol,
                                hdspm_get_s1_sample_rate(hdspm,
                                                ucontrol->id.index-1);
                }
+               break;
 
        case AES32:
 
@@ -2204,8 +2223,23 @@ static int snd_hdspm_get_autosync_sample_rate(struct snd_kcontrol *kcontrol,
                                hdspm_get_s1_sample_rate(hdspm,
                                                kcontrol->private_value-1);
                        break;
+               }
+               break;
 
+       case MADI:
+       case MADIface:
+               {
+                       int rate = hdspm_external_sample_rate(hdspm);
+                       int i, selected_rate = 0;
+                       for (i = 1; i < 10; i++)
+                               if (HDSPM_bit2freq(i) == rate) {
+                                       selected_rate = i;
+                                       break;
+                               }
+                       ucontrol->value.enumerated.item[0] = selected_rate;
                }
+               break;
+
        default:
                break;
        }
@@ -2430,7 +2464,7 @@ static int snd_hdspm_put_clock_source(struct snd_kcontrol *kcontrol,
 
 
 #define HDSPM_PREF_SYNC_REF(xname, xindex) \
-{.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
        .name = xname, \
        .index = xindex, \
        .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
@@ -2766,12 +2800,12 @@ static int snd_hdspm_put_pref_sync_ref(struct snd_kcontrol *kcontrol,
 
 
 #define HDSPM_AUTOSYNC_REF(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-  .name = xname, \
-  .index = xindex, \
-  .access = SNDRV_CTL_ELEM_ACCESS_READ, \
-  .info = snd_hdspm_info_autosync_ref, \
-  .get = snd_hdspm_get_autosync_ref, \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+       .name = xname, \
+       .index = xindex, \
+       .access = SNDRV_CTL_ELEM_ACCESS_READ, \
+       .info = snd_hdspm_info_autosync_ref, \
+       .get = snd_hdspm_get_autosync_ref, \
 }
 
 static int hdspm_autosync_ref(struct hdspm *hdspm)
@@ -2855,12 +2889,12 @@ static int snd_hdspm_get_autosync_ref(struct snd_kcontrol *kcontrol,
 
 
 #define HDSPM_LINE_OUT(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-  .name = xname, \
-  .index = xindex, \
-  .info = snd_hdspm_info_line_out, \
-  .get = snd_hdspm_get_line_out, \
-  .put = snd_hdspm_put_line_out \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+       .name = xname, \
+       .index = xindex, \
+       .info = snd_hdspm_info_line_out, \
+       .get = snd_hdspm_get_line_out, \
+       .put = snd_hdspm_put_line_out \
 }
 
 static int hdspm_line_out(struct hdspm * hdspm)
@@ -2912,12 +2946,12 @@ static int snd_hdspm_put_line_out(struct snd_kcontrol *kcontrol,
 
 
 #define HDSPM_TX_64(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-  .name = xname, \
-  .index = xindex, \
-  .info = snd_hdspm_info_tx_64, \
-  .get = snd_hdspm_get_tx_64, \
-  .put = snd_hdspm_put_tx_64 \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+       .name = xname, \
+       .index = xindex, \
+       .info = snd_hdspm_info_tx_64, \
+       .get = snd_hdspm_get_tx_64, \
+       .put = snd_hdspm_put_tx_64 \
 }
 
 static int hdspm_tx_64(struct hdspm * hdspm)
@@ -2968,12 +3002,12 @@ static int snd_hdspm_put_tx_64(struct snd_kcontrol *kcontrol,
 
 
 #define HDSPM_C_TMS(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-  .name = xname, \
-  .index = xindex, \
-  .info = snd_hdspm_info_c_tms, \
-  .get = snd_hdspm_get_c_tms, \
-  .put = snd_hdspm_put_c_tms \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+       .name = xname, \
+       .index = xindex, \
+       .info = snd_hdspm_info_c_tms, \
+       .get = snd_hdspm_get_c_tms, \
+       .put = snd_hdspm_put_c_tms \
 }
 
 static int hdspm_c_tms(struct hdspm * hdspm)
@@ -3024,12 +3058,12 @@ static int snd_hdspm_put_c_tms(struct snd_kcontrol *kcontrol,
 
 
 #define HDSPM_SAFE_MODE(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-  .name = xname, \
-  .index = xindex, \
-  .info = snd_hdspm_info_safe_mode, \
-  .get = snd_hdspm_get_safe_mode, \
-  .put = snd_hdspm_put_safe_mode \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+       .name = xname, \
+       .index = xindex, \
+       .info = snd_hdspm_info_safe_mode, \
+       .get = snd_hdspm_get_safe_mode, \
+       .put = snd_hdspm_put_safe_mode \
 }
 
 static int hdspm_safe_mode(struct hdspm * hdspm)
@@ -3080,12 +3114,12 @@ static int snd_hdspm_put_safe_mode(struct snd_kcontrol *kcontrol,
 
 
 #define HDSPM_EMPHASIS(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-  .name = xname, \
-  .index = xindex, \
-  .info = snd_hdspm_info_emphasis, \
-  .get = snd_hdspm_get_emphasis, \
-  .put = snd_hdspm_put_emphasis \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+       .name = xname, \
+       .index = xindex, \
+       .info = snd_hdspm_info_emphasis, \
+       .get = snd_hdspm_get_emphasis, \
+       .put = snd_hdspm_put_emphasis \
 }
 
 static int hdspm_emphasis(struct hdspm * hdspm)
@@ -3136,12 +3170,12 @@ static int snd_hdspm_put_emphasis(struct snd_kcontrol *kcontrol,
 
 
 #define HDSPM_DOLBY(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-  .name = xname, \
-  .index = xindex, \
-  .info = snd_hdspm_info_dolby, \
-  .get = snd_hdspm_get_dolby, \
-  .put = snd_hdspm_put_dolby \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+       .name = xname, \
+       .index = xindex, \
+       .info = snd_hdspm_info_dolby, \
+       .get = snd_hdspm_get_dolby, \
+       .put = snd_hdspm_put_dolby \
 }
 
 static int hdspm_dolby(struct hdspm * hdspm)
@@ -3192,12 +3226,12 @@ static int snd_hdspm_put_dolby(struct snd_kcontrol *kcontrol,
 
 
 #define HDSPM_PROFESSIONAL(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-  .name = xname, \
-  .index = xindex, \
-  .info = snd_hdspm_info_professional, \
-  .get = snd_hdspm_get_professional, \
-  .put = snd_hdspm_put_professional \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+       .name = xname, \
+       .index = xindex, \
+       .info = snd_hdspm_info_professional, \
+       .get = snd_hdspm_get_professional, \
+       .put = snd_hdspm_put_professional \
 }
 
 static int hdspm_professional(struct hdspm * hdspm)
@@ -3247,12 +3281,12 @@ static int snd_hdspm_put_professional(struct snd_kcontrol *kcontrol,
 }
 
 #define HDSPM_INPUT_SELECT(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-  .name = xname, \
-  .index = xindex, \
-  .info = snd_hdspm_info_input_select, \
-  .get = snd_hdspm_get_input_select, \
-  .put = snd_hdspm_put_input_select \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+       .name = xname, \
+       .index = xindex, \
+       .info = snd_hdspm_info_input_select, \
+       .get = snd_hdspm_get_input_select, \
+       .put = snd_hdspm_put_input_select \
 }
 
 static int hdspm_input_select(struct hdspm * hdspm)
@@ -3319,12 +3353,12 @@ static int snd_hdspm_put_input_select(struct snd_kcontrol *kcontrol,
 
 
 #define HDSPM_DS_WIRE(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-  .name = xname, \
-  .index = xindex, \
-  .info = snd_hdspm_info_ds_wire, \
-  .get = snd_hdspm_get_ds_wire, \
-  .put = snd_hdspm_put_ds_wire \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+       .name = xname, \
+       .index = xindex, \
+       .info = snd_hdspm_info_ds_wire, \
+       .get = snd_hdspm_get_ds_wire, \
+       .put = snd_hdspm_put_ds_wire \
 }
 
 static int hdspm_ds_wire(struct hdspm * hdspm)
@@ -3391,12 +3425,12 @@ static int snd_hdspm_put_ds_wire(struct snd_kcontrol *kcontrol,
 
 
 #define HDSPM_QS_WIRE(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-  .name = xname, \
-  .index = xindex, \
-  .info = snd_hdspm_info_qs_wire, \
-  .get = snd_hdspm_get_qs_wire, \
-  .put = snd_hdspm_put_qs_wire \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+       .name = xname, \
+       .index = xindex, \
+       .info = snd_hdspm_info_qs_wire, \
+       .get = snd_hdspm_get_qs_wire, \
+       .put = snd_hdspm_put_qs_wire \
 }
 
 static int hdspm_qs_wire(struct hdspm * hdspm)
@@ -3563,15 +3597,15 @@ static int snd_hdspm_put_madi_speedmode(struct snd_kcontrol *kcontrol,
 }
 
 #define HDSPM_MIXER(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
-  .name = xname, \
-  .index = xindex, \
-  .device = 0, \
-  .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
-                SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
-  .info = snd_hdspm_info_mixer, \
-  .get = snd_hdspm_get_mixer, \
-  .put = snd_hdspm_put_mixer \
+{      .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+       .name = xname, \
+       .index = xindex, \
+       .device = 0, \
+       .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
+               SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
+       .info = snd_hdspm_info_mixer, \
+       .get = snd_hdspm_get_mixer, \
+       .put = snd_hdspm_put_mixer \
 }
 
 static int snd_hdspm_info_mixer(struct snd_kcontrol *kcontrol,
@@ -3670,12 +3704,12 @@ static int snd_hdspm_put_mixer(struct snd_kcontrol *kcontrol,
 */
 
 #define HDSPM_PLAYBACK_MIXER \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-  .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE | \
-                SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
-  .info = snd_hdspm_info_playback_mixer, \
-  .get = snd_hdspm_get_playback_mixer, \
-  .put = snd_hdspm_put_playback_mixer \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+       .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE | \
+               SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
+       .info = snd_hdspm_info_playback_mixer, \
+       .get = snd_hdspm_get_playback_mixer, \
+       .put = snd_hdspm_put_playback_mixer \
 }
 
 static int snd_hdspm_info_playback_mixer(struct snd_kcontrol *kcontrol,
@@ -3851,12 +3885,17 @@ static int hdspm_sync_in_sync_check(struct hdspm *hdspm)
                break;
 
        case MADI:
-       case AES32:
-               status = hdspm_read(hdspm, HDSPM_statusRegister2);
+               status = hdspm_read(hdspm, HDSPM_statusRegister);
                lock = (status & HDSPM_syncInLock) ? 1 : 0;
                sync = (status & HDSPM_syncInSync) ? 1 : 0;
                break;
 
+       case AES32:
+               status = hdspm_read(hdspm, HDSPM_statusRegister2);
+               lock = (status & 0x100000) ? 1 : 0;
+               sync = (status & 0x200000) ? 1 : 0;
+               break;
+
        case MADIface:
                break;
        }
@@ -3942,6 +3981,7 @@ static int snd_hdspm_get_sync_check(struct snd_kcontrol *kcontrol,
                default:
                        val = hdspm_s1_sync_check(hdspm, ucontrol->id.index-1);
                }
+               break;
 
        case AIO:
                switch (kcontrol->private_value) {
@@ -3954,6 +3994,7 @@ static int snd_hdspm_get_sync_check(struct snd_kcontrol *kcontrol,
                default:
                        val = hdspm_s1_sync_check(hdspm, ucontrol->id.index-1);
                }
+               break;
 
        case MADI:
                switch (kcontrol->private_value) {
@@ -3966,6 +4007,7 @@ static int snd_hdspm_get_sync_check(struct snd_kcontrol *kcontrol,
                case 3: /* SYNC_IN */
                        val = hdspm_sync_in_sync_check(hdspm); break;
                }
+               break;
 
        case MADIface:
                val = hdspm_madi_sync_check(hdspm); /* MADI */
@@ -3983,6 +4025,7 @@ static int snd_hdspm_get_sync_check(struct snd_kcontrol *kcontrol,
                         val = hdspm_aes_sync_check(hdspm,
                                         kcontrol->private_value-1);
                }
+               break;
 
        }
 
@@ -4427,9 +4470,10 @@ static struct snd_kcontrol_new snd_hdspm_controls_madi[] = {
        HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
        HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
        HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
+       HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
        HDSPM_SYNC_CHECK("WC SyncCheck", 0),
        HDSPM_SYNC_CHECK("MADI SyncCheck", 1),
-       HDSPM_SYNC_CHECK("TCO SyncCHeck", 2),
+       HDSPM_SYNC_CHECK("TCO SyncCheck", 2),
        HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 3),
        HDSPM_LINE_OUT("Line Out", 0),
        HDSPM_TX_64("TX 64 channels mode", 0),
index c88351488f45c5c6adb0529a212ab257531a90fd..228ca6a8e77bf5d1a6d609fa4646c38607e21e5c 100644 (file)
@@ -195,22 +195,15 @@ static struct snd_soc_card snd_soc_at91sam9g20ek = {
        .set_bias_level = at91sam9g20ek_set_bias_level,
 };
 
-static struct platform_device *at91sam9g20ek_snd_device;
-
-static int __init at91sam9g20ek_init(void)
+static int __devinit at91sam9g20ek_audio_probe(struct platform_device *pdev)
 {
        struct clk *pllb;
+       struct snd_soc_card *card = &snd_soc_at91sam9g20ek;
        int ret;
 
        if (!(machine_is_at91sam9g20ek() || machine_is_at91sam9g20ek_2mmc()))
                return -ENODEV;
 
-       ret = atmel_ssc_set_audio(0);
-       if (ret != 0) {
-               pr_err("Failed to set SSC 0 for audio: %d\n", ret);
-               return ret;
-       }
-
        /*
         * Codec MCLK is supplied by PCK0 - set it up.
         */
@@ -236,26 +229,14 @@ static int __init at91sam9g20ek_init(void)
 
        clk_set_rate(mclk, MCLK_RATE);
 
-       at91sam9g20ek_snd_device = platform_device_alloc("soc-audio", -1);
-       if (!at91sam9g20ek_snd_device) {
-               printk(KERN_ERR "ASoC: Platform device allocation failed\n");
-               ret = -ENOMEM;
-               goto err_mclk;
-       }
-
-       platform_set_drvdata(at91sam9g20ek_snd_device,
-                       &snd_soc_at91sam9g20ek);
-
-       ret = platform_device_add(at91sam9g20ek_snd_device);
+       card->dev = &pdev->dev;
+       ret = snd_soc_register_card(card);
        if (ret) {
-               printk(KERN_ERR "ASoC: Platform device allocation failed\n");
-               goto err_device_add;
+               printk(KERN_ERR "ASoC: snd_soc_register_card() failed\n");
        }
 
        return ret;
 
-err_device_add:
-       platform_device_put(at91sam9g20ek_snd_device);
 err_mclk:
        clk_put(mclk);
        mclk = NULL;
@@ -263,18 +244,30 @@ err:
        return ret;
 }
 
-static void __exit at91sam9g20ek_exit(void)
+static int __devexit at91sam9g20ek_audio_remove(struct platform_device *pdev)
 {
-       platform_device_unregister(at91sam9g20ek_snd_device);
-       at91sam9g20ek_snd_device = NULL;
+       struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+       snd_soc_unregister_card(card);
        clk_put(mclk);
        mclk = NULL;
+
+       return 0;
 }
 
-module_init(at91sam9g20ek_init);
-module_exit(at91sam9g20ek_exit);
+static struct platform_driver at91sam9g20ek_audio_driver = {
+       .driver = {
+               .name   = "at91sam9g20ek-audio",
+               .owner  = THIS_MODULE,
+       },
+       .probe  = at91sam9g20ek_audio_probe,
+       .remove = __devexit_p(at91sam9g20ek_audio_remove),
+};
+
+module_platform_driver(at91sam9g20ek_audio_driver);
 
 /* Module information */
 MODULE_AUTHOR("Sedji Gaouaou <sedji.gaouaou@atmel.com>");
 MODULE_DESCRIPTION("ALSA SoC AT91SAM9G20EK_WM8731");
+MODULE_ALIAS("platform:at91sam9g20ek-audio");
 MODULE_LICENSE("GPL");
index b92759a3936157e0884b98f752935ccbef7b8945..6f4f2845f856ec9cdacfec3a93305f75bc71019b 100644 (file)
@@ -54,6 +54,7 @@ config SND_SOC_ALL_CODECS
        select SND_SOC_PCM3008
        select SND_SOC_RT5631 if I2C
        select SND_SOC_SGTL5000 if I2C
+       select SND_SOC_SI476X if MFD_SI476X_CORE
        select SND_SOC_SN95031 if INTEL_SCU_IPC
        select SND_SOC_SPDIF
        select SND_SOC_SSM2602 if SND_SOC_I2C_AND_SPI
@@ -277,6 +278,9 @@ config SND_SOC_RT5631
 config SND_SOC_SGTL5000
        tristate
 
+config SND_SOC_SI476X
+       tristate
+
 config SND_SOC_SIGMADSP
        tristate
        select CRC32
index 9bd4d95aab4ffcecb9abf5bff4e0c94d7203adee..c55d2d7d06b499b58c88d11b7e0ac64a4ac99c84 100644 (file)
@@ -45,6 +45,7 @@ snd-soc-sgtl5000-objs := sgtl5000.o
 snd-soc-alc5623-objs := alc5623.o
 snd-soc-alc5632-objs := alc5632.o
 snd-soc-sigmadsp-objs := sigmadsp.o
+snd-soc-si476x-objs := si476x.o
 snd-soc-sn95031-objs := sn95031.o
 snd-soc-spdif-tx-objs := spdif_transciever.o
 snd-soc-spdif-rx-objs := spdif_receiver.o
@@ -164,6 +165,7 @@ obj-$(CONFIG_SND_SOC_PCM3008)       += snd-soc-pcm3008.o
 obj-$(CONFIG_SND_SOC_RT5631)   += snd-soc-rt5631.o
 obj-$(CONFIG_SND_SOC_SGTL5000)  += snd-soc-sgtl5000.o
 obj-$(CONFIG_SND_SOC_SIGMADSP) += snd-soc-sigmadsp.o
+obj-$(CONFIG_SND_SOC_SI476X)   += snd-soc-si476x.o
 obj-$(CONFIG_SND_SOC_SN95031)  +=snd-soc-sn95031.o
 obj-$(CONFIG_SND_SOC_SPDIF)    += snd-soc-spdif-rx.o snd-soc-spdif-tx.o
 obj-$(CONFIG_SND_SOC_SSM2602)  += snd-soc-ssm2602.o
index 31d4483245d0db951584a0e1619b91c8ac8fa726..d4d4858088940526105002be6a22870b9d48c0e9 100644 (file)
@@ -98,14 +98,32 @@ static int ak4104_hw_params(struct snd_pcm_substream *substream,
        val = 0;
 
        switch (params_rate(params)) {
+       case 22050:
+               val |= IEC958_AES3_CON_FS_22050;
+               break;
+       case 24000:
+               val |= IEC958_AES3_CON_FS_24000;
+               break;
+       case 32000:
+               val |= IEC958_AES3_CON_FS_32000;
+               break;
        case 44100:
                val |= IEC958_AES3_CON_FS_44100;
                break;
        case 48000:
                val |= IEC958_AES3_CON_FS_48000;
                break;
-       case 32000:
-               val |= IEC958_AES3_CON_FS_32000;
+       case 88200:
+               val |= IEC958_AES3_CON_FS_88200;
+               break;
+       case 96000:
+               val |= IEC958_AES3_CON_FS_96000;
+               break;
+       case 176400:
+               val |= IEC958_AES3_CON_FS_176400;
+               break;
+       case 192000:
+               val |= IEC958_AES3_CON_FS_192000;
                break;
        default:
                dev_err(codec->dev, "unsupported sampling rate\n");
@@ -240,10 +258,17 @@ static int __devexit ak4104_spi_remove(struct spi_device *spi)
        return 0;
 }
 
+static const struct of_device_id ak4104_of_match[] = {
+       { .compatible = "asahi-kasei,ak4104", },
+       { }
+};
+MODULE_DEVICE_TABLE(of, ak4104_of_match);
+
 static struct spi_driver ak4104_spi_driver = {
        .driver  = {
                .name   = DRV_NAME,
                .owner  = THIS_MODULE,
+               .of_match_table = ak4104_of_match,
        },
        .probe  = ak4104_spi_probe,
        .remove = __devexit_p(ak4104_spi_remove),
index f994af34f552f4b08c4e01880c3410a4890afb7c..2ac5fe61a96c9f893cb09014b9fcb2772997fa4c 100644 (file)
@@ -474,15 +474,25 @@ static int cs4271_probe(struct snd_soc_codec *codec)
        struct cs4271_platform_data *cs4271plat = codec->dev->platform_data;
        int ret;
        int gpio_nreset = -EINVAL;
+       int amutec_eq_bmutec = 0;
 
 #ifdef CONFIG_OF
-       if (of_match_device(cs4271_dt_ids, codec->dev))
+       if (of_match_device(cs4271_dt_ids, codec->dev)) {
                gpio_nreset = of_get_named_gpio(codec->dev->of_node,
                                                "reset-gpio", 0);
+
+               if (!of_get_property(codec->dev->of_node,
+                                    "cirrus,amutec-eq-bmutec", NULL))
+                       amutec_eq_bmutec = 1;
+       }
 #endif
 
-       if (cs4271plat && gpio_is_valid(cs4271plat->gpio_nreset))
-               gpio_nreset = cs4271plat->gpio_nreset;
+       if (cs4271plat) {
+               if (gpio_is_valid(cs4271plat->gpio_nreset))
+                       gpio_nreset = cs4271plat->gpio_nreset;
+
+               amutec_eq_bmutec = cs4271plat->amutec_eq_bmutec;
+       }
 
        if (gpio_nreset >= 0)
                if (gpio_request(gpio_nreset, "CS4271 Reset"))
@@ -528,6 +538,11 @@ static int cs4271_probe(struct snd_soc_codec *codec)
        /* Power-up sequence requires 85 uS */
        udelay(85);
 
+       if (amutec_eq_bmutec)
+               snd_soc_update_bits(codec, CS4271_MODE2,
+                                   CS4271_MODE2_MUTECAEQUB,
+                                   CS4271_MODE2_MUTECAEQUB);
+
        return snd_soc_add_codec_controls(codec, cs4271_snd_controls,
                ARRAY_SIZE(cs4271_snd_controls));
 }
index f379b085c39204dfeb2a6fc34d7c07d9f15c9f0b..d3a6de2e757b9f8d0b96fd2ac0f3444f2d017dc5 100644 (file)
 #define DA9055_AIF_FORMAT_I2S_MODE     (0 << 0)
 #define DA9055_AIF_FORMAT_LEFT_J       (1 << 0)
 #define DA9055_AIF_FORMAT_RIGHT_J      (2 << 0)
+#define DA9055_AIF_FORMAT_DSP          (3 << 0)
 #define DA9055_AIF_WORD_S16_LE         (0 << 2)
 #define DA9055_AIF_WORD_S20_3LE                (1 << 2)
 #define DA9055_AIF_WORD_S24_LE         (2 << 2)
@@ -752,6 +753,17 @@ static const struct snd_kcontrol_new da9055_dapm_mixoutr_controls[] = {
                        6, 1, 0),
 };
 
+/* Headphone Output Enable */
+static const struct snd_kcontrol_new da9055_dapm_hp_l_control =
+SOC_DAPM_SINGLE("Switch", DA9055_HP_L_CTRL, 3, 1, 0);
+
+static const struct snd_kcontrol_new da9055_dapm_hp_r_control =
+SOC_DAPM_SINGLE("Switch", DA9055_HP_R_CTRL, 3, 1, 0);
+
+/* Lineout Output Enable */
+static const struct snd_kcontrol_new da9055_dapm_lineout_control =
+SOC_DAPM_SINGLE("Switch", DA9055_LINE_CTRL, 3, 1, 0);
+
 /* DAPM widgets */
 static const struct snd_soc_dapm_widget da9055_dapm_widgets[] = {
        /* Input Side */
@@ -816,6 +828,14 @@ static const struct snd_soc_dapm_widget da9055_dapm_widgets[] = {
                           &da9055_dapm_mixoutr_controls[0],
                           ARRAY_SIZE(da9055_dapm_mixoutr_controls)),
 
+       /* Output Enable Switches */
+       SND_SOC_DAPM_SWITCH("Headphone Left Enable", SND_SOC_NOPM, 0, 0,
+                           &da9055_dapm_hp_l_control),
+       SND_SOC_DAPM_SWITCH("Headphone Right Enable", SND_SOC_NOPM, 0, 0,
+                           &da9055_dapm_hp_r_control),
+       SND_SOC_DAPM_SWITCH("Lineout Enable", SND_SOC_NOPM, 0, 0,
+                           &da9055_dapm_lineout_control),
+
        /* Output PGAs */
        SND_SOC_DAPM_PGA("MIXOUT Left", DA9055_MIXOUT_L_CTRL, 7, 0, NULL, 0),
        SND_SOC_DAPM_PGA("MIXOUT Right", DA9055_MIXOUT_R_CTRL, 7, 0, NULL, 0),
@@ -901,17 +921,20 @@ static const struct snd_soc_dapm_route da9055_audio_map[] = {
        {"Out Mixer Right", "DAC Right Switch", "DAC Right"},
 
        {"MIXOUT Left", NULL, "Out Mixer Left"},
-       {"Headphone Left", NULL, "MIXOUT Left"},
+       {"Headphone Left Enable", "Switch", "MIXOUT Left"},
+       {"Headphone Left", NULL, "Headphone Left Enable"},
        {"Headphone Left", NULL, "Charge Pump"},
        {"HPL", NULL, "Headphone Left"},
 
        {"MIXOUT Right", NULL, "Out Mixer Right"},
-       {"Headphone Right", NULL, "MIXOUT Right"},
+       {"Headphone Right Enable", "Switch", "MIXOUT Right"},
+       {"Headphone Right", NULL, "Headphone Right Enable"},
        {"Headphone Right", NULL, "Charge Pump"},
        {"HPR", NULL, "Headphone Right"},
 
        {"MIXOUT Right", NULL, "Out Mixer Right"},
-       {"Lineout", NULL, "MIXOUT Right"},
+       {"Lineout Enable", "Switch", "MIXOUT Right"},
+       {"Lineout", NULL, "Lineout Enable"},
        {"LINE", NULL, "Lineout"},
 };
 
@@ -1175,6 +1198,9 @@ static int da9055_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
        case SND_SOC_DAIFMT_RIGHT_J:
                aif_ctrl = DA9055_AIF_FORMAT_RIGHT_J;
                break;
+       case SND_SOC_DAIFMT_DSP_A:
+               aif_ctrl = DA9055_AIF_FORMAT_DSP;
+               break;
        default:
                return -EINVAL;
        }
@@ -1390,8 +1416,7 @@ static int da9055_probe(struct snd_soc_codec *codec)
                            DA9055_GAIN_RAMPING_EN, DA9055_GAIN_RAMPING_EN);
 
        /*
-        * There are two separate control bits for input and output mixers as
-        * well as headphone and line outs.
+        * There are two separate control bits for input and output mixers.
         * One to enable corresponding amplifier and other to enable its
         * output. As amplifier bits are related to power control, they are
         * being managed by DAPM while other (non power related) bits are
@@ -1407,14 +1432,6 @@ static int da9055_probe(struct snd_soc_codec *codec)
        snd_soc_update_bits(codec, DA9055_MIXOUT_R_CTRL,
                            DA9055_MIXOUT_R_MIX_EN, DA9055_MIXOUT_R_MIX_EN);
 
-       snd_soc_update_bits(codec, DA9055_HP_L_CTRL,
-                           DA9055_HP_L_AMP_OE, DA9055_HP_L_AMP_OE);
-       snd_soc_update_bits(codec, DA9055_HP_R_CTRL,
-                           DA9055_HP_R_AMP_OE, DA9055_HP_R_AMP_OE);
-
-       snd_soc_update_bits(codec, DA9055_LINE_CTRL,
-                           DA9055_LINE_AMP_OE, DA9055_LINE_AMP_OE);
-
        /* Set this as per your system configuration */
        snd_soc_write(codec, DA9055_PLL_CTRL, DA9055_PLL_INDIV_10_20_MHZ);
 
diff --git a/sound/soc/codecs/si476x.c b/sound/soc/codecs/si476x.c
new file mode 100644 (file)
index 0000000..38145ba
--- /dev/null
@@ -0,0 +1,255 @@
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/initval.h>
+
+#include <linux/i2c.h>
+
+#include <linux/mfd/si476x-core.h>
+
+enum si476x_audio_registers {
+       SI476X_DIGITAL_IO_OUTPUT_FORMAT         = 0x0203,
+       SI476X_DIGITAL_IO_OUTPUT_SAMPLE_RATE    = 0x0202,
+};
+
+enum si476x_digital_io_output_format {
+       SI476X_DIGITAL_IO_SLOT_SIZE_SHIFT       = 11,
+       SI476X_DIGITAL_IO_SAMPLE_SIZE_SHIFT     = 8,
+};
+
+#define SI476X_DIGITAL_IO_OUTPUT_WIDTH_MASK    ((0b111 << SI476X_DIGITAL_IO_SLOT_SIZE_SHIFT) | \
+                                                 (0b111 << SI476X_DIGITAL_IO_SAMPLE_SIZE_SHIFT))
+#define SI476X_DIGITAL_IO_OUTPUT_FORMAT_MASK   (0b1111110)
+
+enum si476x_daudio_formats {
+       SI476X_DAUDIO_MODE_I2S          = (0x0 << 1),
+       SI476X_DAUDIO_MODE_DSP_A        = (0x6 << 1),
+       SI476X_DAUDIO_MODE_DSP_B        = (0x7 << 1),
+       SI476X_DAUDIO_MODE_LEFT_J       = (0x8 << 1),
+       SI476X_DAUDIO_MODE_RIGHT_J      = (0x9 << 1),
+
+       SI476X_DAUDIO_MODE_IB           = (1 << 5),
+       SI476X_DAUDIO_MODE_IF           = (1 << 6),
+};
+
+enum si476x_pcm_format {
+       SI476X_PCM_FORMAT_S8            = 2,
+       SI476X_PCM_FORMAT_S16_LE        = 4,
+       SI476X_PCM_FORMAT_S20_3LE       = 5,
+       SI476X_PCM_FORMAT_S24_LE        = 6,
+};
+
+static unsigned int si476x_codec_read(struct snd_soc_codec *codec,
+                                     unsigned int reg)
+{
+       int err;
+       struct si476x_core *core = codec->control_data;
+
+       si476x_core_lock(core);
+       err = si476x_core_cmd_get_property(core, reg);
+       si476x_core_unlock(core);
+
+       return err;
+}
+
+static int si476x_codec_write(struct snd_soc_codec *codec,
+                             unsigned int reg, unsigned int val)
+{
+       int err;
+       struct si476x_core *core = codec->control_data;
+
+       si476x_core_lock(core);
+       err = si476x_core_cmd_set_property(core, reg, val);
+       si476x_core_unlock(core);
+
+       return err;
+}
+
+static int si476x_codec_set_dai_fmt(struct snd_soc_dai *codec_dai,
+                                   unsigned int fmt)
+{
+       int err;
+       u16 format = 0;
+
+       if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS)
+               return -EINVAL;
+
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_DSP_A:
+               format |= SI476X_DAUDIO_MODE_DSP_A;
+               break;
+       case SND_SOC_DAIFMT_DSP_B:
+               format |= SI476X_DAUDIO_MODE_DSP_B;
+               break;
+       case SND_SOC_DAIFMT_I2S:
+               format |= SI476X_DAUDIO_MODE_I2S;
+               break;
+       case SND_SOC_DAIFMT_RIGHT_J:
+               format |= SI476X_DAUDIO_MODE_RIGHT_J;
+               break;
+       case SND_SOC_DAIFMT_LEFT_J:
+               format |= SI476X_DAUDIO_MODE_LEFT_J;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_DSP_A:
+       case SND_SOC_DAIFMT_DSP_B:
+               switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+               case SND_SOC_DAIFMT_NB_NF:
+                       break;
+               case SND_SOC_DAIFMT_IB_NF:
+                       format |= SI476X_DAUDIO_MODE_IB;
+                       break;
+               default:
+                       return -EINVAL;
+               }
+               break;
+       case SND_SOC_DAIFMT_I2S:
+       case SND_SOC_DAIFMT_RIGHT_J:
+       case SND_SOC_DAIFMT_LEFT_J:
+               switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+               case SND_SOC_DAIFMT_NB_NF:
+                       break;
+               case SND_SOC_DAIFMT_IB_IF:
+                       format |= SI476X_DAUDIO_MODE_IB |
+                               SI476X_DAUDIO_MODE_IF;
+                       break;
+               case SND_SOC_DAIFMT_IB_NF:
+                       format |= SI476X_DAUDIO_MODE_IB;
+                       break;
+               case SND_SOC_DAIFMT_NB_IF:
+                       format |= SI476X_DAUDIO_MODE_IF;
+                       break;
+               default:
+                       return -EINVAL;
+               }
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       err = snd_soc_update_bits(codec_dai->codec, SI476X_DIGITAL_IO_OUTPUT_FORMAT,
+                                 SI476X_DIGITAL_IO_OUTPUT_FORMAT_MASK,
+                                 format);
+       if (err < 0) {
+               dev_err(codec_dai->codec->dev, "Failed to set output format\n");
+               return err;
+       }
+       
+       return 0;
+}
+
+static int si476x_codec_hw_params(struct snd_pcm_substream *substream,
+                                 struct snd_pcm_hw_params *params,
+                                 struct snd_soc_dai *dai)
+{
+       int rate, width, err;
+
+       rate = params_rate(params);
+       if (rate < 32000 || rate > 48000) {
+               dev_err(dai->codec->dev, "Rate: %d is not supported\n", rate);
+               return -EINVAL;
+       }
+
+       switch (params_format(params)) {
+       case SNDRV_PCM_FORMAT_S8:
+               width = SI476X_PCM_FORMAT_S8;
+       case SNDRV_PCM_FORMAT_S16_LE:
+               width = SI476X_PCM_FORMAT_S16_LE;
+               break;
+       case SNDRV_PCM_FORMAT_S20_3LE:
+               width = SI476X_PCM_FORMAT_S20_3LE;
+               break;
+       case SNDRV_PCM_FORMAT_S24_LE:
+               width = SI476X_PCM_FORMAT_S24_LE;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       err = snd_soc_write(dai->codec, SI476X_DIGITAL_IO_OUTPUT_SAMPLE_RATE,
+                           rate);
+       if (err < 0) {
+               dev_err(dai->codec->dev, "Failed to set sample rate\n");
+               return err;
+       }
+
+       err = snd_soc_update_bits(dai->codec, SI476X_DIGITAL_IO_OUTPUT_FORMAT,
+                                 SI476X_DIGITAL_IO_OUTPUT_WIDTH_MASK,
+                                 (width << SI476X_DIGITAL_IO_SLOT_SIZE_SHIFT) | 
+                                 (width << SI476X_DIGITAL_IO_SAMPLE_SIZE_SHIFT));
+       if (err < 0) {
+               dev_err(dai->codec->dev, "Failed to set output width\n");
+               return err;
+       }
+
+       return 0;
+}
+
+static int si476x_codec_probe(struct snd_soc_codec *codec)
+{
+       codec->control_data = i2c_mfd_cell_to_core(codec->dev);
+       return 0;
+}
+
+static struct snd_soc_dai_ops si476x_dai_ops = {
+       .hw_params      = si476x_codec_hw_params,
+       .set_fmt        = si476x_codec_set_dai_fmt,
+};
+
+static struct snd_soc_dai_driver si476x_dai = {
+       .name           = "si476x-codec",
+       .capture        = {
+               .stream_name    = "Capture",
+               .channels_min   = 2,
+               .channels_max   = 2,
+
+               .rates = SNDRV_PCM_RATE_32000 |
+               SNDRV_PCM_RATE_44100 |
+               SNDRV_PCM_RATE_48000,
+               .formats = SNDRV_PCM_FMTBIT_S8 |
+               SNDRV_PCM_FMTBIT_S16_LE |
+               SNDRV_PCM_FMTBIT_S20_3LE |
+               SNDRV_PCM_FMTBIT_S24_LE
+       },
+       .ops            = &si476x_dai_ops,
+};
+
+static struct snd_soc_codec_driver soc_codec_dev_si476x = {
+       .probe  = si476x_codec_probe,
+       .read   = si476x_codec_read,
+       .write  = si476x_codec_write,
+};
+
+static int __devinit si476x_platform_probe(struct platform_device *pdev)
+{
+       return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_si476x,
+                                     &si476x_dai, 1);
+}
+
+static int __devexit si476x_platform_remove(struct platform_device *pdev)
+{
+       snd_soc_unregister_codec(&pdev->dev);
+       return 0;
+}
+
+MODULE_ALIAS("platform:si476x-codec");
+
+static struct platform_driver si476x_platform_driver = {
+       .driver         = {
+               .name   = "si476x-codec",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = si476x_platform_probe,
+       .remove         = __devexit_p(si476x_platform_remove),
+};
+module_platform_driver(si476x_platform_driver);
+
+MODULE_AUTHOR("Andrey Smirnov <andrey.smirnov@convergeddevices.net>");
+MODULE_DESCRIPTION("ASoC Si4761/64 codec driver");
+MODULE_LICENSE("GPL");
index eab64a193989ac2917773a4df7613cbf644dd58f..2148ee31cd662d3661495fea28101908c4a494a8 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/pm.h>
+#include <linux/firmware.h>
 #include <linux/gcd.h>
 #include <linux/gpio.h>
 #include <linux/i2c.h>
 #include <sound/wm2200.h>
 
 #include "wm2200.h"
+#include "wmfw.h"
+
+#define WM2200_DSP_CONTROL_1                   0x00
+#define WM2200_DSP_CONTROL_2                   0x02
+#define WM2200_DSP_CONTROL_3                   0x03
+#define WM2200_DSP_CONTROL_4                   0x04
+#define WM2200_DSP_CONTROL_5                   0x06
+#define WM2200_DSP_CONTROL_6                   0x07
+#define WM2200_DSP_CONTROL_7                   0x08
+#define WM2200_DSP_CONTROL_8                   0x09
+#define WM2200_DSP_CONTROL_9                   0x0A
+#define WM2200_DSP_CONTROL_10                  0x0B
+#define WM2200_DSP_CONTROL_11                  0x0C
+#define WM2200_DSP_CONTROL_12                  0x0D
+#define WM2200_DSP_CONTROL_13                  0x0F
+#define WM2200_DSP_CONTROL_14                  0x10
+#define WM2200_DSP_CONTROL_15                  0x11
+#define WM2200_DSP_CONTROL_16                  0x12
+#define WM2200_DSP_CONTROL_17                  0x13
+#define WM2200_DSP_CONTROL_18                  0x14
+#define WM2200_DSP_CONTROL_19                  0x16
+#define WM2200_DSP_CONTROL_20                  0x17
+#define WM2200_DSP_CONTROL_21                  0x18
+#define WM2200_DSP_CONTROL_22                  0x1A
+#define WM2200_DSP_CONTROL_23                  0x1B
+#define WM2200_DSP_CONTROL_24                  0x1C
+#define WM2200_DSP_CONTROL_25                  0x1E
+#define WM2200_DSP_CONTROL_26                  0x20
+#define WM2200_DSP_CONTROL_27                  0x21
+#define WM2200_DSP_CONTROL_28                  0x22
+#define WM2200_DSP_CONTROL_29                  0x23
+#define WM2200_DSP_CONTROL_30                  0x24
+#define WM2200_DSP_CONTROL_31                  0x26
 
 /* The code assumes DCVDD is generated internally */
 #define WM2200_NUM_CORE_SUPPLIES 2
@@ -64,6 +98,60 @@ struct wm2200_priv {
        int sysclk;
 };
 
+#define WM2200_DSP_RANGE_BASE (WM2200_MAX_REGISTER + 1)
+#define WM2200_DSP_SPACING 12288
+
+#define WM2200_DSP1_DM_BASE (WM2200_DSP_RANGE_BASE + (0 * WM2200_DSP_SPACING))
+#define WM2200_DSP1_PM_BASE (WM2200_DSP_RANGE_BASE + (1 * WM2200_DSP_SPACING))
+#define WM2200_DSP1_ZM_BASE (WM2200_DSP_RANGE_BASE + (2 * WM2200_DSP_SPACING))
+#define WM2200_DSP2_DM_BASE (WM2200_DSP_RANGE_BASE + (3 * WM2200_DSP_SPACING))
+#define WM2200_DSP2_PM_BASE (WM2200_DSP_RANGE_BASE + (4 * WM2200_DSP_SPACING))
+#define WM2200_DSP2_ZM_BASE (WM2200_DSP_RANGE_BASE + (5 * WM2200_DSP_SPACING))
+
+static const struct regmap_range_cfg wm2200_ranges[] = {
+       { .name = "DSP1DM", .range_min = WM2200_DSP1_DM_BASE,
+         .range_max = WM2200_DSP1_DM_BASE + 12287,
+         .selector_reg = WM2200_DSP1_CONTROL_3,
+         .selector_mask = WM2200_DSP1_PAGE_BASE_DM_0_MASK,
+         .selector_shift = WM2200_DSP1_PAGE_BASE_DM_0_SHIFT,
+         .window_start = WM2200_DSP1_DM_0, .window_len = 2048, },
+
+       { .name = "DSP1PM", .range_min = WM2200_DSP1_PM_BASE,
+         .range_max = WM2200_DSP1_PM_BASE + 12287,
+         .selector_reg = WM2200_DSP1_CONTROL_2,
+         .selector_mask = WM2200_DSP1_PAGE_BASE_PM_0_MASK,
+         .selector_shift = WM2200_DSP1_PAGE_BASE_PM_0_SHIFT,
+         .window_start = WM2200_DSP1_PM_0, .window_len = 768, },
+
+       { .name = "DSP1ZM", .range_min = WM2200_DSP1_ZM_BASE,
+         .range_max = WM2200_DSP1_ZM_BASE + 2047,
+         .selector_reg = WM2200_DSP1_CONTROL_4,
+         .selector_mask = WM2200_DSP1_PAGE_BASE_ZM_0_MASK,
+         .selector_shift = WM2200_DSP1_PAGE_BASE_ZM_0_SHIFT,
+         .window_start = WM2200_DSP1_ZM_0, .window_len = 1024, },
+
+       { .name = "DSP2DM", .range_min = WM2200_DSP2_DM_BASE,
+         .range_max = WM2200_DSP2_DM_BASE + 4095,
+         .selector_reg = WM2200_DSP2_CONTROL_3,
+         .selector_mask = WM2200_DSP2_PAGE_BASE_DM_0_MASK,
+         .selector_shift = WM2200_DSP2_PAGE_BASE_DM_0_SHIFT,
+         .window_start = WM2200_DSP2_DM_0, .window_len = 2048, },
+
+       { .name = "DSP2PM", .range_min = WM2200_DSP2_PM_BASE,
+         .range_max = WM2200_DSP2_PM_BASE + 11287,
+         .selector_reg = WM2200_DSP2_CONTROL_2,
+         .selector_mask = WM2200_DSP2_PAGE_BASE_PM_0_MASK,
+         .selector_shift = WM2200_DSP2_PAGE_BASE_PM_0_SHIFT,
+         .window_start = WM2200_DSP2_PM_0, .window_len = 768, },
+
+       { .name = "DSP2ZM", .range_min = WM2200_DSP2_ZM_BASE,
+         .range_max = WM2200_DSP2_ZM_BASE + 2047,
+         .selector_reg = WM2200_DSP2_CONTROL_4,
+         .selector_mask = WM2200_DSP2_PAGE_BASE_ZM_0_MASK,
+         .selector_shift = WM2200_DSP2_PAGE_BASE_ZM_0_SHIFT,
+         .window_start = WM2200_DSP2_ZM_0, .window_len = 1024, },
+};
+
 static struct reg_default wm2200_reg_defaults[] = {
        { 0x000B, 0x0000 },   /* R11    - Tone Generator 1 */
        { 0x0102, 0x0000 },   /* R258   - Clocking 3 */
@@ -407,6 +495,16 @@ static struct reg_default wm2200_reg_defaults[] = {
 
 static bool wm2200_volatile_register(struct device *dev, unsigned int reg)
 {
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(wm2200_ranges); i++)
+               if ((reg >= wm2200_ranges[i].window_start &&
+                    reg <= wm2200_ranges[i].window_start +
+                    wm2200_ranges[i].window_len) ||
+                   (reg >= wm2200_ranges[i].range_min &&
+                    reg <= wm2200_ranges[i].range_max))
+                       return true;
+
        switch (reg) {
        case WM2200_SOFTWARE_RESET:
        case WM2200_DEVICE_REVISION:
@@ -423,6 +521,16 @@ static bool wm2200_volatile_register(struct device *dev, unsigned int reg)
 
 static bool wm2200_readable_register(struct device *dev, unsigned int reg)
 {
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(wm2200_ranges); i++)
+               if ((reg >= wm2200_ranges[i].window_start &&
+                    reg <= wm2200_ranges[i].window_start +
+                    wm2200_ranges[i].window_len) ||
+                   (reg >= wm2200_ranges[i].range_min &&
+                    reg <= wm2200_ranges[i].range_max))
+                       return true;
+
        switch (reg) {
        case WM2200_SOFTWARE_RESET:
        case WM2200_DEVICE_REVISION:
@@ -873,6 +981,400 @@ static int wm2200_reset(struct wm2200_priv *wm2200)
        }
 }
 
+static int wm2200_dsp_load(struct snd_soc_codec *codec, int base)
+{
+       const struct firmware *firmware;
+       struct regmap *regmap = codec->control_data;
+       unsigned int pos = 0;
+       const struct wmfw_header *header;
+       const struct wmfw_adsp1_sizes *adsp1_sizes;
+       const struct wmfw_footer *footer;
+       const struct wmfw_region *region;
+       const char *file, *region_name;
+       char *text;
+       unsigned int dm, pm, zm, reg;
+       int regions = 0;
+       int ret, offset, type;
+
+       switch (base) {
+       case WM2200_DSP1_CONTROL_1:
+               file = "wm2200-dsp1.wmfw";
+               dm = WM2200_DSP1_DM_BASE;
+               pm = WM2200_DSP1_PM_BASE;
+               zm = WM2200_DSP1_ZM_BASE;
+               break;
+       case WM2200_DSP2_CONTROL_1:
+               file = "wm2200-dsp2.wmfw";
+               dm = WM2200_DSP2_DM_BASE;
+               pm = WM2200_DSP2_PM_BASE;
+               zm = WM2200_DSP2_ZM_BASE;
+               break;
+       default:
+               dev_err(codec->dev, "BASE %x\n", base);
+               BUG_ON(1);
+               return -EINVAL;
+       }
+
+       ret = request_firmware(&firmware, file, codec->dev);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to request '%s'\n", file);
+               return ret;
+       }
+
+       pos = sizeof(*header) + sizeof(*adsp1_sizes) + sizeof(*footer);
+       if (pos >= firmware->size) {
+               dev_err(codec->dev, "%s: file too short, %zu bytes\n",
+                       file, firmware->size);
+               return -EINVAL;
+       }
+
+       header = (void*)&firmware->data[0];
+
+       if (memcmp(&header->magic[0], "WMFW", 4) != 0) {
+               dev_err(codec->dev, "%s: invalid magic\n", file);
+               return -EINVAL;
+       }
+
+       if (header->ver != 0) {
+               dev_err(codec->dev, "%s: unknown file format %d\n",
+                       file, header->ver);
+               return -EINVAL;
+       }
+
+       if (le32_to_cpu(header->len) != sizeof(*header) +
+           sizeof(*adsp1_sizes) + sizeof(*footer)) {
+               dev_err(codec->dev, "%s: unexpected header length %d\n",
+                       file, le32_to_cpu(header->len));
+               return -EINVAL;
+       }
+
+       if (header->core != WMFW_ADSP1) {
+               dev_err(codec->dev, "%s: invalid core %d\n",
+                       file, header->core);
+               return -EINVAL;
+       }
+
+       adsp1_sizes = (void *)&(header[1]);
+       footer = (void *)&(adsp1_sizes[1]);
+
+       dev_dbg(codec->dev, "%s: %d DM, %d PM, %d ZM\n",
+               file, le32_to_cpu(adsp1_sizes->dm),
+               le32_to_cpu(adsp1_sizes->pm), le32_to_cpu(adsp1_sizes->zm));
+
+       dev_dbg(codec->dev, "%s: timestamp %llu\n", file,
+               le64_to_cpu(footer->timestamp));
+
+       while (pos < firmware->size &&
+              pos - firmware->size > sizeof(*region)) {
+               region = (void *)&(firmware->data[pos]);
+               region_name = "Unknown";
+               reg = 0;
+               text = NULL;
+               offset = le32_to_cpu(region->offset) & 0xffffff;
+               type = be32_to_cpu(region->type) & 0xff;
+               
+               switch (type) {
+               case WMFW_NAME_TEXT:
+                       region_name = "Firmware name";
+                       text = kzalloc(le32_to_cpu(region->len) + 1,
+                                      GFP_KERNEL);
+                       break;
+               case WMFW_INFO_TEXT:
+                       region_name = "Information";
+                       text = kzalloc(le32_to_cpu(region->len) + 1,
+                                      GFP_KERNEL);
+                       break;
+               case WMFW_ABSOLUTE:
+                       region_name = "Absolute";
+                       reg = offset;
+                       break;
+               case WMFW_ADSP1_PM:
+                       region_name = "PM";
+                       reg = pm + (offset * 3);
+                       break;
+               case WMFW_ADSP1_DM:
+                       region_name = "DM";
+                       reg = dm + (offset * 2);
+                       break;
+               case WMFW_ADSP1_ZM:
+                       region_name = "ZM";
+                       reg = zm + (offset * 2);
+                       break;
+               default:
+                       dev_warn(codec->dev,
+                                "%s.%d: Unknown region type %x at %d(%x)\n",
+                                file, regions, type, pos, pos);
+                       break;
+               }
+
+               dev_dbg(codec->dev, "%s.%d: %d bytes at %d in %s\n", file,
+                       regions, le32_to_cpu(region->len), offset,
+                       region_name);
+
+               if (text) {
+                       memcpy(text, region->data, le32_to_cpu(region->len));
+                       dev_info(codec->dev, "%s: %s\n", file, text);
+                       kfree(text);
+               }
+
+               if (reg) {
+                       ret = regmap_raw_write(regmap, reg, region->data,
+                                              le32_to_cpu(region->len));
+                       if (ret != 0) {
+                               dev_err(codec->dev,
+                                       "%s.%d: Failed to write %d bytes at %d in %s: %d\n",
+                                       file, regions,
+                                       le32_to_cpu(region->len), offset,
+                                       region_name, ret);
+                               goto out;
+                       }
+               }
+
+               pos += le32_to_cpu(region->len) + sizeof(*region);
+               regions++;
+       }
+
+       if (pos > firmware->size)
+               dev_warn(codec->dev, "%s.%d: %zu bytes at end of file\n",
+                        file, regions, pos - firmware->size);
+
+out:
+       release_firmware(firmware);
+       
+       return ret;
+}
+
+static int wm2200_setup_algs(struct snd_soc_codec *codec, int base)
+{
+       struct regmap *regmap = codec->control_data;
+       struct wmfw_adsp1_id_hdr id;
+       struct wmfw_adsp1_alg_hdr *alg;
+       size_t algs;
+       int zm, dm, pm, ret, i;
+       __be32 val;
+
+       switch (base) {
+       case WM2200_DSP1_CONTROL_1:
+               dm = WM2200_DSP1_DM_BASE;
+               pm = WM2200_DSP1_PM_BASE;
+               zm = WM2200_DSP1_ZM_BASE;
+               break;
+       case WM2200_DSP2_CONTROL_1:
+               dm = WM2200_DSP2_DM_BASE;
+               pm = WM2200_DSP2_PM_BASE;
+               zm = WM2200_DSP2_ZM_BASE;
+               break;
+       default:
+               dev_err(codec->dev, "BASE %x\n", base);
+               BUG_ON(1);
+               return -EINVAL;
+       }
+
+       ret = regmap_raw_read(regmap, dm, &id, sizeof(id));
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to read algorithm info: %d\n",
+                       ret);
+               return ret;
+       }
+
+       algs = be32_to_cpu(id.algs);
+       dev_info(codec->dev, "Firmware: %x v%d.%d.%d, %zu algorithms\n",
+                be32_to_cpu(id.fw.id),
+                (be32_to_cpu(id.fw.ver) & 0xff000) >> 16,
+                (be32_to_cpu(id.fw.ver) & 0xff00) >> 8,
+                be32_to_cpu(id.fw.ver) & 0xff,
+                algs);
+
+       /* Read the terminator first to validate the length */
+       ret = regmap_raw_read(regmap, dm +
+                             (sizeof(id) + (algs * sizeof(*alg))) / 2,
+                             &val, sizeof(val));
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to read algorithm list end: %d\n",
+                       ret);
+               return ret;
+       }
+
+       if (be32_to_cpu(val) != 0xbedead)
+               dev_warn(codec->dev, "Algorithm list end %zx 0x%x != 0xbeadead\n",
+                        (sizeof(id) + (algs * sizeof(*alg))) / 2,
+                        be32_to_cpu(val));
+
+       alg = kzalloc(sizeof(*alg) * algs, GFP_KERNEL);
+       if (!alg)
+               return -ENOMEM;
+
+       ret = regmap_raw_read(regmap, dm + (sizeof(id) / 2),
+                             alg, algs * sizeof(*alg));
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to read algorithm list: %d\n",
+                       ret);
+               goto out;
+       }
+
+       for (i = 0; i < algs; i++) {
+               dev_info(codec->dev, "%d: ID %x v%d.%d.%d\n",
+                        i, be32_to_cpu(alg[i].alg.id),
+                        (be32_to_cpu(alg[i].alg.ver) & 0xff000) >> 16,
+                        (be32_to_cpu(alg[i].alg.ver) & 0xff00) >> 8,
+                        be32_to_cpu(alg[i].alg.ver) & 0xff);
+       }
+
+out:
+       kfree(alg);
+       return ret;
+}
+
+static int wm2200_load_coeff(struct snd_soc_codec *codec, int base)
+{
+       struct regmap *regmap = codec->control_data;
+       struct wmfw_coeff_hdr *hdr;
+       struct wmfw_coeff_item *blk;
+       const struct firmware *firmware;
+       const char *file, *region_name;
+       int ret, dm, pm, zm, pos, blocks, type, offset, reg;
+
+       switch (base) {
+       case WM2200_DSP1_CONTROL_1:
+               file = "wm2200-dsp1.bin";
+               dm = WM2200_DSP1_DM_BASE;
+               pm = WM2200_DSP1_PM_BASE;
+               zm = WM2200_DSP1_ZM_BASE;
+               break;
+       case WM2200_DSP2_CONTROL_1:
+               file = "wm2200-dsp2.bin";
+               dm = WM2200_DSP2_DM_BASE;
+               pm = WM2200_DSP2_PM_BASE;
+               zm = WM2200_DSP2_ZM_BASE;
+               break;
+       default:
+               dev_err(codec->dev, "BASE %x\n", base);
+               BUG_ON(1);
+               return -EINVAL;
+       }
+
+       ret = request_firmware(&firmware, file, codec->dev);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to request '%s'\n", file);
+               return ret;
+       }
+
+       if (sizeof(*hdr) >= firmware->size) {
+               dev_err(codec->dev, "%s: file too short, %zu bytes\n",
+                       file, firmware->size);
+               return -EINVAL;
+       }
+
+       hdr = (void*)&firmware->data[0];
+       if (memcmp(hdr->magic, "WMDR", 4) != 0) {
+               dev_err(codec->dev, "%s: invalid magic\n", file);
+               return -EINVAL;
+       }
+
+       dev_dbg(codec->dev, "%s: v%d.%d.%d\n", file,
+               (le32_to_cpu(hdr->ver) >> 16) & 0xff,
+               (le32_to_cpu(hdr->ver) >>  8) & 0xff,
+               le32_to_cpu(hdr->ver) & 0xff);
+
+       pos = le32_to_cpu(hdr->len);
+
+       blocks = 0;
+       while (pos < firmware->size &&
+              pos - firmware->size > sizeof(*blk)) {
+               blk = (void*)(&firmware->data[pos]);
+
+               type = be32_to_cpu(blk->type) & 0xff;
+               offset = le32_to_cpu(blk->offset) & 0xffffff;
+
+               dev_dbg(codec->dev, "%s.%d: %x v%d.%d.%d\n",
+                       file, blocks, le32_to_cpu(blk->id),
+                       (le32_to_cpu(blk->ver) >> 16) & 0xff,
+                       (le32_to_cpu(blk->ver) >>  8) & 0xff,
+                       le32_to_cpu(blk->ver) & 0xff);
+               dev_dbg(codec->dev, "%s.%d: %d bytes at 0x%x in %x\n",
+                       file, blocks, le32_to_cpu(blk->len), offset, type);
+
+               reg = 0;
+               region_name = "Unknown";
+               switch (type) {
+               case WMFW_NAME_TEXT:
+               case WMFW_INFO_TEXT:
+                       break;
+               case WMFW_ABSOLUTE:
+                       region_name = "register";
+                       reg = offset;
+                       break;
+               default:
+                       dev_err(codec->dev, "Unknown region type %x\n", type);
+                       break;
+               }
+
+               if (reg) {
+                       ret = regmap_raw_write(regmap, reg, blk->data,
+                                              le32_to_cpu(blk->len));
+                       if (ret != 0) {
+                               dev_err(codec->dev,
+                                       "%s.%d: Failed to write to %x in %s\n",
+                                       file, blocks, reg, region_name);
+                       }
+               }
+
+               pos += le32_to_cpu(blk->len) + sizeof(*blk);
+               blocks++;
+       }
+
+       if (pos > firmware->size)
+               dev_warn(codec->dev, "%s.%d: %zu bytes at end of file\n",
+                        file, blocks, pos - firmware->size);
+
+       return 0;
+}
+
+static int wm2200_dsp_ev(struct snd_soc_dapm_widget *w,
+                        struct snd_kcontrol *kcontrol,
+                        int event)
+{
+       struct snd_soc_codec *codec = w->codec;
+       int base = w->reg - WM2200_DSP_CONTROL_30;
+       int ret;
+
+       switch (event) {
+       case SND_SOC_DAPM_POST_PMU:
+               ret = wm2200_dsp_load(codec, base);
+               if (ret != 0)
+                       return ret;
+
+               ret = wm2200_setup_algs(codec, base);
+               if (ret != 0)
+                       return ret;
+
+               ret = wm2200_load_coeff(codec, base);
+               if (ret != 0)
+                       return ret;
+
+               /* Start the core running */
+               snd_soc_update_bits(codec, w->reg,
+                                   WM2200_DSP1_CORE_ENA | WM2200_DSP1_START,
+                                   WM2200_DSP1_CORE_ENA | WM2200_DSP1_START);
+               break;
+
+       case SND_SOC_DAPM_PRE_PMD:
+               /* Halt the core */
+               snd_soc_update_bits(codec, w->reg,
+                                   WM2200_DSP1_CORE_ENA | WM2200_DSP1_START,
+                                   0);
+
+               snd_soc_update_bits(codec, base + WM2200_DSP_CONTROL_19,
+                                   WM2200_DSP1_WDMA_BUFFER_LENGTH_MASK, 0);
+               break;
+
+       default:
+               break;
+       }
+
+       return 0;
+}
+
 static DECLARE_TLV_DB_SCALE(in_tlv, -6300, 100, 0);
 static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0);
 static DECLARE_TLV_DB_SCALE(out_tlv, -6400, 100, 0);
@@ -880,7 +1382,7 @@ static DECLARE_TLV_DB_SCALE(out_tlv, -6400, 100, 0);
 static const char *wm2200_mixer_texts[] = {
        "None",
        "Tone Generator",
-       "AEC loopback",
+       "AEC Loopback",
        "IN1L",
        "IN1R",
        "IN2L",
@@ -976,6 +1478,20 @@ static int wm2200_mixer_values[] = {
        static WM2200_MUX_CTL_DECL(name##_in3); \
        static WM2200_MUX_CTL_DECL(name##_in4)
 
+#define WM2200_DSP_ENUMS(name, base_reg) \
+       static WM2200_MUX_ENUM_DECL(name##_aux1_enum, base_reg);     \
+       static WM2200_MUX_ENUM_DECL(name##_aux2_enum, base_reg + 1); \
+       static WM2200_MUX_ENUM_DECL(name##_aux3_enum, base_reg + 2); \
+       static WM2200_MUX_ENUM_DECL(name##_aux4_enum, base_reg + 3); \
+       static WM2200_MUX_ENUM_DECL(name##_aux5_enum, base_reg + 4); \
+       static WM2200_MUX_ENUM_DECL(name##_aux6_enum, base_reg + 5); \
+       static WM2200_MUX_CTL_DECL(name##_aux1); \
+       static WM2200_MUX_CTL_DECL(name##_aux2); \
+       static WM2200_MUX_CTL_DECL(name##_aux3); \
+       static WM2200_MUX_CTL_DECL(name##_aux4); \
+       static WM2200_MUX_CTL_DECL(name##_aux5); \
+       static WM2200_MUX_CTL_DECL(name##_aux6);
+
 static const struct snd_kcontrol_new wm2200_snd_controls[] = {
 SOC_SINGLE("IN1 High Performance Switch", WM2200_IN1L_CONTROL,
           WM2200_IN1_OSR_SHIFT, 1, 0),
@@ -1051,6 +1567,9 @@ WM2200_MIXER_ENUMS(DSP1R, WM2200_DSP1RMIX_INPUT_1_SOURCE);
 WM2200_MIXER_ENUMS(DSP2L, WM2200_DSP2LMIX_INPUT_1_SOURCE);
 WM2200_MIXER_ENUMS(DSP2R, WM2200_DSP2RMIX_INPUT_1_SOURCE);
 
+WM2200_DSP_ENUMS(DSP1, WM2200_DSP1AUX1MIX_INPUT_1_SOURCE);
+WM2200_DSP_ENUMS(DSP2, WM2200_DSP2AUX1MIX_INPUT_1_SOURCE);
+
 WM2200_MIXER_ENUMS(LHPF1, WM2200_LHPF1MIX_INPUT_1_SOURCE);
 WM2200_MIXER_ENUMS(LHPF2, WM2200_LHPF2MIX_INPUT_1_SOURCE);
 
@@ -1064,8 +1583,19 @@ WM2200_MIXER_ENUMS(LHPF2, WM2200_LHPF2MIX_INPUT_1_SOURCE);
        WM2200_MUX(name_str " Input 4", &name##_in4_mux), \
        SND_SOC_DAPM_MIXER(name_str " Mixer", SND_SOC_NOPM, 0, 0, NULL, 0)
 
+#define WM2200_DSP_WIDGETS(name, name_str) \
+       WM2200_MIXER_WIDGETS(name##L, name_str "L"), \
+       WM2200_MIXER_WIDGETS(name##R, name_str "R"), \
+       WM2200_MUX(name_str " Aux 1", &name##_aux1_mux), \
+       WM2200_MUX(name_str " Aux 2", &name##_aux2_mux), \
+       WM2200_MUX(name_str " Aux 3", &name##_aux3_mux), \
+       WM2200_MUX(name_str " Aux 4", &name##_aux4_mux), \
+       WM2200_MUX(name_str " Aux 5", &name##_aux5_mux), \
+       WM2200_MUX(name_str " Aux 6", &name##_aux6_mux)
+
 #define WM2200_MIXER_INPUT_ROUTES(name)        \
        { name, "Tone Generator", "Tone Generator" }, \
+       { name, "AEC Loopback", "AEC Loopback" }, \
         { name, "IN1L", "IN1L PGA" }, \
         { name, "IN1R", "IN1R PGA" }, \
         { name, "IN2L", "IN2L PGA" }, \
@@ -1106,6 +1636,33 @@ WM2200_MIXER_ENUMS(LHPF2, WM2200_LHPF2MIX_INPUT_1_SOURCE);
        WM2200_MIXER_INPUT_ROUTES(name " Input 3"), \
        WM2200_MIXER_INPUT_ROUTES(name " Input 4")
 
+#define WM2200_DSP_AUX_ROUTES(name) \
+       { name, NULL, name " Aux 1" }, \
+       { name, NULL, name " Aux 2" }, \
+       { name, NULL, name " Aux 3" }, \
+       { name, NULL, name " Aux 4" }, \
+       { name, NULL, name " Aux 5" }, \
+       { name, NULL, name " Aux 6" }, \
+       WM2200_MIXER_INPUT_ROUTES(name " Aux 1"), \
+       WM2200_MIXER_INPUT_ROUTES(name " Aux 2"), \
+       WM2200_MIXER_INPUT_ROUTES(name " Aux 3"), \
+       WM2200_MIXER_INPUT_ROUTES(name " Aux 4"), \
+       WM2200_MIXER_INPUT_ROUTES(name " Aux 5"), \
+       WM2200_MIXER_INPUT_ROUTES(name " Aux 6")
+
+static const char *wm2200_aec_loopback_texts[] = {
+       "OUT1L", "OUT1R", "OUT2L", "OUT2R",
+};
+
+static const struct soc_enum wm2200_aec_loopback =
+       SOC_ENUM_SINGLE(WM2200_DAC_AEC_CONTROL_1,
+                       WM2200_AEC_LOOPBACK_SRC_SHIFT,
+                       ARRAY_SIZE(wm2200_aec_loopback_texts),
+                       wm2200_aec_loopback_texts);
+
+static const struct snd_kcontrol_new wm2200_aec_loopback_mux =
+       SOC_DAPM_ENUM("AEC Loopback", wm2200_aec_loopback);
+
 static const struct snd_soc_dapm_widget wm2200_dapm_widgets[] = {
 SND_SOC_DAPM_SUPPLY("SYSCLK", WM2200_CLOCKING_3, WM2200_SYSCLK_ENA_SHIFT, 0,
                    NULL, 0),
@@ -1165,8 +1722,12 @@ SND_SOC_DAPM_PGA("LHPF1", WM2200_HPLPF1_1, WM2200_LHPF1_ENA_SHIFT, 0,
 SND_SOC_DAPM_PGA("LHPF2", WM2200_HPLPF2_1, WM2200_LHPF2_ENA_SHIFT, 0,
                 NULL, 0),
 
-SND_SOC_DAPM_PGA_E("DSP1", SND_SOC_NOPM, 0, 0, NULL, 0, NULL, 0),
-SND_SOC_DAPM_PGA_E("DSP2", SND_SOC_NOPM, 1, 0, NULL, 0, NULL, 0),
+SND_SOC_DAPM_PGA_E("DSP1", WM2200_DSP1_CONTROL_30, WM2200_DSP1_SYS_ENA_SHIFT,
+                  0, NULL, 0, wm2200_dsp_ev,
+                  SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+SND_SOC_DAPM_PGA_E("DSP2", WM2200_DSP2_CONTROL_30, WM2200_DSP2_SYS_ENA_SHIFT,
+                  0, NULL, 0, wm2200_dsp_ev,
+                  SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
 
 SND_SOC_DAPM_AIF_OUT("AIF1TX1", "Capture", 0,
                    WM2200_AUDIO_IF_1_22, WM2200_AIF1TX1_ENA_SHIFT, 0),
@@ -1181,6 +1742,9 @@ SND_SOC_DAPM_AIF_OUT("AIF1TX5", "Capture", 4,
 SND_SOC_DAPM_AIF_OUT("AIF1TX6", "Capture", 5,
                    WM2200_AUDIO_IF_1_22, WM2200_AIF1TX6_ENA_SHIFT, 0),
 
+SND_SOC_DAPM_MUX("AEC Loopback", WM2200_DAC_AEC_CONTROL_1,
+                WM2200_AEC_LOOPBACK_ENA_SHIFT, 0, &wm2200_aec_loopback_mux),
+
 SND_SOC_DAPM_PGA_S("OUT1L", 0, WM2200_OUTPUT_ENABLES,
                   WM2200_OUT1L_ENA_SHIFT, 0, NULL, 0),
 SND_SOC_DAPM_PGA_S("OUT1R", 0, WM2200_OUTPUT_ENABLES,
@@ -1231,10 +1795,8 @@ WM2200_MIXER_WIDGETS(EQR, "EQR"),
 WM2200_MIXER_WIDGETS(LHPF1, "LHPF1"),
 WM2200_MIXER_WIDGETS(LHPF2, "LHPF2"),
 
-WM2200_MIXER_WIDGETS(DSP1L, "DSP1L"),
-WM2200_MIXER_WIDGETS(DSP1R, "DSP1R"),
-WM2200_MIXER_WIDGETS(DSP2L, "DSP2L"),
-WM2200_MIXER_WIDGETS(DSP2R, "DSP2R"),
+WM2200_DSP_WIDGETS(DSP1, "DSP1"),
+WM2200_DSP_WIDGETS(DSP2, "DSP2"),
 
 WM2200_MIXER_WIDGETS(AIF1TX1, "AIF1TX1"),
 WM2200_MIXER_WIDGETS(AIF1TX2, "AIF1TX2"),
@@ -1326,11 +1888,19 @@ static const struct snd_soc_dapm_route wm2200_dapm_routes[] = {
        { "SPK", NULL, "OUT2L" },
        { "SPK", NULL, "OUT2R" },
 
+       { "AEC Loopback", "OUT1L", "OUT1L" },
+       { "AEC Loopback", "OUT1R", "OUT1R" },
+       { "AEC Loopback", "OUT2L", "OUT2L" },
+       { "AEC Loopback", "OUT2R", "OUT2R" },
+
        WM2200_MIXER_ROUTES("DSP1", "DSP1L"),
        WM2200_MIXER_ROUTES("DSP1", "DSP1R"),
        WM2200_MIXER_ROUTES("DSP2", "DSP2L"),
        WM2200_MIXER_ROUTES("DSP2", "DSP2R"),
 
+       WM2200_DSP_AUX_ROUTES("DSP1"),
+       WM2200_DSP_AUX_ROUTES("DSP2"),
+
        WM2200_MIXER_ROUTES("OUT1L", "OUT1L"),
        WM2200_MIXER_ROUTES("OUT1R", "OUT1R"),
        WM2200_MIXER_ROUTES("OUT2L", "OUT2L"),
@@ -1968,12 +2538,15 @@ static const struct regmap_config wm2200_regmap = {
        .reg_bits = 16,
        .val_bits = 16,
 
-       .max_register = WM2200_MAX_REGISTER,
+       .max_register = WM2200_MAX_REGISTER + (ARRAY_SIZE(wm2200_ranges) *
+                                              WM2200_DSP_SPACING),
        .reg_defaults = wm2200_reg_defaults,
        .num_reg_defaults = ARRAY_SIZE(wm2200_reg_defaults),
        .volatile_reg = wm2200_volatile_register,
        .readable_reg = wm2200_readable_register,
        .cache_type = REGCACHE_RBTREE,
+       .ranges = wm2200_ranges,
+       .num_ranges = ARRAY_SIZE(wm2200_ranges),
 };
 
 static const unsigned int wm2200_dig_vu[] = {
@@ -2011,7 +2584,7 @@ static __devinit int wm2200_i2c_probe(struct i2c_client *i2c,
        wm2200->dev = &i2c->dev;
        init_completion(&wm2200->fll_lock);
 
-       wm2200->regmap = regmap_init_i2c(i2c, &wm2200_regmap);
+       wm2200->regmap = devm_regmap_init_i2c(i2c, &wm2200_regmap);
        if (IS_ERR(wm2200->regmap)) {
                ret = PTR_ERR(wm2200->regmap);
                dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
@@ -2027,8 +2600,9 @@ static __devinit int wm2200_i2c_probe(struct i2c_client *i2c,
        for (i = 0; i < ARRAY_SIZE(wm2200->core_supplies); i++)
                wm2200->core_supplies[i].supply = wm2200_core_supply_names[i];
 
-       ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm2200->core_supplies),
-                                wm2200->core_supplies);
+       ret = devm_regulator_bulk_get(&i2c->dev,
+                                     ARRAY_SIZE(wm2200->core_supplies),
+                                     wm2200->core_supplies);
        if (ret != 0) {
                dev_err(&i2c->dev, "Failed to request core supplies: %d\n",
                        ret);
@@ -2044,8 +2618,9 @@ static __devinit int wm2200_i2c_probe(struct i2c_client *i2c,
        }
 
        if (wm2200->pdata.ldo_ena) {
-               ret = gpio_request_one(wm2200->pdata.ldo_ena,
-                                      GPIOF_OUT_INIT_HIGH, "WM2200 LDOENA");
+               ret = devm_gpio_request_one(&i2c->dev, wm2200->pdata.ldo_ena,
+                                           GPIOF_OUT_INIT_HIGH,
+                                           "WM2200 LDOENA");
                if (ret < 0) {
                        dev_err(&i2c->dev, "Failed to request LDOENA %d: %d\n",
                                wm2200->pdata.ldo_ena, ret);
@@ -2055,8 +2630,9 @@ static __devinit int wm2200_i2c_probe(struct i2c_client *i2c,
        }
 
        if (wm2200->pdata.reset) {
-               ret = gpio_request_one(wm2200->pdata.reset,
-                                      GPIOF_OUT_INIT_HIGH, "WM2200 /RESET");
+               ret = devm_gpio_request_one(&i2c->dev, wm2200->pdata.reset,
+                                           GPIOF_OUT_INIT_HIGH,
+                                           "WM2200 /RESET");
                if (ret < 0) {
                        dev_err(&i2c->dev, "Failed to request /RESET %d: %d\n",
                                wm2200->pdata.reset, ret);
@@ -2166,23 +2742,16 @@ static __devinit int wm2200_i2c_probe(struct i2c_client *i2c,
 err_pm_runtime:
        pm_runtime_disable(&i2c->dev);
 err_reset:
-       if (wm2200->pdata.reset) {
+       if (wm2200->pdata.reset)
                gpio_set_value_cansleep(wm2200->pdata.reset, 0);
-               gpio_free(wm2200->pdata.reset);
-       }
 err_ldo:
-       if (wm2200->pdata.ldo_ena) {
+       if (wm2200->pdata.ldo_ena)
                gpio_set_value_cansleep(wm2200->pdata.ldo_ena, 0);
-               gpio_free(wm2200->pdata.ldo_ena);
-       }
 err_enable:
        regulator_bulk_disable(ARRAY_SIZE(wm2200->core_supplies),
                               wm2200->core_supplies);
 err_core:
-       regulator_bulk_free(ARRAY_SIZE(wm2200->core_supplies),
-                           wm2200->core_supplies);
 err_regmap:
-       regmap_exit(wm2200->regmap);
 err:
        return ret;
 }
@@ -2194,17 +2763,10 @@ static __devexit int wm2200_i2c_remove(struct i2c_client *i2c)
        snd_soc_unregister_codec(&i2c->dev);
        if (i2c->irq)
                free_irq(i2c->irq, wm2200);
-       if (wm2200->pdata.reset) {
+       if (wm2200->pdata.reset)
                gpio_set_value_cansleep(wm2200->pdata.reset, 0);
-               gpio_free(wm2200->pdata.reset);
-       }
-       if (wm2200->pdata.ldo_ena) {
+       if (wm2200->pdata.ldo_ena)
                gpio_set_value_cansleep(wm2200->pdata.ldo_ena, 0);
-               gpio_free(wm2200->pdata.ldo_ena);
-       }
-       regulator_bulk_free(ARRAY_SIZE(wm2200->core_supplies),
-                           wm2200->core_supplies);
-       regmap_exit(wm2200->regmap);
 
        return 0;
 }
index 89151ca5e7766b69cd57447e611fcf1301fd301f..7665d68c4558ee071e8f8067ad92e458a3b3b9fd 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
+#include <linux/regmap.h>
 #include <linux/spi/spi.h>
 #include <linux/slab.h>
 #include <linux/of_device.h>
  * We can't read the WM8750 register space when we
  * are using 2 wire for device control, so we cache them instead.
  */
-static const u16 wm8750_reg[] = {
-       0x0097, 0x0097, 0x0079, 0x0079,  /*  0 */
-       0x0000, 0x0008, 0x0000, 0x000a,  /*  4 */
-       0x0000, 0x0000, 0x00ff, 0x00ff,  /*  8 */
-       0x000f, 0x000f, 0x0000, 0x0000,  /* 12 */
-       0x0000, 0x007b, 0x0000, 0x0032,  /* 16 */
-       0x0000, 0x00c3, 0x00c3, 0x00c0,  /* 20 */
-       0x0000, 0x0000, 0x0000, 0x0000,  /* 24 */
-       0x0000, 0x0000, 0x0000, 0x0000,  /* 28 */
-       0x0000, 0x0000, 0x0050, 0x0050,  /* 32 */
-       0x0050, 0x0050, 0x0050, 0x0050,  /* 36 */
-       0x0079, 0x0079, 0x0079,          /* 40 */
+static const struct reg_default wm8750_reg_defaults[] = {
+       {  0, 0x0097 },
+       {  1, 0x0097 },
+       {  2, 0x0079 },
+       {  3, 0x0079 },
+       {  4, 0x0000 },
+       {  5, 0x0008 },
+       {  6, 0x0000 },
+       {  7, 0x000a },
+       {  8, 0x0000 },
+       {  9, 0x0000 },
+       { 10, 0x00ff },
+       { 11, 0x00ff },
+       { 12, 0x000f },
+       { 13, 0x000f },
+       { 14, 0x0000 },
+       { 15, 0x0000 },
+       { 16, 0x0000 },
+       { 17, 0x007b },
+       { 18, 0x0000 },
+       { 19, 0x0032 },
+       { 20, 0x0000 },
+       { 21, 0x00c3 },
+       { 22, 0x00c3 },
+       { 23, 0x00c0 },
+       { 24, 0x0000 },
+       { 25, 0x0000 },
+       { 26, 0x0000 },
+       { 27, 0x0000 },
+       { 28, 0x0000 },
+       { 29, 0x0000 },
+       { 30, 0x0000 },
+       { 31, 0x0000 },
+       { 32, 0x0000 },
+       { 33, 0x0000 },
+       { 34, 0x0050 },
+       { 35, 0x0050 },
+       { 36, 0x0050 },
+       { 37, 0x0050 },
+       { 38, 0x0050 },
+       { 39, 0x0050 },
+       { 40, 0x0079 },
+       { 41, 0x0079 },
+       { 42, 0x0079 },
 };
 
 /* codec private data */
 struct wm8750_priv {
        unsigned int sysclk;
-       enum snd_soc_control_type control_type;
 };
 
 #define wm8750_reset(c)        snd_soc_write(c, WM8750_RESET, 0)
@@ -668,10 +700,9 @@ static int wm8750_resume(struct snd_soc_codec *codec)
 
 static int wm8750_probe(struct snd_soc_codec *codec)
 {
-       struct wm8750_priv *wm8750 = snd_soc_codec_get_drvdata(codec);
        int ret;
 
-       ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8750->control_type);
+       ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
        if (ret < 0) {
                printk(KERN_ERR "wm8750: failed to set cache I/O: %d\n", ret);
                return ret;
@@ -711,9 +742,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8750 = {
        .suspend =      wm8750_suspend,
        .resume =       wm8750_resume,
        .set_bias_level = wm8750_set_bias_level,
-       .reg_cache_size = ARRAY_SIZE(wm8750_reg),
-       .reg_word_size = sizeof(u16),
-       .reg_cache_default = wm8750_reg,
 
        .controls = wm8750_snd_controls,
        .num_controls = ARRAY_SIZE(wm8750_snd_controls),
@@ -730,10 +758,21 @@ static const struct of_device_id wm8750_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, wm8750_of_match);
 
+static const struct regmap_config wm8750_regmap = {
+       .reg_bits = 7,
+       .val_bits = 9,
+       .max_register = WM8750_MOUTV,
+
+       .reg_defaults = wm8750_reg_defaults,
+       .num_reg_defaults = ARRAY_SIZE(wm8750_reg_defaults),
+       .cache_type = REGCACHE_RBTREE,
+};
+
 #if defined(CONFIG_SPI_MASTER)
 static int __devinit wm8750_spi_probe(struct spi_device *spi)
 {
        struct wm8750_priv *wm8750;
+       struct regmap *regmap;
        int ret;
 
        wm8750 = devm_kzalloc(&spi->dev, sizeof(struct wm8750_priv),
@@ -741,7 +780,10 @@ static int __devinit wm8750_spi_probe(struct spi_device *spi)
        if (wm8750 == NULL)
                return -ENOMEM;
 
-       wm8750->control_type = SND_SOC_SPI;
+       regmap = devm_regmap_init_spi(spi, &wm8750_regmap);
+       if (IS_ERR(regmap))
+               return PTR_ERR(regmap);
+
        spi_set_drvdata(spi, wm8750);
 
        ret = snd_soc_register_codec(&spi->dev,
@@ -779,6 +821,7 @@ static __devinit int wm8750_i2c_probe(struct i2c_client *i2c,
                                      const struct i2c_device_id *id)
 {
        struct wm8750_priv *wm8750;
+       struct regmap *regmap;
        int ret;
 
        wm8750 = devm_kzalloc(&i2c->dev, sizeof(struct wm8750_priv),
@@ -787,7 +830,10 @@ static __devinit int wm8750_i2c_probe(struct i2c_client *i2c,
                return -ENOMEM;
 
        i2c_set_clientdata(i2c, wm8750);
-       wm8750->control_type = SND_SOC_I2C;
+
+       regmap = devm_regmap_init_i2c(i2c, &wm8750_regmap);
+       if (IS_ERR(regmap))
+               return PTR_ERR(regmap);
 
        ret =  snd_soc_register_codec(&i2c->dev,
                        &soc_codec_dev_wm8750, &wm8750_dai, 1);
index c7c0034d39669a5e4b548bd7a46f40eb716f00cd..0b690ba875f84ba1bd2df6934afc27930a81a29b 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/of_device.h>
 #include <linux/pm.h>
 #include <linux/spi/spi.h>
+#include <linux/regmap.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
 #include <sound/core.h>
@@ -35,19 +36,52 @@ static const char *wm8770_supply_names[WM8770_NUM_SUPPLIES] = {
        "DVDD"
 };
 
-static const u16 wm8770_reg_defs[WM8770_CACHEREGNUM] = {
-       0x7f, 0x7f, 0x7f, 0x7f,
-       0x7f, 0x7f, 0x7f, 0x7f,
-       0x7f, 0xff, 0xff, 0xff,
-       0xff, 0xff, 0xff, 0xff,
-       0xff, 0xff, 0, 0x90, 0,
-       0, 0x22, 0x22, 0x3e,
-       0xc, 0xc, 0x100, 0x189,
-       0x189, 0x8770
+static const struct reg_default wm8770_reg_defaults[] = {
+       {  0, 0x7f },
+       {  1, 0x7f },
+       {  2, 0x7f },
+       {  3, 0x7f },
+       {  4, 0x7f },
+       {  5, 0x7f },
+       {  6, 0x7f },
+       {  7, 0x7f },
+       {  8, 0x7f },
+       {  9, 0xff },
+       { 10, 0xff },
+       { 11, 0xff },
+       { 12, 0xff },
+       { 13, 0xff },
+       { 14, 0xff },
+       { 15, 0xff },
+       { 16, 0xff },
+       { 17, 0xff },
+       { 18, 0    },
+       { 19, 0x90 },
+       { 20, 0    },
+       { 21, 0    },
+       { 22, 0x22 },
+       { 23, 0x22 },
+       { 24, 0x3e },
+       { 25, 0xc  },
+       { 26, 0xc  },
+       { 27, 0x100 },
+       { 28, 0x189 },
+       { 29, 0x189 },
+       { 30, 0x8770 },
 };
 
+static bool wm8770_volatile_reg(struct device *dev, unsigned int reg)
+{
+       switch (reg) {
+       case WM8770_RESET:
+               return true;
+       default:
+               return false;
+       }
+}
+
 struct wm8770_priv {
-       enum snd_soc_control_type control_type;
+       struct regmap *regmap;
        struct regulator_bulk_data supplies[WM8770_NUM_SUPPLIES];
        struct notifier_block disable_nb[WM8770_NUM_SUPPLIES];
        struct snd_soc_codec *codec;
@@ -71,7 +105,7 @@ static int wm8770_regulator_event_##n(struct notifier_block *nb, \
        struct wm8770_priv *wm8770 = container_of(nb, struct wm8770_priv, \
                                     disable_nb[n]); \
        if (event & REGULATOR_EVENT_DISABLE) { \
-               wm8770->codec->cache_sync = 1; \
+               regcache_mark_dirty(wm8770->regmap);    \
        } \
        return 0; \
 }
@@ -466,24 +500,6 @@ static int wm8770_set_sysclk(struct snd_soc_dai *dai,
        return 0;
 }
 
-static void wm8770_sync_cache(struct snd_soc_codec *codec)
-{
-       int i;
-       u16 *cache;
-
-       if (!codec->cache_sync)
-               return;
-
-       codec->cache_only = 0;
-       cache = codec->reg_cache;
-       for (i = 0; i < codec->driver->reg_cache_size; i++) {
-               if (i == WM8770_RESET || cache[i] == wm8770_reg_defs[i])
-                       continue;
-               snd_soc_write(codec, i, cache[i]);
-       }
-       codec->cache_sync = 0;
-}
-
 static int wm8770_set_bias_level(struct snd_soc_codec *codec,
                                 enum snd_soc_bias_level level)
 {
@@ -507,7 +523,9 @@ static int wm8770_set_bias_level(struct snd_soc_codec *codec,
                                        ret);
                                return ret;
                        }
-                       wm8770_sync_cache(codec);
+
+                       regcache_sync(wm8770->regmap);
+
                        /* global powerup */
                        snd_soc_write(codec, WM8770_PWDNCTRL, 0);
                }
@@ -554,68 +572,25 @@ static struct snd_soc_dai_driver wm8770_dai = {
        .symmetric_rates = 1
 };
 
-#ifdef CONFIG_PM
-static int wm8770_suspend(struct snd_soc_codec *codec)
-{
-       wm8770_set_bias_level(codec, SND_SOC_BIAS_OFF);
-       return 0;
-}
-
-static int wm8770_resume(struct snd_soc_codec *codec)
-{
-       wm8770_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-       return 0;
-}
-#else
-#define wm8770_suspend NULL
-#define wm8770_resume NULL
-#endif
-
 static int wm8770_probe(struct snd_soc_codec *codec)
 {
        struct wm8770_priv *wm8770;
        int ret;
-       int i;
 
        wm8770 = snd_soc_codec_get_drvdata(codec);
        wm8770->codec = codec;
 
-       ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8770->control_type);
+       ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
        if (ret < 0) {
                dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
                return ret;
        }
 
-       for (i = 0; i < ARRAY_SIZE(wm8770->supplies); i++)
-               wm8770->supplies[i].supply = wm8770_supply_names[i];
-
-       ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8770->supplies),
-                                wm8770->supplies);
-       if (ret) {
-               dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
-               return ret;
-       }
-
-       wm8770->disable_nb[0].notifier_call = wm8770_regulator_event_0;
-       wm8770->disable_nb[1].notifier_call = wm8770_regulator_event_1;
-       wm8770->disable_nb[2].notifier_call = wm8770_regulator_event_2;
-
-       /* This should really be moved into the regulator core */
-       for (i = 0; i < ARRAY_SIZE(wm8770->supplies); i++) {
-               ret = regulator_register_notifier(wm8770->supplies[i].consumer,
-                                                 &wm8770->disable_nb[i]);
-               if (ret) {
-                       dev_err(codec->dev,
-                               "Failed to register regulator notifier: %d\n",
-                               ret);
-               }
-       }
-
        ret = regulator_bulk_enable(ARRAY_SIZE(wm8770->supplies),
                                    wm8770->supplies);
        if (ret) {
                dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
-               goto err_reg_get;
+               return ret;
        }
 
        ret = wm8770_reset(codec);
@@ -624,8 +599,6 @@ static int wm8770_probe(struct snd_soc_codec *codec)
                goto err_reg_enable;
        }
 
-       wm8770_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
        /* latch the volume update bits */
        snd_soc_update_bits(codec, WM8770_MSDIGVOL, 0x100, 0x100);
        snd_soc_update_bits(codec, WM8770_MSALGVOL, 0x100, 0x100);
@@ -641,46 +614,22 @@ static int wm8770_probe(struct snd_soc_codec *codec)
        /* mute all DACs */
        snd_soc_update_bits(codec, WM8770_DACMUTE, 0x10, 0x10);
 
-       snd_soc_add_codec_controls(codec, wm8770_snd_controls,
-                            ARRAY_SIZE(wm8770_snd_controls));
-       snd_soc_dapm_new_controls(&codec->dapm, wm8770_dapm_widgets,
-                                 ARRAY_SIZE(wm8770_dapm_widgets));
-       snd_soc_dapm_add_routes(&codec->dapm, wm8770_intercon,
-                               ARRAY_SIZE(wm8770_intercon));
-       return 0;
-
 err_reg_enable:
        regulator_bulk_disable(ARRAY_SIZE(wm8770->supplies), wm8770->supplies);
-err_reg_get:
-       regulator_bulk_free(ARRAY_SIZE(wm8770->supplies), wm8770->supplies);
        return ret;
 }
 
-static int wm8770_remove(struct snd_soc_codec *codec)
-{
-       struct wm8770_priv *wm8770;
-       int i;
-
-       wm8770 = snd_soc_codec_get_drvdata(codec);
-       wm8770_set_bias_level(codec, SND_SOC_BIAS_OFF);
-
-       for (i = 0; i < ARRAY_SIZE(wm8770->supplies); ++i)
-               regulator_unregister_notifier(wm8770->supplies[i].consumer,
-                                             &wm8770->disable_nb[i]);
-       regulator_bulk_free(ARRAY_SIZE(wm8770->supplies), wm8770->supplies);
-       return 0;
-}
-
 static struct snd_soc_codec_driver soc_codec_dev_wm8770 = {
        .probe = wm8770_probe,
-       .remove = wm8770_remove,
-       .suspend = wm8770_suspend,
-       .resume = wm8770_resume,
        .set_bias_level = wm8770_set_bias_level,
        .idle_bias_off = true,
-       .reg_cache_size = ARRAY_SIZE(wm8770_reg_defs),
-       .reg_word_size = sizeof (u16),
-       .reg_cache_default = wm8770_reg_defs
+
+       .controls = wm8770_snd_controls,
+       .num_controls = ARRAY_SIZE(wm8770_snd_controls),
+       .dapm_widgets = wm8770_dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(wm8770_dapm_widgets),
+       .dapm_routes = wm8770_intercon,
+       .num_dapm_routes = ARRAY_SIZE(wm8770_intercon),
 };
 
 static const struct of_device_id wm8770_of_match[] = {
@@ -689,17 +638,57 @@ static const struct of_device_id wm8770_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, wm8770_of_match);
 
+static const struct regmap_config wm8770_regmap = {
+       .reg_bits = 7,
+       .val_bits = 9,
+       .max_register = WM8770_RESET,
+
+       .reg_defaults = wm8770_reg_defaults,
+       .num_reg_defaults = ARRAY_SIZE(wm8770_reg_defaults),
+       .cache_type = REGCACHE_RBTREE,
+
+       .volatile_reg = wm8770_volatile_reg,
+};
+
 static int __devinit wm8770_spi_probe(struct spi_device *spi)
 {
        struct wm8770_priv *wm8770;
-       int ret;
+       int ret, i;
 
        wm8770 = devm_kzalloc(&spi->dev, sizeof(struct wm8770_priv),
                              GFP_KERNEL);
        if (!wm8770)
                return -ENOMEM;
 
-       wm8770->control_type = SND_SOC_SPI;
+       for (i = 0; i < ARRAY_SIZE(wm8770->supplies); i++)
+               wm8770->supplies[i].supply = wm8770_supply_names[i];
+
+       ret = devm_regulator_bulk_get(&spi->dev, ARRAY_SIZE(wm8770->supplies),
+                                     wm8770->supplies);
+       if (ret) {
+               dev_err(&spi->dev, "Failed to request supplies: %d\n", ret);
+               return ret;
+       }
+
+       wm8770->disable_nb[0].notifier_call = wm8770_regulator_event_0;
+       wm8770->disable_nb[1].notifier_call = wm8770_regulator_event_1;
+       wm8770->disable_nb[2].notifier_call = wm8770_regulator_event_2;
+
+       /* This should really be moved into the regulator core */
+       for (i = 0; i < ARRAY_SIZE(wm8770->supplies); i++) {
+               ret = regulator_register_notifier(wm8770->supplies[i].consumer,
+                                                 &wm8770->disable_nb[i]);
+               if (ret) {
+                       dev_err(&spi->dev,
+                               "Failed to register regulator notifier: %d\n",
+                               ret);
+               }
+       }
+
+       wm8770->regmap = devm_regmap_init_spi(spi, &wm8770_regmap);
+       if (IS_ERR(wm8770->regmap))
+               return PTR_ERR(wm8770->regmap);
+
        spi_set_drvdata(spi, wm8770);
 
        ret = snd_soc_register_codec(&spi->dev,
@@ -710,7 +699,15 @@ static int __devinit wm8770_spi_probe(struct spi_device *spi)
 
 static int __devexit wm8770_spi_remove(struct spi_device *spi)
 {
+       struct wm8770_priv *wm8770 = spi_get_drvdata(spi);
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(wm8770->supplies); ++i)
+               regulator_unregister_notifier(wm8770->supplies[i].consumer,
+                                             &wm8770->disable_nb[i]);
+
        snd_soc_unregister_codec(&spi->dev);
+
        return 0;
 }
 
index 00121ba3659718ab4c4af6ff5135373762de4765..bff96500c3f38bae8f279993ad432e06f21fbb46 100644 (file)
@@ -883,13 +883,6 @@ static void wm8958_mbc_vss_loaded(const struct firmware *fw, void *context)
                wm8994->mbc_vss = fw;
                mutex_unlock(&codec->mutex);
        }
-
-       /* We can't have more than one request outstanding at once so
-        * we daisy chain.
-        */
-       request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
-                               "wm8958_enh_eq.wfw", codec->dev, GFP_KERNEL,
-                               codec, wm8958_enh_eq_loaded);
 }
 
 static void wm8958_mbc_loaded(const struct firmware *fw, void *context)
@@ -897,19 +890,11 @@ static void wm8958_mbc_loaded(const struct firmware *fw, void *context)
        struct snd_soc_codec *codec = context;
        struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
 
-       if (wm8958_dsp2_fw(codec, "MBC", fw, true) != 0)
-               return;
-
-       mutex_lock(&codec->mutex);
-       wm8994->mbc = fw;
-       mutex_unlock(&codec->mutex);
-
-       /* We can't have more than one request outstanding at once so
-        * we daisy chain.
-        */
-       request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
-                               "wm8958_mbc_vss.wfw", codec->dev, GFP_KERNEL,
-                               codec, wm8958_mbc_vss_loaded);
+       if (fw && (wm8958_dsp2_fw(codec, "MBC", fw, true) == 0)) {
+               mutex_lock(&codec->mutex);
+               wm8994->mbc = fw;
+               mutex_unlock(&codec->mutex);
+       }
 }
 
 void wm8958_dsp2_init(struct snd_soc_codec *codec)
@@ -932,6 +917,12 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec)
        request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
                                "wm8958_mbc.wfw", codec->dev, GFP_KERNEL,
                                codec, wm8958_mbc_loaded);
+       request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
+                               "wm8958_mbc_vss.wfw", codec->dev, GFP_KERNEL,
+                               codec, wm8958_mbc_vss_loaded);
+       request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
+                               "wm8958_enh_eq.wfw", codec->dev, GFP_KERNEL,
+                               codec, wm8958_enh_eq_loaded);
 
        if (!pdata)
                return;
index 5ce6477584438b3a8555bada53f8e17c1dd7cc5e..70dd27e9451408c7af2dec5da5e938cdfb4ff000 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
+#include <linux/regmap.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -34,7 +35,6 @@ static struct workqueue_struct *wm8971_workq = NULL;
 
 /* codec private data */
 struct wm8971_priv {
-       enum snd_soc_control_type control_type;
        unsigned int sysclk;
 };
 
@@ -43,18 +43,50 @@ struct wm8971_priv {
  * We can't read the WM8971 register space when we
  * are using 2 wire for device control, so we cache them instead.
  */
-static const u16 wm8971_reg[] = {
-       0x0097, 0x0097, 0x0079, 0x0079,  /*  0 */
-       0x0000, 0x0008, 0x0000, 0x000a,  /*  4 */
-       0x0000, 0x0000, 0x00ff, 0x00ff,  /*  8 */
-       0x000f, 0x000f, 0x0000, 0x0000,  /* 12 */
-       0x0000, 0x007b, 0x0000, 0x0032,  /* 16 */
-       0x0000, 0x00c3, 0x00c3, 0x00c0,  /* 20 */
-       0x0000, 0x0000, 0x0000, 0x0000,  /* 24 */
-       0x0000, 0x0000, 0x0000, 0x0000,  /* 28 */
-       0x0000, 0x0000, 0x0050, 0x0050,  /* 32 */
-       0x0050, 0x0050, 0x0050, 0x0050,  /* 36 */
-       0x0079, 0x0079, 0x0079,          /* 40 */
+static const struct reg_default wm8971_reg_defaults[] = {
+       {  0, 0x0097 },
+       {  1, 0x0097 },
+       {  2, 0x0079 },
+       {  3, 0x0079 },
+       {  4, 0x0000 },
+       {  5, 0x0008 },
+       {  6, 0x0000 },
+       {  7, 0x000a },
+       {  8, 0x0000 },
+       {  9, 0x0000 },
+       { 10, 0x00ff },
+       { 11, 0x00ff },
+       { 12, 0x000f },
+       { 13, 0x000f },
+       { 14, 0x0000 },
+       { 15, 0x0000 },
+       { 16, 0x0000 },
+       { 17, 0x007b },
+       { 18, 0x0000 },
+       { 19, 0x0032 },
+       { 20, 0x0000 },
+       { 21, 0x00c3 },
+       { 22, 0x00c3 },
+       { 23, 0x00c0 },
+       { 24, 0x0000 },
+       { 25, 0x0000 },
+       { 26, 0x0000 },
+       { 27, 0x0000 },
+       { 28, 0x0000 },
+       { 29, 0x0000 },
+       { 30, 0x0000 },
+       { 31, 0x0000 },
+       { 32, 0x0000 },
+       { 33, 0x0000 },
+       { 34, 0x0050 },
+       { 35, 0x0050 },
+       { 36, 0x0050 },
+       { 37, 0x0050 },
+       { 38, 0x0050 },
+       { 39, 0x0050 },
+       { 40, 0x0079 },
+       { 41, 0x0079 },
+       { 42, 0x0079 },
 };
 
 #define wm8971_reset(c)        snd_soc_write(c, WM8971_RESET, 0)
@@ -613,11 +645,10 @@ static int wm8971_resume(struct snd_soc_codec *codec)
 
 static int wm8971_probe(struct snd_soc_codec *codec)
 {
-       struct wm8971_priv *wm8971 = snd_soc_codec_get_drvdata(codec);
        int ret = 0;
        u16 reg;
 
-       ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8971->control_type);
+       ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
        if (ret < 0) {
                printk(KERN_ERR "wm8971: failed to set cache I/O: %d\n", ret);
                return ret;
@@ -667,9 +698,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8971 = {
        .suspend =      wm8971_suspend,
        .resume =       wm8971_resume,
        .set_bias_level = wm8971_set_bias_level,
-       .reg_cache_size = ARRAY_SIZE(wm8971_reg),
-       .reg_word_size = sizeof(u16),
-       .reg_cache_default = wm8971_reg,
 
        .controls = wm8971_snd_controls,
        .num_controls = ARRAY_SIZE(wm8971_snd_controls),
@@ -679,10 +707,21 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8971 = {
        .num_dapm_routes = ARRAY_SIZE(wm8971_dapm_routes),
 };
 
+static const struct regmap_config wm8971_regmap = {
+       .reg_bits = 7,
+       .val_bits = 9,
+       .max_register = WM8971_MOUTV,
+
+       .reg_defaults = wm8971_reg_defaults,
+       .num_reg_defaults = ARRAY_SIZE(wm8971_reg_defaults),
+       .cache_type = REGCACHE_RBTREE,
+};
+
 static __devinit int wm8971_i2c_probe(struct i2c_client *i2c,
                                      const struct i2c_device_id *id)
 {
        struct wm8971_priv *wm8971;
+       struct regmap *regmap;
        int ret;
 
        wm8971 = devm_kzalloc(&i2c->dev, sizeof(struct wm8971_priv),
@@ -690,7 +729,10 @@ static __devinit int wm8971_i2c_probe(struct i2c_client *i2c,
        if (wm8971 == NULL)
                return -ENOMEM;
 
-       wm8971->control_type = SND_SOC_I2C;
+       regmap = devm_regmap_init_i2c(i2c, &wm8971_regmap);
+       if (IS_ERR(regmap))
+               return PTR_ERR(regmap);
+
        i2c_set_clientdata(i2c, wm8971);
 
        ret = snd_soc_register_codec(&i2c->dev,
index 2b2dadc54dac5cfe729ddc2fd402e748195a6882..11982bf93a1db64ca877b1bdec2b87d68e5ecf31 100644 (file)
@@ -862,7 +862,7 @@ static void vmid_reference(struct snd_soc_codec *codec)
                                            WM8994_BIAS_SRC |
                                            WM8994_STARTUP_BIAS_ENA |
                                            WM8994_VMID_BUF_ENA |
-                                           (0x3 << WM8994_VMID_RAMP_SHIFT));
+                                           (0x2 << WM8994_VMID_RAMP_SHIFT));
 
                        /* Main bias enable, VMID=2x40k */
                        snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
@@ -870,7 +870,7 @@ static void vmid_reference(struct snd_soc_codec *codec)
                                            WM8994_VMID_SEL_MASK,
                                            WM8994_BIAS_ENA | 0x2);
 
-                       msleep(50);
+                       msleep(300);
 
                        snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
                                            WM8994_VMID_RAMP_MASK |
@@ -939,16 +939,10 @@ static void vmid_dereference(struct snd_soc_codec *codec)
                                    WM8994_BIAS_SRC |
                                    WM8994_VMID_DISCH);
 
-               switch (wm8994->vmid_mode) {
-               case WM8994_VMID_FORCE:
-                       msleep(350);
-                       break;
-               default:
-                       break;
-               }
+               snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
+                                   WM8994_VMID_SEL_MASK, 0);
 
-               snd_soc_update_bits(codec, WM8994_ADDITIONAL_CONTROL,
-                                   WM8994_VROI, WM8994_VROI);
+               msleep(400);
 
                /* Active discharge */
                snd_soc_update_bits(codec, WM8994_ANTIPOP_1,
@@ -957,17 +951,12 @@ static void vmid_dereference(struct snd_soc_codec *codec)
                                    WM8994_LINEOUT1_DISCH |
                                    WM8994_LINEOUT2_DISCH);
 
-               msleep(150);
-
                snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_3,
                                    WM8994_LINEOUT1N_ENA |
                                    WM8994_LINEOUT1P_ENA |
                                    WM8994_LINEOUT2N_ENA |
                                    WM8994_LINEOUT2P_ENA, 0);
 
-               snd_soc_update_bits(codec, WM8994_ADDITIONAL_CONTROL,
-                                   WM8994_VROI, 0);
-
                /* Switch off startup biases */
                snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
                                    WM8994_BIAS_SRC |
@@ -976,10 +965,7 @@ static void vmid_dereference(struct snd_soc_codec *codec)
                                    WM8994_VMID_RAMP_MASK, 0);
 
                snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
-                                   WM8994_BIAS_ENA | WM8994_VMID_SEL_MASK, 0);
-
-               snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
-                                   WM8994_VMID_RAMP_MASK, 0);
+                                   WM8994_VMID_SEL_MASK, 0);
        }
 
        pm_runtime_put(codec->dev);
@@ -1045,6 +1031,7 @@ static int aif1clk_ev(struct snd_soc_dapm_widget *w,
                      struct snd_kcontrol *kcontrol, int event)
 {
        struct snd_soc_codec *codec = w->codec;
+       struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
        struct wm8994 *control = codec->control_data;
        int mask = WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC1R_ENA;
        int i;
@@ -1063,6 +1050,10 @@ static int aif1clk_ev(struct snd_soc_dapm_widget *w,
 
        switch (event) {
        case SND_SOC_DAPM_PRE_PMU:
+               /* Don't enable timeslot 2 if not in use */
+               if (wm8994->channels[0] <= 2)
+                       mask &= ~(WM8994_AIF1DAC2L_ENA | WM8994_AIF1DAC2R_ENA);
+
                val = snd_soc_read(codec, WM8994_AIF1_CONTROL_1);
                if ((val & WM8994_AIF1ADCL_SRC) &&
                    (val & WM8994_AIF1ADCR_SRC))
@@ -2687,7 +2678,7 @@ static int wm8994_hw_params(struct snd_pcm_substream *substream,
                return -EINVAL;
        }
 
-       bclk_rate = params_rate(params) * 4;
+       bclk_rate = params_rate(params);
        switch (params_format(params)) {
        case SNDRV_PCM_FORMAT_S16_LE:
                bclk_rate *= 16;
@@ -2708,6 +2699,17 @@ static int wm8994_hw_params(struct snd_pcm_substream *substream,
                return -EINVAL;
        }
 
+       wm8994->channels[id] = params_channels(params);
+       switch (params_channels(params)) {
+       case 1:
+       case 2:
+               bclk_rate *= 2;
+               break;
+       default:
+               bclk_rate *= 4;
+               break;
+       }
+
        /* Try to find an appropriate sample rate; look for an exact match. */
        for (i = 0; i < ARRAY_SIZE(srs); i++)
                if (srs[i].rate == params_rate(params))
@@ -3470,11 +3472,46 @@ static void wm8958_default_micdet(u16 status, void *data)
        }
 }
 
+/* Deferred mic detection to allow for extra settling time */
+static void wm1811_mic_work(struct work_struct *work)
+{
+       struct wm8994_priv *wm8994 = container_of(work, struct wm8994_priv,
+                                                 mic_work.work);
+       struct snd_soc_codec *codec = wm8994->hubs.codec;
+
+       pm_runtime_get_sync(codec->dev);
+
+       /* If required for an external cap force MICBIAS on */
+       if (wm8994->pdata->jd_ext_cap) {
+               snd_soc_dapm_force_enable_pin(&codec->dapm,
+                                             "MICBIAS2");
+               snd_soc_dapm_sync(&codec->dapm);
+       }
+
+       mutex_lock(&wm8994->accdet_lock);
+
+       dev_dbg(codec->dev, "Starting mic detection\n");
+
+       /*
+        * Start off measument of microphone impedence to find out
+        * what's actually there.
+        */
+       wm8994->mic_detecting = true;
+       wm1811_jackdet_set_mode(codec, WM1811_JACKDET_MODE_MIC);
+
+       snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
+                           WM8958_MICD_ENA, WM8958_MICD_ENA);
+
+       mutex_unlock(&wm8994->accdet_lock);
+
+       pm_runtime_put(codec->dev);
+}
+
 static irqreturn_t wm1811_jackdet_irq(int irq, void *data)
 {
        struct wm8994_priv *wm8994 = data;
        struct snd_soc_codec *codec = wm8994->hubs.codec;
-       int reg;
+       int reg, delay;
        bool present;
 
        pm_runtime_get_sync(codec->dev);
@@ -3505,18 +3542,14 @@ static irqreturn_t wm1811_jackdet_irq(int irq, void *data)
                snd_soc_update_bits(codec, WM1811_JACKDET_CTRL,
                                    WM1811_JACKDET_DB, 0);
 
-               /*
-                * Start off measument of microphone impedence to find
-                * out what's actually there.
-                */
-               wm8994->mic_detecting = true;
-               wm1811_jackdet_set_mode(codec, WM1811_JACKDET_MODE_MIC);
-
-               snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
-                                   WM8958_MICD_ENA, WM8958_MICD_ENA);
+               delay = wm8994->pdata->micdet_delay;
+               schedule_delayed_work(&wm8994->mic_work,
+                                     msecs_to_jiffies(delay));
        } else {
                dev_dbg(codec->dev, "Jack not detected\n");
 
+               cancel_delayed_work_sync(&wm8994->mic_work);
+
                snd_soc_update_bits(codec, WM8958_MICBIAS2,
                                    WM8958_MICB2_DISCH, WM8958_MICB2_DISCH);
 
@@ -3533,14 +3566,9 @@ static irqreturn_t wm1811_jackdet_irq(int irq, void *data)
 
        mutex_unlock(&wm8994->accdet_lock);
 
-       /* If required for an external cap force MICBIAS on */
-       if (wm8994->pdata->jd_ext_cap) {
-               if (present)
-                       snd_soc_dapm_force_enable_pin(&codec->dapm,
-                                                     "MICBIAS2");
-               else
-                       snd_soc_dapm_disable_pin(&codec->dapm, "MICBIAS2");
-       }
+       /* Turn off MICBIAS if it was on for an external cap */
+       if (wm8994->pdata->jd_ext_cap && !present)
+               snd_soc_dapm_disable_pin(&codec->dapm, "MICBIAS2");
 
        if (present)
                snd_soc_jack_report(wm8994->micdet[0].jack,
@@ -3763,10 +3791,20 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
        snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP);
 
        mutex_init(&wm8994->accdet_lock);
-       INIT_DELAYED_WORK(&wm8994->mic_work, wm8994_mic_work);
        INIT_DELAYED_WORK(&wm8994->jackdet_bootstrap,
                          wm1811_jackdet_bootstrap);
 
+       switch (control->type) {
+       case WM8994:
+               INIT_DELAYED_WORK(&wm8994->mic_work, wm8994_mic_work);
+               break;
+       case WM1811:
+               INIT_DELAYED_WORK(&wm8994->mic_work, wm1811_mic_work);
+               break;
+       default:
+               break;
+       }
+
        for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++)
                init_completion(&wm8994->fll_locked[i]);
 
index f142ec198db3dabfcfc5d1e20a51cdfd5e42874b..ccbce5791e95829b5d98ce472ac50d922e6e4703 100644 (file)
@@ -77,6 +77,7 @@ struct wm8994_priv {
        int sysclk_rate[2];
        int mclk[2];
        int aifclk[2];
+       int channels[2];
        struct wm8994_fll_config fll[2], fll_suspend[2];
        struct completion fll_locked[2];
        bool fll_locked_irq;
diff --git a/sound/soc/codecs/wmfw.h b/sound/soc/codecs/wmfw.h
new file mode 100644 (file)
index 0000000..5791f8e
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * wmfw.h - Wolfson firmware format information
+ *
+ * Copyright 2012 Wolfson Microelectronics plc
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __WMFW_H
+#define __WMFW_H
+
+#include <linux/types.h>
+
+struct wmfw_header {
+       char magic[4];
+       __le32 len;
+       __le16 rev;
+       u8 core;
+       u8 ver;
+} __packed;
+
+struct wmfw_footer {
+       __le64 timestamp;
+       __le32 checksum;
+} __packed;
+
+struct wmfw_adsp1_sizes {
+       __le32 dm;
+       __le32 pm;
+       __le32 zm;
+} __packed;
+
+struct wmfw_region {
+       union {
+               __be32 type;
+               __le32 offset;
+       };
+       __le32 len;
+       u8 data[];
+} __packed;
+
+struct wmfw_id_hdr {
+       __be32 core_id;
+       __be32 core_rev;
+       __be32 id;
+       __be32 ver;
+} __packed;
+
+struct wmfw_adsp1_id_hdr {
+       struct wmfw_id_hdr fw;
+       __be32 zm;
+       __be32 dm;
+       __be32 algs;
+} __packed;
+
+struct wmfw_alg_hdr {
+       __be32 id;
+       __be32 ver;
+} __packed;
+
+struct wmfw_adsp1_alg_hdr {
+       struct wmfw_alg_hdr alg;
+       __be32 zm;
+       __be32 dm;
+} __packed;
+
+struct wmfw_coeff_hdr {
+       u8 magic[4];
+       __le32 len;
+       __le32 ver;
+       u8 data[];
+} __packed;
+
+struct wmfw_coeff_item {
+       union {
+               __be32 type;
+               __le32 offset;
+       };
+       __le32 id;
+       __le32 ver;
+       __le32 sr;
+       __le32 len;
+       u8 data[];
+} __packed;
+#define WMFW_ADSP1 1
+
+#define WMFW_ABSOLUTE  0xf0
+#define WMFW_NAME_TEXT 0xfe
+#define WMFW_INFO_TEXT 0xff
+
+#define WMFW_ADSP1_PM 2
+#define WMFW_ADSP1_DM 3
+#define WMFW_ADSP1_ZM 4
+
+#endif
index 6fac5af13298ffa2c64ebf5bad1b5fde6a0ac6f6..d55e6477bff0c9a855379d26db50538ff7b5e178 100644 (file)
@@ -71,6 +71,11 @@ static int evm_hw_params(struct snd_pcm_substream *substream,
        if (ret < 0)
                return ret;
 
+       /* set the CPU system clock */
+       ret = snd_soc_dai_set_sysclk(cpu_dai, 0, sysclk, SND_SOC_CLOCK_OUT);
+       if (ret < 0)
+               return ret;
+
        return 0;
 }
 
index 714e51e5be5bd2c7038f1965a74545a01c5a268c..571559501b0b6f79854701e74753347b2edd21ca 100644 (file)
 #define ACLKXE         BIT(5)
 #define TX_ASYNC       BIT(6)
 #define ACLKXPOL       BIT(7)
+#define ACLKXDIV_MASK  0x1f
 
 /*
  * DAVINCI_MCASP_ACLKRCTL_REG Receive Clock Control Register Bits
 #define ACLKRE         BIT(5)
 #define RX_ASYNC       BIT(6)
 #define ACLKRPOL       BIT(7)
+#define ACLKRDIV_MASK  0x1f
 
 /*
  * DAVINCI_MCASP_AHCLKXCTL_REG - High Frequency Transmit Clock Control
 #define AHCLKXDIV(val) (val)
 #define AHCLKXPOL      BIT(14)
 #define AHCLKXE                BIT(15)
+#define AHCLKXDIV_MASK 0xfff
 
 /*
  * DAVINCI_MCASP_AHCLKRCTL_REG - High Frequency Receive Clock Control
 #define AHCLKRDIV(val) (val)
 #define AHCLKRPOL      BIT(14)
 #define AHCLKRE                BIT(15)
+#define AHCLKRDIV_MASK 0xfff
 
 /*
  * DAVINCI_MCASP_XRSRCTL_BASE_REG -  Serializer Control Register Bits
@@ -473,6 +477,23 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
        struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);
        void __iomem *base = dev->base;
 
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_DSP_B:
+       case SND_SOC_DAIFMT_AC97:
+               mcasp_clr_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG, FSXDUR);
+               mcasp_clr_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG, FSRDUR);
+               break;
+       default:
+               /* configure a full-word SYNC pulse (LRCLK) */
+               mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG, FSXDUR);
+               mcasp_set_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG, FSRDUR);
+
+               /* make 1st data bit occur one ACLK cycle after the frame sync */
+               mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, FSXDLY(1));
+               mcasp_set_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, FSRDLY(1));
+               break;
+       }
+
        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
        case SND_SOC_DAIFMT_CBS_CFS:
                /* codec is clock and frame slave */
@@ -482,8 +503,7 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
                mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
                mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE);
 
-               mcasp_set_bits(base + DAVINCI_MCASP_PDIR_REG,
-                               ACLKX | AHCLKX | AFSX);
+               mcasp_set_bits(base + DAVINCI_MCASP_PDIR_REG, ACLKX | AFSX);
                break;
        case SND_SOC_DAIFMT_CBM_CFS:
                /* codec is clock master and frame slave */
@@ -554,6 +574,50 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
        return 0;
 }
 
+static int davinci_mcasp_set_clkdiv(struct snd_soc_dai *dai, int div_id, int div)
+{
+       struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(dai);
+
+       switch (div_id) {
+       case 0:         /* MCLK divider */
+               mcasp_mod_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG,
+                              AHCLKXDIV(div - 1), AHCLKXDIV_MASK);
+               mcasp_mod_bits(dev->base + DAVINCI_MCASP_AHCLKRCTL_REG,
+                              AHCLKRDIV(div - 1), AHCLKRDIV_MASK);
+               break;
+
+       case 1:         /* BCLK divider */
+               mcasp_mod_bits(dev->base + DAVINCI_MCASP_ACLKXCTL_REG,
+                              ACLKXDIV(div - 1), ACLKXDIV_MASK);
+               mcasp_mod_bits(dev->base + DAVINCI_MCASP_ACLKRCTL_REG,
+                              ACLKRDIV(div - 1), ACLKRDIV_MASK);
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int davinci_mcasp_set_sysclk(struct snd_soc_dai *dai, int clk_id,
+                                   unsigned int freq, int dir)
+{
+       struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(dai);
+
+       if (dir == SND_SOC_CLOCK_OUT) {
+               mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXE);
+               mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKRCTL_REG, AHCLKRE);
+               mcasp_set_bits(dev->base + DAVINCI_MCASP_PDIR_REG, AHCLKX);
+       } else {
+               mcasp_clr_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXE);
+               mcasp_clr_bits(dev->base + DAVINCI_MCASP_AHCLKRCTL_REG, AHCLKRE);
+               mcasp_clr_bits(dev->base + DAVINCI_MCASP_PDIR_REG, AHCLKX);
+       }
+
+       return 0;
+}
+
 static int davinci_config_channel_size(struct davinci_audio_dev *dev,
                                       int channel_size)
 {
@@ -709,8 +773,6 @@ static void davinci_hw_param(struct davinci_audio_dev *dev, int stream)
        if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
                /* bit stream is MSB first  with no delay */
                /* DSP_B mode */
-               mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG,
-                               AHCLKXE);
                mcasp_set_reg(dev->base + DAVINCI_MCASP_TXTDM_REG, mask);
                mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, TXORD);
 
@@ -720,14 +782,10 @@ static void davinci_hw_param(struct davinci_audio_dev *dev, int stream)
                else
                        printk(KERN_ERR "playback tdm slot %d not supported\n",
                                dev->tdm_slots);
-
-               mcasp_clr_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG, FSXDUR);
        } else {
                /* bit stream is MSB first with no delay */
                /* DSP_B mode */
                mcasp_set_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, RXORD);
-               mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKRCTL_REG,
-                               AHCLKRE);
                mcasp_set_reg(dev->base + DAVINCI_MCASP_RXTDM_REG, mask);
 
                if ((dev->tdm_slots >= 2) && (dev->tdm_slots <= 32))
@@ -736,8 +794,6 @@ static void davinci_hw_param(struct davinci_audio_dev *dev, int stream)
                else
                        printk(KERN_ERR "capture tdm slot %d not supported\n",
                                dev->tdm_slots);
-
-               mcasp_clr_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG, FSRDUR);
        }
 }
 
@@ -809,6 +865,14 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
                word_length = DAVINCI_AUDIO_WORD_16;
                break;
 
+       case SNDRV_PCM_FORMAT_U24_3LE:
+       case SNDRV_PCM_FORMAT_S24_3LE:
+               dma_params->data_type = 3;
+               word_length = DAVINCI_AUDIO_WORD_24;
+               break;
+
+       case SNDRV_PCM_FORMAT_U24_LE:
+       case SNDRV_PCM_FORMAT_S24_LE:
        case SNDRV_PCM_FORMAT_U32_LE:
        case SNDRV_PCM_FORMAT_S32_LE:
                dma_params->data_type = 4;
@@ -880,13 +944,18 @@ static const struct snd_soc_dai_ops davinci_mcasp_dai_ops = {
        .trigger        = davinci_mcasp_trigger,
        .hw_params      = davinci_mcasp_hw_params,
        .set_fmt        = davinci_mcasp_set_dai_fmt,
-
+       .set_clkdiv     = davinci_mcasp_set_clkdiv,
+       .set_sysclk     = davinci_mcasp_set_sysclk,
 };
 
 #define DAVINCI_MCASP_PCM_FMTS (SNDRV_PCM_FMTBIT_S8 | \
                                SNDRV_PCM_FMTBIT_U8 | \
                                SNDRV_PCM_FMTBIT_S16_LE | \
                                SNDRV_PCM_FMTBIT_U16_LE | \
+                               SNDRV_PCM_FMTBIT_S24_LE | \
+                               SNDRV_PCM_FMTBIT_U24_LE | \
+                               SNDRV_PCM_FMTBIT_S24_3LE | \
+                               SNDRV_PCM_FMTBIT_U24_3LE | \
                                SNDRV_PCM_FMTBIT_S32_LE | \
                                SNDRV_PCM_FMTBIT_U32_LE)
 
@@ -1098,6 +1167,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
        dma_data = &dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK];
        dma_data->asp_chan_q = pdata->asp_chan_q;
        dma_data->ram_chan_q = pdata->ram_chan_q;
+       dma_data->sram_pool = pdata->sram_pool;
        dma_data->sram_size = pdata->sram_size_playback;
        dma_data->dma_addr = (dma_addr_t) (pdata->tx_dma_offset +
                                                        mem->start);
@@ -1115,6 +1185,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
        dma_data = &dev->dma_params[SNDRV_PCM_STREAM_CAPTURE];
        dma_data->asp_chan_q = pdata->asp_chan_q;
        dma_data->ram_chan_q = pdata->ram_chan_q;
+       dma_data->sram_pool = pdata->sram_pool;
        dma_data->sram_size = pdata->sram_size_capture;
        dma_data->dma_addr = (dma_addr_t)(pdata->rx_dma_offset +
                                                        mem->start);
index 0de9ed6ce038a8472aeb762d403fbf26d579bc24..156f15f55744582dadff2a350f8b581466128134 100644 (file)
@@ -23,7 +23,7 @@
 
 #include "davinci-pcm.h"
 
-#define DAVINCI_MCASP_RATES    SNDRV_PCM_RATE_8000_96000
+#define DAVINCI_MCASP_RATES    SNDRV_PCM_RATE_8000_192000
 #define DAVINCI_MCASP_I2S_DAI  0
 #define DAVINCI_MCASP_DIT_DAI  1
 
index 93ea3bf567e1fd1835ff643ff4e73d67fecdce12..afab81f844ae82c32418d6d1f83301c2d29d1f4e 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/slab.h>
 #include <linux/dma-mapping.h>
 #include <linux/kernel.h>
+#include <linux/genalloc.h>
 
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -23,7 +24,6 @@
 #include <sound/soc.h>
 
 #include <asm/dma.h>
-#include <mach/sram.h>
 
 #include "davinci-pcm.h"
 
@@ -67,13 +67,9 @@ static struct snd_pcm_hardware pcm_hardware_playback = {
                 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME|
                 SNDRV_PCM_INFO_BATCH),
        .formats = DAVINCI_PCM_FMTBITS,
-       .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
-                 SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 |
-                 SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
-                 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
-                 SNDRV_PCM_RATE_KNOT),
+       .rates = SNDRV_PCM_RATE_8000_192000 | SNDRV_PCM_RATE_KNOT,
        .rate_min = 8000,
-       .rate_max = 96000,
+       .rate_max = 192000,
        .channels_min = 2,
        .channels_max = 384,
        .buffer_bytes_max = 128 * 1024,
@@ -90,13 +86,9 @@ static struct snd_pcm_hardware pcm_hardware_capture = {
                 SNDRV_PCM_INFO_PAUSE |
                 SNDRV_PCM_INFO_BATCH),
        .formats = DAVINCI_PCM_FMTBITS,
-       .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
-                 SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 |
-                 SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
-                 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
-                 SNDRV_PCM_RATE_KNOT),
+       .rates = SNDRV_PCM_RATE_8000_192000 | SNDRV_PCM_RATE_KNOT,
        .rate_min = 8000,
-       .rate_max = 96000,
+       .rate_max = 192000,
        .channels_min = 2,
        .channels_max = 384,
        .buffer_bytes_max = 128 * 1024,
@@ -259,7 +251,9 @@ static void davinci_pcm_dma_irq(unsigned link, u16 ch_status, void *data)
        }
 }
 
-static int allocate_sram(struct snd_pcm_substream *substream, unsigned size,
+#ifdef CONFIG_GENERIC_ALLOCATOR
+static int allocate_sram(struct snd_pcm_substream *substream,
+               struct gen_pool *sram_pool, unsigned size,
                struct snd_pcm_hardware *ppcm)
 {
        struct snd_dma_buffer *buf = &substream->dma_buffer;
@@ -271,9 +265,10 @@ static int allocate_sram(struct snd_pcm_substream *substream, unsigned size,
                return 0;
 
        ppcm->period_bytes_max = size;
-       iram_virt = sram_alloc(size, &iram_phys);
+       iram_virt = (void *)gen_pool_alloc(sram_pool, size);
        if (!iram_virt)
                goto exit1;
+       iram_phys = gen_pool_virt_to_phys(sram_pool, (unsigned)iram_virt);
        iram_dma = kzalloc(sizeof(*iram_dma), GFP_KERNEL);
        if (!iram_dma)
                goto exit2;
@@ -285,11 +280,33 @@ static int allocate_sram(struct snd_pcm_substream *substream, unsigned size,
        return 0;
 exit2:
        if (iram_virt)
-               sram_free(iram_virt, size);
+               gen_pool_free(sram_pool, (unsigned)iram_virt, size);
 exit1:
        return -ENOMEM;
 }
 
+static void davinci_free_sram(struct snd_pcm_substream *substream,
+                             struct snd_dma_buffer *iram_dma)
+{
+       struct davinci_runtime_data *prtd = substream->runtime->private_data;
+       struct gen_pool *sram_pool = prtd->params->sram_pool;
+
+       gen_pool_free(sram_pool, (unsigned) iram_dma->area, iram_dma->bytes);
+}
+#else
+static int allocate_sram(struct snd_pcm_substream *substream,
+               struct gen_pool *sram_pool, unsigned size,
+               struct snd_pcm_hardware *ppcm)
+{
+       return 0;
+}
+
+static void davinci_free_sram(struct snd_pcm_substream *substream,
+                             struct snd_dma_buffer *iram_dma)
+{
+}
+#endif
+
 /*
  * Only used with ping/pong.
  * This is called after runtime->dma_addr, period_bytes and data_type are valid
@@ -676,7 +693,7 @@ static int davinci_pcm_open(struct snd_pcm_substream *substream)
 
        ppcm = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
                        &pcm_hardware_playback : &pcm_hardware_capture;
-       allocate_sram(substream, params->sram_size, ppcm);
+       allocate_sram(substream, params->sram_pool, params->sram_size, ppcm);
        snd_soc_set_runtime_hwparams(substream, ppcm);
        /* ensure that buffer size is a multiple of period size */
        ret = snd_pcm_hw_constraint_integer(runtime,
@@ -819,7 +836,7 @@ static void davinci_pcm_free(struct snd_pcm *pcm)
                buf->area = NULL;
                iram_dma = buf->private_data;
                if (iram_dma) {
-                       sram_free(iram_dma->area, iram_dma->bytes);
+                       davinci_free_sram(substream, iram_dma);
                        kfree(iram_dma);
                }
        }
index fc4d01cdd8c95c92b11694faece56d77fc648bd9..b6ef7039dd097b4ac99c6e9b14a0c35ed59fd203 100644 (file)
@@ -12,6 +12,7 @@
 #ifndef _DAVINCI_PCM_H
 #define _DAVINCI_PCM_H
 
+#include <linux/genalloc.h>
 #include <linux/platform_data/davinci_asp.h>
 #include <mach/edma.h>
 
@@ -20,6 +21,7 @@ struct davinci_pcm_dma_params {
        unsigned short acnt;
        dma_addr_t dma_addr;            /* device physical address for DMA */
        unsigned sram_size;
+       struct gen_pool *sram_pool;     /* SRAM gen_pool for ping pong */
        enum dma_event_q asp_chan_q;    /* event queue number for ASP channel */
        enum dma_event_q ram_chan_q;    /* event queue number for RAM channel */
        unsigned char data_type;        /* xfer data type */
index 4563b28bd6254ddbeda6f0cd8229f22b10159ef7..10fd172ee3c6777064c654e3fe4d361fd23b4dfe 100644 (file)
@@ -46,6 +46,20 @@ config SND_SOC_P1022_DS
          This will also include the Wolfson Microelectronics WM8776 codec
          driver.
 
+config SND_SOC_P1022_RDK
+       tristate "ALSA SoC support for the Freescale / iVeia P1022 RDK board"
+       # I2C is necessary for the WM8960 driver
+       depends on P1022_RDK && I2C
+       select SND_SOC_FSL_SSI
+       select SND_SOC_FSL_UTILS
+       select SND_SOC_POWERPC_DMA
+       select SND_SOC_WM8960
+       default y if P1022_RDK
+       help
+         Say Y if you want to enable audio on the Freescale / iVeia
+         P1022 RDK board.  This will also include the Wolfson
+         Microelectronics WM8960 codec driver.
+
 config SND_SOC_MPC5200_I2S
        tristate "Freescale MPC5200 PSC in I2S mode driver"
        depends on PPC_MPC52xx && PPC_BESTCOMM
@@ -112,7 +126,7 @@ config SND_SOC_IMX_AUDMUX
 
 config SND_MXC_SOC_WM1133_EV1
        tristate "Audio on the i.MX31ADS with WM1133-EV1 fitted"
-       depends on MACH_MX31ADS_WM1133_EV1 && EXPERIMENTAL
+       depends on MACH_MX31ADS_WM1133_EV1
        select SND_SOC_WM8350
        select SND_SOC_IMX_PCM_FIQ
        select SND_SOC_IMX_AUDMUX
index 5f3cf3f52ea03e16a1a374ca530f6daec7a2ed35..515ba665f97c222714f5b138f1a8c03b95b74724 100644 (file)
@@ -6,6 +6,10 @@ obj-$(CONFIG_SND_SOC_MPC8610_HPCD) += snd-soc-mpc8610-hpcd.o
 snd-soc-p1022-ds-objs := p1022_ds.o
 obj-$(CONFIG_SND_SOC_P1022_DS) += snd-soc-p1022-ds.o
 
+# P1022 RDK Machine Support
+snd-soc-p1022-rdk-objs := p1022_rdk.o
+obj-$(CONFIG_SND_SOC_P1022_RDK) += snd-soc-p1022-rdk.o
+
 # Freescale PowerPC SSI/DMA Platform Support
 snd-soc-fsl-ssi-objs := fsl_ssi.o
 snd-soc-fsl-utils-objs := fsl_utils.o
index 22c6130957ba429626004f310469ac94444f56be..9ffc9e66308f297a5e9a6ed39c7a3ddece48b9d2 100644 (file)
@@ -29,7 +29,6 @@
 
 #include <asm/fiq.h>
 
-#include <mach/irqs.h>
 #include <linux/platform_data/asoc-imx-ssi.h>
 
 #include "imx-ssi.h"
index 006f7d465ed2dda2f3122b307cb40820aef37a5d..dd566444e3c3b61b832a62e3763645393fcfbd88 100644 (file)
@@ -48,7 +48,6 @@
 #include <sound/soc.h>
 
 #include <linux/platform_data/asoc-imx-ssi.h>
-#include <mach/hardware.h>
 
 #include "imx-ssi.h"
 
diff --git a/sound/soc/fsl/p1022_rdk.c b/sound/soc/fsl/p1022_rdk.c
new file mode 100644 (file)
index 0000000..897e32f
--- /dev/null
@@ -0,0 +1,392 @@
+/**
+ * Freescale P1022RDK ALSA SoC Machine driver
+ *
+ * Author: Timur Tabi <timur@freescale.com>
+ *
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ *
+ * Note: in order for audio to work correctly, the output controls need
+ * to be enabled, because they control the clock.  So for playback, for
+ * example:
+ *
+ *      amixer sset 'Left Output Mixer PCM' on
+ *      amixer sset 'Right Output Mixer PCM' on
+ */
+
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/of_device.h>
+#include <linux/slab.h>
+#include <sound/soc.h>
+#include <asm/fsl_guts.h>
+
+#include "fsl_dma.h"
+#include "fsl_ssi.h"
+#include "fsl_utils.h"
+
+/* P1022-specific PMUXCR and DMUXCR bit definitions */
+
+#define CCSR_GUTS_PMUXCR_UART0_I2C1_MASK       0x0001c000
+#define CCSR_GUTS_PMUXCR_UART0_I2C1_UART0_SSI  0x00010000
+#define CCSR_GUTS_PMUXCR_UART0_I2C1_SSI                0x00018000
+
+#define CCSR_GUTS_PMUXCR_SSI_DMA_TDM_MASK      0x00000c00
+#define CCSR_GUTS_PMUXCR_SSI_DMA_TDM_SSI       0x00000000
+
+#define CCSR_GUTS_DMUXCR_PAD   1       /* DMA controller/channel set to pad */
+#define CCSR_GUTS_DMUXCR_SSI   2       /* DMA controller/channel set to SSI */
+
+/*
+ * Set the DMACR register in the GUTS
+ *
+ * The DMACR register determines the source of initiated transfers for each
+ * channel on each DMA controller.  Rather than have a bunch of repetitive
+ * macros for the bit patterns, we just have a function that calculates
+ * them.
+ *
+ * guts: Pointer to GUTS structure
+ * co: The DMA controller (0 or 1)
+ * ch: The channel on the DMA controller (0, 1, 2, or 3)
+ * device: The device to set as the target (CCSR_GUTS_DMUXCR_xxx)
+ */
+static inline void guts_set_dmuxcr(struct ccsr_guts __iomem *guts,
+       unsigned int co, unsigned int ch, unsigned int device)
+{
+       unsigned int shift = 16 + (8 * (1 - co) + 2 * (3 - ch));
+
+       clrsetbits_be32(&guts->dmuxcr, 3 << shift, device << shift);
+}
+
+/* There's only one global utilities register */
+static phys_addr_t guts_phys;
+
+/**
+ * machine_data: machine-specific ASoC device data
+ *
+ * This structure contains data for a single sound platform device on an
+ * P1022 RDK.  Some of the data is taken from the device tree.
+ */
+struct machine_data {
+       struct snd_soc_dai_link dai[2];
+       struct snd_soc_card card;
+       unsigned int dai_format;
+       unsigned int codec_clk_direction;
+       unsigned int cpu_clk_direction;
+       unsigned int clk_frequency;
+       unsigned int dma_id[2];         /* 0 = DMA1, 1 = DMA2, etc */
+       unsigned int dma_channel_id[2]; /* 0 = ch 0, 1 = ch 1, etc*/
+       char platform_name[2][DAI_NAME_SIZE]; /* One for each DMA channel */
+};
+
+/**
+ * p1022_rdk_machine_probe: initialize the board
+ *
+ * This function is used to initialize the board-specific hardware.
+ *
+ * Here we program the DMACR and PMUXCR registers.
+ */
+static int p1022_rdk_machine_probe(struct snd_soc_card *card)
+{
+       struct machine_data *mdata =
+               container_of(card, struct machine_data, card);
+       struct ccsr_guts __iomem *guts;
+
+       guts = ioremap(guts_phys, sizeof(struct ccsr_guts));
+       if (!guts) {
+               dev_err(card->dev, "could not map global utilities\n");
+               return -ENOMEM;
+       }
+
+       /* Enable SSI Tx signal */
+       clrsetbits_be32(&guts->pmuxcr, CCSR_GUTS_PMUXCR_UART0_I2C1_MASK,
+                       CCSR_GUTS_PMUXCR_UART0_I2C1_UART0_SSI);
+
+       /* Enable SSI Rx signal */
+       clrsetbits_be32(&guts->pmuxcr, CCSR_GUTS_PMUXCR_SSI_DMA_TDM_MASK,
+                       CCSR_GUTS_PMUXCR_SSI_DMA_TDM_SSI);
+
+       /* Enable DMA Channel for SSI */
+       guts_set_dmuxcr(guts, mdata->dma_id[0], mdata->dma_channel_id[0],
+                       CCSR_GUTS_DMUXCR_SSI);
+
+       guts_set_dmuxcr(guts, mdata->dma_id[1], mdata->dma_channel_id[1],
+                       CCSR_GUTS_DMUXCR_SSI);
+
+       iounmap(guts);
+
+       return 0;
+}
+
+/**
+ * p1022_rdk_startup: program the board with various hardware parameters
+ *
+ * This function takes board-specific information, like clock frequencies
+ * and serial data formats, and passes that information to the codec and
+ * transport drivers.
+ */
+static int p1022_rdk_startup(struct snd_pcm_substream *substream)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct machine_data *mdata =
+               container_of(rtd->card, struct machine_data, card);
+       struct device *dev = rtd->card->dev;
+       int ret = 0;
+
+       /* Tell the codec driver what the serial protocol is. */
+       ret = snd_soc_dai_set_fmt(rtd->codec_dai, mdata->dai_format);
+       if (ret < 0) {
+               dev_err(dev, "could not set codec driver audio format (ret=%i)\n",
+                       ret);
+               return ret;
+       }
+
+       ret = snd_soc_dai_set_pll(rtd->codec_dai, 0, 0, mdata->clk_frequency,
+               mdata->clk_frequency);
+       if (ret < 0) {
+               dev_err(dev, "could not set codec PLL frequency (ret=%i)\n",
+                       ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+/**
+ * p1022_rdk_machine_remove: Remove the sound device
+ *
+ * This function is called to remove the sound device for one SSI.  We
+ * de-program the DMACR and PMUXCR register.
+ */
+static int p1022_rdk_machine_remove(struct snd_soc_card *card)
+{
+       struct machine_data *mdata =
+               container_of(card, struct machine_data, card);
+       struct ccsr_guts __iomem *guts;
+
+       guts = ioremap(guts_phys, sizeof(struct ccsr_guts));
+       if (!guts) {
+               dev_err(card->dev, "could not map global utilities\n");
+               return -ENOMEM;
+       }
+
+       /* Restore the signal routing */
+       clrbits32(&guts->pmuxcr, CCSR_GUTS_PMUXCR_UART0_I2C1_MASK);
+       clrbits32(&guts->pmuxcr, CCSR_GUTS_PMUXCR_SSI_DMA_TDM_MASK);
+       guts_set_dmuxcr(guts, mdata->dma_id[0], mdata->dma_channel_id[0], 0);
+       guts_set_dmuxcr(guts, mdata->dma_id[1], mdata->dma_channel_id[1], 0);
+
+       iounmap(guts);
+
+       return 0;
+}
+
+/**
+ * p1022_rdk_ops: ASoC machine driver operations
+ */
+static struct snd_soc_ops p1022_rdk_ops = {
+       .startup = p1022_rdk_startup,
+};
+
+/**
+ * p1022_rdk_probe: platform probe function for the machine driver
+ *
+ * Although this is a machine driver, the SSI node is the "master" node with
+ * respect to audio hardware connections.  Therefore, we create a new ASoC
+ * device for each new SSI node that has a codec attached.
+ */
+static int p1022_rdk_probe(struct platform_device *pdev)
+{
+       struct device *dev = pdev->dev.parent;
+       /* ssi_pdev is the platform device for the SSI node that probed us */
+       struct platform_device *ssi_pdev =
+               container_of(dev, struct platform_device, dev);
+       struct device_node *np = ssi_pdev->dev.of_node;
+       struct device_node *codec_np = NULL;
+       struct machine_data *mdata;
+       const u32 *iprop;
+       int ret;
+
+       /* Find the codec node for this SSI. */
+       codec_np = of_parse_phandle(np, "codec-handle", 0);
+       if (!codec_np) {
+               dev_err(dev, "could not find codec node\n");
+               return -EINVAL;
+       }
+
+       mdata = kzalloc(sizeof(struct machine_data), GFP_KERNEL);
+       if (!mdata) {
+               ret = -ENOMEM;
+               goto error_put;
+       }
+
+       mdata->dai[0].cpu_dai_name = dev_name(&ssi_pdev->dev);
+       mdata->dai[0].ops = &p1022_rdk_ops;
+
+       /* ASoC core can match codec with device node */
+       mdata->dai[0].codec_of_node = codec_np;
+
+       /*
+        * We register two DAIs per SSI, one for playback and the other for
+        * capture.  We support codecs that have separate DAIs for both playback
+        * and capture.
+        */
+       memcpy(&mdata->dai[1], &mdata->dai[0], sizeof(struct snd_soc_dai_link));
+
+       /* The DAI names from the codec (snd_soc_dai_driver.name) */
+       mdata->dai[0].codec_dai_name = "wm8960-hifi";
+       mdata->dai[1].codec_dai_name = mdata->dai[0].codec_dai_name;
+
+       /*
+        * Configure the SSI for I2S slave mode.  Older device trees have
+        * an fsl,mode property, but we ignore that since there's really
+        * only one way to configure the SSI.
+        */
+       mdata->dai_format = SND_SOC_DAIFMT_NB_NF |
+               SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM;
+       mdata->codec_clk_direction = SND_SOC_CLOCK_OUT;
+       mdata->cpu_clk_direction = SND_SOC_CLOCK_IN;
+
+       /*
+        * In i2s-slave mode, the codec has its own clock source, so we
+        * need to get the frequency from the device tree and pass it to
+        * the codec driver.
+        */
+       iprop = of_get_property(codec_np, "clock-frequency", NULL);
+       if (!iprop || !*iprop) {
+               dev_err(&pdev->dev, "codec bus-frequency property is missing or invalid\n");
+               ret = -EINVAL;
+               goto error;
+       }
+       mdata->clk_frequency = be32_to_cpup(iprop);
+
+       if (!mdata->clk_frequency) {
+               dev_err(&pdev->dev, "unknown clock frequency\n");
+               ret = -EINVAL;
+               goto error;
+       }
+
+       /* Find the playback DMA channel to use. */
+       mdata->dai[0].platform_name = mdata->platform_name[0];
+       ret = fsl_asoc_get_dma_channel(np, "fsl,playback-dma", &mdata->dai[0],
+                                      &mdata->dma_channel_id[0],
+                                      &mdata->dma_id[0]);
+       if (ret) {
+               dev_err(&pdev->dev, "missing/invalid playback DMA phandle (ret=%i)\n",
+                       ret);
+               goto error;
+       }
+
+       /* Find the capture DMA channel to use. */
+       mdata->dai[1].platform_name = mdata->platform_name[1];
+       ret = fsl_asoc_get_dma_channel(np, "fsl,capture-dma", &mdata->dai[1],
+                                      &mdata->dma_channel_id[1],
+                                      &mdata->dma_id[1]);
+       if (ret) {
+               dev_err(&pdev->dev, "missing/invalid capture DMA phandle (ret=%i)\n",
+                       ret);
+               goto error;
+       }
+
+       /* Initialize our DAI data structure.  */
+       mdata->dai[0].stream_name = "playback";
+       mdata->dai[1].stream_name = "capture";
+       mdata->dai[0].name = mdata->dai[0].stream_name;
+       mdata->dai[1].name = mdata->dai[1].stream_name;
+
+       mdata->card.probe = p1022_rdk_machine_probe;
+       mdata->card.remove = p1022_rdk_machine_remove;
+       mdata->card.name = pdev->name; /* The platform driver name */
+       mdata->card.owner = THIS_MODULE;
+       mdata->card.dev = &pdev->dev;
+       mdata->card.num_links = 2;
+       mdata->card.dai_link = mdata->dai;
+
+       /* Register with ASoC */
+       ret = snd_soc_register_card(&mdata->card);
+       if (ret) {
+               dev_err(&pdev->dev, "could not register card (ret=%i)\n", ret);
+               goto error;
+       }
+
+       return 0;
+
+error:
+       kfree(mdata);
+error_put:
+       of_node_put(codec_np);
+       return ret;
+}
+
+/**
+ * p1022_rdk_remove: remove the platform device
+ *
+ * This function is called when the platform device is removed.
+ */
+static int __devexit p1022_rdk_remove(struct platform_device *pdev)
+{
+       struct snd_soc_card *card = platform_get_drvdata(pdev);
+       struct machine_data *mdata =
+               container_of(card, struct machine_data, card);
+
+       snd_soc_unregister_card(card);
+       kfree(mdata);
+
+       return 0;
+}
+
+static struct platform_driver p1022_rdk_driver = {
+       .probe = p1022_rdk_probe,
+       .remove = __devexit_p(p1022_rdk_remove),
+       .driver = {
+               /*
+                * The name must match 'compatible' property in the device tree,
+                * in lowercase letters.
+                */
+               .name = "snd-soc-p1022rdk",
+               .owner = THIS_MODULE,
+       },
+};
+
+/**
+ * p1022_rdk_init: machine driver initialization.
+ *
+ * This function is called when this module is loaded.
+ */
+static int __init p1022_rdk_init(void)
+{
+       struct device_node *guts_np;
+       struct resource res;
+
+       /* Get the physical address of the global utilities registers */
+       guts_np = of_find_compatible_node(NULL, NULL, "fsl,p1022-guts");
+       if (of_address_to_resource(guts_np, 0, &res)) {
+               pr_err("snd-soc-p1022rdk: missing/invalid global utils node\n");
+               of_node_put(guts_np);
+               return -EINVAL;
+       }
+       guts_phys = res.start;
+       of_node_put(guts_np);
+
+       return platform_driver_register(&p1022_rdk_driver);
+}
+
+/**
+ * p1022_rdk_exit: machine driver exit
+ *
+ * This function is called when this driver is unloaded.
+ */
+static void __exit p1022_rdk_exit(void)
+{
+       platform_driver_unregister(&p1022_rdk_driver);
+}
+
+late_initcall(p1022_rdk_init);
+module_exit(p1022_rdk_exit);
+
+MODULE_AUTHOR("Timur Tabi <timur@freescale.com>");
+MODULE_DESCRIPTION("Freescale / iVeia P1022 RDK ALSA SoC machine driver");
+MODULE_LICENSE("GPL v2");
index 4b63ec8eb372ee917a06c314764a2d7f6804a892..4d261927662ff123cca004beb025919eaee508fe 100644 (file)
@@ -29,14 +29,14 @@ struct pcm030_audio_data {
 
 static struct snd_soc_dai_link pcm030_fabric_dai[] = {
 {
-       .name = "AC97",
+       .name = "AC97.0",
        .stream_name = "AC97 Analog",
        .codec_dai_name = "wm9712-hifi",
        .cpu_dai_name = "mpc5200-psc-ac97.0",
        .codec_name = "wm9712-codec",
 },
 {
-       .name = "AC97",
+       .name = "AC97.1",
        .stream_name = "AC97 IEC958",
        .codec_dai_name = "wm9712-aux",
        .cpu_dai_name = "mpc5200-psc-ac97.1",
index 14fbcd30cae574dbc57b8f20eae191dc332c0f93..386bab1f99abe9d05032dbbe819edddace9fe42f 100644 (file)
@@ -442,7 +442,7 @@ static __devinit int s3c_ac97_probe(struct platform_device *pdev)
                ret = -ENODEV;
                goto err2;
        }
-       clk_enable(s3c_ac97.ac97_clk);
+       clk_prepare_enable(s3c_ac97.ac97_clk);
 
        if (ac97_pdata->cfg_gpio(pdev)) {
                dev_err(&pdev->dev, "Unable to configure gpio\n");
@@ -468,7 +468,7 @@ err5:
        free_irq(irq_res->start, NULL);
 err4:
 err3:
-       clk_disable(s3c_ac97.ac97_clk);
+       clk_disable_unprepare(s3c_ac97.ac97_clk);
        clk_put(s3c_ac97.ac97_clk);
 err2:
        iounmap(s3c_ac97.regs);
@@ -488,7 +488,7 @@ static __devexit int s3c_ac97_remove(struct platform_device *pdev)
        if (irq_res)
                free_irq(irq_res->start, NULL);
 
-       clk_disable(s3c_ac97.ac97_clk);
+       clk_disable_unprepare(s3c_ac97.ac97_clk);
        clk_put(s3c_ac97.ac97_clk);
 
        iounmap(s3c_ac97.regs);
index b0d46d63d55ea784f2f6970cd77bd2915a1c32fa..3d7ace796063e565a30219d39012804686855a06 100644 (file)
 #include "../codecs/wm5102.h"
 #include "../codecs/wm9081.h"
 
-/*
- * 44.1kHz based clocks for the SYSCLK domain, use a very high clock
- * to allow all the DSP functionality to be enabled if desired.
- */
-#define SYSCLK_RATE (44100 * 1024)
-
-/* 48kHz based clocks for the ASYNC domain */
-#define ASYNCCLK_RATE (48000 * 512)
-
 /* BCLK2 is fixed at this currently */
 #define BCLK2_RATE (64 * 8000)
 
  */
 #define MCLK_RATE 24576000
 
-#define WM9081_AUDIO_RATE 44100
-#define WM9081_MCLK_RATE  (WM9081_AUDIO_RATE * 256)
+#define SYS_AUDIO_RATE 44100
+#define SYS_MCLK_RATE  (SYS_AUDIO_RATE * 256)
+
+#define DAI_AP_DSP    0
+#define DAI_DSP_CODEC 1
+#define DAI_CODEC_CP  2
+#define DAI_CODEC_SUB 3
+
+struct bells_drvdata {
+       int sysclk_rate;
+       int asyncclk_rate;
+};
+
+static struct bells_drvdata wm2200_drvdata = {
+       .sysclk_rate = 22579200,
+};
+
+static struct bells_drvdata wm5102_drvdata = {
+       .sysclk_rate = 45158400,
+       .asyncclk_rate = 49152000,
+};
+
+static struct bells_drvdata wm5110_drvdata = {
+       .sysclk_rate = 135475200,
+       .asyncclk_rate = 147456000,
+};
 
 static int bells_set_bias_level(struct snd_soc_card *card,
                                struct snd_soc_dapm_context *dapm,
                                enum snd_soc_bias_level level)
 {
-       struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai;
+       struct snd_soc_dai *codec_dai = card->rtd[DAI_DSP_CODEC].codec_dai;
        struct snd_soc_codec *codec = codec_dai->codec;
+       struct bells_drvdata *bells = card->drvdata;
        int ret;
 
        if (dapm->dev != codec_dai->dev)
@@ -52,18 +68,21 @@ static int bells_set_bias_level(struct snd_soc_card *card,
 
        switch (level) {
        case SND_SOC_BIAS_PREPARE:
-               if (dapm->bias_level == SND_SOC_BIAS_STANDBY) {
-                       ret = snd_soc_codec_set_pll(codec, WM5102_FLL1,
-                                                   ARIZONA_FLL_SRC_MCLK1,
-                                                   MCLK_RATE,
-                                                   SYSCLK_RATE);
-                       if (ret < 0)
-                               pr_err("Failed to start FLL: %d\n", ret);
+               if (dapm->bias_level != SND_SOC_BIAS_STANDBY)
+                       break;
+
+               ret = snd_soc_codec_set_pll(codec, WM5102_FLL1,
+                                           ARIZONA_FLL_SRC_MCLK1,
+                                           MCLK_RATE,
+                                           bells->sysclk_rate);
+               if (ret < 0)
+                       pr_err("Failed to start FLL: %d\n", ret);
 
+               if (bells->asyncclk_rate) {
                        ret = snd_soc_codec_set_pll(codec, WM5102_FLL2,
                                                    ARIZONA_FLL_SRC_AIF2BCLK,
                                                    BCLK2_RATE,
-                                                   ASYNCCLK_RATE);
+                                                   bells->asyncclk_rate);
                        if (ret < 0)
                                pr_err("Failed to start FLL: %d\n", ret);
                }
@@ -80,8 +99,9 @@ static int bells_set_bias_level_post(struct snd_soc_card *card,
                                     struct snd_soc_dapm_context *dapm,
                                     enum snd_soc_bias_level level)
 {
-       struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai;
+       struct snd_soc_dai *codec_dai = card->rtd[DAI_DSP_CODEC].codec_dai;
        struct snd_soc_codec *codec = codec_dai->codec;
+       struct bells_drvdata *bells = card->drvdata;
        int ret;
 
        if (dapm->dev != codec_dai->dev)
@@ -95,10 +115,13 @@ static int bells_set_bias_level_post(struct snd_soc_card *card,
                        return ret;
                }
 
-               ret = snd_soc_codec_set_pll(codec, WM5102_FLL2, 0, 0, 0);
-               if (ret < 0) {
-                       pr_err("Failed to stop FLL: %d\n", ret);
-                       return ret;
+               if (bells->asyncclk_rate) {
+                       ret = snd_soc_codec_set_pll(codec, WM5102_FLL2,
+                                                   0, 0, 0);
+                       if (ret < 0) {
+                               pr_err("Failed to stop FLL: %d\n", ret);
+                               return ret;
+                       }
                }
                break;
 
@@ -113,56 +136,73 @@ static int bells_set_bias_level_post(struct snd_soc_card *card,
 
 static int bells_late_probe(struct snd_soc_card *card)
 {
-       struct snd_soc_codec *codec = card->rtd[0].codec;
-       struct snd_soc_dai *aif1_dai = card->rtd[0].codec_dai;
-       struct snd_soc_dai *aif2_dai = card->rtd[1].cpu_dai;
-       struct snd_soc_dai *aif3_dai = card->rtd[2].cpu_dai;
-       struct snd_soc_dai *wm9081_dai = card->rtd[2].codec_dai;
+       struct bells_drvdata *bells = card->drvdata;
+       struct snd_soc_codec *wm0010 = card->rtd[DAI_AP_DSP].codec;
+       struct snd_soc_codec *codec = card->rtd[DAI_DSP_CODEC].codec;
+       struct snd_soc_dai *aif1_dai = card->rtd[DAI_DSP_CODEC].codec_dai;
+       struct snd_soc_dai *aif2_dai;
+       struct snd_soc_dai *aif3_dai;
+       struct snd_soc_dai *wm9081_dai;
        int ret;
 
-       ret = snd_soc_dai_set_sysclk(aif1_dai, ARIZONA_CLK_SYSCLK, 0, 0);
+       ret = snd_soc_codec_set_sysclk(codec, ARIZONA_CLK_SYSCLK,
+                                      ARIZONA_CLK_SRC_FLL1,
+                                      bells->sysclk_rate,
+                                      SND_SOC_CLOCK_IN);
        if (ret != 0) {
-               dev_err(aif1_dai->dev, "Failed to set AIF1 clock: %d\n", ret);
+               dev_err(codec->dev, "Failed to set SYSCLK: %d\n", ret);
                return ret;
        }
 
-       ret = snd_soc_dai_set_sysclk(aif2_dai, ARIZONA_CLK_ASYNCCLK, 0, 0);
+       ret = snd_soc_codec_set_sysclk(wm0010, 0, 0, SYS_MCLK_RATE, 0);
        if (ret != 0) {
-               dev_err(aif2_dai->dev, "Failed to set AIF2 clock: %d\n", ret);
+               dev_err(wm0010->dev, "Failed to set WM0010 clock: %d\n", ret);
                return ret;
        }
 
-       ret = snd_soc_dai_set_sysclk(aif3_dai, ARIZONA_CLK_SYSCLK, 0, 0);
-       if (ret != 0) {
+       ret = snd_soc_dai_set_sysclk(aif1_dai, ARIZONA_CLK_SYSCLK, 0, 0);
+       if (ret != 0)
                dev_err(aif1_dai->dev, "Failed to set AIF1 clock: %d\n", ret);
-               return ret;
-       }
 
-       ret = snd_soc_codec_set_sysclk(codec, ARIZONA_CLK_SYSCLK,
-                                      ARIZONA_CLK_SRC_FLL1, SYSCLK_RATE,
+       ret = snd_soc_codec_set_sysclk(codec, ARIZONA_CLK_OPCLK, 0,
+                                      SYS_MCLK_RATE, SND_SOC_CLOCK_OUT);
+       if (ret != 0)
+               dev_err(codec->dev, "Failed to set OPCLK: %d\n", ret);
+
+       if (card->num_rtd == DAI_CODEC_CP)
+               return 0;
+
+       ret = snd_soc_codec_set_sysclk(codec, ARIZONA_CLK_ASYNCCLK,
+                                      ARIZONA_CLK_SRC_FLL2,
+                                      bells->asyncclk_rate,
                                       SND_SOC_CLOCK_IN);
        if (ret != 0) {
-               dev_err(codec->dev, "Failed to set SYSCLK: %d\n", ret);
+               dev_err(codec->dev, "Failed to set ASYNCCLK: %d\n", ret);
                return ret;
        }
 
-       ret = snd_soc_codec_set_sysclk(codec, ARIZONA_CLK_OPCLK, 0,
-                                      WM9081_MCLK_RATE, SND_SOC_CLOCK_OUT);
+       aif2_dai = card->rtd[DAI_CODEC_CP].cpu_dai;
+
+       ret = snd_soc_dai_set_sysclk(aif2_dai, ARIZONA_CLK_ASYNCCLK, 0, 0);
        if (ret != 0) {
-               dev_err(codec->dev, "Failed to set OPCLK: %d\n", ret);
+               dev_err(aif2_dai->dev, "Failed to set AIF2 clock: %d\n", ret);
                return ret;
        }
 
-       ret = snd_soc_codec_set_sysclk(codec, ARIZONA_CLK_ASYNCCLK,
-                                      ARIZONA_CLK_SRC_FLL2, ASYNCCLK_RATE,
-                                      SND_SOC_CLOCK_IN);
+       if (card->num_rtd == DAI_CODEC_SUB)
+               return 0;
+
+       aif3_dai = card->rtd[DAI_CODEC_SUB].cpu_dai;
+       wm9081_dai = card->rtd[DAI_CODEC_SUB].codec_dai;
+
+       ret = snd_soc_dai_set_sysclk(aif3_dai, ARIZONA_CLK_SYSCLK, 0, 0);
        if (ret != 0) {
-               dev_err(codec->dev, "Failed to set SYSCLK: %d\n", ret);
+               dev_err(aif1_dai->dev, "Failed to set AIF1 clock: %d\n", ret);
                return ret;
        }
 
        ret = snd_soc_codec_set_sysclk(wm9081_dai->codec, WM9081_SYSCLK_MCLK,
-                                      0, WM9081_MCLK_RATE, 0);
+                                      0, SYS_MCLK_RATE, 0);
        if (ret != 0) {
                dev_err(wm9081_dai->dev, "Failed to set MCLK: %d\n", ret);
                return ret;
@@ -181,22 +221,57 @@ static const struct snd_soc_pcm_stream baseband_params = {
 
 static const struct snd_soc_pcm_stream sub_params = {
        .formats = SNDRV_PCM_FMTBIT_S32_LE,
-       .rate_min = WM9081_AUDIO_RATE,
-       .rate_max = WM9081_AUDIO_RATE,
+       .rate_min = SYS_AUDIO_RATE,
+       .rate_max = SYS_AUDIO_RATE,
        .channels_min = 2,
        .channels_max = 2,
 };
 
+static struct snd_soc_dai_link bells_dai_wm2200[] = {
+       {
+               .name = "CPU-DSP",
+               .stream_name = "CPU-DSP",
+               .cpu_dai_name = "samsung-i2s.0",
+               .codec_dai_name = "wm0010-sdi1",
+               .platform_name = "samsung-audio",
+               .codec_name = "spi0.0",
+               .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
+                               | SND_SOC_DAIFMT_CBM_CFM,
+       },
+       {
+               .name = "DSP-CODEC",
+               .stream_name = "DSP-CODEC",
+               .cpu_dai_name = "wm0010-sdi2",
+               .codec_dai_name = "wm2200",
+               .codec_name = "wm2200.1-003a",
+               .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
+                               | SND_SOC_DAIFMT_CBM_CFM,
+               .params = &sub_params,
+               .ignore_suspend = 1,
+       },
+};
+
 static struct snd_soc_dai_link bells_dai_wm5102[] = {
        {
-               .name = "CPU",
-               .stream_name = "CPU",
+               .name = "CPU-DSP",
+               .stream_name = "CPU-DSP",
                .cpu_dai_name = "samsung-i2s.0",
-               .codec_dai_name = "wm5102-aif1",
+               .codec_dai_name = "wm0010-sdi1",
                .platform_name = "samsung-audio",
+               .codec_name = "spi0.0",
+               .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
+                               | SND_SOC_DAIFMT_CBM_CFM,
+       },
+       {
+               .name = "DSP-CODEC",
+               .stream_name = "DSP-CODEC",
+               .cpu_dai_name = "wm0010-sdi2",
+               .codec_dai_name = "wm5102-aif1",
                .codec_name = "wm5102-codec",
                .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
                                | SND_SOC_DAIFMT_CBM_CFM,
+               .params = &sub_params,
+               .ignore_suspend = 1,
        },
        {
                .name = "Baseband",
@@ -224,14 +299,25 @@ static struct snd_soc_dai_link bells_dai_wm5102[] = {
 
 static struct snd_soc_dai_link bells_dai_wm5110[] = {
        {
-               .name = "CPU",
-               .stream_name = "CPU",
+               .name = "CPU-DSP",
+               .stream_name = "CPU-DSP",
                .cpu_dai_name = "samsung-i2s.0",
-               .codec_dai_name = "wm5110-aif1",
+               .codec_dai_name = "wm0010-sdi1",
                .platform_name = "samsung-audio",
+               .codec_name = "spi0.0",
+               .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
+                               | SND_SOC_DAIFMT_CBM_CFM,
+       },
+       {
+               .name = "DSP-CODEC",
+               .stream_name = "DSP-CODEC",
+               .cpu_dai_name = "wm0010-sdi2",
+               .codec_dai_name = "wm5110-aif1",
                .codec_name = "wm5110-codec",
                .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
                                | SND_SOC_DAIFMT_CBM_CFM,
+               .params = &sub_params,
+               .ignore_suspend = 1,
        },
        {
                .name = "Baseband",
@@ -269,6 +355,24 @@ static struct snd_soc_dapm_route bells_routes[] = {
 };
 
 static struct snd_soc_card bells_cards[] = {
+       {
+               .name = "Bells WM2200",
+               .owner = THIS_MODULE,
+               .dai_link = bells_dai_wm2200,
+               .num_links = ARRAY_SIZE(bells_dai_wm2200),
+               .codec_conf = bells_codec_conf,
+               .num_configs = ARRAY_SIZE(bells_codec_conf),
+
+               .late_probe = bells_late_probe,
+
+               .dapm_routes = bells_routes,
+               .num_dapm_routes = ARRAY_SIZE(bells_routes),
+
+               .set_bias_level = bells_set_bias_level,
+               .set_bias_level_post = bells_set_bias_level_post,
+
+               .drvdata = &wm2200_drvdata,
+       },
        {
                .name = "Bells WM5102",
                .owner = THIS_MODULE,
@@ -284,6 +388,8 @@ static struct snd_soc_card bells_cards[] = {
 
                .set_bias_level = bells_set_bias_level,
                .set_bias_level_post = bells_set_bias_level_post,
+
+               .drvdata = &wm5102_drvdata,
        },
        {
                .name = "Bells WM5110",
@@ -300,6 +406,8 @@ static struct snd_soc_card bells_cards[] = {
 
                .set_bias_level = bells_set_bias_level,
                .set_bias_level_post = bells_set_bias_level_post,
+
+               .drvdata = &wm5110_drvdata,
        },
 };
 
index 40b00a13dcd1b1c664636406ae693faa0bdf996f..547b9190c88f421b6ad2d9c803d7887c98e7f69f 100644 (file)
@@ -423,7 +423,7 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai,
                        if (i2s->op_clk) {
                                if ((clk_id && !(mod & MOD_IMS_SYSMUX)) ||
                                        (!clk_id && (mod & MOD_IMS_SYSMUX))) {
-                                       clk_disable(i2s->op_clk);
+                                       clk_disable_unprepare(i2s->op_clk);
                                        clk_put(i2s->op_clk);
                                } else {
                                        i2s->rclk_srcrate =
@@ -434,7 +434,7 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai,
 
                        i2s->op_clk = clk_get(&i2s->pdev->dev,
                                                i2s->src_clk[clk_id]);
-                       clk_enable(i2s->op_clk);
+                       clk_prepare_enable(i2s->op_clk);
                        i2s->rclk_srcrate = clk_get_rate(i2s->op_clk);
 
                        /* Over-ride the other's */
@@ -880,7 +880,7 @@ static int samsung_i2s_dai_probe(struct snd_soc_dai *dai)
                iounmap(i2s->addr);
                return -ENOENT;
        }
-       clk_enable(i2s->clk);
+       clk_prepare_enable(i2s->clk);
 
        if (other) {
                other->addr = i2s->addr;
@@ -922,7 +922,7 @@ static int samsung_i2s_dai_remove(struct snd_soc_dai *dai)
                if (i2s->quirks & QUIRK_NEED_RSTCLR)
                        writel(0, i2s->addr + I2SCON);
 
-               clk_disable(i2s->clk);
+               clk_disable_unprepare(i2s->clk);
                clk_put(i2s->clk);
 
                iounmap(i2s->addr);
index c86081992dfd9331eeaed79c97f656705162b450..45f4a752d2a007a476bbfdf1aec2efec2f43c2ce 100644 (file)
@@ -543,7 +543,7 @@ static __devinit int s3c_pcm_dev_probe(struct platform_device *pdev)
                ret = PTR_ERR(pcm->cclk);
                goto err1;
        }
-       clk_enable(pcm->cclk);
+       clk_prepare_enable(pcm->cclk);
 
        /* record our pcm structure for later use in the callbacks */
        dev_set_drvdata(&pdev->dev, pcm);
@@ -568,7 +568,7 @@ static __devinit int s3c_pcm_dev_probe(struct platform_device *pdev)
                ret = -ENOENT;
                goto err4;
        }
-       clk_enable(pcm->pclk);
+       clk_prepare_enable(pcm->pclk);
 
        s3c_pcm_stereo_in[pdev->id].dma_addr = mem_res->start
                                                        + S3C_PCM_RXFIFO;
@@ -592,14 +592,14 @@ static __devinit int s3c_pcm_dev_probe(struct platform_device *pdev)
        return 0;
 
 err5:
-       clk_disable(pcm->pclk);
+       clk_disable_unprepare(pcm->pclk);
        clk_put(pcm->pclk);
 err4:
        iounmap(pcm->regs);
 err3:
        release_mem_region(mem_res->start, resource_size(mem_res));
 err2:
-       clk_disable(pcm->cclk);
+       clk_disable_unprepare(pcm->cclk);
        clk_put(pcm->cclk);
 err1:
        return ret;
@@ -619,8 +619,8 @@ static __devexit int s3c_pcm_dev_remove(struct platform_device *pdev)
        mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        release_mem_region(mem_res->start, resource_size(mem_res));
 
-       clk_disable(pcm->cclk);
-       clk_disable(pcm->pclk);
+       clk_disable_unprepare(pcm->cclk);
+       clk_disable_unprepare(pcm->pclk);
        clk_put(pcm->pclk);
        clk_put(pcm->cclk);
 
index bc24c7af02b2e23ff57342b1901841c879198fd1..5f3b06d36e9cfcd24cb84e26c78e5937e76836ad 100644 (file)
@@ -397,7 +397,7 @@ static __devinit int spdif_probe(struct platform_device *pdev)
                ret = -ENOENT;
                goto err0;
        }
-       clk_enable(spdif->pclk);
+       clk_prepare_enable(spdif->pclk);
 
        spdif->sclk = clk_get(&pdev->dev, "sclk_spdif");
        if (IS_ERR(spdif->sclk)) {
@@ -405,7 +405,7 @@ static __devinit int spdif_probe(struct platform_device *pdev)
                ret = -ENOENT;
                goto err1;
        }
-       clk_enable(spdif->sclk);
+       clk_prepare_enable(spdif->sclk);
 
        /* Request S/PDIF Register's memory region */
        if (!request_mem_region(mem_res->start,
@@ -444,10 +444,10 @@ err4:
 err3:
        release_mem_region(mem_res->start, resource_size(mem_res));
 err2:
-       clk_disable(spdif->sclk);
+       clk_disable_unprepare(spdif->sclk);
        clk_put(spdif->sclk);
 err1:
-       clk_disable(spdif->pclk);
+       clk_disable_unprepare(spdif->pclk);
        clk_put(spdif->pclk);
 err0:
        return ret;
@@ -466,9 +466,9 @@ static __devexit int spdif_remove(struct platform_device *pdev)
        if (mem_res)
                release_mem_region(mem_res->start, resource_size(mem_res));
 
-       clk_disable(spdif->sclk);
+       clk_disable_unprepare(spdif->sclk);
        clk_put(spdif->sclk);
-       clk_disable(spdif->pclk);
+       clk_disable_unprepare(spdif->pclk);
        clk_put(spdif->pclk);
 
        return 0;
index 9d7f30774a44d9524cb71f6697fc0ce96825295c..4e8ce364e233b8b08f5b597cb136fa4ff4196cfe 100644 (file)
@@ -1498,7 +1498,7 @@ static struct snd_pcm_hardware fsi_pcm_hardware = {
        .rates                  = FSI_RATES,
        .rate_min               = 8000,
        .rate_max               = 192000,
-       .channels_min           = 1,
+       .channels_min           = 2,
        .channels_max           = 2,
        .buffer_bytes_max       = 64 * 1024,
        .period_bytes_min       = 32,
@@ -1586,14 +1586,14 @@ static struct snd_soc_dai_driver fsi_soc_dai[] = {
                .playback = {
                        .rates          = FSI_RATES,
                        .formats        = FSI_FMTS,
-                       .channels_min   = 1,
-                       .channels_max   = 8,
+                       .channels_min   = 2,
+                       .channels_max   = 2,
                },
                .capture = {
                        .rates          = FSI_RATES,
                        .formats        = FSI_FMTS,
-                       .channels_min   = 1,
-                       .channels_max   = 8,
+                       .channels_min   = 2,
+                       .channels_max   = 2,
                },
                .ops = &fsi_dai_ops,
        },
@@ -1602,14 +1602,14 @@ static struct snd_soc_dai_driver fsi_soc_dai[] = {
                .playback = {
                        .rates          = FSI_RATES,
                        .formats        = FSI_FMTS,
-                       .channels_min   = 1,
-                       .channels_max   = 8,
+                       .channels_min   = 2,
+                       .channels_max   = 2,
                },
                .capture = {
                        .rates          = FSI_RATES,
                        .formats        = FSI_FMTS,
-                       .channels_min   = 1,
-                       .channels_max   = 8,
+                       .channels_min   = 2,
+                       .channels_max   = 2,
                },
                .ops = &fsi_dai_ops,
        },
@@ -1702,7 +1702,7 @@ static int fsi_probe(struct platform_device *pdev)
        pm_runtime_enable(&pdev->dev);
        dev_set_drvdata(&pdev->dev, master);
 
-       ret = request_irq(irq, &fsi_interrupt, 0,
+       ret = devm_request_irq(&pdev->dev, irq, &fsi_interrupt, 0,
                          id_entry->name, master);
        if (ret) {
                dev_err(&pdev->dev, "irq request err\n");
@@ -1712,7 +1712,7 @@ static int fsi_probe(struct platform_device *pdev)
        ret = snd_soc_register_platform(&pdev->dev, &fsi_soc_platform);
        if (ret < 0) {
                dev_err(&pdev->dev, "cannot snd soc register\n");
-               goto exit_free_irq;
+               goto exit_fsib;
        }
 
        ret = snd_soc_register_dais(&pdev->dev, fsi_soc_dai,
@@ -1726,8 +1726,6 @@ static int fsi_probe(struct platform_device *pdev)
 
 exit_snd_soc:
        snd_soc_unregister_platform(&pdev->dev);
-exit_free_irq:
-       free_irq(irq, master);
 exit_fsib:
        pm_runtime_disable(&pdev->dev);
        fsi_stream_remove(&master->fsib);
@@ -1743,7 +1741,6 @@ static int fsi_remove(struct platform_device *pdev)
 
        master = dev_get_drvdata(&pdev->dev);
 
-       free_irq(master->irq, master);
        pm_runtime_disable(&pdev->dev);
 
        snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(fsi_soc_dai));
index 1ab5fe04bfccb066853fc664d9db9bea68a9f8ce..e41e14c9565e76bf39f7bcdb99fd51561641dc54 100644 (file)
@@ -66,7 +66,6 @@ void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask)
        struct snd_soc_dapm_context *dapm;
        struct snd_soc_jack_pin *pin;
        int enable;
-       int oldstatus;
 
        trace_snd_soc_jack_report(jack, mask, status);
 
@@ -78,8 +77,6 @@ void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask)
 
        mutex_lock(&jack->mutex);
 
-       oldstatus = jack->status;
-
        jack->status &= ~mask;
        jack->status |= status & mask;
 
index bf5610122c763b85ec91f7132f6eb00de92a2b06..64b67a3091964a655c19a6106aa671332cd2b89f 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/regmap.h>
 #include <linux/slab.h>
 #include <mach/clk.h>
-#include <mach/dma.h>
 #include <sound/soc.h>
 #include "tegra30_ahub.h"
 
index b40279b9f413922bc42db08b00117a8653ef32f1..bc8b46af928e1efca0877ac5e93c59e5fba4d9eb 100644 (file)
@@ -31,8 +31,6 @@
 #ifndef __TEGRA_PCM_H__
 #define __TEGRA_PCM_H__
 
-#include <mach/dma.h>
-
 struct tegra_pcm_dma_params {
        unsigned long addr;
        unsigned long wrap;
index 356611d9654db90e1f0206995de6b7064b83bdf9..54f7e25b6f7d479d30bed372ba5d12ce1abacb22 100644 (file)
@@ -57,6 +57,20 @@ static struct snd_soc_card mop500_card = {
        .num_links = ARRAY_SIZE(mop500_dai_links),
 };
 
+static void mop500_of_node_put(void)
+{
+       int i;
+
+       for (i = 0; i < 2; i++) {
+               if (mop500_dai_links[i].cpu_of_node)
+                       of_node_put((struct device_node *)
+                               mop500_dai_links[i].cpu_of_node);
+               if (mop500_dai_links[i].codec_of_node)
+                       of_node_put((struct device_node *)
+                               mop500_dai_links[i].codec_of_node);
+       }
+}
+
 static int __devinit mop500_of_probe(struct platform_device *pdev,
                                struct device_node *np)
 {
@@ -69,6 +83,7 @@ static int __devinit mop500_of_probe(struct platform_device *pdev,
 
        if (!(msp_np[0] && msp_np[1] && codec_np)) {
                dev_err(&pdev->dev, "Phandle missing or invalid\n");
+               mop500_of_node_put();
                return -EINVAL;
        }
 
@@ -83,6 +98,7 @@ static int __devinit mop500_of_probe(struct platform_device *pdev,
 
        return 0;
 }
+
 static int __devinit mop500_probe(struct platform_device *pdev)
 {
        struct device_node *np = pdev->dev.of_node;
@@ -128,6 +144,7 @@ static int __devexit mop500_remove(struct platform_device *pdev)
 
        snd_soc_unregister_card(mop500_card);
        mop500_ab8500_remove(mop500_card);
+       mop500_of_node_put();
 
        return 0;
 }
index b7c996e77570bd527a0a92fd904276a40c44cd2b..a26c6bf0a29b2ad570050519b7e6c87e418e62a5 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/pinctrl/consumer.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
+#include <linux/io.h>
 #include <linux/of.h>
 
 #include <mach/hardware.h>
@@ -697,14 +698,11 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev,
                        platform_data = devm_kzalloc(&pdev->dev,
                                sizeof(struct msp_i2s_platform_data), GFP_KERNEL);
                        if (!platform_data)
-                               ret = -ENOMEM;
+                               return -ENOMEM;
                }
        } else
                if (!platform_data)
-                       ret = -EINVAL;
-
-       if (ret)
-               goto err_res;
+                       return -EINVAL;
 
        dev_dbg(&pdev->dev, "%s: Enter (name: %s, id: %d).\n", __func__,
                pdev->name, platform_data->id);
index ff77b28f3da167fe0dd0788bfc110b52964c4b6f..225dfd737265411bead537f7f839b75863432e51 100644 (file)
@@ -90,7 +90,7 @@ config SND_USB_CAIAQ_INPUT
 
 config SND_USB_US122L
        tristate "Tascam US-122L USB driver"
-       depends on X86 && EXPERIMENTAL
+       depends on X86
        select SND_HWDEP
        select SND_RAWMIDI
        help
index 55e19e1b80ec4eeb282c91cea482ef7434cf8dce..f77b87ad02566e65d2ea76248351923f9a24fdff 100644 (file)
@@ -171,11 +171,8 @@ static int init_pitch_v2(struct snd_usb_audio *chip, int iface,
 {
        struct usb_device *dev = chip->dev;
        unsigned char data[1];
-       unsigned int ep;
        int err;
 
-       ep = get_endpoint(alts, 0)->bEndpointAddress;
-
        data[0] = 1;
        if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC2_CS_CUR,
                                   USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_OUT,
index 88d8cebbb244ade66eb43db91be9d9b5cf9669d5..49c788d7de5787f465dbc4ef26a801568eb4ee0d 100644 (file)
@@ -1456,6 +1456,40 @@ YAMAHA_DEVICE(0x7010, "UB99"),
                }
        }
 },
+{
+       /* Advanced mode of the Roland VG-99, with MIDI and 24-bit PCM at 44.1
+        * kHz. In standard mode, the device has ID 0582:00b3, and offers
+        * 16-bit PCM at 44.1 kHz with no MIDI.
+        */
+       USB_DEVICE(0x0582, 0x00b2),
+       .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+               .vendor_name = "Roland",
+               .product_name = "VG-99",
+               .ifnum = QUIRK_ANY_INTERFACE,
+               .type = QUIRK_COMPOSITE,
+               .data = (const struct snd_usb_audio_quirk[]) {
+                       {
+                               .ifnum = 0,
+                               .type = QUIRK_AUDIO_STANDARD_INTERFACE
+                       },
+                       {
+                               .ifnum = 1,
+                               .type = QUIRK_AUDIO_STANDARD_INTERFACE
+                       },
+                       {
+                               .ifnum = 2,
+                               .type = QUIRK_MIDI_FIXED_ENDPOINT,
+                               .data = & (const struct snd_usb_midi_endpoint_info) {
+                                       .out_cables = 0x0003,
+                                       .in_cables  = 0x0003
+                               }
+                       },
+                       {
+                               .ifnum = -1
+                       }
+               }
+       }
+},
 {
        /* Roland SonicCell */
        USB_DEVICE(0x0582, 0x00c2),
@@ -2880,6 +2914,47 @@ YAMAHA_DEVICE(0x7010, "UB99"),
        }
 },
 
+/* Reloop Play */
+{
+       USB_DEVICE(0x200c, 0x100b),
+       .bInterfaceClass = USB_CLASS_PER_INTERFACE,
+       .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
+               .ifnum = QUIRK_ANY_INTERFACE,
+               .type = QUIRK_COMPOSITE,
+               .data = &(const struct snd_usb_audio_quirk[]) {
+                       {
+                               .ifnum = 0,
+                               .type = QUIRK_AUDIO_STANDARD_MIXER,
+                       },
+                       {
+                               .ifnum = 1,
+                               .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+                               .data = &(const struct audioformat) {
+                                       .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+                                       .channels = 4,
+                                       .iface = 1,
+                                       .altsetting = 1,
+                                       .altset_idx = 1,
+                                       .attributes = UAC_EP_CS_ATTR_SAMPLE_RATE,
+                                       .endpoint = 0x01,
+                                       .ep_attr = USB_ENDPOINT_SYNC_ADAPTIVE,
+                                       .rates = SNDRV_PCM_RATE_44100 |
+                                                SNDRV_PCM_RATE_48000,
+                                       .rate_min = 44100,
+                                       .rate_max = 48000,
+                                       .nr_rates = 2,
+                                       .rate_table = (unsigned int[]) {
+                                               44100, 48000
+                                       }
+                               }
+                       },
+                       {
+                               .ifnum = -1
+                       }
+               }
+       }
+},
+
 {
        /*
         * Some USB MIDI devices don't have an audio control interface,
diff --git a/tools/kvm/.gitignore b/tools/kvm/.gitignore
new file mode 100644 (file)
index 0000000..60dd6db
--- /dev/null
@@ -0,0 +1,12 @@
+/lkvm
+/vm
+*.o
+*.d
+.cscope
+tags
+include/common-cmds.h
+tests/boot/boot_test.iso
+tests/boot/rootfs/
+guest/init
+guest/init_stage2
+KVMTOOLS-VERSION-FILE
diff --git a/tools/kvm/CREDITS-Git b/tools/kvm/CREDITS-Git
new file mode 100644 (file)
index 0000000..c2ddcb3
--- /dev/null
@@ -0,0 +1,30 @@
+Most of the infrastructure that 'perf' uses here has been reused
+from the Git project, as of version:
+
+    66996ec: Sync with 1.6.2.4
+
+Here is an (incomplete!) list of main contributors to those files
+in util/* and elsewhere:
+
+ Alex Riesen
+ Christian Couder
+ Dmitry Potapov
+ Jeff King
+ Johannes Schindelin
+ Johannes Sixt
+ Junio C Hamano
+ Linus Torvalds
+ Matthias Kestenholz
+ Michal Ostrowski
+ Miklos Vajna
+ Petr Baudis
+ Pierre Habouzit
+ René Scharfe
+ Samuel Tardieu
+ Shawn O. Pearce
+ Steffen Prohaska
+ Steve Haslam
+
+Thanks guys!
+
+The full history of the files can be found in the upstream Git commits.
diff --git a/tools/kvm/Documentation/kernel-debugging.txt b/tools/kvm/Documentation/kernel-debugging.txt
new file mode 100644 (file)
index 0000000..98b9438
--- /dev/null
@@ -0,0 +1,15 @@
+This document explains how to debug a guests' kernel using KGDB.
+
+1. Run the guest:
+        'lkvm run -k [vmlinuz] -p "kgdboc=ttyS1 kgdbwait" --tty 1'
+
+And see which PTY got assigned to ttyS1 (you'll see:
+'  Info: Assigned terminal 1 to pty /dev/pts/X').
+
+2. Run GDB on the host:
+        'gdb [vmlinuz]'
+
+3. Connect to the guest (from within GDB):
+        'target remote /dev/pty/X'
+
+4. Start debugging! (enter 'continue' to continue boot).
diff --git a/tools/kvm/Documentation/kvm-balloon.txt b/tools/kvm/Documentation/kvm-balloon.txt
new file mode 100644 (file)
index 0000000..efc0a87
--- /dev/null
@@ -0,0 +1,24 @@
+lkvm-balloon(1)
+================
+
+NAME
+----
+lkvm-balloon - Inflate or deflate the virtio balloon
+
+SYNOPSIS
+--------
+[verse]
+'lkvm balloon [command] [size] [instance]'
+
+DESCRIPTION
+-----------
+The command inflates or deflates the virtio balloon located in the
+specified instance.
+For a list of running instances see 'lkvm list'.
+
+Command can be either 'inflate' or 'deflate'. Inflate increases the
+size of the balloon, thus decreasing the amount of virtual RAM available
+for the guest. Deflation returns previously inflated memory back to the
+guest.
+
+size is specified in Mb.
diff --git a/tools/kvm/Documentation/kvm-debug.txt b/tools/kvm/Documentation/kvm-debug.txt
new file mode 100644 (file)
index 0000000..a8eb2c0
--- /dev/null
@@ -0,0 +1,16 @@
+lkvm-debug(1)
+================
+
+NAME
+----
+lkvm-debug - Print debug information from a running instance
+
+SYNOPSIS
+--------
+[verse]
+'lkvm debug [instance]'
+
+DESCRIPTION
+-----------
+The command prints debug information from a running instance.
+For a list of running instances see 'lkvm list'.
diff --git a/tools/kvm/Documentation/kvm-list.txt b/tools/kvm/Documentation/kvm-list.txt
new file mode 100644 (file)
index 0000000..a245607
--- /dev/null
@@ -0,0 +1,16 @@
+lkvm-list(1)
+================
+
+NAME
+----
+lkvm-list - Print a list of running instances on the host.
+
+SYNOPSIS
+--------
+[verse]
+'lkvm list'
+
+DESCRIPTION
+-----------
+This command prints a list of running instances on the host which
+belong to the user who currently ran 'lkvm list'.
diff --git a/tools/kvm/Documentation/kvm-pause.txt b/tools/kvm/Documentation/kvm-pause.txt
new file mode 100644 (file)
index 0000000..1ea2a23
--- /dev/null
@@ -0,0 +1,16 @@
+lkvm-pause(1)
+================
+
+NAME
+----
+lkvm-pause - Pause the virtual machine
+
+SYNOPSIS
+--------
+[verse]
+'lkvm pause [instance]'
+
+DESCRIPTION
+-----------
+The command pauses a virtual machine.
+For a list of running instances see 'lkvm list'.
diff --git a/tools/kvm/Documentation/kvm-resume.txt b/tools/kvm/Documentation/kvm-resume.txt
new file mode 100644 (file)
index 0000000..a36c4df
--- /dev/null
@@ -0,0 +1,16 @@
+lkvm-resume(1)
+================
+
+NAME
+----
+lkvm-resume - Resume the virtual machine
+
+SYNOPSIS
+--------
+[verse]
+'lkvm resume [instance]'
+
+DESCRIPTION
+-----------
+The command resumes a virtual machine.
+For a list of running instances see 'lkvm list'.
diff --git a/tools/kvm/Documentation/kvm-run.txt b/tools/kvm/Documentation/kvm-run.txt
new file mode 100644 (file)
index 0000000..8ddf470
--- /dev/null
@@ -0,0 +1,62 @@
+lkvm-run(1)
+================
+
+NAME
+----
+lkvm-run - Start the virtual machine
+
+SYNOPSIS
+--------
+[verse]
+'lkvm run' [-k <kernel image> | --kernel <kernel image>]
+
+DESCRIPTION
+-----------
+The command starts a virtual machine.
+
+OPTIONS
+-------
+-m::
+--mem=::
+       Virtual machine memory size in MiB.
+
+-p::
+--params::
+       Additional kernel command line arguments.
+
+-r::
+--initrd=::
+       Initial RAM disk image.
+
+-k::
+--kernel=::
+       The virtual machine kernel.
+
+--dev=::
+       KVM device file.
+
+-i::
+--image=::
+       A disk image file.
+
+-s::
+--single-step::
+       Enable single stepping.
+
+-g::
+--ioport-debug::
+       Enable ioport debugging.
+
+-c::
+--enable-virtio-console::
+       Enable the virtual IO console.
+
+--cpus::
+       The number of virtual CPUs to run.
+
+--debug::
+       Enable debug messages.
+
+SEE ALSO
+--------
+linkkvm:
diff --git a/tools/kvm/Documentation/kvm-sandbox.txt b/tools/kvm/Documentation/kvm-sandbox.txt
new file mode 100644 (file)
index 0000000..2d7f558
--- /dev/null
@@ -0,0 +1,16 @@
+lkvm-sandbox(1)
+================
+
+NAME
+----
+lkvm-sandbox - Run a command in a sandboxed guest
+
+SYNOPSIS
+--------
+[verse]
+'lkvm sandbox ['lkvm run' arguments] -- [sandboxed command]'
+
+DESCRIPTION
+-----------
+The sandboxed command will run in a guest as part of it's init
+command.
diff --git a/tools/kvm/Documentation/kvm-setup.txt b/tools/kvm/Documentation/kvm-setup.txt
new file mode 100644 (file)
index 0000000..4b6e331
--- /dev/null
@@ -0,0 +1,15 @@
+lkvm-setup(1)
+================
+
+NAME
+----
+lkvm-setup - Setup a new virtual machine
+
+SYNOPSIS
+--------
+[verse]
+'lkvm setup <name>'
+
+DESCRIPTION
+-----------
+The command setups a virtual machine.
diff --git a/tools/kvm/Documentation/kvm-stat.txt b/tools/kvm/Documentation/kvm-stat.txt
new file mode 100644 (file)
index 0000000..101ce7a
--- /dev/null
@@ -0,0 +1,19 @@
+lkvm-stat(1)
+================
+
+NAME
+----
+lkvm-stat - Print statistics about a running instance
+
+SYNOPSIS
+--------
+[verse]
+'lkvm [command] [-n instance] [-p instance pid] [--all]'
+
+DESCRIPTION
+-----------
+The command prints statistics about a running instance.
+For a list of running instances see 'lkvm list'.
+
+Commands:
+ --memory, -m  Display memory statistics
diff --git a/tools/kvm/Documentation/kvm-stop.txt b/tools/kvm/Documentation/kvm-stop.txt
new file mode 100644 (file)
index 0000000..6e4bc83
--- /dev/null
@@ -0,0 +1,16 @@
+lkvm-stop(1)
+================
+
+NAME
+----
+lkvm-stop - Stop a running instance
+
+SYNOPSIS
+--------
+[verse]
+'lkvm stop [instance]'
+
+DESCRIPTION
+-----------
+The command stops a running instance.
+For a list of running instances see 'lkvm list'.
diff --git a/tools/kvm/Documentation/kvm-version.txt b/tools/kvm/Documentation/kvm-version.txt
new file mode 100644 (file)
index 0000000..41003d2
--- /dev/null
@@ -0,0 +1,21 @@
+lkvm-version(1)
+================
+
+NAME
+----
+lkvm-version - Print the version of the kernel tree kvm tools
+was built on.
+
+SYNOPSIS
+--------
+[verse]
+'lkvm version'
+
+DESCRIPTION
+-----------
+The command prints the version of the kernel that was used to build
+kvm tools.
+
+Note that the version is not the version of the kernel which is currently
+running on the host, but is the version of the kernel tree from which kvm
+tools was built.
diff --git a/tools/kvm/Documentation/virtio-console.txt b/tools/kvm/Documentation/virtio-console.txt
new file mode 100644 (file)
index 0000000..4a58d56
--- /dev/null
@@ -0,0 +1,41 @@
+General
+--------
+
+virtio-console as the name implies is a console over virtio transport. Here is
+a simple head to head comparison of the virtio-console vs regular 8250 console:
+
+8250 serial console:
+
+ - Requires CONFIG_SERIAL_8250=y and CONFIG_SERIAL_8250_CONSOLE=y kernel configs,
+which are enabled almost everywhere.
+ - Doesn't require guest-side changes.
+ - Compatible with older guests.
+
+virtio-console:
+
+ - Requires CONFIG_VIRTIO_CONSOLE=y (along with all other virtio dependencies),
+which got enabled only in recent kernels (but not all of them).
+ - Much faster.
+ - Consumes less processing resources.
+ - Requires guest-side changes.
+
+Enabling virtio-console
+------------------------
+
+First, make sure guest kernel is built with CONFIG_VIRTIO_CONSOLE=y. Once this
+is done, the following has to be done inside guest image:
+
+ - Add the following line to /etc/inittab:
+       'hvc0:2345:respawn:/sbin/agetty -L 9600 hvc0'
+ - Add 'hvc0' to /etc/securetty (so you could actually log on)
+ - Start the guest with '--console virtio'
+
+Common errors
+--------------
+
+Q: I don't see anything on the screen!
+A: Make sure CONFIG_VIRTIO_CONSOLE=y is enabled in the *guest* kernel, also
+make sure you've updated /etc/inittab
+
+Q: It won't accept my username/password, but I enter them correctly!
+A: You didn't add 'hvc0' to /etc/securetty
diff --git a/tools/kvm/Makefile b/tools/kvm/Makefile
new file mode 100644 (file)
index 0000000..64f2646
--- /dev/null
@@ -0,0 +1,460 @@
+#
+# Define WERROR=0 to disable -Werror.
+#
+
+ifeq ($(strip $(V)),)
+       E = @echo
+       Q = @
+else
+       E = @\#
+       Q =
+endif
+ifneq ($(I), )
+       KINCL_PATH=$(I)
+else
+       KINCL_PATH=../..
+endif
+export E Q KINCL_PATH
+
+include config/utilities.mak
+include config/feature-tests.mak
+
+CC     := $(CROSS_COMPILE)$(CC)
+LD     := $(CROSS_COMPILE)$(LD)
+
+FIND   := find
+CSCOPE := cscope
+TAGS   := ctags
+INSTALL := install
+
+prefix = $(HOME)
+bindir_relative = bin
+bindir = $(prefix)/$(bindir_relative)
+
+DESTDIR_SQ = $(subst ','\'',$(DESTDIR))
+bindir_SQ = $(subst ','\'',$(bindir))
+
+PROGRAM        := lkvm
+PROGRAM_ALIAS := vm
+
+GUEST_INIT := guest/init
+
+OBJS   += builtin-balloon.o
+OBJS   += builtin-debug.o
+OBJS   += builtin-help.o
+OBJS   += builtin-list.o
+OBJS   += builtin-stat.o
+OBJS   += builtin-pause.o
+OBJS   += builtin-resume.o
+OBJS   += builtin-run.o
+OBJS   += builtin-setup.o
+OBJS   += builtin-stop.o
+OBJS   += builtin-version.o
+OBJS   += disk/core.o
+OBJS   += framebuffer.o
+OBJS   += guest_compat.o
+OBJS   += hw/rtc.o
+OBJS   += hw/serial.o
+OBJS   += ioport.o
+OBJS   += kvm-cpu.o
+OBJS   += kvm.o
+OBJS   += main.o
+OBJS   += mmio.o
+OBJS   += pci.o
+OBJS   += term.o
+OBJS   += virtio/blk.o
+OBJS   += virtio/scsi.o
+OBJS   += virtio/console.o
+OBJS   += virtio/core.o
+OBJS   += virtio/net.o
+OBJS   += virtio/rng.o
+OBJS    += virtio/balloon.o
+OBJS   += virtio/pci.o
+OBJS   += disk/blk.o
+OBJS   += disk/qcow.o
+OBJS   += disk/raw.o
+OBJS   += ioeventfd.o
+OBJS   += net/uip/core.o
+OBJS   += net/uip/arp.o
+OBJS   += net/uip/icmp.o
+OBJS   += net/uip/ipv4.o
+OBJS   += net/uip/tcp.o
+OBJS   += net/uip/udp.o
+OBJS   += net/uip/buf.o
+OBJS   += net/uip/csum.o
+OBJS   += net/uip/dhcp.o
+OBJS   += kvm-cmd.o
+OBJS   += util/init.o
+OBJS   += util/rbtree.o
+OBJS   += util/threadpool.o
+OBJS   += util/parse-options.o
+OBJS   += util/rbtree-interval.o
+OBJS   += util/strbuf.o
+OBJS   += util/read-write.o
+OBJS   += util/util.o
+OBJS   += virtio/9p.o
+OBJS   += virtio/9p-pdu.o
+OBJS   += hw/vesa.o
+OBJS   += hw/pci-shmem.o
+OBJS   += kvm-ipc.o
+OBJS   += builtin-sandbox.o
+OBJS   += virtio/mmio.o
+
+# Translate uname -m into ARCH string
+ARCH ?= $(shell uname -m | sed -e s/i.86/i386/ -e s/ppc.*/powerpc/)
+
+ifeq ($(ARCH),i386)
+       ARCH         := x86
+       DEFINES      += -DCONFIG_X86_32
+endif
+ifeq ($(ARCH),x86_64)
+       ARCH         := x86
+       DEFINES      += -DCONFIG_X86_64
+endif
+
+LIBFDT_SRC = fdt.o fdt_ro.o fdt_wip.o fdt_sw.o fdt_rw.o fdt_strerror.o
+LIBFDT_OBJS = $(patsubst %,../../scripts/dtc/libfdt/%,$(LIBFDT_SRC))
+
+### Arch-specific stuff
+
+#x86
+ifeq ($(ARCH),x86)
+       DEFINES += -DCONFIG_X86
+       OBJS    += x86/boot.o
+       OBJS    += x86/cpuid.o
+       OBJS    += x86/interrupt.o
+       OBJS    += x86/ioport.o
+       OBJS    += x86/irq.o
+       OBJS    += x86/kvm.o
+       OBJS    += x86/kvm-cpu.o
+       OBJS    += x86/mptable.o
+       OBJS    += hw/i8042.o
+# Exclude BIOS object files from header dependencies.
+       OTHEROBJS       += x86/bios.o
+       OTHEROBJS       += x86/bios/bios-rom.o
+       ARCH_INCLUDE := x86/include
+endif
+# POWER/ppc:  Actually only support ppc64 currently.
+ifeq ($(ARCH), powerpc)
+       DEFINES += -DCONFIG_PPC
+       OBJS    += powerpc/boot.o
+       OBJS    += powerpc/ioport.o
+       OBJS    += powerpc/irq.o
+       OBJS    += powerpc/kvm.o
+       OBJS    += powerpc/cpu_info.o
+       OBJS    += powerpc/kvm-cpu.o
+       OBJS    += powerpc/spapr_hcall.o
+       OBJS    += powerpc/spapr_rtas.o
+       OBJS    += powerpc/spapr_hvcons.o
+       OBJS    += powerpc/spapr_pci.o
+       OBJS    += powerpc/xics.o
+# We use libfdt, but it's sometimes not packaged 64bit.  It's small too,
+# so just build it in:
+       CFLAGS  += -I../../scripts/dtc/libfdt
+       OTHEROBJS       += $(LIBFDT_OBJS)
+       ARCH_INCLUDE := powerpc/include
+       CFLAGS  += -m64
+endif
+
+###
+
+ifeq (,$(ARCH_INCLUDE))
+       UNSUPP_ERR = @echo "This architecture is not supported in kvmtool." && exit 1
+else
+       UNSUPP_ERR =
+endif
+
+###
+
+# Detect optional features.
+# On a given system, some libs may link statically, some may not; so, check
+# both and only build those that link!
+
+FLAGS_BFD := $(CFLAGS) -lbfd
+ifeq ($(call try-cc,$(SOURCE_BFD),$(FLAGS_BFD)),y)
+       CFLAGS_DYNOPT   += -DCONFIG_HAS_BFD
+       OBJS_DYNOPT     += symbol.o
+       LIBS_DYNOPT     += -lbfd
+endif
+ifeq ($(call try-cc,$(SOURCE_BFD),$(FLAGS_BFD) -static),y)
+       CFLAGS_STATOPT  += -DCONFIG_HAS_BFD
+       OBJS_STATOPT    += symbol.o
+       LIBS_STATOPT    += -lbfd
+endif
+
+FLAGS_VNCSERVER := $(CFLAGS) -lvncserver
+ifeq ($(call try-cc,$(SOURCE_VNCSERVER),$(FLAGS_VNCSERVER)),y)
+       OBJS_DYNOPT     += ui/vnc.o
+       CFLAGS_DYNOPT   += -DCONFIG_HAS_VNCSERVER
+       LIBS_DYNOPT     += -lvncserver
+endif
+ifeq ($(call try-cc,$(SOURCE_VNCSERVER),$(FLAGS_VNCSERVER) -static),y)
+       OBJS_STATOPT    += ui/vnc.o
+       CFLAGS_STATOPT  += -DCONFIG_HAS_VNCSERVER
+       LIBS_STATOPT    += -lvncserver
+endif
+
+FLAGS_SDL := $(CFLAGS) -lSDL
+ifeq ($(call try-cc,$(SOURCE_SDL),$(FLAGS_SDL)),y)
+       OBJS_DYNOPT     += ui/sdl.o
+       CFLAGS_DYNOPT   += -DCONFIG_HAS_SDL
+       LIBS_DYNOPT     += -lSDL
+endif
+ifeq ($(call try-cc,$(SOURCE_SDL),$(FLAGS_SDL) -static), y)
+       OBJS_STATOPT    += ui/sdl.o
+       CFLAGS_STATOPT  += -DCONFIG_HAS_SDL
+       LIBS_STATOPT    += -lSDL
+endif
+
+FLAGS_ZLIB := $(CFLAGS) -lz
+ifeq ($(call try-cc,$(SOURCE_ZLIB),$(FLAGS_ZLIB)),y)
+       CFLAGS_DYNOPT   += -DCONFIG_HAS_ZLIB
+       LIBS_DYNOPT     += -lz
+endif
+ifeq ($(call try-cc,$(SOURCE_ZLIB),$(FLAGS_ZLIB) -static),y)
+       CFLAGS_STATOPT  += -DCONFIG_HAS_ZLIB
+       LIBS_STATOPT    += -lz
+endif
+
+FLAGS_AIO := $(CFLAGS) -laio
+ifeq ($(call try-cc,$(SOURCE_AIO),$(FLAGS_AIO)),y)
+       CFLAGS_DYNOPT   += -DCONFIG_HAS_AIO
+       LIBS_DYNOPT     += -laio
+endif
+ifeq ($(call try-cc,$(SOURCE_AIO),$(FLAGS_AIO) -static),y)
+       CFLAGS_STATOPT  += -DCONFIG_HAS_AIO
+       LIBS_STATOPT    += -laio
+endif
+
+ifneq ($(call try-build,$(SOURCE_STATIC),-static,),y)
+$(error No static libc found. Please install glibc-static package.)
+endif
+###
+
+LIBS   += -lrt
+LIBS   += -lpthread
+LIBS   += -lutil
+
+
+DEPS   := $(patsubst %.o,%.d,$(OBJS))
+
+DEFINES        += -D_FILE_OFFSET_BITS=64
+DEFINES        += -D_GNU_SOURCE
+DEFINES        += -DKVMTOOLS_VERSION='"$(KVMTOOLS_VERSION)"'
+DEFINES        += -DBUILD_ARCH='"$(ARCH)"'
+
+KVM_INCLUDE := include
+CFLAGS += $(CPPFLAGS) $(DEFINES) -I$(KVM_INCLUDE) -I$(ARCH_INCLUDE) -I$(KINCL_PATH)/include/uapi -I$(KINCL_PATH)/include -I$(KINCL_PATH)/arch/$(ARCH)/include/ -O2 -fno-strict-aliasing -g -flto
+
+WARNINGS += -Wall
+WARNINGS += -Wcast-align
+WARNINGS += -Wformat=2
+WARNINGS += -Winit-self
+WARNINGS += -Wmissing-declarations
+WARNINGS += -Wmissing-prototypes
+WARNINGS += -Wnested-externs
+WARNINGS += -Wno-system-headers
+WARNINGS += -Wold-style-definition
+WARNINGS += -Wredundant-decls
+WARNINGS += -Wsign-compare
+WARNINGS += -Wstrict-prototypes
+WARNINGS += -Wundef
+WARNINGS += -Wvolatile-register-var
+WARNINGS += -Wwrite-strings
+
+CFLAGS += $(WARNINGS)
+
+# Some targets may use 'external' sources that don't build totally cleanly.
+CFLAGS_EASYGOING := $(CFLAGS)
+
+ifneq ($(WERROR),0)
+       CFLAGS += -Werror
+endif
+
+all: arch_support_check $(PROGRAM) $(PROGRAM_ALIAS) $(GUEST_INIT)
+
+arch_support_check:
+       $(UNSUPP_ERR)
+
+KVMTOOLS-VERSION-FILE:
+       @$(SHELL_PATH) util/KVMTOOLS-VERSION-GEN $(OUTPUT)
+-include $(OUTPUT)KVMTOOLS-VERSION-FILE
+
+# When building -static all objects are built with appropriate flags, which
+# may differ between static & dynamic .o.  The objects are separated into
+# .o and .static.o.  See the %.o: %.c rules below.
+#
+# $(OTHEROBJS) are things that do not get substituted like this.
+#
+STATIC_OBJS = $(patsubst %.o,%.static.o,$(OBJS) $(OBJS_STATOPT))
+GUEST_OBJS = guest/guest_init.o
+
+$(PROGRAM)-static:  $(DEPS) $(STATIC_OBJS) $(OTHEROBJS) $(GUEST_INIT)
+       $(E) "  LINK    " $@
+       $(Q) $(CC) -static $(CFLAGS) $(STATIC_OBJS) $(OTHEROBJS) $(GUEST_OBJS) $(LIBS) $(LIBS_STATOPT) -o $@
+
+$(PROGRAM): $(DEPS) $(OBJS) $(OBJS_DYNOPT) $(OTHEROBJS) $(GUEST_INIT)
+       $(E) "  LINK    " $@
+       $(Q) $(CC) $(CFLAGS) $(OBJS) $(OBJS_DYNOPT) $(OTHEROBJS) $(GUEST_OBJS) $(LIBS) $(LIBS_DYNOPT) -o $@
+
+$(PROGRAM_ALIAS): $(PROGRAM)
+       $(E) "  LN      " $@
+       $(Q) ln -f $(PROGRAM) $@
+
+$(GUEST_INIT): guest/init.c
+       $(E) "  LINK    " $@
+       $(Q) $(CC) -static guest/init.c -o $@
+       $(Q) $(LD) -r -b binary -o guest/guest_init.o $(GUEST_INIT)
+
+$(DEPS):
+
+util/rbtree.d: ../../lib/rbtree.c
+       $(Q) $(CC) -M -MT util/rbtree.o $(CFLAGS) $< -o $@
+
+%.d: %.c
+       $(Q) $(CC) -M -MT $(patsubst %.d,%.o,$@) $(CFLAGS) $< -o $@
+
+%.s: %.c
+       $(Q) $(CC) -o $@ -S $(CFLAGS) -fverbose-asm $<
+
+# The header file common-cmds.h is needed for compilation of builtin-help.c.
+builtin-help.d: $(KVM_INCLUDE)/common-cmds.h
+
+$(OBJS):
+
+# This rule relaxes the -Werror on libfdt, since for now it still has
+# a bunch of warnings. :(
+../../scripts/dtc/libfdt/%.o: ../../scripts/dtc/libfdt/%.c
+ifeq ($(C),1)
+       $(E) "  CHECK   " $@
+       $(Q) $(CHECK) -c $(CFLAGS_EASYGOING) $< -o $@
+endif
+       $(E) "  CC      " $@
+       $(Q) $(CC) -c $(CFLAGS_EASYGOING) $< -o $@
+
+util/rbtree.static.o util/rbtree.o: ../../lib/rbtree.c
+ifeq ($(C),1)
+       $(E) "  CHECK   " $@
+       $(Q) $(CHECK) -c $(CFLAGS) $< -o $@
+endif
+       $(E) "  CC      " $@
+       $(Q) $(CC) -c $(CFLAGS) $< -o $@
+
+%.static.o: %.c
+ifeq ($(C),1)
+       $(E) "  CHECK   " $@
+       $(Q) $(CHECK) -c $(CFLAGS) $(CFLAGS_STATOPT) $< -o $@
+endif
+       $(E) "  CC      " $@
+       $(Q) $(CC) -c $(CFLAGS) $(CFLAGS_STATOPT)  $< -o $@
+
+%.o: %.c
+ifeq ($(C),1)
+       $(E) "  CHECK   " $@
+       $(Q) $(CHECK) -c $(CFLAGS) $(CFLAGS_DYNOPT) $< -o $@
+endif
+       $(E) "  CC      " $@
+       $(Q) $(CC) -c $(CFLAGS) $(CFLAGS_DYNOPT) $< -o $@
+
+
+$(KVM_INCLUDE)/common-cmds.h: util/generate-cmdlist.sh command-list.txt
+
+$(KVM_INCLUDE)/common-cmds.h: $(wildcard Documentation/kvm-*.txt)
+       $(E) "  GEN     " $@
+       $(Q) util/generate-cmdlist.sh > $@+ && mv $@+ $@
+
+#
+# BIOS assembly weirdness
+#
+BIOS_CFLAGS += -m32
+BIOS_CFLAGS += -march=i386
+BIOS_CFLAGS += -mregparm=3
+
+BIOS_CFLAGS += -fno-stack-protector
+BIOS_CFLAGS += -I../../arch/$(ARCH)
+
+x86/bios.o: x86/bios/bios.bin x86/bios/bios-rom.h
+
+x86/bios/bios.bin.elf: x86/bios/entry.S x86/bios/e820.c x86/bios/int10.c x86/bios/int15.c x86/bios/rom.ld.S
+       $(E) "  CC       x86/bios/memcpy.o"
+       $(Q) $(CC) -include code16gcc.h $(CFLAGS) $(BIOS_CFLAGS) -c -s x86/bios/memcpy.c -o x86/bios/memcpy.o
+       $(E) "  CC       x86/bios/e820.o"
+       $(Q) $(CC) -include code16gcc.h $(CFLAGS) $(BIOS_CFLAGS) -c -s x86/bios/e820.c -o x86/bios/e820.o
+       $(E) "  CC       x86/bios/int10.o"
+       $(Q) $(CC) -include code16gcc.h $(CFLAGS) $(BIOS_CFLAGS) -c -s x86/bios/int10.c -o x86/bios/int10.o
+       $(E) "  CC       x86/bios/int15.o"
+       $(Q) $(CC) -include code16gcc.h $(CFLAGS) $(BIOS_CFLAGS) -c -s x86/bios/int15.c -o x86/bios/int15.o
+       $(E) "  CC       x86/bios/entry.o"
+       $(Q) $(CC) $(CFLAGS) $(BIOS_CFLAGS) -c -s x86/bios/entry.S -o x86/bios/entry.o
+       $(E) "  LD      " $@
+       $(Q) $(LD) -T x86/bios/rom.ld.S -o x86/bios/bios.bin.elf x86/bios/memcpy.o x86/bios/entry.o x86/bios/e820.o x86/bios/int10.o x86/bios/int15.o
+
+x86/bios/bios.bin: x86/bios/bios.bin.elf
+       $(E) "  OBJCOPY " $@
+       $(Q) objcopy -O binary -j .text x86/bios/bios.bin.elf x86/bios/bios.bin
+
+x86/bios/bios-rom.o: x86/bios/bios-rom.S x86/bios/bios.bin x86/bios/bios-rom.h
+       $(E) "  CC      " $@
+       $(Q) $(CC) -c $(CFLAGS) x86/bios/bios-rom.S -o x86/bios/bios-rom.o
+
+x86/bios/bios-rom.h: x86/bios/bios.bin.elf
+       $(E) "  NM      " $@
+       $(Q) cd x86/bios && sh gen-offsets.sh > bios-rom.h && cd ..
+
+check: all
+       $(MAKE) -C tests
+       ./$(PROGRAM) run tests/pit/tick.bin
+       ./$(PROGRAM) run -d tests/boot/boot_test.iso -p "init=init"
+.PHONY: check
+
+install: all
+       $(E) "  INSTALL"
+       $(Q) $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(bindir_SQ)' 
+       $(Q) $(INSTALL) $(PROGRAM) '$(DESTDIR_SQ)$(bindir_SQ)' 
+.PHONY: install
+
+clean:
+       $(E) "  CLEAN"
+       $(Q) rm -f x86/bios/*.bin
+       $(Q) rm -f x86/bios/*.elf
+       $(Q) rm -f x86/bios/*.o
+       $(Q) rm -f x86/bios/bios-rom.h
+       $(Q) rm -f tests/boot/boot_test.iso
+       $(Q) rm -rf tests/boot/rootfs/
+       $(Q) rm -f $(DEPS) $(OBJS) $(OTHEROBJS) $(OBJS_DYNOPT) $(STATIC_OBJS) $(PROGRAM) $(PROGRAM_ALIAS) $(PROGRAM)-static $(GUEST_INIT) $(GUEST_OBJS)
+       $(Q) rm -f cscope.*
+       $(Q) rm -f tags
+       $(Q) rm -f TAGS
+       $(Q) rm -f $(KVM_INCLUDE)/common-cmds.h
+       $(Q) rm -f KVMTOOLS-VERSION-FILE
+.PHONY: clean
+
+KVM_DEV        ?= /dev/kvm
+
+$(KVM_DEV):
+       $(E) "  MKNOD " $@
+       $(Q) mknod $@ char 10 232
+
+devices: $(KVM_DEV)
+.PHONY: devices
+
+TAGS:
+       $(E) "  GEN" $@
+       $(Q) $(RM) -f TAGS
+       $(Q) $(FIND) . -name '*.[hcS]' -print | xargs etags -a
+.PHONY: TAGS
+
+tags:
+       $(E) "  GEN" $@
+       $(Q) $(RM) -f tags
+       $(Q) $(FIND) . -name '*.[hcS]' -print | xargs ctags -a
+.PHONY: tags
+
+cscope:
+       $(E) "  GEN" $@
+       $(Q) $(FIND) . -name '*.[hcS]' -print > cscope.files
+       $(Q) $(CSCOPE) -bkqu
+.PHONY: cscope
+
+# Deps
+-include $(DEPS)
diff --git a/tools/kvm/README b/tools/kvm/README
new file mode 100644 (file)
index 0000000..358fa23
--- /dev/null
@@ -0,0 +1,112 @@
+Native Linux KVM tool
+=====================
+The goal of this tool is to provide a clean, from-scratch, lightweight
+KVM host tool implementation that can boot Linux guest images (just a
+hobby, won't be big and professional like QEMU) with no BIOS
+dependencies and with only the minimal amount of legacy device
+emulation.
+
+It's great as a learning tool if you want to get your feet wet in
+virtualization land: it's only 5 KLOC of clean C code that can already
+boot a guest Linux image.
+
+Right now it can boot a Linux image and provide you output via a serial
+console, over the host terminal, i.e. you can use it to boot a guest
+Linux image in a terminal or over ssh and log into the guest without
+much guest or host side setup work needed.
+
+1. To try out the tool, clone the git repository:
+
+  git clone git://github.com/penberg/linux-kvm.git
+
+or alternatively, if you already have a kernel source tree:
+
+  git remote add kvm-tool git://github.com/penberg/linux-kvm.git
+  git remote update
+  git checkout -b kvm-tool/master kvm-tool
+
+2. Compile the tool:
+
+  cd tools/kvm && make
+
+3. Download a raw userspace image:
+
+  wget http://wiki.qemu.org/download/linux-0.2.img.bz2 && bunzip2
+linux-0.2.img.bz2
+
+4. The guest kernel has to be built with the following configuration:
+
+ - For the default console output:
+       CONFIG_SERIAL_8250=y
+       CONFIG_SERIAL_8250_CONSOLE=y
+
+ - For running 32bit images on 64bit hosts:
+       CONFIG_IA32_EMULATION=y
+
+ - Proper FS options according to image FS (e.g. CONFIG_EXT2_FS, CONFIG_EXT4_FS).
+
+ - For all virtio devices listed below:
+       CONFIG_VIRTIO=y
+       CONFIG_VIRTIO_RING=y
+       CONFIG_VIRTIO_PCI=y
+
+ - For virtio-blk devices (--disk, -d):
+       CONFIG_VIRTIO_BLK=y
+
+ - For virtio-net devices ([--network, -n] virtio):
+       CONFIG_VIRTIO_NET=y
+
+ - For virtio-9p devices (--virtio-9p):
+       CONFIG_NET_9P=y
+       CONFIG_NET_9P_VIRTIO=y
+       CONFIG_9P_FS=y
+
+ - For virtio-balloon device (--balloon):
+       CONFIG_VIRTIO_BALLOON=y
+
+ - For virtio-console device (--console virtio):
+       CONFIG_VIRTIO_CONSOLE=y
+
+ - For virtio-rng device (--rng):
+       CONFIG_HW_RANDOM_VIRTIO=y
+
+ - For vesa device (--sdl or --vnc):
+       CONFIG_FB_VESA=y
+
+
+5. And finally, launch the hypervisor:
+
+  ./lkvm run --disk linux-0.2.img \
+           --kernel ../../arch/x86/boot/bzImage \
+or
+
+  sudo ./lkvm run --disk linux-0.2.img \
+                --kernel ../../arch/x86/boot/bzImage \
+                --network virtio
+
+The tool has been written by Pekka Enberg, Cyrill Gorcunov, Asias He,
+Sasha Levin and Prasad Joshi. Special thanks to Avi Kivity for his help
+on KVM internals and Ingo Molnar for all-around support and encouragement!
+
+See the following thread for original discussion for motivation of this
+project:
+
+http://thread.gmane.org/gmane.linux.kernel/962051/focus=962620
+
+Build dependencies
+=====================
+For deb based systems:
+32-bit:
+sudo apt-get install build-essential
+64-bit:
+sudo apt-get install build-essential libc6-dev-i386
+
+For rpm based systems:
+32-bit:
+yum install glibc-devel
+64-bit:
+yum install glibc-devel glibc-static
+
+On 64-bit Arch Linux make sure the multilib repository is enabled in your
+/etc/pacman.conf and run
+pacman -Sy lib32-glibc
diff --git a/tools/kvm/builtin-balloon.c b/tools/kvm/builtin-balloon.c
new file mode 100644 (file)
index 0000000..5bd2291
--- /dev/null
@@ -0,0 +1,80 @@
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+
+#include <kvm/util.h>
+#include <kvm/kvm-cmd.h>
+#include <kvm/builtin-balloon.h>
+#include <kvm/parse-options.h>
+#include <kvm/kvm.h>
+#include <kvm/kvm-ipc.h>
+
+static const char *instance_name;
+static u64 inflate;
+static u64 deflate;
+
+static const char * const balloon_usage[] = {
+       "lkvm balloon [-n name] [-p pid] [-i amount] [-d amount]",
+       NULL
+};
+
+static const struct option balloon_options[] = {
+       OPT_GROUP("Instance options:"),
+       OPT_STRING('n', "name", &instance_name, "name", "Instance name"),
+       OPT_GROUP("Balloon options:"),
+       OPT_U64('i', "inflate", &inflate, "Amount to inflate"),
+       OPT_U64('d', "deflate", &deflate, "Amount to deflate"),
+       OPT_END(),
+};
+
+void kvm_balloon_help(void)
+{
+       usage_with_options(balloon_usage, balloon_options);
+}
+
+static void parse_balloon_options(int argc, const char **argv)
+{
+       while (argc != 0) {
+               argc = parse_options(argc, argv, balloon_options, balloon_usage,
+                               PARSE_OPT_STOP_AT_NON_OPTION);
+               if (argc != 0)
+                       kvm_balloon_help();
+       }
+}
+
+int kvm_cmd_balloon(int argc, const char **argv, const char *prefix)
+{
+       int instance;
+       int r;
+       int amount;
+
+       parse_balloon_options(argc, argv);
+
+       if (inflate == 0 && deflate == 0)
+               kvm_balloon_help();
+
+       if (instance_name == NULL)
+               kvm_balloon_help();
+
+       instance = kvm__get_sock_by_instance(instance_name);
+
+       if (instance <= 0)
+               die("Failed locating instance");
+
+       if (inflate)
+               amount = inflate;
+       else if (deflate)
+               amount = -deflate;
+       else
+               kvm_balloon_help();
+
+       r = kvm_ipc__send_msg(instance, KVM_IPC_BALLOON,
+                       sizeof(amount), (u8 *)&amount);
+
+       close(instance);
+
+       if (r < 0)
+               return -1;
+
+       return 0;
+}
diff --git a/tools/kvm/builtin-debug.c b/tools/kvm/builtin-debug.c
new file mode 100644 (file)
index 0000000..4ae51d2
--- /dev/null
@@ -0,0 +1,110 @@
+#include <kvm/util.h>
+#include <kvm/kvm-cmd.h>
+#include <kvm/builtin-debug.h>
+#include <kvm/kvm.h>
+#include <kvm/parse-options.h>
+#include <kvm/kvm-ipc.h>
+#include <kvm/read-write.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+
+#define BUFFER_SIZE 100
+
+static bool all;
+static int nmi = -1;
+static bool dump;
+static const char *instance_name;
+static const char *sysrq;
+
+static const char * const debug_usage[] = {
+       "lkvm debug [--all] [-n name] [-d] [-m vcpu]",
+       NULL
+};
+
+static const struct option debug_options[] = {
+       OPT_GROUP("General options:"),
+       OPT_BOOLEAN('d', "dump", &dump, "Generate a debug dump from guest"),
+       OPT_INTEGER('m', "nmi", &nmi, "Generate NMI on VCPU"),
+       OPT_STRING('s', "sysrq", &sysrq, "sysrq", "Inject a sysrq"),
+       OPT_GROUP("Instance options:"),
+       OPT_BOOLEAN('a', "all", &all, "Debug all instances"),
+       OPT_STRING('n', "name", &instance_name, "name", "Instance name"),
+       OPT_END()
+};
+
+static void parse_debug_options(int argc, const char **argv)
+{
+       while (argc != 0) {
+               argc = parse_options(argc, argv, debug_options, debug_usage,
+                               PARSE_OPT_STOP_AT_NON_OPTION);
+               if (argc != 0)
+                       kvm_debug_help();
+       }
+}
+
+void kvm_debug_help(void)
+{
+       usage_with_options(debug_usage, debug_options);
+}
+
+static int do_debug(const char *name, int sock)
+{
+       char buff[BUFFER_SIZE];
+       struct debug_cmd_params cmd = {.dbg_type = 0};
+       int r;
+
+       if (dump)
+               cmd.dbg_type |= KVM_DEBUG_CMD_TYPE_DUMP;
+
+       if (nmi != -1) {
+               cmd.dbg_type |= KVM_DEBUG_CMD_TYPE_NMI;
+               cmd.cpu = nmi;
+       }
+
+       if (sysrq) {
+               cmd.dbg_type |= KVM_DEBUG_CMD_TYPE_SYSRQ;
+               cmd.sysrq = sysrq[0];
+       }
+
+       r = kvm_ipc__send_msg(sock, KVM_IPC_DEBUG, sizeof(cmd), (u8 *)&cmd);
+       if (r < 0)
+               return r;
+
+       if (!dump)
+               return 0;
+
+       do {
+               r = xread(sock, buff, BUFFER_SIZE);
+               if (r < 0)
+                       return 0;
+               printf("%.*s", r, buff);
+       } while (r > 0);
+
+       return 0;
+}
+
+int kvm_cmd_debug(int argc, const char **argv, const char *prefix)
+{
+       parse_debug_options(argc, argv);
+       int instance;
+       int r;
+
+       if (all)
+               return kvm__enumerate_instances(do_debug);
+
+       if (instance_name == NULL)
+               kvm_debug_help();
+
+       instance = kvm__get_sock_by_instance(instance_name);
+
+       if (instance <= 0)
+               die("Failed locating instance");
+
+       r = do_debug(instance_name, instance);
+
+       close(instance);
+
+       return r;
+}
diff --git a/tools/kvm/builtin-help.c b/tools/kvm/builtin-help.c
new file mode 100644 (file)
index 0000000..5970fb7
--- /dev/null
@@ -0,0 +1,63 @@
+#include <stdio.h>
+#include <string.h>
+
+/* user defined headers */
+#include <common-cmds.h>
+
+#include <kvm/util.h>
+#include <kvm/kvm-cmd.h>
+#include <kvm/builtin-help.h>
+#include <kvm/kvm.h>
+
+
+const char kvm_usage_string[] =
+       "lkvm COMMAND [ARGS]";
+
+const char kvm_more_info_string[] =
+       "See 'lkvm help COMMAND' for more information on a specific command.";
+
+
+static void list_common_cmds_help(void)
+{
+       unsigned int i, longest = 0;
+
+       for (i = 0; i < ARRAY_SIZE(common_cmds); i++) {
+               if (longest < strlen(common_cmds[i].name))
+                       longest = strlen(common_cmds[i].name);
+       }
+
+       puts(" The most commonly used lkvm commands are:");
+       for (i = 0; i < ARRAY_SIZE(common_cmds); i++) {
+               printf("   %-*s   ", longest, common_cmds[i].name);
+               puts(common_cmds[i].help);
+       }
+}
+
+static void kvm_help(void)
+{
+       printf("\n To start a simple non-privileged shell run '%s run'\n\n"
+               "usage: %s\n\n", KVM_BINARY_NAME, kvm_usage_string);
+       list_common_cmds_help();
+       printf("\n %s\n\n", kvm_more_info_string);
+}
+
+
+static void help_cmd(const char *cmd)
+{
+       struct cmd_struct *p;
+       p = kvm_get_command(kvm_commands, cmd);
+       if (!p)
+               kvm_help();
+       else if (p->help)
+               p->help();
+}
+
+int kvm_cmd_help(int argc, const char **argv, const char *prefix)
+{
+       if (!argv || !*argv) {
+               kvm_help();
+               return 0;
+       }
+       help_cmd(argv[0]);
+       return 0;
+}
diff --git a/tools/kvm/builtin-list.c b/tools/kvm/builtin-list.c
new file mode 100644 (file)
index 0000000..9299f17
--- /dev/null
@@ -0,0 +1,149 @@
+#include <kvm/util.h>
+#include <kvm/kvm-cmd.h>
+#include <kvm/builtin-list.h>
+#include <kvm/kvm.h>
+#include <kvm/parse-options.h>
+#include <kvm/kvm-ipc.h>
+
+#include <dirent.h>
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+#include <fcntl.h>
+
+static bool run;
+static bool rootfs;
+
+static const char * const list_usage[] = {
+       "lkvm list",
+       NULL
+};
+
+static const struct option list_options[] = {
+       OPT_GROUP("General options:"),
+       OPT_BOOLEAN('i', "run", &run, "List running instances"),
+       OPT_BOOLEAN('r', "rootfs", &rootfs, "List rootfs instances"),
+       OPT_END()
+};
+
+#define KVM_INSTANCE_RUNNING   "running"
+#define KVM_INSTANCE_PAUSED    "paused"
+#define KVM_INSTANCE_SHUTOFF   "shut off"
+
+void kvm_list_help(void)
+{
+       usage_with_options(list_usage, list_options);
+}
+
+static pid_t get_pid(int sock)
+{
+       pid_t pid;
+       int r;
+
+       r = kvm_ipc__send(sock, KVM_IPC_PID);
+       if (r < 0)
+               return r;
+
+       r = read(sock, &pid, sizeof(pid));
+       if (r < 0)
+               return r;
+
+       return pid;
+}
+
+int get_vmstate(int sock)
+{
+       int vmstate;
+       int r;
+
+       r = kvm_ipc__send(sock, KVM_IPC_VMSTATE);
+       if (r < 0)
+               return r;
+
+       r = read(sock, &vmstate, sizeof(vmstate));
+       if (r < 0)
+               return r;
+
+       return vmstate;
+
+}
+
+static int print_guest(const char *name, int sock)
+{
+       pid_t pid;
+       int vmstate;
+
+       pid = get_pid(sock);
+       vmstate = get_vmstate(sock);
+
+       if ((int)pid < 0 || vmstate < 0)
+               return -1;
+
+       if (vmstate == KVM_VMSTATE_PAUSED)
+               printf("%5d %-20s %s\n", pid, name, KVM_INSTANCE_PAUSED);
+       else
+               printf("%5d %-20s %s\n", pid, name, KVM_INSTANCE_RUNNING);
+
+       return 0;
+}
+
+static int kvm_list_running_instances(void)
+{
+       return kvm__enumerate_instances(print_guest);
+}
+
+static int kvm_list_rootfs(void)
+{
+       DIR *dir;
+       struct dirent *dirent;
+
+       dir = opendir(kvm__get_dir());
+       if (dir == NULL)
+               return -1;
+
+       while ((dirent = readdir(dir))) {
+               if (dirent->d_type == DT_DIR &&
+                       strcmp(dirent->d_name, ".") &&
+                       strcmp(dirent->d_name, ".."))
+                       printf("%5s %-20s %s\n", "", dirent->d_name, KVM_INSTANCE_SHUTOFF);
+       }
+
+       return 0;
+}
+
+static void parse_setup_options(int argc, const char **argv)
+{
+       while (argc != 0) {
+               argc = parse_options(argc, argv, list_options, list_usage,
+                               PARSE_OPT_STOP_AT_NON_OPTION);
+               if (argc != 0)
+                       kvm_list_help();
+       }
+}
+
+int kvm_cmd_list(int argc, const char **argv, const char *prefix)
+{
+       int r;
+
+       parse_setup_options(argc, argv);
+
+       if (!run && !rootfs)
+               run = rootfs = true;
+
+       printf("%6s %-20s %s\n", "PID", "NAME", "STATE");
+       printf("------------------------------------\n");
+
+       if (run) {
+               r = kvm_list_running_instances();
+               if (r < 0)
+                       perror("Error listing instances");
+       }
+
+       if (rootfs) {
+               r = kvm_list_rootfs();
+               if (r < 0)
+                       perror("Error listing rootfs");
+       }
+
+       return 0;
+}
diff --git a/tools/kvm/builtin-pause.c b/tools/kvm/builtin-pause.c
new file mode 100644 (file)
index 0000000..c08595a
--- /dev/null
@@ -0,0 +1,88 @@
+#include <kvm/util.h>
+#include <kvm/kvm-cmd.h>
+#include <kvm/builtin-pause.h>
+#include <kvm/builtin-list.h>
+#include <kvm/kvm.h>
+#include <kvm/parse-options.h>
+#include <kvm/kvm-ipc.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+
+static bool all;
+static const char *instance_name;
+
+static const char * const pause_usage[] = {
+       "lkvm pause [--all] [-n name]",
+       NULL
+};
+
+static const struct option pause_options[] = {
+       OPT_GROUP("General options:"),
+       OPT_BOOLEAN('a', "all", &all, "Pause all instances"),
+       OPT_STRING('n', "name", &instance_name, "name", "Instance name"),
+       OPT_END()
+};
+
+static void parse_pause_options(int argc, const char **argv)
+{
+       while (argc != 0) {
+               argc = parse_options(argc, argv, pause_options, pause_usage,
+                               PARSE_OPT_STOP_AT_NON_OPTION);
+               if (argc != 0)
+                       kvm_pause_help();
+       }
+}
+
+void kvm_pause_help(void)
+{
+       usage_with_options(pause_usage, pause_options);
+}
+
+static int do_pause(const char *name, int sock)
+{
+       int r;
+       int vmstate;
+
+       vmstate = get_vmstate(sock);
+       if (vmstate < 0)
+               return vmstate;
+       if (vmstate == KVM_VMSTATE_PAUSED) {
+               printf("Guest %s is already paused.\n", name);
+               return 0;
+       }
+
+       r = kvm_ipc__send(sock, KVM_IPC_PAUSE);
+       if (r)
+               return r;
+
+       printf("Guest %s paused\n", name);
+
+       return 0;
+}
+
+int kvm_cmd_pause(int argc, const char **argv, const char *prefix)
+{
+       int instance;
+       int r;
+
+       parse_pause_options(argc, argv);
+
+       if (all)
+               return kvm__enumerate_instances(do_pause);
+
+       if (instance_name == NULL)
+               kvm_pause_help();
+
+       instance = kvm__get_sock_by_instance(instance_name);
+
+       if (instance <= 0)
+               die("Failed locating instance");
+
+       r = do_pause(instance_name, instance);
+
+       close(instance);
+
+       return r;
+}
diff --git a/tools/kvm/builtin-resume.c b/tools/kvm/builtin-resume.c
new file mode 100644 (file)
index 0000000..0e954b4
--- /dev/null
@@ -0,0 +1,88 @@
+#include <kvm/util.h>
+#include <kvm/kvm-cmd.h>
+#include <kvm/builtin-resume.h>
+#include <kvm/builtin-list.h>
+#include <kvm/kvm.h>
+#include <kvm/parse-options.h>
+#include <kvm/kvm-ipc.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+
+static bool all;
+static const char *instance_name;
+
+static const char * const resume_usage[] = {
+       "lkvm resume [--all] [-n name]",
+       NULL
+};
+
+static const struct option resume_options[] = {
+       OPT_GROUP("General options:"),
+       OPT_BOOLEAN('a', "all", &all, "Resume all instances"),
+       OPT_STRING('n', "name", &instance_name, "name", "Instance name"),
+       OPT_END()
+};
+
+static void parse_resume_options(int argc, const char **argv)
+{
+       while (argc != 0) {
+               argc = parse_options(argc, argv, resume_options, resume_usage,
+                               PARSE_OPT_STOP_AT_NON_OPTION);
+               if (argc != 0)
+                       kvm_resume_help();
+       }
+}
+
+void kvm_resume_help(void)
+{
+       usage_with_options(resume_usage, resume_options);
+}
+
+static int do_resume(const char *name, int sock)
+{
+       int r;
+       int vmstate;
+
+       vmstate = get_vmstate(sock);
+       if (vmstate < 0)
+               return vmstate;
+       if (vmstate == KVM_VMSTATE_RUNNING) {
+               printf("Guest %s is still running.\n", name);
+               return 0;
+       }
+
+       r = kvm_ipc__send(sock, KVM_IPC_RESUME);
+       if (r)
+               return r;
+
+       printf("Guest %s resumed\n", name);
+
+       return 0;
+}
+
+int kvm_cmd_resume(int argc, const char **argv, const char *prefix)
+{
+       int instance;
+       int r;
+
+       parse_resume_options(argc, argv);
+
+       if (all)
+               return kvm__enumerate_instances(do_resume);
+
+       if (instance_name == NULL)
+               kvm_resume_help();
+
+       instance = kvm__get_sock_by_instance(instance_name);
+
+       if (instance <= 0)
+               die("Failed locating instance");
+
+       r = do_resume(instance_name, instance);
+
+       close(instance);
+
+       return r;
+}
diff --git a/tools/kvm/builtin-run.c b/tools/kvm/builtin-run.c
new file mode 100644 (file)
index 0000000..709ed33
--- /dev/null
@@ -0,0 +1,705 @@
+#include "kvm/builtin-run.h"
+
+#include "kvm/builtin-setup.h"
+#include "kvm/virtio-balloon.h"
+#include "kvm/virtio-console.h"
+#include "kvm/parse-options.h"
+#include "kvm/8250-serial.h"
+#include "kvm/framebuffer.h"
+#include "kvm/disk-image.h"
+#include "kvm/threadpool.h"
+#include "kvm/virtio-scsi.h"
+#include "kvm/virtio-blk.h"
+#include "kvm/virtio-net.h"
+#include "kvm/virtio-rng.h"
+#include "kvm/ioeventfd.h"
+#include "kvm/virtio-9p.h"
+#include "kvm/barrier.h"
+#include "kvm/kvm-cpu.h"
+#include "kvm/ioport.h"
+#include "kvm/symbol.h"
+#include "kvm/i8042.h"
+#include "kvm/mutex.h"
+#include "kvm/term.h"
+#include "kvm/util.h"
+#include "kvm/strbuf.h"
+#include "kvm/vesa.h"
+#include "kvm/irq.h"
+#include "kvm/kvm.h"
+#include "kvm/pci.h"
+#include "kvm/rtc.h"
+#include "kvm/sdl.h"
+#include "kvm/vnc.h"
+#include "kvm/guest_compat.h"
+#include "kvm/pci-shmem.h"
+#include "kvm/kvm-ipc.h"
+#include "kvm/builtin-debug.h"
+
+#include <linux/types.h>
+#include <linux/err.h>
+
+#include <sys/utsname.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <termios.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <stdio.h>
+
+#define MB_SHIFT               (20)
+#define KB_SHIFT               (10)
+#define GB_SHIFT               (30)
+
+__thread struct kvm_cpu *current_kvm_cpu;
+
+static int  kvm_run_wrapper;
+
+bool do_debug_print = false;
+
+extern char _binary_guest_init_start;
+extern char _binary_guest_init_size;
+
+static const char * const run_usage[] = {
+       "lkvm run [<options>] [<kernel image>]",
+       NULL
+};
+
+enum {
+       KVM_RUN_DEFAULT,
+       KVM_RUN_SANDBOX,
+};
+
+static int img_name_parser(const struct option *opt, const char *arg, int unset)
+{
+       char path[PATH_MAX];
+       struct stat st;
+
+       snprintf(path, PATH_MAX, "%s%s", kvm__get_dir(), arg);
+
+       if ((stat(arg, &st) == 0 && S_ISDIR(st.st_mode)) ||
+          (stat(path, &st) == 0 && S_ISDIR(st.st_mode)))
+               return virtio_9p_img_name_parser(opt, arg, unset);
+       return disk_img_name_parser(opt, arg, unset);
+}
+
+void kvm_run_set_wrapper_sandbox(void)
+{
+       kvm_run_wrapper = KVM_RUN_SANDBOX;
+}
+
+#define BUILD_OPTIONS(name, cfg, kvm)                                  \
+       struct option name[] = {                                        \
+       OPT_GROUP("Basic options:"),                                    \
+       OPT_STRING('\0', "name", &(cfg)->guest_name, "guest name",      \
+                       "A name for the guest"),                        \
+       OPT_INTEGER('c', "cpus", &(cfg)->nrcpus, "Number of CPUs"),     \
+       OPT_U64('m', "mem", &(cfg)->ram_size, "Virtual machine memory"  \
+               " size in MiB."),                                       \
+       OPT_CALLBACK('\0', "shmem", NULL,                               \
+                    "[pci:]<addr>:<size>[:handle=<handle>][:create]",  \
+                    "Share host shmem with guest via pci device",      \
+                    shmem_parser, NULL),                               \
+       OPT_CALLBACK('d', "disk", kvm, "image or rootfs_dir", "Disk "   \
+                       " image or rootfs directory", img_name_parser,  \
+                       kvm),                                           \
+       OPT_BOOLEAN('\0', "balloon", &(cfg)->balloon, "Enable virtio"   \
+                       " balloon"),                                    \
+       OPT_BOOLEAN('\0', "vnc", &(cfg)->vnc, "Enable VNC framebuffer"),\
+       OPT_BOOLEAN('\0', "sdl", &(cfg)->sdl, "Enable SDL framebuffer"),\
+       OPT_BOOLEAN('\0', "rng", &(cfg)->virtio_rng, "Enable virtio"    \
+                       " Random Number Generator"),                    \
+       OPT_CALLBACK('\0', "9p", NULL, "dir_to_share,tag_name",         \
+                    "Enable virtio 9p to share files between host and" \
+                    " guest", virtio_9p_rootdir_parser, kvm),          \
+       OPT_STRING('\0', "console", &(cfg)->console, "serial, virtio or"\
+                       " hv", "Console to use"),                       \
+       OPT_STRING('\0', "dev", &(cfg)->dev, "device_file",             \
+                       "KVM device file"),                             \
+       OPT_CALLBACK('\0', "tty", NULL, "tty id",                       \
+                    "Remap guest TTY into a pty on the host",          \
+                    tty_parser, NULL),                                 \
+       OPT_STRING('\0', "sandbox", &(cfg)->sandbox, "script",          \
+                       "Run this script when booting into custom"      \
+                       " rootfs"),                                     \
+       OPT_STRING('\0', "hugetlbfs", &(cfg)->hugetlbfs_path, "path",   \
+                       "Hugetlbfs path"),                              \
+                                                                       \
+       OPT_GROUP("Kernel options:"),                                   \
+       OPT_STRING('k', "kernel", &(cfg)->kernel_filename, "kernel",    \
+                       "Kernel to boot in virtual machine"),           \
+       OPT_STRING('i', "initrd", &(cfg)->initrd_filename, "initrd",    \
+                       "Initial RAM disk image"),                      \
+       OPT_STRING('p', "params", &(cfg)->kernel_cmdline, "params",     \
+                       "Kernel command line arguments"),               \
+       OPT_STRING('f', "firmware", &(cfg)->firmware_filename, "firmware",\
+                       "Firmware image to boot in virtual machine"),   \
+                                                                       \
+       OPT_GROUP("Networking options:"),                               \
+       OPT_CALLBACK_DEFAULT('n', "network", NULL, "network params",    \
+                    "Create a new guest NIC",                          \
+                    netdev_parser, NULL, kvm),                         \
+       OPT_BOOLEAN('\0', "no-dhcp", &(cfg)->no_dhcp, "Disable kernel"  \
+                       " DHCP in rootfs mode"),                        \
+                                                                       \
+       OPT_GROUP("BIOS options:"),                                     \
+       OPT_INTEGER('\0', "vidmode", &(cfg)->vidmode,                   \
+                   "Video mode"),                                      \
+                                                                       \
+       OPT_GROUP("Debug options:"),                                    \
+       OPT_BOOLEAN('\0', "debug", &do_debug_print,                     \
+                       "Enable debug messages"),                       \
+       OPT_BOOLEAN('\0', "debug-single-step", &(cfg)->single_step,     \
+                       "Enable single stepping"),                      \
+       OPT_BOOLEAN('\0', "debug-ioport", &(cfg)->ioport_debug,         \
+                       "Enable ioport debugging"),                     \
+       OPT_BOOLEAN('\0', "debug-mmio", &(cfg)->mmio_debug,             \
+                       "Enable MMIO debugging"),                       \
+       OPT_INTEGER('\0', "debug-iodelay", &(cfg)->debug_iodelay,       \
+                       "Delay IO by millisecond"),                     \
+       OPT_END()                                                       \
+       };
+
+static void handle_sigalrm(int sig, siginfo_t *si, void *uc)
+{
+       struct kvm *kvm = si->si_value.sival_ptr;
+
+       kvm__arch_periodic_poll(kvm);
+}
+
+static void *kvm_cpu_thread(void *arg)
+{
+       current_kvm_cpu         = arg;
+
+       if (kvm_cpu__start(current_kvm_cpu))
+               goto panic_kvm;
+
+       return (void *) (intptr_t) 0;
+
+panic_kvm:
+       fprintf(stderr, "KVM exit reason: %u (\"%s\")\n",
+               current_kvm_cpu->kvm_run->exit_reason,
+               kvm_exit_reasons[current_kvm_cpu->kvm_run->exit_reason]);
+       if (current_kvm_cpu->kvm_run->exit_reason == KVM_EXIT_UNKNOWN)
+               fprintf(stderr, "KVM exit code: 0x%Lu\n",
+                       current_kvm_cpu->kvm_run->hw.hardware_exit_reason);
+
+       kvm_cpu__set_debug_fd(STDOUT_FILENO);
+       kvm_cpu__show_registers(current_kvm_cpu);
+       kvm_cpu__show_code(current_kvm_cpu);
+       kvm_cpu__show_page_tables(current_kvm_cpu);
+
+       return (void *) (intptr_t) 1;
+}
+
+static char kernel[PATH_MAX];
+
+static const char *host_kernels[] = {
+       "/boot/vmlinuz",
+       "/boot/bzImage",
+       NULL
+};
+
+static const char *default_kernels[] = {
+       "./bzImage",
+       "arch/" BUILD_ARCH "/boot/bzImage",
+       "../../arch/" BUILD_ARCH "/boot/bzImage",
+       NULL
+};
+
+static const char *default_vmlinux[] = {
+       "vmlinux",
+       "../../../vmlinux",
+       "../../vmlinux",
+       NULL
+};
+
+static void kernel_usage_with_options(void)
+{
+       const char **k;
+       struct utsname uts;
+
+       fprintf(stderr, "Fatal: could not find default kernel image in:\n");
+       k = &default_kernels[0];
+       while (*k) {
+               fprintf(stderr, "\t%s\n", *k);
+               k++;
+       }
+
+       if (uname(&uts) < 0)
+               return;
+
+       k = &host_kernels[0];
+       while (*k) {
+               if (snprintf(kernel, PATH_MAX, "%s-%s", *k, uts.release) < 0)
+                       return;
+               fprintf(stderr, "\t%s\n", kernel);
+               k++;
+       }
+       fprintf(stderr, "\nPlease see '%s run --help' for more options.\n\n",
+               KVM_BINARY_NAME);
+}
+
+static u64 host_ram_size(void)
+{
+       long page_size;
+       long nr_pages;
+
+       nr_pages        = sysconf(_SC_PHYS_PAGES);
+       if (nr_pages < 0) {
+               pr_warning("sysconf(_SC_PHYS_PAGES) failed");
+               return 0;
+       }
+
+       page_size       = sysconf(_SC_PAGE_SIZE);
+       if (page_size < 0) {
+               pr_warning("sysconf(_SC_PAGE_SIZE) failed");
+               return 0;
+       }
+
+       return (nr_pages * page_size) >> MB_SHIFT;
+}
+
+/*
+ * If user didn't specify how much memory it wants to allocate for the guest,
+ * avoid filling the whole host RAM.
+ */
+#define RAM_SIZE_RATIO         0.8
+
+static u64 get_ram_size(int nr_cpus)
+{
+       u64 available;
+       u64 ram_size;
+
+       ram_size        = 64 * (nr_cpus + 3);
+
+       available       = host_ram_size() * RAM_SIZE_RATIO;
+       if (!available)
+               available = MIN_RAM_SIZE_MB;
+
+       if (ram_size > available)
+               ram_size        = available;
+
+       return ram_size;
+}
+
+static const char *find_kernel(void)
+{
+       const char **k;
+       struct stat st;
+       struct utsname uts;
+
+       k = &default_kernels[0];
+       while (*k) {
+               if (stat(*k, &st) < 0 || !S_ISREG(st.st_mode)) {
+                       k++;
+                       continue;
+               }
+               strncpy(kernel, *k, PATH_MAX);
+               return kernel;
+       }
+
+       if (uname(&uts) < 0)
+               return NULL;
+
+       k = &host_kernels[0];
+       while (*k) {
+               if (snprintf(kernel, PATH_MAX, "%s-%s", *k, uts.release) < 0)
+                       return NULL;
+
+               if (stat(kernel, &st) < 0 || !S_ISREG(st.st_mode)) {
+                       k++;
+                       continue;
+               }
+               return kernel;
+
+       }
+       return NULL;
+}
+
+static const char *find_vmlinux(void)
+{
+       const char **vmlinux;
+
+       vmlinux = &default_vmlinux[0];
+       while (*vmlinux) {
+               struct stat st;
+
+               if (stat(*vmlinux, &st) < 0 || !S_ISREG(st.st_mode)) {
+                       vmlinux++;
+                       continue;
+               }
+               return *vmlinux;
+       }
+       return NULL;
+}
+
+void kvm_run_help(void)
+{
+       struct kvm *kvm = NULL;
+
+       BUILD_OPTIONS(options, &kvm->cfg, kvm);
+       usage_with_options(run_usage, options);
+}
+
+static int kvm_setup_guest_init(struct kvm *kvm)
+{
+       const char *rootfs = kvm->cfg.custom_rootfs_name;
+       char tmp[PATH_MAX];
+       size_t size;
+       int fd, ret;
+       char *data;
+
+       /* Setup /virt/init */
+       size = (size_t)&_binary_guest_init_size;
+       data = (char *)&_binary_guest_init_start;
+       snprintf(tmp, PATH_MAX, "%s%s/virt/init", kvm__get_dir(), rootfs);
+       remove(tmp);
+       fd = open(tmp, O_CREAT | O_WRONLY, 0755);
+       if (fd < 0)
+               die("Fail to setup %s", tmp);
+       ret = xwrite(fd, data, size);
+       if (ret < 0)
+               die("Fail to setup %s", tmp);
+       close(fd);
+
+       return 0;
+}
+
+static int kvm_run_set_sandbox(struct kvm *kvm)
+{
+       const char *guestfs_name = kvm->cfg.custom_rootfs_name;
+       char path[PATH_MAX], script[PATH_MAX], *tmp;
+
+       snprintf(path, PATH_MAX, "%s%s/virt/sandbox.sh", kvm__get_dir(), guestfs_name);
+
+       remove(path);
+
+       if (kvm->cfg.sandbox == NULL)
+               return 0;
+
+       tmp = realpath(kvm->cfg.sandbox, NULL);
+       if (tmp == NULL)
+               return -ENOMEM;
+
+       snprintf(script, PATH_MAX, "/host/%s", tmp);
+       free(tmp);
+
+       return symlink(script, path);
+}
+
+static void kvm_write_sandbox_cmd_exactly(int fd, const char *arg)
+{
+       const char *single_quote;
+
+       if (!*arg) { /* zero length string */
+               if (write(fd, "''", 2) <= 0)
+                       die("Failed writing sandbox script");
+               return;
+       }
+
+       while (*arg) {
+               single_quote = strchrnul(arg, '\'');
+
+               /* write non-single-quote string as #('string') */
+               if (arg != single_quote) {
+                       if (write(fd, "'", 1) <= 0 ||
+                           write(fd, arg, single_quote - arg) <= 0 ||
+                           write(fd, "'", 1) <= 0)
+                               die("Failed writing sandbox script");
+               }
+
+               /* write single quote as #("'") */
+               if (*single_quote) {
+                       if (write(fd, "\"'\"", 3) <= 0)
+                               die("Failed writing sandbox script");
+               } else
+                       break;
+
+               arg = single_quote + 1;
+       }
+}
+
+static void resolve_program(const char *src, char *dst, size_t len)
+{
+       struct stat st;
+       int err;
+
+       err = stat(src, &st);
+
+       if (!err && S_ISREG(st.st_mode)) {
+               char resolved_path[PATH_MAX];
+
+               if (!realpath(src, resolved_path))
+                       die("Unable to resolve program %s: %s\n", src, strerror(errno));
+
+               snprintf(dst, len, "/host%s", resolved_path);
+       } else
+               strncpy(dst, src, len);
+}
+
+static void kvm_run_write_sandbox_cmd(struct kvm *kvm, const char **argv, int argc)
+{
+       const char script_hdr[] = "#! /bin/bash\n\n";
+       char program[PATH_MAX];
+       int fd;
+
+       remove(kvm->cfg.sandbox);
+
+       fd = open(kvm->cfg.sandbox, O_RDWR | O_CREAT, 0777);
+       if (fd < 0)
+               die("Failed creating sandbox script");
+
+       if (write(fd, script_hdr, sizeof(script_hdr) - 1) <= 0)
+               die("Failed writing sandbox script");
+
+       resolve_program(argv[0], program, PATH_MAX);
+       kvm_write_sandbox_cmd_exactly(fd, program);
+
+       argv++;
+       argc--;
+
+       while (argc) {
+               if (write(fd, " ", 1) <= 0)
+                       die("Failed writing sandbox script");
+
+               kvm_write_sandbox_cmd_exactly(fd, argv[0]);
+               argv++;
+               argc--;
+       }
+       if (write(fd, "\n", 1) <= 0)
+               die("Failed writing sandbox script");
+
+       close(fd);
+}
+
+static struct kvm *kvm_cmd_run_init(int argc, const char **argv)
+{
+       static char real_cmdline[2048], default_name[20];
+       unsigned int nr_online_cpus;
+       struct sigaction sa;
+       struct kvm *kvm = kvm__new();
+
+       if (IS_ERR(kvm))
+               return kvm;
+
+       sa.sa_flags = SA_SIGINFO;
+       sa.sa_sigaction = handle_sigalrm;
+       sigemptyset(&sa.sa_mask);
+       sigaction(SIGALRM, &sa, NULL);
+
+       nr_online_cpus = sysconf(_SC_NPROCESSORS_ONLN);
+       kvm->cfg.custom_rootfs_name = "default";
+
+       while (argc != 0) {
+               BUILD_OPTIONS(options, &kvm->cfg, kvm);
+               argc = parse_options(argc, argv, options, run_usage,
+                               PARSE_OPT_STOP_AT_NON_OPTION |
+                               PARSE_OPT_KEEP_DASHDASH);
+               if (argc != 0) {
+                       /* Cusrom options, should have been handled elsewhere */
+                       if (strcmp(argv[0], "--") == 0) {
+                               if (kvm_run_wrapper == KVM_RUN_SANDBOX) {
+                                       kvm->cfg.sandbox = DEFAULT_SANDBOX_FILENAME;
+                                       kvm_run_write_sandbox_cmd(kvm, argv+1, argc-1);
+                                       break;
+                               }
+                       }
+
+                       if ((kvm_run_wrapper == KVM_RUN_DEFAULT && kvm->cfg.kernel_filename) ||
+                               (kvm_run_wrapper == KVM_RUN_SANDBOX && kvm->cfg.sandbox)) {
+                               fprintf(stderr, "Cannot handle parameter: "
+                                               "%s\n", argv[0]);
+                               usage_with_options(run_usage, options);
+                               free(kvm);
+                               return ERR_PTR(-EINVAL);
+                       }
+                       if (kvm_run_wrapper == KVM_RUN_SANDBOX) {
+                               /*
+                                * first unhandled parameter is treated as
+                                * sandbox command
+                                */
+                               kvm->cfg.sandbox = DEFAULT_SANDBOX_FILENAME;
+                               kvm_run_write_sandbox_cmd(kvm, argv, argc);
+                       } else {
+                               /*
+                                * first unhandled parameter is treated as a kernel
+                                * image
+                                */
+                               kvm->cfg.kernel_filename = argv[0];
+                       }
+                       argv++;
+                       argc--;
+               }
+
+       }
+
+       kvm->nr_disks = kvm->cfg.image_count;
+
+       if (!kvm->cfg.kernel_filename)
+               kvm->cfg.kernel_filename = find_kernel();
+
+       if (!kvm->cfg.kernel_filename) {
+               kernel_usage_with_options();
+               return ERR_PTR(-EINVAL);
+       }
+
+       kvm->cfg.vmlinux_filename = find_vmlinux();
+       kvm->vmlinux = kvm->cfg.vmlinux_filename;
+
+       if (kvm->cfg.nrcpus == 0)
+               kvm->cfg.nrcpus = nr_online_cpus;
+
+       if (!kvm->cfg.ram_size)
+               kvm->cfg.ram_size = get_ram_size(kvm->cfg.nrcpus);
+
+       if (kvm->cfg.ram_size < MIN_RAM_SIZE_MB)
+               die("Not enough memory specified: %lluMB (min %lluMB)", kvm->cfg.ram_size, MIN_RAM_SIZE_MB);
+
+       if (kvm->cfg.ram_size > host_ram_size())
+               pr_warning("Guest memory size %lluMB exceeds host physical RAM size %lluMB", kvm->cfg.ram_size, host_ram_size());
+
+       kvm->cfg.ram_size <<= MB_SHIFT;
+
+       if (!kvm->cfg.dev)
+               kvm->cfg.dev = DEFAULT_KVM_DEV;
+
+       if (!kvm->cfg.console)
+               kvm->cfg.console = DEFAULT_CONSOLE;
+
+       if (!strncmp(kvm->cfg.console, "virtio", 6))
+               kvm->cfg.active_console  = CONSOLE_VIRTIO;
+       else if (!strncmp(kvm->cfg.console, "serial", 6))
+               kvm->cfg.active_console  = CONSOLE_8250;
+       else if (!strncmp(kvm->cfg.console, "hv", 2))
+               kvm->cfg.active_console = CONSOLE_HV;
+       else
+               pr_warning("No console!");
+
+       if (!kvm->cfg.host_ip)
+               kvm->cfg.host_ip = DEFAULT_HOST_ADDR;
+
+       if (!kvm->cfg.guest_ip)
+               kvm->cfg.guest_ip = DEFAULT_GUEST_ADDR;
+
+       if (!kvm->cfg.guest_mac)
+               kvm->cfg.guest_mac = DEFAULT_GUEST_MAC;
+
+       if (!kvm->cfg.host_mac)
+               kvm->cfg.host_mac = DEFAULT_HOST_MAC;
+
+       if (!kvm->cfg.script)
+               kvm->cfg.script = DEFAULT_SCRIPT;
+
+       if (!kvm->cfg.vidmode)
+               kvm->cfg.vidmode = -1;
+
+       /* vidmode should be either specified or set by default */
+       if (kvm->cfg.vnc || kvm->cfg.sdl) {
+               if (kvm->cfg.vidmode == -1)
+                       kvm->cfg.vidmode = 0x312;
+       } else {
+               kvm->cfg.vidmode = 0;
+       }
+
+       if (!kvm->cfg.network)
+                kvm->cfg.network = DEFAULT_NETWORK;
+
+       memset(real_cmdline, 0, sizeof(real_cmdline));
+       kvm__arch_set_cmdline(real_cmdline, kvm->cfg.vnc || kvm->cfg.sdl);
+
+       if (strlen(real_cmdline) > 0)
+               strcat(real_cmdline, " ");
+
+       if (kvm->cfg.kernel_cmdline)
+               strlcat(real_cmdline, kvm->cfg.kernel_cmdline, sizeof(real_cmdline));
+
+       if (!kvm->cfg.guest_name) {
+               if (kvm->cfg.custom_rootfs) {
+                       kvm->cfg.guest_name = kvm->cfg.custom_rootfs_name;
+               } else {
+                       sprintf(default_name, "guest-%u", getpid());
+                       kvm->cfg.guest_name = default_name;
+               }
+       }
+
+       if (!kvm->cfg.using_rootfs && !kvm->cfg.disk_image[0].filename && !kvm->cfg.initrd_filename) {
+               char tmp[PATH_MAX];
+
+               kvm_setup_create_new(kvm->cfg.custom_rootfs_name);
+               kvm_setup_resolv(kvm->cfg.custom_rootfs_name);
+
+               snprintf(tmp, PATH_MAX, "%s%s", kvm__get_dir(), "default");
+               if (virtio_9p__register(kvm, tmp, "/dev/root") < 0)
+                       die("Unable to initialize virtio 9p");
+               if (virtio_9p__register(kvm, "/", "hostfs") < 0)
+                       die("Unable to initialize virtio 9p");
+               kvm->cfg.using_rootfs = kvm->cfg.custom_rootfs = 1;
+       }
+
+       if (kvm->cfg.using_rootfs) {
+               strcat(real_cmdline, " root=/dev/root rw rootflags=rw,trans=virtio,version=9p2000.L rootfstype=9p");
+               if (kvm->cfg.custom_rootfs) {
+                       kvm_run_set_sandbox(kvm);
+
+                       strcat(real_cmdline, " init=/virt/init");
+
+                       if (!kvm->cfg.no_dhcp)
+                               strcat(real_cmdline, "  ip=dhcp");
+                       if (kvm_setup_guest_init(kvm))
+                               die("Failed to setup init for guest.");
+               }
+       } else if (!strstr(real_cmdline, "root=")) {
+               strlcat(real_cmdline, " root=/dev/vda rw ", sizeof(real_cmdline));
+       }
+
+       kvm->cfg.real_cmdline = real_cmdline;
+
+       printf("  # %s run -k %s -m %Lu -c %d --name %s\n", KVM_BINARY_NAME,
+               kvm->cfg.kernel_filename, kvm->cfg.ram_size / 1024 / 1024, kvm->cfg.nrcpus, kvm->cfg.guest_name);
+
+       init_list__init(kvm);
+
+       return kvm;
+}
+
+static int kvm_cmd_run_work(struct kvm *kvm)
+{
+       int i;
+       void *ret = NULL;
+
+       for (i = 0; i < kvm->nrcpus; i++) {
+               if (pthread_create(&kvm->cpus[i]->thread, NULL, kvm_cpu_thread, kvm->cpus[i]) != 0)
+                       die("unable to create KVM VCPU thread");
+       }
+
+       /* Only VCPU #0 is going to exit by itself when shutting down */
+       return pthread_join(kvm->cpus[0]->thread, &ret);
+}
+
+static void kvm_cmd_run_exit(struct kvm *kvm, int guest_ret)
+{
+       compat__print_all_messages();
+
+       init_list__exit(kvm);
+
+       if (guest_ret == 0)
+               printf("\n  # KVM session ended normally.\n");
+}
+
+int kvm_cmd_run(int argc, const char **argv, const char *prefix)
+{
+       int ret = -EFAULT;
+       struct kvm *kvm;
+
+       kvm = kvm_cmd_run_init(argc, argv);
+       if (IS_ERR(kvm))
+               return PTR_ERR(kvm);
+
+       ret = kvm_cmd_run_work(kvm);
+       kvm_cmd_run_exit(kvm, ret);
+
+       return ret;
+}
diff --git a/tools/kvm/builtin-sandbox.c b/tools/kvm/builtin-sandbox.c
new file mode 100644 (file)
index 0000000..433f536
--- /dev/null
@@ -0,0 +1,9 @@
+#include "kvm/builtin-sandbox.h"
+#include "kvm/builtin-run.h"
+
+int kvm_cmd_sandbox(int argc, const char **argv, const char *prefix)
+{
+       kvm_run_set_wrapper_sandbox();
+
+       return kvm_cmd_run(argc, argv, prefix);
+}
diff --git a/tools/kvm/builtin-setup.c b/tools/kvm/builtin-setup.c
new file mode 100644 (file)
index 0000000..1b865b7
--- /dev/null
@@ -0,0 +1,262 @@
+#include <kvm/util.h>
+#include <kvm/kvm-cmd.h>
+#include <kvm/builtin-setup.h>
+#include <kvm/kvm.h>
+#include <kvm/parse-options.h>
+#include <kvm/read-write.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <limits.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+extern char _binary_guest_init_start;
+extern char _binary_guest_init_size;
+
+static const char *instance_name;
+
+static const char * const setup_usage[] = {
+       "lkvm setup [name]",
+       NULL
+};
+
+static const struct option setup_options[] = {
+       OPT_END()
+};
+
+static void parse_setup_options(int argc, const char **argv)
+{
+       while (argc != 0) {
+               argc = parse_options(argc, argv, setup_options, setup_usage,
+                               PARSE_OPT_STOP_AT_NON_OPTION);
+               if (argc != 0 && instance_name)
+                       kvm_setup_help();
+               else
+                       instance_name = argv[0];
+               argv++;
+               argc--;
+       }
+}
+
+void kvm_setup_help(void)
+{
+       printf("\n%s setup creates a new rootfs under %s.\n"
+               "This can be used later by the '-d' parameter of '%s run'.\n",
+               KVM_BINARY_NAME, kvm__get_dir(), KVM_BINARY_NAME);
+       usage_with_options(setup_usage, setup_options);
+}
+
+static int copy_file(const char *from, const char *to)
+{
+       int in_fd, out_fd;
+       void *src, *dst;
+       struct stat st;
+       int err = -1;
+
+       in_fd = open(from, O_RDONLY);
+       if (in_fd < 0)
+               return err;
+
+       if (fstat(in_fd, &st) < 0)
+               goto error_close_in;
+
+       out_fd = open(to, O_RDWR | O_CREAT | O_TRUNC, st.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO));
+       if (out_fd < 0)
+               goto error_close_in;
+
+       src = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, in_fd, 0);
+       if (src == MAP_FAILED)
+               goto error_close_out;
+
+       if (ftruncate(out_fd, st.st_size) < 0)
+               goto error_munmap_src;
+
+       dst = mmap(NULL, st.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, out_fd, 0);
+       if (dst == MAP_FAILED)
+               goto error_munmap_src;
+
+       memcpy(dst, src, st.st_size);
+
+       if (fsync(out_fd) < 0)
+               goto error_munmap_dst;
+
+       err = 0;
+
+error_munmap_dst:
+       munmap(dst, st.st_size);
+error_munmap_src:
+       munmap(src, st.st_size);
+error_close_out:
+       close(out_fd);
+error_close_in:
+       close(in_fd);
+
+       return err;
+}
+
+static const char *guestfs_dirs[] = {
+       "/dev",
+       "/etc",
+       "/home",
+       "/host",
+       "/proc",
+       "/root",
+       "/sys",
+       "/tmp",
+       "/var",
+       "/var/lib",
+       "/virt",
+       "/virt/home",
+};
+
+static const char *guestfs_symlinks[] = {
+       "/bin",
+       "/lib",
+       "/lib64",
+       "/sbin",
+       "/usr",
+       "/etc/ld.so.conf",
+};
+
+static int copy_init(const char *guestfs_name)
+{
+       char path[PATH_MAX];
+       size_t size;
+       int fd, ret;
+       char *data;
+
+       size = (size_t)&_binary_guest_init_size;
+       data = (char *)&_binary_guest_init_start;
+       snprintf(path, PATH_MAX, "%s%s/virt/init", kvm__get_dir(), guestfs_name);
+       remove(path);
+       fd = open(path, O_CREAT | O_WRONLY, 0755);
+       if (fd < 0)
+               die("Fail to setup %s", path);
+       ret = xwrite(fd, data, size);
+       if (ret < 0)
+               die("Fail to setup %s", path);
+       close(fd);
+
+       return 0;
+}
+
+static int copy_passwd(const char *guestfs_name)
+{
+       char path[PATH_MAX];
+       FILE *file;
+       int ret;
+
+       snprintf(path, PATH_MAX, "%s%s/etc/passwd", kvm__get_dir(), guestfs_name);
+
+       file = fopen(path, "w");
+       if (!file)
+               return -1;
+
+       ret = fprintf(file, "root:x:0:0:root:/root:/bin/sh\n");
+       if (ret < 0)
+               return ret;
+
+       fclose(file);
+
+       return 0;
+}
+
+static int make_guestfs_symlink(const char *guestfs_name, const char *path)
+{
+       char target[PATH_MAX];
+       char name[PATH_MAX];
+
+       snprintf(name, PATH_MAX, "%s%s%s", kvm__get_dir(), guestfs_name, path);
+
+       snprintf(target, PATH_MAX, "/host%s", path);
+
+       return symlink(target, name);
+}
+
+static int make_dir(const char *dir)
+{
+       char name[PATH_MAX];
+
+       snprintf(name, PATH_MAX, "%s%s", kvm__get_dir(), dir);
+
+       return mkdir(name, 0777);
+}
+
+static void make_guestfs_dir(const char *guestfs_name, const char *dir)
+{
+       char name[PATH_MAX];
+
+       snprintf(name, PATH_MAX, "%s%s", guestfs_name, dir);
+
+       make_dir(name);
+}
+
+void kvm_setup_resolv(const char *guestfs_name)
+{
+       char path[PATH_MAX];
+
+       snprintf(path, PATH_MAX, "%s%s/etc/resolv.conf", kvm__get_dir(), guestfs_name);
+
+       copy_file("/etc/resolv.conf", path);
+}
+
+static int do_setup(const char *guestfs_name)
+{
+       unsigned int i;
+       int ret;
+
+       ret = make_dir(guestfs_name);
+       if (ret < 0)
+               return ret;
+
+       for (i = 0; i < ARRAY_SIZE(guestfs_dirs); i++)
+               make_guestfs_dir(guestfs_name, guestfs_dirs[i]);
+
+       for (i = 0; i < ARRAY_SIZE(guestfs_symlinks); i++) {
+               make_guestfs_symlink(guestfs_name, guestfs_symlinks[i]);
+       }
+
+       ret = copy_init(guestfs_name);
+       if (ret < 0)
+               return ret;
+
+       return copy_passwd(guestfs_name);
+}
+
+int kvm_setup_create_new(const char *guestfs_name)
+{
+       return do_setup(guestfs_name);
+}
+
+int kvm_cmd_setup(int argc, const char **argv, const char *prefix)
+{
+       int r;
+
+       parse_setup_options(argc, argv);
+
+       if (instance_name == NULL)
+               kvm_setup_help();
+
+       r = do_setup(instance_name);
+       if (r == 0)
+               printf("A new rootfs '%s' has been created in '%s%s'.\n\n"
+                       "You can now start it by running the following command:\n\n"
+                       "  %s run -d %s\n",
+                       instance_name, kvm__get_dir(), instance_name,
+                       KVM_BINARY_NAME,instance_name);
+       else
+               printf("Unable to create rootfs in %s%s: %s\n",
+                       kvm__get_dir(), instance_name, strerror(errno));
+
+       return r;
+}
diff --git a/tools/kvm/builtin-stat.c b/tools/kvm/builtin-stat.c
new file mode 100644 (file)
index 0000000..ffd72e8
--- /dev/null
@@ -0,0 +1,127 @@
+#include <kvm/util.h>
+#include <kvm/kvm-cmd.h>
+#include <kvm/builtin-stat.h>
+#include <kvm/kvm.h>
+#include <kvm/parse-options.h>
+#include <kvm/kvm-ipc.h>
+
+#include <sys/select.h>
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+
+#include <linux/virtio_balloon.h>
+
+static bool mem;
+static bool all;
+static const char *instance_name;
+
+static const char * const stat_usage[] = {
+       "lkvm stat [command] [--all] [-n name]",
+       NULL
+};
+
+static const struct option stat_options[] = {
+       OPT_GROUP("Commands options:"),
+       OPT_BOOLEAN('m', "memory", &mem, "Display memory statistics"),
+       OPT_GROUP("Instance options:"),
+       OPT_BOOLEAN('a', "all", &all, "All instances"),
+       OPT_STRING('n', "name", &instance_name, "name", "Instance name"),
+       OPT_END()
+};
+
+static void parse_stat_options(int argc, const char **argv)
+{
+       while (argc != 0) {
+               argc = parse_options(argc, argv, stat_options, stat_usage,
+                               PARSE_OPT_STOP_AT_NON_OPTION);
+               if (argc != 0)
+                       kvm_stat_help();
+       }
+}
+
+void kvm_stat_help(void)
+{
+       usage_with_options(stat_usage, stat_options);
+}
+
+static int do_memstat(const char *name, int sock)
+{
+       struct virtio_balloon_stat stats[VIRTIO_BALLOON_S_NR];
+       fd_set fdset;
+       struct timeval t = { .tv_sec = 1 };
+       int r;
+       u8 i;
+
+       FD_ZERO(&fdset);
+       FD_SET(sock, &fdset);
+       r = kvm_ipc__send(sock, KVM_IPC_STAT);
+       if (r < 0)
+               return r;
+
+       r = select(1, &fdset, NULL, NULL, &t);
+       if (r < 0) {
+               pr_err("Could not retrieve mem stats from %s", name);
+               return r;
+       }
+       r = read(sock, &stats, sizeof(stats));
+       if (r < 0)
+               return r;
+
+       printf("\n\n\t*** Guest memory statistics ***\n\n");
+       for (i = 0; i < VIRTIO_BALLOON_S_NR; i++) {
+               switch (stats[i].tag) {
+               case VIRTIO_BALLOON_S_SWAP_IN:
+                       printf("The amount of memory that has been swapped in (in bytes):");
+                       break;
+               case VIRTIO_BALLOON_S_SWAP_OUT:
+                       printf("The amount of memory that has been swapped out to disk (in bytes):");
+                       break;
+               case VIRTIO_BALLOON_S_MAJFLT:
+                       printf("The number of major page faults that have occurred:");
+                       break;
+               case VIRTIO_BALLOON_S_MINFLT:
+                       printf("The number of minor page faults that have occurred:");
+                       break;
+               case VIRTIO_BALLOON_S_MEMFREE:
+                       printf("The amount of memory not being used for any purpose (in bytes):");
+                       break;
+               case VIRTIO_BALLOON_S_MEMTOT:
+                       printf("The total amount of memory available (in bytes):");
+                       break;
+               }
+               printf("%llu\n", stats[i].val);
+       }
+       printf("\n");
+
+       return 0;
+}
+
+int kvm_cmd_stat(int argc, const char **argv, const char *prefix)
+{
+       int instance;
+       int r = 0;
+
+       parse_stat_options(argc, argv);
+
+       if (!mem)
+               usage_with_options(stat_usage, stat_options);
+
+       if (mem && all)
+               return kvm__enumerate_instances(do_memstat);
+
+       if (instance_name == NULL)
+               kvm_stat_help();
+
+       instance = kvm__get_sock_by_instance(instance_name);
+
+       if (instance <= 0)
+               die("Failed locating instance");
+
+       if (mem)
+               r = do_memstat(instance_name, instance);
+
+       close(instance);
+
+       return r;
+}
diff --git a/tools/kvm/builtin-stop.c b/tools/kvm/builtin-stop.c
new file mode 100644 (file)
index 0000000..6067630
--- /dev/null
@@ -0,0 +1,70 @@
+#include <kvm/util.h>
+#include <kvm/kvm-cmd.h>
+#include <kvm/builtin-stop.h>
+#include <kvm/kvm.h>
+#include <kvm/parse-options.h>
+#include <kvm/kvm-ipc.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+
+static bool all;
+static const char *instance_name;
+
+static const char * const stop_usage[] = {
+       "lkvm stop [--all] [-n name]",
+       NULL
+};
+
+static const struct option stop_options[] = {
+       OPT_GROUP("General options:"),
+       OPT_BOOLEAN('a', "all", &all, "Stop all instances"),
+       OPT_STRING('n', "name", &instance_name, "name", "Instance name"),
+       OPT_END()
+};
+
+static void parse_stop_options(int argc, const char **argv)
+{
+       while (argc != 0) {
+               argc = parse_options(argc, argv, stop_options, stop_usage,
+                               PARSE_OPT_STOP_AT_NON_OPTION);
+               if (argc != 0)
+                       kvm_stop_help();
+       }
+}
+
+void kvm_stop_help(void)
+{
+       usage_with_options(stop_usage, stop_options);
+}
+
+static int do_stop(const char *name, int sock)
+{
+       return kvm_ipc__send(sock, KVM_IPC_STOP);
+}
+
+int kvm_cmd_stop(int argc, const char **argv, const char *prefix)
+{
+       int instance;
+       int r;
+
+       parse_stop_options(argc, argv);
+
+       if (all)
+               return kvm__enumerate_instances(do_stop);
+
+       if (instance_name == NULL)
+               kvm_stop_help();
+
+       instance = kvm__get_sock_by_instance(instance_name);
+
+       if (instance <= 0)
+               die("Failed locating instance");
+
+       r = do_stop(instance_name, instance);
+
+       close(instance);
+
+       return r;
+}
diff --git a/tools/kvm/builtin-version.c b/tools/kvm/builtin-version.c
new file mode 100644 (file)
index 0000000..b8bb859
--- /dev/null
@@ -0,0 +1,15 @@
+#include <kvm/util.h>
+#include <kvm/kvm-cmd.h>
+#include <kvm/builtin-version.h>
+#include <kvm/kvm.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+
+int kvm_cmd_version(int argc, const char **argv, const char *prefix)
+{
+       printf("kvm tool %s\n", KVMTOOLS_VERSION);
+
+       return 0;
+}
diff --git a/tools/kvm/code16gcc.h b/tools/kvm/code16gcc.h
new file mode 100644 (file)
index 0000000..d93e480
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * code16gcc.h
+ *
+ * This file is -include'd when compiling 16-bit C code.
+ * Note: this asm() needs to be emitted before gcc emits any code.
+ * Depending on gcc version, this requires -fno-unit-at-a-time or
+ * -fno-toplevel-reorder.
+ *
+ * Hopefully gcc will eventually have a real -m16 option so we can
+ * drop this hack long term.
+ */
+
+#ifndef __ASSEMBLY__
+asm(".code16gcc");
+#endif
diff --git a/tools/kvm/command-list.txt b/tools/kvm/command-list.txt
new file mode 100644 (file)
index 0000000..d93597d
--- /dev/null
@@ -0,0 +1,15 @@
+#
+# List of known perf commands.
+# command name                 category [deprecated] [common]
+#
+lkvm-run                       mainporcelain common
+lkvm-setup                     mainporcelain common
+lkvm-pause                     common
+lkvm-resume                    common
+lkvm-version                   common
+lkvm-list                      common
+lkvm-debug                     common
+lkvm-balloon                   common
+lkvm-stop                      common
+lkvm-stat                      common
+lkvm-sandbox                   common
diff --git a/tools/kvm/config/feature-tests.mak b/tools/kvm/config/feature-tests.mak
new file mode 100644 (file)
index 0000000..4a81f56
--- /dev/null
@@ -0,0 +1,177 @@
+define SOURCE_HELLO
+#include <stdio.h>
+int main(void)
+{
+       return puts(\"hi\");
+}
+endef
+
+ifndef NO_DWARF
+define SOURCE_DWARF
+#include <dwarf.h>
+#include <elfutils/libdw.h>
+#include <elfutils/version.h>
+#ifndef _ELFUTILS_PREREQ
+#error
+#endif
+
+int main(void)
+{
+       Dwarf *dbg = dwarf_begin(0, DWARF_C_READ);
+       return (long)dbg;
+}
+endef
+endif
+
+define SOURCE_LIBELF
+#include <libelf.h>
+
+int main(void)
+{
+       Elf *elf = elf_begin(0, ELF_C_READ, 0);
+       return (long)elf;
+}
+endef
+
+define SOURCE_GLIBC
+#include <gnu/libc-version.h>
+
+int main(void)
+{
+       const char *version = gnu_get_libc_version();
+       return (long)version;
+}
+endef
+
+define SOURCE_ELF_MMAP
+#include <libelf.h>
+int main(void)
+{
+       Elf *elf = elf_begin(0, ELF_C_READ_MMAP, 0);
+       return (long)elf;
+}
+endef
+
+ifndef NO_NEWT
+define SOURCE_NEWT
+#include <newt.h>
+
+int main(void)
+{
+       newtInit();
+       newtCls();
+       return newtFinished();
+}
+endef
+endif
+
+ifndef NO_LIBPERL
+define SOURCE_PERL_EMBED
+#include <EXTERN.h>
+#include <perl.h>
+
+int main(void)
+{
+perl_alloc();
+return 0;
+}
+endef
+endif
+
+ifndef NO_LIBPYTHON
+define SOURCE_PYTHON_VERSION
+#include <Python.h>
+#if PY_VERSION_HEX >= 0x03000000
+       #error
+#endif
+int main(void){}
+endef
+define SOURCE_PYTHON_EMBED
+#include <Python.h>
+int main(void)
+{
+       Py_Initialize();
+       return 0;
+}
+endef
+endif
+
+define SOURCE_BFD
+#include <bfd.h>
+
+int main(void)
+{
+       bfd_demangle(0, 0, 0);
+       return 0;
+}
+endef
+
+define SOURCE_CPLUS_DEMANGLE
+extern char *cplus_demangle(const char *, int);
+
+int main(void)
+{
+       cplus_demangle(0, 0);
+       return 0;
+}
+endef
+
+define SOURCE_STRLCPY
+#include <stdlib.h>
+extern size_t strlcpy(char *dest, const char *src, size_t size);
+
+int main(void)
+{
+       strlcpy(NULL, NULL, 0);
+       return 0;
+}
+endef
+
+define SOURCE_VNCSERVER
+#include <rfb/rfb.h>
+
+int main(void)
+{
+       rfbIsActive((void *)0);
+       return 0;
+}
+endef
+
+define SOURCE_SDL
+#include <SDL/SDL.h>
+
+int main(void)
+{
+       SDL_Init(SDL_INIT_VIDEO);
+       return 0;
+}
+endef
+
+define SOURCE_ZLIB
+#include <zlib.h>
+
+int main(void)
+{
+       inflateInit2(NULL, 0);
+       return 0;
+}
+endef
+
+define SOURCE_AIO
+#include <libaio.h>
+
+int main(void)
+{
+       io_setup(0, NULL);
+       return 0;
+}
+endef
+
+define SOURCE_STATIC
+#include <stdlib.h>
+
+int main(void)
+{
+       return 0;
+}
+endef
diff --git a/tools/kvm/config/utilities.mak b/tools/kvm/config/utilities.mak
new file mode 100644 (file)
index 0000000..a70963b
--- /dev/null
@@ -0,0 +1,196 @@
+# This allows us to work with the newline character:
+define newline
+
+
+endef
+newline := $(newline)
+
+# nl-escape
+#
+# Usage: escape = $(call nl-escape[,escape])
+#
+# This is used as the common way to specify
+# what should replace a newline when escaping
+# newlines; the default is a bizarre string.
+#
+nl-escape = $(or $(1),m822df3020w6a44id34bt574ctac44eb9f4n)
+
+# escape-nl
+#
+# Usage: escaped-text = $(call escape-nl,text[,escape])
+#
+# GNU make's $(shell ...) function converts to a
+# single space each newline character in the output
+# produced during the expansion; this may not be
+# desirable.
+#
+# The only solution is to change each newline into
+# something that won't be converted, so that the
+# information can be recovered later with
+# $(call unescape-nl...)
+#
+escape-nl = $(subst $(newline),$(call nl-escape,$(2)),$(1))
+
+# unescape-nl
+#
+# Usage: text = $(call unescape-nl,escaped-text[,escape])
+#
+# See escape-nl.
+#
+unescape-nl = $(subst $(call nl-escape,$(2)),$(newline),$(1))
+
+# shell-escape-nl
+#
+# Usage: $(shell some-command | $(call shell-escape-nl[,escape]))
+#
+# Use this to escape newlines from within a shell call;
+# the default escape is a bizarre string.
+#
+# NOTE: The escape is used directly as a string constant
+#       in an `awk' program that is delimited by shell
+#       single-quotes, so be wary of the characters
+#       that are chosen.
+#
+define shell-escape-nl
+awk 'NR==1 {t=$$0} NR>1 {t=t "$(nl-escape)" $$0} END {printf t}'
+endef
+
+# shell-unescape-nl
+#
+# Usage: $(shell some-command | $(call shell-unescape-nl[,escape]))
+#
+# Use this to unescape newlines from within a shell call;
+# the default escape is a bizarre string.
+#
+# NOTE: The escape is used directly as an extended regular
+#       expression constant in an `awk' program that is
+#       delimited by shell single-quotes, so be wary
+#       of the characters that are chosen.
+#
+# (The bash shell has a bug where `{gsub(...),...}' is
+#  misinterpreted as a brace expansion; this can be
+#  overcome by putting a space between `{' and `gsub').
+#
+define shell-unescape-nl
+awk 'NR==1 {t=$$0} NR>1 {t=t "\n" $$0} END { gsub(/$(nl-escape)/,"\n",t); printf t }'
+endef
+
+# escape-for-shell-sq
+#
+# Usage: embeddable-text = $(call escape-for-shell-sq,text)
+#
+# This function produces text that is suitable for
+# embedding in a shell string that is delimited by
+# single-quotes.
+#
+escape-for-shell-sq =  $(subst ','\'',$(1))
+
+# shell-sq
+#
+# Usage: single-quoted-and-escaped-text = $(call shell-sq,text)
+#
+shell-sq = '$(escape-for-shell-sq)'
+
+# shell-wordify
+#
+# Usage: wordified-text = $(call shell-wordify,text)
+#
+# For instance:
+#
+#  |define text
+#  |hello
+#  |world
+#  |endef
+#  |
+#  |target:
+#  |   echo $(call shell-wordify,$(text))
+#
+# At least GNU make gets confused by expanding a newline
+# within the context of a command line of a makefile rule
+# (this is in constrast to a `$(shell ...)' function call,
+# which can handle it just fine).
+#
+# This function avoids the problem by producing a string
+# that works as a shell word, regardless of whether or
+# not it contains a newline.
+#
+# If the text to be wordified contains a newline, then
+# an intrictate shell command substitution is constructed
+# to render the text as a single line; when the shell
+# processes the resulting escaped text, it transforms
+# it into the original unescaped text.
+#
+# If the text does not contain a newline, then this function
+# produces the same results as the `$(shell-sq)' function.
+#
+shell-wordify = $(if $(findstring $(newline),$(1)),$(_sw-esc-nl),$(shell-sq))
+define _sw-esc-nl
+"$$(echo $(call escape-nl,$(shell-sq),$(2)) | $(call shell-unescape-nl,$(2)))"
+endef
+
+# is-absolute
+#
+# Usage: bool-value = $(call is-absolute,path)
+#
+is-absolute = $(shell echo $(shell-sq) | grep ^/ -q && echo y)
+
+# lookup
+#
+# Usage: absolute-executable-path-or-empty = $(call lookup,path)
+#
+# (It's necessary to use `sh -c' because GNU make messes up by
+#  trying too hard and getting things wrong).
+#
+lookup = $(call unescape-nl,$(shell sh -c $(_l-sh)))
+_l-sh = $(call shell-sq,command -v $(shell-sq) | $(call shell-escape-nl,))
+
+# is-executable
+#
+# Usage: bool-value = $(call is-executable,path)
+#
+# (It's necessary to use `sh -c' because GNU make messes up by
+#  trying too hard and getting things wrong).
+#
+is-executable = $(call _is-executable-helper,$(shell-sq))
+_is-executable-helper = $(shell sh -c $(_is-executable-sh))
+_is-executable-sh = $(call shell-sq,test -f $(1) -a -x $(1) && echo y)
+
+# get-executable
+#
+# Usage: absolute-executable-path-or-empty = $(call get-executable,path)
+#
+# The goal is to get an absolute path for an executable;
+# the `command -v' is defined by POSIX, but it's not
+# necessarily very portable, so it's only used if
+# relative path resolution is requested, as determined
+# by the presence of a leading `/'.
+#
+get-executable = $(if $(1),$(if $(is-absolute),$(_ge-abspath),$(lookup)))
+_ge-abspath = $(if $(is-executable),$(1))
+
+# get-supplied-or-default-executable
+#
+# Usage: absolute-executable-path-or-empty = $(call get-executable-or-default,variable,default)
+#
+define get-executable-or-default
+$(if $($(1)),$(call _ge_attempt,$($(1)),$(1)),$(call _ge_attempt,$(2)))
+endef
+_ge_attempt = $(or $(get-executable),$(_gea_warn),$(call _gea_err,$(2)))
+_gea_warn = $(warning The path '$(1)' is not executable.)
+_gea_err  = $(if $(1),$(error Please set '$(1)' appropriately))
+
+# try-cc
+# Usage: option = $(call try-cc, source-to-build, cc-options)
+try-cc = $(shell sh -c                                           \
+       'TMP="$(OUTPUT)$(TMPOUT).$$$$";                           \
+        echo "$(1)" |                                            \
+        $(CC) -x c - $(2) -o "$$TMP" > /dev/null 2>&1 && echo y; \
+        rm -f "$$TMP"')
+
+# try-build
+# Usage: option = $(call try-build, source-to-build, cc-options, link-options)
+try-build = $(shell sh -c                                                      \
+       'TMP="$(OUTPUT)$(TMPOUT).$$$$";                                         \
+       echo "$(1)" |                                                           \
+       $(CC) -x c - $(2) $(3) -o "$$TMP" > /dev/null 2>&1 && echo y;           \
+       rm -f "$$TMP"')
diff --git a/tools/kvm/disk/blk.c b/tools/kvm/disk/blk.c
new file mode 100644 (file)
index 0000000..37581d3
--- /dev/null
@@ -0,0 +1,76 @@
+#include "kvm/disk-image.h"
+
+#include <linux/err.h>
+#include <mntent.h>
+
+/*
+ * raw image and blk dev are similar, so reuse raw image ops.
+ */
+static struct disk_image_operations blk_dev_ops = {
+       .read   = raw_image__read,
+       .write  = raw_image__write,
+};
+
+static bool is_mounted(struct stat *st)
+{
+       struct stat st_buf;
+       struct mntent *mnt;
+       FILE *f;
+
+       f = setmntent("/proc/mounts", "r");
+       if (!f)
+               return false;
+
+       while ((mnt = getmntent(f)) != NULL) {
+               if (stat(mnt->mnt_fsname, &st_buf) == 0 &&
+                   S_ISBLK(st_buf.st_mode) && st->st_rdev == st_buf.st_rdev) {
+                       fclose(f);
+                       return true;
+               }
+       }
+
+       fclose(f);
+       return false;
+}
+
+struct disk_image *blkdev__probe(const char *filename, int flags, struct stat *st)
+{
+       struct disk_image *disk;
+       int fd, r;
+       u64 size;
+
+       if (!S_ISBLK(st->st_mode))
+               return ERR_PTR(-EINVAL);
+
+       if (is_mounted(st)) {
+               pr_err("Block device %s is already mounted! Unmount before use.",
+                      filename);
+               return ERR_PTR(-EINVAL);
+       }
+
+       /*
+        * Be careful! We are opening host block device!
+        * Open it readonly since we do not want to break user's data on disk.
+        */
+       fd = open(filename, flags);
+       if (fd < 0)
+               return ERR_PTR(fd);
+
+       if (ioctl(fd, BLKGETSIZE64, &size) < 0) {
+               r = -errno;
+               close(fd);
+               return ERR_PTR(r);
+       }
+
+       /*
+        * FIXME: This will not work on 32-bit host because we can not
+        * mmap large disk. There is not enough virtual address space
+        * in 32-bit host. However, this works on 64-bit host.
+        */
+       disk = disk_image__new(fd, size, &blk_dev_ops, DISK_IMAGE_REGULAR);
+#ifdef CONFIG_HAS_AIO
+               if (!IS_ERR_OR_NULL(disk))
+                       disk->async = 1;
+#endif
+       return disk;
+}
diff --git a/tools/kvm/disk/core.c b/tools/kvm/disk/core.c
new file mode 100644 (file)
index 0000000..b313b28
--- /dev/null
@@ -0,0 +1,354 @@
+#include "kvm/disk-image.h"
+#include "kvm/qcow.h"
+#include "kvm/virtio-blk.h"
+#include "kvm/kvm.h"
+
+#include <linux/err.h>
+#include <sys/eventfd.h>
+#include <sys/poll.h>
+
+#define AIO_MAX 256
+
+int debug_iodelay;
+
+static int disk_image__close(struct disk_image *disk);
+
+int disk_img_name_parser(const struct option *opt, const char *arg, int unset)
+{
+       const char *cur;
+       char *sep;
+       struct kvm *kvm = opt->ptr;
+
+       if (kvm->cfg.image_count >= MAX_DISK_IMAGES)
+               die("Currently only 4 images are supported");
+
+       kvm->cfg.disk_image[kvm->cfg.image_count].filename = arg;
+       cur = arg;
+
+       if (strncmp(arg, "scsi:", 5) == 0) {
+               sep = strstr(arg, ":");
+               if (sep)
+                       kvm->cfg.disk_image[kvm->cfg.image_count].wwpn = sep + 1;
+               sep = strstr(sep + 1, ":");
+               if (sep) {
+                       *sep = 0;
+                       kvm->cfg.disk_image[kvm->cfg.image_count].tpgt = sep + 1;
+               }
+               cur = sep + 1;
+       }
+
+       do {
+               sep = strstr(cur, ",");
+               if (sep) {
+                       if (strncmp(sep + 1, "ro", 2) == 0)
+                               kvm->cfg.disk_image[kvm->cfg.image_count].readonly = true;
+                       else if (strncmp(sep + 1, "direct", 6) == 0)
+                               kvm->cfg.disk_image[kvm->cfg.image_count].direct = true;
+                       *sep = 0;
+                       cur = sep + 1;
+               }
+       } while (sep);
+
+       kvm->cfg.image_count++;
+
+       return 0;
+}
+
+#ifdef CONFIG_HAS_AIO
+static void *disk_image__thread(void *param)
+{
+       struct disk_image *disk = param;
+       struct io_event event[AIO_MAX];
+       struct timespec notime = {0};
+       int nr, i;
+       u64 dummy;
+
+       while (read(disk->evt, &dummy, sizeof(dummy)) > 0) {
+               nr = io_getevents(disk->ctx, 1, ARRAY_SIZE(event), event, &notime);
+               for (i = 0; i < nr; i++)
+                       disk->disk_req_cb(event[i].data, event[i].res);
+       }
+
+       return NULL;
+}
+#endif
+
+struct disk_image *disk_image__new(int fd, u64 size,
+                                  struct disk_image_operations *ops,
+                                  int use_mmap)
+{
+       struct disk_image *disk;
+       int r;
+
+       disk = malloc(sizeof *disk);
+       if (!disk)
+               return ERR_PTR(-ENOMEM);
+
+       *disk = (struct disk_image) {
+               .fd     = fd,
+               .size   = size,
+               .ops    = ops,
+       };
+
+       if (use_mmap == DISK_IMAGE_MMAP) {
+               /*
+                * The write to disk image will be discarded
+                */
+               disk->priv = mmap(NULL, size, PROT_RW, MAP_PRIVATE | MAP_NORESERVE, fd, 0);
+               if (disk->priv == MAP_FAILED) {
+                       r = -errno;
+                       free(disk);
+                       return ERR_PTR(r);
+               }
+       }
+
+#ifdef CONFIG_HAS_AIO
+       if (disk) {
+               pthread_t thread;
+
+               disk->evt = eventfd(0, 0);
+               io_setup(AIO_MAX, &disk->ctx);
+               r = pthread_create(&thread, NULL, disk_image__thread, disk);
+               if (r) {
+                       r = -errno;
+                       free(disk);
+                       return ERR_PTR(r);
+               }
+       }
+#endif
+       return disk;
+}
+
+static struct disk_image *disk_image__open(const char *filename, bool readonly, bool direct)
+{
+       struct disk_image *disk;
+       struct stat st;
+       int fd, flags;
+
+       if (readonly)
+               flags = O_RDONLY;
+       else
+               flags = O_RDWR;
+       if (direct)
+               flags |= O_DIRECT;
+
+       if (stat(filename, &st) < 0)
+               return ERR_PTR(-errno);
+
+       /* blk device ?*/
+       disk = blkdev__probe(filename, flags, &st);
+       if (!IS_ERR_OR_NULL(disk))
+               return disk;
+
+       fd = open(filename, flags);
+       if (fd < 0)
+               return ERR_PTR(fd);
+
+       /* qcow image ?*/
+       disk = qcow_probe(fd, true);
+       if (!IS_ERR_OR_NULL(disk)) {
+               pr_warning("Forcing read-only support for QCOW");
+               return disk;
+       }
+
+       /* raw image ?*/
+       disk = raw_image__probe(fd, &st, readonly);
+       if (!IS_ERR_OR_NULL(disk))
+               return disk;
+
+       if (close(fd) < 0)
+               pr_warning("close() failed");
+
+       return ERR_PTR(-ENOSYS);
+}
+
+static struct disk_image **disk_image__open_all(struct kvm *kvm)
+{
+       struct disk_image **disks;
+       const char *filename;
+       const char *wwpn;
+       const char *tpgt;
+       bool readonly;
+       bool direct;
+       void *err;
+       int i;
+       struct disk_image_params *params = (struct disk_image_params *)&kvm->cfg.disk_image;
+       int count = kvm->cfg.image_count;
+
+       if (!count)
+               return ERR_PTR(-EINVAL);
+       if (count > MAX_DISK_IMAGES)
+               return ERR_PTR(-ENOSPC);
+
+       disks = calloc(count, sizeof(*disks));
+       if (!disks)
+               return ERR_PTR(-ENOMEM);
+
+       for (i = 0; i < count; i++) {
+               filename = params[i].filename;
+               readonly = params[i].readonly;
+               direct = params[i].direct;
+               wwpn = params[i].wwpn;
+               tpgt = params[i].tpgt;
+
+               if (wwpn) {
+                       disks[i] = malloc(sizeof(struct disk_image));
+                       if (!disks[i])
+                               return ERR_PTR(-ENOMEM);
+                       disks[i]->wwpn = wwpn;
+                       disks[i]->tpgt = tpgt;
+                       continue;
+               }
+
+               if (!filename)
+                       continue;
+
+               disks[i] = disk_image__open(filename, readonly, direct);
+               if (IS_ERR_OR_NULL(disks[i])) {
+                       pr_err("Loading disk image '%s' failed", filename);
+                       err = disks[i];
+                       goto error;
+               }
+               disks[i]->debug_iodelay = kvm->cfg.debug_iodelay;
+       }
+
+       return disks;
+error:
+       for (i = 0; i < count; i++)
+               if (!IS_ERR_OR_NULL(disks[i]))
+                       disk_image__close(disks[i]);
+
+       free(disks);
+       return err;
+}
+
+int disk_image__flush(struct disk_image *disk)
+{
+       if (disk->ops->flush)
+               return disk->ops->flush(disk);
+
+       return fsync(disk->fd);
+}
+
+static int disk_image__close(struct disk_image *disk)
+{
+       /* If there was no disk image then there's nothing to do: */
+       if (!disk)
+               return 0;
+
+       if (disk->ops->close)
+               return disk->ops->close(disk);
+
+       if (close(disk->fd) < 0)
+               pr_warning("close() failed");
+
+       free(disk);
+
+       return 0;
+}
+
+static int disk_image__close_all(struct disk_image **disks, int count)
+{
+       while (count)
+               disk_image__close(disks[--count]);
+
+       free(disks);
+
+       return 0;
+}
+
+/*
+ * Fill iov with disk data, starting from sector 'sector'.
+ * Return amount of bytes read.
+ */
+ssize_t disk_image__read(struct disk_image *disk, u64 sector,
+                        const struct iovec *iov, int iovcount, void *param)
+{
+       ssize_t total = 0;
+
+       if (debug_iodelay)
+               msleep(debug_iodelay);
+
+       if (disk->ops->read) {
+               total = disk->ops->read(disk, sector, iov, iovcount, param);
+               if (total < 0) {
+                       pr_info("disk_image__read error: total=%ld\n", (long)total);
+                       return total;
+               }
+       }
+
+       if (!disk->async && disk->disk_req_cb)
+               disk->disk_req_cb(param, total);
+
+       return total;
+}
+
+/*
+ * Write iov to disk, starting from sector 'sector'.
+ * Return amount of bytes written.
+ */
+ssize_t disk_image__write(struct disk_image *disk, u64 sector,
+                         const struct iovec *iov, int iovcount, void *param)
+{
+       ssize_t total = 0;
+
+       if (debug_iodelay)
+               msleep(debug_iodelay);
+
+       if (disk->ops->write) {
+               /*
+                * Try writev based operation first
+                */
+
+               total = disk->ops->write(disk, sector, iov, iovcount, param);
+               if (total < 0) {
+                       pr_info("disk_image__write error: total=%ld\n", (long)total);
+                       return total;
+               }
+       } else {
+               /* Do nothing */
+       }
+
+       if (!disk->async && disk->disk_req_cb)
+               disk->disk_req_cb(param, total);
+
+       return total;
+}
+
+ssize_t disk_image__get_serial(struct disk_image *disk, void *buffer, ssize_t *len)
+{
+       struct stat st;
+       int r;
+
+       r = fstat(disk->fd, &st);
+       if (r)
+               return r;
+
+       *len = snprintf(buffer, *len, "%llu%llu%llu",
+                       (u64)st.st_dev, (u64)st.st_rdev, (u64)st.st_ino);
+       return *len;
+}
+
+void disk_image__set_callback(struct disk_image *disk,
+                             void (*disk_req_cb)(void *param, long len))
+{
+       disk->disk_req_cb = disk_req_cb;
+}
+
+int disk_image__init(struct kvm *kvm)
+{
+       if (kvm->cfg.image_count) {
+               kvm->disks = disk_image__open_all(kvm);
+               if (IS_ERR(kvm->disks))
+                       return PTR_ERR(kvm->disks);
+       }
+
+       return 0;
+}
+dev_base_init(disk_image__init);
+
+int disk_image__exit(struct kvm *kvm)
+{
+       return disk_image__close_all(kvm->disks, kvm->nr_disks);
+}
+dev_base_exit(disk_image__exit);
diff --git a/tools/kvm/disk/qcow.c b/tools/kvm/disk/qcow.c
new file mode 100644 (file)
index 0000000..ee2992e
--- /dev/null
@@ -0,0 +1,1529 @@
+#include "kvm/qcow.h"
+
+#include "kvm/disk-image.h"
+#include "kvm/read-write.h"
+#include "kvm/mutex.h"
+#include "kvm/util.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#ifdef CONFIG_HAS_ZLIB
+#include <zlib.h>
+#endif
+
+#include <linux/err.h>
+#include <linux/byteorder.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+static int update_cluster_refcount(struct qcow *q, u64 clust_idx, u16 append);
+static int qcow_write_refcount_table(struct qcow *q);
+static u64 qcow_alloc_clusters(struct qcow *q, u64 size, int update_ref);
+static void  qcow_free_clusters(struct qcow *q, u64 clust_start, u64 size);
+
+static inline int qcow_pwrite_sync(int fd,
+       void *buf, size_t count, off_t offset)
+{
+       if (pwrite_in_full(fd, buf, count, offset) < 0)
+               return -1;
+
+       return fdatasync(fd);
+}
+
+static int l2_table_insert(struct rb_root *root, struct qcow_l2_table *new)
+{
+       struct rb_node **link = &(root->rb_node), *parent = NULL;
+       u64 offset = new->offset;
+
+       /* search the tree */
+       while (*link) {
+               struct qcow_l2_table *t;
+
+               t = rb_entry(*link, struct qcow_l2_table, node);
+               if (!t)
+                       goto error;
+
+               parent = *link;
+
+               if (t->offset > offset)
+                       link = &(*link)->rb_left;
+               else if (t->offset < offset)
+                       link = &(*link)->rb_right;
+               else
+                       goto out;
+       }
+
+       /* add new node */
+       rb_link_node(&new->node, parent, link);
+       rb_insert_color(&new->node, root);
+out:
+       return 0;
+error:
+       return -1;
+}
+
+static struct qcow_l2_table *l2_table_lookup(struct rb_root *root, u64 offset)
+{
+       struct rb_node *link = root->rb_node;
+
+       while (link) {
+               struct qcow_l2_table *t;
+
+               t = rb_entry(link, struct qcow_l2_table, node);
+               if (!t)
+                       goto out;
+
+               if (t->offset > offset)
+                       link = link->rb_left;
+               else if (t->offset < offset)
+                       link = link->rb_right;
+               else
+                       return t;
+       }
+out:
+       return NULL;
+}
+
+static void l1_table_free_cache(struct qcow_l1_table *l1t)
+{
+       struct rb_root *r = &l1t->root;
+       struct list_head *pos, *n;
+       struct qcow_l2_table *t;
+
+       list_for_each_safe(pos, n, &l1t->lru_list) {
+               /* Remove cache table from the list and RB tree */
+               list_del(pos);
+               t = list_entry(pos, struct qcow_l2_table, list);
+               rb_erase(&t->node, r);
+
+               /* Free the cached node */
+               free(t);
+       }
+}
+
+static int qcow_l2_cache_write(struct qcow *q, struct qcow_l2_table *c)
+{
+       struct qcow_header *header = q->header;
+       u64 size;
+
+       if (!c->dirty)
+               return 0;
+
+       size = 1 << header->l2_bits;
+
+       if (qcow_pwrite_sync(q->fd, c->table,
+               size * sizeof(u64), c->offset) < 0)
+               return -1;
+
+       c->dirty = 0;
+
+       return 0;
+}
+
+static int cache_table(struct qcow *q, struct qcow_l2_table *c)
+{
+       struct qcow_l1_table *l1t = &q->table;
+       struct rb_root *r = &l1t->root;
+       struct qcow_l2_table *lru;
+
+       if (l1t->nr_cached == MAX_CACHE_NODES) {
+               /*
+                * The node at the head of the list is least recently used
+                * node. Remove it from the list and replaced with a new node.
+                */
+               lru = list_first_entry(&l1t->lru_list, struct qcow_l2_table, list);
+
+               /* Remove the node from the cache */
+               rb_erase(&lru->node, r);
+               list_del_init(&lru->list);
+               l1t->nr_cached--;
+
+               /* Free the LRUed node */
+               free(lru);
+       }
+
+       /* Add new node in RB Tree: Helps in searching faster */
+       if (l2_table_insert(r, c) < 0)
+               goto error;
+
+       /* Add in LRU replacement list */
+       list_add_tail(&c->list, &l1t->lru_list);
+       l1t->nr_cached++;
+
+       return 0;
+error:
+       return -1;
+}
+
+static struct qcow_l2_table *l2_table_search(struct qcow *q, u64 offset)
+{
+       struct qcow_l1_table *l1t = &q->table;
+       struct qcow_l2_table *l2t;
+
+       l2t = l2_table_lookup(&l1t->root, offset);
+       if (!l2t)
+               return NULL;
+
+       /* Update the LRU state, by moving the searched node to list tail */
+       list_move_tail(&l2t->list, &l1t->lru_list);
+
+       return l2t;
+}
+
+/* Allocates a new node for caching L2 table */
+static struct qcow_l2_table *new_cache_table(struct qcow *q, u64 offset)
+{
+       struct qcow_header *header = q->header;
+       struct qcow_l2_table *c;
+       u64 l2t_sz;
+       u64 size;
+
+       l2t_sz = 1 << header->l2_bits;
+       size   = sizeof(*c) + l2t_sz * sizeof(u64);
+       c      = calloc(1, size);
+       if (!c)
+               goto out;
+
+       c->offset = offset;
+       RB_CLEAR_NODE(&c->node);
+       INIT_LIST_HEAD(&c->list);
+out:
+       return c;
+}
+
+static inline u64 get_l1_index(struct qcow *q, u64 offset)
+{
+       struct qcow_header *header = q->header;
+
+       return offset >> (header->l2_bits + header->cluster_bits);
+}
+
+static inline u64 get_l2_index(struct qcow *q, u64 offset)
+{
+       struct qcow_header *header = q->header;
+
+       return (offset >> (header->cluster_bits)) & ((1 << header->l2_bits)-1);
+}
+
+static inline u64 get_cluster_offset(struct qcow *q, u64 offset)
+{
+       struct qcow_header *header = q->header;
+
+       return offset & ((1 << header->cluster_bits)-1);
+}
+
+static struct qcow_l2_table *qcow_read_l2_table(struct qcow *q, u64 offset)
+{
+       struct qcow_header *header = q->header;
+       struct qcow_l2_table *l2t;
+       u64 size;
+
+       size = 1 << header->l2_bits;
+
+       /* search an entry for offset in cache */
+       l2t = l2_table_search(q, offset);
+       if (l2t)
+               return l2t;
+
+       /* allocate new node for caching l2 table */
+       l2t = new_cache_table(q, offset);
+       if (!l2t)
+               goto error;
+
+       /* table not cached: read from the disk */
+       if (pread_in_full(q->fd, l2t->table, size * sizeof(u64), offset) < 0)
+               goto error;
+
+       /* cache the table */
+       if (cache_table(q, l2t) < 0)
+               goto error;
+
+       return l2t;
+error:
+       free(l2t);
+       return NULL;
+}
+
+static int qcow_decompress_buffer(u8 *out_buf, int out_buf_size,
+       const u8 *buf, int buf_size)
+{
+#ifdef CONFIG_HAS_ZLIB
+       z_stream strm1, *strm = &strm1;
+       int ret, out_len;
+
+       memset(strm, 0, sizeof(*strm));
+
+       strm->next_in   = (u8 *)buf;
+       strm->avail_in  = buf_size;
+       strm->next_out  = out_buf;
+       strm->avail_out = out_buf_size;
+
+       ret = inflateInit2(strm, -12);
+       if (ret != Z_OK)
+               return -1;
+
+       ret = inflate(strm, Z_FINISH);
+       out_len = strm->next_out - out_buf;
+       if ((ret != Z_STREAM_END && ret != Z_BUF_ERROR) ||
+               out_len != out_buf_size) {
+               inflateEnd(strm);
+               return -1;
+       }
+
+       inflateEnd(strm);
+       return 0;
+#else
+       return -1;
+#endif
+}
+
+static ssize_t qcow1_read_cluster(struct qcow *q, u64 offset,
+       void *dst, u32 dst_len)
+{
+       struct qcow_header *header = q->header;
+       struct qcow_l1_table *l1t = &q->table;
+       struct qcow_l2_table *l2t;
+       u64 clust_offset;
+       u64 clust_start;
+       u64 l2t_offset;
+       size_t length;
+       u64 l2t_size;
+       u64 l1_idx;
+       u64 l2_idx;
+       int coffset;
+       int csize;
+
+       l1_idx = get_l1_index(q, offset);
+       if (l1_idx >= l1t->table_size)
+               return -1;
+
+       clust_offset = get_cluster_offset(q, offset);
+       if (clust_offset >= q->cluster_size)
+               return -1;
+
+       length = q->cluster_size - clust_offset;
+       if (length > dst_len)
+               length = dst_len;
+
+       mutex_lock(&q->mutex);
+
+       l2t_offset = be64_to_cpu(l1t->l1_table[l1_idx]);
+       if (!l2t_offset)
+               goto zero_cluster;
+
+       l2t_size = 1 << header->l2_bits;
+
+       /* read and cache level 2 table */
+       l2t = qcow_read_l2_table(q, l2t_offset);
+       if (!l2t)
+               goto out_error;
+
+       l2_idx = get_l2_index(q, offset);
+       if (l2_idx >= l2t_size)
+               goto out_error;
+
+       clust_start = be64_to_cpu(l2t->table[l2_idx]);
+       if (clust_start & QCOW1_OFLAG_COMPRESSED) {
+               coffset = clust_start & q->cluster_offset_mask;
+               csize   = clust_start >> (63 - q->header->cluster_bits);
+               csize   &= (q->cluster_size - 1);
+
+               if (pread_in_full(q->fd, q->cluster_data, csize,
+                                 coffset) < 0)
+                       goto out_error;
+
+               if (qcow_decompress_buffer(q->cluster_cache, q->cluster_size,
+                                       q->cluster_data, csize) < 0)
+                       goto out_error;
+
+               memcpy(dst, q->cluster_cache + clust_offset, length);
+               mutex_unlock(&q->mutex);
+       } else {
+               if (!clust_start)
+                       goto zero_cluster;
+
+               mutex_unlock(&q->mutex);
+
+               if (pread_in_full(q->fd, dst, length,
+                                 clust_start + clust_offset) < 0)
+                       return -1;
+       }
+
+       return length;
+
+zero_cluster:
+       mutex_unlock(&q->mutex);
+       memset(dst, 0, length);
+       return length;
+
+out_error:
+       mutex_unlock(&q->mutex);
+       length = -1;
+       return -1;
+}
+
+static ssize_t qcow2_read_cluster(struct qcow *q, u64 offset,
+       void *dst, u32 dst_len)
+{
+       struct qcow_header *header = q->header;
+       struct qcow_l1_table *l1t = &q->table;
+       struct qcow_l2_table *l2t;
+       u64 clust_offset;
+       u64 clust_start;
+       u64 l2t_offset;
+       size_t length;
+       u64 l2t_size;
+       u64 l1_idx;
+       u64 l2_idx;
+       int coffset;
+       int sector_offset;
+       int nb_csectors;
+       int csize;
+
+       l1_idx = get_l1_index(q, offset);
+       if (l1_idx >= l1t->table_size)
+               return -1;
+
+       clust_offset = get_cluster_offset(q, offset);
+       if (clust_offset >= q->cluster_size)
+               return -1;
+
+       length = q->cluster_size - clust_offset;
+       if (length > dst_len)
+               length = dst_len;
+
+       mutex_lock(&q->mutex);
+
+       l2t_offset = be64_to_cpu(l1t->l1_table[l1_idx]);
+
+       l2t_offset &= ~QCOW2_OFLAG_COPIED;
+       if (!l2t_offset)
+               goto zero_cluster;
+
+       l2t_size = 1 << header->l2_bits;
+
+       /* read and cache level 2 table */
+       l2t = qcow_read_l2_table(q, l2t_offset);
+       if (!l2t)
+               goto out_error;
+
+       l2_idx = get_l2_index(q, offset);
+       if (l2_idx >= l2t_size)
+               goto out_error;
+
+       clust_start = be64_to_cpu(l2t->table[l2_idx]);
+       if (clust_start & QCOW2_OFLAG_COMPRESSED) {
+               coffset = clust_start & q->cluster_offset_mask;
+               nb_csectors = ((clust_start >> q->csize_shift)
+                       & q->csize_mask) + 1;
+               sector_offset = coffset & (SECTOR_SIZE - 1);
+               csize = nb_csectors * SECTOR_SIZE - sector_offset;
+
+               if (pread_in_full(q->fd, q->cluster_data,
+                                 nb_csectors * SECTOR_SIZE,
+                                 coffset & ~(SECTOR_SIZE - 1)) < 0) {
+                       goto out_error;
+               }
+
+               if (qcow_decompress_buffer(q->cluster_cache, q->cluster_size,
+                                       q->cluster_data + sector_offset,
+                                       csize) < 0) {
+                       goto out_error;
+               }
+
+               memcpy(dst, q->cluster_cache + clust_offset, length);
+               mutex_unlock(&q->mutex);
+       } else {
+               clust_start &= QCOW2_OFFSET_MASK;
+               if (!clust_start)
+                       goto zero_cluster;
+
+               mutex_unlock(&q->mutex);
+
+               if (pread_in_full(q->fd, dst, length,
+                                 clust_start + clust_offset) < 0)
+                       return -1;
+       }
+
+       return length;
+
+zero_cluster:
+       mutex_unlock(&q->mutex);
+       memset(dst, 0, length);
+       return length;
+
+out_error:
+       mutex_unlock(&q->mutex);
+       length = -1;
+       return -1;
+}
+
+static ssize_t qcow_read_sector_single(struct disk_image *disk, u64 sector,
+       void *dst, u32 dst_len)
+{
+       struct qcow *q = disk->priv;
+       struct qcow_header *header = q->header;
+       u32 nr_read;
+       u64 offset;
+       char *buf;
+       u32 nr;
+
+       buf = dst;
+       nr_read = 0;
+
+       while (nr_read < dst_len) {
+               offset = sector << SECTOR_SHIFT;
+               if (offset >= header->size)
+                       return -1;
+
+               if (q->version == QCOW1_VERSION)
+                       nr = qcow1_read_cluster(q, offset, buf,
+                               dst_len - nr_read);
+               else
+                       nr = qcow2_read_cluster(q, offset, buf,
+                               dst_len - nr_read);
+
+               if (nr <= 0)
+                       return -1;
+
+               nr_read += nr;
+               buf     += nr;
+               sector  += (nr >> SECTOR_SHIFT);
+       }
+
+       return dst_len;
+}
+
+static ssize_t qcow_read_sector(struct disk_image *disk, u64 sector,
+                               const struct iovec *iov, int iovcount, void *param)
+{
+       ssize_t nr, total = 0;
+
+       while (iovcount--) {
+               nr = qcow_read_sector_single(disk, sector, iov->iov_base, iov->iov_len);
+               if (nr != (ssize_t)iov->iov_len) {
+                       pr_info("qcow_read_sector error: nr=%ld iov_len=%ld\n", (long)nr, (long)iov->iov_len);
+                       return -1;
+               }
+
+               sector += iov->iov_len >> SECTOR_SHIFT;
+               total += nr;
+               iov++;
+       }
+
+       return total;
+}
+
+static void refcount_table_free_cache(struct qcow_refcount_table *rft)
+{
+       struct rb_root *r = &rft->root;
+       struct list_head *pos, *n;
+       struct qcow_refcount_block *t;
+
+       list_for_each_safe(pos, n, &rft->lru_list) {
+               list_del(pos);
+               t = list_entry(pos, struct qcow_refcount_block, list);
+               rb_erase(&t->node, r);
+
+               free(t);
+       }
+}
+
+static int refcount_block_insert(struct rb_root *root, struct qcow_refcount_block *new)
+{
+       struct rb_node **link = &(root->rb_node), *parent = NULL;
+       u64 offset = new->offset;
+
+       /* search the tree */
+       while (*link) {
+               struct qcow_refcount_block *t;
+
+               t = rb_entry(*link, struct qcow_refcount_block, node);
+               if (!t)
+                       goto error;
+
+               parent = *link;
+
+               if (t->offset > offset)
+                       link = &(*link)->rb_left;
+               else if (t->offset < offset)
+                       link = &(*link)->rb_right;
+               else
+                       goto out;
+       }
+
+       /* add new node */
+       rb_link_node(&new->node, parent, link);
+       rb_insert_color(&new->node, root);
+out:
+       return 0;
+error:
+       return -1;
+}
+
+static int write_refcount_block(struct qcow *q, struct qcow_refcount_block *rfb)
+{
+       if (!rfb->dirty)
+               return 0;
+
+       if (qcow_pwrite_sync(q->fd, rfb->entries,
+               rfb->size * sizeof(u16), rfb->offset) < 0)
+               return -1;
+
+       rfb->dirty = 0;
+
+       return 0;
+}
+
+static int cache_refcount_block(struct qcow *q, struct qcow_refcount_block *c)
+{
+       struct qcow_refcount_table *rft = &q->refcount_table;
+       struct rb_root *r = &rft->root;
+       struct qcow_refcount_block *lru;
+
+       if (rft->nr_cached == MAX_CACHE_NODES) {
+               lru = list_first_entry(&rft->lru_list, struct qcow_refcount_block, list);
+
+               rb_erase(&lru->node, r);
+               list_del_init(&lru->list);
+               rft->nr_cached--;
+
+               free(lru);
+       }
+
+       if (refcount_block_insert(r, c) < 0)
+               goto error;
+
+       list_add_tail(&c->list, &rft->lru_list);
+       rft->nr_cached++;
+
+       return 0;
+error:
+       return -1;
+}
+
+static struct qcow_refcount_block *new_refcount_block(struct qcow *q, u64 rfb_offset)
+{
+       struct qcow_refcount_block *rfb;
+
+       rfb = malloc(sizeof *rfb + q->cluster_size);
+       if (!rfb)
+               return NULL;
+
+       rfb->offset = rfb_offset;
+       rfb->size = q->cluster_size / sizeof(u16);
+       RB_CLEAR_NODE(&rfb->node);
+       INIT_LIST_HEAD(&rfb->list);
+
+       return rfb;
+}
+
+static struct qcow_refcount_block *refcount_block_lookup(struct rb_root *root, u64 offset)
+{
+       struct rb_node *link = root->rb_node;
+
+       while (link) {
+               struct qcow_refcount_block *t;
+
+               t = rb_entry(link, struct qcow_refcount_block, node);
+               if (!t)
+                       goto out;
+
+               if (t->offset > offset)
+                       link = link->rb_left;
+               else if (t->offset < offset)
+                       link = link->rb_right;
+               else
+                       return t;
+       }
+out:
+       return NULL;
+}
+
+static struct qcow_refcount_block *refcount_block_search(struct qcow *q, u64 offset)
+{
+       struct qcow_refcount_table *rft = &q->refcount_table;
+       struct qcow_refcount_block *rfb;
+
+       rfb = refcount_block_lookup(&rft->root, offset);
+       if (!rfb)
+               return NULL;
+
+       /* Update the LRU state, by moving the searched node to list tail */
+       list_move_tail(&rfb->list, &rft->lru_list);
+
+       return rfb;
+}
+
+static struct qcow_refcount_block *qcow_grow_refcount_block(struct qcow *q,
+       u64 clust_idx)
+{
+       struct qcow_header *header = q->header;
+       struct qcow_refcount_table *rft = &q->refcount_table;
+       struct qcow_refcount_block *rfb;
+       u64 new_block_offset;
+       u64 rft_idx;
+
+       rft_idx = clust_idx >> (header->cluster_bits -
+               QCOW_REFCOUNT_BLOCK_SHIFT);
+
+       if (rft_idx >= rft->rf_size) {
+               pr_warning("Don't support grow refcount block table");
+               return NULL;
+       }
+
+       new_block_offset = qcow_alloc_clusters(q, q->cluster_size, 0);
+       if (new_block_offset < 0)
+               return NULL;
+
+       rfb = new_refcount_block(q, new_block_offset);
+       if (!rfb)
+               return NULL;
+
+       memset(rfb->entries, 0x00, q->cluster_size);
+       rfb->dirty = 1;
+
+       /* write refcount block */
+       if (write_refcount_block(q, rfb) < 0)
+               goto free_rfb;
+
+       if (cache_refcount_block(q, rfb) < 0)
+               goto free_rfb;
+
+       rft->rf_table[rft_idx] = cpu_to_be64(new_block_offset);
+       if (update_cluster_refcount(q, new_block_offset >>
+                   header->cluster_bits, 1) < 0)
+               goto recover_rft;
+
+       if (qcow_write_refcount_table(q) < 0)
+               goto recover_rft;
+
+       return rfb;
+
+recover_rft:
+       rft->rf_table[rft_idx] = 0;
+free_rfb:
+       free(rfb);
+       return NULL;
+}
+
+static struct qcow_refcount_block *qcow_read_refcount_block(struct qcow *q, u64 clust_idx)
+{
+       struct qcow_header *header = q->header;
+       struct qcow_refcount_table *rft = &q->refcount_table;
+       struct qcow_refcount_block *rfb;
+       u64 rfb_offset;
+       u64 rft_idx;
+
+       rft_idx = clust_idx >> (header->cluster_bits - QCOW_REFCOUNT_BLOCK_SHIFT);
+       if (rft_idx >= rft->rf_size)
+               return ERR_PTR(-ENOSPC);
+
+       rfb_offset = be64_to_cpu(rft->rf_table[rft_idx]);
+       if (!rfb_offset)
+               return ERR_PTR(-ENOSPC);
+
+       rfb = refcount_block_search(q, rfb_offset);
+       if (rfb)
+               return rfb;
+
+       rfb = new_refcount_block(q, rfb_offset);
+       if (!rfb)
+               return NULL;
+
+       if (pread_in_full(q->fd, rfb->entries, rfb->size * sizeof(u16), rfb_offset) < 0)
+               goto error_free_rfb;
+
+       if (cache_refcount_block(q, rfb) < 0)
+               goto error_free_rfb;
+
+       return rfb;
+
+error_free_rfb:
+       free(rfb);
+
+       return NULL;
+}
+
+static u16 qcow_get_refcount(struct qcow *q, u64 clust_idx)
+{
+       struct qcow_refcount_block *rfb = NULL;
+       struct qcow_header *header = q->header;
+       u64 rfb_idx;
+
+       rfb = qcow_read_refcount_block(q, clust_idx);
+       if (PTR_ERR(rfb) == -ENOSPC)
+               return 0;
+       else if (IS_ERR_OR_NULL(rfb)) {
+               pr_warning("Error while reading refcount table");
+               return -1;
+       }
+
+       rfb_idx = clust_idx & (((1ULL <<
+               (header->cluster_bits - QCOW_REFCOUNT_BLOCK_SHIFT)) - 1));
+
+       if (rfb_idx >= rfb->size) {
+               pr_warning("L1: refcount block index out of bounds");
+               return -1;
+       }
+
+       return be16_to_cpu(rfb->entries[rfb_idx]);
+}
+
+static int update_cluster_refcount(struct qcow *q, u64 clust_idx, u16 append)
+{
+       struct qcow_refcount_block *rfb = NULL;
+       struct qcow_header *header = q->header;
+       u16 refcount;
+       u64 rfb_idx;
+
+       rfb = qcow_read_refcount_block(q, clust_idx);
+       if (PTR_ERR(rfb) == -ENOSPC) {
+               rfb = qcow_grow_refcount_block(q, clust_idx);
+               if (!rfb) {
+                       pr_warning("error while growing refcount table");
+                       return -1;
+               }
+       } else if (IS_ERR_OR_NULL(rfb)) {
+               pr_warning("error while reading refcount table");
+               return -1;
+       }
+
+       rfb_idx = clust_idx & (((1ULL <<
+               (header->cluster_bits - QCOW_REFCOUNT_BLOCK_SHIFT)) - 1));
+       if (rfb_idx >= rfb->size) {
+               pr_warning("refcount block index out of bounds");
+               return -1;
+       }
+
+       refcount = be16_to_cpu(rfb->entries[rfb_idx]) + append;
+       rfb->entries[rfb_idx] = cpu_to_be16(refcount);
+       rfb->dirty = 1;
+
+       /* write refcount block */
+       if (write_refcount_block(q, rfb) < 0) {
+               pr_warning("refcount block index out of bounds");
+               return -1;
+       }
+
+       /* update free_clust_idx since refcount becomes zero */
+       if (!refcount && clust_idx < q->free_clust_idx)
+               q->free_clust_idx = clust_idx;
+
+       return 0;
+}
+
+static void  qcow_free_clusters(struct qcow *q, u64 clust_start, u64 size)
+{
+       struct qcow_header *header = q->header;
+       u64 start, end, offset;
+
+       start = clust_start & ~(q->cluster_size - 1);
+       end = (clust_start + size - 1) & ~(q->cluster_size - 1);
+       for (offset = start; offset <= end; offset += q->cluster_size)
+               update_cluster_refcount(q, offset >> header->cluster_bits, -1);
+}
+
+/*
+ * Allocate clusters according to the size. Find a postion that
+ * can satisfy the size. free_clust_idx is initialized to zero and
+ * Record last position.
+ */
+static u64 qcow_alloc_clusters(struct qcow *q, u64 size, int update_ref)
+{
+       struct qcow_header *header = q->header;
+       u16 clust_refcount;
+       u32 clust_idx = 0, i;
+       u64 clust_num;
+
+       clust_num = (size + (q->cluster_size - 1)) >> header->cluster_bits;
+
+again:
+       for (i = 0; i < clust_num; i++) {
+               clust_idx = q->free_clust_idx++;
+               clust_refcount = qcow_get_refcount(q, clust_idx);
+               if (clust_refcount < 0)
+                       return -1;
+               else if (clust_refcount > 0)
+                       goto again;
+       }
+
+       clust_idx++;
+
+       if (update_ref)
+               for (i = 0; i < clust_num; i++)
+                       if (update_cluster_refcount(q,
+                               clust_idx - clust_num + i, 1))
+                               return -1;
+
+       return (clust_idx - clust_num) << header->cluster_bits;
+}
+
+static int qcow_write_l1_table(struct qcow *q)
+{
+       struct qcow_l1_table *l1t = &q->table;
+       struct qcow_header *header = q->header;
+
+       if (qcow_pwrite_sync(q->fd, l1t->l1_table,
+               l1t->table_size * sizeof(u64),
+               header->l1_table_offset) < 0)
+               return -1;
+
+       return 0;
+}
+
+/*
+ * Get l2 table. If the table has been copied, read table directly.
+ * If the table exists, allocate a new cluster and copy the table
+ * to the new cluster.
+ */
+static int get_cluster_table(struct qcow *q, u64 offset,
+       struct qcow_l2_table **result_l2t, u64 *result_l2_index)
+{
+       struct qcow_header *header = q->header;
+       struct qcow_l1_table *l1t = &q->table;
+       struct qcow_l2_table *l2t;
+       u64 l1t_idx;
+       u64 l2t_offset;
+       u64 l2t_idx;
+       u64 l2t_size;
+       u64 l2t_new_offset;
+
+       l2t_size = 1 << header->l2_bits;
+
+       l1t_idx = get_l1_index(q, offset);
+       if (l1t_idx >= l1t->table_size)
+               return -1;
+
+       l2t_idx = get_l2_index(q, offset);
+       if (l2t_idx >= l2t_size)
+               return -1;
+
+       l2t_offset = be64_to_cpu(l1t->l1_table[l1t_idx]);
+       if (l2t_offset & QCOW2_OFLAG_COPIED) {
+               l2t_offset &= ~QCOW2_OFLAG_COPIED;
+               l2t = qcow_read_l2_table(q, l2t_offset);
+               if (!l2t)
+                       goto error;
+       } else {
+               l2t_new_offset = qcow_alloc_clusters(q,
+                       l2t_size*sizeof(u64), 1);
+
+               if (l2t_new_offset < 0)
+                       goto error;
+
+               l2t = new_cache_table(q, l2t_new_offset);
+               if (!l2t)
+                       goto free_cluster;
+
+               if (l2t_offset) {
+                       l2t = qcow_read_l2_table(q, l2t_offset);
+                       if (!l2t)
+                               goto free_cache;
+               } else
+                       memset(l2t->table, 0x00, l2t_size * sizeof(u64));
+
+               /* write l2 table */
+               l2t->dirty = 1;
+               if (qcow_l2_cache_write(q, l2t) < 0)
+                       goto free_cache;
+
+               /* cache l2 table */
+               if (cache_table(q, l2t))
+                       goto free_cache;
+
+               /* update the l1 talble */
+               l1t->l1_table[l1t_idx] = cpu_to_be64(l2t_new_offset
+                       | QCOW2_OFLAG_COPIED);
+               if (qcow_write_l1_table(q)) {
+                       pr_warning("Update l1 table error");
+                       goto free_cache;
+               }
+
+               /* free old cluster */
+               qcow_free_clusters(q, l2t_offset, q->cluster_size);
+       }
+
+       *result_l2t = l2t;
+       *result_l2_index = l2t_idx;
+
+       return 0;
+
+free_cache:
+       free(l2t);
+
+free_cluster:
+       qcow_free_clusters(q, l2t_new_offset, q->cluster_size);
+
+error:
+       return -1;
+}
+
+/*
+ * If the cluster has been copied, write data directly. If not,
+ * read the original data and write it to the new cluster with
+ * modification.
+ */
+static ssize_t qcow_write_cluster(struct qcow *q, u64 offset,
+               void *buf, u32 src_len)
+{
+       struct qcow_l2_table *l2t;
+       u64 clust_new_start;
+       u64 clust_start;
+       u64 clust_flags;
+       u64 clust_off;
+       u64 l2t_idx;
+       u64 len;
+
+       l2t = NULL;
+
+       clust_off = get_cluster_offset(q, offset);
+       if (clust_off >= q->cluster_size)
+               return -1;
+
+       len = q->cluster_size - clust_off;
+       if (len > src_len)
+               len = src_len;
+
+       mutex_lock(&q->mutex);
+
+       if (get_cluster_table(q, offset, &l2t, &l2t_idx)) {
+               pr_warning("Get l2 table error");
+               goto error;
+       }
+
+       clust_start = be64_to_cpu(l2t->table[l2t_idx]);
+       clust_flags = clust_start & QCOW2_OFLAGS_MASK;
+
+       clust_start &= QCOW2_OFFSET_MASK;
+       if (!(clust_flags & QCOW2_OFLAG_COPIED)) {
+               clust_new_start = qcow_alloc_clusters(q, q->cluster_size, 1);
+               if (clust_new_start < 0) {
+                       pr_warning("Cluster alloc error");
+                       goto error;
+               }
+
+               offset &= ~(q->cluster_size - 1);
+
+               /* if clust_start is not zero, read the original data*/
+               if (clust_start) {
+                       mutex_unlock(&q->mutex);
+                       if (qcow2_read_cluster(q, offset, q->copy_buff,
+                               q->cluster_size) < 0) {
+                               pr_warning("Read copy cluster error");
+                               qcow_free_clusters(q, clust_new_start,
+                                       q->cluster_size);
+                               return -1;
+                       }
+                       mutex_lock(&q->mutex);
+               } else
+                       memset(q->copy_buff, 0x00, q->cluster_size);
+
+               memcpy(q->copy_buff + clust_off, buf, len);
+
+                /* Write actual data */
+               if (pwrite_in_full(q->fd, q->copy_buff, q->cluster_size,
+                       clust_new_start) < 0)
+                       goto free_cluster;
+
+               /* update l2 table*/
+               l2t->table[l2t_idx] = cpu_to_be64(clust_new_start
+                       | QCOW2_OFLAG_COPIED);
+               l2t->dirty = 1;
+
+               if (qcow_l2_cache_write(q, l2t))
+                       goto free_cluster;
+
+               /* free old cluster*/
+               if (clust_flags & QCOW2_OFLAG_COMPRESSED) {
+                       int size;
+                       size = ((clust_start >> q->csize_shift) &
+                               q->csize_mask) + 1;
+                       size *= 512;
+                       clust_start &= q->cluster_offset_mask;
+                       clust_start &= ~511;
+
+                       qcow_free_clusters(q, clust_start, size);
+               } else if (clust_start)
+                       qcow_free_clusters(q, clust_start, q->cluster_size);
+
+       } else {
+               /* Write actual data */
+               if (pwrite_in_full(q->fd, buf, len,
+                       clust_start + clust_off) < 0)
+                       goto error;
+       }
+       mutex_unlock(&q->mutex);
+       return len;
+
+free_cluster:
+       qcow_free_clusters(q, clust_new_start, q->cluster_size);
+
+error:
+       mutex_unlock(&q->mutex);
+       return -1;
+}
+
+static ssize_t qcow_write_sector_single(struct disk_image *disk, u64 sector, void *src, u32 src_len)
+{
+       struct qcow *q = disk->priv;
+       struct qcow_header *header = q->header;
+       u32 nr_written;
+       char *buf;
+       u64 offset;
+       ssize_t nr;
+
+       buf             = src;
+       nr_written      = 0;
+       offset          = sector << SECTOR_SHIFT;
+
+       while (nr_written < src_len) {
+               if (offset >= header->size)
+                       return -1;
+
+               nr = qcow_write_cluster(q, offset, buf, src_len - nr_written);
+               if (nr < 0)
+                       return -1;
+
+               nr_written      += nr;
+               buf             += nr;
+               offset          += nr;
+       }
+
+       return nr_written;
+}
+
+static ssize_t qcow_write_sector(struct disk_image *disk, u64 sector,
+                               const struct iovec *iov, int iovcount, void *param)
+{
+       ssize_t nr, total = 0;
+
+       while (iovcount--) {
+               nr = qcow_write_sector_single(disk, sector, iov->iov_base, iov->iov_len);
+               if (nr != (ssize_t)iov->iov_len) {
+                       pr_info("qcow_write_sector error: nr=%ld iov_len=%ld\n", (long)nr, (long)iov->iov_len);
+                       return -1;
+               }
+
+               sector  += iov->iov_len >> SECTOR_SHIFT;
+               iov++;
+               total   += nr;
+       }
+
+       return total;
+}
+
+static int qcow_disk_flush(struct disk_image *disk)
+{
+       struct qcow *q = disk->priv;
+       struct qcow_refcount_table *rft;
+       struct list_head *pos, *n;
+       struct qcow_l1_table *l1t;
+
+       l1t = &q->table;
+       rft = &q->refcount_table;
+
+       mutex_lock(&q->mutex);
+
+       list_for_each_safe(pos, n, &rft->lru_list) {
+               struct qcow_refcount_block *c = list_entry(pos, struct qcow_refcount_block, list);
+
+               if (write_refcount_block(q, c) < 0)
+                       goto error_unlock;
+       }
+
+       list_for_each_safe(pos, n, &l1t->lru_list) {
+               struct qcow_l2_table *c = list_entry(pos, struct qcow_l2_table, list);
+
+               if (qcow_l2_cache_write(q, c) < 0)
+                       goto error_unlock;
+       }
+
+       if (qcow_write_l1_table < 0)
+               goto error_unlock;
+
+       mutex_unlock(&q->mutex);
+
+       return fsync(disk->fd);
+
+error_unlock:
+       mutex_unlock(&q->mutex);
+       return -1;
+}
+
+static int qcow_disk_close(struct disk_image *disk)
+{
+       struct qcow *q;
+
+       if (!disk)
+               return 0;
+
+       q = disk->priv;
+
+       refcount_table_free_cache(&q->refcount_table);
+       l1_table_free_cache(&q->table);
+       free(q->copy_buff);
+       free(q->cluster_data);
+       free(q->cluster_cache);
+       free(q->refcount_table.rf_table);
+       free(q->table.l1_table);
+       free(q->header);
+       free(q);
+
+       return 0;
+}
+
+static struct disk_image_operations qcow_disk_readonly_ops = {
+       .read   = qcow_read_sector,
+       .close  = qcow_disk_close,
+};
+
+static struct disk_image_operations qcow_disk_ops = {
+       .read   = qcow_read_sector,
+       .write  = qcow_write_sector,
+       .flush  = qcow_disk_flush,
+       .close  = qcow_disk_close,
+};
+
+static int qcow_read_refcount_table(struct qcow *q)
+{
+       struct qcow_header *header = q->header;
+       struct qcow_refcount_table *rft = &q->refcount_table;
+
+       rft->rf_size = (header->refcount_table_size * q->cluster_size)
+               / sizeof(u64);
+
+       rft->rf_table = calloc(rft->rf_size, sizeof(u64));
+       if (!rft->rf_table)
+               return -1;
+
+       rft->root = RB_ROOT;
+       INIT_LIST_HEAD(&rft->lru_list);
+
+       return pread_in_full(q->fd, rft->rf_table, sizeof(u64) * rft->rf_size, header->refcount_table_offset);
+}
+
+static int qcow_write_refcount_table(struct qcow *q)
+{
+       struct qcow_header *header = q->header;
+       struct qcow_refcount_table *rft = &q->refcount_table;
+
+       return qcow_pwrite_sync(q->fd, rft->rf_table,
+               rft->rf_size * sizeof(u64), header->refcount_table_offset);
+}
+
+static int qcow_read_l1_table(struct qcow *q)
+{
+       struct qcow_header *header = q->header;
+       struct qcow_l1_table *table = &q->table;
+
+       table->table_size = header->l1_size;
+
+       table->l1_table = calloc(table->table_size, sizeof(u64));
+       if (!table->l1_table)
+               return -1;
+
+       return pread_in_full(q->fd, table->l1_table, sizeof(u64) * table->table_size, header->l1_table_offset);
+}
+
+static void *qcow2_read_header(int fd)
+{
+       struct qcow2_header_disk f_header;
+       struct qcow_header *header;
+
+       header = malloc(sizeof(struct qcow_header));
+       if (!header)
+               return NULL;
+
+       if (pread_in_full(fd, &f_header, sizeof(struct qcow2_header_disk), 0) < 0) {
+               free(header);
+               return NULL;
+       }
+
+       be32_to_cpus(&f_header.magic);
+       be32_to_cpus(&f_header.version);
+       be64_to_cpus(&f_header.backing_file_offset);
+       be32_to_cpus(&f_header.backing_file_size);
+       be32_to_cpus(&f_header.cluster_bits);
+       be64_to_cpus(&f_header.size);
+       be32_to_cpus(&f_header.crypt_method);
+       be32_to_cpus(&f_header.l1_size);
+       be64_to_cpus(&f_header.l1_table_offset);
+       be64_to_cpus(&f_header.refcount_table_offset);
+       be32_to_cpus(&f_header.refcount_table_clusters);
+       be32_to_cpus(&f_header.nb_snapshots);
+       be64_to_cpus(&f_header.snapshots_offset);
+
+       *header         = (struct qcow_header) {
+               .size                   = f_header.size,
+               .l1_table_offset        = f_header.l1_table_offset,
+               .l1_size                = f_header.l1_size,
+               .cluster_bits           = f_header.cluster_bits,
+               .l2_bits                = f_header.cluster_bits - 3,
+               .refcount_table_offset  = f_header.refcount_table_offset,
+               .refcount_table_size    = f_header.refcount_table_clusters,
+       };
+
+       return header;
+}
+
+static struct disk_image *qcow2_probe(int fd, bool readonly)
+{
+       struct disk_image *disk_image;
+       struct qcow_l1_table *l1t;
+       struct qcow_header *h;
+       struct qcow *q;
+
+       q = calloc(1, sizeof(struct qcow));
+       if (!q)
+               return NULL;
+
+       mutex_init(&q->mutex);
+       q->fd = fd;
+
+       l1t = &q->table;
+
+       l1t->root = RB_ROOT;
+       INIT_LIST_HEAD(&l1t->lru_list);
+
+       h = q->header = qcow2_read_header(fd);
+       if (!h)
+               goto free_qcow;
+
+       q->version = QCOW2_VERSION;
+       q->csize_shift = (62 - (q->header->cluster_bits - 8));
+       q->csize_mask = (1 << (q->header->cluster_bits - 8)) - 1;
+       q->cluster_offset_mask = (1LL << q->csize_shift) - 1;
+       q->cluster_size = 1 << q->header->cluster_bits;
+
+       q->copy_buff = malloc(q->cluster_size);
+       if (!q->copy_buff) {
+               pr_warning("copy buff malloc error");
+               goto free_header;
+       }
+
+       q->cluster_data = malloc(q->cluster_size);
+       if (!q->cluster_data) {
+               pr_warning("cluster data malloc error");
+               goto free_copy_buff;
+       }
+
+       q->cluster_cache = malloc(q->cluster_size);
+       if (!q->cluster_cache) {
+               pr_warning("cluster cache malloc error");
+               goto free_cluster_data;
+       }
+
+       if (qcow_read_l1_table(q) < 0)
+               goto free_cluster_cache;
+
+       if (qcow_read_refcount_table(q) < 0)
+               goto free_l1_table;
+
+       /*
+        * Do not use mmap use read/write instead
+        */
+       if (readonly)
+               disk_image = disk_image__new(fd, h->size, &qcow_disk_readonly_ops, DISK_IMAGE_REGULAR);
+       else
+               disk_image = disk_image__new(fd, h->size, &qcow_disk_ops, DISK_IMAGE_REGULAR);
+
+       if (IS_ERR_OR_NULL(disk_image))
+               goto free_refcount_table;
+
+       disk_image->async = 0;
+       disk_image->priv = q;
+
+       return disk_image;
+
+free_refcount_table:
+       if (q->refcount_table.rf_table)
+               free(q->refcount_table.rf_table);
+free_l1_table:
+       if (q->table.l1_table)
+               free(q->table.l1_table);
+free_cluster_cache:
+       if (q->cluster_cache)
+               free(q->cluster_cache);
+free_cluster_data:
+       if (q->cluster_data)
+               free(q->cluster_data);
+free_copy_buff:
+       if (q->copy_buff)
+               free(q->copy_buff);
+free_header:
+       if (q->header)
+               free(q->header);
+free_qcow:
+       if (q)
+               free(q);
+
+       return NULL;
+}
+
+static bool qcow2_check_image(int fd)
+{
+       struct qcow2_header_disk f_header;
+
+       if (pread_in_full(fd, &f_header, sizeof(struct qcow2_header_disk), 0) < 0)
+               return false;
+
+       be32_to_cpus(&f_header.magic);
+       be32_to_cpus(&f_header.version);
+
+       if (f_header.magic != QCOW_MAGIC)
+               return false;
+
+       if (f_header.version != QCOW2_VERSION)
+               return false;
+
+       return true;
+}
+
+static void *qcow1_read_header(int fd)
+{
+       struct qcow1_header_disk f_header;
+       struct qcow_header *header;
+
+       header = malloc(sizeof(struct qcow_header));
+       if (!header)
+               return NULL;
+
+       if (pread_in_full(fd, &f_header, sizeof(struct qcow1_header_disk), 0) < 0) {
+               free(header);
+               return NULL;
+       }
+
+       be32_to_cpus(&f_header.magic);
+       be32_to_cpus(&f_header.version);
+       be64_to_cpus(&f_header.backing_file_offset);
+       be32_to_cpus(&f_header.backing_file_size);
+       be32_to_cpus(&f_header.mtime);
+       be64_to_cpus(&f_header.size);
+       be32_to_cpus(&f_header.crypt_method);
+       be64_to_cpus(&f_header.l1_table_offset);
+
+       *header         = (struct qcow_header) {
+               .size                   = f_header.size,
+               .l1_table_offset        = f_header.l1_table_offset,
+               .l1_size                = f_header.size / ((1 << f_header.l2_bits) * (1 << f_header.cluster_bits)),
+               .cluster_bits           = f_header.cluster_bits,
+               .l2_bits                = f_header.l2_bits,
+       };
+
+       return header;
+}
+
+static struct disk_image *qcow1_probe(int fd, bool readonly)
+{
+       struct disk_image *disk_image;
+       struct qcow_l1_table *l1t;
+       struct qcow_header *h;
+       struct qcow *q;
+
+       q = calloc(1, sizeof(struct qcow));
+       if (!q)
+               return NULL;
+
+       mutex_init(&q->mutex);
+       q->fd = fd;
+
+       l1t = &q->table;
+
+       l1t->root = RB_ROOT;
+       INIT_LIST_HEAD(&l1t->lru_list);
+
+       h = q->header = qcow1_read_header(fd);
+       if (!h)
+               goto free_qcow;
+
+       q->version = QCOW1_VERSION;
+       q->cluster_size = 1 << q->header->cluster_bits;
+       q->cluster_offset_mask = (1LL << (63 - q->header->cluster_bits)) - 1;
+       q->free_clust_idx = 0;
+
+       q->cluster_data = malloc(q->cluster_size);
+       if (!q->cluster_data) {
+               pr_warning("cluster data malloc error");
+               goto free_header;
+       }
+
+       q->cluster_cache = malloc(q->cluster_size);
+       if (!q->cluster_cache) {
+               pr_warning("cluster cache malloc error");
+               goto free_cluster_data;
+       }
+
+       if (qcow_read_l1_table(q) < 0)
+               goto free_cluster_cache;
+
+       /*
+        * Do not use mmap use read/write instead
+        */
+       if (readonly)
+               disk_image = disk_image__new(fd, h->size, &qcow_disk_readonly_ops, DISK_IMAGE_REGULAR);
+       else
+               disk_image = disk_image__new(fd, h->size, &qcow_disk_ops, DISK_IMAGE_REGULAR);
+
+       if (!disk_image)
+               goto free_l1_table;
+
+       disk_image->async = 1;
+       disk_image->priv = q;
+
+       return disk_image;
+
+free_l1_table:
+       if (q->table.l1_table)
+               free(q->table.l1_table);
+free_cluster_cache:
+       if (q->cluster_cache)
+               free(q->cluster_cache);
+free_cluster_data:
+       if (q->cluster_data)
+               free(q->cluster_data);
+free_header:
+       if (q->header)
+               free(q->header);
+free_qcow:
+       if (q)
+               free(q);
+
+       return NULL;
+}
+
+static bool qcow1_check_image(int fd)
+{
+       struct qcow1_header_disk f_header;
+
+       if (pread_in_full(fd, &f_header, sizeof(struct qcow1_header_disk), 0) < 0)
+               return false;
+
+       be32_to_cpus(&f_header.magic);
+       be32_to_cpus(&f_header.version);
+
+       if (f_header.magic != QCOW_MAGIC)
+               return false;
+
+       if (f_header.version != QCOW1_VERSION)
+               return false;
+
+       return true;
+}
+
+struct disk_image *qcow_probe(int fd, bool readonly)
+{
+       if (qcow1_check_image(fd))
+               return qcow1_probe(fd, readonly);
+
+       if (qcow2_check_image(fd))
+               return qcow2_probe(fd, readonly);
+
+       return NULL;
+}
diff --git a/tools/kvm/disk/raw.c b/tools/kvm/disk/raw.c
new file mode 100644 (file)
index 0000000..93b2b4e
--- /dev/null
@@ -0,0 +1,141 @@
+#include "kvm/disk-image.h"
+
+#include <linux/err.h>
+
+#ifdef CONFIG_HAS_AIO
+#include <libaio.h>
+#endif
+
+ssize_t raw_image__read(struct disk_image *disk, u64 sector, const struct iovec *iov,
+                               int iovcount, void *param)
+{
+       u64 offset = sector << SECTOR_SHIFT;
+
+#ifdef CONFIG_HAS_AIO
+       struct iocb iocb;
+
+       return aio_preadv(disk->ctx, &iocb, disk->fd, iov, iovcount, offset,
+                               disk->evt, param);
+#else
+       return preadv_in_full(disk->fd, iov, iovcount, offset);
+#endif
+}
+
+ssize_t raw_image__write(struct disk_image *disk, u64 sector, const struct iovec *iov,
+                               int iovcount, void *param)
+{
+       u64 offset = sector << SECTOR_SHIFT;
+
+#ifdef CONFIG_HAS_AIO
+       struct iocb iocb;
+
+       return aio_pwritev(disk->ctx, &iocb, disk->fd, iov, iovcount, offset,
+                               disk->evt, param);
+#else
+       return pwritev_in_full(disk->fd, iov, iovcount, offset);
+#endif
+}
+
+ssize_t raw_image__read_mmap(struct disk_image *disk, u64 sector, const struct iovec *iov,
+                               int iovcount, void *param)
+{
+       u64 offset = sector << SECTOR_SHIFT;
+       ssize_t total = 0;
+
+       while (iovcount--) {
+               memcpy(iov->iov_base, disk->priv + offset, iov->iov_len);
+
+               sector  += iov->iov_len >> SECTOR_SHIFT;
+               offset  += iov->iov_len;
+               total   += iov->iov_len;
+               iov++;
+       }
+
+       return total;
+}
+
+ssize_t raw_image__write_mmap(struct disk_image *disk, u64 sector, const struct iovec *iov,
+                               int iovcount, void *param)
+{
+       u64 offset = sector << SECTOR_SHIFT;
+       ssize_t total = 0;
+
+       while (iovcount--) {
+               memcpy(disk->priv + offset, iov->iov_base, iov->iov_len);
+
+               sector  += iov->iov_len >> SECTOR_SHIFT;
+               offset  += iov->iov_len;
+               total   += iov->iov_len;
+               iov++;
+       }
+
+       return total;
+}
+
+int raw_image__close(struct disk_image *disk)
+{
+       int ret = 0;
+
+       if (disk->priv != MAP_FAILED)
+               ret = munmap(disk->priv, disk->size);
+
+       close(disk->evt);
+
+#ifdef CONFIG_HAS_VIRTIO
+       io_destroy(disk->ctx);
+#endif
+
+       return ret;
+}
+
+/*
+ * multiple buffer based disk image operations
+ */
+static struct disk_image_operations raw_image_regular_ops = {
+       .read   = raw_image__read,
+       .write  = raw_image__write,
+};
+
+struct disk_image_operations ro_ops = {
+       .read   = raw_image__read_mmap,
+       .write  = raw_image__write_mmap,
+       .close  = raw_image__close,
+};
+
+struct disk_image_operations ro_ops_nowrite = {
+       .read   = raw_image__read,
+};
+
+struct disk_image *raw_image__probe(int fd, struct stat *st, bool readonly)
+{
+       struct disk_image *disk;
+
+       if (readonly) {
+               /*
+                * Use mmap's MAP_PRIVATE to implement non-persistent write
+                * FIXME: This does not work on 32-bit host.
+                */
+               struct disk_image *disk;
+
+               disk = disk_image__new(fd, st->st_size, &ro_ops, DISK_IMAGE_MMAP);
+               if (IS_ERR_OR_NULL(disk)) {
+                       disk = disk_image__new(fd, st->st_size, &ro_ops_nowrite, DISK_IMAGE_REGULAR);
+#ifdef CONFIG_HAS_AIO
+                       if (!IS_ERR_OR_NULL(disk))
+                               disk->async = 1;
+#endif
+               }
+
+               return disk;
+       } else {
+               /*
+                * Use read/write instead of mmap
+                */
+               disk = disk_image__new(fd, st->st_size, &raw_image_regular_ops, DISK_IMAGE_REGULAR);
+#ifdef CONFIG_HAS_AIO
+               if (!IS_ERR_OR_NULL(disk))
+                       disk->async = 1;
+#endif
+               return disk;
+       }
+}
diff --git a/tools/kvm/framebuffer.c b/tools/kvm/framebuffer.c
new file mode 100644 (file)
index 0000000..fb8f51d
--- /dev/null
@@ -0,0 +1,80 @@
+#include "kvm/framebuffer.h"
+#include "kvm/kvm.h"
+
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <errno.h>
+
+static LIST_HEAD(framebuffers);
+
+struct framebuffer *fb__register(struct framebuffer *fb)
+{
+       INIT_LIST_HEAD(&fb->node);
+       list_add(&fb->node, &framebuffers);
+
+       return fb;
+}
+
+int fb__attach(struct framebuffer *fb, struct fb_target_operations *ops)
+{
+       if (fb->nr_targets >= FB_MAX_TARGETS)
+               return -ENOSPC;
+
+       fb->targets[fb->nr_targets++] = ops;
+
+       return 0;
+}
+
+static int start_targets(struct framebuffer *fb)
+{
+       unsigned long i;
+
+       for (i = 0; i < fb->nr_targets; i++) {
+               struct fb_target_operations *ops = fb->targets[i];
+               int err = 0;
+
+               if (ops->start)
+                       err = ops->start(fb);
+
+               if (err)
+                       return err;
+       }
+
+       return 0;
+}
+
+int fb__init(struct kvm *kvm)
+{
+       struct framebuffer *fb;
+
+       list_for_each_entry(fb, &framebuffers, node) {
+               int err;
+
+               err = start_targets(fb);
+               if (err)
+                       return err;
+       }
+
+       return 0;
+}
+firmware_init(fb__init);
+
+int fb__exit(struct kvm *kvm)
+{
+       struct framebuffer *fb;
+
+       list_for_each_entry(fb, &framebuffers, node) {
+               u32 i;
+
+               for (i = 0; i < fb->nr_targets; i++)
+                       if (fb->targets[i]->stop)
+                               fb->targets[i]->stop(fb);
+
+               munmap(fb->mem, fb->mem_size);
+       }
+
+       return 0;
+}
+firmware_exit(fb__exit);
diff --git a/tools/kvm/guest/init.c b/tools/kvm/guest/init.c
new file mode 100644 (file)
index 0000000..ece48fd
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * This is a simple init for shared rootfs guests. This part should be limited
+ * to doing mounts and running stage 2 of the init process.
+ */
+#include <sys/mount.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <linux/reboot.h>
+
+static int run_process(char *filename)
+{
+       char *new_argv[] = { filename, NULL };
+       char *new_env[] = { "TERM=linux", "DISPLAY=192.168.33.1:0",
+                               "HOME=/virt/home", NULL };
+
+       return execve(filename, new_argv, new_env);
+}
+
+static int run_process_sandbox(char *filename)
+{
+       char *new_argv[] = { filename, "/virt/sandbox.sh", NULL };
+       char *new_env[] = { "TERM=linux", "HOME=/virt/home", NULL };
+
+       return execve(filename, new_argv, new_env);
+}
+
+static void do_mounts(void)
+{
+       mount("hostfs", "/host", "9p", MS_RDONLY, "trans=virtio,version=9p2000.L");
+       mount("", "/sys", "sysfs", 0, NULL);
+       mount("proc", "/proc", "proc", 0, NULL);
+       mount("devtmpfs", "/dev", "devtmpfs", 0, NULL);
+       mkdir("/dev/pts", 0755);
+       mount("devpts", "/dev/pts", "devpts", 0, NULL);
+}
+
+int main(int argc, char *argv[])
+{
+       pid_t child;
+       int status;
+
+       puts("Mounting...");
+
+       do_mounts();
+
+       /* get session leader */
+       setsid();
+
+       /* set controlling terminal */
+       ioctl(0, TIOCSCTTY, 1);
+
+       child = fork();
+       if (child < 0) {
+               printf("Fatal: fork() failed with %d\n", child);
+               return 0;
+       } else if (child == 0) {
+               if (access("/virt/sandbox.sh", R_OK) == 0)
+                       run_process_sandbox("/bin/sh");
+               else
+                       run_process("/bin/sh");
+       } else {
+               waitpid(child, &status, 0);
+       }
+
+       reboot(LINUX_REBOOT_CMD_RESTART);
+
+       printf("Init failed: %s\n", strerror(errno));
+
+       return 0;
+}
diff --git a/tools/kvm/guest_compat.c b/tools/kvm/guest_compat.c
new file mode 100644 (file)
index 0000000..fd4704b
--- /dev/null
@@ -0,0 +1,99 @@
+#include "kvm/guest_compat.h"
+
+#include "kvm/mutex.h"
+
+#include <linux/kernel.h>
+#include <linux/list.h>
+
+struct compat_message {
+       int id;
+       char *title;
+       char *desc;
+
+       struct list_head list;
+};
+
+static int id;
+static DEFINE_MUTEX(compat_mtx);
+static LIST_HEAD(messages);
+
+static void compat__free(struct compat_message *msg)
+{
+       free(msg->title);
+       free(msg->desc);
+       free(msg);
+}
+
+int compat__add_message(const char *title, const char *desc)
+{
+       struct compat_message *msg;
+       int msg_id;
+
+       msg = malloc(sizeof(*msg));
+       if (msg == NULL)
+               goto cleanup;
+
+       msg->title = strdup(title);
+       msg->desc = strdup(desc);
+
+       if (msg->title == NULL || msg->desc == NULL)
+               goto cleanup;
+
+       mutex_lock(&compat_mtx);
+
+       msg->id = msg_id = id++;
+       list_add_tail(&msg->list, &messages);
+
+       mutex_unlock(&compat_mtx);
+
+       return msg_id;
+
+cleanup:
+       if (msg)
+               compat__free(msg);
+
+       return -ENOMEM;
+}
+
+int compat__remove_message(int id)
+{
+       struct compat_message *pos, *n;
+
+       mutex_lock(&compat_mtx);
+
+       list_for_each_entry_safe(pos, n, &messages, list) {
+               if (pos->id == id) {
+                       list_del(&pos->list);
+                       compat__free(pos);
+
+                       mutex_unlock(&compat_mtx);
+
+                       return 0;
+               }
+       }
+
+       mutex_unlock(&compat_mtx);
+
+       return -ENOENT;
+}
+
+int compat__print_all_messages(void)
+{
+       mutex_lock(&compat_mtx);
+
+       while (!list_empty(&messages)) {
+               struct compat_message *msg;
+
+               msg = list_first_entry(&messages, struct compat_message, list);
+
+               printf("\n  # KVM compatibility warning.\n\t%s\n\t%s\n",
+                       msg->title, msg->desc);
+
+               list_del(&msg->list);
+               compat__free(msg);
+       }
+
+       mutex_unlock(&compat_mtx);
+
+       return 0;
+}
diff --git a/tools/kvm/hw/i8042.c b/tools/kvm/hw/i8042.c
new file mode 100644 (file)
index 0000000..9f8be6a
--- /dev/null
@@ -0,0 +1,355 @@
+#include "kvm/read-write.h"
+#include "kvm/ioport.h"
+#include "kvm/mutex.h"
+#include "kvm/util.h"
+#include "kvm/term.h"
+#include "kvm/kvm.h"
+#include "kvm/i8042.h"
+#include "kvm/kvm-cpu.h"
+
+#include <stdint.h>
+
+/*
+ * IRQs
+ */
+#define KBD_IRQ                        1
+#define AUX_IRQ                        12
+
+/*
+ * Registers
+ */
+#define I8042_DATA_REG         0x60
+#define I8042_COMMAND_REG      0x64
+
+/*
+ * Commands
+ */
+#define I8042_CMD_CTL_RCTR     0x20
+#define I8042_CMD_CTL_WCTR     0x60
+#define I8042_CMD_AUX_LOOP     0xD3
+#define I8042_CMD_AUX_SEND     0xD4
+#define I8042_CMD_AUX_TEST     0xA9
+#define I8042_CMD_AUX_DISABLE  0xA7
+#define I8042_CMD_AUX_ENABLE   0xA8
+#define I8042_CMD_SYSTEM_RESET 0xFE
+
+#define RESPONSE_ACK           0xFA
+
+#define MODE_DISABLE_AUX       0x20
+
+#define AUX_ENABLE_REPORTING   0x20
+#define AUX_SCALING_FLAG       0x10
+#define AUX_DEFAULT_RESOLUTION 0x2
+#define AUX_DEFAULT_SAMPLE     100
+
+/*
+ * Status register bits
+ */
+#define I8042_STR_AUXDATA      0x20
+#define I8042_STR_KEYLOCK      0x10
+#define I8042_STR_CMDDAT       0x08
+#define I8042_STR_MUXERR       0x04
+#define I8042_STR_OBF          0x01
+
+#define KBD_MODE_KBD_INT       0x01
+#define KBD_MODE_SYS           0x02
+
+#define QUEUE_SIZE             128
+
+/*
+ * This represents the current state of the PS/2 keyboard system,
+ * including the AUX device (the mouse)
+ */
+struct kbd_state {
+       struct kvm              *kvm;
+
+       char                    kq[QUEUE_SIZE]; /* Keyboard queue */
+       int                     kread, kwrite;  /* Indexes into the queue */
+       int                     kcount;         /* number of elements in queue */
+
+       char                    mq[QUEUE_SIZE];
+       int                     mread, mwrite;
+       int                     mcount;
+
+       u8                      mstatus;        /* Mouse status byte */
+       u8                      mres;           /* Current mouse resolution */
+       u8                      msample;        /* Current mouse samples/second */
+
+       u8                      mode;           /* i8042 mode register */
+       u8                      status;         /* i8042 status register */
+       /*
+        * Some commands (on port 0x64) have arguments;
+        * we store the command here while we wait for the argument
+        */
+       u32                     write_cmd;
+};
+
+static struct kbd_state                state;
+
+/*
+ * If there are packets to be read, set the appropriate IRQs high
+ */
+static void kbd_update_irq(void)
+{
+       u8 klevel = 0;
+       u8 mlevel = 0;
+
+       /* First, clear the kbd and aux output buffer full bits */
+       state.status &= ~(I8042_STR_OBF | I8042_STR_AUXDATA);
+
+       if (state.kcount > 0) {
+               state.status |= I8042_STR_OBF;
+               klevel = 1;
+       }
+
+       /* Keyboard has higher priority than mouse */
+       if (klevel == 0 && state.mcount != 0) {
+               state.status |= I8042_STR_OBF | I8042_STR_AUXDATA;
+               mlevel = 1;
+       }
+
+       kvm__irq_line(state.kvm, KBD_IRQ, klevel);
+       kvm__irq_line(state.kvm, AUX_IRQ, mlevel);
+}
+
+/*
+ * Add a byte to the mouse queue, then set IRQs
+ */
+void mouse_queue(u8 c)
+{
+       if (state.mcount >= QUEUE_SIZE)
+               return;
+
+       state.mq[state.mwrite++ % QUEUE_SIZE] = c;
+
+       state.mcount++;
+       kbd_update_irq();
+}
+
+/*
+ * Add a byte to the keyboard queue, then set IRQs
+ */
+void kbd_queue(u8 c)
+{
+       if (state.kcount >= QUEUE_SIZE)
+               return;
+
+       state.kq[state.kwrite++ % QUEUE_SIZE] = c;
+
+       state.kcount++;
+       kbd_update_irq();
+}
+
+static void kbd_write_command(struct kvm *kvm, u8 val)
+{
+       switch (val) {
+       case I8042_CMD_CTL_RCTR:
+               kbd_queue(state.mode);
+               break;
+       case I8042_CMD_CTL_WCTR:
+       case I8042_CMD_AUX_SEND:
+       case I8042_CMD_AUX_LOOP:
+               state.write_cmd = val;
+               break;
+       case I8042_CMD_AUX_TEST:
+               /* 0 means we're a normal PS/2 mouse */
+               mouse_queue(0);
+               break;
+       case I8042_CMD_AUX_DISABLE:
+               state.mode |= MODE_DISABLE_AUX;
+               break;
+       case I8042_CMD_AUX_ENABLE:
+               state.mode &= ~MODE_DISABLE_AUX;
+               break;
+       case I8042_CMD_SYSTEM_RESET:
+               kvm_cpu__reboot(kvm);
+               break;
+       default:
+               break;
+       }
+}
+
+/*
+ * Called when the OS reads from port 0x60 (PS/2 data)
+ */
+static u32 kbd_read_data(void)
+{
+       u32 ret;
+       int i;
+
+       if (state.kcount != 0) {
+               /* Keyboard data gets read first */
+               ret = state.kq[state.kread++ % QUEUE_SIZE];
+               state.kcount--;
+               kvm__irq_line(state.kvm, KBD_IRQ, 0);
+               kbd_update_irq();
+       } else if (state.mcount > 0) {
+               /* Followed by the mouse */
+               ret = state.mq[state.mread++ % QUEUE_SIZE];
+               state.mcount--;
+               kvm__irq_line(state.kvm, AUX_IRQ, 0);
+               kbd_update_irq();
+       } else if (state.kcount == 0) {
+               i = state.kread - 1;
+               if (i < 0)
+                       i = QUEUE_SIZE;
+               ret = state.kq[i];
+       }
+       return ret;
+}
+
+/*
+ * Called when the OS read from port 0x64, the command port
+ */
+static u32 kbd_read_status(void)
+{
+       return (u32)state.status;
+}
+
+/*
+ * Called when the OS writes to port 0x60 (data port)
+ * Things written here are generally arguments to commands previously
+ * written to port 0x64 and stored in state.write_cmd
+ */
+static void kbd_write_data(u32 val)
+{
+       switch (state.write_cmd) {
+       case I8042_CMD_CTL_WCTR:
+               state.mode = val;
+               kbd_update_irq();
+               break;
+       case I8042_CMD_AUX_LOOP:
+               mouse_queue(val);
+               mouse_queue(RESPONSE_ACK);
+               break;
+       case I8042_CMD_AUX_SEND:
+               /* The OS wants to send a command to the mouse */
+               mouse_queue(RESPONSE_ACK);
+               switch (val) {
+               case 0xe6:
+                       /* set scaling = 1:1 */
+                       state.mstatus &= ~AUX_SCALING_FLAG;
+                       break;
+               case 0xe8:
+                       /* set resolution */
+                       state.mres = val;
+                       break;
+               case 0xe9:
+                       /* Report mouse status/config */
+                       mouse_queue(state.mstatus);
+                       mouse_queue(state.mres);
+                       mouse_queue(state.msample);
+                       break;
+               case 0xf2:
+                       /* send ID */
+                       mouse_queue(0); /* normal mouse */
+                       break;
+               case 0xf3:
+                       /* set sample rate */
+                       state.msample = val;
+                       break;
+               case 0xf4:
+                       /* enable reporting */
+                       state.mstatus |= AUX_ENABLE_REPORTING;
+                       break;
+               case 0xf5:
+                       state.mstatus &= ~AUX_ENABLE_REPORTING;
+                       break;
+               case 0xf6:
+                       /* set defaults, just fall through to reset */
+               case 0xff:
+                       /* reset */
+                       state.mstatus = 0x0;
+                       state.mres = AUX_DEFAULT_RESOLUTION;
+                       state.msample = AUX_DEFAULT_SAMPLE;
+                       break;
+               default:
+                       break;
+       }
+       break;
+       case 0:
+               /* Just send the ID */
+               kbd_queue(RESPONSE_ACK);
+               kbd_queue(0xab);
+               kbd_queue(0x41);
+               kbd_update_irq();
+               break;
+       default:
+               /* Yeah whatever */
+               break;
+       }
+       state.write_cmd = 0;
+}
+
+static void kbd_reset(void)
+{
+       state = (struct kbd_state) {
+               .status         = I8042_STR_MUXERR | I8042_STR_CMDDAT | I8042_STR_KEYLOCK, /* 0x1c */
+               .mode           = KBD_MODE_KBD_INT | KBD_MODE_SYS, /* 0x3 */
+               .mres           = AUX_DEFAULT_RESOLUTION,
+               .msample        = AUX_DEFAULT_SAMPLE,
+       };
+}
+
+/*
+ * Called when the OS has written to one of the keyboard's ports (0x60 or 0x64)
+ */
+static bool kbd_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
+{
+       switch (port) {
+       case I8042_COMMAND_REG: {
+               u8 value = kbd_read_status();
+               ioport__write8(data, value);
+               break;
+       }
+       case I8042_DATA_REG: {
+               u32 value = kbd_read_data();
+               ioport__write32(data, value);
+               break;
+       }
+       default:
+               return false;
+       }
+
+       return true;
+}
+
+static bool kbd_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
+{
+       switch (port) {
+       case I8042_COMMAND_REG: {
+               u8 value = ioport__read8(data);
+               kbd_write_command(kvm, value);
+               break;
+       }
+       case I8042_DATA_REG: {
+               u32 value = ioport__read32(data);
+               kbd_write_data(value);
+               break;
+       }
+       default:
+               return false;
+       }
+
+       return true;
+}
+
+static struct ioport_operations kbd_ops = {
+       .io_in          = kbd_in,
+       .io_out         = kbd_out,
+};
+
+int kbd__init(struct kvm *kvm)
+{
+#ifndef CONFIG_X86
+       return 0;
+#endif
+
+       kbd_reset();
+       state.kvm = kvm;
+       ioport__register(kvm, I8042_DATA_REG, &kbd_ops, 2, NULL);
+       ioport__register(kvm, I8042_COMMAND_REG, &kbd_ops, 2, NULL);
+
+       return 0;
+}
+dev_init(kbd__init);
diff --git a/tools/kvm/hw/pci-shmem.c b/tools/kvm/hw/pci-shmem.c
new file mode 100644 (file)
index 0000000..4161335
--- /dev/null
@@ -0,0 +1,405 @@
+#include "kvm/pci-shmem.h"
+#include "kvm/virtio-pci-dev.h"
+#include "kvm/irq.h"
+#include "kvm/kvm.h"
+#include "kvm/pci.h"
+#include "kvm/util.h"
+#include "kvm/ioport.h"
+#include "kvm/ioeventfd.h"
+
+#include <linux/kvm.h>
+#include <linux/byteorder.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+
+#define MB_SHIFT (20)
+#define KB_SHIFT (10)
+#define GB_SHIFT (30)
+
+static struct pci_device_header pci_shmem_pci_device = {
+       .vendor_id      = cpu_to_le16(PCI_VENDOR_ID_REDHAT_QUMRANET),
+       .device_id      = cpu_to_le16(0x1110),
+       .header_type    = PCI_HEADER_TYPE_NORMAL,
+       .class[2]       = 0xFF, /* misc pci device */
+       .status         = cpu_to_le16(PCI_STATUS_CAP_LIST),
+       .capabilities   = (void *)&pci_shmem_pci_device.msix - (void *)&pci_shmem_pci_device,
+       .msix.cap       = PCI_CAP_ID_MSIX,
+       .msix.ctrl      = cpu_to_le16(1),
+       .msix.table_offset = cpu_to_le32(1),            /* Use BAR 1 */
+       .msix.pba_offset = cpu_to_le32(0x1001),         /* Use BAR 1 */
+};
+
+/* registers for the Inter-VM shared memory device */
+enum ivshmem_registers {
+       INTRMASK = 0,
+       INTRSTATUS = 4,
+       IVPOSITION = 8,
+       DOORBELL = 12,
+};
+
+static struct shmem_info *shmem_region;
+static u16 ivshmem_registers;
+static int local_fd;
+static u32 local_id;
+static u64 msix_block;
+static u64 msix_pba;
+static struct msix_table msix_table[2];
+
+int pci_shmem__register_mem(struct shmem_info *si)
+{
+       if (shmem_region == NULL) {
+               shmem_region = si;
+       } else {
+               pr_warning("only single shmem currently avail. ignoring.\n");
+               free(si);
+       }
+       return 0;
+}
+
+static bool shmem_pci__io_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
+{
+       u16 offset = port - ivshmem_registers;
+
+       switch (offset) {
+       case INTRMASK:
+               break;
+       case INTRSTATUS:
+               break;
+       case IVPOSITION:
+               ioport__write32(data, local_id);
+               break;
+       case DOORBELL:
+               break;
+       };
+
+       return true;
+}
+
+static bool shmem_pci__io_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
+{
+       u16 offset = port - ivshmem_registers;
+
+       switch (offset) {
+       case INTRMASK:
+               break;
+       case INTRSTATUS:
+               break;
+       case IVPOSITION:
+               break;
+       case DOORBELL:
+               break;
+       };
+
+       return true;
+}
+
+static struct ioport_operations shmem_pci__io_ops = {
+       .io_in  = shmem_pci__io_in,
+       .io_out = shmem_pci__io_out,
+};
+
+static void callback_mmio_msix(u64 addr, u8 *data, u32 len, u8 is_write, void *ptr)
+{
+       void *mem;
+
+       if (addr - msix_block < 0x1000)
+               mem = &msix_table;
+       else
+               mem = &msix_pba;
+
+       if (is_write)
+               memcpy(mem + addr - msix_block, data, len);
+       else
+               memcpy(data, mem + addr - msix_block, len);
+}
+
+/*
+ * Return an irqfd which can be used by other guests to signal this guest
+ * whenever they need to poke it
+ */
+int pci_shmem__get_local_irqfd(struct kvm *kvm)
+{
+       int fd, gsi, r;
+       struct kvm_irqfd irqfd;
+
+       if (local_fd == 0) {
+               fd = eventfd(0, 0);
+               if (fd < 0)
+                       return fd;
+
+               if (pci_shmem_pci_device.msix.ctrl & cpu_to_le16(PCI_MSIX_FLAGS_ENABLE)) {
+                       gsi = irq__add_msix_route(kvm, &msix_table[0].msg);
+               } else {
+                       gsi = pci_shmem_pci_device.irq_line;
+               }
+
+               irqfd = (struct kvm_irqfd) {
+                       .fd = fd,
+                       .gsi = gsi,
+               };
+
+               r = ioctl(kvm->vm_fd, KVM_IRQFD, &irqfd);
+               if (r < 0)
+                       return r;
+
+               local_fd = fd;
+       }
+
+       return local_fd;
+}
+
+/*
+ * Connect a new client to ivshmem by adding the appropriate datamatch
+ * to the DOORBELL
+ */
+int pci_shmem__add_client(struct kvm *kvm, u32 id, int fd)
+{
+       struct kvm_ioeventfd ioevent;
+
+       ioevent = (struct kvm_ioeventfd) {
+               .addr           = ivshmem_registers + DOORBELL,
+               .len            = sizeof(u32),
+               .datamatch      = id,
+               .fd             = fd,
+               .flags          = KVM_IOEVENTFD_FLAG_PIO | KVM_IOEVENTFD_FLAG_DATAMATCH,
+       };
+
+       return ioctl(kvm->vm_fd, KVM_IOEVENTFD, &ioevent);
+}
+
+/*
+ * Remove a client connected to ivshmem by removing the appropriate datamatch
+ * from the DOORBELL
+ */
+int pci_shmem__remove_client(struct kvm *kvm, u32 id)
+{
+       struct kvm_ioeventfd ioevent;
+
+       ioevent = (struct kvm_ioeventfd) {
+               .addr           = ivshmem_registers + DOORBELL,
+               .len            = sizeof(u32),
+               .datamatch      = id,
+               .flags          = KVM_IOEVENTFD_FLAG_PIO
+                               | KVM_IOEVENTFD_FLAG_DATAMATCH
+                               | KVM_IOEVENTFD_FLAG_DEASSIGN,
+       };
+
+       return ioctl(kvm->vm_fd, KVM_IOEVENTFD, &ioevent);
+}
+
+static void *setup_shmem(const char *key, size_t len, int creating)
+{
+       int fd;
+       int rtn;
+       void *mem;
+       int flag = O_RDWR;
+
+       if (creating)
+               flag |= O_CREAT;
+
+       fd = shm_open(key, flag, S_IRUSR | S_IWUSR);
+       if (fd < 0) {
+               pr_warning("Failed to open shared memory file %s\n", key);
+               return NULL;
+       }
+
+       if (creating) {
+               rtn = ftruncate(fd, (off_t) len);
+               if (rtn < 0)
+                       pr_warning("Can't ftruncate(fd,%zu)\n", len);
+       }
+       mem = mmap(NULL, len,
+                  PROT_READ | PROT_WRITE, MAP_SHARED | MAP_NORESERVE, fd, 0);
+       if (mem == MAP_FAILED) {
+               pr_warning("Failed to mmap shared memory file");
+               mem = NULL;
+       }
+       close(fd);
+
+       return mem;
+}
+
+int shmem_parser(const struct option *opt, const char *arg, int unset)
+{
+       const u64 default_size = SHMEM_DEFAULT_SIZE;
+       const u64 default_phys_addr = SHMEM_DEFAULT_ADDR;
+       const char *default_handle = SHMEM_DEFAULT_HANDLE;
+       struct shmem_info *si = malloc(sizeof(struct shmem_info));
+       u64 phys_addr;
+       u64 size;
+       char *handle = NULL;
+       int create = 0;
+       const char *p = arg;
+       char *next;
+       int base = 10;
+       int verbose = 0;
+
+       const int skip_pci = strlen("pci:");
+       if (verbose)
+               pr_info("shmem_parser(%p,%s,%d)", opt, arg, unset);
+       /* parse out optional addr family */
+       if (strcasestr(p, "pci:")) {
+               p += skip_pci;
+       } else if (strcasestr(p, "mem:")) {
+               die("I can't add to E820 map yet.\n");
+       }
+       /* parse out physical addr */
+       base = 10;
+       if (strcasestr(p, "0x"))
+               base = 16;
+       phys_addr = strtoll(p, &next, base);
+       if (next == p && phys_addr == 0) {
+               pr_info("shmem: no physical addr specified, using default.");
+               phys_addr = default_phys_addr;
+       }
+       if (*next != ':' && *next != '\0')
+               die("shmem: unexpected chars after phys addr.\n");
+       if (*next == '\0')
+               p = next;
+       else
+               p = next + 1;
+       /* parse out size */
+       base = 10;
+       if (strcasestr(p, "0x"))
+               base = 16;
+       size = strtoll(p, &next, base);
+       if (next == p && size == 0) {
+               pr_info("shmem: no size specified, using default.");
+               size = default_size;
+       }
+       /* look for [KMGkmg][Bb]*  uses base 2. */
+       int skip_B = 0;
+       if (strspn(next, "KMGkmg")) {   /* might have a prefix */
+               if (*(next + 1) == 'B' || *(next + 1) == 'b')
+                       skip_B = 1;
+               switch (*next) {
+               case 'K':
+               case 'k':
+                       size = size << KB_SHIFT;
+                       break;
+               case 'M':
+               case 'm':
+                       size = size << MB_SHIFT;
+                       break;
+               case 'G':
+               case 'g':
+                       size = size << GB_SHIFT;
+                       break;
+               default:
+                       die("shmem: bug in detecting size prefix.");
+                       break;
+               }
+               next += 1 + skip_B;
+       }
+       if (*next != ':' && *next != '\0') {
+               die("shmem: unexpected chars after phys size. <%c><%c>\n",
+                   *next, *p);
+       }
+       if (*next == '\0')
+               p = next;
+       else
+               p = next + 1;
+       /* parse out optional shmem handle */
+       const int skip_handle = strlen("handle=");
+       next = strcasestr(p, "handle=");
+       if (*p && next) {
+               if (p != next)
+                       die("unexpected chars before handle\n");
+               p += skip_handle;
+               next = strchrnul(p, ':');
+               if (next - p) {
+                       handle = malloc(next - p + 1);
+                       strncpy(handle, p, next - p);
+                       handle[next - p] = '\0';        /* just in case. */
+               }
+               if (*next == '\0')
+                       p = next;
+               else
+                       p = next + 1;
+       }
+       /* parse optional create flag to see if we should create shm seg. */
+       if (*p && strcasestr(p, "create")) {
+               create = 1;
+               p += strlen("create");
+       }
+       if (*p != '\0')
+               die("shmem: unexpected trailing chars\n");
+       if (handle == NULL) {
+               handle = malloc(strlen(default_handle) + 1);
+               strcpy(handle, default_handle);
+       }
+       if (verbose) {
+               pr_info("shmem: phys_addr = %llx", phys_addr);
+               pr_info("shmem: size      = %llx", size);
+               pr_info("shmem: handle    = %s", handle);
+               pr_info("shmem: create    = %d", create);
+       }
+
+       si->phys_addr = phys_addr;
+       si->size = size;
+       si->handle = handle;
+       si->create = create;
+       pci_shmem__register_mem(si);    /* ownership of si, etc. passed on. */
+       return 0;
+}
+
+int pci_shmem__init(struct kvm *kvm)
+{
+       u8 dev, line, pin;
+       char *mem;
+       int r;
+
+       if (shmem_region == 0)
+               return 0;
+
+       /* Register good old INTx */
+       r = irq__register_device(PCI_DEVICE_ID_PCI_SHMEM, &dev, &pin, &line);
+       if (r < 0)
+               return r;
+
+       pci_shmem_pci_device.irq_pin = pin;
+       pci_shmem_pci_device.irq_line = line;
+
+       /* Register MMIO space for MSI-X */
+       r = ioport__register(kvm, IOPORT_EMPTY, &shmem_pci__io_ops, IOPORT_SIZE, NULL);
+       if (r < 0)
+               return r;
+       ivshmem_registers = (u16)r;
+
+       msix_block = pci_get_io_space_block(0x1010);
+       kvm__register_mmio(kvm, msix_block, 0x1010, false, callback_mmio_msix, NULL);
+
+       /*
+        * This registers 3 BARs:
+        *
+        * 0 - ivshmem registers
+        * 1 - MSI-X MMIO space
+        * 2 - Shared memory block
+        */
+       pci_shmem_pci_device.bar[0] = cpu_to_le32(ivshmem_registers | PCI_BASE_ADDRESS_SPACE_IO);
+       pci_shmem_pci_device.bar_size[0] = shmem_region->size;
+       pci_shmem_pci_device.bar[1] = cpu_to_le32(msix_block | PCI_BASE_ADDRESS_SPACE_MEMORY);
+       pci_shmem_pci_device.bar_size[1] = 0x1010;
+       pci_shmem_pci_device.bar[2] = cpu_to_le32(shmem_region->phys_addr | PCI_BASE_ADDRESS_SPACE_MEMORY);
+       pci_shmem_pci_device.bar_size[2] = shmem_region->size;
+
+       pci__register(&pci_shmem_pci_device, dev);
+
+       /* Open shared memory and plug it into the guest */
+       mem = setup_shmem(shmem_region->handle, shmem_region->size,
+                               shmem_region->create);
+       if (mem == NULL)
+               return -EINVAL;
+
+       kvm__register_mem(kvm, shmem_region->phys_addr, shmem_region->size,
+                         mem);
+       return 0;
+}
+dev_init(pci_shmem__init);
+
+int pci_shmem__exit(struct kvm *kvm)
+{
+       return 0;
+}
+dev_exit(pci_shmem__exit);
diff --git a/tools/kvm/hw/rtc.c b/tools/kvm/hw/rtc.c
new file mode 100644 (file)
index 0000000..4a862d6
--- /dev/null
@@ -0,0 +1,149 @@
+#include "kvm/rtc.h"
+
+#include "kvm/ioport.h"
+#include "kvm/kvm.h"
+
+#include <time.h>
+
+/*
+ * MC146818 RTC registers
+ */
+#define RTC_SECONDS                    0x00
+#define RTC_SECONDS_ALARM              0x01
+#define RTC_MINUTES                    0x02
+#define RTC_MINUTES_ALARM              0x03
+#define RTC_HOURS                      0x04
+#define RTC_HOURS_ALARM                        0x05
+#define RTC_DAY_OF_WEEK                        0x06
+#define RTC_DAY_OF_MONTH               0x07
+#define RTC_MONTH                      0x08
+#define RTC_YEAR                       0x09
+
+#define RTC_REG_A                      0x0A
+#define RTC_REG_B                      0x0B
+#define RTC_REG_C                      0x0C
+#define RTC_REG_D                      0x0D
+
+struct rtc_device {
+       u8                      cmos_idx;
+       u8                      cmos_data[128];
+};
+
+static struct rtc_device       rtc;
+
+static inline unsigned char bin2bcd(unsigned val)
+{
+       return ((val / 10) << 4) + val % 10;
+}
+
+static bool cmos_ram_data_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
+{
+       struct tm *tm;
+       time_t ti;
+       int year;
+
+       time(&ti);
+
+       tm = gmtime(&ti);
+
+       switch (rtc.cmos_idx) {
+       case RTC_SECONDS:
+               ioport__write8(data, bin2bcd(tm->tm_sec));
+               break;
+       case RTC_MINUTES:
+               ioport__write8(data, bin2bcd(tm->tm_min));
+               break;
+       case RTC_HOURS:
+               ioport__write8(data, bin2bcd(tm->tm_hour));
+               break;
+       case RTC_DAY_OF_WEEK:
+               ioport__write8(data, bin2bcd(tm->tm_wday + 1));
+               break;
+       case RTC_DAY_OF_MONTH:
+               ioport__write8(data, bin2bcd(tm->tm_mday));
+               break;
+       case RTC_MONTH:
+               ioport__write8(data, bin2bcd(tm->tm_mon + 1));
+               break;
+       case RTC_YEAR:
+               /*
+                * The gmtime() function returns time since 1900. The CMOS
+                * standard is time since 2000. If the year is < 100, do
+                * nothing; if it is > 100, subtract 100; this is the best fit
+                * with the twisted CMOS logic.
+                */
+               year = tm->tm_year;
+               if (year > 99)
+                       year -= 100;
+               ioport__write8(data, bin2bcd(year));
+               break;
+       default:
+               ioport__write8(data, rtc.cmos_data[rtc.cmos_idx]);
+               break;
+       }
+
+       return true;
+}
+
+static bool cmos_ram_data_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
+{
+       switch (rtc.cmos_idx) {
+       case RTC_REG_C:
+       case RTC_REG_D:
+               /* Read-only */
+               break;
+       default:
+               rtc.cmos_data[rtc.cmos_idx] = ioport__read8(data);
+               break;
+       }
+
+       return true;
+}
+
+static struct ioport_operations cmos_ram_data_ioport_ops = {
+       .io_out         = cmos_ram_data_out,
+       .io_in          = cmos_ram_data_in,
+};
+
+static bool cmos_ram_index_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
+{
+       u8 value = ioport__read8(data);
+
+       kvm->nmi_disabled       = value & (1UL << 7);
+       rtc.cmos_idx            = value & ~(1UL << 7);
+
+       return true;
+}
+
+static struct ioport_operations cmos_ram_index_ioport_ops = {
+       .io_out         = cmos_ram_index_out,
+};
+
+int rtc__init(struct kvm *kvm)
+{
+       int r = 0;
+
+       /* PORT 0070-007F - CMOS RAM/RTC (REAL TIME CLOCK) */
+       r = ioport__register(kvm, 0x0070, &cmos_ram_index_ioport_ops, 1, NULL);
+       if (r < 0)
+               return r;
+
+       r = ioport__register(kvm, 0x0071, &cmos_ram_data_ioport_ops, 1, NULL);
+       if (r < 0) {
+               ioport__unregister(kvm, 0x0071);
+               return r;
+       }
+
+       return r;
+}
+dev_init(rtc__init);
+
+int rtc__exit(struct kvm *kvm)
+{
+       /* PORT 0070-007F - CMOS RAM/RTC (REAL TIME CLOCK) */
+       ioport__unregister(kvm, 0x0070);
+       ioport__unregister(kvm, 0x0071);
+
+       return 0;
+}
+dev_exit(rtc__exit);
diff --git a/tools/kvm/hw/serial.c b/tools/kvm/hw/serial.c
new file mode 100644 (file)
index 0000000..a177a7f
--- /dev/null
@@ -0,0 +1,452 @@
+#include "kvm/8250-serial.h"
+
+#include "kvm/read-write.h"
+#include "kvm/ioport.h"
+#include "kvm/mutex.h"
+#include "kvm/util.h"
+#include "kvm/term.h"
+#include "kvm/kvm.h"
+
+#include <linux/types.h>
+#include <linux/serial_reg.h>
+
+#include <pthread.h>
+
+/*
+ * This fakes a U6_16550A. The fifo len needs to be 64 as the kernel
+ * expects that for autodetection.
+ */
+#define FIFO_LEN               64
+#define FIFO_MASK              (FIFO_LEN - 1)
+
+#define UART_IIR_TYPE_BITS     0xc0
+
+struct serial8250_device {
+       pthread_mutex_t         mutex;
+       u8                      id;
+
+       u16                     iobase;
+       u8                      irq;
+       u8                      irq_state;
+       int                     txcnt;
+       int                     rxcnt;
+       int                     rxdone;
+       char                    txbuf[FIFO_LEN];
+       char                    rxbuf[FIFO_LEN];
+
+       u8                      dll;
+       u8                      dlm;
+       u8                      iir;
+       u8                      ier;
+       u8                      fcr;
+       u8                      lcr;
+       u8                      mcr;
+       u8                      lsr;
+       u8                      msr;
+       u8                      scr;
+};
+
+#define SERIAL_REGS_SETTING \
+       .iir                    = UART_IIR_NO_INT, \
+       .lsr                    = UART_LSR_TEMT | UART_LSR_THRE, \
+       .msr                    = UART_MSR_DCD | UART_MSR_DSR | UART_MSR_CTS, \
+       .mcr                    = UART_MCR_OUT2,
+
+static struct serial8250_device devices[] = {
+       /* ttyS0 */
+       [0]     = {
+               .mutex                  = PTHREAD_MUTEX_INITIALIZER,
+
+               .id                     = 0,
+               .iobase                 = 0x3f8,
+               .irq                    = 4,
+
+               SERIAL_REGS_SETTING
+       },
+       /* ttyS1 */
+       [1]     = {
+               .mutex                  = PTHREAD_MUTEX_INITIALIZER,
+
+               .id                     = 1,
+               .iobase                 = 0x2f8,
+               .irq                    = 3,
+
+               SERIAL_REGS_SETTING
+       },
+       /* ttyS2 */
+       [2]     = {
+               .mutex                  = PTHREAD_MUTEX_INITIALIZER,
+
+               .id                     = 2,
+               .iobase                 = 0x3e8,
+               .irq                    = 4,
+
+               SERIAL_REGS_SETTING
+       },
+       /* ttyS3 */
+       [3]     = {
+               .mutex                  = PTHREAD_MUTEX_INITIALIZER,
+
+               .id                     = 3,
+               .iobase                 = 0x2e8,
+               .irq                    = 3,
+
+               SERIAL_REGS_SETTING
+       },
+};
+
+static void serial8250_flush_tx(struct kvm *kvm, struct serial8250_device *dev)
+{
+       dev->lsr |= UART_LSR_TEMT | UART_LSR_THRE;
+
+       if (dev->txcnt) {
+               if (kvm->cfg.active_console == CONSOLE_8250)
+                       term_putc(dev->txbuf, dev->txcnt, dev->id);
+               dev->txcnt = 0;
+       }
+}
+
+static void serial8250_update_irq(struct kvm *kvm, struct serial8250_device *dev)
+{
+       u8 iir = 0;
+
+       /* Handle clear rx */
+       if (dev->lcr & UART_FCR_CLEAR_RCVR) {
+               dev->lcr &= ~UART_FCR_CLEAR_RCVR;
+               dev->rxcnt = dev->rxdone = 0;
+               dev->lsr &= ~UART_LSR_DR;
+       }
+
+       /* Handle clear tx */
+       if (dev->lcr & UART_FCR_CLEAR_XMIT) {
+               dev->lcr &= ~UART_FCR_CLEAR_XMIT;
+               dev->txcnt = 0;
+               dev->lsr |= UART_LSR_TEMT | UART_LSR_THRE;
+       }
+
+       /* Data ready and rcv interrupt enabled ? */
+       if ((dev->ier & UART_IER_RDI) && (dev->lsr & UART_LSR_DR))
+               iir |= UART_IIR_RDI;
+
+       /* Transmitter empty and interrupt enabled ? */
+       if ((dev->ier & UART_IER_THRI) && (dev->lsr & UART_LSR_TEMT))
+               iir |= UART_IIR_THRI;
+
+       /* Now update the irq line, if necessary */
+       if (!iir) {
+               dev->iir = UART_IIR_NO_INT;
+               if (dev->irq_state)
+                       kvm__irq_line(kvm, dev->irq, 0);
+       } else {
+               dev->iir = iir;
+               if (!dev->irq_state)
+                       kvm__irq_line(kvm, dev->irq, 1);
+       }
+       dev->irq_state = iir;
+
+       /*
+        * If the kernel disabled the tx interrupt, we know that there
+        * is nothing more to transmit, so we can reset our tx logic
+        * here.
+        */
+       if (!(dev->ier & UART_IER_THRI))
+               serial8250_flush_tx(kvm, dev);
+}
+
+#define SYSRQ_PENDING_NONE             0
+
+static int sysrq_pending;
+
+static void serial8250__sysrq(struct kvm *kvm, struct serial8250_device *dev)
+{
+       dev->lsr |= UART_LSR_DR | UART_LSR_BI;
+       dev->rxbuf[dev->rxcnt++] = sysrq_pending;
+       sysrq_pending   = SYSRQ_PENDING_NONE;
+}
+
+static void serial8250__receive(struct kvm *kvm, struct serial8250_device *dev,
+                               bool handle_sysrq)
+{
+       int c;
+
+       /*
+        * If the guest transmitted a full fifo, we clear the
+        * TEMT/THRE bits to let the kernel escape from the 8250
+        * interrupt handler. We come here only once a ms, so that
+        * should give the kernel the desired pause. That also flushes
+        * the tx fifo to the terminal.
+        */
+       serial8250_flush_tx(kvm, dev);
+
+       if (dev->mcr & UART_MCR_LOOP)
+               return;
+
+       if ((dev->lsr & UART_LSR_DR) || dev->rxcnt)
+               return;
+
+       if (handle_sysrq && sysrq_pending) {
+               serial8250__sysrq(kvm, dev);
+               return;
+       }
+
+       if (kvm->cfg.active_console != CONSOLE_8250)
+               return;
+
+       while (term_readable(dev->id) &&
+              dev->rxcnt < FIFO_LEN) {
+
+               c = term_getc(kvm, dev->id);
+
+               if (c < 0)
+                       break;
+               dev->rxbuf[dev->rxcnt++] = c;
+               dev->lsr |= UART_LSR_DR;
+       }
+}
+
+void serial8250__update_consoles(struct kvm *kvm)
+{
+       unsigned int i;
+
+       for (i = 0; i < ARRAY_SIZE(devices); i++) {
+               struct serial8250_device *dev = &devices[i];
+
+               mutex_lock(&dev->mutex);
+
+               /* Restrict sysrq injection to the first port */
+               serial8250__receive(kvm, dev, i == 0);
+
+               serial8250_update_irq(kvm, dev);
+
+               mutex_unlock(&dev->mutex);
+       }
+}
+
+void serial8250__inject_sysrq(struct kvm *kvm, char sysrq)
+{
+       sysrq_pending = sysrq;
+}
+
+static struct serial8250_device *find_device(u16 port)
+{
+       unsigned int i;
+
+       for (i = 0; i < ARRAY_SIZE(devices); i++) {
+               struct serial8250_device *dev = &devices[i];
+
+               if (dev->iobase == (port & ~0x7))
+                       return dev;
+       }
+       return NULL;
+}
+
+static bool serial8250_out(struct ioport *ioport, struct kvm *kvm, u16 port,
+                          void *data, int size)
+{
+       struct serial8250_device *dev;
+       u16 offset;
+       bool ret = true;
+       char *addr = data;
+
+       dev = find_device(port);
+       if (!dev)
+               return false;
+
+       mutex_lock(&dev->mutex);
+
+       offset = port - dev->iobase;
+
+       switch (offset) {
+       case UART_TX:
+               if (dev->lcr & UART_LCR_DLAB) {
+                       dev->dll = ioport__read8(data);
+                       break;
+               }
+
+               /* Loopback mode */
+               if (dev->mcr & UART_MCR_LOOP) {
+                       if (dev->rxcnt < FIFO_LEN) {
+                               dev->rxbuf[dev->rxcnt++] = *addr;
+                               dev->lsr |= UART_LSR_DR;
+                       }
+                       break;
+               }
+
+               if (dev->txcnt < FIFO_LEN) {
+                       dev->txbuf[dev->txcnt++] = *addr;
+                       dev->lsr &= ~UART_LSR_TEMT;
+                       if (dev->txcnt == FIFO_LEN / 2)
+                               dev->lsr &= ~UART_LSR_THRE;
+               } else {
+                       /* Should never happpen */
+                       dev->lsr &= ~(UART_LSR_TEMT | UART_LSR_THRE);
+               }
+               break;
+       case UART_IER:
+               if (!(dev->lcr & UART_LCR_DLAB))
+                       dev->ier = ioport__read8(data) & 0x0f;
+               else
+                       dev->dlm = ioport__read8(data);
+               break;
+       case UART_FCR:
+               dev->fcr = ioport__read8(data);
+               break;
+       case UART_LCR:
+               dev->lcr = ioport__read8(data);
+               break;
+       case UART_MCR:
+               dev->mcr = ioport__read8(data);
+               break;
+       case UART_LSR:
+               /* Factory test */
+               break;
+       case UART_MSR:
+               /* Not used */
+               break;
+       case UART_SCR:
+               dev->scr = ioport__read8(data);
+               break;
+       default:
+               ret = false;
+               break;
+       }
+
+       serial8250_update_irq(kvm, dev);
+
+       mutex_unlock(&dev->mutex);
+
+       return ret;
+}
+
+static void serial8250_rx(struct serial8250_device *dev, void *data)
+{
+       if (dev->rxdone == dev->rxcnt)
+               return;
+
+       /* Break issued ? */
+       if (dev->lsr & UART_LSR_BI) {
+               dev->lsr &= ~UART_LSR_BI;
+               ioport__write8(data, 0);
+               return;
+       }
+
+       ioport__write8(data, dev->rxbuf[dev->rxdone++]);
+       if (dev->rxcnt == dev->rxdone) {
+               dev->lsr &= ~UART_LSR_DR;
+               dev->rxcnt = dev->rxdone = 0;
+       }
+}
+
+static bool serial8250_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
+{
+       struct serial8250_device *dev;
+       u16 offset;
+       bool ret = true;
+
+       dev = find_device(port);
+       if (!dev)
+               return false;
+
+       mutex_lock(&dev->mutex);
+
+       offset = port - dev->iobase;
+
+       switch (offset) {
+       case UART_RX:
+               if (dev->lcr & UART_LCR_DLAB)
+                       ioport__write8(data, dev->dll);
+               else
+                       serial8250_rx(dev, data);
+               break;
+       case UART_IER:
+               if (dev->lcr & UART_LCR_DLAB)
+                       ioport__write8(data, dev->dlm);
+               else
+                       ioport__write8(data, dev->ier);
+               break;
+       case UART_IIR:
+               ioport__write8(data, dev->iir | UART_IIR_TYPE_BITS);
+               break;
+       case UART_LCR:
+               ioport__write8(data, dev->lcr);
+               break;
+       case UART_MCR:
+               ioport__write8(data, dev->mcr);
+               break;
+       case UART_LSR:
+               ioport__write8(data, dev->lsr);
+               break;
+       case UART_MSR:
+               ioport__write8(data, dev->msr);
+               break;
+       case UART_SCR:
+               ioport__write8(data, dev->scr);
+               break;
+       default:
+               ret = false;
+               break;
+       }
+
+       serial8250_update_irq(kvm, dev);
+
+       mutex_unlock(&dev->mutex);
+
+       return ret;
+}
+
+static struct ioport_operations serial8250_ops = {
+       .io_in          = serial8250_in,
+       .io_out         = serial8250_out,
+};
+
+static int serial8250__device_init(struct kvm *kvm, struct serial8250_device *dev)
+{
+       int r;
+
+       r = ioport__register(kvm, dev->iobase, &serial8250_ops, 8, NULL);
+       kvm__irq_line(kvm, dev->irq, 0);
+
+       return r;
+}
+
+int serial8250__init(struct kvm *kvm)
+{
+       unsigned int i, j;
+       int r = 0;
+
+       for (i = 0; i < ARRAY_SIZE(devices); i++) {
+               struct serial8250_device *dev = &devices[i];
+
+               r = serial8250__device_init(kvm, dev);
+               if (r < 0)
+                       goto cleanup;
+       }
+
+       return r;
+cleanup:
+       for (j = 0; j <= i; j++) {
+               struct serial8250_device *dev = &devices[j];
+
+               ioport__unregister(kvm, dev->iobase);
+       }
+
+       return r;
+}
+dev_init(serial8250__init);
+
+int serial8250__exit(struct kvm *kvm)
+{
+       unsigned int i;
+       int r;
+
+       for (i = 0; i < ARRAY_SIZE(devices); i++) {
+               struct serial8250_device *dev = &devices[i];
+
+               r = ioport__unregister(kvm, dev->iobase);
+               if (r < 0)
+                       return r;
+       }
+
+       return 0;
+}
+dev_exit(serial8250__exit);
diff --git a/tools/kvm/hw/vesa.c b/tools/kvm/hw/vesa.c
new file mode 100644 (file)
index 0000000..a211491
--- /dev/null
@@ -0,0 +1,89 @@
+#include "kvm/vesa.h"
+
+#include "kvm/virtio-pci-dev.h"
+#include "kvm/framebuffer.h"
+#include "kvm/kvm-cpu.h"
+#include "kvm/ioport.h"
+#include "kvm/util.h"
+#include "kvm/irq.h"
+#include "kvm/kvm.h"
+#include "kvm/pci.h"
+
+#include <linux/byteorder.h>
+#include <sys/mman.h>
+#include <linux/err.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <inttypes.h>
+#include <unistd.h>
+
+static bool vesa_pci_io_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
+{
+       return true;
+}
+
+static bool vesa_pci_io_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
+{
+       return true;
+}
+
+static struct ioport_operations vesa_io_ops = {
+       .io_in                  = vesa_pci_io_in,
+       .io_out                 = vesa_pci_io_out,
+};
+
+static struct pci_device_header vesa_pci_device = {
+       .vendor_id              = cpu_to_le16(PCI_VENDOR_ID_REDHAT_QUMRANET),
+       .device_id              = cpu_to_le16(PCI_DEVICE_ID_VESA),
+       .header_type            = PCI_HEADER_TYPE_NORMAL,
+       .revision_id            = 0,
+       .class[2]               = 0x03,
+       .subsys_vendor_id       = cpu_to_le16(PCI_SUBSYSTEM_VENDOR_ID_REDHAT_QUMRANET),
+       .subsys_id              = cpu_to_le16(PCI_SUBSYSTEM_ID_VESA),
+       .bar[1]                 = cpu_to_le32(VESA_MEM_ADDR | PCI_BASE_ADDRESS_SPACE_MEMORY),
+       .bar_size[1]            = VESA_MEM_SIZE,
+};
+
+static struct framebuffer vesafb;
+
+struct framebuffer *vesa__init(struct kvm *kvm)
+{
+       u16 vesa_base_addr;
+       u8 dev, line, pin;
+       char *mem;
+       int r;
+
+       if (!kvm->cfg.vnc && !kvm->cfg.sdl)
+               return NULL;
+
+       r = irq__register_device(PCI_DEVICE_ID_VESA, &dev, &pin, &line);
+       if (r < 0)
+               return ERR_PTR(r);
+
+       r = ioport__register(kvm, IOPORT_EMPTY, &vesa_io_ops, IOPORT_SIZE, NULL);
+       if (r < 0)
+               return ERR_PTR(r);
+
+       vesa_pci_device.irq_pin         = pin;
+       vesa_pci_device.irq_line        = line;
+       vesa_base_addr                  = (u16)r;
+       vesa_pci_device.bar[0]          = cpu_to_le32(vesa_base_addr | PCI_BASE_ADDRESS_SPACE_IO);
+       pci__register(&vesa_pci_device, dev);
+
+       mem = mmap(NULL, VESA_MEM_SIZE, PROT_RW, MAP_ANON_NORESERVE, -1, 0);
+       if (mem == MAP_FAILED)
+               ERR_PTR(-errno);
+
+       kvm__register_mem(kvm, VESA_MEM_ADDR, VESA_MEM_SIZE, mem);
+
+       vesafb = (struct framebuffer) {
+               .width                  = VESA_WIDTH,
+               .height                 = VESA_HEIGHT,
+               .depth                  = VESA_BPP,
+               .mem                    = mem,
+               .mem_addr               = VESA_MEM_ADDR,
+               .mem_size               = VESA_MEM_SIZE,
+               .kvm                    = kvm,
+       };
+       return fb__register(&vesafb);
+}
diff --git a/tools/kvm/include/asm/hweight.h b/tools/kvm/include/asm/hweight.h
new file mode 100644 (file)
index 0000000..1a43977
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef _KVM_ASM_HWEIGHT_H_
+#define _KVM_ASM_HWEIGHT_H_
+
+#include <linux/types.h>
+unsigned int hweight32(unsigned int w);
+unsigned long hweight64(__u64 w);
+
+#endif /* _KVM_ASM_HWEIGHT_H_ */
diff --git a/tools/kvm/include/bios/memcpy.h b/tools/kvm/include/bios/memcpy.h
new file mode 100644 (file)
index 0000000..e021044
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef KVM_BIOS_MEMCPY_H
+#define KVM_BIOS_MEMCPY_H
+
+#include <linux/types.h>
+#include <stddef.h>
+
+void memcpy16(u16 dst_seg, void *dst, u16 src_seg, const void *src, size_t len);
+
+#endif /* KVM_BIOS_MEMCPY_H */
diff --git a/tools/kvm/include/kvm/8250-serial.h b/tools/kvm/include/kvm/8250-serial.h
new file mode 100644 (file)
index 0000000..e954551
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef KVM__8250_SERIAL_H
+#define KVM__8250_SERIAL_H
+
+struct kvm;
+
+int serial8250__init(struct kvm *kvm);
+int serial8250__exit(struct kvm *kvm);
+void serial8250__update_consoles(struct kvm *kvm);
+void serial8250__inject_sysrq(struct kvm *kvm, char sysrq);
+
+#endif /* KVM__8250_SERIAL_H */
diff --git a/tools/kvm/include/kvm/apic.h b/tools/kvm/include/kvm/apic.h
new file mode 100644 (file)
index 0000000..2129997
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef KVM_APIC_H_
+#define KVM_APIC_H_
+
+#include <asm/apicdef.h>
+
+/*
+ * APIC, IOAPIC stuff
+ */
+#define APIC_BASE_ADDR_STEP    0x00400000
+#define IOAPIC_BASE_ADDR_STEP  0x00100000
+
+#define APIC_ADDR(apic)                (APIC_DEFAULT_PHYS_BASE + apic * APIC_BASE_ADDR_STEP)
+#define IOAPIC_ADDR(ioapic)    (IO_APIC_DEFAULT_PHYS_BASE + ioapic * IOAPIC_BASE_ADDR_STEP)
+
+#define KVM_APIC_VERSION       0x14 /* xAPIC */
+
+#endif /* KVM_APIC_H_ */
diff --git a/tools/kvm/include/kvm/brlock.h b/tools/kvm/include/kvm/brlock.h
new file mode 100644 (file)
index 0000000..29f72e0
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef KVM__BRLOCK_H
+#define KVM__BRLOCK_H
+
+#include "kvm/kvm.h"
+#include "kvm/barrier.h"
+
+/*
+ * brlock is a lock which is very cheap for reads, but very expensive
+ * for writes.
+ * This lock will be used when updates are very rare and reads are common.
+ * This lock is currently implemented by stopping the guest while
+ * performing the updates. We assume that the only threads whichread from
+ * the locked data are VCPU threads, and the only writer isn't a VCPU thread.
+ */
+
+#ifndef barrier
+#define barrier()              __asm__ __volatile__("": : :"memory")
+#endif
+
+#ifdef KVM_BRLOCK_DEBUG
+
+#include "kvm/rwsem.h"
+
+DECLARE_RWSEM(brlock_sem);
+
+#define br_read_lock(kvm)      down_read(&brlock_sem);
+#define br_read_unlock(kvm)    up_read(&brlock_sem);
+
+#define br_write_lock(kvm)     down_write(&brlock_sem);
+#define br_write_unlock(kvm)   up_write(&brlock_sem);
+
+#else
+
+#define br_read_lock(kvm)      barrier()
+#define br_read_unlock(kvm)    barrier()
+
+#define br_write_lock(kvm)     kvm__pause(kvm)
+#define br_write_unlock(kvm)   kvm__continue(kvm)
+#endif
+
+#endif
diff --git a/tools/kvm/include/kvm/builtin-balloon.h b/tools/kvm/include/kvm/builtin-balloon.h
new file mode 100644 (file)
index 0000000..77ee656
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef KVM__BALLOON_H
+#define KVM__BALLOON_H
+
+#include <kvm/util.h>
+
+int kvm_cmd_balloon(int argc, const char **argv, const char *prefix);
+void kvm_balloon_help(void) NORETURN;
+
+#endif
diff --git a/tools/kvm/include/kvm/builtin-debug.h b/tools/kvm/include/kvm/builtin-debug.h
new file mode 100644 (file)
index 0000000..efa0268
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef KVM__DEBUG_H
+#define KVM__DEBUG_H
+
+#include <kvm/util.h>
+#include <linux/types.h>
+
+#define KVM_DEBUG_CMD_TYPE_DUMP        (1 << 0)
+#define KVM_DEBUG_CMD_TYPE_NMI (1 << 1)
+#define KVM_DEBUG_CMD_TYPE_SYSRQ (1 << 2)
+
+struct debug_cmd_params {
+       u32 dbg_type;
+       u32 cpu;
+       char sysrq;
+};
+
+int kvm_cmd_debug(int argc, const char **argv, const char *prefix);
+void kvm_debug_help(void) NORETURN;
+
+#endif
diff --git a/tools/kvm/include/kvm/builtin-help.h b/tools/kvm/include/kvm/builtin-help.h
new file mode 100644 (file)
index 0000000..2946743
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __KVM_HELP_H__
+#define __KVM_HELP_H__
+
+int kvm_cmd_help(int argc, const char **argv, const char *prefix);
+
+#endif
diff --git a/tools/kvm/include/kvm/builtin-list.h b/tools/kvm/include/kvm/builtin-list.h
new file mode 100644 (file)
index 0000000..47029ca
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef KVM__LIST_H
+#define KVM__LIST_H
+
+#include <kvm/util.h>
+
+int kvm_cmd_list(int argc, const char **argv, const char *prefix);
+void kvm_list_help(void) NORETURN;
+int get_vmstate(int sock);
+
+#endif
diff --git a/tools/kvm/include/kvm/builtin-pause.h b/tools/kvm/include/kvm/builtin-pause.h
new file mode 100644 (file)
index 0000000..84aaee3
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef KVM__PAUSE_H
+#define KVM__PAUSE_H
+
+#include <kvm/util.h>
+
+int kvm_cmd_pause(int argc, const char **argv, const char *prefix);
+void kvm_pause_help(void) NORETURN;
+
+#endif
diff --git a/tools/kvm/include/kvm/builtin-resume.h b/tools/kvm/include/kvm/builtin-resume.h
new file mode 100644 (file)
index 0000000..7de999b
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef KVM__RESUME_H
+#define KVM__RESUME_H
+
+#include <kvm/util.h>
+
+int kvm_cmd_resume(int argc, const char **argv, const char *prefix);
+void kvm_resume_help(void) NORETURN;
+
+#endif
diff --git a/tools/kvm/include/kvm/builtin-run.h b/tools/kvm/include/kvm/builtin-run.h
new file mode 100644 (file)
index 0000000..91521a5
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef __KVM_RUN_H__
+#define __KVM_RUN_H__
+
+#include <kvm/util.h>
+
+int kvm_cmd_run(int argc, const char **argv, const char *prefix);
+void kvm_run_help(void) NORETURN;
+
+void kvm_run_set_wrapper_sandbox(void);
+
+#endif
diff --git a/tools/kvm/include/kvm/builtin-sandbox.h b/tools/kvm/include/kvm/builtin-sandbox.h
new file mode 100644 (file)
index 0000000..98cd6be
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef KVM__SANDBOX_H
+#define KVM__SANDBOX_H
+
+int kvm_cmd_sandbox(int argc, const char **argv, const char *prefix);
+
+#endif
diff --git a/tools/kvm/include/kvm/builtin-setup.h b/tools/kvm/include/kvm/builtin-setup.h
new file mode 100644 (file)
index 0000000..4a8d7ee
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef KVM__SETUP_H
+#define KVM__SETUP_H
+
+#include <kvm/util.h>
+
+int kvm_cmd_setup(int argc, const char **argv, const char *prefix);
+void kvm_setup_help(void) NORETURN;
+int kvm_setup_create_new(const char *guestfs_name);
+void kvm_setup_resolv(const char *guestfs_name);
+
+#endif
diff --git a/tools/kvm/include/kvm/builtin-stat.h b/tools/kvm/include/kvm/builtin-stat.h
new file mode 100644 (file)
index 0000000..4fecb37
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef KVM__STAT_H
+#define KVM__STAT_H
+
+#include <kvm/util.h>
+
+int kvm_cmd_stat(int argc, const char **argv, const char *prefix);
+void kvm_stat_help(void) NORETURN;
+
+#endif
diff --git a/tools/kvm/include/kvm/builtin-stop.h b/tools/kvm/include/kvm/builtin-stop.h
new file mode 100644 (file)
index 0000000..b26b275
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef KVM__STOP_H
+#define KVM__STOP_H
+
+#include <kvm/util.h>
+
+int kvm_cmd_stop(int argc, const char **argv, const char *prefix);
+void kvm_stop_help(void) NORETURN;
+
+#endif
diff --git a/tools/kvm/include/kvm/builtin-version.h b/tools/kvm/include/kvm/builtin-version.h
new file mode 100644 (file)
index 0000000..83cac4d
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef KVM__VERSION_H
+#define KVM__VERSION_H
+
+int kvm_cmd_version(int argc, const char **argv, const char *prefix);
+
+#endif
diff --git a/tools/kvm/include/kvm/compiler.h b/tools/kvm/include/kvm/compiler.h
new file mode 100644 (file)
index 0000000..2013a83
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef KVM_COMPILER_H_
+#define KVM_COMPILER_H_
+
+#ifndef __compiletime_error
+# define __compiletime_error(message)
+#endif
+
+#define notrace __attribute__((no_instrument_function))
+
+#endif /* KVM_COMPILER_H_ */
diff --git a/tools/kvm/include/kvm/disk-image.h b/tools/kvm/include/kvm/disk-image.h
new file mode 100644 (file)
index 0000000..b728052
--- /dev/null
@@ -0,0 +1,96 @@
+#ifndef KVM__DISK_IMAGE_H
+#define KVM__DISK_IMAGE_H
+
+#include "kvm/read-write.h"
+#include "kvm/util.h"
+#include "kvm/parse-options.h"
+
+#include <linux/types.h>
+#include <linux/fs.h>  /* for BLKGETSIZE64 */
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <stdbool.h>
+#include <sys/uio.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#define SECTOR_SHIFT           9
+#define SECTOR_SIZE            (1UL << SECTOR_SHIFT)
+
+enum {
+       DISK_IMAGE_REGULAR,
+       DISK_IMAGE_MMAP,
+};
+
+#define MAX_DISK_IMAGES         4
+
+struct disk_image;
+
+struct disk_image_operations {
+       ssize_t (*read)(struct disk_image *disk, u64 sector, const struct iovec *iov,
+                       int iovcount, void *param);
+       ssize_t (*write)(struct disk_image *disk, u64 sector, const struct iovec *iov,
+                       int iovcount, void *param);
+       int (*flush)(struct disk_image *disk);
+       int (*close)(struct disk_image *disk);
+};
+
+struct disk_image_params {
+       const char *filename;
+       /*
+        * wwpn == World Wide Port Number
+        * tpgt == Target Portal Group Tag
+        */
+       const char *wwpn;
+       const char *tpgt;
+       bool readonly;
+       bool direct;
+};
+
+struct disk_image {
+       int                             fd;
+       u64                             size;
+       struct disk_image_operations    *ops;
+       void                            *priv;
+       void                            *disk_req_cb_param;
+       void                            (*disk_req_cb)(void *param, long len);
+       bool                            async;
+       int                             evt;
+#ifdef CONFIG_HAS_AIO
+       io_context_t                    ctx;
+#endif
+       const char                      *wwpn;
+       const char                      *tpgt;
+       int                             debug_iodelay;
+};
+
+int disk_img_name_parser(const struct option *opt, const char *arg, int unset);
+int disk_image__init(struct kvm *kvm);
+int disk_image__exit(struct kvm *kvm);
+struct disk_image *disk_image__new(int fd, u64 size, struct disk_image_operations *ops, int mmap);
+int disk_image__flush(struct disk_image *disk);
+ssize_t disk_image__read(struct disk_image *disk, u64 sector, const struct iovec *iov,
+                               int iovcount, void *param);
+ssize_t disk_image__write(struct disk_image *disk, u64 sector, const struct iovec *iov,
+                               int iovcount, void *param);
+ssize_t disk_image__get_serial(struct disk_image *disk, void *buffer, ssize_t *len);
+
+struct disk_image *raw_image__probe(int fd, struct stat *st, bool readonly);
+struct disk_image *blkdev__probe(const char *filename, int flags, struct stat *st);
+
+ssize_t raw_image__read(struct disk_image *disk, u64 sector,
+                               const struct iovec *iov, int iovcount, void *param);
+ssize_t raw_image__write(struct disk_image *disk, u64 sector,
+                               const struct iovec *iov, int iovcount, void *param);
+ssize_t raw_image__read_mmap(struct disk_image *disk, u64 sector,
+                               const struct iovec *iov, int iovcount, void *param);
+ssize_t raw_image__write_mmap(struct disk_image *disk, u64 sector,
+                               const struct iovec *iov, int iovcount, void *param);
+int raw_image__close(struct disk_image *disk);
+void disk_image__set_callback(struct disk_image *disk, void (*disk_req_cb)(void *param, long len));
+#endif /* KVM__DISK_IMAGE_H */
diff --git a/tools/kvm/include/kvm/e820.h b/tools/kvm/include/kvm/e820.h
new file mode 100644 (file)
index 0000000..15f62cc
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef KVM_E820_H
+#define KVM_E820_H
+
+#include <linux/types.h>
+#include <kvm/bios.h>
+
+#define SMAP    0x534d4150      /* ASCII "SMAP" */
+
+struct biosregs;
+
+extern bioscall void e820_query_map(struct biosregs *regs);
+
+#endif /* KVM_E820_H */
diff --git a/tools/kvm/include/kvm/framebuffer.h b/tools/kvm/include/kvm/framebuffer.h
new file mode 100644 (file)
index 0000000..e3200e5
--- /dev/null
@@ -0,0 +1,36 @@
+#ifndef KVM__FRAMEBUFFER_H
+#define KVM__FRAMEBUFFER_H
+
+#include <linux/types.h>
+#include <linux/list.h>
+
+struct framebuffer;
+
+struct fb_target_operations {
+       int (*start)(struct framebuffer *fb);
+       int (*stop)(struct framebuffer *fb);
+};
+
+#define FB_MAX_TARGETS                 2
+
+struct framebuffer {
+       struct list_head                node;
+
+       u32                             width;
+       u32                             height;
+       u8                              depth;
+       char                            *mem;
+       u64                             mem_addr;
+       u64                             mem_size;
+       struct kvm                      *kvm;
+
+       unsigned long                   nr_targets;
+       struct fb_target_operations     *targets[FB_MAX_TARGETS];
+};
+
+struct framebuffer *fb__register(struct framebuffer *fb);
+int fb__attach(struct framebuffer *fb, struct fb_target_operations *ops);
+int fb__init(struct kvm *kvm);
+int fb__exit(struct kvm *kvm);
+
+#endif /* KVM__FRAMEBUFFER_H */
diff --git a/tools/kvm/include/kvm/guest_compat.h b/tools/kvm/include/kvm/guest_compat.h
new file mode 100644 (file)
index 0000000..ae7abbd
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef KVM__GUEST_COMPAT_H
+#define KVM__GUEST_COMPAT_H
+
+int compat__print_all_messages(void);
+int compat__remove_message(int id);
+int compat__add_message(const char *title, const char *description);
+
+
+#endif
\ No newline at end of file
diff --git a/tools/kvm/include/kvm/i8042.h b/tools/kvm/include/kvm/i8042.h
new file mode 100644 (file)
index 0000000..3b4ab68
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef KVM__PCKBD_H
+#define KVM__PCKBD_H
+
+#include <linux/types.h>
+
+struct kvm;
+
+void mouse_queue(u8 c);
+void kbd_queue(u8 c);
+int kbd__init(struct kvm *kvm);
+
+#endif
diff --git a/tools/kvm/include/kvm/ioeventfd.h b/tools/kvm/include/kvm/ioeventfd.h
new file mode 100644 (file)
index 0000000..d71fa40
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef KVM__IOEVENTFD_H
+#define KVM__IOEVENTFD_H
+
+#include <linux/types.h>
+#include <linux/list.h>
+#include <sys/eventfd.h>
+#include "kvm/util.h"
+
+struct kvm;
+
+struct ioevent {
+       u64                     io_addr;
+       u8                      io_len;
+       void                    (*fn)(struct kvm *kvm, void *ptr);
+       struct kvm              *fn_kvm;
+       void                    *fn_ptr;
+       int                     fd;
+       u64                     datamatch;
+
+       struct list_head        list;
+};
+
+int ioeventfd__init(struct kvm *kvm);
+int ioeventfd__exit(struct kvm *kvm);
+int ioeventfd__add_event(struct ioevent *ioevent, bool is_pio, bool poll_in_userspace);
+int ioeventfd__del_event(u64 addr, u64 datamatch);
+
+#endif
diff --git a/tools/kvm/include/kvm/ioport.h b/tools/kvm/include/kvm/ioport.h
new file mode 100644 (file)
index 0000000..6660acb
--- /dev/null
@@ -0,0 +1,70 @@
+#ifndef KVM__IOPORT_H
+#define KVM__IOPORT_H
+
+#include "kvm/rbtree-interval.h"
+
+#include <stdbool.h>
+#include <limits.h>
+#include <asm/types.h>
+#include <linux/types.h>
+#include <linux/byteorder.h>
+
+/* some ports we reserve for own use */
+#define IOPORT_DBG                     0xe0
+#define IOPORT_START                   0x6200
+#define IOPORT_SIZE                    0x400
+
+#define IOPORT_EMPTY                   USHRT_MAX
+
+struct kvm;
+
+struct ioport {
+       struct rb_int_node              node;
+       struct ioport_operations        *ops;
+       void                            *priv;
+};
+
+struct ioport_operations {
+       bool (*io_in)(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size);
+       bool (*io_out)(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size);
+};
+
+void ioport__setup_arch(struct kvm *kvm);
+
+int ioport__register(struct kvm *kvm, u16 port, struct ioport_operations *ops,
+                       int count, void *param);
+int ioport__unregister(struct kvm *kvm, u16 port);
+int ioport__init(struct kvm *kvm);
+int ioport__exit(struct kvm *kvm);
+
+static inline u8 ioport__read8(u8 *data)
+{
+       return *data;
+}
+/* On BE platforms, PCI I/O is byteswapped, i.e. LE, so swap back. */
+static inline u16 ioport__read16(u16 *data)
+{
+       return le16_to_cpu(*data);
+}
+
+static inline u32 ioport__read32(u32 *data)
+{
+       return le32_to_cpu(*data);
+}
+
+static inline void ioport__write8(u8 *data, u8 value)
+{
+       *data            = value;
+}
+
+static inline void ioport__write16(u16 *data, u16 value)
+{
+       *data            = cpu_to_le16(value);
+}
+
+static inline void ioport__write32(u32 *data, u32 value)
+{
+       *data            = cpu_to_le32(value);
+}
+
+#endif /* KVM__IOPORT_H */
diff --git a/tools/kvm/include/kvm/irq.h b/tools/kvm/include/kvm/irq.h
new file mode 100644 (file)
index 0000000..43fecaf
--- /dev/null
@@ -0,0 +1,33 @@
+#ifndef KVM__IRQ_H
+#define KVM__IRQ_H
+
+#include <linux/types.h>
+#include <linux/rbtree.h>
+#include <linux/list.h>
+#include <linux/kvm.h>
+
+#include "kvm/msi.h"
+
+struct kvm;
+
+struct irq_line {
+       u8                      line;
+       struct list_head        node;
+};
+
+struct pci_dev {
+       struct rb_node          node;
+       u32                     id;
+       u8                      pin;
+       struct list_head        lines;
+};
+
+int irq__register_device(u32 dev, u8 *num, u8 *pin, u8 *line);
+
+struct rb_node *irq__get_pci_tree(void);
+
+int irq__init(struct kvm *kvm);
+int irq__exit(struct kvm *kvm);
+int irq__add_msix_route(struct kvm *kvm, struct msi_msg *msg);
+
+#endif
diff --git a/tools/kvm/include/kvm/kvm-cmd.h b/tools/kvm/include/kvm/kvm-cmd.h
new file mode 100644 (file)
index 0000000..0a73bce
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef __KVM_CMD_H__
+#define __KVM_CMD_H__
+
+struct cmd_struct {
+       const char *cmd;
+       int (*fn)(int, const char **, const char *);
+       void (*help)(void);
+       int option;
+};
+
+extern struct cmd_struct kvm_commands[];
+struct cmd_struct *kvm_get_command(struct cmd_struct *command,
+                const char *cmd);
+
+int handle_command(struct cmd_struct *command, int argc, const char **argv);
+
+#endif
diff --git a/tools/kvm/include/kvm/kvm-config.h b/tools/kvm/include/kvm/kvm-config.h
new file mode 100644 (file)
index 0000000..df36a76
--- /dev/null
@@ -0,0 +1,60 @@
+#ifndef KVM_CONFIG_H_
+#define KVM_CONFIG_H_
+
+#include "kvm/disk-image.h"
+
+#define DEFAULT_KVM_DEV                "/dev/kvm"
+#define DEFAULT_CONSOLE                "serial"
+#define DEFAULT_NETWORK                "user"
+#define DEFAULT_HOST_ADDR      "192.168.33.1"
+#define DEFAULT_GUEST_ADDR     "192.168.33.15"
+#define DEFAULT_GUEST_MAC      "02:15:15:15:15:15"
+#define DEFAULT_HOST_MAC       "02:01:01:01:01:01"
+#define DEFAULT_SCRIPT         "none"
+#define DEFAULT_SANDBOX_FILENAME "guest/sandbox.sh"
+
+#define MIN_RAM_SIZE_MB                (64ULL)
+#define MIN_RAM_SIZE_BYTE      (MIN_RAM_SIZE_MB << MB_SHIFT)
+
+struct kvm_config {
+       struct disk_image_params disk_image[MAX_DISK_IMAGES];
+       u64 ram_size;
+       u8  image_count;
+       u8 num_net_devices;
+       bool virtio_rng;
+       int active_console;
+       int debug_iodelay;
+       int nrcpus;
+       int vidmode;
+       const char *kernel_cmdline;
+       const char *kernel_filename;
+       const char *vmlinux_filename;
+       const char *initrd_filename;
+       const char *firmware_filename;
+       const char *console;
+       const char *dev;
+       const char *network;
+       const char *host_ip;
+       const char *guest_ip;
+       const char *guest_mac;
+       const char *host_mac;
+       const char *script;
+       const char *guest_name;
+       const char *sandbox;
+       const char *hugetlbfs_path;
+       const char *custom_rootfs_name;
+       const char *real_cmdline;
+       struct virtio_net_params *net_params;
+       bool single_step;
+       bool vnc;
+       bool sdl;
+       bool balloon;
+       bool using_rootfs;
+       bool custom_rootfs;
+       bool no_net;
+       bool no_dhcp;
+       bool ioport_debug;
+       bool mmio_debug;
+};
+
+#endif
diff --git a/tools/kvm/include/kvm/kvm-cpu.h b/tools/kvm/include/kvm/kvm-cpu.h
new file mode 100644 (file)
index 0000000..0ece28c
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef KVM__KVM_CPU_H
+#define KVM__KVM_CPU_H
+
+#include "kvm/kvm-cpu-arch.h"
+#include <stdbool.h>
+
+int kvm_cpu__init(struct kvm *kvm);
+int kvm_cpu__exit(struct kvm *kvm);
+struct kvm_cpu *kvm_cpu__arch_init(struct kvm *kvm, unsigned long cpu_id);
+void kvm_cpu__delete(struct kvm_cpu *vcpu);
+void kvm_cpu__reset_vcpu(struct kvm_cpu *vcpu);
+void kvm_cpu__setup_cpuid(struct kvm_cpu *vcpu);
+void kvm_cpu__enable_singlestep(struct kvm_cpu *vcpu);
+void kvm_cpu__run(struct kvm_cpu *vcpu);
+void kvm_cpu__reboot(struct kvm *kvm);
+int kvm_cpu__start(struct kvm_cpu *cpu);
+bool kvm_cpu__handle_exit(struct kvm_cpu *vcpu);
+
+int kvm_cpu__get_debug_fd(void);
+void kvm_cpu__set_debug_fd(int fd);
+void kvm_cpu__show_code(struct kvm_cpu *vcpu);
+void kvm_cpu__show_registers(struct kvm_cpu *vcpu);
+void kvm_cpu__show_page_tables(struct kvm_cpu *vcpu);
+void kvm_cpu__arch_nmi(struct kvm_cpu *cpu);
+
+#endif /* KVM__KVM_CPU_H */
diff --git a/tools/kvm/include/kvm/kvm-ipc.h b/tools/kvm/include/kvm/kvm-ipc.h
new file mode 100644 (file)
index 0000000..5494da4
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef KVM__IPC_H_
+#define KVM__IPC_H_
+
+#include <linux/types.h>
+#include "kvm/kvm.h"
+
+enum {
+       KVM_IPC_BALLOON = 1,
+       KVM_IPC_DEBUG   = 2,
+       KVM_IPC_STAT    = 3,
+       KVM_IPC_PAUSE   = 4,
+       KVM_IPC_RESUME  = 5,
+       KVM_IPC_STOP    = 6,
+       KVM_IPC_PID     = 7,
+       KVM_IPC_VMSTATE = 8,
+};
+
+int kvm_ipc__register_handler(u32 type, void (*cb)(struct kvm *kvm,
+                               int fd, u32 type, u32 len, u8 *msg));
+int kvm_ipc__init(struct kvm *kvm);
+int kvm_ipc__exit(struct kvm *kvm);
+
+int kvm_ipc__send(int fd, u32 type);
+int kvm_ipc__send_msg(int fd, u32 type, u32 len, u8 *msg);
+
+#endif
diff --git a/tools/kvm/include/kvm/kvm.h b/tools/kvm/include/kvm/kvm.h
new file mode 100644 (file)
index 0000000..b460656
--- /dev/null
@@ -0,0 +1,121 @@
+#ifndef KVM__KVM_H
+#define KVM__KVM_H
+
+#include "kvm/kvm-arch.h"
+#include "kvm/kvm-config.h"
+#include "kvm/util-init.h"
+#include "kvm/kvm.h"
+
+#include <stdbool.h>
+#include <linux/types.h>
+#include <time.h>
+#include <signal.h>
+
+#define SIGKVMEXIT             (SIGRTMIN + 0)
+#define SIGKVMPAUSE            (SIGRTMIN + 1)
+
+#define KVM_PID_FILE_PATH      "/.lkvm/"
+#define HOME_DIR               getenv("HOME")
+#define KVM_BINARY_NAME                "lkvm"
+
+#define PAGE_SIZE (sysconf(_SC_PAGE_SIZE))
+
+#define DEFINE_KVM_EXT(ext)            \
+       .name = #ext,                   \
+       .code = ext
+
+enum {
+       KVM_VMSTATE_RUNNING,
+       KVM_VMSTATE_PAUSED,
+};
+
+struct kvm_ext {
+       const char *name;
+       int code;
+};
+
+struct kvm {
+       struct kvm_arch         arch;
+       struct kvm_config       cfg;
+       int                     sys_fd;         /* For system ioctls(), i.e. /dev/kvm */
+       int                     vm_fd;          /* For VM ioctls() */
+       timer_t                 timerid;        /* Posix timer for interrupts */
+
+       int                     nrcpus;         /* Number of cpus to run */
+       struct kvm_cpu          **cpus;
+
+       u32                     mem_slots;      /* for KVM_SET_USER_MEMORY_REGION */
+       u64                     ram_size;
+       void                    *ram_start;
+       u64                     ram_pagesize;
+
+       bool                    nmi_disabled;
+
+       const char              *vmlinux;
+       struct disk_image       **disks;
+       int                     nr_disks;
+
+       int                     vm_state;
+};
+
+void kvm__set_dir(const char *fmt, ...);
+const char *kvm__get_dir(void);
+
+int kvm__init(struct kvm *kvm);
+struct kvm *kvm__new(void);
+int kvm__recommended_cpus(struct kvm *kvm);
+int kvm__max_cpus(struct kvm *kvm);
+void kvm__init_ram(struct kvm *kvm);
+int kvm__exit(struct kvm *kvm);
+bool kvm__load_firmware(struct kvm *kvm, const char *firmware_filename);
+bool kvm__load_kernel(struct kvm *kvm, const char *kernel_filename,
+                       const char *initrd_filename, const char *kernel_cmdline, u16 vidmode);
+int kvm_timer__init(struct kvm *kvm);
+int kvm_timer__exit(struct kvm *kvm);
+void kvm__irq_line(struct kvm *kvm, int irq, int level);
+void kvm__irq_trigger(struct kvm *kvm, int irq);
+bool kvm__emulate_io(struct kvm *kvm, u16 port, void *data, int direction, int size, u32 count);
+bool kvm__emulate_mmio(struct kvm *kvm, u64 phys_addr, u8 *data, u32 len, u8 is_write);
+int kvm__register_mem(struct kvm *kvm, u64 guest_phys, u64 size, void *userspace_addr);
+int kvm__register_mmio(struct kvm *kvm, u64 phys_addr, u64 phys_addr_len, bool coalesce,
+                       void (*mmio_fn)(u64 addr, u8 *data, u32 len, u8 is_write, void *ptr),
+                       void *ptr);
+bool kvm__deregister_mmio(struct kvm *kvm, u64 phys_addr);
+void kvm__pause(struct kvm *kvm);
+void kvm__continue(struct kvm *kvm);
+void kvm__notify_paused(void);
+int kvm__get_sock_by_instance(const char *name);
+int kvm__enumerate_instances(int (*callback)(const char *name, int pid));
+void kvm__remove_socket(const char *name);
+
+void kvm__arch_set_cmdline(char *cmdline, bool video);
+void kvm__arch_init(struct kvm *kvm, const char *hugetlbfs_path, u64 ram_size);
+void kvm__arch_delete_ram(struct kvm *kvm);
+int kvm__arch_setup_firmware(struct kvm *kvm);
+int kvm__arch_free_firmware(struct kvm *kvm);
+bool kvm__arch_cpu_supports_vm(void);
+void kvm__arch_periodic_poll(struct kvm *kvm);
+
+int load_flat_binary(struct kvm *kvm, int fd_kernel, int fd_initrd, const char *kernel_cmdline);
+bool load_bzimage(struct kvm *kvm, int fd_kernel, int fd_initrd, const char *kernel_cmdline, u16 vidmode);
+
+/*
+ * Debugging
+ */
+void kvm__dump_mem(struct kvm *kvm, unsigned long addr, unsigned long size);
+
+extern const char *kvm_exit_reasons[];
+
+static inline bool host_ptr_in_ram(struct kvm *kvm, void *p)
+{
+       return kvm->ram_start <= p && p < (kvm->ram_start + kvm->ram_size);
+}
+
+static inline void *guest_flat_to_host(struct kvm *kvm, unsigned long offset)
+{
+       return kvm->ram_start + offset;
+}
+
+bool kvm__supports_extension(struct kvm *kvm, unsigned int extension);
+
+#endif /* KVM__KVM_H */
diff --git a/tools/kvm/include/kvm/msi.h b/tools/kvm/include/kvm/msi.h
new file mode 100644 (file)
index 0000000..885eb5b
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef LKVM_MSI_H
+#define LKVM_MSI_H
+
+struct msi_msg {
+       u32     address_lo;     /* low 32 bits of msi message address */
+       u32     address_hi;     /* high 32 bits of msi message address */
+       u32     data;           /* 16 bits of msi message data */
+};
+
+#endif /* LKVM_MSI_H */
diff --git a/tools/kvm/include/kvm/mutex.h b/tools/kvm/include/kvm/mutex.h
new file mode 100644 (file)
index 0000000..3286cea
--- /dev/null
@@ -0,0 +1,33 @@
+#ifndef KVM__MUTEX_H
+#define KVM__MUTEX_H
+
+#include <pthread.h>
+
+#include "kvm/util.h"
+
+/*
+ * Kernel-alike mutex API - to make it easier for kernel developers
+ * to write user-space code! :-)
+ */
+
+#define DEFINE_MUTEX(mutex) pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER
+
+static inline void mutex_init(pthread_mutex_t *mutex)
+{
+       if (pthread_mutex_init(mutex, NULL) != 0)
+               die("unexpected pthread_mutex_init() failure!");
+}
+
+static inline void mutex_lock(pthread_mutex_t *mutex)
+{
+       if (pthread_mutex_lock(mutex) != 0)
+               die("unexpected pthread_mutex_lock() failure!");
+}
+
+static inline void mutex_unlock(pthread_mutex_t *mutex)
+{
+       if (pthread_mutex_unlock(mutex) != 0)
+               die("unexpected pthread_mutex_unlock() failure!");
+}
+
+#endif /* KVM__MUTEX_H */
diff --git a/tools/kvm/include/kvm/parse-options.h b/tools/kvm/include/kvm/parse-options.h
new file mode 100644 (file)
index 0000000..cc188b9
--- /dev/null
@@ -0,0 +1,218 @@
+#ifndef __PARSE_OPTIONS_H__
+#define __PARSE_OPTIONS_H__
+
+#include <inttypes.h>
+#include <kvm/util.h>
+
+enum parse_opt_type {
+       /* special types */
+       OPTION_END,
+       OPTION_ARGUMENT,
+       OPTION_GROUP,
+       /* options with no arguments */
+       OPTION_BIT,
+       OPTION_BOOLEAN,
+       OPTION_INCR,
+       OPTION_SET_UINT,
+       OPTION_SET_PTR,
+       /* options with arguments (usually) */
+       OPTION_STRING,
+       OPTION_INTEGER,
+       OPTION_LONG,
+       OPTION_CALLBACK,
+       OPTION_U64,
+       OPTION_UINTEGER,
+};
+
+enum parse_opt_flags {
+       PARSE_OPT_KEEP_DASHDASH = 1,
+       PARSE_OPT_STOP_AT_NON_OPTION = 2,
+       PARSE_OPT_KEEP_ARGV0 = 4,
+       PARSE_OPT_KEEP_UNKNOWN = 8,
+       PARSE_OPT_NO_INTERNAL_HELP = 16,
+};
+
+enum parse_opt_option_flags {
+       PARSE_OPT_OPTARG  = 1,
+       PARSE_OPT_NOARG   = 2,
+       PARSE_OPT_NONEG   = 4,
+       PARSE_OPT_HIDDEN  = 8,
+       PARSE_OPT_LASTARG_DEFAULT = 16,
+};
+
+struct option;
+typedef int parse_opt_cb(const struct option *, const char *arg, int unset);
+/*
+ * `type`::
+ *   holds the type of the option, you must have an OPTION_END last in your
+ *   array.
+ *
+ * `short_name`::
+ *   the character to use as a short option name, '\0' if none.
+ *
+ * `long_name`::
+ *   the long option name, without the leading dashes, NULL if none.
+ *
+ * `value`::
+ *   stores pointers to the values to be filled.
+ *
+ * `argh`::
+ *   token to explain the kind of argument this option wants. Keep it
+ *   homogenous across the repository.
+ *
+ * `help`::
+ *   the short help associated to what the option does.
+ *   Must never be NULL (except for OPTION_END).
+ *   OPTION_GROUP uses this pointer to store the group header.
+ *
+ * `flags`::
+ *   mask of parse_opt_option_flags.
+ *   PARSE_OPT_OPTARG: says that the argument is optionnal (not for BOOLEANs)
+ *   PARSE_OPT_NOARG: says that this option takes no argument, for CALLBACKs
+ *   PARSE_OPT_NONEG: says that this option cannot be negated
+ *   PARSE_OPT_HIDDEN this option is skipped in the default usage, showed in
+ *                    the long one.
+ *
+ * `callback`::
+ *   pointer to the callback to use for OPTION_CALLBACK.
+ *
+ * `defval`::
+ *   default value to fill (*->value) with for PARSE_OPT_OPTARG.
+ *   OPTION_{BIT,SET_UINT,SET_PTR} store the {mask,integer,pointer} to put in
+ *   the value when met.
+ *   CALLBACKS can use it like they want.
+ */
+struct option {
+       enum parse_opt_type type;
+       int short_name;
+       const char *long_name;
+       void *value;
+       const char *argh;
+       const char *help;
+       void *ptr;
+
+       int flags;
+       parse_opt_cb *callback;
+       intptr_t defval;
+};
+
+#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))
+#define check_vtype(v, type) \
+       (BUILD_BUG_ON_ZERO(!__builtin_types_compatible_p(typeof(v), type)) + v)
+
+#define OPT_INTEGER(s, l, v, h)             \
+{                                           \
+       .type = OPTION_INTEGER,             \
+       .short_name = (s),                  \
+       .long_name = (l),                   \
+       .value = check_vtype(v, int *),     \
+       .help = (h)                         \
+}
+
+#define OPT_U64(s, l, v, h)                 \
+{                                           \
+       .type = OPTION_U64,                 \
+       .short_name = (s),                  \
+       .long_name = (l),                   \
+       .value = check_vtype(v, u64 *),     \
+       .help = (h)                         \
+}
+
+#define OPT_STRING(s, l, v, a, h)           \
+{                                           \
+       .type = OPTION_STRING,              \
+       .short_name = (s),                  \
+       .long_name = (l),                   \
+       .value = check_vtype(v, const char **), (a), \
+       .help = (h)                         \
+}
+
+#define OPT_BOOLEAN(s, l, v, h)             \
+{                                           \
+       .type = OPTION_BOOLEAN,             \
+       .short_name = (s),                  \
+       .long_name = (l),                   \
+       .value = check_vtype(v, bool *),    \
+       .help = (h)                         \
+}
+
+#define OPT_INCR(s, l, v, h)                \
+{                                           \
+       .type = OPTION_INCR,                \
+       .short_name = (s),                  \
+       .long_name = (l),                   \
+       .value = check_vtype(v, int *),     \
+       .help = (h)                         \
+}
+
+#define OPT_GROUP(h)                        \
+{                                           \
+       .type = OPTION_GROUP,               \
+       .help = (h)                         \
+}
+
+#define OPT_CALLBACK(s, l, v, a, h, f, p)   \
+{                                          \
+       .type = OPTION_CALLBACK,            \
+       .short_name = (s),                  \
+       .long_name = (l),                   \
+       .value = (v),                       \
+       (a),                                \
+       .help = (h),                        \
+       .callback = (f),                    \
+       .ptr = (p),                         \
+}
+
+#define OPT_CALLBACK_NOOPT(s, l, v, a, h, f, p) \
+{                                          \
+       .type = OPTION_CALLBACK,            \
+       .short_name = (s),                  \
+       .long_name = (l),                   \
+       .value = (v),                       \
+       (a),                                \
+       .help = (h),                        \
+       .callback = (f),                    \
+       .flags = PARSE_OPT_NOARG,           \
+       .ptr = (p),                         \
+}
+
+#define OPT_CALLBACK_DEFAULT(s, l, v, a, h, f, d, p) \
+{                                          \
+       .type = OPTION_CALLBACK,            \
+       .short_name = (s),                  \
+       .long_name = (l),                   \
+       .value = (v), (a),                  \
+       .help = (h),                        \
+       .callback = (f),                    \
+       .defval = (intptr_t)d,              \
+       .flags = PARSE_OPT_LASTARG_DEFAULT, \
+       .ptr = (p)                          \
+}
+
+#define OPT_END() { .type = OPTION_END }
+
+enum {
+       PARSE_OPT_HELP = -1,
+       PARSE_OPT_DONE,
+       PARSE_OPT_UNKNOWN,
+};
+
+/*
+ * It's okay for the caller to consume argv/argc in the usual way.
+ * Other fields of that structure are private to parse-options and should not
+ * be modified in any way.
+ **/
+struct parse_opt_ctx_t {
+       const char **argv;
+       const char **out;
+       int argc, cpidx;
+       const char *opt;
+       int flags;
+};
+
+/* global functions */
+void usage_with_options(const char * const *usagestr,
+               const struct option *opts) NORETURN;
+int parse_options(int argc, const char **argv, const struct option *options,
+               const char * const usagestr[], int flags);
+#endif
diff --git a/tools/kvm/include/kvm/pci-shmem.h b/tools/kvm/include/kvm/pci-shmem.h
new file mode 100644 (file)
index 0000000..6cff2b8
--- /dev/null
@@ -0,0 +1,32 @@
+#ifndef KVM__PCI_SHMEM_H
+#define KVM__PCI_SHMEM_H
+
+#include <linux/types.h>
+#include <linux/list.h>
+
+#include "kvm/parse-options.h"
+
+#define SHMEM_DEFAULT_SIZE (16 << MB_SHIFT)
+#define SHMEM_DEFAULT_ADDR (0xc8000000)
+#define SHMEM_DEFAULT_HANDLE "/kvm_shmem"
+
+struct kvm;
+struct shmem_info;
+
+struct shmem_info {
+       u64 phys_addr;
+       u64 size;
+       char *handle;
+       int create;
+};
+
+int pci_shmem__init(struct kvm *kvm);
+int pci_shmem__exit(struct kvm *kvm);
+int pci_shmem__register_mem(struct shmem_info *si);
+int shmem_parser(const struct option *opt, const char *arg, int unset);
+
+int pci_shmem__get_local_irqfd(struct kvm *kvm);
+int pci_shmem__add_client(struct kvm *kvm, u32 id, int fd);
+int pci_shmem__remove_client(struct kvm *kvm, u32 id);
+
+#endif
diff --git a/tools/kvm/include/kvm/pci.h b/tools/kvm/include/kvm/pci.h
new file mode 100644 (file)
index 0000000..26639b5
--- /dev/null
@@ -0,0 +1,95 @@
+#ifndef KVM__PCI_H
+#define KVM__PCI_H
+
+#include <linux/types.h>
+#include <linux/kvm.h>
+#include <linux/pci_regs.h>
+#include <endian.h>
+
+#include "kvm/kvm.h"
+#include "kvm/msi.h"
+
+#define PCI_MAX_DEVICES                256
+/*
+ * PCI Configuration Mechanism #1 I/O ports. See Section 3.7.4.1.
+ * ("Configuration Mechanism #1") of the PCI Local Bus Specification 2.1 for
+ * details.
+ */
+#define PCI_CONFIG_ADDRESS     0xcf8
+#define PCI_CONFIG_DATA                0xcfc
+#define PCI_CONFIG_BUS_FORWARD 0xcfa
+#define PCI_IO_SIZE            0x100
+
+union pci_config_address {
+       struct {
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+               unsigned        reg_offset      : 2;            /* 1  .. 0  */
+               unsigned        register_number : 6;            /* 7  .. 2  */
+               unsigned        function_number : 3;            /* 10 .. 8  */
+               unsigned        device_number   : 5;            /* 15 .. 11 */
+               unsigned        bus_number      : 8;            /* 23 .. 16 */
+               unsigned        reserved        : 7;            /* 30 .. 24 */
+               unsigned        enable_bit      : 1;            /* 31       */
+#else
+               unsigned        enable_bit      : 1;            /* 31       */
+               unsigned        reserved        : 7;            /* 30 .. 24 */
+               unsigned        bus_number      : 8;            /* 23 .. 16 */
+               unsigned        device_number   : 5;            /* 15 .. 11 */
+               unsigned        function_number : 3;            /* 10 .. 8  */
+               unsigned        register_number : 6;            /* 7  .. 2  */
+               unsigned        reg_offset      : 2;            /* 1  .. 0  */
+#endif
+       };
+       u32 w;
+};
+
+struct msix_table {
+       struct msi_msg msg;
+       u32 ctrl;
+};
+
+struct msix_cap {
+       u8 cap;
+       u8 next;
+       u16 ctrl;
+       u32 table_offset;
+       u32 pba_offset;
+};
+
+struct pci_device_header {
+       u16             vendor_id;
+       u16             device_id;
+       u16             command;
+       u16             status;
+       u8              revision_id;
+       u8              class[3];
+       u8              cacheline_size;
+       u8              latency_timer;
+       u8              header_type;
+       u8              bist;
+       u32             bar[6];
+       u32             card_bus;
+       u16             subsys_vendor_id;
+       u16             subsys_id;
+       u32             exp_rom_bar;
+       u8              capabilities;
+       u8              reserved1[3];
+       u32             reserved2;
+       u8              irq_line;
+       u8              irq_pin;
+       u8              min_gnt;
+       u8              max_lat;
+       struct msix_cap msix;
+       u8              empty[136]; /* Rest of PCI config space */
+       u32             bar_size[6];
+} __attribute__((packed));
+
+int pci__init(struct kvm *kvm);
+int pci__exit(struct kvm *kvm);
+int pci__register(struct pci_device_header *dev, u8 dev_num);
+struct pci_device_header *pci__find_dev(u8 dev_num);
+u32 pci_get_io_space_block(u32 size);
+void pci__config_wr(struct kvm *kvm, union pci_config_address addr, void *data, int size);
+void pci__config_rd(struct kvm *kvm, union pci_config_address addr, void *data, int size);
+
+#endif /* KVM__PCI_H */
diff --git a/tools/kvm/include/kvm/qcow.h b/tools/kvm/include/kvm/qcow.h
new file mode 100644 (file)
index 0000000..e032a1e
--- /dev/null
@@ -0,0 +1,133 @@
+#ifndef KVM__QCOW_H
+#define KVM__QCOW_H
+
+#include "kvm/mutex.h"
+
+#include <linux/types.h>
+#include <stdbool.h>
+#include <linux/rbtree.h>
+#include <linux/list.h>
+
+#define QCOW_MAGIC             (('Q' << 24) | ('F' << 16) | ('I' << 8) | 0xfb)
+
+#define QCOW1_VERSION          1
+#define QCOW2_VERSION          2
+
+#define QCOW1_OFLAG_COMPRESSED (1ULL << 63)
+
+#define QCOW2_OFLAG_COPIED     (1ULL << 63)
+#define QCOW2_OFLAG_COMPRESSED (1ULL << 62)
+
+#define QCOW2_OFLAGS_MASK      (QCOW2_OFLAG_COPIED|QCOW2_OFLAG_COMPRESSED)
+
+#define QCOW2_OFFSET_MASK      (~QCOW2_OFLAGS_MASK)
+
+#define MAX_CACHE_NODES         32
+
+struct qcow_l2_table {
+       u64                             offset;
+       struct rb_node                  node;
+       struct list_head                list;
+       u8                              dirty;
+       u64                             table[];
+};
+
+struct qcow_l1_table {
+       u32                             table_size;
+       u64                             *l1_table;
+
+       /* Level2 caching data structures */
+       struct rb_root                  root;
+       struct list_head                lru_list;
+       int                             nr_cached;
+};
+
+#define QCOW_REFCOUNT_BLOCK_SHIFT      1
+
+struct qcow_refcount_block {
+       u64                             offset;
+       struct rb_node                  node;
+       struct list_head                list;
+       u64                             size;
+       u8                              dirty;
+       u16                             entries[];
+};
+
+struct qcow_refcount_table {
+       u32                             rf_size;
+       u64                             *rf_table;
+
+       /* Refcount block caching data structures */
+       struct rb_root                  root;
+       struct list_head                lru_list;
+       int                             nr_cached;
+};
+
+struct qcow_header {
+       u64                             size;   /* in bytes */
+       u64                             l1_table_offset;
+       u32                             l1_size;
+       u8                              cluster_bits;
+       u8                              l2_bits;
+       u64                             refcount_table_offset;
+       u32                             refcount_table_size;
+};
+
+struct qcow {
+       pthread_mutex_t                 mutex;
+       struct qcow_header              *header;
+       struct qcow_l1_table            table;
+       struct qcow_refcount_table      refcount_table;
+       int                             fd;
+       int                             csize_shift;
+       int                             csize_mask;
+       u32                             version;
+       u64                             cluster_size;
+       u64                             cluster_offset_mask;
+       u64                             free_clust_idx;
+       void                            *cluster_cache;
+       void                            *cluster_data;
+       void                            *copy_buff;
+};
+
+struct qcow1_header_disk {
+       u32                             magic;
+       u32                             version;
+
+       u64                             backing_file_offset;
+       u32                             backing_file_size;
+       u32                             mtime;
+
+       u64                             size;   /* in bytes */
+
+       u8                              cluster_bits;
+       u8                              l2_bits;
+       u32                             crypt_method;
+
+       u64                             l1_table_offset;
+};
+
+struct qcow2_header_disk {
+       u32                             magic;
+       u32                             version;
+
+       u64                             backing_file_offset;
+       u32                             backing_file_size;
+
+       u32                             cluster_bits;
+       u64                             size;   /* in bytes */
+       u32                             crypt_method;
+
+       u32                             l1_size;
+       u64                             l1_table_offset;
+
+       u64                             refcount_table_offset;
+       u32                             refcount_table_clusters;
+
+       u32                             nb_snapshots;
+       u64                             snapshots_offset;
+};
+
+struct disk_image *qcow_probe(int fd, bool readonly);
+
+#endif /* KVM__QCOW_H */
diff --git a/tools/kvm/include/kvm/rbtree-interval.h b/tools/kvm/include/kvm/rbtree-interval.h
new file mode 100644 (file)
index 0000000..e97d05b
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef KVM__INTERVAL_RBTREE_H
+#define KVM__INTERVAL_RBTREE_H
+
+#include <linux/rbtree_augmented.h>
+#include <linux/types.h>
+
+#define RB_INT_INIT(l, h) (struct rb_int_node){.low = l, .high = h}
+#define rb_int(n) rb_entry(n, struct rb_int_node, node)
+
+struct rb_int_node {
+       struct rb_node  node;
+       u64             low;
+       u64             high;
+
+       /* max_high will store the highest high of it's 2 children. */
+       u64             max_high;
+};
+
+/* Return the rb_int_node interval in which 'point' is located. */
+struct rb_int_node *rb_int_search_single(struct rb_root *root, u64 point);
+
+/* Return the rb_int_node in which start:len is located. */
+struct rb_int_node *rb_int_search_range(struct rb_root *root, u64 low, u64 high);
+
+int rb_int_insert(struct rb_root *root, struct rb_int_node *data);
+void rb_int_erase(struct rb_root *root, struct rb_int_node *node);
+
+#endif
diff --git a/tools/kvm/include/kvm/read-write.h b/tools/kvm/include/kvm/read-write.h
new file mode 100644 (file)
index 0000000..67571f9
--- /dev/null
@@ -0,0 +1,43 @@
+#ifndef KVM_READ_WRITE_H
+#define KVM_READ_WRITE_H
+
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <unistd.h>
+
+#ifdef CONFIG_HAS_AIO
+#include <libaio.h>
+#endif
+
+ssize_t xread(int fd, void *buf, size_t count);
+ssize_t xwrite(int fd, const void *buf, size_t count);
+
+ssize_t read_in_full(int fd, void *buf, size_t count);
+ssize_t write_in_full(int fd, const void *buf, size_t count);
+
+ssize_t xpread(int fd, void *buf, size_t count, off_t offset);
+ssize_t xpwrite(int fd, const void *buf, size_t count, off_t offset);
+
+ssize_t pread_in_full(int fd, void *buf, size_t count, off_t offset);
+ssize_t pwrite_in_full(int fd, const void *buf, size_t count, off_t offset);
+
+ssize_t xreadv(int fd, const struct iovec *iov, int iovcnt);
+ssize_t xwritev(int fd, const struct iovec *iov, int iovcnt);
+
+ssize_t readv_in_full(int fd, const struct iovec *iov, int iovcnt);
+ssize_t writev_in_full(int fd, const struct iovec *iov, int iovcnt);
+
+ssize_t xpreadv(int fd, const struct iovec *iov, int iovcnt, off_t offset);
+ssize_t xpwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset);
+
+ssize_t preadv_in_full(int fd, const struct iovec *iov, int iovcnt, off_t offset);
+ssize_t pwritev_in_full(int fd, const struct iovec *iov, int iovcnt, off_t offset);
+
+#ifdef CONFIG_HAS_AIO
+int aio_preadv(io_context_t ctx, struct iocb *iocb, int fd, const struct iovec *iov, int iovcnt,
+               off_t offset, int ev, void *param);
+int aio_pwritev(io_context_t ctx, struct iocb *iocb, int fd, const struct iovec *iov, int iovcnt,
+               off_t offset, int ev, void *param);
+#endif
+
+#endif /* KVM_READ_WRITE_H */
diff --git a/tools/kvm/include/kvm/rtc.h b/tools/kvm/include/kvm/rtc.h
new file mode 100644 (file)
index 0000000..6aa9299
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef KVM__RTC_H
+#define KVM__RTC_H
+
+struct kvm;
+
+int rtc__init(struct kvm *kvm);
+int rtc__exit(struct kvm *kvm);
+
+#endif /* KVM__RTC_H */
diff --git a/tools/kvm/include/kvm/rwsem.h b/tools/kvm/include/kvm/rwsem.h
new file mode 100644 (file)
index 0000000..75a22f8
--- /dev/null
@@ -0,0 +1,39 @@
+#ifndef KVM__RWSEM_H
+#define KVM__RWSEM_H
+
+#include <pthread.h>
+
+#include "kvm/util.h"
+
+/*
+ * Kernel-alike rwsem API - to make it easier for kernel developers
+ * to write user-space code! :-)
+ */
+
+#define DECLARE_RWSEM(sem) pthread_rwlock_t sem = PTHREAD_RWLOCK_INITIALIZER
+
+static inline void down_read(pthread_rwlock_t *rwsem)
+{
+       if (pthread_rwlock_rdlock(rwsem) != 0)
+               die("unexpected pthread_rwlock_rdlock() failure!");
+}
+
+static inline void down_write(pthread_rwlock_t *rwsem)
+{
+       if (pthread_rwlock_wrlock(rwsem) != 0)
+               die("unexpected pthread_rwlock_wrlock() failure!");
+}
+
+static inline void up_read(pthread_rwlock_t *rwsem)
+{
+       if (pthread_rwlock_unlock(rwsem) != 0)
+               die("unexpected pthread_rwlock_unlock() failure!");
+}
+
+static inline void up_write(pthread_rwlock_t *rwsem)
+{
+       if (pthread_rwlock_unlock(rwsem) != 0)
+               die("unexpected pthread_rwlock_unlock() failure!");
+}
+
+#endif /* KVM__RWSEM_H */
diff --git a/tools/kvm/include/kvm/sdl.h b/tools/kvm/include/kvm/sdl.h
new file mode 100644 (file)
index 0000000..2f0c213
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef KVM__SDL_H
+#define KVM__SDL_H
+
+#include "kvm/util.h"
+
+struct framebuffer;
+
+#ifdef CONFIG_HAS_SDL
+int sdl__init(struct kvm *kvm);
+int sdl__exit(struct kvm *kvm);
+#else
+static inline int sdl__init(struct kvm *kvm)
+{
+       if (kvm->cfg.sdl)
+               die("SDL support not compiled in. (install the SDL-dev[el] package)");
+
+       return 0;
+}
+static inline int sdl__exit(struct kvm *kvm)
+{
+       if (kvm->cfg.sdl)
+               die("SDL support not compiled in. (install the SDL-dev[el] package)");
+
+       return 0;
+}
+#endif
+
+#endif /* KVM__SDL_H */
diff --git a/tools/kvm/include/kvm/segment.h b/tools/kvm/include/kvm/segment.h
new file mode 100644 (file)
index 0000000..9387a82
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef KVM_SEGMENT_H
+#define KVM_SEGMENT_H
+
+#include <linux/types.h>
+
+static inline u32 segment_to_flat(u16 selector, u16 offset)
+{
+       return ((u32)selector << 4) + (u32) offset;
+}
+
+static inline u16 flat_to_seg16(u32 address)
+{
+       return address >> 4;
+}
+
+static inline u16 flat_to_off16(u32 address, u32 segment)
+{
+       return address - (segment << 4);
+}
+
+#endif /* KVM_SEGMENT_H */
diff --git a/tools/kvm/include/kvm/strbuf.h b/tools/kvm/include/kvm/strbuf.h
new file mode 100644 (file)
index 0000000..2beefbc
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef __STRBUF_H__
+#define __STRBUF_H__
+
+#include <sys/types.h>
+#include <string.h>
+
+int prefixcmp(const char *str, const char *prefix);
+
+extern size_t strlcat(char *dest, const char *src, size_t count);
+extern size_t strlcpy(char *dest, const char *src, size_t size);
+
+/* some inline functions */
+
+static inline const char *skip_prefix(const char *str, const char *prefix)
+{
+       size_t len = strlen(prefix);
+       return strncmp(str, prefix, len) ? NULL : str + len;
+}
+
+#endif
diff --git a/tools/kvm/include/kvm/symbol.h b/tools/kvm/include/kvm/symbol.h
new file mode 100644 (file)
index 0000000..725bbaf
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef KVM__SYMBOL_H
+#define KVM__SYMBOL_H
+
+#include <stddef.h>
+#include <string.h>
+
+struct kvm;
+
+#define SYMBOL_DEFAULT_UNKNOWN "<unknown>"
+
+#ifdef CONFIG_HAS_BFD
+
+int symbol_init(struct kvm *kvm);
+int symbol_exit(struct kvm *kvm);
+char *symbol_lookup(struct kvm *kvm, unsigned long addr, char *sym, size_t size);
+
+#else
+
+static inline int symbol_init(struct kvm *kvm) { return 0; }
+static inline char *symbol_lookup(struct kvm *kvm, unsigned long addr, char *sym, size_t size)
+{
+       char *s = strncpy(sym, SYMBOL_DEFAULT_UNKNOWN, size);
+       sym[size - 1] = '\0';
+       return s;
+}
+static inline int symbol_exit(struct kvm *kvm) { return 0; }
+
+#endif
+
+#endif /* KVM__SYMBOL_H */
diff --git a/tools/kvm/include/kvm/term.h b/tools/kvm/include/kvm/term.h
new file mode 100644 (file)
index 0000000..5f63457
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef KVM__TERM_H
+#define KVM__TERM_H
+
+#include "kvm/kvm.h"
+
+#include <sys/uio.h>
+#include <stdbool.h>
+
+#define CONSOLE_8250   1
+#define CONSOLE_VIRTIO 2
+#define CONSOLE_HV     3
+
+int term_putc_iov(struct iovec *iov, int iovcnt, int term);
+int term_getc_iov(struct kvm *kvm, struct iovec *iov, int iovcnt, int term);
+int term_putc(char *addr, int cnt, int term);
+int term_getc(struct kvm *kvm, int term);
+
+bool term_readable(int term);
+void term_set_tty(int term);
+int term_init(struct kvm *kvm);
+int term_exit(struct kvm *kvm);
+int tty_parser(const struct option *opt, const char *arg, int unset);
+
+#endif /* KVM__TERM_H */
diff --git a/tools/kvm/include/kvm/threadpool.h b/tools/kvm/include/kvm/threadpool.h
new file mode 100644 (file)
index 0000000..abe46ea
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef KVM__THREADPOOL_H
+#define KVM__THREADPOOL_H
+
+#include "kvm/mutex.h"
+
+#include <linux/list.h>
+
+struct kvm;
+
+typedef void (*kvm_thread_callback_fn_t)(struct kvm *kvm, void *data);
+
+struct thread_pool__job {
+       kvm_thread_callback_fn_t        callback;
+       struct kvm                      *kvm;
+       void                            *data;
+
+       int                             signalcount;
+       pthread_mutex_t                 mutex;
+
+       struct list_head                queue;
+};
+
+static inline void thread_pool__init_job(struct thread_pool__job *job, struct kvm *kvm, kvm_thread_callback_fn_t callback, void *data)
+{
+       *job = (struct thread_pool__job) {
+               .kvm            = kvm,
+               .callback       = callback,
+               .data           = data,
+               .mutex          = PTHREAD_MUTEX_INITIALIZER,
+       };
+}
+
+int thread_pool__init(struct kvm *kvm);
+int thread_pool__exit(struct kvm *kvm);
+
+void thread_pool__do_job(struct thread_pool__job *job);
+
+#endif
diff --git a/tools/kvm/include/kvm/types.h b/tools/kvm/include/kvm/types.h
new file mode 100644 (file)
index 0000000..0cbc5fb
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef KVM_TYPES_H
+#define KVM_TYPES_H
+
+/* FIXME: include/linux/if_tun.h and include/linux/if_ether.h complains */
+#define __be16 u16
+
+#endif /* KVM_TYPES_H */
diff --git a/tools/kvm/include/kvm/uip.h b/tools/kvm/include/kvm/uip.h
new file mode 100644 (file)
index 0000000..9af0110
--- /dev/null
@@ -0,0 +1,360 @@
+#ifndef KVM__UIP_H
+#define KVM__UIP_H
+
+#include "linux/types.h"
+#include "kvm/mutex.h"
+
+#include <netinet/in.h>
+#include <sys/uio.h>
+
+#define UIP_BUF_STATUS_FREE    0
+#define UIP_BUF_STATUS_INUSE   1
+#define UIP_BUF_STATUS_USED    2
+
+#define UIP_ETH_P_IP           0X0800
+#define UIP_ETH_P_ARP          0X0806
+
+#define UIP_IP_VER_4           0X40
+#define UIP_IP_HDR_LEN         0X05
+#define UIP_IP_TTL             0X40
+#define UIP_IP_P_UDP           0X11
+#define UIP_IP_P_TCP           0X06
+#define UIP_IP_P_ICMP          0X01
+
+#define UIP_TCP_HDR_LEN                0x50
+#define UIP_TCP_WIN_SIZE       14600
+#define UIP_TCP_FLAG_FIN       1
+#define UIP_TCP_FLAG_SYN       2
+#define UIP_TCP_FLAG_RST       4
+#define UIP_TCP_FLAG_PSH       8
+#define UIP_TCP_FLAG_ACK       16
+#define UIP_TCP_FLAG_URG       32
+
+#define UIP_BOOTP_VENDOR_SPECIFIC_LEN  64
+#define UIP_BOOTP_MAX_PAYLOAD_LEN      300
+#define UIP_DHCP_VENDOR_SPECIFIC_LEN   312
+#define UIP_DHCP_PORT_SERVER           67
+#define UIP_DHCP_PORT_CLIENT           68
+#define UIP_DHCP_MACPAD_LEN            10
+#define UIP_DHCP_HOSTNAME_LEN          64
+#define UIP_DHCP_FILENAME_LEN          128
+#define UIP_DHCP_MAGIC_COOKIE          0x63825363
+#define UIP_DHCP_MAGIC_COOKIE_LEN      4
+#define UIP_DHCP_LEASE_TIME            0x00003840
+#define UIP_DHCP_MAX_PAYLOAD_LEN       (UIP_BOOTP_MAX_PAYLOAD_LEN - UIP_BOOTP_VENDOR_SPECIFIC_LEN +  UIP_DHCP_VENDOR_SPECIFIC_LEN)
+#define UIP_DHCP_OPTION_LEN            (UIP_DHCP_VENDOR_SPECIFIC_LEN - UIP_DHCP_MAGIC_COOKIE_LEN)
+#define UIP_DHCP_DISCOVER              1
+#define UIP_DHCP_OFFER                 2
+#define UIP_DHCP_REQUEST               3
+#define UIP_DHCP_ACK                   5
+#define UIP_DHCP_MAX_DNS_SERVER_NR     3
+#define UIP_DHCP_MAX_DOMAIN_NAME_LEN   256
+#define UIP_DHCP_TAG_MSG_TYPE          53
+#define UIP_DHCP_TAG_MSG_TYPE_LEN      1
+#define UIP_DHCP_TAG_SERVER_ID         54
+#define UIP_DHCP_TAG_SERVER_ID_LEN     4
+#define UIP_DHCP_TAG_LEASE_TIME                51
+#define UIP_DHCP_TAG_LEASE_TIME_LEN    4
+#define UIP_DHCP_TAG_SUBMASK           1
+#define UIP_DHCP_TAG_SUBMASK_LEN       4
+#define UIP_DHCP_TAG_ROUTER            3
+#define UIP_DHCP_TAG_ROUTER_LEN                4
+#define UIP_DHCP_TAG_ROOT              17
+#define UIP_DHCP_TAG_ROOT_LEN          4
+#define UIP_DHCP_TAG_DNS_SERVER                6
+#define UIP_DHCP_TAG_DNS_SERVER_LEN    4
+#define UIP_DHCP_TAG_DOMAIN_NAME       15
+#define UIP_DHCP_TAG_END               255
+
+/*
+ * IP package maxium len == 64 KBytes
+ * IP header == 20 Bytes
+ * TCP header == 20 Bytes
+ * UDP header == 8 Bytes
+ */
+#define UIP_MAX_TCP_PAYLOAD    (64*1024 - 20 - 20 - 1)
+#define UIP_MAX_UDP_PAYLOAD    (64*1024 - 20 -  8 - 1)
+
+struct uip_eth_addr {
+       u8 addr[6];
+};
+
+struct uip_eth {
+       struct uip_eth_addr dst;
+       struct uip_eth_addr src;
+       u16 type;
+} __attribute__((packed));
+
+struct uip_arp {
+       struct uip_eth eth;
+       u16 hwtype;
+       u16 proto;
+       u8 hwlen;
+       u8 protolen;
+       u16 op;
+       struct uip_eth_addr smac;
+       u32 sip;
+       struct uip_eth_addr dmac;
+       u32 dip;
+} __attribute__((packed));
+
+struct uip_ip {
+       struct uip_eth eth;
+       u8 vhl;
+       u8 tos;
+       /*
+        * len = IP hdr +  IP payload
+        */
+       u16 len;
+       u16 id;
+       u16 flgfrag;
+       u8 ttl;
+       u8 proto;
+       u16 csum;
+       u32 sip;
+       u32 dip;
+} __attribute__((packed));
+
+struct uip_icmp {
+       struct uip_ip ip;
+       u8 type;
+       u8 code;
+       u16 csum;
+       u16 id;
+       u16 seq;
+} __attribute__((packed));
+
+struct uip_udp {
+       /*
+        * FIXME: IP Options (IP hdr len > 20 bytes) are not supported
+        */
+       struct uip_ip ip;
+       u16 sport;
+       u16 dport;
+       /*
+        * len = UDP hdr +  UDP payload
+        */
+       u16 len;
+       u16 csum;
+       u8 payload[0];
+} __attribute__((packed));
+
+struct uip_tcp {
+       /*
+        * FIXME: IP Options (IP hdr len > 20 bytes) are not supported
+        */
+       struct uip_ip ip;
+       u16 sport;
+       u16 dport;
+       u32 seq;
+       u32 ack;
+       u8  off;
+       u8  flg;
+       u16 win;
+       u16 csum;
+       u16 urgent;
+} __attribute__((packed));
+
+struct uip_pseudo_hdr {
+       u32 sip;
+       u32 dip;
+       u8 zero;
+       u8 proto;
+       u16 len;
+} __attribute__((packed));
+
+struct uip_dhcp {
+       struct uip_udp udp;
+       u8 msg_type;
+       u8 hardware_type;
+       u8 hardware_len;
+       u8 hops;
+       u32 id;
+       u16 time;
+       u16 flg;
+       u32 client_ip;
+       u32 your_ip;
+       u32 server_ip;
+       u32 agent_ip;
+       struct uip_eth_addr client_mac;
+       u8 pad[UIP_DHCP_MACPAD_LEN];
+       u8 server_hostname[UIP_DHCP_HOSTNAME_LEN];
+       u8 boot_filename[UIP_DHCP_FILENAME_LEN];
+       u32 magic_cookie;
+       u8 option[UIP_DHCP_OPTION_LEN];
+} __attribute__((packed));
+
+struct uip_info {
+       struct list_head udp_socket_head;
+       struct list_head tcp_socket_head;
+       pthread_mutex_t udp_socket_lock;
+       pthread_mutex_t tcp_socket_lock;
+       struct uip_eth_addr guest_mac;
+       struct uip_eth_addr host_mac;
+       pthread_cond_t buf_free_cond;
+       pthread_cond_t buf_used_cond;
+       struct list_head buf_head;
+       pthread_mutex_t buf_lock;
+       pthread_t udp_thread;
+       int udp_epollfd;
+       int buf_free_nr;
+       int buf_used_nr;
+       u32 guest_ip;
+       u32 guest_netmask;
+       u32 host_ip;
+       u32 dns_ip[UIP_DHCP_MAX_DNS_SERVER_NR];
+       char *domain_name;
+       u32 buf_nr;
+};
+
+struct uip_buf {
+       struct list_head list;
+       struct uip_info *info;
+       int vnet_len;
+       int eth_len;
+       int status;
+       char *vnet;
+       char *eth;
+       int id;
+};
+
+struct uip_udp_socket {
+       struct sockaddr_in addr;
+       struct list_head list;
+       pthread_mutex_t *lock;
+       u32 dport, sport;
+       u32 dip, sip;
+       int fd;
+};
+
+struct uip_tcp_socket {
+       struct sockaddr_in addr;
+       struct list_head list;
+       struct uip_info *info;
+       pthread_cond_t  cond;
+       pthread_mutex_t *lock;
+       pthread_t thread;
+       u32 dport, sport;
+       u32 guest_acked;
+       u16 window_size;
+       /*
+        * Initial Sequence Number
+        */
+       u32 isn_server;
+       u32 isn_guest;
+       u32 ack_server;
+       u32 seq_server;
+       int write_done;
+       int read_done;
+       u32 dip, sip;
+       u8 *payload;
+       int fd;
+};
+
+struct uip_tx_arg {
+       struct virtio_net_hdr *vnet;
+       struct uip_info *info;
+       struct uip_eth *eth;
+       int vnet_len;
+       int eth_len;
+};
+
+static inline u16 uip_ip_hdrlen(struct uip_ip *ip)
+{
+       return (ip->vhl & 0x0f) * 4;
+}
+
+static inline u16 uip_ip_len(struct uip_ip *ip)
+{
+       return htons(ip->len);
+}
+
+static inline u16 uip_udp_hdrlen(struct uip_udp *udp)
+{
+       return 8;
+}
+
+static inline u16 uip_udp_len(struct uip_udp *udp)
+{
+       return ntohs(udp->len);
+}
+
+static inline u16 uip_tcp_hdrlen(struct uip_tcp *tcp)
+{
+       return (tcp->off >> 4) * 4;
+}
+
+static inline u16 uip_tcp_len(struct uip_tcp *tcp)
+{
+       struct uip_ip *ip;
+
+       ip = &tcp->ip;
+
+       return uip_ip_len(ip) - uip_ip_hdrlen(ip);
+}
+
+static inline u16 uip_tcp_payloadlen(struct uip_tcp *tcp)
+{
+       return uip_tcp_len(tcp) - uip_tcp_hdrlen(tcp);
+}
+
+static inline u8 *uip_tcp_payload(struct uip_tcp *tcp)
+{
+       return (u8 *)&tcp->sport + uip_tcp_hdrlen(tcp);
+}
+
+static inline bool uip_tcp_is_syn(struct uip_tcp *tcp)
+{
+       return (tcp->flg & UIP_TCP_FLAG_SYN) != 0;
+}
+
+static inline bool uip_tcp_is_fin(struct uip_tcp *tcp)
+{
+       return (tcp->flg & UIP_TCP_FLAG_FIN) != 0;
+}
+
+static inline u32 uip_tcp_isn(struct uip_tcp *tcp)
+{
+       return ntohl(tcp->seq);
+}
+
+static inline u32 uip_tcp_isn_alloc(void)
+{
+       /*
+        * FIXME: should increase every 4ms
+        */
+       return 10000000;
+}
+
+static inline u16 uip_eth_hdrlen(struct uip_eth *eth)
+{
+       return sizeof(*eth);
+}
+
+int uip_tx(struct iovec *iov, u16 out, struct uip_info *info);
+int uip_rx(struct iovec *iov, u16 in, struct uip_info *info);
+int uip_init(struct uip_info *info);
+
+int uip_tx_do_ipv4_udp_dhcp(struct uip_tx_arg *arg);
+int uip_tx_do_ipv4_icmp(struct uip_tx_arg *arg);
+int uip_tx_do_ipv4_tcp(struct uip_tx_arg *arg);
+int uip_tx_do_ipv4_udp(struct uip_tx_arg *arg);
+int uip_tx_do_ipv4(struct uip_tx_arg *arg);
+int uip_tx_do_arp(struct uip_tx_arg *arg);
+
+u16 uip_csum_icmp(struct uip_icmp *icmp);
+u16 uip_csum_udp(struct uip_udp *udp);
+u16 uip_csum_tcp(struct uip_tcp *tcp);
+u16 uip_csum_ip(struct uip_ip *ip);
+
+struct uip_buf *uip_buf_set_used(struct uip_info *info, struct uip_buf *buf);
+struct uip_buf *uip_buf_set_free(struct uip_info *info, struct uip_buf *buf);
+struct uip_buf *uip_buf_get_used(struct uip_info *info);
+struct uip_buf *uip_buf_get_free(struct uip_info *info);
+struct uip_buf *uip_buf_clone(struct uip_tx_arg *arg);
+
+int uip_udp_make_pkg(struct uip_info *info, struct uip_udp_socket *sk, struct uip_buf *buf, u8 *payload, int payload_len);
+bool uip_udp_is_dhcp(struct uip_udp *udp);
+
+int uip_dhcp_get_dns(struct uip_info *info);
+#endif /* KVM__UIP_H */
diff --git a/tools/kvm/include/kvm/util-init.h b/tools/kvm/include/kvm/util-init.h
new file mode 100644 (file)
index 0000000..13d4f04
--- /dev/null
@@ -0,0 +1,51 @@
+#ifndef KVM__UTIL_INIT_H
+#define KVM__UTIL_INIT_H
+
+struct kvm;
+
+struct init_item {
+       struct hlist_node n;
+       const char *fn_name;
+       int (*init)(struct kvm *);
+};
+
+int init_list__init(struct kvm *kvm);
+int init_list__exit(struct kvm *kvm);
+
+int init_list_add(struct init_item *t, int (*init)(struct kvm *),
+                       int priority, const char *name);
+int exit_list_add(struct init_item *t, int (*init)(struct kvm *),
+                       int priority, const char *name);
+
+#define __init_list_add(cb, l)                                         \
+static void __attribute__ ((constructor)) __init__##cb(void)           \
+{                                                                      \
+       static char name[] = #cb;                                       \
+       static struct init_item t;                                      \
+       init_list_add(&t, cb, l, name);                                 \
+}
+
+#define __exit_list_add(cb, l)                                         \
+static void __attribute__ ((constructor)) __init__##cb(void)           \
+{                                                                      \
+       static char name[] = #cb;                                       \
+       static struct init_item t;                                      \
+       exit_list_add(&t, cb, l, name);                                 \
+}
+
+#define core_init(cb) __init_list_add(cb, 0)
+#define base_init(cb) __init_list_add(cb, 2)
+#define dev_base_init(cb)  __init_list_add(cb, 4)
+#define dev_init(cb) __init_list_add(cb, 5)
+#define virtio_dev_init(cb) __init_list_add(cb, 6)
+#define firmware_init(cb) __init_list_add(cb, 7)
+#define late_init(cb) __init_list_add(cb, 9)
+
+#define core_exit(cb) __exit_list_add(cb, 0)
+#define base_exit(cb) __exit_list_add(cb, 2)
+#define dev_base_exit(cb) __exit_list_add(cb, 4)
+#define dev_exit(cb) __exit_list_add(cb, 5)
+#define virtio_dev_exit(cb) __exit_list_add(cb, 6)
+#define firmware_exit(cb) __exit_list_add(cb, 7)
+#define late_exit(cb) __exit_list_add(cb, 9)
+#endif
diff --git a/tools/kvm/include/kvm/util.h b/tools/kvm/include/kvm/util.h
new file mode 100644 (file)
index 0000000..0df9f0d
--- /dev/null
@@ -0,0 +1,97 @@
+#include <linux/stringify.h>
+
+#ifndef KVM__UTIL_H
+#define KVM__UTIL_H
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+/*
+ * Some bits are stolen from perf tool :)
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdbool.h>
+#include <signal.h>
+#include <errno.h>
+#include <limits.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <linux/types.h>
+
+#ifdef __GNUC__
+#define NORETURN __attribute__((__noreturn__))
+#else
+#define NORETURN
+#ifndef __attribute__
+#define __attribute__(x)
+#endif
+#endif
+
+extern bool do_debug_print;
+
+#define PROT_RW (PROT_READ|PROT_WRITE)
+#define MAP_ANON_NORESERVE (MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE)
+
+extern void die(const char *err, ...) NORETURN __attribute__((format (printf, 1, 2)));
+extern void die_perror(const char *s) NORETURN;
+extern int pr_err(const char *err, ...) __attribute__((format (printf, 1, 2)));
+extern void pr_warning(const char *err, ...) __attribute__((format (printf, 1, 2)));
+extern void pr_info(const char *err, ...) __attribute__((format (printf, 1, 2)));
+extern void set_die_routine(void (*routine)(const char *err, va_list params) NORETURN);
+
+#define pr_debug(fmt, ...)                                             \
+       do {                                                            \
+               if (do_debug_print)                                     \
+                       pr_info("(%s) %s:%d: " fmt, __FILE__,           \
+                               __func__, __LINE__, ##__VA_ARGS__);     \
+       } while (0)
+
+
+#define BUILD_BUG_ON(condition)        ((void)sizeof(char[1 - 2*!!(condition)]))
+
+#ifndef BUG_ON_HANDLER
+# define BUG_ON_HANDLER(condition)                                     \
+       do {                                                            \
+               if ((condition)) {                                      \
+                       pr_err("BUG at %s:%d", __FILE__, __LINE__);     \
+                       raise(SIGABRT);                                 \
+               }                                                       \
+       } while (0)
+#endif
+
+#define BUG_ON(condition)      BUG_ON_HANDLER((condition))
+
+#define DIE_IF(cnd)                                            \
+do {                                                           \
+       if (cnd)                                                \
+       die(" at (" __FILE__ ":" __stringify(__LINE__) "): "    \
+               __stringify(cnd) "\n");                         \
+} while (0)
+
+#define WARN_ON(condition) ({                                  \
+       int __ret_warn_on = !!(condition);                      \
+       if (__ret_warn_on)                                      \
+               pr_warning("(%s) %s:%d: failed condition: %s",  \
+                               __FILE__, __func__, __LINE__,   \
+                               __stringify(condition));        \
+       __ret_warn_on;                                          \
+})
+
+#define MSECS_TO_USECS(s) ((s) * 1000)
+
+/* Millisecond sleep */
+static inline void msleep(unsigned int msecs)
+{
+       usleep(MSECS_TO_USECS(msecs));
+}
+
+struct kvm;
+void *mmap_hugetlbfs(struct kvm *kvm, const char *htlbfs_path, u64 size);
+void *mmap_anon_or_hugetlbfs(struct kvm *kvm, const char *hugetlbfs_path, u64 size);
+
+#endif /* KVM__UTIL_H */
diff --git a/tools/kvm/include/kvm/vesa.h b/tools/kvm/include/kvm/vesa.h
new file mode 100644 (file)
index 0000000..ac041d9
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef KVM__VESA_H
+#define KVM__VESA_H
+
+#include <linux/types.h>
+
+#define VESA_WIDTH     640
+#define VESA_HEIGHT    480
+
+#define VESA_MEM_ADDR  0xd0000000
+#define VESA_MEM_SIZE  (4*VESA_WIDTH*VESA_HEIGHT)
+#define VESA_BPP       32
+
+struct kvm;
+struct biosregs;
+
+struct framebuffer *vesa__init(struct kvm *self);
+
+#endif
diff --git a/tools/kvm/include/kvm/virtio-9p.h b/tools/kvm/include/kvm/virtio-9p.h
new file mode 100644 (file)
index 0000000..19ffe50
--- /dev/null
@@ -0,0 +1,76 @@
+#ifndef KVM__VIRTIO_9P_H
+#define KVM__VIRTIO_9P_H
+#include "kvm/virtio.h"
+#include "kvm/pci.h"
+#include "kvm/threadpool.h"
+#include "kvm/parse-options.h"
+
+#include <sys/types.h>
+#include <dirent.h>
+#include <linux/list.h>
+#include <linux/rbtree.h>
+
+#define NUM_VIRT_QUEUES                1
+#define VIRTQUEUE_NUM          128
+#define        VIRTIO_9P_DEFAULT_TAG   "kvm_9p"
+#define VIRTIO_9P_HDR_LEN      (sizeof(u32)+sizeof(u8)+sizeof(u16))
+#define VIRTIO_9P_VERSION_DOTL "9P2000.L"
+#define MAX_TAG_LEN            32
+
+struct p9_msg {
+       u32                     size;
+       u8                      cmd;
+       u16                     tag;
+       u8                      msg[0];
+} __attribute__((packed));
+
+struct p9_fid {
+       u32                     fid;
+       u32                     uid;
+       char                    abs_path[PATH_MAX];
+       char                    *path;
+       DIR                     *dir;
+       int                     fd;
+       struct rb_node          node;
+};
+
+struct p9_dev_job {
+       struct virt_queue       *vq;
+       struct p9_dev           *p9dev;
+       struct thread_pool__job job_id;
+};
+
+struct p9_dev {
+       struct list_head        list;
+       struct virtio_device    vdev;
+       struct rb_root          fids;
+
+       struct virtio_9p_config *config;
+       u32                     features;
+
+       /* virtio queue */
+       struct virt_queue       vqs[NUM_VIRT_QUEUES];
+       struct p9_dev_job       jobs[NUM_VIRT_QUEUES];
+       char                    root_dir[PATH_MAX];
+};
+
+struct p9_pdu {
+       u32                     queue_head;
+       size_t                  read_offset;
+       size_t                  write_offset;
+       u16                     out_iov_cnt;
+       u16                     in_iov_cnt;
+       struct iovec            in_iov[VIRTQUEUE_NUM];
+       struct iovec            out_iov[VIRTQUEUE_NUM];
+};
+
+struct kvm;
+
+int virtio_9p_rootdir_parser(const struct option *opt, const char *arg, int unset);
+int virtio_9p_img_name_parser(const struct option *opt, const char *arg, int unset);
+int virtio_9p__register(struct kvm *kvm, const char *root, const char *tag_name);
+int virtio_9p__init(struct kvm *kvm);
+int virtio_p9_pdu_readf(struct p9_pdu *pdu, const char *fmt, ...);
+int virtio_p9_pdu_writef(struct p9_pdu *pdu, const char *fmt, ...);
+
+#endif
diff --git a/tools/kvm/include/kvm/virtio-balloon.h b/tools/kvm/include/kvm/virtio-balloon.h
new file mode 100644 (file)
index 0000000..844a1ba
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef KVM__BLN_VIRTIO_H
+#define KVM__BLN_VIRTIO_H
+
+struct kvm;
+
+int virtio_bln__init(struct kvm *kvm);
+int virtio_bln__exit(struct kvm *kvm);
+
+#endif /* KVM__BLN_VIRTIO_H */
diff --git a/tools/kvm/include/kvm/virtio-blk.h b/tools/kvm/include/kvm/virtio-blk.h
new file mode 100644 (file)
index 0000000..12e59b6
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef KVM__BLK_VIRTIO_H
+#define KVM__BLK_VIRTIO_H
+
+#include "kvm/disk-image.h"
+
+struct kvm;
+
+int virtio_blk__init(struct kvm *kvm);
+int virtio_blk__exit(struct kvm *kvm);
+void virtio_blk_complete(void *param, long len);
+
+#endif /* KVM__BLK_VIRTIO_H */
diff --git a/tools/kvm/include/kvm/virtio-console.h b/tools/kvm/include/kvm/virtio-console.h
new file mode 100644 (file)
index 0000000..8980920
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef KVM__CONSOLE_VIRTIO_H
+#define KVM__CONSOLE_VIRTIO_H
+
+struct kvm;
+
+int virtio_console__init(struct kvm *kvm);
+void virtio_console__inject_interrupt(struct kvm *kvm);
+int virtio_console__exit(struct kvm *kvm);
+
+#endif /* KVM__CONSOLE_VIRTIO_H */
diff --git a/tools/kvm/include/kvm/virtio-mmio.h b/tools/kvm/include/kvm/virtio-mmio.h
new file mode 100644 (file)
index 0000000..e0ede3c
--- /dev/null
@@ -0,0 +1,58 @@
+#ifndef KVM__VIRTIO_MMIO_H
+#define KVM__VIRTIO_MMIO_H
+
+#include <linux/types.h>
+#include <linux/virtio_mmio.h>
+
+#define VIRTIO_MMIO_MAX_VQ     3
+#define VIRTIO_MMIO_MAX_CONFIG 1
+#define VIRTIO_MMIO_IO_SIZE    0x200
+
+struct kvm;
+
+struct virtio_mmio_ioevent_param {
+       struct virtio_device    *vdev;
+       u32                     vq;
+};
+
+struct virtio_mmio_hdr {
+       char    magic[4];
+       u32     version;
+       u32     device_id;
+       u32     vendor_id;
+       u32     host_features;
+       u32     host_features_sel;
+       u32     reserved_1[2];
+       u32     guest_features;
+       u32     guest_features_sel;
+       u32     guest_page_size;
+       u32     reserved_2;
+       u32     queue_sel;
+       u32     queue_num_max;
+       u32     queue_num;
+       u32     queue_align;
+       u32     queue_pfn;
+       u32     reserved_3[3];
+       u32     queue_notify;
+       u32     reserved_4[3];
+       u32     interrupt_state;
+       u32     interrupt_ack;
+       u32     reserved_5[2];
+       u32     status;
+} __attribute__((packed));
+
+struct virtio_mmio {
+       u32                     addr;
+       void                    *dev;
+       struct kvm              *kvm;
+       u8                      irq;
+       struct virtio_mmio_hdr  hdr;
+       struct virtio_mmio_ioevent_param ioeventfds[VIRTIO_MMIO_MAX_VQ];
+};
+
+int virtio_mmio_signal_vq(struct kvm *kvm, struct virtio_device *vdev, u32 vq);
+int virtio_mmio_signal_config(struct kvm *kvm, struct virtio_device *vdev);
+int virtio_mmio_exit(struct kvm *kvm, struct virtio_device *vdev);
+int virtio_mmio_init(struct kvm *kvm, void *dev, struct virtio_device *vdev,
+                     int device_id, int subsys_id, int class);
+#endif
diff --git a/tools/kvm/include/kvm/virtio-net.h b/tools/kvm/include/kvm/virtio-net.h
new file mode 100644 (file)
index 0000000..db43d98
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef KVM__VIRTIO_NET_H
+#define KVM__VIRTIO_NET_H
+
+#include "kvm/parse-options.h"
+
+struct kvm;
+
+struct virtio_net_params {
+       const char *guest_ip;
+       const char *host_ip;
+       const char *script;
+       const char *trans;
+       char guest_mac[6];
+       char host_mac[6];
+       struct kvm *kvm;
+       int mode;
+       int vhost;
+       int fd;
+};
+
+int virtio_net__init(struct kvm *kvm);
+int virtio_net__exit(struct kvm *kvm);
+int netdev_parser(const struct option *opt, const char *arg, int unset);
+
+enum {
+       NET_MODE_USER,
+       NET_MODE_TAP
+};
+
+#endif /* KVM__VIRTIO_NET_H */
diff --git a/tools/kvm/include/kvm/virtio-pci-dev.h b/tools/kvm/include/kvm/virtio-pci-dev.h
new file mode 100644 (file)
index 0000000..48ae018
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef VIRTIO_PCI_DEV_H_
+#define VIRTIO_PCI_DEV_H_
+
+#include <linux/virtio_ids.h>
+
+/*
+ * Virtio PCI device constants and resources
+ * they do use (such as irqs and pins).
+ */
+
+#define PCI_DEVICE_ID_VIRTIO_NET               0x1000
+#define PCI_DEVICE_ID_VIRTIO_BLK               0x1001
+#define PCI_DEVICE_ID_VIRTIO_CONSOLE           0x1003
+#define PCI_DEVICE_ID_VIRTIO_RNG               0x1004
+#define PCI_DEVICE_ID_VIRTIO_BLN               0x1005
+#define PCI_DEVICE_ID_VIRTIO_SCSI              0x1008
+#define PCI_DEVICE_ID_VIRTIO_9P                        0x1009
+#define PCI_DEVICE_ID_VESA                     0x2000
+#define PCI_DEVICE_ID_PCI_SHMEM                        0x0001
+
+#define PCI_VENDOR_ID_REDHAT_QUMRANET          0x1af4
+#define PCI_VENDOR_ID_PCI_SHMEM                        0x0001
+#define PCI_SUBSYSTEM_VENDOR_ID_REDHAT_QUMRANET        0x1af4
+
+#define PCI_SUBSYSTEM_ID_VESA                  0x0004
+#define PCI_SUBSYSTEM_ID_PCI_SHMEM             0x0001
+
+#define PCI_CLASS_BLK                          0x018000
+#define PCI_CLASS_NET                          0x020000
+#define PCI_CLASS_CONSOLE                      0x078000
+/*
+ * 0xFF Device does not fit in any defined classes
+ */
+#define PCI_CLASS_RNG                          0xff0000
+#define PCI_CLASS_BLN                          0xff0000
+#define PCI_CLASS_9P                           0xff0000
+
+#endif /* VIRTIO_PCI_DEV_H_ */
diff --git a/tools/kvm/include/kvm/virtio-pci.h b/tools/kvm/include/kvm/virtio-pci.h
new file mode 100644 (file)
index 0000000..44130e0
--- /dev/null
@@ -0,0 +1,49 @@
+#ifndef KVM__VIRTIO_PCI_H
+#define KVM__VIRTIO_PCI_H
+
+#include "kvm/pci.h"
+
+#include <linux/types.h>
+
+#define VIRTIO_PCI_MAX_VQ      3
+#define VIRTIO_PCI_MAX_CONFIG  1
+
+struct kvm;
+
+struct virtio_pci_ioevent_param {
+       struct virtio_device    *vdev;
+       u32                     vq;
+};
+
+#define VIRTIO_PCI_F_SIGNAL_MSI (1 << 0)
+
+struct virtio_pci {
+       struct pci_device_header pci_hdr;
+       void                    *dev;
+
+       u16                     base_addr;
+       u8                      status;
+       u8                      isr;
+       u32                     features;
+
+       /* MSI-X */
+       u16                     config_vector;
+       u32                     config_gsi;
+       u32                     vq_vector[VIRTIO_PCI_MAX_VQ];
+       u32                     gsis[VIRTIO_PCI_MAX_VQ];
+       u32                     msix_io_block;
+       u64                     msix_pba;
+       struct msix_table       msix_table[VIRTIO_PCI_MAX_VQ + VIRTIO_PCI_MAX_CONFIG];
+
+       /* virtio queue */
+       u16                     queue_selector;
+       struct virtio_pci_ioevent_param ioeventfds[VIRTIO_PCI_MAX_VQ];
+};
+
+int virtio_pci__signal_vq(struct kvm *kvm, struct virtio_device *vdev, u32 vq);
+int virtio_pci__signal_config(struct kvm *kvm, struct virtio_device *vdev);
+int virtio_pci__exit(struct kvm *kvm, struct virtio_device *vdev);
+int virtio_pci__init(struct kvm *kvm, void *dev, struct virtio_device *vdev,
+                    int device_id, int subsys_id, int class);
+
+#endif
diff --git a/tools/kvm/include/kvm/virtio-rng.h b/tools/kvm/include/kvm/virtio-rng.h
new file mode 100644 (file)
index 0000000..b585b37
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef KVM__RNG_VIRTIO_H
+#define KVM__RNG_VIRTIO_H
+
+struct kvm;
+
+int virtio_rng__init(struct kvm *kvm);
+int virtio_rng__exit(struct kvm *kvm);
+
+#endif /* KVM__RNG_VIRTIO_H */
diff --git a/tools/kvm/include/kvm/virtio-scsi.h b/tools/kvm/include/kvm/virtio-scsi.h
new file mode 100644 (file)
index 0000000..a780d7e
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef KVM__SCSI_VIRTIO_H
+#define KVM__SCSI_VIRTIO_H
+
+#include "kvm/disk-image.h"
+
+struct kvm;
+
+int virtio_scsi_init(struct kvm *kvm);
+int virtio_scsi_exit(struct kvm *kvm);
+
+/*----------------------------------------------------*/
+/* TODO: Remove this when tcm_vhost goes upstream */
+#define TRANSPORT_IQN_LEN              224
+#define VHOST_SCSI_ABI_VERSION         0
+struct vhost_scsi_target {
+       int abi_version;
+       unsigned char vhost_wwpn[TRANSPORT_IQN_LEN];
+       unsigned short vhost_tpgt;
+};
+/* VHOST_SCSI specific defines */
+#define VHOST_SCSI_SET_ENDPOINT _IOW(VHOST_VIRTIO, 0x40, struct vhost_scsi_target)
+#define VHOST_SCSI_CLEAR_ENDPOINT _IOW(VHOST_VIRTIO, 0x41, struct vhost_scsi_target)
+#define VHOST_SCSI_GET_ABI_VERSION _IOW(VHOST_VIRTIO, 0x42, struct vhost_scsi_target)
+/*----------------------------------------------------*/
+
+#endif /* KVM__SCSI_VIRTIO_H */
diff --git a/tools/kvm/include/kvm/virtio.h b/tools/kvm/include/kvm/virtio.h
new file mode 100644 (file)
index 0000000..5dc2544
--- /dev/null
@@ -0,0 +1,102 @@
+#ifndef KVM__VIRTIO_H
+#define KVM__VIRTIO_H
+
+#include <linux/virtio_ring.h>
+#include <linux/virtio_pci.h>
+
+#include <linux/types.h>
+#include <sys/uio.h>
+
+#include "kvm/kvm.h"
+
+#define VIRTIO_IRQ_LOW         0
+#define VIRTIO_IRQ_HIGH                1
+
+#define VIRTIO_PCI_O_CONFIG    0
+#define VIRTIO_PCI_O_MSIX      1
+
+struct virt_queue {
+       struct vring    vring;
+       u32             pfn;
+       /* The last_avail_idx field is an index to ->ring of struct vring_avail.
+          It's where we assume the next request index is at.  */
+       u16             last_avail_idx;
+       u16             last_used_signalled;
+};
+
+static inline u16 virt_queue__pop(struct virt_queue *queue)
+{
+       return queue->vring.avail->ring[queue->last_avail_idx++ % queue->vring.num];
+}
+
+static inline struct vring_desc *virt_queue__get_desc(struct virt_queue *queue, u16 desc_ndx)
+{
+       return &queue->vring.desc[desc_ndx];
+}
+
+static inline bool virt_queue__available(struct virt_queue *vq)
+{
+       if (!vq->vring.avail)
+               return 0;
+
+       vring_avail_event(&vq->vring) = vq->last_avail_idx;
+       return vq->vring.avail->idx !=  vq->last_avail_idx;
+}
+
+/*
+ * Warning: on 32-bit hosts, shifting pfn left may cause a truncation of pfn values
+ * higher than 4GB - thus, pointing to the wrong area in guest virtual memory space
+ * and breaking the virt queue which owns this pfn.
+ */
+static inline void *guest_pfn_to_host(struct kvm *kvm, u32 pfn)
+{
+       return guest_flat_to_host(kvm, (unsigned long)pfn << VIRTIO_PCI_QUEUE_ADDR_SHIFT);
+}
+
+
+struct vring_used_elem *virt_queue__set_used_elem(struct virt_queue *queue, u32 head, u32 len);
+
+bool virtio_queue__should_signal(struct virt_queue *vq);
+u16 virt_queue__get_iov(struct virt_queue *vq, struct iovec iov[],
+                       u16 *out, u16 *in, struct kvm *kvm);
+u16 virt_queue__get_head_iov(struct virt_queue *vq, struct iovec iov[],
+                            u16 *out, u16 *in, u16 head, struct kvm *kvm);
+u16 virt_queue__get_inout_iov(struct kvm *kvm, struct virt_queue *queue,
+                             struct iovec in_iov[], struct iovec out_iov[],
+                             u16 *in, u16 *out);
+int virtio__get_dev_specific_field(int offset, bool msix, u32 *config_off);
+
+enum virtio_trans {
+       VIRTIO_PCI,
+       VIRTIO_MMIO,
+};
+
+struct virtio_device {
+       bool                    use_vhost;
+       void                    *virtio;
+       struct virtio_ops       *ops;
+};
+
+struct virtio_ops {
+       u8 *(*get_config)(struct kvm *kvm, void *dev);
+       u32 (*get_host_features)(struct kvm *kvm, void *dev);
+       void (*set_guest_features)(struct kvm *kvm, void *dev, u32 features);
+       int (*init_vq)(struct kvm *kvm, void *dev, u32 vq, u32 pfn);
+       int (*notify_vq)(struct kvm *kvm, void *dev, u32 vq);
+       int (*get_pfn_vq)(struct kvm *kvm, void *dev, u32 vq);
+       int (*get_size_vq)(struct kvm *kvm, void *dev, u32 vq);
+       int (*set_size_vq)(struct kvm *kvm, void *dev, u32 vq, int size);
+       void (*notify_vq_gsi)(struct kvm *kvm, void *dev, u32 vq, u32 gsi);
+       void (*notify_vq_eventfd)(struct kvm *kvm, void *dev, u32 vq, u32 efd);
+       int (*signal_vq)(struct kvm *kvm, struct virtio_device *vdev, u32 queueid);
+       int (*signal_config)(struct kvm *kvm, struct virtio_device *vdev);
+       int (*init)(struct kvm *kvm, void *dev, struct virtio_device *vdev,
+                   int device_id, int subsys_id, int class);
+       int (*exit)(struct kvm *kvm, struct virtio_device *vdev);
+};
+
+int virtio_init(struct kvm *kvm, void *dev, struct virtio_device *vdev,
+               struct virtio_ops *ops, enum virtio_trans trans,
+               int device_id, int subsys_id, int class);
+int virtio_compat_add_message(const char *device, const char *config);
+#endif /* KVM__VIRTIO_H */
diff --git a/tools/kvm/include/kvm/vnc.h b/tools/kvm/include/kvm/vnc.h
new file mode 100644 (file)
index 0000000..c2934a4
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef KVM__VNC_H
+#define KVM__VNC_H
+
+#include "kvm/kvm.h"
+
+struct framebuffer;
+
+#ifdef CONFIG_HAS_VNCSERVER
+int vnc__init(struct kvm *kvm);
+int vnc__exit(struct kvm *kvm);
+#else
+static inline int vnc__init(struct kvm *kvm)
+{
+       return 0;
+}
+static inline int vnc__exit(struct kvm *kvm)
+{
+       return 0;
+}
+#endif
+
+#endif /* KVM__VNC_H */
diff --git a/tools/kvm/include/linux/bitops.h b/tools/kvm/include/linux/bitops.h
new file mode 100644 (file)
index 0000000..56448b7
--- /dev/null
@@ -0,0 +1,33 @@
+#ifndef _KVM_LINUX_BITOPS_H_
+#define _KVM_LINUX_BITOPS_H_
+
+#include <linux/kernel.h>
+#include <linux/compiler.h>
+#include <asm/hweight.h>
+
+#define BITS_PER_LONG __WORDSIZE
+#define BITS_PER_BYTE           8
+#define BITS_TO_LONGS(nr)       DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
+
+static inline void set_bit(int nr, unsigned long *addr)
+{
+       addr[nr / BITS_PER_LONG] |= 1UL << (nr % BITS_PER_LONG);
+}
+
+static inline void clear_bit(int nr, unsigned long *addr)
+{
+       addr[nr / BITS_PER_LONG] &= ~(1UL << (nr % BITS_PER_LONG));
+}
+
+static __always_inline int test_bit(unsigned int nr, const unsigned long *addr)
+{
+       return ((1UL << (nr % BITS_PER_LONG)) &
+               (((unsigned long *)addr)[nr / BITS_PER_LONG])) != 0;
+}
+
+static inline unsigned long hweight_long(unsigned long w)
+{
+       return sizeof(w) == 4 ? hweight32(w) : hweight64(w);
+}
+
+#endif
diff --git a/tools/kvm/include/linux/byteorder.h b/tools/kvm/include/linux/byteorder.h
new file mode 100644 (file)
index 0000000..c490de8
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef __BYTE_ORDER_H__
+#define __BYTE_ORDER_H__
+
+#include <asm/byteorder.h>
+#include <linux/byteorder/generic.h>
+
+#endif
diff --git a/tools/kvm/include/linux/compiler.h b/tools/kvm/include/linux/compiler.h
new file mode 100644 (file)
index 0000000..898420b
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef _PERF_LINUX_COMPILER_H_
+#define _PERF_LINUX_COMPILER_H_
+
+#ifndef __always_inline
+#define __always_inline        inline
+#endif
+#define __user
+
+#ifndef __attribute_const__
+#define __attribute_const__
+#endif
+
+#define __used         __attribute__((__unused__))
+#define __packed       __attribute__((packed))
+#define __iomem
+#define __force
+#define __must_check
+#define unlikely
+
+#endif
diff --git a/tools/kvm/include/linux/kernel.h b/tools/kvm/include/linux/kernel.h
new file mode 100644 (file)
index 0000000..1e9abe9
--- /dev/null
@@ -0,0 +1,41 @@
+
+#ifndef KVM__LINUX_KERNEL_H_
+#define KVM__LINUX_KERNEL_H_
+
+#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
+
+#define ALIGN(x,a)             __ALIGN_MASK(x,(typeof(x))(a)-1)
+#define __ALIGN_MASK(x,mask)   (((x)+(mask))&~(mask))
+
+#ifndef offsetof
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+#endif
+
+#ifndef container_of
+/**
+ * container_of - cast a member of a structure out to the containing structure
+ * @ptr:       the pointer to the member.
+ * @type:      the type of the container struct this is embedded in.
+ * @member:    the name of the member within the struct.
+ *
+ */
+#define container_of(ptr, type, member) ({                     \
+       const typeof(((type *)0)->member) * __mptr = (ptr);     \
+       (type *)((char *)__mptr - offsetof(type, member)); })
+#endif
+
+#define min(x, y) ({                           \
+       typeof(x) _min1 = (x);                  \
+       typeof(y) _min2 = (y);                  \
+       (void) (&_min1 == &_min2);              \
+       _min1 < _min2 ? _min1 : _min2; })
+
+#define max(x, y) ({                           \
+       typeof(x) _max1 = (x);                  \
+       typeof(y) _max2 = (y);                  \
+       (void) (&_max1 == &_max2);              \
+       _max1 > _max2 ? _max1 : _max2; })
+
+#define true 1
+
+#endif
diff --git a/tools/kvm/include/linux/module.h b/tools/kvm/include/linux/module.h
new file mode 100644 (file)
index 0000000..0e4c6a3
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef KVM__LINUX_MODULE_H
+#define KVM__LINUX_MODULE_H
+
+#define EXPORT_SYMBOL(name)
+
+#endif
diff --git a/tools/kvm/include/linux/prefetch.h b/tools/kvm/include/linux/prefetch.h
new file mode 100644 (file)
index 0000000..62f6788
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef KVM__LINUX_PREFETCH_H
+#define KVM__LINUX_PREFETCH_H
+
+static inline void prefetch(void *a __attribute__((unused))) { }
+
+#endif
diff --git a/tools/kvm/include/linux/stddef.h b/tools/kvm/include/linux/stddef.h
new file mode 100644 (file)
index 0000000..60ea512
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef _LINUX_STDDEF_H
+#define _LINUX_STDDEF_H
+
+#include <linux/compiler.h>
+
+#undef NULL
+#define NULL ((void *)0)
+
+#undef offsetof
+#ifdef __compiler_offsetof
+#define offsetof(TYPE,MEMBER) __compiler_offsetof(TYPE,MEMBER)
+#else
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+#endif
+
+#endif
diff --git a/tools/kvm/include/linux/types.h b/tools/kvm/include/linux/types.h
new file mode 100644 (file)
index 0000000..5e20f10
--- /dev/null
@@ -0,0 +1,51 @@
+#ifndef LINUX_TYPES_H
+#define LINUX_TYPES_H
+
+#include <kvm/compiler.h>
+#define __SANE_USERSPACE_TYPES__       /* For PPC64, to get LL64 types */
+#include <asm/types.h>
+
+typedef __u64 u64;
+typedef __s64 s64;
+
+typedef __u32 u32;
+typedef __s32 s32;
+
+typedef __u16 u16;
+typedef __s16 s16;
+
+typedef __u8  u8;
+typedef __s8  s8;
+
+#ifdef __CHECKER__
+#define __bitwise__ __attribute__((bitwise))
+#else
+#define __bitwise__
+#endif
+#ifdef __CHECK_ENDIAN__
+#define __bitwise __bitwise__
+#else
+#define __bitwise
+#endif
+
+
+typedef __u16 __bitwise __le16;
+typedef __u16 __bitwise __be16;
+typedef __u32 __bitwise __le32;
+typedef __u32 __bitwise __be32;
+typedef __u64 __bitwise __le64;
+typedef __u64 __bitwise __be64;
+
+struct list_head {
+       struct list_head *next, *prev;
+};
+
+struct hlist_head {
+       struct hlist_node *first;
+};
+
+struct hlist_node {
+       struct hlist_node *next, **pprev;
+};
+
+#endif /* LINUX_TYPES_H */
diff --git a/tools/kvm/ioeventfd.c b/tools/kvm/ioeventfd.c
new file mode 100644 (file)
index 0000000..a68d8d0
--- /dev/null
@@ -0,0 +1,216 @@
+#include <sys/epoll.h>
+#include <sys/ioctl.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <signal.h>
+
+#include <linux/kernel.h>
+#include <linux/kvm.h>
+#include <linux/types.h>
+
+#include "kvm/ioeventfd.h"
+#include "kvm/kvm.h"
+#include "kvm/util.h"
+
+#define IOEVENTFD_MAX_EVENTS   20
+
+static struct  epoll_event events[IOEVENTFD_MAX_EVENTS];
+static int     epoll_fd, epoll_stop_fd;
+static LIST_HEAD(used_ioevents);
+static bool    ioeventfd_avail;
+
+static void *ioeventfd__thread(void *param)
+{
+       u64 tmp = 1;
+
+       for (;;) {
+               int nfds, i;
+
+               nfds = epoll_wait(epoll_fd, events, IOEVENTFD_MAX_EVENTS, -1);
+               for (i = 0; i < nfds; i++) {
+                       struct ioevent *ioevent;
+
+                       if (events[i].data.fd == epoll_stop_fd)
+                               goto done;
+
+                       ioevent = events[i].data.ptr;
+
+                       if (read(ioevent->fd, &tmp, sizeof(tmp)) < 0)
+                               die("Failed reading event");
+
+                       ioevent->fn(ioevent->fn_kvm, ioevent->fn_ptr);
+               }
+       }
+
+done:
+       tmp = write(epoll_stop_fd, &tmp, sizeof(tmp));
+
+       return NULL;
+}
+
+static int ioeventfd__start(void)
+{
+       pthread_t thread;
+
+       if (!ioeventfd_avail)
+               return -ENOSYS;
+
+       return pthread_create(&thread, NULL, ioeventfd__thread, NULL);
+}
+
+int ioeventfd__init(struct kvm *kvm)
+{
+       struct epoll_event epoll_event = {.events = EPOLLIN};
+       int r;
+
+       ioeventfd_avail = kvm__supports_extension(kvm, KVM_CAP_IOEVENTFD);
+       if (!ioeventfd_avail)
+               return 1; /* Not fatal, but let caller determine no-go. */
+
+       epoll_fd = epoll_create(IOEVENTFD_MAX_EVENTS);
+       if (epoll_fd < 0)
+               return -errno;
+
+       epoll_stop_fd = eventfd(0, 0);
+       epoll_event.data.fd = epoll_stop_fd;
+
+       r = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, epoll_stop_fd, &epoll_event);
+       if (r < 0)
+               goto cleanup;
+
+       r = ioeventfd__start();
+       if (r < 0)
+               goto cleanup;
+
+       r = 0;
+
+       return r;
+
+cleanup:
+       close(epoll_stop_fd);
+       close(epoll_fd);
+
+       return r;
+}
+base_init(ioeventfd__init);
+
+int ioeventfd__exit(struct kvm *kvm)
+{
+       u64 tmp = 1;
+       int r;
+
+       if (!ioeventfd_avail)
+               return 0;
+
+       r = write(epoll_stop_fd, &tmp, sizeof(tmp));
+       if (r < 0)
+               return r;
+
+       r = read(epoll_stop_fd, &tmp, sizeof(tmp));
+       if (r < 0)
+               return r;
+
+       close(epoll_fd);
+       close(epoll_stop_fd);
+
+       return 0;
+}
+base_exit(ioeventfd__exit);
+
+int ioeventfd__add_event(struct ioevent *ioevent, bool is_pio, bool poll_in_userspace)
+{
+       struct kvm_ioeventfd kvm_ioevent;
+       struct epoll_event epoll_event;
+       struct ioevent *new_ioevent;
+       int event, r;
+
+       if (!ioeventfd_avail)
+               return -ENOSYS;
+
+       new_ioevent = malloc(sizeof(*new_ioevent));
+       if (new_ioevent == NULL)
+               return -ENOMEM;
+
+       *new_ioevent = *ioevent;
+       event = new_ioevent->fd;
+
+       kvm_ioevent = (struct kvm_ioeventfd) {
+               .addr           = ioevent->io_addr,
+               .len            = ioevent->io_len,
+               .datamatch      = ioevent->datamatch,
+               .fd             = event,
+               .flags          = KVM_IOEVENTFD_FLAG_DATAMATCH,
+       };
+
+       if (is_pio)
+               kvm_ioevent.flags |= KVM_IOEVENTFD_FLAG_PIO;
+
+       r = ioctl(ioevent->fn_kvm->vm_fd, KVM_IOEVENTFD, &kvm_ioevent);
+       if (r) {
+               r = -errno;
+               goto cleanup;
+       }
+
+       if (!poll_in_userspace)
+               return 0;
+
+       epoll_event = (struct epoll_event) {
+               .events         = EPOLLIN,
+               .data.ptr       = new_ioevent,
+       };
+
+       r = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, event, &epoll_event);
+       if (r) {
+               r = -errno;
+               goto cleanup;
+       }
+
+       list_add_tail(&new_ioevent->list, &used_ioevents);
+
+       return 0;
+
+cleanup:
+       free(new_ioevent);
+       return r;
+}
+
+int ioeventfd__del_event(u64 addr, u64 datamatch)
+{
+       struct kvm_ioeventfd kvm_ioevent;
+       struct ioevent *ioevent;
+       u8 found = 0;
+
+       if (!ioeventfd_avail)
+               return -ENOSYS;
+
+       list_for_each_entry(ioevent, &used_ioevents, list) {
+               if (ioevent->io_addr == addr) {
+                       found = 1;
+                       break;
+               }
+       }
+
+       if (found == 0 || ioevent == NULL)
+               return -ENOENT;
+
+       kvm_ioevent = (struct kvm_ioeventfd) {
+               .addr                   = ioevent->io_addr,
+               .len                    = ioevent->io_len,
+               .datamatch              = ioevent->datamatch,
+               .flags                  = KVM_IOEVENTFD_FLAG_PIO
+                                       | KVM_IOEVENTFD_FLAG_DEASSIGN
+                                       | KVM_IOEVENTFD_FLAG_DATAMATCH,
+       };
+
+       ioctl(ioevent->fn_kvm->vm_fd, KVM_IOEVENTFD, &kvm_ioevent);
+
+       epoll_ctl(epoll_fd, EPOLL_CTL_DEL, ioevent->fd, NULL);
+
+       list_del(&ioevent->list);
+
+       close(ioevent->fd);
+       free(ioevent);
+
+       return 0;
+}
diff --git a/tools/kvm/ioport.c b/tools/kvm/ioport.c
new file mode 100644 (file)
index 0000000..a4f1582
--- /dev/null
@@ -0,0 +1,198 @@
+#include "kvm/ioport.h"
+
+#include "kvm/kvm.h"
+#include "kvm/util.h"
+#include "kvm/brlock.h"
+#include "kvm/rbtree-interval.h"
+#include "kvm/mutex.h"
+
+#include <linux/kvm.h> /* for KVM_EXIT_* */
+#include <linux/types.h>
+
+#include <stdbool.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#define ioport_node(n) rb_entry(n, struct ioport, node)
+
+DEFINE_MUTEX(ioport_mutex);
+
+static u16                     free_io_port_idx; /* protected by ioport_mutex */
+
+static struct rb_root          ioport_tree = RB_ROOT;
+
+static u16 ioport__find_free_port(void)
+{
+       u16 free_port;
+
+       mutex_lock(&ioport_mutex);
+       free_port = IOPORT_START + free_io_port_idx * IOPORT_SIZE;
+       free_io_port_idx++;
+       mutex_unlock(&ioport_mutex);
+
+       return free_port;
+}
+
+static struct ioport *ioport_search(struct rb_root *root, u64 addr)
+{
+       struct rb_int_node *node;
+
+       node = rb_int_search_single(root, addr);
+       if (node == NULL)
+               return NULL;
+
+       return ioport_node(node);
+}
+
+static int ioport_insert(struct rb_root *root, struct ioport *data)
+{
+       return rb_int_insert(root, &data->node);
+}
+
+static void ioport_remove(struct rb_root *root, struct ioport *data)
+{
+       rb_int_erase(root, &data->node);
+}
+
+int ioport__register(struct kvm *kvm, u16 port, struct ioport_operations *ops, int count, void *param)
+{
+       struct ioport *entry;
+       int r;
+
+       br_write_lock(kvm);
+       if (port == IOPORT_EMPTY)
+               port = ioport__find_free_port();
+
+       entry = ioport_search(&ioport_tree, port);
+       if (entry) {
+               pr_warning("ioport re-registered: %x", port);
+               rb_int_erase(&ioport_tree, &entry->node);
+       }
+
+       entry = malloc(sizeof(*entry));
+       if (entry == NULL)
+               return -ENOMEM;
+
+       *entry = (struct ioport) {
+               .node   = RB_INT_INIT(port, port + count),
+               .ops    = ops,
+               .priv   = param,
+       };
+
+       r = ioport_insert(&ioport_tree, entry);
+       if (r < 0) {
+               free(entry);
+               br_write_unlock(kvm);
+               return r;
+       }
+       br_write_unlock(kvm);
+
+       return port;
+}
+
+int ioport__unregister(struct kvm *kvm, u16 port)
+{
+       struct ioport *entry;
+       int r;
+
+       br_write_lock(kvm);
+
+       r = -ENOENT;
+       entry = ioport_search(&ioport_tree, port);
+       if (!entry)
+               goto done;
+
+       ioport_remove(&ioport_tree, entry);
+
+       free(entry);
+
+       r = 0;
+
+done:
+       br_write_unlock(kvm);
+
+       return r;
+}
+
+static void ioport__unregister_all(void)
+{
+       struct ioport *entry;
+       struct rb_node *rb;
+       struct rb_int_node *rb_node;
+
+       rb = rb_first(&ioport_tree);
+       while (rb) {
+               rb_node = rb_int(rb);
+               entry = ioport_node(rb_node);
+               ioport_remove(&ioport_tree, entry);
+               free(entry);
+               rb = rb_first(&ioport_tree);
+       }
+}
+
+static const char *to_direction(int direction)
+{
+       if (direction == KVM_EXIT_IO_IN)
+               return "IN";
+       else
+               return "OUT";
+}
+
+static void ioport_error(u16 port, void *data, int direction, int size, u32 count)
+{
+       fprintf(stderr, "IO error: %s port=%x, size=%d, count=%u\n", to_direction(direction), port, size, count);
+}
+
+bool kvm__emulate_io(struct kvm *kvm, u16 port, void *data, int direction, int size, u32 count)
+{
+       struct ioport_operations *ops;
+       bool ret = false;
+       struct ioport *entry;
+       void *ptr = data;
+
+       br_read_lock();
+       entry = ioport_search(&ioport_tree, port);
+       if (!entry)
+               goto error;
+
+       ops     = entry->ops;
+
+       while (count--) {
+               if (direction == KVM_EXIT_IO_IN && ops->io_in)
+                               ret = ops->io_in(entry, kvm, port, ptr, size);
+               else if (ops->io_out)
+                               ret = ops->io_out(entry, kvm, port, ptr, size);
+
+               ptr += size;
+       }
+
+       br_read_unlock();
+
+       if (!ret)
+               goto error;
+
+       return true;
+error:
+       br_read_unlock();
+
+       if (kvm->cfg.ioport_debug)
+               ioport_error(port, data, direction, size, count);
+
+       return !kvm->cfg.ioport_debug;
+}
+
+int ioport__init(struct kvm *kvm)
+{
+       ioport__setup_arch(kvm);
+
+       return 0;
+}
+dev_base_init(ioport__init);
+
+int ioport__exit(struct kvm *kvm)
+{
+       ioport__unregister_all();
+       return 0;
+}
+dev_base_exit(ioport__exit);
diff --git a/tools/kvm/kvm-cmd.c b/tools/kvm/kvm-cmd.c
new file mode 100644 (file)
index 0000000..2520b08
--- /dev/null
@@ -0,0 +1,91 @@
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+/* user defined header files */
+#include "kvm/builtin-debug.h"
+#include "kvm/builtin-pause.h"
+#include "kvm/builtin-resume.h"
+#include "kvm/builtin-balloon.h"
+#include "kvm/builtin-list.h"
+#include "kvm/builtin-version.h"
+#include "kvm/builtin-setup.h"
+#include "kvm/builtin-stop.h"
+#include "kvm/builtin-stat.h"
+#include "kvm/builtin-help.h"
+#include "kvm/builtin-sandbox.h"
+#include "kvm/kvm-cmd.h"
+#include "kvm/builtin-run.h"
+#include "kvm/util.h"
+
+struct cmd_struct kvm_commands[] = {
+       { "pause",      kvm_cmd_pause,          kvm_pause_help,         0 },
+       { "resume",     kvm_cmd_resume,         kvm_resume_help,        0 },
+       { "debug",      kvm_cmd_debug,          kvm_debug_help,         0 },
+       { "balloon",    kvm_cmd_balloon,        kvm_balloon_help,       0 },
+       { "list",       kvm_cmd_list,           kvm_list_help,          0 },
+       { "version",    kvm_cmd_version,        NULL,                   0 },
+       { "--version",  kvm_cmd_version,        NULL,                   0 },
+       { "stop",       kvm_cmd_stop,           kvm_stop_help,          0 },
+       { "stat",       kvm_cmd_stat,           kvm_stat_help,          0 },
+       { "help",       kvm_cmd_help,           NULL,                   0 },
+       { "setup",      kvm_cmd_setup,          kvm_setup_help,         0 },
+       { "run",        kvm_cmd_run,            kvm_run_help,           0 },
+       { "sandbox",    kvm_cmd_sandbox,        kvm_run_help,           0 },
+       { NULL,         NULL,                   NULL,                   0 },
+};
+
+/*
+ * kvm_get_command: Searches the command in an array of the commands and
+ * returns a pointer to cmd_struct if a match is found.
+ *
+ * Input parameters:
+ * command: Array of possible commands. The last entry in the array must be
+ *          NULL.
+ * cmd: A string command to search in the array
+ *
+ * Return Value:
+ * NULL: If the cmd is not matched with any of the command in the command array
+ * p: Pointer to cmd_struct of the matching command
+ */
+struct cmd_struct *kvm_get_command(struct cmd_struct *command,
+               const char *cmd)
+{
+       struct cmd_struct *p = command;
+
+       while (p->cmd) {
+               if (!strcmp(p->cmd, cmd))
+                       return p;
+               p++;
+       }
+       return NULL;
+}
+
+int handle_command(struct cmd_struct *command, int argc, const char **argv)
+{
+       struct cmd_struct *p;
+       const char *prefix = NULL;
+       int ret = 0;
+
+       if (!argv || !*argv) {
+               p = kvm_get_command(command, "help");
+               BUG_ON(!p);
+               return p->fn(argc, argv, prefix);
+       }
+
+       p = kvm_get_command(command, argv[0]);
+       if (!p) {
+               p = kvm_get_command(command, "help");
+               BUG_ON(!p);
+               p->fn(0, NULL, prefix);
+               return EINVAL;
+       }
+
+       ret = p->fn(argc - 1, &argv[1], prefix);
+       if (ret < 0) {
+               if (errno == EPERM)
+                       die("Permission error - are you root?");
+       }
+
+       return ret;
+}
diff --git a/tools/kvm/kvm-cpu.c b/tools/kvm/kvm-cpu.c
new file mode 100644 (file)
index 0000000..be05c49
--- /dev/null
@@ -0,0 +1,242 @@
+#include "kvm/kvm-cpu.h"
+
+#include "kvm/symbol.h"
+#include "kvm/util.h"
+#include "kvm/kvm.h"
+
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <stdio.h>
+
+extern __thread struct kvm_cpu *current_kvm_cpu;
+
+void kvm_cpu__enable_singlestep(struct kvm_cpu *vcpu)
+{
+       struct kvm_guest_debug debug = {
+               .control        = KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_SINGLESTEP,
+       };
+
+       if (ioctl(vcpu->vcpu_fd, KVM_SET_GUEST_DEBUG, &debug) < 0)
+               pr_warning("KVM_SET_GUEST_DEBUG failed");
+}
+
+void kvm_cpu__run(struct kvm_cpu *vcpu)
+{
+       int err;
+
+       if (!vcpu->is_running)
+               return;
+
+       err = ioctl(vcpu->vcpu_fd, KVM_RUN, 0);
+       if (err < 0 && (errno != EINTR && errno != EAGAIN))
+               die_perror("KVM_RUN failed");
+}
+
+static void kvm_cpu_signal_handler(int signum)
+{
+       if (signum == SIGKVMEXIT) {
+               if (current_kvm_cpu && current_kvm_cpu->is_running) {
+                       current_kvm_cpu->is_running = false;
+                       kvm__continue(current_kvm_cpu->kvm);
+               }
+       } else if (signum == SIGKVMPAUSE) {
+               current_kvm_cpu->paused = 1;
+       }
+}
+
+static void kvm_cpu__handle_coalesced_mmio(struct kvm_cpu *cpu)
+{
+       if (cpu->ring) {
+               while (cpu->ring->first != cpu->ring->last) {
+                       struct kvm_coalesced_mmio *m;
+                       m = &cpu->ring->coalesced_mmio[cpu->ring->first];
+                       kvm_cpu__emulate_mmio(cpu->kvm,
+                                             m->phys_addr,
+                                             m->data,
+                                             m->len,
+                                             1);
+                       cpu->ring->first = (cpu->ring->first + 1) % KVM_COALESCED_MMIO_MAX;
+               }
+       }
+}
+
+void kvm_cpu__reboot(struct kvm *kvm)
+{
+       int i;
+
+       /* The kvm->cpus array contains a null pointer in the last location */
+       for (i = 0; ; i++) {
+               if (kvm->cpus[i])
+                       pthread_kill(kvm->cpus[i]->thread, SIGKVMEXIT);
+               else
+                       break;
+       }
+}
+
+int kvm_cpu__start(struct kvm_cpu *cpu)
+{
+       sigset_t sigset;
+
+       sigemptyset(&sigset);
+       sigaddset(&sigset, SIGALRM);
+
+       pthread_sigmask(SIG_BLOCK, &sigset, NULL);
+
+       signal(SIGKVMEXIT, kvm_cpu_signal_handler);
+       signal(SIGKVMPAUSE, kvm_cpu_signal_handler);
+
+       kvm_cpu__reset_vcpu(cpu);
+
+       if (cpu->kvm->cfg.single_step)
+               kvm_cpu__enable_singlestep(cpu);
+
+       while (cpu->is_running) {
+               if (cpu->paused) {
+                       kvm__notify_paused();
+                       cpu->paused = 0;
+               }
+
+               if (cpu->needs_nmi) {
+                       kvm_cpu__arch_nmi(cpu);
+                       cpu->needs_nmi = 0;
+               }
+
+               kvm_cpu__run(cpu);
+
+               switch (cpu->kvm_run->exit_reason) {
+               case KVM_EXIT_UNKNOWN:
+                       break;
+               case KVM_EXIT_DEBUG:
+                       kvm_cpu__show_registers(cpu);
+                       kvm_cpu__show_code(cpu);
+                       break;
+               case KVM_EXIT_IO: {
+                       bool ret;
+
+                       ret = kvm_cpu__emulate_io(cpu->kvm,
+                                                 cpu->kvm_run->io.port,
+                                                 (u8 *)cpu->kvm_run +
+                                                 cpu->kvm_run->io.data_offset,
+                                                 cpu->kvm_run->io.direction,
+                                                 cpu->kvm_run->io.size,
+                                                 cpu->kvm_run->io.count);
+
+                       if (!ret)
+                               goto panic_kvm;
+                       break;
+               }
+               case KVM_EXIT_MMIO: {
+                       bool ret;
+
+                       /*
+                        * If we had MMIO exit, coalesced ring should be processed
+                        * *before* processing the exit itself
+                        */
+                       kvm_cpu__handle_coalesced_mmio(cpu);
+
+                       ret = kvm_cpu__emulate_mmio(cpu->kvm,
+                                                   cpu->kvm_run->mmio.phys_addr,
+                                                   cpu->kvm_run->mmio.data,
+                                                   cpu->kvm_run->mmio.len,
+                                                   cpu->kvm_run->mmio.is_write);
+
+                       if (!ret)
+                               goto panic_kvm;
+                       break;
+               }
+               case KVM_EXIT_INTR:
+                       if (cpu->is_running)
+                               break;
+                       goto exit_kvm;
+               case KVM_EXIT_SHUTDOWN:
+                       goto exit_kvm;
+               default: {
+                       bool ret;
+
+                       ret = kvm_cpu__handle_exit(cpu);
+                       if (!ret)
+                               goto panic_kvm;
+                       break;
+               }
+               }
+               kvm_cpu__handle_coalesced_mmio(cpu);
+       }
+
+exit_kvm:
+       return 0;
+
+panic_kvm:
+       return 1;
+}
+
+int kvm_cpu__init(struct kvm *kvm)
+{
+       int max_cpus, recommended_cpus, i;
+
+       max_cpus = kvm__max_cpus(kvm);
+       recommended_cpus = kvm__recommended_cpus(kvm);
+
+       if (kvm->cfg.nrcpus > max_cpus) {
+               printf("  # Limit the number of CPUs to %d\n", max_cpus);
+               kvm->cfg.nrcpus = max_cpus;
+       } else if (kvm->cfg.nrcpus > recommended_cpus) {
+               printf("  # Warning: The maximum recommended amount of VCPUs"
+                       " is %d\n", recommended_cpus);
+       }
+
+       kvm->nrcpus = kvm->cfg.nrcpus;
+
+       /* Alloc one pointer too many, so array ends up 0-terminated */
+       kvm->cpus = calloc(kvm->nrcpus + 1, sizeof(void *));
+       if (!kvm->cpus) {
+               pr_warning("Couldn't allocate array for %d CPUs", kvm->nrcpus);
+               return -ENOMEM;
+       }
+
+       for (i = 0; i < kvm->nrcpus; i++) {
+               kvm->cpus[i] = kvm_cpu__arch_init(kvm, i);
+               if (!kvm->cpus[i]) {
+                       pr_warning("unable to initialize KVM VCPU");
+                       goto fail_alloc;
+               }
+       }
+
+       return 0;
+
+fail_alloc:
+       for (i = 0; i < kvm->nrcpus; i++)
+               free(kvm->cpus[i]);
+       return -ENOMEM;
+}
+base_init(kvm_cpu__init);
+
+int kvm_cpu__exit(struct kvm *kvm)
+{
+       int i, r;
+       void *ret = NULL;
+
+       kvm_cpu__delete(kvm->cpus[0]);
+       kvm->cpus[0] = NULL;
+
+       for (i = 1; i < kvm->nrcpus; i++) {
+               if (kvm->cpus[i]->is_running) {
+                       pthread_kill(kvm->cpus[i]->thread, SIGKVMEXIT);
+                       if (pthread_join(kvm->cpus[i]->thread, &ret) != 0)
+                               die("pthread_join");
+                       kvm_cpu__delete(kvm->cpus[i]);
+               }
+               if (ret == NULL)
+                       r = 0;
+       }
+
+       free(kvm->cpus);
+
+       kvm->nrcpus = 0;
+
+       return r;
+}
+late_exit(kvm_cpu__exit);
diff --git a/tools/kvm/kvm-ipc.c b/tools/kvm/kvm-ipc.c
new file mode 100644 (file)
index 0000000..d23edd2
--- /dev/null
@@ -0,0 +1,498 @@
+#include <sys/epoll.h>
+#include <sys/un.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/eventfd.h>
+#include <dirent.h>
+
+#include "kvm/kvm-ipc.h"
+#include "kvm/rwsem.h"
+#include "kvm/read-write.h"
+#include "kvm/util.h"
+#include "kvm/kvm.h"
+#include "kvm/builtin-debug.h"
+#include "kvm/strbuf.h"
+#include "kvm/kvm-cpu.h"
+#include "kvm/8250-serial.h"
+
+struct kvm_ipc_head {
+       u32 type;
+       u32 len;
+};
+
+#define KVM_IPC_MAX_MSGS 16
+
+#define KVM_SOCK_SUFFIX                ".sock"
+#define KVM_SOCK_SUFFIX_LEN    ((ssize_t)sizeof(KVM_SOCK_SUFFIX) - 1)
+
+extern __thread struct kvm_cpu *current_kvm_cpu;
+static void (*msgs[KVM_IPC_MAX_MSGS])(struct kvm *kvm, int fd, u32 type, u32 len, u8 *msg);
+static DECLARE_RWSEM(msgs_rwlock);
+static int epoll_fd, server_fd, stop_fd;
+static pthread_t thread;
+
+static int kvm__create_socket(struct kvm *kvm)
+{
+       char full_name[PATH_MAX];
+       unsigned int s;
+       struct sockaddr_un local;
+       int len, r;
+
+       /* This usually 108 bytes long */
+       BUILD_BUG_ON(sizeof(local.sun_path) < 32);
+
+       snprintf(full_name, sizeof(full_name), "%s/%s%s",
+                kvm__get_dir(), kvm->cfg.guest_name, KVM_SOCK_SUFFIX);
+       if (access(full_name, F_OK) == 0) {
+               pr_err("Socket file %s already exist", full_name);
+               return -EEXIST;
+       }
+
+       s = socket(AF_UNIX, SOCK_STREAM, 0);
+       if (s < 0)
+               return s;
+       local.sun_family = AF_UNIX;
+       strlcpy(local.sun_path, full_name, sizeof(local.sun_path));
+       len = strlen(local.sun_path) + sizeof(local.sun_family);
+       r = bind(s, (struct sockaddr *)&local, len);
+       if (r < 0)
+               goto fail;
+
+       r = listen(s, 5);
+       if (r < 0)
+               goto fail;
+
+       return s;
+
+fail:
+       close(s);
+       return r;
+}
+
+void kvm__remove_socket(const char *name)
+{
+       char full_name[PATH_MAX];
+
+       snprintf(full_name, sizeof(full_name), "%s/%s%s",
+                kvm__get_dir(), name, KVM_SOCK_SUFFIX);
+       unlink(full_name);
+}
+
+int kvm__get_sock_by_instance(const char *name)
+{
+       int s, len, r;
+       char sock_file[PATH_MAX];
+       struct sockaddr_un local;
+
+       snprintf(sock_file, sizeof(sock_file), "%s/%s%s",
+                kvm__get_dir(), name, KVM_SOCK_SUFFIX);
+       s = socket(AF_UNIX, SOCK_STREAM, 0);
+
+       local.sun_family = AF_UNIX;
+       strlcpy(local.sun_path, sock_file, sizeof(local.sun_path));
+       len = strlen(local.sun_path) + sizeof(local.sun_family);
+
+       r = connect(s, &local, len);
+       if (r < 0 && errno == ECONNREFUSED) {
+               /* Tell the user clean ghost socket file */
+               pr_err("\"%s\" could be a ghost socket file, please remove it",
+                               sock_file);
+               return r;
+       } else if (r < 0) {
+               return r;
+       }
+
+       return s;
+}
+
+int kvm__enumerate_instances(int (*callback)(const char *name, int fd))
+{
+       int sock;
+       DIR *dir;
+       struct dirent entry, *result;
+       int ret = 0;
+
+       dir = opendir(kvm__get_dir());
+       if (!dir)
+               return -errno;
+
+       for (;;) {
+               readdir_r(dir, &entry, &result);
+               if (result == NULL)
+                       break;
+               if (entry.d_type == DT_SOCK) {
+                       ssize_t name_len = strlen(entry.d_name);
+                       char *p;
+
+                       if (name_len <= KVM_SOCK_SUFFIX_LEN)
+                               continue;
+
+                       p = &entry.d_name[name_len - KVM_SOCK_SUFFIX_LEN];
+                       if (memcmp(KVM_SOCK_SUFFIX, p, KVM_SOCK_SUFFIX_LEN))
+                               continue;
+
+                       *p = 0;
+                       sock = kvm__get_sock_by_instance(entry.d_name);
+                       if (sock < 0)
+                               continue;
+                       ret = callback(entry.d_name, sock);
+                       close(sock);
+                       if (ret < 0)
+                               break;
+               }
+       }
+
+       closedir(dir);
+
+       return ret;
+}
+
+int kvm_ipc__register_handler(u32 type, void (*cb)(struct kvm *kvm, int fd, u32 type, u32 len, u8 *msg))
+{
+       if (type >= KVM_IPC_MAX_MSGS)
+               return -ENOSPC;
+
+       down_write(&msgs_rwlock);
+       msgs[type] = cb;
+       up_write(&msgs_rwlock);
+
+       return 0;
+}
+
+int kvm_ipc__send(int fd, u32 type)
+{
+       struct kvm_ipc_head head = {.type = type, .len = 0,};
+
+       if (write_in_full(fd, &head, sizeof(head)) < 0)
+               return -1;
+
+       return 0;
+}
+
+int kvm_ipc__send_msg(int fd, u32 type, u32 len, u8 *msg)
+{
+       struct kvm_ipc_head head = {.type = type, .len = len,};
+
+       if (write_in_full(fd, &head, sizeof(head)) < 0)
+               return -1;
+
+       if (write_in_full(fd, msg, len) < 0)
+               return -1;
+
+       return 0;
+}
+
+static int kvm_ipc__handle(struct kvm *kvm, int fd, u32 type, u32 len, u8 *data)
+{
+       void (*cb)(struct kvm *kvm, int fd, u32 type, u32 len, u8 *msg);
+
+       if (type >= KVM_IPC_MAX_MSGS)
+               return -ENOSPC;
+
+       down_read(&msgs_rwlock);
+       cb = msgs[type];
+       up_read(&msgs_rwlock);
+
+       if (cb == NULL) {
+               pr_warning("No device handles type %u\n", type);
+               return -ENODEV;
+       }
+
+       cb(kvm, fd, type, len, data);
+
+       return 0;
+}
+
+static int kvm_ipc__new_conn(int fd)
+{
+       int client;
+       struct epoll_event ev;
+
+       client = accept(fd, NULL, NULL);
+       if (client < 0)
+               return -1;
+
+       ev.events = EPOLLIN | EPOLLRDHUP;
+       ev.data.fd = client;
+       if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, client, &ev) < 0) {
+               close(client);
+               return -1;
+       }
+
+       return client;
+}
+
+static void kvm_ipc__close_conn(int fd)
+{
+       epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, NULL);
+       close(fd);
+}
+
+static int kvm_ipc__receive(struct kvm *kvm, int fd)
+{
+       struct kvm_ipc_head head;
+       u8 *msg = NULL;
+       u32 n;
+
+       n = read(fd, &head, sizeof(head));
+       if (n != sizeof(head))
+               goto done;
+
+       msg = malloc(head.len);
+       if (msg == NULL)
+               goto done;
+
+       n = read_in_full(fd, msg, head.len);
+       if (n != head.len)
+               goto done;
+
+       kvm_ipc__handle(kvm, fd, head.type, head.len, msg);
+
+       return 0;
+
+done:
+       free(msg);
+       return -1;
+}
+
+static void *kvm_ipc__thread(void *param)
+{
+       struct epoll_event event;
+       struct kvm *kvm = param;
+
+       for (;;) {
+               int nfds;
+
+               nfds = epoll_wait(epoll_fd, &event, 1, -1);
+               if (nfds > 0) {
+                       int fd = event.data.fd;
+
+                       if (fd == stop_fd && event.events & EPOLLIN) {
+                               break;
+                       } else if (fd == server_fd) {
+                               int client, r;
+
+                               client = kvm_ipc__new_conn(fd);
+                               /*
+                                * Handle multiple IPC cmd at a time
+                                */
+                               do {
+                                       r = kvm_ipc__receive(kvm, client);
+                               } while (r == 0);
+
+                       } else if (event.events & (EPOLLERR | EPOLLRDHUP | EPOLLHUP)) {
+                               kvm_ipc__close_conn(fd);
+                       } else {
+                               kvm_ipc__receive(kvm, fd);
+                       }
+               }
+       }
+
+       return NULL;
+}
+
+static void kvm__pid(struct kvm *kvm, int fd, u32 type, u32 len, u8 *msg)
+{
+       pid_t pid = getpid();
+       int r = 0;
+
+       if (type == KVM_IPC_PID)
+               r = write(fd, &pid, sizeof(pid));
+
+       if (r < 0)
+               pr_warning("Failed sending PID");
+}
+
+static void handle_stop(struct kvm *kvm, int fd, u32 type, u32 len, u8 *msg)
+{
+       if (WARN_ON(type != KVM_IPC_STOP || len))
+               return;
+
+       kvm_cpu__reboot(kvm);
+}
+
+/* Pause/resume the guest using SIGUSR2 */
+static int is_paused;
+
+static void handle_pause(struct kvm *kvm, int fd, u32 type, u32 len, u8 *msg)
+{
+       if (WARN_ON(len))
+               return;
+
+       if (type == KVM_IPC_RESUME && is_paused) {
+               kvm->vm_state = KVM_VMSTATE_RUNNING;
+               kvm__continue(kvm);
+       } else if (type == KVM_IPC_PAUSE && !is_paused) {
+               kvm->vm_state = KVM_VMSTATE_PAUSED;
+               ioctl(kvm->vm_fd, KVM_KVMCLOCK_CTRL);
+               kvm__pause(kvm);
+       } else {
+               return;
+       }
+
+       is_paused = !is_paused;
+}
+
+static void handle_vmstate(struct kvm *kvm, int fd, u32 type, u32 len, u8 *msg)
+{
+       int r = 0;
+
+       if (type == KVM_IPC_VMSTATE)
+               r = write(fd, &kvm->vm_state, sizeof(kvm->vm_state));
+
+       if (r < 0)
+               pr_warning("Failed sending VMSTATE");
+}
+
+/*
+ * Serialize debug printout so that the output of multiple vcpus does not
+ * get mixed up:
+ */
+static int printout_done;
+
+static void handle_sigusr1(int sig)
+{
+       struct kvm_cpu *cpu = current_kvm_cpu;
+       int fd = kvm_cpu__get_debug_fd();
+
+       if (!cpu || cpu->needs_nmi)
+               return;
+
+       dprintf(fd, "\n #\n # vCPU #%ld's dump:\n #\n", cpu->cpu_id);
+       kvm_cpu__show_registers(cpu);
+       kvm_cpu__show_code(cpu);
+       kvm_cpu__show_page_tables(cpu);
+       fflush(stdout);
+       printout_done = 1;
+}
+
+static void handle_debug(struct kvm *kvm, int fd, u32 type, u32 len, u8 *msg)
+{
+       int i;
+       struct debug_cmd_params *params;
+       u32 dbg_type;
+       u32 vcpu;
+
+       if (WARN_ON(type != KVM_IPC_DEBUG || len != sizeof(*params)))
+               return;
+
+       params = (void *)msg;
+       dbg_type = params->dbg_type;
+       vcpu = params->cpu;
+
+       if (dbg_type & KVM_DEBUG_CMD_TYPE_SYSRQ)
+               serial8250__inject_sysrq(kvm, params->sysrq);
+
+       if (dbg_type & KVM_DEBUG_CMD_TYPE_NMI) {
+               if ((int)vcpu >= kvm->nrcpus)
+                       return;
+
+               kvm->cpus[vcpu]->needs_nmi = 1;
+               pthread_kill(kvm->cpus[vcpu]->thread, SIGUSR1);
+       }
+
+       if (!(dbg_type & KVM_DEBUG_CMD_TYPE_DUMP))
+               return;
+
+       for (i = 0; i < kvm->nrcpus; i++) {
+               struct kvm_cpu *cpu = kvm->cpus[i];
+
+               if (!cpu)
+                       continue;
+
+               printout_done = 0;
+
+               kvm_cpu__set_debug_fd(fd);
+               pthread_kill(cpu->thread, SIGUSR1);
+               /*
+                * Wait for the vCPU to dump state before signalling
+                * the next thread. Since this is debug code it does
+                * not matter that we are burning CPU time a bit:
+                */
+               while (!printout_done)
+                       sleep(0);
+       }
+
+       close(fd);
+
+       serial8250__inject_sysrq(kvm, 'p');
+}
+
+int kvm_ipc__init(struct kvm *kvm)
+{
+       int ret;
+       int sock = kvm__create_socket(kvm);
+       struct epoll_event ev = {0};
+
+       server_fd = sock;
+
+       epoll_fd = epoll_create(KVM_IPC_MAX_MSGS);
+       if (epoll_fd < 0) {
+               ret = epoll_fd;
+               goto err;
+       }
+
+       ev.events = EPOLLIN | EPOLLET;
+       ev.data.fd = sock;
+       if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, sock, &ev) < 0) {
+               pr_err("Failed starting IPC thread");
+               ret = -EFAULT;
+               goto err_epoll;
+       }
+
+       stop_fd = eventfd(0, 0);
+       if (stop_fd < 0) {
+               ret = stop_fd;
+               goto err_epoll;
+       }
+
+       ev.events = EPOLLIN | EPOLLET;
+       ev.data.fd = stop_fd;
+       if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, stop_fd, &ev) < 0) {
+               pr_err("Failed adding stop event to epoll");
+               ret = -EFAULT;
+               goto err_stop;
+       }
+
+       if (pthread_create(&thread, NULL, kvm_ipc__thread, kvm) != 0) {
+               pr_err("Failed starting IPC thread");
+               ret = -EFAULT;
+               goto err_stop;
+       }
+
+       kvm_ipc__register_handler(KVM_IPC_PID, kvm__pid);
+       kvm_ipc__register_handler(KVM_IPC_DEBUG, handle_debug);
+       kvm_ipc__register_handler(KVM_IPC_PAUSE, handle_pause);
+       kvm_ipc__register_handler(KVM_IPC_RESUME, handle_pause);
+       kvm_ipc__register_handler(KVM_IPC_STOP, handle_stop);
+       kvm_ipc__register_handler(KVM_IPC_VMSTATE, handle_vmstate);
+       signal(SIGUSR1, handle_sigusr1);
+
+       return 0;
+
+err_stop:
+       close(stop_fd);
+err_epoll:
+       close(epoll_fd);
+err:
+       return ret;
+}
+base_init(kvm_ipc__init);
+
+int kvm_ipc__exit(struct kvm *kvm)
+{
+       u64 val = 1;
+       int ret;
+
+       ret = write(stop_fd, &val, sizeof(val));
+       if (ret < 0)
+               return ret;
+
+       close(server_fd);
+       close(epoll_fd);
+
+       kvm__remove_socket(kvm->cfg.guest_name);
+
+       return ret;
+}
+base_exit(kvm_ipc__exit);
diff --git a/tools/kvm/kvm.c b/tools/kvm/kvm.c
new file mode 100644 (file)
index 0000000..b283171
--- /dev/null
@@ -0,0 +1,458 @@
+#include "kvm/kvm.h"
+#include "kvm/read-write.h"
+#include "kvm/util.h"
+#include "kvm/strbuf.h"
+#include "kvm/mutex.h"
+#include "kvm/kvm-cpu.h"
+#include "kvm/kvm-ipc.h"
+
+#include <linux/kvm.h>
+#include <linux/err.h>
+
+#include <sys/un.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <stdbool.h>
+#include <limits.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <time.h>
+#include <sys/eventfd.h>
+#include <asm/unistd.h>
+#include <dirent.h>
+
+#define DEFINE_KVM_EXIT_REASON(reason) [reason] = #reason
+
+const char *kvm_exit_reasons[] = {
+       DEFINE_KVM_EXIT_REASON(KVM_EXIT_UNKNOWN),
+       DEFINE_KVM_EXIT_REASON(KVM_EXIT_EXCEPTION),
+       DEFINE_KVM_EXIT_REASON(KVM_EXIT_IO),
+       DEFINE_KVM_EXIT_REASON(KVM_EXIT_HYPERCALL),
+       DEFINE_KVM_EXIT_REASON(KVM_EXIT_DEBUG),
+       DEFINE_KVM_EXIT_REASON(KVM_EXIT_HLT),
+       DEFINE_KVM_EXIT_REASON(KVM_EXIT_MMIO),
+       DEFINE_KVM_EXIT_REASON(KVM_EXIT_IRQ_WINDOW_OPEN),
+       DEFINE_KVM_EXIT_REASON(KVM_EXIT_SHUTDOWN),
+       DEFINE_KVM_EXIT_REASON(KVM_EXIT_FAIL_ENTRY),
+       DEFINE_KVM_EXIT_REASON(KVM_EXIT_INTR),
+       DEFINE_KVM_EXIT_REASON(KVM_EXIT_SET_TPR),
+       DEFINE_KVM_EXIT_REASON(KVM_EXIT_TPR_ACCESS),
+       DEFINE_KVM_EXIT_REASON(KVM_EXIT_S390_SIEIC),
+       DEFINE_KVM_EXIT_REASON(KVM_EXIT_S390_RESET),
+       DEFINE_KVM_EXIT_REASON(KVM_EXIT_DCR),
+       DEFINE_KVM_EXIT_REASON(KVM_EXIT_NMI),
+       DEFINE_KVM_EXIT_REASON(KVM_EXIT_INTERNAL_ERROR),
+#ifdef CONFIG_PPC64
+       DEFINE_KVM_EXIT_REASON(KVM_EXIT_PAPR_HCALL),
+#endif
+};
+
+static int pause_event;
+static DEFINE_MUTEX(pause_lock);
+extern struct kvm_ext kvm_req_ext[];
+
+static char kvm_dir[PATH_MAX];
+
+static int set_dir(const char *fmt, va_list args)
+{
+       char tmp[PATH_MAX];
+
+       vsnprintf(tmp, sizeof(tmp), fmt, args);
+
+       mkdir(tmp, 0777);
+
+       if (!realpath(tmp, kvm_dir))
+               return -errno;
+
+       strcat(kvm_dir, "/");
+
+       return 0;
+}
+
+void kvm__set_dir(const char *fmt, ...)
+{
+       va_list args;
+
+       va_start(args, fmt);
+       set_dir(fmt, args);
+       va_end(args);
+}
+
+const char *kvm__get_dir(void)
+{
+       return kvm_dir;
+}
+
+bool kvm__supports_extension(struct kvm *kvm, unsigned int extension)
+{
+       int ret;
+
+       ret = ioctl(kvm->sys_fd, KVM_CHECK_EXTENSION, extension);
+       if (ret < 0)
+               return false;
+
+       return ret;
+}
+
+static int kvm__check_extensions(struct kvm *kvm)
+{
+       int i;
+
+       for (i = 0; ; i++) {
+               if (!kvm_req_ext[i].name)
+                       break;
+               if (!kvm__supports_extension(kvm, kvm_req_ext[i].code)) {
+                       pr_err("Unsuppored KVM extension detected: %s",
+                               kvm_req_ext[i].name);
+                       return -i;
+               }
+       }
+
+       return 0;
+}
+
+struct kvm *kvm__new(void)
+{
+       struct kvm *kvm = calloc(1, sizeof(*kvm));
+       if (!kvm)
+               return ERR_PTR(-ENOMEM);
+
+       kvm->sys_fd = -1;
+       kvm->vm_fd = -1;
+
+       return kvm;
+}
+
+int kvm__exit(struct kvm *kvm)
+{
+       kvm__arch_delete_ram(kvm);
+       free(kvm);
+
+       return 0;
+}
+core_exit(kvm__exit);
+
+/*
+ * Note: KVM_SET_USER_MEMORY_REGION assumes that we don't pass overlapping
+ * memory regions to it. Therefore, be careful if you use this function for
+ * registering memory regions for emulating hardware.
+ */
+int kvm__register_mem(struct kvm *kvm, u64 guest_phys, u64 size, void *userspace_addr)
+{
+       struct kvm_userspace_memory_region mem;
+       int ret;
+
+       mem = (struct kvm_userspace_memory_region) {
+               .slot                   = kvm->mem_slots++,
+               .guest_phys_addr        = guest_phys,
+               .memory_size            = size,
+               .userspace_addr         = (unsigned long)userspace_addr,
+       };
+
+       ret = ioctl(kvm->vm_fd, KVM_SET_USER_MEMORY_REGION, &mem);
+       if (ret < 0)
+               return -errno;
+
+       return 0;
+}
+
+int kvm__recommended_cpus(struct kvm *kvm)
+{
+       int ret;
+
+       ret = ioctl(kvm->sys_fd, KVM_CHECK_EXTENSION, KVM_CAP_NR_VCPUS);
+       if (ret <= 0)
+               /*
+                * api.txt states that if KVM_CAP_NR_VCPUS does not exist,
+                * assume 4.
+                */
+               return 4;
+
+       return ret;
+}
+
+/*
+ * The following hack should be removed once 'x86: Raise the hard
+ * VCPU count limit' makes it's way into the mainline.
+ */
+#ifndef KVM_CAP_MAX_VCPUS
+#define KVM_CAP_MAX_VCPUS 66
+#endif
+
+int kvm__max_cpus(struct kvm *kvm)
+{
+       int ret;
+
+       ret = ioctl(kvm->sys_fd, KVM_CHECK_EXTENSION, KVM_CAP_MAX_VCPUS);
+       if (ret <= 0)
+               ret = kvm__recommended_cpus(kvm);
+
+       return ret;
+}
+
+int kvm__init(struct kvm *kvm)
+{
+       int ret;
+
+       if (!kvm__arch_cpu_supports_vm()) {
+               pr_err("Your CPU does not support hardware virtualization");
+               ret = -ENOSYS;
+               goto err;
+       }
+
+       kvm->sys_fd = open(kvm->cfg.dev, O_RDWR);
+       if (kvm->sys_fd < 0) {
+               if (errno == ENOENT)
+                       pr_err("'%s' not found. Please make sure your kernel has CONFIG_KVM "
+                              "enabled and that the KVM modules are loaded.", kvm->cfg.dev);
+               else if (errno == ENODEV)
+                       pr_err("'%s' KVM driver not available.\n  # (If the KVM "
+                              "module is loaded then 'dmesg' may offer further clues "
+                              "about the failure.)", kvm->cfg.dev);
+               else
+                       pr_err("Could not open %s: ", kvm->cfg.dev);
+
+               ret = -errno;
+               goto err_free;
+       }
+
+       ret = ioctl(kvm->sys_fd, KVM_GET_API_VERSION, 0);
+       if (ret != KVM_API_VERSION) {
+               pr_err("KVM_API_VERSION ioctl");
+               ret = -errno;
+               goto err_sys_fd;
+       }
+
+       kvm->vm_fd = ioctl(kvm->sys_fd, KVM_CREATE_VM, 0);
+       if (kvm->vm_fd < 0) {
+               ret = kvm->vm_fd;
+               goto err_sys_fd;
+       }
+
+       if (kvm__check_extensions(kvm)) {
+               pr_err("A required KVM extention is not supported by OS");
+               ret = -ENOSYS;
+               goto err_vm_fd;
+       }
+
+       kvm__arch_init(kvm, kvm->cfg.hugetlbfs_path, kvm->cfg.ram_size);
+
+       kvm__init_ram(kvm);
+
+       if (!kvm->cfg.firmware_filename) {
+               if (!kvm__load_kernel(kvm, kvm->cfg.kernel_filename,
+                               kvm->cfg.initrd_filename, kvm->cfg.real_cmdline, kvm->cfg.vidmode))
+                       die("unable to load kernel %s", kvm->cfg.kernel_filename);
+       }
+
+       if (kvm->cfg.firmware_filename) {
+               if (!kvm__load_firmware(kvm, kvm->cfg.firmware_filename))
+                       die("unable to load firmware image %s: %s", kvm->cfg.firmware_filename, strerror(errno));
+       } else {
+               ret = kvm__arch_setup_firmware(kvm);
+               if (ret < 0)
+                       die("kvm__arch_setup_firmware() failed with error %d\n", ret);
+       }
+
+       return 0;
+
+err_vm_fd:
+       close(kvm->vm_fd);
+err_sys_fd:
+       close(kvm->sys_fd);
+err_free:
+       free(kvm);
+err:
+       return ret;
+}
+core_init(kvm__init);
+
+/* RFC 1952 */
+#define GZIP_ID1               0x1f
+#define GZIP_ID2               0x8b
+#define CPIO_MAGIC             "0707"
+/* initrd may be gzipped, or a plain cpio */
+static bool initrd_check(int fd)
+{
+       unsigned char id[4];
+
+       if (read_in_full(fd, id, ARRAY_SIZE(id)) < 0)
+               return false;
+
+       if (lseek(fd, 0, SEEK_SET) < 0)
+               die_perror("lseek");
+
+       return (id[0] == GZIP_ID1 && id[1] == GZIP_ID2) ||
+               !memcmp(id, CPIO_MAGIC, 4);
+}
+
+bool kvm__load_kernel(struct kvm *kvm, const char *kernel_filename,
+               const char *initrd_filename, const char *kernel_cmdline, u16 vidmode)
+{
+       bool ret;
+       int fd_kernel = -1, fd_initrd = -1;
+
+       fd_kernel = open(kernel_filename, O_RDONLY);
+       if (fd_kernel < 0)
+               die("Unable to open kernel %s", kernel_filename);
+
+       if (initrd_filename) {
+               fd_initrd = open(initrd_filename, O_RDONLY);
+               if (fd_initrd < 0)
+                       die("Unable to open initrd %s", initrd_filename);
+
+               if (!initrd_check(fd_initrd))
+                       die("%s is not an initrd", initrd_filename);
+       }
+
+       ret = load_bzimage(kvm, fd_kernel, fd_initrd, kernel_cmdline, vidmode);
+
+       if (ret)
+               goto found_kernel;
+
+       pr_warning("%s is not a bzImage. Trying to load it as a flat binary...", kernel_filename);
+
+       ret = load_flat_binary(kvm, fd_kernel, fd_initrd, kernel_cmdline);
+
+       if (ret)
+               goto found_kernel;
+
+       if (initrd_filename)
+               close(fd_initrd);
+       close(fd_kernel);
+
+       die("%s is not a valid bzImage or flat binary", kernel_filename);
+
+found_kernel:
+       if (initrd_filename)
+               close(fd_initrd);
+       close(fd_kernel);
+
+       return ret;
+}
+
+#define TIMER_INTERVAL_NS 1000000      /* 1 msec */
+
+/*
+ * This function sets up a timer that's used to inject interrupts from the
+ * userspace hypervisor into the guest at periodical intervals. Please note
+ * that clock interrupt, for example, is not handled here.
+ */
+int kvm_timer__init(struct kvm *kvm)
+{
+       struct itimerspec its;
+       struct sigevent sev;
+       int r;
+
+       memset(&sev, 0, sizeof(struct sigevent));
+       sev.sigev_value.sival_int       = 0;
+       sev.sigev_notify                = SIGEV_THREAD_ID;
+       sev.sigev_signo                 = SIGALRM;
+       sev.sigev_value.sival_ptr       = kvm;
+       sev._sigev_un._tid              = syscall(__NR_gettid);
+
+       r = timer_create(CLOCK_REALTIME, &sev, &kvm->timerid);
+       if (r < 0)
+               return r;
+
+       its.it_value.tv_sec             = TIMER_INTERVAL_NS / 1000000000;
+       its.it_value.tv_nsec            = TIMER_INTERVAL_NS % 1000000000;
+       its.it_interval.tv_sec          = its.it_value.tv_sec;
+       its.it_interval.tv_nsec         = its.it_value.tv_nsec;
+
+       r = timer_settime(kvm->timerid, 0, &its, NULL);
+       if (r < 0) {
+               timer_delete(kvm->timerid);
+               return r;
+       }
+
+       return 0;
+}
+firmware_init(kvm_timer__init);
+
+int kvm_timer__exit(struct kvm *kvm)
+{
+       if (kvm->timerid)
+               if (timer_delete(kvm->timerid) < 0)
+                       die("timer_delete()");
+
+       kvm->timerid = 0;
+
+       return 0;
+}
+firmware_exit(kvm_timer__exit);
+
+void kvm__dump_mem(struct kvm *kvm, unsigned long addr, unsigned long size)
+{
+       unsigned char *p;
+       unsigned long n;
+
+       size &= ~7; /* mod 8 */
+       if (!size)
+               return;
+
+       p = guest_flat_to_host(kvm, addr);
+
+       for (n = 0; n < size; n += 8) {
+               if (!host_ptr_in_ram(kvm, p + n))
+                       break;
+
+               printf("  0x%08lx: %02x %02x %02x %02x  %02x %02x %02x %02x\n",
+                       addr + n, p[n + 0], p[n + 1], p[n + 2], p[n + 3],
+                                 p[n + 4], p[n + 5], p[n + 6], p[n + 7]);
+       }
+}
+
+void kvm__pause(struct kvm *kvm)
+{
+       int i, paused_vcpus = 0;
+
+       /* Check if the guest is running */
+       if (!kvm->cpus[0] || kvm->cpus[0]->thread == 0)
+               return;
+
+       mutex_lock(&pause_lock);
+
+       pause_event = eventfd(0, 0);
+       if (pause_event < 0)
+               die("Failed creating pause notification event");
+       for (i = 0; i < kvm->nrcpus; i++)
+               pthread_kill(kvm->cpus[i]->thread, SIGKVMPAUSE);
+
+       while (paused_vcpus < kvm->nrcpus) {
+               u64 cur_read;
+
+               if (read(pause_event, &cur_read, sizeof(cur_read)) < 0)
+                       die("Failed reading pause event");
+               paused_vcpus += cur_read;
+       }
+       close(pause_event);
+}
+
+void kvm__continue(struct kvm *kvm)
+{
+       /* Check if the guest is running */
+       if (!kvm->cpus[0] || kvm->cpus[0]->thread == 0)
+               return;
+
+       mutex_unlock(&pause_lock);
+}
+
+void kvm__notify_paused(void)
+{
+       u64 p = 1;
+
+       if (write(pause_event, &p, sizeof(p)) < 0)
+               die("Failed notifying of paused VCPU.");
+
+       mutex_lock(&pause_lock);
+       mutex_unlock(&pause_lock);
+}
diff --git a/tools/kvm/main.c b/tools/kvm/main.c
new file mode 100644 (file)
index 0000000..05bc82c
--- /dev/null
@@ -0,0 +1,19 @@
+#include "kvm/kvm.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+
+/* user defined header files */
+#include <kvm/kvm-cmd.h>
+
+static int handle_kvm_command(int argc, char **argv)
+{
+       return handle_command(kvm_commands, argc, (const char **) &argv[0]);
+}
+
+int main(int argc, char *argv[])
+{
+       kvm__set_dir("%s/%s", HOME_DIR, KVM_PID_FILE_PATH);
+
+       return handle_kvm_command(argc - 1, &argv[1]);
+}
diff --git a/tools/kvm/mmio.c b/tools/kvm/mmio.c
new file mode 100644 (file)
index 0000000..5d65d28
--- /dev/null
@@ -0,0 +1,139 @@
+#include "kvm/kvm.h"
+#include "kvm/rbtree-interval.h"
+#include "kvm/brlock.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sys/ioctl.h>
+#include <linux/kvm.h>
+#include <linux/types.h>
+#include <linux/rbtree.h>
+#include <linux/err.h>
+#include <errno.h>
+
+#define mmio_node(n) rb_entry(n, struct mmio_mapping, node)
+
+struct mmio_mapping {
+       struct rb_int_node      node;
+       void                    (*mmio_fn)(u64 addr, u8 *data, u32 len, u8 is_write, void *ptr);
+       void                    *ptr;
+};
+
+static struct rb_root mmio_tree = RB_ROOT;
+
+static struct mmio_mapping *mmio_search(struct rb_root *root, u64 addr, u64 len)
+{
+       struct rb_int_node *node;
+
+       node = rb_int_search_range(root, addr, addr + len);
+       if (node == NULL)
+               return NULL;
+
+       return mmio_node(node);
+}
+
+/* Find lowest match, Check for overlap */
+static struct mmio_mapping *mmio_search_single(struct rb_root *root, u64 addr)
+{
+       struct rb_int_node *node;
+
+       node = rb_int_search_single(root, addr);
+       if (node == NULL)
+               return NULL;
+
+       return mmio_node(node);
+}
+
+static int mmio_insert(struct rb_root *root, struct mmio_mapping *data)
+{
+       return rb_int_insert(root, &data->node);
+}
+
+static const char *to_direction(u8 is_write)
+{
+       if (is_write)
+               return "write";
+
+       return "read";
+}
+
+int kvm__register_mmio(struct kvm *kvm, u64 phys_addr, u64 phys_addr_len, bool coalesce,
+                       void (*mmio_fn)(u64 addr, u8 *data, u32 len, u8 is_write, void *ptr),
+                       void *ptr)
+{
+       struct mmio_mapping *mmio;
+       struct kvm_coalesced_mmio_zone zone;
+       int ret;
+
+       mmio = malloc(sizeof(*mmio));
+       if (mmio == NULL)
+               return -ENOMEM;
+
+       *mmio = (struct mmio_mapping) {
+               .node = RB_INT_INIT(phys_addr, phys_addr + phys_addr_len),
+               .mmio_fn = mmio_fn,
+               .ptr    = ptr,
+       };
+
+       if (coalesce) {
+               zone = (struct kvm_coalesced_mmio_zone) {
+                       .addr   = phys_addr,
+                       .size   = phys_addr_len,
+               };
+               ret = ioctl(kvm->vm_fd, KVM_REGISTER_COALESCED_MMIO, &zone);
+               if (ret < 0) {
+                       free(mmio);
+                       return -errno;
+               }
+       }
+       br_write_lock(kvm);
+       ret = mmio_insert(&mmio_tree, mmio);
+       br_write_unlock(kvm);
+
+       return ret;
+}
+
+bool kvm__deregister_mmio(struct kvm *kvm, u64 phys_addr)
+{
+       struct mmio_mapping *mmio;
+       struct kvm_coalesced_mmio_zone zone;
+
+       br_write_lock(kvm);
+       mmio = mmio_search_single(&mmio_tree, phys_addr);
+       if (mmio == NULL) {
+               br_write_unlock(kvm);
+               return false;
+       }
+
+       zone = (struct kvm_coalesced_mmio_zone) {
+               .addr   = phys_addr,
+               .size   = 1,
+       };
+       ioctl(kvm->vm_fd, KVM_UNREGISTER_COALESCED_MMIO, &zone);
+
+       rb_int_erase(&mmio_tree, &mmio->node);
+       br_write_unlock(kvm);
+
+       free(mmio);
+       return true;
+}
+
+bool kvm__emulate_mmio(struct kvm *kvm, u64 phys_addr, u8 *data, u32 len, u8 is_write)
+{
+       struct mmio_mapping *mmio;
+
+       br_read_lock();
+       mmio = mmio_search(&mmio_tree, phys_addr, len);
+
+       if (mmio)
+               mmio->mmio_fn(phys_addr, data, len, is_write, mmio->ptr);
+       else {
+               if (kvm->cfg.mmio_debug)
+                       fprintf(stderr, "Warning: Ignoring MMIO %s at %016llx (length %u)\n",
+                               to_direction(is_write), phys_addr, len);
+       }
+       br_read_unlock();
+
+       return true;
+}
diff --git a/tools/kvm/net/uip/arp.c b/tools/kvm/net/uip/arp.c
new file mode 100644 (file)
index 0000000..98423da
--- /dev/null
@@ -0,0 +1,30 @@
+#include "kvm/uip.h"
+
+int uip_tx_do_arp(struct uip_tx_arg *arg)
+{
+       struct uip_arp *arp, *arp2;
+       struct uip_info *info;
+       struct uip_buf *buf;
+
+       info = arg->info;
+       buf = uip_buf_clone(arg);
+
+       arp      = (struct uip_arp *)(arg->eth);
+       arp2     = (struct uip_arp *)(buf->eth);
+
+       /*
+        * ARP replay code: 2
+        */
+       arp2->op   = htons(0x2);
+       arp2->dmac = arp->smac;
+       arp2->dip  = arp->sip;
+
+       if (arp->dip == htonl(info->host_ip)) {
+               arp2->smac = info->host_mac;
+               arp2->sip = htonl(info->host_ip);
+
+               uip_buf_set_used(info, buf);
+       }
+
+       return 0;
+}
diff --git a/tools/kvm/net/uip/buf.c b/tools/kvm/net/uip/buf.c
new file mode 100644 (file)
index 0000000..5e564a9
--- /dev/null
@@ -0,0 +1,114 @@
+#include "kvm/uip.h"
+
+#include <linux/kernel.h>
+#include <linux/list.h>
+
+struct uip_buf *uip_buf_get_used(struct uip_info *info)
+{
+       struct uip_buf *buf;
+       bool found = false;
+
+       mutex_lock(&info->buf_lock);
+
+       while (!(info->buf_used_nr > 0))
+               pthread_cond_wait(&info->buf_used_cond, &info->buf_lock);
+
+       list_for_each_entry(buf, &info->buf_head, list) {
+               if (buf->status == UIP_BUF_STATUS_USED) {
+                       /*
+                        * Set status to INUSE immediately to prevent
+                        * someone from using this buf until we free it
+                        */
+                       buf->status = UIP_BUF_STATUS_INUSE;
+                       info->buf_used_nr--;
+                       found = true;
+                       break;
+               }
+       }
+
+       mutex_unlock(&info->buf_lock);
+
+       return found ? buf : NULL;
+}
+
+struct uip_buf *uip_buf_get_free(struct uip_info *info)
+{
+       struct uip_buf *buf;
+       bool found = false;
+
+       mutex_lock(&info->buf_lock);
+
+       while (!(info->buf_free_nr > 0))
+               pthread_cond_wait(&info->buf_free_cond, &info->buf_lock);
+
+       list_for_each_entry(buf, &info->buf_head, list) {
+               if (buf->status == UIP_BUF_STATUS_FREE) {
+                       /*
+                        * Set status to INUSE immediately to prevent
+                        * someone from using this buf until we free it
+                        */
+                       buf->status = UIP_BUF_STATUS_INUSE;
+                       info->buf_free_nr--;
+                       found = true;
+                       break;
+               }
+       }
+
+       mutex_unlock(&info->buf_lock);
+
+       return found ? buf : NULL;
+}
+
+struct uip_buf *uip_buf_set_used(struct uip_info *info, struct uip_buf *buf)
+{
+       mutex_lock(&info->buf_lock);
+
+       buf->status = UIP_BUF_STATUS_USED;
+       info->buf_used_nr++;
+       pthread_cond_signal(&info->buf_used_cond);
+
+       mutex_unlock(&info->buf_lock);
+
+       return buf;
+}
+
+struct uip_buf *uip_buf_set_free(struct uip_info *info, struct uip_buf *buf)
+{
+       mutex_lock(&info->buf_lock);
+
+       buf->status = UIP_BUF_STATUS_FREE;
+       info->buf_free_nr++;
+       pthread_cond_signal(&info->buf_free_cond);
+
+       mutex_unlock(&info->buf_lock);
+
+       return buf;
+}
+
+struct uip_buf *uip_buf_clone(struct uip_tx_arg *arg)
+{
+       struct uip_buf *buf;
+       struct uip_eth *eth2;
+       struct uip_info *info;
+
+       info = arg->info;
+
+       /*
+        * Get buffer from device to guest
+        */
+       buf = uip_buf_get_free(info);
+
+       /*
+        * Clone buffer
+        */
+       memcpy(buf->vnet, arg->vnet, arg->vnet_len);
+       memcpy(buf->eth, arg->eth, arg->eth_len);
+       buf->vnet_len   = arg->vnet_len;
+       buf->eth_len    = arg->eth_len;
+
+       eth2            = (struct uip_eth *)buf->eth;
+       eth2->src       = info->host_mac;
+       eth2->dst       = arg->eth->src;
+
+       return buf;
+}
diff --git a/tools/kvm/net/uip/core.c b/tools/kvm/net/uip/core.c
new file mode 100644 (file)
index 0000000..2e7603c
--- /dev/null
@@ -0,0 +1,190 @@
+#include "kvm/mutex.h"
+#include "kvm/uip.h"
+
+#include <linux/virtio_net.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+
+int uip_tx(struct iovec *iov, u16 out, struct uip_info *info)
+{
+       struct virtio_net_hdr *vnet;
+       struct uip_tx_arg arg;
+       int eth_len, vnet_len;
+       struct uip_eth *eth;
+       u8 *buf = NULL;
+       u16 proto;
+       int i;
+
+       /*
+        * Buffer from guest to device
+        */
+       vnet_len = iov[0].iov_len;
+       vnet     = iov[0].iov_base;
+
+       eth_len  = iov[1].iov_len;
+       eth      = iov[1].iov_base;
+
+       /*
+        * In case, ethernet frame is in more than one iov entry.
+        * Copy iov buffer into one linear buffer.
+        */
+       if (out > 2) {
+               eth_len = 0;
+               for (i = 1; i < out; i++)
+                       eth_len += iov[i].iov_len;
+
+               buf = malloc(eth_len);
+               if (!buf)
+                       return -1;
+
+               eth = (struct uip_eth *)buf;
+               for (i = 1; i < out; i++) {
+                       memcpy(buf, iov[i].iov_base, iov[i].iov_len);
+                       buf += iov[i].iov_len;
+               }
+       }
+
+       memset(&arg, 0, sizeof(arg));
+
+       arg.vnet_len = vnet_len;
+       arg.eth_len = eth_len;
+       arg.info = info;
+       arg.vnet = vnet;
+       arg.eth = eth;
+
+       /*
+        * Check package type
+        */
+       proto = ntohs(eth->type);
+
+       switch (proto) {
+       case UIP_ETH_P_ARP:
+               uip_tx_do_arp(&arg);
+               break;
+       case UIP_ETH_P_IP:
+               uip_tx_do_ipv4(&arg);
+               break;
+       default:
+               break;
+       }
+
+       if (out > 2 && buf)
+               free(eth);
+
+       return vnet_len + eth_len;
+}
+
+int uip_rx(struct iovec *iov, u16 in, struct uip_info *info)
+{
+       struct virtio_net_hdr *vnet;
+       struct uip_eth *eth;
+       struct uip_buf *buf;
+       int vnet_len;
+       int eth_len;
+       char *p;
+       int len;
+       int cnt;
+       int i;
+
+       /*
+        * Sleep until there is a buffer for guest
+        */
+       buf = uip_buf_get_used(info);
+
+       /*
+        * Fill device to guest buffer, vnet hdr fisrt
+        */
+       vnet_len = iov[0].iov_len;
+       vnet = iov[0].iov_base;
+       if (buf->vnet_len > vnet_len) {
+               len = -1;
+               goto out;
+       }
+       memcpy(vnet, buf->vnet, buf->vnet_len);
+
+       /*
+        * Then, the real eth data
+        * Note: Be sure buf->eth_len is not bigger than the buffer len that guest provides
+        */
+       cnt = buf->eth_len;
+       p = buf->eth;
+       for (i = 1; i < in; i++) {
+               eth_len = iov[i].iov_len;
+               eth = iov[i].iov_base;
+               if (cnt > eth_len) {
+                       memcpy(eth, p, eth_len);
+                       cnt -= eth_len;
+                       p += eth_len;
+               } else {
+                       memcpy(eth, p, cnt);
+                       cnt -= cnt;
+                       break;
+               }
+       }
+
+       if (cnt) {
+               pr_warning("uip_rx error");
+               len = -1;
+               goto out;
+       }
+
+       len = buf->vnet_len + buf->eth_len;
+
+out:
+       uip_buf_set_free(info, buf);
+       return len;
+}
+
+int uip_init(struct uip_info *info)
+{
+       struct list_head *udp_socket_head;
+       struct list_head *tcp_socket_head;
+       struct list_head *buf_head;
+       struct uip_buf *buf;
+       int buf_nr;
+       int i;
+
+       udp_socket_head = &info->udp_socket_head;
+       tcp_socket_head = &info->tcp_socket_head;
+       buf_head        = &info->buf_head;
+       buf_nr          = info->buf_nr;
+
+       INIT_LIST_HEAD(udp_socket_head);
+       INIT_LIST_HEAD(tcp_socket_head);
+       INIT_LIST_HEAD(buf_head);
+
+       pthread_mutex_init(&info->udp_socket_lock, NULL);
+       pthread_mutex_init(&info->tcp_socket_lock, NULL);
+       pthread_mutex_init(&info->buf_lock, NULL);
+
+       pthread_cond_init(&info->buf_used_cond, NULL);
+       pthread_cond_init(&info->buf_free_cond, NULL);
+
+
+       for (i = 0; i < buf_nr; i++) {
+               buf = malloc(sizeof(*buf));
+               memset(buf, 0, sizeof(*buf));
+
+               buf->status     = UIP_BUF_STATUS_FREE;
+               buf->info       = info;
+               buf->id         = i;
+               list_add_tail(&buf->list, buf_head);
+       }
+
+       list_for_each_entry(buf, buf_head, list) {
+               buf->vnet       = malloc(sizeof(struct virtio_net_hdr));
+               buf->vnet_len   = sizeof(struct virtio_net_hdr);
+               buf->eth        = malloc(1024*64 + sizeof(struct uip_pseudo_hdr));
+               buf->eth_len    = 1024*64 + sizeof(struct uip_pseudo_hdr);
+
+               memset(buf->vnet, 0, buf->vnet_len);
+               memset(buf->eth, 0, buf->eth_len);
+       }
+
+       info->buf_free_nr = buf_nr;
+       info->buf_used_nr = 0;
+
+       uip_dhcp_get_dns(info);
+
+       return 0;
+}
diff --git a/tools/kvm/net/uip/csum.c b/tools/kvm/net/uip/csum.c
new file mode 100644 (file)
index 0000000..7ca8bad
--- /dev/null
@@ -0,0 +1,92 @@
+#include "kvm/uip.h"
+
+static u16 uip_csum(u16 csum, u8 *addr, u16 count)
+{
+       long sum = csum;
+
+       while (count > 1) {
+               sum     += *(u16 *)addr;
+               addr    += 2;
+               count   -= 2;
+       }
+
+       if (count > 0)
+               sum += *(unsigned char *)addr;
+
+       while (sum>>16)
+               sum = (sum & 0xffff) + (sum >> 16);
+
+       return ~sum;
+}
+
+u16 uip_csum_ip(struct uip_ip *ip)
+{
+       return uip_csum(0, &ip->vhl, uip_ip_hdrlen(ip));
+}
+
+u16 uip_csum_icmp(struct uip_icmp *icmp)
+{
+       struct uip_ip *ip;
+
+       ip = &icmp->ip;
+       return icmp->csum = uip_csum(0, &icmp->type, htons(ip->len) - uip_ip_hdrlen(ip) - 8); /* icmp header len = 8 */
+}
+
+u16 uip_csum_udp(struct uip_udp *udp)
+{
+       struct uip_pseudo_hdr hdr;
+       struct uip_ip *ip;
+       int udp_len;
+       u8 *pad;
+
+       ip        = &udp->ip;
+
+       hdr.sip   = ip->sip;
+       hdr.dip   = ip->dip;
+       hdr.zero  = 0;
+       hdr.proto = ip->proto;
+       hdr.len   = udp->len;
+
+       udp_len   = uip_udp_len(udp);
+
+       if (udp_len % 2) {
+               pad = (u8 *)&udp->sport + udp_len;
+               *pad = 0;
+               memcpy((u8 *)&udp->sport + udp_len + 1, &hdr, sizeof(hdr));
+               return uip_csum(0, (u8 *)&udp->sport, udp_len + 1 + sizeof(hdr));
+       } else {
+               memcpy((u8 *)&udp->sport + udp_len, &hdr, sizeof(hdr));
+               return uip_csum(0, (u8 *)&udp->sport, udp_len + sizeof(hdr));
+       }
+
+}
+
+u16 uip_csum_tcp(struct uip_tcp *tcp)
+{
+       struct uip_pseudo_hdr hdr;
+       struct uip_ip *ip;
+       u16 tcp_len;
+       u8 *pad;
+
+       ip        = &tcp->ip;
+       tcp_len   = ntohs(ip->len) - uip_ip_hdrlen(ip);
+
+       hdr.sip   = ip->sip;
+       hdr.dip   = ip->dip;
+       hdr.zero  = 0;
+       hdr.proto = ip->proto;
+       hdr.len   = htons(tcp_len);
+
+       if (tcp_len > UIP_MAX_TCP_PAYLOAD + 20)
+               pr_warning("tcp_len(%d) is too large", tcp_len);
+
+       if (tcp_len % 2) {
+               pad = (u8 *)&tcp->sport + tcp_len;
+               *pad = 0;
+               memcpy((u8 *)&tcp->sport + tcp_len + 1, &hdr, sizeof(hdr));
+               return uip_csum(0, (u8 *)&tcp->sport, tcp_len + 1 + sizeof(hdr));
+       } else {
+               memcpy((u8 *)&tcp->sport + tcp_len, &hdr, sizeof(hdr));
+               return uip_csum(0, (u8 *)&tcp->sport, tcp_len + sizeof(hdr));
+       }
+}
diff --git a/tools/kvm/net/uip/dhcp.c b/tools/kvm/net/uip/dhcp.c
new file mode 100644 (file)
index 0000000..b17d352
--- /dev/null
@@ -0,0 +1,202 @@
+#include "kvm/uip.h"
+
+#include <arpa/inet.h>
+
+#define EMPTY_ADDR "0.0.0.0"
+
+static inline bool uip_dhcp_is_discovery(struct uip_dhcp *dhcp)
+{
+       return (dhcp->option[2] == UIP_DHCP_DISCOVER &&
+               dhcp->option[1] == UIP_DHCP_TAG_MSG_TYPE_LEN &&
+               dhcp->option[0] == UIP_DHCP_TAG_MSG_TYPE);
+}
+
+static inline bool uip_dhcp_is_request(struct uip_dhcp *dhcp)
+{
+       return (dhcp->option[2] == UIP_DHCP_REQUEST &&
+               dhcp->option[1] == UIP_DHCP_TAG_MSG_TYPE_LEN &&
+               dhcp->option[0] == UIP_DHCP_TAG_MSG_TYPE);
+}
+
+bool uip_udp_is_dhcp(struct uip_udp *udp)
+{
+       struct uip_dhcp *dhcp;
+
+       if (ntohs(udp->sport) != UIP_DHCP_PORT_CLIENT ||
+           ntohs(udp->dport) != UIP_DHCP_PORT_SERVER)
+               return false;
+
+       dhcp = (struct uip_dhcp *)udp;
+
+       if (ntohl(dhcp->magic_cookie) != UIP_DHCP_MAGIC_COOKIE)
+               return false;
+
+       return true;
+}
+
+int uip_dhcp_get_dns(struct uip_info *info)
+{
+       char key[256], val[256];
+       struct in_addr addr;
+       int ret = -1;
+       int n = 0;
+       FILE *fp;
+       u32 ip;
+
+       fp = fopen("/etc/resolv.conf", "r");
+       if (!fp)
+               return ret;
+
+       while (!feof(fp)) {
+               if (fscanf(fp, "%s %s\n", key, val) != 2)
+                       continue;
+               if (strncmp("domain", key, 6) == 0)
+                       info->domain_name = strndup(val, UIP_DHCP_MAX_DOMAIN_NAME_LEN);
+               else if (strncmp("nameserver", key, 10) == 0) {
+                       if (!inet_aton(val, &addr))
+                               continue;
+                       ip = ntohl(addr.s_addr);
+                       if (n < UIP_DHCP_MAX_DNS_SERVER_NR)
+                               info->dns_ip[n++] = ip;
+                       ret = 0;
+               }
+       }
+
+       fclose(fp);
+       return ret;
+}
+
+static int uip_dhcp_fill_option_name_and_server(struct uip_info *info, u8 *opt, int i)
+{
+       u8 domain_name_len;
+       u32 *addr;
+       int n;
+
+       if (info->domain_name) {
+               domain_name_len = strlen(info->domain_name);
+               opt[i++]        = UIP_DHCP_TAG_DOMAIN_NAME;
+               opt[i++]        = domain_name_len;
+               memcpy(&opt[i], info->domain_name, domain_name_len);
+               i               += domain_name_len;
+       }
+
+       for (n = 0; n < UIP_DHCP_MAX_DNS_SERVER_NR; n++) {
+               if (info->dns_ip[n] == 0)
+                       continue;
+               opt[i++]        = UIP_DHCP_TAG_DNS_SERVER;
+               opt[i++]        = UIP_DHCP_TAG_DNS_SERVER_LEN;
+               addr            = (u32 *)&opt[i];
+               *addr           = htonl(info->dns_ip[n]);
+               i               += UIP_DHCP_TAG_DNS_SERVER_LEN;
+       }
+
+       return i;
+}
+static int uip_dhcp_fill_option(struct uip_info *info, struct uip_dhcp *dhcp, int reply_msg_type)
+{
+       int i = 0;
+       u32 *addr;
+       u8 *opt;
+
+       opt             = dhcp->option;
+
+       opt[i++]        = UIP_DHCP_TAG_MSG_TYPE;
+       opt[i++]        = UIP_DHCP_TAG_MSG_TYPE_LEN;
+       opt[i++]        = reply_msg_type;
+
+       opt[i++]        = UIP_DHCP_TAG_SERVER_ID;
+       opt[i++]        = UIP_DHCP_TAG_SERVER_ID_LEN;
+       addr            = (u32 *)&opt[i];
+       *addr           = htonl(info->host_ip);
+       i               += UIP_DHCP_TAG_SERVER_ID_LEN;
+
+       opt[i++]        = UIP_DHCP_TAG_LEASE_TIME;
+       opt[i++]        = UIP_DHCP_TAG_LEASE_TIME_LEN;
+       addr            = (u32 *)&opt[i];
+       *addr           = htonl(UIP_DHCP_LEASE_TIME);
+       i               += UIP_DHCP_TAG_LEASE_TIME_LEN;
+
+       opt[i++]        = UIP_DHCP_TAG_SUBMASK;
+       opt[i++]        = UIP_DHCP_TAG_SUBMASK_LEN;
+       addr            = (u32 *)&opt[i];
+       *addr           = htonl(info->guest_netmask);
+       i               += UIP_DHCP_TAG_SUBMASK_LEN;
+
+       opt[i++]        = UIP_DHCP_TAG_ROUTER;
+       opt[i++]        = UIP_DHCP_TAG_ROUTER_LEN;
+       addr            = (u32 *)&opt[i];
+       *addr           = htonl(info->host_ip);
+       i               += UIP_DHCP_TAG_ROUTER_LEN;
+
+       opt[i++]        = UIP_DHCP_TAG_ROOT;
+       opt[i++]        = strlen(EMPTY_ADDR);
+       addr            = (u32 *)&opt[i];
+       strncpy((void *) addr, EMPTY_ADDR, strlen(EMPTY_ADDR));
+       i               += strlen(EMPTY_ADDR);
+
+       i               = uip_dhcp_fill_option_name_and_server(info, opt, i);
+
+       opt[i++]        = UIP_DHCP_TAG_END;
+
+       return 0;
+}
+
+static int uip_dhcp_make_pkg(struct uip_info *info, struct uip_udp_socket *sk, struct uip_buf *buf, u8 reply_msg_type)
+{
+       struct uip_dhcp *dhcp;
+
+       dhcp            = (struct uip_dhcp *)buf->eth;
+
+       dhcp->msg_type  = 2;
+       dhcp->client_ip = 0;
+       dhcp->your_ip   = htonl(info->guest_ip);
+       dhcp->server_ip = htonl(info->host_ip);
+       dhcp->agent_ip  = 0;
+
+       uip_dhcp_fill_option(info, dhcp, reply_msg_type);
+
+       sk->sip         = htonl(info->guest_ip);
+       sk->dip         = htonl(info->host_ip);
+       sk->sport       = htons(UIP_DHCP_PORT_CLIENT);
+       sk->dport       = htons(UIP_DHCP_PORT_SERVER);
+
+       return 0;
+}
+
+int uip_tx_do_ipv4_udp_dhcp(struct uip_tx_arg *arg)
+{
+       struct uip_udp_socket sk;
+       struct uip_dhcp *dhcp;
+       struct uip_info *info;
+       struct uip_buf *buf;
+       u8 reply_msg_type;
+
+       dhcp = (struct uip_dhcp *)arg->eth;
+
+       if (uip_dhcp_is_discovery(dhcp))
+               reply_msg_type = UIP_DHCP_OFFER;
+       else if (uip_dhcp_is_request(dhcp))
+               reply_msg_type = UIP_DHCP_ACK;
+       else
+               return -1;
+
+       buf = uip_buf_clone(arg);
+       info = arg->info;
+
+       /*
+        * Cook DHCP pkg
+        */
+       uip_dhcp_make_pkg(info, &sk, buf, reply_msg_type);
+
+       /*
+        * Cook UDP pkg
+        */
+       uip_udp_make_pkg(info, &sk, buf, NULL, UIP_DHCP_MAX_PAYLOAD_LEN);
+
+       /*
+        * Send data received from socket to guest
+        */
+       uip_buf_set_used(info, buf);
+
+       return 0;
+}
diff --git a/tools/kvm/net/uip/icmp.c b/tools/kvm/net/uip/icmp.c
new file mode 100644 (file)
index 0000000..233297c
--- /dev/null
@@ -0,0 +1,29 @@
+#include "kvm/uip.h"
+
+int uip_tx_do_ipv4_icmp(struct uip_tx_arg *arg)
+{
+       struct uip_ip *ip, *ip2;
+       struct uip_icmp *icmp2;
+       struct uip_buf *buf;
+
+       buf             = uip_buf_clone(arg);
+
+       icmp2           = (struct uip_icmp *)(buf->eth);
+       ip2             = (struct uip_ip *)(buf->eth);
+       ip              = (struct uip_ip *)(arg->eth);
+
+       ip2->sip        = ip->dip;
+       ip2->dip        = ip->sip;
+       ip2->csum       = 0;
+       /*
+        * ICMP reply: 0
+        */
+       icmp2->type     = 0;
+       icmp2->csum     = 0;
+       ip2->csum       = uip_csum_ip(ip2);
+       icmp2->csum     = uip_csum_icmp(icmp2);
+
+       uip_buf_set_used(arg->info, buf);
+
+       return 0;
+}
diff --git a/tools/kvm/net/uip/ipv4.c b/tools/kvm/net/uip/ipv4.c
new file mode 100644 (file)
index 0000000..58373fd
--- /dev/null
@@ -0,0 +1,29 @@
+#include "kvm/uip.h"
+
+int uip_tx_do_ipv4(struct uip_tx_arg *arg)
+{
+       struct uip_ip *ip;
+
+       ip = (struct uip_ip *)(arg->eth);
+
+       if (uip_ip_hdrlen(ip) != 20) {
+               pr_warning("IP header length is not 20 bytes");
+               return -1;
+       }
+
+       switch (ip->proto) {
+       case UIP_IP_P_ICMP:
+               uip_tx_do_ipv4_icmp(arg);
+               break;
+       case UIP_IP_P_TCP:
+               uip_tx_do_ipv4_tcp(arg);
+               break;
+       case UIP_IP_P_UDP:
+               uip_tx_do_ipv4_udp(arg);
+               break;
+       default:
+               break;
+       }
+
+       return 0;
+}
diff --git a/tools/kvm/net/uip/tcp.c b/tools/kvm/net/uip/tcp.c
new file mode 100644 (file)
index 0000000..711a716
--- /dev/null
@@ -0,0 +1,345 @@
+#include "kvm/uip.h"
+
+#include <linux/virtio_net.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <arpa/inet.h>
+
+static int uip_tcp_socket_close(struct uip_tcp_socket *sk, int how)
+{
+       shutdown(sk->fd, how);
+
+       if (sk->write_done && sk->read_done) {
+               shutdown(sk->fd, SHUT_RDWR);
+               close(sk->fd);
+
+               mutex_lock(sk->lock);
+               list_del(&sk->list);
+               mutex_unlock(sk->lock);
+
+               free(sk);
+       }
+
+       return 0;
+}
+
+static struct uip_tcp_socket *uip_tcp_socket_find(struct uip_tx_arg *arg, u32 sip, u32 dip, u16 sport, u16 dport)
+{
+       struct list_head *sk_head;
+       pthread_mutex_t *sk_lock;
+       struct uip_tcp_socket *sk;
+
+       sk_head = &arg->info->tcp_socket_head;
+       sk_lock = &arg->info->tcp_socket_lock;
+
+       mutex_lock(sk_lock);
+       list_for_each_entry(sk, sk_head, list) {
+               if (sk->sip == sip && sk->dip == dip && sk->sport == sport && sk->dport == dport) {
+                       mutex_unlock(sk_lock);
+                       return sk;
+               }
+       }
+       mutex_unlock(sk_lock);
+
+       return NULL;
+}
+
+static struct uip_tcp_socket *uip_tcp_socket_alloc(struct uip_tx_arg *arg, u32 sip, u32 dip, u16 sport, u16 dport)
+{
+       struct list_head *sk_head;
+       struct uip_tcp_socket *sk;
+       pthread_mutex_t *sk_lock;
+       struct uip_tcp *tcp;
+       struct uip_ip *ip;
+       int ret;
+
+       tcp = (struct uip_tcp *)arg->eth;
+       ip = (struct uip_ip *)arg->eth;
+
+       sk_head = &arg->info->tcp_socket_head;
+       sk_lock = &arg->info->tcp_socket_lock;
+
+       sk = malloc(sizeof(*sk));
+       memset(sk, 0, sizeof(*sk));
+
+       sk->lock                        = sk_lock;
+       sk->info                        = arg->info;
+
+       sk->fd                          = socket(AF_INET, SOCK_STREAM, 0);
+       sk->addr.sin_family             = AF_INET;
+       sk->addr.sin_port               = dport;
+       sk->addr.sin_addr.s_addr        = dip;
+
+       pthread_cond_init(&sk->cond, NULL);
+
+       if (ntohl(dip) == arg->info->host_ip)
+               sk->addr.sin_addr.s_addr = inet_addr("127.0.0.1");
+
+       ret = connect(sk->fd, (struct sockaddr *)&sk->addr, sizeof(sk->addr));
+       if (ret) {
+               free(sk);
+               return NULL;
+       }
+
+       sk->sip         = ip->sip;
+       sk->dip         = ip->dip;
+       sk->sport       = tcp->sport;
+       sk->dport       = tcp->dport;
+
+       mutex_lock(sk_lock);
+       list_add_tail(&sk->list, sk_head);
+       mutex_unlock(sk_lock);
+
+       return sk;
+}
+
+static int uip_tcp_payload_send(struct uip_tcp_socket *sk, u8 flag, u16 payload_len)
+{
+       struct uip_info *info;
+       struct uip_eth *eth2;
+       struct uip_tcp *tcp2;
+       struct uip_buf *buf;
+       struct uip_ip *ip2;
+
+       info            = sk->info;
+
+       /*
+        * Get free buffer to send data to guest
+        */
+       buf             = uip_buf_get_free(info);
+
+       /*
+        * Cook a ethernet frame
+        */
+       tcp2            = (struct uip_tcp *)buf->eth;
+       eth2            = (struct uip_eth *)buf->eth;
+       ip2             = (struct uip_ip *)buf->eth;
+
+       eth2->src       = info->host_mac;
+       eth2->dst       = info->guest_mac;
+       eth2->type      = htons(UIP_ETH_P_IP);
+
+       ip2->vhl        = UIP_IP_VER_4 | UIP_IP_HDR_LEN;
+       ip2->tos        = 0;
+       ip2->id         = 0;
+       ip2->flgfrag    = 0;
+       ip2->ttl        = UIP_IP_TTL;
+       ip2->proto      = UIP_IP_P_TCP;
+       ip2->csum       = 0;
+       ip2->sip        = sk->dip;
+       ip2->dip        = sk->sip;
+
+       tcp2->sport     = sk->dport;
+       tcp2->dport     = sk->sport;
+       tcp2->seq       = htonl(sk->seq_server);
+       tcp2->ack       = htonl(sk->ack_server);
+       /*
+        * Diable TCP options, tcp hdr len equals 20 bytes
+        */
+       tcp2->off       = UIP_TCP_HDR_LEN;
+       tcp2->flg       = flag;
+       tcp2->win       = htons(UIP_TCP_WIN_SIZE);
+       tcp2->csum      = 0;
+       tcp2->urgent    = 0;
+
+       if (payload_len > 0)
+               memcpy(uip_tcp_payload(tcp2), sk->payload, payload_len);
+
+       ip2->len        = htons(uip_tcp_hdrlen(tcp2) + payload_len + uip_ip_hdrlen(ip2));
+       ip2->csum       = uip_csum_ip(ip2);
+       tcp2->csum      = uip_csum_tcp(tcp2);
+
+       /*
+        * virtio_net_hdr
+        */
+       buf->vnet_len   = sizeof(struct virtio_net_hdr);
+       memset(buf->vnet, 0, buf->vnet_len);
+
+       buf->eth_len    = ntohs(ip2->len) + uip_eth_hdrlen(&ip2->eth);
+
+       /*
+        * Increase server seq
+        */
+       sk->seq_server  += payload_len;
+
+       /*
+        * Send data received from socket to guest
+        */
+       uip_buf_set_used(info, buf);
+
+       return 0;
+}
+
+static void *uip_tcp_socket_thread(void *p)
+{
+       struct uip_tcp_socket *sk;
+       int len, left, ret;
+       u8 *payload, *pos;
+
+       sk = p;
+
+       payload = malloc(UIP_MAX_TCP_PAYLOAD);
+       if (!payload)
+               goto out;
+
+       while (1) {
+               pos = payload;
+
+               ret = read(sk->fd, payload, UIP_MAX_TCP_PAYLOAD);
+
+               if (ret <= 0 || ret > UIP_MAX_TCP_PAYLOAD)
+                       goto out;
+
+               left = ret;
+
+               while (left > 0) {
+                       mutex_lock(sk->lock);
+                       while ((len = sk->guest_acked + sk->window_size - sk->seq_server) <= 0)
+                               pthread_cond_wait(&sk->cond, sk->lock);
+                       mutex_unlock(sk->lock);
+
+                       sk->payload = pos;
+                       if (len > left)
+                               len = left;
+                       if (len > UIP_MAX_TCP_PAYLOAD)
+                               len = UIP_MAX_TCP_PAYLOAD;
+                       left -= len;
+                       pos += len;
+
+                       uip_tcp_payload_send(sk, UIP_TCP_FLAG_ACK, len);
+               }
+       }
+
+out:
+       /*
+        * Close server to guest TCP connection
+        */
+       uip_tcp_socket_close(sk, SHUT_RD);
+
+       uip_tcp_payload_send(sk, UIP_TCP_FLAG_FIN | UIP_TCP_FLAG_ACK, 0);
+       sk->seq_server += 1;
+
+       sk->read_done = 1;
+
+       free(payload);
+       pthread_exit(NULL);
+
+       return NULL;
+}
+
+static int uip_tcp_socket_receive(struct uip_tcp_socket *sk)
+{
+       if (sk->thread == 0)
+               return pthread_create(&sk->thread, NULL, uip_tcp_socket_thread, (void *)sk);
+
+       return 0;
+}
+
+static int uip_tcp_socket_send(struct uip_tcp_socket *sk, struct uip_tcp *tcp)
+{
+       int len;
+       int ret;
+       u8 *payload;
+
+       if (sk->write_done)
+               return 0;
+
+       payload = uip_tcp_payload(tcp);
+       len = uip_tcp_payloadlen(tcp);
+
+       ret = write(sk->fd, payload, len);
+       if (ret != len)
+               pr_warning("tcp send error");
+
+       return ret;
+}
+
+int uip_tx_do_ipv4_tcp(struct uip_tx_arg *arg)
+{
+       struct uip_tcp_socket *sk;
+       struct uip_tcp *tcp;
+       struct uip_ip *ip;
+       int ret;
+
+       tcp = (struct uip_tcp *)arg->eth;
+       ip = (struct uip_ip *)arg->eth;
+
+       /*
+        * Guest is trying to start a TCP session, let's fake SYN-ACK to guest
+        */
+       if (uip_tcp_is_syn(tcp)) {
+               sk = uip_tcp_socket_alloc(arg, ip->sip, ip->dip, tcp->sport, tcp->dport);
+               if (!sk)
+                       return -1;
+
+               sk->window_size = ntohs(tcp->win);
+
+               /*
+                * Setup ISN number
+                */
+               sk->isn_guest  = uip_tcp_isn(tcp);
+               sk->isn_server = uip_tcp_isn_alloc();
+
+               sk->seq_server = sk->isn_server;
+               sk->ack_server = sk->isn_guest + 1;
+               uip_tcp_payload_send(sk, UIP_TCP_FLAG_SYN | UIP_TCP_FLAG_ACK, 0);
+               sk->seq_server += 1;
+
+               /*
+                * Start receive thread for data from remote to guest
+                */
+               uip_tcp_socket_receive(sk);
+
+               goto out;
+       }
+
+       /*
+        * Find socket we have allocated
+        */
+       sk = uip_tcp_socket_find(arg, ip->sip, ip->dip, tcp->sport, tcp->dport);
+       if (!sk)
+               return -1;
+
+       mutex_lock(sk->lock);
+       sk->window_size = ntohs(tcp->win);
+       sk->guest_acked = ntohl(tcp->ack);
+       pthread_cond_signal(&sk->cond);
+       mutex_unlock(sk->lock);
+
+       if (uip_tcp_is_fin(tcp)) {
+               if (sk->write_done)
+                       goto out;
+
+               sk->write_done = 1;
+               sk->ack_server += 1;
+               uip_tcp_payload_send(sk, UIP_TCP_FLAG_ACK, 0);
+
+               /*
+                * Close guest to server TCP connection
+                */
+               uip_tcp_socket_close(sk, SHUT_WR);
+
+               goto out;
+       }
+
+       /*
+        * Ignore guest to server frames with zero tcp payload
+        */
+       if (uip_tcp_payloadlen(tcp) == 0)
+               goto out;
+
+       /*
+        * Sent out TCP data to remote host
+        */
+       ret = uip_tcp_socket_send(sk, tcp);
+       if (ret < 0)
+               return -1;
+       /*
+        * Send ACK to guest imediately
+        */
+       sk->ack_server += ret;
+       uip_tcp_payload_send(sk, UIP_TCP_FLAG_ACK, 0);
+
+out:
+       return 0;
+}
diff --git a/tools/kvm/net/uip/udp.c b/tools/kvm/net/uip/udp.c
new file mode 100644 (file)
index 0000000..d4518b2
--- /dev/null
@@ -0,0 +1,236 @@
+#include "kvm/uip.h"
+
+#include <linux/virtio_net.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <sys/socket.h>
+#include <sys/epoll.h>
+#include <fcntl.h>
+
+#define UIP_UDP_MAX_EVENTS 1000
+
+static struct uip_udp_socket *uip_udp_socket_find(struct uip_tx_arg *arg, u32 sip, u32 dip, u16 sport, u16 dport)
+{
+       struct list_head *sk_head;
+       struct uip_udp_socket *sk;
+       pthread_mutex_t *sk_lock;
+       struct epoll_event ev;
+       int flags;
+       int ret;
+
+       sk_head = &arg->info->udp_socket_head;
+       sk_lock = &arg->info->udp_socket_lock;
+
+       /*
+        * Find existing sk
+        */
+       mutex_lock(sk_lock);
+       list_for_each_entry(sk, sk_head, list) {
+               if (sk->sip == sip && sk->dip == dip && sk->sport == sport && sk->dport == dport) {
+                       mutex_unlock(sk_lock);
+                       return sk;
+               }
+       }
+       mutex_unlock(sk_lock);
+
+       /*
+        * Allocate new one
+        */
+       sk = malloc(sizeof(*sk));
+       memset(sk, 0, sizeof(*sk));
+
+       sk->lock = sk_lock;
+
+       sk->fd = socket(AF_INET, SOCK_DGRAM, 0);
+       if (sk->fd < 0)
+               goto out;
+
+       /*
+        * Set non-blocking
+        */
+       flags = fcntl(sk->fd, F_GETFL, 0);
+       flags |= O_NONBLOCK;
+       fcntl(sk->fd, F_SETFL, flags);
+
+       /*
+        * Add sk->fd to epoll_wait
+        */
+       ev.events       = EPOLLIN;
+       ev.data.fd      = sk->fd;
+       ev.data.ptr     = sk;
+       if (arg->info->udp_epollfd <= 0)
+               arg->info->udp_epollfd = epoll_create(UIP_UDP_MAX_EVENTS);
+       ret = epoll_ctl(arg->info->udp_epollfd, EPOLL_CTL_ADD, sk->fd, &ev);
+       if (ret == -1)
+               pr_warning("epoll_ctl error");
+
+       sk->addr.sin_family      = AF_INET;
+       sk->addr.sin_addr.s_addr = dip;
+       sk->addr.sin_port        = dport;
+
+       sk->sip                  = sip;
+       sk->dip                  = dip;
+       sk->sport                = sport;
+       sk->dport                = dport;
+
+       mutex_lock(sk_lock);
+       list_add_tail(&sk->list, sk_head);
+       mutex_unlock(sk_lock);
+
+       return sk;
+
+out:
+       free(sk);
+       return NULL;
+}
+
+static int uip_udp_socket_send(struct uip_udp_socket *sk, struct uip_udp *udp)
+{
+       int len;
+       int ret;
+
+       len = ntohs(udp->len) - uip_udp_hdrlen(udp);
+
+       ret = sendto(sk->fd, udp->payload, len, 0, (struct sockaddr *)&sk->addr, sizeof(sk->addr));
+       if (ret != len)
+               return -1;
+
+       return 0;
+}
+
+int uip_udp_make_pkg(struct uip_info *info, struct uip_udp_socket *sk, struct uip_buf *buf, u8* payload, int payload_len)
+{
+       struct uip_eth *eth2;
+       struct uip_udp *udp2;
+       struct uip_ip *ip2;
+
+       /*
+        * Cook a ethernet frame
+        */
+       udp2            = (struct uip_udp *)(buf->eth);
+       eth2            = (struct uip_eth *)buf->eth;
+       ip2             = (struct uip_ip *)(buf->eth);
+
+       eth2->src       = info->host_mac;
+       eth2->dst       = info->guest_mac;
+       eth2->type      = htons(UIP_ETH_P_IP);
+
+       ip2->vhl        = UIP_IP_VER_4 | UIP_IP_HDR_LEN;
+       ip2->tos        = 0;
+       ip2->id         = 0;
+       ip2->flgfrag    = 0;
+       ip2->ttl        = UIP_IP_TTL;
+       ip2->proto      = UIP_IP_P_UDP;
+       ip2->csum       = 0;
+
+       ip2->sip        = sk->dip;
+       ip2->dip        = sk->sip;
+       udp2->sport     = sk->dport;
+       udp2->dport     = sk->sport;
+
+       udp2->len       = htons(payload_len + uip_udp_hdrlen(udp2));
+       udp2->csum      = 0;
+
+       if (payload)
+               memcpy(udp2->payload, payload, payload_len);
+
+       ip2->len        = udp2->len + htons(uip_ip_hdrlen(ip2));
+       ip2->csum       = uip_csum_ip(ip2);
+       udp2->csum      = uip_csum_udp(udp2);
+
+       /*
+        * virtio_net_hdr
+        */
+       buf->vnet_len   = sizeof(struct virtio_net_hdr);
+       memset(buf->vnet, 0, buf->vnet_len);
+
+       buf->eth_len    = ntohs(ip2->len) + uip_eth_hdrlen(&ip2->eth);
+
+       return 0;
+}
+
+static void *uip_udp_socket_thread(void *p)
+{
+       struct epoll_event events[UIP_UDP_MAX_EVENTS];
+       struct uip_udp_socket *sk;
+       struct uip_info *info;
+       struct uip_buf *buf;
+       int payload_len;
+       u8 *payload;
+       int nfds;
+       int i;
+
+       info = p;
+
+       do {
+               payload = malloc(UIP_MAX_UDP_PAYLOAD);
+       } while (!payload);
+
+       while (1) {
+               nfds = epoll_wait(info->udp_epollfd, events, UIP_UDP_MAX_EVENTS, -1);
+
+               if (nfds == -1)
+                       continue;
+
+               for (i = 0; i < nfds; i++) {
+
+                       sk = events[i].data.ptr;
+                       payload_len = recvfrom(sk->fd, payload, UIP_MAX_UDP_PAYLOAD, 0, NULL, NULL);
+                       if (payload_len < 0)
+                               continue;
+
+                       /*
+                        * Get free buffer to send data to guest
+                        */
+                       buf = uip_buf_get_free(info);
+
+                       uip_udp_make_pkg(info, sk, buf, payload, payload_len);
+
+                       /*
+                        * Send data received from socket to guest
+                        */
+                       uip_buf_set_used(info, buf);
+               }
+       }
+
+       free(payload);
+       pthread_exit(NULL);
+       return NULL;
+}
+
+int uip_tx_do_ipv4_udp(struct uip_tx_arg *arg)
+{
+       struct uip_udp_socket *sk;
+       struct uip_info *info;
+       struct uip_udp *udp;
+       struct uip_ip *ip;
+       int ret;
+
+       udp     = (struct uip_udp *)(arg->eth);
+       ip      = (struct uip_ip *)(arg->eth);
+       info    = arg->info;
+
+       if (uip_udp_is_dhcp(udp)) {
+               uip_tx_do_ipv4_udp_dhcp(arg);
+               return 0;
+       }
+
+       /*
+        * Find socket we have allocated before, otherwise allocate one
+        */
+       sk = uip_udp_socket_find(arg, ip->sip, ip->dip, udp->sport, udp->dport);
+       if (!sk)
+               return -1;
+
+       /*
+        * Send out UDP data to remote host
+        */
+       ret = uip_udp_socket_send(sk, udp);
+       if (ret)
+               return -1;
+
+       if (!info->udp_thread)
+               pthread_create(&info->udp_thread, NULL, uip_udp_socket_thread, (void *)info);
+
+       return 0;
+}
diff --git a/tools/kvm/pci.c b/tools/kvm/pci.c
new file mode 100644 (file)
index 0000000..a28b5e2
--- /dev/null
@@ -0,0 +1,215 @@
+#include "kvm/pci.h"
+#include "kvm/ioport.h"
+#include "kvm/util.h"
+#include "kvm/kvm.h"
+
+#include <linux/err.h>
+#include <assert.h>
+
+#define PCI_BAR_OFFSET(b)              (offsetof(struct pci_device_header, bar[b]))
+
+static struct pci_device_header                *pci_devices[PCI_MAX_DEVICES];
+
+static union pci_config_address                pci_config_address;
+
+/* This is within our PCI gap - in an unused area.
+ * Note this is a PCI *bus address*, is used to assign BARs etc.!
+ * (That's why it can still 32bit even with 64bit guests-- 64bit
+ * PCI isn't currently supported.)
+ */
+static u32 io_space_blocks             = KVM_PCI_MMIO_AREA;
+
+u32 pci_get_io_space_block(u32 size)
+{
+       u32 block = io_space_blocks;
+       io_space_blocks += size;
+
+       return block;
+}
+
+static void *pci_config_address_ptr(u16 port)
+{
+       unsigned long offset;
+       void *base;
+
+       offset  = port - PCI_CONFIG_ADDRESS;
+       base    = &pci_config_address;
+
+       return base + offset;
+}
+
+static bool pci_config_address_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
+{
+       void *p = pci_config_address_ptr(port);
+
+       memcpy(p, data, size);
+
+       return true;
+}
+
+static bool pci_config_address_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
+{
+       void *p = pci_config_address_ptr(port);
+
+       memcpy(data, p, size);
+
+       return true;
+}
+
+static struct ioport_operations pci_config_address_ops = {
+       .io_in  = pci_config_address_in,
+       .io_out = pci_config_address_out,
+};
+
+static bool pci_device_exists(u8 bus_number, u8 device_number, u8 function_number)
+{
+       struct pci_device_header *dev;
+
+       if (pci_config_address.bus_number != bus_number)
+               return false;
+
+       if (pci_config_address.function_number != function_number)
+               return false;
+
+       if (device_number >= PCI_MAX_DEVICES)
+               return false;
+
+       dev = pci_devices[device_number];
+
+       return dev != NULL;
+}
+
+static bool pci_config_data_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
+{
+       /*
+        * If someone accesses PCI configuration space offsets that are not
+        * aligned to 4 bytes, it uses ioports to signify that.
+        */
+       pci_config_address.reg_offset = port - PCI_CONFIG_DATA;
+
+       pci__config_wr(kvm, pci_config_address, data, size);
+
+       return true;
+}
+
+static bool pci_config_data_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
+{
+       /*
+        * If someone accesses PCI configuration space offsets that are not
+        * aligned to 4 bytes, it uses ioports to signify that.
+        */
+       pci_config_address.reg_offset = port - PCI_CONFIG_DATA;
+
+       pci__config_rd(kvm, pci_config_address, data, size);
+
+       return true;
+}
+
+static struct ioport_operations pci_config_data_ops = {
+       .io_in  = pci_config_data_in,
+       .io_out = pci_config_data_out,
+};
+
+void pci__config_wr(struct kvm *kvm, union pci_config_address addr, void *data, int size)
+{
+       u8 dev_num;
+
+       dev_num = addr.device_number;
+
+       if (pci_device_exists(0, dev_num, 0)) {
+               unsigned long offset;
+
+               offset = addr.w & 0xff;
+               if (offset < sizeof(struct pci_device_header)) {
+                       void *p = pci_devices[dev_num];
+                       u8 bar = (offset - PCI_BAR_OFFSET(0)) / (sizeof(u32));
+                       u32 sz = PCI_IO_SIZE;
+
+                       if (bar < 6 && pci_devices[dev_num]->bar_size[bar])
+                               sz = pci_devices[dev_num]->bar_size[bar];
+
+                       /*
+                        * If the kernel masks the BAR it would expect to find the
+                        * size of the BAR there next time it reads from it.
+                        * When the kernel got the size it would write the address
+                        * back.
+                        */
+                       if (*(u32 *)(p + offset)) {
+                               /* See if kernel tries to mask one of the BARs */
+                               if ((offset >= PCI_BAR_OFFSET(0)) &&
+                                   (offset <= PCI_BAR_OFFSET(6)) &&
+                                   (ioport__read32(data)  == 0xFFFFFFFF))
+                                       memcpy(p + offset, &sz, sizeof(sz));
+                                   else
+                                       memcpy(p + offset, data, size);
+                       }
+               }
+       }
+}
+
+void pci__config_rd(struct kvm *kvm, union pci_config_address addr, void *data, int size)
+{
+       u8 dev_num;
+
+       dev_num = addr.device_number;
+
+       if (pci_device_exists(0, dev_num, 0)) {
+               unsigned long offset;
+
+               offset = addr.w & 0xff;
+               if (offset < sizeof(struct pci_device_header)) {
+                       void *p = pci_devices[dev_num];
+
+                       memcpy(data, p + offset, size);
+               } else {
+                       memset(data, 0x00, size);
+               }
+       } else {
+               memset(data, 0xff, size);
+       }
+}
+
+int pci__register(struct pci_device_header *dev, u8 dev_num)
+{
+       if (dev_num >= PCI_MAX_DEVICES)
+               return -ENOSPC;
+
+       pci_devices[dev_num] = dev;
+
+       return 0;
+}
+
+struct pci_device_header *pci__find_dev(u8 dev_num)
+{
+       if (dev_num >= PCI_MAX_DEVICES)
+               return ERR_PTR(-EOVERFLOW);
+
+       return pci_devices[dev_num];
+}
+
+int pci__init(struct kvm *kvm)
+{
+       int r;
+
+       r = ioport__register(kvm, PCI_CONFIG_DATA + 0, &pci_config_data_ops, 4, NULL);
+       if (r < 0)
+               return r;
+
+       r = ioport__register(kvm, PCI_CONFIG_ADDRESS + 0, &pci_config_address_ops, 4, NULL);
+       if (r < 0) {
+               ioport__unregister(kvm, PCI_CONFIG_DATA);
+               return r;
+       }
+
+       return 0;
+}
+base_init(pci__init);
+
+int pci__exit(struct kvm *kvm)
+{
+       ioport__unregister(kvm, PCI_CONFIG_DATA);
+       ioport__unregister(kvm, PCI_CONFIG_ADDRESS);
+
+       return 0;
+}
+base_exit(pci__exit);
diff --git a/tools/kvm/powerpc/boot.c b/tools/kvm/powerpc/boot.c
new file mode 100644 (file)
index 0000000..2557fc0
--- /dev/null
@@ -0,0 +1,8 @@
+#include "kvm/kvm.h"
+
+#include <stdbool.h>
+
+bool kvm__load_firmware(struct kvm *kvm, const char *firmware_filename)
+{
+       return false;
+}
diff --git a/tools/kvm/powerpc/cpu_info.c b/tools/kvm/powerpc/cpu_info.c
new file mode 100644 (file)
index 0000000..11ca14e
--- /dev/null
@@ -0,0 +1,195 @@
+/*
+ * PPC CPU identification
+ *
+ * This is a very simple "host CPU info" struct to get us going.
+ * For the little host information we need, I don't want to grub about
+ * parsing stuff in /proc/device-tree so just match host PVR to differentiate
+ * PPC970 and POWER7 (which is all that's currently supported).
+ *
+ * Qemu does something similar but this is MUCH simpler!
+ *
+ * Copyright 2012 Matt Evans <matt@ozlabs.org>, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#include <kvm/kvm.h>
+#include <sys/ioctl.h>
+
+#include "cpu_info.h"
+#include "kvm/util.h"
+
+/* POWER7 */
+
+static struct cpu_info cpu_power7_info = {
+       .name = "POWER7",
+       .tb_freq = 512000000,
+       .d_bsize = 128,
+       .i_bsize = 128,
+       .flags = CPUINFO_FLAG_DFP | CPUINFO_FLAG_VSX | CPUINFO_FLAG_VMX,
+       .mmu_info = {
+               .flags = KVM_PPC_PAGE_SIZES_REAL | KVM_PPC_1T_SEGMENTS,
+               .slb_size = 32,
+       },
+};
+
+/* PPC970/G5 */
+
+static struct cpu_info cpu_970_info = {
+       .name = "G5",
+       .tb_freq = 33333333,
+       .d_bsize = 128,
+       .i_bsize = 128,
+       .flags = CPUINFO_FLAG_VMX,
+};
+
+/* This is a default catchall for 'no match' on PVR: */
+static struct cpu_info cpu_dummy_info = { .name = "unknown" };
+
+static struct pvr_info host_pvr_info[] = {
+       { 0xffffffff, 0x0f000003, &cpu_power7_info },
+       { 0xffff0000, 0x003f0000, &cpu_power7_info },
+       { 0xffff0000, 0x004a0000, &cpu_power7_info },
+       { 0xffff0000, 0x00390000, &cpu_970_info },
+       { 0xffff0000, 0x003c0000, &cpu_970_info },
+        { 0xffff0000, 0x00440000, &cpu_970_info },
+        { 0xffff0000, 0x00450000, &cpu_970_info },
+};
+
+/* If we can't query the kernel for supported page sizes assume 4K and 16M */
+static struct kvm_ppc_one_seg_page_size fallback_sps[] = {
+       [0] = {
+               .page_shift = 12,
+               .slb_enc    = 0,
+               .enc =  {
+                       [0] = {
+                               .page_shift = 12,
+                               .pte_enc    = 0,
+                       },
+               },
+       },
+       [1] = {
+               .page_shift = 24,
+               .slb_enc    = 0x100,
+               .enc =  {
+                       [0] = {
+                               .page_shift = 24,
+                               .pte_enc    = 0,
+                       },
+               },
+       },
+};
+
+
+static void setup_mmu_info(struct kvm *kvm, struct cpu_info *cpu_info)
+{
+       static struct kvm_ppc_smmu_info *mmu_info;
+       struct kvm_ppc_one_seg_page_size *sps;
+       int i, j, k, valid;
+
+       if (!kvm__supports_extension(kvm, KVM_CAP_PPC_GET_SMMU_INFO)) {
+               memcpy(&cpu_info->mmu_info.sps, fallback_sps, sizeof(fallback_sps));
+       } else if (ioctl(kvm->vm_fd, KVM_PPC_GET_SMMU_INFO, &cpu_info->mmu_info) < 0) {
+                       die_perror("KVM_PPC_GET_SMMU_INFO failed");
+       }
+
+       mmu_info = &cpu_info->mmu_info;
+
+       if (!(mmu_info->flags & KVM_PPC_PAGE_SIZES_REAL))
+               /* Guest pages are not restricted by the backing page size */
+               return;
+
+       /* Filter based on backing page size */
+
+       for (i = 0; i < KVM_PPC_PAGE_SIZES_MAX_SZ; i++) {
+               sps = &mmu_info->sps[i];
+
+               if (!sps->page_shift)
+                       break;
+
+               if (kvm->ram_pagesize < (1ul << sps->page_shift)) {
+                       /* Mark the whole segment size invalid */
+                       sps->page_shift = 0;
+                       continue;
+               }
+
+               /* Check each page size for the segment */
+               for (j = 0, valid = 0; j < KVM_PPC_PAGE_SIZES_MAX_SZ; j++) {
+                       if (!sps->enc[j].page_shift)
+                               break;
+
+                       if (kvm->ram_pagesize < (1ul << sps->enc[j].page_shift))
+                               sps->enc[j].page_shift = 0;
+                       else
+                               valid++;
+               }
+
+               if (!valid) {
+                       /* Mark the whole segment size invalid */
+                       sps->page_shift = 0;
+                       continue;
+               }
+
+               /* Mark any trailing entries invalid if we broke out early */
+               for (k = j; k < KVM_PPC_PAGE_SIZES_MAX_SZ; k++)
+                       sps->enc[k].page_shift = 0;
+
+               /* Collapse holes */
+               for (j = 0; j < KVM_PPC_PAGE_SIZES_MAX_SZ; j++) {
+                       if (sps->enc[j].page_shift)
+                               continue;
+
+                       for (k = j + 1; k < KVM_PPC_PAGE_SIZES_MAX_SZ; k++) {
+                               if (sps->enc[k].page_shift) {
+                                       sps->enc[j] = sps->enc[k];
+                                       sps->enc[k].page_shift = 0;
+                                       break;
+                               }
+                       }
+               }
+       }
+
+       /* Mark any trailing entries invalid if we broke out early */
+       for (j = i; j < KVM_PPC_PAGE_SIZES_MAX_SZ; j++)
+               mmu_info->sps[j].page_shift = 0;
+
+       /* Collapse holes */
+       for (i = 0; i < KVM_PPC_PAGE_SIZES_MAX_SZ; i++) {
+               if (mmu_info->sps[i].page_shift)
+                       continue;
+
+               for (j = i + 1; j < KVM_PPC_PAGE_SIZES_MAX_SZ; j++) {
+                       if (mmu_info->sps[j].page_shift) {
+                               mmu_info->sps[i] = mmu_info->sps[j];
+                               mmu_info->sps[j].page_shift = 0;
+                               break;
+                       }
+               }
+       }
+}
+
+struct cpu_info *find_cpu_info(struct kvm *kvm)
+{
+       struct cpu_info *info;
+       unsigned int i;
+       u32 pvr = kvm->arch.pvr;
+
+       for (info = NULL, i = 0; i < ARRAY_SIZE(host_pvr_info); i++) {
+               if ((pvr & host_pvr_info[i].pvr_mask) == host_pvr_info[i].pvr) {
+                       info = host_pvr_info[i].cpu_info;
+                       break;
+               }
+       }
+
+       /* Didn't find anything? Rut-ro. */
+       if (!info) {
+               pr_warning("Host CPU unsupported by kvmtool\n");
+               info = &cpu_dummy_info;
+       }
+
+       setup_mmu_info(kvm, info);
+
+       return info;
+}
diff --git a/tools/kvm/powerpc/cpu_info.h b/tools/kvm/powerpc/cpu_info.h
new file mode 100644 (file)
index 0000000..f61707a
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * PPC CPU identification
+ *
+ * Copyright 2012 Matt Evans <matt@ozlabs.org>, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#ifndef CPU_INFO_H
+#define CPU_INFO_H
+
+#include <kvm/kvm.h>
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/kvm.h>
+
+struct cpu_info {
+       const char      *name;
+       u32             tb_freq; /* timebase frequency */
+       u32             d_bsize; /* d-cache block size */
+       u32             i_bsize; /* i-cache block size */
+       u32             flags;
+       struct kvm_ppc_smmu_info mmu_info;
+};
+
+struct pvr_info {
+       u32             pvr_mask;
+       u32             pvr;
+       struct cpu_info *cpu_info;
+};
+
+/* Misc capabilities/CPU properties */
+#define CPUINFO_FLAG_DFP       0x00000001
+#define CPUINFO_FLAG_VMX       0x00000002
+#define CPUINFO_FLAG_VSX       0x00000004
+
+struct cpu_info *find_cpu_info(struct kvm *kvm);
+
+#endif
diff --git a/tools/kvm/powerpc/include/kvm/barrier.h b/tools/kvm/powerpc/include/kvm/barrier.h
new file mode 100644 (file)
index 0000000..dd5115a
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _KVM_BARRIER_H_
+#define _KVM_BARRIER_H_
+
+#include <asm/barrier.h>
+
+#endif /* _KVM_BARRIER_H_ */
diff --git a/tools/kvm/powerpc/include/kvm/kvm-arch.h b/tools/kvm/powerpc/include/kvm/kvm-arch.h
new file mode 100644 (file)
index 0000000..97181c4
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * PPC64 architecture-specific definitions
+ *
+ * Copyright 2011 Matt Evans <matt@ozlabs.org>, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#ifndef KVM__KVM_ARCH_H
+#define KVM__KVM_ARCH_H
+
+#include <stdbool.h>
+#include <linux/types.h>
+#include <time.h>
+
+/*
+ * MMIO lives after RAM, but it'd be nice if it didn't constantly move.
+ * Choose a suitably high address, e.g. 63T...  This limits RAM size.
+ */
+#define PPC_MMIO_START                 0x3F0000000000UL
+#define PPC_MMIO_SIZE                  0x010000000000UL
+
+#define KERNEL_LOAD_ADDR               0x0000000000000000
+#define KERNEL_START_ADDR              0x0000000000000000
+#define KERNEL_SECONDARY_START_ADDR     0x0000000000000060
+#define INITRD_LOAD_ADDR               0x0000000002800000
+
+#define FDT_MAX_SIZE                   0x10000
+#define RTAS_MAX_SIZE                  0x10000
+
+#define TIMEBASE_FREQ                  512000000ULL
+
+#define KVM_MMIO_START                 PPC_MMIO_START
+
+/*
+ * This is the address that pci_get_io_space_block() starts allocating
+ * from.  Note that this is a PCI bus address.
+ */
+#define KVM_PCI_MMIO_AREA              0x1000000
+#define KVM_VIRTIO_MMIO_AREA           0x2000000
+
+struct spapr_phb;
+
+struct kvm_arch {
+       u64                     sdr1;
+       u32                     pvr;
+       unsigned long           rtas_gra;
+       unsigned long           rtas_size;
+       unsigned long           fdt_gra;
+       unsigned long           initrd_gra;
+       unsigned long           initrd_size;
+       struct icp_state        *icp;
+       struct spapr_phb        *phb;
+};
+
+/* Helper for the various bits of code that generate FDT nodes */
+#define _FDT(exp)                                                      \
+       do {                                                            \
+               int ret = (exp);                                        \
+               if (ret < 0) {                                          \
+                       die("Error creating device tree: %s: %s\n",     \
+                           #exp, fdt_strerror(ret));                   \
+               }                                                       \
+       } while (0)
+
+#endif /* KVM__KVM_ARCH_H */
diff --git a/tools/kvm/powerpc/include/kvm/kvm-cpu-arch.h b/tools/kvm/powerpc/include/kvm/kvm-cpu-arch.h
new file mode 100644 (file)
index 0000000..7520c04
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * PPC64 cpu-specific definitions
+ *
+ * Copyright 2011 Matt Evans <matt@ozlabs.org>, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#ifndef KVM__KVM_CPU_ARCH_H
+#define KVM__KVM_CPU_ARCH_H
+
+/* Architecture-specific kvm_cpu definitions. */
+
+#include <linux/kvm.h> /* for struct kvm_regs */
+#include <stdbool.h>
+#include <pthread.h>
+
+#define MSR_SF         (1UL<<63)
+#define MSR_HV         (1UL<<60)
+#define MSR_VEC                (1UL<<25)
+#define MSR_VSX                (1UL<<23)
+#define MSR_POW                (1UL<<18)
+#define MSR_EE         (1UL<<15)
+#define MSR_PR         (1UL<<14)
+#define MSR_FP         (1UL<<13)
+#define MSR_ME         (1UL<<12)
+#define MSR_FE0                (1UL<<11)
+#define MSR_SE         (1UL<<10)
+#define MSR_BE         (1UL<<9)
+#define MSR_FE1                (1UL<<8)
+#define MSR_IR         (1UL<<5)
+#define MSR_DR         (1UL<<4)
+#define MSR_PMM                (1UL<<2)
+#define MSR_RI         (1UL<<1)
+#define MSR_LE         (1UL<<0)
+
+#define POWER7_EXT_IRQ 0
+
+struct kvm;
+
+struct kvm_cpu {
+       pthread_t               thread;         /* VCPU thread */
+
+       unsigned long           cpu_id;
+
+       struct kvm              *kvm;           /* parent KVM */
+       int                     vcpu_fd;        /* For VCPU ioctls() */
+       struct kvm_run          *kvm_run;
+
+       struct kvm_regs         regs;
+       struct kvm_sregs        sregs;
+       struct kvm_fpu          fpu;
+
+       u8                      is_running;
+       u8                      paused;
+       u8                      needs_nmi;
+       /*
+        * Although PPC KVM doesn't yet support coalesced MMIO, generic code
+        * needs this in our kvm_cpu:
+        */
+       struct kvm_coalesced_mmio_ring  *ring;
+};
+
+void kvm_cpu__irq(struct kvm_cpu *vcpu, int pin, int level);
+
+/* This is never actually called on PPC. */
+static inline bool kvm_cpu__emulate_io(struct kvm *kvm, u16 port, void *data, int direction, int size, u32 count)
+{
+       return false;
+}
+
+bool kvm_cpu__emulate_mmio(struct kvm *kvm, u64 phys_addr, u8 *data, u32 len, u8 is_write);
+
+#endif /* KVM__KVM_CPU_ARCH_H */
diff --git a/tools/kvm/powerpc/ioport.c b/tools/kvm/powerpc/ioport.c
new file mode 100644 (file)
index 0000000..264fb7e
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * PPC64 ioport platform setup.  There isn't any! :-)
+ *
+ * Copyright 2011 Matt Evans <matt@ozlabs.org>, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#include "kvm/ioport.h"
+
+#include <stdlib.h>
+
+void ioport__setup_arch(struct kvm *kvm)
+{
+       /* PPC has no legacy ioports to set up */
+}
diff --git a/tools/kvm/powerpc/irq.c b/tools/kvm/powerpc/irq.c
new file mode 100644 (file)
index 0000000..e89fa3b
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * PPC64 IRQ routines
+ *
+ * Copyright 2011 Matt Evans <matt@ozlabs.org>, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#include "kvm/irq.h"
+#include "kvm/kvm.h"
+#include "kvm/util.h"
+
+#include <linux/types.h>
+#include <linux/rbtree.h>
+#include <linux/list.h>
+#include <linux/kvm.h>
+#include <sys/ioctl.h>
+
+#include <stddef.h>
+#include <stdlib.h>
+
+#include "kvm/pci.h"
+
+#include "xics.h"
+#include "spapr_pci.h"
+
+/*
+ * FIXME: The code in this file assumes an SPAPR guest, using XICS.  Make
+ * generic & cope with multiple PPC platform types.
+ */
+
+static int pci_devs = 0;
+
+int irq__register_device(u32 dev, u8 *num, u8 *pin, u8 *line)
+{
+       if (pci_devs >= PCI_MAX_DEVICES)
+               die("Hit PCI device limit!\n");
+
+       *num = pci_devs++;
+
+       *pin = 1;
+       /*
+        * Have I said how nasty I find this?  Line should be dontcare... PHB
+        * should determine which CPU/XICS IRQ to fire.
+        */
+       *line = xics_alloc_irqnum();
+       return 0;
+}
+
+int irq__add_msix_route(struct kvm *kvm, struct msi_msg *msg)
+{
+       die(__FUNCTION__);
+       return 0;
+}
diff --git a/tools/kvm/powerpc/kvm-cpu.c b/tools/kvm/powerpc/kvm-cpu.c
new file mode 100644 (file)
index 0000000..8fce121
--- /dev/null
@@ -0,0 +1,290 @@
+/*
+ * PPC64 processor support
+ *
+ * Copyright 2011 Matt Evans <matt@ozlabs.org>, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#include "kvm/kvm-cpu.h"
+
+#include "kvm/symbol.h"
+#include "kvm/util.h"
+#include "kvm/kvm.h"
+
+#include "spapr.h"
+#include "spapr_pci.h"
+#include "xics.h"
+
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <stdio.h>
+#include <assert.h>
+
+static int debug_fd;
+
+void kvm_cpu__set_debug_fd(int fd)
+{
+       debug_fd = fd;
+}
+
+int kvm_cpu__get_debug_fd(void)
+{
+       return debug_fd;
+}
+
+static struct kvm_cpu *kvm_cpu__new(struct kvm *kvm)
+{
+       struct kvm_cpu *vcpu;
+
+       vcpu            = calloc(1, sizeof *vcpu);
+       if (!vcpu)
+               return NULL;
+
+       vcpu->kvm       = kvm;
+
+       return vcpu;
+}
+
+void kvm_cpu__delete(struct kvm_cpu *vcpu)
+{
+       free(vcpu);
+}
+
+struct kvm_cpu *kvm_cpu__arch_init(struct kvm *kvm, unsigned long cpu_id)
+{
+       struct kvm_cpu *vcpu;
+       int mmap_size;
+       struct kvm_enable_cap papr_cap = { .cap = KVM_CAP_PPC_PAPR };
+
+       vcpu            = kvm_cpu__new(kvm);
+       if (!vcpu)
+               return NULL;
+
+       vcpu->cpu_id    = cpu_id;
+
+       vcpu->vcpu_fd = ioctl(vcpu->kvm->vm_fd, KVM_CREATE_VCPU, cpu_id);
+       if (vcpu->vcpu_fd < 0)
+               die_perror("KVM_CREATE_VCPU ioctl");
+
+       mmap_size = ioctl(vcpu->kvm->sys_fd, KVM_GET_VCPU_MMAP_SIZE, 0);
+       if (mmap_size < 0)
+               die_perror("KVM_GET_VCPU_MMAP_SIZE ioctl");
+
+       vcpu->kvm_run = mmap(NULL, mmap_size, PROT_RW, MAP_SHARED, vcpu->vcpu_fd, 0);
+       if (vcpu->kvm_run == MAP_FAILED)
+               die("unable to mmap vcpu fd");
+
+       if (ioctl(vcpu->vcpu_fd, KVM_ENABLE_CAP, &papr_cap) < 0)
+               die("unable to enable PAPR capability");
+
+       /*
+        * We start all CPUs, directing non-primary threads into the kernel's
+        * secondary start point.  When we come to support SLOF, we will start
+        * only one and SLOF will RTAS call us to ask for others to be
+        * started.  (FIXME: make more generic & interface with whichever
+        * firmware a platform may be using.)
+        */
+       vcpu->is_running = true;
+
+       return vcpu;
+}
+
+static void kvm_cpu__setup_fpu(struct kvm_cpu *vcpu)
+{
+       /* Don't have to do anything, there's no expected FPU state. */
+}
+
+static void kvm_cpu__setup_regs(struct kvm_cpu *vcpu)
+{
+       /*
+        * FIXME: This assumes PPC64 and Linux guest.  It doesn't use the
+        * OpenFirmware entry method, but instead the "embedded" entry which
+        * passes the FDT address directly.
+        */
+       struct kvm_regs *r = &vcpu->regs;
+
+       if (vcpu->cpu_id == 0) {
+               r->pc = KERNEL_START_ADDR;
+               r->gpr[3] = vcpu->kvm->arch.fdt_gra;
+               r->gpr[5] = 0;
+       } else {
+               r->pc = KERNEL_SECONDARY_START_ADDR;
+               r->gpr[3] = vcpu->cpu_id;
+       }
+       r->msr = 0x8000000000001000UL; /* 64bit, non-HV, ME */
+
+       if (ioctl(vcpu->vcpu_fd, KVM_SET_REGS, &vcpu->regs) < 0)
+               die_perror("KVM_SET_REGS failed");
+}
+
+static void kvm_cpu__setup_sregs(struct kvm_cpu *vcpu)
+{
+       /*
+        * Some sregs setup to initialise SDR1/PVR/HIOR on PPC64 SPAPR
+        * platforms using PR KVM.  (Technically, this is all ignored on
+        * SPAPR HV KVM.)  Different setup is required for non-PV non-SPAPR
+        * platforms!  (FIXME.)
+        */
+       struct kvm_sregs sregs;
+       struct kvm_one_reg reg = {};
+       u64 value;
+
+       if (ioctl(vcpu->vcpu_fd, KVM_GET_SREGS, &sregs) < 0)
+               die("KVM_GET_SREGS failed");
+
+       sregs.u.s.sdr1 = vcpu->kvm->arch.sdr1;
+       sregs.pvr = vcpu->kvm->arch.pvr;
+
+       if (ioctl(vcpu->vcpu_fd, KVM_SET_SREGS, &sregs) < 0)
+               die("KVM_SET_SREGS failed");
+
+       reg.id = KVM_REG_PPC_HIOR;
+       value = 0;
+       reg.addr = (u64)&value;
+       if (ioctl(vcpu->vcpu_fd, KVM_SET_ONE_REG, &reg) < 0)
+               die("KVM_SET_ONE_REG failed");
+}
+
+/**
+ * kvm_cpu__reset_vcpu - reset virtual CPU to a known state
+ */
+void kvm_cpu__reset_vcpu(struct kvm_cpu *vcpu)
+{
+       kvm_cpu__setup_regs(vcpu);
+       kvm_cpu__setup_sregs(vcpu);
+       kvm_cpu__setup_fpu(vcpu);
+}
+
+/* kvm_cpu__irq - set KVM's IRQ flag on this vcpu */
+void kvm_cpu__irq(struct kvm_cpu *vcpu, int pin, int level)
+{
+       unsigned int virq = level ? KVM_INTERRUPT_SET_LEVEL : KVM_INTERRUPT_UNSET;
+
+       /* FIXME: POWER-specific */
+       if (pin != POWER7_EXT_IRQ)
+               return;
+       if (ioctl(vcpu->vcpu_fd, KVM_INTERRUPT, &virq) < 0)
+               pr_warning("Could not KVM_INTERRUPT.");
+}
+
+void kvm_cpu__arch_nmi(struct kvm_cpu *cpu)
+{
+}
+
+bool kvm_cpu__handle_exit(struct kvm_cpu *vcpu)
+{
+       bool ret = true;
+       struct kvm_run *run = vcpu->kvm_run;
+       switch(run->exit_reason) {
+       case KVM_EXIT_PAPR_HCALL:
+               run->papr_hcall.ret = spapr_hypercall(vcpu, run->papr_hcall.nr,
+                                                     (target_ulong*)run->papr_hcall.args);
+               break;
+       default:
+               ret = false;
+       }
+       return ret;
+}
+
+bool kvm_cpu__emulate_mmio(struct kvm *kvm, u64 phys_addr, u8 *data, u32 len, u8 is_write)
+{
+       /*
+        * FIXME: This function will need to be split in order to support
+        * various PowerPC platforms/PHB types, etc.  It currently assumes SPAPR
+        * PPC64 guest.
+        */
+       bool ret = false;
+
+       if ((phys_addr >= SPAPR_PCI_WIN_START) &&
+           (phys_addr < SPAPR_PCI_WIN_END)) {
+               ret = spapr_phb_mmio(kvm, phys_addr, data, len, is_write);
+       } else {
+               pr_warning("MMIO %s unknown address %llx (size %d)!\n",
+                          is_write ? "write to" : "read from",
+                          phys_addr, len);
+       }
+       return ret;
+}
+
+#define CONDSTR_BIT(m, b) (((m) & MSR_##b) ? #b" " : "")
+
+void kvm_cpu__show_registers(struct kvm_cpu *vcpu)
+{
+       struct kvm_regs regs;
+       struct kvm_sregs sregs;
+       int r;
+
+       if (ioctl(vcpu->vcpu_fd, KVM_GET_REGS, &regs) < 0)
+               die("KVM_GET_REGS failed");
+        if (ioctl(vcpu->vcpu_fd, KVM_GET_SREGS, &sregs) < 0)
+               die("KVM_GET_SREGS failed");
+
+       dprintf(debug_fd, "\n Registers:\n");
+       dprintf(debug_fd, " NIP:   %016llx  MSR:   %016llx "
+               "( %s%s%s%s%s%s%s%s%s%s%s%s)\n",
+               regs.pc, regs.msr,
+               CONDSTR_BIT(regs.msr, SF),
+               CONDSTR_BIT(regs.msr, HV), /* ! */
+               CONDSTR_BIT(regs.msr, VEC),
+               CONDSTR_BIT(regs.msr, VSX),
+               CONDSTR_BIT(regs.msr, EE),
+               CONDSTR_BIT(regs.msr, PR),
+               CONDSTR_BIT(regs.msr, FP),
+               CONDSTR_BIT(regs.msr, ME),
+               CONDSTR_BIT(regs.msr, IR),
+               CONDSTR_BIT(regs.msr, DR),
+               CONDSTR_BIT(regs.msr, RI),
+               CONDSTR_BIT(regs.msr, LE));
+       dprintf(debug_fd, " CTR:   %016llx  LR:    %016llx  CR:   %08llx\n",
+               regs.ctr, regs.lr, regs.cr);
+       dprintf(debug_fd, " SRR0:  %016llx  SRR1:  %016llx  XER:  %016llx\n",
+               regs.srr0, regs.srr1, regs.xer);
+       dprintf(debug_fd, " SPRG0: %016llx  SPRG1: %016llx\n",
+               regs.sprg0, regs.sprg1);
+       dprintf(debug_fd, " SPRG2: %016llx  SPRG3: %016llx\n",
+               regs.sprg2, regs.sprg3);
+       dprintf(debug_fd, " SPRG4: %016llx  SPRG5: %016llx\n",
+               regs.sprg4, regs.sprg5);
+       dprintf(debug_fd, " SPRG6: %016llx  SPRG7: %016llx\n",
+               regs.sprg6, regs.sprg7);
+       dprintf(debug_fd, " GPRs:\n ");
+       for (r = 0; r < 32; r++) {
+               dprintf(debug_fd, "%016llx  ", regs.gpr[r]);
+               if ((r & 3) == 3)
+                       dprintf(debug_fd, "\n ");
+       }
+       dprintf(debug_fd, "\n");
+
+       /* FIXME: Assumes SLB-based (book3s) guest */
+       for (r = 0; r < 32; r++) {
+               dprintf(debug_fd, " SLB%02d  %016llx %016llx\n", r,
+                       sregs.u.s.ppc64.slb[r].slbe,
+                       sregs.u.s.ppc64.slb[r].slbv);
+       }
+       dprintf(debug_fd, "----------\n");
+}
+
+void kvm_cpu__show_code(struct kvm_cpu *vcpu)
+{
+       if (ioctl(vcpu->vcpu_fd, KVM_GET_REGS, &vcpu->regs) < 0)
+               die("KVM_GET_REGS failed");
+
+       /* FIXME: Dump/disassemble some code...! */
+
+       dprintf(debug_fd, "\n Stack:\n");
+       dprintf(debug_fd,   " ------\n");
+       /* Only works in real mode: */
+       kvm__dump_mem(vcpu->kvm, vcpu->regs.gpr[1], 32);
+}
+
+void kvm_cpu__show_page_tables(struct kvm_cpu *vcpu)
+{
+       /* Does nothing yet */
+}
diff --git a/tools/kvm/powerpc/kvm.c b/tools/kvm/powerpc/kvm.c
new file mode 100644 (file)
index 0000000..d675265
--- /dev/null
@@ -0,0 +1,529 @@
+/*
+ * PPC64 (SPAPR) platform support
+ *
+ * Copyright 2011 Matt Evans <matt@ozlabs.org>, IBM Corporation.
+ *
+ * Portions of FDT setup borrowed from QEMU, copyright 2010 David Gibson, IBM
+ * Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#include "kvm/kvm.h"
+#include "kvm/util.h"
+#include "libfdt.h"
+#include "cpu_info.h"
+
+#include "spapr.h"
+#include "spapr_hvcons.h"
+#include "spapr_pci.h"
+
+#include <linux/kvm.h>
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <asm/unistd.h>
+#include <errno.h>
+
+#include <linux/byteorder.h>
+
+#define HPT_ORDER 24
+
+#define HUGETLBFS_PATH "/var/lib/hugetlbfs/global/pagesize-16MB/"
+
+#define PHANDLE_XICP           0x00001111
+
+static char kern_cmdline[2048];
+
+struct kvm_ext kvm_req_ext[] = {
+       { DEFINE_KVM_EXT(KVM_CAP_PPC_UNSET_IRQ) },
+       { DEFINE_KVM_EXT(KVM_CAP_PPC_IRQ_LEVEL) },
+       { 0, 0 }
+};
+
+static uint32_t mfpvr(void)
+{
+       uint32_t r;
+       asm volatile ("mfpvr %0" : "=r"(r));
+       return r;
+}
+
+bool kvm__arch_cpu_supports_vm(void)
+{
+       return true;
+}
+
+void kvm__init_ram(struct kvm *kvm)
+{
+       u64     phys_start, phys_size;
+       void    *host_mem;
+
+       phys_start = 0;
+       phys_size  = kvm->ram_size;
+       host_mem   = kvm->ram_start;
+
+       /*
+        * We put MMIO at PPC_MMIO_START, high up.  Make sure that this doesn't
+        * crash into the end of RAM -- on PPC64 at least, this is so high
+        * (63TB!) that this is unlikely.
+        */
+       if (phys_size >= PPC_MMIO_START)
+               die("Too much memory (%lld, what a nice problem): "
+                   "overlaps MMIO!\n",
+                   phys_size);
+
+       kvm__register_mem(kvm, phys_start, phys_size, host_mem);
+}
+
+void kvm__arch_set_cmdline(char *cmdline, bool video)
+{
+       /* We don't need anything unusual in here. */
+}
+
+/* Architecture-specific KVM init */
+void kvm__arch_init(struct kvm *kvm, const char *hugetlbfs_path, u64 ram_size)
+{
+       int cap_ppc_rma;
+       unsigned long hpt;
+
+       kvm->ram_size           = ram_size;
+
+       /* Map "default" hugetblfs path to the standard 16M mount point */
+       if (hugetlbfs_path && !strcmp(hugetlbfs_path, "default"))
+               hugetlbfs_path = HUGETLBFS_PATH;
+
+       kvm->ram_start = mmap_anon_or_hugetlbfs(kvm, hugetlbfs_path, kvm->ram_size);
+
+       if (kvm->ram_start == MAP_FAILED)
+               die("Couldn't map %lld bytes for RAM (%d)\n",
+                   kvm->ram_size, errno);
+
+       /* FDT goes at top of memory, RTAS just below */
+       kvm->arch.fdt_gra = kvm->ram_size - FDT_MAX_SIZE;
+       /* FIXME: Not all PPC systems have RTAS */
+       kvm->arch.rtas_gra = kvm->arch.fdt_gra - RTAS_MAX_SIZE;
+       madvise(kvm->ram_start, kvm->ram_size, MADV_MERGEABLE);
+
+       /* FIXME:  SPAPR-PR specific; allocate a guest HPT. */
+       if (posix_memalign((void **)&hpt, (1<<HPT_ORDER), (1<<HPT_ORDER)))
+               die("Can't allocate %d bytes for HPT\n", (1<<HPT_ORDER));
+
+       kvm->arch.sdr1 = ((hpt + 0x3ffffULL) & ~0x3ffffULL) | (HPT_ORDER-18);
+
+       kvm->arch.pvr = mfpvr();
+
+       /* FIXME: This is book3s-specific */
+       cap_ppc_rma = ioctl(kvm->sys_fd, KVM_CHECK_EXTENSION, KVM_CAP_PPC_RMA);
+       if (cap_ppc_rma == 2)
+               die("Need contiguous RMA allocation on this hardware, "
+                   "which is not yet supported.");
+
+       /* Do these before FDT setup, IRQ setup, etc. */
+       /* FIXME: SPAPR-specific */
+       hypercall_init();
+       register_core_rtas();
+       /* Now that hypercalls are initialised, register a couple for the console: */
+       spapr_hvcons_init();
+       spapr_create_phb(kvm, "pci", SPAPR_PCI_BUID,
+                        SPAPR_PCI_MEM_WIN_ADDR,
+                        SPAPR_PCI_MEM_WIN_SIZE,
+                        SPAPR_PCI_IO_WIN_ADDR,
+                        SPAPR_PCI_IO_WIN_SIZE);
+}
+
+void kvm__arch_delete_ram(struct kvm *kvm)
+{
+       munmap(kvm->ram_start, kvm->ram_size);
+}
+
+void kvm__irq_trigger(struct kvm *kvm, int irq)
+{
+       kvm__irq_line(kvm, irq, 1);
+       kvm__irq_line(kvm, irq, 0);
+}
+
+void kvm__arch_periodic_poll(struct kvm *kvm)
+{
+       /* FIXME: Should register callbacks to platform-specific polls */
+       spapr_hvcons_poll(kvm);
+}
+
+int load_flat_binary(struct kvm *kvm, int fd_kernel, int fd_initrd, const char *kernel_cmdline)
+{
+       void *p;
+       void *k_start;
+       void *i_start;
+       int nr;
+
+       if (lseek(fd_kernel, 0, SEEK_SET) < 0)
+               die_perror("lseek");
+
+       p = k_start = guest_flat_to_host(kvm, KERNEL_LOAD_ADDR);
+
+       while ((nr = read(fd_kernel, p, 65536)) > 0)
+               p += nr;
+
+       pr_info("Loaded kernel to 0x%x (%ld bytes)", KERNEL_LOAD_ADDR, p-k_start);
+
+       if (fd_initrd != -1) {
+               if (lseek(fd_initrd, 0, SEEK_SET) < 0)
+                       die_perror("lseek");
+
+               if (p-k_start > INITRD_LOAD_ADDR)
+                       die("Kernel overlaps initrd!");
+
+               /* Round up kernel size to 8byte alignment, and load initrd right after. */
+               i_start = p = guest_flat_to_host(kvm, INITRD_LOAD_ADDR);
+
+               while (((nr = read(fd_initrd, p, 65536)) > 0) &&
+                      p < (kvm->ram_start + kvm->ram_size))
+                       p += nr;
+
+               if (p >= (kvm->ram_start + kvm->ram_size))
+                       die("initrd too big to contain in guest RAM.\n");
+
+               pr_info("Loaded initrd to 0x%x (%ld bytes)",
+                       INITRD_LOAD_ADDR, p-i_start);
+               kvm->arch.initrd_gra = INITRD_LOAD_ADDR;
+               kvm->arch.initrd_size = p-i_start;
+       } else {
+               kvm->arch.initrd_size = 0;
+       }
+       strncpy(kern_cmdline, kernel_cmdline, 2048);
+       kern_cmdline[2047] = '\0';
+
+       return true;
+}
+
+bool load_bzimage(struct kvm *kvm, int fd_kernel,
+                 int fd_initrd, const char *kernel_cmdline, u16 vidmode)
+{
+       /* We don't support bzImages. */
+       return false;
+}
+
+struct fdt_prop {
+       void *value;
+       int size;
+};
+
+static void generate_segment_page_sizes(struct kvm_ppc_smmu_info *info, struct fdt_prop *prop)
+{
+       struct kvm_ppc_one_seg_page_size *sps;
+       int i, j, size;
+       u32 *p;
+
+       for (size = 0, i = 0; i < KVM_PPC_PAGE_SIZES_MAX_SZ; i++) {
+               sps = &info->sps[i];
+
+               if (sps->page_shift == 0)
+                       break;
+
+               /* page shift, slb enc & count */
+               size += 3;
+
+               for (j = 0; j < KVM_PPC_PAGE_SIZES_MAX_SZ; j++) {
+                       if (info->sps[i].enc[j].page_shift == 0)
+                               break;
+
+                       /* page shift & pte enc */
+                       size += 2;
+               }
+       }
+
+       if (!size) {
+               prop->value = NULL;
+               prop->size = 0;
+               return;
+       }
+
+       /* Convert size to bytes */
+       prop->size = size * sizeof(u32);
+
+       prop->value = malloc(prop->size);
+       if (!prop->value)
+               die_perror("malloc failed");
+
+       p = (u32 *)prop->value;
+       for (i = 0; i < KVM_PPC_PAGE_SIZES_MAX_SZ; i++) {
+               sps = &info->sps[i];
+
+               if (sps->page_shift == 0)
+                       break;
+
+               *p++ = sps->page_shift;
+               *p++ = sps->slb_enc;
+
+               for (j = 0; j < KVM_PPC_PAGE_SIZES_MAX_SZ; j++)
+                       if (!info->sps[i].enc[j].page_shift)
+                               break;
+
+               *p++ = j;       /* count of enc */
+
+               for (j = 0; j < KVM_PPC_PAGE_SIZES_MAX_SZ; j++) {
+                       if (!info->sps[i].enc[j].page_shift)
+                               break;
+
+                       *p++ = info->sps[i].enc[j].page_shift;
+                       *p++ = info->sps[i].enc[j].pte_enc;
+               }
+       }
+}
+
+#define SMT_THREADS 4
+
+/*
+ * Set up the FDT for the kernel: This function is currently fairly SPAPR-heavy,
+ * and whilst most PPC targets will require CPU/memory nodes, others like RTAS
+ * should eventually be added separately.
+ */
+static int setup_fdt(struct kvm *kvm)
+{
+       uint64_t        mem_reg_property[] = { 0, cpu_to_be64(kvm->ram_size) };
+       int             smp_cpus = kvm->nrcpus;
+       uint32_t        int_server_ranges_prop[] = {0, cpu_to_be32(smp_cpus)};
+       char            hypertas_prop_kvm[] = "hcall-pft\0hcall-term\0"
+               "hcall-dabr\0hcall-interrupt\0hcall-tce\0hcall-vio\0"
+               "hcall-splpar\0hcall-bulk";
+       int             i, j;
+       char            cpu_name[30];
+       u8              staging_fdt[FDT_MAX_SIZE];
+       struct cpu_info *cpu_info = find_cpu_info(kvm);
+       struct fdt_prop segment_page_sizes;
+       u32 segment_sizes_1T[] = {0x1c, 0x28, 0xffffffff, 0xffffffff};
+
+       /* Generate an appropriate DT at kvm->arch.fdt_gra */
+       void *fdt_dest = guest_flat_to_host(kvm, kvm->arch.fdt_gra);
+       void *fdt = staging_fdt;
+
+       _FDT(fdt_create(fdt, FDT_MAX_SIZE));
+       _FDT(fdt_finish_reservemap(fdt));
+
+       _FDT(fdt_begin_node(fdt, ""));
+
+       _FDT(fdt_property_string(fdt, "device_type", "chrp"));
+       _FDT(fdt_property_string(fdt, "model", "IBM pSeries (kvmtool)"));
+       _FDT(fdt_property_cell(fdt, "#address-cells", 0x2));
+       _FDT(fdt_property_cell(fdt, "#size-cells", 0x2));
+
+       /* RTAS */
+       _FDT(fdt_begin_node(fdt, "rtas"));
+       /* This is what the kernel uses to switch 'We're an LPAR'! */
+        _FDT(fdt_property(fdt, "ibm,hypertas-functions", hypertas_prop_kvm,
+                           sizeof(hypertas_prop_kvm)));
+       _FDT(fdt_property_cell(fdt, "linux,rtas-base", kvm->arch.rtas_gra));
+       _FDT(fdt_property_cell(fdt, "linux,rtas-entry", kvm->arch.rtas_gra));
+       _FDT(fdt_property_cell(fdt, "rtas-size", kvm->arch.rtas_size));
+       /* Now add properties for all RTAS tokens: */
+       if (spapr_rtas_fdt_setup(kvm, fdt))
+               die("Couldn't create RTAS FDT properties\n");
+
+       _FDT(fdt_end_node(fdt));
+
+       /* /chosen */
+       _FDT(fdt_begin_node(fdt, "chosen"));
+       /* cmdline */
+       _FDT(fdt_property_string(fdt, "bootargs", kern_cmdline));
+       /* Initrd */
+       if (kvm->arch.initrd_size != 0) {
+               uint32_t ird_st_prop = cpu_to_be32(kvm->arch.initrd_gra);
+               uint32_t ird_end_prop = cpu_to_be32(kvm->arch.initrd_gra +
+                                                   kvm->arch.initrd_size);
+               _FDT(fdt_property(fdt, "linux,initrd-start",
+                                  &ird_st_prop, sizeof(ird_st_prop)));
+               _FDT(fdt_property(fdt, "linux,initrd-end",
+                                  &ird_end_prop, sizeof(ird_end_prop)));
+       }
+
+       /*
+        * stdout-path: This is assuming we're using the HV console.  Also, the
+        * address is hardwired until we do a VIO bus.
+        */
+       _FDT(fdt_property_string(fdt, "linux,stdout-path",
+                                "/vdevice/vty@30000000"));
+       _FDT(fdt_end_node(fdt));
+
+       /*
+        * Memory: We don't alloc. a separate RMA yet.  If we ever need to
+        * (CAP_PPC_RMA == 2) then have one memory node for 0->RMAsize, and
+        * another RMAsize->endOfMem.
+        */
+       _FDT(fdt_begin_node(fdt, "memory@0"));
+       _FDT(fdt_property_string(fdt, "device_type", "memory"));
+       _FDT(fdt_property(fdt, "reg", mem_reg_property,
+                         sizeof(mem_reg_property)));
+       _FDT(fdt_end_node(fdt));
+
+       generate_segment_page_sizes(&cpu_info->mmu_info, &segment_page_sizes);
+
+       /* CPUs */
+       _FDT(fdt_begin_node(fdt, "cpus"));
+       _FDT(fdt_property_cell(fdt, "#address-cells", 0x1));
+       _FDT(fdt_property_cell(fdt, "#size-cells", 0x0));
+
+       for (i = 0; i < smp_cpus; i += SMT_THREADS) {
+               int32_t pft_size_prop[] = { 0, HPT_ORDER };
+               uint32_t servers_prop[SMT_THREADS];
+               uint32_t gservers_prop[SMT_THREADS * 2];
+               int threads = (smp_cpus - i) >= SMT_THREADS ? SMT_THREADS :
+                       smp_cpus - i;
+
+               sprintf(cpu_name, "PowerPC,%s@%d", cpu_info->name, i);
+               _FDT(fdt_begin_node(fdt, cpu_name));
+               sprintf(cpu_name, "PowerPC,%s", cpu_info->name);
+               _FDT(fdt_property_string(fdt, "name", cpu_name));
+               _FDT(fdt_property_string(fdt, "device_type", "cpu"));
+
+               _FDT(fdt_property_cell(fdt, "reg", i));
+               _FDT(fdt_property_cell(fdt, "cpu-version", kvm->arch.pvr));
+
+               _FDT(fdt_property_cell(fdt, "dcache-block-size", cpu_info->d_bsize));
+               _FDT(fdt_property_cell(fdt, "icache-block-size", cpu_info->i_bsize));
+
+               _FDT(fdt_property_cell(fdt, "timebase-frequency", cpu_info->tb_freq));
+               /* Lies, but safeish lies! */
+               _FDT(fdt_property_cell(fdt, "clock-frequency", 0xddbab200));
+
+               if (cpu_info->mmu_info.slb_size)
+                       _FDT(fdt_property_cell(fdt, "ibm,slb-size", cpu_info->mmu_info.slb_size));
+
+               /*
+                * HPT size is hardwired; KVM currently fixes it at 16MB but the
+                * moment that changes we'll need to read it out of the kernel.
+                */
+               _FDT(fdt_property(fdt, "ibm,pft-size", pft_size_prop,
+                                 sizeof(pft_size_prop)));
+
+               _FDT(fdt_property_string(fdt, "status", "okay"));
+               _FDT(fdt_property(fdt, "64-bit", NULL, 0));
+               /* A server for each thread in this core */
+               for (j = 0; j < SMT_THREADS; j++) {
+                       servers_prop[j] = cpu_to_be32(i+j);
+                       /*
+                        * Hack borrowed from QEMU, direct the group queues back
+                        * to cpu 0:
+                        */
+                       gservers_prop[j*2] = cpu_to_be32(i+j);
+                       gservers_prop[j*2 + 1] = 0;
+               }
+               _FDT(fdt_property(fdt, "ibm,ppc-interrupt-server#s",
+                                  servers_prop, threads * sizeof(uint32_t)));
+               _FDT(fdt_property(fdt, "ibm,ppc-interrupt-gserver#s",
+                                 gservers_prop,
+                                 threads * 2 * sizeof(uint32_t)));
+
+               if (segment_page_sizes.value)
+                       _FDT(fdt_property(fdt, "ibm,segment-page-sizes",
+                                         segment_page_sizes.value,
+                                         segment_page_sizes.size));
+
+               if (cpu_info->mmu_info.flags & KVM_PPC_1T_SEGMENTS)
+                       _FDT(fdt_property(fdt, "ibm,processor-segment-sizes",
+                                         segment_sizes_1T, sizeof(segment_sizes_1T)));
+
+               /* VSX / DFP options: */
+               if (cpu_info->flags & CPUINFO_FLAG_VMX)
+                       _FDT(fdt_property_cell(fdt, "ibm,vmx",
+                                              (cpu_info->flags &
+                                               CPUINFO_FLAG_VSX) ? 2 : 1));
+               if (cpu_info->flags & CPUINFO_FLAG_DFP)
+                       _FDT(fdt_property_cell(fdt, "ibm,dfp", 0x1));
+               _FDT(fdt_end_node(fdt));
+       }
+       _FDT(fdt_end_node(fdt));
+
+       /* IRQ controller */
+       _FDT(fdt_begin_node(fdt, "interrupt-controller@0"));
+
+       _FDT(fdt_property_string(fdt, "device_type",
+                                "PowerPC-External-Interrupt-Presentation"));
+       _FDT(fdt_property_string(fdt, "compatible", "IBM,ppc-xicp"));
+       _FDT(fdt_property_cell(fdt, "reg", 0));
+       _FDT(fdt_property(fdt, "interrupt-controller", NULL, 0));
+       _FDT(fdt_property(fdt, "ibm,interrupt-server-ranges",
+                          int_server_ranges_prop,
+                          sizeof(int_server_ranges_prop)));
+       _FDT(fdt_property_cell(fdt, "#interrupt-cells", 2));
+       _FDT(fdt_property_cell(fdt, "linux,phandle", PHANDLE_XICP));
+       _FDT(fdt_property_cell(fdt, "phandle", PHANDLE_XICP));
+       _FDT(fdt_end_node(fdt));
+
+       /*
+        * VIO: See comment in linux,stdout-path; we don't yet represent a VIO
+        * bus/address allocation so addresses are hardwired here.
+        */
+       _FDT(fdt_begin_node(fdt, "vdevice"));
+       _FDT(fdt_property_cell(fdt, "#address-cells", 0x1));
+       _FDT(fdt_property_cell(fdt, "#size-cells", 0x0));
+       _FDT(fdt_property_string(fdt, "device_type", "vdevice"));
+       _FDT(fdt_property_string(fdt, "compatible", "IBM,vdevice"));
+       _FDT(fdt_begin_node(fdt, "vty@30000000"));
+       _FDT(fdt_property_string(fdt, "name", "vty"));
+       _FDT(fdt_property_string(fdt, "device_type", "serial"));
+       _FDT(fdt_property_string(fdt, "compatible", "hvterm1"));
+       _FDT(fdt_property_cell(fdt, "reg", 0x30000000));
+       _FDT(fdt_end_node(fdt));
+       _FDT(fdt_end_node(fdt));
+
+       /* Finalise: */
+       _FDT(fdt_end_node(fdt)); /* Root node */
+       _FDT(fdt_finish(fdt));
+
+       _FDT(fdt_open_into(fdt, fdt_dest, FDT_MAX_SIZE));
+
+       /* PCI */
+       if (spapr_populate_pci_devices(kvm, PHANDLE_XICP, fdt_dest))
+               die("Fail populating PCI device nodes");
+
+       _FDT(fdt_add_mem_rsv(fdt_dest, kvm->arch.rtas_gra, kvm->arch.rtas_size));
+       _FDT(fdt_pack(fdt_dest));
+
+       free(segment_page_sizes.value);
+
+       return 0;
+}
+firmware_init(setup_fdt);
+
+/**
+ * kvm__arch_setup_firmware
+ */
+int kvm__arch_setup_firmware(struct kvm *kvm)
+{
+       /*
+        * Set up RTAS stub.  All it is is a single hypercall:
+        *  0:   7c 64 1b 78     mr      r4,r3
+        *  4:   3c 60 00 00     lis     r3,0
+        *  8:   60 63 f0 00     ori     r3,r3,61440
+        *  c:   44 00 00 22     sc      1
+        * 10:   4e 80 00 20     blr
+        */
+       uint32_t *rtas = guest_flat_to_host(kvm, kvm->arch.rtas_gra);
+
+       rtas[0] = 0x7c641b78;
+       rtas[1] = 0x3c600000;
+       rtas[2] = 0x6063f000;
+       rtas[3] = 0x44000022;
+       rtas[4] = 0x4e800020;
+       kvm->arch.rtas_size = 20;
+
+       pr_info("Set up %ld bytes of RTAS at 0x%lx\n",
+               kvm->arch.rtas_size, kvm->arch.rtas_gra);
+
+       /* Load SLOF */
+
+       return 0;
+}
+
+int kvm__arch_free_firmware(struct kvm *kvm)
+{
+       return 0;
+}
diff --git a/tools/kvm/powerpc/spapr.h b/tools/kvm/powerpc/spapr.h
new file mode 100644 (file)
index 0000000..0537f88
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * SPAPR definitions and declarations
+ *
+ * Borrowed heavily from QEMU's spapr.h,
+ * Copyright (c) 2010 David Gibson, IBM Corporation.
+ *
+ * Modifications by Matt Evans <matt@ozlabs.org>, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#if !defined(__HW_SPAPR_H__)
+#define __HW_SPAPR_H__
+
+#include <inttypes.h>
+
+/* We need some of the H_ hcall defs, but they're __KERNEL__ only. */
+#define __KERNEL__
+#include <asm/hvcall.h>
+#undef __KERNEL__
+
+#include "kvm/kvm.h"
+#include "kvm/kvm-cpu.h"
+
+typedef unsigned long target_ulong;
+typedef uintptr_t target_phys_addr_t;
+
+/*
+ * The hcalls above are standardized in PAPR and implemented by pHyp
+ * as well.
+ *
+ * We also need some hcalls which are specific to qemu / KVM-on-POWER.
+ * So far we just need one for H_RTAS, but in future we'll need more
+ * for extensions like virtio.  We put those into the 0xf000-0xfffc
+ * range which is reserved by PAPR for "platform-specific" hcalls.
+ */
+#define KVMPPC_HCALL_BASE       0xf000
+#define KVMPPC_H_RTAS           (KVMPPC_HCALL_BASE + 0x0)
+#define KVMPPC_HCALL_MAX        KVMPPC_H_RTAS
+
+#define DEBUG_SPAPR_HCALLS
+
+#ifdef DEBUG_SPAPR_HCALLS
+#define hcall_dprintf(fmt, ...) \
+    do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
+#else
+#define hcall_dprintf(fmt, ...) \
+    do { } while (0)
+#endif
+
+typedef target_ulong (*spapr_hcall_fn)(struct kvm_cpu *vcpu,
+                                      target_ulong opcode,
+                                       target_ulong *args);
+
+void hypercall_init(void);
+void register_core_rtas(void);
+
+void spapr_register_hypercall(target_ulong opcode, spapr_hcall_fn fn);
+target_ulong spapr_hypercall(struct kvm_cpu *vcpu, target_ulong opcode,
+                             target_ulong *args);
+
+int spapr_rtas_fdt_setup(struct kvm *kvm, void *fdt);
+
+static inline uint32_t rtas_ld(struct kvm *kvm, target_ulong phys, int n)
+{
+       return *((uint32_t *)guest_flat_to_host(kvm, phys + 4*n));
+}
+
+static inline void rtas_st(struct kvm *kvm, target_ulong phys, int n, uint32_t val)
+{
+       *((uint32_t *)guest_flat_to_host(kvm, phys + 4*n)) = val;
+}
+
+typedef void (*spapr_rtas_fn)(struct kvm_cpu *vcpu, uint32_t token,
+                              uint32_t nargs, target_ulong args,
+                              uint32_t nret, target_ulong rets);
+void spapr_rtas_register(const char *name, spapr_rtas_fn fn);
+target_ulong spapr_rtas_call(struct kvm_cpu *vcpu,
+                             uint32_t token, uint32_t nargs, target_ulong args,
+                             uint32_t nret, target_ulong rets);
+
+#define SPAPR_PCI_BUID          0x800000020000001ULL
+#define SPAPR_PCI_MEM_WIN_ADDR  (KVM_MMIO_START + 0xA0000000)
+#define SPAPR_PCI_MEM_WIN_SIZE  0x20000000
+#define SPAPR_PCI_IO_WIN_ADDR   (SPAPR_PCI_MEM_WIN_ADDR + SPAPR_PCI_MEM_WIN_SIZE)
+#define SPAPR_PCI_IO_WIN_SIZE  0x2000000
+
+#define SPAPR_PCI_WIN_START    SPAPR_PCI_MEM_WIN_ADDR
+#define SPAPR_PCI_WIN_END      (SPAPR_PCI_IO_WIN_ADDR + SPAPR_PCI_IO_WIN_SIZE)
+
+#endif /* !defined (__HW_SPAPR_H__) */
diff --git a/tools/kvm/powerpc/spapr_hcall.c b/tools/kvm/powerpc/spapr_hcall.c
new file mode 100644 (file)
index 0000000..ff1d63a
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * SPAPR hypercalls
+ *
+ * Borrowed heavily from QEMU's spapr_hcall.c,
+ * Copyright (c) 2010 David Gibson, IBM Corporation.
+ *
+ * Copyright (c) 2011 Matt Evans <matt@ozlabs.org>, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#include "spapr.h"
+#include "kvm/util.h"
+#include "kvm/kvm.h"
+#include "kvm/kvm-cpu.h"
+
+#include <stdio.h>
+#include <assert.h>
+
+static spapr_hcall_fn papr_hypercall_table[(MAX_HCALL_OPCODE / 4) + 1];
+static spapr_hcall_fn kvmppc_hypercall_table[KVMPPC_HCALL_MAX -
+                                            KVMPPC_HCALL_BASE + 1];
+
+static target_ulong h_set_dabr(struct kvm_cpu *vcpu, target_ulong opcode, target_ulong *args)
+{
+       /* FIXME:  Implement this for -PR.  (-HV does this in kernel.) */
+       return H_HARDWARE;
+}
+
+static target_ulong h_rtas(struct kvm_cpu *vcpu, target_ulong opcode, target_ulong *args)
+{
+       target_ulong rtas_r3 = args[0];
+       /*
+        * Pointer read from phys mem; these ptrs cannot be MMIO (!) so just
+        * reference guest RAM directly.
+        */
+       uint32_t token, nargs, nret;
+
+       token = rtas_ld(vcpu->kvm, rtas_r3, 0);
+       nargs = rtas_ld(vcpu->kvm, rtas_r3, 1);
+       nret  = rtas_ld(vcpu->kvm, rtas_r3, 2);
+
+       return spapr_rtas_call(vcpu, token, nargs, rtas_r3 + 12,
+                              nret, rtas_r3 + 12 + 4*nargs);
+}
+
+static target_ulong h_logical_load(struct kvm_cpu *vcpu, target_ulong opcode, target_ulong *args)
+{
+       /* SLOF will require these, though kernel doesn't. */
+       die(__PRETTY_FUNCTION__);
+       return H_PARAMETER;
+}
+
+static target_ulong h_logical_store(struct kvm_cpu *vcpu, target_ulong opcode, target_ulong *args)
+{
+       /* SLOF will require these, though kernel doesn't. */
+       die(__PRETTY_FUNCTION__);
+       return H_PARAMETER;
+}
+
+static target_ulong h_logical_icbi(struct kvm_cpu *vcpu, target_ulong opcode, target_ulong *args)
+{
+       /* KVM will trap this in the kernel.  Die if it misses. */
+       die(__PRETTY_FUNCTION__);
+       return H_SUCCESS;
+}
+
+static target_ulong h_logical_dcbf(struct kvm_cpu *vcpu, target_ulong opcode, target_ulong *args)
+{
+       /* KVM will trap this in the kernel.  Die if it misses. */
+       die(__PRETTY_FUNCTION__);
+       return H_SUCCESS;
+}
+
+void spapr_register_hypercall(target_ulong opcode, spapr_hcall_fn fn)
+{
+       spapr_hcall_fn *slot;
+
+       if (opcode <= MAX_HCALL_OPCODE) {
+               assert((opcode & 0x3) == 0);
+
+               slot = &papr_hypercall_table[opcode / 4];
+       } else {
+               assert((opcode >= KVMPPC_HCALL_BASE) &&
+                      (opcode <= KVMPPC_HCALL_MAX));
+
+               slot = &kvmppc_hypercall_table[opcode - KVMPPC_HCALL_BASE];
+       }
+
+       assert(!(*slot) || (fn == *slot));
+       *slot = fn;
+}
+
+target_ulong spapr_hypercall(struct kvm_cpu *vcpu, target_ulong opcode,
+                            target_ulong *args)
+{
+       if ((opcode <= MAX_HCALL_OPCODE)
+           && ((opcode & 0x3) == 0)) {
+               spapr_hcall_fn fn = papr_hypercall_table[opcode / 4];
+
+               if (fn) {
+                       return fn(vcpu, opcode, args);
+               }
+       } else if ((opcode >= KVMPPC_HCALL_BASE) &&
+                  (opcode <= KVMPPC_HCALL_MAX)) {
+               spapr_hcall_fn fn = kvmppc_hypercall_table[opcode -
+                                                          KVMPPC_HCALL_BASE];
+
+               if (fn) {
+                       return fn(vcpu, opcode, args);
+               }
+       }
+
+       hcall_dprintf("Unimplemented hcall 0x%lx\n", opcode);
+       return H_FUNCTION;
+}
+
+void hypercall_init(void)
+{
+       /* hcall-dabr */
+       spapr_register_hypercall(H_SET_DABR, h_set_dabr);
+
+       spapr_register_hypercall(H_LOGICAL_CI_LOAD, h_logical_load);
+       spapr_register_hypercall(H_LOGICAL_CI_STORE, h_logical_store);
+       spapr_register_hypercall(H_LOGICAL_CACHE_LOAD, h_logical_load);
+       spapr_register_hypercall(H_LOGICAL_CACHE_STORE, h_logical_store);
+       spapr_register_hypercall(H_LOGICAL_ICBI, h_logical_icbi);
+       spapr_register_hypercall(H_LOGICAL_DCBF, h_logical_dcbf);
+
+       /* KVM-PPC specific hcalls */
+       spapr_register_hypercall(KVMPPC_H_RTAS, h_rtas);
+}
diff --git a/tools/kvm/powerpc/spapr_hvcons.c b/tools/kvm/powerpc/spapr_hvcons.c
new file mode 100644 (file)
index 0000000..0bdf75b
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * SPAPR HV console
+ *
+ * Borrowed lightly from QEMU's spapr_vty.c, Copyright (c) 2010 David Gibson,
+ * IBM Corporation.
+ *
+ * Copyright (c) 2011 Matt Evans <matt@ozlabs.org>, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#include "kvm/term.h"
+#include "kvm/kvm.h"
+#include "kvm/kvm-cpu.h"
+#include "kvm/util.h"
+#include "spapr.h"
+#include "spapr_hvcons.h"
+
+#include <stdio.h>
+#include <sys/uio.h>
+#include <errno.h>
+
+#include <linux/byteorder.h>
+
+union hv_chario {
+       struct {
+               uint64_t char0_7;
+               uint64_t char8_15;
+       } a;
+       uint8_t buf[16];
+};
+
+static unsigned long h_put_term_char(struct kvm_cpu *vcpu, unsigned long opcode, unsigned long *args)
+{
+       /* To do: Read register from args[0], and check it. */
+       unsigned long len = args[1];
+       union hv_chario data;
+       struct iovec iov;
+
+       if (len > 16) {
+               return H_PARAMETER;
+       }
+       data.a.char0_7 = cpu_to_be64(args[2]);
+       data.a.char8_15 = cpu_to_be64(args[3]);
+
+       iov.iov_base = data.buf;
+       iov.iov_len = len;
+       do {
+               int ret;
+
+               if (vcpu->kvm->cfg.active_console == CONSOLE_HV)
+                       ret = term_putc_iov(&iov, 1, 0);
+               else
+                       ret = 0;
+               if (ret < 0) {
+                       die("term_putc_iov error %d!\n", errno);
+               }
+               iov.iov_base += ret;
+               iov.iov_len -= ret;
+       } while (iov.iov_len > 0);
+
+       return H_SUCCESS;
+}
+
+
+static unsigned long h_get_term_char(struct kvm_cpu *vcpu, unsigned long opcode, unsigned long *args)
+{
+       /* To do: Read register from args[0], and check it. */
+       unsigned long *len = args + 0;
+       unsigned long *char0_7 = args + 1;
+       unsigned long *char8_15 = args + 2;
+       union hv_chario data;
+       struct iovec iov;
+
+       if (vcpu->kvm->cfg.active_console != CONSOLE_HV)
+               return H_SUCCESS;
+
+       if (term_readable(0)) {
+               iov.iov_base = data.buf;
+               iov.iov_len = 16;
+
+               *len = term_getc_iov(vcpu->kvm, &iov, 1, 0);
+               *char0_7 = be64_to_cpu(data.a.char0_7);
+               *char8_15 = be64_to_cpu(data.a.char8_15);
+       } else {
+               *len = 0;
+       }
+
+       return H_SUCCESS;
+}
+
+void spapr_hvcons_poll(struct kvm *kvm)
+{
+       if (term_readable(0)) {
+               /*
+                * We can inject an IRQ to guest here if we want.  The guest
+                * will happily poll, though, so not required.
+                */
+       }
+}
+
+void spapr_hvcons_init(void)
+{
+       spapr_register_hypercall(H_PUT_TERM_CHAR, h_put_term_char);
+       spapr_register_hypercall(H_GET_TERM_CHAR, h_get_term_char);
+}
diff --git a/tools/kvm/powerpc/spapr_hvcons.h b/tools/kvm/powerpc/spapr_hvcons.h
new file mode 100644 (file)
index 0000000..d3e4414
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * SPAPR HV console
+ *
+ * Copyright (c) 2011 Matt Evans <matt@ozlabs.org>, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#ifndef spapr_hvcons_H
+#define spapr_hvcons_H
+
+#include "kvm/kvm.h"
+
+void spapr_hvcons_init(void);
+void spapr_hvcons_poll(struct kvm *kvm);
+
+#endif
diff --git a/tools/kvm/powerpc/spapr_pci.c b/tools/kvm/powerpc/spapr_pci.c
new file mode 100644 (file)
index 0000000..b74790e
--- /dev/null
@@ -0,0 +1,423 @@
+/*
+ * SPAPR PHB emulation, RTAS interface to PCI config space, device tree nodes
+ * for enumerated devices.
+ *
+ * Borrowed heavily from QEMU's spapr_pci.c,
+ * Copyright (c) 2011 Alexey Kardashevskiy, IBM Corporation.
+ * Copyright (c) 2011 David Gibson, IBM Corporation.
+ *
+ * Modifications copyright 2011 Matt Evans <matt@ozlabs.org>, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#include "spapr.h"
+#include "spapr_pci.h"
+#include "kvm/util.h"
+#include "kvm/pci.h"
+#include "libfdt.h"
+
+#include <linux/pci_regs.h>
+#include <linux/byteorder.h>
+
+
+/* #define DEBUG_PHB yes */
+#ifdef DEBUG_PHB
+#define phb_dprintf(fmt, ...)                                  \
+       do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
+#else
+#define phb_dprintf(fmt, ...)                  \
+       do { } while (0)
+#endif
+
+static const uint32_t bars[] = {
+       PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_1,
+       PCI_BASE_ADDRESS_2, PCI_BASE_ADDRESS_3,
+       PCI_BASE_ADDRESS_4, PCI_BASE_ADDRESS_5
+       /*, PCI_ROM_ADDRESS*/
+};
+
+#define PCI_NUM_REGIONS                7
+
+/* Macros to operate with address in OF binding to PCI */
+#define b_x(x, p, l)   (((x) & ((1<<(l))-1)) << (p))
+#define b_n(x)         b_x((x), 31, 1) /* 0 if relocatable */
+#define b_p(x)         b_x((x), 30, 1) /* 1 if prefetchable */
+#define b_t(x)         b_x((x), 29, 1) /* 1 if the address is aliased */
+#define b_ss(x)                b_x((x), 24, 2) /* the space code */
+#define b_bbbbbbbb(x)  b_x((x), 16, 8) /* bus number */
+#define b_ddddd(x)     b_x((x), 11, 5) /* device number */
+#define b_fff(x)       b_x((x), 8, 3)  /* function number */
+#define b_rrrrrrrr(x)  b_x((x), 0, 8)  /* register number */
+
+#define SS_M64         3
+#define SS_M32         2
+#define SS_IO          1
+#define SS_CONFIG      0
+
+
+static struct spapr_phb phb;
+
+
+static void rtas_ibm_read_pci_config(struct kvm_cpu *vcpu,
+                                    uint32_t token, uint32_t nargs,
+                                    target_ulong args,
+                                    uint32_t nret, target_ulong rets)
+{
+       uint32_t val = 0;
+       uint64_t buid = ((uint64_t)rtas_ld(vcpu->kvm, args, 1) << 32) | rtas_ld(vcpu->kvm, args, 2);
+       union pci_config_address addr = { .w = rtas_ld(vcpu->kvm, args, 0) };
+       struct pci_device_header *dev = pci__find_dev(addr.device_number);
+       uint32_t size = rtas_ld(vcpu->kvm, args, 3);
+
+       if (buid != phb.buid || !dev || (size > 4)) {
+               phb_dprintf("- cfgRd buid 0x%lx cfg addr 0x%x size %d not found\n",
+                           buid, addr.w, size);
+
+               rtas_st(vcpu->kvm, rets, 0, -1);
+               return;
+       }
+       pci__config_rd(vcpu->kvm, addr, &val, size);
+       /* It appears this wants a byteswapped result... */
+       switch (size) {
+       case 4:
+               val = le32_to_cpu(val);
+               break;
+       case 2:
+               val = le16_to_cpu(val>>16);
+               break;
+       case 1:
+               val = val >> 24;
+               break;
+       }
+       phb_dprintf("- cfgRd buid 0x%lx addr 0x%x (/%d): b%d,d%d,f%d,r0x%x, val 0x%x\n",
+                   buid, addr.w, size, addr.bus_number, addr.device_number, addr.function_number,
+                   addr.register_number, val);
+
+       rtas_st(vcpu->kvm, rets, 0, 0);
+       rtas_st(vcpu->kvm, rets, 1, val);
+}
+
+static void rtas_read_pci_config(struct kvm_cpu *vcpu,
+                                uint32_t token, uint32_t nargs,
+                                target_ulong args,
+                                uint32_t nret, target_ulong rets)
+{
+       uint32_t val;
+       union pci_config_address addr = { .w = rtas_ld(vcpu->kvm, args, 0) };
+       struct pci_device_header *dev = pci__find_dev(addr.device_number);
+       uint32_t size = rtas_ld(vcpu->kvm, args, 1);
+
+       if (!dev || (size > 4)) {
+               rtas_st(vcpu->kvm, rets, 0, -1);
+               return;
+       }
+       pci__config_rd(vcpu->kvm, addr, &val, size);
+       switch (size) {
+       case 4:
+               val = le32_to_cpu(val);
+               break;
+       case 2:
+               val = le16_to_cpu(val>>16); /* We're yuck-endian. */
+               break;
+       case 1:
+               val = val >> 24;
+               break;
+       }
+       phb_dprintf("- cfgRd addr 0x%x size %d, val 0x%x\n", addr.w, size, val);
+       rtas_st(vcpu->kvm, rets, 0, 0);
+       rtas_st(vcpu->kvm, rets, 1, val);
+}
+
+static void rtas_ibm_write_pci_config(struct kvm_cpu *vcpu,
+                                     uint32_t token, uint32_t nargs,
+                                     target_ulong args,
+                                     uint32_t nret, target_ulong rets)
+{
+       uint64_t buid = ((uint64_t)rtas_ld(vcpu->kvm, args, 1) << 32) | rtas_ld(vcpu->kvm, args, 2);
+       union pci_config_address addr = { .w = rtas_ld(vcpu->kvm, args, 0) };
+       struct pci_device_header *dev = pci__find_dev(addr.device_number);
+       uint32_t size = rtas_ld(vcpu->kvm, args, 3);
+       uint32_t val = rtas_ld(vcpu->kvm, args, 4);
+
+       if (buid != phb.buid || !dev || (size > 4)) {
+               phb_dprintf("- cfgWr buid 0x%lx cfg addr 0x%x/%d error (val 0x%x)\n",
+                           buid, addr.w, size, val);
+
+               rtas_st(vcpu->kvm, rets, 0, -1);
+               return;
+       }
+       phb_dprintf("- cfgWr buid 0x%lx addr 0x%x (/%d): b%d,d%d,f%d,r0x%x, val 0x%x\n",
+                   buid, addr.w, size, addr.bus_number, addr.device_number, addr.function_number,
+                   addr.register_number, val);
+       switch (size) {
+       case 4:
+               val = le32_to_cpu(val);
+               break;
+       case 2:
+               val = le16_to_cpu(val) << 16;
+               break;
+       case 1:
+               val = val >> 24;
+               break;
+       }
+       pci__config_wr(vcpu->kvm, addr, &val, size);
+       rtas_st(vcpu->kvm, rets, 0, 0);
+}
+
+static void rtas_write_pci_config(struct kvm_cpu *vcpu,
+                                 uint32_t token, uint32_t nargs,
+                                 target_ulong args,
+                                 uint32_t nret, target_ulong rets)
+{
+       union pci_config_address addr = { .w = rtas_ld(vcpu->kvm, args, 0) };
+       struct pci_device_header *dev = pci__find_dev(addr.device_number);
+       uint32_t size = rtas_ld(vcpu->kvm, args, 1);
+       uint32_t val = rtas_ld(vcpu->kvm, args, 2);
+
+       if (!dev || (size > 4)) {
+               rtas_st(vcpu->kvm, rets, 0, -1);
+               return;
+       }
+
+       phb_dprintf("- cfgWr addr 0x%x (/%d): b%d,d%d,f%d,r0x%x, val 0x%x\n",
+                   addr.w, size, addr.bus_number, addr.device_number, addr.function_number,
+                   addr.register_number, val);
+       switch (size) {
+       case 4:
+               val = le32_to_cpu(val);
+               break;
+       case 2:
+               val = le16_to_cpu(val) << 16;
+               break;
+       case 1:
+               val = val >> 24;
+               break;
+       }
+       pci__config_wr(vcpu->kvm, addr, &val, size);
+       rtas_st(vcpu->kvm, rets, 0, 0);
+}
+
+void spapr_create_phb(struct kvm *kvm,
+                     const char *busname, uint64_t buid,
+                     uint64_t mem_win_addr, uint64_t mem_win_size,
+                     uint64_t io_win_addr, uint64_t io_win_size)
+{
+       /*
+        * Since kvmtool doesn't really have any concept of buses etc.,
+        * there's nothing to register here.  Just register RTAS.
+        */
+       spapr_rtas_register("read-pci-config", rtas_read_pci_config);
+       spapr_rtas_register("write-pci-config", rtas_write_pci_config);
+       spapr_rtas_register("ibm,read-pci-config", rtas_ibm_read_pci_config);
+       spapr_rtas_register("ibm,write-pci-config", rtas_ibm_write_pci_config);
+
+       phb.buid = buid;
+       phb.mem_addr = mem_win_addr;
+       phb.mem_size = mem_win_size;
+       phb.io_addr  = io_win_addr;
+       phb.io_size  = io_win_size;
+
+       kvm->arch.phb = &phb;
+}
+
+static uint32_t bar_to_ss(unsigned long bar)
+{
+       if ((bar & PCI_BASE_ADDRESS_SPACE) ==
+           PCI_BASE_ADDRESS_SPACE_IO)
+               return SS_IO;
+       else if (bar & PCI_BASE_ADDRESS_MEM_TYPE_64)
+               return SS_M64;
+       else
+               return SS_M32;
+}
+
+static unsigned long bar_to_addr(unsigned long bar)
+{
+       if ((bar & PCI_BASE_ADDRESS_SPACE) ==
+           PCI_BASE_ADDRESS_SPACE_IO)
+               return bar & PCI_BASE_ADDRESS_IO_MASK;
+       else
+               return bar & PCI_BASE_ADDRESS_MEM_MASK;
+}
+
+int spapr_populate_pci_devices(struct kvm *kvm,
+                              uint32_t xics_phandle,
+                              void *fdt)
+{
+       int bus_off, node_off = 0, devid, fn, i, n, devices;
+       char nodename[256];
+       struct {
+               uint32_t hi;
+               uint64_t addr;
+               uint64_t size;
+       } __attribute__((packed)) reg[PCI_NUM_REGIONS + 1],
+                 assigned_addresses[PCI_NUM_REGIONS];
+       uint32_t bus_range[] = { cpu_to_be32(0), cpu_to_be32(0xff) };
+       struct {
+               uint32_t hi;
+               uint64_t child;
+               uint64_t parent;
+               uint64_t size;
+       } __attribute__((packed)) ranges[] = {
+               {
+                       cpu_to_be32(b_ss(1)), cpu_to_be64(0),
+                       cpu_to_be64(phb.io_addr),
+                       cpu_to_be64(phb.io_size),
+               },
+               {
+                       cpu_to_be32(b_ss(2)), cpu_to_be64(0),
+                       cpu_to_be64(phb.mem_addr),
+                       cpu_to_be64(phb.mem_size),
+               },
+       };
+       uint64_t bus_reg[] = { cpu_to_be64(phb.buid), 0 };
+       uint32_t interrupt_map_mask[] = {
+               cpu_to_be32(b_ddddd(-1)|b_fff(-1)), 0x0, 0x0, 0x0};
+       uint32_t interrupt_map[SPAPR_PCI_NUM_LSI][7];
+
+       /* Start populating the FDT */
+       sprintf(nodename, "pci@%" PRIx64, phb.buid);
+       bus_off = fdt_add_subnode(fdt, 0, nodename);
+       if (bus_off < 0) {
+               die("error making bus subnode, %s\n", fdt_strerror(bus_off));
+               return bus_off;
+       }
+
+       /* Write PHB properties */
+       _FDT(fdt_setprop_string(fdt, bus_off, "device_type", "pci"));
+       _FDT(fdt_setprop_string(fdt, bus_off, "compatible", "IBM,Logical_PHB"));
+       _FDT(fdt_setprop_cell(fdt, bus_off, "#address-cells", 0x3));
+       _FDT(fdt_setprop_cell(fdt, bus_off, "#size-cells", 0x2));
+       _FDT(fdt_setprop_cell(fdt, bus_off, "#interrupt-cells", 0x1));
+       _FDT(fdt_setprop(fdt, bus_off, "used-by-rtas", NULL, 0));
+       _FDT(fdt_setprop(fdt, bus_off, "bus-range", &bus_range, sizeof(bus_range)));
+       _FDT(fdt_setprop(fdt, bus_off, "ranges", &ranges, sizeof(ranges)));
+       _FDT(fdt_setprop(fdt, bus_off, "reg", &bus_reg, sizeof(bus_reg)));
+       _FDT(fdt_setprop(fdt, bus_off, "interrupt-map-mask",
+                        &interrupt_map_mask, sizeof(interrupt_map_mask)));
+
+       /* Populate PCI devices and allocate IRQs */
+       devices = 0;
+
+       for (devid = 0; devid < PCI_MAX_DEVICES; devid++) {
+               uint32_t *irqmap = interrupt_map[devices];
+               struct pci_device_header *hdr = pci__find_dev(devid);
+
+               if (!hdr)
+                       continue;
+
+               fn = 0; /* kvmtool doesn't yet do multifunction devices */
+
+               sprintf(nodename, "pci@%u,%u", devid, fn);
+
+               /* Allocate interrupt from the map */
+               if (devid > SPAPR_PCI_NUM_LSI)  {
+                       die("Unexpected behaviour in spapr_populate_pci_devices,"
+                           "wrong devid %u\n", devid);
+               }
+               irqmap[0] = cpu_to_be32(b_ddddd(devid)|b_fff(fn));
+               irqmap[1] = 0;
+               irqmap[2] = 0;
+               irqmap[3] = 0;
+               irqmap[4] = cpu_to_be32(xics_phandle);
+               /*
+                * This is nasty; the PCI devs are set up such that their own
+                * header's irq_line indicates the direct XICS IRQ number to
+                * use.  There REALLY needs to be a hierarchical system in place
+                * to 'raise' an IRQ on the bridge which indexes/looks up which
+                * XICS IRQ to fire.
+                */
+               irqmap[5] = cpu_to_be32(hdr->irq_line);
+               irqmap[6] = cpu_to_be32(0x8);
+
+               /* Add node to FDT */
+               node_off = fdt_add_subnode(fdt, bus_off, nodename);
+               if (node_off < 0) {
+                       die("error making node subnode, %s\n", fdt_strerror(bus_off));
+                       return node_off;
+               }
+
+               _FDT(fdt_setprop_cell(fdt, node_off, "vendor-id",
+                                     le16_to_cpu(hdr->vendor_id)));
+               _FDT(fdt_setprop_cell(fdt, node_off, "device-id",
+                                     le16_to_cpu(hdr->device_id)));
+               _FDT(fdt_setprop_cell(fdt, node_off, "revision-id",
+                                     hdr->revision_id));
+               _FDT(fdt_setprop_cell(fdt, node_off, "class-code",
+                                     hdr->class[0] | (hdr->class[1] << 8) | (hdr->class[2] << 16)));
+               _FDT(fdt_setprop_cell(fdt, node_off, "subsystem-id",
+                                     le16_to_cpu(hdr->subsys_id)));
+               _FDT(fdt_setprop_cell(fdt, node_off, "subsystem-vendor-id",
+                                     le16_to_cpu(hdr->subsys_vendor_id)));
+
+               /* Config space region comes first */
+               reg[0].hi = cpu_to_be32(
+                       b_n(0) |
+                       b_p(0) |
+                       b_t(0) |
+                       b_ss(SS_CONFIG) |
+                       b_bbbbbbbb(0) |
+                       b_ddddd(devid) |
+                       b_fff(fn));
+               reg[0].addr = 0;
+               reg[0].size = 0;
+
+               n = 0;
+               /* Six BARs, no ROM supported, addresses are 32bit */
+               for (i = 0; i < 6; ++i) {
+                       if (0 == hdr->bar[i]) {
+                               continue;
+                       }
+
+                       reg[n+1].hi = cpu_to_be32(
+                               b_n(0) |
+                               b_p(0) |
+                               b_t(0) |
+                               b_ss(bar_to_ss(le32_to_cpu(hdr->bar[i]))) |
+                               b_bbbbbbbb(0) |
+                               b_ddddd(devid) |
+                               b_fff(fn) |
+                               b_rrrrrrrr(bars[i]));
+                       reg[n+1].addr = 0;
+                       reg[n+1].size = cpu_to_be64(hdr->bar_size[i]);
+
+                       assigned_addresses[n].hi = cpu_to_be32(
+                               b_n(1) |
+                               b_p(0) |
+                               b_t(0) |
+                               b_ss(bar_to_ss(le32_to_cpu(hdr->bar[i]))) |
+                               b_bbbbbbbb(0) |
+                               b_ddddd(devid) |
+                               b_fff(fn) |
+                               b_rrrrrrrr(bars[i]));
+
+                       /*
+                        * Writing zeroes to assigned_addresses causes the guest kernel to
+                        * reassign BARs
+                        */
+                       assigned_addresses[n].addr = cpu_to_be64(bar_to_addr(le32_to_cpu(hdr->bar[i])));
+                       assigned_addresses[n].size = reg[n+1].size;
+
+                       ++n;
+               }
+               _FDT(fdt_setprop(fdt, node_off, "reg", reg, sizeof(reg[0])*(n+1)));
+               _FDT(fdt_setprop(fdt, node_off, "assigned-addresses",
+                                assigned_addresses,
+                                sizeof(assigned_addresses[0])*(n)));
+               _FDT(fdt_setprop_cell(fdt, node_off, "interrupts",
+                                     hdr->irq_pin));
+
+               /* We don't set ibm,dma-window property as we don't have an IOMMU. */
+
+               ++devices;
+       }
+
+       /* Write interrupt map */
+       _FDT(fdt_setprop(fdt, bus_off, "interrupt-map", &interrupt_map,
+                        devices * sizeof(interrupt_map[0])));
+
+       return 0;
+}
diff --git a/tools/kvm/powerpc/spapr_pci.h b/tools/kvm/powerpc/spapr_pci.h
new file mode 100644 (file)
index 0000000..48b221c
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * SPAPR PHB definitions
+ *
+ * Modifications by Matt Evans <matt@ozlabs.org>, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#ifndef SPAPR_PCI_H
+#define SPAPR_PCI_H
+
+#include "kvm/kvm.h"
+#include "spapr.h"
+#include <inttypes.h>
+
+/* With XICS, we can easily accomodate 1 IRQ per PCI device. */
+
+#define SPAPR_PCI_NUM_LSI 256
+
+struct spapr_phb {
+       uint64_t buid;
+       uint64_t mem_addr;
+       uint64_t mem_size;
+       uint64_t io_addr;
+       uint64_t io_size;
+};
+
+void spapr_create_phb(struct kvm *kvm,
+                      const char *busname, uint64_t buid,
+                      uint64_t mem_win_addr, uint64_t mem_win_size,
+                      uint64_t io_win_addr, uint64_t io_win_size);
+
+int spapr_populate_pci_devices(struct kvm *kvm,
+                               uint32_t xics_phandle,
+                               void *fdt);
+
+static inline bool spapr_phb_mmio(struct kvm *kvm, u64 phys_addr, u8 *data, u32 len, u8 is_write)
+{
+       if ((phys_addr >= SPAPR_PCI_IO_WIN_ADDR) &&
+           (phys_addr < SPAPR_PCI_IO_WIN_ADDR +
+            SPAPR_PCI_IO_WIN_SIZE)) {
+               return kvm__emulate_io(kvm, phys_addr - SPAPR_PCI_IO_WIN_ADDR,
+                                      data, is_write ? KVM_EXIT_IO_OUT :
+                                      KVM_EXIT_IO_IN,
+                                      len, 1);
+       } else if ((phys_addr >= SPAPR_PCI_MEM_WIN_ADDR) &&
+                  (phys_addr < SPAPR_PCI_MEM_WIN_ADDR +
+                   SPAPR_PCI_MEM_WIN_SIZE)) {
+               return kvm__emulate_mmio(kvm, phys_addr - SPAPR_PCI_MEM_WIN_ADDR,
+                                        data, len, is_write);
+       }
+       return false;
+}
+
+#endif
diff --git a/tools/kvm/powerpc/spapr_rtas.c b/tools/kvm/powerpc/spapr_rtas.c
new file mode 100644 (file)
index 0000000..c81d82b
--- /dev/null
@@ -0,0 +1,233 @@
+/*
+ * SPAPR base RTAS calls
+ *
+ * Borrowed heavily from QEMU's spapr_rtas.c
+ * Copyright (c) 2010-2011 David Gibson, IBM Corporation.
+ *
+ * Modifications copyright 2011 Matt Evans <matt@ozlabs.org>, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#include "kvm/kvm.h"
+#include "kvm/kvm-cpu.h"
+#include "kvm/util.h"
+#include "kvm/term.h"
+#include "libfdt.h"
+
+#include "spapr.h"
+
+#include <stdio.h>
+#include <assert.h>
+
+#define TOKEN_BASE      0x2000
+#define TOKEN_MAX       0x100
+
+#define RTAS_CONSOLE
+
+static struct rtas_call {
+       const char *name;
+       spapr_rtas_fn fn;
+} rtas_table[TOKEN_MAX];
+
+struct rtas_call *rtas_next = rtas_table;
+
+
+static void rtas_display_character(struct kvm_cpu *vcpu,
+                                   uint32_t token, uint32_t nargs,
+                                   target_ulong args,
+                                   uint32_t nret, target_ulong rets)
+{
+       char c = rtas_ld(vcpu->kvm, args, 0);
+       term_putc(&c, 1, 0);
+       rtas_st(vcpu->kvm, rets, 0, 0);
+}
+
+#ifdef RTAS_CONSOLE
+static void rtas_put_term_char(struct kvm_cpu *vcpu,
+                              uint32_t token, uint32_t nargs,
+                              target_ulong args,
+                              uint32_t nret, target_ulong rets)
+{
+       char c = rtas_ld(vcpu->kvm, args, 0);
+
+       if (vcpu->kvm->cfg.active_console == CONSOLE_HV)
+               term_putc(&c, 1, 0);
+
+       rtas_st(vcpu->kvm, rets, 0, 0);
+}
+
+static void rtas_get_term_char(struct kvm_cpu *vcpu,
+                              uint32_t token, uint32_t nargs,
+                              target_ulong args,
+                              uint32_t nret, target_ulong rets)
+{
+       int c;
+
+       if (vcpu->kvm->cfg.active_console == CONSOLE_HV && term_readable(0) &&
+           (c = term_getc(vcpu->kvm, 0)) >= 0) {
+               rtas_st(vcpu->kvm, rets, 0, 0);
+               rtas_st(vcpu->kvm, rets, 1, c);
+       } else {
+               rtas_st(vcpu->kvm, rets, 0, -2);
+       }
+}
+#endif
+
+static void rtas_get_time_of_day(struct kvm_cpu *vcpu,
+                                 uint32_t token, uint32_t nargs,
+                                 target_ulong args,
+                                 uint32_t nret, target_ulong rets)
+{
+       struct tm tm;
+       time_t tnow;
+
+       if (nret != 8) {
+               rtas_st(vcpu->kvm, rets, 0, -3);
+               return;
+       }
+
+       tnow = time(NULL);
+       /* Guest time is currently not offset in any way. */
+       gmtime_r(&tnow, &tm);
+
+       rtas_st(vcpu->kvm, rets, 0, 0); /* Success */
+       rtas_st(vcpu->kvm, rets, 1, tm.tm_year + 1900);
+       rtas_st(vcpu->kvm, rets, 2, tm.tm_mon + 1);
+       rtas_st(vcpu->kvm, rets, 3, tm.tm_mday);
+       rtas_st(vcpu->kvm, rets, 4, tm.tm_hour);
+       rtas_st(vcpu->kvm, rets, 5, tm.tm_min);
+       rtas_st(vcpu->kvm, rets, 6, tm.tm_sec);
+       rtas_st(vcpu->kvm, rets, 7, 0);
+}
+
+static void rtas_set_time_of_day(struct kvm_cpu *vcpu,
+                                 uint32_t token, uint32_t nargs,
+                                 target_ulong args,
+                                 uint32_t nret, target_ulong rets)
+{
+       pr_warning("%s called; TOD set ignored.\n", __FUNCTION__);
+}
+
+static void rtas_power_off(struct kvm_cpu *vcpu,
+                           uint32_t token, uint32_t nargs, target_ulong args,
+                           uint32_t nret, target_ulong rets)
+{
+       if (nargs != 2 || nret != 1) {
+               rtas_st(vcpu->kvm, rets, 0, -3);
+               return;
+       }
+       kvm_cpu__reboot(vcpu->kvm);
+}
+
+static void rtas_query_cpu_stopped_state(struct kvm_cpu *vcpu,
+                                         uint32_t token, uint32_t nargs,
+                                         target_ulong args,
+                                         uint32_t nret, target_ulong rets)
+{
+       if (nargs != 1 || nret != 2) {
+               rtas_st(vcpu->kvm, rets, 0, -3);
+               return;
+       }
+
+       /*
+        * Can read id = rtas_ld(vcpu->kvm, args, 0), but
+        * we currently start all CPUs.  So just return true.
+        */
+       rtas_st(vcpu->kvm, rets, 0, 0);
+       rtas_st(vcpu->kvm, rets, 1, 2);
+}
+
+static void rtas_start_cpu(struct kvm_cpu *vcpu,
+                           uint32_t token, uint32_t nargs,
+                           target_ulong args,
+                           uint32_t nret, target_ulong rets)
+{
+       die(__FUNCTION__);
+}
+
+target_ulong spapr_rtas_call(struct kvm_cpu *vcpu,
+                             uint32_t token, uint32_t nargs, target_ulong args,
+                             uint32_t nret, target_ulong rets)
+{
+       if ((token >= TOKEN_BASE)
+           && ((token - TOKEN_BASE) < TOKEN_MAX)) {
+               struct rtas_call *call = rtas_table + (token - TOKEN_BASE);
+
+               if (call->fn) {
+                       call->fn(vcpu, token, nargs, args, nret, rets);
+                       return H_SUCCESS;
+               }
+       }
+
+       /*
+        * HACK: Some Linux early debug code uses RTAS display-character,
+        * but assumes the token value is 0xa (which it is on some real
+        * machines) without looking it up in the device tree.  This
+        * special case makes this work
+        */
+       if (token == 0xa) {
+               rtas_display_character(vcpu, 0xa, nargs, args, nret, rets);
+               return H_SUCCESS;
+       }
+
+       hcall_dprintf("Unknown RTAS token 0x%x\n", token);
+       rtas_st(vcpu->kvm, rets, 0, -3);
+       return H_PARAMETER;
+}
+
+void spapr_rtas_register(const char *name, spapr_rtas_fn fn)
+{
+       assert(rtas_next < (rtas_table + TOKEN_MAX));
+
+       rtas_next->name = name;
+       rtas_next->fn = fn;
+
+       rtas_next++;
+}
+
+/*
+ * This is called from the context of an open /rtas node, in order to add
+ * properties for the rtas call tokens.
+ */
+int spapr_rtas_fdt_setup(struct kvm *kvm, void *fdt)
+{
+       int ret;
+       int i;
+
+       for (i = 0; i < TOKEN_MAX; i++) {
+               struct rtas_call *call = &rtas_table[i];
+
+               if (!call->fn) {
+                       continue;
+               }
+
+               ret = fdt_property_cell(fdt, call->name, i + TOKEN_BASE);
+
+               if (ret < 0) {
+                       pr_warning("Couldn't add rtas token for %s: %s\n",
+                                  call->name, fdt_strerror(ret));
+                       return ret;
+               }
+
+       }
+       return 0;
+}
+
+void register_core_rtas(void)
+{
+       spapr_rtas_register("display-character", rtas_display_character);
+       spapr_rtas_register("get-time-of-day", rtas_get_time_of_day);
+       spapr_rtas_register("set-time-of-day", rtas_set_time_of_day);
+       spapr_rtas_register("power-off", rtas_power_off);
+       spapr_rtas_register("query-cpu-stopped-state",
+                           rtas_query_cpu_stopped_state);
+       spapr_rtas_register("start-cpu", rtas_start_cpu);
+#ifdef RTAS_CONSOLE
+       /* These are unused: We do console I/O via hcalls, not rtas. */
+       spapr_rtas_register("put-term-char", rtas_put_term_char);
+       spapr_rtas_register("get-term-char", rtas_get_term_char);
+#endif
+}
diff --git a/tools/kvm/powerpc/xics.c b/tools/kvm/powerpc/xics.c
new file mode 100644 (file)
index 0000000..d4b5caa
--- /dev/null
@@ -0,0 +1,522 @@
+/*
+ * PAPR Virtualized Interrupt System, aka ICS/ICP aka xics
+ *
+ * Borrowed heavily from QEMU's xics.c,
+ * Copyright (c) 2010,2011 David Gibson, IBM Corporation.
+ *
+ * Modifications copyright 2011 Matt Evans <matt@ozlabs.org>, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#include "spapr.h"
+#include "xics.h"
+#include "kvm/util.h"
+
+#include <stdio.h>
+#include <malloc.h>
+
+#define XICS_NUM_IRQS  1024
+
+
+/* #define DEBUG_XICS yes */
+#ifdef DEBUG_XICS
+#define xics_dprintf(fmt, ...)                                 \
+       do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
+#else
+#define xics_dprintf(fmt, ...)                 \
+       do { } while (0)
+#endif
+
+/*
+ * ICP: Presentation layer
+ */
+
+struct icp_server_state {
+       uint32_t xirr;
+       uint8_t pending_priority;
+       uint8_t mfrr;
+       struct kvm_cpu *cpu;
+};
+
+#define XICS_IRQ_OFFSET 16
+#define XISR_MASK      0x00ffffff
+#define CPPR_MASK      0xff000000
+
+#define XISR(ss)   (((ss)->xirr) & XISR_MASK)
+#define CPPR(ss)   (((ss)->xirr) >> 24)
+
+struct ics_state;
+
+struct icp_state {
+       unsigned long nr_servers;
+       struct icp_server_state *ss;
+       struct ics_state *ics;
+};
+
+static void ics_reject(struct ics_state *ics, int nr);
+static void ics_resend(struct ics_state *ics);
+static void ics_eoi(struct ics_state *ics, int nr);
+
+static inline void cpu_irq_raise(struct kvm_cpu *vcpu)
+{
+       xics_dprintf("INT1[%p]\n", vcpu);
+       kvm_cpu__irq(vcpu, POWER7_EXT_IRQ, 1);
+}
+
+static inline void cpu_irq_lower(struct kvm_cpu *vcpu)
+{
+       xics_dprintf("INT0[%p]\n", vcpu);
+       kvm_cpu__irq(vcpu, POWER7_EXT_IRQ, 0);
+}
+
+static void icp_check_ipi(struct icp_state *icp, int server)
+{
+       struct icp_server_state *ss = icp->ss + server;
+
+       if (XISR(ss) && (ss->pending_priority <= ss->mfrr)) {
+               return;
+       }
+
+       if (XISR(ss)) {
+               ics_reject(icp->ics, XISR(ss));
+       }
+
+       ss->xirr = (ss->xirr & ~XISR_MASK) | XICS_IPI;
+       ss->pending_priority = ss->mfrr;
+       cpu_irq_raise(ss->cpu);
+}
+
+static void icp_resend(struct icp_state *icp, int server)
+{
+       struct icp_server_state *ss = icp->ss + server;
+
+       if (ss->mfrr < CPPR(ss)) {
+               icp_check_ipi(icp, server);
+       }
+       ics_resend(icp->ics);
+}
+
+static void icp_set_cppr(struct icp_state *icp, int server, uint8_t cppr)
+{
+       struct icp_server_state *ss = icp->ss + server;
+       uint8_t old_cppr;
+       uint32_t old_xisr;
+
+       old_cppr = CPPR(ss);
+       ss->xirr = (ss->xirr & ~CPPR_MASK) | (cppr << 24);
+
+       if (cppr < old_cppr) {
+               if (XISR(ss) && (cppr <= ss->pending_priority)) {
+                       old_xisr = XISR(ss);
+                       ss->xirr &= ~XISR_MASK; /* Clear XISR */
+                       cpu_irq_lower(ss->cpu);
+                       ics_reject(icp->ics, old_xisr);
+               }
+       } else {
+               if (!XISR(ss)) {
+                       icp_resend(icp, server);
+               }
+       }
+}
+
+static void icp_set_mfrr(struct icp_state *icp, int nr, uint8_t mfrr)
+{
+       struct icp_server_state *ss = icp->ss + nr;
+
+       ss->mfrr = mfrr;
+       if (mfrr < CPPR(ss)) {
+               icp_check_ipi(icp, nr);
+       }
+}
+
+static uint32_t icp_accept(struct icp_server_state *ss)
+{
+       uint32_t xirr;
+
+       cpu_irq_lower(ss->cpu);
+       xirr = ss->xirr;
+       ss->xirr = ss->pending_priority << 24;
+       return xirr;
+}
+
+static void icp_eoi(struct icp_state *icp, int server, uint32_t xirr)
+{
+       struct icp_server_state *ss = icp->ss + server;
+
+       ics_eoi(icp->ics, xirr & XISR_MASK);
+       /* Send EOI -> ICS */
+       ss->xirr = (ss->xirr & ~CPPR_MASK) | (xirr & CPPR_MASK);
+       if (!XISR(ss)) {
+               icp_resend(icp, server);
+       }
+}
+
+static void icp_irq(struct icp_state *icp, int server, int nr, uint8_t priority)
+{
+       struct icp_server_state *ss = icp->ss + server;
+       xics_dprintf("icp_irq(nr %d, server %d, prio 0x%x)\n", nr, server, priority);
+       if ((priority >= CPPR(ss))
+           || (XISR(ss) && (ss->pending_priority <= priority))) {
+               xics_dprintf("reject %d, CPPR 0x%x, XISR 0x%x, pprio 0x%x, prio 0x%x\n",
+                            nr, CPPR(ss), XISR(ss), ss->pending_priority, priority);
+               ics_reject(icp->ics, nr);
+       } else {
+               if (XISR(ss)) {
+                       xics_dprintf("reject %d, CPPR 0x%x, XISR 0x%x, pprio 0x%x, prio 0x%x\n",
+                                    nr, CPPR(ss), XISR(ss), ss->pending_priority, priority);
+                       ics_reject(icp->ics, XISR(ss));
+               }
+               ss->xirr = (ss->xirr & ~XISR_MASK) | (nr & XISR_MASK);
+               ss->pending_priority = priority;
+               cpu_irq_raise(ss->cpu);
+       }
+}
+
+/*
+ * ICS: Source layer
+ */
+
+struct ics_irq_state {
+       int server;
+       uint8_t priority;
+       uint8_t saved_priority;
+       int rejected:1;
+       int masked_pending:1;
+};
+
+struct ics_state {
+       unsigned int nr_irqs;
+       unsigned int offset;
+       struct ics_irq_state *irqs;
+       struct icp_state *icp;
+};
+
+static int ics_valid_irq(struct ics_state *ics, uint32_t nr)
+{
+       return (nr >= ics->offset)
+               && (nr < (ics->offset + ics->nr_irqs));
+}
+
+static void ics_set_irq_msi(struct ics_state *ics, int srcno, int val)
+{
+       struct ics_irq_state *irq = ics->irqs + srcno;
+
+       if (val) {
+               if (irq->priority == 0xff) {
+                       xics_dprintf(" irq pri ff, masked pending\n");
+                       irq->masked_pending = 1;
+               } else  {
+                       icp_irq(ics->icp, irq->server, srcno + ics->offset, irq->priority);
+               }
+       }
+}
+
+static void ics_reject_msi(struct ics_state *ics, int nr)
+{
+       struct ics_irq_state *irq = ics->irqs + nr - ics->offset;
+
+       irq->rejected = 1;
+}
+
+static void ics_resend_msi(struct ics_state *ics)
+{
+       unsigned int i;
+
+       for (i = 0; i < ics->nr_irqs; i++) {
+               struct ics_irq_state *irq = ics->irqs + i;
+
+               /* FIXME: filter by server#? */
+               if (irq->rejected) {
+                       irq->rejected = 0;
+                       if (irq->priority != 0xff) {
+                               icp_irq(ics->icp, irq->server, i + ics->offset, irq->priority);
+                       }
+               }
+       }
+}
+
+static void ics_write_xive_msi(struct ics_state *ics, int nr, int server,
+                              uint8_t priority)
+{
+       struct ics_irq_state *irq = ics->irqs + nr - ics->offset;
+
+       irq->server = server;
+       irq->priority = priority;
+       xics_dprintf("ics_write_xive_msi(nr %d, server %d, pri 0x%x)\n", nr, server, priority);
+
+       if (!irq->masked_pending || (priority == 0xff)) {
+               return;
+       }
+
+       irq->masked_pending = 0;
+       icp_irq(ics->icp, server, nr, priority);
+}
+
+static void ics_reject(struct ics_state *ics, int nr)
+{
+       ics_reject_msi(ics, nr);
+}
+
+static void ics_resend(struct ics_state *ics)
+{
+       ics_resend_msi(ics);
+}
+
+static void ics_eoi(struct ics_state *ics, int nr)
+{
+}
+
+/*
+ * Exported functions
+ */
+
+static int allocated_irqnum = XICS_IRQ_OFFSET;
+
+/*
+ * xics_alloc_irqnum(): This is hacky.  The problem boils down to the PCI device
+ * code which just calls kvm__irq_line( .. pcidev->pci_hdr.irq_line ..) at will.
+ * Each PCI device's IRQ line is allocated by irq__register_device() (which
+ * allocates an IRQ AND allocates a.. PCI device num..).
+ *
+ * In future I'd like to at least mimic some kind of 'upstream IRQ controller'
+ * whereby PCI devices let their PHB know when they want to IRQ, and that
+ * percolates up.
+ *
+ * For now, allocate a REAL xics irq number and (via irq__register_device) push
+ * that into the config space. 8 bits only though!
+ */
+int xics_alloc_irqnum(void)
+{
+       int irq = allocated_irqnum++;
+
+       if (irq > 255)
+               die("Huge numbers of IRQs aren't supported with the daft kvmtool IRQ system.");
+
+       return irq;
+}
+
+static target_ulong h_cppr(struct kvm_cpu *vcpu,
+                          target_ulong opcode, target_ulong *args)
+{
+       target_ulong cppr = args[0];
+
+       xics_dprintf("h_cppr(%lx)\n", cppr);
+       icp_set_cppr(vcpu->kvm->arch.icp, vcpu->cpu_id, cppr);
+       return H_SUCCESS;
+}
+
+static target_ulong h_ipi(struct kvm_cpu *vcpu,
+                         target_ulong opcode, target_ulong *args)
+{
+       target_ulong server = args[0];
+       target_ulong mfrr = args[1];
+
+       xics_dprintf("h_ipi(%lx, %lx)\n", server, mfrr);
+       if (server >= vcpu->kvm->arch.icp->nr_servers) {
+               return H_PARAMETER;
+       }
+
+       icp_set_mfrr(vcpu->kvm->arch.icp, server, mfrr);
+       return H_SUCCESS;
+}
+
+static target_ulong h_xirr(struct kvm_cpu *vcpu,
+                          target_ulong opcode, target_ulong *args)
+{
+       uint32_t xirr = icp_accept(vcpu->kvm->arch.icp->ss + vcpu->cpu_id);
+
+       xics_dprintf("h_xirr() = %x\n", xirr);
+       args[0] = xirr;
+       return H_SUCCESS;
+}
+
+static target_ulong h_eoi(struct kvm_cpu *vcpu,
+                         target_ulong opcode, target_ulong *args)
+{
+       target_ulong xirr = args[0];
+
+       xics_dprintf("h_eoi(%lx)\n", xirr);
+       icp_eoi(vcpu->kvm->arch.icp, vcpu->cpu_id, xirr);
+       return H_SUCCESS;
+}
+
+static void rtas_set_xive(struct kvm_cpu *vcpu, uint32_t token,
+                         uint32_t nargs, target_ulong args,
+                         uint32_t nret, target_ulong rets)
+{
+       struct ics_state *ics = vcpu->kvm->arch.icp->ics;
+       uint32_t nr, server, priority;
+
+       if ((nargs != 3) || (nret != 1)) {
+               rtas_st(vcpu->kvm, rets, 0, -3);
+               return;
+       }
+
+       nr = rtas_ld(vcpu->kvm, args, 0);
+       server = rtas_ld(vcpu->kvm, args, 1);
+       priority = rtas_ld(vcpu->kvm, args, 2);
+
+       xics_dprintf("rtas_set_xive(%x,%x,%x)\n", nr, server, priority);
+       if (!ics_valid_irq(ics, nr) || (server >= ics->icp->nr_servers)
+           || (priority > 0xff)) {
+               rtas_st(vcpu->kvm, rets, 0, -3);
+               return;
+       }
+
+       ics_write_xive_msi(ics, nr, server, priority);
+
+       rtas_st(vcpu->kvm, rets, 0, 0); /* Success */
+}
+
+static void rtas_get_xive(struct kvm_cpu *vcpu, uint32_t token,
+                         uint32_t nargs, target_ulong args,
+                         uint32_t nret, target_ulong rets)
+{
+       struct ics_state *ics = vcpu->kvm->arch.icp->ics;
+       uint32_t nr;
+
+       if ((nargs != 1) || (nret != 3)) {
+               rtas_st(vcpu->kvm, rets, 0, -3);
+               return;
+       }
+
+       nr = rtas_ld(vcpu->kvm, args, 0);
+
+       if (!ics_valid_irq(ics, nr)) {
+               rtas_st(vcpu->kvm, rets, 0, -3);
+               return;
+       }
+
+       rtas_st(vcpu->kvm, rets, 0, 0); /* Success */
+       rtas_st(vcpu->kvm, rets, 1, ics->irqs[nr - ics->offset].server);
+       rtas_st(vcpu->kvm, rets, 2, ics->irqs[nr - ics->offset].priority);
+}
+
+static void rtas_int_off(struct kvm_cpu *vcpu, uint32_t token,
+                        uint32_t nargs, target_ulong args,
+                        uint32_t nret, target_ulong rets)
+{
+       struct ics_state *ics = vcpu->kvm->arch.icp->ics;
+       uint32_t nr;
+
+       if ((nargs != 1) || (nret != 1)) {
+               rtas_st(vcpu->kvm, rets, 0, -3);
+               return;
+       }
+
+       nr = rtas_ld(vcpu->kvm, args, 0);
+
+       if (!ics_valid_irq(ics, nr)) {
+               rtas_st(vcpu->kvm, rets, 0, -3);
+               return;
+       }
+
+       /* ME: QEMU wrote xive_msi here, in #if 0.  Deleted. */
+
+       rtas_st(vcpu->kvm, rets, 0, 0); /* Success */
+}
+
+static void rtas_int_on(struct kvm_cpu *vcpu, uint32_t token,
+                       uint32_t nargs, target_ulong args,
+                       uint32_t nret, target_ulong rets)
+{
+       struct ics_state *ics = vcpu->kvm->arch.icp->ics;
+       uint32_t nr;
+
+       if ((nargs != 1) || (nret != 1)) {
+               rtas_st(vcpu->kvm, rets, 0, -3);
+               return;
+       }
+
+       nr = rtas_ld(vcpu->kvm, args, 0);
+
+       if (!ics_valid_irq(ics, nr)) {
+               rtas_st(vcpu->kvm, rets, 0, -3);
+               return;
+       }
+
+       /* ME: QEMU wrote xive_msi here, in #if 0.  Deleted. */
+
+       rtas_st(vcpu->kvm, rets, 0, 0); /* Success */
+}
+
+static int xics_init(struct kvm *kvm)
+{
+       int max_server_num;
+       unsigned int i;
+       struct icp_state *icp;
+       struct ics_state *ics;
+       int j;
+
+       max_server_num = kvm->nrcpus;
+
+       icp = malloc(sizeof(*icp));
+       icp->nr_servers = max_server_num + 1;
+       icp->ss = malloc(icp->nr_servers * sizeof(struct icp_server_state));
+
+       for (i = 0; i < icp->nr_servers; i++) {
+               icp->ss[i].xirr = 0;
+               icp->ss[i].pending_priority = 0;
+               icp->ss[i].cpu = 0;
+               icp->ss[i].mfrr = 0xff;
+       }
+
+       /*
+        * icp->ss[env->cpu_index].cpu is set by CPUs calling in to
+        * xics_cpu_register().
+        */
+
+       ics = malloc(sizeof(*ics));
+       ics->nr_irqs = XICS_NUM_IRQS;
+       ics->offset = XICS_IRQ_OFFSET;
+       ics->irqs = malloc(ics->nr_irqs * sizeof(struct ics_irq_state));
+
+       icp->ics = ics;
+       ics->icp = icp;
+
+       for (i = 0; i < ics->nr_irqs; i++) {
+               ics->irqs[i].server = 0;
+               ics->irqs[i].priority = 0xff;
+               ics->irqs[i].saved_priority = 0xff;
+               ics->irqs[i].rejected = 0;
+               ics->irqs[i].masked_pending = 0;
+       }
+
+       spapr_register_hypercall(H_CPPR, h_cppr);
+       spapr_register_hypercall(H_IPI, h_ipi);
+       spapr_register_hypercall(H_XIRR, h_xirr);
+       spapr_register_hypercall(H_EOI, h_eoi);
+
+       spapr_rtas_register("ibm,set-xive", rtas_set_xive);
+       spapr_rtas_register("ibm,get-xive", rtas_get_xive);
+       spapr_rtas_register("ibm,int-off", rtas_int_off);
+       spapr_rtas_register("ibm,int-on", rtas_int_on);
+
+       for (j = 0; j < kvm->nrcpus; j++) {
+               struct kvm_cpu *vcpu = kvm->cpus[j];
+
+               if (vcpu->cpu_id >= icp->nr_servers)
+                       die("Invalid server number for cpuid %ld\n", vcpu->cpu_id);
+
+               icp->ss[vcpu->cpu_id].cpu = vcpu;
+       }
+
+       kvm->arch.icp = icp;
+
+       return 0;
+}
+base_init(xics_init);
+
+
+void kvm__irq_line(struct kvm *kvm, int irq, int level)
+{
+       /*
+        * Route event to ICS, which routes to ICP, which eventually does a
+        * kvm_cpu__irq(vcpu, POWER7_EXT_IRQ, 1)
+        */
+       xics_dprintf("Raising IRQ %d -> %d\n", irq, level);
+       ics_set_irq_msi(kvm->arch.icp->ics, irq - kvm->arch.icp->ics->offset, level);
+}
diff --git a/tools/kvm/powerpc/xics.h b/tools/kvm/powerpc/xics.h
new file mode 100644 (file)
index 0000000..d5bc6f9
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * PAPR Virtualized Interrupt System, aka ICS/ICP aka xics
+ *
+ * Copyright 2011 Matt Evans <matt@ozlabs.org>, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#ifndef XICS_H
+#define XICS_H
+
+#define XICS_IPI        0x2
+
+int xics_alloc_irqnum(void);
+
+#endif
diff --git a/tools/kvm/symbol.c b/tools/kvm/symbol.c
new file mode 100644 (file)
index 0000000..07dd9d5
--- /dev/null
@@ -0,0 +1,133 @@
+#include "kvm/symbol.h"
+
+#include "kvm/kvm.h"
+
+#include <linux/err.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <bfd.h>
+
+static bfd *abfd;
+
+int symbol_init(struct kvm *kvm)
+{
+       int ret = 0;
+
+       if (!kvm->vmlinux)
+               return 0;
+
+       bfd_init();
+
+       abfd = bfd_openr(kvm->vmlinux, NULL);
+       if (abfd == NULL) {
+               bfd_error_type err = bfd_get_error();
+
+               switch (err) {
+               case bfd_error_no_memory:
+                       ret = -ENOMEM;
+                       break;
+               case bfd_error_invalid_target:
+                       ret = -EINVAL;
+                       break;
+               default:
+                       ret = -EFAULT;
+                       break;
+               }
+       }
+
+       return ret;
+}
+late_init(symbol_init);
+
+static asymbol *lookup(asymbol **symbols, int nr_symbols, const char *symbol_name)
+{
+       int i, ret;
+
+       ret = -ENOENT;
+
+       for (i = 0; i < nr_symbols; i++) {
+               asymbol *symbol = symbols[i];
+
+               if (!strcmp(bfd_asymbol_name(symbol), symbol_name))
+                       return symbol;
+       }
+
+       return ERR_PTR(ret);
+}
+
+char *symbol_lookup(struct kvm *kvm, unsigned long addr, char *sym, size_t size)
+{
+       const char *filename;
+       bfd_vma sym_offset;
+       bfd_vma sym_start;
+       asection *section;
+       unsigned int line;
+       const char *func;
+       long symtab_size;
+       asymbol *symbol;
+       asymbol **syms;
+       int nr_syms, ret;
+
+       ret = -ENOENT;
+       if (!abfd)
+               goto not_found;
+
+       if (!bfd_check_format(abfd, bfd_object))
+               goto not_found;
+
+       symtab_size = bfd_get_symtab_upper_bound(abfd);
+       if (!symtab_size)
+               goto not_found;
+
+       ret = -ENOMEM;
+       syms = malloc(symtab_size);
+       if (!syms)
+               goto not_found;
+
+       nr_syms = bfd_canonicalize_symtab(abfd, syms);
+
+       ret = -ENOENT;
+       section = bfd_get_section_by_name(abfd, ".debug_aranges");
+       if (!section)
+               goto not_found;
+
+       if (!bfd_find_nearest_line(abfd, section, NULL, addr, &filename, &func, &line))
+               goto not_found;
+
+       if (!func)
+               goto not_found;
+
+       symbol = lookup(syms, nr_syms, func);
+       if (IS_ERR(symbol))
+               goto not_found;
+
+       sym_start = bfd_asymbol_value(symbol);
+
+       sym_offset = addr - sym_start;
+
+       snprintf(sym, size, "%s+%llx (%s:%i)", func, (long long) sym_offset, filename, line);
+
+       sym[size - 1] = '\0';
+
+       free(syms);
+
+       return sym;
+
+not_found:
+       return ERR_PTR(ret);
+}
+
+int symbol_exit(struct kvm *kvm)
+{
+       bfd_boolean ret = TRUE;
+
+       if (abfd)
+               ret = bfd_close(abfd);
+
+       if (ret == TRUE)
+               return 0;
+
+       return -EFAULT;
+}
+late_exit(symbol_exit);
diff --git a/tools/kvm/term.c b/tools/kvm/term.c
new file mode 100644 (file)
index 0000000..4413450
--- /dev/null
@@ -0,0 +1,171 @@
+#include <poll.h>
+#include <stdbool.h>
+#include <termios.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/uio.h>
+#include <signal.h>
+#include <pty.h>
+#include <utmp.h>
+
+#include "kvm/read-write.h"
+#include "kvm/term.h"
+#include "kvm/util.h"
+#include "kvm/kvm.h"
+#include "kvm/kvm-cpu.h"
+
+#define TERM_FD_IN      0
+#define TERM_FD_OUT     1
+
+static struct termios  orig_term;
+
+int term_escape_char   = 0x01; /* ctrl-a is used for escape */
+bool term_got_escape   = false;
+
+int term_fds[4][2];
+
+int term_getc(struct kvm *kvm, int term)
+{
+       unsigned char c;
+
+       if (read_in_full(term_fds[term][TERM_FD_IN], &c, 1) < 0)
+               return -1;
+
+       if (term_got_escape) {
+               term_got_escape = false;
+               if (c == 'x')
+                       kvm_cpu__reboot(kvm);
+               if (c == term_escape_char)
+                       return c;
+       }
+
+       if (c == term_escape_char) {
+               term_got_escape = true;
+               return -1;
+       }
+
+       return c;
+}
+
+int term_putc(char *addr, int cnt, int term)
+{
+       int ret;
+
+       while (cnt--) {
+               ret = write(term_fds[term][TERM_FD_OUT], addr++, 1);
+               if (ret < 0)
+                       return 0;
+       }
+
+       return cnt;
+}
+
+int term_getc_iov(struct kvm *kvm, struct iovec *iov, int iovcnt, int term)
+{
+       int c;
+
+       c = term_getc(kvm, term);
+
+       if (c < 0)
+               return 0;
+
+       *((char *)iov[TERM_FD_IN].iov_base)     = (char)c;
+
+       return sizeof(char);
+}
+
+int term_putc_iov(struct iovec *iov, int iovcnt, int term)
+{
+       return writev(term_fds[term][TERM_FD_OUT], iov, iovcnt);
+}
+
+bool term_readable(int term)
+{
+       struct pollfd pollfd = (struct pollfd) {
+               .fd     = term_fds[term][TERM_FD_IN],
+               .events = POLLIN,
+               .revents = 0,
+       };
+
+       return poll(&pollfd, 1, 0) > 0;
+}
+
+static void term_cleanup(void)
+{
+       int i;
+
+       for (i = 0; i < 4; i++)
+               tcsetattr(term_fds[i][TERM_FD_IN], TCSANOW, &orig_term);
+}
+
+static void term_sig_cleanup(int sig)
+{
+       term_cleanup();
+       signal(sig, SIG_DFL);
+       raise(sig);
+}
+
+void term_set_tty(int term)
+{
+       struct termios orig_term;
+       int master, slave;
+       char new_pty[PATH_MAX];
+
+       if (tcgetattr(STDIN_FILENO, &orig_term) < 0)
+               die("unable to save initial standard input settings");
+
+       orig_term.c_lflag &= ~(ICANON | ECHO | ISIG);
+
+       if (openpty(&master, &slave, new_pty, &orig_term, NULL) < 0)
+               return;
+
+       close(slave);
+
+       pr_info("Assigned terminal %d to pty %s\n", term, new_pty);
+
+       term_fds[term][TERM_FD_IN] = term_fds[term][TERM_FD_OUT] = master;
+}
+
+int tty_parser(const struct option *opt, const char *arg, int unset)
+{
+       int tty = atoi(arg);
+
+       term_set_tty(tty);
+
+       return 0;
+}
+
+int term_init(struct kvm *kvm)
+{
+       struct termios term;
+       int i, r;
+
+       r = tcgetattr(STDIN_FILENO, &orig_term);
+       if (r < 0) {
+               pr_warning("unable to save initial standard input settings");
+               return r;
+       }
+
+
+       term = orig_term;
+       term.c_lflag &= ~(ICANON | ECHO | ISIG);
+       tcsetattr(STDIN_FILENO, TCSANOW, &term);
+
+       for (i = 0; i < 4; i++)
+               if (term_fds[i][TERM_FD_IN] == 0) {
+                       term_fds[i][TERM_FD_IN] = STDIN_FILENO;
+                       term_fds[i][TERM_FD_OUT] = STDOUT_FILENO;
+               }
+
+       signal(SIGTERM, term_sig_cleanup);
+       atexit(term_cleanup);
+
+       return 0;
+}
+dev_init(term_init);
+
+int term_exit(struct kvm *kvm)
+{
+       return 0;
+}
+dev_exit(term_exit);
diff --git a/tools/kvm/tests/Makefile b/tools/kvm/tests/Makefile
new file mode 100644 (file)
index 0000000..cad14ec
--- /dev/null
@@ -0,0 +1,19 @@
+all: kernel pit boot
+
+kernel:
+       $(MAKE) -C kernel
+.PHONY: kernel
+
+pit:
+       $(MAKE) -C pit
+.PHONY: pit
+
+boot:
+       $(MAKE) -C boot
+.PHONY: boot
+
+clean:
+       $(MAKE) -C kernel clean
+       $(MAKE) -C pit clean
+       $(MAKE) -C boot clean
+.PHONY: clean
diff --git a/tools/kvm/tests/boot/Makefile b/tools/kvm/tests/boot/Makefile
new file mode 100644 (file)
index 0000000..40cba68
--- /dev/null
@@ -0,0 +1,13 @@
+NAME   := init
+
+OBJ    := $(NAME).o
+
+all: $(.o)
+       rm -rf rootfs
+       mkdir rootfs
+       gcc -static init.c -o rootfs/init
+       mkisofs rootfs > boot_test.iso
+
+clean:
+       rm -rf rootfs boot_test.iso
+.PHONY: clean
diff --git a/tools/kvm/tests/boot/init.c b/tools/kvm/tests/boot/init.c
new file mode 100644 (file)
index 0000000..094f8ba
--- /dev/null
@@ -0,0 +1,11 @@
+#include <linux/reboot.h>
+#include <unistd.h>
+
+int main(int argc, char *argv[])
+{
+       puts("hello, KVM guest!\r");
+
+       reboot(LINUX_REBOOT_CMD_RESTART);
+
+       return 0;
+}
diff --git a/tools/kvm/tests/kernel/.gitignore b/tools/kvm/tests/kernel/.gitignore
new file mode 100644 (file)
index 0000000..d0cd209
--- /dev/null
@@ -0,0 +1,2 @@
+kernel.bin
+kernel.elf
diff --git a/tools/kvm/tests/kernel/Makefile b/tools/kvm/tests/kernel/Makefile
new file mode 100644 (file)
index 0000000..c7dd8da
--- /dev/null
@@ -0,0 +1,20 @@
+NAME   := kernel
+
+BIN    := $(NAME).bin
+ELF    := $(NAME).elf
+OBJ    := $(NAME).o
+
+all: $(BIN)
+
+$(BIN): $(ELF)
+       objcopy -O binary $< $@
+
+$(ELF): $(OBJ)
+       ld -Ttext=0x00 -nostdlib -static $< -o $@
+
+%.o: %.S
+       gcc -nostdinc -c $< -o $@
+
+clean:
+       rm -f $(BIN) $(ELF) $(OBJ)
+.PHONY: clean
diff --git a/tools/kvm/tests/kernel/README b/tools/kvm/tests/kernel/README
new file mode 100644 (file)
index 0000000..2923777
--- /dev/null
@@ -0,0 +1,16 @@
+Compiling
+---------
+
+You can simply type:
+
+  $ make
+
+to build a 16-bit binary that uses the i8086 instruction set.
+
+Disassembling
+-------------
+
+Use the "-m i8086" command line option with objdump to make sure it knows we're
+dealing with i8086 instruction set:
+
+  $ objdump -d -m i8086 i8086.elf
diff --git a/tools/kvm/tests/kernel/kernel.S b/tools/kvm/tests/kernel/kernel.S
new file mode 100644 (file)
index 0000000..2824b64
--- /dev/null
@@ -0,0 +1,8 @@
+       .code16gcc
+       .text
+       .globl  _start
+       .type   _start, @function
+_start:
+       # "This is probably the largest possible kernel that is bug free." -- Avi Kivity
+       1:
+       jmp 1b
diff --git a/tools/kvm/tests/pit/.gitignore b/tools/kvm/tests/pit/.gitignore
new file mode 100644 (file)
index 0000000..43f0aa8
--- /dev/null
@@ -0,0 +1,2 @@
+*.bin
+*.elf
diff --git a/tools/kvm/tests/pit/Makefile b/tools/kvm/tests/pit/Makefile
new file mode 100644 (file)
index 0000000..2fae9b2
--- /dev/null
@@ -0,0 +1,20 @@
+NAME   := tick
+
+BIN    := $(NAME).bin
+ELF    := $(NAME).elf
+OBJ    := $(NAME).o
+
+all: $(BIN)
+
+$(BIN): $(ELF)
+       objcopy -O binary $< $@
+
+$(ELF): $(OBJ)
+       ld -Ttext=0x00 -nostdlib -static $< -o $@
+
+%.o: %.S
+       gcc -nostdinc -c $< -o $@
+
+clean:
+       rm -f $(BIN) $(ELF) $(OBJ)
+.PHONY: clean
diff --git a/tools/kvm/tests/pit/README b/tools/kvm/tests/pit/README
new file mode 100644 (file)
index 0000000..2923777
--- /dev/null
@@ -0,0 +1,16 @@
+Compiling
+---------
+
+You can simply type:
+
+  $ make
+
+to build a 16-bit binary that uses the i8086 instruction set.
+
+Disassembling
+-------------
+
+Use the "-m i8086" command line option with objdump to make sure it knows we're
+dealing with i8086 instruction set:
+
+  $ objdump -d -m i8086 i8086.elf
diff --git a/tools/kvm/tests/pit/tick.S b/tools/kvm/tests/pit/tick.S
new file mode 100644 (file)
index 0000000..635dc8d
--- /dev/null
@@ -0,0 +1,101 @@
+#define IO_PIC         0x20
+#define IRQ_OFFSET     32
+#define IO_PIT         0x40
+#define TIMER_FREQ     1193182
+#define TIMER_DIV(x)   ((TIMER_FREQ+(x)/2)/(x))
+
+#define TEST_COUNT     0x0200
+
+       .code16gcc
+       .text
+       .globl  _start
+       .type   _start, @function
+_start:
+/*
+ * fill up noop handlers
+ */
+       xorw    %ax, %ax
+       xorw    %di, %di
+       movw    %ax, %es
+       movw    $256, %cx
+fill_noop_idt:
+       movw    $noop_handler, %es:(%di)
+       movw    %cs, %es:2(%di)
+       add     $4, %di
+       loop    fill_noop_idt
+
+set_idt:
+       movw    $timer_isr, %es:(IRQ_OFFSET*4)
+       movw    %cs, %es:(IRQ_OFFSET*4+2)
+
+set_pic:
+       # ICW1
+       mov     $0x11, %al
+       mov     $(IO_PIC), %dx
+       out     %al,%dx
+       # ICW2
+       mov     $(IRQ_OFFSET), %al
+       mov     $(IO_PIC+1), %dx
+       out     %al, %dx
+       # ICW3
+       mov     $0x00, %al
+       mov     $(IO_PIC+1), %dx
+       out     %al, %dx
+       # ICW4
+       mov     $0x3, %al
+       mov     $(IO_PIC+1), %dx
+       out     %al, %dx
+
+set_pit:
+       # set 8254 mode
+       mov     $(IO_PIT+3), %dx
+       mov     $0x34, %al
+       outb    %al, %dx
+       # set 8254 freq 1KHz
+       mov     $(IO_PIT), %dx
+       movb    $(TIMER_DIV(1000) % 256), %al
+       outb    %al, %dx
+       movb    $(TIMER_DIV(1000) / 256), %al
+       outb    %al, %dx
+
+enable_irq0:
+       mov     $0xfe, %al
+       mov     $(IO_PIC+1), %dx
+       out     %al, %dx
+       sti
+loop:
+       1:
+       jmp     1b
+
+test_ok:
+       mov     $0x3f8,%dx
+       cs lea  msg2, %si
+       mov     $(msg2_end-msg2), %cx
+       cs rep/outsb
+
+       /* Reboot by using the i8042 reboot line */
+       mov     $0xfe, %al
+       outb    %al, $0x64
+
+timer_isr:
+       cli
+       pushaw
+       pushfw
+       mov     $0x3f8,%dx
+       mov     $0x2e, %al      # .
+       out     %al,%dx
+       decw    count
+       jz      test_ok
+       popfw
+       popaw
+       iretw
+
+noop_handler:
+       iretw
+
+count:
+       .word   TEST_COUNT
+
+msg2:
+       .asciz "\nTest OK\n"
+msg2_end:
diff --git a/tools/kvm/ui/sdl.c b/tools/kvm/ui/sdl.c
new file mode 100644 (file)
index 0000000..172a12b
--- /dev/null
@@ -0,0 +1,321 @@
+#include "kvm/sdl.h"
+
+#include "kvm/framebuffer.h"
+#include "kvm/i8042.h"
+#include "kvm/util.h"
+#include "kvm/kvm.h"
+#include "kvm/kvm-cpu.h"
+#include "kvm/vesa.h"
+
+#include <SDL/SDL.h>
+#include <pthread.h>
+#include <signal.h>
+#include <linux/err.h>
+
+#define FRAME_RATE             25
+
+#define SCANCODE_UNKNOWN      0
+#define SCANCODE_NORMAL       1
+#define SCANCODE_ESCAPED      2
+#define SCANCODE_KEY_PAUSE    3
+#define SCANCODE_KEY_PRNTSCRN 4
+
+struct set2_scancode {
+       u8 code;
+       u8 type;
+};
+
+#define DEFINE_SC(_code) {\
+       .code = _code,\
+       .type = SCANCODE_NORMAL,\
+}
+
+/* escaped scancodes */
+#define DEFINE_ESC(_code) {\
+       .code = _code,\
+       .type = SCANCODE_ESCAPED,\
+}
+
+static const struct set2_scancode const keymap[256] = {
+       [9]     = DEFINE_SC(0x76),      /* <esc> */
+       [10]    = DEFINE_SC(0x16),      /* 1 */
+       [11]    = DEFINE_SC(0x1e),      /* 2 */
+       [12]    = DEFINE_SC(0x26),      /* 3 */
+       [13]    = DEFINE_SC(0x25),      /* 4 */
+       [14]    = DEFINE_SC(0x2e),      /* 5 */
+       [15]    = DEFINE_SC(0x36),      /* 6 */
+       [16]    = DEFINE_SC(0x3d),      /* 7 */
+       [17]    = DEFINE_SC(0x3e),      /* 8 */
+       [18]    = DEFINE_SC(0x46),      /* 9 */
+       [19]    = DEFINE_SC(0x45),      /* 9 */
+       [20]    = DEFINE_SC(0x4e),      /* - */
+       [21]    = DEFINE_SC(0x55),      /* + */
+       [22]    = DEFINE_SC(0x66),      /* <backspace> */
+       [23]    = DEFINE_SC(0x0d),      /* <tab> */
+       [24]    = DEFINE_SC(0x15),      /* q */
+       [25]    = DEFINE_SC(0x1d),      /* w */
+       [26]    = DEFINE_SC(0x24),      /* e */
+       [27]    = DEFINE_SC(0x2d),      /* r */
+       [28]    = DEFINE_SC(0x2c),      /* t */
+       [29]    = DEFINE_SC(0x35),      /* y */
+       [30]    = DEFINE_SC(0x3c),      /* u */
+       [31]    = DEFINE_SC(0x43),      /* i */
+       [32]    = DEFINE_SC(0x44),      /* o */
+       [33]    = DEFINE_SC(0x4d),      /* p */
+       [34]    = DEFINE_SC(0x54),      /* [ */
+       [35]    = DEFINE_SC(0x5b),      /* ] */
+       [36]    = DEFINE_SC(0x5a),      /* <enter> */
+       [37]    = DEFINE_SC(0x14),      /* <left ctrl> */
+       [38]    = DEFINE_SC(0x1c),      /* a */
+       [39]    = DEFINE_SC(0x1b),      /* s */
+       [40]    = DEFINE_SC(0x23),      /* d */
+       [41]    = DEFINE_SC(0x2b),      /* f */
+       [42]    = DEFINE_SC(0x34),      /* g */
+       [43]    = DEFINE_SC(0x33),      /* h */
+       [44]    = DEFINE_SC(0x3b),      /* j */
+       [45]    = DEFINE_SC(0x42),      /* k */
+       [46]    = DEFINE_SC(0x4b),      /* l */
+       [47]    = DEFINE_SC(0x4c),      /* ; */
+       [48]    = DEFINE_SC(0x52),      /* ' */
+       [49]    = DEFINE_SC(0x0e),      /* ` */
+       [50]    = DEFINE_SC(0x12),      /* <left shift> */
+       [51]    = DEFINE_SC(0x5d),      /* \ */
+       [52]    = DEFINE_SC(0x1a),      /* z */
+       [53]    = DEFINE_SC(0x22),      /* x */
+       [54]    = DEFINE_SC(0x21),      /* c */
+       [55]    = DEFINE_SC(0x2a),      /* v */
+       [56]    = DEFINE_SC(0x32),      /* b */
+       [57]    = DEFINE_SC(0x31),      /* n */
+       [58]    = DEFINE_SC(0x3a),      /* m */
+       [59]    = DEFINE_SC(0x41),      /* < */
+       [60]    = DEFINE_SC(0x49),      /* > */
+       [61]    = DEFINE_SC(0x4a),      /* / */
+       [62]    = DEFINE_SC(0x59),      /* <right shift> */
+       [63]    = DEFINE_SC(0x7c),      /* keypad * */
+       [64]    = DEFINE_SC(0x11),      /* <left alt> */
+       [65]    = DEFINE_SC(0x29),      /* <space> */
+
+       [67]    = DEFINE_SC(0x05),      /* <F1> */
+       [68]    = DEFINE_SC(0x06),      /* <F2> */
+       [69]    = DEFINE_SC(0x04),      /* <F3> */
+       [70]    = DEFINE_SC(0x0c),      /* <F4> */
+       [71]    = DEFINE_SC(0x03),      /* <F5> */
+       [72]    = DEFINE_SC(0x0b),      /* <F6> */
+       [73]    = DEFINE_SC(0x83),      /* <F7> */
+       [74]    = DEFINE_SC(0x0a),      /* <F8> */
+       [75]    = DEFINE_SC(0x01),      /* <F9> */
+       [76]    = DEFINE_SC(0x09),      /* <F10> */
+
+       [79]    = DEFINE_SC(0x6c),      /* keypad 7 */
+       [80]    = DEFINE_SC(0x75),      /* keypad 8 */
+       [81]    = DEFINE_SC(0x7d),      /* keypad 9 */
+       [82]    = DEFINE_SC(0x7b),      /* keypad - */
+       [83]    = DEFINE_SC(0x6b),      /* keypad 4 */
+       [84]    = DEFINE_SC(0x73),      /* keypad 5 */
+       [85]    = DEFINE_SC(0x74),      /* keypad 6 */
+       [86]    = DEFINE_SC(0x79),      /* keypad + */
+       [87]    = DEFINE_SC(0x69),      /* keypad 1 */
+       [88]    = DEFINE_SC(0x72),      /* keypad 2 */
+       [89]    = DEFINE_SC(0x7a),      /* keypad 3 */
+       [90]    = DEFINE_SC(0x70),      /* keypad 0 */
+       [91]    = DEFINE_SC(0x71),      /* keypad . */
+
+       [94]    = DEFINE_SC(0x61),      /* <INT 1> */
+       [95]    = DEFINE_SC(0x78),      /* <F11> */
+       [96]    = DEFINE_SC(0x07),      /* <F12> */
+
+       [104]   = DEFINE_ESC(0x5a),     /* keypad <enter> */
+       [105]   = DEFINE_ESC(0x14),     /* <right ctrl> */
+       [106]   = DEFINE_ESC(0x4a),     /* keypad / */
+       [108]   = DEFINE_ESC(0x11),     /* <right alt> */
+       [110]   = DEFINE_ESC(0x6c),     /* <home> */
+       [111]   = DEFINE_ESC(0x75),     /* <up> */
+       [112]   = DEFINE_ESC(0x7d),     /* <pag up> */
+       [113]   = DEFINE_ESC(0x6b),     /* <left> */
+       [114]   = DEFINE_ESC(0x74),     /* <right> */
+       [115]   = DEFINE_ESC(0x69),     /* <end> */
+       [116]   = DEFINE_ESC(0x72),     /* <down> */
+       [117]   = DEFINE_ESC(0x7a),     /* <pag down> */
+       [118]   = DEFINE_ESC(0x70),     /* <ins> */
+       [119]   = DEFINE_ESC(0x71),     /* <delete> */
+};
+static bool running, done;
+
+static const struct set2_scancode *to_code(u8 scancode)
+{
+       return &keymap[scancode];
+}
+
+static void key_press(const struct set2_scancode *sc)
+{
+       switch (sc->type) {
+       case SCANCODE_ESCAPED:
+               kbd_queue(0xe0);
+               /* fallthrough */
+       case SCANCODE_NORMAL:
+               kbd_queue(sc->code);
+               break;
+       case SCANCODE_KEY_PAUSE:
+               kbd_queue(0xe1);
+               kbd_queue(0x14);
+               kbd_queue(0x77);
+               kbd_queue(0xe1);
+               kbd_queue(0xf0);
+               kbd_queue(0x14);
+               kbd_queue(0x77);
+               break;
+       case SCANCODE_KEY_PRNTSCRN:
+               kbd_queue(0xe0);
+               kbd_queue(0x12);
+               kbd_queue(0xe0);
+               kbd_queue(0x7c);
+               break;
+       }
+}
+
+static void key_release(const struct set2_scancode *sc)
+{
+       switch (sc->type) {
+       case SCANCODE_ESCAPED:
+               kbd_queue(0xe0);
+               /* fallthrough */
+       case SCANCODE_NORMAL:
+               kbd_queue(0xf0);
+               kbd_queue(sc->code);
+               break;
+       case SCANCODE_KEY_PAUSE:
+               /* nothing to do */
+               break;
+       case SCANCODE_KEY_PRNTSCRN:
+               kbd_queue(0xe0);
+               kbd_queue(0xf0);
+               kbd_queue(0x7c);
+               kbd_queue(0xe0);
+               kbd_queue(0xf0);
+               kbd_queue(0x12);
+               break;
+       }
+}
+
+static void *sdl__thread(void *p)
+{
+       Uint32 rmask, gmask, bmask, amask;
+       struct framebuffer *fb = p;
+       SDL_Surface *guest_screen;
+       SDL_Surface *screen;
+       SDL_Event ev;
+       Uint32 flags;
+
+       if (SDL_Init(SDL_INIT_VIDEO) != 0)
+               die("Unable to initialize SDL");
+
+       rmask = 0x000000ff;
+       gmask = 0x0000ff00;
+       bmask = 0x00ff0000;
+       amask = 0x00000000;
+
+       guest_screen = SDL_CreateRGBSurfaceFrom(fb->mem, fb->width, fb->height, fb->depth, fb->width * fb->depth / 8, rmask, gmask, bmask, amask);
+       if (!guest_screen)
+               die("Unable to create SDL RBG surface");
+
+       flags = SDL_HWSURFACE | SDL_ASYNCBLIT | SDL_HWACCEL | SDL_DOUBLEBUF;
+
+       SDL_WM_SetCaption("KVM tool", "KVM tool");
+
+       screen = SDL_SetVideoMode(fb->width, fb->height, fb->depth, flags);
+       if (!screen)
+               die("Unable to set SDL video mode");
+
+       SDL_EnableKeyRepeat(200, 50);
+
+       while (running) {
+               SDL_BlitSurface(guest_screen, NULL, screen, NULL);
+               SDL_Flip(screen);
+
+               while (SDL_PollEvent(&ev)) {
+                       switch (ev.type) {
+                       case SDL_KEYDOWN: {
+                               const struct set2_scancode *sc = to_code(ev.key.keysym.scancode);
+                               if (sc->type == SCANCODE_UNKNOWN) {
+                                       pr_warning("key '%d' not found in keymap", ev.key.keysym.scancode);
+                                       break;
+                               }
+                               key_press(sc);
+                               break;
+                       }
+                       case SDL_KEYUP: {
+                               const struct set2_scancode *sc = to_code(ev.key.keysym.scancode);
+                               if (sc->type == SCANCODE_UNKNOWN)
+                                       break;
+                               key_release(sc);
+                               break;
+                       }
+                       case SDL_QUIT:
+                               goto exit;
+                       }
+               }
+
+               SDL_Delay(1000 / FRAME_RATE);
+       }
+
+       if (running == false && done == false) {
+               done = true;
+               return NULL;
+       }
+exit:
+       kvm_cpu__reboot(fb->kvm);
+
+       return NULL;
+}
+
+static int sdl__start(struct framebuffer *fb)
+{
+       pthread_t thread;
+
+       running = true;
+
+       if (pthread_create(&thread, NULL, sdl__thread, fb) != 0)
+               return -1;
+
+       return 0;
+}
+
+static int sdl__stop(struct framebuffer *fb)
+{
+       running = false;
+       while (done == false)
+               sleep(0);
+
+       return 0;
+}
+
+static struct fb_target_operations sdl_ops = {
+       .start  = sdl__start,
+       .stop   = sdl__stop,
+};
+
+int sdl__init(struct kvm *kvm)
+{
+       struct framebuffer *fb;
+
+       if (!kvm->cfg.sdl)
+               return 0;
+
+       fb = vesa__init(kvm);
+       if (IS_ERR(fb)) {
+               pr_err("vesa__init() failed with error %ld\n", PTR_ERR(fb));
+               return PTR_ERR(fb);
+       }
+
+       return fb__attach(fb, &sdl_ops);
+}
+dev_init(sdl__init);
+
+int sdl__exit(struct kvm *kvm)
+{
+       if (kvm->cfg.sdl)
+               return sdl__stop(NULL);
+
+       return 0;
+}
+dev_exit(sdl__exit);
diff --git a/tools/kvm/ui/vnc.c b/tools/kvm/ui/vnc.c
new file mode 100644 (file)
index 0000000..efdc0f4
--- /dev/null
@@ -0,0 +1,248 @@
+#include "kvm/vnc.h"
+
+#include "kvm/framebuffer.h"
+#include "kvm/i8042.h"
+#include "kvm/vesa.h"
+
+#include <linux/types.h>
+#include <rfb/keysym.h>
+#include <rfb/rfb.h>
+#include <pthread.h>
+#include <linux/err.h>
+
+#define VESA_QUEUE_SIZE                128
+#define VESA_IRQ               14
+
+/*
+ * This "6000" value is pretty much the result of experimentation
+ * It seems that around this value, things update pretty smoothly
+ */
+#define VESA_UPDATE_TIME       6000
+
+/*
+ * We can map the letters and numbers without a fuss,
+ * but the other characters not so much.
+ */
+static char letters[26] = {
+       0x1c, 0x32, 0x21, 0x23, 0x24, /* a-e */
+       0x2b, 0x34, 0x33, 0x43, 0x3b, /* f-j */
+       0x42, 0x4b, 0x3a, 0x31, 0x44, /* k-o */
+       0x4d, 0x15, 0x2d, 0x1b, 0x2c, /* p-t */
+       0x3c, 0x2a, 0x1d, 0x22, 0x35, /* u-y */
+       0x1a,
+};
+
+static rfbScreenInfoPtr server;
+static char num[10] = {
+       0x45, 0x16, 0x1e, 0x26, 0x2e, 0x23, 0x36, 0x3d, 0x3e, 0x46,
+};
+
+/*
+ * This is called when the VNC server receives a key event
+ * The reason this function is such a beast is that we have
+ * to convert from ASCII characters (which is what VNC gets)
+ * to PC keyboard scancodes, which is what Linux expects to
+ * get from its keyboard. ASCII and the scancode set don't
+ * really seem to mesh in any good way beyond some basics with
+ * the letters and numbers.
+ */
+static void kbd_handle_key(rfbBool down, rfbKeySym key, rfbClientPtr cl)
+{
+       char tosend = 0;
+
+       if (key >= 0x41 && key <= 0x5a)
+               key += 0x20; /* convert to lowercase */
+
+       if (key >= 0x61 && key <= 0x7a) /* a-z */
+               tosend = letters[key - 0x61];
+
+       if (key >= 0x30 && key <= 0x39)
+               tosend = num[key - 0x30];
+
+       switch (key) {
+       case XK_Insert:         kbd_queue(0xe0);        tosend = 0x70;  break;
+       case XK_Delete:         kbd_queue(0xe0);        tosend = 0x71;  break;
+       case XK_Up:             kbd_queue(0xe0);        tosend = 0x75;  break;
+       case XK_Down:           kbd_queue(0xe0);        tosend = 0x72;  break;
+       case XK_Left:           kbd_queue(0xe0);        tosend = 0x6b;  break;
+       case XK_Right:          kbd_queue(0xe0);        tosend = 0x74;  break;
+       case XK_Page_Up:        kbd_queue(0xe0);        tosend = 0x7d;  break;
+       case XK_Page_Down:      kbd_queue(0xe0);        tosend = 0x7a;  break;
+       case XK_Home:           kbd_queue(0xe0);        tosend = 0x6c;  break;
+       case XK_BackSpace:      tosend = 0x66;          break;
+       case XK_Tab:            tosend = 0x0d;          break;
+       case XK_Return:         tosend = 0x5a;          break;
+       case XK_Escape:         tosend = 0x76;          break;
+       case XK_End:            tosend = 0x69;          break;
+       case XK_Shift_L:        tosend = 0x12;          break;
+       case XK_Shift_R:        tosend = 0x59;          break;
+       case XK_Control_R:      kbd_queue(0xe0);
+       case XK_Control_L:      tosend = 0x14;          break;
+       case XK_Alt_R:          kbd_queue(0xe0);
+       case XK_Alt_L:          tosend = 0x11;          break;
+       case XK_quoteleft:      tosend = 0x0e;          break;
+       case XK_minus:          tosend = 0x4e;          break;
+       case XK_equal:          tosend = 0x55;          break;
+       case XK_bracketleft:    tosend = 0x54;          break;
+       case XK_bracketright:   tosend = 0x5b;          break;
+       case XK_backslash:      tosend = 0x5d;          break;
+       case XK_Caps_Lock:      tosend = 0x58;          break;
+       case XK_semicolon:      tosend = 0x4c;          break;
+       case XK_quoteright:     tosend = 0x52;          break;
+       case XK_comma:          tosend = 0x41;          break;
+       case XK_period:         tosend = 0x49;          break;
+       case XK_slash:          tosend = 0x4a;          break;
+       case XK_space:          tosend = 0x29;          break;
+
+       /*
+        * This is where I handle the shifted characters.
+        * They don't really map nicely the way A-Z maps to a-z,
+        * so I'm doing it manually
+        */
+       case XK_exclam:         tosend = 0x16;          break;
+       case XK_quotedbl:       tosend = 0x52;          break;
+       case XK_numbersign:     tosend = 0x26;          break;
+       case XK_dollar:         tosend = 0x25;          break;
+       case XK_percent:        tosend = 0x2e;          break;
+       case XK_ampersand:      tosend = 0x3d;          break;
+       case XK_parenleft:      tosend = 0x46;          break;
+       case XK_parenright:     tosend = 0x45;          break;
+       case XK_asterisk:       tosend = 0x3e;          break;
+       case XK_plus:           tosend = 0x55;          break;
+       case XK_colon:          tosend = 0x4c;          break;
+       case XK_less:           tosend = 0x41;          break;
+       case XK_greater:        tosend = 0x49;          break;
+       case XK_question:       tosend = 0x4a;          break;
+       case XK_at:             tosend = 0x1e;          break;
+       case XK_asciicircum:    tosend = 0x36;          break;
+       case XK_underscore:     tosend = 0x4e;          break;
+       case XK_braceleft:      tosend = 0x54;          break;
+       case XK_braceright:     tosend = 0x5b;          break;
+       case XK_bar:            tosend = 0x5d;          break;
+       case XK_asciitilde:     tosend = 0x0e;          break;
+       default:                break;
+       }
+
+       /*
+        * If this is a "key up" event (the user has released the key, we
+        * need to send 0xf0 first.
+        */
+       if (!down && tosend != 0x0)
+               kbd_queue(0xf0);
+
+       if (tosend)
+               kbd_queue(tosend);
+}
+
+/* The previous X and Y coordinates of the mouse */
+static int xlast, ylast = -1;
+
+/*
+ * This function is called by the VNC server whenever a mouse event occurs.
+ */
+static void kbd_handle_ptr(int buttonMask, int x, int y, rfbClientPtr cl)
+{
+       int dx, dy;
+       char b1 = 0x8;
+
+       /* The VNC mask and the PS/2 button encoding are the same */
+       b1 |= buttonMask;
+
+       if (xlast >= 0 && ylast >= 0) {
+               /* The PS/2 mouse sends deltas, not absolutes */
+               dx = x - xlast;
+               dy = ylast - y;
+
+               /* Set overflow bits if needed */
+               if (dy > 255)
+                       b1 |= 0x80;
+               if (dx > 255)
+                       b1 |= 0x40;
+
+               /* Set negative bits if needed */
+               if (dy < 0)
+                       b1 |= 0x20;
+               if (dx < 0)
+                       b1 |= 0x10;
+
+               mouse_queue(b1);
+               mouse_queue(dx);
+               mouse_queue(dy);
+       }
+
+       xlast = x;
+       ylast = y;
+       rfbDefaultPtrAddEvent(buttonMask, x, y, cl);
+}
+
+static void *vnc__thread(void *p)
+{
+       struct framebuffer *fb = p;
+       /*
+        * Make a fake argc and argv because the getscreen function
+        * seems to want it.
+        */
+       char argv[1][1] = {{0}};
+       int argc = 1;
+
+       server = rfbGetScreen(&argc, (char **) argv, fb->width, fb->height, 8, 3, 4);
+       server->frameBuffer             = fb->mem;
+       server->alwaysShared            = TRUE;
+       server->kbdAddEvent             = kbd_handle_key;
+       server->ptrAddEvent             = kbd_handle_ptr;
+       rfbInitServer(server);
+
+       while (rfbIsActive(server)) {
+               rfbMarkRectAsModified(server, 0, 0, fb->width, fb->height);
+               rfbProcessEvents(server, server->deferUpdateTime * VESA_UPDATE_TIME);
+       }
+       return NULL;
+}
+
+static int vnc__start(struct framebuffer *fb)
+{
+       pthread_t thread;
+
+       if (pthread_create(&thread, NULL, vnc__thread, fb) != 0)
+               return -1;
+
+       return 0;
+}
+
+static int vnc__stop(struct framebuffer *fb)
+{
+       rfbShutdownServer(server, TRUE);
+
+       return 0;
+}
+
+static struct fb_target_operations vnc_ops = {
+       .start  = vnc__start,
+       .stop   = vnc__stop,
+};
+
+int vnc__init(struct kvm *kvm)
+{
+       struct framebuffer *fb;
+
+       if (!kvm->cfg.vnc)
+               return 0;
+
+       fb = vesa__init(kvm);
+       if (IS_ERR(fb)) {
+               pr_err("vesa__init() failed with error %ld\n", PTR_ERR(fb));
+               return PTR_ERR(fb);
+       }
+
+       return fb__attach(fb, &vnc_ops);
+}
+dev_init(vnc__init);
+
+int vnc__exit(struct kvm *kvm)
+{
+       if (kvm->cfg.vnc)
+               return vnc__stop(NULL);
+
+       return 0;
+}
+dev_exit(vnc__exit);
diff --git a/tools/kvm/util/KVMTOOLS-VERSION-GEN b/tools/kvm/util/KVMTOOLS-VERSION-GEN
new file mode 100755 (executable)
index 0000000..1af9d6c
--- /dev/null
@@ -0,0 +1,40 @@
+#!/bin/sh
+
+if [ $# -eq 1 ]  ; then
+       OUTPUT=$1
+fi
+
+GVF=${OUTPUT}KVMTOOLS-VERSION-FILE
+
+LF='
+'
+
+# First check if there is a .git to get the version from git describe
+# otherwise try to get the version from the kernel makefile
+if test -d ../../.git -o -f ../../.git &&
+       VN=$(git describe --abbrev=4 HEAD 2>/dev/null) &&
+       case "$VN" in
+       *$LF*) (exit 1) ;;
+       v[0-9]*)
+               git update-index -q --refresh
+               test -z "$(git diff-index --name-only HEAD --)" ||
+               VN="$VN-dirty" ;;
+       esac
+then
+       VN=$(echo "$VN" | sed -e 's/-/./g');
+else
+       VN=$(MAKEFLAGS= make -sC ../.. kernelversion)
+fi
+
+VN=$(expr "$VN" : v*'\(.*\)')
+
+if test -r $GVF
+then
+       VC=$(sed -e 's/^KVMTOOLS_VERSION = //' <$GVF)
+else
+       VC=unset
+fi
+test "$VN" = "$VC" || {
+       echo >&2 "KVMTOOLS_VERSION = $VN"
+       echo "KVMTOOLS_VERSION = $VN" >$GVF
+}
diff --git a/tools/kvm/util/generate-cmdlist.sh b/tools/kvm/util/generate-cmdlist.sh
new file mode 100755 (executable)
index 0000000..c8be0bd
--- /dev/null
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+echo "/* Automatically generated by $0 */
+struct cmdname_help
+{
+    char name[16];
+    char help[80];
+};
+
+static struct cmdname_help common_cmds[] = {"
+
+sed -n 's/^lkvm-\([^ \t]*\).*common/\1/p' command-list.txt |
+while read cmd
+do
+        # TODO following sed command should be fixed
+     sed -n '/^NAME/,/^lkvm-'"$cmd"'/ {
+                /NAME/d
+                /--/d
+                s/.*kvm-'"$cmd"' - \(.*\)/  {"'"$cmd"'", "\1"},/
+            p
+        }' "Documentation/kvm-$cmd.txt"
+done
+echo "};"
diff --git a/tools/kvm/util/init.c b/tools/kvm/util/init.c
new file mode 100644 (file)
index 0000000..33a5952
--- /dev/null
@@ -0,0 +1,69 @@
+#include <linux/list.h>
+#include <linux/kernel.h>
+
+#include "kvm/kvm.h"
+#include "kvm/util-init.h"
+
+#define PRIORITY_LISTS 10
+
+static struct hlist_head init_lists[PRIORITY_LISTS];
+static struct hlist_head exit_lists[PRIORITY_LISTS];
+
+int init_list_add(struct init_item *t, int (*init)(struct kvm *),
+                       int priority, const char *name)
+{
+       t->init = init;
+       t->fn_name = name;
+       hlist_add_head(&t->n, &init_lists[priority]);
+
+       return 0;
+}
+
+int exit_list_add(struct init_item *t, int (*init)(struct kvm *),
+                       int priority, const char *name)
+{
+       t->init = init;
+       t->fn_name = name;
+       hlist_add_head(&t->n, &exit_lists[priority]);
+
+       return 0;
+}
+
+int init_list__init(struct kvm *kvm)
+{
+       unsigned int i;
+       int r = 0;
+       struct hlist_node *n;
+       struct init_item *t;
+
+       for (i = 0; i < ARRAY_SIZE(init_lists); i++)
+               hlist_for_each_entry(t, n, &init_lists[i], n) {
+                       r = t->init(kvm);
+                       if (r < 0) {
+                               pr_warning("Failed init: %s\n", t->fn_name);
+                               goto fail;
+                       }
+               }
+
+fail:
+       return r;
+}
+
+int init_list__exit(struct kvm *kvm)
+{
+       int i;
+       int r = 0;
+       struct hlist_node *n;
+       struct init_item *t;
+
+       for (i = ARRAY_SIZE(exit_lists) - 1; i >= 0; i--)
+               hlist_for_each_entry(t, n, &exit_lists[i], n) {
+                       r = t->init(kvm);
+                       if (r < 0) {
+                               pr_warning("%s failed.\n", t->fn_name);
+                               goto fail;
+                       }
+               }
+fail:
+       return r;
+}
diff --git a/tools/kvm/util/kvm-ifup-vbr0 b/tools/kvm/util/kvm-ifup-vbr0
new file mode 100755 (executable)
index 0000000..a91c37f
--- /dev/null
@@ -0,0 +1,6 @@
+#!/bin/sh
+switch=vbr0
+/sbin/ifconfig $1 0.0.0.0 up
+/usr/sbin/brctl addif ${switch} $1
+/usr/sbin/brctl setfd ${switch} 0
+/usr/sbin/brctl stp ${switch} off
diff --git a/tools/kvm/util/parse-options.c b/tools/kvm/util/parse-options.c
new file mode 100644 (file)
index 0000000..9a1bbee
--- /dev/null
@@ -0,0 +1,577 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <stdbool.h>
+
+/* user defined includes */
+#include <linux/types.h>
+#include <kvm/util.h>
+#include <kvm/parse-options.h>
+#include <kvm/strbuf.h>
+
+#define OPT_SHORT 1
+#define OPT_UNSET 2
+
+static int opterror(const struct option *opt, const char *reason, int flags)
+{
+       if (flags & OPT_SHORT)
+               return pr_err("switch `%c' %s", opt->short_name, reason);
+       if (flags & OPT_UNSET)
+               return pr_err("option `no-%s' %s", opt->long_name, reason);
+       return pr_err("option `%s' %s", opt->long_name, reason);
+}
+
+static int get_arg(struct parse_opt_ctx_t *p, const struct option *opt,
+               int flags, const char **arg)
+{
+       if (p->opt) {
+               *arg = p->opt;
+               p->opt = NULL;
+       } else if ((opt->flags & PARSE_OPT_LASTARG_DEFAULT) && (p->argc == 1 ||
+                               **(p->argv + 1) == '-')) {
+               *arg = (const char *)opt->defval;
+       } else if (p->argc > 1) {
+               p->argc--;
+               *arg = *++p->argv;
+       } else
+               return opterror(opt, "requires a value", flags);
+       return 0;
+}
+
+static int readnum(const struct option *opt, int flags,
+                  const char *str, char **end)
+{
+       switch (opt->type) {
+       case OPTION_INTEGER:
+               *(int *)opt->value = strtol(str, end, 0);
+               break;
+       case OPTION_UINTEGER:
+               *(unsigned int *)opt->value = strtol(str, end, 0);
+               break;
+       case OPTION_LONG:
+               *(long *)opt->value = strtol(str, end, 0);
+               break;
+       case OPTION_U64:
+               *(u64 *)opt->value = strtoull(str, end, 0);
+               break;
+       default:
+               return opterror(opt, "invalid numeric conversion", flags);
+       }
+
+       return 0;
+}
+
+static int get_value(struct parse_opt_ctx_t *p,
+               const struct option *opt, int flags)
+{
+       const char *s, *arg = NULL;
+       const int unset = flags & OPT_UNSET;
+
+       if (unset && p->opt)
+               return opterror(opt, "takes no value", flags);
+       if (unset && (opt->flags & PARSE_OPT_NONEG))
+               return opterror(opt, "isn't available", flags);
+
+       if (!(flags & OPT_SHORT) && p->opt) {
+               switch (opt->type) {
+               case OPTION_CALLBACK:
+                       if (!(opt->flags & PARSE_OPT_NOARG))
+                               break;
+               /* FALLTHROUGH */
+               case OPTION_BOOLEAN:
+               case OPTION_INCR:
+               case OPTION_BIT:
+               case OPTION_SET_UINT:
+               case OPTION_SET_PTR:
+                       return opterror(opt, "takes no value", flags);
+               case OPTION_END:
+               case OPTION_ARGUMENT:
+               case OPTION_GROUP:
+               case OPTION_STRING:
+               case OPTION_INTEGER:
+               case OPTION_UINTEGER:
+               case OPTION_LONG:
+               case OPTION_U64:
+               default:
+                       break;
+               }
+       }
+
+       switch (opt->type) {
+       case OPTION_BIT:
+               if (unset)
+                       *(int *)opt->value &= ~opt->defval;
+               else
+                       *(int *)opt->value |= opt->defval;
+               return 0;
+
+       case OPTION_BOOLEAN:
+               *(bool *)opt->value = unset ? false : true;
+               return 0;
+
+       case OPTION_INCR:
+               *(int *)opt->value = unset ? 0 : *(int *)opt->value + 1;
+               return 0;
+
+       case OPTION_SET_UINT:
+               *(unsigned int *)opt->value = unset ? 0 : opt->defval;
+               return 0;
+
+       case OPTION_SET_PTR:
+               *(void **)opt->value = unset ? NULL : (void *)opt->defval;
+               return 0;
+
+       case OPTION_STRING:
+               if (unset)
+                       *(const char **)opt->value = NULL;
+               else if (opt->flags & PARSE_OPT_OPTARG && !p->opt)
+                       *(const char **)opt->value = (const char *)opt->defval;
+               else
+                       return get_arg(p, opt, flags,
+                                       (const char **)opt->value);
+               return 0;
+
+       case OPTION_CALLBACK:
+               if (unset)
+                       return (*opt->callback)(opt, NULL, 1) ? (-1) : 0;
+               if (opt->flags & PARSE_OPT_NOARG)
+                       return (*opt->callback)(opt, NULL, 0) ? (-1) : 0;
+               if (opt->flags & PARSE_OPT_OPTARG && !p->opt)
+                       return (*opt->callback)(opt, NULL, 0) ? (-1) : 0;
+               if (get_arg(p, opt, flags, &arg))
+                       return -1;
+               return (*opt->callback)(opt, arg, 0) ? (-1) : 0;
+
+       case OPTION_INTEGER:
+               if (unset) {
+                       *(int *)opt->value = 0;
+                       return 0;
+               }
+               if (opt->flags & PARSE_OPT_OPTARG && !p->opt) {
+                       *(int *)opt->value = opt->defval;
+                       return 0;
+               }
+               if (get_arg(p, opt, flags, &arg))
+                       return -1;
+               return readnum(opt, flags, arg, (char **)&s);
+
+       case OPTION_UINTEGER:
+               if (unset) {
+                       *(unsigned int *)opt->value = 0;
+                       return 0;
+               }
+               if (opt->flags & PARSE_OPT_OPTARG && !p->opt) {
+                       *(unsigned int *)opt->value = opt->defval;
+                       return 0;
+               }
+               if (get_arg(p, opt, flags, &arg))
+                       return -1;
+               return readnum(opt, flags, arg, (char **)&s);
+
+       case OPTION_LONG:
+               if (unset) {
+                       *(long *)opt->value = 0;
+                       return 0;
+               }
+               if (opt->flags & PARSE_OPT_OPTARG && !p->opt) {
+                       *(long *)opt->value = opt->defval;
+                       return 0;
+               }
+               if (get_arg(p, opt, flags, &arg))
+                       return -1;
+               return readnum(opt, flags, arg, (char **)&s);
+
+       case OPTION_U64:
+               if (unset) {
+                       *(u64 *)opt->value = 0;
+                       return 0;
+               }
+               if (opt->flags & PARSE_OPT_OPTARG && !p->opt) {
+                       *(u64 *)opt->value = opt->defval;
+                       return 0;
+               }
+               if (get_arg(p, opt, flags, &arg))
+                       return -1;
+               return readnum(opt, flags, arg, (char **)&s);
+
+       case OPTION_END:
+       case OPTION_ARGUMENT:
+       case OPTION_GROUP:
+       default:
+               die("should not happen, someone must be hit on the forehead");
+       }
+}
+
+#define USAGE_OPTS_WIDTH 24
+#define USAGE_GAP         2
+
+static int usage_with_options_internal(const char * const *usagestr,
+               const struct option *opts, int full)
+{
+       if (!usagestr)
+               return PARSE_OPT_HELP;
+
+       fprintf(stderr, "\n usage: %s\n", *usagestr++);
+       while (*usagestr && **usagestr)
+               fprintf(stderr, "    or: %s\n", *usagestr++);
+       while (*usagestr) {
+               fprintf(stderr, "%s%s\n",
+                               **usagestr ? "    " : "",
+                               *usagestr);
+               usagestr++;
+       }
+
+       if (opts->type != OPTION_GROUP)
+               fputc('\n', stderr);
+
+       for (; opts->type != OPTION_END; opts++) {
+               size_t pos;
+               int pad;
+
+               if (opts->type == OPTION_GROUP) {
+                       fputc('\n', stderr);
+                       if (*opts->help)
+                               fprintf(stderr, "%s\n", opts->help);
+                       continue;
+               }
+               if (!full && (opts->flags & PARSE_OPT_HIDDEN))
+                       continue;
+
+               pos = fprintf(stderr, "    ");
+               if (opts->short_name)
+                       pos += fprintf(stderr, "-%c", opts->short_name);
+               else
+                       pos += fprintf(stderr, "    ");
+
+               if (opts->long_name && opts->short_name)
+                       pos += fprintf(stderr, ", ");
+               if (opts->long_name)
+                       pos += fprintf(stderr, "--%s", opts->long_name);
+
+               switch (opts->type) {
+               case OPTION_ARGUMENT:
+                       break;
+               case OPTION_LONG:
+               case OPTION_U64:
+               case OPTION_INTEGER:
+               case OPTION_UINTEGER:
+                       if (opts->flags & PARSE_OPT_OPTARG)
+                               if (opts->long_name)
+                                       pos += fprintf(stderr, "[=<n>]");
+                               else
+                                       pos += fprintf(stderr, "[<n>]");
+                       else
+                               pos += fprintf(stderr, " <n>");
+                       break;
+               case OPTION_CALLBACK:
+                       if (opts->flags & PARSE_OPT_NOARG)
+                               break;
+               /* FALLTHROUGH */
+               case OPTION_STRING:
+                       if (opts->argh) {
+                               if (opts->flags & PARSE_OPT_OPTARG)
+                                       if (opts->long_name)
+                                               pos += fprintf(stderr, "[=<%s>]", opts->argh);
+                                       else
+                                               pos += fprintf(stderr, "[<%s>]", opts->argh);
+                               else
+                                       pos += fprintf(stderr, " <%s>", opts->argh);
+                       } else {
+                               if (opts->flags & PARSE_OPT_OPTARG)
+                                       if (opts->long_name)
+                                               pos += fprintf(stderr, "[=...]");
+                                       else
+                                               pos += fprintf(stderr, "[...]");
+                               else
+                                       pos += fprintf(stderr, " ...");
+                       }
+                               break;
+               default: /* OPTION_{BIT,BOOLEAN,SET_UINT,SET_PTR} */
+               case OPTION_END:
+               case OPTION_GROUP:
+               case OPTION_BIT:
+               case OPTION_BOOLEAN:
+               case OPTION_INCR:
+               case OPTION_SET_UINT:
+               case OPTION_SET_PTR:
+                       break;
+               }
+               if (pos <= USAGE_OPTS_WIDTH)
+                       pad = USAGE_OPTS_WIDTH - pos;
+               else {
+                       fputc('\n', stderr);
+                       pad = USAGE_OPTS_WIDTH;
+               }
+               fprintf(stderr, "%*s%s\n", pad + USAGE_GAP, "", opts->help);
+       }
+       fputc('\n', stderr);
+
+       return PARSE_OPT_HELP;
+}
+
+void usage_with_options(const char * const *usagestr,
+               const struct option *opts)
+{
+       usage_with_options_internal(usagestr, opts, 0);
+       exit(129);
+}
+
+static void check_typos(const char *arg, const struct option *options)
+{
+       if (strlen(arg) < 3)
+               return;
+
+       if (!prefixcmp(arg, "no-")) {
+               pr_err("did you mean `--%s` (with two dashes ?)", arg);
+               exit(129);
+       }
+
+       for (; options->type != OPTION_END; options++) {
+               if (!options->long_name)
+                       continue;
+               if (!prefixcmp(options->long_name, arg)) {
+                       pr_err("did you mean `--%s` (with two dashes ?)", arg);
+                       exit(129);
+               }
+       }
+}
+
+static int parse_options_usage(const char * const *usagestr,
+               const struct option *opts)
+{
+       return usage_with_options_internal(usagestr, opts, 0);
+}
+
+static int parse_short_opt(struct parse_opt_ctx_t *p,
+        const struct option *options)
+{
+       for (; options->type != OPTION_END; options++) {
+               if (options->short_name == *p->opt) {
+                       p->opt = p->opt[1] ? p->opt + 1 : NULL;
+                       return get_value(p, options, OPT_SHORT);
+               }
+       }
+       return -2;
+}
+
+static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg,
+               const struct option *options)
+{
+       const char *arg_end = strchr(arg, '=');
+       const struct option *abbrev_option = NULL, *ambiguous_option = NULL;
+       int abbrev_flags = 0, ambiguous_flags = 0;
+
+       if (!arg_end)
+               arg_end = arg + strlen(arg);
+
+       for (; options->type != OPTION_END; options++) {
+               const char *rest;
+               int flags = 0;
+
+               if (!options->long_name)
+                       continue;
+
+               rest = skip_prefix(arg, options->long_name);
+               if (options->type == OPTION_ARGUMENT) {
+                       if (!rest)
+                               continue;
+                       if (*rest == '=')
+                               return opterror(options, "takes no value",
+                                               flags);
+                       if (*rest)
+                               continue;
+                       p->out[p->cpidx++] = arg - 2;
+                       return 0;
+               }
+               if (!rest) {
+                       /* abbreviated? */
+                       if (!strncmp(options->long_name, arg, arg_end - arg)) {
+is_abbreviated:
+                               if (abbrev_option) {
+                                       /*
+                                        * If this is abbreviated, it is
+                                        * ambiguous. So when there is no
+                                        * exact match later, we need to
+                                        * error out.
+                                        */
+                                       ambiguous_option = abbrev_option;
+                                       ambiguous_flags = abbrev_flags;
+                               }
+                               if (!(flags & OPT_UNSET) && *arg_end)
+                                       p->opt = arg_end + 1;
+                               abbrev_option = options;
+                               abbrev_flags = flags;
+                               continue;
+                       }
+                       /* negated and abbreviated very much? */
+                       if (!prefixcmp("no-", arg)) {
+                               flags |= OPT_UNSET;
+                               goto is_abbreviated;
+                       }
+                       /* negated? */
+                       if (strncmp(arg, "no-", 3))
+                               continue;
+                       flags |= OPT_UNSET;
+                       rest = skip_prefix(arg + 3, options->long_name);
+                       /* abbreviated and negated? */
+                       if (!rest && !prefixcmp(options->long_name, arg + 3))
+                               goto is_abbreviated;
+                       if (!rest)
+                               continue;
+               }
+               if (*rest) {
+                       if (*rest != '=')
+                               continue;
+                       p->opt = rest + 1;
+               }
+               return get_value(p, options, flags);
+       }
+
+       if (ambiguous_option)
+               return pr_err("Ambiguous option: %s "
+                               "(could be --%s%s or --%s%s)",
+                               arg,
+                               (ambiguous_flags & OPT_UNSET) ?  "no-" : "",
+                               ambiguous_option->long_name,
+                               (abbrev_flags & OPT_UNSET) ?  "no-" : "",
+                               abbrev_option->long_name);
+       if (abbrev_option)
+               return get_value(p, abbrev_option, abbrev_flags);
+       return -2;
+}
+
+
+static void parse_options_start(struct parse_opt_ctx_t *ctx, int argc,
+               const char **argv, int flags)
+{
+       memset(ctx, 0, sizeof(*ctx));
+       ctx->argc = argc;
+       ctx->argv = argv;
+       ctx->out  = argv;
+       ctx->cpidx = ((flags & PARSE_OPT_KEEP_ARGV0) != 0);
+       ctx->flags = flags;
+       if ((flags & PARSE_OPT_KEEP_UNKNOWN) &&
+                       (flags & PARSE_OPT_STOP_AT_NON_OPTION))
+               die("STOP_AT_NON_OPTION and KEEP_UNKNOWN don't go together");
+}
+
+static int parse_options_end(struct parse_opt_ctx_t *ctx)
+{
+       memmove(ctx->out + ctx->cpidx, ctx->argv, ctx->argc * sizeof(*ctx->out));
+       ctx->out[ctx->cpidx + ctx->argc] = NULL;
+       return ctx->cpidx + ctx->argc;
+}
+
+
+static int parse_options_step(struct parse_opt_ctx_t *ctx,
+               const struct option *options, const char * const usagestr[])
+{
+       int internal_help = !(ctx->flags & PARSE_OPT_NO_INTERNAL_HELP);
+
+       /* we must reset ->opt, unknown short option leave it dangling */
+       ctx->opt = NULL;
+
+       for (; ctx->argc; ctx->argc--, ctx->argv++) {
+               const char *arg = ctx->argv[0];
+
+               if (*arg != '-' || !arg[1]) {
+                       if (ctx->flags & PARSE_OPT_STOP_AT_NON_OPTION)
+                               break;
+                       ctx->out[ctx->cpidx++] = ctx->argv[0];
+                       continue;
+               }
+
+               if (arg[1] != '-') {
+                       ctx->opt = arg + 1;
+                       if (internal_help && *ctx->opt == 'h')
+                               return parse_options_usage(usagestr, options);
+                       switch (parse_short_opt(ctx, options)) {
+                       case -1:
+                               return parse_options_usage(usagestr, options);
+                       case -2:
+                               goto unknown;
+                       default:
+                               break;
+                       }
+                       if (ctx->opt)
+                               check_typos(arg + 1, options);
+                       while (ctx->opt) {
+                               if (internal_help && *ctx->opt == 'h')
+                                       return parse_options_usage(usagestr,
+                                                       options);
+                               switch (parse_short_opt(ctx, options)) {
+                               case -1:
+                                       return parse_options_usage(usagestr,
+                                                       options);
+                               case -2:
+                                       /* fake a short option thing to hide
+                                        * the fact that we may have
+                                        * started to parse aggregated stuff
+                                        *
+                                        * This is leaky, too bad.
+                                        */
+                                       ctx->argv[0] = strdup(ctx->opt - 1);
+                                       *(char *)ctx->argv[0] = '-';
+                                       goto unknown;
+                               default:
+                                       break;
+                               }
+                       }
+                       continue;
+               }
+
+               if (!arg[2]) { /* "--" */
+                       if (!(ctx->flags & PARSE_OPT_KEEP_DASHDASH)) {
+                               ctx->argc--;
+                               ctx->argv++;
+                       }
+                       break;
+               }
+
+               if (internal_help && !strcmp(arg + 2, "help-all"))
+                       return usage_with_options_internal(usagestr, options,
+                                       1);
+               if (internal_help && !strcmp(arg + 2, "help"))
+                       return parse_options_usage(usagestr, options);
+               switch (parse_long_opt(ctx, arg + 2, options)) {
+               case -1:
+                       return parse_options_usage(usagestr, options);
+               case -2:
+                       goto unknown;
+               default:
+                       break;
+               }
+               continue;
+unknown:
+               if (!(ctx->flags & PARSE_OPT_KEEP_UNKNOWN))
+                       return PARSE_OPT_UNKNOWN;
+               ctx->out[ctx->cpidx++] = ctx->argv[0];
+               ctx->opt = NULL;
+       }
+       return PARSE_OPT_DONE;
+}
+
+int parse_options(int argc, const char **argv, const struct option *options,
+               const char * const usagestr[], int flags)
+{
+       struct parse_opt_ctx_t ctx;
+
+       parse_options_start(&ctx, argc, argv, flags);
+       switch (parse_options_step(&ctx, options, usagestr)) {
+       case PARSE_OPT_HELP:
+               exit(129);
+       case PARSE_OPT_DONE:
+               break;
+       default: /* PARSE_OPT_UNKNOWN */
+               if (ctx.argv[0][1] == '-') {
+                       pr_err("unknown option `%s'", ctx.argv[0] + 2);
+               } else {
+                       pr_err("unknown switch `%c'", *ctx.opt);
+               }
+               usage_with_options(usagestr, options);
+       }
+
+       return parse_options_end(&ctx);
+}
diff --git a/tools/kvm/util/rbtree-interval.c b/tools/kvm/util/rbtree-interval.c
new file mode 100644 (file)
index 0000000..c82ce98
--- /dev/null
@@ -0,0 +1,118 @@
+#include <kvm/rbtree-interval.h>
+#include <stddef.h>
+#include <errno.h>
+
+struct rb_int_node *rb_int_search_single(struct rb_root *root, u64 point)
+{
+       struct rb_node *node = root->rb_node;
+       struct rb_node *lowest = NULL;
+
+       while (node) {
+               struct rb_int_node *cur = rb_int(node);
+
+               if (node->rb_left && (rb_int(node->rb_left)->max_high > point)) {
+                       node = node->rb_left;
+               } else if (cur->low <= point && cur->high > point) {
+                       lowest = node;
+                       break;
+               } else if (point > cur->low) {
+                       node = node->rb_right;
+               } else {
+                       break;
+               }
+       }
+
+       if (lowest == NULL)
+               return NULL;
+
+       return rb_int(lowest);
+}
+
+struct rb_int_node *rb_int_search_range(struct rb_root *root, u64 low, u64 high)
+{
+       struct rb_int_node *range;
+
+       range = rb_int_search_single(root, low);
+       if (range == NULL)
+               return NULL;
+
+       /* We simply verify that 'high' is smaller than the end of the range where 'low' is located */
+       if (range->high < high)
+               return NULL;
+
+       return range;
+}
+
+/*
+ * Update a node after it has been linked into the tree:
+ */
+static void propagate_callback(struct rb_node *node, struct rb_node *stop)
+{
+       struct rb_int_node *i_node = rb_int(node);
+
+       i_node->max_high = i_node->high;
+
+       if (node->rb_left)
+               i_node->max_high = max(i_node->max_high, rb_int(node->rb_left)->max_high);
+       if (node->rb_right)
+               i_node->max_high = max(i_node->max_high, rb_int(node->rb_right)->max_high);
+}
+
+/*
+ * Copy the extra data to a new node:
+ */
+static void copy_callback(struct rb_node *node_old, struct rb_node *node_new)
+{
+       struct rb_int_node *i_node_old = rb_int(node_old);
+       struct rb_int_node *i_node_new = rb_int(node_new);
+
+       i_node_new->low         = i_node_old->low;
+       i_node_new->high        = i_node_old->high;
+
+       i_node_new->max_high    = i_node_old->max_high;
+}
+
+/*
+ * Update after tree rotation:
+ */
+static void rotate_callback(struct rb_node *node_old, struct rb_node *node_new)
+{
+       propagate_callback(node_old, NULL);
+       propagate_callback(node_new, NULL);
+}
+
+/*
+ * All augmented rbtree callbacks:
+ */
+struct rb_augment_callbacks callbacks = {
+       .propagate      = propagate_callback,
+       .copy           = copy_callback,
+       .rotate         = rotate_callback,
+};
+
+int rb_int_insert(struct rb_root *root, struct rb_int_node *i_node)
+{
+       struct rb_node **node = &root->rb_node, *parent = NULL;
+
+       while (*node) {
+               int result = i_node->low - rb_int(*node)->low;
+
+               parent = *node;
+               if (result < 0)
+                       node    = &((*node)->rb_left);
+               else if (result > 0)
+                       node    = &((*node)->rb_right);
+               else
+                       return -EEXIST;
+       }
+
+       rb_link_node(&i_node->node, parent, node);
+       rb_insert_augmented(&i_node->node, root, &callbacks);
+
+       return 0;
+}
+
+void rb_int_erase(struct rb_root *root, struct rb_int_node *node)
+{
+       rb_erase_augmented(&node->node, root, &callbacks);
+}
diff --git a/tools/kvm/util/read-write.c b/tools/kvm/util/read-write.c
new file mode 100644 (file)
index 0000000..44709df
--- /dev/null
@@ -0,0 +1,354 @@
+#include "kvm/read-write.h"
+
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+/* Same as read(2) except that this function never returns EAGAIN or EINTR. */
+ssize_t xread(int fd, void *buf, size_t count)
+{
+       ssize_t nr;
+
+restart:
+       nr = read(fd, buf, count);
+       if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR)))
+               goto restart;
+
+       return nr;
+}
+
+/* Same as write(2) except that this function never returns EAGAIN or EINTR. */
+ssize_t xwrite(int fd, const void *buf, size_t count)
+{
+       ssize_t nr;
+
+restart:
+       nr = write(fd, buf, count);
+       if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR)))
+               goto restart;
+
+       return nr;
+}
+
+ssize_t read_in_full(int fd, void *buf, size_t count)
+{
+       ssize_t total = 0;
+       char *p = buf;
+
+       while (count > 0) {
+               ssize_t nr;
+
+               nr = xread(fd, p, count);
+               if (nr <= 0) {
+                       if (total > 0)
+                               return total;
+
+                       return -1;
+               }
+
+               count -= nr;
+               total += nr;
+               p += nr;
+       }
+
+       return total;
+}
+
+ssize_t write_in_full(int fd, const void *buf, size_t count)
+{
+       const char *p = buf;
+       ssize_t total = 0;
+
+       while (count > 0) {
+               ssize_t nr;
+
+               nr = xwrite(fd, p, count);
+               if (nr < 0)
+                       return -1;
+               if (nr == 0) {
+                       errno = ENOSPC;
+                       return -1;
+               }
+               count -= nr;
+               total += nr;
+               p += nr;
+       }
+
+       return total;
+}
+
+/* Same as pread(2) except that this function never returns EAGAIN or EINTR. */
+ssize_t xpread(int fd, void *buf, size_t count, off_t offset)
+{
+       ssize_t nr;
+
+restart:
+       nr = pread(fd, buf, count, offset);
+       if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR)))
+               goto restart;
+
+       return nr;
+}
+
+/* Same as pwrite(2) except that this function never returns EAGAIN or EINTR. */
+ssize_t xpwrite(int fd, const void *buf, size_t count, off_t offset)
+{
+       ssize_t nr;
+
+restart:
+       nr = pwrite(fd, buf, count, offset);
+       if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR)))
+               goto restart;
+
+       return nr;
+}
+
+ssize_t pread_in_full(int fd, void *buf, size_t count, off_t offset)
+{
+       ssize_t total = 0;
+       char *p = buf;
+
+       while (count > 0) {
+               ssize_t nr;
+
+               nr = xpread(fd, p, count, offset);
+               if (nr <= 0) {
+                       if (total > 0)
+                               return total;
+
+                       return -1;
+               }
+
+               count -= nr;
+               total += nr;
+               p += nr;
+               offset += nr;
+       }
+
+       return total;
+}
+
+ssize_t pwrite_in_full(int fd, const void *buf, size_t count, off_t offset)
+{
+       const char *p = buf;
+       ssize_t total = 0;
+
+       while (count > 0) {
+               ssize_t nr;
+
+               nr = xpwrite(fd, p, count, offset);
+               if (nr < 0)
+                       return -1;
+               if (nr == 0) {
+                       errno = ENOSPC;
+                       return -1;
+               }
+               count -= nr;
+               total += nr;
+               p += nr;
+               offset += nr;
+       }
+
+       return total;
+}
+
+/* Same as readv(2) except that this function never returns EAGAIN or EINTR. */
+ssize_t xreadv(int fd, const struct iovec *iov, int iovcnt)
+{
+       ssize_t nr;
+
+restart:
+       nr = readv(fd, iov, iovcnt);
+       if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR)))
+               goto restart;
+
+       return nr;
+}
+
+/* Same as writev(2) except that this function never returns EAGAIN or EINTR. */
+ssize_t xwritev(int fd, const struct iovec *iov, int iovcnt)
+{
+       ssize_t nr;
+
+restart:
+       nr = writev(fd, iov, iovcnt);
+       if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR)))
+               goto restart;
+
+       return nr;
+}
+
+static inline ssize_t get_iov_size(const struct iovec *iov, int iovcnt)
+{
+       size_t size = 0;
+       while (iovcnt--)
+               size += (iov++)->iov_len;
+
+       return size;
+}
+
+static inline void shift_iovec(const struct iovec **iov, int *iovcnt,
+                               size_t nr, ssize_t *total, size_t *count, off_t *offset)
+{
+       while (nr >= (*iov)->iov_len) {
+               nr -= (*iov)->iov_len;
+               *total += (*iov)->iov_len;
+               *count -= (*iov)->iov_len;
+               if (offset)
+                       *offset += (*iov)->iov_len;
+               (*iovcnt)--;
+               (*iov)++;
+       }
+}
+
+ssize_t readv_in_full(int fd, const struct iovec *iov, int iovcnt)
+{
+       ssize_t total = 0;
+       size_t count = get_iov_size(iov, iovcnt);
+
+       while (count > 0) {
+               ssize_t nr;
+
+               nr = xreadv(fd, iov, iovcnt);
+               if (nr <= 0) {
+                       if (total > 0)
+                               return total;
+
+                       return -1;
+               }
+
+               shift_iovec(&iov, &iovcnt, nr, &total, &count, NULL);
+       }
+
+       return total;
+}
+
+ssize_t writev_in_full(int fd, const struct iovec *iov, int iovcnt)
+{
+       ssize_t total = 0;
+       size_t count = get_iov_size(iov, iovcnt);
+
+       while (count > 0) {
+               ssize_t nr;
+
+               nr = xwritev(fd, iov, iovcnt);
+               if (nr < 0)
+                       return -1;
+               if (nr == 0) {
+                       errno = ENOSPC;
+                       return -1;
+               }
+
+               shift_iovec(&iov, &iovcnt, nr, &total, &count, NULL);
+       }
+
+       return total;
+}
+
+/* Same as preadv(2) except that this function never returns EAGAIN or EINTR. */
+ssize_t xpreadv(int fd, const struct iovec *iov, int iovcnt, off_t offset)
+{
+       ssize_t nr;
+
+restart:
+       nr = preadv(fd, iov, iovcnt, offset);
+       if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR)))
+               goto restart;
+
+       return nr;
+}
+
+/* Same as pwritev(2) except that this function never returns EAGAIN or EINTR. */
+ssize_t xpwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset)
+{
+       ssize_t nr;
+
+restart:
+       nr = pwritev(fd, iov, iovcnt, offset);
+       if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR)))
+               goto restart;
+
+       return nr;
+}
+
+ssize_t preadv_in_full(int fd, const struct iovec *iov, int iovcnt, off_t offset)
+{
+       ssize_t total = 0;
+       size_t count = get_iov_size(iov, iovcnt);
+
+       while (count > 0) {
+               ssize_t nr;
+
+               nr = xpreadv(fd, iov, iovcnt, offset);
+               if (nr <= 0) {
+                       if (total > 0)
+                               return total;
+
+                       return -1;
+               }
+
+               shift_iovec(&iov, &iovcnt, nr, &total, &count, &offset);
+       }
+
+       return total;
+}
+
+ssize_t pwritev_in_full(int fd, const struct iovec *iov, int iovcnt, off_t offset)
+{
+       ssize_t total = 0;
+       size_t count = get_iov_size(iov, iovcnt);
+
+       while (count > 0) {
+               ssize_t nr;
+
+               nr = xpwritev(fd, iov, iovcnt, offset);
+               if (nr < 0)
+                       return -1;
+               if (nr == 0) {
+                       errno = ENOSPC;
+                       return -1;
+               }
+
+               shift_iovec(&iov, &iovcnt, nr, &total, &count, &offset);
+       }
+
+       return total;
+}
+
+#ifdef CONFIG_HAS_AIO
+int aio_pwritev(io_context_t ctx, struct iocb *iocb, int fd, const struct iovec *iov, int iovcnt,
+               off_t offset, int ev, void *param)
+{
+       struct iocb *ios[1] = { iocb };
+       int ret;
+
+       io_prep_pwritev(iocb, fd, iov, iovcnt, offset);
+       io_set_eventfd(iocb, ev);
+       iocb->data = param;
+
+restart:
+       ret = io_submit(ctx, 1, ios);
+       if (ret == -EAGAIN)
+               goto restart;
+       return ret;
+}
+
+int aio_preadv(io_context_t ctx, struct iocb *iocb, int fd, const struct iovec *iov, int iovcnt,
+               off_t offset, int ev, void *param)
+{
+       struct iocb *ios[1] = { iocb };
+       int ret;
+
+       io_prep_preadv(iocb, fd, iov, iovcnt, offset);
+       io_set_eventfd(iocb, ev);
+       iocb->data = param;
+
+restart:
+       ret = io_submit(ctx, 1, ios);
+       if (ret == -EAGAIN)
+               goto restart;
+       return ret;
+}
+#endif
diff --git a/tools/kvm/util/set_private_br.sh b/tools/kvm/util/set_private_br.sh
new file mode 100755 (executable)
index 0000000..49867dd
--- /dev/null
@@ -0,0 +1,51 @@
+#!/bin/bash
+#
+# Author: Amos Kong <kongjianjun@gmail.com>
+# Date: Apr 14, 2011
+# Description: this script is used to create/delete a private bridge,
+# launch a dhcp server on the bridge by dnsmasq.
+#
+# @ ./set_private_br.sh $bridge_name $subnet_prefix
+# @ ./set_private_br.sh vbr0 192.168.33
+
+brname='vbr0'
+subnet='192.168.33'
+
+add_br()
+{
+    echo "add new private bridge: $brname"
+    /usr/sbin/brctl addbr $brname
+    echo 1 > /proc/sys/net/ipv6/conf/$brname/disable_ipv6
+    echo 1 > /proc/sys/net/ipv4/ip_forward
+    /usr/sbin/brctl stp $brname on
+    /usr/sbin/brctl setfd $brname 0
+    ifconfig $brname $subnet.1
+    ifconfig $brname up
+    # Add forward rule, then guest can access public network
+    iptables -t nat -A POSTROUTING -s $subnet.254/24 ! -d $subnet.254/24 -j MASQUERADE
+    /etc/init.d/dnsmasq stop
+    /etc/init.d/tftpd-hpa stop 2>/dev/null
+    dnsmasq --strict-order --bind-interfaces --listen-address $subnet.1 --dhcp-range $subnet.1,$subnet.254 $tftp_cmd
+}
+
+del_br()
+{
+    echo "cleanup bridge setup"
+    kill -9 `pgrep dnsmasq|tail -1`
+    ifconfig $brname down
+    /usr/sbin/brctl delbr $brname
+    iptables -t nat -D POSTROUTING -s $subnet.254/24 ! -d $subnet.254/24 -j MASQUERADE
+}
+
+
+if [ $# = 0 ]; then
+    del_br 2>/dev/null
+    exit
+fi
+if [ $# > 1 ]; then
+    brname="$1"
+fi
+if [ $# = 2 ]; then
+    subnet="$2"
+fi
+add_br
diff --git a/tools/kvm/util/strbuf.c b/tools/kvm/util/strbuf.c
new file mode 100644 (file)
index 0000000..99d6b0c
--- /dev/null
@@ -0,0 +1,62 @@
+
+/* user defined headers */
+#include <kvm/util.h>
+#include <kvm/strbuf.h>
+
+int prefixcmp(const char *str, const char *prefix)
+{
+       for (; ; str++, prefix++) {
+               if (!*prefix)
+                       return 0;
+               else if (*str != *prefix)
+                       return (unsigned char)*prefix - (unsigned char)*str;
+       }
+}
+
+/**
+ * strlcat - Append a length-limited, %NUL-terminated string to another
+ * @dest: The string to be appended to
+ * @src: The string to append to it
+ * @count: The size of the destination buffer.
+ */
+size_t strlcat(char *dest, const char *src, size_t count)
+{
+       size_t dsize = strlen(dest);
+       size_t len = strlen(src);
+       size_t res = dsize + len;
+
+       DIE_IF(dsize >= count);
+
+       dest += dsize;
+       count -= dsize;
+       if (len >= count)
+               len = count - 1;
+
+       memcpy(dest, src, len);
+       dest[len] = 0;
+
+       return res;
+}
+
+/**
+ * strlcpy - Copy a %NUL terminated string into a sized buffer
+ * @dest: Where to copy the string to
+ * @src: Where to copy the string from
+ * @size: size of destination buffer
+ *
+ * Compatible with *BSD: the result is always a valid
+ * NUL-terminated string that fits in the buffer (unless,
+ * of course, the buffer size is zero). It does not pad
+ * out the result like strncpy() does.
+ */
+size_t strlcpy(char *dest, const char *src, size_t size)
+{
+       size_t ret = strlen(src);
+
+       if (size) {
+               size_t len = (ret >= size) ? size - 1 : ret;
+               memcpy(dest, src, len);
+               dest[len] = '\0';
+       }
+       return ret;
+}
diff --git a/tools/kvm/util/threadpool.c b/tools/kvm/util/threadpool.c
new file mode 100644 (file)
index 0000000..85ac7e7
--- /dev/null
@@ -0,0 +1,173 @@
+#include "kvm/threadpool.h"
+#include "kvm/mutex.h"
+#include "kvm/kvm.h"
+
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <pthread.h>
+#include <stdbool.h>
+
+static pthread_mutex_t job_mutex       = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t thread_mutex    = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t  job_cond        = PTHREAD_COND_INITIALIZER;
+
+static LIST_HEAD(head);
+
+static pthread_t       *threads;
+static long            threadcount;
+static bool            running;
+
+static struct thread_pool__job *thread_pool__job_pop_locked(void)
+{
+       struct thread_pool__job *job;
+
+       if (list_empty(&head))
+               return NULL;
+
+       job = list_first_entry(&head, struct thread_pool__job, queue);
+       list_del(&job->queue);
+
+       return job;
+}
+
+static void thread_pool__job_push_locked(struct thread_pool__job *job)
+{
+       list_add_tail(&job->queue, &head);
+}
+
+static struct thread_pool__job *thread_pool__job_pop(void)
+{
+       struct thread_pool__job *job;
+
+       mutex_lock(&job_mutex);
+       job = thread_pool__job_pop_locked();
+       mutex_unlock(&job_mutex);
+       return job;
+}
+
+static void thread_pool__job_push(struct thread_pool__job *job)
+{
+       mutex_lock(&job_mutex);
+       thread_pool__job_push_locked(job);
+       mutex_unlock(&job_mutex);
+}
+
+static void thread_pool__handle_job(struct thread_pool__job *job)
+{
+       while (job) {
+               job->callback(job->kvm, job->data);
+
+               mutex_lock(&job->mutex);
+
+               if (--job->signalcount > 0)
+                       /* If the job was signaled again while we were working */
+                       thread_pool__job_push(job);
+
+               mutex_unlock(&job->mutex);
+
+               job = thread_pool__job_pop();
+       }
+}
+
+static void thread_pool__threadfunc_cleanup(void *param)
+{
+       mutex_unlock(&job_mutex);
+}
+
+static void *thread_pool__threadfunc(void *param)
+{
+       pthread_cleanup_push(thread_pool__threadfunc_cleanup, NULL);
+
+       while (running) {
+               struct thread_pool__job *curjob = NULL;
+
+               mutex_lock(&job_mutex);
+               while (running && (curjob = thread_pool__job_pop_locked()) == NULL)
+                       pthread_cond_wait(&job_cond, &job_mutex);
+               mutex_unlock(&job_mutex);
+
+               if (running)
+                       thread_pool__handle_job(curjob);
+       }
+
+       pthread_cleanup_pop(0);
+
+       return NULL;
+}
+
+static int thread_pool__addthread(void)
+{
+       int res;
+       void *newthreads;
+
+       mutex_lock(&thread_mutex);
+       newthreads = realloc(threads, (threadcount + 1) * sizeof(pthread_t));
+       if (newthreads == NULL) {
+               mutex_unlock(&thread_mutex);
+               return -1;
+       }
+
+       threads = newthreads;
+
+       res = pthread_create(threads + threadcount, NULL,
+                            thread_pool__threadfunc, NULL);
+
+       if (res == 0)
+               threadcount++;
+       mutex_unlock(&thread_mutex);
+
+       return res;
+}
+
+int thread_pool__init(struct kvm *kvm)
+{
+       unsigned long i;
+       unsigned int thread_count = sysconf(_SC_NPROCESSORS_ONLN);
+
+       running = true;
+
+       for (i = 0; i < thread_count; i++)
+               if (thread_pool__addthread() < 0)
+                       return i;
+
+       return i;
+}
+late_init(thread_pool__init);
+
+int thread_pool__exit(struct kvm *kvm)
+{
+       int i;
+       void *NUL = NULL;
+
+       running = false;
+
+       for (i = 0; i < threadcount; i++) {
+               mutex_lock(&job_mutex);
+               pthread_cond_signal(&job_cond);
+               mutex_unlock(&job_mutex);
+       }
+
+       for (i = 0; i < threadcount; i++) {
+               pthread_join(threads[i], NUL);
+       }
+
+       return 0;
+}
+late_exit(thread_pool__exit);
+
+void thread_pool__do_job(struct thread_pool__job *job)
+{
+       struct thread_pool__job *jobinfo = job;
+
+       if (jobinfo == NULL || jobinfo->callback == NULL)
+               return;
+
+       mutex_lock(&jobinfo->mutex);
+       if (jobinfo->signalcount++ == 0)
+               thread_pool__job_push(job);
+       mutex_unlock(&jobinfo->mutex);
+
+       mutex_lock(&job_mutex);
+       pthread_cond_signal(&job_cond);
+       mutex_unlock(&job_mutex);
+}
diff --git a/tools/kvm/util/util.c b/tools/kvm/util/util.c
new file mode 100644 (file)
index 0000000..c11a15a
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * Taken from perf which in turn take it from GIT
+ */
+
+#include "kvm/util.h"
+
+#include <kvm/kvm.h>
+#include <linux/magic.h>       /* For HUGETLBFS_MAGIC */
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/statfs.h>
+
+static void report(const char *prefix, const char *err, va_list params)
+{
+       char msg[1024];
+       vsnprintf(msg, sizeof(msg), err, params);
+       fprintf(stderr, " %s%s\n", prefix, msg);
+}
+
+static NORETURN void die_builtin(const char *err, va_list params)
+{
+       report(" Fatal: ", err, params);
+       exit(128);
+}
+
+static void error_builtin(const char *err, va_list params)
+{
+       report(" Error: ", err, params);
+}
+
+static void warn_builtin(const char *warn, va_list params)
+{
+       report(" Warning: ", warn, params);
+}
+
+static void info_builtin(const char *info, va_list params)
+{
+       report(" Info: ", info, params);
+}
+
+void die(const char *err, ...)
+{
+       va_list params;
+
+       va_start(params, err);
+       die_builtin(err, params);
+       va_end(params);
+}
+
+int pr_err(const char *err, ...)
+{
+       va_list params;
+
+       va_start(params, err);
+       error_builtin(err, params);
+       va_end(params);
+       return -1;
+}
+
+void pr_warning(const char *warn, ...)
+{
+       va_list params;
+
+       va_start(params, warn);
+       warn_builtin(warn, params);
+       va_end(params);
+}
+
+void pr_info(const char *info, ...)
+{
+       va_list params;
+
+       va_start(params, info);
+       info_builtin(info, params);
+       va_end(params);
+}
+
+void die_perror(const char *s)
+{
+       perror(s);
+       exit(1);
+}
+
+void *mmap_hugetlbfs(struct kvm *kvm, const char *htlbfs_path, u64 size)
+{
+       char mpath[PATH_MAX];
+       int fd;
+       struct statfs sfs;
+       void *addr;
+       unsigned long blk_size;
+
+       if (statfs(htlbfs_path, &sfs) < 0)
+               die("Can't stat %s\n", htlbfs_path);
+
+       if ((unsigned int)sfs.f_type != HUGETLBFS_MAGIC)
+               die("%s is not hugetlbfs!\n", htlbfs_path);
+
+       blk_size = (unsigned long)sfs.f_bsize;
+       if (sfs.f_bsize == 0 || blk_size > size) {
+               die("Can't use hugetlbfs pagesize %ld for mem size %lld\n",
+                   blk_size, size);
+       }
+
+       kvm->ram_pagesize = blk_size;
+
+       snprintf(mpath, PATH_MAX, "%s/kvmtoolXXXXXX", htlbfs_path);
+       fd = mkstemp(mpath);
+       if (fd < 0)
+               die("Can't open %s for hugetlbfs map\n", mpath);
+       unlink(mpath);
+       if (ftruncate(fd, size) < 0)
+               die("Can't ftruncate for mem mapping size %lld\n",
+                   size);
+       addr = mmap(NULL, size, PROT_RW, MAP_PRIVATE, fd, 0);
+       close(fd);
+
+       return addr;
+}
+
+/* This function wraps the decision between hugetlbfs map (if requested) or normal mmap */
+void *mmap_anon_or_hugetlbfs(struct kvm *kvm, const char *hugetlbfs_path, u64 size)
+{
+       if (hugetlbfs_path)
+               /*
+                * We don't /need/ to map guest RAM from hugetlbfs, but we do so
+                * if the user specifies a hugetlbfs path.
+                */
+               return mmap_hugetlbfs(kvm, hugetlbfs_path, size);
+       else {
+               kvm->ram_pagesize = getpagesize();
+               return mmap(NULL, size, PROT_RW, MAP_ANON_NORESERVE, -1, 0);
+       }
+}
diff --git a/tools/kvm/virtio/9p-pdu.c b/tools/kvm/virtio/9p-pdu.c
new file mode 100644 (file)
index 0000000..b9ce8ce
--- /dev/null
@@ -0,0 +1,287 @@
+#include "kvm/util.h"
+#include "kvm/virtio-9p.h"
+
+#include <endian.h>
+#include <stdint.h>
+
+#include <linux/compiler.h>
+#include <net/9p/9p.h>
+
+static void virtio_p9_pdu_read(struct p9_pdu *pdu, void *data, size_t size)
+{
+       size_t len;
+       int i, copied = 0;
+       u16 iov_cnt = pdu->out_iov_cnt;
+       size_t offset = pdu->read_offset;
+       struct iovec *iov = pdu->out_iov;
+
+       for (i = 0; i < iov_cnt && size; i++) {
+               if (offset >= iov[i].iov_len) {
+                       offset -= iov[i].iov_len;
+                       continue;
+               } else {
+                       len = MIN(iov[i].iov_len - offset, size);
+                       memcpy(data, iov[i].iov_base + offset, len);
+                       size -= len;
+                       data += len;
+                       offset = 0;
+                       copied += len;
+               }
+       }
+       pdu->read_offset += copied;
+}
+
+static void virtio_p9_pdu_write(struct p9_pdu *pdu,
+                               const void *data, size_t size)
+{
+       size_t len;
+       int i, copied = 0;
+       u16 iov_cnt = pdu->in_iov_cnt;
+       size_t offset = pdu->write_offset;
+       struct iovec *iov = pdu->in_iov;
+
+       for (i = 0; i < iov_cnt && size; i++) {
+               if (offset >= iov[i].iov_len) {
+                       offset -= iov[i].iov_len;
+                       continue;
+               } else {
+                       len = MIN(iov[i].iov_len - offset, size);
+                       memcpy(iov[i].iov_base + offset, data, len);
+                       size -= len;
+                       data += len;
+                       offset = 0;
+                       copied += len;
+               }
+       }
+       pdu->write_offset += copied;
+}
+
+static void virtio_p9_wstat_free(struct p9_wstat *stbuf)
+{
+       free(stbuf->name);
+       free(stbuf->uid);
+       free(stbuf->gid);
+       free(stbuf->muid);
+}
+
+static int virtio_p9_decode(struct p9_pdu *pdu, const char *fmt, va_list ap)
+{
+       int retval = 0;
+       const char *ptr;
+
+       for (ptr = fmt; *ptr; ptr++) {
+               switch (*ptr) {
+               case 'b':
+               {
+                       int8_t *val = va_arg(ap, int8_t *);
+                       virtio_p9_pdu_read(pdu, val, sizeof(*val));
+               }
+               break;
+               case 'w':
+               {
+                       int16_t le_val;
+                       int16_t *val = va_arg(ap, int16_t *);
+                       virtio_p9_pdu_read(pdu, &le_val, sizeof(le_val));
+                       *val = le16toh(le_val);
+               }
+               break;
+               case 'd':
+               {
+                       int32_t le_val;
+                       int32_t *val = va_arg(ap, int32_t *);
+                       virtio_p9_pdu_read(pdu, &le_val, sizeof(le_val));
+                       *val = le32toh(le_val);
+               }
+               break;
+               case 'q':
+               {
+                       int64_t le_val;
+                       int64_t *val = va_arg(ap, int64_t *);
+                       virtio_p9_pdu_read(pdu, &le_val, sizeof(le_val));
+                       *val = le64toh(le_val);
+               }
+               break;
+               case 's':
+               {
+                       int16_t len;
+                       char **str = va_arg(ap, char **);
+
+                       virtio_p9_pdu_readf(pdu, "w", &len);
+                       *str = malloc(len + 1);
+                       if (*str == NULL) {
+                               retval = ENOMEM;
+                               break;
+                       }
+                       virtio_p9_pdu_read(pdu, *str, len);
+                       (*str)[len] = 0;
+               }
+               break;
+               case 'Q':
+               {
+                       struct p9_qid *qid = va_arg(ap, struct p9_qid *);
+                       retval = virtio_p9_pdu_readf(pdu, "bdq",
+                                                    &qid->type, &qid->version,
+                                                    &qid->path);
+               }
+               break;
+               case 'S':
+               {
+                       struct p9_wstat *stbuf = va_arg(ap, struct p9_wstat *);
+                       memset(stbuf, 0, sizeof(struct p9_wstat));
+                       stbuf->n_uid = stbuf->n_gid = stbuf->n_muid = -1;
+                       retval = virtio_p9_pdu_readf(pdu, "wwdQdddqssss",
+                                               &stbuf->size, &stbuf->type,
+                                               &stbuf->dev, &stbuf->qid,
+                                               &stbuf->mode, &stbuf->atime,
+                                               &stbuf->mtime, &stbuf->length,
+                                               &stbuf->name, &stbuf->uid,
+                                               &stbuf->gid, &stbuf->muid);
+                       if (retval)
+                               virtio_p9_wstat_free(stbuf);
+               }
+               break;
+               case 'I':
+               {
+                       struct p9_iattr_dotl *p9attr = va_arg(ap,
+                                                      struct p9_iattr_dotl *);
+
+                       retval = virtio_p9_pdu_readf(pdu, "ddddqqqqq",
+                                                    &p9attr->valid,
+                                                    &p9attr->mode,
+                                                    &p9attr->uid,
+                                                    &p9attr->gid,
+                                                    &p9attr->size,
+                                                    &p9attr->atime_sec,
+                                                    &p9attr->atime_nsec,
+                                                    &p9attr->mtime_sec,
+                                                    &p9attr->mtime_nsec);
+               }
+               break;
+               default:
+                       retval = EINVAL;
+                       break;
+               }
+       }
+       return retval;
+}
+
+static int virtio_p9_pdu_encode(struct p9_pdu *pdu, const char *fmt, va_list ap)
+{
+       int retval = 0;
+       const char *ptr;
+
+       for (ptr = fmt; *ptr; ptr++) {
+               switch (*ptr) {
+               case 'b':
+               {
+                       int8_t val = va_arg(ap, int);
+                       virtio_p9_pdu_write(pdu, &val, sizeof(val));
+               }
+               break;
+               case 'w':
+               {
+                       int16_t val = htole16(va_arg(ap, int));
+                       virtio_p9_pdu_write(pdu, &val, sizeof(val));
+               }
+               break;
+               case 'd':
+               {
+                       int32_t val = htole32(va_arg(ap, int32_t));
+                       virtio_p9_pdu_write(pdu, &val, sizeof(val));
+               }
+               break;
+               case 'q':
+               {
+                       int64_t val = htole64(va_arg(ap, int64_t));
+                       virtio_p9_pdu_write(pdu, &val, sizeof(val));
+               }
+               break;
+               case 's':
+               {
+                       uint16_t len = 0;
+                       const char *s = va_arg(ap, char *);
+                       if (s)
+                               len = MIN(strlen(s), USHRT_MAX);
+                       virtio_p9_pdu_writef(pdu, "w", len);
+                       virtio_p9_pdu_write(pdu, s, len);
+               }
+               break;
+               case 'Q':
+               {
+                       struct p9_qid *qid = va_arg(ap, struct p9_qid *);
+                       retval = virtio_p9_pdu_writef(pdu, "bdq",
+                                                     qid->type, qid->version,
+                                                     qid->path);
+               }
+               break;
+               case 'S':
+               {
+                       struct p9_wstat *stbuf = va_arg(ap, struct p9_wstat *);
+                       retval = virtio_p9_pdu_writef(pdu, "wwdQdddqssss",
+                                               stbuf->size, stbuf->type,
+                                               stbuf->dev, &stbuf->qid,
+                                               stbuf->mode, stbuf->atime,
+                                               stbuf->mtime, stbuf->length,
+                                               stbuf->name, stbuf->uid,
+                                               stbuf->gid, stbuf->muid);
+               }
+               break;
+               case 'A':
+               {
+                       struct p9_stat_dotl *stbuf = va_arg(ap,
+                                                     struct p9_stat_dotl *);
+                       retval  = virtio_p9_pdu_writef(pdu,
+                                                      "qQdddqqqqqqqqqqqqqqq",
+                                                      stbuf->st_result_mask,
+                                                      &stbuf->qid,
+                                                      stbuf->st_mode,
+                                                      stbuf->st_uid,
+                                                      stbuf->st_gid,
+                                                      stbuf->st_nlink,
+                                                      stbuf->st_rdev,
+                                                      stbuf->st_size,
+                                                      stbuf->st_blksize,
+                                                      stbuf->st_blocks,
+                                                      stbuf->st_atime_sec,
+                                                      stbuf->st_atime_nsec,
+                                                      stbuf->st_mtime_sec,
+                                                      stbuf->st_mtime_nsec,
+                                                      stbuf->st_ctime_sec,
+                                                      stbuf->st_ctime_nsec,
+                                                      stbuf->st_btime_sec,
+                                                      stbuf->st_btime_nsec,
+                                                      stbuf->st_gen,
+                                                      stbuf->st_data_version);
+               }
+               break;
+               default:
+                       retval = EINVAL;
+                       break;
+               }
+       }
+       return retval;
+}
+
+int virtio_p9_pdu_readf(struct p9_pdu *pdu, const char *fmt, ...)
+{
+       int ret;
+       va_list ap;
+
+       va_start(ap, fmt);
+       ret = virtio_p9_decode(pdu, fmt, ap);
+       va_end(ap);
+
+       return ret;
+}
+
+int virtio_p9_pdu_writef(struct p9_pdu *pdu, const char *fmt, ...)
+{
+       int ret;
+       va_list ap;
+
+       va_start(ap, fmt);
+       ret = virtio_p9_pdu_encode(pdu, fmt, ap);
+       va_end(ap);
+
+       return ret;
+}
diff --git a/tools/kvm/virtio/9p.c b/tools/kvm/virtio/9p.c
new file mode 100644 (file)
index 0000000..835a8c4
--- /dev/null
@@ -0,0 +1,1432 @@
+#include "kvm/virtio-pci-dev.h"
+#include "kvm/ioport.h"
+#include "kvm/util.h"
+#include "kvm/threadpool.h"
+#include "kvm/irq.h"
+#include "kvm/virtio-9p.h"
+#include "kvm/guest_compat.h"
+#include "kvm/builtin-setup.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/vfs.h>
+
+#include <linux/virtio_ring.h>
+#include <linux/virtio_9p.h>
+#include <net/9p/9p.h>
+
+static LIST_HEAD(devs);
+static int compat_id = -1;
+
+static int insert_new_fid(struct p9_dev *dev, struct p9_fid *fid);
+static struct p9_fid *find_or_create_fid(struct p9_dev *dev, u32 fid)
+{
+       struct rb_node *node = dev->fids.rb_node;
+       struct p9_fid *pfid = NULL;
+
+       while (node) {
+               struct p9_fid *cur = rb_entry(node, struct p9_fid, node);
+
+               if (fid < cur->fid) {
+                       node = node->rb_left;
+               } else if (fid > cur->fid) {
+                       node = node->rb_right;
+               } else {
+                       return cur;
+               }
+       }
+
+       pfid = calloc(sizeof(*pfid), 1);
+       if (!pfid)
+               return NULL;
+
+       pfid->fid = fid;
+       strcpy(pfid->abs_path, dev->root_dir);
+       pfid->path = pfid->abs_path + strlen(dev->root_dir);
+
+       insert_new_fid(dev, pfid);
+
+       return pfid;
+}
+
+static int insert_new_fid(struct p9_dev *dev, struct p9_fid *fid)
+{
+       struct rb_node **node = &(dev->fids.rb_node), *parent = NULL;
+
+       while (*node) {
+               int result = fid->fid - rb_entry(*node, struct p9_fid, node)->fid;
+
+               parent = *node;
+               if (result < 0)
+                       node    = &((*node)->rb_left);
+               else if (result > 0)
+                       node    = &((*node)->rb_right);
+               else
+                       return -EEXIST;
+       }
+
+       rb_link_node(&fid->node, parent, node);
+       rb_insert_color(&fid->node, &dev->fids);
+       return 0;
+}
+
+static struct p9_fid *get_fid(struct p9_dev *p9dev, int fid)
+{
+       struct p9_fid *new;
+
+       new = find_or_create_fid(p9dev, fid);
+
+       return new;
+}
+
+/* Warning: Immediately use value returned from this function */
+static const char *rel_to_abs(struct p9_dev *p9dev,
+                             const char *path, char *abs_path)
+{
+       sprintf(abs_path, "%s/%s", p9dev->root_dir, path);
+
+       return abs_path;
+}
+
+static void stat2qid(struct stat *st, struct p9_qid *qid)
+{
+       *qid = (struct p9_qid) {
+               .path           = st->st_ino,
+               .version        = st->st_mtime,
+       };
+
+       if (S_ISDIR(st->st_mode))
+               qid->type       |= P9_QTDIR;
+}
+
+static void close_fid(struct p9_dev *p9dev, u32 fid)
+{
+       struct p9_fid *pfid = get_fid(p9dev, fid);
+
+       if (pfid->fd > 0)
+               close(pfid->fd);
+
+       if (pfid->dir)
+               closedir(pfid->dir);
+
+       rb_erase(&pfid->node, &p9dev->fids);
+       free(pfid);
+}
+
+static void virtio_p9_set_reply_header(struct p9_pdu *pdu, u32 size)
+{
+       u8 cmd;
+       u16 tag;
+
+       pdu->read_offset = sizeof(u32);
+       virtio_p9_pdu_readf(pdu, "bw", &cmd, &tag);
+       pdu->write_offset = 0;
+       /* cmd + 1 is the reply message */
+       virtio_p9_pdu_writef(pdu, "dbw", size, cmd + 1, tag);
+}
+
+static u16 virtio_p9_update_iov_cnt(struct iovec iov[], u32 count, int iov_cnt)
+{
+       int i;
+       u32 total = 0;
+       for (i = 0; (i < iov_cnt) && (total < count); i++) {
+               if (total + iov[i].iov_len > count) {
+                       /* we don't need this iov fully */
+                       iov[i].iov_len -= ((total + iov[i].iov_len) - count);
+                       i++;
+                       break;
+               }
+               total += iov[i].iov_len;
+       }
+       return i;
+}
+
+static void virtio_p9_error_reply(struct p9_dev *p9dev,
+                                 struct p9_pdu *pdu, int err, u32 *outlen)
+{
+       u16 tag;
+
+       pdu->write_offset = VIRTIO_9P_HDR_LEN;
+       virtio_p9_pdu_writef(pdu, "d", err);
+       *outlen = pdu->write_offset;
+
+       /* read the tag from input */
+       pdu->read_offset = sizeof(u32) + sizeof(u8);
+       virtio_p9_pdu_readf(pdu, "w", &tag);
+
+       /* Update the header */
+       pdu->write_offset = 0;
+       virtio_p9_pdu_writef(pdu, "dbw", *outlen, P9_RLERROR, tag);
+}
+
+static void virtio_p9_version(struct p9_dev *p9dev,
+                             struct p9_pdu *pdu, u32 *outlen)
+{
+       u32 msize;
+       char *version;
+       virtio_p9_pdu_readf(pdu, "ds", &msize, &version);
+       /*
+        * reply with the same msize the client sent us
+        * Error out if the request is not for 9P2000.L
+        */
+       if (!strcmp(version, VIRTIO_9P_VERSION_DOTL))
+               virtio_p9_pdu_writef(pdu, "ds", msize, version);
+       else
+               virtio_p9_pdu_writef(pdu, "ds", msize, "unknown");
+
+       *outlen = pdu->write_offset;
+       virtio_p9_set_reply_header(pdu, *outlen);
+       free(version);
+       return;
+}
+
+static void virtio_p9_clunk(struct p9_dev *p9dev,
+                           struct p9_pdu *pdu, u32 *outlen)
+{
+       u32 fid;
+
+       virtio_p9_pdu_readf(pdu, "d", &fid);
+       close_fid(p9dev, fid);
+
+       *outlen = pdu->write_offset;
+       virtio_p9_set_reply_header(pdu, *outlen);
+       return;
+}
+
+/*
+ * FIXME!! Need to map to protocol independent value. Upstream
+ * 9p also have the same BUG
+ */
+static int virtio_p9_openflags(int flags)
+{
+       flags &= ~(O_NOCTTY | O_ASYNC | O_CREAT | O_DIRECT);
+       flags |= O_NOFOLLOW;
+       return flags;
+}
+
+static bool is_dir(struct p9_fid *fid)
+{
+       struct stat st;
+
+       stat(fid->abs_path, &st);
+
+       return S_ISDIR(st.st_mode);
+}
+
+static void virtio_p9_open(struct p9_dev *p9dev,
+                          struct p9_pdu *pdu, u32 *outlen)
+{
+       u32 fid, flags;
+       struct stat st;
+       struct p9_qid qid;
+       struct p9_fid *new_fid;
+
+
+       virtio_p9_pdu_readf(pdu, "dd", &fid, &flags);
+       new_fid = get_fid(p9dev, fid);
+
+       if (lstat(new_fid->abs_path, &st) < 0)
+               goto err_out;
+
+       stat2qid(&st, &qid);
+
+       if (is_dir(new_fid)) {
+               new_fid->dir = opendir(new_fid->abs_path);
+               if (!new_fid->dir)
+                       goto err_out;
+       } else {
+               new_fid->fd  = open(new_fid->abs_path,
+                                   virtio_p9_openflags(flags));
+               if (new_fid->fd < 0)
+                       goto err_out;
+       }
+       /* FIXME!! need ot send proper iounit  */
+       virtio_p9_pdu_writef(pdu, "Qd", &qid, 0);
+
+       *outlen = pdu->write_offset;
+       virtio_p9_set_reply_header(pdu, *outlen);
+       return;
+err_out:
+       virtio_p9_error_reply(p9dev, pdu, errno, outlen);
+       return;
+}
+
+static void virtio_p9_create(struct p9_dev *p9dev,
+                            struct p9_pdu *pdu, u32 *outlen)
+{
+       int fd, ret;
+       char *name;
+       struct stat st;
+       struct p9_qid qid;
+       struct p9_fid *dfid;
+       char full_path[PATH_MAX];
+       u32 dfid_val, flags, mode, gid;
+
+       virtio_p9_pdu_readf(pdu, "dsddd", &dfid_val,
+                           &name, &flags, &mode, &gid);
+       dfid = get_fid(p9dev, dfid_val);
+
+       flags = virtio_p9_openflags(flags);
+
+       sprintf(full_path, "%s/%s", dfid->abs_path, name);
+       fd = open(full_path, flags | O_CREAT, mode);
+       if (fd < 0)
+               goto err_out;
+       dfid->fd = fd;
+
+       if (lstat(full_path, &st) < 0)
+               goto err_out;
+
+       ret = chmod(full_path, mode & 0777);
+       if (ret < 0)
+               goto err_out;
+
+       sprintf(dfid->path, "%s/%s", dfid->path, name);
+       stat2qid(&st, &qid);
+       virtio_p9_pdu_writef(pdu, "Qd", &qid, 0);
+       *outlen = pdu->write_offset;
+       virtio_p9_set_reply_header(pdu, *outlen);
+       free(name);
+       return;
+err_out:
+       free(name);
+       virtio_p9_error_reply(p9dev, pdu, errno, outlen);
+       return;
+}
+
+static void virtio_p9_mkdir(struct p9_dev *p9dev,
+                           struct p9_pdu *pdu, u32 *outlen)
+{
+       int ret;
+       char *name;
+       struct stat st;
+       struct p9_qid qid;
+       struct p9_fid *dfid;
+       char full_path[PATH_MAX];
+       u32 dfid_val, mode, gid;
+
+       virtio_p9_pdu_readf(pdu, "dsdd", &dfid_val,
+                           &name, &mode, &gid);
+       dfid = get_fid(p9dev, dfid_val);
+
+       sprintf(full_path, "%s/%s", dfid->abs_path, name);
+       ret = mkdir(full_path, mode);
+       if (ret < 0)
+               goto err_out;
+
+       if (lstat(full_path, &st) < 0)
+               goto err_out;
+
+       ret = chmod(full_path, mode & 0777);
+       if (ret < 0)
+               goto err_out;
+
+       stat2qid(&st, &qid);
+       virtio_p9_pdu_writef(pdu, "Qd", &qid, 0);
+       *outlen = pdu->write_offset;
+       virtio_p9_set_reply_header(pdu, *outlen);
+       free(name);
+       return;
+err_out:
+       free(name);
+       virtio_p9_error_reply(p9dev, pdu, errno, outlen);
+       return;
+}
+
+static void virtio_p9_walk(struct p9_dev *p9dev,
+                          struct p9_pdu *pdu, u32 *outlen)
+{
+       u8 i;
+       u16 nwqid;
+       u16 nwname;
+       struct p9_qid wqid;
+       struct p9_fid *new_fid, *old_fid;
+       u32 fid_val, newfid_val;
+
+
+       virtio_p9_pdu_readf(pdu, "ddw", &fid_val, &newfid_val, &nwname);
+       new_fid = get_fid(p9dev, newfid_val);
+
+       nwqid = 0;
+       if (nwname) {
+               struct p9_fid *fid = get_fid(p9dev, fid_val);
+
+               strcpy(new_fid->path, fid->path);
+               /* skip the space for count */
+               pdu->write_offset += sizeof(u16);
+               for (i = 0; i < nwname; i++) {
+                       struct stat st;
+                       char tmp[PATH_MAX] = {0};
+                       char full_path[PATH_MAX];
+                       char *str;
+
+                       virtio_p9_pdu_readf(pdu, "s", &str);
+
+                       /* Format the new path we're 'walk'ing into */
+                       sprintf(tmp, "%s/%s", new_fid->path, str);
+
+                       free(str);
+
+                       if (lstat(rel_to_abs(p9dev, tmp, full_path), &st) < 0)
+                               goto err_out;
+
+                       stat2qid(&st, &wqid);
+                       strcpy(new_fid->path, tmp);
+                       new_fid->uid = fid->uid;
+                       nwqid++;
+                       virtio_p9_pdu_writef(pdu, "Q", &wqid);
+               }
+       } else {
+               /*
+                * update write_offset so our outlen get correct value
+                */
+               pdu->write_offset += sizeof(u16);
+               old_fid = get_fid(p9dev, fid_val);
+               strcpy(new_fid->path, old_fid->path);
+               new_fid->uid    = old_fid->uid;
+       }
+       *outlen = pdu->write_offset;
+       pdu->write_offset = VIRTIO_9P_HDR_LEN;
+       virtio_p9_pdu_writef(pdu, "d", nwqid);
+       virtio_p9_set_reply_header(pdu, *outlen);
+       return;
+err_out:
+       virtio_p9_error_reply(p9dev, pdu, errno, outlen);
+       return;
+}
+
+static void virtio_p9_attach(struct p9_dev *p9dev,
+                            struct p9_pdu *pdu, u32 *outlen)
+{
+       char *uname;
+       char *aname;
+       struct stat st;
+       struct p9_qid qid;
+       struct p9_fid *fid;
+       u32 fid_val, afid, uid;
+
+       virtio_p9_pdu_readf(pdu, "ddssd", &fid_val, &afid,
+                           &uname, &aname, &uid);
+
+       free(uname);
+       free(aname);
+
+       if (lstat(p9dev->root_dir, &st) < 0)
+               goto err_out;
+
+       stat2qid(&st, &qid);
+
+       fid = get_fid(p9dev, fid_val);
+       fid->uid = uid;
+       strcpy(fid->path, "/");
+
+       virtio_p9_pdu_writef(pdu, "Q", &qid);
+       *outlen = pdu->write_offset;
+       virtio_p9_set_reply_header(pdu, *outlen);
+       return;
+err_out:
+       virtio_p9_error_reply(p9dev, pdu, errno, outlen);
+       return;
+}
+
+static void virtio_p9_fill_stat(struct p9_dev *p9dev,
+                               struct stat *st, struct p9_stat_dotl *statl)
+{
+       memset(statl, 0, sizeof(*statl));
+       statl->st_mode          = st->st_mode;
+       statl->st_nlink         = st->st_nlink;
+       statl->st_uid           = st->st_uid;
+       statl->st_gid           = st->st_gid;
+       statl->st_rdev          = st->st_rdev;
+       statl->st_size          = st->st_size;
+       statl->st_blksize       = st->st_blksize;
+       statl->st_blocks        = st->st_blocks;
+       statl->st_atime_sec     = st->st_atime;
+       statl->st_atime_nsec    = st->st_atim.tv_nsec;
+       statl->st_mtime_sec     = st->st_mtime;
+       statl->st_mtime_nsec    = st->st_mtim.tv_nsec;
+       statl->st_ctime_sec     = st->st_ctime;
+       statl->st_ctime_nsec    = st->st_ctim.tv_nsec;
+       /* Currently we only support BASIC fields in stat */
+       statl->st_result_mask   = P9_STATS_BASIC;
+       stat2qid(st, &statl->qid);
+}
+
+static void virtio_p9_read(struct p9_dev *p9dev,
+                          struct p9_pdu *pdu, u32 *outlen)
+{
+       u64 offset;
+       u32 fid_val;
+       u16 iov_cnt;
+       void *iov_base;
+       size_t iov_len;
+       u32 count, rcount;
+       struct p9_fid *fid;
+
+
+       rcount = 0;
+       virtio_p9_pdu_readf(pdu, "dqd", &fid_val, &offset, &count);
+       fid = get_fid(p9dev, fid_val);
+
+       iov_base = pdu->in_iov[0].iov_base;
+       iov_len  = pdu->in_iov[0].iov_len;
+       iov_cnt  = pdu->in_iov_cnt;
+       pdu->in_iov[0].iov_base += VIRTIO_9P_HDR_LEN + sizeof(u32);
+       pdu->in_iov[0].iov_len -= VIRTIO_9P_HDR_LEN + sizeof(u32);
+       pdu->in_iov_cnt = virtio_p9_update_iov_cnt(pdu->in_iov,
+                                                  count,
+                                                  pdu->in_iov_cnt);
+       rcount = preadv(fid->fd, pdu->in_iov,
+                       pdu->in_iov_cnt, offset);
+       if (rcount > count)
+               rcount = count;
+       /*
+        * Update the iov_base back, so that rest of
+        * pdu_writef works correctly.
+        */
+       pdu->in_iov[0].iov_base = iov_base;
+       pdu->in_iov[0].iov_len  = iov_len;
+       pdu->in_iov_cnt         = iov_cnt;
+
+       pdu->write_offset = VIRTIO_9P_HDR_LEN;
+       virtio_p9_pdu_writef(pdu, "d", rcount);
+       *outlen = pdu->write_offset + rcount;
+       virtio_p9_set_reply_header(pdu, *outlen);
+       return;
+}
+
+static int virtio_p9_dentry_size(struct dirent *dent)
+{
+       /*
+        * Size of each dirent:
+        * qid(13) + offset(8) + type(1) + name_len(2) + name
+        */
+       return 24 + strlen(dent->d_name);
+}
+
+static void virtio_p9_readdir(struct p9_dev *p9dev,
+                             struct p9_pdu *pdu, u32 *outlen)
+{
+       u32 fid_val;
+       u32 count, rcount;
+       struct stat st;
+       struct p9_fid *fid;
+       struct dirent *dent;
+       char full_path[PATH_MAX];
+       u64 offset, old_offset;
+
+       rcount = 0;
+       virtio_p9_pdu_readf(pdu, "dqd", &fid_val, &offset, &count);
+       fid = get_fid(p9dev, fid_val);
+
+       if (!is_dir(fid)) {
+               errno = EINVAL;
+               goto err_out;
+       }
+
+       /* Move the offset specified */
+       seekdir(fid->dir, offset);
+
+       old_offset = offset;
+       /* If reading a dir, fill the buffer with p9_stat entries */
+       dent = readdir(fid->dir);
+
+       /* Skip the space for writing count */
+       pdu->write_offset += sizeof(u32);
+       while (dent) {
+               u32 read;
+               struct p9_qid qid;
+
+               if ((rcount + virtio_p9_dentry_size(dent)) > count) {
+                       /* seek to the previous offset and return */
+                       seekdir(fid->dir, old_offset);
+                       break;
+               }
+               old_offset = dent->d_off;
+               lstat(rel_to_abs(p9dev, dent->d_name, full_path), &st);
+               stat2qid(&st, &qid);
+               read = pdu->write_offset;
+               virtio_p9_pdu_writef(pdu, "Qqbs", &qid, dent->d_off,
+                                    dent->d_type, dent->d_name);
+               rcount += pdu->write_offset - read;
+               dent = readdir(fid->dir);
+       }
+
+       pdu->write_offset = VIRTIO_9P_HDR_LEN;
+       virtio_p9_pdu_writef(pdu, "d", rcount);
+       *outlen = pdu->write_offset + rcount;
+       virtio_p9_set_reply_header(pdu, *outlen);
+       return;
+err_out:
+       virtio_p9_error_reply(p9dev, pdu, errno, outlen);
+       return;
+}
+
+
+static void virtio_p9_getattr(struct p9_dev *p9dev,
+                             struct p9_pdu *pdu, u32 *outlen)
+{
+       u32 fid_val;
+       struct stat st;
+       u64 request_mask;
+       struct p9_fid *fid;
+       struct p9_stat_dotl statl;
+
+       virtio_p9_pdu_readf(pdu, "dq", &fid_val, &request_mask);
+       fid = get_fid(p9dev, fid_val);
+       if (lstat(fid->abs_path, &st) < 0)
+               goto err_out;
+
+       virtio_p9_fill_stat(p9dev, &st, &statl);
+       virtio_p9_pdu_writef(pdu, "A", &statl);
+       *outlen = pdu->write_offset;
+       virtio_p9_set_reply_header(pdu, *outlen);
+       return;
+err_out:
+       virtio_p9_error_reply(p9dev, pdu, errno, outlen);
+       return;
+}
+
+/* FIXME!! from linux/fs.h */
+/*
+ * Attribute flags.  These should be or-ed together to figure out what
+ * has been changed!
+ */
+#define ATTR_MODE      (1 << 0)
+#define ATTR_UID       (1 << 1)
+#define ATTR_GID       (1 << 2)
+#define ATTR_SIZE      (1 << 3)
+#define ATTR_ATIME     (1 << 4)
+#define ATTR_MTIME     (1 << 5)
+#define ATTR_CTIME     (1 << 6)
+#define ATTR_ATIME_SET (1 << 7)
+#define ATTR_MTIME_SET (1 << 8)
+#define ATTR_FORCE     (1 << 9) /* Not a change, but a change it */
+#define ATTR_ATTR_FLAG (1 << 10)
+#define ATTR_KILL_SUID (1 << 11)
+#define ATTR_KILL_SGID (1 << 12)
+#define ATTR_FILE      (1 << 13)
+#define ATTR_KILL_PRIV (1 << 14)
+#define ATTR_OPEN      (1 << 15) /* Truncating from open(O_TRUNC) */
+#define ATTR_TIMES_SET (1 << 16)
+
+#define ATTR_MASK    127
+
+static void virtio_p9_setattr(struct p9_dev *p9dev,
+                             struct p9_pdu *pdu, u32 *outlen)
+{
+       int ret = 0;
+       u32 fid_val;
+       struct p9_fid *fid;
+       struct p9_iattr_dotl p9attr;
+
+       virtio_p9_pdu_readf(pdu, "dI", &fid_val, &p9attr);
+       fid = get_fid(p9dev, fid_val);
+
+       if (p9attr.valid & ATTR_MODE) {
+               ret = chmod(fid->abs_path, p9attr.mode);
+               if (ret < 0)
+                       goto err_out;
+       }
+       if (p9attr.valid & (ATTR_ATIME | ATTR_MTIME)) {
+               struct timespec times[2];
+               if (p9attr.valid & ATTR_ATIME) {
+                       if (p9attr.valid & ATTR_ATIME_SET) {
+                               times[0].tv_sec = p9attr.atime_sec;
+                               times[0].tv_nsec = p9attr.atime_nsec;
+                       } else {
+                               times[0].tv_nsec = UTIME_NOW;
+                       }
+               } else {
+                       times[0].tv_nsec = UTIME_OMIT;
+               }
+               if (p9attr.valid & ATTR_MTIME) {
+                       if (p9attr.valid & ATTR_MTIME_SET) {
+                               times[1].tv_sec = p9attr.mtime_sec;
+                               times[1].tv_nsec = p9attr.mtime_nsec;
+                       } else {
+                               times[1].tv_nsec = UTIME_NOW;
+                       }
+               } else
+                       times[1].tv_nsec = UTIME_OMIT;
+
+               ret = utimensat(-1, fid->abs_path, times, AT_SYMLINK_NOFOLLOW);
+               if (ret < 0)
+                       goto err_out;
+       }
+       /*
+        * If the only valid entry in iattr is ctime we can call
+        * chown(-1,-1) to update the ctime of the file
+        */
+       if ((p9attr.valid & (ATTR_UID | ATTR_GID)) ||
+           ((p9attr.valid & ATTR_CTIME)
+            && !((p9attr.valid & ATTR_MASK) & ~ATTR_CTIME))) {
+               if (!(p9attr.valid & ATTR_UID))
+                       p9attr.uid = -1;
+
+               if (!(p9attr.valid & ATTR_GID))
+                       p9attr.gid = -1;
+
+               ret = lchown(fid->abs_path, p9attr.uid, p9attr.gid);
+               if (ret < 0)
+                       goto err_out;
+       }
+       if (p9attr.valid & (ATTR_SIZE)) {
+               ret = truncate(fid->abs_path, p9attr.size);
+               if (ret < 0)
+                       goto err_out;
+       }
+       *outlen = VIRTIO_9P_HDR_LEN;
+       virtio_p9_set_reply_header(pdu, *outlen);
+       return;
+err_out:
+       virtio_p9_error_reply(p9dev, pdu, errno, outlen);
+       return;
+}
+
+static void virtio_p9_write(struct p9_dev *p9dev,
+                           struct p9_pdu *pdu, u32 *outlen)
+{
+
+       u64 offset;
+       u32 fid_val;
+       u32 count;
+       ssize_t res;
+       u16 iov_cnt;
+       void *iov_base;
+       size_t iov_len;
+       struct p9_fid *fid;
+       /* u32 fid + u64 offset + u32 count */
+       int twrite_size = sizeof(u32) + sizeof(u64) + sizeof(u32);
+
+       virtio_p9_pdu_readf(pdu, "dqd", &fid_val, &offset, &count);
+       fid = get_fid(p9dev, fid_val);
+
+       iov_base = pdu->out_iov[0].iov_base;
+       iov_len  = pdu->out_iov[0].iov_len;
+       iov_cnt  = pdu->out_iov_cnt;
+
+       /* Adjust the iovec to skip the header and meta data */
+       pdu->out_iov[0].iov_base += (sizeof(struct p9_msg) + twrite_size);
+       pdu->out_iov[0].iov_len -=  (sizeof(struct p9_msg) + twrite_size);
+       pdu->out_iov_cnt = virtio_p9_update_iov_cnt(pdu->out_iov, count,
+                                                   pdu->out_iov_cnt);
+       res = pwritev(fid->fd, pdu->out_iov, pdu->out_iov_cnt, offset);
+       /*
+        * Update the iov_base back, so that rest of
+        * pdu_readf works correctly.
+        */
+       pdu->out_iov[0].iov_base = iov_base;
+       pdu->out_iov[0].iov_len  = iov_len;
+       pdu->out_iov_cnt         = iov_cnt;
+
+       if (res < 0)
+               goto err_out;
+       virtio_p9_pdu_writef(pdu, "d", res);
+       *outlen = pdu->write_offset;
+       virtio_p9_set_reply_header(pdu, *outlen);
+       return;
+err_out:
+       virtio_p9_error_reply(p9dev, pdu, errno, outlen);
+       return;
+}
+
+static void virtio_p9_remove(struct p9_dev *p9dev,
+                            struct p9_pdu *pdu, u32 *outlen)
+{
+       int ret;
+       u32 fid_val;
+       struct p9_fid *fid;
+
+       virtio_p9_pdu_readf(pdu, "d", &fid_val);
+       fid = get_fid(p9dev, fid_val);
+
+       ret = remove(fid->abs_path);
+       if (ret < 0)
+               goto err_out;
+       *outlen = pdu->write_offset;
+       virtio_p9_set_reply_header(pdu, *outlen);
+       return;
+
+err_out:
+       virtio_p9_error_reply(p9dev, pdu, errno, outlen);
+       return;
+}
+
+static void virtio_p9_rename(struct p9_dev *p9dev,
+                            struct p9_pdu *pdu, u32 *outlen)
+{
+       int ret;
+       u32 fid_val, new_fid_val;
+       struct p9_fid *fid, *new_fid;
+       char full_path[PATH_MAX], *new_name;
+
+       virtio_p9_pdu_readf(pdu, "dds", &fid_val, &new_fid_val, &new_name);
+       fid = get_fid(p9dev, fid_val);
+       new_fid = get_fid(p9dev, new_fid_val);
+
+       sprintf(full_path, "%s/%s", new_fid->abs_path, new_name);
+       ret = rename(fid->abs_path, full_path);
+       if (ret < 0)
+               goto err_out;
+       *outlen = pdu->write_offset;
+       virtio_p9_set_reply_header(pdu, *outlen);
+       return;
+
+err_out:
+       virtio_p9_error_reply(p9dev, pdu, errno, outlen);
+       return;
+}
+
+static void virtio_p9_readlink(struct p9_dev *p9dev,
+                              struct p9_pdu *pdu, u32 *outlen)
+{
+       int ret;
+       u32 fid_val;
+       struct p9_fid *fid;
+       char target_path[PATH_MAX];
+
+       virtio_p9_pdu_readf(pdu, "d", &fid_val);
+       fid = get_fid(p9dev, fid_val);
+
+       memset(target_path, 0, PATH_MAX);
+       ret = readlink(fid->abs_path, target_path, PATH_MAX - 1);
+       if (ret < 0)
+               goto err_out;
+
+       virtio_p9_pdu_writef(pdu, "s", target_path);
+       *outlen = pdu->write_offset;
+       virtio_p9_set_reply_header(pdu, *outlen);
+       return;
+err_out:
+       virtio_p9_error_reply(p9dev, pdu, errno, outlen);
+       return;
+}
+
+static void virtio_p9_statfs(struct p9_dev *p9dev,
+                            struct p9_pdu *pdu, u32 *outlen)
+{
+       int ret;
+       u64 fsid;
+       u32 fid_val;
+       struct p9_fid *fid;
+       struct statfs stat_buf;
+
+       virtio_p9_pdu_readf(pdu, "d", &fid_val);
+       fid = get_fid(p9dev, fid_val);
+
+       ret = statfs(fid->abs_path, &stat_buf);
+       if (ret < 0)
+               goto err_out;
+       /* FIXME!! f_blocks needs update based on client msize */
+       fsid = (unsigned int) stat_buf.f_fsid.__val[0] |
+               (unsigned long long)stat_buf.f_fsid.__val[1] << 32;
+       virtio_p9_pdu_writef(pdu, "ddqqqqqqd", stat_buf.f_type,
+                            stat_buf.f_bsize, stat_buf.f_blocks,
+                            stat_buf.f_bfree, stat_buf.f_bavail,
+                            stat_buf.f_files, stat_buf.f_ffree,
+                            fsid, stat_buf.f_namelen);
+       *outlen = pdu->write_offset;
+       virtio_p9_set_reply_header(pdu, *outlen);
+       return;
+err_out:
+       virtio_p9_error_reply(p9dev, pdu, errno, outlen);
+       return;
+}
+
+static void virtio_p9_mknod(struct p9_dev *p9dev,
+                           struct p9_pdu *pdu, u32 *outlen)
+{
+       int ret;
+       char *name;
+       struct stat st;
+       struct p9_fid *dfid;
+       struct p9_qid qid;
+       char full_path[PATH_MAX];
+       u32 fid_val, mode, major, minor, gid;
+
+       virtio_p9_pdu_readf(pdu, "dsdddd", &fid_val, &name, &mode,
+                           &major, &minor, &gid);
+
+       dfid = get_fid(p9dev, fid_val);
+       sprintf(full_path, "%s/%s", dfid->abs_path, name);
+       ret = mknod(full_path, mode, makedev(major, minor));
+       if (ret < 0)
+               goto err_out;
+
+       if (lstat(full_path, &st) < 0)
+               goto err_out;
+
+       ret = chmod(full_path, mode & 0777);
+       if (ret < 0)
+               goto err_out;
+
+       stat2qid(&st, &qid);
+       virtio_p9_pdu_writef(pdu, "Q", &qid);
+       free(name);
+       *outlen = pdu->write_offset;
+       virtio_p9_set_reply_header(pdu, *outlen);
+       return;
+err_out:
+       free(name);
+       virtio_p9_error_reply(p9dev, pdu, errno, outlen);
+       return;
+}
+
+static void virtio_p9_fsync(struct p9_dev *p9dev,
+                           struct p9_pdu *pdu, u32 *outlen)
+{
+       int ret;
+       struct p9_fid *fid;
+       u32 fid_val, datasync;
+
+       virtio_p9_pdu_readf(pdu, "dd", &fid_val, &datasync);
+       fid = get_fid(p9dev, fid_val);
+
+       if (datasync)
+               ret = fdatasync(fid->fd);
+       else
+               ret = fsync(fid->fd);
+       if (ret < 0)
+               goto err_out;
+       *outlen = pdu->write_offset;
+       virtio_p9_set_reply_header(pdu, *outlen);
+       return;
+err_out:
+       virtio_p9_error_reply(p9dev, pdu, errno, outlen);
+       return;
+}
+
+static void virtio_p9_symlink(struct p9_dev *p9dev,
+                             struct p9_pdu *pdu, u32 *outlen)
+{
+       int ret;
+       struct stat st;
+       u32 fid_val, gid;
+       struct p9_qid qid;
+       struct p9_fid *dfid;
+       char new_name[PATH_MAX];
+       char *old_path, *name;
+
+       virtio_p9_pdu_readf(pdu, "dssd", &fid_val, &name, &old_path, &gid);
+
+       dfid = get_fid(p9dev, fid_val);
+       sprintf(new_name, "%s/%s", dfid->abs_path, name);
+       ret = symlink(old_path, new_name);
+       if (ret < 0)
+               goto err_out;
+
+       if (lstat(new_name, &st) < 0)
+               goto err_out;
+
+       stat2qid(&st, &qid);
+       virtio_p9_pdu_writef(pdu, "Q", &qid);
+       free(name);
+       free(old_path);
+       *outlen = pdu->write_offset;
+       virtio_p9_set_reply_header(pdu, *outlen);
+       return;
+err_out:
+       free(name);
+       free(old_path);
+       virtio_p9_error_reply(p9dev, pdu, errno, outlen);
+       return;
+}
+
+static void virtio_p9_link(struct p9_dev *p9dev,
+                          struct p9_pdu *pdu, u32 *outlen)
+{
+       int ret;
+       char *name;
+       u32 fid_val, dfid_val;
+       struct p9_fid *dfid, *fid;
+       char full_path[PATH_MAX];
+
+       virtio_p9_pdu_readf(pdu, "dds", &dfid_val, &fid_val, &name);
+
+       dfid = get_fid(p9dev, dfid_val);
+       fid =  get_fid(p9dev, fid_val);
+       sprintf(full_path, "%s/%s", dfid->abs_path, name);
+       ret = link(fid->abs_path, full_path);
+       if (ret < 0)
+               goto err_out;
+       free(name);
+       *outlen = pdu->write_offset;
+       virtio_p9_set_reply_header(pdu, *outlen);
+       return;
+err_out:
+       free(name);
+       virtio_p9_error_reply(p9dev, pdu, errno, outlen);
+       return;
+
+}
+
+static void virtio_p9_lock(struct p9_dev *p9dev,
+                          struct p9_pdu *pdu, u32 *outlen)
+{
+       u8 ret;
+       u32 fid_val;
+       struct p9_flock flock;
+
+       virtio_p9_pdu_readf(pdu, "dbdqqds", &fid_val, &flock.type,
+                           &flock.flags, &flock.start, &flock.length,
+                           &flock.proc_id, &flock.client_id);
+
+       /* Just return success */
+       ret = P9_LOCK_SUCCESS;
+       virtio_p9_pdu_writef(pdu, "d", ret);
+       *outlen = pdu->write_offset;
+       virtio_p9_set_reply_header(pdu, *outlen);
+       free(flock.client_id);
+       return;
+}
+
+static void virtio_p9_getlock(struct p9_dev *p9dev,
+                             struct p9_pdu *pdu, u32 *outlen)
+{
+       u32 fid_val;
+       struct p9_getlock glock;
+       virtio_p9_pdu_readf(pdu, "dbqqds", &fid_val, &glock.type,
+                           &glock.start, &glock.length, &glock.proc_id,
+                           &glock.client_id);
+
+       /* Just return success */
+       glock.type = F_UNLCK;
+       virtio_p9_pdu_writef(pdu, "bqqds", glock.type,
+                            glock.start, glock.length, glock.proc_id,
+                            glock.client_id);
+       *outlen = pdu->write_offset;
+       virtio_p9_set_reply_header(pdu, *outlen);
+       free(glock.client_id);
+       return;
+}
+
+static int virtio_p9_ancestor(char *path, char *ancestor)
+{
+       int size = strlen(ancestor);
+       if (!strncmp(path, ancestor, size)) {
+               /*
+                * Now check whether ancestor is a full name or
+                * or directory component and not just part
+                * of a name.
+                */
+               if (path[size] == '\0' || path[size] == '/')
+                       return 1;
+       }
+       return 0;
+}
+
+static void virtio_p9_fix_path(char *fid_path, char *old_name, char *new_name)
+{
+       char tmp_name[PATH_MAX];
+       size_t rp_sz = strlen(old_name);
+
+       if (rp_sz == strlen(fid_path)) {
+               /* replace the full name */
+               strcpy(fid_path, new_name);
+               return;
+       }
+       /* save the trailing path details */
+       strcpy(tmp_name, fid_path + rp_sz);
+       sprintf(fid_path, "%s%s", new_name, tmp_name);
+       return;
+}
+
+static void rename_fids(struct p9_dev *p9dev, char *old_name, char *new_name)
+{
+       struct rb_node *node = rb_first(&p9dev->fids);
+
+       while (node) {
+               struct p9_fid *fid = rb_entry(node, struct p9_fid, node);
+
+               if (fid->fid != P9_NOFID && virtio_p9_ancestor(fid->path, old_name)) {
+                               virtio_p9_fix_path(fid->path, old_name, new_name);
+               }
+               node = rb_next(node);
+       }
+}
+
+static void virtio_p9_renameat(struct p9_dev *p9dev,
+                              struct p9_pdu *pdu, u32 *outlen)
+{
+       int ret;
+       char *old_name, *new_name;
+       u32 old_dfid_val, new_dfid_val;
+       struct p9_fid *old_dfid, *new_dfid;
+       char old_full_path[PATH_MAX], new_full_path[PATH_MAX];
+
+
+       virtio_p9_pdu_readf(pdu, "dsds", &old_dfid_val, &old_name,
+                           &new_dfid_val, &new_name);
+
+       old_dfid = get_fid(p9dev, old_dfid_val);
+       new_dfid = get_fid(p9dev, new_dfid_val);
+
+       sprintf(old_full_path, "%s/%s", old_dfid->abs_path, old_name);
+       sprintf(new_full_path, "%s/%s", new_dfid->abs_path, new_name);
+       ret = rename(old_full_path, new_full_path);
+       if (ret < 0)
+               goto err_out;
+       /*
+        * Now fix path in other fids, if the renamed path is part of
+        * that.
+        */
+       rename_fids(p9dev, old_name, new_name);
+       free(old_name);
+       free(new_name);
+       *outlen = pdu->write_offset;
+       virtio_p9_set_reply_header(pdu, *outlen);
+       return;
+err_out:
+       free(old_name);
+       free(new_name);
+       virtio_p9_error_reply(p9dev, pdu, errno, outlen);
+       return;
+}
+
+static void virtio_p9_unlinkat(struct p9_dev *p9dev,
+                              struct p9_pdu *pdu, u32 *outlen)
+{
+       int ret;
+       char *name;
+       u32 fid_val, flags;
+       struct p9_fid *fid;
+       char full_path[PATH_MAX];
+
+       virtio_p9_pdu_readf(pdu, "dsd", &fid_val, &name, &flags);
+       fid = get_fid(p9dev, fid_val);
+
+       sprintf(full_path, "%s/%s", fid->abs_path, name);
+       ret = remove(full_path);
+       if (ret < 0)
+               goto err_out;
+       free(name);
+       *outlen = pdu->write_offset;
+       virtio_p9_set_reply_header(pdu, *outlen);
+       return;
+err_out:
+       free(name);
+       virtio_p9_error_reply(p9dev, pdu, errno, outlen);
+       return;
+}
+
+static void virtio_p9_flush(struct p9_dev *p9dev,
+                               struct p9_pdu *pdu, u32 *outlen)
+{
+       u16 tag, oldtag;
+
+       virtio_p9_pdu_readf(pdu, "ww", &tag, &oldtag);
+       virtio_p9_pdu_writef(pdu, "w", tag);
+       *outlen = pdu->write_offset;
+       virtio_p9_set_reply_header(pdu, *outlen);
+
+       return;
+}
+
+static void virtio_p9_eopnotsupp(struct p9_dev *p9dev,
+                                struct p9_pdu *pdu, u32 *outlen)
+{
+       return virtio_p9_error_reply(p9dev, pdu, EOPNOTSUPP, outlen);
+}
+
+typedef void p9_handler(struct p9_dev *p9dev,
+                       struct p9_pdu *pdu, u32 *outlen);
+
+/* FIXME should be removed when merging with latest linus tree */
+#define P9_TRENAMEAT 74
+#define P9_TUNLINKAT 76
+
+static p9_handler *virtio_9p_dotl_handler [] = {
+       [P9_TREADDIR]     = virtio_p9_readdir,
+       [P9_TSTATFS]      = virtio_p9_statfs,
+       [P9_TGETATTR]     = virtio_p9_getattr,
+       [P9_TSETATTR]     = virtio_p9_setattr,
+       [P9_TXATTRWALK]   = virtio_p9_eopnotsupp,
+       [P9_TXATTRCREATE] = virtio_p9_eopnotsupp,
+       [P9_TMKNOD]       = virtio_p9_mknod,
+       [P9_TLOCK]        = virtio_p9_lock,
+       [P9_TGETLOCK]     = virtio_p9_getlock,
+       [P9_TRENAMEAT]    = virtio_p9_renameat,
+       [P9_TREADLINK]    = virtio_p9_readlink,
+       [P9_TUNLINKAT]    = virtio_p9_unlinkat,
+       [P9_TMKDIR]       = virtio_p9_mkdir,
+       [P9_TVERSION]     = virtio_p9_version,
+       [P9_TLOPEN]       = virtio_p9_open,
+       [P9_TATTACH]      = virtio_p9_attach,
+       [P9_TWALK]        = virtio_p9_walk,
+       [P9_TCLUNK]       = virtio_p9_clunk,
+       [P9_TFSYNC]       = virtio_p9_fsync,
+       [P9_TREAD]        = virtio_p9_read,
+       [P9_TFLUSH]       = virtio_p9_flush,
+       [P9_TLINK]        = virtio_p9_link,
+       [P9_TSYMLINK]     = virtio_p9_symlink,
+       [P9_TLCREATE]     = virtio_p9_create,
+       [P9_TWRITE]       = virtio_p9_write,
+       [P9_TREMOVE]      = virtio_p9_remove,
+       [P9_TRENAME]      = virtio_p9_rename,
+};
+
+static struct p9_pdu *virtio_p9_pdu_init(struct kvm *kvm, struct virt_queue *vq)
+{
+       struct p9_pdu *pdu = calloc(1, sizeof(*pdu));
+       if (!pdu)
+               return NULL;
+
+       /* skip the pdu header p9_msg */
+       pdu->read_offset        = VIRTIO_9P_HDR_LEN;
+       pdu->write_offset       = VIRTIO_9P_HDR_LEN;
+       pdu->queue_head         = virt_queue__get_inout_iov(kvm, vq, pdu->in_iov,
+                                       pdu->out_iov, &pdu->in_iov_cnt, &pdu->out_iov_cnt);
+       return pdu;
+}
+
+static u8 virtio_p9_get_cmd(struct p9_pdu *pdu)
+{
+       struct p9_msg *msg;
+       /*
+        * we can peek directly into pdu for a u8
+        * value. The host endianess won't be an issue
+        */
+       msg = pdu->out_iov[0].iov_base;
+       return msg->cmd;
+}
+
+static bool virtio_p9_do_io_request(struct kvm *kvm, struct p9_dev_job *job)
+{
+       u8 cmd;
+       u32 len = 0;
+       p9_handler *handler;
+       struct p9_dev *p9dev;
+       struct virt_queue *vq;
+       struct p9_pdu *p9pdu;
+
+       vq = job->vq;
+       p9dev = job->p9dev;
+
+       p9pdu = virtio_p9_pdu_init(kvm, vq);
+       cmd = virtio_p9_get_cmd(p9pdu);
+
+       if ((cmd >= ARRAY_SIZE(virtio_9p_dotl_handler)) ||
+           !virtio_9p_dotl_handler[cmd])
+               handler = virtio_p9_eopnotsupp;
+       else
+               handler = virtio_9p_dotl_handler[cmd];
+
+       handler(p9dev, p9pdu, &len);
+       virt_queue__set_used_elem(vq, p9pdu->queue_head, len);
+       free(p9pdu);
+       return true;
+}
+
+static void virtio_p9_do_io(struct kvm *kvm, void *param)
+{
+       struct p9_dev_job *job = (struct p9_dev_job *)param;
+       struct p9_dev *p9dev   = job->p9dev;
+       struct virt_queue *vq  = job->vq;
+
+       while (virt_queue__available(vq)) {
+               virtio_p9_do_io_request(kvm, job);
+               p9dev->vdev.ops->signal_vq(kvm, &p9dev->vdev, vq - p9dev->vqs);
+       }
+}
+
+static u8 *get_config(struct kvm *kvm, void *dev)
+{
+       struct p9_dev *p9dev = dev;
+
+       return ((u8 *)(p9dev->config));
+}
+
+static u32 get_host_features(struct kvm *kvm, void *dev)
+{
+       return 1 << VIRTIO_9P_MOUNT_TAG;
+}
+
+static void set_guest_features(struct kvm *kvm, void *dev, u32 features)
+{
+       struct p9_dev *p9dev = dev;
+
+       p9dev->features = features;
+}
+
+static int init_vq(struct kvm *kvm, void *dev, u32 vq, u32 pfn)
+{
+       struct p9_dev *p9dev = dev;
+       struct p9_dev_job *job;
+       struct virt_queue *queue;
+       void *p;
+
+       compat__remove_message(compat_id);
+
+       queue           = &p9dev->vqs[vq];
+       queue->pfn      = pfn;
+       p               = guest_pfn_to_host(kvm, queue->pfn);
+       job             = &p9dev->jobs[vq];
+
+       vring_init(&queue->vring, VIRTQUEUE_NUM, p, VIRTIO_PCI_VRING_ALIGN);
+
+       *job            = (struct p9_dev_job) {
+               .vq             = queue,
+               .p9dev          = p9dev,
+       };
+       thread_pool__init_job(&job->job_id, kvm, virtio_p9_do_io, job);
+
+       return 0;
+}
+
+static int notify_vq(struct kvm *kvm, void *dev, u32 vq)
+{
+       struct p9_dev *p9dev = dev;
+
+       thread_pool__do_job(&p9dev->jobs[vq].job_id);
+
+       return 0;
+}
+
+static int get_pfn_vq(struct kvm *kvm, void *dev, u32 vq)
+{
+       struct p9_dev *p9dev = dev;
+
+       return p9dev->vqs[vq].pfn;
+}
+
+static int get_size_vq(struct kvm *kvm, void *dev, u32 vq)
+{
+       return VIRTQUEUE_NUM;
+}
+
+struct virtio_ops p9_dev_virtio_ops = (struct virtio_ops) {
+       .get_config             = get_config,
+       .get_host_features      = get_host_features,
+       .set_guest_features     = set_guest_features,
+       .init_vq                = init_vq,
+       .notify_vq              = notify_vq,
+       .get_pfn_vq             = get_pfn_vq,
+       .get_size_vq            = get_size_vq,
+};
+
+int virtio_9p_rootdir_parser(const struct option *opt, const char *arg, int unset)
+{
+       char *tag_name;
+       char tmp[PATH_MAX];
+       struct kvm *kvm = opt->ptr;
+
+       /*
+        * 9p dir can be of the form dirname,tag_name or
+        * just dirname. In the later case we use the
+        * default tag name
+        */
+       tag_name = strstr(arg, ",");
+       if (tag_name) {
+               *tag_name = '\0';
+               tag_name++;
+       }
+       if (realpath(arg, tmp)) {
+               if (virtio_9p__register(kvm, tmp, tag_name) < 0)
+                       die("Unable to initialize virtio 9p");
+       } else
+               die("Failed resolving 9p path");
+       return 0;
+}
+
+int virtio_9p_img_name_parser(const struct option *opt, const char *arg, int unset)
+{
+       char path[PATH_MAX];
+       struct stat st;
+       struct kvm *kvm = opt->ptr;
+
+       if (stat(arg, &st) == 0 &&
+           S_ISDIR(st.st_mode)) {
+               char tmp[PATH_MAX];
+
+               if (kvm->cfg.using_rootfs)
+                       die("Please use only one rootfs directory atmost");
+
+               if (realpath(arg, tmp) == 0 ||
+                   virtio_9p__register(kvm, tmp, "/dev/root") < 0)
+                       die("Unable to initialize virtio 9p");
+               kvm->cfg.using_rootfs = 1;
+               return 0;
+       }
+
+       snprintf(path, PATH_MAX, "%s%s", kvm__get_dir(), arg);
+
+       if (stat(path, &st) == 0 &&
+           S_ISDIR(st.st_mode)) {
+               char tmp[PATH_MAX];
+
+               if (kvm->cfg.using_rootfs)
+                       die("Please use only one rootfs directory atmost");
+
+               if (realpath(path, tmp) == 0 ||
+                   virtio_9p__register(kvm, tmp, "/dev/root") < 0)
+                       die("Unable to initialize virtio 9p");
+               if (virtio_9p__register(kvm, "/", "hostfs") < 0)
+                       die("Unable to initialize virtio 9p");
+               kvm_setup_resolv(arg);
+               kvm->cfg.using_rootfs = kvm->cfg.custom_rootfs = 1;
+               kvm->cfg.custom_rootfs_name = arg;
+               return 0;
+       }
+
+       return -1;
+}
+
+int virtio_9p__init(struct kvm *kvm)
+{
+       struct p9_dev *p9dev;
+
+       list_for_each_entry(p9dev, &devs, list) {
+               virtio_init(kvm, p9dev, &p9dev->vdev, &p9_dev_virtio_ops,
+                           VIRTIO_PCI, PCI_DEVICE_ID_VIRTIO_9P, VIRTIO_ID_9P, PCI_CLASS_9P);
+       }
+
+       return 0;
+}
+virtio_dev_init(virtio_9p__init);
+
+int virtio_9p__register(struct kvm *kvm, const char *root, const char *tag_name)
+{
+       struct p9_dev *p9dev;
+       int err = 0;
+
+       p9dev = calloc(1, sizeof(*p9dev));
+       if (!p9dev)
+               return -ENOMEM;
+
+       if (!tag_name)
+               tag_name = VIRTIO_9P_DEFAULT_TAG;
+
+       p9dev->config = calloc(1, sizeof(*p9dev->config) + strlen(tag_name) + 1);
+       if (p9dev->config == NULL) {
+               err = -ENOMEM;
+               goto free_p9dev;
+       }
+
+       strcpy(p9dev->root_dir, root);
+       p9dev->config->tag_len = strlen(tag_name);
+       if (p9dev->config->tag_len > MAX_TAG_LEN) {
+               err = -EINVAL;
+               goto free_p9dev_config;
+       }
+
+       memcpy(&p9dev->config->tag, tag_name, strlen(tag_name));
+
+       list_add(&p9dev->list, &devs);
+
+       if (compat_id == -1)
+               compat_id = virtio_compat_add_message("virtio-9p", "CONFIG_NET_9P_VIRTIO");
+
+       return err;
+
+free_p9dev_config:
+       free(p9dev->config);
+free_p9dev:
+       free(p9dev);
+       return err;
+}
diff --git a/tools/kvm/virtio/balloon.c b/tools/kvm/virtio/balloon.c
new file mode 100644 (file)
index 0000000..e08f628
--- /dev/null
@@ -0,0 +1,270 @@
+#include "kvm/virtio-balloon.h"
+
+#include "kvm/virtio-pci-dev.h"
+
+#include "kvm/virtio.h"
+#include "kvm/util.h"
+#include "kvm/kvm.h"
+#include "kvm/pci.h"
+#include "kvm/threadpool.h"
+#include "kvm/guest_compat.h"
+#include "kvm/kvm-ipc.h"
+
+#include <linux/virtio_ring.h>
+#include <linux/virtio_balloon.h>
+
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <pthread.h>
+#include <sys/eventfd.h>
+
+#define NUM_VIRT_QUEUES                3
+#define VIRTIO_BLN_QUEUE_SIZE  128
+#define VIRTIO_BLN_INFLATE     0
+#define VIRTIO_BLN_DEFLATE     1
+#define VIRTIO_BLN_STATS       2
+
+struct bln_dev {
+       struct list_head        list;
+       struct virtio_device    vdev;
+
+       u32                     features;
+
+       /* virtio queue */
+       struct virt_queue       vqs[NUM_VIRT_QUEUES];
+       struct thread_pool__job jobs[NUM_VIRT_QUEUES];
+
+       struct virtio_balloon_stat stats[VIRTIO_BALLOON_S_NR];
+       struct virtio_balloon_stat *cur_stat;
+       u32                     cur_stat_head;
+       u16                     stat_count;
+       int                     stat_waitfd;
+
+       struct virtio_balloon_config config;
+};
+
+static struct bln_dev bdev;
+static int compat_id = -1;
+
+static bool virtio_bln_do_io_request(struct kvm *kvm, struct bln_dev *bdev, struct virt_queue *queue)
+{
+       struct iovec iov[VIRTIO_BLN_QUEUE_SIZE];
+       unsigned int len = 0;
+       u16 out, in, head;
+       u32 *ptrs, i;
+
+       head    = virt_queue__get_iov(queue, iov, &out, &in, kvm);
+       ptrs    = iov[0].iov_base;
+       len     = iov[0].iov_len / sizeof(u32);
+
+       for (i = 0 ; i < len ; i++) {
+               void *guest_ptr;
+
+               guest_ptr = guest_flat_to_host(kvm, ptrs[i] << VIRTIO_BALLOON_PFN_SHIFT);
+               if (queue == &bdev->vqs[VIRTIO_BLN_INFLATE]) {
+                       madvise(guest_ptr, 1 << VIRTIO_BALLOON_PFN_SHIFT, MADV_DONTNEED);
+                       bdev->config.actual++;
+               } else if (queue == &bdev->vqs[VIRTIO_BLN_DEFLATE]) {
+                       bdev->config.actual--;
+               }
+       }
+
+       virt_queue__set_used_elem(queue, head, len);
+
+       return true;
+}
+
+static bool virtio_bln_do_stat_request(struct kvm *kvm, struct bln_dev *bdev, struct virt_queue *queue)
+{
+       struct iovec iov[VIRTIO_BLN_QUEUE_SIZE];
+       u16 out, in, head;
+       struct virtio_balloon_stat *stat;
+       u64 wait_val = 1;
+
+       head = virt_queue__get_iov(queue, iov, &out, &in, kvm);
+       stat = iov[0].iov_base;
+
+       /* Initial empty stat buffer */
+       if (bdev->cur_stat == NULL) {
+               bdev->cur_stat = stat;
+               bdev->cur_stat_head = head;
+
+               return true;
+       }
+
+       memcpy(bdev->stats, stat, iov[0].iov_len);
+
+       bdev->stat_count = iov[0].iov_len / sizeof(struct virtio_balloon_stat);
+       bdev->cur_stat = stat;
+       bdev->cur_stat_head = head;
+
+       if (write(bdev->stat_waitfd, &wait_val, sizeof(wait_val)) <= 0)
+               return -EFAULT;
+
+       return 1;
+}
+
+static void virtio_bln_do_io(struct kvm *kvm, void *param)
+{
+       struct virt_queue *vq = param;
+
+       if (vq == &bdev.vqs[VIRTIO_BLN_STATS]) {
+               virtio_bln_do_stat_request(kvm, &bdev, vq);
+               bdev.vdev.ops->signal_vq(kvm, &bdev.vdev, VIRTIO_BLN_STATS);
+               return;
+       }
+
+       while (virt_queue__available(vq)) {
+               virtio_bln_do_io_request(kvm, &bdev, vq);
+               bdev.vdev.ops->signal_vq(kvm, &bdev.vdev, vq - bdev.vqs);
+       }
+}
+
+static int virtio_bln__collect_stats(struct kvm *kvm)
+{
+       u64 tmp;
+
+       virt_queue__set_used_elem(&bdev.vqs[VIRTIO_BLN_STATS], bdev.cur_stat_head,
+                                 sizeof(struct virtio_balloon_stat));
+       bdev.vdev.ops->signal_vq(kvm, &bdev.vdev, VIRTIO_BLN_STATS);
+
+       if (read(bdev.stat_waitfd, &tmp, sizeof(tmp)) <= 0)
+               return -EFAULT;
+
+       return 0;
+}
+
+static void virtio_bln__print_stats(struct kvm *kvm, int fd, u32 type, u32 len, u8 *msg)
+{
+       int r;
+
+       if (WARN_ON(type != KVM_IPC_STAT || len))
+               return;
+
+       if (virtio_bln__collect_stats(kvm) < 0)
+               return;
+
+       r = write(fd, bdev.stats, sizeof(bdev.stats));
+       if (r < 0)
+               pr_warning("Failed sending memory stats");
+}
+
+static void handle_mem(struct kvm *kvm, int fd, u32 type, u32 len, u8 *msg)
+{
+       int mem;
+
+       if (WARN_ON(type != KVM_IPC_BALLOON || len != sizeof(int)))
+               return;
+
+       mem = *(int *)msg;
+       if (mem > 0) {
+               bdev.config.num_pages += 256 * mem;
+       } else if (mem < 0) {
+               if (bdev.config.num_pages < (u32)(256 * (-mem)))
+                       return;
+
+               bdev.config.num_pages += 256 * mem;
+       }
+
+       /* Notify that the configuration space has changed */
+       bdev.vdev.ops->signal_config(kvm, &bdev.vdev);
+}
+
+static u8 *get_config(struct kvm *kvm, void *dev)
+{
+       struct bln_dev *bdev = dev;
+
+       return ((u8 *)(&bdev->config));
+}
+
+static u32 get_host_features(struct kvm *kvm, void *dev)
+{
+       return 1 << VIRTIO_BALLOON_F_STATS_VQ;
+}
+
+static void set_guest_features(struct kvm *kvm, void *dev, u32 features)
+{
+       struct bln_dev *bdev = dev;
+
+       bdev->features = features;
+}
+
+static int init_vq(struct kvm *kvm, void *dev, u32 vq, u32 pfn)
+{
+       struct bln_dev *bdev = dev;
+       struct virt_queue *queue;
+       void *p;
+
+       compat__remove_message(compat_id);
+
+       queue           = &bdev->vqs[vq];
+       queue->pfn      = pfn;
+       p               = guest_pfn_to_host(kvm, queue->pfn);
+
+       thread_pool__init_job(&bdev->jobs[vq], kvm, virtio_bln_do_io, queue);
+       vring_init(&queue->vring, VIRTIO_BLN_QUEUE_SIZE, p, VIRTIO_PCI_VRING_ALIGN);
+
+       return 0;
+}
+
+static int notify_vq(struct kvm *kvm, void *dev, u32 vq)
+{
+       struct bln_dev *bdev = dev;
+
+       thread_pool__do_job(&bdev->jobs[vq]);
+
+       return 0;
+}
+
+static int get_pfn_vq(struct kvm *kvm, void *dev, u32 vq)
+{
+       struct bln_dev *bdev = dev;
+
+       return bdev->vqs[vq].pfn;
+}
+
+static int get_size_vq(struct kvm *kvm, void *dev, u32 vq)
+{
+       return VIRTIO_BLN_QUEUE_SIZE;
+}
+
+struct virtio_ops bln_dev_virtio_ops = (struct virtio_ops) {
+       .get_config             = get_config,
+       .get_host_features      = get_host_features,
+       .set_guest_features     = set_guest_features,
+       .init_vq                = init_vq,
+       .notify_vq              = notify_vq,
+       .get_pfn_vq             = get_pfn_vq,
+       .get_size_vq            = get_size_vq,
+};
+
+int virtio_bln__init(struct kvm *kvm)
+{
+       if (!kvm->cfg.balloon)
+               return 0;
+
+       kvm_ipc__register_handler(KVM_IPC_BALLOON, handle_mem);
+       kvm_ipc__register_handler(KVM_IPC_STAT, virtio_bln__print_stats);
+
+       bdev.stat_waitfd        = eventfd(0, 0);
+       memset(&bdev.config, 0, sizeof(struct virtio_balloon_config));
+
+       virtio_init(kvm, &bdev, &bdev.vdev, &bln_dev_virtio_ops,
+                   VIRTIO_PCI, PCI_DEVICE_ID_VIRTIO_BLN, VIRTIO_ID_BALLOON, PCI_CLASS_BLN);
+
+       if (compat_id == -1)
+               compat_id = virtio_compat_add_message("virtio-balloon", "CONFIG_VIRTIO_BALLOON");
+
+       return 0;
+}
+virtio_dev_init(virtio_bln__init);
+
+int virtio_bln__exit(struct kvm *kvm)
+{
+       return 0;
+}
+virtio_dev_exit(virtio_bln__exit);
diff --git a/tools/kvm/virtio/blk.c b/tools/kvm/virtio/blk.c
new file mode 100644 (file)
index 0000000..cff38aa
--- /dev/null
@@ -0,0 +1,315 @@
+#include "kvm/virtio-blk.h"
+
+#include "kvm/virtio-pci-dev.h"
+#include "kvm/disk-image.h"
+#include "kvm/mutex.h"
+#include "kvm/util.h"
+#include "kvm/kvm.h"
+#include "kvm/pci.h"
+#include "kvm/threadpool.h"
+#include "kvm/ioeventfd.h"
+#include "kvm/guest_compat.h"
+#include "kvm/virtio-pci.h"
+#include "kvm/virtio.h"
+
+#include <linux/virtio_ring.h>
+#include <linux/virtio_blk.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/types.h>
+#include <pthread.h>
+
+#define VIRTIO_BLK_MAX_DEV             4
+
+/*
+ * the header and status consume too entries
+ */
+#define DISK_SEG_MAX                   (VIRTIO_BLK_QUEUE_SIZE - 2)
+#define VIRTIO_BLK_QUEUE_SIZE          256
+#define NUM_VIRT_QUEUES                        1
+
+struct blk_dev_req {
+       struct virt_queue               *vq;
+       struct blk_dev                  *bdev;
+       struct iovec                    iov[VIRTIO_BLK_QUEUE_SIZE];
+       u16                             out, in, head;
+       struct kvm                      *kvm;
+};
+
+struct blk_dev {
+       pthread_mutex_t                 mutex;
+
+       struct list_head                list;
+
+       struct virtio_device            vdev;
+       struct virtio_blk_config        blk_config;
+       struct disk_image               *disk;
+       u32                             features;
+
+       struct virt_queue               vqs[NUM_VIRT_QUEUES];
+       struct blk_dev_req              reqs[VIRTIO_BLK_QUEUE_SIZE];
+
+       pthread_t                       io_thread;
+       int                             io_efd;
+
+       struct kvm                      *kvm;
+};
+
+static LIST_HEAD(bdevs);
+static int compat_id = -1;
+
+void virtio_blk_complete(void *param, long len)
+{
+       struct blk_dev_req *req = param;
+       struct blk_dev *bdev = req->bdev;
+       int queueid = req->vq - bdev->vqs;
+       u8 *status;
+
+       /* status */
+       status  = req->iov[req->out + req->in - 1].iov_base;
+       *status = (len < 0) ? VIRTIO_BLK_S_IOERR : VIRTIO_BLK_S_OK;
+
+       mutex_lock(&bdev->mutex);
+       virt_queue__set_used_elem(req->vq, req->head, len);
+       mutex_unlock(&bdev->mutex);
+
+       if (virtio_queue__should_signal(&bdev->vqs[queueid]))
+               bdev->vdev.ops->signal_vq(req->kvm, &bdev->vdev, queueid);
+}
+
+static void virtio_blk_do_io_request(struct kvm *kvm, struct blk_dev_req *req)
+{
+       struct virtio_blk_outhdr *req_hdr;
+       ssize_t block_cnt;
+       struct blk_dev *bdev;
+       struct iovec *iov;
+       u16 out, in;
+
+       block_cnt       = -1;
+       bdev            = req->bdev;
+       iov             = req->iov;
+       out             = req->out;
+       in              = req->in;
+       req_hdr         = iov[0].iov_base;
+
+       switch (req_hdr->type) {
+       case VIRTIO_BLK_T_IN:
+               block_cnt = disk_image__read(bdev->disk, req_hdr->sector,
+                               iov + 1, in + out - 2, req);
+               break;
+       case VIRTIO_BLK_T_OUT:
+               block_cnt = disk_image__write(bdev->disk, req_hdr->sector,
+                               iov + 1, in + out - 2, req);
+               break;
+       case VIRTIO_BLK_T_FLUSH:
+               block_cnt = disk_image__flush(bdev->disk);
+               virtio_blk_complete(req, block_cnt);
+               break;
+       case VIRTIO_BLK_T_GET_ID:
+               block_cnt = VIRTIO_BLK_ID_BYTES;
+               disk_image__get_serial(bdev->disk,
+                               (iov + 1)->iov_base, &block_cnt);
+               virtio_blk_complete(req, block_cnt);
+               break;
+       default:
+               pr_warning("request type %d", req_hdr->type);
+               block_cnt       = -1;
+               break;
+       }
+}
+
+static void virtio_blk_do_io(struct kvm *kvm, struct virt_queue *vq, struct blk_dev *bdev)
+{
+       struct blk_dev_req *req;
+       u16 head;
+
+       while (virt_queue__available(vq)) {
+               head            = virt_queue__pop(vq);
+               req             = &bdev->reqs[head];
+               req->head       = virt_queue__get_head_iov(vq, req->iov, &req->out,
+                                       &req->in, head, kvm);
+               req->vq         = vq;
+
+               virtio_blk_do_io_request(kvm, req);
+       }
+}
+
+static u8 *get_config(struct kvm *kvm, void *dev)
+{
+       struct blk_dev *bdev = dev;
+
+       return ((u8 *)(&bdev->blk_config));
+}
+
+static u32 get_host_features(struct kvm *kvm, void *dev)
+{
+       return  1UL << VIRTIO_BLK_F_SEG_MAX
+               | 1UL << VIRTIO_BLK_F_FLUSH
+               | 1UL << VIRTIO_RING_F_EVENT_IDX
+               | 1UL << VIRTIO_RING_F_INDIRECT_DESC;
+}
+
+static void set_guest_features(struct kvm *kvm, void *dev, u32 features)
+{
+       struct blk_dev *bdev = dev;
+
+       bdev->features = features;
+}
+
+static int init_vq(struct kvm *kvm, void *dev, u32 vq, u32 pfn)
+{
+       struct blk_dev *bdev = dev;
+       struct virt_queue *queue;
+       void *p;
+
+       compat__remove_message(compat_id);
+
+       queue           = &bdev->vqs[vq];
+       queue->pfn      = pfn;
+       p               = guest_pfn_to_host(kvm, queue->pfn);
+
+       vring_init(&queue->vring, VIRTIO_BLK_QUEUE_SIZE, p, VIRTIO_PCI_VRING_ALIGN);
+
+       return 0;
+}
+
+static void *virtio_blk_thread(void *dev)
+{
+       struct blk_dev *bdev = dev;
+       u64 data;
+       int r;
+
+       while (1) {
+               r = read(bdev->io_efd, &data, sizeof(u64));
+               if (r < 0)
+                       continue;
+               virtio_blk_do_io(bdev->kvm, &bdev->vqs[0], bdev);
+       }
+
+       pthread_exit(NULL);
+       return NULL;
+}
+
+static int notify_vq(struct kvm *kvm, void *dev, u32 vq)
+{
+       struct blk_dev *bdev = dev;
+       u64 data = 1;
+       int r;
+
+       r = write(bdev->io_efd, &data, sizeof(data));
+       if (r < 0)
+               return r;
+
+       return 0;
+}
+
+static int get_pfn_vq(struct kvm *kvm, void *dev, u32 vq)
+{
+       struct blk_dev *bdev = dev;
+
+       return bdev->vqs[vq].pfn;
+}
+
+static int get_size_vq(struct kvm *kvm, void *dev, u32 vq)
+{
+       /* FIXME: dynamic */
+       return VIRTIO_BLK_QUEUE_SIZE;
+}
+
+static int set_size_vq(struct kvm *kvm, void *dev, u32 vq, int size)
+{
+       /* FIXME: dynamic */
+       return size;
+}
+
+static struct virtio_ops blk_dev_virtio_ops = (struct virtio_ops) {
+       .get_config             = get_config,
+       .get_host_features      = get_host_features,
+       .set_guest_features     = set_guest_features,
+       .init_vq                = init_vq,
+       .notify_vq              = notify_vq,
+       .get_pfn_vq             = get_pfn_vq,
+       .get_size_vq            = get_size_vq,
+       .set_size_vq            = set_size_vq,
+};
+
+static int virtio_blk__init_one(struct kvm *kvm, struct disk_image *disk)
+{
+       struct blk_dev *bdev;
+       unsigned int i;
+
+       if (!disk)
+               return -EINVAL;
+
+       bdev = calloc(1, sizeof(struct blk_dev));
+       if (bdev == NULL)
+               return -ENOMEM;
+
+       *bdev = (struct blk_dev) {
+               .mutex                  = PTHREAD_MUTEX_INITIALIZER,
+               .disk                   = disk,
+               .blk_config             = (struct virtio_blk_config) {
+                       .capacity       = disk->size / SECTOR_SIZE,
+                       .seg_max        = DISK_SEG_MAX,
+               },
+               .io_efd                 = eventfd(0, 0),
+               .kvm                    = kvm,
+       };
+
+       virtio_init(kvm, bdev, &bdev->vdev, &blk_dev_virtio_ops,
+                   VIRTIO_PCI, PCI_DEVICE_ID_VIRTIO_BLK, VIRTIO_ID_BLOCK, PCI_CLASS_BLK);
+
+       list_add_tail(&bdev->list, &bdevs);
+
+       for (i = 0; i < ARRAY_SIZE(bdev->reqs); i++) {
+               bdev->reqs[i].bdev = bdev;
+               bdev->reqs[i].kvm = kvm;
+       }
+
+       disk_image__set_callback(bdev->disk, virtio_blk_complete);
+
+       pthread_create(&bdev->io_thread, NULL, virtio_blk_thread, bdev);
+       if (compat_id == -1)
+               compat_id = virtio_compat_add_message("virtio-blk", "CONFIG_VIRTIO_BLK");
+
+       return 0;
+}
+
+static int virtio_blk__exit_one(struct kvm *kvm, struct blk_dev *bdev)
+{
+       list_del(&bdev->list);
+       free(bdev);
+
+       return 0;
+}
+
+int virtio_blk__init(struct kvm *kvm)
+{
+       int i, r = 0;
+
+       for (i = 0; i < kvm->nr_disks; i++) {
+               if (kvm->disks[i]->wwpn)
+                       continue;
+               r = virtio_blk__init_one(kvm, kvm->disks[i]);
+               if (r < 0)
+                       goto cleanup;
+       }
+
+       return 0;
+cleanup:
+       return virtio_blk__exit(kvm);
+}
+virtio_dev_init(virtio_blk__init);
+
+int virtio_blk__exit(struct kvm *kvm)
+{
+       while (!list_empty(&bdevs)) {
+               struct blk_dev *bdev;
+
+               bdev = list_first_entry(&bdevs, struct blk_dev, list);
+               virtio_blk__exit_one(kvm, bdev);
+       }
+
+       return 0;
+}
+virtio_dev_exit(virtio_blk__exit);
diff --git a/tools/kvm/virtio/console.c b/tools/kvm/virtio/console.c
new file mode 100644 (file)
index 0000000..88b1106
--- /dev/null
@@ -0,0 +1,203 @@
+#include "kvm/virtio-console.h"
+#include "kvm/virtio-pci-dev.h"
+#include "kvm/disk-image.h"
+#include "kvm/virtio.h"
+#include "kvm/ioport.h"
+#include "kvm/util.h"
+#include "kvm/term.h"
+#include "kvm/mutex.h"
+#include "kvm/kvm.h"
+#include "kvm/pci.h"
+#include "kvm/threadpool.h"
+#include "kvm/irq.h"
+#include "kvm/guest_compat.h"
+
+#include <linux/virtio_console.h>
+#include <linux/virtio_ring.h>
+#include <linux/virtio_blk.h>
+
+#include <sys/uio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <termios.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#define VIRTIO_CONSOLE_QUEUE_SIZE      128
+#define VIRTIO_CONSOLE_NUM_QUEUES      2
+#define VIRTIO_CONSOLE_RX_QUEUE                0
+#define VIRTIO_CONSOLE_TX_QUEUE                1
+
+struct con_dev {
+       pthread_mutex_t                 mutex;
+
+       struct virtio_device            vdev;
+       struct virt_queue               vqs[VIRTIO_CONSOLE_NUM_QUEUES];
+       struct virtio_console_config    config;
+       u32                             features;
+
+       struct thread_pool__job         jobs[VIRTIO_CONSOLE_NUM_QUEUES];
+};
+
+static struct con_dev cdev = {
+       .mutex                          = PTHREAD_MUTEX_INITIALIZER,
+
+       .config = {
+               .cols                   = 80,
+               .rows                   = 24,
+               .max_nr_ports           = 1,
+       },
+};
+
+static int compat_id = -1;
+
+/*
+ * Interrupts are injected for hvc0 only.
+ */
+static void virtio_console__inject_interrupt_callback(struct kvm *kvm, void *param)
+{
+       struct iovec iov[VIRTIO_CONSOLE_QUEUE_SIZE];
+       struct virt_queue *vq;
+       u16 out, in;
+       u16 head;
+       int len;
+
+       if (kvm->cfg.active_console != CONSOLE_VIRTIO)
+               return;
+
+       mutex_lock(&cdev.mutex);
+
+       vq = param;
+
+       if (term_readable(0) && virt_queue__available(vq)) {
+               head = virt_queue__get_iov(vq, iov, &out, &in, kvm);
+               len = term_getc_iov(kvm, iov, in, 0);
+               virt_queue__set_used_elem(vq, head, len);
+               cdev.vdev.ops->signal_vq(kvm, &cdev.vdev, vq - cdev.vqs);
+       }
+
+       mutex_unlock(&cdev.mutex);
+}
+
+void virtio_console__inject_interrupt(struct kvm *kvm)
+{
+       thread_pool__do_job(&cdev.jobs[VIRTIO_CONSOLE_RX_QUEUE]);
+}
+
+static void virtio_console_handle_callback(struct kvm *kvm, void *param)
+{
+       struct iovec iov[VIRTIO_CONSOLE_QUEUE_SIZE];
+       struct virt_queue *vq;
+       u16 out, in;
+       u16 head;
+       u32 len;
+
+       vq = param;
+
+       /*
+        * The current Linux implementation polls for the buffer
+        * to be used, rather than waiting for an interrupt.
+        * So there is no need to inject an interrupt for the tx path.
+        */
+
+       while (virt_queue__available(vq)) {
+               head = virt_queue__get_iov(vq, iov, &out, &in, kvm);
+               if (kvm->cfg.active_console == CONSOLE_VIRTIO)
+                       len = term_putc_iov(iov, out, 0);
+               else
+                       len = 0;
+               virt_queue__set_used_elem(vq, head, len);
+       }
+
+}
+
+static u8 *get_config(struct kvm *kvm, void *dev)
+{
+       struct con_dev *cdev = dev;
+
+       return ((u8 *)(&cdev->config));
+}
+
+static u32 get_host_features(struct kvm *kvm, void *dev)
+{
+       return 0;
+}
+
+static void set_guest_features(struct kvm *kvm, void *dev, u32 features)
+{
+       /* Unused */
+}
+
+static int init_vq(struct kvm *kvm, void *dev, u32 vq, u32 pfn)
+{
+       struct virt_queue *queue;
+       void *p;
+
+       BUG_ON(vq >= VIRTIO_CONSOLE_NUM_QUEUES);
+
+       compat__remove_message(compat_id);
+
+       queue           = &cdev.vqs[vq];
+       queue->pfn      = pfn;
+       p               = guest_pfn_to_host(kvm, queue->pfn);
+
+       vring_init(&queue->vring, VIRTIO_CONSOLE_QUEUE_SIZE, p, VIRTIO_PCI_VRING_ALIGN);
+
+       if (vq == VIRTIO_CONSOLE_TX_QUEUE)
+               thread_pool__init_job(&cdev.jobs[vq], kvm, virtio_console_handle_callback, queue);
+       else if (vq == VIRTIO_CONSOLE_RX_QUEUE)
+               thread_pool__init_job(&cdev.jobs[vq], kvm, virtio_console__inject_interrupt_callback, queue);
+
+       return 0;
+}
+
+static int notify_vq(struct kvm *kvm, void *dev, u32 vq)
+{
+       struct con_dev *cdev = dev;
+
+       thread_pool__do_job(&cdev->jobs[vq]);
+
+       return 0;
+}
+
+static int get_pfn_vq(struct kvm *kvm, void *dev, u32 vq)
+{
+       struct con_dev *cdev = dev;
+
+       return cdev->vqs[vq].pfn;
+}
+
+static int get_size_vq(struct kvm *kvm, void *dev, u32 vq)
+{
+       return VIRTIO_CONSOLE_QUEUE_SIZE;
+}
+
+static struct virtio_ops con_dev_virtio_ops = (struct virtio_ops) {
+       .get_config             = get_config,
+       .get_host_features      = get_host_features,
+       .set_guest_features     = set_guest_features,
+       .init_vq                = init_vq,
+       .notify_vq              = notify_vq,
+       .get_pfn_vq             = get_pfn_vq,
+       .get_size_vq            = get_size_vq,
+};
+
+int virtio_console__init(struct kvm *kvm)
+{
+       if (kvm->cfg.active_console != CONSOLE_VIRTIO)
+               return 0;
+
+       virtio_init(kvm, &cdev, &cdev.vdev, &con_dev_virtio_ops,
+                   VIRTIO_PCI, PCI_DEVICE_ID_VIRTIO_CONSOLE, VIRTIO_ID_CONSOLE, PCI_CLASS_CONSOLE);
+       if (compat_id == -1)
+               compat_id = virtio_compat_add_message("virtio-console", "CONFIG_VIRTIO_CONSOLE");
+
+       return 0;
+}
+virtio_dev_init(virtio_console__init);
+
+int virtio_console__exit(struct kvm *kvm)
+{
+       return 0;
+}
+virtio_dev_exit(virtio_console__exit);
diff --git a/tools/kvm/virtio/core.c b/tools/kvm/virtio/core.c
new file mode 100644 (file)
index 0000000..2dfb828
--- /dev/null
@@ -0,0 +1,233 @@
+#include <linux/virtio_ring.h>
+#include <linux/types.h>
+#include <sys/uio.h>
+#include <stdlib.h>
+
+#include "kvm/guest_compat.h"
+#include "kvm/barrier.h"
+#include "kvm/virtio.h"
+#include "kvm/virtio-pci.h"
+#include "kvm/virtio-mmio.h"
+#include "kvm/util.h"
+#include "kvm/kvm.h"
+
+
+struct vring_used_elem *virt_queue__set_used_elem(struct virt_queue *queue, u32 head, u32 len)
+{
+       struct vring_used_elem *used_elem;
+
+       used_elem       = &queue->vring.used->ring[queue->vring.used->idx % queue->vring.num];
+       used_elem->id   = head;
+       used_elem->len  = len;
+
+       /*
+        * Use wmb to assure that used elem was updated with head and len.
+        * We need a wmb here since we can't advance idx unless we're ready
+        * to pass the used element to the guest.
+        */
+       wmb();
+       queue->vring.used->idx++;
+
+       /*
+        * Use wmb to assure used idx has been increased before we signal the guest.
+        * Without a wmb here the guest may ignore the queue since it won't see
+        * an updated idx.
+        */
+       wmb();
+
+       return used_elem;
+}
+
+/*
+ * Each buffer in the virtqueues is actually a chain of descriptors.  This
+ * function returns the next descriptor in the chain, or vq->vring.num if we're
+ * at the end.
+ */
+static unsigned next_desc(struct vring_desc *desc,
+                         unsigned int i, unsigned int max)
+{
+       unsigned int next;
+
+       /* If this descriptor says it doesn't chain, we're done. */
+       if (!(desc[i].flags & VRING_DESC_F_NEXT))
+               return max;
+
+       /* Check they're not leading us off end of descriptors. */
+       next = desc[i].next;
+       /* Make sure compiler knows to grab that: we don't want it changing! */
+       wmb();
+
+       return next;
+}
+
+u16 virt_queue__get_head_iov(struct virt_queue *vq, struct iovec iov[], u16 *out, u16 *in, u16 head, struct kvm *kvm)
+{
+       struct vring_desc *desc;
+       u16 idx;
+       u16 max;
+
+       idx = head;
+       *out = *in = 0;
+       max = vq->vring.num;
+       desc = vq->vring.desc;
+
+       if (desc[idx].flags & VRING_DESC_F_INDIRECT) {
+               max = desc[idx].len / sizeof(struct vring_desc);
+               desc = guest_flat_to_host(kvm, desc[idx].addr);
+               idx = 0;
+       }
+
+       do {
+               /* Grab the first descriptor, and check it's OK. */
+               iov[*out + *in].iov_len = desc[idx].len;
+               iov[*out + *in].iov_base = guest_flat_to_host(kvm, desc[idx].addr);
+               /* If this is an input descriptor, increment that count. */
+               if (desc[idx].flags & VRING_DESC_F_WRITE)
+                       (*in)++;
+               else
+                       (*out)++;
+       } while ((idx = next_desc(desc, idx, max)) != max);
+
+       return head;
+}
+
+u16 virt_queue__get_iov(struct virt_queue *vq, struct iovec iov[], u16 *out, u16 *in, struct kvm *kvm)
+{
+       u16 head;
+
+       head = virt_queue__pop(vq);
+
+       return virt_queue__get_head_iov(vq, iov, out, in, head, kvm);
+}
+
+/* in and out are relative to guest */
+u16 virt_queue__get_inout_iov(struct kvm *kvm, struct virt_queue *queue,
+                             struct iovec in_iov[], struct iovec out_iov[],
+                             u16 *in, u16 *out)
+{
+       struct vring_desc *desc;
+       u16 head, idx;
+
+       idx = head = virt_queue__pop(queue);
+       *out = *in = 0;
+       do {
+               desc = virt_queue__get_desc(queue, idx);
+               if (desc->flags & VRING_DESC_F_WRITE) {
+                       in_iov[*in].iov_base = guest_flat_to_host(kvm,
+                                                                 desc->addr);
+                       in_iov[*in].iov_len = desc->len;
+                       (*in)++;
+               } else {
+                       out_iov[*out].iov_base = guest_flat_to_host(kvm,
+                                                                   desc->addr);
+                       out_iov[*out].iov_len = desc->len;
+                       (*out)++;
+               }
+               if (desc->flags & VRING_DESC_F_NEXT)
+                       idx = desc->next;
+               else
+                       break;
+       } while (1);
+
+       return head;
+}
+
+int virtio__get_dev_specific_field(int offset, bool msix, u32 *config_off)
+{
+       if (msix) {
+               if (offset < 4)
+                       return VIRTIO_PCI_O_MSIX;
+               else
+                       offset -= 4;
+       }
+
+       *config_off = offset;
+
+       return VIRTIO_PCI_O_CONFIG;
+}
+
+bool virtio_queue__should_signal(struct virt_queue *vq)
+{
+       u16 old_idx, new_idx, event_idx;
+
+       old_idx         = vq->last_used_signalled;
+       new_idx         = vq->vring.used->idx;
+       event_idx       = vring_used_event(&vq->vring);
+
+       if (vring_need_event(event_idx, new_idx, old_idx)) {
+               vq->last_used_signalled = new_idx;
+               return true;
+       }
+
+       return false;
+}
+
+int virtio_init(struct kvm *kvm, void *dev, struct virtio_device *vdev,
+               struct virtio_ops *ops, enum virtio_trans trans,
+               int device_id, int subsys_id, int class)
+{
+       void *virtio;
+
+       switch (trans) {
+       case VIRTIO_PCI:
+               virtio = calloc(sizeof(struct virtio_pci), 1);
+               if (!virtio)
+                       return -ENOMEM;
+               vdev->virtio                    = virtio;
+               vdev->ops                       = ops;
+               vdev->ops->signal_vq            = virtio_pci__signal_vq;
+               vdev->ops->signal_config        = virtio_pci__signal_config;
+               vdev->ops->init                 = virtio_pci__init;
+               vdev->ops->exit                 = virtio_pci__exit;
+               vdev->ops->init(kvm, dev, vdev, device_id, subsys_id, class);
+               break;
+       case VIRTIO_MMIO:
+               virtio = calloc(sizeof(struct virtio_mmio), 1);
+               if (!virtio)
+                       return -ENOMEM;
+               vdev->virtio                    = virtio;
+               vdev->ops                       = ops;
+               vdev->ops->signal_vq            = virtio_mmio_signal_vq;
+               vdev->ops->signal_config        = virtio_mmio_signal_config;
+               vdev->ops->init                 = virtio_mmio_init;
+               vdev->ops->exit                 = virtio_mmio_exit;
+               vdev->ops->init(kvm, dev, vdev, device_id, subsys_id, class);
+               break;
+       default:
+               return -1;
+       };
+
+       return 0;
+}
+
+int virtio_compat_add_message(const char *device, const char *config)
+{
+       int len = 1024;
+       int compat_id;
+       char *title;
+       char *desc;
+
+       title = malloc(len);
+       if (!title)
+               return -ENOMEM;
+
+       desc = malloc(len);
+       if (!desc) {
+               free(title);
+               return -ENOMEM;
+       }
+
+       snprintf(title, len, "%s device was not detected.", device);
+       snprintf(desc,  len, "While you have requested a %s device, "
+                            "the guest kernel did not initialize it.\n"
+                            "\tPlease make sure that the guest kernel was "
+                            "compiled with %s=y enabled in .config.",
+                            device, config);
+
+       compat_id = compat__add_message(title, desc);
+
+       free(desc);
+       free(title);
+
+       return compat_id;
+}
diff --git a/tools/kvm/virtio/mmio.c b/tools/kvm/virtio/mmio.c
new file mode 100644 (file)
index 0000000..6ec33ec
--- /dev/null
@@ -0,0 +1,264 @@
+#include "kvm/virtio-mmio.h"
+#include "kvm/ioeventfd.h"
+#include "kvm/ioport.h"
+#include "kvm/virtio.h"
+#include "kvm/kvm.h"
+#include "kvm/irq.h"
+
+#include <linux/virtio_mmio.h>
+#include <string.h>
+
+static u32 virtio_mmio_io_space_blocks = KVM_VIRTIO_MMIO_AREA;
+
+static u32 virtio_mmio_get_io_space_block(u32 size)
+{
+       u32 block = virtio_mmio_io_space_blocks;
+       virtio_mmio_io_space_blocks += size;
+
+       return block;
+}
+
+static void virtio_mmio_ioevent_callback(struct kvm *kvm, void *param)
+{
+       struct virtio_mmio_ioevent_param *ioeventfd = param;
+       struct virtio_mmio *vmmio = ioeventfd->vdev->virtio;
+
+       ioeventfd->vdev->ops->notify_vq(kvm, vmmio->dev, ioeventfd->vq);
+}
+
+static int virtio_mmio_init_ioeventfd(struct kvm *kvm,
+                                     struct virtio_device *vdev, u32 vq)
+{
+       struct virtio_mmio *vmmio = vdev->virtio;
+       struct ioevent ioevent;
+       int err;
+
+       vmmio->ioeventfds[vq] = (struct virtio_mmio_ioevent_param) {
+               .vdev           = vdev,
+               .vq             = vq,
+       };
+
+       ioevent = (struct ioevent) {
+               .io_addr        = vmmio->addr + VIRTIO_MMIO_QUEUE_NOTIFY,
+               .io_len         = sizeof(u32),
+               .fn             = virtio_mmio_ioevent_callback,
+               .fn_ptr         = &vmmio->ioeventfds[vq],
+               .datamatch      = vq,
+               .fn_kvm         = kvm,
+               .fd             = eventfd(0, 0),
+       };
+
+       if (vdev->use_vhost)
+               /*
+                * Vhost will poll the eventfd in host kernel side,
+                * no need to poll in userspace.
+                */
+               err = ioeventfd__add_event(&ioevent, true, false);
+       else
+               /* Need to poll in userspace. */
+               err = ioeventfd__add_event(&ioevent, true, true);
+       if (err)
+               return err;
+
+       if (vdev->ops->notify_vq_eventfd)
+               vdev->ops->notify_vq_eventfd(kvm, vmmio->dev, vq, ioevent.fd);
+
+       return 0;
+}
+
+int virtio_mmio_signal_vq(struct kvm *kvm, struct virtio_device *vdev, u32 vq)
+{
+       struct virtio_mmio *vmmio = vdev->virtio;
+
+       vmmio->hdr.interrupt_state |= VIRTIO_MMIO_INT_VRING;
+       kvm__irq_trigger(vmmio->kvm, vmmio->irq);
+
+       return 0;
+}
+
+int virtio_mmio_signal_config(struct kvm *kvm, struct virtio_device *vdev)
+{
+       struct virtio_mmio *vmmio = vdev->virtio;
+
+       vmmio->hdr.interrupt_state |= VIRTIO_MMIO_INT_CONFIG;
+       kvm__irq_trigger(vmmio->kvm, vmmio->irq);
+
+       return 0;
+}
+
+static void virtio_mmio_device_specific(u64 addr, u8 *data, u32 len,
+                                       u8 is_write, struct virtio_device *vdev)
+{
+       struct virtio_mmio *vmmio = vdev->virtio;
+       u32 i;
+
+       for (i = 0; i < len; i++) {
+               if (is_write)
+                       vdev->ops->get_config(vmmio->kvm, vmmio->dev)[addr + i] =
+                                             *(u8 *)data + i;
+               else
+                       data[i] = vdev->ops->get_config(vmmio->kvm,
+                                                       vmmio->dev)[addr + i];
+       }
+}
+
+static void virtio_mmio_config_in(u64 addr, void *data, u32 len,
+                                 struct virtio_device *vdev)
+{
+       struct virtio_mmio *vmmio = vdev->virtio;
+       u32 val = 0;
+
+       switch (addr) {
+       case VIRTIO_MMIO_MAGIC_VALUE:
+       case VIRTIO_MMIO_VERSION:
+       case VIRTIO_MMIO_DEVICE_ID:
+       case VIRTIO_MMIO_VENDOR_ID:
+       case VIRTIO_MMIO_STATUS:
+       case VIRTIO_MMIO_INTERRUPT_STATUS:
+               ioport__write32(data, *(u32 *)(((void *)&vmmio->hdr) + addr));
+               break;
+       case VIRTIO_MMIO_HOST_FEATURES:
+               if (vmmio->hdr.host_features_sel == 0)
+                       val = vdev->ops->get_host_features(vmmio->kvm,
+                                                          vmmio->dev);
+               ioport__write32(data, val);
+               break;
+       case VIRTIO_MMIO_QUEUE_PFN:
+               val = vdev->ops->get_pfn_vq(vmmio->kvm, vmmio->dev,
+                                           vmmio->hdr.queue_sel);
+               ioport__write32(data, val);
+               break;
+       case VIRTIO_MMIO_QUEUE_NUM_MAX:
+               val = vdev->ops->get_size_vq(vmmio->kvm, vmmio->dev,
+                                            vmmio->hdr.queue_sel);
+               ioport__write32(data, val);
+               break;
+       default:
+               break;
+       }
+}
+
+static void virtio_mmio_config_out(u64 addr, void *data, u32 len,
+                                  struct virtio_device *vdev)
+{
+       struct virtio_mmio *vmmio = vdev->virtio;
+       u32 val = 0;
+
+       switch (addr) {
+       case VIRTIO_MMIO_HOST_FEATURES_SEL:
+       case VIRTIO_MMIO_GUEST_FEATURES_SEL:
+       case VIRTIO_MMIO_QUEUE_SEL:
+       case VIRTIO_MMIO_STATUS:
+               val = ioport__read32(data);
+               *(u32 *)(((void *)&vmmio->hdr) + addr) = val;
+               break;
+       case VIRTIO_MMIO_GUEST_FEATURES:
+               if (vmmio->hdr.guest_features_sel == 0) {
+                       val = ioport__read32(data);
+                       vdev->ops->set_guest_features(vmmio->kvm,
+                                                     vmmio->dev, val);
+               }
+               break;
+       case VIRTIO_MMIO_GUEST_PAGE_SIZE:
+               val = ioport__read32(data);
+               vmmio->hdr.guest_page_size = val;
+               /* FIXME: set guest page size */
+               break;
+       case VIRTIO_MMIO_QUEUE_NUM:
+               val = ioport__read32(data);
+               vmmio->hdr.queue_num = val;
+               /* FIXME: set vq size */
+               vdev->ops->set_size_vq(vmmio->kvm, vmmio->dev,
+                                      vmmio->hdr.queue_sel, val);
+               break;
+       case VIRTIO_MMIO_QUEUE_ALIGN:
+               val = ioport__read32(data);
+               vmmio->hdr.queue_align = val;
+               /* FIXME: set used ring alignment */
+               break;
+       case VIRTIO_MMIO_QUEUE_PFN:
+               val = ioport__read32(data);
+               virtio_mmio_init_ioeventfd(vmmio->kvm, vdev, vmmio->hdr.queue_sel);
+               vdev->ops->init_vq(vmmio->kvm, vmmio->dev,
+                                  vmmio->hdr.queue_sel, val);
+               break;
+       case VIRTIO_MMIO_QUEUE_NOTIFY:
+               val = ioport__read32(data);
+               vdev->ops->notify_vq(vmmio->kvm, vmmio->dev, val);
+               break;
+       case VIRTIO_MMIO_INTERRUPT_ACK:
+               val = ioport__read32(data);
+               vmmio->hdr.interrupt_state &= ~val;
+               break;
+       default:
+               break;
+       };
+}
+
+static void virtio_mmio_mmio_callback(u64 addr, u8 *data, u32 len,
+                                     u8 is_write, void *ptr)
+{
+       struct virtio_device *vdev = ptr;
+       struct virtio_mmio *vmmio = vdev->virtio;
+       u32 offset = addr - vmmio->addr;
+
+       if (offset >= VIRTIO_MMIO_CONFIG) {
+               offset -= VIRTIO_MMIO_CONFIG;
+               virtio_mmio_device_specific(offset, data, len, is_write, ptr);
+               return;
+       }
+
+       if (is_write)
+               virtio_mmio_config_out(offset, data, len, ptr);
+       else
+               virtio_mmio_config_in(offset, data, len, ptr);
+}
+
+int virtio_mmio_init(struct kvm *kvm, void *dev, struct virtio_device *vdev,
+                    int device_id, int subsys_id, int class)
+{
+       struct virtio_mmio *vmmio = vdev->virtio;
+       u8 device, pin, line;
+
+       vmmio->addr     = virtio_mmio_get_io_space_block(VIRTIO_MMIO_IO_SIZE);
+       vmmio->kvm      = kvm;
+       vmmio->dev      = dev;
+
+       kvm__register_mmio(kvm, vmmio->addr, VIRTIO_MMIO_IO_SIZE,
+                          false, virtio_mmio_mmio_callback, vdev);
+
+       vmmio->hdr = (struct virtio_mmio_hdr) {
+               .magic          = {'v', 'i', 'r', 't'},
+               .version        = 1,
+               .device_id      = device_id - 0x1000 + 1,
+               .vendor_id      = 0x4d564b4c , /* 'LKVM' */
+               .queue_num_max  = 256,
+       };
+
+       if (irq__register_device(subsys_id, &device, &pin, &line) < 0)
+               return -1;
+       vmmio->irq = line;
+
+       /*
+        * Instantiate guest virtio-mmio devices using kernel command line
+        * (or module) parameter, e.g
+        *
+        * virtio_mmio.devices=0x200@0xd2000000:5,0x200@0xd2000200:6
+        */
+       pr_info("virtio-mmio.devices=0x%x@0x%x:%d\n", VIRTIO_MMIO_IO_SIZE, vmmio->addr, line);
+
+       return 0;
+}
+
+int virtio_mmio_exit(struct kvm *kvm, struct virtio_device *vdev)
+{
+       struct virtio_mmio *vmmio = vdev->virtio;
+       int i;
+
+       kvm__deregister_mmio(kvm, vmmio->addr);
+
+       for (i = 0; i < VIRTIO_MMIO_MAX_VQ; i++)
+               ioeventfd__del_event(vmmio->addr + VIRTIO_MMIO_QUEUE_NOTIFY, i);
+
+       return 0;
+}
diff --git a/tools/kvm/virtio/net.c b/tools/kvm/virtio/net.c
new file mode 100644 (file)
index 0000000..d6d344a
--- /dev/null
@@ -0,0 +1,670 @@
+#include "kvm/virtio-pci-dev.h"
+#include "kvm/virtio-net.h"
+#include "kvm/virtio.h"
+#include "kvm/types.h"
+#include "kvm/mutex.h"
+#include "kvm/util.h"
+#include "kvm/kvm.h"
+#include "kvm/irq.h"
+#include "kvm/uip.h"
+#include "kvm/guest_compat.h"
+
+#include <linux/vhost.h>
+#include <linux/virtio_net.h>
+#include <linux/if_tun.h>
+#include <linux/types.h>
+
+#include <arpa/inet.h>
+#include <net/if.h>
+
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/eventfd.h>
+
+#define VIRTIO_NET_QUEUE_SIZE          256
+#define VIRTIO_NET_NUM_QUEUES          2
+#define VIRTIO_NET_RX_QUEUE            0
+#define VIRTIO_NET_TX_QUEUE            1
+
+struct net_dev;
+
+struct net_dev_operations {
+       int (*rx)(struct iovec *iov, u16 in, struct net_dev *ndev);
+       int (*tx)(struct iovec *iov, u16 in, struct net_dev *ndev);
+};
+
+struct net_dev {
+       pthread_mutex_t                 mutex;
+       struct virtio_device            vdev;
+       struct list_head                list;
+
+       struct virt_queue               vqs[VIRTIO_NET_NUM_QUEUES];
+       struct virtio_net_config        config;
+       u32                             features;
+
+       pthread_t                       io_rx_thread;
+       pthread_mutex_t                 io_rx_lock;
+       pthread_cond_t                  io_rx_cond;
+
+       pthread_t                       io_tx_thread;
+       pthread_mutex_t                 io_tx_lock;
+       pthread_cond_t                  io_tx_cond;
+
+       int                             vhost_fd;
+       int                             tap_fd;
+       char                            tap_name[IFNAMSIZ];
+
+       int                             mode;
+
+       struct uip_info                 info;
+       struct net_dev_operations       *ops;
+       struct kvm                      *kvm;
+};
+
+static LIST_HEAD(ndevs);
+static int compat_id = -1;
+
+static void *virtio_net_rx_thread(void *p)
+{
+       struct iovec iov[VIRTIO_NET_QUEUE_SIZE];
+       struct virt_queue *vq;
+       struct kvm *kvm;
+       struct net_dev *ndev = p;
+       u16 out, in;
+       u16 head;
+       int len;
+
+       kvm = ndev->kvm;
+       vq = &ndev->vqs[VIRTIO_NET_RX_QUEUE];
+
+       while (1) {
+               mutex_lock(&ndev->io_rx_lock);
+               if (!virt_queue__available(vq))
+                       pthread_cond_wait(&ndev->io_rx_cond, &ndev->io_rx_lock);
+               mutex_unlock(&ndev->io_rx_lock);
+
+               while (virt_queue__available(vq)) {
+                       head = virt_queue__get_iov(vq, iov, &out, &in, kvm);
+                       len = ndev->ops->rx(iov, in, ndev);
+                       virt_queue__set_used_elem(vq, head, len);
+
+                       /* We should interrupt guest right now, otherwise latency is huge. */
+                       if (virtio_queue__should_signal(&ndev->vqs[VIRTIO_NET_RX_QUEUE]))
+                               ndev->vdev.ops->signal_vq(kvm, &ndev->vdev,
+                                                          VIRTIO_NET_RX_QUEUE);
+               }
+       }
+
+       pthread_exit(NULL);
+       return NULL;
+
+}
+
+static void *virtio_net_tx_thread(void *p)
+{
+       struct iovec iov[VIRTIO_NET_QUEUE_SIZE];
+       struct virt_queue *vq;
+       struct kvm *kvm;
+       struct net_dev *ndev = p;
+       u16 out, in;
+       u16 head;
+       int len;
+
+       kvm = ndev->kvm;
+       vq = &ndev->vqs[VIRTIO_NET_TX_QUEUE];
+
+       while (1) {
+               mutex_lock(&ndev->io_tx_lock);
+               if (!virt_queue__available(vq))
+                       pthread_cond_wait(&ndev->io_tx_cond, &ndev->io_tx_lock);
+               mutex_unlock(&ndev->io_tx_lock);
+
+               while (virt_queue__available(vq)) {
+                       head = virt_queue__get_iov(vq, iov, &out, &in, kvm);
+                       len = ndev->ops->tx(iov, out, ndev);
+                       virt_queue__set_used_elem(vq, head, len);
+               }
+
+               if (virtio_queue__should_signal(&ndev->vqs[VIRTIO_NET_TX_QUEUE]))
+                       ndev->vdev.ops->signal_vq(kvm, &ndev->vdev, VIRTIO_NET_TX_QUEUE);
+       }
+
+       pthread_exit(NULL);
+
+       return NULL;
+
+}
+
+static void virtio_net_handle_callback(struct kvm *kvm, struct net_dev *ndev, int queue)
+{
+       switch (queue) {
+       case VIRTIO_NET_TX_QUEUE:
+               mutex_lock(&ndev->io_tx_lock);
+               pthread_cond_signal(&ndev->io_tx_cond);
+               mutex_unlock(&ndev->io_tx_lock);
+               break;
+       case VIRTIO_NET_RX_QUEUE:
+               mutex_lock(&ndev->io_rx_lock);
+               pthread_cond_signal(&ndev->io_rx_cond);
+               mutex_unlock(&ndev->io_rx_lock);
+               break;
+       default:
+               pr_warning("Unknown queue index %u", queue);
+       }
+}
+
+static bool virtio_net__tap_init(const struct virtio_net_params *params,
+                                       struct net_dev *ndev)
+{
+       int sock = socket(AF_INET, SOCK_STREAM, 0);
+       int pid, status, offload, hdr_len;
+       struct sockaddr_in sin = {0};
+       struct ifreq ifr;
+
+       /* Did the user already gave us the FD? */
+       if (params->fd) {
+               ndev->tap_fd = params->fd;
+               return 1;
+       }
+
+       ndev->tap_fd = open("/dev/net/tun", O_RDWR);
+       if (ndev->tap_fd < 0) {
+               pr_warning("Unable to open /dev/net/tun");
+               goto fail;
+       }
+
+       memset(&ifr, 0, sizeof(ifr));
+       ifr.ifr_flags = IFF_TAP | IFF_NO_PI | IFF_VNET_HDR;
+       if (ioctl(ndev->tap_fd, TUNSETIFF, &ifr) < 0) {
+               pr_warning("Config tap device error. Are you root?");
+               goto fail;
+       }
+
+       strncpy(ndev->tap_name, ifr.ifr_name, sizeof(ndev->tap_name));
+
+       if (ioctl(ndev->tap_fd, TUNSETNOCSUM, 1) < 0) {
+               pr_warning("Config tap device TUNSETNOCSUM error");
+               goto fail;
+       }
+
+       hdr_len = sizeof(struct virtio_net_hdr);
+       if (ioctl(ndev->tap_fd, TUNSETVNETHDRSZ, &hdr_len) < 0)
+               pr_warning("Config tap device TUNSETVNETHDRSZ error");
+
+       offload = TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6 | TUN_F_UFO;
+       if (ioctl(ndev->tap_fd, TUNSETOFFLOAD, offload) < 0) {
+               pr_warning("Config tap device TUNSETOFFLOAD error");
+               goto fail;
+       }
+
+       if (strcmp(params->script, "none")) {
+               pid = fork();
+               if (pid == 0) {
+                       execl(params->script, params->script, ndev->tap_name, NULL);
+                       _exit(1);
+               } else {
+                       waitpid(pid, &status, 0);
+                       if (WIFEXITED(status) && WEXITSTATUS(status) != 0) {
+                               pr_warning("Fail to setup tap by %s", params->script);
+                               goto fail;
+                       }
+               }
+       } else {
+               memset(&ifr, 0, sizeof(ifr));
+               strncpy(ifr.ifr_name, ndev->tap_name, sizeof(ndev->tap_name));
+               sin.sin_addr.s_addr = inet_addr(params->host_ip);
+               memcpy(&(ifr.ifr_addr), &sin, sizeof(ifr.ifr_addr));
+               ifr.ifr_addr.sa_family = AF_INET;
+               if (ioctl(sock, SIOCSIFADDR, &ifr) < 0) {
+                       pr_warning("Could not set ip address on tap device");
+                       goto fail;
+               }
+       }
+
+       memset(&ifr, 0, sizeof(ifr));
+       strncpy(ifr.ifr_name, ndev->tap_name, sizeof(ndev->tap_name));
+       ioctl(sock, SIOCGIFFLAGS, &ifr);
+       ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
+       if (ioctl(sock, SIOCSIFFLAGS, &ifr) < 0)
+               pr_warning("Could not bring tap device up");
+
+       close(sock);
+
+       return 1;
+
+fail:
+       if (sock >= 0)
+               close(sock);
+       if (ndev->tap_fd >= 0)
+               close(ndev->tap_fd);
+
+       return 0;
+}
+
+static void virtio_net__io_thread_init(struct kvm *kvm, struct net_dev *ndev)
+{
+       pthread_mutex_init(&ndev->io_tx_lock, NULL);
+       pthread_mutex_init(&ndev->io_rx_lock, NULL);
+
+       pthread_cond_init(&ndev->io_tx_cond, NULL);
+       pthread_cond_init(&ndev->io_rx_cond, NULL);
+
+       pthread_create(&ndev->io_tx_thread, NULL, virtio_net_tx_thread, ndev);
+       pthread_create(&ndev->io_rx_thread, NULL, virtio_net_rx_thread, ndev);
+}
+
+static inline int tap_ops_tx(struct iovec *iov, u16 out, struct net_dev *ndev)
+{
+       return writev(ndev->tap_fd, iov, out);
+}
+
+static inline int tap_ops_rx(struct iovec *iov, u16 in, struct net_dev *ndev)
+{
+       return readv(ndev->tap_fd, iov, in);
+}
+
+static inline int uip_ops_tx(struct iovec *iov, u16 out, struct net_dev *ndev)
+{
+       return uip_tx(iov, out, &ndev->info);
+}
+
+static inline int uip_ops_rx(struct iovec *iov, u16 in, struct net_dev *ndev)
+{
+       return uip_rx(iov, in, &ndev->info);
+}
+
+static struct net_dev_operations tap_ops = {
+       .rx     = tap_ops_rx,
+       .tx     = tap_ops_tx,
+};
+
+static struct net_dev_operations uip_ops = {
+       .rx     = uip_ops_rx,
+       .tx     = uip_ops_tx,
+};
+
+static u8 *get_config(struct kvm *kvm, void *dev)
+{
+       struct net_dev *ndev = dev;
+
+       return ((u8 *)(&ndev->config));
+}
+
+static u32 get_host_features(struct kvm *kvm, void *dev)
+{
+       return 1UL << VIRTIO_NET_F_MAC
+               | 1UL << VIRTIO_NET_F_CSUM
+               | 1UL << VIRTIO_NET_F_HOST_UFO
+               | 1UL << VIRTIO_NET_F_HOST_TSO4
+               | 1UL << VIRTIO_NET_F_HOST_TSO6
+               | 1UL << VIRTIO_NET_F_GUEST_UFO
+               | 1UL << VIRTIO_NET_F_GUEST_TSO4
+               | 1UL << VIRTIO_NET_F_GUEST_TSO6
+               | 1UL << VIRTIO_RING_F_EVENT_IDX
+               | 1UL << VIRTIO_RING_F_INDIRECT_DESC;
+}
+
+static void set_guest_features(struct kvm *kvm, void *dev, u32 features)
+{
+       struct net_dev *ndev = dev;
+
+       ndev->features = features;
+}
+
+static int init_vq(struct kvm *kvm, void *dev, u32 vq, u32 pfn)
+{
+       struct vhost_vring_state state = { .index = vq };
+       struct vhost_vring_addr addr;
+       struct net_dev *ndev = dev;
+       struct virt_queue *queue;
+       void *p;
+       int r;
+
+       compat__remove_message(compat_id);
+
+       queue           = &ndev->vqs[vq];
+       queue->pfn      = pfn;
+       p               = guest_pfn_to_host(kvm, queue->pfn);
+
+       /* FIXME: respect pci and mmio vring alignment */
+       vring_init(&queue->vring, VIRTIO_NET_QUEUE_SIZE, p, VIRTIO_PCI_VRING_ALIGN);
+
+       if (ndev->vhost_fd == 0)
+               return 0;
+
+       state.num = queue->vring.num;
+       r = ioctl(ndev->vhost_fd, VHOST_SET_VRING_NUM, &state);
+       if (r < 0)
+               die_perror("VHOST_SET_VRING_NUM failed");
+       state.num = 0;
+       r = ioctl(ndev->vhost_fd, VHOST_SET_VRING_BASE, &state);
+       if (r < 0)
+               die_perror("VHOST_SET_VRING_BASE failed");
+
+       addr = (struct vhost_vring_addr) {
+               .index = vq,
+               .desc_user_addr = (u64)(unsigned long)queue->vring.desc,
+               .avail_user_addr = (u64)(unsigned long)queue->vring.avail,
+               .used_user_addr = (u64)(unsigned long)queue->vring.used,
+       };
+
+       r = ioctl(ndev->vhost_fd, VHOST_SET_VRING_ADDR, &addr);
+       if (r < 0)
+               die_perror("VHOST_SET_VRING_ADDR failed");
+
+       return 0;
+}
+
+static void notify_vq_gsi(struct kvm *kvm, void *dev, u32 vq, u32 gsi)
+{
+       struct net_dev *ndev = dev;
+       struct kvm_irqfd irq;
+       struct vhost_vring_file file;
+       int r;
+
+       if (ndev->vhost_fd == 0)
+               return;
+
+       irq = (struct kvm_irqfd) {
+               .gsi    = gsi,
+               .fd     = eventfd(0, 0),
+       };
+       file = (struct vhost_vring_file) {
+               .index  = vq,
+               .fd     = irq.fd,
+       };
+
+       r = ioctl(kvm->vm_fd, KVM_IRQFD, &irq);
+       if (r < 0)
+               die_perror("KVM_IRQFD failed");
+
+       r = ioctl(ndev->vhost_fd, VHOST_SET_VRING_CALL, &file);
+       if (r < 0)
+               die_perror("VHOST_SET_VRING_CALL failed");
+       file.fd = ndev->tap_fd;
+       r = ioctl(ndev->vhost_fd, VHOST_NET_SET_BACKEND, &file);
+       if (r != 0)
+               die("VHOST_NET_SET_BACKEND failed %d", errno);
+
+}
+
+static void notify_vq_eventfd(struct kvm *kvm, void *dev, u32 vq, u32 efd)
+{
+       struct net_dev *ndev = dev;
+       struct vhost_vring_file file = {
+               .index  = vq,
+               .fd     = efd,
+       };
+       int r;
+
+       if (ndev->vhost_fd == 0)
+               return;
+
+       r = ioctl(ndev->vhost_fd, VHOST_SET_VRING_KICK, &file);
+       if (r < 0)
+               die_perror("VHOST_SET_VRING_KICK failed");
+}
+
+static int notify_vq(struct kvm *kvm, void *dev, u32 vq)
+{
+       struct net_dev *ndev = dev;
+
+       virtio_net_handle_callback(kvm, ndev, vq);
+
+       return 0;
+}
+
+static int get_pfn_vq(struct kvm *kvm, void *dev, u32 vq)
+{
+       struct net_dev *ndev = dev;
+
+       return ndev->vqs[vq].pfn;
+}
+
+static int get_size_vq(struct kvm *kvm, void *dev, u32 vq)
+{
+       /* FIXME: dynamic */
+       return VIRTIO_NET_QUEUE_SIZE;
+}
+
+static int set_size_vq(struct kvm *kvm, void *dev, u32 vq, int size)
+{
+       /* FIXME: dynamic */
+       return size;
+}
+
+static struct virtio_ops net_dev_virtio_ops = (struct virtio_ops) {
+       .get_config             = get_config,
+       .get_host_features      = get_host_features,
+       .set_guest_features     = set_guest_features,
+       .init_vq                = init_vq,
+       .get_pfn_vq             = get_pfn_vq,
+       .get_size_vq            = get_size_vq,
+       .set_size_vq            = set_size_vq,
+       .notify_vq              = notify_vq,
+       .notify_vq_gsi          = notify_vq_gsi,
+       .notify_vq_eventfd      = notify_vq_eventfd,
+};
+
+static void virtio_net__vhost_init(struct kvm *kvm, struct net_dev *ndev)
+{
+       u64 features = 1UL << VIRTIO_RING_F_EVENT_IDX;
+       struct vhost_memory *mem;
+       int r;
+
+       ndev->vhost_fd = open("/dev/vhost-net", O_RDWR);
+       if (ndev->vhost_fd < 0)
+               die_perror("Failed openning vhost-net device");
+
+       mem = calloc(1, sizeof(*mem) + sizeof(struct vhost_memory_region));
+       if (mem == NULL)
+               die("Failed allocating memory for vhost memory map");
+
+       mem->nregions = 1;
+       mem->regions[0] = (struct vhost_memory_region) {
+               .guest_phys_addr        = 0,
+               .memory_size            = kvm->ram_size,
+               .userspace_addr         = (unsigned long)kvm->ram_start,
+       };
+
+       r = ioctl(ndev->vhost_fd, VHOST_SET_OWNER);
+       if (r != 0)
+               die_perror("VHOST_SET_OWNER failed");
+
+       r = ioctl(ndev->vhost_fd, VHOST_SET_FEATURES, &features);
+       if (r != 0)
+               die_perror("VHOST_SET_FEATURES failed");
+       r = ioctl(ndev->vhost_fd, VHOST_SET_MEM_TABLE, mem);
+       if (r != 0)
+               die_perror("VHOST_SET_MEM_TABLE failed");
+
+       ndev->vdev.use_vhost = true;
+
+       free(mem);
+}
+
+static inline void str_to_mac(const char *str, char *mac)
+{
+       sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
+               mac, mac+1, mac+2, mac+3, mac+4, mac+5);
+}
+static int set_net_param(struct kvm *kvm, struct virtio_net_params *p,
+                       const char *param, const char *val)
+{
+       if (strcmp(param, "guest_mac") == 0) {
+               str_to_mac(val, p->guest_mac);
+       } else if (strcmp(param, "mode") == 0) {
+               if (!strncmp(val, "user", 4)) {
+                       int i;
+
+                       for (i = 0; i < kvm->cfg.num_net_devices; i++)
+                               if (kvm->cfg.net_params[i].mode == NET_MODE_USER)
+                                       die("Only one usermode network device allowed at a time");
+                       p->mode = NET_MODE_USER;
+               } else if (!strncmp(val, "tap", 3)) {
+                       p->mode = NET_MODE_TAP;
+               } else if (!strncmp(val, "none", 4)) {
+                       kvm->cfg.no_net = 1;
+                       return -1;
+               } else
+                       die("Unknown network mode %s, please use user, tap or none", kvm->cfg.network);
+       } else if (strcmp(param, "script") == 0) {
+               p->script = strdup(val);
+       } else if (strcmp(param, "guest_ip") == 0) {
+               p->guest_ip = strdup(val);
+       } else if (strcmp(param, "host_ip") == 0) {
+               p->host_ip = strdup(val);
+       } else if (strcmp(param, "trans") == 0) {
+               p->trans = strdup(val);
+       } else if (strcmp(param, "vhost") == 0) {
+               p->vhost = atoi(val);
+       } else if (strcmp(param, "fd") == 0) {
+               p->fd = atoi(val);
+       } else
+               die("Unknown network parameter %s", param);
+
+       return 0;
+}
+
+int netdev_parser(const struct option *opt, const char *arg, int unset)
+{
+       struct virtio_net_params p;
+       char *buf = NULL, *cmd = NULL, *cur = NULL;
+       bool on_cmd = true;
+       struct kvm *kvm = opt->ptr;
+
+       if (arg) {
+               buf = strdup(arg);
+               if (buf == NULL)
+                       die("Failed allocating new net buffer");
+               cur = strtok(buf, ",=");
+       }
+
+       p = (struct virtio_net_params) {
+               .guest_ip       = DEFAULT_GUEST_ADDR,
+               .host_ip        = DEFAULT_HOST_ADDR,
+               .script         = DEFAULT_SCRIPT,
+               .mode           = NET_MODE_TAP,
+       };
+
+       str_to_mac(DEFAULT_GUEST_MAC, p.guest_mac);
+       p.guest_mac[5] += kvm->cfg.num_net_devices;
+
+       while (cur) {
+               if (on_cmd) {
+                       cmd = cur;
+               } else {
+                       if (set_net_param(kvm, &p, cmd, cur) < 0)
+                               goto done;
+               }
+               on_cmd = !on_cmd;
+
+               cur = strtok(NULL, ",=");
+       };
+
+       kvm->cfg.num_net_devices++;
+
+       kvm->cfg.net_params = realloc(kvm->cfg.net_params, kvm->cfg.num_net_devices * sizeof(*kvm->cfg.net_params));
+       if (kvm->cfg.net_params == NULL)
+               die("Failed adding new network device");
+
+       kvm->cfg.net_params[kvm->cfg.num_net_devices - 1] = p;
+
+done:
+       free(buf);
+       return 0;
+}
+
+static int virtio_net__init_one(struct virtio_net_params *params)
+{
+       int i;
+       struct net_dev *ndev;
+
+       ndev = calloc(1, sizeof(struct net_dev));
+       if (ndev == NULL)
+               return -ENOMEM;
+
+       list_add_tail(&ndev->list, &ndevs);
+
+       ndev->kvm = params->kvm;
+
+       mutex_init(&ndev->mutex);
+       ndev->config.status = VIRTIO_NET_S_LINK_UP;
+
+       for (i = 0 ; i < 6 ; i++) {
+               ndev->config.mac[i]             = params->guest_mac[i];
+               ndev->info.guest_mac.addr[i]    = params->guest_mac[i];
+               ndev->info.host_mac.addr[i]     = params->host_mac[i];
+       }
+
+       ndev->mode = params->mode;
+       if (ndev->mode == NET_MODE_TAP) {
+               if (!virtio_net__tap_init(params, ndev))
+                       die_perror("You have requested a TAP device, but creation of one has failed because");
+               ndev->ops = &tap_ops;
+       } else {
+               ndev->info.host_ip              = ntohl(inet_addr(params->host_ip));
+               ndev->info.guest_ip             = ntohl(inet_addr(params->guest_ip));
+               ndev->info.guest_netmask        = ntohl(inet_addr("255.255.255.0"));
+               ndev->info.buf_nr               = 20,
+               uip_init(&ndev->info);
+               ndev->ops = &uip_ops;
+       }
+
+       if (params->trans && strcmp(params->trans, "mmio") == 0)
+               virtio_init(params->kvm, ndev, &ndev->vdev, &net_dev_virtio_ops,
+                           VIRTIO_MMIO, PCI_DEVICE_ID_VIRTIO_NET, VIRTIO_ID_NET, PCI_CLASS_NET);
+       else
+               virtio_init(params->kvm, ndev, &ndev->vdev, &net_dev_virtio_ops,
+                           VIRTIO_PCI, PCI_DEVICE_ID_VIRTIO_NET, VIRTIO_ID_NET, PCI_CLASS_NET);
+
+       if (params->vhost)
+               virtio_net__vhost_init(params->kvm, ndev);
+       else
+               virtio_net__io_thread_init(params->kvm, ndev);
+
+       if (compat_id == -1)
+               compat_id = virtio_compat_add_message("virtio-net", "CONFIG_VIRTIO_NET");
+
+       return 0;
+}
+
+int virtio_net__init(struct kvm *kvm)
+{
+       int i;
+
+       for (i = 0; i < kvm->cfg.num_net_devices; i++) {
+               kvm->cfg.net_params[i].kvm = kvm;
+               virtio_net__init_one(&kvm->cfg.net_params[i]);
+       }
+
+       if (kvm->cfg.num_net_devices == 0 && kvm->cfg.no_net == 0) {
+               struct virtio_net_params net_params;
+
+               net_params = (struct virtio_net_params) {
+                       .guest_ip       = kvm->cfg.guest_ip,
+                       .host_ip        = kvm->cfg.host_ip,
+                       .kvm            = kvm,
+                       .script         = kvm->cfg.script,
+                       .mode           = NET_MODE_USER,
+               };
+               str_to_mac(kvm->cfg.guest_mac, net_params.guest_mac);
+               str_to_mac(kvm->cfg.host_mac, net_params.host_mac);
+
+               virtio_net__init_one(&net_params);
+       }
+
+       return 0;
+}
+virtio_dev_init(virtio_net__init);
+
+int virtio_net__exit(struct kvm *kvm)
+{
+       return 0;
+}
+virtio_dev_exit(virtio_net__exit);
diff --git a/tools/kvm/virtio/pci.c b/tools/kvm/virtio/pci.c
new file mode 100644 (file)
index 0000000..b6ac571
--- /dev/null
@@ -0,0 +1,398 @@
+#include "kvm/virtio-pci.h"
+
+#include "kvm/ioport.h"
+#include "kvm/kvm.h"
+#include "kvm/virtio-pci-dev.h"
+#include "kvm/irq.h"
+#include "kvm/virtio.h"
+#include "kvm/ioeventfd.h"
+
+#include <sys/ioctl.h>
+#include <linux/virtio_pci.h>
+#include <linux/byteorder.h>
+#include <string.h>
+
+static void virtio_pci__ioevent_callback(struct kvm *kvm, void *param)
+{
+       struct virtio_pci_ioevent_param *ioeventfd = param;
+       struct virtio_pci *vpci = ioeventfd->vdev->virtio;
+
+       ioeventfd->vdev->ops->notify_vq(kvm, vpci->dev, ioeventfd->vq);
+}
+
+static int virtio_pci__init_ioeventfd(struct kvm *kvm, struct virtio_device *vdev, u32 vq)
+{
+       struct ioevent ioevent;
+       struct virtio_pci *vpci = vdev->virtio;
+       int r;
+
+       vpci->ioeventfds[vq] = (struct virtio_pci_ioevent_param) {
+               .vdev           = vdev,
+               .vq             = vq,
+       };
+
+       ioevent = (struct ioevent) {
+               .io_addr        = vpci->base_addr + VIRTIO_PCI_QUEUE_NOTIFY,
+               .io_len         = sizeof(u16),
+               .fn             = virtio_pci__ioevent_callback,
+               .fn_ptr         = &vpci->ioeventfds[vq],
+               .datamatch      = vq,
+               .fn_kvm         = kvm,
+               .fd             = eventfd(0, 0),
+       };
+
+       if (vdev->use_vhost)
+               /*
+                * Vhost will poll the eventfd in host kernel side,
+                * no need to poll in userspace.
+                */
+               r = ioeventfd__add_event(&ioevent, true, false);
+       else
+               /* Need to poll in userspace. */
+               r = ioeventfd__add_event(&ioevent, true, true);
+       if (r)
+               return r;
+
+       if (vdev->ops->notify_vq_eventfd)
+               vdev->ops->notify_vq_eventfd(kvm, vpci->dev, vq, ioevent.fd);
+
+       return 0;
+}
+
+static inline bool virtio_pci__msix_enabled(struct virtio_pci *vpci)
+{
+       return vpci->pci_hdr.msix.ctrl & cpu_to_le16(PCI_MSIX_FLAGS_ENABLE);
+}
+
+static bool virtio_pci__specific_io_in(struct kvm *kvm, struct virtio_device *vdev, u16 port,
+                                       void *data, int size, int offset)
+{
+       u32 config_offset;
+       struct virtio_pci *vpci = vdev->virtio;
+       int type = virtio__get_dev_specific_field(offset - 20,
+                                                       virtio_pci__msix_enabled(vpci),
+                                                       &config_offset);
+       if (type == VIRTIO_PCI_O_MSIX) {
+               switch (offset) {
+               case VIRTIO_MSI_CONFIG_VECTOR:
+                       ioport__write16(data, vpci->config_vector);
+                       break;
+               case VIRTIO_MSI_QUEUE_VECTOR:
+                       ioport__write16(data, vpci->vq_vector[vpci->queue_selector]);
+                       break;
+               };
+
+               return true;
+       } else if (type == VIRTIO_PCI_O_CONFIG) {
+               u8 cfg;
+
+               cfg = vdev->ops->get_config(kvm, vpci->dev)[config_offset];
+               ioport__write8(data, cfg);
+               return true;
+       }
+
+       return false;
+}
+
+static bool virtio_pci__io_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
+{
+       unsigned long offset;
+       bool ret = true;
+       struct virtio_device *vdev;
+       struct virtio_pci *vpci;
+       u32 val;
+
+       vdev = ioport->priv;
+       vpci = vdev->virtio;
+       offset = port - vpci->base_addr;
+
+       switch (offset) {
+       case VIRTIO_PCI_HOST_FEATURES:
+               val = vdev->ops->get_host_features(kvm, vpci->dev);
+               ioport__write32(data, val);
+               break;
+       case VIRTIO_PCI_QUEUE_PFN:
+               val = vdev->ops->get_pfn_vq(kvm, vpci->dev, vpci->queue_selector);
+               ioport__write32(data, val);
+               break;
+       case VIRTIO_PCI_QUEUE_NUM:
+               val = vdev->ops->get_size_vq(kvm, vpci->dev, vpci->queue_selector);
+               ioport__write16(data, val);
+               break;
+       case VIRTIO_PCI_STATUS:
+               ioport__write8(data, vpci->status);
+               break;
+       case VIRTIO_PCI_ISR:
+               ioport__write8(data, vpci->isr);
+               kvm__irq_line(kvm, vpci->pci_hdr.irq_line, VIRTIO_IRQ_LOW);
+               vpci->isr = VIRTIO_IRQ_LOW;
+               break;
+       default:
+               ret = virtio_pci__specific_io_in(kvm, vdev, port, data, size, offset);
+               break;
+       };
+
+       return ret;
+}
+
+static bool virtio_pci__specific_io_out(struct kvm *kvm, struct virtio_device *vdev, u16 port,
+                                       void *data, int size, int offset)
+{
+       struct virtio_pci *vpci = vdev->virtio;
+       u32 config_offset, gsi, vec;
+       int type = virtio__get_dev_specific_field(offset - 20, virtio_pci__msix_enabled(vpci),
+                                                       &config_offset);
+       if (type == VIRTIO_PCI_O_MSIX) {
+               switch (offset) {
+               case VIRTIO_MSI_CONFIG_VECTOR:
+                       vec = vpci->config_vector = ioport__read16(data);
+
+                       gsi = irq__add_msix_route(kvm, &vpci->msix_table[vec].msg);
+
+                       vpci->config_gsi = gsi;
+                       break;
+               case VIRTIO_MSI_QUEUE_VECTOR:
+                       vec = vpci->vq_vector[vpci->queue_selector] = ioport__read16(data);
+
+                       gsi = irq__add_msix_route(kvm, &vpci->msix_table[vec].msg);
+                       vpci->gsis[vpci->queue_selector] = gsi;
+                       if (vdev->ops->notify_vq_gsi)
+                               vdev->ops->notify_vq_gsi(kvm, vpci->dev,
+                                                       vpci->queue_selector, gsi);
+                       break;
+               };
+
+               return true;
+       } else if (type == VIRTIO_PCI_O_CONFIG) {
+               vdev->ops->get_config(kvm, vpci->dev)[config_offset] = *(u8 *)data;
+
+               return true;
+       }
+
+       return false;
+}
+
+static bool virtio_pci__io_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
+{
+       unsigned long offset;
+       bool ret = true;
+       struct virtio_device *vdev;
+       struct virtio_pci *vpci;
+       u32 val;
+
+       vdev = ioport->priv;
+       vpci = vdev->virtio;
+       offset = port - vpci->base_addr;
+
+       switch (offset) {
+       case VIRTIO_PCI_GUEST_FEATURES:
+               val = ioport__read32(data);
+               vdev->ops->set_guest_features(kvm, vpci->dev, val);
+               break;
+       case VIRTIO_PCI_QUEUE_PFN:
+               val = ioport__read32(data);
+               virtio_pci__init_ioeventfd(kvm, vdev, vpci->queue_selector);
+               vdev->ops->init_vq(kvm, vpci->dev, vpci->queue_selector, val);
+               break;
+       case VIRTIO_PCI_QUEUE_SEL:
+               vpci->queue_selector = ioport__read16(data);
+               break;
+       case VIRTIO_PCI_QUEUE_NOTIFY:
+               val = ioport__read16(data);
+               vdev->ops->notify_vq(kvm, vpci->dev, val);
+               break;
+       case VIRTIO_PCI_STATUS:
+               vpci->status = ioport__read8(data);
+               break;
+       default:
+               ret = virtio_pci__specific_io_out(kvm, vdev, port, data, size, offset);
+               break;
+       };
+
+       return ret;
+}
+
+static struct ioport_operations virtio_pci__io_ops = {
+       .io_in  = virtio_pci__io_in,
+       .io_out = virtio_pci__io_out,
+};
+
+static void virtio_pci__mmio_callback(u64 addr, u8 *data, u32 len, u8 is_write, void *ptr)
+{
+       struct virtio_pci *vpci = ptr;
+       void *table;
+       u32 offset;
+
+       if (addr > vpci->msix_io_block + PCI_IO_SIZE) {
+               table   = &vpci->msix_pba;
+               offset  = vpci->msix_io_block + PCI_IO_SIZE;
+       } else {
+               table   = &vpci->msix_table;
+               offset  = vpci->msix_io_block;
+       }
+
+       if (is_write)
+               memcpy(table + addr - offset, data, len);
+       else
+               memcpy(data, table + addr - offset, len);
+}
+
+static void virtio_pci__signal_msi(struct kvm *kvm, struct virtio_pci *vpci, int vec)
+{
+       struct kvm_msi msi = {
+               .address_lo = vpci->msix_table[vec].msg.address_lo,
+               .address_hi = vpci->msix_table[vec].msg.address_hi,
+               .data = vpci->msix_table[vec].msg.data,
+       };
+
+       ioctl(kvm->vm_fd, KVM_SIGNAL_MSI, &msi);
+}
+
+int virtio_pci__signal_vq(struct kvm *kvm, struct virtio_device *vdev, u32 vq)
+{
+       struct virtio_pci *vpci = vdev->virtio;
+       int tbl = vpci->vq_vector[vq];
+
+       if (virtio_pci__msix_enabled(vpci)) {
+               if (vpci->pci_hdr.msix.ctrl & cpu_to_le16(PCI_MSIX_FLAGS_MASKALL) ||
+                   vpci->msix_table[tbl].ctrl & cpu_to_le16(PCI_MSIX_ENTRY_CTRL_MASKBIT)) {
+
+                       vpci->msix_pba |= 1 << tbl;
+                       return 0;
+               }
+
+               if (vpci->features & VIRTIO_PCI_F_SIGNAL_MSI)
+                       virtio_pci__signal_msi(kvm, vpci, vpci->vq_vector[vq]);
+               else
+                       kvm__irq_trigger(kvm, vpci->gsis[vq]);
+       } else {
+               vpci->isr = VIRTIO_IRQ_HIGH;
+               kvm__irq_trigger(kvm, vpci->pci_hdr.irq_line);
+       }
+       return 0;
+}
+
+int virtio_pci__signal_config(struct kvm *kvm, struct virtio_device *vdev)
+{
+       struct virtio_pci *vpci = vdev->virtio;
+       int tbl = vpci->config_vector;
+
+       if (virtio_pci__msix_enabled(vpci)) {
+               if (vpci->pci_hdr.msix.ctrl & cpu_to_le16(PCI_MSIX_FLAGS_MASKALL) ||
+                   vpci->msix_table[tbl].ctrl & cpu_to_le16(PCI_MSIX_ENTRY_CTRL_MASKBIT)) {
+
+                       vpci->msix_pba |= 1 << tbl;
+                       return 0;
+               }
+
+               if (vpci->features & VIRTIO_PCI_F_SIGNAL_MSI)
+                       virtio_pci__signal_msi(kvm, vpci, vpci->vq_vector[vpci->config_vector]);
+               else
+                       kvm__irq_trigger(kvm, vpci->config_gsi);
+       } else {
+               vpci->isr = VIRTIO_PCI_ISR_CONFIG;
+               kvm__irq_trigger(kvm, vpci->pci_hdr.irq_line);
+       }
+
+       return 0;
+}
+
+int virtio_pci__init(struct kvm *kvm, void *dev, struct virtio_device *vdev,
+                    int device_id, int subsys_id, int class)
+{
+       struct virtio_pci *vpci = vdev->virtio;
+       u8 pin, line, ndev;
+       int r;
+
+       vpci->dev = dev;
+       vpci->msix_io_block = pci_get_io_space_block(PCI_IO_SIZE * 2);
+
+       r = ioport__register(kvm, IOPORT_EMPTY, &virtio_pci__io_ops, IOPORT_SIZE, vdev);
+       if (r < 0)
+               return r;
+
+       vpci->base_addr = (u16)r;
+       r = kvm__register_mmio(kvm, vpci->msix_io_block, PCI_IO_SIZE, false,
+                              virtio_pci__mmio_callback, vpci);
+       if (r < 0)
+               goto free_ioport;
+
+       vpci->pci_hdr = (struct pci_device_header) {
+               .vendor_id              = cpu_to_le16(PCI_VENDOR_ID_REDHAT_QUMRANET),
+               .device_id              = cpu_to_le16(device_id),
+               .header_type            = PCI_HEADER_TYPE_NORMAL,
+               .revision_id            = 0,
+               .class[0]               = class & 0xff,
+               .class[1]               = (class >> 8) & 0xff,
+               .class[2]               = (class >> 16) & 0xff,
+               .subsys_vendor_id       = cpu_to_le16(PCI_SUBSYSTEM_VENDOR_ID_REDHAT_QUMRANET),
+               .subsys_id              = cpu_to_le16(subsys_id),
+               .bar[0]                 = cpu_to_le32(vpci->base_addr
+                                                       | PCI_BASE_ADDRESS_SPACE_IO),
+               .bar[1]                 = cpu_to_le32(vpci->msix_io_block
+                                                       | PCI_BASE_ADDRESS_SPACE_MEMORY),
+               .status                 = cpu_to_le16(PCI_STATUS_CAP_LIST),
+               .capabilities           = (void *)&vpci->pci_hdr.msix - (void *)&vpci->pci_hdr,
+               .bar_size[0]            = IOPORT_SIZE,
+               .bar_size[1]            = PCI_IO_SIZE,
+               .bar_size[3]            = PCI_IO_SIZE,
+       };
+
+       vpci->pci_hdr.msix.cap = PCI_CAP_ID_MSIX;
+       vpci->pci_hdr.msix.next = 0;
+       /*
+        * We at most have VIRTIO_PCI_MAX_VQ entries for virt queue,
+        * VIRTIO_PCI_MAX_CONFIG entries for config.
+        *
+        * To quote the PCI spec:
+        *
+        * System software reads this field to determine the
+        * MSI-X Table Size N, which is encoded as N-1.
+        * For example, a returned value of "00000000011"
+        * indicates a table size of 4.
+        */
+       vpci->pci_hdr.msix.ctrl = cpu_to_le16(VIRTIO_PCI_MAX_VQ + VIRTIO_PCI_MAX_CONFIG - 1);
+
+       /*
+        * Both table and PBA could be mapped on the same BAR, but for now
+        * we're not in short of BARs
+        */
+       vpci->pci_hdr.msix.table_offset = cpu_to_le32(1); /* Use BAR 1 */
+       vpci->pci_hdr.msix.pba_offset = cpu_to_le32(1 | PCI_IO_SIZE); /* Use BAR 3 */
+       vpci->config_vector = 0;
+
+       r = irq__register_device(subsys_id, &ndev, &pin, &line);
+       if (r < 0)
+               goto free_mmio;
+
+       if (kvm__supports_extension(kvm, KVM_CAP_SIGNAL_MSI))
+               vpci->features |= VIRTIO_PCI_F_SIGNAL_MSI;
+
+       vpci->pci_hdr.irq_pin   = pin;
+       vpci->pci_hdr.irq_line  = line;
+       r = pci__register(&vpci->pci_hdr, ndev);
+       if (r < 0)
+               goto free_ioport;
+
+       return 0;
+
+free_mmio:
+       kvm__deregister_mmio(kvm, vpci->msix_io_block);
+free_ioport:
+       ioport__unregister(kvm, vpci->base_addr);
+       return r;
+}
+
+int virtio_pci__exit(struct kvm *kvm, struct virtio_device *vdev)
+{
+       struct virtio_pci *vpci = vdev->virtio;
+       int i;
+
+       kvm__deregister_mmio(kvm, vpci->msix_io_block);
+       ioport__unregister(kvm, vpci->base_addr);
+
+       for (i = 0; i < VIRTIO_PCI_MAX_VQ; i++)
+               ioeventfd__del_event(vpci->base_addr + VIRTIO_PCI_QUEUE_NOTIFY, i);
+
+       return 0;
+}
diff --git a/tools/kvm/virtio/rng.c b/tools/kvm/virtio/rng.c
new file mode 100644 (file)
index 0000000..b2616d8
--- /dev/null
@@ -0,0 +1,193 @@
+#include "kvm/virtio-rng.h"
+
+#include "kvm/virtio-pci-dev.h"
+
+#include "kvm/virtio.h"
+#include "kvm/util.h"
+#include "kvm/kvm.h"
+#include "kvm/threadpool.h"
+#include "kvm/guest_compat.h"
+
+#include <linux/virtio_ring.h>
+#include <linux/virtio_rng.h>
+
+#include <linux/list.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <pthread.h>
+#include <linux/kernel.h>
+
+#define NUM_VIRT_QUEUES                1
+#define VIRTIO_RNG_QUEUE_SIZE  128
+
+struct rng_dev_job {
+       struct virt_queue       *vq;
+       struct rng_dev          *rdev;
+       struct thread_pool__job job_id;
+};
+
+struct rng_dev {
+       struct list_head        list;
+       struct virtio_device    vdev;
+
+       int                     fd;
+
+       /* virtio queue */
+       struct virt_queue       vqs[NUM_VIRT_QUEUES];
+       struct rng_dev_job      jobs[NUM_VIRT_QUEUES];
+};
+
+static LIST_HEAD(rdevs);
+static int compat_id = -1;
+
+static u8 *get_config(struct kvm *kvm, void *dev)
+{
+       /* Unused */
+       return 0;
+}
+
+static u32 get_host_features(struct kvm *kvm, void *dev)
+{
+       /* Unused */
+       return 0;
+}
+
+static void set_guest_features(struct kvm *kvm, void *dev, u32 features)
+{
+       /* Unused */
+}
+
+static bool virtio_rng_do_io_request(struct kvm *kvm, struct rng_dev *rdev, struct virt_queue *queue)
+{
+       struct iovec iov[VIRTIO_RNG_QUEUE_SIZE];
+       unsigned int len = 0;
+       u16 out, in, head;
+
+       head    = virt_queue__get_iov(queue, iov, &out, &in, kvm);
+       len     = readv(rdev->fd, iov, in);
+
+       virt_queue__set_used_elem(queue, head, len);
+
+       return true;
+}
+
+static void virtio_rng_do_io(struct kvm *kvm, void *param)
+{
+       struct rng_dev_job *job = param;
+       struct virt_queue *vq   = job->vq;
+       struct rng_dev *rdev    = job->rdev;
+
+       while (virt_queue__available(vq))
+               virtio_rng_do_io_request(kvm, rdev, vq);
+
+       rdev->vdev.ops->signal_vq(kvm, &rdev->vdev, vq - rdev->vqs);
+}
+
+static int init_vq(struct kvm *kvm, void *dev, u32 vq, u32 pfn)
+{
+       struct rng_dev *rdev = dev;
+       struct virt_queue *queue;
+       struct rng_dev_job *job;
+       void *p;
+
+       compat__remove_message(compat_id);
+
+       queue           = &rdev->vqs[vq];
+       queue->pfn      = pfn;
+       p               = guest_pfn_to_host(kvm, queue->pfn);
+
+       job = &rdev->jobs[vq];
+
+       vring_init(&queue->vring, VIRTIO_RNG_QUEUE_SIZE, p, VIRTIO_PCI_VRING_ALIGN);
+
+       *job = (struct rng_dev_job) {
+               .vq     = queue,
+               .rdev   = rdev,
+       };
+
+       thread_pool__init_job(&job->job_id, kvm, virtio_rng_do_io, job);
+
+       return 0;
+}
+
+static int notify_vq(struct kvm *kvm, void *dev, u32 vq)
+{
+       struct rng_dev *rdev = dev;
+
+       thread_pool__do_job(&rdev->jobs[vq].job_id);
+
+       return 0;
+}
+
+static int get_pfn_vq(struct kvm *kvm, void *dev, u32 vq)
+{
+       struct rng_dev *rdev = dev;
+
+       return rdev->vqs[vq].pfn;
+}
+
+static int get_size_vq(struct kvm *kvm, void *dev, u32 vq)
+{
+       return VIRTIO_RNG_QUEUE_SIZE;
+}
+
+static struct virtio_ops rng_dev_virtio_ops = (struct virtio_ops) {
+       .get_config             = get_config,
+       .get_host_features      = get_host_features,
+       .set_guest_features     = set_guest_features,
+       .init_vq                = init_vq,
+       .notify_vq              = notify_vq,
+       .get_pfn_vq             = get_pfn_vq,
+       .get_size_vq            = get_size_vq,
+};
+
+int virtio_rng__init(struct kvm *kvm)
+{
+       struct rng_dev *rdev;
+       int r;
+
+       if (!kvm->cfg.virtio_rng)
+               return 0;
+
+       rdev = malloc(sizeof(*rdev));
+       if (rdev == NULL)
+               return -ENOMEM;
+
+       rdev->fd = open("/dev/urandom", O_RDONLY);
+       if (rdev->fd < 0) {
+               r = rdev->fd;
+               goto cleanup;
+       }
+
+       r = virtio_init(kvm, rdev, &rdev->vdev, &rng_dev_virtio_ops,
+                       VIRTIO_PCI, PCI_DEVICE_ID_VIRTIO_RNG, VIRTIO_ID_RNG, PCI_CLASS_RNG);
+       if (r < 0)
+               goto cleanup;
+
+       list_add_tail(&rdev->list, &rdevs);
+
+       if (compat_id == -1)
+               compat_id = virtio_compat_add_message("virtio-rng", "CONFIG_HW_RANDOM_VIRTIO");
+       return 0;
+cleanup:
+       close(rdev->fd);
+       free(rdev);
+
+       return r;
+}
+virtio_dev_init(virtio_rng__init);
+
+int virtio_rng__exit(struct kvm *kvm)
+{
+       struct rng_dev *rdev, *tmp;
+
+       list_for_each_entry_safe(rdev, tmp, &rdevs, list) {
+               list_del(&rdev->list);
+               rdev->vdev.ops->exit(kvm, &rdev->vdev);
+               free(rdev);
+       }
+
+       return 0;
+}
+virtio_dev_exit(virtio_rng__exit);
diff --git a/tools/kvm/virtio/scsi.c b/tools/kvm/virtio/scsi.c
new file mode 100644 (file)
index 0000000..881898b
--- /dev/null
@@ -0,0 +1,309 @@
+#include "kvm/virtio-scsi.h"
+#include "kvm/virtio-pci-dev.h"
+#include "kvm/disk-image.h"
+#include "kvm/kvm.h"
+#include "kvm/pci.h"
+#include "kvm/ioeventfd.h"
+#include "kvm/guest_compat.h"
+#include "kvm/virtio-pci.h"
+#include "kvm/virtio.h"
+
+#include <linux/kernel.h>
+#include <linux/virtio_scsi.h>
+#include <linux/vhost.h>
+
+#define VIRTIO_SCSI_QUEUE_SIZE         128
+#define NUM_VIRT_QUEUES                        3
+
+static LIST_HEAD(sdevs);
+static int compat_id = -1;
+
+struct scsi_dev {
+       struct virt_queue               vqs[NUM_VIRT_QUEUES];
+       struct virtio_scsi_config       config;
+       struct vhost_scsi_target        target;
+       u32                             features;
+       int                             vhost_fd;
+       struct virtio_device            vdev;
+       struct list_head                list;
+       struct kvm                      *kvm;
+};
+
+static u8 *get_config(struct kvm *kvm, void *dev)
+{
+       struct scsi_dev *sdev = dev;
+
+       return ((u8 *)(&sdev->config));
+}
+
+static u32 get_host_features(struct kvm *kvm, void *dev)
+{
+       return  1UL << VIRTIO_RING_F_EVENT_IDX |
+               1UL << VIRTIO_RING_F_INDIRECT_DESC;
+}
+
+static void set_guest_features(struct kvm *kvm, void *dev, u32 features)
+{
+       struct scsi_dev *sdev = dev;
+
+       sdev->features = features;
+}
+
+static int init_vq(struct kvm *kvm, void *dev, u32 vq, u32 pfn)
+{
+       struct vhost_vring_state state = { .index = vq };
+       struct vhost_vring_addr addr;
+       struct scsi_dev *sdev = dev;
+       struct virt_queue *queue;
+       void *p;
+       int r;
+
+       compat__remove_message(compat_id);
+
+       queue           = &sdev->vqs[vq];
+       queue->pfn      = pfn;
+       p               = guest_pfn_to_host(kvm, queue->pfn);
+
+       vring_init(&queue->vring, VIRTIO_SCSI_QUEUE_SIZE, p, VIRTIO_PCI_VRING_ALIGN);
+
+       if (sdev->vhost_fd == 0)
+               return 0;
+
+       state.num = queue->vring.num;
+       r = ioctl(sdev->vhost_fd, VHOST_SET_VRING_NUM, &state);
+       if (r < 0)
+               die_perror("VHOST_SET_VRING_NUM failed");
+       state.num = 0;
+       r = ioctl(sdev->vhost_fd, VHOST_SET_VRING_BASE, &state);
+       if (r < 0)
+               die_perror("VHOST_SET_VRING_BASE failed");
+
+       addr = (struct vhost_vring_addr) {
+               .index = vq,
+               .desc_user_addr = (u64)(unsigned long)queue->vring.desc,
+               .avail_user_addr = (u64)(unsigned long)queue->vring.avail,
+               .used_user_addr = (u64)(unsigned long)queue->vring.used,
+       };
+
+       r = ioctl(sdev->vhost_fd, VHOST_SET_VRING_ADDR, &addr);
+       if (r < 0)
+               die_perror("VHOST_SET_VRING_ADDR failed");
+
+       return 0;
+}
+
+static void notify_vq_gsi(struct kvm *kvm, void *dev, u32 vq, u32 gsi)
+{
+       struct vhost_vring_file file;
+       struct scsi_dev *sdev = dev;
+       struct kvm_irqfd irq;
+       int r;
+
+       if (sdev->vhost_fd == 0)
+               return;
+
+       irq = (struct kvm_irqfd) {
+               .gsi    = gsi,
+               .fd     = eventfd(0, 0),
+       };
+       file = (struct vhost_vring_file) {
+               .index  = vq,
+               .fd     = irq.fd,
+       };
+
+       r = ioctl(kvm->vm_fd, KVM_IRQFD, &irq);
+       if (r < 0)
+               die_perror("KVM_IRQFD failed");
+
+       r = ioctl(sdev->vhost_fd, VHOST_SET_VRING_CALL, &file);
+       if (r < 0)
+               die_perror("VHOST_SET_VRING_CALL failed");
+
+       if (vq > 0)
+               return;
+
+       r = ioctl(sdev->vhost_fd, VHOST_SCSI_SET_ENDPOINT, &sdev->target);
+       if (r != 0)
+               die("VHOST_SCSI_SET_ENDPOINT failed %d", errno);
+}
+
+static void notify_vq_eventfd(struct kvm *kvm, void *dev, u32 vq, u32 efd)
+{
+       struct scsi_dev *sdev = dev;
+       struct vhost_vring_file file = {
+               .index  = vq,
+               .fd     = efd,
+       };
+       int r;
+
+       if (sdev->vhost_fd == 0)
+               return;
+
+       r = ioctl(sdev->vhost_fd, VHOST_SET_VRING_KICK, &file);
+       if (r < 0)
+               die_perror("VHOST_SET_VRING_KICK failed");
+}
+
+static int notify_vq(struct kvm *kvm, void *dev, u32 vq)
+{
+       return 0;
+}
+
+static int get_pfn_vq(struct kvm *kvm, void *dev, u32 vq)
+{
+       struct scsi_dev *sdev = dev;
+
+       return sdev->vqs[vq].pfn;
+}
+
+static int get_size_vq(struct kvm *kvm, void *dev, u32 vq)
+{
+       return VIRTIO_SCSI_QUEUE_SIZE;
+}
+
+static int set_size_vq(struct kvm *kvm, void *dev, u32 vq, int size)
+{
+       return size;
+}
+
+static struct virtio_ops scsi_dev_virtio_ops = (struct virtio_ops) {
+       .get_config             = get_config,
+       .get_host_features      = get_host_features,
+       .set_guest_features     = set_guest_features,
+       .init_vq                = init_vq,
+       .get_pfn_vq             = get_pfn_vq,
+       .get_size_vq            = get_size_vq,
+       .set_size_vq            = set_size_vq,
+       .notify_vq              = notify_vq,
+       .notify_vq_gsi          = notify_vq_gsi,
+       .notify_vq_eventfd      = notify_vq_eventfd,
+};
+
+static void virtio_scsi_vhost_init(struct kvm *kvm, struct scsi_dev *sdev)
+{
+       struct vhost_memory *mem;
+       u64 features;
+       int r;
+
+       sdev->vhost_fd = open("/dev/vhost-scsi", O_RDWR);
+       if (sdev->vhost_fd < 0)
+               die_perror("Failed openning vhost-scsi device");
+
+       mem = calloc(1, sizeof(*mem) + sizeof(struct vhost_memory_region));
+       if (mem == NULL)
+               die("Failed allocating memory for vhost memory map");
+
+       mem->nregions = 1;
+       mem->regions[0] = (struct vhost_memory_region) {
+               .guest_phys_addr        = 0,
+               .memory_size            = kvm->ram_size,
+               .userspace_addr         = (unsigned long)kvm->ram_start,
+       };
+
+       r = ioctl(sdev->vhost_fd, VHOST_SET_OWNER);
+       if (r != 0)
+               die_perror("VHOST_SET_OWNER failed");
+
+       r = ioctl(sdev->vhost_fd, VHOST_GET_FEATURES, &features);
+       if (r != 0)
+               die_perror("VHOST_GET_FEATURES failed");
+
+       r = ioctl(sdev->vhost_fd, VHOST_SET_FEATURES, &features);
+       if (r != 0)
+               die_perror("VHOST_SET_FEATURES failed");
+       r = ioctl(sdev->vhost_fd, VHOST_SET_MEM_TABLE, mem);
+       if (r != 0)
+               die_perror("VHOST_SET_MEM_TABLE failed");
+
+       sdev->vdev.use_vhost = true;
+
+       free(mem);
+}
+
+
+static int virtio_scsi_init_one(struct kvm *kvm, struct disk_image *disk)
+{
+       struct scsi_dev *sdev;
+
+       if (!disk)
+               return -EINVAL;
+
+       sdev = calloc(1, sizeof(struct scsi_dev));
+       if (sdev == NULL)
+               return -ENOMEM;
+
+       *sdev = (struct scsi_dev) {
+               .config = (struct virtio_scsi_config) {
+                       .num_queues     = NUM_VIRT_QUEUES - 2,
+                       .seg_max        = VIRTIO_SCSI_CDB_SIZE - 2,
+                       .max_sectors    = 65535,
+                       .cmd_per_lun    = 128,
+                       .sense_size     = VIRTIO_SCSI_SENSE_SIZE,
+                       .cdb_size       = VIRTIO_SCSI_CDB_SIZE,
+                       .max_channel    = 0,
+                       .max_target     = 0,
+                       .max_lun        = 16383,
+                       .event_info_size = sizeof(struct virtio_scsi_event),
+               },
+               .kvm                    = kvm,
+       };
+       strncpy((char *)&sdev->target.vhost_wwpn, disk->wwpn, sizeof(sdev->target.vhost_wwpn));
+       sdev->target.vhost_tpgt = strtol(disk->tpgt, NULL, 0);
+
+       virtio_init(kvm, sdev, &sdev->vdev, &scsi_dev_virtio_ops,
+                   VIRTIO_PCI, PCI_DEVICE_ID_VIRTIO_SCSI, VIRTIO_ID_SCSI, PCI_CLASS_BLK);
+
+       list_add_tail(&sdev->list, &sdevs);
+
+       virtio_scsi_vhost_init(kvm, sdev);
+
+       if (compat_id == -1)
+               compat_id = virtio_compat_add_message("virtio-scsi", "CONFIG_VIRTIO_SCSI");
+
+       return 0;
+}
+
+static int virtio_scsi_exit_one(struct kvm *kvm, struct scsi_dev *sdev)
+{
+       int r;
+
+       r = ioctl(sdev->vhost_fd, VHOST_SCSI_CLEAR_ENDPOINT, &sdev->target);
+       if (r != 0)
+               die("VHOST_SCSI_CLEAR_ENDPOINT failed %d", errno);
+
+       list_del(&sdev->list);
+       free(sdev);
+
+       return 0;
+}
+
+int virtio_scsi_init(struct kvm *kvm)
+{
+       int i, r = 0;
+
+       for (i = 0; i < kvm->nr_disks; i++) {
+               if (!kvm->disks[i]->wwpn)
+                       continue;
+               r = virtio_scsi_init_one(kvm, kvm->disks[i]);
+               if (r < 0)
+                       goto cleanup;
+       }
+
+       return 0;
+cleanup:
+       return virtio_scsi_exit(kvm);
+}
+virtio_dev_init(virtio_scsi_init);
+
+int virtio_scsi_exit(struct kvm *kvm)
+{
+       while (!list_empty(&sdevs)) {
+               struct scsi_dev *sdev;
+
+               sdev = list_first_entry(&sdevs, struct scsi_dev, list);
+               virtio_scsi_exit_one(kvm, sdev);
+       }
+
+       return 0;
+}
+virtio_dev_exit(virtio_scsi_exit);
diff --git a/tools/kvm/x86/bios.c b/tools/kvm/x86/bios.c
new file mode 100644 (file)
index 0000000..f05cc02
--- /dev/null
@@ -0,0 +1,174 @@
+#include "kvm/kvm.h"
+#include "kvm/boot-protocol.h"
+#include "kvm/e820.h"
+#include "kvm/interrupt.h"
+#include "kvm/util.h"
+
+#include <string.h>
+#include <asm/e820.h>
+
+#include "bios/bios-rom.h"
+
+struct irq_handler {
+       unsigned long           address;
+       unsigned int            irq;
+       void                    *handler;
+       size_t                  size;
+};
+
+#define BIOS_IRQ_PA_ADDR(name) (MB_BIOS_BEGIN + BIOS_OFFSET__##name)
+#define BIOS_IRQ_FUNC(name)    ((char *)&bios_rom[BIOS_OFFSET__##name])
+#define BIOS_IRQ_SIZE(name)    (BIOS_ENTRY_SIZE(BIOS_OFFSET__##name))
+
+#define DEFINE_BIOS_IRQ_HANDLER(_irq, _handler)                        \
+       {                                                       \
+               .irq            = _irq,                         \
+               .address        = BIOS_IRQ_PA_ADDR(_handler),   \
+               .handler        = BIOS_IRQ_FUNC(_handler),      \
+               .size           = BIOS_IRQ_SIZE(_handler),      \
+       }
+
+static struct irq_handler bios_irq_handlers[] = {
+       DEFINE_BIOS_IRQ_HANDLER(0x10, bios_int10),
+       DEFINE_BIOS_IRQ_HANDLER(0x15, bios_int15),
+};
+
+static void setup_irq_handler(struct kvm *kvm, struct irq_handler *handler)
+{
+       struct real_intr_desc intr_desc;
+       void *p;
+
+       p = guest_flat_to_host(kvm, handler->address);
+       memcpy(p, handler->handler, handler->size);
+
+       intr_desc = (struct real_intr_desc) {
+               .segment        = REAL_SEGMENT(MB_BIOS_BEGIN),
+               .offset         = handler->address - MB_BIOS_BEGIN,
+       };
+
+       DIE_IF((handler->address - MB_BIOS_BEGIN) > 0xffffUL);
+
+       interrupt_table__set(&kvm->arch.interrupt_table, &intr_desc, handler->irq);
+}
+
+/**
+ * e820_setup - setup some simple E820 memory map
+ * @kvm - guest system descriptor
+ */
+static void e820_setup(struct kvm *kvm)
+{
+       struct e820map *e820;
+       struct e820entry *mem_map;
+       unsigned int i = 0;
+
+       e820            = guest_flat_to_host(kvm, E820_MAP_START);
+       mem_map         = e820->map;
+
+       mem_map[i++]    = (struct e820entry) {
+               .addr           = REAL_MODE_IVT_BEGIN,
+               .size           = EBDA_START - REAL_MODE_IVT_BEGIN,
+               .type           = E820_RAM,
+       };
+       mem_map[i++]    = (struct e820entry) {
+               .addr           = EBDA_START,
+               .size           = VGA_RAM_BEGIN - EBDA_START,
+               .type           = E820_RESERVED,
+       };
+       mem_map[i++]    = (struct e820entry) {
+               .addr           = MB_BIOS_BEGIN,
+               .size           = MB_BIOS_END - MB_BIOS_BEGIN,
+               .type           = E820_RESERVED,
+       };
+       if (kvm->ram_size < KVM_32BIT_GAP_START) {
+               mem_map[i++]    = (struct e820entry) {
+                       .addr           = BZ_KERNEL_START,
+                       .size           = kvm->ram_size - BZ_KERNEL_START,
+                       .type           = E820_RAM,
+               };
+       } else {
+               mem_map[i++]    = (struct e820entry) {
+                       .addr           = BZ_KERNEL_START,
+                       .size           = KVM_32BIT_GAP_START - BZ_KERNEL_START,
+                       .type           = E820_RAM,
+               };
+               mem_map[i++]    = (struct e820entry) {
+                       .addr           = KVM_32BIT_MAX_MEM_SIZE,
+                       .size           = kvm->ram_size - KVM_32BIT_MAX_MEM_SIZE,
+                       .type           = E820_RAM,
+               };
+       }
+
+       BUG_ON(i > E820_X_MAX);
+
+       e820->nr_map = i;
+}
+
+static void setup_vga_rom(struct kvm *kvm)
+{
+       u16 *mode;
+       void *p;
+
+       p = guest_flat_to_host(kvm, VGA_ROM_OEM_STRING);
+       memset(p, 0, VGA_ROM_OEM_STRING_SIZE);
+       strncpy(p, "KVM VESA", VGA_ROM_OEM_STRING_SIZE);
+
+       mode = guest_flat_to_host(kvm, VGA_ROM_MODES);
+       mode[0] = 0x0112;
+       mode[1] = 0xffff;
+}
+
+/**
+ * setup_bios - inject BIOS into guest memory
+ * @kvm - guest system descriptor
+ */
+void setup_bios(struct kvm *kvm)
+{
+       unsigned long address = MB_BIOS_BEGIN;
+       struct real_intr_desc intr_desc;
+       unsigned int i;
+       void *p;
+
+       /*
+        * before anything else -- clean some known areas
+        * we definitely don't want any trash here
+        */
+       p = guest_flat_to_host(kvm, BDA_START);
+       memset(p, 0, BDA_END - BDA_START);
+
+       p = guest_flat_to_host(kvm, EBDA_START);
+       memset(p, 0, EBDA_END - EBDA_START);
+
+       p = guest_flat_to_host(kvm, MB_BIOS_BEGIN);
+       memset(p, 0, MB_BIOS_END - MB_BIOS_BEGIN);
+
+       p = guest_flat_to_host(kvm, VGA_ROM_BEGIN);
+       memset(p, 0, VGA_ROM_END - VGA_ROM_BEGIN);
+
+       /* just copy the bios rom into the place */
+       p = guest_flat_to_host(kvm, MB_BIOS_BEGIN);
+       memcpy(p, bios_rom, bios_rom_size);
+
+       /* E820 memory map must be present */
+       e820_setup(kvm);
+
+       /* VESA needs own tricks */
+       setup_vga_rom(kvm);
+
+       /*
+        * Setup a *fake* real mode vector table, it has only
+        * one real handler which does just iret
+        */
+       address = BIOS_IRQ_PA_ADDR(bios_intfake);
+       intr_desc = (struct real_intr_desc) {
+               .segment        = REAL_SEGMENT(MB_BIOS_BEGIN),
+               .offset         = address - MB_BIOS_BEGIN,
+       };
+       interrupt_table__setup(&kvm->arch.interrupt_table, &intr_desc);
+
+       for (i = 0; i < ARRAY_SIZE(bios_irq_handlers); i++)
+               setup_irq_handler(kvm, &bios_irq_handlers[i]);
+
+       /* we almost done */
+       p = guest_flat_to_host(kvm, 0);
+       interrupt_table__copy(&kvm->arch.interrupt_table, p, REAL_INTR_SIZE);
+}
diff --git a/tools/kvm/x86/bios/.gitignore b/tools/kvm/x86/bios/.gitignore
new file mode 100644 (file)
index 0000000..1f0080b
--- /dev/null
@@ -0,0 +1,3 @@
+bios-rom.bin
+bios-rom.bin.elf
+bios-rom.h
diff --git a/tools/kvm/x86/bios/bios-rom.S b/tools/kvm/x86/bios/bios-rom.S
new file mode 100644 (file)
index 0000000..3269ce9
--- /dev/null
@@ -0,0 +1,12 @@
+#include <kvm/assembly.h>
+
+       .org 0
+#ifdef CONFIG_X86_64
+       .code64
+#else
+       .code32
+#endif
+
+GLOBAL(bios_rom)
+       .incbin "x86/bios/bios.bin"
+END(bios_rom)
diff --git a/tools/kvm/x86/bios/e820.c b/tools/kvm/x86/bios/e820.c
new file mode 100644 (file)
index 0000000..a9bca29
--- /dev/null
@@ -0,0 +1,72 @@
+#include "kvm/e820.h"
+
+#include "kvm/segment.h"
+#include "kvm/bios.h"
+
+#include <asm/processor-flags.h>
+#include <asm/e820.h>
+
+static inline void set_fs(u16 seg)
+{
+       asm volatile("movw %0,%%fs" : : "rm" (seg));
+}
+
+static inline u8 rdfs8(unsigned long addr)
+{
+       u8 v;
+
+       asm volatile("addr32 movb %%fs:%1,%0" : "=q" (v) : "m" (*(u8 *)addr));
+
+       return v;
+}
+
+static inline u32 rdfs32(unsigned long addr)
+{
+       u32 v;
+
+       asm volatile("addr32 movl %%fs:%1,%0" : "=q" (v) : "m" (*(u32 *)addr));
+
+       return v;
+}
+
+bioscall void e820_query_map(struct biosregs *regs)
+{
+       struct e820map *e820;
+       u32 map_size;
+       u16 fs_seg;
+       u32 ndx;
+
+       e820            = (struct e820map *)E820_MAP_START;
+       fs_seg          = flat_to_seg16(E820_MAP_START);
+       set_fs(fs_seg);
+
+       ndx             = regs->ebx;
+
+       map_size        = rdfs32(flat_to_off16((u32)&e820->nr_map, fs_seg));
+
+       if (ndx < map_size) {
+               u32 start;
+               unsigned int i;
+               u8 *p;
+
+               fs_seg  = flat_to_seg16(E820_MAP_START);
+               set_fs(fs_seg);
+
+               start   = (u32)&e820->map[ndx];
+
+               p       = (void *) regs->edi;
+
+               for (i = 0; i < sizeof(struct e820entry); i++)
+                       *p++    = rdfs8(flat_to_off16(start + i, fs_seg));
+       }
+
+       regs->eax       = SMAP;
+       regs->ecx       = sizeof(struct e820entry);
+       regs->ebx       = ++ndx;
+
+       /* Clear CF to indicate success.  */
+       regs->eflags    &= ~X86_EFLAGS_CF;
+
+       if (ndx >= map_size)
+               regs->ebx       = 0;    /* end of map */
+}
diff --git a/tools/kvm/x86/bios/entry.S b/tools/kvm/x86/bios/entry.S
new file mode 100644 (file)
index 0000000..85056e9
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Our pretty trivial BIOS emulation
+ */
+
+#include <kvm/bios.h>
+#include <kvm/assembly.h>
+
+       .org 0
+       .code16gcc
+
+#define EFLAGS_CF      (1 << 0)
+
+#include "macro.S"
+
+/* If you change these macros, remember to update 'struct biosregs' */
+.macro SAVE_BIOSREGS
+       pushl   %fs
+       pushl   %es
+       pushl   %ds
+       pushl   %edi
+       pushl   %esi
+       pushl   %ebp
+       pushl   %esp
+       pushl   %edx
+       pushl   %ecx
+       pushl   %ebx
+       pushl   %eax
+.endm
+
+.macro RESTORE_BIOSREGS
+       popl    %eax
+       popl    %ebx
+       popl    %ecx
+       popl    %edx
+       popl    %esp
+       popl    %ebp
+       popl    %esi
+       popl    %edi
+       popl    %ds
+       popl    %es
+       popl    %fs
+.endm
+
+/*
+ * fake interrupt handler, nothing can be faster ever
+ */
+ENTRY(bios_intfake)
+       /*
+        * Set CF to indicate failure. We don't want callers to think that the
+        * interrupt handler succeeded and then treat the return values in
+        * registers as valid data.
+        */
+       orl     $EFLAGS_CF, 0x4(%esp)
+
+       IRET
+ENTRY_END(bios_intfake)
+
+/*
+ * int 10 - video - service
+ */
+ENTRY(bios_int10)
+       SAVE_BIOSREGS
+
+       movl            %esp, %eax
+       /* this is way easier than doing it in assembly */
+       /* just push all the regs and jump to a C handler */
+       call    int10_handler
+
+       RESTORE_BIOSREGS
+
+       /* Clear CF to indicate success.  */
+       andl    $~EFLAGS_CF, 0x4(%esp)
+
+       IRET
+ENTRY_END(bios_int10)
+
+ENTRY(bios_int15)
+       SAVE_BIOSREGS
+
+       movl    %esp, %eax
+       call    int15_handler
+
+       RESTORE_BIOSREGS
+
+       IRET
+ENTRY_END(bios_int15)
+
+GLOBAL(__locals)
+
+#include "local.S"
+
+END(__locals)
diff --git a/tools/kvm/x86/bios/gen-offsets.sh b/tools/kvm/x86/bios/gen-offsets.sh
new file mode 100644 (file)
index 0000000..8771bbe
--- /dev/null
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+echo "/* Autogenerated file, don't edit */"
+echo "#ifndef BIOS_OFFSETS_H"
+echo "#define BIOS_OFFSETS_H"
+
+echo ""
+echo "#define BIOS_ENTRY_SIZE(name) (name##_end - name)"
+echo ""
+
+nm bios.bin.elf | grep ' [Tt] ' | awk '{ print "#define BIOS_OFFSET__" $3 " 0x" $1; }'
+
+echo ""
+echo "#endif"
diff --git a/tools/kvm/x86/bios/int10.c b/tools/kvm/x86/bios/int10.c
new file mode 100644 (file)
index 0000000..7cc0b3f
--- /dev/null
@@ -0,0 +1,110 @@
+#include "kvm/segment.h"
+#include "kvm/bios.h"
+#include "kvm/vesa.h"
+
+#include "bios/memcpy.h"
+
+#include <boot/vesa.h>
+
+static far_ptr gen_far_ptr(unsigned int pa)
+{
+       far_ptr ptr;
+
+       ptr.seg = (pa >> 4);
+       ptr.off = pa - (ptr.seg << 4);
+
+       return ptr;
+}
+
+static inline void outb(unsigned short port, unsigned char val)
+{
+       asm volatile("outb %0, %1" : : "a"(val), "Nd"(port));
+}
+
+/*
+ * It's probably much more useful to make this print to the serial
+ * line rather than print to a non-displayed VGA memory
+ */
+static inline void int10_putchar(struct biosregs *args)
+{
+       u8 al = args->eax & 0xFF;
+
+       outb(0x3f8, al);
+}
+
+static void vbe_get_mode(struct biosregs *args)
+{
+       struct vesa_mode_info *info = (struct vesa_mode_info *) args->edi;
+
+       *info = (struct vesa_mode_info) {
+               .mode_attr              = 0xd9, /* 11011011 */
+               .logical_scan           = VESA_WIDTH*4,
+               .h_res                  = VESA_WIDTH,
+               .v_res                  = VESA_HEIGHT,
+               .bpp                    = VESA_BPP,
+               .memory_layout          = 6,
+               .memory_planes          = 1,
+               .lfb_ptr                = VESA_MEM_ADDR,
+               .rmask                  = 8,
+               .gmask                  = 8,
+               .bmask                  = 8,
+               .resv_mask              = 8,
+               .resv_pos               = 24,
+               .bpos                   = 16,
+               .gpos                   = 8,
+       };
+}
+
+static void vbe_get_info(struct biosregs *args)
+{
+       struct vesa_general_info *infop = (struct vesa_general_info *) args->edi;
+       struct vesa_general_info info;
+
+       info = (struct vesa_general_info) {
+               .signature              = VESA_MAGIC,
+               .version                = 0x102,
+               .vendor_string          = gen_far_ptr(VGA_ROM_BEGIN),
+               .capabilities           = 0x10,
+               .video_mode_ptr         = gen_far_ptr(VGA_ROM_MODES),
+               .total_memory           = (4 * VESA_WIDTH * VESA_HEIGHT) / 0x10000,
+       };
+
+       memcpy16(args->es, infop, args->ds, &info, sizeof(info));
+}
+
+#define VBE_STATUS_OK          0x004F
+
+static void int10_vesa(struct biosregs *args)
+{
+       u8 al;
+
+       al = args->eax & 0xff;
+
+       switch (al) {
+       case 0x00:
+               vbe_get_info(args);
+               break;
+       case 0x01:
+               vbe_get_mode(args);
+               break;
+       }
+
+       args->eax = VBE_STATUS_OK;
+}
+
+bioscall void int10_handler(struct biosregs *args)
+{
+       u8 ah;
+
+       ah = (args->eax & 0xff00) >> 8;
+
+       switch (ah) {
+       case 0x0e:
+               int10_putchar(args);
+               break;
+       case 0x4f:
+               int10_vesa(args);
+               break;
+       }
+
+}
diff --git a/tools/kvm/x86/bios/int15.c b/tools/kvm/x86/bios/int15.c
new file mode 100644 (file)
index 0000000..faf5343
--- /dev/null
@@ -0,0 +1,18 @@
+#include "kvm/bios.h"
+
+#include "kvm/e820.h"
+
+#include <asm/processor-flags.h>
+
+bioscall void int15_handler(struct biosregs *regs)
+{
+       switch (regs->eax) {
+       case 0xe820:
+               e820_query_map(regs);
+               break;
+       default:
+               /* Set CF to indicate failure.  */
+               regs->eflags    |= X86_EFLAGS_CF;
+               break;
+       }
+}
diff --git a/tools/kvm/x86/bios/local.S b/tools/kvm/x86/bios/local.S
new file mode 100644 (file)
index 0000000..f2cdbf4
--- /dev/null
@@ -0,0 +1,7 @@
+/*
+ * Local variables for almost every BIOS irq handler
+ * Must be put somewhere inside irq handler body
+ */
+__CALLER_SS:           .int  0
+__CALLER_SP:           .long 0
+__CALLER_CLOBBER:      .long 0
diff --git a/tools/kvm/x86/bios/macro.S b/tools/kvm/x86/bios/macro.S
new file mode 100644 (file)
index 0000000..0d5e567
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * handy BIOS macros
+ */
+
+/*
+ * switch to BIOS stack
+ */
+.macro stack_swap
+       movw %ss, %cs:(__CALLER_SS)
+       movl %esp, %cs:(__CALLER_SP)
+       movl %edx, %cs:(__CALLER_CLOBBER)
+       movw $MB_BIOS_SS, %dx
+       movw %dx, %ss
+       movw $MB_BIOS_SP, %sp
+       movl %cs:(__CALLER_CLOBBER), %edx
+.endm
+
+/*
+ * restore the original stack
+ */
+.macro stack_restore
+       movl %cs:(__CALLER_SP), %esp
+       movw %cs:(__CALLER_SS), %ss
+.endm
+
diff --git a/tools/kvm/x86/bios/memcpy.c b/tools/kvm/x86/bios/memcpy.c
new file mode 100644 (file)
index 0000000..40b9b65
--- /dev/null
@@ -0,0 +1,23 @@
+#include "bios/memcpy.h"
+
+/*
+ *  Copy memory area in 16-bit real mode.
+ */
+void memcpy16(u16 dst_seg, void *dst, u16 src_seg, const void *src, size_t len)
+{
+       __asm__ __volatile__ (
+               "pushw  %%ds                            \n"
+               "pushw  %%es                            \n"
+               "movw   %[src_seg], %%ds                \n"
+               "movw   %[dst_seg], %%es                \n"
+               "rep movsb %%ds:(%%si), %%es:(%%di)     \n"
+               "popw   %%es                            \n"
+               "popw   %%ds                            \n"
+               :
+               : "S"(src),
+                 "D"(dst),
+                 "c"(len),
+                 [src_seg] "r"(src_seg),
+                 [dst_seg] "r"(dst_seg)
+               : "cc", "memory");
+}
diff --git a/tools/kvm/x86/bios/rom.ld.S b/tools/kvm/x86/bios/rom.ld.S
new file mode 100644 (file)
index 0000000..f4f1835
--- /dev/null
@@ -0,0 +1,16 @@
+OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
+OUTPUT_ARCH(i386)
+
+SECTIONS {
+       .text 0 : {
+               *(.text)
+       }
+
+       /DISCARD/ : {
+               *(.debug*)
+               *(.data)
+               *(.bss)
+               *(.eh_frame*)
+       }
+}
+
diff --git a/tools/kvm/x86/boot.c b/tools/kvm/x86/boot.c
new file mode 100644 (file)
index 0000000..61535eb
--- /dev/null
@@ -0,0 +1,41 @@
+#include "kvm/kvm.h"
+
+#include "kvm/util.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdbool.h>
+#include <fcntl.h>
+
+#define BIOS_SELECTOR  0xf000
+#define BIOS_IP                0xfff0
+#define BIOS_SP                0x8000
+
+bool kvm__load_firmware(struct kvm *kvm, const char *firmware_filename)
+{
+       struct stat st;
+       void *p;
+       int fd;
+       int nr;
+
+       fd = open(firmware_filename, O_RDONLY);
+       if (fd < 0)
+               return false;
+
+       if (fstat(fd, &st))
+               return false;
+
+       if (st.st_size > MB_FIRMWARE_BIOS_SIZE)
+               die("firmware image %s is too big to fit in memory (%Lu KB).\n", firmware_filename, (u64)(st.st_size / 1024));
+
+       p = guest_flat_to_host(kvm, MB_FIRMWARE_BIOS_BEGIN);
+
+       while ((nr = read(fd, p, st.st_size)) > 0)
+               p += nr;
+
+       kvm->arch.boot_selector = BIOS_SELECTOR;
+       kvm->arch.boot_ip       = BIOS_IP;
+       kvm->arch.boot_sp       = BIOS_SP;
+
+       return true;
+}
diff --git a/tools/kvm/x86/cpuid.c b/tools/kvm/x86/cpuid.c
new file mode 100644 (file)
index 0000000..4c140f0
--- /dev/null
@@ -0,0 +1,60 @@
+#include "kvm/kvm-cpu.h"
+
+#include "kvm/kvm.h"
+#include "kvm/util.h"
+
+#include <sys/ioctl.h>
+#include <stdlib.h>
+
+#define CPUID_FUNC_PERFMON             0x0A
+
+#define        MAX_KVM_CPUID_ENTRIES           100
+
+static void filter_cpuid(struct kvm_cpuid2 *kvm_cpuid)
+{
+       unsigned int i;
+
+       /*
+        * Filter CPUID functions that are not supported by the hypervisor.
+        */
+       for (i = 0; i < kvm_cpuid->nent; i++) {
+               struct kvm_cpuid_entry2 *entry = &kvm_cpuid->entries[i];
+
+               switch (entry->function) {
+               case 1:
+                       /* Set X86_FEATURE_HYPERVISOR */
+                       if (entry->index == 0)
+                               entry->ecx |= (1 << 31);
+                       break;
+               case 6:
+                       /* Clear X86_FEATURE_EPB */
+                       entry->ecx = entry->ecx & ~(1 << 3);
+                       break;
+               case CPUID_FUNC_PERFMON:
+                       entry->eax = 0x00; /* disable it */
+                       break;
+               default:
+                       /* Keep the CPUID function as -is */
+                       break;
+               };
+       }
+}
+
+void kvm_cpu__setup_cpuid(struct kvm_cpu *vcpu)
+{
+       struct kvm_cpuid2 *kvm_cpuid;
+
+       kvm_cpuid = calloc(1, sizeof(*kvm_cpuid) +
+                               MAX_KVM_CPUID_ENTRIES * sizeof(*kvm_cpuid->entries));
+
+       kvm_cpuid->nent = MAX_KVM_CPUID_ENTRIES;
+       if (ioctl(vcpu->kvm->sys_fd, KVM_GET_SUPPORTED_CPUID, kvm_cpuid) < 0)
+               die_perror("KVM_GET_SUPPORTED_CPUID failed");
+
+       filter_cpuid(kvm_cpuid);
+
+       if (ioctl(vcpu->vcpu_fd, KVM_SET_CPUID2, kvm_cpuid) < 0)
+               die_perror("KVM_SET_CPUID2 failed");
+
+       free(kvm_cpuid);
+}
diff --git a/tools/kvm/x86/include/kvm/assembly.h b/tools/kvm/x86/include/kvm/assembly.h
new file mode 100644 (file)
index 0000000..e70baab
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef ASSEMBLY_H_
+#define ASSEMBLY_H_
+
+#define __ALIGN        .p2align 4, 0x90
+#define ENTRY(name)    \
+       __ALIGN;        \
+       .globl name;    \
+       name:
+
+#define GLOBAL(name)   \
+       .globl name;    \
+       name:
+
+#define ENTRY_END(name)        GLOBAL(name##_end)
+#define END(name)      GLOBAL(name##_end)
+
+/*
+ * gas produces size override prefix with which
+ * we are unhappy, lets make it hardcoded for
+ * 16 bit mode
+ */
+#define IRET   .byte 0xcf
+
+#endif /* ASSEMBLY_H_ */
diff --git a/tools/kvm/x86/include/kvm/barrier.h b/tools/kvm/x86/include/kvm/barrier.h
new file mode 100644 (file)
index 0000000..46d14f6
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef _KVM_BARRIER_H_
+#define _KVM_BARRIER_H_
+
+#define barrier() asm volatile("": : :"memory")
+
+#define mb()   asm volatile ("mfence": : :"memory")
+#define rmb()  asm volatile ("lfence": : :"memory")
+#define wmb()  asm volatile ("sfence": : :"memory")
+
+#ifdef CONFIG_SMP
+#define smp_mb()       mb()
+#define smp_rmb()      rmb()
+#define smp_wmb()      wmb()
+#else
+#define smp_mb()       barrier()
+#define smp_rmb()      barrier()
+#define smp_wmb()      barrier()
+#endif
+
+#endif /* _KVM_BARRIER_H_ */
diff --git a/tools/kvm/x86/include/kvm/bios-export.h b/tools/kvm/x86/include/kvm/bios-export.h
new file mode 100644 (file)
index 0000000..23825aa
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef BIOS_EXPORT_H_
+#define BIOS_EXPORT_H_
+
+struct kvm;
+
+extern char bios_rom[0];
+extern char bios_rom_end[0];
+
+#define bios_rom_size          (bios_rom_end - bios_rom)
+
+extern void setup_bios(struct kvm *kvm);
+
+#endif /* BIOS_EXPORT_H_ */
diff --git a/tools/kvm/x86/include/kvm/bios.h b/tools/kvm/x86/include/kvm/bios.h
new file mode 100644 (file)
index 0000000..ec7ed71
--- /dev/null
@@ -0,0 +1,93 @@
+#ifndef BIOS_H_
+#define BIOS_H_
+
+/*
+ * X86-32 Memory Map (typical)
+ *                                     start      end
+ * Real Mode Interrupt Vector Table    0x00000000 0x000003FF
+ * BDA area                            0x00000400 0x000004FF
+ * Conventional Low Memory             0x00000500 0x0009FBFF
+ * EBDA area                           0x0009FC00 0x0009FFFF
+ * VIDEO RAM                           0x000A0000 0x000BFFFF
+ * VIDEO ROM (BIOS)                    0x000C0000 0x000C7FFF
+ * ROMs & unus. space (mapped hw & misc)0x000C8000 0x000EFFFF 160 KiB (typically)
+ * Motherboard BIOS                    0x000F0000 0x000FFFFF
+ * Extended Memory                     0x00100000 0xFEBFFFFF
+ * Reserved (configs, ACPI, PnP, etc)  0xFEC00000 0xFFFFFFFF
+ */
+
+#define REAL_MODE_IVT_BEGIN            0x00000000
+#define REAL_MODE_IVT_END              0x000003ff
+
+#define BDA_START                      0x00000400
+#define BDA_END                                0x000004ff
+
+#define EBDA_START                     0x0009fc00
+#define EBDA_END                       0x0009ffff
+
+#define E820_MAP_START                 EBDA_START
+
+#define MB_BIOS_BEGIN                  0x000f0000
+#define MB_FIRMWARE_BIOS_BEGIN         0x000e0000
+#define MB_BIOS_END                    0x000fffff
+
+#define MB_BIOS_SIZE                   (MB_BIOS_END - MB_BIOS_BEGIN + 1)
+#define MB_FIRMWARE_BIOS_SIZE          (MB_BIOS_END - MB_FIRMWARE_BIOS_BEGIN + 1)
+
+#define VGA_RAM_BEGIN                  0x000a0000
+#define VGA_RAM_END                    0x000bffff
+
+#define VGA_ROM_BEGIN                  0x000c0000
+#define VGA_ROM_OEM_STRING             VGA_ROM_BEGIN
+#define VGA_ROM_OEM_STRING_SIZE                16
+#define VGA_ROM_MODES                  (VGA_ROM_OEM_STRING + VGA_ROM_OEM_STRING_SIZE)
+#define VGA_ROM_MODES_SIZE             32
+#define VGA_ROM_END                    0x000c7fff
+
+/* we handle one page only */
+#define VGA_RAM_SEG                    (VGA_RAM_BEGIN >> 4)
+#define VGA_PAGE_SIZE                  0x007d0 /* 80x25 */
+
+/* real mode interrupt vector table */
+#define REAL_INTR_BASE                 REAL_MODE_IVT_BEGIN
+#define REAL_INTR_VECTORS              256
+
+/*
+ * BIOS stack must be at absolute predefined memory address
+ * We reserve 64 bytes for BIOS stack
+ */
+#define MB_BIOS_SS                     0xfff7
+#define MB_BIOS_SP                     0x40
+
+/*
+ * When interfere with assembler code we need to be sure how
+ * arguments are passed in real mode.
+ */
+#define bioscall __attribute__((regparm(3)))
+
+#ifndef __ASSEMBLER__
+
+#include <linux/types.h>
+
+struct biosregs {
+       u32                     eax;
+       u32                     ebx;
+       u32                     ecx;
+       u32                     edx;
+       u32                     esp;
+       u32                     ebp;
+       u32                     esi;
+       u32                     edi;
+       u32                     ds;
+       u32                     es;
+       u32                     fs;
+       u32                     eip;
+       u32                     eflags;
+};
+
+extern bioscall void int10_handler(struct biosregs *regs);
+extern bioscall void int15_handler(struct biosregs *regs);
+
+#endif
+
+#endif /* BIOS_H_ */
diff --git a/tools/kvm/x86/include/kvm/boot-protocol.h b/tools/kvm/x86/include/kvm/boot-protocol.h
new file mode 100644 (file)
index 0000000..85b637f
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * Linux boot protocol specifics
+ */
+
+#ifndef BOOT_PROTOCOL_H_
+#define BOOT_PROTOCOL_H_
+
+/*
+ * The protected mode kernel part of a modern bzImage is loaded
+ * at 1 MB by default.
+ */
+#define BZ_DEFAULT_SETUP_SECTS         4
+#define BZ_KERNEL_START                        0x100000UL
+#define INITRD_START                   0x1000000UL
+
+#endif /* BOOT_PROTOCOL_H_ */
diff --git a/tools/kvm/x86/include/kvm/cpufeature.h b/tools/kvm/x86/include/kvm/cpufeature.h
new file mode 100644 (file)
index 0000000..bc4abbb
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef KVM__CPUFEATURE_H
+#define KVM__CPUFEATURE_H
+
+#define CPUID_VENDOR_INTEL_1 0x756e6547 /* "Genu" */
+#define CPUID_VENDOR_INTEL_2 0x49656e69 /* "ineI" */
+#define CPUID_VENDOR_INTEL_3 0x6c65746e /* "ntel" */
+
+#define CPUID_VENDOR_AMD_1   0x68747541 /* "Auth" */
+#define CPUID_VENDOR_AMD_2   0x69746e65 /* "enti" */
+#define CPUID_VENDOR_AMD_3   0x444d4163 /* "cAMD" */
+
+/*
+ * CPUID flags we need to deal with
+ */
+#define KVM__X86_FEATURE_VMX           5       /* Hardware virtualization */
+#define KVM__X86_FEATURE_SVM           2       /* Secure virtual machine */
+#define KVM__X86_FEATURE_XSAVE         26      /* XSAVE/XRSTOR/XSETBV/XGETBV */
+
+#define cpu_feature_disable(reg, feature)      \
+       ((reg) & ~(1 << (feature)))
+#define cpu_feature_enable(reg, feature)       \
+       ((reg) |  (1 << (feature)))
+
+struct cpuid_regs {
+       u32     eax;
+       u32     ebx;
+       u32     ecx;
+       u32     edx;
+};
+
+static inline void host_cpuid(struct cpuid_regs *regs)
+{
+       asm volatile("cpuid"
+               : "=a" (regs->eax),
+                 "=b" (regs->ebx),
+                 "=c" (regs->ecx),
+                 "=d" (regs->edx)
+               : "0" (regs->eax), "2" (regs->ecx));
+}
+
+#endif /* KVM__CPUFEATURE_H */
diff --git a/tools/kvm/x86/include/kvm/interrupt.h b/tools/kvm/x86/include/kvm/interrupt.h
new file mode 100644 (file)
index 0000000..00c7ed7
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef KVM__INTERRUPT_H
+#define KVM__INTERRUPT_H
+
+#include <linux/types.h>
+#include "kvm/bios.h"
+#include "kvm/bios-export.h"
+
+struct real_intr_desc {
+       u16 offset;
+       u16 segment;
+} __attribute__((packed));
+
+#define REAL_SEGMENT_SHIFT     4
+#define REAL_SEGMENT(addr)     ((addr) >> REAL_SEGMENT_SHIFT)
+#define REAL_OFFSET(addr)      ((addr) & ((1 << REAL_SEGMENT_SHIFT) - 1))
+#define REAL_INTR_SIZE         (REAL_INTR_VECTORS * sizeof(struct real_intr_desc))
+
+struct interrupt_table {
+       struct real_intr_desc entries[REAL_INTR_VECTORS];
+};
+
+void interrupt_table__copy(struct interrupt_table *itable, void *dst, unsigned int size);
+void interrupt_table__setup(struct interrupt_table *itable, struct real_intr_desc *entry);
+void interrupt_table__set(struct interrupt_table *itable, struct real_intr_desc *entry, unsigned int num);
+
+#endif /* KVM__INTERRUPT_H */
diff --git a/tools/kvm/x86/include/kvm/kvm-arch.h b/tools/kvm/x86/include/kvm/kvm-arch.h
new file mode 100644 (file)
index 0000000..30086f4
--- /dev/null
@@ -0,0 +1,43 @@
+#ifndef KVM__KVM_ARCH_H
+#define KVM__KVM_ARCH_H
+
+#include "kvm/interrupt.h"
+#include "kvm/segment.h"
+
+#include <stdbool.h>
+#include <linux/types.h>
+#include <time.h>
+
+/*
+ * The hole includes VESA framebuffer and PCI memory.
+ */
+#define KVM_32BIT_MAX_MEM_SIZE  (1ULL << 32)
+#define KVM_32BIT_GAP_SIZE     (768 << 20)
+#define KVM_32BIT_GAP_START    (KVM_32BIT_MAX_MEM_SIZE - KVM_32BIT_GAP_SIZE)
+
+#define KVM_MMIO_START         KVM_32BIT_GAP_START
+
+/* This is the address that pci_get_io_space_block() starts allocating
+ * from.  Note that this is a PCI bus address (though same on x86).
+ */
+#define KVM_PCI_MMIO_AREA      (KVM_MMIO_START + 0x1000000)
+#define KVM_VIRTIO_MMIO_AREA   (KVM_MMIO_START + 0x2000000)
+
+struct kvm_arch {
+       u16                     boot_selector;
+       u16                     boot_ip;
+       u16                     boot_sp;
+
+       struct interrupt_table  interrupt_table;
+};
+
+static inline void *guest_flat_to_host(struct kvm *kvm, unsigned long offset); /* In kvm.h */
+
+static inline void *guest_real_to_host(struct kvm *kvm, u16 selector, u16 offset)
+{
+       unsigned long flat = segment_to_flat(selector, offset);
+
+       return guest_flat_to_host(kvm, flat);
+}
+
+#endif /* KVM__KVM_ARCH_H */
diff --git a/tools/kvm/x86/include/kvm/kvm-cpu-arch.h b/tools/kvm/x86/include/kvm/kvm-cpu-arch.h
new file mode 100644 (file)
index 0000000..198efe6
--- /dev/null
@@ -0,0 +1,49 @@
+#ifndef KVM__KVM_CPU_ARCH_H
+#define KVM__KVM_CPU_ARCH_H
+
+/* Architecture-specific kvm_cpu definitions. */
+
+#include <linux/kvm.h> /* for struct kvm_regs */
+#include "kvm/kvm.h"   /* for kvm__emulate_{mm}io() */
+#include <stdbool.h>
+#include <pthread.h>
+
+struct kvm;
+
+struct kvm_cpu {
+       pthread_t               thread;         /* VCPU thread */
+
+       unsigned long           cpu_id;
+
+       struct kvm              *kvm;           /* parent KVM */
+       int                     vcpu_fd;        /* For VCPU ioctls() */
+       struct kvm_run          *kvm_run;
+
+       struct kvm_regs         regs;
+       struct kvm_sregs        sregs;
+       struct kvm_fpu          fpu;
+
+       struct kvm_msrs         *msrs;          /* dynamically allocated */
+
+       u8                      is_running;
+       u8                      paused;
+       u8                      needs_nmi;
+
+       struct kvm_coalesced_mmio_ring  *ring;
+};
+
+/*
+ * As these are such simple wrappers, let's have them in the header so they'll
+ * be cheaper to call:
+ */
+static inline bool kvm_cpu__emulate_io(struct kvm *kvm, u16 port, void *data, int direction, int size, u32 count)
+{
+       return kvm__emulate_io(kvm, port, data, direction, size, count);
+}
+
+static inline bool kvm_cpu__emulate_mmio(struct kvm *kvm, u64 phys_addr, u8 *data, u32 len, u8 is_write)
+{
+       return kvm__emulate_mmio(kvm, phys_addr, data, len, is_write);
+}
+
+#endif /* KVM__KVM_CPU_ARCH_H */
diff --git a/tools/kvm/x86/include/kvm/mptable.h b/tools/kvm/x86/include/kvm/mptable.h
new file mode 100644 (file)
index 0000000..9e3cfa6
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef KVM_MPTABLE_H_
+#define KVM_MPTABLE_H_
+
+struct kvm;
+
+int mptable__init(struct kvm *kvm);
+int mptable__exit(struct kvm *kvm);
+
+#endif /* KVM_MPTABLE_H_ */
diff --git a/tools/kvm/x86/interrupt.c b/tools/kvm/x86/interrupt.c
new file mode 100644 (file)
index 0000000..7d47869
--- /dev/null
@@ -0,0 +1,28 @@
+#include "kvm/interrupt.h"
+
+#include "kvm/util.h"
+
+#include <string.h>
+
+void interrupt_table__copy(struct interrupt_table *itable, void *dst, unsigned int size)
+{
+       if (size < sizeof(itable->entries))
+               die("An attempt to overwrite host memory");
+
+       memcpy(dst, itable->entries, sizeof(itable->entries));
+}
+
+void interrupt_table__setup(struct interrupt_table *itable, struct real_intr_desc *entry)
+{
+       unsigned int i;
+
+       for (i = 0; i < REAL_INTR_VECTORS; i++)
+               itable->entries[i] = *entry;
+}
+
+void interrupt_table__set(struct interrupt_table *itable,
+                               struct real_intr_desc *entry, unsigned int num)
+{
+       if (num < REAL_INTR_VECTORS)
+               itable->entries[num] = *entry;
+}
diff --git a/tools/kvm/x86/ioport.c b/tools/kvm/x86/ioport.c
new file mode 100644 (file)
index 0000000..e35d0ee
--- /dev/null
@@ -0,0 +1,77 @@
+#include "kvm/ioport.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+
+static bool debug_io_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
+{
+       return 0;
+}
+
+static struct ioport_operations debug_ops = {
+       .io_out         = debug_io_out,
+};
+
+static bool seabios_debug_io_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
+{
+       char ch;
+
+       ch = ioport__read8(data);
+
+       putchar(ch);
+
+       return true;
+}
+
+static struct ioport_operations seabios_debug_ops = {
+       .io_out         = seabios_debug_io_out,
+};
+
+static bool dummy_io_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
+{
+       return true;
+}
+
+static bool dummy_io_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
+{
+       return true;
+}
+
+static struct ioport_operations dummy_read_write_ioport_ops = {
+       .io_in          = dummy_io_in,
+       .io_out         = dummy_io_out,
+};
+
+static struct ioport_operations dummy_write_only_ioport_ops = {
+       .io_out         = dummy_io_out,
+};
+
+void ioport__setup_arch(struct kvm *kvm)
+{
+       /* Legacy ioport setup */
+
+       /* 0x0020 - 0x003F - 8259A PIC 1 */
+       ioport__register(kvm, 0x0020, &dummy_read_write_ioport_ops, 2, NULL);
+
+       /* PORT 0040-005F - PIT - PROGRAMMABLE INTERVAL TIMER (8253, 8254) */
+       ioport__register(kvm, 0x0040, &dummy_read_write_ioport_ops, 4, NULL);
+
+       /* 0x00A0 - 0x00AF - 8259A PIC 2 */
+       ioport__register(kvm, 0x00A0, &dummy_read_write_ioport_ops, 2, NULL);
+
+       /* PORT 00E0-00EF are 'motherboard specific' so we use them for our
+          internal debugging purposes.  */
+       ioport__register(kvm, IOPORT_DBG, &debug_ops, 1, NULL);
+
+       /* PORT 00ED - DUMMY PORT FOR DELAY??? */
+       ioport__register(kvm, 0x00ED, &dummy_write_only_ioport_ops, 1, NULL);
+
+       /* 0x00F0 - 0x00FF - Math co-processor */
+       ioport__register(kvm, 0x00F0, &dummy_write_only_ioport_ops, 2, NULL);
+
+       /* PORT 03D4-03D5 - COLOR VIDEO - CRT CONTROL REGISTERS */
+       ioport__register(kvm, 0x03D4, &dummy_read_write_ioport_ops, 1, NULL);
+       ioport__register(kvm, 0x03D5, &dummy_write_only_ioport_ops, 1, NULL);
+
+       ioport__register(kvm, 0x402, &seabios_debug_ops, 1, NULL);
+}
diff --git a/tools/kvm/x86/irq.c b/tools/kvm/x86/irq.c
new file mode 100644 (file)
index 0000000..8dc90bf
--- /dev/null
@@ -0,0 +1,224 @@
+#include "kvm/irq.h"
+#include "kvm/kvm.h"
+#include "kvm/util.h"
+
+#include <linux/types.h>
+#include <linux/rbtree.h>
+#include <linux/list.h>
+#include <linux/kvm.h>
+#include <sys/ioctl.h>
+
+#include <stddef.h>
+#include <stdlib.h>
+
+#define IRQ_MAX_GSI                    64
+#define IRQCHIP_MASTER                 0
+#define IRQCHIP_SLAVE                  1
+#define IRQCHIP_IOAPIC                 2
+
+static u8              next_line       = 5;
+static u8              next_dev        = 1;
+static struct rb_root  pci_tree        = RB_ROOT;
+
+/* First 24 GSIs are routed between IRQCHIPs and IOAPICs */
+static u32 gsi = 24;
+
+struct kvm_irq_routing *irq_routing;
+
+static int irq__add_routing(u32 gsi, u32 type, u32 irqchip, u32 pin)
+{
+       if (gsi >= IRQ_MAX_GSI)
+               return -ENOSPC;
+
+       irq_routing->entries[irq_routing->nr++] =
+               (struct kvm_irq_routing_entry) {
+                       .gsi = gsi,
+                       .type = type,
+                       .u.irqchip.irqchip = irqchip,
+                       .u.irqchip.pin = pin,
+               };
+
+       return 0;
+}
+
+static struct pci_dev *search(struct rb_root *root, u32 id)
+{
+       struct rb_node *node = root->rb_node;
+
+       while (node) {
+               struct pci_dev *data = rb_entry(node, struct pci_dev, node);
+               int result;
+
+               result = id - data->id;
+
+               if (result < 0)
+                       node = node->rb_left;
+               else if (result > 0)
+                       node = node->rb_right;
+               else
+                       return data;
+       }
+       return NULL;
+}
+
+static int insert(struct rb_root *root, struct pci_dev *data)
+{
+       struct rb_node **new = &(root->rb_node), *parent = NULL;
+
+       /* Figure out where to put new node */
+       while (*new) {
+               struct pci_dev *this    = container_of(*new, struct pci_dev, node);
+               int result              = data->id - this->id;
+
+               parent = *new;
+               if (result < 0)
+                       new = &((*new)->rb_left);
+               else if (result > 0)
+                       new = &((*new)->rb_right);
+               else
+                       return -EEXIST;
+       }
+
+       /* Add new node and rebalance tree. */
+       rb_link_node(&data->node, parent, new);
+       rb_insert_color(&data->node, root);
+
+       return 0;
+}
+
+int irq__register_device(u32 dev, u8 *num, u8 *pin, u8 *line)
+{
+       struct pci_dev *node;
+       int r;
+
+       node = search(&pci_tree, dev);
+
+       if (!node) {
+               /* We haven't found a node - First device of it's kind */
+               node = malloc(sizeof(*node));
+               if (node == NULL)
+                       return -ENOMEM;
+
+               *node = (struct pci_dev) {
+                       .id     = dev,
+                       /*
+                        * PCI supports only INTA#,B#,C#,D# per device.
+                        * A#,B#,C#,D# are allowed for multifunctional
+                        * devices so stick with A# for our single
+                        * function devices.
+                        */
+                       .pin    = 1,
+               };
+
+               INIT_LIST_HEAD(&node->lines);
+
+               r = insert(&pci_tree, node);
+               if (r) {
+                       free(node);
+                       return r;
+               }
+       }
+
+       if (node) {
+               /* This device already has a pin assigned, give out a new line and device id */
+               struct irq_line *new = malloc(sizeof(*new));
+               if (new == NULL)
+                       return -ENOMEM;
+
+               new->line       = next_line++;
+               *line           = new->line;
+               *pin            = node->pin;
+               *num            = next_dev++;
+
+               list_add(&new->node, &node->lines);
+
+               return 0;
+       }
+
+       return -EFAULT;
+}
+
+int irq__init(struct kvm *kvm)
+{
+       int i, r;
+
+       irq_routing = calloc(sizeof(struct kvm_irq_routing) +
+                       IRQ_MAX_GSI * sizeof(struct kvm_irq_routing_entry), 1);
+       if (irq_routing == NULL)
+               return -ENOMEM;
+
+       /* Hook first 8 GSIs to master IRQCHIP */
+       for (i = 0; i < 8; i++)
+               if (i != 2)
+                       irq__add_routing(i, KVM_IRQ_ROUTING_IRQCHIP, IRQCHIP_MASTER, i);
+
+       /* Hook next 8 GSIs to slave IRQCHIP */
+       for (i = 8; i < 16; i++)
+               irq__add_routing(i, KVM_IRQ_ROUTING_IRQCHIP, IRQCHIP_SLAVE, i - 8);
+
+       /* Last but not least, IOAPIC */
+       for (i = 0; i < 24; i++) {
+               if (i == 0)
+                       irq__add_routing(i, KVM_IRQ_ROUTING_IRQCHIP, IRQCHIP_IOAPIC, 2);
+               else if (i != 2)
+                       irq__add_routing(i, KVM_IRQ_ROUTING_IRQCHIP, IRQCHIP_IOAPIC, i);
+       }
+
+       r = ioctl(kvm->vm_fd, KVM_SET_GSI_ROUTING, irq_routing);
+       if (r) {
+               free(irq_routing);
+               return errno;
+       }
+
+       return 0;
+}
+dev_base_init(irq__init);
+
+int irq__exit(struct kvm *kvm)
+{
+       struct rb_node *ent;
+
+       free(irq_routing);
+
+       while ((ent = rb_first(&pci_tree))) {
+               struct pci_dev *dev;
+               struct irq_line *line;
+
+               dev = rb_entry(ent, struct pci_dev, node);
+               while (!list_empty(&dev->lines)) {
+                       line = list_first_entry(&dev->lines, struct irq_line, node);
+                       list_del(&line->node);
+                       free(line);
+               }
+               rb_erase(&dev->node, &pci_tree);
+               free(dev);
+       }
+
+       return 0;
+}
+dev_base_exit(irq__exit);
+
+int irq__add_msix_route(struct kvm *kvm, struct msi_msg *msg)
+{
+       int r;
+
+       irq_routing->entries[irq_routing->nr++] =
+               (struct kvm_irq_routing_entry) {
+                       .gsi = gsi,
+                       .type = KVM_IRQ_ROUTING_MSI,
+                       .u.msi.address_hi = msg->address_hi,
+                       .u.msi.address_lo = msg->address_lo,
+                       .u.msi.data = msg->data,
+               };
+
+       r = ioctl(kvm->vm_fd, KVM_SET_GSI_ROUTING, irq_routing);
+       if (r)
+               return r;
+
+       return gsi++;
+}
+
+struct rb_node *irq__get_pci_tree(void)
+{
+       return rb_first(&pci_tree);
+}
diff --git a/tools/kvm/x86/kvm-cpu.c b/tools/kvm/x86/kvm-cpu.c
new file mode 100644 (file)
index 0000000..b6190ed
--- /dev/null
@@ -0,0 +1,425 @@
+#include "kvm/kvm-cpu.h"
+
+#include "kvm/symbol.h"
+#include "kvm/util.h"
+#include "kvm/kvm.h"
+
+#include <asm/msr-index.h>
+#include <asm/apicdef.h>
+#include <linux/err.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <stdio.h>
+
+static int debug_fd;
+
+void kvm_cpu__set_debug_fd(int fd)
+{
+       debug_fd = fd;
+}
+
+int kvm_cpu__get_debug_fd(void)
+{
+       return debug_fd;
+}
+
+static inline bool is_in_protected_mode(struct kvm_cpu *vcpu)
+{
+       return vcpu->sregs.cr0 & 0x01;
+}
+
+static inline u64 ip_to_flat(struct kvm_cpu *vcpu, u64 ip)
+{
+       u64 cs;
+
+       /*
+        * NOTE! We should take code segment base address into account here.
+        * Luckily it's usually zero because Linux uses flat memory model.
+        */
+       if (is_in_protected_mode(vcpu))
+               return ip;
+
+       cs = vcpu->sregs.cs.selector;
+
+       return ip + (cs << 4);
+}
+
+static inline u32 selector_to_base(u16 selector)
+{
+       /*
+        * KVM on Intel requires 'base' to be 'selector * 16' in real mode.
+        */
+       return (u32)selector << 4;
+}
+
+static struct kvm_cpu *kvm_cpu__new(struct kvm *kvm)
+{
+       struct kvm_cpu *vcpu;
+
+       vcpu = calloc(1, sizeof(*vcpu));
+       if (!vcpu)
+               return NULL;
+
+       vcpu->kvm = kvm;
+
+       return vcpu;
+}
+
+void kvm_cpu__delete(struct kvm_cpu *vcpu)
+{
+       if (vcpu->msrs)
+               free(vcpu->msrs);
+
+       free(vcpu);
+}
+
+static int kvm_cpu__set_lint(struct kvm_cpu *vcpu)
+{
+       struct local_apic lapic;
+
+       if (ioctl(vcpu->vcpu_fd, KVM_GET_LAPIC, &lapic))
+               return -1;
+
+       lapic.lvt_lint0.delivery_mode = APIC_MODE_EXTINT;
+       lapic.lvt_lint1.delivery_mode = APIC_MODE_NMI;
+
+       return ioctl(vcpu->vcpu_fd, KVM_SET_LAPIC, &lapic);
+}
+
+struct kvm_cpu *kvm_cpu__arch_init(struct kvm *kvm, unsigned long cpu_id)
+{
+       struct kvm_cpu *vcpu;
+       int mmap_size;
+       int coalesced_offset;
+
+       vcpu = kvm_cpu__new(kvm);
+       if (!vcpu)
+               return NULL;
+
+       vcpu->cpu_id = cpu_id;
+
+       vcpu->vcpu_fd = ioctl(vcpu->kvm->vm_fd, KVM_CREATE_VCPU, cpu_id);
+       if (vcpu->vcpu_fd < 0)
+               die_perror("KVM_CREATE_VCPU ioctl");
+
+       mmap_size = ioctl(vcpu->kvm->sys_fd, KVM_GET_VCPU_MMAP_SIZE, 0);
+       if (mmap_size < 0)
+               die_perror("KVM_GET_VCPU_MMAP_SIZE ioctl");
+
+       vcpu->kvm_run = mmap(NULL, mmap_size, PROT_RW, MAP_SHARED, vcpu->vcpu_fd, 0);
+       if (vcpu->kvm_run == MAP_FAILED)
+               die("unable to mmap vcpu fd");
+
+       coalesced_offset = ioctl(kvm->sys_fd, KVM_CHECK_EXTENSION, KVM_CAP_COALESCED_MMIO);
+       if (coalesced_offset)
+               vcpu->ring = (void *)vcpu->kvm_run + (coalesced_offset * PAGE_SIZE);
+
+       if (kvm_cpu__set_lint(vcpu))
+               die_perror("KVM_SET_LAPIC failed");
+
+       vcpu->is_running = true;
+
+       return vcpu;
+}
+
+static struct kvm_msrs *kvm_msrs__new(size_t nmsrs)
+{
+       struct kvm_msrs *vcpu = calloc(1, sizeof(*vcpu) + (sizeof(struct kvm_msr_entry) * nmsrs));
+
+       if (!vcpu)
+               die("out of memory");
+
+       return vcpu;
+}
+
+#define KVM_MSR_ENTRY(_index, _data)   \
+       (struct kvm_msr_entry) { .index = _index, .data = _data }
+
+static void kvm_cpu__setup_msrs(struct kvm_cpu *vcpu)
+{
+       unsigned long ndx = 0;
+
+       vcpu->msrs = kvm_msrs__new(100);
+
+       vcpu->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_IA32_SYSENTER_CS,        0x0);
+       vcpu->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_IA32_SYSENTER_ESP,       0x0);
+       vcpu->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_IA32_SYSENTER_EIP,       0x0);
+#ifdef CONFIG_X86_64
+       vcpu->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_STAR,                    0x0);
+       vcpu->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_CSTAR,                   0x0);
+       vcpu->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_KERNEL_GS_BASE,          0x0);
+       vcpu->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_SYSCALL_MASK,            0x0);
+       vcpu->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_LSTAR,                   0x0);
+#endif
+       vcpu->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_IA32_TSC,                0x0);
+       vcpu->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_IA32_MISC_ENABLE,
+                                               MSR_IA32_MISC_ENABLE_FAST_STRING);
+
+       vcpu->msrs->nmsrs = ndx;
+
+       if (ioctl(vcpu->vcpu_fd, KVM_SET_MSRS, vcpu->msrs) < 0)
+               die_perror("KVM_SET_MSRS failed");
+}
+
+static void kvm_cpu__setup_fpu(struct kvm_cpu *vcpu)
+{
+       vcpu->fpu = (struct kvm_fpu) {
+               .fcw    = 0x37f,
+               .mxcsr  = 0x1f80,
+       };
+
+       if (ioctl(vcpu->vcpu_fd, KVM_SET_FPU, &vcpu->fpu) < 0)
+               die_perror("KVM_SET_FPU failed");
+}
+
+static void kvm_cpu__setup_regs(struct kvm_cpu *vcpu)
+{
+       vcpu->regs = (struct kvm_regs) {
+               /* We start the guest in 16-bit real mode  */
+               .rflags = 0x0000000000000002ULL,
+
+               .rip    = vcpu->kvm->arch.boot_ip,
+               .rsp    = vcpu->kvm->arch.boot_sp,
+               .rbp    = vcpu->kvm->arch.boot_sp,
+       };
+
+       if (vcpu->regs.rip > USHRT_MAX)
+               die("ip 0x%llx is too high for real mode", (u64)vcpu->regs.rip);
+
+       if (ioctl(vcpu->vcpu_fd, KVM_SET_REGS, &vcpu->regs) < 0)
+               die_perror("KVM_SET_REGS failed");
+}
+
+static void kvm_cpu__setup_sregs(struct kvm_cpu *vcpu)
+{
+       if (ioctl(vcpu->vcpu_fd, KVM_GET_SREGS, &vcpu->sregs) < 0)
+               die_perror("KVM_GET_SREGS failed");
+
+       vcpu->sregs.cs.selector = vcpu->kvm->arch.boot_selector;
+       vcpu->sregs.cs.base     = selector_to_base(vcpu->kvm->arch.boot_selector);
+       vcpu->sregs.ss.selector = vcpu->kvm->arch.boot_selector;
+       vcpu->sregs.ss.base     = selector_to_base(vcpu->kvm->arch.boot_selector);
+       vcpu->sregs.ds.selector = vcpu->kvm->arch.boot_selector;
+       vcpu->sregs.ds.base     = selector_to_base(vcpu->kvm->arch.boot_selector);
+       vcpu->sregs.es.selector = vcpu->kvm->arch.boot_selector;
+       vcpu->sregs.es.base     = selector_to_base(vcpu->kvm->arch.boot_selector);
+       vcpu->sregs.fs.selector = vcpu->kvm->arch.boot_selector;
+       vcpu->sregs.fs.base     = selector_to_base(vcpu->kvm->arch.boot_selector);
+       vcpu->sregs.gs.selector = vcpu->kvm->arch.boot_selector;
+       vcpu->sregs.gs.base     = selector_to_base(vcpu->kvm->arch.boot_selector);
+
+       if (ioctl(vcpu->vcpu_fd, KVM_SET_SREGS, &vcpu->sregs) < 0)
+               die_perror("KVM_SET_SREGS failed");
+}
+
+/**
+ * kvm_cpu__reset_vcpu - reset virtual CPU to a known state
+ */
+void kvm_cpu__reset_vcpu(struct kvm_cpu *vcpu)
+{
+       kvm_cpu__setup_cpuid(vcpu);
+       kvm_cpu__setup_sregs(vcpu);
+       kvm_cpu__setup_regs(vcpu);
+       kvm_cpu__setup_fpu(vcpu);
+       kvm_cpu__setup_msrs(vcpu);
+}
+
+bool kvm_cpu__handle_exit(struct kvm_cpu *vcpu)
+{
+       return false;
+}
+
+static void print_dtable(const char *name, struct kvm_dtable *dtable)
+{
+       dprintf(debug_fd, " %s                 %016llx  %08hx\n",
+               name, (u64) dtable->base, (u16) dtable->limit);
+}
+
+static void print_segment(const char *name, struct kvm_segment *seg)
+{
+       dprintf(debug_fd, " %s       %04hx      %016llx  %08x  %02hhx    %x %x   %x  %x %x %x %x\n",
+               name, (u16) seg->selector, (u64) seg->base, (u32) seg->limit,
+               (u8) seg->type, seg->present, seg->dpl, seg->db, seg->s, seg->l, seg->g, seg->avl);
+}
+
+void kvm_cpu__show_registers(struct kvm_cpu *vcpu)
+{
+       unsigned long cr0, cr2, cr3;
+       unsigned long cr4, cr8;
+       unsigned long rax, rbx, rcx;
+       unsigned long rdx, rsi, rdi;
+       unsigned long rbp,  r8,  r9;
+       unsigned long r10, r11, r12;
+       unsigned long r13, r14, r15;
+       unsigned long rip, rsp;
+       struct kvm_sregs sregs;
+       unsigned long rflags;
+       struct kvm_regs regs;
+       int i;
+
+       if (ioctl(vcpu->vcpu_fd, KVM_GET_REGS, &regs) < 0)
+               die("KVM_GET_REGS failed");
+
+       rflags = regs.rflags;
+
+       rip = regs.rip; rsp = regs.rsp;
+       rax = regs.rax; rbx = regs.rbx; rcx = regs.rcx;
+       rdx = regs.rdx; rsi = regs.rsi; rdi = regs.rdi;
+       rbp = regs.rbp; r8  = regs.r8;  r9  = regs.r9;
+       r10 = regs.r10; r11 = regs.r11; r12 = regs.r12;
+       r13 = regs.r13; r14 = regs.r14; r15 = regs.r15;
+
+       dprintf(debug_fd, "\n Registers:\n");
+       dprintf(debug_fd,   " ----------\n");
+       dprintf(debug_fd, " rip: %016lx   rsp: %016lx flags: %016lx\n", rip, rsp, rflags);
+       dprintf(debug_fd, " rax: %016lx   rbx: %016lx   rcx: %016lx\n", rax, rbx, rcx);
+       dprintf(debug_fd, " rdx: %016lx   rsi: %016lx   rdi: %016lx\n", rdx, rsi, rdi);
+       dprintf(debug_fd, " rbp: %016lx    r8: %016lx    r9: %016lx\n", rbp, r8,  r9);
+       dprintf(debug_fd, " r10: %016lx   r11: %016lx   r12: %016lx\n", r10, r11, r12);
+       dprintf(debug_fd, " r13: %016lx   r14: %016lx   r15: %016lx\n", r13, r14, r15);
+
+       if (ioctl(vcpu->vcpu_fd, KVM_GET_SREGS, &sregs) < 0)
+               die("KVM_GET_REGS failed");
+
+       cr0 = sregs.cr0; cr2 = sregs.cr2; cr3 = sregs.cr3;
+       cr4 = sregs.cr4; cr8 = sregs.cr8;
+
+       dprintf(debug_fd, " cr0: %016lx   cr2: %016lx   cr3: %016lx\n", cr0, cr2, cr3);
+       dprintf(debug_fd, " cr4: %016lx   cr8: %016lx\n", cr4, cr8);
+       dprintf(debug_fd, "\n Segment registers:\n");
+       dprintf(debug_fd,   " ------------------\n");
+       dprintf(debug_fd, " register  selector  base              limit     type  p dpl db s l g avl\n");
+       print_segment("cs ", &sregs.cs);
+       print_segment("ss ", &sregs.ss);
+       print_segment("ds ", &sregs.ds);
+       print_segment("es ", &sregs.es);
+       print_segment("fs ", &sregs.fs);
+       print_segment("gs ", &sregs.gs);
+       print_segment("tr ", &sregs.tr);
+       print_segment("ldt", &sregs.ldt);
+       print_dtable("gdt", &sregs.gdt);
+       print_dtable("idt", &sregs.idt);
+
+       dprintf(debug_fd, "\n APIC:\n");
+       dprintf(debug_fd,   " -----\n");
+       dprintf(debug_fd, " efer: %016llx  apic base: %016llx  nmi: %s\n",
+               (u64) sregs.efer, (u64) sregs.apic_base,
+               (vcpu->kvm->nmi_disabled ? "disabled" : "enabled"));
+
+       dprintf(debug_fd, "\n Interrupt bitmap:\n");
+       dprintf(debug_fd,   " -----------------\n");
+       for (i = 0; i < (KVM_NR_INTERRUPTS + 63) / 64; i++)
+               dprintf(debug_fd, " %016llx", (u64) sregs.interrupt_bitmap[i]);
+       dprintf(debug_fd, "\n");
+}
+
+#define MAX_SYM_LEN 128
+
+void kvm_cpu__show_code(struct kvm_cpu *vcpu)
+{
+       unsigned int code_bytes = 64;
+       unsigned int code_prologue = 43;
+       unsigned int code_len = code_bytes;
+       char sym[MAX_SYM_LEN] = SYMBOL_DEFAULT_UNKNOWN, *psym;
+       unsigned char c;
+       unsigned int i;
+       u8 *ip;
+
+       if (ioctl(vcpu->vcpu_fd, KVM_GET_REGS, &vcpu->regs) < 0)
+               die("KVM_GET_REGS failed");
+
+       if (ioctl(vcpu->vcpu_fd, KVM_GET_SREGS, &vcpu->sregs) < 0)
+               die("KVM_GET_SREGS failed");
+
+       ip = guest_flat_to_host(vcpu->kvm, ip_to_flat(vcpu, vcpu->regs.rip) - code_prologue);
+
+       dprintf(debug_fd, "\n Code:\n");
+       dprintf(debug_fd,   " -----\n");
+
+       psym = symbol_lookup(vcpu->kvm, vcpu->regs.rip, sym, MAX_SYM_LEN);
+       if (IS_ERR(psym))
+               dprintf(debug_fd,
+                       "Warning: symbol_lookup() failed to find symbol "
+                       "with error: %ld\n", PTR_ERR(psym));
+
+       dprintf(debug_fd, " rip: [<%016lx>] %s\n\n", (unsigned long) vcpu->regs.rip, sym);
+
+       for (i = 0; i < code_len; i++, ip++) {
+               if (!host_ptr_in_ram(vcpu->kvm, ip))
+                       break;
+
+               c = *ip;
+
+               if (ip == guest_flat_to_host(vcpu->kvm, ip_to_flat(vcpu, vcpu->regs.rip)))
+                       dprintf(debug_fd, " <%02x>", c);
+               else
+                       dprintf(debug_fd, " %02x", c);
+       }
+
+       dprintf(debug_fd, "\n");
+
+       dprintf(debug_fd, "\n Stack:\n");
+       dprintf(debug_fd,   " ------\n");
+       kvm__dump_mem(vcpu->kvm, vcpu->regs.rsp, 32);
+}
+
+void kvm_cpu__show_page_tables(struct kvm_cpu *vcpu)
+{
+       u64 *pte1;
+       u64 *pte2;
+       u64 *pte3;
+       u64 *pte4;
+
+       if (!is_in_protected_mode(vcpu))
+               return;
+
+       if (ioctl(vcpu->vcpu_fd, KVM_GET_SREGS, &vcpu->sregs) < 0)
+               die("KVM_GET_SREGS failed");
+
+       pte4 = guest_flat_to_host(vcpu->kvm, vcpu->sregs.cr3);
+       if (!host_ptr_in_ram(vcpu->kvm, pte4))
+               return;
+
+       pte3 = guest_flat_to_host(vcpu->kvm, (*pte4 & ~0xfff));
+       if (!host_ptr_in_ram(vcpu->kvm, pte3))
+               return;
+
+       pte2 = guest_flat_to_host(vcpu->kvm, (*pte3 & ~0xfff));
+       if (!host_ptr_in_ram(vcpu->kvm, pte2))
+               return;
+
+       pte1 = guest_flat_to_host(vcpu->kvm, (*pte2 & ~0xfff));
+       if (!host_ptr_in_ram(vcpu->kvm, pte1))
+               return;
+
+       dprintf(debug_fd, "Page Tables:\n");
+       if (*pte2 & (1 << 7))
+               dprintf(debug_fd, " pte4: %016llx   pte3: %016llx"
+                       "   pte2: %016llx\n",
+                       *pte4, *pte3, *pte2);
+       else
+               dprintf(debug_fd, " pte4: %016llx  pte3: %016llx   pte2: %016"
+                       "llx   pte1: %016llx\n",
+                       *pte4, *pte3, *pte2, *pte1);
+}
+
+void kvm_cpu__arch_nmi(struct kvm_cpu *cpu)
+{
+       struct kvm_lapic_state klapic;
+       struct local_apic *lapic = (void *)&klapic;
+
+       if (ioctl(cpu->vcpu_fd, KVM_GET_LAPIC, &klapic) != 0)
+               return;
+
+       if (lapic->lvt_lint1.mask)
+               return;
+
+       if (lapic->lvt_lint1.delivery_mode != APIC_MODE_NMI)
+               return;
+
+       ioctl(cpu->vcpu_fd, KVM_NMI);
+}
diff --git a/tools/kvm/x86/kvm.c b/tools/kvm/x86/kvm.c
new file mode 100644 (file)
index 0000000..ecada45
--- /dev/null
@@ -0,0 +1,362 @@
+#include "kvm/kvm.h"
+#include "kvm/boot-protocol.h"
+#include "kvm/cpufeature.h"
+#include "kvm/interrupt.h"
+#include "kvm/mptable.h"
+#include "kvm/util.h"
+#include "kvm/8250-serial.h"
+#include "kvm/virtio-console.h"
+
+#include <asm/bootparam.h>
+#include <linux/kvm.h>
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <fcntl.h>
+
+struct kvm_ext kvm_req_ext[] = {
+       { DEFINE_KVM_EXT(KVM_CAP_COALESCED_MMIO) },
+       { DEFINE_KVM_EXT(KVM_CAP_SET_TSS_ADDR) },
+       { DEFINE_KVM_EXT(KVM_CAP_PIT2) },
+       { DEFINE_KVM_EXT(KVM_CAP_USER_MEMORY) },
+       { DEFINE_KVM_EXT(KVM_CAP_IRQ_ROUTING) },
+       { DEFINE_KVM_EXT(KVM_CAP_IRQCHIP) },
+       { DEFINE_KVM_EXT(KVM_CAP_HLT) },
+       { DEFINE_KVM_EXT(KVM_CAP_IRQ_INJECT_STATUS) },
+       { DEFINE_KVM_EXT(KVM_CAP_EXT_CPUID) },
+       { 0, 0 }
+};
+
+bool kvm__arch_cpu_supports_vm(void)
+{
+       struct cpuid_regs regs;
+       u32 eax_base;
+       int feature;
+
+       regs    = (struct cpuid_regs) {
+               .eax            = 0x00,
+       };
+       host_cpuid(&regs);
+
+       switch (regs.ebx) {
+       case CPUID_VENDOR_INTEL_1:
+               eax_base        = 0x00;
+               feature         = KVM__X86_FEATURE_VMX;
+               break;
+
+       case CPUID_VENDOR_AMD_1:
+               eax_base        = 0x80000000;
+               feature         = KVM__X86_FEATURE_SVM;
+               break;
+
+       default:
+               return false;
+       }
+
+       regs    = (struct cpuid_regs) {
+               .eax            = eax_base,
+       };
+       host_cpuid(&regs);
+
+       if (regs.eax < eax_base + 0x01)
+               return false;
+
+       regs    = (struct cpuid_regs) {
+               .eax            = eax_base + 0x01
+       };
+       host_cpuid(&regs);
+
+       return regs.ecx & (1 << feature);
+}
+
+/*
+ * Allocating RAM size bigger than 4GB requires us to leave a gap
+ * in the RAM which is used for PCI MMIO, hotplug, and unconfigured
+ * devices (see documentation of e820_setup_gap() for details).
+ *
+ * If we're required to initialize RAM bigger than 4GB, we will create
+ * a gap between 0xe0000000 and 0x100000000 in the guest virtual mem space.
+ */
+
+void kvm__init_ram(struct kvm *kvm)
+{
+       u64     phys_start, phys_size;
+       void    *host_mem;
+
+       if (kvm->ram_size < KVM_32BIT_GAP_START) {
+               /* Use a single block of RAM for 32bit RAM */
+
+               phys_start = 0;
+               phys_size  = kvm->ram_size;
+               host_mem   = kvm->ram_start;
+
+               kvm__register_mem(kvm, phys_start, phys_size, host_mem);
+       } else {
+               /* First RAM range from zero to the PCI gap: */
+
+               phys_start = 0;
+               phys_size  = KVM_32BIT_GAP_START;
+               host_mem   = kvm->ram_start;
+
+               kvm__register_mem(kvm, phys_start, phys_size, host_mem);
+
+               /* Second RAM range from 4GB to the end of RAM: */
+
+               phys_start = KVM_32BIT_MAX_MEM_SIZE;
+               phys_size  = kvm->ram_size - phys_start;
+               host_mem   = kvm->ram_start + phys_start;
+
+               kvm__register_mem(kvm, phys_start, phys_size, host_mem);
+       }
+}
+
+/* Arch-specific commandline setup */
+void kvm__arch_set_cmdline(char *cmdline, bool video)
+{
+       strcpy(cmdline, "noapic noacpi pci=conf1 reboot=k panic=1 i8042.direct=1 "
+                               "i8042.dumbkbd=1 i8042.nopnp=1");
+       if (video)
+               strcat(cmdline, " video=vesafb console=tty0");
+       else
+               strcat(cmdline, " console=ttyS0 earlyprintk=serial i8042.noaux=1");
+}
+
+/* Architecture-specific KVM init */
+void kvm__arch_init(struct kvm *kvm, const char *hugetlbfs_path, u64 ram_size)
+{
+       struct kvm_pit_config pit_config = { .flags = 0, };
+       int ret;
+
+       ret = ioctl(kvm->vm_fd, KVM_SET_TSS_ADDR, 0xfffbd000);
+       if (ret < 0)
+               die_perror("KVM_SET_TSS_ADDR ioctl");
+
+       ret = ioctl(kvm->vm_fd, KVM_CREATE_PIT2, &pit_config);
+       if (ret < 0)
+               die_perror("KVM_CREATE_PIT2 ioctl");
+
+       if (ram_size < KVM_32BIT_GAP_START) {
+               kvm->ram_size = ram_size;
+               kvm->ram_start = mmap_anon_or_hugetlbfs(kvm, hugetlbfs_path, ram_size);
+       } else {
+               kvm->ram_start = mmap_anon_or_hugetlbfs(kvm, hugetlbfs_path, ram_size + KVM_32BIT_GAP_SIZE);
+               kvm->ram_size = ram_size + KVM_32BIT_GAP_SIZE;
+               if (kvm->ram_start != MAP_FAILED)
+                       /*
+                        * We mprotect the gap (see kvm__init_ram() for details) PROT_NONE so that
+                        * if we accidently write to it, we will know.
+                        */
+                       mprotect(kvm->ram_start + KVM_32BIT_GAP_START, KVM_32BIT_GAP_SIZE, PROT_NONE);
+       }
+       if (kvm->ram_start == MAP_FAILED)
+               die("out of memory");
+
+       madvise(kvm->ram_start, kvm->ram_size, MADV_MERGEABLE);
+
+       ret = ioctl(kvm->vm_fd, KVM_CREATE_IRQCHIP);
+       if (ret < 0)
+               die_perror("KVM_CREATE_IRQCHIP ioctl");
+}
+
+void kvm__arch_delete_ram(struct kvm *kvm)
+{
+       munmap(kvm->ram_start, kvm->ram_size);
+}
+
+void kvm__irq_line(struct kvm *kvm, int irq, int level)
+{
+       struct kvm_irq_level irq_level;
+
+       irq_level       = (struct kvm_irq_level) {
+               {
+                       .irq            = irq,
+               },
+               .level          = level,
+       };
+
+       if (ioctl(kvm->vm_fd, KVM_IRQ_LINE, &irq_level) < 0)
+               die_perror("KVM_IRQ_LINE failed");
+}
+
+void kvm__irq_trigger(struct kvm *kvm, int irq)
+{
+       kvm__irq_line(kvm, irq, 1);
+       kvm__irq_line(kvm, irq, 0);
+}
+
+#define BOOT_LOADER_SELECTOR   0x1000
+#define BOOT_LOADER_IP         0x0000
+#define BOOT_LOADER_SP         0x8000
+#define BOOT_CMDLINE_OFFSET    0x20000
+
+#define BOOT_PROTOCOL_REQUIRED 0x206
+#define LOAD_HIGH              0x01
+
+int load_flat_binary(struct kvm *kvm, int fd_kernel, int fd_initrd, const char *kernel_cmdline)
+{
+       void *p;
+       int nr;
+
+       /*
+        * Some architectures may support loading an initrd alongside the flat kernel,
+        * but we do not.
+        */
+       if (fd_initrd != -1)
+               pr_warning("Loading initrd with flat binary not supported.");
+
+       if (lseek(fd_kernel, 0, SEEK_SET) < 0)
+               die_perror("lseek");
+
+       p = guest_real_to_host(kvm, BOOT_LOADER_SELECTOR, BOOT_LOADER_IP);
+
+       while ((nr = read(fd_kernel, p, 65536)) > 0)
+               p += nr;
+
+       kvm->arch.boot_selector = BOOT_LOADER_SELECTOR;
+       kvm->arch.boot_ip       = BOOT_LOADER_IP;
+       kvm->arch.boot_sp       = BOOT_LOADER_SP;
+
+       return true;
+}
+
+static const char *BZIMAGE_MAGIC = "HdrS";
+
+bool load_bzimage(struct kvm *kvm, int fd_kernel,
+                 int fd_initrd, const char *kernel_cmdline, u16 vidmode)
+{
+       struct boot_params *kern_boot;
+       unsigned long setup_sects;
+       struct boot_params boot;
+       size_t cmdline_size;
+       ssize_t setup_size;
+       void *p;
+       int nr;
+
+       /*
+        * See Documentation/x86/boot.txt for details no bzImage on-disk and
+        * memory layout.
+        */
+
+       if (lseek(fd_kernel, 0, SEEK_SET) < 0)
+               die_perror("lseek");
+
+       if (read(fd_kernel, &boot, sizeof(boot)) != sizeof(boot))
+               return false;
+
+       if (memcmp(&boot.hdr.header, BZIMAGE_MAGIC, strlen(BZIMAGE_MAGIC)))
+               return false;
+
+       if (boot.hdr.version < BOOT_PROTOCOL_REQUIRED)
+               die("Too old kernel");
+
+       if (lseek(fd_kernel, 0, SEEK_SET) < 0)
+               die_perror("lseek");
+
+       if (!boot.hdr.setup_sects)
+               boot.hdr.setup_sects = BZ_DEFAULT_SETUP_SECTS;
+       setup_sects = boot.hdr.setup_sects + 1;
+
+       setup_size = setup_sects << 9;
+       p = guest_real_to_host(kvm, BOOT_LOADER_SELECTOR, BOOT_LOADER_IP);
+
+       /* copy setup.bin to mem*/
+       if (read(fd_kernel, p, setup_size) != setup_size)
+               die_perror("read");
+
+       /* copy vmlinux.bin to BZ_KERNEL_START*/
+       p = guest_flat_to_host(kvm, BZ_KERNEL_START);
+
+       while ((nr = read(fd_kernel, p, 65536)) > 0)
+               p += nr;
+
+       p = guest_flat_to_host(kvm, BOOT_CMDLINE_OFFSET);
+       if (kernel_cmdline) {
+               cmdline_size = strlen(kernel_cmdline) + 1;
+               if (cmdline_size > boot.hdr.cmdline_size)
+                       cmdline_size = boot.hdr.cmdline_size;
+
+               memset(p, 0, boot.hdr.cmdline_size);
+               memcpy(p, kernel_cmdline, cmdline_size - 1);
+       }
+
+       kern_boot       = guest_real_to_host(kvm, BOOT_LOADER_SELECTOR, 0x00);
+
+       kern_boot->hdr.cmd_line_ptr     = BOOT_CMDLINE_OFFSET;
+       kern_boot->hdr.type_of_loader   = 0xff;
+       kern_boot->hdr.heap_end_ptr     = 0xfe00;
+       kern_boot->hdr.loadflags        |= CAN_USE_HEAP;
+       kern_boot->hdr.vid_mode         = vidmode;
+
+       /*
+        * Read initrd image into guest memory
+        */
+       if (fd_initrd >= 0) {
+               struct stat initrd_stat;
+               unsigned long addr;
+
+               if (fstat(fd_initrd, &initrd_stat))
+                       die_perror("fstat");
+
+               addr = boot.hdr.initrd_addr_max & ~0xfffff;
+               for (;;) {
+                       if (addr < BZ_KERNEL_START)
+                               die("Not enough memory for initrd");
+                       else if (addr < (kvm->ram_size - initrd_stat.st_size))
+                               break;
+                       addr -= 0x100000;
+               }
+
+               p = guest_flat_to_host(kvm, addr);
+               nr = read(fd_initrd, p, initrd_stat.st_size);
+               if (nr != initrd_stat.st_size)
+                       die("Failed to read initrd");
+
+               kern_boot->hdr.ramdisk_image    = addr;
+               kern_boot->hdr.ramdisk_size     = initrd_stat.st_size;
+       }
+
+       kvm->arch.boot_selector = BOOT_LOADER_SELECTOR;
+       /*
+        * The real-mode setup code starts at offset 0x200 of a bzImage. See
+        * Documentation/x86/boot.txt for details.
+        */
+       kvm->arch.boot_ip = BOOT_LOADER_IP + 0x200;
+       kvm->arch.boot_sp = BOOT_LOADER_SP;
+
+       return true;
+}
+
+/**
+ * kvm__arch_setup_firmware - inject BIOS into guest system memory
+ * @kvm - guest system descriptor
+ *
+ * This function is a main routine where we poke guest memory
+ * and install BIOS there.
+ */
+int kvm__arch_setup_firmware(struct kvm *kvm)
+{
+       /* standart minimal configuration */
+       setup_bios(kvm);
+
+       /* FIXME: SMP, ACPI and friends here */
+
+       return 0;
+}
+
+int kvm__arch_free_firmware(struct kvm *kvm)
+{
+       return 0;
+}
+
+void kvm__arch_periodic_poll(struct kvm *kvm)
+{
+       serial8250__update_consoles(kvm);
+       virtio_console__inject_interrupt(kvm);
+}
diff --git a/tools/kvm/x86/mptable.c b/tools/kvm/x86/mptable.c
new file mode 100644 (file)
index 0000000..ea8c6e8
--- /dev/null
@@ -0,0 +1,289 @@
+#include "kvm/kvm.h"
+#include "kvm/bios.h"
+#include "kvm/apic.h"
+#include "kvm/mptable.h"
+#include "kvm/util.h"
+#include "kvm/irq.h"
+
+#include <linux/kernel.h>
+#include <string.h>
+
+#include <asm/mpspec_def.h>
+#include <linux/types.h>
+
+/*
+ * FIXME: please make sure the addresses borrowed
+ * for apic/ioapic never overlaped! We need a global
+ * tracker of system resources (including io, mmio,
+ * and friends).
+ */
+
+static unsigned int mpf_checksum(unsigned char *mp, int len)
+{
+       unsigned int sum = 0;
+
+       while (len--)
+               sum += *mp++;
+
+       return sum & 0xFF;
+}
+
+static unsigned int gen_cpu_flag(unsigned int cpu, unsigned int ncpu)
+{
+       /* sets enabled/disabled | BSP/AP processor */
+       return ( (cpu < ncpu) ? CPU_ENABLED       : 0) |
+               ((cpu == 0)   ? CPU_BOOTPROCESSOR : 0x00);
+}
+
+#define MPTABLE_SIG_FLOATING   "_MP_"
+#define MPTABLE_OEM            "KVMCPU00"
+#define MPTABLE_PRODUCTID      "0.1         "
+#define MPTABLE_PCIBUSTYPE     "PCI   "
+#define MPTABLE_ISABUSTYPE     "ISA   "
+
+#define MPTABLE_STRNCPY(d, s)  memcpy(d, s, sizeof(d))
+
+/* It should be more than enough */
+#define MPTABLE_MAX_SIZE       (32 << 20)
+
+/*
+ * Too many cpus will require x2apic mode
+ * and rather ACPI support so we limit it
+ * here for a while.
+ */
+#define MPTABLE_MAX_CPUS       255
+
+static void mptable_add_irq_src(struct mpc_intsrc *mpc_intsrc,
+                               u16 srcbusid,   u16 srcbusirq,
+                               u16 dstapic,    u16 dstirq)
+{
+       *mpc_intsrc = (struct mpc_intsrc) {
+               .type           = MP_INTSRC,
+               .irqtype        = mp_INT,
+               .irqflag        = MP_IRQDIR_DEFAULT,
+               .srcbus         = srcbusid,
+               .srcbusirq      = srcbusirq,
+               .dstapic        = dstapic,
+               .dstirq         = dstirq
+       };
+}
+
+/**
+ * mptable_setup - create mptable and fill guest memory with it
+ */
+int mptable__init(struct kvm *kvm)
+{
+       unsigned long real_mpc_table, real_mpf_intel, size;
+       struct mpf_intel *mpf_intel;
+       struct mpc_table *mpc_table;
+       struct mpc_cpu *mpc_cpu;
+       struct mpc_bus *mpc_bus;
+       struct mpc_ioapic *mpc_ioapic;
+       struct mpc_intsrc *mpc_intsrc;
+       struct rb_node *pci_tree;
+
+       const int pcibusid = 0;
+       const int isabusid = 1;
+
+       unsigned int i, nentries = 0, ncpus = kvm->nrcpus;
+       unsigned int ioapicid;
+       void *last_addr;
+
+       /* That is where MP table will be in guest memory */
+       real_mpc_table = ALIGN(MB_BIOS_BEGIN + bios_rom_size, 16);
+
+       if (ncpus > MPTABLE_MAX_CPUS) {
+               pr_warning("Too many cpus: %d limited to %d",
+                       ncpus, MPTABLE_MAX_CPUS);
+               ncpus = MPTABLE_MAX_CPUS;
+       }
+
+       mpc_table = calloc(1, MPTABLE_MAX_SIZE);
+       if (!mpc_table)
+               return -ENOMEM;
+
+       MPTABLE_STRNCPY(mpc_table->signature,   MPC_SIGNATURE);
+       MPTABLE_STRNCPY(mpc_table->oem,         MPTABLE_OEM);
+       MPTABLE_STRNCPY(mpc_table->productid,   MPTABLE_PRODUCTID);
+
+       mpc_table->spec         = 4;
+       mpc_table->lapic        = APIC_ADDR(0);
+       mpc_table->oemcount     = ncpus; /* will be updated again at end */
+
+       /*
+        * CPUs enumeration. Technically speaking we should
+        * ask either host or HV for apic version supported
+        * but for a while we simply put some random value
+        * here.
+        */
+       mpc_cpu = (void *)&mpc_table[1];
+       for (i = 0; i < ncpus; i++) {
+               mpc_cpu->type           = MP_PROCESSOR;
+               mpc_cpu->apicid         = i;
+               mpc_cpu->apicver        = KVM_APIC_VERSION;
+               mpc_cpu->cpuflag        = gen_cpu_flag(i, ncpus);
+               mpc_cpu->cpufeature     = 0x600; /* some default value */
+               mpc_cpu->featureflag    = 0x201; /* some default value */
+               mpc_cpu++;
+       }
+
+       last_addr = (void *)mpc_cpu;
+       nentries += ncpus;
+
+       /*
+        * PCI buses.
+        * FIXME: Some callback here to obtain real number
+        * of PCI buses present in system.
+        */
+       mpc_bus         = last_addr;
+       mpc_bus->type   = MP_BUS;
+       mpc_bus->busid  = pcibusid;
+       MPTABLE_STRNCPY(mpc_bus->bustype, MPTABLE_PCIBUSTYPE);
+
+       last_addr = (void *)&mpc_bus[1];
+       nentries++;
+
+       /*
+        * ISA bus.
+        * FIXME: Same issue as for PCI bus.
+        */
+       mpc_bus         = last_addr;
+       mpc_bus->type   = MP_BUS;
+       mpc_bus->busid  = isabusid;
+       MPTABLE_STRNCPY(mpc_bus->bustype, MPTABLE_ISABUSTYPE);
+
+       last_addr = (void *)&mpc_bus[1];
+       nentries++;
+
+       /*
+        * IO-APIC chip.
+        */
+       ioapicid                = ncpus + 1;
+       mpc_ioapic              = last_addr;
+       mpc_ioapic->type        = MP_IOAPIC;
+       mpc_ioapic->apicid      = ioapicid;
+       mpc_ioapic->apicver     = KVM_APIC_VERSION;
+       mpc_ioapic->flags       = MPC_APIC_USABLE;
+       mpc_ioapic->apicaddr    = IOAPIC_ADDR(0);
+
+       last_addr = (void *)&mpc_ioapic[1];
+       nentries++;
+
+       /*
+        * IRQ sources.
+        *
+        * FIXME: Same issue as with buses. We definitely
+        * need kind of collector routine which enumerate
+        * resources used first and pass them here.
+        * At moment we know we have only virtio block device
+        * and virtio console but this is g00berfish.
+        *
+        * Also note we use PCI irqs here, no for ISA bus yet.
+        */
+
+       for (pci_tree = irq__get_pci_tree(); pci_tree; pci_tree = rb_next(pci_tree)) {
+               struct pci_dev *dev = rb_entry(pci_tree, struct pci_dev, node);
+               struct irq_line *irq_line;
+
+               list_for_each_entry(irq_line, &dev->lines, node) {
+                       unsigned char srcbusirq;
+
+                       srcbusirq = (dev->id << 2) | (dev->pin - 1);
+
+                       mpc_intsrc = last_addr;
+
+                       mptable_add_irq_src(mpc_intsrc, pcibusid, srcbusirq, ioapicid, irq_line->line);
+                       last_addr = (void *)&mpc_intsrc[1];
+                       nentries++;
+               }
+       }
+
+       /*
+        * Local IRQs assignment (LINT0, LINT1)
+        */
+       mpc_intsrc              = last_addr;
+       mpc_intsrc->type        = MP_LINTSRC;
+       mpc_intsrc->irqtype     = mp_ExtINT;
+       mpc_intsrc->irqtype     = mp_INT;
+       mpc_intsrc->irqflag     = MP_IRQDIR_DEFAULT;
+       mpc_intsrc->srcbus      = isabusid;
+       mpc_intsrc->srcbusirq   = 0;
+       mpc_intsrc->dstapic     = 0; /* FIXME: BSP apic */
+       mpc_intsrc->dstirq      = 0; /* LINT0 */
+
+       last_addr = (void *)&mpc_intsrc[1];
+       nentries++;
+
+       mpc_intsrc              = last_addr;
+       mpc_intsrc->type        = MP_LINTSRC;
+       mpc_intsrc->irqtype     = mp_NMI;
+       mpc_intsrc->irqflag     = MP_IRQDIR_DEFAULT;
+       mpc_intsrc->srcbus      = isabusid;
+       mpc_intsrc->srcbusirq   = 0;
+       mpc_intsrc->dstapic     = 0; /* FIXME: BSP apic */
+       mpc_intsrc->dstirq      = 1; /* LINT1 */
+
+       last_addr = (void *)&mpc_intsrc[1];
+       nentries++;
+
+       /*
+        * Floating MP table finally.
+        */
+       real_mpf_intel  = ALIGN((unsigned long)last_addr - (unsigned long)mpc_table, 16);
+       mpf_intel       = (void *)((unsigned long)mpc_table + real_mpf_intel);
+
+       MPTABLE_STRNCPY(mpf_intel->signature, MPTABLE_SIG_FLOATING);
+       mpf_intel->length       = 1;
+       mpf_intel->specification= 4;
+       mpf_intel->physptr      = (unsigned int)real_mpc_table;
+       mpf_intel->checksum     = -mpf_checksum((unsigned char *)mpf_intel, sizeof(*mpf_intel));
+
+       /*
+        * No last_addr inclrement here please, we need last
+        * active position here to compute table size.
+        */
+
+       /*
+        * Don't forget to update header in fixed table.
+       */
+       mpc_table->oemcount     = nentries;
+       mpc_table->length       = last_addr - (void *)mpc_table;
+       mpc_table->checksum     = -mpf_checksum((unsigned char *)mpc_table, mpc_table->length);
+
+
+       /*
+        * We will copy the whole table, no need to separate
+        * floating structure and table itkvm.
+        */
+       size = (unsigned long)mpf_intel + sizeof(*mpf_intel) - (unsigned long)mpc_table;
+
+       /*
+        * The finial check -- never get out of system bios
+        * area. Lets also check for allocated memory overrun,
+        * in real it's late but still usefull.
+        */
+
+       if (size > (unsigned long)(MB_BIOS_END - bios_rom_size) ||
+           size > MPTABLE_MAX_SIZE) {
+               free(mpc_table);
+               pr_err("MP table is too big");
+
+               return -E2BIG;
+       }
+
+       /*
+        * OK, it is time to move it to guest memory.
+        */
+       memcpy(guest_flat_to_host(kvm, real_mpc_table), mpc_table, size);
+
+       free(mpc_table);
+
+       return 0;
+}
+firmware_init(mptable__init);
+
+int mptable__exit(struct kvm *kvm)
+{
+       return 0;
+}
+firmware_exit(mptable__exit);
index fd2f9221b24120e25d32c2c8d8b4849d8d24569a..07a03452c227e3804a04661f26e7ca8cc73bec35 100644 (file)
@@ -179,29 +179,6 @@ static struct termios orig_term;
 #define wmb() __asm__ __volatile__("" : : : "memory")
 #define mb() __asm__ __volatile__("" : : : "memory")
 
-/*
- * Convert an iovec element to the given type.
- *
- * This is a fairly ugly trick: we need to know the size of the type and
- * alignment requirement to check the pointer is kosher.  It's also nice to
- * have the name of the type in case we report failure.
- *
- * Typing those three things all the time is cumbersome and error prone, so we
- * have a macro which sets them all up and passes to the real function.
- */
-#define convert(iov, type) \
-       ((type *)_convert((iov), sizeof(type), __alignof__(type), #type))
-
-static void *_convert(struct iovec *iov, size_t size, size_t align,
-                     const char *name)
-{
-       if (iov->iov_len != size)
-               errx(1, "Bad iovec size %zu for %s", iov->iov_len, name);
-       if ((unsigned long)iov->iov_base % align != 0)
-               errx(1, "Bad alignment %p for %s", iov->iov_base, name);
-       return iov->iov_base;
-}
-
 /* Wrapper for the last available index.  Makes it easier to change. */
 #define lg_last_avail(vq)      ((vq)->last_avail_idx)
 
@@ -228,7 +205,8 @@ static bool iov_empty(const struct iovec iov[], unsigned int num_iov)
 }
 
 /* Take len bytes from the front of this iovec. */
-static void iov_consume(struct iovec iov[], unsigned num_iov, unsigned len)
+static void iov_consume(struct iovec iov[], unsigned num_iov,
+                       void *dest, unsigned len)
 {
        unsigned int i;
 
@@ -236,11 +214,16 @@ static void iov_consume(struct iovec iov[], unsigned num_iov, unsigned len)
                unsigned int used;
 
                used = iov[i].iov_len < len ? iov[i].iov_len : len;
+               if (dest) {
+                       memcpy(dest, iov[i].iov_base, used);
+                       dest += used;
+               }
                iov[i].iov_base += used;
                iov[i].iov_len -= used;
                len -= used;
        }
-       assert(len == 0);
+       if (len != 0)
+               errx(1, "iovec too short!");
 }
 
 /* The device virtqueue descriptors are followed by feature bitmasks. */
@@ -864,7 +847,7 @@ static void console_output(struct virtqueue *vq)
                        warn("Write to stdout gave %i (%d)", len, errno);
                        break;
                }
-               iov_consume(iov, out, len);
+               iov_consume(iov, out, NULL, len);
        }
 
        /*
@@ -1591,9 +1574,9 @@ static void blk_request(struct virtqueue *vq)
 {
        struct vblk_info *vblk = vq->dev->priv;
        unsigned int head, out_num, in_num, wlen;
-       int ret;
+       int ret, i;
        u8 *in;
-       struct virtio_blk_outhdr *out;
+       struct virtio_blk_outhdr out;
        struct iovec iov[vq->vring.num];
        off64_t off;
 
@@ -1603,32 +1586,36 @@ static void blk_request(struct virtqueue *vq)
         */
        head = wait_for_vq_desc(vq, iov, &out_num, &in_num);
 
-       /*
-        * Every block request should contain at least one output buffer
-        * (detailing the location on disk and the type of request) and one
-        * input buffer (to hold the result).
-        */
-       if (out_num == 0 || in_num == 0)
-               errx(1, "Bad virtblk cmd %u out=%u in=%u",
-                    head, out_num, in_num);
+       /* Copy the output header from the front of the iov (adjusts iov) */
+       iov_consume(iov, out_num, &out, sizeof(out));
+
+       /* Find and trim end of iov input array, for our status byte. */
+       in = NULL;
+       for (i = out_num + in_num - 1; i >= out_num; i--) {
+               if (iov[i].iov_len > 0) {
+                       in = iov[i].iov_base + iov[i].iov_len - 1;
+                       iov[i].iov_len--;
+                       break;
+               }
+       }
+       if (!in)
+               errx(1, "Bad virtblk cmd with no room for status");
 
-       out = convert(&iov[0], struct virtio_blk_outhdr);
-       in = convert(&iov[out_num+in_num-1], u8);
        /*
         * For historical reasons, block operations are expressed in 512 byte
         * "sectors".
         */
-       off = out->sector * 512;
+       off = out.sector * 512;
 
        /*
         * In general the virtio block driver is allowed to try SCSI commands.
         * It'd be nice if we supported eject, for example, but we don't.
         */
-       if (out->type & VIRTIO_BLK_T_SCSI_CMD) {
+       if (out.type & VIRTIO_BLK_T_SCSI_CMD) {
                fprintf(stderr, "Scsi commands unsupported\n");
                *in = VIRTIO_BLK_S_UNSUPP;
                wlen = sizeof(*in);
-       } else if (out->type & VIRTIO_BLK_T_OUT) {
+       } else if (out.type & VIRTIO_BLK_T_OUT) {
                /*
                 * Write
                 *
@@ -1636,10 +1623,10 @@ static void blk_request(struct virtqueue *vq)
                 * if they try to write past end.
                 */
                if (lseek64(vblk->fd, off, SEEK_SET) != off)
-                       err(1, "Bad seek to sector %llu", out->sector);
+                       err(1, "Bad seek to sector %llu", out.sector);
 
-               ret = writev(vblk->fd, iov+1, out_num-1);
-               verbose("WRITE to sector %llu: %i\n", out->sector, ret);
+               ret = writev(vblk->fd, iov, out_num);
+               verbose("WRITE to sector %llu: %i\n", out.sector, ret);
 
                /*
                 * Grr... Now we know how long the descriptor they sent was, we
@@ -1655,7 +1642,7 @@ static void blk_request(struct virtqueue *vq)
 
                wlen = sizeof(*in);
                *in = (ret >= 0 ? VIRTIO_BLK_S_OK : VIRTIO_BLK_S_IOERR);
-       } else if (out->type & VIRTIO_BLK_T_FLUSH) {
+       } else if (out.type & VIRTIO_BLK_T_FLUSH) {
                /* Flush */
                ret = fdatasync(vblk->fd);
                verbose("FLUSH fdatasync: %i\n", ret);
@@ -1669,10 +1656,9 @@ static void blk_request(struct virtqueue *vq)
                 * if they try to read past end.
                 */
                if (lseek64(vblk->fd, off, SEEK_SET) != off)
-                       err(1, "Bad seek to sector %llu", out->sector);
+                       err(1, "Bad seek to sector %llu", out.sector);
 
-               ret = readv(vblk->fd, iov+1, in_num-1);
-               verbose("READ from sector %llu: %i\n", out->sector, ret);
+               ret = readv(vblk->fd, iov + out_num, in_num);
                if (ret >= 0) {
                        wlen = sizeof(*in) + ret;
                        *in = VIRTIO_BLK_S_OK;
@@ -1758,7 +1744,7 @@ static void rng_input(struct virtqueue *vq)
                len = readv(rng_info->rfd, iov, in_num);
                if (len <= 0)
                        err(1, "Read from /dev/random gave %i", len);
-               iov_consume(iov, in_num, len);
+               iov_consume(iov, in_num, NULL, len);
                totlen += len;
        }
 
index 47264b4652b990f3d237531607060f94036ad7cf..f2989c525e48a6865729cff8962fca28d39532fc 100644 (file)
@@ -2602,6 +2602,9 @@ find_func_handler(struct pevent *pevent, char *func_name)
 {
        struct pevent_function_handler *func;
 
+       if (!pevent)
+               return NULL;
+
        for (func = pevent->func_handlers; func; func = func->next) {
                if (strcmp(func->name, func_name) == 0)
                        break;
@@ -4938,6 +4941,9 @@ enum pevent_errno __pevent_parse_format(struct event_format **eventp,
                goto event_alloc_failed;
        }
 
+       /* Add pevent to event so that it can be referenced */
+       event->pevent = pevent;
+
        ret = event_read_format(event);
        if (ret < 0) {
                ret = PEVENT_ERRNO__READ_FORMAT_FAILED;
@@ -5041,9 +5047,6 @@ enum pevent_errno pevent_parse_event(struct pevent *pevent, const char *buf,
        if (event == NULL)
                return ret;
 
-       /* Add pevent to event so that it can be referenced */
-       event->pevent = pevent;
-
        if (add_event(pevent, event)) {
                ret = PEVENT_ERRNO__MEM_ALLOC_FAILED;
                goto event_add_failed;
index ad17855528f9adaa82cb37b0e6a8fe7ede2ed755..5ea4326ad11f5d16901d49ff68ddc36648671bf4 100644 (file)
@@ -209,7 +209,16 @@ static void free_arg(struct filter_arg *arg)
        switch (arg->type) {
        case FILTER_ARG_NONE:
        case FILTER_ARG_BOOLEAN:
+               break;
+
        case FILTER_ARG_NUM:
+               free_arg(arg->num.left);
+               free_arg(arg->num.right);
+               break;
+
+       case FILTER_ARG_EXP:
+               free_arg(arg->exp.left);
+               free_arg(arg->exp.right);
                break;
 
        case FILTER_ARG_STR:
@@ -218,6 +227,12 @@ static void free_arg(struct filter_arg *arg)
                free(arg->str.buffer);
                break;
 
+       case FILTER_ARG_VALUE:
+               if (arg->value.type == FILTER_STRING ||
+                   arg->value.type == FILTER_CHAR)
+                       free(arg->value.str);
+               break;
+
        case FILTER_ARG_OP:
                free_arg(arg->op.left);
                free_arg(arg->op.right);
diff --git a/tools/perf/Documentation/android.txt b/tools/perf/Documentation/android.txt
new file mode 100644 (file)
index 0000000..a39dbbb
--- /dev/null
@@ -0,0 +1,75 @@
+How to compile perf for Android
+=========================================
+
+I. Set the Android NDK environment
+------------------------------------------------
+
+(a). Use the Android NDK
+------------------------------------------------
+1. You need to download and install the Android Native Development Kit (NDK).
+Set the NDK variable to point to the path where you installed the NDK:
+  export NDK=/path/to/android-ndk
+
+2. Set cross-compiling environment variables for NDK toolchain and sysroot.
+For arm:
+  export NDK_TOOLCHAIN=${NDK}/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86/bin/arm-linux-androideabi-
+  export NDK_SYSROOT=${NDK}/platforms/android-9/arch-arm
+For x86:
+  export NDK_TOOLCHAIN=${NDK}/toolchains/x86-4.6/prebuilt/linux-x86/bin/i686-linux-android-
+  export NDK_SYSROOT=${NDK}/platforms/android-9/arch-x86
+
+This method is not working for Android NDK versions up to Revision 8b.
+perf uses some bionic enhancements that are not included in these NDK versions.
+You can use method (b) described below instead.
+
+(b). Use the Android source tree
+-----------------------------------------------
+1. Download the master branch of the Android source tree.
+Set the environment for the target you want using:
+  source build/envsetup.sh
+  lunch
+
+2. Build your own NDK sysroot to contain latest bionic changes and set the
+NDK sysroot environment variable.
+  cd ${ANDROID_BUILD_TOP}/ndk
+For arm:
+  ./build/tools/build-ndk-sysroot.sh --abi=arm
+  export NDK_SYSROOT=${ANDROID_BUILD_TOP}/ndk/build/platforms/android-3/arch-arm
+For x86:
+  ./build/tools/build-ndk-sysroot.sh --abi=x86
+  export NDK_SYSROOT=${ANDROID_BUILD_TOP}/ndk/build/platforms/android-3/arch-x86
+
+3. Set the NDK toolchain environment variable.
+For arm:
+  export NDK_TOOLCHAIN=${ANDROID_TOOLCHAIN}/arm-linux-androideabi-
+For x86:
+  export NDK_TOOLCHAIN=${ANDROID_TOOLCHAIN}/i686-linux-android-
+
+II. Compile perf for Android
+------------------------------------------------
+You need to run make with the NDK toolchain and sysroot defined above:
+  make CROSS_COMPILE=${NDK_TOOLCHAIN} CFLAGS="--sysroot=${NDK_SYSROOT}"
+
+III. Install perf
+-----------------------------------------------
+You need to connect to your Android device/emulator using adb.
+Install perf using:
+  adb push perf /data/perf
+
+If you also want to use perf-archive you need busybox tools for Android.
+For installing perf-archive, you first need to replace #!/bin/bash with #!/system/bin/sh:
+  sed 's/#!\/bin\/bash/#!\/system\/bin\/sh/g' perf-archive >> /tmp/perf-archive
+  chmod +x /tmp/perf-archive
+  adb push /tmp/perf-archive /data/perf-archive
+
+IV. Environment settings for running perf
+------------------------------------------------
+Some perf features need environment variables to run properly.
+You need to set these before running perf on the target:
+  adb shell
+  # PERF_PAGER=cat
+
+IV. Run perf
+------------------------------------------------
+Run perf on your device/emulator to which you previously connected using adb:
+  # ./data/perf
index ab7f667de1b158d290443397696166a573bbb7f4..194f37d635dfa3e543f21a37807f6be61e9e91bc 100644 (file)
@@ -72,6 +72,66 @@ OPTIONS
 --symfs=<directory>::
         Look for files with symbols relative to this directory.
 
+-b::
+--baseline-only::
+        Show only items with match in baseline.
+
+-c::
+--compute::
+        Differential computation selection - delta,ratio,wdiff (default is delta).
+        If '+' is specified as a first character, the output is sorted based
+        on the computation results.
+        See COMPARISON METHODS section for more info.
+
+-p::
+--period::
+        Show period values for both compared hist entries.
+
+-F::
+--formula::
+        Show formula for given computation.
+
+COMPARISON METHODS
+------------------
+delta
+~~~~~
+If specified the 'Delta' column is displayed with value 'd' computed as:
+
+  d = A->period_percent - B->period_percent
+
+with:
+  - A/B being matching hist entry from first/second file specified
+    (or perf.data/perf.data.old) respectively.
+
+  - period_percent being the % of the hist entry period value within
+    single data file
+
+ratio
+~~~~~
+If specified the 'Ratio' column is displayed with value 'r' computed as:
+
+  r = A->period / B->period
+
+with:
+  - A/B being matching hist entry from first/second file specified
+    (or perf.data/perf.data.old) respectively.
+
+  - period being the hist entry period value
+
+wdiff
+~~~~~
+If specified the 'Weighted diff' column is displayed with value 'd' computed as:
+
+   d = B->period * WEIGHT-A - A->period * WEIGHT-B
+
+  - A/B being matching hist entry from first/second file specified
+    (or perf.data/perf.data.old) respectively.
+
+  - period being the hist entry period value
+
+  - WEIGHT-A/WEIGHT-B being user suplied weights in the the '-c' option
+    behind ':' separator like '-c wdiff:1,2'.
+
 SEE ALSO
 --------
 linkperf:perf-record[1]
index f7c968ad51780760fb5630e35b5091a8b0699826..f530502630a411f81fa466228a1359abe9e9648f 100644 (file)
@@ -155,15 +155,15 @@ SPARSE_FLAGS = -D__BIG_ENDIAN__ -D__powerpc__
 
 -include config/feature-tests.mak
 
-ifeq ($(call try-cc,$(SOURCE_HELLO),-Werror -fstack-protector-all),y)
+ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -Werror -fstack-protector-all),y)
        CFLAGS := $(CFLAGS) -fstack-protector-all
 endif
 
-ifeq ($(call try-cc,$(SOURCE_HELLO),-Werror -Wstack-protector),y)
+ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -Werror -Wstack-protector),y)
        CFLAGS := $(CFLAGS) -Wstack-protector
 endif
 
-ifeq ($(call try-cc,$(SOURCE_HELLO),-Werror -Wvolatile-register-var),y)
+ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -Werror -Wvolatile-register-var),y)
        CFLAGS := $(CFLAGS) -Wvolatile-register-var
 endif
 
@@ -172,6 +172,13 @@ endif
 BASIC_CFLAGS = -Iutil/include -Iarch/$(ARCH)/include -I$(OUTPUT)util -I$(TRACE_EVENT_DIR) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
 BASIC_LDFLAGS =
 
+ifeq ($(call try-cc,$(SOURCE_BIONIC),$(CFLAGS)),y)
+       BIONIC := 1
+       EXTLIBS := $(filter-out -lrt,$(EXTLIBS))
+       EXTLIBS := $(filter-out -lpthread,$(EXTLIBS))
+       BASIC_CFLAGS += -I.
+endif
+
 # Guard against environment variables
 BUILTIN_OBJS =
 LIB_H =
@@ -184,9 +191,22 @@ SCRIPT_SH += perf-archive.sh
 grep-libs = $(filter -l%,$(1))
 strip-libs = $(filter-out -l%,$(1))
 
+TRACE_EVENT_DIR = ../lib/traceevent/
+
+ifneq ($(OUTPUT),)
+       TE_PATH=$(OUTPUT)
+else
+       TE_PATH=$(TRACE_EVENT_DIR)
+endif
+
+LIBTRACEEVENT = $(TE_PATH)libtraceevent.a
+TE_LIB := -L$(TE_PATH) -ltraceevent
+
 PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources)
 PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py
 
+export LIBTRACEEVENT
+
 $(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS)
        $(QUIET_GEN)CFLAGS='$(BASIC_CFLAGS)' $(PYTHON_WORD) util/setup.py \
          --quiet build_ext; \
@@ -198,17 +218,6 @@ $(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS)
 
 SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH))
 
-TRACE_EVENT_DIR = ../lib/traceevent/
-
-ifneq ($(OUTPUT),)
-       TE_PATH=$(OUTPUT)
-else
-       TE_PATH=$(TRACE_EVENT_DIR)
-endif
-
-LIBTRACEEVENT = $(TE_PATH)libtraceevent.a
-TE_LIB := -L$(TE_PATH) -ltraceevent
-
 #
 # Single 'perf' binary right now:
 #
@@ -301,6 +310,7 @@ LIB_H += util/evlist.h
 LIB_H += util/exec_cmd.h
 LIB_H += util/types.h
 LIB_H += util/levenshtein.h
+LIB_H += util/machine.h
 LIB_H += util/map.h
 LIB_H += util/parse-options.h
 LIB_H += util/parse-events.h
@@ -384,6 +394,7 @@ LIB_OBJS += $(OUTPUT)util/header.o
 LIB_OBJS += $(OUTPUT)util/callchain.o
 LIB_OBJS += $(OUTPUT)util/values.o
 LIB_OBJS += $(OUTPUT)util/debug.o
+LIB_OBJS += $(OUTPUT)util/machine.o
 LIB_OBJS += $(OUTPUT)util/map.o
 LIB_OBJS += $(OUTPUT)util/pstack.o
 LIB_OBJS += $(OUTPUT)util/session.o
@@ -468,12 +479,18 @@ else
 FLAGS_LIBELF=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS)
 ifneq ($(call try-cc,$(SOURCE_LIBELF),$(FLAGS_LIBELF)),y)
        FLAGS_GLIBC=$(ALL_CFLAGS) $(ALL_LDFLAGS)
-       ifneq ($(call try-cc,$(SOURCE_GLIBC),$(FLAGS_GLIBC)),y)
-               msg := $(error No gnu/libc-version.h found, please install glibc-dev[el]/glibc-static);
-       else
+       ifeq ($(call try-cc,$(SOURCE_GLIBC),$(FLAGS_GLIBC)),y)
+               LIBC_SUPPORT := 1
+       endif
+       ifeq ($(BIONIC),1)
+               LIBC_SUPPORT := 1
+       endif
+       ifeq ($(LIBC_SUPPORT),1)
                NO_LIBELF := 1
                NO_DWARF := 1
                NO_DEMANGLE := 1
+       else
+               msg := $(error No gnu/libc-version.h found, please install glibc-dev[el]/glibc-static);
        endif
 else
        FLAGS_DWARF=$(ALL_CFLAGS) -ldw -lelf $(ALL_LDFLAGS) $(EXTLIBS)
@@ -752,6 +769,12 @@ ifndef NO_STRLCPY
        endif
 endif
 
+ifndef NO_ON_EXIT
+       ifeq ($(call try-cc,$(SOURCE_ON_EXIT),),y)
+               BASIC_CFLAGS += -DHAVE_ON_EXIT
+       endif
+endif
+
 ifndef NO_BACKTRACE
        ifeq ($(call try-cc,$(SOURCE_BACKTRACE),),y)
                BASIC_CFLAGS += -DBACKTRACE_SUPPORT
index 9ea38540b873b5ca02567aeb9114313f96fa6764..690fa9a54657bdfc0f26fe7f6578a08b7f94459e 100644 (file)
@@ -246,7 +246,8 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
                        .sample = process_sample_event,
                        .mmap   = perf_event__process_mmap,
                        .comm   = perf_event__process_comm,
-                       .fork   = perf_event__process_task,
+                       .exit   = perf_event__process_exit,
+                       .fork   = perf_event__process_fork,
                        .ordered_samples = true,
                        .ordering_requires_timestamps = true,
                },
index a0b531c14b974f24cbbd2727a879c59c69415e06..380683de1df38c3f097b3184d6cc62024c3a7170 100644 (file)
@@ -24,6 +24,228 @@ static char const *input_old = "perf.data.old",
 static char      diff__default_sort_order[] = "dso,symbol";
 static bool  force;
 static bool show_displacement;
+static bool show_period;
+static bool show_formula;
+static bool show_baseline_only;
+static bool sort_compute;
+
+static s64 compute_wdiff_w1;
+static s64 compute_wdiff_w2;
+
+enum {
+       COMPUTE_DELTA,
+       COMPUTE_RATIO,
+       COMPUTE_WEIGHTED_DIFF,
+       COMPUTE_MAX,
+};
+
+const char *compute_names[COMPUTE_MAX] = {
+       [COMPUTE_DELTA] = "delta",
+       [COMPUTE_RATIO] = "ratio",
+       [COMPUTE_WEIGHTED_DIFF] = "wdiff",
+};
+
+static int compute;
+
+static int setup_compute_opt_wdiff(char *opt)
+{
+       char *w1_str = opt;
+       char *w2_str;
+
+       int ret = -EINVAL;
+
+       if (!opt)
+               goto out;
+
+       w2_str = strchr(opt, ',');
+       if (!w2_str)
+               goto out;
+
+       *w2_str++ = 0x0;
+       if (!*w2_str)
+               goto out;
+
+       compute_wdiff_w1 = strtol(w1_str, NULL, 10);
+       compute_wdiff_w2 = strtol(w2_str, NULL, 10);
+
+       if (!compute_wdiff_w1 || !compute_wdiff_w2)
+               goto out;
+
+       pr_debug("compute wdiff w1(%" PRId64 ") w2(%" PRId64 ")\n",
+                 compute_wdiff_w1, compute_wdiff_w2);
+
+       ret = 0;
+
+ out:
+       if (ret)
+               pr_err("Failed: wrong weight data, use 'wdiff:w1,w2'\n");
+
+       return ret;
+}
+
+static int setup_compute_opt(char *opt)
+{
+       if (compute == COMPUTE_WEIGHTED_DIFF)
+               return setup_compute_opt_wdiff(opt);
+
+       if (opt) {
+               pr_err("Failed: extra option specified '%s'", opt);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int setup_compute(const struct option *opt, const char *str,
+                        int unset __maybe_unused)
+{
+       int *cp = (int *) opt->value;
+       char *cstr = (char *) str;
+       char buf[50];
+       unsigned i;
+       char *option;
+
+       if (!str) {
+               *cp = COMPUTE_DELTA;
+               return 0;
+       }
+
+       if (*str == '+') {
+               sort_compute = true;
+               cstr = (char *) ++str;
+               if (!*str)
+                       return 0;
+       }
+
+       option = strchr(str, ':');
+       if (option) {
+               unsigned len = option++ - str;
+
+               /*
+                * The str data are not writeable, so we need
+                * to use another buffer.
+                */
+
+               /* No option value is longer. */
+               if (len >= sizeof(buf))
+                       return -EINVAL;
+
+               strncpy(buf, str, len);
+               buf[len] = 0x0;
+               cstr = buf;
+       }
+
+       for (i = 0; i < COMPUTE_MAX; i++)
+               if (!strcmp(cstr, compute_names[i])) {
+                       *cp = i;
+                       return setup_compute_opt(option);
+               }
+
+       pr_err("Failed: '%s' is not computation method "
+              "(use 'delta','ratio' or 'wdiff')\n", str);
+       return -EINVAL;
+}
+
+static double get_period_percent(struct hist_entry *he, u64 period)
+{
+       u64 total = he->hists->stats.total_period;
+       return (period * 100.0) / total;
+}
+
+double perf_diff__compute_delta(struct hist_entry *he)
+{
+       struct hist_entry *pair = he->pair;
+       double new_percent = get_period_percent(he, he->stat.period);
+       double old_percent = pair ? get_period_percent(pair, pair->stat.period) : 0.0;
+
+       he->diff.period_ratio_delta = new_percent - old_percent;
+       he->diff.computed = true;
+       return he->diff.period_ratio_delta;
+}
+
+double perf_diff__compute_ratio(struct hist_entry *he)
+{
+       struct hist_entry *pair = he->pair;
+       double new_period = he->stat.period;
+       double old_period = pair ? pair->stat.period : 0;
+
+       he->diff.computed = true;
+       he->diff.period_ratio = pair ? (new_period / old_period) : 0;
+       return he->diff.period_ratio;
+}
+
+s64 perf_diff__compute_wdiff(struct hist_entry *he)
+{
+       struct hist_entry *pair = he->pair;
+       u64 new_period = he->stat.period;
+       u64 old_period = pair ? pair->stat.period : 0;
+
+       he->diff.computed = true;
+
+       if (!pair)
+               he->diff.wdiff = 0;
+       else
+               he->diff.wdiff = new_period * compute_wdiff_w2 -
+                                old_period * compute_wdiff_w1;
+
+       return he->diff.wdiff;
+}
+
+static int formula_delta(struct hist_entry *he, char *buf, size_t size)
+{
+       struct hist_entry *pair = he->pair;
+
+       if (!pair)
+               return -1;
+
+       return scnprintf(buf, size,
+                        "(%" PRIu64 " * 100 / %" PRIu64 ") - "
+                        "(%" PRIu64 " * 100 / %" PRIu64 ")",
+                         he->stat.period, he->hists->stats.total_period,
+                         pair->stat.period, pair->hists->stats.total_period);
+}
+
+static int formula_ratio(struct hist_entry *he, char *buf, size_t size)
+{
+       struct hist_entry *pair = he->pair;
+       double new_period = he->stat.period;
+       double old_period = pair ? pair->stat.period : 0;
+
+       if (!pair)
+               return -1;
+
+       return scnprintf(buf, size, "%.0F / %.0F", new_period, old_period);
+}
+
+static int formula_wdiff(struct hist_entry *he, char *buf, size_t size)
+{
+       struct hist_entry *pair = he->pair;
+       u64 new_period = he->stat.period;
+       u64 old_period = pair ? pair->stat.period : 0;
+
+       if (!pair)
+               return -1;
+
+       return scnprintf(buf, size,
+                 "(%" PRIu64 " * " "%" PRId64 ") - (%" PRIu64 " * " "%" PRId64 ")",
+                 new_period, compute_wdiff_w2, old_period, compute_wdiff_w1);
+}
+
+int perf_diff__formula(char *buf, size_t size, struct hist_entry *he)
+{
+       switch (compute) {
+       case COMPUTE_DELTA:
+               return formula_delta(he, buf, size);
+       case COMPUTE_RATIO:
+               return formula_ratio(he, buf, size);
+       case COMPUTE_WEIGHTED_DIFF:
+               return formula_wdiff(he, buf, size);
+       default:
+               BUG_ON(1);
+       }
+
+       return -1;
+}
 
 static int hists__add_entry(struct hists *self,
                            struct addr_location *al, u64 period)
@@ -47,7 +269,7 @@ static int diff__process_sample_event(struct perf_tool *tool __maybe_unused,
                return -1;
        }
 
-       if (al.filtered || al.sym == NULL)
+       if (al.filtered)
                return 0;
 
        if (hists__add_entry(&evsel->hists, &al, sample->period)) {
@@ -63,8 +285,8 @@ static struct perf_tool tool = {
        .sample = diff__process_sample_event,
        .mmap   = perf_event__process_mmap,
        .comm   = perf_event__process_comm,
-       .exit   = perf_event__process_task,
-       .fork   = perf_event__process_task,
+       .exit   = perf_event__process_exit,
+       .fork   = perf_event__process_fork,
        .lost   = perf_event__process_lost,
        .ordered_samples = true,
        .ordering_requires_timestamps = true,
@@ -172,6 +394,142 @@ static void perf_evlist__resort_hists(struct perf_evlist *evlist, bool name)
        }
 }
 
+static void hists__baseline_only(struct hists *hists)
+{
+       struct rb_node *next = rb_first(&hists->entries);
+
+       while (next != NULL) {
+               struct hist_entry *he = rb_entry(next, struct hist_entry, rb_node);
+
+               next = rb_next(&he->rb_node);
+               if (!he->pair) {
+                       rb_erase(&he->rb_node, &hists->entries);
+                       hist_entry__free(he);
+               }
+       }
+}
+
+static void hists__precompute(struct hists *hists)
+{
+       struct rb_node *next = rb_first(&hists->entries);
+
+       while (next != NULL) {
+               struct hist_entry *he = rb_entry(next, struct hist_entry, rb_node);
+
+               next = rb_next(&he->rb_node);
+
+               switch (compute) {
+               case COMPUTE_DELTA:
+                       perf_diff__compute_delta(he);
+                       break;
+               case COMPUTE_RATIO:
+                       perf_diff__compute_ratio(he);
+                       break;
+               case COMPUTE_WEIGHTED_DIFF:
+                       perf_diff__compute_wdiff(he);
+                       break;
+               default:
+                       BUG_ON(1);
+               }
+       }
+}
+
+static int64_t cmp_doubles(double l, double r)
+{
+       if (l > r)
+               return -1;
+       else if (l < r)
+               return 1;
+       else
+               return 0;
+}
+
+static int64_t
+hist_entry__cmp_compute(struct hist_entry *left, struct hist_entry *right,
+                       int c)
+{
+       switch (c) {
+       case COMPUTE_DELTA:
+       {
+               double l = left->diff.period_ratio_delta;
+               double r = right->diff.period_ratio_delta;
+
+               return cmp_doubles(l, r);
+       }
+       case COMPUTE_RATIO:
+       {
+               double l = left->diff.period_ratio;
+               double r = right->diff.period_ratio;
+
+               return cmp_doubles(l, r);
+       }
+       case COMPUTE_WEIGHTED_DIFF:
+       {
+               s64 l = left->diff.wdiff;
+               s64 r = right->diff.wdiff;
+
+               return r - l;
+       }
+       default:
+               BUG_ON(1);
+       }
+
+       return 0;
+}
+
+static void insert_hist_entry_by_compute(struct rb_root *root,
+                                        struct hist_entry *he,
+                                        int c)
+{
+       struct rb_node **p = &root->rb_node;
+       struct rb_node *parent = NULL;
+       struct hist_entry *iter;
+
+       while (*p != NULL) {
+               parent = *p;
+               iter = rb_entry(parent, struct hist_entry, rb_node);
+               if (hist_entry__cmp_compute(he, iter, c) < 0)
+                       p = &(*p)->rb_left;
+               else
+                       p = &(*p)->rb_right;
+       }
+
+       rb_link_node(&he->rb_node, parent, p);
+       rb_insert_color(&he->rb_node, root);
+}
+
+static void hists__compute_resort(struct hists *hists)
+{
+       struct rb_root tmp = RB_ROOT;
+       struct rb_node *next = rb_first(&hists->entries);
+
+       while (next != NULL) {
+               struct hist_entry *he = rb_entry(next, struct hist_entry, rb_node);
+
+               next = rb_next(&he->rb_node);
+
+               rb_erase(&he->rb_node, &hists->entries);
+               insert_hist_entry_by_compute(&tmp, he, compute);
+       }
+
+       hists->entries = tmp;
+}
+
+static void hists__process(struct hists *old, struct hists *new)
+{
+       hists__match(old, new);
+
+       if (show_baseline_only)
+               hists__baseline_only(new);
+
+       if (sort_compute) {
+               hists__precompute(new);
+               hists__compute_resort(new);
+       }
+
+       hists__fprintf(new, true, 0, 0, stdout);
+}
+
 static int __cmd_diff(void)
 {
        int ret, i;
@@ -213,8 +571,7 @@ static int __cmd_diff(void)
 
                first = false;
 
-               hists__match(&evsel_old->hists, &evsel->hists);
-               hists__fprintf(&evsel->hists, true, 0, 0, stdout);
+               hists__process(&evsel_old->hists, &evsel->hists);
        }
 
 out_delete:
@@ -235,6 +592,16 @@ static const struct option options[] = {
                    "be more verbose (show symbol address, etc)"),
        OPT_BOOLEAN('M', "displacement", &show_displacement,
                    "Show position displacement relative to baseline"),
+       OPT_BOOLEAN('b', "baseline-only", &show_baseline_only,
+                   "Show only items with match in baseline"),
+       OPT_CALLBACK('c', "compute", &compute,
+                    "delta,ratio,wdiff:w1,w2 (default delta)",
+                    "Entries differential computation selection",
+                    setup_compute),
+       OPT_BOOLEAN('p', "period", &show_period,
+                   "Show period values."),
+       OPT_BOOLEAN('F', "formula", &show_formula,
+                   "Show formula."),
        OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
                    "dump raw trace in ASCII"),
        OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
@@ -263,12 +630,36 @@ static void ui_init(void)
        /* No overhead column. */
        perf_hpp__column_enable(PERF_HPP__OVERHEAD, false);
 
-       /* Display baseline/delta/displacement columns. */
+       /*
+        * Display baseline/delta/ratio/displacement/
+        * formula/periods columns.
+        */
        perf_hpp__column_enable(PERF_HPP__BASELINE, true);
-       perf_hpp__column_enable(PERF_HPP__DELTA, true);
+
+       switch (compute) {
+       case COMPUTE_DELTA:
+               perf_hpp__column_enable(PERF_HPP__DELTA, true);
+               break;
+       case COMPUTE_RATIO:
+               perf_hpp__column_enable(PERF_HPP__RATIO, true);
+               break;
+       case COMPUTE_WEIGHTED_DIFF:
+               perf_hpp__column_enable(PERF_HPP__WEIGHTED_DIFF, true);
+               break;
+       default:
+               BUG_ON(1);
+       };
 
        if (show_displacement)
                perf_hpp__column_enable(PERF_HPP__DISPL, true);
+
+       if (show_formula)
+               perf_hpp__column_enable(PERF_HPP__FORMULA, true);
+
+       if (show_period) {
+               perf_hpp__column_enable(PERF_HPP__PERIOD, true);
+               perf_hpp__column_enable(PERF_HPP__PERIOD_BASELINE, true);
+       }
 }
 
 int cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused)
index 411ee5664e98e1e765bf992f379c16ec30569585..178b88ae3d2f174a5a085f233163d54cef152337 100644 (file)
@@ -414,7 +414,7 @@ static int show_html_page(const char *perf_cmd)
 int cmd_help(int argc, const char **argv, const char *prefix __maybe_unused)
 {
        bool show_all = false;
-       enum help_format help_format = HELP_FORMAT_NONE;
+       enum help_format help_format = HELP_FORMAT_MAN;
        struct option builtin_help_options[] = {
        OPT_BOOLEAN('a', "all", &show_all, "print all available commands"),
        OPT_SET_UINT('m', "man", &help_format, "show man page", HELP_FORMAT_MAN),
index 4688bea95c12e4d3dedfb1d12180848aaa8fd725..386a5c0013ffcace497e44c745f23b663c6fed0d 100644 (file)
@@ -102,14 +102,14 @@ static int perf_event__repipe_mmap(struct perf_tool *tool,
        return err;
 }
 
-static int perf_event__repipe_task(struct perf_tool *tool,
+static int perf_event__repipe_fork(struct perf_tool *tool,
                                   union perf_event *event,
                                   struct perf_sample *sample,
                                   struct machine *machine)
 {
        int err;
 
-       err = perf_event__process_task(tool, event, sample, machine);
+       err = perf_event__process_fork(tool, event, sample, machine);
        perf_event__repipe(tool, event, sample, machine);
 
        return err;
@@ -227,7 +227,7 @@ static int __cmd_inject(struct perf_inject *inject)
        if (inject->build_ids) {
                inject->tool.sample       = perf_event__inject_buildid;
                inject->tool.mmap         = perf_event__repipe_mmap;
-               inject->tool.fork         = perf_event__repipe_task;
+               inject->tool.fork         = perf_event__repipe_fork;
                inject->tool.tracing_data = perf_event__repipe_tracing_data;
        }
 
index 260abc535b5b428e817ebaa5a4354fbe67a947e1..836c82f0137176fb05f80bacab5e47c2b726593e 100644 (file)
@@ -313,9 +313,9 @@ struct vcpu_event_record {
 
 static void init_kvm_event_record(struct perf_kvm *kvm)
 {
-       int i;
+       unsigned int i;
 
-       for (i = 0; i < (int)EVENTS_CACHE_SIZE; i++)
+       for (i = 0; i < EVENTS_CACHE_SIZE; i++)
                INIT_LIST_HEAD(&kvm->kvm_events_cache[i]);
 }
 
@@ -369,9 +369,10 @@ static struct kvm_event *find_create_kvm_event(struct perf_kvm *kvm,
        BUG_ON(key->key == INVALID_KEY);
 
        head = &kvm->kvm_events_cache[kvm_events_hash_fn(key->key)];
-       list_for_each_entry(event, head, hash_entry)
+       list_for_each_entry(event, head, hash_entry) {
                if (event->key.key == key->key && event->key.info == key->info)
                        return event;
+       }
 
        event = kvm_alloc_init_event(key);
        if (!event)
@@ -416,7 +417,10 @@ static double kvm_event_rel_stddev(int vcpu_id, struct kvm_event *event)
 static bool update_kvm_event(struct kvm_event *event, int vcpu_id,
                             u64 time_diff)
 {
-       kvm_update_event_stats(&event->total, time_diff);
+       if (vcpu_id == -1) {
+               kvm_update_event_stats(&event->total, time_diff);
+               return true;
+       }
 
        if (!kvm_event_expand(event, vcpu_id))
                return false;
@@ -432,6 +436,12 @@ static bool handle_end_event(struct perf_kvm *kvm,
 {
        struct kvm_event *event;
        u64 time_begin, time_diff;
+       int vcpu;
+
+       if (kvm->trace_vcpu == -1)
+               vcpu = -1;
+       else
+               vcpu = vcpu_record->vcpu_id;
 
        event = vcpu_record->last_event;
        time_begin = vcpu_record->start_time;
@@ -461,7 +471,7 @@ static bool handle_end_event(struct perf_kvm *kvm,
        BUG_ON(timestamp < time_begin);
 
        time_diff = timestamp - time_begin;
-       return update_kvm_event(event, vcpu_record->vcpu_id, time_diff);
+       return update_kvm_event(event, vcpu, time_diff);
 }
 
 static
@@ -498,6 +508,11 @@ static bool handle_kvm_event(struct perf_kvm *kvm,
        if (!vcpu_record)
                return true;
 
+       /* only process events for vcpus user cares about */
+       if ((kvm->trace_vcpu != -1) &&
+           (kvm->trace_vcpu != vcpu_record->vcpu_id))
+               return true;
+
        if (kvm->events_ops->is_begin_event(evsel, sample, &key))
                return handle_begin_event(kvm, vcpu_record, &key, sample->time);
 
@@ -596,13 +611,15 @@ static void sort_result(struct perf_kvm *kvm)
        int vcpu = kvm->trace_vcpu;
        struct kvm_event *event;
 
-       for (i = 0; i < EVENTS_CACHE_SIZE; i++)
-               list_for_each_entry(event, &kvm->kvm_events_cache[i], hash_entry)
+       for (i = 0; i < EVENTS_CACHE_SIZE; i++) {
+               list_for_each_entry(event, &kvm->kvm_events_cache[i], hash_entry) {
                        if (event_is_valid(event, vcpu)) {
                                update_total_count(kvm, event);
                                insert_to_result(&kvm->result, event,
                                                 kvm->compare, vcpu);
                        }
+               }
+       }
 }
 
 /* returns left most element of result, and erase it */
@@ -659,8 +676,8 @@ static void print_result(struct perf_kvm *kvm)
                pr_info("\n");
        }
 
-       pr_info("\nTotal Samples:%lld, Total events handled time:%.2fus.\n\n",
-               (unsigned long long)kvm->total_count, kvm->total_time / 1e3);
+       pr_info("\nTotal Samples:%" PRIu64 ", Total events handled time:%.2fus.\n\n",
+               kvm->total_count, kvm->total_time / 1e3);
 }
 
 static int process_sample_event(struct perf_tool *tool,
index e9231659754d97ae25d0688c4144d19bffbb1bcd..73b5d7f9119482759be56761f17f01c21226e297 100644 (file)
 #include <sched.h>
 #include <sys/mman.h>
 
+#ifndef HAVE_ON_EXIT
+#ifndef ATEXIT_MAX
+#define ATEXIT_MAX 32
+#endif
+static int __on_exit_count = 0;
+typedef void (*on_exit_func_t) (int, void *);
+static on_exit_func_t __on_exit_funcs[ATEXIT_MAX];
+static void *__on_exit_args[ATEXIT_MAX];
+static int __exitcode = 0;
+static void __handle_on_exit_funcs(void);
+static int on_exit(on_exit_func_t function, void *arg);
+#define exit(x) (exit)(__exitcode = (x))
+
+static int on_exit(on_exit_func_t function, void *arg)
+{
+       if (__on_exit_count == ATEXIT_MAX)
+               return -ENOMEM;
+       else if (__on_exit_count == 0)
+               atexit(__handle_on_exit_funcs);
+       __on_exit_funcs[__on_exit_count] = function;
+       __on_exit_args[__on_exit_count++] = arg;
+       return 0;
+}
+
+static void __handle_on_exit_funcs(void)
+{
+       int i;
+       for (i = 0; i < __on_exit_count; i++)
+               __on_exit_funcs[i] (__exitcode, __on_exit_args[i]);
+}
+#endif
+
 enum write_mode_t {
        WRITE_FORCE,
        WRITE_APPEND
index a61725d89d3ee4188dbe7c4b542c6e1f3685d506..5104a40af5634fb62f0089a81d85e2c73bc2219f 100644 (file)
@@ -556,8 +556,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
                        .sample          = process_sample_event,
                        .mmap            = perf_event__process_mmap,
                        .comm            = perf_event__process_comm,
-                       .exit            = perf_event__process_task,
-                       .fork            = perf_event__process_task,
+                       .exit            = perf_event__process_exit,
+                       .fork            = perf_event__process_fork,
                        .lost            = perf_event__process_lost,
                        .read            = process_read_event,
                        .attr            = perf_event__process_attr,
index 3488ead3b60ce80707493e93f821945bad8a6455..30e53360d3c22e536d66539282d4db1b8736638d 100644 (file)
@@ -1672,7 +1672,8 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused)
                        .sample          = perf_sched__process_tracepoint_sample,
                        .comm            = perf_event__process_comm,
                        .lost            = perf_event__process_lost,
-                       .fork            = perf_event__process_task,
+                       .exit            = perf_event__process_exit,
+                       .fork            = perf_event__process_fork,
                        .ordered_samples = true,
                },
                .cmp_pid              = LIST_HEAD_INIT(sched.cmp_pid),
index fb9625083a2ed6d9d4bd25b94bc306895f18d6fc..04ceb0779d399037567cc80b0f97a7e8e131ebc3 100644 (file)
@@ -520,8 +520,8 @@ static struct perf_tool perf_script = {
        .sample          = process_sample_event,
        .mmap            = perf_event__process_mmap,
        .comm            = perf_event__process_comm,
-       .exit            = perf_event__process_task,
-       .fork            = perf_event__process_task,
+       .exit            = perf_event__process_exit,
+       .fork            = perf_event__process_fork,
        .attr            = perf_event__process_attr,
        .event_type      = perf_event__process_event_type,
        .tracing_data    = perf_event__process_tracing_data,
index 484f26cc0c00c6ee80d74e93bddc3fe24eae4c1f..e2d9872de3d78144b89bdadfb0a0bf9b06e38b43 100644 (file)
@@ -35,7 +35,6 @@ static int test__vmlinux_matches_kallsyms(void)
        struct map *kallsyms_map, *vmlinux_map;
        struct machine kallsyms, vmlinux;
        enum map_type type = MAP__FUNCTION;
-       long page_size = sysconf(_SC_PAGE_SIZE);
        struct ref_reloc_sym ref_reloc_sym = { .name = "_stext", };
 
        /*
@@ -1007,7 +1006,6 @@ static void segfault_handler(int sig __maybe_unused,
 
 static int __test__rdpmc(void)
 {
-       long page_size = sysconf(_SC_PAGE_SIZE);
        volatile int tmp = 0;
        u64 i, loops = 1000;
        int n;
index ff6db8086805e68caa29e2b232ae0d271dc7b47a..fb9da71eba1f63fdcd9e4a8fcbb20ac62f7ed107 100644 (file)
@@ -26,6 +26,7 @@
 #include "util/color.h"
 #include "util/evlist.h"
 #include "util/evsel.h"
+#include "util/machine.h"
 #include "util/session.h"
 #include "util/symbol.h"
 #include "util/thread.h"
@@ -871,7 +872,7 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
                                                   &sample, machine);
                } else if (event->header.type < PERF_RECORD_MAX) {
                        hists__inc_nr_events(&evsel->hists, event->header.type);
-                       perf_event__process(&top->tool, event, &sample, machine);
+                       machine__process_event(machine, event);
                } else
                        ++session->hists.stats.nr_unknown_events;
        }
index dec8ced61fb00c2bc7114346db3edaf0f7dd89b7..14b322961807eac9d7a5626a89f882a108d9f5e5 100644 (file)
@@ -52,10 +52,21 @@ struct trace {
        struct perf_record_opts opts;
 };
 
+static bool done = false;
+
+static void sig_handler(int sig __maybe_unused)
+{
+       done = true;
+}
+
 static int trace__read_syscall_info(struct trace *trace, int id)
 {
        char tp_name[128];
        struct syscall *sc;
+       const char *name = audit_syscall_to_name(id, trace->audit_machine);
+
+       if (name == NULL)
+               return -1;
 
        if (id > trace->syscalls.max) {
                struct syscall *nsyscalls = realloc(trace->syscalls.table, (id + 1) * sizeof(*sc));
@@ -75,11 +86,8 @@ static int trace__read_syscall_info(struct trace *trace, int id)
        }
 
        sc = trace->syscalls.table + id;
-       sc->name = audit_syscall_to_name(id, trace->audit_machine);
-       if (sc->name == NULL)
-               return -1;
-
-       sc->fmt = syscall_fmt__find(sc->name);
+       sc->name = name;
+       sc->fmt  = syscall_fmt__find(sc->name);
 
        snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->name);
        sc->tp_format = event_format__new("syscalls", tp_name);
@@ -189,11 +197,12 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
        return 0;
 }
 
-static int trace__run(struct trace *trace)
+static int trace__run(struct trace *trace, int argc, const char **argv)
 {
        struct perf_evlist *evlist = perf_evlist__new(NULL, NULL);
        struct perf_evsel *evsel;
        int err = -1, i, nr_events = 0, before;
+       const bool forks = argc > 0;
 
        if (evlist == NULL) {
                printf("Not enough memory to run!\n");
@@ -214,6 +223,17 @@ static int trace__run(struct trace *trace)
 
        perf_evlist__config_attrs(evlist, &trace->opts);
 
+       signal(SIGCHLD, sig_handler);
+       signal(SIGINT, sig_handler);
+
+       if (forks) {
+               err = perf_evlist__prepare_workload(evlist, &trace->opts, argv);
+               if (err < 0) {
+                       printf("Couldn't run the workload!\n");
+                       goto out_delete_evlist;
+               }
+       }
+
        err = perf_evlist__open(evlist);
        if (err < 0) {
                printf("Couldn't create the events: %s\n", strerror(errno));
@@ -227,6 +247,10 @@ static int trace__run(struct trace *trace)
        }
 
        perf_evlist__enable(evlist);
+
+       if (forks)
+               perf_evlist__start_workload(evlist);
+
 again:
        before = nr_events;
 
@@ -267,13 +291,27 @@ again:
                        if (evlist->threads->map[0] == -1 || evlist->threads->nr > 1)
                                printf("%d ", sample.tid);
 
+                       if (sample.raw_data == NULL) {
+                               printf("%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n",
+                                      perf_evsel__name(evsel), sample.tid,
+                                      sample.cpu, sample.raw_size);
+                               continue;
+                       }
+
                        handler = evsel->handler.func;
                        handler(trace, evsel, &sample);
                }
        }
 
-       if (nr_events == before)
+       if (nr_events == before) {
+               if (done)
+                       goto out_delete_evlist;
+
                poll(evlist->pollfd, evlist->nr_fds, -1);
+       }
+
+       if (done)
+               perf_evlist__disable(evlist);
 
        goto again;
 
@@ -286,7 +324,8 @@ out:
 int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
 {
        const char * const trace_usage[] = {
-               "perf trace [<options>]",
+               "perf trace [<options>] [<command>]",
+               "perf trace [<options>] -- <command> [<options>]",
                NULL
        };
        struct trace trace = {
@@ -323,18 +362,26 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
        OPT_END()
        };
        int err;
+       char bf[BUFSIZ];
 
        argc = parse_options(argc, argv, trace_options, trace_usage, 0);
-       if (argc)
-               usage_with_options(trace_usage, trace_options);
+
+       err = perf_target__validate(&trace.opts.target);
+       if (err) {
+               perf_target__strerror(&trace.opts.target, err, bf, sizeof(bf));
+               printf("%s", bf);
+               return err;
+       }
 
        err = perf_target__parse_uid(&trace.opts.target);
        if (err) {
-               char bf[BUFSIZ];
                perf_target__strerror(&trace.opts.target, err, bf, sizeof(bf));
                printf("%s", bf);
                return err;
        }
 
-       return trace__run(&trace);
+       if (!argc && perf_target__none(&trace.opts.target))
+               trace.opts.target.system_wide = true;
+
+       return trace__run(&trace, argc, argv);
 }
index 4add41bb0c7eeca264353ffa60603651c0051503..3ef5ec9cdff8ca750bb5864a4fd475c9dd389ee6 100644 (file)
@@ -43,6 +43,15 @@ int main(void)
 }
 endef
 
+define SOURCE_BIONIC
+#include <android/api-level.h>
+
+int main(void)
+{
+       return __ANDROID_API__;
+}
+endef
+
 define SOURCE_ELF_MMAP
 #include <libelf.h>
 int main(void)
@@ -203,4 +212,13 @@ int main(void)
        return audit_open();
 }
 endef
-endif
\ No newline at end of file
+endif
+
+define SOURCE_ON_EXIT
+#include <stdio.h>
+
+int main(void)
+{
+       return on_exit(NULL, NULL);
+}
+endef
index 6d50eb0b425196aea150f699cd97ae09b8840ab8..d480d8a412b88addb457f580b5d0fa0160604d77 100644 (file)
@@ -440,6 +440,8 @@ int main(int argc, const char **argv)
 {
        const char *cmd;
 
+       page_size = sysconf(_SC_PAGE_SIZE);
+
        cmd = perf_extract_argv0_path(argv[0]);
        if (!cmd)
                cmd = "perf-help";
index 276287783a03759af243ff3d55c3b848cd357d3f..c50985eaec41f479d2593dab749d061d3cb03c3d 100644 (file)
@@ -57,7 +57,7 @@ void get_term_dimensions(struct winsize *ws);
 #endif
 
 #ifdef __sparc__
-#include "../../arch/sparc/include/asm/unistd.h"
+#include "../../arch/sparc/include/uapi/asm/unistd.h"
 #define rmb()          asm volatile("":::"memory")
 #define cpu_relax()    asm volatile("":::"memory")
 #define CPUINFO_PROC   "cpu"
index 0568536ecf674fd3ce7e1b397e900a9fd515edcf..ef2f93ca7496d677592255d3bfaf91ed9ebb7c58 100644 (file)
@@ -610,6 +610,7 @@ static int hist_browser__show_entry(struct hist_browser *browser,
        char folded_sign = ' ';
        bool current_entry = ui_browser__is_current_entry(&browser->b, row);
        off_t row_offset = entry->row_offset;
+       bool first = true;
 
        if (current_entry) {
                browser->he_selection = entry;
@@ -633,10 +634,11 @@ static int hist_browser__show_entry(struct hist_browser *browser,
                        if (!perf_hpp__format[i].cond)
                                continue;
 
-                       if (i) {
+                       if (!first) {
                                slsmg_printf("  ");
                                width -= 2;
                        }
+                       first = false;
 
                        if (perf_hpp__format[i].color) {
                                hpp.ptr = &percent;
@@ -645,7 +647,7 @@ static int hist_browser__show_entry(struct hist_browser *browser,
 
                                ui_browser__set_percent_color(&browser->b, percent, current_entry);
 
-                               if (i == 0 && symbol_conf.use_callchain) {
+                               if (i == PERF_HPP__OVERHEAD && symbol_conf.use_callchain) {
                                        slsmg_printf("%c ", folded_sign);
                                        width -= 2;
                                }
index f5a1e4f65263fa0c03468bde22e49364b0ba2c2f..4f5f4756faacdb6e5d1638d4b876655b2116823f 100644 (file)
@@ -179,7 +179,10 @@ static int hpp__color_baseline(struct perf_hpp *hpp, struct hist_entry *he)
 {
        double percent = baseline_percent(he);
 
-       return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%%", percent);
+       if (he->pair)
+               return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%%", percent);
+       else
+               return scnprintf(hpp->buf, hpp->size, "        ");
 }
 
 static int hpp__entry_baseline(struct perf_hpp *hpp, struct hist_entry *he)
@@ -187,7 +190,10 @@ static int hpp__entry_baseline(struct perf_hpp *hpp, struct hist_entry *he)
        double percent = baseline_percent(he);
        const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%%";
 
-       return scnprintf(hpp->buf, hpp->size, fmt, percent);
+       if (he->pair || symbol_conf.field_sep)
+               return scnprintf(hpp->buf, hpp->size, fmt, percent);
+       else
+               return scnprintf(hpp->buf, hpp->size, "            ");
 }
 
 static int hpp__header_samples(struct perf_hpp *hpp)
@@ -228,6 +234,26 @@ static int hpp__entry_period(struct perf_hpp *hpp, struct hist_entry *he)
        return scnprintf(hpp->buf, hpp->size, fmt, he->stat.period);
 }
 
+static int hpp__header_period_baseline(struct perf_hpp *hpp)
+{
+       const char *fmt = symbol_conf.field_sep ? "%s" : "%12s";
+
+       return scnprintf(hpp->buf, hpp->size, fmt, "Period Base");
+}
+
+static int hpp__width_period_baseline(struct perf_hpp *hpp __maybe_unused)
+{
+       return 12;
+}
+
+static int hpp__entry_period_baseline(struct perf_hpp *hpp, struct hist_entry *he)
+{
+       struct hist_entry *pair = he->pair;
+       u64 period = pair ? pair->stat.period : 0;
+       const char *fmt = symbol_conf.field_sep ? "%" PRIu64 : "%12" PRIu64;
+
+       return scnprintf(hpp->buf, hpp->size, fmt, period);
+}
 static int hpp__header_delta(struct perf_hpp *hpp)
 {
        const char *fmt = symbol_conf.field_sep ? "%s" : "%7s";
@@ -242,30 +268,79 @@ static int hpp__width_delta(struct perf_hpp *hpp __maybe_unused)
 
 static int hpp__entry_delta(struct perf_hpp *hpp, struct hist_entry *he)
 {
-       struct hist_entry *pair = he->pair;
-       struct hists *pair_hists = pair ? pair->hists : NULL;
-       struct hists *hists = he->hists;
-       u64 old_total, new_total;
-       double old_percent = 0, new_percent = 0;
-       double diff;
        const char *fmt = symbol_conf.field_sep ? "%s" : "%7.7s";
        char buf[32] = " ";
+       double diff;
 
-       old_total = pair_hists ? pair_hists->stats.total_period : 0;
-       if (old_total > 0 && pair)
-               old_percent = 100.0 * pair->stat.period / old_total;
-
-       new_total = hists->stats.total_period;
-       if (new_total > 0)
-               new_percent = 100.0 * he->stat.period / new_total;
+       if (he->diff.computed)
+               diff = he->diff.period_ratio_delta;
+       else
+               diff = perf_diff__compute_delta(he);
 
-       diff = new_percent - old_percent;
        if (fabs(diff) >= 0.01)
                scnprintf(buf, sizeof(buf), "%+4.2F%%", diff);
 
        return scnprintf(hpp->buf, hpp->size, fmt, buf);
 }
 
+static int hpp__header_ratio(struct perf_hpp *hpp)
+{
+       const char *fmt = symbol_conf.field_sep ? "%s" : "%14s";
+
+       return scnprintf(hpp->buf, hpp->size, fmt, "Ratio");
+}
+
+static int hpp__width_ratio(struct perf_hpp *hpp __maybe_unused)
+{
+       return 14;
+}
+
+static int hpp__entry_ratio(struct perf_hpp *hpp, struct hist_entry *he)
+{
+       const char *fmt = symbol_conf.field_sep ? "%s" : "%14s";
+       char buf[32] = " ";
+       double ratio;
+
+       if (he->diff.computed)
+               ratio = he->diff.period_ratio;
+       else
+               ratio = perf_diff__compute_ratio(he);
+
+       if (ratio > 0.0)
+               scnprintf(buf, sizeof(buf), "%+14.6F", ratio);
+
+       return scnprintf(hpp->buf, hpp->size, fmt, buf);
+}
+
+static int hpp__header_wdiff(struct perf_hpp *hpp)
+{
+       const char *fmt = symbol_conf.field_sep ? "%s" : "%14s";
+
+       return scnprintf(hpp->buf, hpp->size, fmt, "Weighted diff");
+}
+
+static int hpp__width_wdiff(struct perf_hpp *hpp __maybe_unused)
+{
+       return 14;
+}
+
+static int hpp__entry_wdiff(struct perf_hpp *hpp, struct hist_entry *he)
+{
+       const char *fmt = symbol_conf.field_sep ? "%s" : "%14s";
+       char buf[32] = " ";
+       s64 wdiff;
+
+       if (he->diff.computed)
+               wdiff = he->diff.wdiff;
+       else
+               wdiff = perf_diff__compute_wdiff(he);
+
+       if (wdiff != 0)
+               scnprintf(buf, sizeof(buf), "%14ld", wdiff);
+
+       return scnprintf(hpp->buf, hpp->size, fmt, buf);
+}
+
 static int hpp__header_displ(struct perf_hpp *hpp)
 {
        return scnprintf(hpp->buf, hpp->size, "Displ.");
@@ -290,6 +365,27 @@ static int hpp__entry_displ(struct perf_hpp *hpp,
        return scnprintf(hpp->buf, hpp->size, fmt, buf);
 }
 
+static int hpp__header_formula(struct perf_hpp *hpp)
+{
+       const char *fmt = symbol_conf.field_sep ? "%s" : "%70s";
+
+       return scnprintf(hpp->buf, hpp->size, fmt, "Formula");
+}
+
+static int hpp__width_formula(struct perf_hpp *hpp __maybe_unused)
+{
+       return 70;
+}
+
+static int hpp__entry_formula(struct perf_hpp *hpp, struct hist_entry *he)
+{
+       const char *fmt = symbol_conf.field_sep ? "%s" : "%-70s";
+       char buf[96] = " ";
+
+       perf_diff__formula(buf, sizeof(buf), he);
+       return scnprintf(hpp->buf, hpp->size, fmt, buf);
+}
+
 #define HPP__COLOR_PRINT_FNS(_name)            \
        .header = hpp__header_ ## _name,                \
        .width  = hpp__width_ ## _name,         \
@@ -310,8 +406,12 @@ struct perf_hpp_fmt perf_hpp__format[] = {
        { .cond = false, HPP__COLOR_PRINT_FNS(overhead_guest_us) },
        { .cond = false, HPP__PRINT_FNS(samples) },
        { .cond = false, HPP__PRINT_FNS(period) },
+       { .cond = false, HPP__PRINT_FNS(period_baseline) },
        { .cond = false, HPP__PRINT_FNS(delta) },
-       { .cond = false, HPP__PRINT_FNS(displ) }
+       { .cond = false, HPP__PRINT_FNS(ratio) },
+       { .cond = false, HPP__PRINT_FNS(wdiff) },
+       { .cond = false, HPP__PRINT_FNS(displ) },
+       { .cond = false, HPP__PRINT_FNS(formula) }
 };
 
 #undef HPP__COLOR_PRINT_FNS
index fbd4e32d07437280623cf913acfbb35583fdc1be..f0ee204f99bb4bffddedd7434d276f05d98cfb9c 100644 (file)
@@ -342,7 +342,7 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
        const char *sep = symbol_conf.field_sep;
        const char *col_width = symbol_conf.col_width_list_str;
        int idx, nr_rows = 0;
-       char bf[64];
+       char bf[96];
        struct perf_hpp dummy_hpp = {
                .buf    = bf,
                .size   = sizeof(bf),
index 8e3a740ddbd4eed2059aa08d8d7592fea4075833..6a6399955ef2ddee6b163e0a8e1f2c18dfda250b 100644 (file)
@@ -64,7 +64,7 @@ static int perf_event__exit_del_thread(struct perf_tool *tool __maybe_unused,
 struct perf_tool build_id__mark_dso_hit_ops = {
        .sample = build_id__mark_dso_hit,
        .mmap   = perf_event__process_mmap,
-       .fork   = perf_event__process_task,
+       .fork   = perf_event__process_fork,
        .exit   = perf_event__exit_del_thread,
        .attr            = perf_event__process_attr,
        .build_id        = perf_event__process_build_id,
index 6715b19387258cd184bba45d88a00e76eaebbeba..0ae444ef1429939e5fbc7891ac65485eb5bb4c50 100644 (file)
@@ -1,6 +1,7 @@
 #include <linux/types.h>
 #include "event.h"
 #include "debug.h"
+#include "machine.h"
 #include "sort.h"
 #include "string.h"
 #include "strlist.h"
@@ -519,134 +520,15 @@ int perf_event__process_comm(struct perf_tool *tool __maybe_unused,
                             struct perf_sample *sample __maybe_unused,
                             struct machine *machine)
 {
-       struct thread *thread = machine__findnew_thread(machine, event->comm.tid);
-
-       if (dump_trace)
-               perf_event__fprintf_comm(event, stdout);
-
-       if (thread == NULL || thread__set_comm(thread, event->comm.comm)) {
-               dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n");
-               return -1;
-       }
-
-       return 0;
+       return machine__process_comm_event(machine, event);
 }
 
 int perf_event__process_lost(struct perf_tool *tool __maybe_unused,
                             union perf_event *event,
                             struct perf_sample *sample __maybe_unused,
-                            struct machine *machine __maybe_unused)
-{
-       dump_printf(": id:%" PRIu64 ": lost:%" PRIu64 "\n",
-                   event->lost.id, event->lost.lost);
-       return 0;
-}
-
-static void perf_event__set_kernel_mmap_len(union perf_event *event,
-                                           struct map **maps)
+                            struct machine *machine)
 {
-       maps[MAP__FUNCTION]->start = event->mmap.start;
-       maps[MAP__FUNCTION]->end   = event->mmap.start + event->mmap.len;
-       /*
-        * Be a bit paranoid here, some perf.data file came with
-        * a zero sized synthesized MMAP event for the kernel.
-        */
-       if (maps[MAP__FUNCTION]->end == 0)
-               maps[MAP__FUNCTION]->end = ~0ULL;
-}
-
-static int perf_event__process_kernel_mmap(struct perf_tool *tool
-                                          __maybe_unused,
-                                          union perf_event *event,
-                                          struct machine *machine)
-{
-       struct map *map;
-       char kmmap_prefix[PATH_MAX];
-       enum dso_kernel_type kernel_type;
-       bool is_kernel_mmap;
-
-       machine__mmap_name(machine, kmmap_prefix, sizeof(kmmap_prefix));
-       if (machine__is_host(machine))
-               kernel_type = DSO_TYPE_KERNEL;
-       else
-               kernel_type = DSO_TYPE_GUEST_KERNEL;
-
-       is_kernel_mmap = memcmp(event->mmap.filename,
-                               kmmap_prefix,
-                               strlen(kmmap_prefix) - 1) == 0;
-       if (event->mmap.filename[0] == '/' ||
-           (!is_kernel_mmap && event->mmap.filename[0] == '[')) {
-
-               char short_module_name[1024];
-               char *name, *dot;
-
-               if (event->mmap.filename[0] == '/') {
-                       name = strrchr(event->mmap.filename, '/');
-                       if (name == NULL)
-                               goto out_problem;
-
-                       ++name; /* skip / */
-                       dot = strrchr(name, '.');
-                       if (dot == NULL)
-                               goto out_problem;
-                       snprintf(short_module_name, sizeof(short_module_name),
-                                       "[%.*s]", (int)(dot - name), name);
-                       strxfrchar(short_module_name, '-', '_');
-               } else
-                       strcpy(short_module_name, event->mmap.filename);
-
-               map = machine__new_module(machine, event->mmap.start,
-                                         event->mmap.filename);
-               if (map == NULL)
-                       goto out_problem;
-
-               name = strdup(short_module_name);
-               if (name == NULL)
-                       goto out_problem;
-
-               map->dso->short_name = name;
-               map->dso->sname_alloc = 1;
-               map->end = map->start + event->mmap.len;
-       } else if (is_kernel_mmap) {
-               const char *symbol_name = (event->mmap.filename +
-                               strlen(kmmap_prefix));
-               /*
-                * Should be there already, from the build-id table in
-                * the header.
-                */
-               struct dso *kernel = __dsos__findnew(&machine->kernel_dsos,
-                                                    kmmap_prefix);
-               if (kernel == NULL)
-                       goto out_problem;
-
-               kernel->kernel = kernel_type;
-               if (__machine__create_kernel_maps(machine, kernel) < 0)
-                       goto out_problem;
-
-               perf_event__set_kernel_mmap_len(event, machine->vmlinux_maps);
-
-               /*
-                * Avoid using a zero address (kptr_restrict) for the ref reloc
-                * symbol. Effectively having zero here means that at record
-                * time /proc/sys/kernel/kptr_restrict was non zero.
-                */
-               if (event->mmap.pgoff != 0) {
-                       maps__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps,
-                                                        symbol_name,
-                                                        event->mmap.pgoff);
-               }
-
-               if (machine__is_default_guest(machine)) {
-                       /*
-                        * preload dso of guest kernel and modules
-                        */
-                       dso__load(kernel, machine->vmlinux_maps[MAP__FUNCTION],
-                                 NULL);
-               }
-       }
-       return 0;
-out_problem:
-       return -1;
+       return machine__process_lost_event(machine, event);
 }
 
 size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp)
@@ -656,43 +538,12 @@ size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp)
                       event->mmap.len, event->mmap.pgoff, event->mmap.filename);
 }
 
-int perf_event__process_mmap(struct perf_tool *tool,
+int perf_event__process_mmap(struct perf_tool *tool __maybe_unused,
                             union perf_event *event,
                             struct perf_sample *sample __maybe_unused,
                             struct machine *machine)
 {
-       struct thread *thread;
-       struct map *map;
-       u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
-       int ret = 0;
-
-       if (dump_trace)
-               perf_event__fprintf_mmap(event, stdout);
-
-       if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL ||
-           cpumode == PERF_RECORD_MISC_KERNEL) {
-               ret = perf_event__process_kernel_mmap(tool, event, machine);
-               if (ret < 0)
-                       goto out_problem;
-               return 0;
-       }
-
-       thread = machine__findnew_thread(machine, event->mmap.pid);
-       if (thread == NULL)
-               goto out_problem;
-       map = map__new(&machine->user_dsos, event->mmap.start,
-                       event->mmap.len, event->mmap.pgoff,
-                       event->mmap.pid, event->mmap.filename,
-                       MAP__FUNCTION);
-       if (map == NULL)
-               goto out_problem;
-
-       thread__insert_map(thread, map);
-       return 0;
-
-out_problem:
-       dump_printf("problem processing PERF_RECORD_MMAP, skipping event.\n");
-       return 0;
+       return machine__process_mmap_event(machine, event);
 }
 
 size_t perf_event__fprintf_task(union perf_event *event, FILE *fp)
@@ -702,29 +553,20 @@ size_t perf_event__fprintf_task(union perf_event *event, FILE *fp)
                       event->fork.ppid, event->fork.ptid);
 }
 
-int perf_event__process_task(struct perf_tool *tool __maybe_unused,
+int perf_event__process_fork(struct perf_tool *tool __maybe_unused,
                             union perf_event *event,
                             struct perf_sample *sample __maybe_unused,
-                             struct machine *machine)
+                            struct machine *machine)
 {
-       struct thread *thread = machine__findnew_thread(machine, event->fork.tid);
-       struct thread *parent = machine__findnew_thread(machine, event->fork.ptid);
-
-       if (dump_trace)
-               perf_event__fprintf_task(event, stdout);
-
-       if (event->header.type == PERF_RECORD_EXIT) {
-               machine__remove_thread(machine, thread);
-               return 0;
-       }
-
-       if (thread == NULL || parent == NULL ||
-           thread__fork(thread, parent) < 0) {
-               dump_printf("problem processing PERF_RECORD_FORK, skipping event.\n");
-               return -1;
-       }
+       return machine__process_fork_event(machine, event);
+}
 
-       return 0;
+int perf_event__process_exit(struct perf_tool *tool __maybe_unused,
+                            union perf_event *event,
+                            struct perf_sample *sample __maybe_unused,
+                            struct machine *machine)
+{
+       return machine__process_exit_event(machine, event);
 }
 
 size_t perf_event__fprintf(union perf_event *event, FILE *fp)
@@ -750,27 +592,12 @@ size_t perf_event__fprintf(union perf_event *event, FILE *fp)
        return ret;
 }
 
-int perf_event__process(struct perf_tool *tool, union perf_event *event,
-                       struct perf_sample *sample, struct machine *machine)
+int perf_event__process(struct perf_tool *tool __maybe_unused,
+                       union perf_event *event,
+                       struct perf_sample *sample __maybe_unused,
+                       struct machine *machine)
 {
-       switch (event->header.type) {
-       case PERF_RECORD_COMM:
-               perf_event__process_comm(tool, event, sample, machine);
-               break;
-       case PERF_RECORD_MMAP:
-               perf_event__process_mmap(tool, event, sample, machine);
-               break;
-       case PERF_RECORD_FORK:
-       case PERF_RECORD_EXIT:
-               perf_event__process_task(tool, event, sample, machine);
-               break;
-       case PERF_RECORD_LOST:
-               perf_event__process_lost(tool, event, sample, machine);
-       default:
-               break;
-       }
-
-       return 0;
+       return machine__process_event(machine, event);
 }
 
 void thread__find_addr_map(struct thread *self,
index 21b99e741a87c016ab383d683492dfd2aa2017b9..da97aff5bd7592222a7656825f96538eec911361 100644 (file)
@@ -191,7 +191,11 @@ int perf_event__process_mmap(struct perf_tool *tool,
                             union perf_event *event,
                             struct perf_sample *sample,
                             struct machine *machine);
-int perf_event__process_task(struct perf_tool *tool,
+int perf_event__process_fork(struct perf_tool *tool,
+                            union perf_event *event,
+                            struct perf_sample *sample,
+                            struct machine *machine);
+int perf_event__process_exit(struct perf_tool *tool,
                             union perf_event *event,
                             struct perf_sample *sample,
                             struct machine *machine);
index 186b87730396712d6fbfcbc95837168b81287ca4..a41dc4a5c2deeeefbe4794ebd9774e517c3363db 100644 (file)
@@ -325,8 +325,6 @@ struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id)
 
 union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
 {
-       /* XXX Move this to perf.c, making it generally available */
-       unsigned int page_size = sysconf(_SC_PAGE_SIZE);
        struct perf_mmap *md = &evlist->mmap[idx];
        unsigned int head = perf_mmap__read_head(md);
        unsigned int old = md->prev;
@@ -528,7 +526,6 @@ out_unmap:
 int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
                      bool overwrite)
 {
-       unsigned int page_size = sysconf(_SC_PAGE_SIZE);
        struct perf_evsel *evsel;
        const struct cpu_map *cpus = evlist->cpus;
        const struct thread_map *threads = evlist->threads;
index 66cb31fe81d2a7c3b7a45e925a5fc6d3cb7a4e63..c751624d415308fb51457a365baffb779f577397 100644 (file)
@@ -140,8 +140,12 @@ enum {
        PERF_HPP__OVERHEAD_GUEST_US,
        PERF_HPP__SAMPLES,
        PERF_HPP__PERIOD,
+       PERF_HPP__PERIOD_BASELINE,
        PERF_HPP__DELTA,
+       PERF_HPP__RATIO,
+       PERF_HPP__WEIGHTED_DIFF,
        PERF_HPP__DISPL,
+       PERF_HPP__FORMULA,
 
        PERF_HPP__MAX_INDEX
 };
@@ -204,4 +208,8 @@ int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist __maybe_unused,
 
 unsigned int hists__sort_list_width(struct hists *self);
 
+double perf_diff__compute_delta(struct hist_entry *he);
+double perf_diff__compute_ratio(struct hist_entry *he);
+s64 perf_diff__compute_wdiff(struct hist_entry *he);
+int perf_diff__formula(char *buf, size_t size, struct hist_entry *he);
 #endif /* __PERF_HIST_H */
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
new file mode 100644 (file)
index 0000000..502eec0
--- /dev/null
@@ -0,0 +1,277 @@
+#include "debug.h"
+#include "event.h"
+#include "machine.h"
+#include "map.h"
+#include "thread.h"
+#include <stdbool.h>
+
+static struct thread *__machine__findnew_thread(struct machine *machine, pid_t pid,
+                                               bool create)
+{
+       struct rb_node **p = &machine->threads.rb_node;
+       struct rb_node *parent = NULL;
+       struct thread *th;
+
+       /*
+        * Font-end cache - PID lookups come in blocks,
+        * so most of the time we dont have to look up
+        * the full rbtree:
+        */
+       if (machine->last_match && machine->last_match->pid == pid)
+               return machine->last_match;
+
+       while (*p != NULL) {
+               parent = *p;
+               th = rb_entry(parent, struct thread, rb_node);
+
+               if (th->pid == pid) {
+                       machine->last_match = th;
+                       return th;
+               }
+
+               if (pid < th->pid)
+                       p = &(*p)->rb_left;
+               else
+                       p = &(*p)->rb_right;
+       }
+
+       if (!create)
+               return NULL;
+
+       th = thread__new(pid);
+       if (th != NULL) {
+               rb_link_node(&th->rb_node, parent, p);
+               rb_insert_color(&th->rb_node, &machine->threads);
+               machine->last_match = th;
+       }
+
+       return th;
+}
+
+struct thread *machine__findnew_thread(struct machine *machine, pid_t pid)
+{
+       return __machine__findnew_thread(machine, pid, true);
+}
+
+struct thread *machine__find_thread(struct machine *machine, pid_t pid)
+{
+       return __machine__findnew_thread(machine, pid, false);
+}
+
+int machine__process_comm_event(struct machine *machine, union perf_event *event)
+{
+       struct thread *thread = machine__findnew_thread(machine, event->comm.tid);
+
+       if (dump_trace)
+               perf_event__fprintf_comm(event, stdout);
+
+       if (thread == NULL || thread__set_comm(thread, event->comm.comm)) {
+               dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n");
+               return -1;
+       }
+
+       return 0;
+}
+
+int machine__process_lost_event(struct machine *machine __maybe_unused,
+                               union perf_event *event)
+{
+       dump_printf(": id:%" PRIu64 ": lost:%" PRIu64 "\n",
+                   event->lost.id, event->lost.lost);
+       return 0;
+}
+
+static void machine__set_kernel_mmap_len(struct machine *machine,
+                                        union perf_event *event)
+{
+       machine->vmlinux_maps[MAP__FUNCTION]->start = event->mmap.start;
+       machine->vmlinux_maps[MAP__FUNCTION]->end   = (event->mmap.start +
+                                                      event->mmap.len);
+       /*
+        * Be a bit paranoid here, some perf.data file came with
+        * a zero sized synthesized MMAP event for the kernel.
+        */
+       if (machine->vmlinux_maps[MAP__FUNCTION]->end == 0)
+               machine->vmlinux_maps[MAP__FUNCTION]->end = ~0ULL;
+}
+
+static int machine__process_kernel_mmap_event(struct machine *machine,
+                                             union perf_event *event)
+{
+       struct map *map;
+       char kmmap_prefix[PATH_MAX];
+       enum dso_kernel_type kernel_type;
+       bool is_kernel_mmap;
+
+       machine__mmap_name(machine, kmmap_prefix, sizeof(kmmap_prefix));
+       if (machine__is_host(machine))
+               kernel_type = DSO_TYPE_KERNEL;
+       else
+               kernel_type = DSO_TYPE_GUEST_KERNEL;
+
+       is_kernel_mmap = memcmp(event->mmap.filename,
+                               kmmap_prefix,
+                               strlen(kmmap_prefix) - 1) == 0;
+       if (event->mmap.filename[0] == '/' ||
+           (!is_kernel_mmap && event->mmap.filename[0] == '[')) {
+
+               char short_module_name[1024];
+               char *name, *dot;
+
+               if (event->mmap.filename[0] == '/') {
+                       name = strrchr(event->mmap.filename, '/');
+                       if (name == NULL)
+                               goto out_problem;
+
+                       ++name; /* skip / */
+                       dot = strrchr(name, '.');
+                       if (dot == NULL)
+                               goto out_problem;
+                       snprintf(short_module_name, sizeof(short_module_name),
+                                       "[%.*s]", (int)(dot - name), name);
+                       strxfrchar(short_module_name, '-', '_');
+               } else
+                       strcpy(short_module_name, event->mmap.filename);
+
+               map = machine__new_module(machine, event->mmap.start,
+                                         event->mmap.filename);
+               if (map == NULL)
+                       goto out_problem;
+
+               name = strdup(short_module_name);
+               if (name == NULL)
+                       goto out_problem;
+
+               map->dso->short_name = name;
+               map->dso->sname_alloc = 1;
+               map->end = map->start + event->mmap.len;
+       } else if (is_kernel_mmap) {
+               const char *symbol_name = (event->mmap.filename +
+                               strlen(kmmap_prefix));
+               /*
+                * Should be there already, from the build-id table in
+                * the header.
+                */
+               struct dso *kernel = __dsos__findnew(&machine->kernel_dsos,
+                                                    kmmap_prefix);
+               if (kernel == NULL)
+                       goto out_problem;
+
+               kernel->kernel = kernel_type;
+               if (__machine__create_kernel_maps(machine, kernel) < 0)
+                       goto out_problem;
+
+               machine__set_kernel_mmap_len(machine, event);
+
+               /*
+                * Avoid using a zero address (kptr_restrict) for the ref reloc
+                * symbol. Effectively having zero here means that at record
+                * time /proc/sys/kernel/kptr_restrict was non zero.
+                */
+               if (event->mmap.pgoff != 0) {
+                       maps__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps,
+                                                        symbol_name,
+                                                        event->mmap.pgoff);
+               }
+
+               if (machine__is_default_guest(machine)) {
+                       /*
+                        * preload dso of guest kernel and modules
+                        */
+                       dso__load(kernel, machine->vmlinux_maps[MAP__FUNCTION],
+                                 NULL);
+               }
+       }
+       return 0;
+out_problem:
+       return -1;
+}
+
+int machine__process_mmap_event(struct machine *machine, union perf_event *event)
+{
+       u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
+       struct thread *thread;
+       struct map *map;
+       int ret = 0;
+
+       if (dump_trace)
+               perf_event__fprintf_mmap(event, stdout);
+
+       if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL ||
+           cpumode == PERF_RECORD_MISC_KERNEL) {
+               ret = machine__process_kernel_mmap_event(machine, event);
+               if (ret < 0)
+                       goto out_problem;
+               return 0;
+       }
+
+       thread = machine__findnew_thread(machine, event->mmap.pid);
+       if (thread == NULL)
+               goto out_problem;
+       map = map__new(&machine->user_dsos, event->mmap.start,
+                       event->mmap.len, event->mmap.pgoff,
+                       event->mmap.pid, event->mmap.filename,
+                       MAP__FUNCTION);
+       if (map == NULL)
+               goto out_problem;
+
+       thread__insert_map(thread, map);
+       return 0;
+
+out_problem:
+       dump_printf("problem processing PERF_RECORD_MMAP, skipping event.\n");
+       return 0;
+}
+
+int machine__process_fork_event(struct machine *machine, union perf_event *event)
+{
+       struct thread *thread = machine__findnew_thread(machine, event->fork.tid);
+       struct thread *parent = machine__findnew_thread(machine, event->fork.ptid);
+
+       if (dump_trace)
+               perf_event__fprintf_task(event, stdout);
+
+       if (thread == NULL || parent == NULL ||
+           thread__fork(thread, parent) < 0) {
+               dump_printf("problem processing PERF_RECORD_FORK, skipping event.\n");
+               return -1;
+       }
+
+       return 0;
+}
+
+int machine__process_exit_event(struct machine *machine, union perf_event *event)
+{
+       struct thread *thread = machine__find_thread(machine, event->fork.tid);
+
+       if (dump_trace)
+               perf_event__fprintf_task(event, stdout);
+
+       if (thread != NULL)
+               machine__remove_thread(machine, thread);
+
+       return 0;
+}
+
+int machine__process_event(struct machine *machine, union perf_event *event)
+{
+       int ret;
+
+       switch (event->header.type) {
+       case PERF_RECORD_COMM:
+               ret = machine__process_comm_event(machine, event); break;
+       case PERF_RECORD_MMAP:
+               ret = machine__process_mmap_event(machine, event); break;
+       case PERF_RECORD_FORK:
+               ret = machine__process_fork_event(machine, event); break;
+       case PERF_RECORD_EXIT:
+               ret = machine__process_exit_event(machine, event); break;
+       case PERF_RECORD_LOST:
+               ret = machine__process_lost_event(machine, event); break;
+       default:
+               ret = -1;
+               break;
+       }
+
+       return ret;
+}
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
new file mode 100644 (file)
index 0000000..df152f1
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef __PERF_MACHINE_H
+#define __PERF_MACHINE_H
+
+#include <sys/types.h>
+
+struct thread;
+struct machine;
+union perf_event;
+
+struct thread *machine__find_thread(struct machine *machine, pid_t pid);
+
+int machine__process_comm_event(struct machine *machine, union perf_event *event);
+int machine__process_exit_event(struct machine *machine, union perf_event *event);
+int machine__process_fork_event(struct machine *machine, union perf_event *event);
+int machine__process_lost_event(struct machine *machine, union perf_event *event);
+int machine__process_mmap_event(struct machine *machine, union perf_event *event);
+int machine__process_event(struct machine *machine, union perf_event *event);
+
+#endif /* __PERF_MACHINE_H */
index 28c18d1d52c3efceeb2847a1b68bd3dd000d45b6..b49c2eebff33984454db6f349e16437c6c7f62e8 100644 (file)
@@ -443,6 +443,23 @@ static int test__checkevent_pmu_name(struct perf_evlist *evlist)
        return 0;
 }
 
+static int test__checkevent_pmu_events(struct perf_evlist *evlist)
+{
+       struct perf_evsel *evsel;
+
+       evsel = list_entry(evlist->entries.next, struct perf_evsel, node);
+       TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
+       TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type);
+       TEST_ASSERT_VAL("wrong exclude_user",
+                       !evsel->attr.exclude_user);
+       TEST_ASSERT_VAL("wrong exclude_kernel",
+                       evsel->attr.exclude_kernel);
+       TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
+       TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+
+       return 0;
+}
+
 static int test__checkterms_simple(struct list_head *terms)
 {
        struct parse_events__term *term;
@@ -513,7 +530,8 @@ static int test__group1(struct perf_evlist *evlist)
        TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
        TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
        TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
-       TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
+       /* use of precise requires exclude_guest */
+       TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
        TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
        TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 2);
        TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
@@ -599,7 +617,8 @@ static int test__group3(struct perf_evlist *evlist __maybe_unused)
        TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
        TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
        TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
-       TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
+       /* use of precise requires exclude_guest */
+       TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
        TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
        TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 3);
        TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
@@ -662,7 +681,8 @@ static int test__group4(struct perf_evlist *evlist __maybe_unused)
        TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
        TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
        TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
-       TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
+       /* use of precise requires exclude_guest */
+       TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
        TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
        TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 1);
        TEST_ASSERT_VAL("wrong group name", !evsel->group_name);
@@ -676,7 +696,8 @@ static int test__group4(struct perf_evlist *evlist __maybe_unused)
        TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
        TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
        TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
-       TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
+       /* use of precise requires exclude_guest */
+       TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
        TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
        TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 2);
        TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
@@ -1020,6 +1041,51 @@ static int test_pmu(void)
        return !ret;
 }
 
+static int test_pmu_events(void)
+{
+       struct stat st;
+       char path[PATH_MAX];
+       struct dirent *ent;
+       DIR *dir;
+       int ret;
+
+       snprintf(path, PATH_MAX, "%s/bus/event_source/devices/cpu/events/",
+                sysfs_find_mountpoint());
+
+       ret = stat(path, &st);
+       if (ret) {
+               pr_debug("ommiting PMU cpu events tests\n");
+               return 0;
+       }
+
+       dir = opendir(path);
+       if (!dir) {
+               pr_debug("can't open pmu event dir");
+               return -1;
+       }
+
+       while (!ret && (ent = readdir(dir))) {
+#define MAX_NAME 100
+               struct test__event_st e;
+               char name[MAX_NAME];
+
+               if (!strcmp(ent->d_name, ".") ||
+                   !strcmp(ent->d_name, ".."))
+                       continue;
+
+               snprintf(name, MAX_NAME, "cpu/event=%s/u", ent->d_name);
+
+               e.name  = name;
+               e.check = test__checkevent_pmu_events;
+
+               ret = test_event(&e);
+#undef MAX_NAME
+       }
+
+       closedir(dir);
+       return ret;
+}
+
 int parse_events__test(void)
 {
        int ret1, ret2 = 0;
@@ -1036,6 +1102,12 @@ do {                                                     \
        if (test_pmu())
                TEST_EVENTS(test__events_pmu);
 
+       if (test_pmu()) {
+               int ret = test_pmu_events();
+               if (ret)
+                       return ret;
+       }
+
        ret1 = test_terms(test__terms, ARRAY_SIZE(test__terms));
        if (!ret2)
                ret2 = ret1;
index aed38e4b9dfaf143020d3502c56a913acf9b0bb4..2fe15874e46e7fab700be86fbcd781ecd1b17a41 100644 (file)
@@ -690,6 +690,9 @@ static int get_event_modifier(struct event_modifier *mod, char *str,
                        eH = 0;
                } else if (*str == 'p') {
                        precise++;
+                       /* use of precise requires exclude_guest */
+                       if (!exclude_GH)
+                               eG = 1;
                } else
                        break;
 
@@ -1139,6 +1142,24 @@ int parse_events__term_str(struct parse_events__term **term,
                        config, str, 0);
 }
 
+int parse_events__term_sym_hw(struct parse_events__term **term,
+                             char *config, unsigned idx)
+{
+       struct event_symbol *sym;
+
+       BUG_ON(idx >= PERF_COUNT_HW_MAX);
+       sym = &event_symbols_hw[idx];
+
+       if (config)
+               return new_term(term, PARSE_EVENTS__TERM_TYPE_STR,
+                               PARSE_EVENTS__TERM_TYPE_USER, config,
+                               (char *) sym->symbol, 0);
+       else
+               return new_term(term, PARSE_EVENTS__TERM_TYPE_STR,
+                               PARSE_EVENTS__TERM_TYPE_USER,
+                               (char *) "event", (char *) sym->symbol, 0);
+}
+
 int parse_events__term_clone(struct parse_events__term **new,
                             struct parse_events__term *term)
 {
index 839230ceb18bd918b194d0fc719607445ad7bb00..ac9a6aacf2f53d54abbf02f17130ab42fc924dbc 100644 (file)
@@ -76,6 +76,8 @@ int parse_events__term_num(struct parse_events__term **_term,
                           int type_term, char *config, u64 num);
 int parse_events__term_str(struct parse_events__term **_term,
                           int type_term, char *config, char *str);
+int parse_events__term_sym_hw(struct parse_events__term **term,
+                             char *config, unsigned idx);
 int parse_events__term_clone(struct parse_events__term **new,
                             struct parse_events__term *term);
 void parse_events__free_terms(struct list_head *terms);
index cd88209e3c5876e96f26ef9046d2778554c18b9e..0f9914ae6bacb0b801650cb1c9449852b8a0ff1f 100644 (file)
@@ -352,6 +352,15 @@ PE_NAME '=' PE_VALUE
        $$ = term;
 }
 |
+PE_NAME '=' PE_VALUE_SYM_HW
+{
+       struct parse_events__term *term;
+       int config = $3 & 255;
+
+       ABORT_ON(parse_events__term_sym_hw(&term, $1, config));
+       $$ = term;
+}
+|
 PE_NAME
 {
        struct parse_events__term *term;
@@ -361,6 +370,15 @@ PE_NAME
        $$ = term;
 }
 |
+PE_VALUE_SYM_HW
+{
+       struct parse_events__term *term;
+       int config = $1 & 255;
+
+       ABORT_ON(parse_events__term_sym_hw(&term, NULL, config));
+       $$ = term;
+}
+|
 PE_TERM '=' PE_NAME
 {
        struct parse_events__term *term;
index 8a2229da594fca292d6d0672bb40b4a10a0a52f2..18e84801d4d19c6750bd68fedfd66c6469ff7fe3 100644 (file)
@@ -164,7 +164,7 @@ static int pmu_aliases(char *name, struct list_head *head)
                 "%s/bus/event_source/devices/%s/events", sysfs, name);
 
        if (stat(path, &st) < 0)
-               return -1;
+               return 0;        /* no error if 'events' does not exist */
 
        if (pmu_aliases_parse(path, head))
                return -1;
@@ -296,6 +296,9 @@ static struct perf_pmu *pmu_lookup(char *name)
        if (pmu_format(name, &format))
                return NULL;
 
+       if (pmu_aliases(name, &aliases))
+               return NULL;
+
        if (pmu_type(name, &type))
                return NULL;
 
@@ -305,8 +308,6 @@ static struct perf_pmu *pmu_lookup(char *name)
 
        pmu->cpus = pmu_cpumask(name);
 
-       pmu_aliases(name, &aliases);
-
        INIT_LIST_HEAD(&pmu->format);
        INIT_LIST_HEAD(&pmu->aliases);
        list_splice(&format, &pmu->format);
index 730c6630cba5ac254054c0ecc57d7363bd51f6e0..14683dfca2eeb9cfaeac762dc5964d48c093328c 100644 (file)
@@ -32,7 +32,6 @@
 #include "../event.h"
 #include "../thread.h"
 #include "../trace-event.h"
-#include "../evsel.h"
 
 PyMODINIT_FUNC initperf_trace_context(void);
 
index 8cdd23239c9023e8a8659a42b363239ded45cf4c..15abe40dc7021bd8229563a092ce63e67e4d2ccd 100644 (file)
@@ -1375,15 +1375,13 @@ int __perf_session__process_events(struct perf_session *session,
 {
        u64 head, page_offset, file_offset, file_pos, progress_next;
        int err, mmap_prot, mmap_flags, map_idx = 0;
-       size_t  page_size, mmap_size;
+       size_t  mmap_size;
        char *buf, *mmaps[8];
        union perf_event *event;
        uint32_t size;
 
        perf_tool__fill_defaults(tool);
 
-       page_size = sysconf(_SC_PAGESIZE);
-
        page_offset = page_size * (data_offset / page_size);
        file_offset = page_offset;
        head = data_offset - page_offset;
index d0f9f29cf181ad98900ebd9fe6baf2a915a32866..73d510269784a9ec1c68e3860f8f15dd24553567 100644 (file)
@@ -23,6 +23,7 @@ cflags += getenv('CFLAGS', '').split()
 
 build_lib = getenv('PYTHON_EXTBUILD_LIB')
 build_tmp = getenv('PYTHON_EXTBUILD_TMP')
+libtraceevent = getenv('LIBTRACEEVENT')
 
 ext_sources = [f.strip() for f in file('util/python-ext-sources')
                                if len(f.strip()) > 0 and f[0] != '#']
@@ -31,6 +32,7 @@ perf = Extension('perf',
                  sources = ext_sources,
                  include_dirs = ['util/include'],
                  extra_compile_args = cflags,
+                 extra_objects = [libtraceevent],
                  )
 
 setup(name='perf',
index b5b1b9211960884efd1a4c707fa8c56910db01f1..cfd1c0feb32d7da84d0b8b73b81883729fa623df 100644 (file)
@@ -260,6 +260,12 @@ static int hist_entry__srcline_snprintf(struct hist_entry *self, char *bf,
        if (path != NULL)
                goto out_path;
 
+       if (!self->ms.map)
+               goto out_ip;
+
+       if (!strncmp(self->ms.map->dso->long_name, "/tmp/perf-", 10))
+               goto out_ip;
+
        snprintf(cmd, sizeof(cmd), "addr2line -e %s %016" PRIx64,
                 self->ms.map->dso->long_name, self->ip);
        fp = popen(cmd, "r");
index 5786f323b597226a4668f1342ec0f06f5e8ec38c..13761d83a5a07a61d80f8c5841b98531e13625b0 100644 (file)
@@ -52,6 +52,22 @@ struct he_stat {
        u32                     nr_events;
 };
 
+struct hist_entry_diff {
+       bool    computed;
+
+       /* PERF_HPP__DISPL */
+       int     displacement;
+
+       /* PERF_HPP__DELTA */
+       double  period_ratio_delta;
+
+       /* PERF_HPP__RATIO */
+       double  period_ratio;
+
+       /* HISTC_WEIGHTED_DIFF */
+       s64     wdiff;
+};
+
 /**
  * struct hist_entry - histogram entry
  *
@@ -67,6 +83,8 @@ struct hist_entry {
        u64                     ip;
        s32                     cpu;
 
+       struct hist_entry_diff  diff;
+
        /* XXX These two should move to some tree widget lib */
        u16                     row_offset;
        u16                     nr_rows;
index fb4b7ea6752fd86121a968fa77212727f603d7e9..df59623ac7630ccc67ee6f5cbaf5fae1c2847782 100644 (file)
@@ -7,7 +7,7 @@
 #include "util.h"
 #include "debug.h"
 
-static struct thread *thread__new(pid_t pid)
+struct thread *thread__new(pid_t pid)
 {
        struct thread *self = zalloc(sizeof(*self));
 
@@ -39,7 +39,6 @@ int thread__set_comm(struct thread *self, const char *comm)
        err = self->comm == NULL ? -ENOMEM : 0;
        if (!err) {
                self->comm_set = true;
-               map_groups__flush(&self->mg);
        }
        return err;
 }
@@ -61,45 +60,6 @@ static size_t thread__fprintf(struct thread *self, FILE *fp)
               map_groups__fprintf(&self->mg, verbose, fp);
 }
 
-struct thread *machine__findnew_thread(struct machine *self, pid_t pid)
-{
-       struct rb_node **p = &self->threads.rb_node;
-       struct rb_node *parent = NULL;
-       struct thread *th;
-
-       /*
-        * Font-end cache - PID lookups come in blocks,
-        * so most of the time we dont have to look up
-        * the full rbtree:
-        */
-       if (self->last_match && self->last_match->pid == pid)
-               return self->last_match;
-
-       while (*p != NULL) {
-               parent = *p;
-               th = rb_entry(parent, struct thread, rb_node);
-
-               if (th->pid == pid) {
-                       self->last_match = th;
-                       return th;
-               }
-
-               if (pid < th->pid)
-                       p = &(*p)->rb_left;
-               else
-                       p = &(*p)->rb_right;
-       }
-
-       th = thread__new(pid);
-       if (th != NULL) {
-               rb_link_node(&th->rb_node, parent, p);
-               rb_insert_color(&th->rb_node, &self->threads);
-               self->last_match = th;
-       }
-
-       return th;
-}
-
 void thread__insert_map(struct thread *self, struct map *map)
 {
        map_groups__fixup_overlappings(&self->mg, map, verbose, stderr);
index f66610b7bacf344ef0cae7fd01dfefb69c69e073..f2fa17caa7d599e129a6901e0772e9a3916fd2d8 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <linux/rbtree.h>
 #include <unistd.h>
+#include <sys/types.h>
 #include "symbol.h"
 
 struct thread {
@@ -22,6 +23,7 @@ struct thread {
 
 struct machine;
 
+struct thread *thread__new(pid_t pid);
 void thread__delete(struct thread *self);
 
 int thread__set_comm(struct thread *self, const char *comm);
index 719ed74a85652541d19e1f7dc15d26e2348a31fc..3741572696af4446c08a2c3b60ac674496323de6 100644 (file)
@@ -47,8 +47,6 @@ int file_bigendian;
 int host_bigendian;
 static int long_size;
 
-static unsigned long   page_size;
-
 static ssize_t calc_data_size;
 static bool repipe;
 
index 99664598bc1acfa3d03e0aaa1b0a44834be5f2d8..637b5cc5436299d317c71d84af6b64e5e774f58e 100644 (file)
@@ -10,6 +10,8 @@
 /*
  * XXX We need to find a better place for these things...
  */
+unsigned int page_size;
+
 bool perf_host  = true;
 bool perf_guest = false;
 
index 70fa70b535b2ebb2c389efa4ebbc78cfcdfaace2..a6b83f8ebef8726466d110644512a41eb87cf457 100644 (file)
@@ -263,4 +263,6 @@ char *rtrim(char *s);
 
 void dump_stack(void);
 
+extern unsigned int page_size;
+
 #endif
index e626fa553c5ae1b2db0f044fe0c987e13e5af9ec..a11028acf219915cfc81785e4b79a1555b400a44 100644 (file)
@@ -164,7 +164,7 @@ static void run_test(struct vdev_info *dev, struct vq_info *vq,
                                r = virtqueue_add_buf(vq->vq, &sl, 1, 0,
                                                      dev->buf + started,
                                                      GFP_ATOMIC);
-                               if (likely(r >= 0)) {
+                               if (likely(r == 0)) {
                                        ++started;
                                        virtqueue_kick(vq->vq);
                                }
@@ -177,7 +177,7 @@ static void run_test(struct vdev_info *dev, struct vq_info *vq,
                                r = 0;
                        }
 
-               } while (r >= 0);
+               } while (r == 0);
                if (completed == completed_before)
                        ++spurious;
                assert(completed <= bufs);
index 037cb6730e68eef3171b0e9660d1139b423d96de..18e1e30019e3f573a8cd3540bc781b5648a239d4 100644 (file)
@@ -168,11 +168,7 @@ int kvm_assign_device(struct kvm *kvm,
 
        r = iommu_attach_device(domain, &pdev->dev);
        if (r) {
-               printk(KERN_ERR "assign device %x:%x:%x.%x failed",
-                       pci_domain_nr(pdev->bus),
-                       pdev->bus->number,
-                       PCI_SLOT(pdev->devfn),
-                       PCI_FUNC(pdev->devfn));
+               dev_err(&pdev->dev, "kvm assign device failed ret %d", r);
                return r;
        }
 
index e59bb63cb089634c7d9bed701be0581bf536726a..be70035fd42a14edad4c24ae411c4b9d3fdf396c 100644 (file)
@@ -1322,9 +1322,7 @@ EXPORT_SYMBOL_GPL(kvm_release_page_clean);
 
 void kvm_release_pfn_clean(pfn_t pfn)
 {
-       WARN_ON(is_error_pfn(pfn));
-
-       if (!kvm_is_mmio_pfn(pfn))
+       if (!is_error_pfn(pfn) && !kvm_is_mmio_pfn(pfn))
                put_page(pfn_to_page(pfn));
 }
 EXPORT_SYMBOL_GPL(kvm_release_pfn_clean);